18bcb0991SDimitry Andric //===- BitstreamRemarkSerializer.cpp --------------------------------------===//
28bcb0991SDimitry Andric //
38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric //
78bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric //
98bcb0991SDimitry Andric // This file provides the implementation of the LLVM bitstream remark serializer
108bcb0991SDimitry Andric // using LLVM's bitstream writer.
118bcb0991SDimitry Andric //
128bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
138bcb0991SDimitry Andric
148bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkSerializer.h"
1581ad6265SDimitry Andric #include "llvm/Remarks/Remark.h"
16*bdd1243dSDimitry Andric #include <optional>
178bcb0991SDimitry Andric
188bcb0991SDimitry Andric using namespace llvm;
198bcb0991SDimitry Andric using namespace llvm::remarks;
208bcb0991SDimitry Andric
BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType)218bcb0991SDimitry Andric BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper(
228bcb0991SDimitry Andric BitstreamRemarkContainerType ContainerType)
2304eeddc0SDimitry Andric : Bitstream(Encoded), ContainerType(ContainerType) {}
248bcb0991SDimitry Andric
push(SmallVectorImpl<uint64_t> & R,StringRef Str)258bcb0991SDimitry Andric static void push(SmallVectorImpl<uint64_t> &R, StringRef Str) {
26fe6060f1SDimitry Andric append_range(R, Str);
278bcb0991SDimitry Andric }
288bcb0991SDimitry Andric
setRecordName(unsigned RecordID,BitstreamWriter & Bitstream,SmallVectorImpl<uint64_t> & R,StringRef Str)298bcb0991SDimitry Andric static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream,
308bcb0991SDimitry Andric SmallVectorImpl<uint64_t> &R, StringRef Str) {
318bcb0991SDimitry Andric R.clear();
328bcb0991SDimitry Andric R.push_back(RecordID);
338bcb0991SDimitry Andric push(R, Str);
348bcb0991SDimitry Andric Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R);
358bcb0991SDimitry Andric }
368bcb0991SDimitry Andric
initBlock(unsigned BlockID,BitstreamWriter & Bitstream,SmallVectorImpl<uint64_t> & R,StringRef Str)378bcb0991SDimitry Andric static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream,
388bcb0991SDimitry Andric SmallVectorImpl<uint64_t> &R, StringRef Str) {
398bcb0991SDimitry Andric R.clear();
408bcb0991SDimitry Andric R.push_back(BlockID);
418bcb0991SDimitry Andric Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R);
428bcb0991SDimitry Andric
438bcb0991SDimitry Andric R.clear();
448bcb0991SDimitry Andric push(R, Str);
458bcb0991SDimitry Andric Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R);
468bcb0991SDimitry Andric }
478bcb0991SDimitry Andric
setupMetaBlockInfo()488bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaBlockInfo() {
498bcb0991SDimitry Andric // Setup the metadata block.
508bcb0991SDimitry Andric initBlock(META_BLOCK_ID, Bitstream, R, MetaBlockName);
518bcb0991SDimitry Andric
528bcb0991SDimitry Andric // The container information.
538bcb0991SDimitry Andric setRecordName(RECORD_META_CONTAINER_INFO, Bitstream, R,
548bcb0991SDimitry Andric MetaContainerInfoName);
558bcb0991SDimitry Andric
568bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
578bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_CONTAINER_INFO));
588bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
598bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Type.
608bcb0991SDimitry Andric RecordMetaContainerInfoAbbrevID =
618bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
628bcb0991SDimitry Andric }
638bcb0991SDimitry Andric
setupMetaRemarkVersion()648bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaRemarkVersion() {
658bcb0991SDimitry Andric setRecordName(RECORD_META_REMARK_VERSION, Bitstream, R,
668bcb0991SDimitry Andric MetaRemarkVersionName);
678bcb0991SDimitry Andric
688bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
698bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_REMARK_VERSION));
708bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version.
718bcb0991SDimitry Andric RecordMetaRemarkVersionAbbrevID =
728bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
738bcb0991SDimitry Andric }
748bcb0991SDimitry Andric
emitMetaRemarkVersion(uint64_t RemarkVersion)758bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaRemarkVersion(
768bcb0991SDimitry Andric uint64_t RemarkVersion) {
778bcb0991SDimitry Andric // The remark version is emitted only if we emit remarks.
788bcb0991SDimitry Andric R.clear();
798bcb0991SDimitry Andric R.push_back(RECORD_META_REMARK_VERSION);
808bcb0991SDimitry Andric R.push_back(RemarkVersion);
818bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordMetaRemarkVersionAbbrevID, R);
828bcb0991SDimitry Andric }
838bcb0991SDimitry Andric
setupMetaStrTab()848bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaStrTab() {
858bcb0991SDimitry Andric setRecordName(RECORD_META_STRTAB, Bitstream, R, MetaStrTabName);
868bcb0991SDimitry Andric
878bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
888bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_STRTAB));
898bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Raw table.
908bcb0991SDimitry Andric RecordMetaStrTabAbbrevID =
918bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
928bcb0991SDimitry Andric }
938bcb0991SDimitry Andric
emitMetaStrTab(const StringTable & StrTab)948bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaStrTab(
958bcb0991SDimitry Andric const StringTable &StrTab) {
968bcb0991SDimitry Andric // The string table is not emitted if we emit remarks separately.
978bcb0991SDimitry Andric R.clear();
988bcb0991SDimitry Andric R.push_back(RECORD_META_STRTAB);
998bcb0991SDimitry Andric
1008bcb0991SDimitry Andric // Serialize to a blob.
1018bcb0991SDimitry Andric std::string Buf;
1028bcb0991SDimitry Andric raw_string_ostream OS(Buf);
1038bcb0991SDimitry Andric StrTab.serialize(OS);
1048bcb0991SDimitry Andric StringRef Blob = OS.str();
1058bcb0991SDimitry Andric Bitstream.EmitRecordWithBlob(RecordMetaStrTabAbbrevID, R, Blob);
1068bcb0991SDimitry Andric }
1078bcb0991SDimitry Andric
setupMetaExternalFile()1088bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaExternalFile() {
1098bcb0991SDimitry Andric setRecordName(RECORD_META_EXTERNAL_FILE, Bitstream, R, MetaExternalFileName);
1108bcb0991SDimitry Andric
1118bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
1128bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_EXTERNAL_FILE));
1138bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename.
1148bcb0991SDimitry Andric RecordMetaExternalFileAbbrevID =
1158bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev);
1168bcb0991SDimitry Andric }
1178bcb0991SDimitry Andric
emitMetaExternalFile(StringRef Filename)1188bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaExternalFile(StringRef Filename) {
1198bcb0991SDimitry Andric // The external file is emitted only if we emit the separate metadata.
1208bcb0991SDimitry Andric R.clear();
1218bcb0991SDimitry Andric R.push_back(RECORD_META_EXTERNAL_FILE);
1228bcb0991SDimitry Andric Bitstream.EmitRecordWithBlob(RecordMetaExternalFileAbbrevID, R, Filename);
1238bcb0991SDimitry Andric }
1248bcb0991SDimitry Andric
setupRemarkBlockInfo()1258bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupRemarkBlockInfo() {
1268bcb0991SDimitry Andric // Setup the remark block.
1278bcb0991SDimitry Andric initBlock(REMARK_BLOCK_ID, Bitstream, R, RemarkBlockName);
1288bcb0991SDimitry Andric
1298bcb0991SDimitry Andric // The header of a remark.
1308bcb0991SDimitry Andric {
1318bcb0991SDimitry Andric setRecordName(RECORD_REMARK_HEADER, Bitstream, R, RemarkHeaderName);
1328bcb0991SDimitry Andric
1338bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
1348bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HEADER));
1358bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Type
1368bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Remark Name
1378bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Pass name
1388bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Function name
1398bcb0991SDimitry Andric RecordRemarkHeaderAbbrevID =
1408bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
1418bcb0991SDimitry Andric }
1428bcb0991SDimitry Andric
1438bcb0991SDimitry Andric // The location of a remark.
1448bcb0991SDimitry Andric {
1458bcb0991SDimitry Andric setRecordName(RECORD_REMARK_DEBUG_LOC, Bitstream, R, RemarkDebugLocName);
1468bcb0991SDimitry Andric
1478bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
1488bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_DEBUG_LOC));
1498bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File
1508bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
1518bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
1528bcb0991SDimitry Andric RecordRemarkDebugLocAbbrevID =
1538bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
1548bcb0991SDimitry Andric }
1558bcb0991SDimitry Andric
1568bcb0991SDimitry Andric // The hotness of a remark.
1578bcb0991SDimitry Andric {
1588bcb0991SDimitry Andric setRecordName(RECORD_REMARK_HOTNESS, Bitstream, R, RemarkHotnessName);
1598bcb0991SDimitry Andric
1608bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
1618bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HOTNESS));
1628bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Hotness
1638bcb0991SDimitry Andric RecordRemarkHotnessAbbrevID =
1648bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
1658bcb0991SDimitry Andric }
1668bcb0991SDimitry Andric
1678bcb0991SDimitry Andric // An argument entry with a debug location attached.
1688bcb0991SDimitry Andric {
1698bcb0991SDimitry Andric setRecordName(RECORD_REMARK_ARG_WITH_DEBUGLOC, Bitstream, R,
1708bcb0991SDimitry Andric RemarkArgWithDebugLocName);
1718bcb0991SDimitry Andric
1728bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
1738bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITH_DEBUGLOC));
1748bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key
1758bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value
1768bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File
1778bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line
1788bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column
1798bcb0991SDimitry Andric RecordRemarkArgWithDebugLocAbbrevID =
1808bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
1818bcb0991SDimitry Andric }
1828bcb0991SDimitry Andric
1838bcb0991SDimitry Andric // An argument entry with no debug location attached.
1848bcb0991SDimitry Andric {
1858bcb0991SDimitry Andric setRecordName(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC, Bitstream, R,
1868bcb0991SDimitry Andric RemarkArgWithoutDebugLocName);
1878bcb0991SDimitry Andric
1888bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>();
1898bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC));
1908bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key
1918bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value
1928bcb0991SDimitry Andric RecordRemarkArgWithoutDebugLocAbbrevID =
1938bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev);
1948bcb0991SDimitry Andric }
1958bcb0991SDimitry Andric }
1968bcb0991SDimitry Andric
setupBlockInfo()1978bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupBlockInfo() {
1988bcb0991SDimitry Andric // Emit magic number.
1998bcb0991SDimitry Andric for (const char C : ContainerMagic)
2008bcb0991SDimitry Andric Bitstream.Emit(static_cast<unsigned>(C), 8);
2018bcb0991SDimitry Andric
2028bcb0991SDimitry Andric Bitstream.EnterBlockInfoBlock();
2038bcb0991SDimitry Andric
2048bcb0991SDimitry Andric // Setup the main metadata. Depending on the container type, we'll setup the
2058bcb0991SDimitry Andric // required records next.
2068bcb0991SDimitry Andric setupMetaBlockInfo();
2078bcb0991SDimitry Andric
2088bcb0991SDimitry Andric switch (ContainerType) {
2098bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksMeta:
2108bcb0991SDimitry Andric // Needs a string table that the separate remark file is using.
2118bcb0991SDimitry Andric setupMetaStrTab();
2128bcb0991SDimitry Andric // Needs to know where the external remarks file is.
2138bcb0991SDimitry Andric setupMetaExternalFile();
2148bcb0991SDimitry Andric break;
2158bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksFile:
2168bcb0991SDimitry Andric // Contains remarks: emit the version.
2178bcb0991SDimitry Andric setupMetaRemarkVersion();
2188bcb0991SDimitry Andric // Contains remarks: emit the remark abbrevs.
2198bcb0991SDimitry Andric setupRemarkBlockInfo();
2208bcb0991SDimitry Andric break;
2218bcb0991SDimitry Andric case BitstreamRemarkContainerType::Standalone:
2228bcb0991SDimitry Andric // Contains remarks: emit the version.
2238bcb0991SDimitry Andric setupMetaRemarkVersion();
2248bcb0991SDimitry Andric // Needs a string table.
2258bcb0991SDimitry Andric setupMetaStrTab();
2268bcb0991SDimitry Andric // Contains remarks: emit the remark abbrevs.
2278bcb0991SDimitry Andric setupRemarkBlockInfo();
2288bcb0991SDimitry Andric break;
2298bcb0991SDimitry Andric }
2308bcb0991SDimitry Andric
2318bcb0991SDimitry Andric Bitstream.ExitBlock();
2328bcb0991SDimitry Andric }
2338bcb0991SDimitry Andric
emitMetaBlock(uint64_t ContainerVersion,std::optional<uint64_t> RemarkVersion,std::optional<const StringTable * > StrTab,std::optional<StringRef> Filename)2348bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaBlock(
235*bdd1243dSDimitry Andric uint64_t ContainerVersion, std::optional<uint64_t> RemarkVersion,
236*bdd1243dSDimitry Andric std::optional<const StringTable *> StrTab,
237*bdd1243dSDimitry Andric std::optional<StringRef> Filename) {
2388bcb0991SDimitry Andric // Emit the meta block
2398bcb0991SDimitry Andric Bitstream.EnterSubblock(META_BLOCK_ID, 3);
2408bcb0991SDimitry Andric
2418bcb0991SDimitry Andric // The container version and type.
2428bcb0991SDimitry Andric R.clear();
2438bcb0991SDimitry Andric R.push_back(RECORD_META_CONTAINER_INFO);
2448bcb0991SDimitry Andric R.push_back(ContainerVersion);
2458bcb0991SDimitry Andric R.push_back(static_cast<uint64_t>(ContainerType));
2468bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R);
2478bcb0991SDimitry Andric
2488bcb0991SDimitry Andric switch (ContainerType) {
2498bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksMeta:
250*bdd1243dSDimitry Andric assert(StrTab != std::nullopt && *StrTab != nullptr);
2518bcb0991SDimitry Andric emitMetaStrTab(**StrTab);
252*bdd1243dSDimitry Andric assert(Filename != std::nullopt);
2538bcb0991SDimitry Andric emitMetaExternalFile(*Filename);
2548bcb0991SDimitry Andric break;
2558bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksFile:
256*bdd1243dSDimitry Andric assert(RemarkVersion != std::nullopt);
2578bcb0991SDimitry Andric emitMetaRemarkVersion(*RemarkVersion);
2588bcb0991SDimitry Andric break;
2598bcb0991SDimitry Andric case BitstreamRemarkContainerType::Standalone:
260*bdd1243dSDimitry Andric assert(RemarkVersion != std::nullopt);
2618bcb0991SDimitry Andric emitMetaRemarkVersion(*RemarkVersion);
262*bdd1243dSDimitry Andric assert(StrTab != std::nullopt && *StrTab != nullptr);
2638bcb0991SDimitry Andric emitMetaStrTab(**StrTab);
2648bcb0991SDimitry Andric break;
2658bcb0991SDimitry Andric }
2668bcb0991SDimitry Andric
2678bcb0991SDimitry Andric Bitstream.ExitBlock();
2688bcb0991SDimitry Andric }
2698bcb0991SDimitry Andric
emitRemarkBlock(const Remark & Remark,StringTable & StrTab)2708bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark,
2718bcb0991SDimitry Andric StringTable &StrTab) {
2728bcb0991SDimitry Andric Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4);
2738bcb0991SDimitry Andric
2748bcb0991SDimitry Andric R.clear();
2758bcb0991SDimitry Andric R.push_back(RECORD_REMARK_HEADER);
2768bcb0991SDimitry Andric R.push_back(static_cast<uint64_t>(Remark.RemarkType));
2778bcb0991SDimitry Andric R.push_back(StrTab.add(Remark.RemarkName).first);
2788bcb0991SDimitry Andric R.push_back(StrTab.add(Remark.PassName).first);
2798bcb0991SDimitry Andric R.push_back(StrTab.add(Remark.FunctionName).first);
2808bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordRemarkHeaderAbbrevID, R);
2818bcb0991SDimitry Andric
282*bdd1243dSDimitry Andric if (const std::optional<RemarkLocation> &Loc = Remark.Loc) {
2838bcb0991SDimitry Andric R.clear();
2848bcb0991SDimitry Andric R.push_back(RECORD_REMARK_DEBUG_LOC);
2858bcb0991SDimitry Andric R.push_back(StrTab.add(Loc->SourceFilePath).first);
2868bcb0991SDimitry Andric R.push_back(Loc->SourceLine);
2878bcb0991SDimitry Andric R.push_back(Loc->SourceColumn);
2888bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordRemarkDebugLocAbbrevID, R);
2898bcb0991SDimitry Andric }
2908bcb0991SDimitry Andric
291*bdd1243dSDimitry Andric if (std::optional<uint64_t> Hotness = Remark.Hotness) {
2928bcb0991SDimitry Andric R.clear();
2938bcb0991SDimitry Andric R.push_back(RECORD_REMARK_HOTNESS);
2948bcb0991SDimitry Andric R.push_back(*Hotness);
2958bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordRemarkHotnessAbbrevID, R);
2968bcb0991SDimitry Andric }
2978bcb0991SDimitry Andric
2988bcb0991SDimitry Andric for (const Argument &Arg : Remark.Args) {
2998bcb0991SDimitry Andric R.clear();
3008bcb0991SDimitry Andric unsigned Key = StrTab.add(Arg.Key).first;
3018bcb0991SDimitry Andric unsigned Val = StrTab.add(Arg.Val).first;
302*bdd1243dSDimitry Andric bool HasDebugLoc = Arg.Loc != std::nullopt;
3038bcb0991SDimitry Andric R.push_back(HasDebugLoc ? RECORD_REMARK_ARG_WITH_DEBUGLOC
3048bcb0991SDimitry Andric : RECORD_REMARK_ARG_WITHOUT_DEBUGLOC);
3058bcb0991SDimitry Andric R.push_back(Key);
3068bcb0991SDimitry Andric R.push_back(Val);
3078bcb0991SDimitry Andric if (HasDebugLoc) {
3088bcb0991SDimitry Andric R.push_back(StrTab.add(Arg.Loc->SourceFilePath).first);
3098bcb0991SDimitry Andric R.push_back(Arg.Loc->SourceLine);
3108bcb0991SDimitry Andric R.push_back(Arg.Loc->SourceColumn);
3118bcb0991SDimitry Andric }
3128bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(HasDebugLoc
3138bcb0991SDimitry Andric ? RecordRemarkArgWithDebugLocAbbrevID
3148bcb0991SDimitry Andric : RecordRemarkArgWithoutDebugLocAbbrevID,
3158bcb0991SDimitry Andric R);
3168bcb0991SDimitry Andric }
3178bcb0991SDimitry Andric Bitstream.ExitBlock();
3188bcb0991SDimitry Andric }
3198bcb0991SDimitry Andric
flushToStream(raw_ostream & OS)3208bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::flushToStream(raw_ostream &OS) {
3218bcb0991SDimitry Andric OS.write(Encoded.data(), Encoded.size());
3228bcb0991SDimitry Andric Encoded.clear();
3238bcb0991SDimitry Andric }
3248bcb0991SDimitry Andric
getBuffer()3258bcb0991SDimitry Andric StringRef BitstreamRemarkSerializerHelper::getBuffer() {
3268bcb0991SDimitry Andric return StringRef(Encoded.data(), Encoded.size());
3278bcb0991SDimitry Andric }
3288bcb0991SDimitry Andric
BitstreamRemarkSerializer(raw_ostream & OS,SerializerMode Mode)3298bcb0991SDimitry Andric BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
3308bcb0991SDimitry Andric SerializerMode Mode)
3318bcb0991SDimitry Andric : RemarkSerializer(Format::Bitstream, OS, Mode),
3328bcb0991SDimitry Andric Helper(BitstreamRemarkContainerType::SeparateRemarksFile) {
3338bcb0991SDimitry Andric assert(Mode == SerializerMode::Separate &&
3348bcb0991SDimitry Andric "For SerializerMode::Standalone, a pre-filled string table needs to "
3358bcb0991SDimitry Andric "be provided.");
3368bcb0991SDimitry Andric // We always use a string table with bitstream.
3378bcb0991SDimitry Andric StrTab.emplace();
3388bcb0991SDimitry Andric }
3398bcb0991SDimitry Andric
BitstreamRemarkSerializer(raw_ostream & OS,SerializerMode Mode,StringTable StrTabIn)3408bcb0991SDimitry Andric BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
3418bcb0991SDimitry Andric SerializerMode Mode,
3428bcb0991SDimitry Andric StringTable StrTabIn)
3438bcb0991SDimitry Andric : RemarkSerializer(Format::Bitstream, OS, Mode),
3448bcb0991SDimitry Andric Helper(Mode == SerializerMode::Separate
3458bcb0991SDimitry Andric ? BitstreamRemarkContainerType::SeparateRemarksFile
3468bcb0991SDimitry Andric : BitstreamRemarkContainerType::Standalone) {
3478bcb0991SDimitry Andric StrTab = std::move(StrTabIn);
3488bcb0991SDimitry Andric }
3498bcb0991SDimitry Andric
emit(const Remark & Remark)3508bcb0991SDimitry Andric void BitstreamRemarkSerializer::emit(const Remark &Remark) {
3518bcb0991SDimitry Andric if (!DidSetUp) {
3528bcb0991SDimitry Andric // Emit the metadata that is embedded in the remark file.
3538bcb0991SDimitry Andric // If we're in standalone mode, serialize the string table as well.
3548bcb0991SDimitry Andric bool IsStandalone =
3558bcb0991SDimitry Andric Helper.ContainerType == BitstreamRemarkContainerType::Standalone;
3568bcb0991SDimitry Andric BitstreamMetaSerializer MetaSerializer(
3578bcb0991SDimitry Andric OS, Helper,
358*bdd1243dSDimitry Andric IsStandalone ? &*StrTab
359*bdd1243dSDimitry Andric : std::optional<const StringTable *>(std::nullopt));
3608bcb0991SDimitry Andric MetaSerializer.emit();
3618bcb0991SDimitry Andric DidSetUp = true;
3628bcb0991SDimitry Andric }
3638bcb0991SDimitry Andric
3648bcb0991SDimitry Andric assert(DidSetUp &&
3658bcb0991SDimitry Andric "The Block info block and the meta block were not emitted yet.");
3668bcb0991SDimitry Andric Helper.emitRemarkBlock(Remark, *StrTab);
3678bcb0991SDimitry Andric
3688bcb0991SDimitry Andric Helper.flushToStream(OS);
3698bcb0991SDimitry Andric }
3708bcb0991SDimitry Andric
metaSerializer(raw_ostream & OS,std::optional<StringRef> ExternalFilename)3718bcb0991SDimitry Andric std::unique_ptr<MetaSerializer> BitstreamRemarkSerializer::metaSerializer(
372*bdd1243dSDimitry Andric raw_ostream &OS, std::optional<StringRef> ExternalFilename) {
3738bcb0991SDimitry Andric assert(Helper.ContainerType !=
3748bcb0991SDimitry Andric BitstreamRemarkContainerType::SeparateRemarksMeta);
3758bcb0991SDimitry Andric bool IsStandalone =
3768bcb0991SDimitry Andric Helper.ContainerType == BitstreamRemarkContainerType::Standalone;
3778bcb0991SDimitry Andric return std::make_unique<BitstreamMetaSerializer>(
3788bcb0991SDimitry Andric OS,
3798bcb0991SDimitry Andric IsStandalone ? BitstreamRemarkContainerType::Standalone
3808bcb0991SDimitry Andric : BitstreamRemarkContainerType::SeparateRemarksMeta,
3818bcb0991SDimitry Andric &*StrTab, ExternalFilename);
3828bcb0991SDimitry Andric }
3838bcb0991SDimitry Andric
emit()3848bcb0991SDimitry Andric void BitstreamMetaSerializer::emit() {
3858bcb0991SDimitry Andric Helper->setupBlockInfo();
3868bcb0991SDimitry Andric Helper->emitMetaBlock(CurrentContainerVersion, CurrentRemarkVersion, StrTab,
3878bcb0991SDimitry Andric ExternalFilename);
3888bcb0991SDimitry Andric Helper->flushToStream(OS);
3898bcb0991SDimitry Andric }
390