//===- BitstreamRemarkSerializer.cpp --------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file provides the implementation of the LLVM bitstream remark serializer
// using LLVM's bitstream writer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Remarks/BitstreamRemarkSerializer.h"

using namespace llvm;
using namespace llvm::remarks;

BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper(
    BitstreamRemarkContainerType ContainerType)
    : Encoded(), R(), Bitstream(Encoded), ContainerType(ContainerType) {}

static void push(SmallVectorImpl<uint64_t> &R, StringRef Str) {
  append_range(R, Str);
}

static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream,
                          SmallVectorImpl<uint64_t> &R, StringRef Str) {
  R.clear();
  R.push_back(RecordID);
  push(R, Str);
  Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R);
}

static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream,
                      SmallVectorImpl<uint64_t> &R, StringRef Str) {
  R.clear();
  R.push_back(BlockID);
  Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R);

  R.clear();
  push(R, Str);
  Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R);
}

void BitstreamRemarkSerializerHelper::setupMetaBlockInfo() {
  // Setup the metadata block.
  initBlock(META_BLOCK_ID, Bitstream, R, MetaBlockName);

  // The container information.
  setRecordName(RECORD_META_CONTAINER_INFO, Bitstream, R,
                MetaContainerInfoName);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_CONTAINER_INFO));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));  // Type.
  RecordMetaContainerInfoAbbrevID =
      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
}

void BitstreamRemarkSerializerHelper::setupMetaRemarkVersion() {
  setRecordName(RECORD_META_REMARK_VERSION, Bitstream, R,
                MetaRemarkVersionName);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_REMARK_VERSION));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
  RecordMetaRemarkVersionAbbrevID =
      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
}

void BitstreamRemarkSerializerHelper::emitMetaRemarkVersion(
    uint64_t RemarkVersion) {
  // The remark version is emitted only if we emit remarks.
  R.clear();
  R.push_back(RECORD_META_REMARK_VERSION);
  R.push_back(RemarkVersion);
  Bitstream.EmitRecordWithAbbrev(RecordMetaRemarkVersionAbbrevID, R);
}

void BitstreamRemarkSerializerHelper::setupMetaStrTab() {
  setRecordName(RECORD_META_STRTAB, Bitstream, R, MetaStrTabName);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_STRTAB));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Raw table.
  RecordMetaStrTabAbbrevID =
      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
}

void BitstreamRemarkSerializerHelper::emitMetaStrTab(
    const StringTable &StrTab) {
  // The string table is not emitted if we emit remarks separately.
  R.clear();
  R.push_back(RECORD_META_STRTAB);

  // Serialize to a blob.
  std::string Buf;
  raw_string_ostream OS(Buf);
  StrTab.serialize(OS);
  StringRef Blob = OS.str();
  Bitstream.EmitRecordWithBlob(RecordMetaStrTabAbbrevID, R, Blob);
}

void BitstreamRemarkSerializerHelper::setupMetaExternalFile() {
  setRecordName(RECORD_META_EXTERNAL_FILE, Bitstream, R, MetaExternalFileName);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_EXTERNAL_FILE));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename.
  RecordMetaExternalFileAbbrevID =
      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
}

void BitstreamRemarkSerializerHelper::emitMetaExternalFile(StringRef Filename) {
  // The external file is emitted only if we emit the separate metadata.
  R.clear();
  R.push_back(RECORD_META_EXTERNAL_FILE);
  Bitstream.EmitRecordWithBlob(RecordMetaExternalFileAbbrevID, R, Filename);
}

