xref: /freebsd-src/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
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