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/IOSandbox.h"
28#include "llvm/Support/LockFileManager.h"
29#include "llvm/Support/MemoryBuffer.h"
30#include "llvm/Support/OnDiskHashTable.h"
31#include "llvm/Support/Path.h"
32#include "llvm/Support/TimeProfiler.h"
33#include "llvm/Support/raw_ostream.h"
34#include
35using namespace clang;
37
38
39
40
41namespace {
42 enum {
43
44 GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID
45 };
46
47
48 enum IndexRecordTypes {
49
50
51 INDEX_METADATA,
52
53 MODULE,
54
55 IDENTIFIER_INDEX
56 };
57}
58
59
61
62
64
65
66
67
68
69namespace {
70
71
72
73class IdentifierIndexReaderTrait {
74public:
75 typedef StringRef external_key_type;
76 typedef StringRef internal_key_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, llvm::endianness::little>(d);
93 unsigned DataLen = endian::readNext<uint16_t, llvm::endianness::little>(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, llvm::endianness::little>(d);
115 Result.push_back(ID);
116 DataLen -= 4;
117 }
118
119 return Result;
120 }
121};
122
123typedef llvm::OnDiskIterableChainedHashTable
124 IdentifierIndexTable;
125
126}
127
128GlobalModuleIndex::GlobalModuleIndex(
129 std::unique_ptrllvm::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
140 bool InGlobalIndexBlock = false;
141 bool Done = false;
142 while (!Done) {
143 llvm::BitstreamEntry Entry;
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
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
180 StringRef 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
191 return;
192 break;
193
194 case MODULE: {
195 unsigned Idx = 0;
196 unsigned ID = Record[Idx++];
197
198
199 if (ID == Modules.size())
200 Modules.push_back(ModuleInfo());
201 else
202 Modules.resize(ID + 1);
203
204
205
206 Modules[ID].Size = Record[Idx++];
207 Modules[ID].ModTime = Record[Idx++];
208
209
210 unsigned NameLen = Record[Idx++];
211 Modules[ID].FileName.assign(Record.begin() + Idx,
212 Record.begin() + Idx + NameLen);
213 Idx += NameLen;
214
215
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
223 assert(Idx == Record.size() && "More module info?");
224
225
226
227
228 StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName);
229
230 ModuleName = ModuleName.rsplit('-').first;
231 UnresolvedModules[ModuleName] = ID;
232 break;
233 }
234
235 case IDENTIFIER_INDEX:
236
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
249 delete static_cast<IdentifierIndexTable *>(IdentifierIndex);
250}
251
252std::pair<GlobalModuleIndex *, llvm::Error>
254
255 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
256
257
259 IndexPath += Path;
260 llvm::sys::path::append(IndexPath, IndexFileName);
261
262 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer> BufferOrErr =
263 llvm::MemoryBuffer::getFile(IndexPath.c_str());
264 if (!BufferOrErr)
265 return std::make_pair(nullptr,
266 llvm::errorCodeToError(BufferOrErr.getError()));
267 std::unique_ptrllvm::MemoryBuffer Buffer = std::move(BufferOrErr.get());
268
269
270 llvm::BitstreamCursor Cursor(*Buffer);
271
272
273 for (unsigned char C : {'B', 'C', 'G', 'I'}) {
275 if (Res.get() != C)
276 return std::make_pair(
277 nullptr, llvm::createStringError(std::errc::illegal_byte_sequence,
278 "expected signature BCGI"));
279 } else
280 return std::make_pair(nullptr, Res.takeError());
281 }
282
283 return std::make_pair(new GlobalModuleIndex(std::move(Buffer), std::move(Cursor)),
284 llvm::Error::success());
285}
286
288 ModuleFile *File,
290
291 llvm::DenseMap<ModuleFile *, unsigned>::iterator Known
292 = ModulesByFile.find(File);
293 if (Known == ModulesByFile.end())
294 return;
295
296
297 Dependencies.clear();
298 ArrayRef StoredDependencies = Modules[Known->second].Dependencies;
299 for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) {
300 if (ModuleFile *MF = Modules[I].File)
301 Dependencies.push_back(MF);
302 }
303}
304
306 Hits.clear();
307
308
309 if (!IdentifierIndex)
310 return false;
311
312
313 ++NumIdentifierLookups;
314 IdentifierIndexTable &Table
315 = *static_cast<IdentifierIndexTable *>(IdentifierIndex);
316 IdentifierIndexTable::iterator Known = Table.find(Name);
317 if (Known == Table.end()) {
318 return false;
319 }
320
322 for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) {
323 if (ModuleFile *MF = Modules[ModuleIDs[I]].File)
324 Hits.insert(MF);
325 }
326
327 ++NumIdentifierLookupHits;
328 return true;
329}
330
332
333 StringRef Name = File->ModuleName;
334 llvm::StringMap::iterator Known = UnresolvedModules.find(Name);
335 if (Known == UnresolvedModules.end()) {
336 return true;
337 }
338
339
340 ModuleInfo &Info = Modules[Known->second];
341
342
343
344 bool Failed = true;
345 if (File->File.getSize() == Info.Size &&
346 File->File.getModificationTime() == Info.ModTime) {
347 Info.File = File;
348 ModulesByFile[File] = Known->second;
349
350 Failed = false;
351 }
352
353
354 UnresolvedModules.erase(Known);
355 return Failed;
356}
357
359 std::fprintf(stderr, "*** Global Module Index Statistics:\n");
360 if (NumIdentifierLookups) {
361 fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n",
362 NumIdentifierLookupHits, NumIdentifierLookups,
363 (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups);
364 }
365 std::fprintf(stderr, "\n");
366}
367
369 llvm::errs() << "*** Global Module Index Dump:\n";
370 llvm::errs() << "Module files:\n";
371 for (auto &MI : Modules) {
372 llvm::errs() << "** " << MI.FileName << "\n";
373 if (MI.File)
374 MI.File->dump();
375 else
376 llvm::errs() << "\n";
377 }
378 llvm::errs() << "\n";
379}
380
381
382
383
384
385namespace {
386
387 struct ModuleFileInfo {
388
389 unsigned ID;
390
391
392
395 };
396
397 struct ImportedModuleFileInfo {
398 off_t StoredSize;
399 time_t StoredModTime;
401 ImportedModuleFileInfo(off_t Size, time_t ModTime, ASTFileSignature Sig)
402 : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {}
403 };
404
405
406 class GlobalModuleIndexBuilder {
407 FileManager &FileMgr;
408 const PCHContainerReader &PCHContainerRdr;
409
410
411 using ModuleFilesMap = llvm::MapVector<FileEntryRef, ModuleFileInfo>;
412
413
414 ModuleFilesMap ModuleFiles;
415
416
417
418 using ImportedModuleFilesMap =
419 std::multimap<FileEntryRef, ImportedModuleFileInfo>;
420
421
422 ImportedModuleFilesMap ImportedModuleFiles;
423
424
425
426 typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap;
427
428
429
430 InterestingIdentifierMap InterestingIdentifiers;
431
432
433 void emitBlockInfoBlock(llvm::BitstreamWriter &Stream);
434
435
437 auto [It, Inserted] = ModuleFiles.try_emplace(File);
438 if (Inserted) {
439 unsigned NewID = ModuleFiles.size();
441 Info.ID = NewID;
442 }
443 return It->second;
444 }
445
446 public:
447 explicit GlobalModuleIndexBuilder(
448 FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr)
449 : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
450
451
452 llvm::Error loadModuleFile(FileEntryRef File);
453
454
455
456 bool writeIndex(llvm::BitstreamWriter &Stream);
457 };
458}
459
460static void emitBlockID(unsigned ID, const char *Name,
461 llvm::BitstreamWriter &Stream,
464 Record.push_back(ID);
465 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
466
467
468 if (!Name || Name[0] == 0) return;
470 while (*Name)
471 Record.push_back(*Name++);
472 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
473}
474
476 llvm::BitstreamWriter &Stream,
479 Record.push_back(ID);
480 while (*Name)
481 Record.push_back(*Name++);
482 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
483}
484
485void
486GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) {
488 Stream.EnterBlockInfoBlock();
489
490#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record)
491#define RECORD(X) emitRecordID(X, #X, Stream, Record)
492 BLOCK(GLOBAL_INDEX_BLOCK);
493 RECORD(INDEX_METADATA);
495 RECORD(IDENTIFIER_INDEX);
496#undef RECORD
497#undef BLOCK
498
499 Stream.ExitBlock();
500}
501
502namespace {
503 class InterestingASTIdentifierLookupTrait
505
506 public:
507
508 typedef std::pair<StringRef, bool> data_type;
509
510 data_type ReadData(const internal_key_type& k,
511 const unsigned char* d,
512 unsigned DataLen) {
513
514
515 using namespace llvm::support;
517 endian::readNext<IdentifierID, llvm::endianness::little>(d);
518 bool IsInteresting = RawID & 0x01;
519 return std::make_pair(k, IsInteresting);
520 }
521 };
522}
523
524llvm::Error GlobalModuleIndexBuilder::loadModuleFile(FileEntryRef File) {
525
526
527 auto Buffer = FileMgr.getBufferForFile(File, true);
528 if (!Buffer)
529 return llvm::createStringError(Buffer.getError(),
530 "failed getting buffer for module file");
531
532
533 llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer));
534
535
536 for (unsigned char C : {'C', 'P', 'C', 'H'})
538 if (Res.get() != C)
539 return llvm::createStringError(std::errc::illegal_byte_sequence,
540 "expected signature CPCH");
541 } else
542 return Res.takeError();
543
544
545
546 unsigned ID = getModuleFileInfo(File).ID;
547
548
549 enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other;
550 bool Done = false;
551 while (!Done) {
553 if (!MaybeEntry)
554 return MaybeEntry.takeError();
555 llvm::BitstreamEntry Entry = MaybeEntry.get();
556
557 switch (Entry.Kind) {
558 case llvm::BitstreamEntry::Error:
559 Done = true;
560 continue;
561
562 case llvm::BitstreamEntry::Record:
563
564 if (State == Other) {
566 continue;
567 else
568 return Skipped.takeError();
569 }
570
571
572 break;
573
574 case llvm::BitstreamEntry::SubBlock:
576 if (llvm::Error Err = InStream.EnterSubBlock(CONTROL_BLOCK_ID))
577 return Err;
578
579
580 State = ControlBlock;
581 continue;
582 }
583
585 if (llvm::Error Err = InStream.EnterSubBlock(AST_BLOCK_ID))
586 return Err;
587
588
589 State = ASTBlock;
590 continue;
591 }
592
595 return Err;
596
597
598 State = DiagnosticOptionsBlock;
599 continue;
600 }
601
602 if (llvm::Error Err = InStream.SkipBlock())
603 return Err;
604
605 continue;
606
607 case llvm::BitstreamEntry::EndBlock:
609 continue;
610 }
611
612
614 StringRef Blob;
616 if (!MaybeCode)
617 return MaybeCode.takeError();
618 unsigned Code = MaybeCode.get();
619
620
621 if (State == ControlBlock && Code == IMPORT) {
622 unsigned Idx = 0;
623
624
625
626 ++Idx;
627
628
629 ++Idx;
630
631
632
633 Blob = Blob.substr(Record[Idx++]);
634
635
636 ++Idx;
637
638
639 off_t StoredSize = (off_t)Record[Idx++];
640 time_t StoredModTime = (time_t)Record[Idx++];
641
642
643
646 SignatureBytes.end());
648
649
650 unsigned Length = Record[Idx++];
651 StringRef ImportedFile = Blob.substr(0, Length);
652 Blob = Blob.substr(Length);
653
654
655 auto DependsOnFile =
656 FileMgr.getOptionalFileRef(ImportedFile, false,
657 false);
658
659 if (!DependsOnFile)
660 return llvm::createStringError(std::errc::bad_file_descriptor,
661 "imported file \"%s\" not found",
662 std::string(ImportedFile).c_str());
663
664
665
666 ImportedModuleFiles.insert(std::make_pair(
667 *DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime,
668 StoredSignature)));
669
670
671 unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID;
672 getModuleFileInfo(File).Dependencies.push_back(DependsOnID);
673
674 continue;
675 }
676
677
679 typedef llvm::OnDiskIterableChainedHashTable<
680 InterestingASTIdentifierLookupTrait> InterestingIdentifierTable;
681 std::unique_ptr Table(
682 InterestingIdentifierTable::Create(
683 (const unsigned char *)Blob.data() + Record[0],
684 (const unsigned char *)Blob.data() + sizeof(uint32_t),
685 (const unsigned char *)Blob.data()));
686 for (InterestingIdentifierTable::data_iterator D = Table->data_begin(),
687 DEnd = Table->data_end();
688 D != DEnd; ++D) {
689 std::pair<StringRef, bool> Ident = *D;
690 if (Ident.second)
691 InterestingIdentifiers[Ident.first].push_back(ID);
692 else
693 (void)InterestingIdentifiers[Ident.first];
694 }
695 }
696
697
698 if (State == DiagnosticOptionsBlock && Code == SIGNATURE) {
701 "Dummy AST file signature not backpatched in ASTWriter.");
702 getModuleFileInfo(File).Signature = Signature;
703 }
704
705
706 }
707
708 return llvm::Error::success();
709}
710
711namespace {
712
713
714
715class IdentifierIndexWriterTrait {
716public:
717 typedef StringRef key_type;
718 typedef StringRef key_type_ref;
719 typedef SmallVector<unsigned, 2> data_type;
720 typedef const SmallVector<unsigned, 2> &data_type_ref;
721 typedef unsigned hash_value_type;
722 typedef unsigned offset_type;
723
724 static hash_value_type ComputeHash(key_type_ref Key) {
725 return llvm::djbHash(Key);
726 }
727
728 std::pair<unsigned,unsigned>
729 EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) {
730 using namespace llvm::support;
731 endian::Writer LE(Out, llvm::endianness::little);
732 unsigned KeyLen = Key.size();
733 unsigned DataLen = Data.size() * 4;
734 LE.write<uint16_t>(KeyLen);
735 LE.write<uint16_t>(DataLen);
736 return std::make_pair(KeyLen, DataLen);
737 }
738
739 void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
740 Out.write(Key.data(), KeyLen);
741 }
742
743 void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
744 unsigned DataLen) {
745 using namespace llvm::support;
746 for (unsigned I = 0, N = Data.size(); I != N; ++I)
747 endian::write<uint32_t>(Out, Data[I], llvm::endianness::little);
748 }
749};
750
751}
752
753bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
754 for (auto MapEntry : ImportedModuleFiles) {
755 auto File = MapEntry.first;
756 ImportedModuleFileInfo &Info = MapEntry.second;
757 if (getModuleFileInfo(File).Signature) {
758 if (getModuleFileInfo(File).Signature != Info.StoredSignature)
759
760 return true;
761 } else if (Info.StoredSize != File.getSize() ||
762 Info.StoredModTime != File.getModificationTime())
763
764 return true;
765 }
766
767 using namespace llvm;
768 llvm::TimeTraceScope TimeScope("Module WriteIndex");
769
770
771 Stream.Emit((unsigned)'B', 8);
772 Stream.Emit((unsigned)'C', 8);
773 Stream.Emit((unsigned)'G', 8);
774 Stream.Emit((unsigned)'I', 8);
775
776
777
778 emitBlockInfoBlock(Stream);
779
780 Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3);
781
782
785 Stream.EmitRecord(INDEX_METADATA, Record);
786
787
788 for (ModuleFilesMap::iterator M = ModuleFiles.begin(),
789 MEnd = ModuleFiles.end();
790 M != MEnd; ++M) {
792 Record.push_back(M->second.ID);
793 Record.push_back(M->first.getSize());
794 Record.push_back(M->first.getModificationTime());
795
796
797 StringRef Name(M->first.getName());
798 Record.push_back(Name.size());
799 Record.append(Name.begin(), Name.end());
800
801
802 Record.push_back(M->second.Dependencies.size());
803 Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end());
804 Stream.EmitRecord(MODULE, Record);
805 }
806
807
808 {
809 llvm::OnDiskChainedHashTableGenerator Generator;
810 IdentifierIndexWriterTrait Trait;
811
812
813 for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(),
814 IEnd = InterestingIdentifiers.end();
815 I != IEnd; ++I) {
816 Generator.insert(I->first(), I->second, Trait);
817 }
818
819
822 {
823 using namespace llvm::support;
825
826 endian::write<uint32_t>(Out, 0, llvm::endianness::little);
827 BucketOffset = Generator.Emit(Out, Trait);
828 }
829
830
831 auto Abbrev = std::make_shared();
832 Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX));
833 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
834 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
835 unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
836
837
838 uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset};
840 }
841
842 Stream.ExitBlock();
843 return false;
844}
845
846llvm::Error
849 StringRef Path) {
850
851 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
852
854 IndexPath += Path;
855 llvm::sys::path::append(IndexPath, IndexFileName);
856
857
858
859 llvm::LockFileManager Lock(IndexPath);
860 bool Owned;
861 if (llvm::Error Err = Lock.tryLock().moveInto(Owned)) {
862 llvm::consumeError(std::move(Err));
863 return llvm::createStringError(std::errc::io_error, "LFS error");
864 }
865 if (!Owned) {
866
867
868 return llvm::createStringError(std::errc::device_or_resource_busy,
869 "someone else is building the index");
870 }
871
872
873
874
875 GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr);
876
877
878 std::error_code EC;
879 for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd;
880 D != DEnd && !EC;
881 D.increment(EC)) {
882
883 if (llvm::sys::path::extension(D->path()) != ".pcm") {
884
885
886
887 if (llvm::sys::path::extension(D->path()) == ".pcm.lock")
888 return llvm::createStringError(std::errc::device_or_resource_busy,
889 "someone else is building the index");
890
891 continue;
892 }
893
894
895 auto ModuleFile = FileMgr.getOptionalFileRef(D->path());
896 if (!ModuleFile)
897 continue;
898
899
900 if (llvm::Error Err = Builder.loadModuleFile(*ModuleFile))
901 return Err;
902 }
903
904
906 {
907 llvm::BitstreamWriter OutputStream(OutputBuffer);
908 if (Builder.writeIndex(OutputStream))
909 return llvm::createStringError(std::errc::io_error,
910 "failed writing index");
911 }
912
913 return llvm::writeToOutput(IndexPath, [&OutputBuffer](llvm::raw_ostream &OS) {
914 OS << OutputBuffer;
915 return llvm::Error::success();
916 });
917}
918
919namespace {
921
922 IdentifierIndexTable::key_iterator Current;
923
924
925 IdentifierIndexTable::key_iterator End;
926
927 public:
928 explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) {
929 Current = Idx.key_begin();
930 End = Idx.key_end();
931 }
932
933 StringRef Next() override {
934 if (Current == End)
935 return StringRef();
936
937 StringRef Result = *Current;
938 ++Current;
939 return Result;
940 }
941 };
942}
943
945 IdentifierIndexTable &Table =
946 *static_cast<IdentifierIndexTable *>(IdentifierIndex);
947 return new GlobalIndexIdentifierIterator(Table);
948}
#define RECORD(CLASS, BASE)
Defines the clang::FileManager interface and associated types.
FormatToken * Next
The next token in the unwrapped line.
static void emitRecordID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl< uint64_t > &Record)
Definition GlobalModuleIndex.cpp:475
static const unsigned CurrentVersion
The global index file version.
Definition GlobalModuleIndex.cpp:63
static const char *const IndexFileName
The name of the global index file.
Definition GlobalModuleIndex.cpp:60
static void emitBlockID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl< uint64_t > &Record)
Definition GlobalModuleIndex.cpp:460
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.
bool loadedModuleFile(ModuleFile *File)
Note that the given module file has been loaded.
Definition GlobalModuleIndex.cpp:331
void printStats()
Print statistics to standard error.
Definition GlobalModuleIndex.cpp:358
llvm::SmallPtrSet< ModuleFile *, 4 > HitSet
A set of module files in which we found a result.
bool lookupIdentifier(llvm::StringRef Name, HitSet &Hits)
Look for all of the module files with information about the given identifier, e.g....
Definition GlobalModuleIndex.cpp:305
void getModuleDependencies(ModuleFile *File, llvm::SmallVectorImpl< ModuleFile * > &Dependencies)
Retrieve the set of module files on which the given module file directly depends.
Definition GlobalModuleIndex.cpp:287
IdentifierIterator * createIdentifierIterator() const
Returns an iterator for identifiers stored in the index table.
Definition GlobalModuleIndex.cpp:944
static std::pair< GlobalModuleIndex *, llvm::Error > readIndex(llvm::StringRef Path)
Read a global index file for the given directory.
Definition GlobalModuleIndex.cpp:253
~GlobalModuleIndex()
Definition GlobalModuleIndex.cpp:248
void dump()
Print debugging view to standard error.
Definition GlobalModuleIndex.cpp:368
static llvm::Error writeIndex(FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, llvm::StringRef Path)
Write a global index into the given.
Definition GlobalModuleIndex.cpp:847
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.
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.
@ IDENTIFIER_TABLE
Record code for the identifier table.
unsigned ComputeHash(Selector Sel)
uint64_t IdentifierID
An ID number that refers to an identifier in an AST file.
std::shared_ptr< MatchComputation< T > > Generator
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
__LIBC_ATTRS FILE * stderr
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()