clang API Documentation
00001 //===--- GlobalModuleIndex.cpp - Global Module Index ------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the GlobalModuleIndex class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "ASTReaderInternals.h" 00015 #include "clang/Basic/FileManager.h" 00016 #include "clang/Lex/HeaderSearch.h" 00017 #include "clang/Serialization/ASTBitCodes.h" 00018 #include "clang/Serialization/GlobalModuleIndex.h" 00019 #include "clang/Serialization/Module.h" 00020 #include "llvm/ADT/DenseMap.h" 00021 #include "llvm/ADT/MapVector.h" 00022 #include "llvm/ADT/SmallString.h" 00023 #include "llvm/ADT/StringExtras.h" 00024 #include "llvm/Bitcode/BitstreamReader.h" 00025 #include "llvm/Bitcode/BitstreamWriter.h" 00026 #include "llvm/Support/FileSystem.h" 00027 #include "llvm/Support/LockFileManager.h" 00028 #include "llvm/Support/MemoryBuffer.h" 00029 #include "llvm/Support/OnDiskHashTable.h" 00030 #include "llvm/Support/Path.h" 00031 #include <cstdio> 00032 using namespace clang; 00033 using namespace serialization; 00034 00035 //----------------------------------------------------------------------------// 00036 // Shared constants 00037 //----------------------------------------------------------------------------// 00038 namespace { 00039 enum { 00040 /// \brief The block containing the index. 00041 GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID 00042 }; 00043 00044 /// \brief Describes the record types in the index. 00045 enum IndexRecordTypes { 00046 /// \brief Contains version information and potentially other metadata, 00047 /// used to determine if we can read this global index file. 00048 INDEX_METADATA, 00049 /// \brief Describes a module, including its file name and dependencies. 00050 MODULE, 00051 /// \brief The index for identifiers. 00052 IDENTIFIER_INDEX 00053 }; 00054 } 00055 00056 /// \brief The name of the global index file. 00057 static const char * const IndexFileName = "modules.idx"; 00058 00059 /// \brief The global index file version. 00060 static const unsigned CurrentVersion = 1; 00061 00062 //----------------------------------------------------------------------------// 00063 // Global module index reader. 00064 //----------------------------------------------------------------------------// 00065 00066 namespace { 00067 00068 /// \brief Trait used to read the identifier index from the on-disk hash 00069 /// table. 00070 class IdentifierIndexReaderTrait { 00071 public: 00072 typedef StringRef external_key_type; 00073 typedef StringRef internal_key_type; 00074 typedef SmallVector<unsigned, 2> data_type; 00075 typedef unsigned hash_value_type; 00076 typedef unsigned offset_type; 00077 00078 static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 00079 return a == b; 00080 } 00081 00082 static hash_value_type ComputeHash(const internal_key_type& a) { 00083 return llvm::HashString(a); 00084 } 00085 00086 static std::pair<unsigned, unsigned> 00087 ReadKeyDataLength(const unsigned char*& d) { 00088 using namespace llvm::support; 00089 unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); 00090 unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); 00091 return std::make_pair(KeyLen, DataLen); 00092 } 00093 00094 static const internal_key_type& 00095 GetInternalKey(const external_key_type& x) { return x; } 00096 00097 static const external_key_type& 00098 GetExternalKey(const internal_key_type& x) { return x; } 00099 00100 static internal_key_type ReadKey(const unsigned char* d, unsigned n) { 00101 return StringRef((const char *)d, n); 00102 } 00103 00104 static data_type ReadData(const internal_key_type& k, 00105 const unsigned char* d, 00106 unsigned DataLen) { 00107 using namespace llvm::support; 00108 00109 data_type Result; 00110 while (DataLen > 0) { 00111 unsigned ID = endian::readNext<uint32_t, little, unaligned>(d); 00112 Result.push_back(ID); 00113 DataLen -= 4; 00114 } 00115 00116 return Result; 00117 } 00118 }; 00119 00120 typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> 00121 IdentifierIndexTable; 00122 00123 } 00124 00125 GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer, 00126 llvm::BitstreamCursor Cursor) 00127 : Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(), 00128 NumIdentifierLookupHits() { 00129 // Read the global index. 00130 bool InGlobalIndexBlock = false; 00131 bool Done = false; 00132 while (!Done) { 00133 llvm::BitstreamEntry Entry = Cursor.advance(); 00134 00135 switch (Entry.Kind) { 00136 case llvm::BitstreamEntry::Error: 00137 return; 00138 00139 case llvm::BitstreamEntry::EndBlock: 00140 if (InGlobalIndexBlock) { 00141 InGlobalIndexBlock = false; 00142 Done = true; 00143 continue; 00144 } 00145 return; 00146 00147 00148 case llvm::BitstreamEntry::Record: 00149 // Entries in the global index block are handled below. 00150 if (InGlobalIndexBlock) 00151 break; 00152 00153 return; 00154 00155 case llvm::BitstreamEntry::SubBlock: 00156 if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { 00157 if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) 00158 return; 00159 00160 InGlobalIndexBlock = true; 00161 } else if (Cursor.SkipBlock()) { 00162 return; 00163 } 00164 continue; 00165 } 00166 00167 SmallVector<uint64_t, 64> Record; 00168 StringRef Blob; 00169 switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { 00170 case INDEX_METADATA: 00171 // Make sure that the version matches. 00172 if (Record.size() < 1 || Record[0] != CurrentVersion) 00173 return; 00174 break; 00175 00176 case MODULE: { 00177 unsigned Idx = 0; 00178 unsigned ID = Record[Idx++]; 00179 00180 // Make room for this module's information. 00181 if (ID == Modules.size()) 00182 Modules.push_back(ModuleInfo()); 00183 else 00184 Modules.resize(ID + 1); 00185 00186 // Size/modification time for this module file at the time the 00187 // global index was built. 00188 Modules[ID].Size = Record[Idx++]; 00189 Modules[ID].ModTime = Record[Idx++]; 00190 00191 // File name. 00192 unsigned NameLen = Record[Idx++]; 00193 Modules[ID].FileName.assign(Record.begin() + Idx, 00194 Record.begin() + Idx + NameLen); 00195 Idx += NameLen; 00196 00197 // Dependencies 00198 unsigned NumDeps = Record[Idx++]; 00199 Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), 00200 Record.begin() + Idx, 00201 Record.begin() + Idx + NumDeps); 00202 Idx += NumDeps; 00203 00204 // Make sure we're at the end of the record. 00205 assert(Idx == Record.size() && "More module info?"); 00206 00207 // Record this module as an unresolved module. 00208 // FIXME: this doesn't work correctly for module names containing path 00209 // separators. 00210 StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName); 00211 // Remove the -<hash of ModuleMapPath> 00212 ModuleName = ModuleName.rsplit('-').first; 00213 UnresolvedModules[ModuleName] = ID; 00214 break; 00215 } 00216 00217 case IDENTIFIER_INDEX: 00218 // Wire up the identifier index. 00219 if (Record[0]) { 00220 IdentifierIndex = IdentifierIndexTable::Create( 00221 (const unsigned char *)Blob.data() + Record[0], 00222 (const unsigned char *)Blob.data() + sizeof(uint32_t), 00223 (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait()); 00224 } 00225 break; 00226 } 00227 } 00228 } 00229 00230 GlobalModuleIndex::~GlobalModuleIndex() { 00231 delete static_cast<IdentifierIndexTable *>(IdentifierIndex); 00232 } 00233 00234 std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> 00235 GlobalModuleIndex::readIndex(StringRef Path) { 00236 // Load the index file, if it's there. 00237 llvm::SmallString<128> IndexPath; 00238 IndexPath += Path; 00239 llvm::sys::path::append(IndexPath, IndexFileName); 00240 00241 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr = 00242 llvm::MemoryBuffer::getFile(IndexPath.c_str()); 00243 if (!BufferOrErr) 00244 return std::make_pair(nullptr, EC_NotFound); 00245 std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get()); 00246 00247 /// \brief The bitstream reader from which we'll read the AST file. 00248 llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(), 00249 (const unsigned char *)Buffer->getBufferEnd()); 00250 00251 /// \brief The main bitstream cursor for the main block. 00252 llvm::BitstreamCursor Cursor(Reader); 00253 00254 // Sniff for the signature. 00255 if (Cursor.Read(8) != 'B' || 00256 Cursor.Read(8) != 'C' || 00257 Cursor.Read(8) != 'G' || 00258 Cursor.Read(8) != 'I') { 00259 return std::make_pair(nullptr, EC_IOError); 00260 } 00261 00262 return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), 00263 EC_None); 00264 } 00265 00266 void 00267 GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { 00268 ModuleFiles.clear(); 00269 for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 00270 if (ModuleFile *MF = Modules[I].File) 00271 ModuleFiles.push_back(MF); 00272 } 00273 } 00274 00275 void GlobalModuleIndex::getModuleDependencies( 00276 ModuleFile *File, 00277 SmallVectorImpl<ModuleFile *> &Dependencies) { 00278 // Look for information about this module file. 00279 llvm::DenseMap<ModuleFile *, unsigned>::iterator Known 00280 = ModulesByFile.find(File); 00281 if (Known == ModulesByFile.end()) 00282 return; 00283 00284 // Record dependencies. 00285 Dependencies.clear(); 00286 ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; 00287 for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { 00288 if (ModuleFile *MF = Modules[I].File) 00289 Dependencies.push_back(MF); 00290 } 00291 } 00292 00293 bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { 00294 Hits.clear(); 00295 00296 // If there's no identifier index, there is nothing we can do. 00297 if (!IdentifierIndex) 00298 return false; 00299 00300 // Look into the identifier index. 00301 ++NumIdentifierLookups; 00302 IdentifierIndexTable &Table 00303 = *static_cast<IdentifierIndexTable *>(IdentifierIndex); 00304 IdentifierIndexTable::iterator Known = Table.find(Name); 00305 if (Known == Table.end()) { 00306 return true; 00307 } 00308 00309 SmallVector<unsigned, 2> ModuleIDs = *Known; 00310 for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { 00311 if (ModuleFile *MF = Modules[ModuleIDs[I]].File) 00312 Hits.insert(MF); 00313 } 00314 00315 ++NumIdentifierLookupHits; 00316 return true; 00317 } 00318 00319 bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { 00320 // Look for the module in the global module index based on the module name. 00321 StringRef Name = File->ModuleName; 00322 llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); 00323 if (Known == UnresolvedModules.end()) { 00324 return true; 00325 } 00326 00327 // Rectify this module with the global module index. 00328 ModuleInfo &Info = Modules[Known->second]; 00329 00330 // If the size and modification time match what we expected, record this 00331 // module file. 00332 bool Failed = true; 00333 if (File->File->getSize() == Info.Size && 00334 File->File->getModificationTime() == Info.ModTime) { 00335 Info.File = File; 00336 ModulesByFile[File] = Known->second; 00337 00338 Failed = false; 00339 } 00340 00341 // One way or another, we have resolved this module file. 00342 UnresolvedModules.erase(Known); 00343 return Failed; 00344 } 00345 00346 void GlobalModuleIndex::printStats() { 00347 std::fprintf(stderr, "*** Global Module Index Statistics:\n"); 00348 if (NumIdentifierLookups) { 00349 fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n", 00350 NumIdentifierLookupHits, NumIdentifierLookups, 00351 (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); 00352 } 00353 std::fprintf(stderr, "\n"); 00354 } 00355 00356 void GlobalModuleIndex::dump() { 00357 llvm::errs() << "*** Global Module Index Dump:\n"; 00358 llvm::errs() << "Module files:\n"; 00359 for (auto &MI : Modules) { 00360 llvm::errs() << "** " << MI.FileName << "\n"; 00361 if (MI.File) 00362 MI.File->dump(); 00363 else 00364 llvm::errs() << "\n"; 00365 } 00366 llvm::errs() << "\n"; 00367 } 00368 00369 //----------------------------------------------------------------------------// 00370 // Global module index writer. 00371 //----------------------------------------------------------------------------// 00372 00373 namespace { 00374 /// \brief Provides information about a specific module file. 00375 struct ModuleFileInfo { 00376 /// \brief The numberic ID for this module file. 00377 unsigned ID; 00378 00379 /// \brief The set of modules on which this module depends. Each entry is 00380 /// a module ID. 00381 SmallVector<unsigned, 4> Dependencies; 00382 }; 00383 00384 /// \brief Builder that generates the global module index file. 00385 class GlobalModuleIndexBuilder { 00386 FileManager &FileMgr; 00387 00388 /// \brief Mapping from files to module file information. 00389 typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; 00390 00391 /// \brief Information about each of the known module files. 00392 ModuleFilesMap ModuleFiles; 00393 00394 /// \brief Mapping from identifiers to the list of module file IDs that 00395 /// consider this identifier to be interesting. 00396 typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; 00397 00398 /// \brief A mapping from all interesting identifiers to the set of module 00399 /// files in which those identifiers are considered interesting. 00400 InterestingIdentifierMap InterestingIdentifiers; 00401 00402 /// \brief Write the block-info block for the global module index file. 00403 void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); 00404 00405 /// \brief Retrieve the module file information for the given file. 00406 ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { 00407 llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known 00408 = ModuleFiles.find(File); 00409 if (Known != ModuleFiles.end()) 00410 return Known->second; 00411 00412 unsigned NewID = ModuleFiles.size(); 00413 ModuleFileInfo &Info = ModuleFiles[File]; 00414 Info.ID = NewID; 00415 return Info; 00416 } 00417 00418 public: 00419 explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){} 00420 00421 /// \brief Load the contents of the given module file into the builder. 00422 /// 00423 /// \returns true if an error occurred, false otherwise. 00424 bool loadModuleFile(const FileEntry *File); 00425 00426 /// \brief Write the index to the given bitstream. 00427 void writeIndex(llvm::BitstreamWriter &Stream); 00428 }; 00429 } 00430 00431 static void emitBlockID(unsigned ID, const char *Name, 00432 llvm::BitstreamWriter &Stream, 00433 SmallVectorImpl<uint64_t> &Record) { 00434 Record.clear(); 00435 Record.push_back(ID); 00436 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 00437 00438 // Emit the block name if present. 00439 if (!Name || Name[0] == 0) return; 00440 Record.clear(); 00441 while (*Name) 00442 Record.push_back(*Name++); 00443 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 00444 } 00445 00446 static void emitRecordID(unsigned ID, const char *Name, 00447 llvm::BitstreamWriter &Stream, 00448 SmallVectorImpl<uint64_t> &Record) { 00449 Record.clear(); 00450 Record.push_back(ID); 00451 while (*Name) 00452 Record.push_back(*Name++); 00453 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 00454 } 00455 00456 void 00457 GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { 00458 SmallVector<uint64_t, 64> Record; 00459 Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); 00460 00461 #define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 00462 #define RECORD(X) emitRecordID(X, #X, Stream, Record) 00463 BLOCK(GLOBAL_INDEX_BLOCK); 00464 RECORD(INDEX_METADATA); 00465 RECORD(MODULE); 00466 RECORD(IDENTIFIER_INDEX); 00467 #undef RECORD 00468 #undef BLOCK 00469 00470 Stream.ExitBlock(); 00471 } 00472 00473 namespace { 00474 class InterestingASTIdentifierLookupTrait 00475 : public serialization::reader::ASTIdentifierLookupTraitBase { 00476 00477 public: 00478 /// \brief The identifier and whether it is "interesting". 00479 typedef std::pair<StringRef, bool> data_type; 00480 00481 data_type ReadData(const internal_key_type& k, 00482 const unsigned char* d, 00483 unsigned DataLen) { 00484 // The first bit indicates whether this identifier is interesting. 00485 // That's all we care about. 00486 using namespace llvm::support; 00487 unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); 00488 bool IsInteresting = RawID & 0x01; 00489 return std::make_pair(k, IsInteresting); 00490 } 00491 }; 00492 } 00493 00494 bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { 00495 // Open the module file. 00496 00497 auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true); 00498 if (!Buffer) { 00499 return true; 00500 } 00501 00502 // Initialize the input stream 00503 llvm::BitstreamReader InStreamFile; 00504 InStreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(), 00505 (const unsigned char *)(*Buffer)->getBufferEnd()); 00506 llvm::BitstreamCursor InStream(InStreamFile); 00507 00508 // Sniff for the signature. 00509 if (InStream.Read(8) != 'C' || 00510 InStream.Read(8) != 'P' || 00511 InStream.Read(8) != 'C' || 00512 InStream.Read(8) != 'H') { 00513 return true; 00514 } 00515 00516 // Record this module file and assign it a unique ID (if it doesn't have 00517 // one already). 00518 unsigned ID = getModuleFileInfo(File).ID; 00519 00520 // Search for the blocks and records we care about. 00521 enum { Other, ControlBlock, ASTBlock } State = Other; 00522 bool Done = false; 00523 while (!Done) { 00524 llvm::BitstreamEntry Entry = InStream.advance(); 00525 switch (Entry.Kind) { 00526 case llvm::BitstreamEntry::Error: 00527 Done = true; 00528 continue; 00529 00530 case llvm::BitstreamEntry::Record: 00531 // In the 'other' state, just skip the record. We don't care. 00532 if (State == Other) { 00533 InStream.skipRecord(Entry.ID); 00534 continue; 00535 } 00536 00537 // Handle potentially-interesting records below. 00538 break; 00539 00540 case llvm::BitstreamEntry::SubBlock: 00541 if (Entry.ID == CONTROL_BLOCK_ID) { 00542 if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) 00543 return true; 00544 00545 // Found the control block. 00546 State = ControlBlock; 00547 continue; 00548 } 00549 00550 if (Entry.ID == AST_BLOCK_ID) { 00551 if (InStream.EnterSubBlock(AST_BLOCK_ID)) 00552 return true; 00553 00554 // Found the AST block. 00555 State = ASTBlock; 00556 continue; 00557 } 00558 00559 if (InStream.SkipBlock()) 00560 return true; 00561 00562 continue; 00563 00564 case llvm::BitstreamEntry::EndBlock: 00565 State = Other; 00566 continue; 00567 } 00568 00569 // Read the given record. 00570 SmallVector<uint64_t, 64> Record; 00571 StringRef Blob; 00572 unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); 00573 00574 // Handle module dependencies. 00575 if (State == ControlBlock && Code == IMPORTS) { 00576 // Load each of the imported PCH files. 00577 unsigned Idx = 0, N = Record.size(); 00578 while (Idx < N) { 00579 // Read information about the AST file. 00580 00581 // Skip the imported kind 00582 ++Idx; 00583 00584 // Skip the import location 00585 ++Idx; 00586 00587 // Load stored size/modification time. 00588 off_t StoredSize = (off_t)Record[Idx++]; 00589 time_t StoredModTime = (time_t)Record[Idx++]; 00590 00591 // Skip the stored signature. 00592 // FIXME: we could read the signature out of the import and validate it. 00593 Idx++; 00594 00595 // Retrieve the imported file name. 00596 unsigned Length = Record[Idx++]; 00597 SmallString<128> ImportedFile(Record.begin() + Idx, 00598 Record.begin() + Idx + Length); 00599 Idx += Length; 00600 00601 // Find the imported module file. 00602 const FileEntry *DependsOnFile 00603 = FileMgr.getFile(ImportedFile, /*openFile=*/false, 00604 /*cacheFailure=*/false); 00605 if (!DependsOnFile || 00606 (StoredSize != DependsOnFile->getSize()) || 00607 (StoredModTime != DependsOnFile->getModificationTime())) 00608 return true; 00609 00610 // Record the dependency. 00611 unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; 00612 getModuleFileInfo(File).Dependencies.push_back(DependsOnID); 00613 } 00614 00615 continue; 00616 } 00617 00618 // Handle the identifier table 00619 if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { 00620 typedef llvm::OnDiskIterableChainedHashTable< 00621 InterestingASTIdentifierLookupTrait> InterestingIdentifierTable; 00622 std::unique_ptr<InterestingIdentifierTable> Table( 00623 InterestingIdentifierTable::Create( 00624 (const unsigned char *)Blob.data() + Record[0], 00625 (const unsigned char *)Blob.data() + sizeof(uint32_t), 00626 (const unsigned char *)Blob.data())); 00627 for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), 00628 DEnd = Table->data_end(); 00629 D != DEnd; ++D) { 00630 std::pair<StringRef, bool> Ident = *D; 00631 if (Ident.second) 00632 InterestingIdentifiers[Ident.first].push_back(ID); 00633 else 00634 (void)InterestingIdentifiers[Ident.first]; 00635 } 00636 } 00637 00638 // We don't care about this record. 00639 } 00640 00641 return false; 00642 } 00643 00644 namespace { 00645 00646 /// \brief Trait used to generate the identifier index as an on-disk hash 00647 /// table. 00648 class IdentifierIndexWriterTrait { 00649 public: 00650 typedef StringRef key_type; 00651 typedef StringRef key_type_ref; 00652 typedef SmallVector<unsigned, 2> data_type; 00653 typedef const SmallVector<unsigned, 2> &data_type_ref; 00654 typedef unsigned hash_value_type; 00655 typedef unsigned offset_type; 00656 00657 static hash_value_type ComputeHash(key_type_ref Key) { 00658 return llvm::HashString(Key); 00659 } 00660 00661 std::pair<unsigned,unsigned> 00662 EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { 00663 using namespace llvm::support; 00664 endian::Writer<little> LE(Out); 00665 unsigned KeyLen = Key.size(); 00666 unsigned DataLen = Data.size() * 4; 00667 LE.write<uint16_t>(KeyLen); 00668 LE.write<uint16_t>(DataLen); 00669 return std::make_pair(KeyLen, DataLen); 00670 } 00671 00672 void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { 00673 Out.write(Key.data(), KeyLen); 00674 } 00675 00676 void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, 00677 unsigned DataLen) { 00678 using namespace llvm::support; 00679 for (unsigned I = 0, N = Data.size(); I != N; ++I) 00680 endian::Writer<little>(Out).write<uint32_t>(Data[I]); 00681 } 00682 }; 00683 00684 } 00685 00686 void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { 00687 using namespace llvm; 00688 00689 // Emit the file header. 00690 Stream.Emit((unsigned)'B', 8); 00691 Stream.Emit((unsigned)'C', 8); 00692 Stream.Emit((unsigned)'G', 8); 00693 Stream.Emit((unsigned)'I', 8); 00694 00695 // Write the block-info block, which describes the records in this bitcode 00696 // file. 00697 emitBlockInfoBlock(Stream); 00698 00699 Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); 00700 00701 // Write the metadata. 00702 SmallVector<uint64_t, 2> Record; 00703 Record.push_back(CurrentVersion); 00704 Stream.EmitRecord(INDEX_METADATA, Record); 00705 00706 // Write the set of known module files. 00707 for (ModuleFilesMap::iterator M = ModuleFiles.begin(), 00708 MEnd = ModuleFiles.end(); 00709 M != MEnd; ++M) { 00710 Record.clear(); 00711 Record.push_back(M->second.ID); 00712 Record.push_back(M->first->getSize()); 00713 Record.push_back(M->first->getModificationTime()); 00714 00715 // File name 00716 StringRef Name(M->first->getName()); 00717 Record.push_back(Name.size()); 00718 Record.append(Name.begin(), Name.end()); 00719 00720 // Dependencies 00721 Record.push_back(M->second.Dependencies.size()); 00722 Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); 00723 Stream.EmitRecord(MODULE, Record); 00724 } 00725 00726 // Write the identifier -> module file mapping. 00727 { 00728 llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; 00729 IdentifierIndexWriterTrait Trait; 00730 00731 // Populate the hash table. 00732 for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), 00733 IEnd = InterestingIdentifiers.end(); 00734 I != IEnd; ++I) { 00735 Generator.insert(I->first(), I->second, Trait); 00736 } 00737 00738 // Create the on-disk hash table in a buffer. 00739 SmallString<4096> IdentifierTable; 00740 uint32_t BucketOffset; 00741 { 00742 using namespace llvm::support; 00743 llvm::raw_svector_ostream Out(IdentifierTable); 00744 // Make sure that no bucket is at offset 0 00745 endian::Writer<little>(Out).write<uint32_t>(0); 00746 BucketOffset = Generator.Emit(Out, Trait); 00747 } 00748 00749 // Create a blob abbreviation 00750 BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 00751 Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); 00752 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 00753 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 00754 unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); 00755 00756 // Write the identifier table 00757 Record.clear(); 00758 Record.push_back(IDENTIFIER_INDEX); 00759 Record.push_back(BucketOffset); 00760 Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); 00761 } 00762 00763 Stream.ExitBlock(); 00764 } 00765 00766 GlobalModuleIndex::ErrorCode 00767 GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { 00768 llvm::SmallString<128> IndexPath; 00769 IndexPath += Path; 00770 llvm::sys::path::append(IndexPath, IndexFileName); 00771 00772 // Coordinate building the global index file with other processes that might 00773 // try to do the same. 00774 llvm::LockFileManager Locked(IndexPath); 00775 switch (Locked) { 00776 case llvm::LockFileManager::LFS_Error: 00777 return EC_IOError; 00778 00779 case llvm::LockFileManager::LFS_Owned: 00780 // We're responsible for building the index ourselves. Do so below. 00781 break; 00782 00783 case llvm::LockFileManager::LFS_Shared: 00784 // Someone else is responsible for building the index. We don't care 00785 // when they finish, so we're done. 00786 return EC_Building; 00787 } 00788 00789 // The module index builder. 00790 GlobalModuleIndexBuilder Builder(FileMgr); 00791 00792 // Load each of the module files. 00793 std::error_code EC; 00794 for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; 00795 D != DEnd && !EC; 00796 D.increment(EC)) { 00797 // If this isn't a module file, we don't care. 00798 if (llvm::sys::path::extension(D->path()) != ".pcm") { 00799 // ... unless it's a .pcm.lock file, which indicates that someone is 00800 // in the process of rebuilding a module. They'll rebuild the index 00801 // at the end of that translation unit, so we don't have to. 00802 if (llvm::sys::path::extension(D->path()) == ".pcm.lock") 00803 return EC_Building; 00804 00805 continue; 00806 } 00807 00808 // If we can't find the module file, skip it. 00809 const FileEntry *ModuleFile = FileMgr.getFile(D->path()); 00810 if (!ModuleFile) 00811 continue; 00812 00813 // Load this module file. 00814 if (Builder.loadModuleFile(ModuleFile)) 00815 return EC_IOError; 00816 } 00817 00818 // The output buffer, into which the global index will be written. 00819 SmallVector<char, 16> OutputBuffer; 00820 { 00821 llvm::BitstreamWriter OutputStream(OutputBuffer); 00822 Builder.writeIndex(OutputStream); 00823 } 00824 00825 // Write the global index file to a temporary file. 00826 llvm::SmallString<128> IndexTmpPath; 00827 int TmpFD; 00828 if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, 00829 IndexTmpPath)) 00830 return EC_IOError; 00831 00832 // Open the temporary global index file for output. 00833 llvm::raw_fd_ostream Out(TmpFD, true); 00834 if (Out.has_error()) 00835 return EC_IOError; 00836 00837 // Write the index. 00838 Out.write(OutputBuffer.data(), OutputBuffer.size()); 00839 Out.close(); 00840 if (Out.has_error()) 00841 return EC_IOError; 00842 00843 // Remove the old index file. It isn't relevant any more. 00844 llvm::sys::fs::remove(IndexPath.str()); 00845 00846 // Rename the newly-written index file to the proper name. 00847 if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { 00848 // Rename failed; just remove the 00849 llvm::sys::fs::remove(IndexTmpPath.str()); 00850 return EC_IOError; 00851 } 00852 00853 // We're done. 00854 return EC_None; 00855 } 00856 00857 namespace { 00858 class GlobalIndexIdentifierIterator : public IdentifierIterator { 00859 /// \brief The current position within the identifier lookup table. 00860 IdentifierIndexTable::key_iterator Current; 00861 00862 /// \brief The end position within the identifier lookup table. 00863 IdentifierIndexTable::key_iterator End; 00864 00865 public: 00866 explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) { 00867 Current = Idx.key_begin(); 00868 End = Idx.key_end(); 00869 } 00870 00871 StringRef Next() override { 00872 if (Current == End) 00873 return StringRef(); 00874 00875 StringRef Result = *Current; 00876 ++Current; 00877 return Result; 00878 } 00879 }; 00880 } 00881 00882 IdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const { 00883 IdentifierIndexTable &Table = 00884 *static_cast<IdentifierIndexTable *>(IdentifierIndex); 00885 return new GlobalIndexIdentifierIterator(Table); 00886 }