xref: /freebsd-src/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkParser.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
1*8bcb0991SDimitry Andric //===- BitstreamRemarkParser.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 utility methods used by clients that want to use the
10*8bcb0991SDimitry Andric // parser for remark diagnostics in LLVM.
11*8bcb0991SDimitry Andric //
12*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
13*8bcb0991SDimitry Andric 
14*8bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkParser.h"
15*8bcb0991SDimitry Andric #include "BitstreamRemarkParser.h"
16*8bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkContainer.h"
17*8bcb0991SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
18*8bcb0991SDimitry Andric #include "llvm/Support/Path.h"
19*8bcb0991SDimitry Andric 
20*8bcb0991SDimitry Andric using namespace llvm;
21*8bcb0991SDimitry Andric using namespace llvm::remarks;
22*8bcb0991SDimitry Andric 
23*8bcb0991SDimitry Andric static Error unknownRecord(const char *BlockName, unsigned RecordID) {
24*8bcb0991SDimitry Andric   return createStringError(
25*8bcb0991SDimitry Andric       std::make_error_code(std::errc::illegal_byte_sequence),
26*8bcb0991SDimitry Andric       "Error while parsing %s: unknown record entry (%lu).", BlockName,
27*8bcb0991SDimitry Andric       RecordID);
28*8bcb0991SDimitry Andric }
29*8bcb0991SDimitry Andric 
30*8bcb0991SDimitry Andric static Error malformedRecord(const char *BlockName, const char *RecordName) {
31*8bcb0991SDimitry Andric   return createStringError(
32*8bcb0991SDimitry Andric       std::make_error_code(std::errc::illegal_byte_sequence),
33*8bcb0991SDimitry Andric       "Error while parsing %s: malformed record entry (%s).", BlockName,
34*8bcb0991SDimitry Andric       RecordName);
35*8bcb0991SDimitry Andric }
36*8bcb0991SDimitry Andric 
37*8bcb0991SDimitry Andric BitstreamMetaParserHelper::BitstreamMetaParserHelper(
38*8bcb0991SDimitry Andric     BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo)
39*8bcb0991SDimitry Andric     : Stream(Stream), BlockInfo(BlockInfo) {}
40*8bcb0991SDimitry Andric 
41*8bcb0991SDimitry Andric /// Parse a record and fill in the fields in the parser.
42*8bcb0991SDimitry Andric static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code) {
43*8bcb0991SDimitry Andric   BitstreamCursor &Stream = Parser.Stream;
44*8bcb0991SDimitry Andric   // Note: 2 is used here because it's the max number of fields we have per
45*8bcb0991SDimitry Andric   // record.
46*8bcb0991SDimitry Andric   SmallVector<uint64_t, 2> Record;
47*8bcb0991SDimitry Andric   StringRef Blob;
48*8bcb0991SDimitry Andric   Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob);
49*8bcb0991SDimitry Andric   if (!RecordID)
50*8bcb0991SDimitry Andric     return RecordID.takeError();
51*8bcb0991SDimitry Andric 
52*8bcb0991SDimitry Andric   switch (*RecordID) {
53*8bcb0991SDimitry Andric   case RECORD_META_CONTAINER_INFO: {
54*8bcb0991SDimitry Andric     if (Record.size() != 2)
55*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_CONTAINER_INFO");
56*8bcb0991SDimitry Andric     Parser.ContainerVersion = Record[0];
57*8bcb0991SDimitry Andric     Parser.ContainerType = Record[1];
58*8bcb0991SDimitry Andric     break;
59*8bcb0991SDimitry Andric   }
60*8bcb0991SDimitry Andric   case RECORD_META_REMARK_VERSION: {
61*8bcb0991SDimitry Andric     if (Record.size() != 1)
62*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_REMARK_VERSION");
63*8bcb0991SDimitry Andric     Parser.RemarkVersion = Record[0];
64*8bcb0991SDimitry Andric     break;
65*8bcb0991SDimitry Andric   }
66*8bcb0991SDimitry Andric   case RECORD_META_STRTAB: {
67*8bcb0991SDimitry Andric     if (Record.size() != 0)
68*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_STRTAB");
69*8bcb0991SDimitry Andric     Parser.StrTabBuf = Blob;
70*8bcb0991SDimitry Andric     break;
71*8bcb0991SDimitry Andric   }
72*8bcb0991SDimitry Andric   case RECORD_META_EXTERNAL_FILE: {
73*8bcb0991SDimitry Andric     if (Record.size() != 0)
74*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_EXTERNAL_FILE");
75*8bcb0991SDimitry Andric     Parser.ExternalFilePath = Blob;
76*8bcb0991SDimitry Andric     break;
77*8bcb0991SDimitry Andric   }
78*8bcb0991SDimitry Andric   default:
79*8bcb0991SDimitry Andric     return unknownRecord("BLOCK_META", *RecordID);
80*8bcb0991SDimitry Andric   }
81*8bcb0991SDimitry Andric   return Error::success();
82*8bcb0991SDimitry Andric }
83*8bcb0991SDimitry Andric 
84*8bcb0991SDimitry Andric BitstreamRemarkParserHelper::BitstreamRemarkParserHelper(
85*8bcb0991SDimitry Andric     BitstreamCursor &Stream)
86*8bcb0991SDimitry Andric     : Stream(Stream) {}
87*8bcb0991SDimitry Andric 
88*8bcb0991SDimitry Andric /// Parse a record and fill in the fields in the parser.
89*8bcb0991SDimitry Andric static Error parseRecord(BitstreamRemarkParserHelper &Parser, unsigned Code) {
90*8bcb0991SDimitry Andric   BitstreamCursor &Stream = Parser.Stream;
91*8bcb0991SDimitry Andric   // Note: 5 is used here because it's the max number of fields we have per
92*8bcb0991SDimitry Andric   // record.
93*8bcb0991SDimitry Andric   SmallVector<uint64_t, 5> Record;
94*8bcb0991SDimitry Andric   StringRef Blob;
95*8bcb0991SDimitry Andric   Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob);
96*8bcb0991SDimitry Andric   if (!RecordID)
97*8bcb0991SDimitry Andric     return RecordID.takeError();
98*8bcb0991SDimitry Andric 
99*8bcb0991SDimitry Andric   switch (*RecordID) {
100*8bcb0991SDimitry Andric   case RECORD_REMARK_HEADER: {
101*8bcb0991SDimitry Andric     if (Record.size() != 4)
102*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HEADER");
103*8bcb0991SDimitry Andric     Parser.Type = Record[0];
104*8bcb0991SDimitry Andric     Parser.RemarkNameIdx = Record[1];
105*8bcb0991SDimitry Andric     Parser.PassNameIdx = Record[2];
106*8bcb0991SDimitry Andric     Parser.FunctionNameIdx = Record[3];
107*8bcb0991SDimitry Andric     break;
108*8bcb0991SDimitry Andric   }
109*8bcb0991SDimitry Andric   case RECORD_REMARK_DEBUG_LOC: {
110*8bcb0991SDimitry Andric     if (Record.size() != 3)
111*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_DEBUG_LOC");
112*8bcb0991SDimitry Andric     Parser.SourceFileNameIdx = Record[0];
113*8bcb0991SDimitry Andric     Parser.SourceLine = Record[1];
114*8bcb0991SDimitry Andric     Parser.SourceColumn = Record[2];
115*8bcb0991SDimitry Andric     break;
116*8bcb0991SDimitry Andric   }
117*8bcb0991SDimitry Andric   case RECORD_REMARK_HOTNESS: {
118*8bcb0991SDimitry Andric     if (Record.size() != 1)
119*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HOTNESS");
120*8bcb0991SDimitry Andric     Parser.Hotness = Record[0];
121*8bcb0991SDimitry Andric     break;
122*8bcb0991SDimitry Andric   }
123*8bcb0991SDimitry Andric   case RECORD_REMARK_ARG_WITH_DEBUGLOC: {
124*8bcb0991SDimitry Andric     if (Record.size() != 5)
125*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_ARG_WITH_DEBUGLOC");
126*8bcb0991SDimitry Andric     // Create a temporary argument. Use that as a valid memory location for this
127*8bcb0991SDimitry Andric     // argument entry.
128*8bcb0991SDimitry Andric     Parser.TmpArgs.emplace_back();
129*8bcb0991SDimitry Andric     Parser.TmpArgs.back().KeyIdx = Record[0];
130*8bcb0991SDimitry Andric     Parser.TmpArgs.back().ValueIdx = Record[1];
131*8bcb0991SDimitry Andric     Parser.TmpArgs.back().SourceFileNameIdx = Record[2];
132*8bcb0991SDimitry Andric     Parser.TmpArgs.back().SourceLine = Record[3];
133*8bcb0991SDimitry Andric     Parser.TmpArgs.back().SourceColumn = Record[4];
134*8bcb0991SDimitry Andric     Parser.Args =
135*8bcb0991SDimitry Andric         ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs);
136*8bcb0991SDimitry Andric     break;
137*8bcb0991SDimitry Andric   }
138*8bcb0991SDimitry Andric   case RECORD_REMARK_ARG_WITHOUT_DEBUGLOC: {
139*8bcb0991SDimitry Andric     if (Record.size() != 2)
140*8bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK",
141*8bcb0991SDimitry Andric                              "RECORD_REMARK_ARG_WITHOUT_DEBUGLOC");
142*8bcb0991SDimitry Andric     // Create a temporary argument. Use that as a valid memory location for this
143*8bcb0991SDimitry Andric     // argument entry.
144*8bcb0991SDimitry Andric     Parser.TmpArgs.emplace_back();
145*8bcb0991SDimitry Andric     Parser.TmpArgs.back().KeyIdx = Record[0];
146*8bcb0991SDimitry Andric     Parser.TmpArgs.back().ValueIdx = Record[1];
147*8bcb0991SDimitry Andric     Parser.Args =
148*8bcb0991SDimitry Andric         ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs);
149*8bcb0991SDimitry Andric     break;
150*8bcb0991SDimitry Andric   }
151*8bcb0991SDimitry Andric   default:
152*8bcb0991SDimitry Andric     return unknownRecord("BLOCK_REMARK", *RecordID);
153*8bcb0991SDimitry Andric   }
154*8bcb0991SDimitry Andric   return Error::success();
155*8bcb0991SDimitry Andric }
156*8bcb0991SDimitry Andric 
157*8bcb0991SDimitry Andric template <typename T>
158*8bcb0991SDimitry Andric static Error parseBlock(T &ParserHelper, unsigned BlockID,
159*8bcb0991SDimitry Andric                         const char *BlockName) {
160*8bcb0991SDimitry Andric   BitstreamCursor &Stream = ParserHelper.Stream;
161*8bcb0991SDimitry Andric   Expected<BitstreamEntry> Next = Stream.advance();
162*8bcb0991SDimitry Andric   if (!Next)
163*8bcb0991SDimitry Andric     return Next.takeError();
164*8bcb0991SDimitry Andric   if (Next->Kind != BitstreamEntry::SubBlock || Next->ID != BlockID)
165*8bcb0991SDimitry Andric     return createStringError(
166*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
167*8bcb0991SDimitry Andric         "Error while parsing %s: expecting [ENTER_SUBBLOCK, %s, ...].",
168*8bcb0991SDimitry Andric         BlockName, BlockName);
169*8bcb0991SDimitry Andric   if (Stream.EnterSubBlock(BlockID))
170*8bcb0991SDimitry Andric     return createStringError(
171*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
172*8bcb0991SDimitry Andric         "Error while entering %s.", BlockName);
173*8bcb0991SDimitry Andric 
174*8bcb0991SDimitry Andric   // Stop when there is nothing to read anymore or when we encounter an
175*8bcb0991SDimitry Andric   // END_BLOCK.
176*8bcb0991SDimitry Andric   while (!Stream.AtEndOfStream()) {
177*8bcb0991SDimitry Andric     Expected<BitstreamEntry> Next = Stream.advance();
178*8bcb0991SDimitry Andric     if (!Next)
179*8bcb0991SDimitry Andric       return Next.takeError();
180*8bcb0991SDimitry Andric     switch (Next->Kind) {
181*8bcb0991SDimitry Andric     case BitstreamEntry::EndBlock:
182*8bcb0991SDimitry Andric       return Error::success();
183*8bcb0991SDimitry Andric     case BitstreamEntry::Error:
184*8bcb0991SDimitry Andric     case BitstreamEntry::SubBlock:
185*8bcb0991SDimitry Andric       return createStringError(
186*8bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
187*8bcb0991SDimitry Andric           "Error while parsing %s: expecting records.", BlockName);
188*8bcb0991SDimitry Andric     case BitstreamEntry::Record:
189*8bcb0991SDimitry Andric       if (Error E = parseRecord(ParserHelper, Next->ID))
190*8bcb0991SDimitry Andric         return E;
191*8bcb0991SDimitry Andric       continue;
192*8bcb0991SDimitry Andric     }
193*8bcb0991SDimitry Andric   }
194*8bcb0991SDimitry Andric   // If we're here, it means we didn't get an END_BLOCK yet, but we're at the
195*8bcb0991SDimitry Andric   // end of the stream. In this case, error.
196*8bcb0991SDimitry Andric   return createStringError(
197*8bcb0991SDimitry Andric       std::make_error_code(std::errc::illegal_byte_sequence),
198*8bcb0991SDimitry Andric       "Error while parsing %s: unterminated block.", BlockName);
199*8bcb0991SDimitry Andric }
200*8bcb0991SDimitry Andric 
201*8bcb0991SDimitry Andric Error BitstreamMetaParserHelper::parse() {
202*8bcb0991SDimitry Andric   return parseBlock(*this, META_BLOCK_ID, "META_BLOCK");
203*8bcb0991SDimitry Andric }
204*8bcb0991SDimitry Andric 
205*8bcb0991SDimitry Andric Error BitstreamRemarkParserHelper::parse() {
206*8bcb0991SDimitry Andric   return parseBlock(*this, REMARK_BLOCK_ID, "REMARK_BLOCK");
207*8bcb0991SDimitry Andric }
208*8bcb0991SDimitry Andric 
209*8bcb0991SDimitry Andric BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer)
210*8bcb0991SDimitry Andric     : Stream(Buffer) {}
211*8bcb0991SDimitry Andric 
212*8bcb0991SDimitry Andric Expected<std::array<char, 4>> BitstreamParserHelper::parseMagic() {
213*8bcb0991SDimitry Andric   std::array<char, 4> Result;
214*8bcb0991SDimitry Andric   for (unsigned i = 0; i < 4; ++i)
215*8bcb0991SDimitry Andric     if (Expected<unsigned> R = Stream.Read(8))
216*8bcb0991SDimitry Andric       Result[i] = *R;
217*8bcb0991SDimitry Andric     else
218*8bcb0991SDimitry Andric       return R.takeError();
219*8bcb0991SDimitry Andric   return Result;
220*8bcb0991SDimitry Andric }
221*8bcb0991SDimitry Andric 
222*8bcb0991SDimitry Andric Error BitstreamParserHelper::parseBlockInfoBlock() {
223*8bcb0991SDimitry Andric   Expected<BitstreamEntry> Next = Stream.advance();
224*8bcb0991SDimitry Andric   if (!Next)
225*8bcb0991SDimitry Andric     return Next.takeError();
226*8bcb0991SDimitry Andric   if (Next->Kind != BitstreamEntry::SubBlock ||
227*8bcb0991SDimitry Andric       Next->ID != llvm::bitc::BLOCKINFO_BLOCK_ID)
228*8bcb0991SDimitry Andric     return createStringError(
229*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
230*8bcb0991SDimitry Andric         "Error while parsing BLOCKINFO_BLOCK: expecting [ENTER_SUBBLOCK, "
231*8bcb0991SDimitry Andric         "BLOCKINFO_BLOCK, ...].");
232*8bcb0991SDimitry Andric 
233*8bcb0991SDimitry Andric   Expected<Optional<BitstreamBlockInfo>> MaybeBlockInfo =
234*8bcb0991SDimitry Andric       Stream.ReadBlockInfoBlock();
235*8bcb0991SDimitry Andric   if (!MaybeBlockInfo)
236*8bcb0991SDimitry Andric     return MaybeBlockInfo.takeError();
237*8bcb0991SDimitry Andric 
238*8bcb0991SDimitry Andric   if (!*MaybeBlockInfo)
239*8bcb0991SDimitry Andric     return createStringError(
240*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
241*8bcb0991SDimitry Andric         "Error while parsing BLOCKINFO_BLOCK.");
242*8bcb0991SDimitry Andric 
243*8bcb0991SDimitry Andric   BlockInfo = **MaybeBlockInfo;
244*8bcb0991SDimitry Andric 
245*8bcb0991SDimitry Andric   Stream.setBlockInfo(&BlockInfo);
246*8bcb0991SDimitry Andric   return Error::success();
247*8bcb0991SDimitry Andric }
248*8bcb0991SDimitry Andric 
249*8bcb0991SDimitry Andric static Expected<bool> isBlock(BitstreamCursor &Stream, unsigned BlockID) {
250*8bcb0991SDimitry Andric   bool Result = false;
251*8bcb0991SDimitry Andric   uint64_t PreviousBitNo = Stream.GetCurrentBitNo();
252*8bcb0991SDimitry Andric   Expected<BitstreamEntry> Next = Stream.advance();
253*8bcb0991SDimitry Andric   if (!Next)
254*8bcb0991SDimitry Andric     return Next.takeError();
255*8bcb0991SDimitry Andric   switch (Next->Kind) {
256*8bcb0991SDimitry Andric   case BitstreamEntry::SubBlock:
257*8bcb0991SDimitry Andric     // Check for the block id.
258*8bcb0991SDimitry Andric     Result = Next->ID == BlockID;
259*8bcb0991SDimitry Andric     break;
260*8bcb0991SDimitry Andric   case BitstreamEntry::Error:
261*8bcb0991SDimitry Andric     return createStringError(
262*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
263*8bcb0991SDimitry Andric         "Unexpected error while parsing bitstream.");
264*8bcb0991SDimitry Andric   default:
265*8bcb0991SDimitry Andric     Result = false;
266*8bcb0991SDimitry Andric     break;
267*8bcb0991SDimitry Andric   }
268*8bcb0991SDimitry Andric   if (Error E = Stream.JumpToBit(PreviousBitNo))
269*8bcb0991SDimitry Andric     return std::move(E);
270*8bcb0991SDimitry Andric   return Result;
271*8bcb0991SDimitry Andric }
272*8bcb0991SDimitry Andric 
273*8bcb0991SDimitry Andric Expected<bool> BitstreamParserHelper::isMetaBlock() {
274*8bcb0991SDimitry Andric   return isBlock(Stream, META_BLOCK_ID);
275*8bcb0991SDimitry Andric }
276*8bcb0991SDimitry Andric 
277*8bcb0991SDimitry Andric Expected<bool> BitstreamParserHelper::isRemarkBlock() {
278*8bcb0991SDimitry Andric   return isBlock(Stream, META_BLOCK_ID);
279*8bcb0991SDimitry Andric }
280*8bcb0991SDimitry Andric 
281*8bcb0991SDimitry Andric static Error validateMagicNumber(StringRef Magic) {
282*8bcb0991SDimitry Andric   if (Magic != remarks::ContainerMagic)
283*8bcb0991SDimitry Andric     return createStringError(std::make_error_code(std::errc::invalid_argument),
284*8bcb0991SDimitry Andric                              "Unknown magic number: expecting %s, got %.4s.",
285*8bcb0991SDimitry Andric                              remarks::ContainerMagic.data(), Magic.data());
286*8bcb0991SDimitry Andric   return Error::success();
287*8bcb0991SDimitry Andric }
288*8bcb0991SDimitry Andric 
289*8bcb0991SDimitry Andric static Error advanceToMetaBlock(BitstreamParserHelper &Helper) {
290*8bcb0991SDimitry Andric   Expected<std::array<char, 4>> Magic = Helper.parseMagic();
291*8bcb0991SDimitry Andric   if (!Magic)
292*8bcb0991SDimitry Andric     return Magic.takeError();
293*8bcb0991SDimitry Andric   if (Error E = validateMagicNumber(StringRef(Magic->data(), Magic->size())))
294*8bcb0991SDimitry Andric     return E;
295*8bcb0991SDimitry Andric   if (Error E = Helper.parseBlockInfoBlock())
296*8bcb0991SDimitry Andric     return E;
297*8bcb0991SDimitry Andric   Expected<bool> isMetaBlock = Helper.isMetaBlock();
298*8bcb0991SDimitry Andric   if (!isMetaBlock)
299*8bcb0991SDimitry Andric     return isMetaBlock.takeError();
300*8bcb0991SDimitry Andric   if (!*isMetaBlock)
301*8bcb0991SDimitry Andric     return createStringError(
302*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
303*8bcb0991SDimitry Andric         "Expecting META_BLOCK after the BLOCKINFO_BLOCK.");
304*8bcb0991SDimitry Andric   return Error::success();
305*8bcb0991SDimitry Andric }
306*8bcb0991SDimitry Andric 
307*8bcb0991SDimitry Andric Expected<std::unique_ptr<BitstreamRemarkParser>>
308*8bcb0991SDimitry Andric remarks::createBitstreamParserFromMeta(
309*8bcb0991SDimitry Andric     StringRef Buf, Optional<ParsedStringTable> StrTab,
310*8bcb0991SDimitry Andric     Optional<StringRef> ExternalFilePrependPath) {
311*8bcb0991SDimitry Andric   BitstreamParserHelper Helper(Buf);
312*8bcb0991SDimitry Andric   Expected<std::array<char, 4>> Magic = Helper.parseMagic();
313*8bcb0991SDimitry Andric   if (!Magic)
314*8bcb0991SDimitry Andric     return Magic.takeError();
315*8bcb0991SDimitry Andric 
316*8bcb0991SDimitry Andric   if (Error E = validateMagicNumber(StringRef(Magic->data(), Magic->size())))
317*8bcb0991SDimitry Andric     return std::move(E);
318*8bcb0991SDimitry Andric 
319*8bcb0991SDimitry Andric   auto Parser =
320*8bcb0991SDimitry Andric       StrTab ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab))
321*8bcb0991SDimitry Andric              : std::make_unique<BitstreamRemarkParser>(Buf);
322*8bcb0991SDimitry Andric 
323*8bcb0991SDimitry Andric   if (ExternalFilePrependPath)
324*8bcb0991SDimitry Andric     Parser->ExternalFilePrependPath = *ExternalFilePrependPath;
325*8bcb0991SDimitry Andric 
326*8bcb0991SDimitry Andric   return std::move(Parser);
327*8bcb0991SDimitry Andric }
328*8bcb0991SDimitry Andric 
329*8bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::next() {
330*8bcb0991SDimitry Andric   if (ParserHelper.atEndOfStream())
331*8bcb0991SDimitry Andric     return make_error<EndOfFileError>();
332*8bcb0991SDimitry Andric 
333*8bcb0991SDimitry Andric   if (!ReadyToParseRemarks) {
334*8bcb0991SDimitry Andric     if (Error E = parseMeta())
335*8bcb0991SDimitry Andric       return std::move(E);
336*8bcb0991SDimitry Andric     ReadyToParseRemarks = true;
337*8bcb0991SDimitry Andric   }
338*8bcb0991SDimitry Andric 
339*8bcb0991SDimitry Andric   return parseRemark();
340*8bcb0991SDimitry Andric }
341*8bcb0991SDimitry Andric 
342*8bcb0991SDimitry Andric Error BitstreamRemarkParser::parseMeta() {
343*8bcb0991SDimitry Andric   // Advance and to the meta block.
344*8bcb0991SDimitry Andric   if (Error E = advanceToMetaBlock(ParserHelper))
345*8bcb0991SDimitry Andric     return E;
346*8bcb0991SDimitry Andric 
347*8bcb0991SDimitry Andric   BitstreamMetaParserHelper MetaHelper(ParserHelper.Stream,
348*8bcb0991SDimitry Andric                                        ParserHelper.BlockInfo);
349*8bcb0991SDimitry Andric   if (Error E = MetaHelper.parse())
350*8bcb0991SDimitry Andric     return E;
351*8bcb0991SDimitry Andric 
352*8bcb0991SDimitry Andric   if (Error E = processCommonMeta(MetaHelper))
353*8bcb0991SDimitry Andric     return E;
354*8bcb0991SDimitry Andric 
355*8bcb0991SDimitry Andric   switch (ContainerType) {
356*8bcb0991SDimitry Andric   case BitstreamRemarkContainerType::Standalone:
357*8bcb0991SDimitry Andric     return processStandaloneMeta(MetaHelper);
358*8bcb0991SDimitry Andric   case BitstreamRemarkContainerType::SeparateRemarksFile:
359*8bcb0991SDimitry Andric     return processSeparateRemarksFileMeta(MetaHelper);
360*8bcb0991SDimitry Andric   case BitstreamRemarkContainerType::SeparateRemarksMeta:
361*8bcb0991SDimitry Andric     return processSeparateRemarksMetaMeta(MetaHelper);
362*8bcb0991SDimitry Andric   }
363*8bcb0991SDimitry Andric   llvm_unreachable("Unknown BitstreamRemarkContainerType enum");
364*8bcb0991SDimitry Andric }
365*8bcb0991SDimitry Andric 
366*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processCommonMeta(
367*8bcb0991SDimitry Andric     BitstreamMetaParserHelper &MetaHelper) {
368*8bcb0991SDimitry Andric   if (Optional<uint64_t> Version = MetaHelper.ContainerVersion)
369*8bcb0991SDimitry Andric     ContainerVersion = *Version;
370*8bcb0991SDimitry Andric   else
371*8bcb0991SDimitry Andric     return createStringError(
372*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
373*8bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing container version.");
374*8bcb0991SDimitry Andric 
375*8bcb0991SDimitry Andric   if (Optional<uint8_t> Type = MetaHelper.ContainerType) {
376*8bcb0991SDimitry Andric     // Always >= BitstreamRemarkContainerType::First since it's unsigned.
377*8bcb0991SDimitry Andric     if (*Type > static_cast<uint8_t>(BitstreamRemarkContainerType::Last))
378*8bcb0991SDimitry Andric       return createStringError(
379*8bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
380*8bcb0991SDimitry Andric           "Error while parsing BLOCK_META: invalid container type.");
381*8bcb0991SDimitry Andric 
382*8bcb0991SDimitry Andric     ContainerType = static_cast<BitstreamRemarkContainerType>(*Type);
383*8bcb0991SDimitry Andric   } else
384*8bcb0991SDimitry Andric     return createStringError(
385*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
386*8bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing container type.");
387*8bcb0991SDimitry Andric 
388*8bcb0991SDimitry Andric   return Error::success();
389*8bcb0991SDimitry Andric }
390*8bcb0991SDimitry Andric 
391*8bcb0991SDimitry Andric static Error processStrTab(BitstreamRemarkParser &P,
392*8bcb0991SDimitry Andric                            Optional<StringRef> StrTabBuf) {
393*8bcb0991SDimitry Andric   if (!StrTabBuf)
394*8bcb0991SDimitry Andric     return createStringError(
395*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
396*8bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing string table.");
397*8bcb0991SDimitry Andric   // Parse and assign the string table.
398*8bcb0991SDimitry Andric   P.StrTab.emplace(*StrTabBuf);
399*8bcb0991SDimitry Andric   return Error::success();
400*8bcb0991SDimitry Andric }
401*8bcb0991SDimitry Andric 
402*8bcb0991SDimitry Andric static Error processRemarkVersion(BitstreamRemarkParser &P,
403*8bcb0991SDimitry Andric                                   Optional<uint64_t> RemarkVersion) {
404*8bcb0991SDimitry Andric   if (!RemarkVersion)
405*8bcb0991SDimitry Andric     return createStringError(
406*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
407*8bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing remark version.");
408*8bcb0991SDimitry Andric   P.RemarkVersion = *RemarkVersion;
409*8bcb0991SDimitry Andric   return Error::success();
410*8bcb0991SDimitry Andric }
411*8bcb0991SDimitry Andric 
412*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processExternalFilePath(
413*8bcb0991SDimitry Andric     Optional<StringRef> ExternalFilePath) {
414*8bcb0991SDimitry Andric   if (!ExternalFilePath)
415*8bcb0991SDimitry Andric     return createStringError(
416*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
417*8bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing external file path.");
418*8bcb0991SDimitry Andric 
419*8bcb0991SDimitry Andric   SmallString<80> FullPath(ExternalFilePrependPath);
420*8bcb0991SDimitry Andric   sys::path::append(FullPath, *ExternalFilePath);
421*8bcb0991SDimitry Andric 
422*8bcb0991SDimitry Andric   // External file: open the external file, parse it, check if its metadata
423*8bcb0991SDimitry Andric   // matches the one from the separate metadata, then replace the current parser
424*8bcb0991SDimitry Andric   // with the one parsing the remarks.
425*8bcb0991SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
426*8bcb0991SDimitry Andric       MemoryBuffer::getFile(FullPath);
427*8bcb0991SDimitry Andric   if (std::error_code EC = BufferOrErr.getError())
428*8bcb0991SDimitry Andric     return createFileError(FullPath, EC);
429*8bcb0991SDimitry Andric   TmpRemarkBuffer = std::move(*BufferOrErr);
430*8bcb0991SDimitry Andric 
431*8bcb0991SDimitry Andric   // Create a separate parser used for parsing the separate file.
432*8bcb0991SDimitry Andric   ParserHelper = BitstreamParserHelper(TmpRemarkBuffer->getBuffer());
433*8bcb0991SDimitry Andric   // Advance and check until we can parse the meta block.
434*8bcb0991SDimitry Andric   if (Error E = advanceToMetaBlock(ParserHelper))
435*8bcb0991SDimitry Andric     return E;
436*8bcb0991SDimitry Andric   // Parse the meta from the separate file.
437*8bcb0991SDimitry Andric   // Note: here we overwrite the BlockInfo with the one from the file. This will
438*8bcb0991SDimitry Andric   // be used to parse the rest of the file.
439*8bcb0991SDimitry Andric   BitstreamMetaParserHelper SeparateMetaHelper(ParserHelper.Stream,
440*8bcb0991SDimitry Andric                                                ParserHelper.BlockInfo);
441*8bcb0991SDimitry Andric   if (Error E = SeparateMetaHelper.parse())
442*8bcb0991SDimitry Andric     return E;
443*8bcb0991SDimitry Andric 
444*8bcb0991SDimitry Andric   uint64_t PreviousContainerVersion = ContainerVersion;
445*8bcb0991SDimitry Andric   if (Error E = processCommonMeta(SeparateMetaHelper))
446*8bcb0991SDimitry Andric     return E;
447*8bcb0991SDimitry Andric 
448*8bcb0991SDimitry Andric   if (ContainerType != BitstreamRemarkContainerType::SeparateRemarksFile)
449*8bcb0991SDimitry Andric     return createStringError(
450*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
451*8bcb0991SDimitry Andric         "Error while parsing external file's BLOCK_META: wrong container "
452*8bcb0991SDimitry Andric         "type.");
453*8bcb0991SDimitry Andric 
454*8bcb0991SDimitry Andric   if (PreviousContainerVersion != ContainerVersion)
455*8bcb0991SDimitry Andric     return createStringError(
456*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
457*8bcb0991SDimitry Andric         "Error while parsing external file's BLOCK_META: mismatching versions: "
458*8bcb0991SDimitry Andric         "original meta: %lu, external file meta: %lu.",
459*8bcb0991SDimitry Andric         PreviousContainerVersion, ContainerVersion);
460*8bcb0991SDimitry Andric 
461*8bcb0991SDimitry Andric   // Process the meta from the separate file.
462*8bcb0991SDimitry Andric   return processSeparateRemarksFileMeta(SeparateMetaHelper);
463*8bcb0991SDimitry Andric }
464*8bcb0991SDimitry Andric 
465*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processStandaloneMeta(
466*8bcb0991SDimitry Andric     BitstreamMetaParserHelper &Helper) {
467*8bcb0991SDimitry Andric   if (Error E = processStrTab(*this, Helper.StrTabBuf))
468*8bcb0991SDimitry Andric     return E;
469*8bcb0991SDimitry Andric   return processRemarkVersion(*this, Helper.RemarkVersion);
470*8bcb0991SDimitry Andric }
471*8bcb0991SDimitry Andric 
472*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processSeparateRemarksFileMeta(
473*8bcb0991SDimitry Andric     BitstreamMetaParserHelper &Helper) {
474*8bcb0991SDimitry Andric   return processRemarkVersion(*this, Helper.RemarkVersion);
475*8bcb0991SDimitry Andric }
476*8bcb0991SDimitry Andric 
477*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processSeparateRemarksMetaMeta(
478*8bcb0991SDimitry Andric     BitstreamMetaParserHelper &Helper) {
479*8bcb0991SDimitry Andric   if (Error E = processStrTab(*this, Helper.StrTabBuf))
480*8bcb0991SDimitry Andric     return E;
481*8bcb0991SDimitry Andric   return processExternalFilePath(Helper.ExternalFilePath);
482*8bcb0991SDimitry Andric }
483*8bcb0991SDimitry Andric 
484*8bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::parseRemark() {
485*8bcb0991SDimitry Andric   BitstreamRemarkParserHelper RemarkHelper(ParserHelper.Stream);
486*8bcb0991SDimitry Andric   if (Error E = RemarkHelper.parse())
487*8bcb0991SDimitry Andric     return std::move(E);
488*8bcb0991SDimitry Andric 
489*8bcb0991SDimitry Andric   return processRemark(RemarkHelper);
490*8bcb0991SDimitry Andric }
491*8bcb0991SDimitry Andric 
492*8bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>>
493*8bcb0991SDimitry Andric BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) {
494*8bcb0991SDimitry Andric   std::unique_ptr<Remark> Result = std::make_unique<Remark>();
495*8bcb0991SDimitry Andric   Remark &R = *Result;
496*8bcb0991SDimitry Andric 
497*8bcb0991SDimitry Andric   if (StrTab == None)
498*8bcb0991SDimitry Andric     return createStringError(
499*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
500*8bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing string table.");
501*8bcb0991SDimitry Andric 
502*8bcb0991SDimitry Andric   if (!Helper.Type)
503*8bcb0991SDimitry Andric     return createStringError(
504*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
505*8bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark type.");
506*8bcb0991SDimitry Andric 
507*8bcb0991SDimitry Andric   // Always >= Type::First since it's unsigned.
508*8bcb0991SDimitry Andric   if (*Helper.Type > static_cast<uint8_t>(Type::Last))
509*8bcb0991SDimitry Andric     return createStringError(
510*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
511*8bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: unknown remark type.");
512*8bcb0991SDimitry Andric 
513*8bcb0991SDimitry Andric   R.RemarkType = static_cast<Type>(*Helper.Type);
514*8bcb0991SDimitry Andric 
515*8bcb0991SDimitry Andric   if (!Helper.RemarkNameIdx)
516*8bcb0991SDimitry Andric     return createStringError(
517*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
518*8bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark name.");
519*8bcb0991SDimitry Andric 
520*8bcb0991SDimitry Andric   if (Expected<StringRef> RemarkName = (*StrTab)[*Helper.RemarkNameIdx])
521*8bcb0991SDimitry Andric     R.RemarkName = *RemarkName;
522*8bcb0991SDimitry Andric   else
523*8bcb0991SDimitry Andric     return RemarkName.takeError();
524*8bcb0991SDimitry Andric 
525*8bcb0991SDimitry Andric   if (!Helper.PassNameIdx)
526*8bcb0991SDimitry Andric     return createStringError(
527*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
528*8bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark pass.");
529*8bcb0991SDimitry Andric 
530*8bcb0991SDimitry Andric   if (Expected<StringRef> PassName = (*StrTab)[*Helper.PassNameIdx])
531*8bcb0991SDimitry Andric     R.PassName = *PassName;
532*8bcb0991SDimitry Andric   else
533*8bcb0991SDimitry Andric     return PassName.takeError();
534*8bcb0991SDimitry Andric 
535*8bcb0991SDimitry Andric   if (!Helper.FunctionNameIdx)
536*8bcb0991SDimitry Andric     return createStringError(
537*8bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
538*8bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark function name.");
539*8bcb0991SDimitry Andric   if (Expected<StringRef> FunctionName = (*StrTab)[*Helper.FunctionNameIdx])
540*8bcb0991SDimitry Andric     R.FunctionName = *FunctionName;
541*8bcb0991SDimitry Andric   else
542*8bcb0991SDimitry Andric     return FunctionName.takeError();
543*8bcb0991SDimitry Andric 
544*8bcb0991SDimitry Andric   if (Helper.SourceFileNameIdx && Helper.SourceLine && Helper.SourceColumn) {
545*8bcb0991SDimitry Andric     Expected<StringRef> SourceFileName = (*StrTab)[*Helper.SourceFileNameIdx];
546*8bcb0991SDimitry Andric     if (!SourceFileName)
547*8bcb0991SDimitry Andric       return SourceFileName.takeError();
548*8bcb0991SDimitry Andric     R.Loc.emplace();
549*8bcb0991SDimitry Andric     R.Loc->SourceFilePath = *SourceFileName;
550*8bcb0991SDimitry Andric     R.Loc->SourceLine = *Helper.SourceLine;
551*8bcb0991SDimitry Andric     R.Loc->SourceColumn = *Helper.SourceColumn;
552*8bcb0991SDimitry Andric   }
553*8bcb0991SDimitry Andric 
554*8bcb0991SDimitry Andric   if (Helper.Hotness)
555*8bcb0991SDimitry Andric     R.Hotness = *Helper.Hotness;
556*8bcb0991SDimitry Andric 
557*8bcb0991SDimitry Andric   if (!Helper.Args)
558*8bcb0991SDimitry Andric     return std::move(Result);
559*8bcb0991SDimitry Andric 
560*8bcb0991SDimitry Andric   for (const BitstreamRemarkParserHelper::Argument &Arg : *Helper.Args) {
561*8bcb0991SDimitry Andric     if (!Arg.KeyIdx)
562*8bcb0991SDimitry Andric       return createStringError(
563*8bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
564*8bcb0991SDimitry Andric           "Error while parsing BLOCK_REMARK: missing key in remark argument.");
565*8bcb0991SDimitry Andric     if (!Arg.ValueIdx)
566*8bcb0991SDimitry Andric       return createStringError(
567*8bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
568*8bcb0991SDimitry Andric           "Error while parsing BLOCK_REMARK: missing value in remark "
569*8bcb0991SDimitry Andric           "argument.");
570*8bcb0991SDimitry Andric 
571*8bcb0991SDimitry Andric     // We have at least a key and a value, create an entry.
572*8bcb0991SDimitry Andric     R.Args.emplace_back();
573*8bcb0991SDimitry Andric 
574*8bcb0991SDimitry Andric     if (Expected<StringRef> Key = (*StrTab)[*Arg.KeyIdx])
575*8bcb0991SDimitry Andric       R.Args.back().Key = *Key;
576*8bcb0991SDimitry Andric     else
577*8bcb0991SDimitry Andric       return Key.takeError();
578*8bcb0991SDimitry Andric 
579*8bcb0991SDimitry Andric     if (Expected<StringRef> Value = (*StrTab)[*Arg.ValueIdx])
580*8bcb0991SDimitry Andric       R.Args.back().Val = *Value;
581*8bcb0991SDimitry Andric     else
582*8bcb0991SDimitry Andric       return Value.takeError();
583*8bcb0991SDimitry Andric 
584*8bcb0991SDimitry Andric     if (Arg.SourceFileNameIdx && Arg.SourceLine && Arg.SourceColumn) {
585*8bcb0991SDimitry Andric       if (Expected<StringRef> SourceFileName =
586*8bcb0991SDimitry Andric               (*StrTab)[*Arg.SourceFileNameIdx]) {
587*8bcb0991SDimitry Andric         R.Args.back().Loc.emplace();
588*8bcb0991SDimitry Andric         R.Args.back().Loc->SourceFilePath = *SourceFileName;
589*8bcb0991SDimitry Andric         R.Args.back().Loc->SourceLine = *Arg.SourceLine;
590*8bcb0991SDimitry Andric         R.Args.back().Loc->SourceColumn = *Arg.SourceColumn;
591*8bcb0991SDimitry Andric       } else
592*8bcb0991SDimitry Andric         return SourceFileName.takeError();
593*8bcb0991SDimitry Andric     }
594*8bcb0991SDimitry Andric   }
595*8bcb0991SDimitry Andric 
596*8bcb0991SDimitry Andric   return std::move(Result);
597*8bcb0991SDimitry Andric }
598