File: | llvm/include/llvm/Bitstream/BitstreamReader.h |
Warning: | line 221, column 39 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 | //===--- GlobalModuleIndex.cpp - Global Module Index ------------*- 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 file implements the GlobalModuleIndex class. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "clang/Serialization/GlobalModuleIndex.h" | |||
14 | #include "ASTReaderInternals.h" | |||
15 | #include "clang/Basic/FileManager.h" | |||
16 | #include "clang/Lex/HeaderSearch.h" | |||
17 | #include "clang/Serialization/ASTBitCodes.h" | |||
18 | #include "clang/Serialization/ModuleFile.h" | |||
19 | #include "clang/Serialization/PCHContainerOperations.h" | |||
20 | #include "llvm/ADT/DenseMap.h" | |||
21 | #include "llvm/ADT/MapVector.h" | |||
22 | #include "llvm/ADT/SmallString.h" | |||
23 | #include "llvm/ADT/StringRef.h" | |||
24 | #include "llvm/Bitstream/BitstreamReader.h" | |||
25 | #include "llvm/Bitstream/BitstreamWriter.h" | |||
26 | #include "llvm/Support/DJB.h" | |||
27 | #include "llvm/Support/FileSystem.h" | |||
28 | #include "llvm/Support/FileUtilities.h" | |||
29 | #include "llvm/Support/LockFileManager.h" | |||
30 | #include "llvm/Support/MemoryBuffer.h" | |||
31 | #include "llvm/Support/OnDiskHashTable.h" | |||
32 | #include "llvm/Support/Path.h" | |||
33 | #include "llvm/Support/TimeProfiler.h" | |||
34 | #include <cstdio> | |||
35 | using namespace clang; | |||
36 | using namespace serialization; | |||
37 | ||||
38 | //----------------------------------------------------------------------------// | |||
39 | // Shared constants | |||
40 | //----------------------------------------------------------------------------// | |||
41 | namespace { | |||
42 | enum { | |||
43 | /// The block containing the index. | |||
44 | GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID | |||
45 | }; | |||
46 | ||||
47 | /// Describes the record types in the index. | |||
48 | enum IndexRecordTypes { | |||
49 | /// Contains version information and potentially other metadata, | |||
50 | /// used to determine if we can read this global index file. | |||
51 | INDEX_METADATA, | |||
52 | /// Describes a module, including its file name and dependencies. | |||
53 | MODULE, | |||
54 | /// The index for identifiers. | |||
55 | IDENTIFIER_INDEX | |||
56 | }; | |||
57 | } | |||
58 | ||||
59 | /// The name of the global index file. | |||
60 | static const char * const IndexFileName = "modules.idx"; | |||
61 | ||||
62 | /// The global index file version. | |||
63 | static const unsigned CurrentVersion = 1; | |||
64 | ||||
65 | //----------------------------------------------------------------------------// | |||
66 | // Global module index reader. | |||
67 | //----------------------------------------------------------------------------// | |||
68 | ||||
69 | namespace { | |||
70 | ||||
71 | /// Trait used to read the identifier index from the on-disk hash | |||
72 | /// table. | |||
73 | class IdentifierIndexReaderTrait { | |||
74 | public: | |||
75 | typedef StringRef external_key_type; | |||
76 | typedef StringRef internal_key_type; | |||
77 | typedef SmallVector<unsigned, 2> data_type; | |||
78 | typedef unsigned hash_value_type; | |||
79 | typedef unsigned offset_type; | |||
80 | ||||
81 | static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { | |||
82 | return a == b; | |||
83 | } | |||
84 | ||||
85 | static hash_value_type ComputeHash(const internal_key_type& a) { | |||
86 | return llvm::djbHash(a); | |||
87 | } | |||
88 | ||||
89 | static std::pair<unsigned, unsigned> | |||
90 | ReadKeyDataLength(const unsigned char*& d) { | |||
91 | using namespace llvm::support; | |||
92 | unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); | |||
93 | unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); | |||
94 | return std::make_pair(KeyLen, DataLen); | |||
95 | } | |||
96 | ||||
97 | static const internal_key_type& | |||
98 | GetInternalKey(const external_key_type& x) { return x; } | |||
99 | ||||
100 | static const external_key_type& | |||
101 | GetExternalKey(const internal_key_type& x) { return x; } | |||
102 | ||||
103 | static internal_key_type ReadKey(const unsigned char* d, unsigned n) { | |||
104 | return StringRef((const char *)d, n); | |||
105 | } | |||
106 | ||||
107 | static data_type ReadData(const internal_key_type& k, | |||
108 | const unsigned char* d, | |||
109 | unsigned DataLen) { | |||
110 | using namespace llvm::support; | |||
111 | ||||
112 | data_type Result; | |||
113 | while (DataLen > 0) { | |||
114 | unsigned ID = endian::readNext<uint32_t, little, unaligned>(d); | |||
115 | Result.push_back(ID); | |||
116 | DataLen -= 4; | |||
117 | } | |||
118 | ||||
119 | return Result; | |||
120 | } | |||
121 | }; | |||
122 | ||||
123 | typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> | |||
124 | IdentifierIndexTable; | |||
125 | ||||
126 | } | |||
127 | ||||
128 | GlobalModuleIndex::GlobalModuleIndex( | |||
129 | std::unique_ptr<llvm::MemoryBuffer> IndexBuffer, | |||
130 | llvm::BitstreamCursor Cursor) | |||
131 | : Buffer(std::move(IndexBuffer)), IdentifierIndex(), NumIdentifierLookups(), | |||
132 | NumIdentifierLookupHits() { | |||
133 | auto Fail = [&](llvm::Error &&Err) { | |||
134 | report_fatal_error("Module index '" + Buffer->getBufferIdentifier() + | |||
135 | "' failed: " + toString(std::move(Err))); | |||
136 | }; | |||
137 | ||||
138 | llvm::TimeTraceScope TimeScope("Module LoadIndex"); | |||
139 | // Read the global index. | |||
140 | bool InGlobalIndexBlock = false; | |||
141 | bool Done = false; | |||
142 | while (!Done) { | |||
143 | llvm::BitstreamEntry Entry; | |||
144 | if (Expected<llvm::BitstreamEntry> Res = Cursor.advance()) | |||
145 | Entry = Res.get(); | |||
146 | else | |||
147 | Fail(Res.takeError()); | |||
148 | ||||
149 | switch (Entry.Kind) { | |||
150 | case llvm::BitstreamEntry::Error: | |||
151 | return; | |||
152 | ||||
153 | case llvm::BitstreamEntry::EndBlock: | |||
154 | if (InGlobalIndexBlock) { | |||
155 | InGlobalIndexBlock = false; | |||
156 | Done = true; | |||
157 | continue; | |||
158 | } | |||
159 | return; | |||
160 | ||||
161 | ||||
162 | case llvm::BitstreamEntry::Record: | |||
163 | // Entries in the global index block are handled below. | |||
164 | if (InGlobalIndexBlock) | |||
165 | break; | |||
166 | ||||
167 | return; | |||
168 | ||||
169 | case llvm::BitstreamEntry::SubBlock: | |||
170 | if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { | |||
171 | if (llvm::Error Err = Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) | |||
172 | Fail(std::move(Err)); | |||
173 | InGlobalIndexBlock = true; | |||
174 | } else if (llvm::Error Err = Cursor.SkipBlock()) | |||
175 | Fail(std::move(Err)); | |||
176 | continue; | |||
177 | } | |||
178 | ||||
179 | SmallVector<uint64_t, 64> Record; | |||
180 | StringRef Blob; | |||
181 | Expected<unsigned> MaybeIndexRecord = | |||
182 | Cursor.readRecord(Entry.ID, Record, &Blob); | |||
183 | if (!MaybeIndexRecord) | |||
184 | Fail(MaybeIndexRecord.takeError()); | |||
185 | IndexRecordTypes IndexRecord = | |||
186 | static_cast<IndexRecordTypes>(MaybeIndexRecord.get()); | |||
187 | switch (IndexRecord) { | |||
188 | case INDEX_METADATA: | |||
189 | // Make sure that the version matches. | |||
190 | if (Record.size() < 1 || Record[0] != CurrentVersion) | |||
191 | return; | |||
192 | break; | |||
193 | ||||
194 | case MODULE: { | |||
195 | unsigned Idx = 0; | |||
196 | unsigned ID = Record[Idx++]; | |||
197 | ||||
198 | // Make room for this module's information. | |||
199 | if (ID == Modules.size()) | |||
200 | Modules.push_back(ModuleInfo()); | |||
201 | else | |||
202 | Modules.resize(ID + 1); | |||
203 | ||||
204 | // Size/modification time for this module file at the time the | |||
205 | // global index was built. | |||
206 | Modules[ID].Size = Record[Idx++]; | |||
207 | Modules[ID].ModTime = Record[Idx++]; | |||
208 | ||||
209 | // File name. | |||
210 | unsigned NameLen = Record[Idx++]; | |||
211 | Modules[ID].FileName.assign(Record.begin() + Idx, | |||
212 | Record.begin() + Idx + NameLen); | |||
213 | Idx += NameLen; | |||
214 | ||||
215 | // Dependencies | |||
216 | unsigned NumDeps = Record[Idx++]; | |||
217 | Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), | |||
218 | Record.begin() + Idx, | |||
219 | Record.begin() + Idx + NumDeps); | |||
220 | Idx += NumDeps; | |||
221 | ||||
222 | // Make sure we're at the end of the record. | |||
223 | assert(Idx == Record.size() && "More module info?")(static_cast <bool> (Idx == Record.size() && "More module info?" ) ? void (0) : __assert_fail ("Idx == Record.size() && \"More module info?\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Serialization/GlobalModuleIndex.cpp" , 223, __extension__ __PRETTY_FUNCTION__)); | |||
224 | ||||
225 | // Record this module as an unresolved module. | |||
226 | // FIXME: this doesn't work correctly for module names containing path | |||
227 | // separators. | |||
228 | StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName); | |||
229 | // Remove the -<hash of ModuleMapPath> | |||
230 | ModuleName = ModuleName.rsplit('-').first; | |||
231 | UnresolvedModules[ModuleName] = ID; | |||
232 | break; | |||
233 | } | |||
234 | ||||
235 | case IDENTIFIER_INDEX: | |||
236 | // Wire up the identifier index. | |||
237 | if (Record[0]) { | |||
238 | IdentifierIndex = IdentifierIndexTable::Create( | |||
239 | (const unsigned char *)Blob.data() + Record[0], | |||
240 | (const unsigned char *)Blob.data() + sizeof(uint32_t), | |||
241 | (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait()); | |||
242 | } | |||
243 | break; | |||
244 | } | |||
245 | } | |||
246 | } | |||
247 | ||||
248 | GlobalModuleIndex::~GlobalModuleIndex() { | |||
249 | delete static_cast<IdentifierIndexTable *>(IdentifierIndex); | |||
250 | } | |||
251 | ||||
252 | std::pair<GlobalModuleIndex *, llvm::Error> | |||
253 | GlobalModuleIndex::readIndex(StringRef Path) { | |||
254 | // Load the index file, if it's there. | |||
255 | llvm::SmallString<128> IndexPath; | |||
256 | IndexPath += Path; | |||
257 | llvm::sys::path::append(IndexPath, IndexFileName); | |||
258 | ||||
259 | llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr = | |||
260 | llvm::MemoryBuffer::getFile(IndexPath.c_str()); | |||
261 | if (!BufferOrErr) | |||
262 | return std::make_pair(nullptr, | |||
263 | llvm::errorCodeToError(BufferOrErr.getError())); | |||
264 | std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get()); | |||
265 | ||||
266 | /// The main bitstream cursor for the main block. | |||
267 | llvm::BitstreamCursor Cursor(*Buffer); | |||
268 | ||||
269 | // Sniff for the signature. | |||
270 | for (unsigned char C : {'B', 'C', 'G', 'I'}) { | |||
271 | if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Cursor.Read(8)) { | |||
272 | if (Res.get() != C) | |||
273 | return std::make_pair( | |||
274 | nullptr, llvm::createStringError(std::errc::illegal_byte_sequence, | |||
275 | "expected signature BCGI")); | |||
276 | } else | |||
277 | return std::make_pair(nullptr, Res.takeError()); | |||
278 | } | |||
279 | ||||
280 | return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), | |||
281 | llvm::Error::success()); | |||
282 | } | |||
283 | ||||
284 | void | |||
285 | GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { | |||
286 | ModuleFiles.clear(); | |||
287 | for (unsigned I = 0, N = Modules.size(); I != N; ++I) { | |||
288 | if (ModuleFile *MF = Modules[I].File) | |||
289 | ModuleFiles.push_back(MF); | |||
290 | } | |||
291 | } | |||
292 | ||||
293 | void GlobalModuleIndex::getModuleDependencies( | |||
294 | ModuleFile *File, | |||
295 | SmallVectorImpl<ModuleFile *> &Dependencies) { | |||
296 | // Look for information about this module file. | |||
297 | llvm::DenseMap<ModuleFile *, unsigned>::iterator Known | |||
298 | = ModulesByFile.find(File); | |||
299 | if (Known == ModulesByFile.end()) | |||
300 | return; | |||
301 | ||||
302 | // Record dependencies. | |||
303 | Dependencies.clear(); | |||
304 | ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; | |||
305 | for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { | |||
306 | if (ModuleFile *MF = Modules[I].File) | |||
307 | Dependencies.push_back(MF); | |||
308 | } | |||
309 | } | |||
310 | ||||
311 | bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { | |||
312 | Hits.clear(); | |||
313 | ||||
314 | // If there's no identifier index, there is nothing we can do. | |||
315 | if (!IdentifierIndex) | |||
316 | return false; | |||
317 | ||||
318 | // Look into the identifier index. | |||
319 | ++NumIdentifierLookups; | |||
320 | IdentifierIndexTable &Table | |||
321 | = *static_cast<IdentifierIndexTable *>(IdentifierIndex); | |||
322 | IdentifierIndexTable::iterator Known = Table.find(Name); | |||
323 | if (Known == Table.end()) { | |||
324 | return false; | |||
325 | } | |||
326 | ||||
327 | SmallVector<unsigned, 2> ModuleIDs = *Known; | |||
328 | for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { | |||
329 | if (ModuleFile *MF = Modules[ModuleIDs[I]].File) | |||
330 | Hits.insert(MF); | |||
331 | } | |||
332 | ||||
333 | ++NumIdentifierLookupHits; | |||
334 | return true; | |||
335 | } | |||
336 | ||||
337 | bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { | |||
338 | // Look for the module in the global module index based on the module name. | |||
339 | StringRef Name = File->ModuleName; | |||
340 | llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); | |||
341 | if (Known == UnresolvedModules.end()) { | |||
342 | return true; | |||
343 | } | |||
344 | ||||
345 | // Rectify this module with the global module index. | |||
346 | ModuleInfo &Info = Modules[Known->second]; | |||
347 | ||||
348 | // If the size and modification time match what we expected, record this | |||
349 | // module file. | |||
350 | bool Failed = true; | |||
351 | if (File->File->getSize() == Info.Size && | |||
352 | File->File->getModificationTime() == Info.ModTime) { | |||
353 | Info.File = File; | |||
354 | ModulesByFile[File] = Known->second; | |||
355 | ||||
356 | Failed = false; | |||
357 | } | |||
358 | ||||
359 | // One way or another, we have resolved this module file. | |||
360 | UnresolvedModules.erase(Known); | |||
361 | return Failed; | |||
362 | } | |||
363 | ||||
364 | void GlobalModuleIndex::printStats() { | |||
365 | std::fprintf(stderrstderr, "*** Global Module Index Statistics:\n"); | |||
366 | if (NumIdentifierLookups) { | |||
367 | fprintf(stderrstderr, " %u / %u identifier lookups succeeded (%f%%)\n", | |||
368 | NumIdentifierLookupHits, NumIdentifierLookups, | |||
369 | (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); | |||
370 | } | |||
371 | std::fprintf(stderrstderr, "\n"); | |||
372 | } | |||
373 | ||||
374 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void GlobalModuleIndex::dump() { | |||
375 | llvm::errs() << "*** Global Module Index Dump:\n"; | |||
376 | llvm::errs() << "Module files:\n"; | |||
377 | for (auto &MI : Modules) { | |||
378 | llvm::errs() << "** " << MI.FileName << "\n"; | |||
379 | if (MI.File) | |||
380 | MI.File->dump(); | |||
381 | else | |||
382 | llvm::errs() << "\n"; | |||
383 | } | |||
384 | llvm::errs() << "\n"; | |||
385 | } | |||
386 | ||||
387 | //----------------------------------------------------------------------------// | |||
388 | // Global module index writer. | |||
389 | //----------------------------------------------------------------------------// | |||
390 | ||||
391 | namespace { | |||
392 | /// Provides information about a specific module file. | |||
393 | struct ModuleFileInfo { | |||
394 | /// The numberic ID for this module file. | |||
395 | unsigned ID; | |||
396 | ||||
397 | /// The set of modules on which this module depends. Each entry is | |||
398 | /// a module ID. | |||
399 | SmallVector<unsigned, 4> Dependencies; | |||
400 | ASTFileSignature Signature; | |||
401 | }; | |||
402 | ||||
403 | struct ImportedModuleFileInfo { | |||
404 | off_t StoredSize; | |||
405 | time_t StoredModTime; | |||
406 | ASTFileSignature StoredSignature; | |||
407 | ImportedModuleFileInfo(off_t Size, time_t ModTime, ASTFileSignature Sig) | |||
408 | : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {} | |||
409 | }; | |||
410 | ||||
411 | /// Builder that generates the global module index file. | |||
412 | class GlobalModuleIndexBuilder { | |||
413 | FileManager &FileMgr; | |||
414 | const PCHContainerReader &PCHContainerRdr; | |||
415 | ||||
416 | /// Mapping from files to module file information. | |||
417 | typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; | |||
418 | ||||
419 | /// Information about each of the known module files. | |||
420 | ModuleFilesMap ModuleFiles; | |||
421 | ||||
422 | /// Mapping from the imported module file to the imported | |||
423 | /// information. | |||
424 | typedef std::multimap<const FileEntry *, ImportedModuleFileInfo> | |||
425 | ImportedModuleFilesMap; | |||
426 | ||||
427 | /// Information about each importing of a module file. | |||
428 | ImportedModuleFilesMap ImportedModuleFiles; | |||
429 | ||||
430 | /// Mapping from identifiers to the list of module file IDs that | |||
431 | /// consider this identifier to be interesting. | |||
432 | typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; | |||
433 | ||||
434 | /// A mapping from all interesting identifiers to the set of module | |||
435 | /// files in which those identifiers are considered interesting. | |||
436 | InterestingIdentifierMap InterestingIdentifiers; | |||
437 | ||||
438 | /// Write the block-info block for the global module index file. | |||
439 | void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); | |||
440 | ||||
441 | /// Retrieve the module file information for the given file. | |||
442 | ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { | |||
443 | llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known | |||
444 | = ModuleFiles.find(File); | |||
445 | if (Known != ModuleFiles.end()) | |||
446 | return Known->second; | |||
447 | ||||
448 | unsigned NewID = ModuleFiles.size(); | |||
449 | ModuleFileInfo &Info = ModuleFiles[File]; | |||
450 | Info.ID = NewID; | |||
451 | return Info; | |||
452 | } | |||
453 | ||||
454 | public: | |||
455 | explicit GlobalModuleIndexBuilder( | |||
456 | FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr) | |||
457 | : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {} | |||
458 | ||||
459 | /// Load the contents of the given module file into the builder. | |||
460 | llvm::Error loadModuleFile(const FileEntry *File); | |||
461 | ||||
462 | /// Write the index to the given bitstream. | |||
463 | /// \returns true if an error occurred, false otherwise. | |||
464 | bool writeIndex(llvm::BitstreamWriter &Stream); | |||
465 | }; | |||
466 | } | |||
467 | ||||
468 | static void emitBlockID(unsigned ID, const char *Name, | |||
469 | llvm::BitstreamWriter &Stream, | |||
470 | SmallVectorImpl<uint64_t> &Record) { | |||
471 | Record.clear(); | |||
472 | Record.push_back(ID); | |||
473 | Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); | |||
474 | ||||
475 | // Emit the block name if present. | |||
476 | if (!Name || Name[0] == 0) return; | |||
477 | Record.clear(); | |||
478 | while (*Name) | |||
479 | Record.push_back(*Name++); | |||
480 | Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); | |||
481 | } | |||
482 | ||||
483 | static void emitRecordID(unsigned ID, const char *Name, | |||
484 | llvm::BitstreamWriter &Stream, | |||
485 | SmallVectorImpl<uint64_t> &Record) { | |||
486 | Record.clear(); | |||
487 | Record.push_back(ID); | |||
488 | while (*Name) | |||
489 | Record.push_back(*Name++); | |||
490 | Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); | |||
491 | } | |||
492 | ||||
493 | void | |||
494 | GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { | |||
495 | SmallVector<uint64_t, 64> Record; | |||
496 | Stream.EnterBlockInfoBlock(); | |||
497 | ||||
498 | #define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) | |||
499 | #define RECORD(X) emitRecordID(X, #X, Stream, Record) | |||
500 | BLOCK(GLOBAL_INDEX_BLOCK); | |||
501 | RECORD(INDEX_METADATA); | |||
502 | RECORD(MODULE); | |||
503 | RECORD(IDENTIFIER_INDEX); | |||
504 | #undef RECORD | |||
505 | #undef BLOCK | |||
506 | ||||
507 | Stream.ExitBlock(); | |||
508 | } | |||
509 | ||||
510 | namespace { | |||
511 | class InterestingASTIdentifierLookupTrait | |||
512 | : public serialization::reader::ASTIdentifierLookupTraitBase { | |||
513 | ||||
514 | public: | |||
515 | /// The identifier and whether it is "interesting". | |||
516 | typedef std::pair<StringRef, bool> data_type; | |||
517 | ||||
518 | data_type ReadData(const internal_key_type& k, | |||
519 | const unsigned char* d, | |||
520 | unsigned DataLen) { | |||
521 | // The first bit indicates whether this identifier is interesting. | |||
522 | // That's all we care about. | |||
523 | using namespace llvm::support; | |||
524 | unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); | |||
525 | bool IsInteresting = RawID & 0x01; | |||
526 | return std::make_pair(k, IsInteresting); | |||
527 | } | |||
528 | }; | |||
529 | } | |||
530 | ||||
531 | llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { | |||
532 | // Open the module file. | |||
533 | ||||
534 | auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true); | |||
535 | if (!Buffer) | |||
536 | return llvm::createStringError(Buffer.getError(), | |||
537 | "failed getting buffer for module file"); | |||
538 | ||||
539 | // Initialize the input stream | |||
540 | llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer)); | |||
541 | ||||
542 | // Sniff for the signature. | |||
543 | for (unsigned char C : {'C', 'P', 'C', 'H'}) | |||
544 | if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = InStream.Read(8)) { | |||
545 | if (Res.get() != C) | |||
546 | return llvm::createStringError(std::errc::illegal_byte_sequence, | |||
547 | "expected signature CPCH"); | |||
548 | } else | |||
549 | return Res.takeError(); | |||
550 | ||||
551 | // Record this module file and assign it a unique ID (if it doesn't have | |||
552 | // one already). | |||
553 | unsigned ID = getModuleFileInfo(File).ID; | |||
554 | ||||
555 | // Search for the blocks and records we care about. | |||
556 | enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other; | |||
557 | bool Done = false; | |||
558 | while (!Done) { | |||
559 | Expected<llvm::BitstreamEntry> MaybeEntry = InStream.advance(); | |||
560 | if (!MaybeEntry) | |||
561 | return MaybeEntry.takeError(); | |||
562 | llvm::BitstreamEntry Entry = MaybeEntry.get(); | |||
563 | ||||
564 | switch (Entry.Kind) { | |||
565 | case llvm::BitstreamEntry::Error: | |||
566 | Done = true; | |||
567 | continue; | |||
568 | ||||
569 | case llvm::BitstreamEntry::Record: | |||
570 | // In the 'other' state, just skip the record. We don't care. | |||
571 | if (State == Other) { | |||
572 | if (llvm::Expected<unsigned> Skipped = InStream.skipRecord(Entry.ID)) | |||
573 | continue; | |||
574 | else | |||
575 | return Skipped.takeError(); | |||
576 | } | |||
577 | ||||
578 | // Handle potentially-interesting records below. | |||
579 | break; | |||
580 | ||||
581 | case llvm::BitstreamEntry::SubBlock: | |||
582 | if (Entry.ID == CONTROL_BLOCK_ID) { | |||
583 | if (llvm::Error Err = InStream.EnterSubBlock(CONTROL_BLOCK_ID)) | |||
584 | return Err; | |||
585 | ||||
586 | // Found the control block. | |||
587 | State = ControlBlock; | |||
588 | continue; | |||
589 | } | |||
590 | ||||
591 | if (Entry.ID == AST_BLOCK_ID) { | |||
592 | if (llvm::Error Err = InStream.EnterSubBlock(AST_BLOCK_ID)) | |||
593 | return Err; | |||
594 | ||||
595 | // Found the AST block. | |||
596 | State = ASTBlock; | |||
597 | continue; | |||
598 | } | |||
599 | ||||
600 | if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) { | |||
601 | if (llvm::Error Err = InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID)) | |||
602 | return Err; | |||
603 | ||||
604 | // Found the Diagnostic Options block. | |||
605 | State = DiagnosticOptionsBlock; | |||
606 | continue; | |||
607 | } | |||
608 | ||||
609 | if (llvm::Error Err = InStream.SkipBlock()) | |||
610 | return Err; | |||
611 | ||||
612 | continue; | |||
613 | ||||
614 | case llvm::BitstreamEntry::EndBlock: | |||
615 | State = Other; | |||
616 | continue; | |||
617 | } | |||
618 | ||||
619 | // Read the given record. | |||
620 | SmallVector<uint64_t, 64> Record; | |||
621 | StringRef Blob; | |||
622 | Expected<unsigned> MaybeCode = InStream.readRecord(Entry.ID, Record, &Blob); | |||
623 | if (!MaybeCode) | |||
624 | return MaybeCode.takeError(); | |||
625 | unsigned Code = MaybeCode.get(); | |||
626 | ||||
627 | // Handle module dependencies. | |||
628 | if (State == ControlBlock && Code == IMPORTS) { | |||
629 | // Load each of the imported PCH files. | |||
630 | unsigned Idx = 0, N = Record.size(); | |||
631 | while (Idx < N) { | |||
632 | // Read information about the AST file. | |||
633 | ||||
634 | // Skip the imported kind | |||
635 | ++Idx; | |||
636 | ||||
637 | // Skip the import location | |||
638 | ++Idx; | |||
639 | ||||
640 | // Load stored size/modification time. | |||
641 | off_t StoredSize = (off_t)Record[Idx++]; | |||
642 | time_t StoredModTime = (time_t)Record[Idx++]; | |||
643 | ||||
644 | // Skip the stored signature. | |||
645 | // FIXME: we could read the signature out of the import and validate it. | |||
646 | auto FirstSignatureByte = Record.begin() + Idx; | |||
647 | ASTFileSignature StoredSignature = ASTFileSignature::create( | |||
648 | FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size); | |||
649 | Idx += ASTFileSignature::size; | |||
650 | ||||
651 | // Skip the module name (currently this is only used for prebuilt | |||
652 | // modules while here we are only dealing with cached). | |||
653 | Idx += Record[Idx] + 1; | |||
654 | ||||
655 | // Retrieve the imported file name. | |||
656 | unsigned Length = Record[Idx++]; | |||
657 | SmallString<128> ImportedFile(Record.begin() + Idx, | |||
658 | Record.begin() + Idx + Length); | |||
659 | Idx += Length; | |||
660 | ||||
661 | // Find the imported module file. | |||
662 | auto DependsOnFile | |||
663 | = FileMgr.getFile(ImportedFile, /*OpenFile=*/false, | |||
664 | /*CacheFailure=*/false); | |||
665 | ||||
666 | if (!DependsOnFile) | |||
667 | return llvm::createStringError(std::errc::bad_file_descriptor, | |||
668 | "imported file \"%s\" not found", | |||
669 | ImportedFile.c_str()); | |||
670 | ||||
671 | // Save the information in ImportedModuleFileInfo so we can verify after | |||
672 | // loading all pcms. | |||
673 | ImportedModuleFiles.insert(std::make_pair( | |||
674 | *DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime, | |||
675 | StoredSignature))); | |||
676 | ||||
677 | // Record the dependency. | |||
678 | unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID; | |||
679 | getModuleFileInfo(File).Dependencies.push_back(DependsOnID); | |||
680 | } | |||
681 | ||||
682 | continue; | |||
683 | } | |||
684 | ||||
685 | // Handle the identifier table | |||
686 | if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { | |||
687 | typedef llvm::OnDiskIterableChainedHashTable< | |||
688 | InterestingASTIdentifierLookupTrait> InterestingIdentifierTable; | |||
689 | std::unique_ptr<InterestingIdentifierTable> Table( | |||
690 | InterestingIdentifierTable::Create( | |||
691 | (const unsigned char *)Blob.data() + Record[0], | |||
692 | (const unsigned char *)Blob.data() + sizeof(uint32_t), | |||
693 | (const unsigned char *)Blob.data())); | |||
694 | for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), | |||
695 | DEnd = Table->data_end(); | |||
696 | D != DEnd; ++D) { | |||
697 | std::pair<StringRef, bool> Ident = *D; | |||
698 | if (Ident.second) | |||
699 | InterestingIdentifiers[Ident.first].push_back(ID); | |||
700 | else | |||
701 | (void)InterestingIdentifiers[Ident.first]; | |||
702 | } | |||
703 | } | |||
704 | ||||
705 | // Get Signature. | |||
706 | if (State == DiagnosticOptionsBlock && Code == SIGNATURE) | |||
707 | getModuleFileInfo(File).Signature = ASTFileSignature::create( | |||
708 | Record.begin(), Record.begin() + ASTFileSignature::size); | |||
709 | ||||
710 | // We don't care about this record. | |||
711 | } | |||
712 | ||||
713 | return llvm::Error::success(); | |||
714 | } | |||
715 | ||||
716 | namespace { | |||
717 | ||||
718 | /// Trait used to generate the identifier index as an on-disk hash | |||
719 | /// table. | |||
720 | class IdentifierIndexWriterTrait { | |||
721 | public: | |||
722 | typedef StringRef key_type; | |||
723 | typedef StringRef key_type_ref; | |||
724 | typedef SmallVector<unsigned, 2> data_type; | |||
725 | typedef const SmallVector<unsigned, 2> &data_type_ref; | |||
726 | typedef unsigned hash_value_type; | |||
727 | typedef unsigned offset_type; | |||
728 | ||||
729 | static hash_value_type ComputeHash(key_type_ref Key) { | |||
730 | return llvm::djbHash(Key); | |||
731 | } | |||
732 | ||||
733 | std::pair<unsigned,unsigned> | |||
734 | EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { | |||
735 | using namespace llvm::support; | |||
736 | endian::Writer LE(Out, little); | |||
737 | unsigned KeyLen = Key.size(); | |||
738 | unsigned DataLen = Data.size() * 4; | |||
739 | LE.write<uint16_t>(KeyLen); | |||
740 | LE.write<uint16_t>(DataLen); | |||
741 | return std::make_pair(KeyLen, DataLen); | |||
742 | } | |||
743 | ||||
744 | void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { | |||
745 | Out.write(Key.data(), KeyLen); | |||
746 | } | |||
747 | ||||
748 | void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, | |||
749 | unsigned DataLen) { | |||
750 | using namespace llvm::support; | |||
751 | for (unsigned I = 0, N = Data.size(); I != N; ++I) | |||
752 | endian::write<uint32_t>(Out, Data[I], little); | |||
753 | } | |||
754 | }; | |||
755 | ||||
756 | } | |||
757 | ||||
758 | bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { | |||
759 | for (auto MapEntry : ImportedModuleFiles) { | |||
760 | auto *File = MapEntry.first; | |||
761 | ImportedModuleFileInfo &Info = MapEntry.second; | |||
762 | if (getModuleFileInfo(File).Signature) { | |||
763 | if (getModuleFileInfo(File).Signature != Info.StoredSignature) | |||
764 | // Verify Signature. | |||
765 | return true; | |||
766 | } else if (Info.StoredSize != File->getSize() || | |||
767 | Info.StoredModTime != File->getModificationTime()) | |||
768 | // Verify Size and ModTime. | |||
769 | return true; | |||
770 | } | |||
771 | ||||
772 | using namespace llvm; | |||
773 | llvm::TimeTraceScope TimeScope("Module WriteIndex"); | |||
774 | ||||
775 | // Emit the file header. | |||
776 | Stream.Emit((unsigned)'B', 8); | |||
777 | Stream.Emit((unsigned)'C', 8); | |||
778 | Stream.Emit((unsigned)'G', 8); | |||
779 | Stream.Emit((unsigned)'I', 8); | |||
780 | ||||
781 | // Write the block-info block, which describes the records in this bitcode | |||
782 | // file. | |||
783 | emitBlockInfoBlock(Stream); | |||
784 | ||||
785 | Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); | |||
786 | ||||
787 | // Write the metadata. | |||
788 | SmallVector<uint64_t, 2> Record; | |||
789 | Record.push_back(CurrentVersion); | |||
790 | Stream.EmitRecord(INDEX_METADATA, Record); | |||
791 | ||||
792 | // Write the set of known module files. | |||
793 | for (ModuleFilesMap::iterator M = ModuleFiles.begin(), | |||
794 | MEnd = ModuleFiles.end(); | |||
795 | M != MEnd; ++M) { | |||
796 | Record.clear(); | |||
797 | Record.push_back(M->second.ID); | |||
798 | Record.push_back(M->first->getSize()); | |||
799 | Record.push_back(M->first->getModificationTime()); | |||
800 | ||||
801 | // File name | |||
802 | StringRef Name(M->first->getName()); | |||
803 | Record.push_back(Name.size()); | |||
804 | Record.append(Name.begin(), Name.end()); | |||
805 | ||||
806 | // Dependencies | |||
807 | Record.push_back(M->second.Dependencies.size()); | |||
808 | Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); | |||
809 | Stream.EmitRecord(MODULE, Record); | |||
810 | } | |||
811 | ||||
812 | // Write the identifier -> module file mapping. | |||
813 | { | |||
814 | llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; | |||
815 | IdentifierIndexWriterTrait Trait; | |||
816 | ||||
817 | // Populate the hash table. | |||
818 | for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), | |||
819 | IEnd = InterestingIdentifiers.end(); | |||
820 | I != IEnd; ++I) { | |||
821 | Generator.insert(I->first(), I->second, Trait); | |||
822 | } | |||
823 | ||||
824 | // Create the on-disk hash table in a buffer. | |||
825 | SmallString<4096> IdentifierTable; | |||
826 | uint32_t BucketOffset; | |||
827 | { | |||
828 | using namespace llvm::support; | |||
829 | llvm::raw_svector_ostream Out(IdentifierTable); | |||
830 | // Make sure that no bucket is at offset 0 | |||
831 | endian::write<uint32_t>(Out, 0, little); | |||
832 | BucketOffset = Generator.Emit(Out, Trait); | |||
833 | } | |||
834 | ||||
835 | // Create a blob abbreviation | |||
836 | auto Abbrev = std::make_shared<BitCodeAbbrev>(); | |||
837 | Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); | |||
838 | Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); | |||
839 | Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | |||
840 | unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); | |||
841 | ||||
842 | // Write the identifier table | |||
843 | uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset}; | |||
844 | Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); | |||
845 | } | |||
846 | ||||
847 | Stream.ExitBlock(); | |||
848 | return false; | |||
849 | } | |||
850 | ||||
851 | llvm::Error | |||
852 | GlobalModuleIndex::writeIndex(FileManager &FileMgr, | |||
853 | const PCHContainerReader &PCHContainerRdr, | |||
854 | StringRef Path) { | |||
855 | llvm::SmallString<128> IndexPath; | |||
856 | IndexPath += Path; | |||
857 | llvm::sys::path::append(IndexPath, IndexFileName); | |||
858 | ||||
859 | // Coordinate building the global index file with other processes that might | |||
860 | // try to do the same. | |||
861 | llvm::LockFileManager Locked(IndexPath); | |||
862 | switch (Locked) { | |||
| ||||
863 | case llvm::LockFileManager::LFS_Error: | |||
864 | return llvm::createStringError(std::errc::io_error, "LFS error"); | |||
865 | ||||
866 | case llvm::LockFileManager::LFS_Owned: | |||
867 | // We're responsible for building the index ourselves. Do so below. | |||
868 | break; | |||
869 | ||||
870 | case llvm::LockFileManager::LFS_Shared: | |||
871 | // Someone else is responsible for building the index. We don't care | |||
872 | // when they finish, so we're done. | |||
873 | return llvm::createStringError(std::errc::device_or_resource_busy, | |||
874 | "someone else is building the index"); | |||
875 | } | |||
876 | ||||
877 | // The module index builder. | |||
878 | GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr); | |||
879 | ||||
880 | // Load each of the module files. | |||
881 | std::error_code EC; | |||
882 | for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; | |||
883 | D != DEnd && !EC; | |||
884 | D.increment(EC)) { | |||
885 | // If this isn't a module file, we don't care. | |||
886 | if (llvm::sys::path::extension(D->path()) != ".pcm") { | |||
887 | // ... unless it's a .pcm.lock file, which indicates that someone is | |||
888 | // in the process of rebuilding a module. They'll rebuild the index | |||
889 | // at the end of that translation unit, so we don't have to. | |||
890 | if (llvm::sys::path::extension(D->path()) == ".pcm.lock") | |||
891 | return llvm::createStringError(std::errc::device_or_resource_busy, | |||
892 | "someone else is building the index"); | |||
893 | ||||
894 | continue; | |||
895 | } | |||
896 | ||||
897 | // If we can't find the module file, skip it. | |||
898 | auto ModuleFile = FileMgr.getFile(D->path()); | |||
899 | if (!ModuleFile) | |||
900 | continue; | |||
901 | ||||
902 | // Load this module file. | |||
903 | if (llvm::Error Err = Builder.loadModuleFile(*ModuleFile)) | |||
904 | return Err; | |||
905 | } | |||
906 | ||||
907 | // The output buffer, into which the global index will be written. | |||
908 | SmallString<16> OutputBuffer; | |||
909 | { | |||
910 | llvm::BitstreamWriter OutputStream(OutputBuffer); | |||
911 | if (Builder.writeIndex(OutputStream)) | |||
912 | return llvm::createStringError(std::errc::io_error, | |||
913 | "failed writing index"); | |||
914 | } | |||
915 | ||||
916 | return llvm::writeFileAtomically((IndexPath + "-%%%%%%%%").str(), IndexPath, | |||
917 | OutputBuffer); | |||
918 | } | |||
919 | ||||
920 | namespace { | |||
921 | class GlobalIndexIdentifierIterator : public IdentifierIterator { | |||
922 | /// The current position within the identifier lookup table. | |||
923 | IdentifierIndexTable::key_iterator Current; | |||
924 | ||||
925 | /// The end position within the identifier lookup table. | |||
926 | IdentifierIndexTable::key_iterator End; | |||
927 | ||||
928 | public: | |||
929 | explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) { | |||
930 | Current = Idx.key_begin(); | |||
931 | End = Idx.key_end(); | |||
932 | } | |||
933 | ||||
934 | StringRef Next() override { | |||
935 | if (Current == End) | |||
936 | return StringRef(); | |||
937 | ||||
938 | StringRef Result = *Current; | |||
939 | ++Current; | |||
940 | return Result; | |||
941 | } | |||
942 | }; | |||
943 | } | |||
944 | ||||
945 | IdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const { | |||
946 | IdentifierIndexTable &Table = | |||
947 | *static_cast<IdentifierIndexTable *>(IdentifierIndex); | |||
948 | return new GlobalIndexIdentifierIterator(Table); | |||
949 | } |
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")(static_cast <bool> (canSkipToPos(ByteNo) && "Invalid location" ) ? void (0) : __assert_fail ("canSkipToPos(ByteNo) && \"Invalid location\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/Bitstream/BitstreamReader.h" , 134, __extension__ __PRETTY_FUNCTION__)); | ||||
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")(static_cast <bool> (!(BitNo % 8) && "Expected bit on byte boundary" ) ? void (0) : __assert_fail ("!(BitNo % 8) && \"Expected bit on byte boundary\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/Bitstream/BitstreamReader.h" , 160, __extension__ __PRETTY_FUNCTION__)); | ||||
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 &&(static_cast <bool> (NumBits && NumBits <= BitsInWord && "Cannot return zero or more than BitsInWord bits!" ) ? void (0) : __assert_fail ("NumBits && NumBits <= BitsInWord && \"Cannot return zero or more than BitsInWord bits!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/Bitstream/BitstreamReader.h" , 194, __extension__ __PRETTY_FUNCTION__)) | ||||
194 | "Cannot return zero or more than BitsInWord bits!")(static_cast <bool> (NumBits && NumBits <= BitsInWord && "Cannot return zero or more than BitsInWord bits!" ) ? void (0) : __assert_fail ("NumBits && NumBits <= BitsInWord && \"Cannot return zero or more than BitsInWord bits!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/Bitstream/BitstreamReader.h" , 194, __extension__ __PRETTY_FUNCTION__)); | ||||
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
| ||||
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"l" "u", 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 |