brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.5 KiB · abd436e Raw
353 lines · cpp
1//===- BitstreamRemarkSerializer.cpp --------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides the implementation of the LLVM bitstream remark serializer10// using LLVM's bitstream writer.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Remarks/BitstreamRemarkSerializer.h"15#include "llvm/ADT/ScopeExit.h"16#include "llvm/Remarks/Remark.h"17#include <cassert>18#include <optional>19 20using namespace llvm;21using namespace llvm::remarks;22 23BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper(24    BitstreamRemarkContainerType ContainerType, raw_ostream &OS)25    : Bitstream(OS), ContainerType(ContainerType) {}26 27static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream,28                          SmallVectorImpl<uint64_t> &R, StringRef Str) {29  R.clear();30  R.push_back(RecordID);31  append_range(R, Str);32  Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R);33}34 35static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream,36                      SmallVectorImpl<uint64_t> &R, StringRef Str) {37  R.clear();38  R.push_back(BlockID);39  Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R);40 41  R.clear();42  append_range(R, Str);43  Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R);44}45 46void BitstreamRemarkSerializerHelper::setupMetaBlockInfo() {47  // Setup the metadata block.48  initBlock(META_BLOCK_ID, Bitstream, R, MetaBlockName);49 50  // The container information.51  setRecordName(RECORD_META_CONTAINER_INFO, Bitstream, R,52                MetaContainerInfoName);53 54  auto Abbrev = std::make_shared<BitCodeAbbrev>();55  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_CONTAINER_INFO));56  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.57  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));  // Type.58  RecordMetaContainerInfoAbbrevID =59      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);60}61 62void BitstreamRemarkSerializerHelper::setupMetaRemarkVersion() {63  setRecordName(RECORD_META_REMARK_VERSION, Bitstream, R,64                MetaRemarkVersionName);65 66  auto Abbrev = std::make_shared<BitCodeAbbrev>();67  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_REMARK_VERSION));68  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.69  RecordMetaRemarkVersionAbbrevID =70      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);71}72 73void BitstreamRemarkSerializerHelper::emitMetaRemarkVersion(74    uint64_t RemarkVersion) {75  // The remark version is emitted only if we emit remarks.76  R.clear();77  R.push_back(RECORD_META_REMARK_VERSION);78  R.push_back(RemarkVersion);79  Bitstream.EmitRecordWithAbbrev(RecordMetaRemarkVersionAbbrevID, R);80}81 82void BitstreamRemarkSerializerHelper::setupMetaStrTab() {83  setRecordName(RECORD_META_STRTAB, Bitstream, R, MetaStrTabName);84 85  auto Abbrev = std::make_shared<BitCodeAbbrev>();86  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_STRTAB));87  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Raw table.88  RecordMetaStrTabAbbrevID =89      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);90}91 92void BitstreamRemarkSerializerHelper::emitMetaStrTab(93    const StringTable &StrTab) {94  // The string table is not emitted if we emit remarks separately.95  R.clear();96  R.push_back(RECORD_META_STRTAB);97 98  // Serialize to a blob.99  std::string Buf;100  raw_string_ostream OS(Buf);101  StrTab.serialize(OS);102  StringRef Blob = OS.str();103  Bitstream.EmitRecordWithBlob(RecordMetaStrTabAbbrevID, R, Blob);104}105 106void BitstreamRemarkSerializerHelper::setupMetaExternalFile() {107  setRecordName(RECORD_META_EXTERNAL_FILE, Bitstream, R, MetaExternalFileName);108 109  auto Abbrev = std::make_shared<BitCodeAbbrev>();110  Abbrev->Add(BitCodeAbbrevOp(RECORD_META_EXTERNAL_FILE));111  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename.112  RecordMetaExternalFileAbbrevID =113      Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);114}115 116void BitstreamRemarkSerializerHelper::emitMetaExternalFile(StringRef Filename) {117  // The external file is emitted only if we emit the separate metadata.118  R.clear();119  R.push_back(RECORD_META_EXTERNAL_FILE);120  Bitstream.EmitRecordWithBlob(RecordMetaExternalFileAbbrevID, R, Filename);121}122 123void BitstreamRemarkSerializerHelper::setupRemarkBlockInfo() {124  // Setup the remark block.125  initBlock(REMARK_BLOCK_ID, Bitstream, R, RemarkBlockName);126 127  // The header of a remark.128  {129    setRecordName(RECORD_REMARK_HEADER, Bitstream, R, RemarkHeaderName);130 131    auto Abbrev = std::make_shared<BitCodeAbbrev>();132    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HEADER));133    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Type134    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Remark Name135    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Pass name136    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // Function name137    RecordRemarkHeaderAbbrevID =138        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);139  }140 141  // The location of a remark.142  {143    setRecordName(RECORD_REMARK_DEBUG_LOC, Bitstream, R, RemarkDebugLocName);144 145    auto Abbrev = std::make_shared<BitCodeAbbrev>();146    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_DEBUG_LOC));147    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // File148    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line149    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column150    RecordRemarkDebugLocAbbrevID =151        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);152  }153 154  // The hotness of a remark.155  {156    setRecordName(RECORD_REMARK_HOTNESS, Bitstream, R, RemarkHotnessName);157 158    auto Abbrev = std::make_shared<BitCodeAbbrev>();159    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HOTNESS));160    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Hotness161    RecordRemarkHotnessAbbrevID =162        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);163  }164 165  // An argument entry with a debug location attached.166  {167    setRecordName(RECORD_REMARK_ARG_WITH_DEBUGLOC, Bitstream, R,168                  RemarkArgWithDebugLocName);169 170    auto Abbrev = std::make_shared<BitCodeAbbrev>();171    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITH_DEBUGLOC));172    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // Key173    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // Value174    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7));    // File175    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line176    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column177    RecordRemarkArgWithDebugLocAbbrevID =178        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);179  }180 181  // An argument entry with no debug location attached.182  {183    setRecordName(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC, Bitstream, R,184                  RemarkArgWithoutDebugLocName);185 186    auto Abbrev = std::make_shared<BitCodeAbbrev>();187    Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC));188    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key189    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value190    RecordRemarkArgWithoutDebugLocAbbrevID =191        Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);192  }193}194 195void BitstreamRemarkSerializerHelper::setupBlockInfo() {196  // Emit magic number.197  for (const char C : ContainerMagic)198    Bitstream.Emit(static_cast<unsigned>(C), 8);199 200  Bitstream.EnterBlockInfoBlock();201  auto ExitBlock = make_scope_exit([&] { Bitstream.ExitBlock(); });202 203  // Setup the main metadata. Depending on the container type, we'll setup the204  // required records next.205  setupMetaBlockInfo();206 207  switch (ContainerType) {208  case BitstreamRemarkContainerType::RemarksFileExternal:209    // Needs to know where the external remarks file is.210    setupMetaExternalFile();211    return;212  case BitstreamRemarkContainerType::RemarksFile:213    // Contains remarks: emit the version.214    setupMetaRemarkVersion();215    // Needs a string table.216    setupMetaStrTab();217    // Contains remarks: emit the remark abbrevs.218    setupRemarkBlockInfo();219    return;220  }221  llvm_unreachable("Unexpected BitstreamRemarkContainerType");222}223 224void BitstreamRemarkSerializerHelper::emitMetaBlock(225    std::optional<StringRef> Filename) {226  // Emit the meta block227  Bitstream.EnterSubblock(META_BLOCK_ID, 3);228  auto ExitBlock = make_scope_exit([&] { Bitstream.ExitBlock(); });229 230  // The container version and type.231  R.clear();232  R.push_back(RECORD_META_CONTAINER_INFO);233  R.push_back(CurrentContainerVersion);234  R.push_back(static_cast<uint64_t>(ContainerType));235  Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R);236 237  switch (ContainerType) {238  case BitstreamRemarkContainerType::RemarksFileExternal:239    assert(Filename != std::nullopt);240    emitMetaExternalFile(*Filename);241    return;242  case BitstreamRemarkContainerType::RemarksFile:243    emitMetaRemarkVersion(CurrentRemarkVersion);244    return;245  }246  llvm_unreachable("Unexpected BitstreamRemarkContainerType");247}248 249void BitstreamRemarkSerializerHelper::emitLateMetaBlock(250    const StringTable &StrTab) {251  // Emit the late meta block (after all remarks are serialized)252  Bitstream.EnterSubblock(META_BLOCK_ID, 3);253  emitMetaStrTab(StrTab);254  Bitstream.ExitBlock();255}256 257void BitstreamRemarkSerializerHelper::emitRemark(const Remark &Remark,258                                                 StringTable &StrTab) {259  Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4);260 261  R.clear();262  R.push_back(RECORD_REMARK_HEADER);263  R.push_back(static_cast<uint64_t>(Remark.RemarkType));264  R.push_back(StrTab.add(Remark.RemarkName).first);265  R.push_back(StrTab.add(Remark.PassName).first);266  R.push_back(StrTab.add(Remark.FunctionName).first);267  Bitstream.EmitRecordWithAbbrev(RecordRemarkHeaderAbbrevID, R);268 269  if (const std::optional<RemarkLocation> &Loc = Remark.Loc) {270    R.clear();271    R.push_back(RECORD_REMARK_DEBUG_LOC);272    R.push_back(StrTab.add(Loc->SourceFilePath).first);273    R.push_back(Loc->SourceLine);274    R.push_back(Loc->SourceColumn);275    Bitstream.EmitRecordWithAbbrev(RecordRemarkDebugLocAbbrevID, R);276  }277 278  if (std::optional<uint64_t> Hotness = Remark.Hotness) {279    R.clear();280    R.push_back(RECORD_REMARK_HOTNESS);281    R.push_back(*Hotness);282    Bitstream.EmitRecordWithAbbrev(RecordRemarkHotnessAbbrevID, R);283  }284 285  for (const Argument &Arg : Remark.Args) {286    R.clear();287    unsigned Key = StrTab.add(Arg.Key).first;288    unsigned Val = StrTab.add(Arg.Val).first;289    bool HasDebugLoc = Arg.Loc != std::nullopt;290    R.push_back(HasDebugLoc ? RECORD_REMARK_ARG_WITH_DEBUGLOC291                            : RECORD_REMARK_ARG_WITHOUT_DEBUGLOC);292    R.push_back(Key);293    R.push_back(Val);294    if (HasDebugLoc) {295      R.push_back(StrTab.add(Arg.Loc->SourceFilePath).first);296      R.push_back(Arg.Loc->SourceLine);297      R.push_back(Arg.Loc->SourceColumn);298    }299    Bitstream.EmitRecordWithAbbrev(HasDebugLoc300                                       ? RecordRemarkArgWithDebugLocAbbrevID301                                       : RecordRemarkArgWithoutDebugLocAbbrevID,302                                   R);303  }304  Bitstream.ExitBlock();305}306 307BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS)308    : RemarkSerializer(Format::Bitstream, OS) {309  StrTab.emplace();310}311 312BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,313                                                     StringTable StrTabIn)314    : RemarkSerializer(Format::Bitstream, OS) {315  StrTab = std::move(StrTabIn);316}317 318BitstreamRemarkSerializer::~BitstreamRemarkSerializer() { finalize(); }319 320void BitstreamRemarkSerializer::setup() {321  if (Helper)322    return;323  Helper.emplace(BitstreamRemarkContainerType::RemarksFile, OS);324  Helper->setupBlockInfo();325  Helper->emitMetaBlock();326}327 328void BitstreamRemarkSerializer::finalize() {329  if (!Helper)330    return;331  Helper->emitLateMetaBlock(*StrTab);332  Helper = std::nullopt;333}334 335void BitstreamRemarkSerializer::emit(const Remark &Remark) {336  setup();337  Helper->emitRemark(Remark, *StrTab);338}339 340std::unique_ptr<MetaSerializer>341BitstreamRemarkSerializer::metaSerializer(raw_ostream &OS,342                                          StringRef ExternalFilename) {343  return std::make_unique<BitstreamMetaSerializer>(344      OS, BitstreamRemarkContainerType::RemarksFileExternal, ExternalFilename);345}346 347void BitstreamMetaSerializer::emit() {348  assert(Helper && "BitstreamMetaSerializer emitted multiple times");349  Helper->setupBlockInfo();350  Helper->emitMetaBlock(ExternalFilename);351  Helper = std::nullopt;352}353