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