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