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