void BitstreamRemarkSerializerHelper::setupRemarkBlockInfo() {
  // Setup the remark block.
  initBlock(REMARK_BLOCK_ID, Bitstream, R, RemarkBlockName);

  // The header of a remark.
  {
    setRecordName(RECORD_REMARK_HEADER, Bitstream, R, RemarkHeaderName);

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HEADER));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Type
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Remark Name
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Pass name
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // Function name
    RecordRemarkHeaderAbbrevID =
        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
  }

  // The location of a remark.
  {
    setRecordName(RECORD_REMARK_DEBUG_LOC, Bitstream, R, RemarkDebugLocName);

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_DEBUG_LOC));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // File
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
    RecordRemarkDebugLocAbbrevID =
        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
  }

  // The hotness of a remark.
  {
    setRecordName(RECORD_REMARK_HOTNESS, Bitstream, R, RemarkHotnessName);

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HOTNESS));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Hotness
    RecordRemarkHotnessAbbrevID =
        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
  }

  // An argument entry with a debug location attached.
  {
    setRecordName(RECORD_REMARK_ARG_WITH_DEBUGLOC, Bitstream, R,
                  RemarkArgWithDebugLocName);

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITH_DEBUGLOC));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // Key
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // Value
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // File
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
    RecordRemarkArgWithDebugLocAbbrevID =
        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
  }

  // An argument entry with no debug location attached.
  {
    setRecordName(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC, Bitstream, R,
                  RemarkArgWithoutDebugLocName);

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value
    RecordRemarkArgWithoutDebugLocAbbrevID =
        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
  }
}

void BitstreamRemarkSerializerHelper::setupBlockInfo() {
  // Emit magic number.
  for (const char C : ContainerMagic)
    Bitstream.Emit(static_cast<unsigned>(C), 8);

  Bitstream.EnterBlockInfoBlock();

  // Setup the main metadata. Depending on the container type, we'll setup the
  // required records next.
  setupMetaBlockInfo();

  switch (ContainerType) {
  case BitstreamRemarkContainerType::SeparateRemarksMeta:
    // Needs a string table that the separate remark file is using.
    setupMetaStrTab();
    // Needs to know where the external remarks file is.
    setupMetaExternalFile();
    break;
  case BitstreamRemarkContainerType::SeparateRemarksFile:
    // Contains remarks: emit the version.
    setupMetaRemarkVersion();
    // Contains remarks: emit the remark abbrevs.
    setupRemarkBlockInfo();
    break;
  case BitstreamRemarkContainerType::Standalone:
    // Contains remarks: emit the version.
    setupMetaRemarkVersion();
    // Needs a string table.
    setupMetaStrTab();
    // Contains remarks: emit the remark abbrevs.
    setupRemarkBlockInfo();
    break;
  }

  Bitstream.ExitBlock();
}

void BitstreamRemarkSerializerHelper::emitMetaBlock(
    uint64_t ContainerVersion, Optional<uint64_t> RemarkVersion,
    Optional<const StringTable *> StrTab, Optional<StringRef> Filename) {
  // Emit the meta block
  Bitstream.EnterSubblock(META_BLOCK_ID, 3);

  // The container version and type.
  R.clear();
  R.push_back(RECORD_META_CONTAINER_INFO);
  R.push_back(ContainerVersion);
  R.push_back(static_cast<uint64_t>(ContainerType));
  Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R);

  switch (ContainerType) {
  case BitstreamRemarkContainerType::SeparateRemarksMeta:
    assert(StrTab != None && *StrTab != nullptr);
    emitMetaStrTab(**StrTab);
    assert(Filename != None);
    emitMetaExternalFile(*Filename);
    break;
  case BitstreamRemarkContainerType::SeparateRemarksFile:
    assert(RemarkVersion != None);
    emitMetaRemarkVersion(*RemarkVersion);
    break;
  case BitstreamRemarkContainerType::Standalone:
    assert(RemarkVersion != None);
    emitMetaRemarkVersion(*RemarkVersion);
    assert(StrTab != None && *StrTab != nullptr);
    emitMetaStrTab(**StrTab);
    break;
  }

  Bitstream.ExitBlock();
}

