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