File: | src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream/BitstreamReader.h |
Warning: | line 200, column 40 The result of the right shift is undefined due to shifting by '64', which is greater or equal to the width of type 'llvm::SimpleBitstreamCursor::word_t' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
14 | #include "llvm/Remarks/BitstreamRemarkParser.h" | |||
15 | #include "BitstreamRemarkParser.h" | |||
16 | #include "llvm/Support/MemoryBuffer.h" | |||
17 | #include "llvm/Support/Path.h" | |||
18 | ||||
19 | using namespace llvm; | |||
20 | using namespace llvm::remarks; | |||
21 | ||||
22 | static Error unknownRecord(const char *BlockName, unsigned RecordID) { | |||
23 | return createStringError( | |||
24 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
25 | "Error while parsing %s: unknown record entry (%lu).", BlockName, | |||
26 | RecordID); | |||
27 | } | |||
28 | ||||
29 | static Error malformedRecord(const char *BlockName, const char *RecordName) { | |||
30 | return createStringError( | |||
31 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
32 | "Error while parsing %s: malformed record entry (%s).", BlockName, | |||
33 | RecordName); | |||
34 | } | |||
35 | ||||
36 | BitstreamMetaParserHelper::BitstreamMetaParserHelper( | |||
37 | BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo) | |||
38 | : Stream(Stream), BlockInfo(BlockInfo) {} | |||
39 | ||||
40 | /// Parse a record and fill in the fields in the parser. | |||
41 | static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code) { | |||
42 | BitstreamCursor &Stream = Parser.Stream; | |||
43 | // Note: 2 is used here because it's the max number of fields we have per | |||
44 | // record. | |||
45 | SmallVector<uint64_t, 2> Record; | |||
46 | StringRef Blob; | |||
47 | Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob); | |||
48 | if (!RecordID) | |||
49 | return RecordID.takeError(); | |||
50 | ||||
51 | switch (*RecordID) { | |||
52 | case RECORD_META_CONTAINER_INFO: { | |||
53 | if (Record.size() != 2) | |||
54 | return malformedRecord("BLOCK_META", "RECORD_META_CONTAINER_INFO"); | |||
55 | Parser.ContainerVersion = Record[0]; | |||
56 | Parser.ContainerType = Record[1]; | |||
57 | break; | |||
58 | } | |||
59 | case RECORD_META_REMARK_VERSION: { | |||
60 | if (Record.size() != 1) | |||
61 | return malformedRecord("BLOCK_META", "RECORD_META_REMARK_VERSION"); | |||
62 | Parser.RemarkVersion = Record[0]; | |||
63 | break; | |||
64 | } | |||
65 | case RECORD_META_STRTAB: { | |||
66 | if (Record.size() != 0) | |||
67 | return malformedRecord("BLOCK_META", "RECORD_META_STRTAB"); | |||
68 | Parser.StrTabBuf = Blob; | |||
69 | break; | |||
70 | } | |||
71 | case RECORD_META_EXTERNAL_FILE: { | |||
72 | if (Record.size() != 0) | |||
73 | return malformedRecord("BLOCK_META", "RECORD_META_EXTERNAL_FILE"); | |||
74 | Parser.ExternalFilePath = Blob; | |||
75 | break; | |||
76 | } | |||
77 | default: | |||
78 | return unknownRecord("BLOCK_META", *RecordID); | |||
79 | } | |||
80 | return Error::success(); | |||
81 | } | |||
82 | ||||
83 | BitstreamRemarkParserHelper::BitstreamRemarkParserHelper( | |||
84 | BitstreamCursor &Stream) | |||
85 | : Stream(Stream) {} | |||
86 | ||||
87 | /// Parse a record and fill in the fields in the parser. | |||
88 | static Error parseRecord(BitstreamRemarkParserHelper &Parser, unsigned Code) { | |||
89 | BitstreamCursor &Stream = Parser.Stream; | |||
90 | // Note: 5 is used here because it's the max number of fields we have per | |||
91 | // record. | |||
92 | SmallVector<uint64_t, 5> Record; | |||
93 | StringRef Blob; | |||
94 | Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob); | |||
95 | if (!RecordID) | |||
96 | return RecordID.takeError(); | |||
97 | ||||
98 | switch (*RecordID) { | |||
99 | case RECORD_REMARK_HEADER: { | |||
100 | if (Record.size() != 4) | |||
101 | return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HEADER"); | |||
102 | Parser.Type = Record[0]; | |||
103 | Parser.RemarkNameIdx = Record[1]; | |||
104 | Parser.PassNameIdx = Record[2]; | |||
105 | Parser.FunctionNameIdx = Record[3]; | |||
106 | break; | |||
107 | } | |||
108 | case RECORD_REMARK_DEBUG_LOC: { | |||
109 | if (Record.size() != 3) | |||
110 | return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_DEBUG_LOC"); | |||
111 | Parser.SourceFileNameIdx = Record[0]; | |||
112 | Parser.SourceLine = Record[1]; | |||
113 | Parser.SourceColumn = Record[2]; | |||
114 | break; | |||
115 | } | |||
116 | case RECORD_REMARK_HOTNESS: { | |||
117 | if (Record.size() != 1) | |||
118 | return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HOTNESS"); | |||
119 | Parser.Hotness = Record[0]; | |||
120 | break; | |||
121 | } | |||
122 | case RECORD_REMARK_ARG_WITH_DEBUGLOC: { | |||
123 | if (Record.size() != 5) | |||
124 | return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_ARG_WITH_DEBUGLOC"); | |||
125 | // Create a temporary argument. Use that as a valid memory location for this | |||
126 | // argument entry. | |||
127 | Parser.TmpArgs.emplace_back(); | |||
128 | Parser.TmpArgs.back().KeyIdx = Record[0]; | |||
129 | Parser.TmpArgs.back().ValueIdx = Record[1]; | |||
130 | Parser.TmpArgs.back().SourceFileNameIdx = Record[2]; | |||
131 | Parser.TmpArgs.back().SourceLine = Record[3]; | |||
132 | Parser.TmpArgs.back().SourceColumn = Record[4]; | |||
133 | Parser.Args = | |||
134 | ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs); | |||
135 | break; | |||
136 | } | |||
137 | case RECORD_REMARK_ARG_WITHOUT_DEBUGLOC: { | |||
138 | if (Record.size() != 2) | |||
139 | return malformedRecord("BLOCK_REMARK", | |||
140 | "RECORD_REMARK_ARG_WITHOUT_DEBUGLOC"); | |||
141 | // Create a temporary argument. Use that as a valid memory location for this | |||
142 | // argument entry. | |||
143 | Parser.TmpArgs.emplace_back(); | |||
144 | Parser.TmpArgs.back().KeyIdx = Record[0]; | |||
145 | Parser.TmpArgs.back().ValueIdx = Record[1]; | |||
146 | Parser.Args = | |||
147 | ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs); | |||
148 | break; | |||
149 | } | |||
150 | default: | |||
151 | return unknownRecord("BLOCK_REMARK", *RecordID); | |||
152 | } | |||
153 | return Error::success(); | |||
154 | } | |||
155 | ||||
156 | template <typename T> | |||
157 | static Error parseBlock(T &ParserHelper, unsigned BlockID, | |||
158 | const char *BlockName) { | |||
159 | BitstreamCursor &Stream = ParserHelper.Stream; | |||
160 | Expected<BitstreamEntry> Next = Stream.advance(); | |||
161 | if (!Next) | |||
162 | return Next.takeError(); | |||
163 | if (Next->Kind != BitstreamEntry::SubBlock || Next->ID != BlockID) | |||
164 | return createStringError( | |||
165 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
166 | "Error while parsing %s: expecting [ENTER_SUBBLOCK, %s, ...].", | |||
167 | BlockName, BlockName); | |||
168 | if (Stream.EnterSubBlock(BlockID)) | |||
169 | return createStringError( | |||
170 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
171 | "Error while entering %s.", BlockName); | |||
172 | ||||
173 | // Stop when there is nothing to read anymore or when we encounter an | |||
174 | // END_BLOCK. | |||
175 | while (!Stream.AtEndOfStream()) { | |||
176 | Next = Stream.advance(); | |||
177 | if (!Next) | |||
178 | return Next.takeError(); | |||
179 | switch (Next->Kind) { | |||
180 | case BitstreamEntry::EndBlock: | |||
181 | return Error::success(); | |||
182 | case BitstreamEntry::Error: | |||
183 | case BitstreamEntry::SubBlock: | |||
184 | return createStringError( | |||
185 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
186 | "Error while parsing %s: expecting records.", BlockName); | |||
187 | case BitstreamEntry::Record: | |||
188 | if (Error E = parseRecord(ParserHelper, Next->ID)) | |||
189 | return E; | |||
190 | continue; | |||
191 | } | |||
192 | } | |||
193 | // If we're here, it means we didn't get an END_BLOCK yet, but we're at the | |||
194 | // end of the stream. In this case, error. | |||
195 | return createStringError( | |||
196 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
197 | "Error while parsing %s: unterminated block.", BlockName); | |||
198 | } | |||
199 | ||||
200 | Error BitstreamMetaParserHelper::parse() { | |||
201 | return parseBlock(*this, META_BLOCK_ID, "META_BLOCK"); | |||
202 | } | |||
203 | ||||
204 | Error BitstreamRemarkParserHelper::parse() { | |||
205 | return parseBlock(*this, REMARK_BLOCK_ID, "REMARK_BLOCK"); | |||
206 | } | |||
207 | ||||
208 | BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer) | |||
209 | : Stream(Buffer) {} | |||
210 | ||||
211 | Expected<std::array<char, 4>> BitstreamParserHelper::parseMagic() { | |||
212 | std::array<char, 4> Result; | |||
213 | for (unsigned i = 0; i < 4; ++i) | |||
214 | if (Expected<unsigned> R = Stream.Read(8)) | |||
215 | Result[i] = *R; | |||
216 | else | |||
217 | return R.takeError(); | |||
218 | return Result; | |||
219 | } | |||
220 | ||||
221 | Error BitstreamParserHelper::parseBlockInfoBlock() { | |||
222 | Expected<BitstreamEntry> Next = Stream.advance(); | |||
223 | if (!Next) | |||
224 | return Next.takeError(); | |||
225 | if (Next->Kind != BitstreamEntry::SubBlock || | |||
226 | Next->ID != llvm::bitc::BLOCKINFO_BLOCK_ID) | |||
227 | return createStringError( | |||
228 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
229 | "Error while parsing BLOCKINFO_BLOCK: expecting [ENTER_SUBBLOCK, " | |||
230 | "BLOCKINFO_BLOCK, ...]."); | |||
231 | ||||
232 | Expected<Optional<BitstreamBlockInfo>> MaybeBlockInfo = | |||
233 | Stream.ReadBlockInfoBlock(); | |||
234 | if (!MaybeBlockInfo) | |||
235 | return MaybeBlockInfo.takeError(); | |||
236 | ||||
237 | if (!*MaybeBlockInfo) | |||
238 | return createStringError( | |||
239 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
240 | "Error while parsing BLOCKINFO_BLOCK."); | |||
241 | ||||
242 | BlockInfo = **MaybeBlockInfo; | |||
243 | ||||
244 | Stream.setBlockInfo(&BlockInfo); | |||
245 | return Error::success(); | |||
246 | } | |||
247 | ||||
248 | static Expected<bool> isBlock(BitstreamCursor &Stream, unsigned BlockID) { | |||
249 | bool Result = false; | |||
250 | uint64_t PreviousBitNo = Stream.GetCurrentBitNo(); | |||
251 | Expected<BitstreamEntry> Next = Stream.advance(); | |||
252 | if (!Next) | |||
253 | return Next.takeError(); | |||
254 | switch (Next->Kind) { | |||
255 | case BitstreamEntry::SubBlock: | |||
256 | // Check for the block id. | |||
257 | Result = Next->ID == BlockID; | |||
258 | break; | |||
259 | case BitstreamEntry::Error: | |||
260 | return createStringError( | |||
261 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
262 | "Unexpected error while parsing bitstream."); | |||
263 | default: | |||
264 | Result = false; | |||
265 | break; | |||
266 | } | |||
267 | if (Error E = Stream.JumpToBit(PreviousBitNo)) | |||
268 | return std::move(E); | |||
269 | return Result; | |||
270 | } | |||
271 | ||||
272 | Expected<bool> BitstreamParserHelper::isMetaBlock() { | |||
273 | return isBlock(Stream, META_BLOCK_ID); | |||
274 | } | |||
275 | ||||
276 | Expected<bool> BitstreamParserHelper::isRemarkBlock() { | |||
277 | return isBlock(Stream, META_BLOCK_ID); | |||
278 | } | |||
279 | ||||
280 | static Error validateMagicNumber(StringRef MagicNumber) { | |||
281 | if (MagicNumber != remarks::ContainerMagic) | |||
282 | return createStringError(std::make_error_code(std::errc::invalid_argument), | |||
283 | "Unknown magic number: expecting %s, got %.4s.", | |||
284 | remarks::ContainerMagic.data(), MagicNumber.data()); | |||
285 | return Error::success(); | |||
286 | } | |||
287 | ||||
288 | static Error advanceToMetaBlock(BitstreamParserHelper &Helper) { | |||
289 | Expected<std::array<char, 4>> MagicNumber = Helper.parseMagic(); | |||
290 | if (!MagicNumber) | |||
291 | return MagicNumber.takeError(); | |||
292 | if (Error E = validateMagicNumber( | |||
293 | StringRef(MagicNumber->data(), MagicNumber->size()))) | |||
294 | return E; | |||
295 | if (Error E = Helper.parseBlockInfoBlock()) | |||
296 | return E; | |||
297 | Expected<bool> isMetaBlock = Helper.isMetaBlock(); | |||
298 | if (!isMetaBlock) | |||
299 | return isMetaBlock.takeError(); | |||
300 | if (!*isMetaBlock) | |||
301 | return createStringError( | |||
302 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
303 | "Expecting META_BLOCK after the BLOCKINFO_BLOCK."); | |||
304 | return Error::success(); | |||
305 | } | |||
306 | ||||
307 | Expected<std::unique_ptr<BitstreamRemarkParser>> | |||
308 | remarks::createBitstreamParserFromMeta( | |||
309 | StringRef Buf, Optional<ParsedStringTable> StrTab, | |||
310 | Optional<StringRef> ExternalFilePrependPath) { | |||
311 | BitstreamParserHelper Helper(Buf); | |||
312 | Expected<std::array<char, 4>> MagicNumber = Helper.parseMagic(); | |||
313 | if (!MagicNumber) | |||
314 | return MagicNumber.takeError(); | |||
315 | ||||
316 | if (Error E = validateMagicNumber( | |||
317 | StringRef(MagicNumber->data(), MagicNumber->size()))) | |||
318 | return std::move(E); | |||
319 | ||||
320 | auto Parser = | |||
321 | StrTab ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab)) | |||
322 | : std::make_unique<BitstreamRemarkParser>(Buf); | |||
323 | ||||
324 | if (ExternalFilePrependPath) | |||
325 | Parser->ExternalFilePrependPath = std::string(*ExternalFilePrependPath); | |||
326 | ||||
327 | return std::move(Parser); | |||
328 | } | |||
329 | ||||
330 | Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::next() { | |||
331 | if (ParserHelper.atEndOfStream()) | |||
| ||||
332 | return make_error<EndOfFileError>(); | |||
333 | ||||
334 | if (!ReadyToParseRemarks) { | |||
335 | if (Error E = parseMeta()) | |||
336 | return std::move(E); | |||
337 | ReadyToParseRemarks = true; | |||
338 | } | |||
339 | ||||
340 | return parseRemark(); | |||
341 | } | |||
342 | ||||
343 | Error BitstreamRemarkParser::parseMeta() { | |||
344 | // Advance and to the meta block. | |||
345 | if (Error E = advanceToMetaBlock(ParserHelper)) | |||
346 | return E; | |||
347 | ||||
348 | BitstreamMetaParserHelper MetaHelper(ParserHelper.Stream, | |||
349 | ParserHelper.BlockInfo); | |||
350 | if (Error E = MetaHelper.parse()) | |||
351 | return E; | |||
352 | ||||
353 | if (Error E = processCommonMeta(MetaHelper)) | |||
354 | return E; | |||
355 | ||||
356 | switch (ContainerType) { | |||
357 | case BitstreamRemarkContainerType::Standalone: | |||
358 | return processStandaloneMeta(MetaHelper); | |||
359 | case BitstreamRemarkContainerType::SeparateRemarksFile: | |||
360 | return processSeparateRemarksFileMeta(MetaHelper); | |||
361 | case BitstreamRemarkContainerType::SeparateRemarksMeta: | |||
362 | return processSeparateRemarksMetaMeta(MetaHelper); | |||
363 | } | |||
364 | llvm_unreachable("Unknown BitstreamRemarkContainerType enum")__builtin_unreachable(); | |||
365 | } | |||
366 | ||||
367 | Error BitstreamRemarkParser::processCommonMeta( | |||
368 | BitstreamMetaParserHelper &Helper) { | |||
369 | if (Optional<uint64_t> Version = Helper.ContainerVersion) | |||
370 | ContainerVersion = *Version; | |||
371 | else | |||
372 | return createStringError( | |||
373 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
374 | "Error while parsing BLOCK_META: missing container version."); | |||
375 | ||||
376 | if (Optional<uint8_t> Type = Helper.ContainerType) { | |||
377 | // Always >= BitstreamRemarkContainerType::First since it's unsigned. | |||
378 | if (*Type > static_cast<uint8_t>(BitstreamRemarkContainerType::Last)) | |||
379 | return createStringError( | |||
380 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
381 | "Error while parsing BLOCK_META: invalid container type."); | |||
382 | ||||
383 | ContainerType = static_cast<BitstreamRemarkContainerType>(*Type); | |||
384 | } else | |||
385 | return createStringError( | |||
386 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
387 | "Error while parsing BLOCK_META: missing container type."); | |||
388 | ||||
389 | return Error::success(); | |||
390 | } | |||
391 | ||||
392 | static Error processStrTab(BitstreamRemarkParser &P, | |||
393 | Optional<StringRef> StrTabBuf) { | |||
394 | if (!StrTabBuf) | |||
395 | return createStringError( | |||
396 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
397 | "Error while parsing BLOCK_META: missing string table."); | |||
398 | // Parse and assign the string table. | |||
399 | P.StrTab.emplace(*StrTabBuf); | |||
400 | return Error::success(); | |||
401 | } | |||
402 | ||||
403 | static Error processRemarkVersion(BitstreamRemarkParser &P, | |||
404 | Optional<uint64_t> RemarkVersion) { | |||
405 | if (!RemarkVersion) | |||
406 | return createStringError( | |||
407 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
408 | "Error while parsing BLOCK_META: missing remark version."); | |||
409 | P.RemarkVersion = *RemarkVersion; | |||
410 | return Error::success(); | |||
411 | } | |||
412 | ||||
413 | Error BitstreamRemarkParser::processExternalFilePath( | |||
414 | Optional<StringRef> ExternalFilePath) { | |||
415 | if (!ExternalFilePath) | |||
416 | return createStringError( | |||
417 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
418 | "Error while parsing BLOCK_META: missing external file path."); | |||
419 | ||||
420 | SmallString<80> FullPath(ExternalFilePrependPath); | |||
421 | sys::path::append(FullPath, *ExternalFilePath); | |||
422 | ||||
423 | // External file: open the external file, parse it, check if its metadata | |||
424 | // matches the one from the separate metadata, then replace the current parser | |||
425 | // with the one parsing the remarks. | |||
426 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = | |||
427 | MemoryBuffer::getFile(FullPath); | |||
428 | if (std::error_code EC = BufferOrErr.getError()) | |||
429 | return createFileError(FullPath, EC); | |||
430 | ||||
431 | TmpRemarkBuffer = std::move(*BufferOrErr); | |||
432 | ||||
433 | // Don't try to parse the file if it's empty. | |||
434 | if (TmpRemarkBuffer->getBufferSize() == 0) | |||
435 | return make_error<EndOfFileError>(); | |||
436 | ||||
437 | // Create a separate parser used for parsing the separate file. | |||
438 | ParserHelper = BitstreamParserHelper(TmpRemarkBuffer->getBuffer()); | |||
439 | // Advance and check until we can parse the meta block. | |||
440 | if (Error E = advanceToMetaBlock(ParserHelper)) | |||
441 | return E; | |||
442 | // Parse the meta from the separate file. | |||
443 | // Note: here we overwrite the BlockInfo with the one from the file. This will | |||
444 | // be used to parse the rest of the file. | |||
445 | BitstreamMetaParserHelper SeparateMetaHelper(ParserHelper.Stream, | |||
446 | ParserHelper.BlockInfo); | |||
447 | if (Error E = SeparateMetaHelper.parse()) | |||
448 | return E; | |||
449 | ||||
450 | uint64_t PreviousContainerVersion = ContainerVersion; | |||
451 | if (Error E = processCommonMeta(SeparateMetaHelper)) | |||
452 | return E; | |||
453 | ||||
454 | if (ContainerType != BitstreamRemarkContainerType::SeparateRemarksFile) | |||
455 | return createStringError( | |||
456 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
457 | "Error while parsing external file's BLOCK_META: wrong container " | |||
458 | "type."); | |||
459 | ||||
460 | if (PreviousContainerVersion != ContainerVersion) | |||
461 | return createStringError( | |||
462 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
463 | "Error while parsing external file's BLOCK_META: mismatching versions: " | |||
464 | "original meta: %lu, external file meta: %lu.", | |||
465 | PreviousContainerVersion, ContainerVersion); | |||
466 | ||||
467 | // Process the meta from the separate file. | |||
468 | return processSeparateRemarksFileMeta(SeparateMetaHelper); | |||
469 | } | |||
470 | ||||
471 | Error BitstreamRemarkParser::processStandaloneMeta( | |||
472 | BitstreamMetaParserHelper &Helper) { | |||
473 | if (Error E = processStrTab(*this, Helper.StrTabBuf)) | |||
474 | return E; | |||
475 | return processRemarkVersion(*this, Helper.RemarkVersion); | |||
476 | } | |||
477 | ||||
478 | Error BitstreamRemarkParser::processSeparateRemarksFileMeta( | |||
479 | BitstreamMetaParserHelper &Helper) { | |||
480 | return processRemarkVersion(*this, Helper.RemarkVersion); | |||
481 | } | |||
482 | ||||
483 | Error BitstreamRemarkParser::processSeparateRemarksMetaMeta( | |||
484 | BitstreamMetaParserHelper &Helper) { | |||
485 | if (Error E = processStrTab(*this, Helper.StrTabBuf)) | |||
486 | return E; | |||
487 | return processExternalFilePath(Helper.ExternalFilePath); | |||
488 | } | |||
489 | ||||
490 | Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::parseRemark() { | |||
491 | BitstreamRemarkParserHelper RemarkHelper(ParserHelper.Stream); | |||
492 | if (Error E = RemarkHelper.parse()) | |||
493 | return std::move(E); | |||
494 | ||||
495 | return processRemark(RemarkHelper); | |||
496 | } | |||
497 | ||||
498 | Expected<std::unique_ptr<Remark>> | |||
499 | BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) { | |||
500 | std::unique_ptr<Remark> Result = std::make_unique<Remark>(); | |||
501 | Remark &R = *Result; | |||
502 | ||||
503 | if (StrTab == None) | |||
504 | return createStringError( | |||
505 | std::make_error_code(std::errc::invalid_argument), | |||
506 | "Error while parsing BLOCK_REMARK: missing string table."); | |||
507 | ||||
508 | if (!Helper.Type) | |||
509 | return createStringError( | |||
510 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
511 | "Error while parsing BLOCK_REMARK: missing remark type."); | |||
512 | ||||
513 | // Always >= Type::First since it's unsigned. | |||
514 | if (*Helper.Type > static_cast<uint8_t>(Type::Last)) | |||
515 | return createStringError( | |||
516 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
517 | "Error while parsing BLOCK_REMARK: unknown remark type."); | |||
518 | ||||
519 | R.RemarkType = static_cast<Type>(*Helper.Type); | |||
520 | ||||
521 | if (!Helper.RemarkNameIdx) | |||
522 | return createStringError( | |||
523 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
524 | "Error while parsing BLOCK_REMARK: missing remark name."); | |||
525 | ||||
526 | if (Expected<StringRef> RemarkName = (*StrTab)[*Helper.RemarkNameIdx]) | |||
527 | R.RemarkName = *RemarkName; | |||
528 | else | |||
529 | return RemarkName.takeError(); | |||
530 | ||||
531 | if (!Helper.PassNameIdx) | |||
532 | return createStringError( | |||
533 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
534 | "Error while parsing BLOCK_REMARK: missing remark pass."); | |||
535 | ||||
536 | if (Expected<StringRef> PassName = (*StrTab)[*Helper.PassNameIdx]) | |||
537 | R.PassName = *PassName; | |||
538 | else | |||
539 | return PassName.takeError(); | |||
540 | ||||
541 | if (!Helper.FunctionNameIdx) | |||
542 | return createStringError( | |||
543 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
544 | "Error while parsing BLOCK_REMARK: missing remark function name."); | |||
545 | if (Expected<StringRef> FunctionName = (*StrTab)[*Helper.FunctionNameIdx]) | |||
546 | R.FunctionName = *FunctionName; | |||
547 | else | |||
548 | return FunctionName.takeError(); | |||
549 | ||||
550 | if (Helper.SourceFileNameIdx && Helper.SourceLine && Helper.SourceColumn) { | |||
551 | Expected<StringRef> SourceFileName = (*StrTab)[*Helper.SourceFileNameIdx]; | |||
552 | if (!SourceFileName) | |||
553 | return SourceFileName.takeError(); | |||
554 | R.Loc.emplace(); | |||
555 | R.Loc->SourceFilePath = *SourceFileName; | |||
556 | R.Loc->SourceLine = *Helper.SourceLine; | |||
557 | R.Loc->SourceColumn = *Helper.SourceColumn; | |||
558 | } | |||
559 | ||||
560 | if (Helper.Hotness) | |||
561 | R.Hotness = *Helper.Hotness; | |||
562 | ||||
563 | if (!Helper.Args) | |||
564 | return std::move(Result); | |||
565 | ||||
566 | for (const BitstreamRemarkParserHelper::Argument &Arg : *Helper.Args) { | |||
567 | if (!Arg.KeyIdx) | |||
568 | return createStringError( | |||
569 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
570 | "Error while parsing BLOCK_REMARK: missing key in remark argument."); | |||
571 | if (!Arg.ValueIdx) | |||
572 | return createStringError( | |||
573 | std::make_error_code(std::errc::illegal_byte_sequence), | |||
574 | "Error while parsing BLOCK_REMARK: missing value in remark " | |||
575 | "argument."); | |||
576 | ||||
577 | // We have at least a key and a value, create an entry. | |||
578 | R.Args.emplace_back(); | |||
579 | ||||
580 | if (Expected<StringRef> Key = (*StrTab)[*Arg.KeyIdx]) | |||
581 | R.Args.back().Key = *Key; | |||
582 | else | |||
583 | return Key.takeError(); | |||
584 | ||||
585 | if (Expected<StringRef> Value = (*StrTab)[*Arg.ValueIdx]) | |||
586 | R.Args.back().Val = *Value; | |||
587 | else | |||
588 | return Value.takeError(); | |||
589 | ||||
590 | if (Arg.SourceFileNameIdx && Arg.SourceLine && Arg.SourceColumn) { | |||
591 | if (Expected<StringRef> SourceFileName = | |||
592 | (*StrTab)[*Arg.SourceFileNameIdx]) { | |||
593 | R.Args.back().Loc.emplace(); | |||
594 | R.Args.back().Loc->SourceFilePath = *SourceFileName; | |||
595 | R.Args.back().Loc->SourceLine = *Arg.SourceLine; | |||
596 | R.Args.back().Loc->SourceColumn = *Arg.SourceColumn; | |||
597 | } else | |||
598 | return SourceFileName.takeError(); | |||
599 | } | |||
600 | } | |||
601 | ||||
602 | return std::move(Result); | |||
603 | } |
1 | //===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===// | |||
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 header defines the BitstreamReader class. This class can be used to | |||
10 | // read an arbitrary bitstream, regardless of its contents. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #ifndef LLVM_BITSTREAM_BITSTREAMREADER_H | |||
15 | #define LLVM_BITSTREAM_BITSTREAMREADER_H | |||
16 | ||||
17 | #include "llvm/ADT/ArrayRef.h" | |||
18 | #include "llvm/ADT/SmallVector.h" | |||
19 | #include "llvm/Bitstream/BitCodes.h" | |||
20 | #include "llvm/Support/Endian.h" | |||
21 | #include "llvm/Support/Error.h" | |||
22 | #include "llvm/Support/ErrorHandling.h" | |||
23 | #include "llvm/Support/MathExtras.h" | |||
24 | #include "llvm/Support/MemoryBuffer.h" | |||
25 | #include <algorithm> | |||
26 | #include <cassert> | |||
27 | #include <climits> | |||
28 | #include <cstddef> | |||
29 | #include <cstdint> | |||
30 | #include <memory> | |||
31 | #include <string> | |||
32 | #include <utility> | |||
33 | #include <vector> | |||
34 | ||||
35 | namespace llvm { | |||
36 | ||||
37 | /// This class maintains the abbreviations read from a block info block. | |||
38 | class BitstreamBlockInfo { | |||
39 | public: | |||
40 | /// This contains information emitted to BLOCKINFO_BLOCK blocks. These | |||
41 | /// describe abbreviations that all blocks of the specified ID inherit. | |||
42 | struct BlockInfo { | |||
43 | unsigned BlockID = 0; | |||
44 | std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs; | |||
45 | std::string Name; | |||
46 | std::vector<std::pair<unsigned, std::string>> RecordNames; | |||
47 | }; | |||
48 | ||||
49 | private: | |||
50 | std::vector<BlockInfo> BlockInfoRecords; | |||
51 | ||||
52 | public: | |||
53 | /// If there is block info for the specified ID, return it, otherwise return | |||
54 | /// null. | |||
55 | const BlockInfo *getBlockInfo(unsigned BlockID) const { | |||
56 | // Common case, the most recent entry matches BlockID. | |||
57 | if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) | |||
58 | return &BlockInfoRecords.back(); | |||
59 | ||||
60 | for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size()); | |||
61 | i != e; ++i) | |||
62 | if (BlockInfoRecords[i].BlockID == BlockID) | |||
63 | return &BlockInfoRecords[i]; | |||
64 | return nullptr; | |||
65 | } | |||
66 | ||||
67 | BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { | |||
68 | if (const BlockInfo *BI = getBlockInfo(BlockID)) | |||
69 | return *const_cast<BlockInfo*>(BI); | |||
70 | ||||
71 | // Otherwise, add a new record. | |||
72 | BlockInfoRecords.emplace_back(); | |||
73 | BlockInfoRecords.back().BlockID = BlockID; | |||
74 | return BlockInfoRecords.back(); | |||
75 | } | |||
76 | }; | |||
77 | ||||
78 | /// This represents a position within a bitstream. There may be multiple | |||
79 | /// independent cursors reading within one bitstream, each maintaining their | |||
80 | /// own local state. | |||
81 | class SimpleBitstreamCursor { | |||
82 | ArrayRef<uint8_t> BitcodeBytes; | |||
83 | size_t NextChar = 0; | |||
84 | ||||
85 | public: | |||
86 | /// This is the current data we have pulled from the stream but have not | |||
87 | /// returned to the client. This is specifically and intentionally defined to | |||
88 | /// follow the word size of the host machine for efficiency. We use word_t in | |||
89 | /// places that are aware of this to make it perfectly explicit what is going | |||
90 | /// on. | |||
91 | using word_t = size_t; | |||
92 | ||||
93 | private: | |||
94 | word_t CurWord = 0; | |||
95 | ||||
96 | /// This is the number of bits in CurWord that are valid. This is always from | |||
97 | /// [0...bits_of(size_t)-1] inclusive. | |||
98 | unsigned BitsInCurWord = 0; | |||
99 | ||||
100 | public: | |||
101 | static const constexpr size_t MaxChunkSize = sizeof(word_t) * 8; | |||
102 | ||||
103 | SimpleBitstreamCursor() = default; | |||
104 | explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes) | |||
105 | : BitcodeBytes(BitcodeBytes) {} | |||
106 | explicit SimpleBitstreamCursor(StringRef BitcodeBytes) | |||
107 | : BitcodeBytes(arrayRefFromStringRef(BitcodeBytes)) {} | |||
108 | explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes) | |||
109 | : SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {} | |||
110 | ||||
111 | bool canSkipToPos(size_t pos) const { | |||
112 | // pos can be skipped to if it is a valid address or one byte past the end. | |||
113 | return pos <= BitcodeBytes.size(); | |||
114 | } | |||
115 | ||||
116 | bool AtEndOfStream() { | |||
117 | return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar; | |||
118 | } | |||
119 | ||||
120 | /// Return the bit # of the bit we are reading. | |||
121 | uint64_t GetCurrentBitNo() const { | |||
122 | return NextChar*CHAR_BIT8 - BitsInCurWord; | |||
123 | } | |||
124 | ||||
125 | // Return the byte # of the current bit. | |||
126 | uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; } | |||
127 | ||||
128 | ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; } | |||
129 | ||||
130 | /// Reset the stream to the specified bit number. | |||
131 | Error JumpToBit(uint64_t BitNo) { | |||
132 | size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); | |||
133 | unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); | |||
134 | assert(canSkipToPos(ByteNo) && "Invalid location")((void)0); | |||
135 | ||||
136 | // Move the cursor to the right word. | |||
137 | NextChar = ByteNo; | |||
138 | BitsInCurWord = 0; | |||
139 | ||||
140 | // Skip over any bits that are already consumed. | |||
141 | if (WordBitNo) { | |||
142 | if (Expected<word_t> Res = Read(WordBitNo)) | |||
143 | return Error::success(); | |||
144 | else | |||
145 | return Res.takeError(); | |||
146 | } | |||
147 | ||||
148 | return Error::success(); | |||
149 | } | |||
150 | ||||
151 | /// Get a pointer into the bitstream at the specified byte offset. | |||
152 | const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) { | |||
153 | return BitcodeBytes.data() + ByteNo; | |||
154 | } | |||
155 | ||||
156 | /// Get a pointer into the bitstream at the specified bit offset. | |||
157 | /// | |||
158 | /// The bit offset must be on a byte boundary. | |||
159 | const uint8_t *getPointerToBit(uint64_t BitNo, uint64_t NumBytes) { | |||
160 | assert(!(BitNo % 8) && "Expected bit on byte boundary")((void)0); | |||
161 | return getPointerToByte(BitNo / 8, NumBytes); | |||
162 | } | |||
163 | ||||
164 | Error fillCurWord() { | |||
165 | if (NextChar >= BitcodeBytes.size()) | |||
166 | return createStringError(std::errc::io_error, | |||
167 | "Unexpected end of file reading %u of %u bytes", | |||
168 | NextChar, BitcodeBytes.size()); | |||
169 | ||||
170 | // Read the next word from the stream. | |||
171 | const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar; | |||
172 | unsigned BytesRead; | |||
173 | if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) { | |||
174 | BytesRead = sizeof(word_t); | |||
175 | CurWord = | |||
176 | support::endian::read<word_t, support::little, support::unaligned>( | |||
177 | NextCharPtr); | |||
178 | } else { | |||
179 | // Short read. | |||
180 | BytesRead = BitcodeBytes.size() - NextChar; | |||
181 | CurWord = 0; | |||
182 | for (unsigned B = 0; B != BytesRead; ++B) | |||
183 | CurWord |= uint64_t(NextCharPtr[B]) << (B * 8); | |||
184 | } | |||
185 | NextChar += BytesRead; | |||
186 | BitsInCurWord = BytesRead * 8; | |||
187 | return Error::success(); | |||
188 | } | |||
189 | ||||
190 | Expected<word_t> Read(unsigned NumBits) { | |||
191 | static const unsigned BitsInWord = MaxChunkSize; | |||
192 | ||||
193 | assert(NumBits && NumBits <= BitsInWord &&((void)0) | |||
194 | "Cannot return zero or more than BitsInWord bits!")((void)0); | |||
195 | ||||
196 | static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f; | |||
197 | ||||
198 | // If the field is fully contained by CurWord, return it quickly. | |||
199 | if (BitsInCurWord >= NumBits) { | |||
200 | word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits)); | |||
| ||||
201 | ||||
202 | // Use a mask to avoid undefined behavior. | |||
203 | CurWord >>= (NumBits & Mask); | |||
204 | ||||
205 | BitsInCurWord -= NumBits; | |||
206 | return R; | |||
207 | } | |||
208 | ||||
209 | word_t R = BitsInCurWord ? CurWord : 0; | |||
210 | unsigned BitsLeft = NumBits - BitsInCurWord; | |||
211 | ||||
212 | if (Error fillResult = fillCurWord()) | |||
213 | return std::move(fillResult); | |||
214 | ||||
215 | // If we run out of data, abort. | |||
216 | if (BitsLeft > BitsInCurWord) | |||
217 | return createStringError(std::errc::io_error, | |||
218 | "Unexpected end of file reading %u of %u bits", | |||
219 | BitsInCurWord, BitsLeft); | |||
220 | ||||
221 | word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); | |||
222 | ||||
223 | // Use a mask to avoid undefined behavior. | |||
224 | CurWord >>= (BitsLeft & Mask); | |||
225 | ||||
226 | BitsInCurWord -= BitsLeft; | |||
227 | ||||
228 | R |= R2 << (NumBits - BitsLeft); | |||
229 | ||||
230 | return R; | |||
231 | } | |||
232 | ||||
233 | Expected<uint32_t> ReadVBR(unsigned NumBits) { | |||
234 | Expected<unsigned> MaybeRead = Read(NumBits); | |||
235 | if (!MaybeRead) | |||
236 | return MaybeRead; | |||
237 | uint32_t Piece = MaybeRead.get(); | |||
238 | ||||
239 | if ((Piece & (1U << (NumBits-1))) == 0) | |||
240 | return Piece; | |||
241 | ||||
242 | uint32_t Result = 0; | |||
243 | unsigned NextBit = 0; | |||
244 | while (true) { | |||
245 | Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; | |||
246 | ||||
247 | if ((Piece & (1U << (NumBits-1))) == 0) | |||
248 | return Result; | |||
249 | ||||
250 | NextBit += NumBits-1; | |||
251 | MaybeRead = Read(NumBits); | |||
252 | if (!MaybeRead) | |||
253 | return MaybeRead; | |||
254 | Piece = MaybeRead.get(); | |||
255 | } | |||
256 | } | |||
257 | ||||
258 | // Read a VBR that may have a value up to 64-bits in size. The chunk size of | |||
259 | // the VBR must still be <= 32 bits though. | |||
260 | Expected<uint64_t> ReadVBR64(unsigned NumBits) { | |||
261 | Expected<uint64_t> MaybeRead = Read(NumBits); | |||
262 | if (!MaybeRead) | |||
263 | return MaybeRead; | |||
264 | uint32_t Piece = MaybeRead.get(); | |||
265 | ||||
266 | if ((Piece & (1U << (NumBits-1))) == 0) | |||
267 | return uint64_t(Piece); | |||
268 | ||||
269 | uint64_t Result = 0; | |||
270 | unsigned NextBit = 0; | |||
271 | while (true) { | |||
272 | Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit; | |||
273 | ||||
274 | if ((Piece & (1U << (NumBits-1))) == 0) | |||
275 | return Result; | |||
276 | ||||
277 | NextBit += NumBits-1; | |||
278 | MaybeRead = Read(NumBits); | |||
279 | if (!MaybeRead) | |||
280 | return MaybeRead; | |||
281 | Piece = MaybeRead.get(); | |||
282 | } | |||
283 | } | |||
284 | ||||
285 | void SkipToFourByteBoundary() { | |||
286 | // If word_t is 64-bits and if we've read less than 32 bits, just dump | |||
287 | // the bits we have up to the next 32-bit boundary. | |||
288 | if (sizeof(word_t) > 4 && | |||
289 | BitsInCurWord >= 32) { | |||
290 | CurWord >>= BitsInCurWord-32; | |||
291 | BitsInCurWord = 32; | |||
292 | return; | |||
293 | } | |||
294 | ||||
295 | BitsInCurWord = 0; | |||
296 | } | |||
297 | ||||
298 | /// Return the size of the stream in bytes. | |||
299 | size_t SizeInBytes() const { return BitcodeBytes.size(); } | |||
300 | ||||
301 | /// Skip to the end of the file. | |||
302 | void skipToEnd() { NextChar = BitcodeBytes.size(); } | |||
303 | }; | |||
304 | ||||
305 | /// When advancing through a bitstream cursor, each advance can discover a few | |||
306 | /// different kinds of entries: | |||
307 | struct BitstreamEntry { | |||
308 | enum { | |||
309 | Error, // Malformed bitcode was found. | |||
310 | EndBlock, // We've reached the end of the current block, (or the end of the | |||
311 | // file, which is treated like a series of EndBlock records. | |||
312 | SubBlock, // This is the start of a new subblock of a specific ID. | |||
313 | Record // This is a record with a specific AbbrevID. | |||
314 | } Kind; | |||
315 | ||||
316 | unsigned ID; | |||
317 | ||||
318 | static BitstreamEntry getError() { | |||
319 | BitstreamEntry E; E.Kind = Error; return E; | |||
320 | } | |||
321 | ||||
322 | static BitstreamEntry getEndBlock() { | |||
323 | BitstreamEntry E; E.Kind = EndBlock; return E; | |||
324 | } | |||
325 | ||||
326 | static BitstreamEntry getSubBlock(unsigned ID) { | |||
327 | BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; | |||
328 | } | |||
329 | ||||
330 | static BitstreamEntry getRecord(unsigned AbbrevID) { | |||
331 | BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; | |||
332 | } | |||
333 | }; | |||
334 | ||||
335 | /// This represents a position within a bitcode file, implemented on top of a | |||
336 | /// SimpleBitstreamCursor. | |||
337 | /// | |||
338 | /// Unlike iterators, BitstreamCursors are heavy-weight objects that should not | |||
339 | /// be passed by value. | |||
340 | class BitstreamCursor : SimpleBitstreamCursor { | |||
341 | // This is the declared size of code values used for the current block, in | |||
342 | // bits. | |||
343 | unsigned CurCodeSize = 2; | |||
344 | ||||
345 | /// Abbrevs installed at in this block. | |||
346 | std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs; | |||
347 | ||||
348 | struct Block { | |||
349 | unsigned PrevCodeSize; | |||
350 | std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs; | |||
351 | ||||
352 | explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} | |||
353 | }; | |||
354 | ||||
355 | /// This tracks the codesize of parent blocks. | |||
356 | SmallVector<Block, 8> BlockScope; | |||
357 | ||||
358 | BitstreamBlockInfo *BlockInfo = nullptr; | |||
359 | ||||
360 | public: | |||
361 | static const size_t MaxChunkSize = sizeof(word_t) * 8; | |||
362 | ||||
363 | BitstreamCursor() = default; | |||
364 | explicit BitstreamCursor(ArrayRef<uint8_t> BitcodeBytes) | |||
365 | : SimpleBitstreamCursor(BitcodeBytes) {} | |||
366 | explicit BitstreamCursor(StringRef BitcodeBytes) | |||
367 | : SimpleBitstreamCursor(BitcodeBytes) {} | |||
368 | explicit BitstreamCursor(MemoryBufferRef BitcodeBytes) | |||
369 | : SimpleBitstreamCursor(BitcodeBytes) {} | |||
370 | ||||
371 | using SimpleBitstreamCursor::AtEndOfStream; | |||
372 | using SimpleBitstreamCursor::canSkipToPos; | |||
373 | using SimpleBitstreamCursor::fillCurWord; | |||
374 | using SimpleBitstreamCursor::getBitcodeBytes; | |||
375 | using SimpleBitstreamCursor::GetCurrentBitNo; | |||
376 | using SimpleBitstreamCursor::getCurrentByteNo; | |||
377 | using SimpleBitstreamCursor::getPointerToByte; | |||
378 | using SimpleBitstreamCursor::JumpToBit; | |||
379 | using SimpleBitstreamCursor::Read; | |||
380 | using SimpleBitstreamCursor::ReadVBR; | |||
381 | using SimpleBitstreamCursor::ReadVBR64; | |||
382 | using SimpleBitstreamCursor::SizeInBytes; | |||
383 | using SimpleBitstreamCursor::skipToEnd; | |||
384 | ||||
385 | /// Return the number of bits used to encode an abbrev #. | |||
386 | unsigned getAbbrevIDWidth() const { return CurCodeSize; } | |||
387 | ||||
388 | /// Flags that modify the behavior of advance(). | |||
389 | enum { | |||
390 | /// If this flag is used, the advance() method does not automatically pop | |||
391 | /// the block scope when the end of a block is reached. | |||
392 | AF_DontPopBlockAtEnd = 1, | |||
393 | ||||
394 | /// If this flag is used, abbrev entries are returned just like normal | |||
395 | /// records. | |||
396 | AF_DontAutoprocessAbbrevs = 2 | |||
397 | }; | |||
398 | ||||
399 | /// Advance the current bitstream, returning the next entry in the stream. | |||
400 | Expected<BitstreamEntry> advance(unsigned Flags = 0) { | |||
401 | while (true) { | |||
402 | if (AtEndOfStream()) | |||
403 | return BitstreamEntry::getError(); | |||
404 | ||||
405 | Expected<unsigned> MaybeCode = ReadCode(); | |||
406 | if (!MaybeCode) | |||
407 | return MaybeCode.takeError(); | |||
408 | unsigned Code = MaybeCode.get(); | |||
409 | ||||
410 | if (Code == bitc::END_BLOCK) { | |||
411 | // Pop the end of the block unless Flags tells us not to. | |||
412 | if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) | |||
413 | return BitstreamEntry::getError(); | |||
414 | return BitstreamEntry::getEndBlock(); | |||
415 | } | |||
416 | ||||
417 | if (Code == bitc::ENTER_SUBBLOCK) { | |||
418 | if (Expected<unsigned> MaybeSubBlock = ReadSubBlockID()) | |||
419 | return BitstreamEntry::getSubBlock(MaybeSubBlock.get()); | |||
420 | else | |||
421 | return MaybeSubBlock.takeError(); | |||
422 | } | |||
423 | ||||
424 | if (Code == bitc::DEFINE_ABBREV && | |||
425 | !(Flags & AF_DontAutoprocessAbbrevs)) { | |||
426 | // We read and accumulate abbrev's, the client can't do anything with | |||
427 | // them anyway. | |||
428 | if (Error Err = ReadAbbrevRecord()) | |||
429 | return std::move(Err); | |||
430 | continue; | |||
431 | } | |||
432 | ||||
433 | return BitstreamEntry::getRecord(Code); | |||
434 | } | |||
435 | } | |||
436 | ||||
437 | /// This is a convenience function for clients that don't expect any | |||
438 | /// subblocks. This just skips over them automatically. | |||
439 | Expected<BitstreamEntry> advanceSkippingSubblocks(unsigned Flags = 0) { | |||
440 | while (true) { | |||
441 | // If we found a normal entry, return it. | |||
442 | Expected<BitstreamEntry> MaybeEntry = advance(Flags); | |||
443 | if (!MaybeEntry) | |||
444 | return MaybeEntry; | |||
445 | BitstreamEntry Entry = MaybeEntry.get(); | |||
446 | ||||
447 | if (Entry.Kind != BitstreamEntry::SubBlock) | |||
448 | return Entry; | |||
449 | ||||
450 | // If we found a sub-block, just skip over it and check the next entry. | |||
451 | if (Error Err = SkipBlock()) | |||
452 | return std::move(Err); | |||
453 | } | |||
454 | } | |||
455 | ||||
456 | Expected<unsigned> ReadCode() { return Read(CurCodeSize); } | |||
457 | ||||
458 | // Block header: | |||
459 | // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] | |||
460 | ||||
461 | /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. | |||
462 | Expected<unsigned> ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); } | |||
463 | ||||
464 | /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body | |||
465 | /// of this block. | |||
466 | Error SkipBlock() { | |||
467 | // Read and ignore the codelen value. | |||
468 | if (Expected<uint32_t> Res = ReadVBR(bitc::CodeLenWidth)) | |||
469 | ; // Since we are skipping this block, we don't care what code widths are | |||
470 | // used inside of it. | |||
471 | else | |||
472 | return Res.takeError(); | |||
473 | ||||
474 | SkipToFourByteBoundary(); | |||
475 | Expected<unsigned> MaybeNum = Read(bitc::BlockSizeWidth); | |||
476 | if (!MaybeNum) | |||
477 | return MaybeNum.takeError(); | |||
478 | size_t NumFourBytes = MaybeNum.get(); | |||
479 | ||||
480 | // Check that the block wasn't partially defined, and that the offset isn't | |||
481 | // bogus. | |||
482 | size_t SkipTo = GetCurrentBitNo() + NumFourBytes * 4 * 8; | |||
483 | if (AtEndOfStream()) | |||
484 | return createStringError(std::errc::illegal_byte_sequence, | |||
485 | "can't skip block: already at end of stream"); | |||
486 | if (!canSkipToPos(SkipTo / 8)) | |||
487 | return createStringError(std::errc::illegal_byte_sequence, | |||
488 | "can't skip to bit %zu from %" PRIu64"llu", SkipTo, | |||
489 | GetCurrentBitNo()); | |||
490 | ||||
491 | if (Error Res = JumpToBit(SkipTo)) | |||
492 | return Res; | |||
493 | ||||
494 | return Error::success(); | |||
495 | } | |||
496 | ||||
497 | /// Having read the ENTER_SUBBLOCK abbrevid, and enter the block. | |||
498 | Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); | |||
499 | ||||
500 | bool ReadBlockEnd() { | |||
501 | if (BlockScope.empty()) return true; | |||
502 | ||||
503 | // Block tail: | |||
504 | // [END_BLOCK, <align4bytes>] | |||
505 | SkipToFourByteBoundary(); | |||
506 | ||||
507 | popBlockScope(); | |||
508 | return false; | |||
509 | } | |||
510 | ||||
511 | private: | |||
512 | void popBlockScope() { | |||
513 | CurCodeSize = BlockScope.back().PrevCodeSize; | |||
514 | ||||
515 | CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs); | |||
516 | BlockScope.pop_back(); | |||
517 | } | |||
518 | ||||
519 | //===--------------------------------------------------------------------===// | |||
520 | // Record Processing | |||
521 | //===--------------------------------------------------------------------===// | |||
522 | ||||
523 | public: | |||
524 | /// Return the abbreviation for the specified AbbrevId. | |||
525 | const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { | |||
526 | unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV; | |||
527 | if (AbbrevNo >= CurAbbrevs.size()) | |||
528 | report_fatal_error("Invalid abbrev number"); | |||
529 | return CurAbbrevs[AbbrevNo].get(); | |||
530 | } | |||
531 | ||||
532 | /// Read the current record and discard it, returning the code for the record. | |||
533 | Expected<unsigned> skipRecord(unsigned AbbrevID); | |||
534 | ||||
535 | Expected<unsigned> readRecord(unsigned AbbrevID, | |||
536 | SmallVectorImpl<uint64_t> &Vals, | |||
537 | StringRef *Blob = nullptr); | |||
538 | ||||
539 | //===--------------------------------------------------------------------===// | |||
540 | // Abbrev Processing | |||
541 | //===--------------------------------------------------------------------===// | |||
542 | Error ReadAbbrevRecord(); | |||
543 | ||||
544 | /// Read and return a block info block from the bitstream. If an error was | |||
545 | /// encountered, return None. | |||
546 | /// | |||
547 | /// \param ReadBlockInfoNames Whether to read block/record name information in | |||
548 | /// the BlockInfo block. Only llvm-bcanalyzer uses this. | |||
549 | Expected<Optional<BitstreamBlockInfo>> | |||
550 | ReadBlockInfoBlock(bool ReadBlockInfoNames = false); | |||
551 | ||||
552 | /// Set the block info to be used by this BitstreamCursor to interpret | |||
553 | /// abbreviated records. | |||
554 | void setBlockInfo(BitstreamBlockInfo *BI) { BlockInfo = BI; } | |||
555 | }; | |||
556 | ||||
557 | } // end llvm namespace | |||
558 | ||||
559 | #endif // LLVM_BITSTREAM_BITSTREAMREADER_H |