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