1*8bcb0991SDimitry Andric //===- BitstreamRemarkSerializer.cpp --------------------------------------===// 2*8bcb0991SDimitry Andric // 3*8bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*8bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*8bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*8bcb0991SDimitry Andric // 7*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 8*8bcb0991SDimitry Andric // 9*8bcb0991SDimitry Andric // This file provides the implementation of the LLVM bitstream remark serializer 10*8bcb0991SDimitry Andric // using LLVM's bitstream writer. 11*8bcb0991SDimitry Andric // 12*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 13*8bcb0991SDimitry Andric 14*8bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkSerializer.h" 15*8bcb0991SDimitry Andric 16*8bcb0991SDimitry Andric using namespace llvm; 17*8bcb0991SDimitry Andric using namespace llvm::remarks; 18*8bcb0991SDimitry Andric 19*8bcb0991SDimitry Andric BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper( 20*8bcb0991SDimitry Andric BitstreamRemarkContainerType ContainerType) 21*8bcb0991SDimitry Andric : Encoded(), R(), Bitstream(Encoded), ContainerType(ContainerType) {} 22*8bcb0991SDimitry Andric 23*8bcb0991SDimitry Andric static void push(SmallVectorImpl<uint64_t> &R, StringRef Str) { 24*8bcb0991SDimitry Andric for (const char C : Str) 25*8bcb0991SDimitry Andric R.push_back(C); 26*8bcb0991SDimitry Andric } 27*8bcb0991SDimitry Andric 28*8bcb0991SDimitry Andric static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream, 29*8bcb0991SDimitry Andric SmallVectorImpl<uint64_t> &R, StringRef Str) { 30*8bcb0991SDimitry Andric R.clear(); 31*8bcb0991SDimitry Andric R.push_back(RecordID); 32*8bcb0991SDimitry Andric push(R, Str); 33*8bcb0991SDimitry Andric Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R); 34*8bcb0991SDimitry Andric } 35*8bcb0991SDimitry Andric 36*8bcb0991SDimitry Andric static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream, 37*8bcb0991SDimitry Andric SmallVectorImpl<uint64_t> &R, StringRef Str) { 38*8bcb0991SDimitry Andric R.clear(); 39*8bcb0991SDimitry Andric R.push_back(BlockID); 40*8bcb0991SDimitry Andric Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R); 41*8bcb0991SDimitry Andric 42*8bcb0991SDimitry Andric R.clear(); 43*8bcb0991SDimitry Andric push(R, Str); 44*8bcb0991SDimitry Andric Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R); 45*8bcb0991SDimitry Andric } 46*8bcb0991SDimitry Andric 47*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaBlockInfo() { 48*8bcb0991SDimitry Andric // Setup the metadata block. 49*8bcb0991SDimitry Andric initBlock(META_BLOCK_ID, Bitstream, R, MetaBlockName); 50*8bcb0991SDimitry Andric 51*8bcb0991SDimitry Andric // The container information. 52*8bcb0991SDimitry Andric setRecordName(RECORD_META_CONTAINER_INFO, Bitstream, R, 53*8bcb0991SDimitry Andric MetaContainerInfoName); 54*8bcb0991SDimitry Andric 55*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 56*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_CONTAINER_INFO)); 57*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version. 58*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Type. 59*8bcb0991SDimitry Andric RecordMetaContainerInfoAbbrevID = 60*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev); 61*8bcb0991SDimitry Andric } 62*8bcb0991SDimitry Andric 63*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaRemarkVersion() { 64*8bcb0991SDimitry Andric setRecordName(RECORD_META_REMARK_VERSION, Bitstream, R, 65*8bcb0991SDimitry Andric MetaRemarkVersionName); 66*8bcb0991SDimitry Andric 67*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 68*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_REMARK_VERSION)); 69*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Version. 70*8bcb0991SDimitry Andric RecordMetaRemarkVersionAbbrevID = 71*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev); 72*8bcb0991SDimitry Andric } 73*8bcb0991SDimitry Andric 74*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaRemarkVersion( 75*8bcb0991SDimitry Andric uint64_t RemarkVersion) { 76*8bcb0991SDimitry Andric // The remark version is emitted only if we emit remarks. 77*8bcb0991SDimitry Andric R.clear(); 78*8bcb0991SDimitry Andric R.push_back(RECORD_META_REMARK_VERSION); 79*8bcb0991SDimitry Andric R.push_back(RemarkVersion); 80*8bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordMetaRemarkVersionAbbrevID, R); 81*8bcb0991SDimitry Andric } 82*8bcb0991SDimitry Andric 83*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaStrTab() { 84*8bcb0991SDimitry Andric setRecordName(RECORD_META_STRTAB, Bitstream, R, MetaStrTabName); 85*8bcb0991SDimitry Andric 86*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 87*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_STRTAB)); 88*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Raw table. 89*8bcb0991SDimitry Andric RecordMetaStrTabAbbrevID = 90*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev); 91*8bcb0991SDimitry Andric } 92*8bcb0991SDimitry Andric 93*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaStrTab( 94*8bcb0991SDimitry Andric const StringTable &StrTab) { 95*8bcb0991SDimitry Andric // The string table is not emitted if we emit remarks separately. 96*8bcb0991SDimitry Andric R.clear(); 97*8bcb0991SDimitry Andric R.push_back(RECORD_META_STRTAB); 98*8bcb0991SDimitry Andric 99*8bcb0991SDimitry Andric // Serialize to a blob. 100*8bcb0991SDimitry Andric std::string Buf; 101*8bcb0991SDimitry Andric raw_string_ostream OS(Buf); 102*8bcb0991SDimitry Andric StrTab.serialize(OS); 103*8bcb0991SDimitry Andric StringRef Blob = OS.str(); 104*8bcb0991SDimitry Andric Bitstream.EmitRecordWithBlob(RecordMetaStrTabAbbrevID, R, Blob); 105*8bcb0991SDimitry Andric } 106*8bcb0991SDimitry Andric 107*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupMetaExternalFile() { 108*8bcb0991SDimitry Andric setRecordName(RECORD_META_EXTERNAL_FILE, Bitstream, R, MetaExternalFileName); 109*8bcb0991SDimitry Andric 110*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 111*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_META_EXTERNAL_FILE)); 112*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename. 113*8bcb0991SDimitry Andric RecordMetaExternalFileAbbrevID = 114*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(META_BLOCK_ID, Abbrev); 115*8bcb0991SDimitry Andric } 116*8bcb0991SDimitry Andric 117*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaExternalFile(StringRef Filename) { 118*8bcb0991SDimitry Andric // The external file is emitted only if we emit the separate metadata. 119*8bcb0991SDimitry Andric R.clear(); 120*8bcb0991SDimitry Andric R.push_back(RECORD_META_EXTERNAL_FILE); 121*8bcb0991SDimitry Andric Bitstream.EmitRecordWithBlob(RecordMetaExternalFileAbbrevID, R, Filename); 122*8bcb0991SDimitry Andric } 123*8bcb0991SDimitry Andric 124*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupRemarkBlockInfo() { 125*8bcb0991SDimitry Andric // Setup the remark block. 126*8bcb0991SDimitry Andric initBlock(REMARK_BLOCK_ID, Bitstream, R, RemarkBlockName); 127*8bcb0991SDimitry Andric 128*8bcb0991SDimitry Andric // The header of a remark. 129*8bcb0991SDimitry Andric { 130*8bcb0991SDimitry Andric setRecordName(RECORD_REMARK_HEADER, Bitstream, R, RemarkHeaderName); 131*8bcb0991SDimitry Andric 132*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 133*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HEADER)); 134*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Type 135*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Remark Name 136*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Pass name 137*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Function name 138*8bcb0991SDimitry Andric RecordRemarkHeaderAbbrevID = 139*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev); 140*8bcb0991SDimitry Andric } 141*8bcb0991SDimitry Andric 142*8bcb0991SDimitry Andric // The location of a remark. 143*8bcb0991SDimitry Andric { 144*8bcb0991SDimitry Andric setRecordName(RECORD_REMARK_DEBUG_LOC, Bitstream, R, RemarkDebugLocName); 145*8bcb0991SDimitry Andric 146*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 147*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_DEBUG_LOC)); 148*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File 149*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line 150*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column 151*8bcb0991SDimitry Andric RecordRemarkDebugLocAbbrevID = 152*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev); 153*8bcb0991SDimitry Andric } 154*8bcb0991SDimitry Andric 155*8bcb0991SDimitry Andric // The hotness of a remark. 156*8bcb0991SDimitry Andric { 157*8bcb0991SDimitry Andric setRecordName(RECORD_REMARK_HOTNESS, Bitstream, R, RemarkHotnessName); 158*8bcb0991SDimitry Andric 159*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 160*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_HOTNESS)); 161*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Hotness 162*8bcb0991SDimitry Andric RecordRemarkHotnessAbbrevID = 163*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev); 164*8bcb0991SDimitry Andric } 165*8bcb0991SDimitry Andric 166*8bcb0991SDimitry Andric // An argument entry with a debug location attached. 167*8bcb0991SDimitry Andric { 168*8bcb0991SDimitry Andric setRecordName(RECORD_REMARK_ARG_WITH_DEBUGLOC, Bitstream, R, 169*8bcb0991SDimitry Andric RemarkArgWithDebugLocName); 170*8bcb0991SDimitry Andric 171*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 172*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITH_DEBUGLOC)); 173*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key 174*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value 175*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // File 176*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line 177*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column 178*8bcb0991SDimitry Andric RecordRemarkArgWithDebugLocAbbrevID = 179*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev); 180*8bcb0991SDimitry Andric } 181*8bcb0991SDimitry Andric 182*8bcb0991SDimitry Andric // An argument entry with no debug location attached. 183*8bcb0991SDimitry Andric { 184*8bcb0991SDimitry Andric setRecordName(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC, Bitstream, R, 185*8bcb0991SDimitry Andric RemarkArgWithoutDebugLocName); 186*8bcb0991SDimitry Andric 187*8bcb0991SDimitry Andric auto Abbrev = std::make_shared<BitCodeAbbrev>(); 188*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(RECORD_REMARK_ARG_WITHOUT_DEBUGLOC)); 189*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Key 190*8bcb0991SDimitry Andric Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // Value 191*8bcb0991SDimitry Andric RecordRemarkArgWithoutDebugLocAbbrevID = 192*8bcb0991SDimitry Andric Bitstream.EmitBlockInfoAbbrev(REMARK_BLOCK_ID, Abbrev); 193*8bcb0991SDimitry Andric } 194*8bcb0991SDimitry Andric } 195*8bcb0991SDimitry Andric 196*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::setupBlockInfo() { 197*8bcb0991SDimitry Andric // Emit magic number. 198*8bcb0991SDimitry Andric for (const char C : ContainerMagic) 199*8bcb0991SDimitry Andric Bitstream.Emit(static_cast<unsigned>(C), 8); 200*8bcb0991SDimitry Andric 201*8bcb0991SDimitry Andric Bitstream.EnterBlockInfoBlock(); 202*8bcb0991SDimitry Andric 203*8bcb0991SDimitry Andric // Setup the main metadata. Depending on the container type, we'll setup the 204*8bcb0991SDimitry Andric // required records next. 205*8bcb0991SDimitry Andric setupMetaBlockInfo(); 206*8bcb0991SDimitry Andric 207*8bcb0991SDimitry Andric switch (ContainerType) { 208*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksMeta: 209*8bcb0991SDimitry Andric // Needs a string table that the separate remark file is using. 210*8bcb0991SDimitry Andric setupMetaStrTab(); 211*8bcb0991SDimitry Andric // Needs to know where the external remarks file is. 212*8bcb0991SDimitry Andric setupMetaExternalFile(); 213*8bcb0991SDimitry Andric break; 214*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksFile: 215*8bcb0991SDimitry Andric // Contains remarks: emit the version. 216*8bcb0991SDimitry Andric setupMetaRemarkVersion(); 217*8bcb0991SDimitry Andric // Contains remarks: emit the remark abbrevs. 218*8bcb0991SDimitry Andric setupRemarkBlockInfo(); 219*8bcb0991SDimitry Andric break; 220*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::Standalone: 221*8bcb0991SDimitry Andric // Contains remarks: emit the version. 222*8bcb0991SDimitry Andric setupMetaRemarkVersion(); 223*8bcb0991SDimitry Andric // Needs a string table. 224*8bcb0991SDimitry Andric setupMetaStrTab(); 225*8bcb0991SDimitry Andric // Contains remarks: emit the remark abbrevs. 226*8bcb0991SDimitry Andric setupRemarkBlockInfo(); 227*8bcb0991SDimitry Andric break; 228*8bcb0991SDimitry Andric } 229*8bcb0991SDimitry Andric 230*8bcb0991SDimitry Andric Bitstream.ExitBlock(); 231*8bcb0991SDimitry Andric } 232*8bcb0991SDimitry Andric 233*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitMetaBlock( 234*8bcb0991SDimitry Andric uint64_t ContainerVersion, Optional<uint64_t> RemarkVersion, 235*8bcb0991SDimitry Andric Optional<const StringTable *> StrTab, Optional<StringRef> Filename) { 236*8bcb0991SDimitry Andric // Emit the meta block 237*8bcb0991SDimitry Andric Bitstream.EnterSubblock(META_BLOCK_ID, 3); 238*8bcb0991SDimitry Andric 239*8bcb0991SDimitry Andric // The container version and type. 240*8bcb0991SDimitry Andric R.clear(); 241*8bcb0991SDimitry Andric R.push_back(RECORD_META_CONTAINER_INFO); 242*8bcb0991SDimitry Andric R.push_back(ContainerVersion); 243*8bcb0991SDimitry Andric R.push_back(static_cast<uint64_t>(ContainerType)); 244*8bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R); 245*8bcb0991SDimitry Andric 246*8bcb0991SDimitry Andric switch (ContainerType) { 247*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksMeta: 248*8bcb0991SDimitry Andric assert(StrTab != None && *StrTab != nullptr); 249*8bcb0991SDimitry Andric emitMetaStrTab(**StrTab); 250*8bcb0991SDimitry Andric assert(Filename != None); 251*8bcb0991SDimitry Andric emitMetaExternalFile(*Filename); 252*8bcb0991SDimitry Andric break; 253*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksFile: 254*8bcb0991SDimitry Andric assert(RemarkVersion != None); 255*8bcb0991SDimitry Andric emitMetaRemarkVersion(*RemarkVersion); 256*8bcb0991SDimitry Andric break; 257*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::Standalone: 258*8bcb0991SDimitry Andric assert(RemarkVersion != None); 259*8bcb0991SDimitry Andric emitMetaRemarkVersion(*RemarkVersion); 260*8bcb0991SDimitry Andric assert(StrTab != None && *StrTab != nullptr); 261*8bcb0991SDimitry Andric emitMetaStrTab(**StrTab); 262*8bcb0991SDimitry Andric break; 263*8bcb0991SDimitry Andric } 264*8bcb0991SDimitry Andric 265*8bcb0991SDimitry Andric Bitstream.ExitBlock(); 266*8bcb0991SDimitry Andric } 267*8bcb0991SDimitry Andric 268*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark, 269*8bcb0991SDimitry Andric StringTable &StrTab) { 270*8bcb0991SDimitry Andric Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4); 271*8bcb0991SDimitry Andric 272*8bcb0991SDimitry Andric R.clear(); 273*8bcb0991SDimitry Andric R.push_back(RECORD_REMARK_HEADER); 274*8bcb0991SDimitry Andric R.push_back(static_cast<uint64_t>(Remark.RemarkType)); 275*8bcb0991SDimitry Andric R.push_back(StrTab.add(Remark.RemarkName).first); 276*8bcb0991SDimitry Andric R.push_back(StrTab.add(Remark.PassName).first); 277*8bcb0991SDimitry Andric R.push_back(StrTab.add(Remark.FunctionName).first); 278*8bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordRemarkHeaderAbbrevID, R); 279*8bcb0991SDimitry Andric 280*8bcb0991SDimitry Andric if (const Optional<RemarkLocation> &Loc = Remark.Loc) { 281*8bcb0991SDimitry Andric R.clear(); 282*8bcb0991SDimitry Andric R.push_back(RECORD_REMARK_DEBUG_LOC); 283*8bcb0991SDimitry Andric R.push_back(StrTab.add(Loc->SourceFilePath).first); 284*8bcb0991SDimitry Andric R.push_back(Loc->SourceLine); 285*8bcb0991SDimitry Andric R.push_back(Loc->SourceColumn); 286*8bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordRemarkDebugLocAbbrevID, R); 287*8bcb0991SDimitry Andric } 288*8bcb0991SDimitry Andric 289*8bcb0991SDimitry Andric if (Optional<uint64_t> Hotness = Remark.Hotness) { 290*8bcb0991SDimitry Andric R.clear(); 291*8bcb0991SDimitry Andric R.push_back(RECORD_REMARK_HOTNESS); 292*8bcb0991SDimitry Andric R.push_back(*Hotness); 293*8bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(RecordRemarkHotnessAbbrevID, R); 294*8bcb0991SDimitry Andric } 295*8bcb0991SDimitry Andric 296*8bcb0991SDimitry Andric for (const Argument &Arg : Remark.Args) { 297*8bcb0991SDimitry Andric R.clear(); 298*8bcb0991SDimitry Andric unsigned Key = StrTab.add(Arg.Key).first; 299*8bcb0991SDimitry Andric unsigned Val = StrTab.add(Arg.Val).first; 300*8bcb0991SDimitry Andric bool HasDebugLoc = Arg.Loc != None; 301*8bcb0991SDimitry Andric R.push_back(HasDebugLoc ? RECORD_REMARK_ARG_WITH_DEBUGLOC 302*8bcb0991SDimitry Andric : RECORD_REMARK_ARG_WITHOUT_DEBUGLOC); 303*8bcb0991SDimitry Andric R.push_back(Key); 304*8bcb0991SDimitry Andric R.push_back(Val); 305*8bcb0991SDimitry Andric if (HasDebugLoc) { 306*8bcb0991SDimitry Andric R.push_back(StrTab.add(Arg.Loc->SourceFilePath).first); 307*8bcb0991SDimitry Andric R.push_back(Arg.Loc->SourceLine); 308*8bcb0991SDimitry Andric R.push_back(Arg.Loc->SourceColumn); 309*8bcb0991SDimitry Andric } 310*8bcb0991SDimitry Andric Bitstream.EmitRecordWithAbbrev(HasDebugLoc 311*8bcb0991SDimitry Andric ? RecordRemarkArgWithDebugLocAbbrevID 312*8bcb0991SDimitry Andric : RecordRemarkArgWithoutDebugLocAbbrevID, 313*8bcb0991SDimitry Andric R); 314*8bcb0991SDimitry Andric } 315*8bcb0991SDimitry Andric Bitstream.ExitBlock(); 316*8bcb0991SDimitry Andric } 317*8bcb0991SDimitry Andric 318*8bcb0991SDimitry Andric void BitstreamRemarkSerializerHelper::flushToStream(raw_ostream &OS) { 319*8bcb0991SDimitry Andric OS.write(Encoded.data(), Encoded.size()); 320*8bcb0991SDimitry Andric Encoded.clear(); 321*8bcb0991SDimitry Andric } 322*8bcb0991SDimitry Andric 323*8bcb0991SDimitry Andric StringRef BitstreamRemarkSerializerHelper::getBuffer() { 324*8bcb0991SDimitry Andric return StringRef(Encoded.data(), Encoded.size()); 325*8bcb0991SDimitry Andric } 326*8bcb0991SDimitry Andric 327*8bcb0991SDimitry Andric BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS, 328*8bcb0991SDimitry Andric SerializerMode Mode) 329*8bcb0991SDimitry Andric : RemarkSerializer(Format::Bitstream, OS, Mode), 330*8bcb0991SDimitry Andric Helper(BitstreamRemarkContainerType::SeparateRemarksFile) { 331*8bcb0991SDimitry Andric assert(Mode == SerializerMode::Separate && 332*8bcb0991SDimitry Andric "For SerializerMode::Standalone, a pre-filled string table needs to " 333*8bcb0991SDimitry Andric "be provided."); 334*8bcb0991SDimitry Andric // We always use a string table with bitstream. 335*8bcb0991SDimitry Andric StrTab.emplace(); 336*8bcb0991SDimitry Andric } 337*8bcb0991SDimitry Andric 338*8bcb0991SDimitry Andric BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS, 339*8bcb0991SDimitry Andric SerializerMode Mode, 340*8bcb0991SDimitry Andric StringTable StrTabIn) 341*8bcb0991SDimitry Andric : RemarkSerializer(Format::Bitstream, OS, Mode), 342*8bcb0991SDimitry Andric Helper(Mode == SerializerMode::Separate 343*8bcb0991SDimitry Andric ? BitstreamRemarkContainerType::SeparateRemarksFile 344*8bcb0991SDimitry Andric : BitstreamRemarkContainerType::Standalone) { 345*8bcb0991SDimitry Andric StrTab = std::move(StrTabIn); 346*8bcb0991SDimitry Andric } 347*8bcb0991SDimitry Andric 348*8bcb0991SDimitry Andric void BitstreamRemarkSerializer::emit(const Remark &Remark) { 349*8bcb0991SDimitry Andric if (!DidSetUp) { 350*8bcb0991SDimitry Andric // Emit the metadata that is embedded in the remark file. 351*8bcb0991SDimitry Andric // If we're in standalone mode, serialize the string table as well. 352*8bcb0991SDimitry Andric bool IsStandalone = 353*8bcb0991SDimitry Andric Helper.ContainerType == BitstreamRemarkContainerType::Standalone; 354*8bcb0991SDimitry Andric BitstreamMetaSerializer MetaSerializer( 355*8bcb0991SDimitry Andric OS, Helper, 356*8bcb0991SDimitry Andric IsStandalone ? &*StrTab : Optional<const StringTable *>(None)); 357*8bcb0991SDimitry Andric MetaSerializer.emit(); 358*8bcb0991SDimitry Andric DidSetUp = true; 359*8bcb0991SDimitry Andric } 360*8bcb0991SDimitry Andric 361*8bcb0991SDimitry Andric assert(DidSetUp && 362*8bcb0991SDimitry Andric "The Block info block and the meta block were not emitted yet."); 363*8bcb0991SDimitry Andric Helper.emitRemarkBlock(Remark, *StrTab); 364*8bcb0991SDimitry Andric 365*8bcb0991SDimitry Andric Helper.flushToStream(OS); 366*8bcb0991SDimitry Andric } 367*8bcb0991SDimitry Andric 368*8bcb0991SDimitry Andric std::unique_ptr<MetaSerializer> BitstreamRemarkSerializer::metaSerializer( 369*8bcb0991SDimitry Andric raw_ostream &OS, Optional<StringRef> ExternalFilename) { 370*8bcb0991SDimitry Andric assert(Helper.ContainerType != 371*8bcb0991SDimitry Andric BitstreamRemarkContainerType::SeparateRemarksMeta); 372*8bcb0991SDimitry Andric bool IsStandalone = 373*8bcb0991SDimitry Andric Helper.ContainerType == BitstreamRemarkContainerType::Standalone; 374*8bcb0991SDimitry Andric return std::make_unique<BitstreamMetaSerializer>( 375*8bcb0991SDimitry Andric OS, 376*8bcb0991SDimitry Andric IsStandalone ? BitstreamRemarkContainerType::Standalone 377*8bcb0991SDimitry Andric : BitstreamRemarkContainerType::SeparateRemarksMeta, 378*8bcb0991SDimitry Andric &*StrTab, ExternalFilename); 379*8bcb0991SDimitry Andric } 380*8bcb0991SDimitry Andric 381*8bcb0991SDimitry Andric void BitstreamMetaSerializer::emit() { 382*8bcb0991SDimitry Andric Helper->setupBlockInfo(); 383*8bcb0991SDimitry Andric Helper->emitMetaBlock(CurrentContainerVersion, CurrentRemarkVersion, StrTab, 384*8bcb0991SDimitry Andric ExternalFilename); 385*8bcb0991SDimitry Andric Helper->flushToStream(OS); 386*8bcb0991SDimitry Andric } 387