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