//===- 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) {
  for (const char C : Str)
    R.push_back(C);
}

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);
}
