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();

684 D != DEnd; ++D) {

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()