clang: lib/Serialization/GlobalModuleIndex.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/SmallString.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Bitstream/BitstreamReader.h"
24#include "llvm/Bitstream/BitstreamWriter.h"
25#include "llvm/Support/DJB.h"
26#include "llvm/Support/FileSystem.h"
27#include "llvm/Support/LockFileManager.h"
28#include "llvm/Support/MemoryBuffer.h"
29#include "llvm/Support/OnDiskHashTable.h"
30#include "llvm/Support/Path.h"
31#include "llvm/Support/TimeProfiler.h"
32#include "llvm/Support/raw_ostream.h"
33#include
34using namespace clang;
35using namespace serialization;
36
37
38
39
40namespace {
41 enum {
42
43 GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID
44 };
45
46
47 enum IndexRecordTypes {
48
49
50 INDEX_METADATA,
51
52 MODULE,
53
54 IDENTIFIER_INDEX
55 };
56}
57
58
60
61
63
64
65
66
67
68namespace {
69
70
71
72class IdentifierIndexReaderTrait {
73public:
74 typedef StringRef external_key_type;
75 typedef StringRef internal_key_type;
77 typedef unsigned hash_value_type;
78 typedef unsigned offset_type;
79
80 static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
81 return a == b;
82 }
83
84 static hash_value_type ComputeHash(const internal_key_type& a) {
85 return llvm::djbHash(a);
86 }
87
88 static std::pair<unsigned, unsigned>
89 ReadKeyDataLength(const unsigned char*& d) {
90 using namespace llvm::support;
91 unsigned KeyLen = endian::readNext<uint16_t, llvm::endianness::little>(d);
92 unsigned DataLen = endian::readNext<uint16_t, llvm::endianness::little>(d);
93 return std::make_pair(KeyLen, DataLen);
94 }
95
96 static const internal_key_type&
97 GetInternalKey(const external_key_type& x) { return x; }
98
99 static const external_key_type&
100 GetExternalKey(const internal_key_type& x) { return x; }
101
102 static internal_key_type ReadKey(const unsigned char* d, unsigned n) {
103 return StringRef((const char *)d, n);
104 }
105
106 static data_type ReadData(const internal_key_type& k,
107 const unsigned char* d,
108 unsigned DataLen) {
109 using namespace llvm::support;
110
111 data_type Result;
112 while (DataLen > 0) {
113 unsigned ID = endian::readNext<uint32_t, llvm::endianness::little>(d);
114 Result.push_back(ID);
115 DataLen -= 4;
116 }
117
118 return Result;
119 }
120};
121
122typedef llvm::OnDiskIterableChainedHashTable
123 IdentifierIndexTable;
124
125}
126
127GlobalModuleIndex::GlobalModuleIndex(
128 std::unique_ptrllvm::MemoryBuffer IndexBuffer,
129 llvm::BitstreamCursor Cursor)
130 : Buffer(std::move(IndexBuffer)), IdentifierIndex(), NumIdentifierLookups(),
131 NumIdentifierLookupHits() {
132 auto Fail = [&](llvm::Error &&Err) {
133 report_fatal_error("Module index '" + Buffer->getBufferIdentifier() +
134 "' failed: " + toString(std::move(Err)));
135 };
136
137 llvm::TimeTraceScope TimeScope("Module LoadIndex");
138
139 bool InGlobalIndexBlock = false;
140 bool Done = false;
141 while (!Done) {
142 llvm::BitstreamEntry Entry;
144 Entry = Res.get();
145 else
146 Fail(Res.takeError());
147
148 switch (Entry.Kind) {
149 case llvm::BitstreamEntry::Error:
150 return;
151
152 case llvm::BitstreamEntry::EndBlock:
153 if (InGlobalIndexBlock) {
154 InGlobalIndexBlock = false;
155 Done = true;
156 continue;
157 }
158 return;
159
160
161 case llvm::BitstreamEntry::Record:
162
163 if (InGlobalIndexBlock)
164 break;
165
166 return;
167
168 case llvm::BitstreamEntry::SubBlock:
169 if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) {
170 if (llvm::Error Err = Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
171 Fail(std::move(Err));
172 InGlobalIndexBlock = true;
173 } else if (llvm::Error Err = Cursor.SkipBlock())
174 Fail(std::move(Err));
175 continue;
176 }
177
179 StringRef Blob;
182 if (!MaybeIndexRecord)
183 Fail(MaybeIndexRecord.takeError());
184 IndexRecordTypes IndexRecord =
185 static_cast<IndexRecordTypes>(MaybeIndexRecord.get());
186 switch (IndexRecord) {
187 case INDEX_METADATA:
188
190 return;
191 break;
192
193 case MODULE: {
194 unsigned Idx = 0;
196
197
198 if (ID == Modules.size())
199 Modules.push_back(ModuleInfo());
200 else
201 Modules.resize(ID + 1);
202
203
204
205 Modules[ID].Size = Record[Idx++];
206 Modules[ID].ModTime = Record[Idx++];
207
208
210 Modules[ID].FileName.assign(Record.begin() + Idx,
213
214
215 unsigned NumDeps = Record[Idx++];
216 Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(),
217 Record.begin() + Idx,
218 Record.begin() + Idx + NumDeps);
219 Idx += NumDeps;
220
221
222 assert(Idx == Record.size() && "More module info?");
223
224
225
226
227 StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName);
228
229 ModuleName = ModuleName.rsplit('-').first;
230 UnresolvedModules[ModuleName] = ID;
231 break;
232 }
233
234 case IDENTIFIER_INDEX:
235
237 IdentifierIndex = 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());
241 }
242 break;
243 }
244 }
245}
246
248 delete static_cast<IdentifierIndexTable *>(IdentifierIndex);
249}
250
251std::pair<GlobalModuleIndex *, llvm::Error>
253
255 IndexPath += Path;
256 llvm::sys::path::append(IndexPath, IndexFileName);
257
258 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer> BufferOrErr =
259 llvm::MemoryBuffer::getFile(IndexPath.c_str());
260 if (!BufferOrErr)
261 return std::make_pair(nullptr,
262 llvm::errorCodeToError(BufferOrErr.getError()));
263 std::unique_ptrllvm::MemoryBuffer Buffer = std::move(BufferOrErr.get());
264
265
266 llvm::BitstreamCursor Cursor(*Buffer);
267
268
269 for (unsigned char C : {'B', 'C', 'G', 'I'}) {
271 if (Res.get() != C)
272 return std::make_pair(
273 nullptr, llvm::createStringError(std::errc::illegal_byte_sequence,
274 "expected signature BCGI"));
275 } else
276 return std::make_pair(nullptr, Res.takeError());
277 }
278
279 return std::make_pair(new GlobalModuleIndex(std::move(Buffer), std::move(Cursor)),
280 llvm::Error::success());
281}
282
286
287 llvm::DenseMap<ModuleFile *, unsigned>::iterator Known
288 = ModulesByFile.find(File);
289 if (Known == ModulesByFile.end())
290 return;
291
292
293 Dependencies.clear();
294 ArrayRef StoredDependencies = Modules[Known->second].Dependencies;
295 for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) {
297 Dependencies.push_back(MF);
298 }
299}
300
302 Hits.clear();
303
304
305 if (!IdentifierIndex)
306 return false;
307
308
309 ++NumIdentifierLookups;
310 IdentifierIndexTable &Table
311 = *static_cast<IdentifierIndexTable *>(IdentifierIndex);
312 IdentifierIndexTable::iterator Known = Table.find(Name);
313 if (Known == Table.end()) {
314 return false;
315 }
316
318 for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) {
320 Hits.insert(MF);
321 }
322
323 ++NumIdentifierLookupHits;
324 return true;
325}
326
328
329 StringRef Name = File->ModuleName;
330 llvm::StringMap::iterator Known = UnresolvedModules.find(Name);
331 if (Known == UnresolvedModules.end()) {
332 return true;
333 }
334
335
336 ModuleInfo &Info = Modules[Known->second];
337
338
339
340 bool Failed = true;
341 if (File->File.getSize() == Info.Size &&
342 File->File.getModificationTime() == Info.ModTime) {
343 Info.File = File;
344 ModulesByFile[File] = Known->second;
345
346 Failed = false;
347 }
348
349
350 UnresolvedModules.erase(Known);
351 return Failed;
352}
353
355 std::fprintf(stderr, "*** Global Module Index Statistics:\n");
356 if (NumIdentifierLookups) {
357 fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n",
358 NumIdentifierLookupHits, NumIdentifierLookups,
359 (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups);
360 }
361 std::fprintf(stderr, "\n");
362}
363
365 llvm::errs() << "*** Global Module Index Dump:\n";
366 llvm::errs() << "Module files:\n";
367 for (auto &MI : Modules) {
368 llvm::errs() << "** " << MI.FileName << "\n";
369 if (MI.File)
370 MI.File->dump();
371 else
372 llvm::errs() << "\n";
373 }
374 llvm::errs() << "\n";
375}
376
377
378
379
380
381namespace {
382
383 struct ModuleFileInfo {
384
385 unsigned ID;
386
387
388
391 };
392
393 struct ImportedModuleFileInfo {
394 off_t StoredSize;
395 time_t StoredModTime;
397 ImportedModuleFileInfo(off_t Size, time_t ModTime, ASTFileSignature Sig)
398 : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {}
399 };
400
401
402 class GlobalModuleIndexBuilder {
405
406
407 using ModuleFilesMap = llvm::MapVector<FileEntryRef, ModuleFileInfo>;
408
409
410 ModuleFilesMap ModuleFiles;
411
412
413
414 using ImportedModuleFilesMap =
415 std::multimap<FileEntryRef, ImportedModuleFileInfo>;
416
417
418 ImportedModuleFilesMap ImportedModuleFiles;
419
420
421
422 typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap;
423
424
425
426 InterestingIdentifierMap InterestingIdentifiers;
427
428
429 void emitBlockInfoBlock(llvm::BitstreamWriter &Stream);
430
431
433 auto [It, Inserted] = ModuleFiles.try_emplace(File);
434 if (Inserted) {
435 unsigned NewID = ModuleFiles.size();
437 Info.ID = NewID;
438 }
439 return It->second;
440 }
441
442 public:
443 explicit GlobalModuleIndexBuilder(
445 : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
446
447
449
450
451
452 bool writeIndex(llvm::BitstreamWriter &Stream);
453 };
454}
455
456static void emitBlockID(unsigned ID, const char *Name,
457 llvm::BitstreamWriter &Stream,
460 Record.push_back(ID);
461 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
462
463
464 if (!Name || Name[0] == 0) return;
466 while (*Name)
467 Record.push_back(*Name++);
468 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
469}
470
472 llvm::BitstreamWriter &Stream,
475 Record.push_back(ID);
476 while (*Name)
477 Record.push_back(*Name++);
478 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
479}
480
481void
482GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) {
484 Stream.EnterBlockInfoBlock();
485
486#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record)
487#define RECORD(X) emitRecordID(X, #X, Stream, Record)
488 BLOCK(GLOBAL_INDEX_BLOCK);
489 RECORD(INDEX_METADATA);
491 RECORD(IDENTIFIER_INDEX);
492#undef RECORD
493#undef BLOCK
494
495 Stream.ExitBlock();
496}
497
498namespace {
499 class InterestingASTIdentifierLookupTrait
501
502 public:
503
504 typedef std::pair<StringRef, bool> data_type;
505
506 data_type ReadData(const internal_key_type& k,
507 const unsigned char* d,
508 unsigned DataLen) {
509
510
511 using namespace llvm::support;
513 endian::readNext<IdentifierID, llvm::endianness::little>(d);
514 bool IsInteresting = RawID & 0x01;
515 return std::make_pair(k, IsInteresting);
516 }
517 };
518}
519
520llvm::Error GlobalModuleIndexBuilder::loadModuleFile(FileEntryRef File) {
521
522
524 if (!Buffer)
525 return llvm::createStringError(Buffer.getError(),
526 "failed getting buffer for module file");
527
528
529 llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer));
530
531
532 for (unsigned char C : {'C', 'P', 'C', 'H'})
534 if (Res.get() != C)
535 return llvm::createStringError(std::errc::illegal_byte_sequence,
536 "expected signature CPCH");
537 } else
538 return Res.takeError();
539
540
541
542 unsigned ID = getModuleFileInfo(File).ID;
543
544
545 enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other;
546 bool Done = false;
547 while (!Done) {
549 if (!MaybeEntry)
550 return MaybeEntry.takeError();
551 llvm::BitstreamEntry Entry = MaybeEntry.get();
552
553 switch (Entry.Kind) {
554 case llvm::BitstreamEntry::Error:
555 Done = true;
556 continue;
557
558 case llvm::BitstreamEntry::Record:
559
560 if (State == Other) {
562 continue;
563 else
564 return Skipped.takeError();
565 }
566
567
568 break;
569
570 case llvm::BitstreamEntry::SubBlock:
572 if (llvm::Error Err = InStream.EnterSubBlock(CONTROL_BLOCK_ID))
573 return Err;
574
575
576 State = ControlBlock;
577 continue;
578 }
579
581 if (llvm::Error Err = InStream.EnterSubBlock(AST_BLOCK_ID))
582 return Err;
583
584
585 State = ASTBlock;
586 continue;
587 }
588
591 return Err;
592
593
594 State = DiagnosticOptionsBlock;
595 continue;
596 }
597
598 if (llvm::Error Err = InStream.SkipBlock())
599 return Err;
600
601 continue;
602
603 case llvm::BitstreamEntry::EndBlock:
605 continue;
606 }
607
608
610 StringRef Blob;
612 if (!MaybeCode)
613 return MaybeCode.takeError();
614 unsigned Code = MaybeCode.get();
615
616
617 if (State == ControlBlock && Code == IMPORT) {
618 unsigned Idx = 0;
619
620
621
622 ++Idx;
623
624
625 ++Idx;
626
627
628
629 Blob = Blob.substr(Record[Idx++]);
630
631
632 ++Idx;
633
634
635 off_t StoredSize = (off_t)Record[Idx++];
636 time_t StoredModTime = (time_t)Record[Idx++];
637
638
639
642 SignatureBytes.end());
644
645
646 unsigned Length = Record[Idx++];
647 StringRef ImportedFile = Blob.substr(0, Length);
648 Blob = Blob.substr(Length);
649
650
651 auto DependsOnFile =
653 false);
654
655 if (!DependsOnFile)
656 return llvm::createStringError(std::errc::bad_file_descriptor,
657 "imported file \"%s\" not found",
658 std::string(ImportedFile).c_str());
659
660
661
662 ImportedModuleFiles.insert(std::make_pair(
663 *DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime,
664 StoredSignature)));
665
666
667 unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID;
668 getModuleFileInfo(File).Dependencies.push_back(DependsOnID);
669
670 continue;
671 }
672
673
675 typedef llvm::OnDiskIterableChainedHashTable<
676 InterestingASTIdentifierLookupTrait> InterestingIdentifierTable;
677 std::unique_ptr Table(
678 InterestingIdentifierTable::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(),
683 DEnd = Table->data_end();
685 std::pair<StringRef, bool> Ident = *D;
686 if (Ident.second)
687 InterestingIdentifiers[Ident.first].push_back(ID);
688 else
689 (void)InterestingIdentifiers[Ident.first];
690 }
691 }
692
693
694 if (State == DiagnosticOptionsBlock && Code == SIGNATURE) {
697 "Dummy AST file signature not backpatched in ASTWriter.");
698 getModuleFileInfo(File).Signature = Signature;
699 }
700
701
702 }
703
704 return llvm::Error::success();
705}
706
707namespace {
708
709
710
711class IdentifierIndexWriterTrait {
712public:
713 typedef StringRef key_type;
714 typedef StringRef key_type_ref;
717 typedef unsigned hash_value_type;
718 typedef unsigned offset_type;
719
720 static hash_value_type ComputeHash(key_type_ref Key) {
721 return llvm::djbHash(Key);
722 }
723
724 std::pair<unsigned,unsigned>
725 EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) {
726 using namespace llvm::support;
727 endian::Writer LE(Out, llvm::endianness::little);
728 unsigned KeyLen = Key.size();
729 unsigned DataLen = Data.size() * 4;
730 LE.write<uint16_t>(KeyLen);
731 LE.write<uint16_t>(DataLen);
732 return std::make_pair(KeyLen, DataLen);
733 }
734
735 void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
736 Out.write(Key.data(), KeyLen);
737 }
738
739 void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
740 unsigned DataLen) {
741 using namespace llvm::support;
742 for (unsigned I = 0, N = Data.size(); I != N; ++I)
743 endian::write<uint32_t>(Out, Data[I], llvm::endianness::little);
744 }
745};
746
747}
748
749bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
750 for (auto MapEntry : ImportedModuleFiles) {
751 auto File = MapEntry.first;
752 ImportedModuleFileInfo &Info = MapEntry.second;
753 if (getModuleFileInfo(File).Signature) {
754 if (getModuleFileInfo(File).Signature != Info.StoredSignature)
755
756 return true;
757 } else if (Info.StoredSize != File.getSize() ||
758 Info.StoredModTime != File.getModificationTime())
759
760 return true;
761 }
762
763 using namespace llvm;
764 llvm::TimeTraceScope TimeScope("Module WriteIndex");
765
766
767 Stream.Emit((unsigned)'B', 8);
768 Stream.Emit((unsigned)'C', 8);
769 Stream.Emit((unsigned)'G', 8);
770 Stream.Emit((unsigned)'I', 8);
771
772
773
774 emitBlockInfoBlock(Stream);
775
776 Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3);
777
778
781 Stream.EmitRecord(INDEX_METADATA, Record);
782
783
784 for (ModuleFilesMap::iterator M = ModuleFiles.begin(),
785 MEnd = ModuleFiles.end();
786 M != MEnd; ++M) {
788 Record.push_back(M->second.ID);
789 Record.push_back(M->first.getSize());
790 Record.push_back(M->first.getModificationTime());
791
792
793 StringRef Name(M->first.getName());
794 Record.push_back(Name.size());
795 Record.append(Name.begin(), Name.end());
796
797
798 Record.push_back(M->second.Dependencies.size());
799 Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end());
800 Stream.EmitRecord(MODULE, Record);
801 }
802
803
804 {
805 llvm::OnDiskChainedHashTableGenerator Generator;
806 IdentifierIndexWriterTrait Trait;
807
808
809 for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(),
810 IEnd = InterestingIdentifiers.end();
811 I != IEnd; ++I) {
812 Generator.insert(I->first(), I->second, Trait);
813 }
814
815
818 {
819 using namespace llvm::support;
821
822 endian::write<uint32_t>(Out, 0, llvm::endianness::little);
823 BucketOffset = Generator.Emit(Out, Trait);
824 }
825
826
827 auto Abbrev = std::make_shared();
828 Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX));
829 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
830 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
831 unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
832
833
834 uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset};
836 }
837
838 Stream.ExitBlock();
839 return false;
840}
841
842llvm::Error
845 StringRef Path) {
847 IndexPath += Path;
848 llvm::sys::path::append(IndexPath, IndexFileName);
849
850
851
852 llvm::LockFileManager Locked(IndexPath);
853 switch (Locked) {
854 case llvm::LockFileManager::LFS_Error:
855 return llvm::createStringError(std::errc::io_error, "LFS error");
856
857 case llvm::LockFileManager::LFS_Owned:
858
859 break;
860
861 case llvm::LockFileManager::LFS_Shared:
862
863
864 return llvm::createStringError(std::errc::device_or_resource_busy,
865 "someone else is building the index");
866 }
867
868
869 GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr);
870
871
872 std::error_code EC;
873 for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd;
874 D != DEnd && !EC;
875 D.increment(EC)) {
876
877 if (llvm::sys::path::extension(D->path()) != ".pcm") {
878
879
880
881 if (llvm::sys::path::extension(D->path()) == ".pcm.lock")
882 return llvm::createStringError(std::errc::device_or_resource_busy,
883 "someone else is building the index");
884
885 continue;
886 }
887
888
891 continue;
892
893
894 if (llvm::Error Err = Builder.loadModuleFile(*ModuleFile))
895 return Err;
896 }
897
898
900 {
901 llvm::BitstreamWriter OutputStream(OutputBuffer);
902 if (Builder.writeIndex(OutputStream))
903 return llvm::createStringError(std::errc::io_error,
904 "failed writing index");
905 }
906
907 return llvm::writeToOutput(IndexPath, [&OutputBuffer](llvm::raw_ostream &OS) {
908 OS << OutputBuffer;
909 return llvm::Error::success();
910 });
911}
912
913namespace {
915
916 IdentifierIndexTable::key_iterator Current;
917
918
919 IdentifierIndexTable::key_iterator End;
920
921 public:
922 explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) {
923 Current = Idx.key_begin();
924 End = Idx.key_end();
925 }
926
927 StringRef Next() override {
928 if (Current == End)
929 return StringRef();
930
931 StringRef Result = *Current;
932 ++Current;
933 return Result;
934 }
935 };
936}
937
939 IdentifierIndexTable &Table =
940 *static_cast<IdentifierIndexTable *>(IdentifierIndex);
941 return new GlobalIndexIdentifierIterator(Table);
942}
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()