diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp | 386 | 
1 files changed, 386 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp b/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp new file mode 100644 index 000000000000..d02782c7954d --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp @@ -0,0 +1,386 @@ +//===- 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); +}  | 
