;
35using namespaceserialization;
43GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID
47 enumIndexRecordTypes {
72classIdentifierIndexReaderTrait {
74 typedefStringRef external_key_type;
75 typedefStringRef internal_key_type;
77 typedef unsignedhash_value_type;
78 typedef unsignedoffset_type;
80 static boolEqualKey(
constinternal_key_type& a,
constinternal_key_type&
b) {
84 statichash_value_type
ComputeHash(
constinternal_key_type& a) {
85 returnllvm::djbHash(a);
88 staticstd::pair<unsigned, unsigned>
89ReadKeyDataLength(
const unsigned char*& d) {
90 using namespacellvm::support;
91 unsignedKeyLen = endian::readNext<uint16_t, llvm::endianness::little>(d);
92 unsignedDataLen = endian::readNext<uint16_t, llvm::endianness::little>(d);
93 returnstd::make_pair(KeyLen, DataLen);
96 static constinternal_key_type&
97GetInternalKey(
constexternal_key_type& x) {
returnx; }
99 static constexternal_key_type&
100GetExternalKey(
constinternal_key_type& x) {
returnx; }
102 staticinternal_key_type ReadKey(
const unsigned char* d,
unsignedn) {
103 returnStringRef((
const char*)d, n);
106 staticdata_type ReadData(
constinternal_key_type& k,
107 const unsigned char* d,
109 using namespacellvm::support;
112 while(DataLen > 0) {
113 unsignedID = endian::readNext<uint32_t, llvm::endianness::little>(d);
114Result.push_back(ID);
122typedefllvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait>
123IdentifierIndexTable;
127GlobalModuleIndex::GlobalModuleIndex(
128std::unique_ptr<llvm::MemoryBuffer> IndexBuffer,
129llvm::BitstreamCursor Cursor)
130: Buffer(
std::move(IndexBuffer)), IdentifierIndex(), NumIdentifierLookups(),
131NumIdentifierLookupHits() {
132 autoFail = [&](llvm::Error &&Err) {
133report_fatal_error(
"Module index '"+ Buffer->getBufferIdentifier() +
134 "' failed: "+
toString(std::move(Err)));
137llvm::TimeTraceScope TimeScope(
"Module LoadIndex");
139 boolInGlobalIndexBlock =
false;
142llvm::BitstreamEntry Entry;
146Fail(Res.takeError());
148 switch(Entry.Kind) {
149 casellvm::BitstreamEntry::Error:
152 casellvm::BitstreamEntry::EndBlock:
153 if(InGlobalIndexBlock) {
154InGlobalIndexBlock =
false;
161 casellvm::BitstreamEntry::Record:
163 if(InGlobalIndexBlock)
168 casellvm::BitstreamEntry::SubBlock:
169 if(!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) {
170 if(llvm::Error Err =
Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
171Fail(std::move(Err));
172InGlobalIndexBlock =
true;
173}
else if(llvm::Error Err =
Cursor.SkipBlock())
174Fail(std::move(Err));
182 if(!MaybeIndexRecord)
183Fail(MaybeIndexRecord.takeError());
184IndexRecordTypes IndexRecord =
185 static_cast<IndexRecordTypes
>(MaybeIndexRecord.get());
186 switch(IndexRecord) {
198 if(ID == Modules.size())
199Modules.push_back(ModuleInfo());
201Modules.resize(ID + 1);
205Modules[
ID].Size =
Record[Idx++];
206Modules[
ID].ModTime =
Record[Idx++];
210Modules[
ID].FileName.assign(
Record.begin() + Idx,
215 unsignedNumDeps =
Record[Idx++];
216Modules[
ID].Dependencies.insert(Modules[ID].Dependencies.end(),
218 Record.begin() + Idx + NumDeps);
222assert(Idx ==
Record.size() &&
"More module info?");
227StringRef ModuleName = llvm::sys::path::stem(Modules[ID].
FileName);
229ModuleName = ModuleName.rsplit(
'-').first;
230UnresolvedModules[ModuleName] =
ID;
234 caseIDENTIFIER_INDEX:
237IdentifierIndex = IdentifierIndexTable::Create(
238(
const unsigned char*)Blob.data() +
Record[0],
239(
const unsigned char*)Blob.data() +
sizeof(uint32_t),
240(
const unsigned char*)Blob.data(), IdentifierIndexReaderTrait());
248 delete static_cast<IdentifierIndexTable *
>(IdentifierIndex);
251std::pair<GlobalModuleIndex *, llvm::Error>
258llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr =
259llvm::MemoryBuffer::getFile(IndexPath.c_str());
261 returnstd::make_pair(
nullptr,
262llvm::errorCodeToError(BufferOrErr.getError()));
263std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
266llvm::BitstreamCursor Cursor(*Buffer);
269 for(
unsigned char C: {
'B',
'C',
'G',
'I'}) {
272 returnstd::make_pair(
273 nullptr, llvm::createStringError(std::errc::illegal_byte_sequence,
274 "expected signature BCGI"));
276 returnstd::make_pair(
nullptr, Res.takeError());
279 returnstd::make_pair(
new GlobalModuleIndex(std::move(Buffer), std::move(Cursor)),
280llvm::Error::success());
287llvm::DenseMap<ModuleFile *, unsigned>::iterator Known
288= ModulesByFile.find(
File);
289 if(Known == ModulesByFile.end())
293Dependencies.clear();
295 for(
unsignedI = 0, N = StoredDependencies.size(); I != N; ++I) {
297Dependencies.push_back(MF);
305 if(!IdentifierIndex)
309++NumIdentifierLookups;
310IdentifierIndexTable &Table
311= *
static_cast<IdentifierIndexTable *
>(IdentifierIndex);
312IdentifierIndexTable::iterator Known = Table.find(Name);
313 if(Known == Table.end()) {
318 for(
unsignedI = 0, N = ModuleIDs.size(); I != N; ++I) {
323++NumIdentifierLookupHits;
329StringRef Name =
File->ModuleName;
330llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name);
331 if(Known == UnresolvedModules.end()) {
336ModuleInfo &Info = Modules[Known->second];
341 if(
File->File.getSize() == Info.Size &&
342 File->File.getModificationTime() == Info.ModTime) {
344ModulesByFile[
File] = Known->second;
350UnresolvedModules.erase(Known);
355std::fprintf(stderr,
"*** Global Module Index Statistics:\n");
356 if(NumIdentifierLookups) {
357fprintf(stderr,
" %u / %u identifier lookups succeeded (%f%%)\n",
358NumIdentifierLookupHits, NumIdentifierLookups,
359(
double)NumIdentifierLookupHits*100.0/NumIdentifierLookups);
361std::fprintf(stderr,
"\n");
365llvm::errs() <<
"*** Global Module Index Dump:\n";
366llvm::errs() <<
"Module files:\n";
367 for(
auto&MI : Modules) {
368llvm::errs() <<
"** "<< MI.FileName <<
"\n";
372llvm::errs() <<
"\n";
374llvm::errs() <<
"\n";
383 structModuleFileInfo {
393 structImportedModuleFileInfo {
395time_t StoredModTime;
398: StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {}
402 classGlobalModuleIndexBuilder {
407 usingModuleFilesMap = llvm::MapVector<FileEntryRef, ModuleFileInfo>;
410ModuleFilesMap ModuleFiles;
414 usingImportedModuleFilesMap =
415std::multimap<FileEntryRef, ImportedModuleFileInfo>;
418ImportedModuleFilesMap ImportedModuleFiles;
422 typedefllvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap;
426InterestingIdentifierMap InterestingIdentifiers;
429 voidemitBlockInfoBlock(llvm::BitstreamWriter &Stream);
433 auto[It, Inserted] = ModuleFiles.try_emplace(
File);
435 unsignedNewID = ModuleFiles.size();
443 explicitGlobalModuleIndexBuilder(
445: FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
452 boolwriteIndex(llvm::BitstreamWriter &Stream);
457llvm::BitstreamWriter &Stream,
461Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
Record);
464 if(!Name || Name[0] == 0)
return;
467 Record.push_back(*Name++);
468Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
Record);
472llvm::BitstreamWriter &Stream,
477 Record.push_back(*Name++);
478Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME,
Record);
482GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) {
484Stream.EnterBlockInfoBlock();
486#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 487#define RECORD(X) emitRecordID(X, #X, Stream, Record) 488 BLOCK(GLOBAL_INDEX_BLOCK);
491 RECORD(IDENTIFIER_INDEX);
499 classInterestingASTIdentifierLookupTrait
504 typedefstd::pair<StringRef, bool> data_type;
506data_type ReadData(
constinternal_key_type& k,
507 const unsigned char* d,
511 using namespacellvm::support;
513endian::readNext<IdentifierID, llvm::endianness::little>(d);
514 boolIsInteresting = RawID & 0x01;
515 returnstd::make_pair(k, IsInteresting);
525 returnllvm::createStringError(Buffer.getError(),
526 "failed getting buffer for module file");
529llvm::BitstreamCursor InStream(PCHContainerRdr.
ExtractPCH(**Buffer));
532 for(
unsigned char C: {
'C',
'P',
'C',
'H'})
535 returnllvm::createStringError(std::errc::illegal_byte_sequence,
536 "expected signature CPCH");
538 returnRes.takeError();
542 unsigned ID= getModuleFileInfo(
File).ID;
545 enum{
Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State =
Other;
550 returnMaybeEntry.takeError();
551llvm::BitstreamEntry Entry = MaybeEntry.get();
553 switch(Entry.Kind) {
554 casellvm::BitstreamEntry::Error:
558 casellvm::BitstreamEntry::Record:
560 if(State ==
Other) {
564 returnSkipped.takeError();
570 casellvm::BitstreamEntry::SubBlock:
576State = ControlBlock;
581 if(llvm::Error Err = InStream.EnterSubBlock(
AST_BLOCK_ID))
594State = DiagnosticOptionsBlock;
598 if(llvm::Error Err = InStream.SkipBlock())
603 casellvm::BitstreamEntry::EndBlock:
613 returnMaybeCode.takeError();
614 unsignedCode = MaybeCode.get();
617 if(State == ControlBlock && Code ==
IMPORT) {
629Blob = Blob.substr(
Record[Idx++]);
635off_t StoredSize = (off_t)
Record[Idx++];
636time_t StoredModTime = (time_t)
Record[Idx++];
642SignatureBytes.end());
646 unsignedLength =
Record[Idx++];
647StringRef ImportedFile = Blob.substr(0, Length);
648Blob = Blob.substr(Length);
656 returnllvm::createStringError(std::errc::bad_file_descriptor,
657 "imported file \"%s\" not found",
658std::string(ImportedFile).c_str());
662ImportedModuleFiles.insert(std::make_pair(
663*DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime,
667 unsignedDependsOnID = getModuleFileInfo(*DependsOnFile).ID;
668getModuleFileInfo(
File).Dependencies.push_back(DependsOnID);
675 typedefllvm::OnDiskIterableChainedHashTable<
676InterestingASTIdentifierLookupTrait> InterestingIdentifierTable;
677std::unique_ptr<InterestingIdentifierTable> Table(
678InterestingIdentifierTable::Create(
679(
const unsigned char*)Blob.data() +
Record[0],
680(
const unsigned char*)Blob.data() +
sizeof(uint32_t),
681(
const unsigned char*)Blob.data()));
682 for(InterestingIdentifierTable::data_iterator
D= Table->data_begin(),
683DEnd = Table->data_end();
685std::pair<StringRef, bool> Ident = *
D;
687InterestingIdentifiers[Ident.first].push_back(ID);
689(
void)InterestingIdentifiers[Ident.first];
694 if(State == DiagnosticOptionsBlock && Code ==
SIGNATURE) {
697 "Dummy AST file signature not backpatched in ASTWriter.");
698getModuleFileInfo(
File).Signature = Signature;
704 returnllvm::Error::success();
711classIdentifierIndexWriterTrait {
713 typedefStringRef key_type;
714 typedefStringRef key_type_ref;
717 typedef unsignedhash_value_type;
718 typedef unsignedoffset_type;
720 statichash_value_type
ComputeHash(key_type_ref Key) {
721 returnllvm::djbHash(Key);
724std::pair<unsigned,unsigned>
725EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref
Data) {
726 using namespacellvm::support;
727endian::Writer
LE(Out, llvm::endianness::little);
728 unsignedKeyLen = Key.size();
729 unsignedDataLen =
Data.size() * 4;
730 LE.write<uint16_t>(KeyLen);
731 LE.write<uint16_t>(DataLen);
732 returnstd::make_pair(KeyLen, DataLen);
735 voidEmitKey(raw_ostream& Out, key_type_ref Key,
unsignedKeyLen) {
736Out.write(Key.data(), KeyLen);
739 voidEmitData(raw_ostream& Out, key_type_ref Key, data_type_ref
Data,
741 using namespacellvm::support;
742 for(
unsignedI = 0, N =
Data.size(); I != N; ++I)
743endian::write<uint32_t>(Out,
Data[I], llvm::endianness::little);
749boolGlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
750 for(
autoMapEntry : ImportedModuleFiles) {
751 auto File= MapEntry.first;
752ImportedModuleFileInfo &Info = MapEntry.second;
753 if(getModuleFileInfo(
File).Signature) {
754 if(getModuleFileInfo(
File).Signature != Info.StoredSignature)
757}
else if(Info.StoredSize !=
File.getSize() ||
758Info.StoredModTime !=
File.getModificationTime())
763 using namespace llvm;
764llvm::TimeTraceScope TimeScope(
"Module WriteIndex");
767Stream.Emit((
unsigned)
'B', 8);
768Stream.Emit((
unsigned)
'C', 8);
769Stream.Emit((
unsigned)
'G', 8);
770Stream.Emit((
unsigned)
'I', 8);
774emitBlockInfoBlock(Stream);
776Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3);
781Stream.EmitRecord(INDEX_METADATA,
Record);
784 for(ModuleFilesMap::iterator M = ModuleFiles.begin(),
785MEnd = ModuleFiles.end();
788 Record.push_back(M->second.ID);
789 Record.push_back(M->first.getSize());
790 Record.push_back(M->first.getModificationTime());
793StringRef Name(M->first.getName());
794 Record.push_back(Name.size());
795 Record.append(Name.begin(), Name.end());
798 Record.push_back(M->second.Dependencies.size());
799 Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end());
800Stream.EmitRecord(MODULE,
Record);
805llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait>
Generator;
806IdentifierIndexWriterTrait Trait;
809 for(InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(),
810IEnd = InterestingIdentifiers.end();
812 Generator.insert(I->first(), I->second, Trait);
819 using namespacellvm::support;
822endian::write<uint32_t>(Out, 0, llvm::endianness::little);
823BucketOffset =
Generator.Emit(Out, Trait);
827 autoAbbrev = std::make_shared<BitCodeAbbrev>();
828Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX));
829Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
830Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
831 unsignedIDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
852llvm::LockFileManager Locked(IndexPath);
854 casellvm::LockFileManager::LFS_Error:
855 returnllvm::createStringError(std::errc::io_error,
"LFS error");
857 casellvm::LockFileManager::LFS_Owned:
861 casellvm::LockFileManager::LFS_Shared:
864 returnllvm::createStringError(std::errc::device_or_resource_busy,
865 "someone else is building the index");
869GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr);
873 for(llvm::sys::fs::directory_iterator
D(
Path, EC), DEnd;
877 if(llvm::sys::path::extension(
D->path()) !=
".pcm") {
881 if(llvm::sys::path::extension(
D->path()) ==
".pcm.lock")
882 returnllvm::createStringError(std::errc::device_or_resource_busy,
883 "someone else is building the index");
894 if(llvm::Error Err = Builder.loadModuleFile(*
ModuleFile))
901llvm::BitstreamWriter OutputStream(OutputBuffer);
902 if(Builder.writeIndex(OutputStream))
903 returnllvm::createStringError(std::errc::io_error,
904 "failed writing index");
907 returnllvm::writeToOutput(IndexPath, [&OutputBuffer](llvm::raw_ostream &OS) {
909 returnllvm::Error::success();
916IdentifierIndexTable::key_iterator Current;
919IdentifierIndexTable::key_iterator End;
922 explicitGlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) {
923Current = Idx.key_begin();
927StringRef Next()
override{
931StringRef Result = *Current;
939IdentifierIndexTable &Table =
940*
static_cast<IdentifierIndexTable *
>(IdentifierIndex);
941 return newGlobalIndexIdentifierIterator(Table);
Defines the clang::FileManager interface and associated types.
static void emitRecordID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl< uint64_t > &Record)
static const unsigned CurrentVersion
The global index file version.
static const char *const IndexFileName
The name of the global index file.
static void emitBlockID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl< uint64_t > &Record)
llvm::MachO::Record Record
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
#define IMPORT(DERIVED, BASE)
#define BLOCK(DERIVED, BASE)
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
A global index for a set of module files, providing information about the identifiers within those mo...
bool loadedModuleFile(ModuleFile *File)
Note that the given module file has been loaded.
void printStats()
Print statistics to standard error.
bool lookupIdentifier(llvm::StringRef Name, HitSet &Hits)
Look for all of the module files with information about the given identifier, e.g....
void getModuleDependencies(ModuleFile *File, llvm::SmallVectorImpl< ModuleFile * > &Dependencies)
Retrieve the set of module files on which the given module file directly depends.
IdentifierIterator * createIdentifierIterator() const
Returns an iterator for identifiers stored in the index table.
static std::pair< GlobalModuleIndex *, llvm::Error > readIndex(llvm::StringRef Path)
Read a global index file for the given directory.
void dump()
Print debugging view to standard error.
static llvm::Error writeIndex(FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, llvm::StringRef Path)
Write a global index into the given.
An iterator that walks over all of the known identifiers in the lookup table.
Implements an efficient mapping from strings to IdentifierInfo nodes.
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const =0
Returns the serialized AST inside the PCH container Buffer.
Information about a module that has been loaded by the ASTReader.
Base class for the trait describing the on-disk hash table for the identifiers in an AST file.
@ ModuleFileInfo
Dump information about a module file.
bool LE(InterpState &S, CodePtr OpPC)
@ AST_BLOCK_ID
The AST block, which acts as a container around the full AST block.
@ CONTROL_BLOCK_ID
The control block, which contains all of the information that needs to be validated prior to committi...
@ UNHASHED_CONTROL_BLOCK_ID
A block with unhashed content.
@ SIGNATURE
Record code for the signature that identifiers this AST file.
uint64_t IdentifierID
An ID number that refers to an identifier in an AST file.
@ IDENTIFIER_TABLE
Record code for the identifier table.
unsigned ComputeHash(Selector Sel)
std::shared_ptr< MatchComputation< T > > Generator
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
Diagnostic wrappers for TextAPI types for error reporting.
The signature of a module, which is a hash of the AST content.
static constexpr size_t size
static ASTFileSignature create(std::array< uint8_t, 20 > Bytes)
static ASTFileSignature createDummy()
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4