void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark,
                                                      StringTable &StrTab) {
  Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4);

  R.clear();
  R.push_back(RECORD_REMARK_HEADER);
  R.push_back(static_cast<uint64_t>(Remark.RemarkType));
  R.push_back(StrTab.add(Remark.RemarkName).first);
  R.push_back(StrTab.add(Remark.PassName).first);
  R.push_back(StrTab.add(Remark.FunctionName).first);
  Bitstream.EmitRecordWithAbbrev(RecordRemarkHeaderAbbrevID, R);

  if (const Optional<RemarkLocation> &Loc = Remark.Loc) {
    R.clear();
    R.push_back(RECORD_REMARK_DEBUG_LOC);
    R.push_back(StrTab.add(Loc->SourceFilePath).first);
    R.push_back(Loc->SourceLine);
    R.push_back(Loc->SourceColumn);
    Bitstream.EmitRecordWithAbbrev(RecordRemarkDebugLocAbbrevID, R);
  }

  if (Optional<uint64_t> Hotness = Remark.Hotness) {
    R.clear();
    R.push_back(RECORD_REMARK_HOTNESS);
    R.push_back(*Hotness);
    Bitstream.EmitRecordWithAbbrev(RecordRemarkHotnessAbbrevID, R);
  }

  for (const Argument &Arg : Remark.Args) {
    R.clear();
    unsigned Key = StrTab.add(Arg.Key).first;
    unsigned Val = StrTab.add(Arg.Val).first;
    bool HasDebugLoc = Arg.Loc != None;
    R.push_back(HasDebugLoc ? RECORD_REMARK_ARG_WITH_DEBUGLOC
                            : RECORD_REMARK_ARG_WITHOUT_DEBUGLOC);
    R.push_back(Key);
    R.push_back(Val);
    if (HasDebugLoc) {
      R.push_back(StrTab.add(Arg.Loc->SourceFilePath).first);
      R.push_back(Arg.Loc->SourceLine);
      R.push_back(Arg.Loc->SourceColumn);
    }
    Bitstream.EmitRecordWithAbbrev(HasDebugLoc
                                       ? RecordRemarkArgWithDebugLocAbbrevID
                                       : RecordRemarkArgWithoutDebugLocAbbrevID,
                                   R);
  }
  Bitstream.ExitBlock();
}

void BitstreamRemarkSerializerHelper::flushToStream(raw_ostream &OS) {
  OS.write(Encoded.data(), Encoded.size());
  Encoded.clear();
}

StringRef BitstreamRemarkSerializerHelper::getBuffer() {
  return StringRef(Encoded.data(), Encoded.size());
}

BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
                                                     SerializerMode Mode)
    : RemarkSerializer(Format::Bitstream, OS, Mode),
      Helper(BitstreamRemarkContainerType::SeparateRemarksFile) {
  assert(Mode == SerializerMode::Separate &&
         "For SerializerMode::Standalone, a pre-filled string table needs to "
         "be provided.");
  // We always use a string table with bitstream.
  StrTab.emplace();
}

BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
                                                     SerializerMode Mode,
                                                     StringTable StrTabIn)
    : RemarkSerializer(Format::Bitstream, OS, Mode),
      Helper(Mode == SerializerMode::Separate
                 ? BitstreamRemarkContainerType::SeparateRemarksFile
                 : BitstreamRemarkContainerType::Standalone) {
  StrTab = std::move(StrTabIn);
}

void BitstreamRemarkSerializer::emit(const Remark &Remark) {
  if (!DidSetUp) {
    // Emit the metadata that is embedded in the remark file.
    // If we're in standalone mode, serialize the string table as well.
    bool IsStandalone =
        Helper.ContainerType == BitstreamRemarkContainerType::Standalone;
    BitstreamMetaSerializer MetaSerializer(
        OS, Helper,
        IsStandalone ? &*StrTab : Optional<const StringTable *>(None));
    MetaSerializer.emit();
    DidSetUp = true;
  }

  assert(DidSetUp &&
         "The Block info block and the meta block were not emitted yet.");
  Helper.emitRemarkBlock(Remark, *StrTab);

  Helper.flushToStream(OS);
}

std::unique_ptr<MetaSerializer> BitstreamRemarkSerializer::metaSerializer(
    raw_ostream &OS, Optional<StringRef> ExternalFilename) {
  assert(Helper.ContainerType !=
         BitstreamRemarkContainerType::SeparateRemarksMeta);
  bool IsStandalone =
      Helper.ContainerType == BitstreamRemarkContainerType::Standalone;
  return std::make_unique<BitstreamMetaSerializer>(
      OS,
      IsStandalone ? BitstreamRemarkContainerType::Standalone
                   : BitstreamRemarkContainerType::SeparateRemarksMeta,
      &*StrTab, ExternalFilename);
}

void BitstreamMetaSerializer::emit() {
  Helper->setupBlockInfo();
  Helper->emitMetaBlock(CurrentContainerVersion, CurrentRemarkVersion, StrTab,
                        ExternalFilename);
  Helper->flushToStream(OS);
}
