LLVM 19.0.0git
BitstreamRemarkParser.cpp
Go to the documentation of this file.
1//===- BitstreamRemarkParser.cpp ------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file provides utility methods used by clients that want to use the
10// parser for remark diagnostics in LLVM.
11//
12//===----------------------------------------------------------------------===//
13
16#include "llvm/Remarks/Remark.h"
18#include "llvm/Support/Path.h"
19#include <optional>
20
21using namespace llvm;
22using namespace llvm::remarks;
23
24static Error unknownRecord(const char *BlockName, unsigned RecordID) {
25 return createStringError(
26 std::make_error_code(std::errc::illegal_byte_sequence),
27 "Error while parsing %s: unknown record entry (%lu).", BlockName,
28 RecordID);
29}
30
31static Error malformedRecord(const char *BlockName, const char *RecordName) {
32 return createStringError(
33 std::make_error_code(std::errc::illegal_byte_sequence),
34 "Error while parsing %s: malformed record entry (%s).", BlockName,
35 RecordName);
36}
37
39 BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo)
40 : Stream(Stream), BlockInfo(BlockInfo) {}
41
42/// Parse a record and fill in the fields in the parser.
43static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code) {
44 BitstreamCursor &Stream = Parser.Stream;
45 // Note: 2 is used here because it's the max number of fields we have per
46 // record.
48 StringRef Blob;
49 Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob);
50 if (!RecordID)
51 return RecordID.takeError();
52
53 switch (*RecordID) {
55 if (Record.size() != 2)
56 return malformedRecord("BLOCK_META", "RECORD_META_CONTAINER_INFO");
57 Parser.ContainerVersion = Record[0];
58 Parser.ContainerType = Record[1];
59 break;
60 }
62 if (Record.size() != 1)
63 return malformedRecord("BLOCK_META", "RECORD_META_REMARK_VERSION");
64 Parser.RemarkVersion = Record[0];
65 break;
66 }
67 case RECORD_META_STRTAB: {
68 if (Record.size() != 0)
69 return malformedRecord("BLOCK_META", "RECORD_META_STRTAB");
70 Parser.StrTabBuf = Blob;
71 break;
72 }
74 if (Record.size() != 0)
75 return malformedRecord("BLOCK_META", "RECORD_META_EXTERNAL_FILE");
76 Parser.ExternalFilePath = Blob;
77 break;
78 }
79 default:
80 return unknownRecord("BLOCK_META", *RecordID);
81 }
82 return Error::success();
83}
84
86 BitstreamCursor &Stream)
87 : Stream(Stream) {}
88
89/// Parse a record and fill in the fields in the parser.
90static Error parseRecord(BitstreamRemarkParserHelper &Parser, unsigned Code) {
91 BitstreamCursor &Stream = Parser.Stream;
92 // Note: 5 is used here because it's the max number of fields we have per
93 // record.
95 StringRef Blob;
96 Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob);
97 if (!RecordID)
98 return RecordID.takeError();
99
100 switch (*RecordID) {
102 if (Record.size() != 4)
103 return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HEADER");
104 Parser.Type = Record[0];
105 Parser.RemarkNameIdx = Record[1];
106 Parser.PassNameIdx = Record[2];
107 Parser.FunctionNameIdx = Record[3];
108 break;
109 }
111 if (Record.size() != 3)
112 return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_DEBUG_LOC");
113 Parser.SourceFileNameIdx = Record[0];
114 Parser.SourceLine = Record[1];
115 Parser.SourceColumn = Record[2];
116 break;
117 }
119 if (Record.size() != 1)
120 return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HOTNESS");
121 Parser.Hotness = Record[0];
122 break;
123 }
125 if (Record.size() != 5)
126 return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_ARG_WITH_DEBUGLOC");
127 // Create a temporary argument. Use that as a valid memory location for this
128 // argument entry.
129 Parser.TmpArgs.emplace_back();
130 Parser.TmpArgs.back().KeyIdx = Record[0];
131 Parser.TmpArgs.back().ValueIdx = Record[1];
132 Parser.TmpArgs.back().SourceFileNameIdx = Record[2];
133 Parser.TmpArgs.back().SourceLine = Record[3];
134 Parser.TmpArgs.back().SourceColumn = Record[4];
135 Parser.Args =
137 break;
138 }
140 if (Record.size() != 2)
141 return malformedRecord("BLOCK_REMARK",
142 "RECORD_REMARK_ARG_WITHOUT_DEBUGLOC");
143 // Create a temporary argument. Use that as a valid memory location for this
144 // argument entry.
145 Parser.TmpArgs.emplace_back();
146 Parser.TmpArgs.back().KeyIdx = Record[0];
147 Parser.TmpArgs.back().ValueIdx = Record[1];
148 Parser.Args =
150 break;
151 }
152 default:
153 return unknownRecord("BLOCK_REMARK", *RecordID);
154 }
155 return Error::success();
156}
157
158template <typename T>
159static Error parseBlock(T &ParserHelper, unsigned BlockID,
160 const char *BlockName) {
161 BitstreamCursor &Stream = ParserHelper.Stream;
162 Expected<BitstreamEntry> Next = Stream.advance();
163 if (!Next)
164 return Next.takeError();
165 if (Next->Kind != BitstreamEntry::SubBlock || Next->ID != BlockID)
166 return createStringError(
167 std::make_error_code(std::errc::illegal_byte_sequence),
168 "Error while parsing %s: expecting [ENTER_SUBBLOCK, %s, ...].",
169 BlockName, BlockName);
170 if (Stream.EnterSubBlock(BlockID))
171 return createStringError(
172 std::make_error_code(std::errc::illegal_byte_sequence),
173 "Error while entering %s.", BlockName);
174
175 // Stop when there is nothing to read anymore or when we encounter an
176 // END_BLOCK.
177 while (!Stream.AtEndOfStream()) {
178 Next = Stream.advance();
179 if (!Next)
180 return Next.takeError();
181 switch (Next->Kind) {
183 return Error::success();
186 return createStringError(
187 std::make_error_code(std::errc::illegal_byte_sequence),
188 "Error while parsing %s: expecting records.", BlockName);
190 if (Error E = parseRecord(ParserHelper, Next->ID))
191 return E;
192 continue;
193 }
194 }
195 // If we're here, it means we didn't get an END_BLOCK yet, but we're at the
196 // end of the stream. In this case, error.
197 return createStringError(
198 std::make_error_code(std::errc::illegal_byte_sequence),
199 "Error while parsing %s: unterminated block.", BlockName);
200}
201
203 return parseBlock(*this, META_BLOCK_ID, "META_BLOCK");
204}
205
207 return parseBlock(*this, REMARK_BLOCK_ID, "REMARK_BLOCK");
208}
209
211 : Stream(Buffer) {}
212
214 std::array<char, 4> Result;
215 for (unsigned i = 0; i < 4; ++i)
216 if (Expected<unsigned> R = Stream.Read(8))
217 Result[i] = *R;
218 else
219 return R.takeError();
220 return Result;
221}
222
225 if (!Next)
226 return Next.takeError();
227 if (Next->Kind != BitstreamEntry::SubBlock ||
229 return createStringError(
230 std::make_error_code(std::errc::illegal_byte_sequence),
231 "Error while parsing BLOCKINFO_BLOCK: expecting [ENTER_SUBBLOCK, "
232 "BLOCKINFO_BLOCK, ...].");
233
236 if (!MaybeBlockInfo)
237 return MaybeBlockInfo.takeError();
238
239 if (!*MaybeBlockInfo)
240 return createStringError(
241 std::make_error_code(std::errc::illegal_byte_sequence),
242 "Error while parsing BLOCKINFO_BLOCK.");
243
244 BlockInfo = **MaybeBlockInfo;
245
247 return Error::success();
248}
249
250static Expected<bool> isBlock(BitstreamCursor &Stream, unsigned BlockID) {
251 bool Result = false;
252 uint64_t PreviousBitNo = Stream.GetCurrentBitNo();
253 Expected<BitstreamEntry> Next = Stream.advance();
254 if (!Next)
255 return Next.takeError();
256 switch (Next->Kind) {
258 // Check for the block id.
259 Result = Next->ID == BlockID;
260 break;
262 return createStringError(
263 std::make_error_code(std::errc::illegal_byte_sequence),
264 "Unexpected error while parsing bitstream.");
265 default:
266 Result = false;
267 break;
268 }
269 if (Error E = Stream.JumpToBit(PreviousBitNo))
270 return std::move(E);
271 return Result;
272}
273
276}
277
280}
281
284 return createStringError(std::make_error_code(std::errc::invalid_argument),
285 "Unknown magic number: expecting %s, got %.4s.",
287 return Error::success();
288}
289
292 if (!MagicNumber)
293 return MagicNumber.takeError();
295 StringRef(MagicNumber->data(), MagicNumber->size())))
296 return E;
297 if (Error E = Helper.parseBlockInfoBlock())
298 return E;
299 Expected<bool> isMetaBlock = Helper.isMetaBlock();
300 if (!isMetaBlock)
301 return isMetaBlock.takeError();
302 if (!*isMetaBlock)
303 return createStringError(
304 std::make_error_code(std::errc::illegal_byte_sequence),
305 "Expecting META_BLOCK after the BLOCKINFO_BLOCK.");
306 return Error::success();
307}
308
311 StringRef Buf, std::optional<ParsedStringTable> StrTab,
312 std::optional<StringRef> ExternalFilePrependPath) {
313 BitstreamParserHelper Helper(Buf);
315 if (!MagicNumber)
316 return MagicNumber.takeError();
317
319 StringRef(MagicNumber->data(), MagicNumber->size())))
320 return std::move(E);
321
322 auto Parser =
323 StrTab ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab))
324 : std::make_unique<BitstreamRemarkParser>(Buf);
325
326 if (ExternalFilePrependPath)
327 Parser->ExternalFilePrependPath = std::string(*ExternalFilePrependPath);
328
329 return std::move(Parser);
330}
331
334 return make_error<EndOfFileError>();
335
336 if (!ReadyToParseRemarks) {
337 if (Error E = parseMeta())
338 return std::move(E);
339 ReadyToParseRemarks = true;
340 }
341
342 return parseRemark();
343}
344
346 // Advance and to the meta block.
348 return E;
349
352 if (Error E = MetaHelper.parse())
353 return E;
354
355 if (Error E = processCommonMeta(MetaHelper))
356 return E;
357
358 switch (ContainerType) {
360 return processStandaloneMeta(MetaHelper);
362 return processSeparateRemarksFileMeta(MetaHelper);
364 return processSeparateRemarksMetaMeta(MetaHelper);
365 }
366 llvm_unreachable("Unknown BitstreamRemarkContainerType enum");
367}
368
369Error BitstreamRemarkParser::processCommonMeta(
371 if (std::optional<uint64_t> Version = Helper.ContainerVersion)
372 ContainerVersion = *Version;
373 else
374 return createStringError(
375 std::make_error_code(std::errc::illegal_byte_sequence),
376 "Error while parsing BLOCK_META: missing container version.");
377
378 if (std::optional<uint8_t> Type = Helper.ContainerType) {
379 // Always >= BitstreamRemarkContainerType::First since it's unsigned.
380 if (*Type > static_cast<uint8_t>(BitstreamRemarkContainerType::Last))
381 return createStringError(
382 std::make_error_code(std::errc::illegal_byte_sequence),
383 "Error while parsing BLOCK_META: invalid container type.");
384
385 ContainerType = static_cast<BitstreamRemarkContainerType>(*Type);
386 } else
387 return createStringError(
388 std::make_error_code(std::errc::illegal_byte_sequence),
389 "Error while parsing BLOCK_META: missing container type.");
390
391 return Error::success();
392}
393
395 std::optional<StringRef> StrTabBuf) {
396 if (!StrTabBuf)
397 return createStringError(
398 std::make_error_code(std::errc::illegal_byte_sequence),
399 "Error while parsing BLOCK_META: missing string table.");
400 // Parse and assign the string table.
401 P.StrTab.emplace(*StrTabBuf);
402 return Error::success();
403}
404
406 std::optional<uint64_t> RemarkVersion) {
407 if (!RemarkVersion)
408 return createStringError(
409 std::make_error_code(std::errc::illegal_byte_sequence),
410 "Error while parsing BLOCK_META: missing remark version.");
411 P.RemarkVersion = *RemarkVersion;
412 return Error::success();
413}
414
415Error BitstreamRemarkParser::processExternalFilePath(
416 std::optional<StringRef> ExternalFilePath) {
417 if (!ExternalFilePath)
418 return createStringError(
419 std::make_error_code(std::errc::illegal_byte_sequence),
420 "Error while parsing BLOCK_META: missing external file path.");
421
423 sys::path::append(FullPath, *ExternalFilePath);
424
425 // External file: open the external file, parse it, check if its metadata
426 // matches the one from the separate metadata, then replace the current parser
427 // with the one parsing the remarks.
429 MemoryBuffer::getFile(FullPath);
430 if (std::error_code EC = BufferOrErr.getError())
431 return createFileError(FullPath, EC);
432
433 TmpRemarkBuffer = std::move(*BufferOrErr);
434
435 // Don't try to parse the file if it's empty.
436 if (TmpRemarkBuffer->getBufferSize() == 0)
437 return make_error<EndOfFileError>();
438
439 // Create a separate parser used for parsing the separate file.
441 // Advance and check until we can parse the meta block.
443 return E;
444 // Parse the meta from the separate file.
445 // Note: here we overwrite the BlockInfo with the one from the file. This will
446 // be used to parse the rest of the file.
449 if (Error E = SeparateMetaHelper.parse())
450 return E;
451
452 uint64_t PreviousContainerVersion = ContainerVersion;
453 if (Error E = processCommonMeta(SeparateMetaHelper))
454 return E;
455
457 return createStringError(
458 std::make_error_code(std::errc::illegal_byte_sequence),
459 "Error while parsing external file's BLOCK_META: wrong container "
460 "type.");
461
462 if (PreviousContainerVersion != ContainerVersion)
463 return createStringError(
464 std::make_error_code(std::errc::illegal_byte_sequence),
465 "Error while parsing external file's BLOCK_META: mismatching versions: "
466 "original meta: %lu, external file meta: %lu.",
467 PreviousContainerVersion, ContainerVersion);
468
469 // Process the meta from the separate file.
470 return processSeparateRemarksFileMeta(SeparateMetaHelper);
471}
472
473Error BitstreamRemarkParser::processStandaloneMeta(
475 if (Error E = processStrTab(*this, Helper.StrTabBuf))
476 return E;
477 return processRemarkVersion(*this, Helper.RemarkVersion);
478}
479
480Error BitstreamRemarkParser::processSeparateRemarksFileMeta(
482 return processRemarkVersion(*this, Helper.RemarkVersion);
483}
484
485Error BitstreamRemarkParser::processSeparateRemarksMetaMeta(
487 if (Error E = processStrTab(*this, Helper.StrTabBuf))
488 return E;
489 return processExternalFilePath(Helper.ExternalFilePath);
490}
491
494 if (Error E = RemarkHelper.parse())
495 return std::move(E);
496
497 return processRemark(RemarkHelper);
498}
499
501BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) {
502 std::unique_ptr<Remark> Result = std::make_unique<Remark>();
503 Remark &R = *Result;
504
505 if (StrTab == std::nullopt)
506 return createStringError(
507 std::make_error_code(std::errc::invalid_argument),
508 "Error while parsing BLOCK_REMARK: missing string table.");
509
510 if (!Helper.Type)
511 return createStringError(
512 std::make_error_code(std::errc::illegal_byte_sequence),
513 "Error while parsing BLOCK_REMARK: missing remark type.");
514
515 // Always >= Type::First since it's unsigned.
516 if (*Helper.Type > static_cast<uint8_t>(Type::Last))
517 return createStringError(
518 std::make_error_code(std::errc::illegal_byte_sequence),
519 "Error while parsing BLOCK_REMARK: unknown remark type.");
520
521 R.RemarkType = static_cast<Type>(*Helper.Type);
522
523 if (!Helper.RemarkNameIdx)
524 return createStringError(
525 std::make_error_code(std::errc::illegal_byte_sequence),
526 "Error while parsing BLOCK_REMARK: missing remark name.");
527
528 if (Expected<StringRef> RemarkName = (*StrTab)[*Helper.RemarkNameIdx])
529 R.RemarkName = *RemarkName;
530 else
531 return RemarkName.takeError();
532
533 if (!Helper.PassNameIdx)
534 return createStringError(
535 std::make_error_code(std::errc::illegal_byte_sequence),
536 "Error while parsing BLOCK_REMARK: missing remark pass.");
537
539 R.PassName = *PassName;
540 else
541 return PassName.takeError();
542
543 if (!Helper.FunctionNameIdx)
544 return createStringError(
545 std::make_error_code(std::errc::illegal_byte_sequence),
546 "Error while parsing BLOCK_REMARK: missing remark function name.");
547 if (Expected<StringRef> FunctionName = (*StrTab)[*Helper.FunctionNameIdx])
548 R.FunctionName = *FunctionName;
549 else
550 return FunctionName.takeError();
551
552 if (Helper.SourceFileNameIdx && Helper.SourceLine && Helper.SourceColumn) {
553 Expected<StringRef> SourceFileName = (*StrTab)[*Helper.SourceFileNameIdx];
554 if (!SourceFileName)
555 return SourceFileName.takeError();
556 R.Loc.emplace();
557 R.Loc->SourceFilePath = *SourceFileName;
558 R.Loc->SourceLine = *Helper.SourceLine;
559 R.Loc->SourceColumn = *Helper.SourceColumn;
560 }
561
562 if (Helper.Hotness)
563 R.Hotness = *Helper.Hotness;
564
565 if (!Helper.Args)
566 return std::move(Result);
567
568 for (const BitstreamRemarkParserHelper::Argument &Arg : *Helper.Args) {
569 if (!Arg.KeyIdx)
570 return createStringError(
571 std::make_error_code(std::errc::illegal_byte_sequence),
572 "Error while parsing BLOCK_REMARK: missing key in remark argument.");
573 if (!Arg.ValueIdx)
574 return createStringError(
575 std::make_error_code(std::errc::illegal_byte_sequence),
576 "Error while parsing BLOCK_REMARK: missing value in remark "
577 "argument.");
578
579 // We have at least a key and a value, create an entry.
580 R.Args.emplace_back();
581
582 if (Expected<StringRef> Key = (*StrTab)[*Arg.KeyIdx])
583 R.Args.back().Key = *Key;
584 else
585 return Key.takeError();
586
588 R.Args.back().Val = *Value;
589 else
590 return Value.takeError();
591
592 if (Arg.SourceFileNameIdx && Arg.SourceLine && Arg.SourceColumn) {
593 if (Expected<StringRef> SourceFileName =
594 (*StrTab)[*Arg.SourceFileNameIdx]) {
595 R.Args.back().Loc.emplace();
596 R.Args.back().Loc->SourceFilePath = *SourceFileName;
597 R.Args.back().Loc->SourceLine = *Arg.SourceLine;
598 R.Args.back().Loc->SourceColumn = *Arg.SourceColumn;
599 } else
600 return SourceFileName.takeError();
601 }
602 }
603
604 return std::move(Result);
605}
static Error processRemarkVersion(BitstreamRemarkParser &P, std::optional< uint64_t > RemarkVersion)
static Error malformedRecord(const char *BlockName, const char *RecordName)
static Error validateMagicNumber(StringRef MagicNumber)
static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code)
Parse a record and fill in the fields in the parser.
static Error parseBlock(T &ParserHelper, unsigned BlockID, const char *BlockName)
static Error processStrTab(BitstreamRemarkParser &P, std::optional< StringRef > StrTabBuf)
static Error unknownRecord(const char *BlockName, unsigned RecordID)
static Expected< bool > isBlock(BitstreamCursor &Stream, unsigned BlockID)
static Error advanceToMetaBlock(BitstreamParserHelper &Helper)
#define P(N)
static const char PassName[]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This class maintains the abbreviations read from a block info block.
This represents a position within a bitcode file, implemented on top of a SimpleBitstreamCursor.
Error JumpToBit(uint64_t BitNo)
Reset the stream to the specified bit number.
uint64_t GetCurrentBitNo() const
Return the bit # of the bit we are reading.
Expected< word_t > Read(unsigned NumBits)
Expected< BitstreamEntry > advance(unsigned Flags=0)
Advance the current bitstream, returning the next entry in the stream.
void setBlockInfo(BitstreamBlockInfo *BI)
Set the block info to be used by this BitstreamCursor to interpret abbreviated records.
Expected< unsigned > readRecord(unsigned AbbrevID, SmallVectorImpl< uint64_t > &Vals, StringRef *Blob=nullptr)
Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP=nullptr)
Having read the ENTER_SUBBLOCK abbrevid, and enter the block.
Expected< std::optional< BitstreamBlockInfo > > ReadBlockInfoBlock(bool ReadBlockInfoNames=false)
Read and return a block info block from the bitstream.
Represents either an error or a value T.
Definition: ErrorOr.h:56
std::error_code getError() const
Definition: ErrorOr.h:152
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MagicNumber
Definition: XCOFF.h:48
@ BLOCKINFO_BLOCK_ID
BLOCKINFO_BLOCK is used to define metadata about blocks, for example, standard abbrevs that should be...
Definition: BitCodeEnums.h:69
BitstreamRemarkContainerType
Type of the remark container.
@ SeparateRemarksFile
The remarks emitted separately.
@ SeparateRemarksMeta
The metadata emitted separately.
@ Standalone
Everything is emitted together.
Expected< std::unique_ptr< BitstreamRemarkParser > > createBitstreamParserFromMeta(StringRef Buf, std::optional< ParsedStringTable > StrTab=std::nullopt, std::optional< StringRef > ExternalFilePrependPath=std::nullopt)
@ REMARK_BLOCK_ID
One remark entry is represented using a REMARK_BLOCK.
@ META_BLOCK_ID
The metadata block is mandatory.
constexpr StringLiteral ContainerMagic("RMRK")
The magic number used for identifying remark blocks.
Type
The type of the remark.
Definition: Remark.h:65
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1339
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1258
Helper to parse a META_BLOCK for a bitstream remark container.
std::optional< uint64_t > ContainerVersion
The parsed content: depending on the container type, some fields might be empty.
BitstreamCursor & Stream
The Bitstream reader.
Error parse()
Parse the META_BLOCK and fill the available entries.
BitstreamMetaParserHelper(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo)
Continue parsing with Stream.
Helper to parse any bitstream remark container.
BitstreamParserHelper(StringRef Buffer)
Start parsing at Buffer.
Expected< bool > isRemarkBlock()
Return true if the next block is a REMARK_BLOCK.
bool atEndOfStream()
Return true if the parser reached the end of the stream.
Expected< std::array< char, 4 > > parseMagic()
Parse the magic number.
BitstreamBlockInfo BlockInfo
The block info block.
BitstreamCursor Stream
The Bitstream reader.
Expected< bool > isMetaBlock()
Return true if the next block is a META_BLOCK.
Error parseBlockInfoBlock()
Parse the block info block containing all the abbrevs.
Helper to parse a REMARK_BLOCK for a bitstream remark container.
std::optional< uint8_t > Type
The parsed content: depending on the remark, some fields might be empty.
std::optional< ArrayRef< Argument > > Args
BitstreamCursor & Stream
The Bitstream reader.
SmallVector< Argument, 8 > TmpArgs
Avoid re-allocating a vector every time.
BitstreamRemarkParserHelper(BitstreamCursor &Stream)
Continue parsing with Stream.
Error parse()
Parse the REMARK_BLOCK and fill the available entries.
Parses and holds the state of the latest parsed remark.
Error parseMeta()
Parse and process the metadata of the buffer.
std::optional< ParsedStringTable > StrTab
The string table used for parsing strings.
Expected< std::unique_ptr< Remark > > parseRemark()
Parse a Bitstream remark.
std::unique_ptr< MemoryBuffer > TmpRemarkBuffer
Temporary remark buffer used when the remarks are stored separately.
uint64_t ContainerVersion
The common metadata used to decide how to parse the buffer.
BitstreamParserHelper ParserHelper
The buffer to parse.
Expected< std::unique_ptr< Remark > > next() override
If no error occurs, this returns a valid Remark object.
BitstreamRemarkContainerType ContainerType
bool ReadyToParseRemarks
Wether the parser is ready to parse remarks.
std::string ExternalFilePrependPath
Path to prepend when opening an external remark file.
Definition: RemarkParser.h:44
A remark type used for both emission and parsing.
Definition: Remark.h:97