//===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "TestModuleFileExtension.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
using namespace clang;
using namespace clang::serialization;

char TestModuleFileExtension::ID = 0;

TestModuleFileExtension::Writer::~Writer() { }

void TestModuleFileExtension::Writer::writeExtensionContents(
       Sema &SemaRef,
       llvm::BitstreamWriter &Stream) {
  using namespace llvm;

  // Write an abbreviation for this record.
  auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // message
  auto Abbrev = Stream.EmitAbbrev(std::move(Abv));

  // Write a message into the extension block.
  SmallString<64> Message;
  {
    auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
    raw_svector_ostream OS(Message);
    OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
       << Ext->MinorVersion;
  }
  uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
  Stream.EmitRecordWithBlob(Abbrev, Record, Message);
}

TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
                                        const llvm::BitstreamCursor &InStream)
  : ModuleFileExtensionReader(Ext), Stream(InStream)
{
  // Read the extension block.
  SmallVector<uint64_t, 4> Record;
  while (true) {
    llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
        Stream.advanceSkippingSubblocks();
    if (!MaybeEntry)
      (void)MaybeEntry.takeError();
    llvm::BitstreamEntry Entry = MaybeEntry.get();

    switch (Entry.Kind) {
    case llvm::BitstreamEntry::SubBlock:
    case llvm::BitstreamEntry::EndBlock:
    case llvm::BitstreamEntry::Error:
      return;

    case llvm::BitstreamEntry::Record:
      break;
    }

    Record.clear();
    StringRef Blob;
    Expected<unsigned> MaybeRecCode =
        Stream.readRecord(Entry.ID, Record, &Blob);
    if (!MaybeRecCode)
      fprintf(stderr, "Failed reading rec code: %s\n",
              toString(MaybeRecCode.takeError()).c_str());
    switch (MaybeRecCode.get()) {
    case FIRST_EXTENSION_RECORD_ID: {
      StringRef Message = Blob.substr(0, Record[0]);
      fprintf(stderr, "Read extension block message: %s\n",
              Message.str().c_str());
      break;
    }
    }
  }
}

TestModuleFileExtension::Reader::~Reader() { }

TestModuleFileExtension::~TestModuleFileExtension() { }

ModuleFileExtensionMetadata
TestModuleFileExtension::getExtensionMetadata() const {
  return { BlockName, MajorVersion, MinorVersion, UserInfo };
}

void TestModuleFileExtension::hashExtension(
    ExtensionHashBuilder &HBuilder) const {
  if (Hashed) {
    HBuilder.add(BlockName);
    HBuilder.add(MajorVersion);
    HBuilder.add(MinorVersion);
    HBuilder.add(UserInfo);
  }
}

std::unique_ptr<ModuleFileExtensionWriter>
TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
  return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
}

std::unique_ptr<ModuleFileExtensionReader>
TestModuleFileExtension::createExtensionReader(
  const ModuleFileExtensionMetadata &Metadata,
  ASTReader &Reader, serialization::ModuleFile &Mod,
  const llvm::BitstreamCursor &Stream)
{
  assert(Metadata.BlockName == BlockName && "Wrong block name");
  if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
        std::make_pair(MajorVersion, MinorVersion)) {
    Reader.getDiags().Report(Mod.ImportLoc,
                             diag::err_test_module_file_extension_version)
      << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
      << MajorVersion << MinorVersion;
    return nullptr;
  }

  return std::unique_ptr<ModuleFileExtensionReader>(
                                                    new TestModuleFileExtension::Reader(this, Stream));
}

std::string TestModuleFileExtension::str() const {
  std::string Buffer;
  llvm::raw_string_ostream OS(Buffer);
  OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
     << ":" << UserInfo;
  return OS.str();
}
