123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- //===- 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)
- : 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);
- }
|