15e306b12SDouglas Gregor //===--- GlobalModuleIndex.cpp - Global Module Index ------------*- C++ -*-===// 25e306b12SDouglas Gregor // 35e306b12SDouglas Gregor // The LLVM Compiler Infrastructure 45e306b12SDouglas Gregor // 55e306b12SDouglas Gregor // This file is distributed under the University of Illinois Open Source 65e306b12SDouglas Gregor // License. See LICENSE.TXT for details. 75e306b12SDouglas Gregor // 85e306b12SDouglas Gregor //===----------------------------------------------------------------------===// 95e306b12SDouglas Gregor // 105e306b12SDouglas Gregor // This file implements the GlobalModuleIndex class. 115e306b12SDouglas Gregor // 125e306b12SDouglas Gregor //===----------------------------------------------------------------------===// 135e306b12SDouglas Gregor 145e306b12SDouglas Gregor #include "ASTReaderInternals.h" 155e306b12SDouglas Gregor #include "clang/Basic/FileManager.h" 165e306b12SDouglas Gregor #include "clang/Basic/OnDiskHashTable.h" 175e306b12SDouglas Gregor #include "clang/Serialization/ASTBitCodes.h" 185e306b12SDouglas Gregor #include "clang/Serialization/GlobalModuleIndex.h" 19603cd869SDouglas Gregor #include "clang/Serialization/Module.h" 205e306b12SDouglas Gregor #include "llvm/ADT/DenseMap.h" 215e306b12SDouglas Gregor #include "llvm/ADT/MapVector.h" 225e306b12SDouglas Gregor #include "llvm/ADT/SmallString.h" 235e306b12SDouglas Gregor #include "llvm/ADT/StringExtras.h" 245e306b12SDouglas Gregor #include "llvm/Bitcode/BitstreamReader.h" 255e306b12SDouglas Gregor #include "llvm/Bitcode/BitstreamWriter.h" 268ec343ccSDouglas Gregor #include "llvm/Support/FileSystem.h" 275e306b12SDouglas Gregor #include "llvm/Support/LockFileManager.h" 285e306b12SDouglas Gregor #include "llvm/Support/MemoryBuffer.h" 29552c169eSRafael Espindola #include "llvm/Support/Path.h" 30f0add23aSNAKAMURA Takumi #include <cstdio> 315e306b12SDouglas Gregor using namespace clang; 325e306b12SDouglas Gregor using namespace serialization; 335e306b12SDouglas Gregor 345e306b12SDouglas Gregor //----------------------------------------------------------------------------// 355e306b12SDouglas Gregor // Shared constants 365e306b12SDouglas Gregor //----------------------------------------------------------------------------// 375e306b12SDouglas Gregor namespace { 385e306b12SDouglas Gregor enum { 395e306b12SDouglas Gregor /// \brief The block containing the index. 405e306b12SDouglas Gregor GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID 415e306b12SDouglas Gregor }; 425e306b12SDouglas Gregor 435e306b12SDouglas Gregor /// \brief Describes the record types in the index. 445e306b12SDouglas Gregor enum IndexRecordTypes { 455e306b12SDouglas Gregor /// \brief Contains version information and potentially other metadata, 465e306b12SDouglas Gregor /// used to determine if we can read this global index file. 47e060e57bSDouglas Gregor INDEX_METADATA, 485e306b12SDouglas Gregor /// \brief Describes a module, including its file name and dependencies. 495e306b12SDouglas Gregor MODULE, 505e306b12SDouglas Gregor /// \brief The index for identifiers. 515e306b12SDouglas Gregor IDENTIFIER_INDEX 525e306b12SDouglas Gregor }; 535e306b12SDouglas Gregor } 545e306b12SDouglas Gregor 555e306b12SDouglas Gregor /// \brief The name of the global index file. 565e306b12SDouglas Gregor static const char * const IndexFileName = "modules.idx"; 575e306b12SDouglas Gregor 585e306b12SDouglas Gregor /// \brief The global index file version. 595e306b12SDouglas Gregor static const unsigned CurrentVersion = 1; 605e306b12SDouglas Gregor 615e306b12SDouglas Gregor //----------------------------------------------------------------------------// 62e060e57bSDouglas Gregor // Global module index reader. 63e060e57bSDouglas Gregor //----------------------------------------------------------------------------// 64e060e57bSDouglas Gregor 65e060e57bSDouglas Gregor namespace { 66e060e57bSDouglas Gregor 67e060e57bSDouglas Gregor /// \brief Trait used to read the identifier index from the on-disk hash 68e060e57bSDouglas Gregor /// table. 69e060e57bSDouglas Gregor class IdentifierIndexReaderTrait { 70e060e57bSDouglas Gregor public: 71e060e57bSDouglas Gregor typedef StringRef external_key_type; 72e060e57bSDouglas Gregor typedef StringRef internal_key_type; 73e060e57bSDouglas Gregor typedef SmallVector<unsigned, 2> data_type; 74e060e57bSDouglas Gregor 75e060e57bSDouglas Gregor static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 76e060e57bSDouglas Gregor return a == b; 77e060e57bSDouglas Gregor } 78e060e57bSDouglas Gregor 79e060e57bSDouglas Gregor static unsigned ComputeHash(const internal_key_type& a) { 80e060e57bSDouglas Gregor return llvm::HashString(a); 81e060e57bSDouglas Gregor } 82e060e57bSDouglas Gregor 83e060e57bSDouglas Gregor static std::pair<unsigned, unsigned> 84e060e57bSDouglas Gregor ReadKeyDataLength(const unsigned char*& d) { 8557ba0b22SJustin Bogner using namespace llvm::support; 8657ba0b22SJustin Bogner unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); 8757ba0b22SJustin Bogner unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); 88e060e57bSDouglas Gregor return std::make_pair(KeyLen, DataLen); 89e060e57bSDouglas Gregor } 90e060e57bSDouglas Gregor 91e060e57bSDouglas Gregor static const internal_key_type& 92e060e57bSDouglas Gregor GetInternalKey(const external_key_type& x) { return x; } 93e060e57bSDouglas Gregor 94e060e57bSDouglas Gregor static const external_key_type& 95e060e57bSDouglas Gregor GetExternalKey(const internal_key_type& x) { return x; } 96e060e57bSDouglas Gregor 97e060e57bSDouglas Gregor static internal_key_type ReadKey(const unsigned char* d, unsigned n) { 98e060e57bSDouglas Gregor return StringRef((const char *)d, n); 99e060e57bSDouglas Gregor } 100e060e57bSDouglas Gregor 101e060e57bSDouglas Gregor static data_type ReadData(const internal_key_type& k, 102e060e57bSDouglas Gregor const unsigned char* d, 103e060e57bSDouglas Gregor unsigned DataLen) { 10457ba0b22SJustin Bogner using namespace llvm::support; 105e060e57bSDouglas Gregor 106e060e57bSDouglas Gregor data_type Result; 107e060e57bSDouglas Gregor while (DataLen > 0) { 10857ba0b22SJustin Bogner unsigned ID = endian::readNext<uint32_t, little, unaligned>(d); 109e060e57bSDouglas Gregor Result.push_back(ID); 110e060e57bSDouglas Gregor DataLen -= 4; 111e060e57bSDouglas Gregor } 112e060e57bSDouglas Gregor 113e060e57bSDouglas Gregor return Result; 114e060e57bSDouglas Gregor } 115e060e57bSDouglas Gregor }; 116e060e57bSDouglas Gregor 117*da4e650eSJustin Bogner typedef OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> 118*da4e650eSJustin Bogner IdentifierIndexTable; 119e060e57bSDouglas Gregor 120e060e57bSDouglas Gregor } 121e060e57bSDouglas Gregor 1227029ce1aSDouglas Gregor GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer, 123e060e57bSDouglas Gregor llvm::BitstreamCursor Cursor) 124603cd869SDouglas Gregor : Buffer(Buffer), IdentifierIndex(), 1257211ac15SDouglas Gregor NumIdentifierLookups(), NumIdentifierLookupHits() 126e060e57bSDouglas Gregor { 127e060e57bSDouglas Gregor // Read the global index. 128e060e57bSDouglas Gregor bool InGlobalIndexBlock = false; 129e060e57bSDouglas Gregor bool Done = false; 130e060e57bSDouglas Gregor while (!Done) { 131e060e57bSDouglas Gregor llvm::BitstreamEntry Entry = Cursor.advance(); 132e060e57bSDouglas Gregor 133e060e57bSDouglas Gregor switch (Entry.Kind) { 134e060e57bSDouglas Gregor case llvm::BitstreamEntry::Error: 135e060e57bSDouglas Gregor return; 136e060e57bSDouglas Gregor 137e060e57bSDouglas Gregor case llvm::BitstreamEntry::EndBlock: 138e060e57bSDouglas Gregor if (InGlobalIndexBlock) { 139e060e57bSDouglas Gregor InGlobalIndexBlock = false; 140e060e57bSDouglas Gregor Done = true; 141e060e57bSDouglas Gregor continue; 142e060e57bSDouglas Gregor } 143e060e57bSDouglas Gregor return; 144e060e57bSDouglas Gregor 145e060e57bSDouglas Gregor 146e060e57bSDouglas Gregor case llvm::BitstreamEntry::Record: 147e060e57bSDouglas Gregor // Entries in the global index block are handled below. 148e060e57bSDouglas Gregor if (InGlobalIndexBlock) 149e060e57bSDouglas Gregor break; 150e060e57bSDouglas Gregor 151e060e57bSDouglas Gregor return; 152e060e57bSDouglas Gregor 153e060e57bSDouglas Gregor case llvm::BitstreamEntry::SubBlock: 154e060e57bSDouglas Gregor if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { 155e060e57bSDouglas Gregor if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) 156e060e57bSDouglas Gregor return; 157e060e57bSDouglas Gregor 158e060e57bSDouglas Gregor InGlobalIndexBlock = true; 159e060e57bSDouglas Gregor } else if (Cursor.SkipBlock()) { 160e060e57bSDouglas Gregor return; 161e060e57bSDouglas Gregor } 162e060e57bSDouglas Gregor continue; 163e060e57bSDouglas Gregor } 164e060e57bSDouglas Gregor 165e060e57bSDouglas Gregor SmallVector<uint64_t, 64> Record; 166e060e57bSDouglas Gregor StringRef Blob; 167e060e57bSDouglas Gregor switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { 168e060e57bSDouglas Gregor case INDEX_METADATA: 169e060e57bSDouglas Gregor // Make sure that the version matches. 170e060e57bSDouglas Gregor if (Record.size() < 1 || Record[0] != CurrentVersion) 171e060e57bSDouglas Gregor return; 172e060e57bSDouglas Gregor break; 173e060e57bSDouglas Gregor 174e060e57bSDouglas Gregor case MODULE: { 175e060e57bSDouglas Gregor unsigned Idx = 0; 176e060e57bSDouglas Gregor unsigned ID = Record[Idx++]; 177e060e57bSDouglas Gregor 1787029ce1aSDouglas Gregor // Make room for this module's information. 1797029ce1aSDouglas Gregor if (ID == Modules.size()) 1807029ce1aSDouglas Gregor Modules.push_back(ModuleInfo()); 1817029ce1aSDouglas Gregor else 1827029ce1aSDouglas Gregor Modules.resize(ID + 1); 1837029ce1aSDouglas Gregor 1847029ce1aSDouglas Gregor // Size/modification time for this module file at the time the 1857029ce1aSDouglas Gregor // global index was built. 1867029ce1aSDouglas Gregor Modules[ID].Size = Record[Idx++]; 1877029ce1aSDouglas Gregor Modules[ID].ModTime = Record[Idx++]; 188e060e57bSDouglas Gregor 189e060e57bSDouglas Gregor // File name. 190e060e57bSDouglas Gregor unsigned NameLen = Record[Idx++]; 1917029ce1aSDouglas Gregor Modules[ID].FileName.assign(Record.begin() + Idx, 192e060e57bSDouglas Gregor Record.begin() + Idx + NameLen); 193e060e57bSDouglas Gregor Idx += NameLen; 194e060e57bSDouglas Gregor 195e060e57bSDouglas Gregor // Dependencies 196e060e57bSDouglas Gregor unsigned NumDeps = Record[Idx++]; 1977029ce1aSDouglas Gregor Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), 1987029ce1aSDouglas Gregor Record.begin() + Idx, 1997029ce1aSDouglas Gregor Record.begin() + Idx + NumDeps); 2007029ce1aSDouglas Gregor Idx += NumDeps; 201e060e57bSDouglas Gregor 2027029ce1aSDouglas Gregor // Make sure we're at the end of the record. 2037029ce1aSDouglas Gregor assert(Idx == Record.size() && "More module info?"); 204603cd869SDouglas Gregor 205603cd869SDouglas Gregor // Record this module as an unresolved module. 206603cd869SDouglas Gregor UnresolvedModules[llvm::sys::path::stem(Modules[ID].FileName)] = ID; 207e060e57bSDouglas Gregor break; 208e060e57bSDouglas Gregor } 209e060e57bSDouglas Gregor 210e060e57bSDouglas Gregor case IDENTIFIER_INDEX: 211e060e57bSDouglas Gregor // Wire up the identifier index. 212e060e57bSDouglas Gregor if (Record[0]) { 213e060e57bSDouglas Gregor IdentifierIndex = IdentifierIndexTable::Create( 214e060e57bSDouglas Gregor (const unsigned char *)Blob.data() + Record[0], 215*da4e650eSJustin Bogner (const unsigned char *)Blob.data() + sizeof(uint32_t), 216*da4e650eSJustin Bogner (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait()); 217e060e57bSDouglas Gregor } 218e060e57bSDouglas Gregor break; 219e060e57bSDouglas Gregor } 220e060e57bSDouglas Gregor } 221e060e57bSDouglas Gregor } 222e060e57bSDouglas Gregor 223e060e57bSDouglas Gregor GlobalModuleIndex::~GlobalModuleIndex() { } 224e060e57bSDouglas Gregor 225e060e57bSDouglas Gregor std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> 2267029ce1aSDouglas Gregor GlobalModuleIndex::readIndex(StringRef Path) { 227e060e57bSDouglas Gregor // Load the index file, if it's there. 228e060e57bSDouglas Gregor llvm::SmallString<128> IndexPath; 229e060e57bSDouglas Gregor IndexPath += Path; 230e060e57bSDouglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 231e060e57bSDouglas Gregor 232b8984329SAhmed Charles std::unique_ptr<llvm::MemoryBuffer> Buffer; 2331a3605cdSRafael Espindola if (llvm::MemoryBuffer::getFile(IndexPath.c_str(), Buffer) != 2341a3605cdSRafael Espindola llvm::errc::success) 235e060e57bSDouglas Gregor return std::make_pair((GlobalModuleIndex *)0, EC_NotFound); 236e060e57bSDouglas Gregor 237e060e57bSDouglas Gregor /// \brief The bitstream reader from which we'll read the AST file. 238e060e57bSDouglas Gregor llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(), 239e060e57bSDouglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 240e060e57bSDouglas Gregor 241e060e57bSDouglas Gregor /// \brief The main bitstream cursor for the main block. 242e060e57bSDouglas Gregor llvm::BitstreamCursor Cursor(Reader); 243e060e57bSDouglas Gregor 244e060e57bSDouglas Gregor // Sniff for the signature. 245e060e57bSDouglas Gregor if (Cursor.Read(8) != 'B' || 246e060e57bSDouglas Gregor Cursor.Read(8) != 'C' || 247e060e57bSDouglas Gregor Cursor.Read(8) != 'G' || 248e060e57bSDouglas Gregor Cursor.Read(8) != 'I') { 249e060e57bSDouglas Gregor return std::make_pair((GlobalModuleIndex *)0, EC_IOError); 250e060e57bSDouglas Gregor } 251e060e57bSDouglas Gregor 2529a16beb8SAhmed Charles return std::make_pair(new GlobalModuleIndex(Buffer.release(), Cursor), 2539a16beb8SAhmed Charles EC_None); 254e060e57bSDouglas Gregor } 255e060e57bSDouglas Gregor 2567029ce1aSDouglas Gregor void 2577029ce1aSDouglas Gregor GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { 258e060e57bSDouglas Gregor ModuleFiles.clear(); 259e060e57bSDouglas Gregor for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 260603cd869SDouglas Gregor if (ModuleFile *MF = Modules[I].File) 261603cd869SDouglas Gregor ModuleFiles.push_back(MF); 262e060e57bSDouglas Gregor } 263e060e57bSDouglas Gregor } 264e060e57bSDouglas Gregor 265e060e57bSDouglas Gregor void GlobalModuleIndex::getModuleDependencies( 2667029ce1aSDouglas Gregor ModuleFile *File, 2677029ce1aSDouglas Gregor SmallVectorImpl<ModuleFile *> &Dependencies) { 268e060e57bSDouglas Gregor // Look for information about this module file. 2697029ce1aSDouglas Gregor llvm::DenseMap<ModuleFile *, unsigned>::iterator Known 2707029ce1aSDouglas Gregor = ModulesByFile.find(File); 271e060e57bSDouglas Gregor if (Known == ModulesByFile.end()) 272e060e57bSDouglas Gregor return; 273e060e57bSDouglas Gregor 274e060e57bSDouglas Gregor // Record dependencies. 2757029ce1aSDouglas Gregor Dependencies.clear(); 2767029ce1aSDouglas Gregor ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; 2777029ce1aSDouglas Gregor for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { 278603cd869SDouglas Gregor if (ModuleFile *MF = Modules[I].File) 2797029ce1aSDouglas Gregor Dependencies.push_back(MF); 2807029ce1aSDouglas Gregor } 281e060e57bSDouglas Gregor } 282e060e57bSDouglas Gregor 2837211ac15SDouglas Gregor bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { 2847211ac15SDouglas Gregor Hits.clear(); 285e060e57bSDouglas Gregor 286e060e57bSDouglas Gregor // If there's no identifier index, there is nothing we can do. 287e060e57bSDouglas Gregor if (!IdentifierIndex) 288e060e57bSDouglas Gregor return false; 289e060e57bSDouglas Gregor 290e060e57bSDouglas Gregor // Look into the identifier index. 291e060e57bSDouglas Gregor ++NumIdentifierLookups; 292e060e57bSDouglas Gregor IdentifierIndexTable &Table 293e060e57bSDouglas Gregor = *static_cast<IdentifierIndexTable *>(IdentifierIndex); 294e060e57bSDouglas Gregor IdentifierIndexTable::iterator Known = Table.find(Name); 295e060e57bSDouglas Gregor if (Known == Table.end()) { 296e060e57bSDouglas Gregor return true; 297e060e57bSDouglas Gregor } 298e060e57bSDouglas Gregor 299e060e57bSDouglas Gregor SmallVector<unsigned, 2> ModuleIDs = *Known; 300e060e57bSDouglas Gregor for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { 301603cd869SDouglas Gregor if (ModuleFile *MF = Modules[ModuleIDs[I]].File) 302603cd869SDouglas Gregor Hits.insert(MF); 303e060e57bSDouglas Gregor } 304e060e57bSDouglas Gregor 305e060e57bSDouglas Gregor ++NumIdentifierLookupHits; 306e060e57bSDouglas Gregor return true; 307e060e57bSDouglas Gregor } 308e060e57bSDouglas Gregor 309603cd869SDouglas Gregor bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { 310603cd869SDouglas Gregor // Look for the module in the global module index based on the module name. 311603cd869SDouglas Gregor StringRef Name = llvm::sys::path::stem(File->FileName); 312603cd869SDouglas Gregor llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); 313603cd869SDouglas Gregor if (Known == UnresolvedModules.end()) { 314603cd869SDouglas Gregor return true; 3157029ce1aSDouglas Gregor } 3167029ce1aSDouglas Gregor 317603cd869SDouglas Gregor // Rectify this module with the global module index. 318603cd869SDouglas Gregor ModuleInfo &Info = Modules[Known->second]; 319603cd869SDouglas Gregor 320603cd869SDouglas Gregor // If the size and modification time match what we expected, record this 321603cd869SDouglas Gregor // module file. 322603cd869SDouglas Gregor bool Failed = true; 323603cd869SDouglas Gregor if (File->File->getSize() == Info.Size && 324603cd869SDouglas Gregor File->File->getModificationTime() == Info.ModTime) { 325603cd869SDouglas Gregor Info.File = File; 326603cd869SDouglas Gregor ModulesByFile[File] = Known->second; 327603cd869SDouglas Gregor 328603cd869SDouglas Gregor Failed = false; 3297029ce1aSDouglas Gregor } 3307029ce1aSDouglas Gregor 331603cd869SDouglas Gregor // One way or another, we have resolved this module file. 332603cd869SDouglas Gregor UnresolvedModules.erase(Known); 333603cd869SDouglas Gregor return Failed; 3347029ce1aSDouglas Gregor } 3357029ce1aSDouglas Gregor 336e060e57bSDouglas Gregor void GlobalModuleIndex::printStats() { 337e060e57bSDouglas Gregor std::fprintf(stderr, "*** Global Module Index Statistics:\n"); 338e060e57bSDouglas Gregor if (NumIdentifierLookups) { 339e060e57bSDouglas Gregor fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n", 340e060e57bSDouglas Gregor NumIdentifierLookupHits, NumIdentifierLookups, 341e060e57bSDouglas Gregor (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); 342e060e57bSDouglas Gregor } 343e060e57bSDouglas Gregor std::fprintf(stderr, "\n"); 344e060e57bSDouglas Gregor } 345e060e57bSDouglas Gregor 346e060e57bSDouglas Gregor //----------------------------------------------------------------------------// 3475e306b12SDouglas Gregor // Global module index writer. 3485e306b12SDouglas Gregor //----------------------------------------------------------------------------// 3495e306b12SDouglas Gregor 3505e306b12SDouglas Gregor namespace { 3515e306b12SDouglas Gregor /// \brief Provides information about a specific module file. 3525e306b12SDouglas Gregor struct ModuleFileInfo { 3535e306b12SDouglas Gregor /// \brief The numberic ID for this module file. 3545e306b12SDouglas Gregor unsigned ID; 3555e306b12SDouglas Gregor 3565e306b12SDouglas Gregor /// \brief The set of modules on which this module depends. Each entry is 3575e306b12SDouglas Gregor /// a module ID. 3585e306b12SDouglas Gregor SmallVector<unsigned, 4> Dependencies; 3595e306b12SDouglas Gregor }; 3605e306b12SDouglas Gregor 3615e306b12SDouglas Gregor /// \brief Builder that generates the global module index file. 3625e306b12SDouglas Gregor class GlobalModuleIndexBuilder { 3635e306b12SDouglas Gregor FileManager &FileMgr; 3645e306b12SDouglas Gregor 3655e306b12SDouglas Gregor /// \brief Mapping from files to module file information. 3665e306b12SDouglas Gregor typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; 3675e306b12SDouglas Gregor 3685e306b12SDouglas Gregor /// \brief Information about each of the known module files. 3695e306b12SDouglas Gregor ModuleFilesMap ModuleFiles; 3705e306b12SDouglas Gregor 3715e306b12SDouglas Gregor /// \brief Mapping from identifiers to the list of module file IDs that 3725e306b12SDouglas Gregor /// consider this identifier to be interesting. 3735e306b12SDouglas Gregor typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; 3745e306b12SDouglas Gregor 3755e306b12SDouglas Gregor /// \brief A mapping from all interesting identifiers to the set of module 3765e306b12SDouglas Gregor /// files in which those identifiers are considered interesting. 3775e306b12SDouglas Gregor InterestingIdentifierMap InterestingIdentifiers; 3785e306b12SDouglas Gregor 3795e306b12SDouglas Gregor /// \brief Write the block-info block for the global module index file. 3805e306b12SDouglas Gregor void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); 3815e306b12SDouglas Gregor 3825e306b12SDouglas Gregor /// \brief Retrieve the module file information for the given file. 3835e306b12SDouglas Gregor ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { 3845e306b12SDouglas Gregor llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known 3855e306b12SDouglas Gregor = ModuleFiles.find(File); 3865e306b12SDouglas Gregor if (Known != ModuleFiles.end()) 3875e306b12SDouglas Gregor return Known->second; 3885e306b12SDouglas Gregor 3895e306b12SDouglas Gregor unsigned NewID = ModuleFiles.size(); 3905e306b12SDouglas Gregor ModuleFileInfo &Info = ModuleFiles[File]; 3915e306b12SDouglas Gregor Info.ID = NewID; 3925e306b12SDouglas Gregor return Info; 3935e306b12SDouglas Gregor } 3945e306b12SDouglas Gregor 3955e306b12SDouglas Gregor public: 3965e306b12SDouglas Gregor explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){} 3975e306b12SDouglas Gregor 3985e306b12SDouglas Gregor /// \brief Load the contents of the given module file into the builder. 3995e306b12SDouglas Gregor /// 4005e306b12SDouglas Gregor /// \returns true if an error occurred, false otherwise. 4015e306b12SDouglas Gregor bool loadModuleFile(const FileEntry *File); 4025e306b12SDouglas Gregor 4035e306b12SDouglas Gregor /// \brief Write the index to the given bitstream. 4045e306b12SDouglas Gregor void writeIndex(llvm::BitstreamWriter &Stream); 4055e306b12SDouglas Gregor }; 4065e306b12SDouglas Gregor } 4075e306b12SDouglas Gregor 4085e306b12SDouglas Gregor static void emitBlockID(unsigned ID, const char *Name, 4095e306b12SDouglas Gregor llvm::BitstreamWriter &Stream, 4105e306b12SDouglas Gregor SmallVectorImpl<uint64_t> &Record) { 4115e306b12SDouglas Gregor Record.clear(); 4125e306b12SDouglas Gregor Record.push_back(ID); 4135e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 4145e306b12SDouglas Gregor 4155e306b12SDouglas Gregor // Emit the block name if present. 4165e306b12SDouglas Gregor if (Name == 0 || Name[0] == 0) return; 4175e306b12SDouglas Gregor Record.clear(); 4185e306b12SDouglas Gregor while (*Name) 4195e306b12SDouglas Gregor Record.push_back(*Name++); 4205e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 4215e306b12SDouglas Gregor } 4225e306b12SDouglas Gregor 4235e306b12SDouglas Gregor static void emitRecordID(unsigned ID, const char *Name, 4245e306b12SDouglas Gregor llvm::BitstreamWriter &Stream, 4255e306b12SDouglas Gregor SmallVectorImpl<uint64_t> &Record) { 4265e306b12SDouglas Gregor Record.clear(); 4275e306b12SDouglas Gregor Record.push_back(ID); 4285e306b12SDouglas Gregor while (*Name) 4295e306b12SDouglas Gregor Record.push_back(*Name++); 4305e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 4315e306b12SDouglas Gregor } 4325e306b12SDouglas Gregor 4335e306b12SDouglas Gregor void 4345e306b12SDouglas Gregor GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { 4355e306b12SDouglas Gregor SmallVector<uint64_t, 64> Record; 4365e306b12SDouglas Gregor Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); 4375e306b12SDouglas Gregor 4385e306b12SDouglas Gregor #define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 4395e306b12SDouglas Gregor #define RECORD(X) emitRecordID(X, #X, Stream, Record) 4405e306b12SDouglas Gregor BLOCK(GLOBAL_INDEX_BLOCK); 441e060e57bSDouglas Gregor RECORD(INDEX_METADATA); 4425e306b12SDouglas Gregor RECORD(MODULE); 4435e306b12SDouglas Gregor RECORD(IDENTIFIER_INDEX); 4445e306b12SDouglas Gregor #undef RECORD 4455e306b12SDouglas Gregor #undef BLOCK 4465e306b12SDouglas Gregor 4475e306b12SDouglas Gregor Stream.ExitBlock(); 4485e306b12SDouglas Gregor } 4495e306b12SDouglas Gregor 450e060e57bSDouglas Gregor namespace { 4515e306b12SDouglas Gregor class InterestingASTIdentifierLookupTrait 4525e306b12SDouglas Gregor : public serialization::reader::ASTIdentifierLookupTraitBase { 4535e306b12SDouglas Gregor 4545e306b12SDouglas Gregor public: 4555e306b12SDouglas Gregor /// \brief The identifier and whether it is "interesting". 4565e306b12SDouglas Gregor typedef std::pair<StringRef, bool> data_type; 4575e306b12SDouglas Gregor 4585e306b12SDouglas Gregor data_type ReadData(const internal_key_type& k, 4595e306b12SDouglas Gregor const unsigned char* d, 4605e306b12SDouglas Gregor unsigned DataLen) { 4615e306b12SDouglas Gregor // The first bit indicates whether this identifier is interesting. 4625e306b12SDouglas Gregor // That's all we care about. 46357ba0b22SJustin Bogner using namespace llvm::support; 46457ba0b22SJustin Bogner unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); 4655e306b12SDouglas Gregor bool IsInteresting = RawID & 0x01; 4665e306b12SDouglas Gregor return std::make_pair(k, IsInteresting); 4675e306b12SDouglas Gregor } 4685e306b12SDouglas Gregor }; 4695e306b12SDouglas Gregor } 4705e306b12SDouglas Gregor 4715e306b12SDouglas Gregor bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { 4725e306b12SDouglas Gregor // Open the module file. 473b8984329SAhmed Charles std::unique_ptr<llvm::MemoryBuffer> Buffer; 474cb680661SDouglas Gregor std::string ErrorStr; 475cb680661SDouglas Gregor Buffer.reset(FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)); 4765e306b12SDouglas Gregor if (!Buffer) { 4775e306b12SDouglas Gregor return true; 4785e306b12SDouglas Gregor } 4795e306b12SDouglas Gregor 4805e306b12SDouglas Gregor // Initialize the input stream 4815e306b12SDouglas Gregor llvm::BitstreamReader InStreamFile; 4825e306b12SDouglas Gregor llvm::BitstreamCursor InStream; 4835e306b12SDouglas Gregor InStreamFile.init((const unsigned char *)Buffer->getBufferStart(), 4845e306b12SDouglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 4855e306b12SDouglas Gregor InStream.init(InStreamFile); 4865e306b12SDouglas Gregor 4875e306b12SDouglas Gregor // Sniff for the signature. 4885e306b12SDouglas Gregor if (InStream.Read(8) != 'C' || 4895e306b12SDouglas Gregor InStream.Read(8) != 'P' || 4905e306b12SDouglas Gregor InStream.Read(8) != 'C' || 4915e306b12SDouglas Gregor InStream.Read(8) != 'H') { 4925e306b12SDouglas Gregor return true; 4935e306b12SDouglas Gregor } 4945e306b12SDouglas Gregor 4955e306b12SDouglas Gregor // Record this module file and assign it a unique ID (if it doesn't have 4965e306b12SDouglas Gregor // one already). 4975e306b12SDouglas Gregor unsigned ID = getModuleFileInfo(File).ID; 4985e306b12SDouglas Gregor 4995e306b12SDouglas Gregor // Search for the blocks and records we care about. 500e060e57bSDouglas Gregor enum { Other, ControlBlock, ASTBlock } State = Other; 5015e306b12SDouglas Gregor bool Done = false; 5025e306b12SDouglas Gregor while (!Done) { 503e060e57bSDouglas Gregor llvm::BitstreamEntry Entry = InStream.advance(); 5045e306b12SDouglas Gregor switch (Entry.Kind) { 5055e306b12SDouglas Gregor case llvm::BitstreamEntry::Error: 506e060e57bSDouglas Gregor Done = true; 507e060e57bSDouglas Gregor continue; 5085e306b12SDouglas Gregor 5095e306b12SDouglas Gregor case llvm::BitstreamEntry::Record: 510e060e57bSDouglas Gregor // In the 'other' state, just skip the record. We don't care. 511e060e57bSDouglas Gregor if (State == Other) { 5125e306b12SDouglas Gregor InStream.skipRecord(Entry.ID); 5135e306b12SDouglas Gregor continue; 5145e306b12SDouglas Gregor } 5155e306b12SDouglas Gregor 5165e306b12SDouglas Gregor // Handle potentially-interesting records below. 5175e306b12SDouglas Gregor break; 5185e306b12SDouglas Gregor 5195e306b12SDouglas Gregor case llvm::BitstreamEntry::SubBlock: 520e060e57bSDouglas Gregor if (Entry.ID == CONTROL_BLOCK_ID) { 5215e306b12SDouglas Gregor if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) 5225e306b12SDouglas Gregor return true; 5235e306b12SDouglas Gregor 5245e306b12SDouglas Gregor // Found the control block. 5255e306b12SDouglas Gregor State = ControlBlock; 5265e306b12SDouglas Gregor continue; 5275e306b12SDouglas Gregor } 5285e306b12SDouglas Gregor 529e060e57bSDouglas Gregor if (Entry.ID == AST_BLOCK_ID) { 5305e306b12SDouglas Gregor if (InStream.EnterSubBlock(AST_BLOCK_ID)) 5315e306b12SDouglas Gregor return true; 5325e306b12SDouglas Gregor 5335e306b12SDouglas Gregor // Found the AST block. 5345e306b12SDouglas Gregor State = ASTBlock; 5355e306b12SDouglas Gregor continue; 5365e306b12SDouglas Gregor } 5375e306b12SDouglas Gregor 5385e306b12SDouglas Gregor if (InStream.SkipBlock()) 5395e306b12SDouglas Gregor return true; 5405e306b12SDouglas Gregor 5415e306b12SDouglas Gregor continue; 5425e306b12SDouglas Gregor 5435e306b12SDouglas Gregor case llvm::BitstreamEntry::EndBlock: 544e060e57bSDouglas Gregor State = Other; 5455e306b12SDouglas Gregor continue; 5465e306b12SDouglas Gregor } 5475e306b12SDouglas Gregor 5485e306b12SDouglas Gregor // Read the given record. 5495e306b12SDouglas Gregor SmallVector<uint64_t, 64> Record; 5505e306b12SDouglas Gregor StringRef Blob; 5515e306b12SDouglas Gregor unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); 5525e306b12SDouglas Gregor 5535e306b12SDouglas Gregor // Handle module dependencies. 5545e306b12SDouglas Gregor if (State == ControlBlock && Code == IMPORTS) { 5555e306b12SDouglas Gregor // Load each of the imported PCH files. 5565e306b12SDouglas Gregor unsigned Idx = 0, N = Record.size(); 5575e306b12SDouglas Gregor while (Idx < N) { 5585e306b12SDouglas Gregor // Read information about the AST file. 5595e306b12SDouglas Gregor 5605e306b12SDouglas Gregor // Skip the imported kind 5615e306b12SDouglas Gregor ++Idx; 5625e306b12SDouglas Gregor 5635e306b12SDouglas Gregor // Skip the import location 5645e306b12SDouglas Gregor ++Idx; 5655e306b12SDouglas Gregor 5667029ce1aSDouglas Gregor // Load stored size/modification time. 5677029ce1aSDouglas Gregor off_t StoredSize = (off_t)Record[Idx++]; 5687029ce1aSDouglas Gregor time_t StoredModTime = (time_t)Record[Idx++]; 5697029ce1aSDouglas Gregor 5705e306b12SDouglas Gregor // Retrieve the imported file name. 5715e306b12SDouglas Gregor unsigned Length = Record[Idx++]; 5725e306b12SDouglas Gregor SmallString<128> ImportedFile(Record.begin() + Idx, 5735e306b12SDouglas Gregor Record.begin() + Idx + Length); 5745e306b12SDouglas Gregor Idx += Length; 5755e306b12SDouglas Gregor 5765e306b12SDouglas Gregor // Find the imported module file. 577dadd85dcSDouglas Gregor const FileEntry *DependsOnFile 578dadd85dcSDouglas Gregor = FileMgr.getFile(ImportedFile, /*openFile=*/false, 579dadd85dcSDouglas Gregor /*cacheFailure=*/false); 5807029ce1aSDouglas Gregor if (!DependsOnFile || 5817029ce1aSDouglas Gregor (StoredSize != DependsOnFile->getSize()) || 5827029ce1aSDouglas Gregor (StoredModTime != DependsOnFile->getModificationTime())) 5835e306b12SDouglas Gregor return true; 5845e306b12SDouglas Gregor 5855e306b12SDouglas Gregor // Record the dependency. 5865e306b12SDouglas Gregor unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; 5875e306b12SDouglas Gregor getModuleFileInfo(File).Dependencies.push_back(DependsOnID); 5885e306b12SDouglas Gregor } 5895e306b12SDouglas Gregor 5905e306b12SDouglas Gregor continue; 5915e306b12SDouglas Gregor } 5925e306b12SDouglas Gregor 5935e306b12SDouglas Gregor // Handle the identifier table 5945e306b12SDouglas Gregor if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { 595*da4e650eSJustin Bogner typedef 596*da4e650eSJustin Bogner OnDiskIterableChainedHashTable<InterestingASTIdentifierLookupTrait> 5975e306b12SDouglas Gregor InterestingIdentifierTable; 598b8984329SAhmed Charles std::unique_ptr<InterestingIdentifierTable> Table( 599b8984329SAhmed Charles InterestingIdentifierTable::Create( 6005e306b12SDouglas Gregor (const unsigned char *)Blob.data() + Record[0], 601*da4e650eSJustin Bogner (const unsigned char *)Blob.data() + sizeof(uint32_t), 6025e306b12SDouglas Gregor (const unsigned char *)Blob.data())); 6035e306b12SDouglas Gregor for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), 6045e306b12SDouglas Gregor DEnd = Table->data_end(); 6055e306b12SDouglas Gregor D != DEnd; ++D) { 6065e306b12SDouglas Gregor std::pair<StringRef, bool> Ident = *D; 6075e306b12SDouglas Gregor if (Ident.second) 6085e306b12SDouglas Gregor InterestingIdentifiers[Ident.first].push_back(ID); 609e060e57bSDouglas Gregor else 610e060e57bSDouglas Gregor (void)InterestingIdentifiers[Ident.first]; 6115e306b12SDouglas Gregor } 6125e306b12SDouglas Gregor } 6135e306b12SDouglas Gregor 6145e306b12SDouglas Gregor // We don't care about this record. 6155e306b12SDouglas Gregor } 6165e306b12SDouglas Gregor 6175e306b12SDouglas Gregor return false; 6185e306b12SDouglas Gregor } 6195e306b12SDouglas Gregor 6205e306b12SDouglas Gregor namespace { 6215e306b12SDouglas Gregor 6225e306b12SDouglas Gregor /// \brief Trait used to generate the identifier index as an on-disk hash 6235e306b12SDouglas Gregor /// table. 6245e306b12SDouglas Gregor class IdentifierIndexWriterTrait { 6255e306b12SDouglas Gregor public: 6265e306b12SDouglas Gregor typedef StringRef key_type; 6275e306b12SDouglas Gregor typedef StringRef key_type_ref; 6285e306b12SDouglas Gregor typedef SmallVector<unsigned, 2> data_type; 6295e306b12SDouglas Gregor typedef const SmallVector<unsigned, 2> &data_type_ref; 6305e306b12SDouglas Gregor 6315e306b12SDouglas Gregor static unsigned ComputeHash(key_type_ref Key) { 6325e306b12SDouglas Gregor return llvm::HashString(Key); 6335e306b12SDouglas Gregor } 6345e306b12SDouglas Gregor 6355e306b12SDouglas Gregor std::pair<unsigned,unsigned> 6365e306b12SDouglas Gregor EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { 637e1c147c3SJustin Bogner using namespace llvm::support; 638e1c147c3SJustin Bogner endian::Writer<little> LE(Out); 6395e306b12SDouglas Gregor unsigned KeyLen = Key.size(); 6405e306b12SDouglas Gregor unsigned DataLen = Data.size() * 4; 641e1c147c3SJustin Bogner LE.write<uint16_t>(KeyLen); 642e1c147c3SJustin Bogner LE.write<uint16_t>(DataLen); 6435e306b12SDouglas Gregor return std::make_pair(KeyLen, DataLen); 6445e306b12SDouglas Gregor } 6455e306b12SDouglas Gregor 6465e306b12SDouglas Gregor void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { 6475e306b12SDouglas Gregor Out.write(Key.data(), KeyLen); 6485e306b12SDouglas Gregor } 6495e306b12SDouglas Gregor 6505e306b12SDouglas Gregor void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, 6515e306b12SDouglas Gregor unsigned DataLen) { 652e1c147c3SJustin Bogner using namespace llvm::support; 6535e306b12SDouglas Gregor for (unsigned I = 0, N = Data.size(); I != N; ++I) 654e1c147c3SJustin Bogner endian::Writer<little>(Out).write<uint32_t>(Data[I]); 6555e306b12SDouglas Gregor } 6565e306b12SDouglas Gregor }; 6575e306b12SDouglas Gregor 6585e306b12SDouglas Gregor } 6595e306b12SDouglas Gregor 6605e306b12SDouglas Gregor void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { 6615e306b12SDouglas Gregor using namespace llvm; 6625e306b12SDouglas Gregor 6635e306b12SDouglas Gregor // Emit the file header. 6645e306b12SDouglas Gregor Stream.Emit((unsigned)'B', 8); 6655e306b12SDouglas Gregor Stream.Emit((unsigned)'C', 8); 6665e306b12SDouglas Gregor Stream.Emit((unsigned)'G', 8); 6675e306b12SDouglas Gregor Stream.Emit((unsigned)'I', 8); 6685e306b12SDouglas Gregor 6695e306b12SDouglas Gregor // Write the block-info block, which describes the records in this bitcode 6705e306b12SDouglas Gregor // file. 6715e306b12SDouglas Gregor emitBlockInfoBlock(Stream); 6725e306b12SDouglas Gregor 6735e306b12SDouglas Gregor Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); 6745e306b12SDouglas Gregor 6755e306b12SDouglas Gregor // Write the metadata. 6765e306b12SDouglas Gregor SmallVector<uint64_t, 2> Record; 6775e306b12SDouglas Gregor Record.push_back(CurrentVersion); 678e060e57bSDouglas Gregor Stream.EmitRecord(INDEX_METADATA, Record); 6795e306b12SDouglas Gregor 6805e306b12SDouglas Gregor // Write the set of known module files. 6815e306b12SDouglas Gregor for (ModuleFilesMap::iterator M = ModuleFiles.begin(), 6825e306b12SDouglas Gregor MEnd = ModuleFiles.end(); 6835e306b12SDouglas Gregor M != MEnd; ++M) { 6845e306b12SDouglas Gregor Record.clear(); 6855e306b12SDouglas Gregor Record.push_back(M->second.ID); 6865e306b12SDouglas Gregor Record.push_back(M->first->getSize()); 6875e306b12SDouglas Gregor Record.push_back(M->first->getModificationTime()); 6885e306b12SDouglas Gregor 6895e306b12SDouglas Gregor // File name 6905e306b12SDouglas Gregor StringRef Name(M->first->getName()); 6915e306b12SDouglas Gregor Record.push_back(Name.size()); 6925e306b12SDouglas Gregor Record.append(Name.begin(), Name.end()); 6935e306b12SDouglas Gregor 6945e306b12SDouglas Gregor // Dependencies 6955e306b12SDouglas Gregor Record.push_back(M->second.Dependencies.size()); 6965e306b12SDouglas Gregor Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); 6975e306b12SDouglas Gregor Stream.EmitRecord(MODULE, Record); 6985e306b12SDouglas Gregor } 6995e306b12SDouglas Gregor 7005e306b12SDouglas Gregor // Write the identifier -> module file mapping. 7015e306b12SDouglas Gregor { 7025e306b12SDouglas Gregor OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; 7035e306b12SDouglas Gregor IdentifierIndexWriterTrait Trait; 7045e306b12SDouglas Gregor 7055e306b12SDouglas Gregor // Populate the hash table. 7065e306b12SDouglas Gregor for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), 7075e306b12SDouglas Gregor IEnd = InterestingIdentifiers.end(); 7085e306b12SDouglas Gregor I != IEnd; ++I) { 7095e306b12SDouglas Gregor Generator.insert(I->first(), I->second, Trait); 7105e306b12SDouglas Gregor } 7115e306b12SDouglas Gregor 7125e306b12SDouglas Gregor // Create the on-disk hash table in a buffer. 7135e306b12SDouglas Gregor SmallString<4096> IdentifierTable; 7145e306b12SDouglas Gregor uint32_t BucketOffset; 7155e306b12SDouglas Gregor { 716e1c147c3SJustin Bogner using namespace llvm::support; 7175e306b12SDouglas Gregor llvm::raw_svector_ostream Out(IdentifierTable); 7185e306b12SDouglas Gregor // Make sure that no bucket is at offset 0 719e1c147c3SJustin Bogner endian::Writer<little>(Out).write<uint32_t>(0); 7205e306b12SDouglas Gregor BucketOffset = Generator.Emit(Out, Trait); 7215e306b12SDouglas Gregor } 7225e306b12SDouglas Gregor 7235e306b12SDouglas Gregor // Create a blob abbreviation 7245e306b12SDouglas Gregor BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 7255e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); 7265e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 7275e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 7285e306b12SDouglas Gregor unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); 7295e306b12SDouglas Gregor 7305e306b12SDouglas Gregor // Write the identifier table 7315e306b12SDouglas Gregor Record.clear(); 7325e306b12SDouglas Gregor Record.push_back(IDENTIFIER_INDEX); 7335e306b12SDouglas Gregor Record.push_back(BucketOffset); 7345e306b12SDouglas Gregor Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); 7355e306b12SDouglas Gregor } 7365e306b12SDouglas Gregor 7375e306b12SDouglas Gregor Stream.ExitBlock(); 7385e306b12SDouglas Gregor } 7395e306b12SDouglas Gregor 7405e306b12SDouglas Gregor GlobalModuleIndex::ErrorCode 7415e306b12SDouglas Gregor GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { 7425e306b12SDouglas Gregor llvm::SmallString<128> IndexPath; 7435e306b12SDouglas Gregor IndexPath += Path; 7445e306b12SDouglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 7455e306b12SDouglas Gregor 7465e306b12SDouglas Gregor // Coordinate building the global index file with other processes that might 7475e306b12SDouglas Gregor // try to do the same. 7485e306b12SDouglas Gregor llvm::LockFileManager Locked(IndexPath); 7495e306b12SDouglas Gregor switch (Locked) { 7505e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Error: 7515e306b12SDouglas Gregor return EC_IOError; 7525e306b12SDouglas Gregor 7535e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Owned: 7545e306b12SDouglas Gregor // We're responsible for building the index ourselves. Do so below. 7555e306b12SDouglas Gregor break; 7565e306b12SDouglas Gregor 7575e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Shared: 7585e306b12SDouglas Gregor // Someone else is responsible for building the index. We don't care 7595e306b12SDouglas Gregor // when they finish, so we're done. 7605e306b12SDouglas Gregor return EC_Building; 7615e306b12SDouglas Gregor } 7625e306b12SDouglas Gregor 7635e306b12SDouglas Gregor // The module index builder. 7645e306b12SDouglas Gregor GlobalModuleIndexBuilder Builder(FileMgr); 7655e306b12SDouglas Gregor 7665e306b12SDouglas Gregor // Load each of the module files. 7675e306b12SDouglas Gregor llvm::error_code EC; 7685e306b12SDouglas Gregor for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; 7695e306b12SDouglas Gregor D != DEnd && !EC; 7705e306b12SDouglas Gregor D.increment(EC)) { 7715e306b12SDouglas Gregor // If this isn't a module file, we don't care. 7725e306b12SDouglas Gregor if (llvm::sys::path::extension(D->path()) != ".pcm") { 7735e306b12SDouglas Gregor // ... unless it's a .pcm.lock file, which indicates that someone is 7745e306b12SDouglas Gregor // in the process of rebuilding a module. They'll rebuild the index 7755e306b12SDouglas Gregor // at the end of that translation unit, so we don't have to. 7765e306b12SDouglas Gregor if (llvm::sys::path::extension(D->path()) == ".pcm.lock") 7775e306b12SDouglas Gregor return EC_Building; 7785e306b12SDouglas Gregor 7795e306b12SDouglas Gregor continue; 7805e306b12SDouglas Gregor } 7815e306b12SDouglas Gregor 7825e306b12SDouglas Gregor // If we can't find the module file, skip it. 7835e306b12SDouglas Gregor const FileEntry *ModuleFile = FileMgr.getFile(D->path()); 7845e306b12SDouglas Gregor if (!ModuleFile) 7855e306b12SDouglas Gregor continue; 7865e306b12SDouglas Gregor 7875e306b12SDouglas Gregor // Load this module file. 7885e306b12SDouglas Gregor if (Builder.loadModuleFile(ModuleFile)) 7895e306b12SDouglas Gregor return EC_IOError; 7905e306b12SDouglas Gregor } 7915e306b12SDouglas Gregor 7925e306b12SDouglas Gregor // The output buffer, into which the global index will be written. 7935e306b12SDouglas Gregor SmallVector<char, 16> OutputBuffer; 7945e306b12SDouglas Gregor { 7955e306b12SDouglas Gregor llvm::BitstreamWriter OutputStream(OutputBuffer); 7965e306b12SDouglas Gregor Builder.writeIndex(OutputStream); 7975e306b12SDouglas Gregor } 7985e306b12SDouglas Gregor 7995e306b12SDouglas Gregor // Write the global index file to a temporary file. 8005e306b12SDouglas Gregor llvm::SmallString<128> IndexTmpPath; 8015e306b12SDouglas Gregor int TmpFD; 80218627115SRafael Espindola if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, 80318627115SRafael Espindola IndexTmpPath)) 8045e306b12SDouglas Gregor return EC_IOError; 8055e306b12SDouglas Gregor 8065e306b12SDouglas Gregor // Open the temporary global index file for output. 807e00c9868SNAKAMURA Takumi llvm::raw_fd_ostream Out(TmpFD, true); 8085e306b12SDouglas Gregor if (Out.has_error()) 8095e306b12SDouglas Gregor return EC_IOError; 8105e306b12SDouglas Gregor 8115e306b12SDouglas Gregor // Write the index. 8125e306b12SDouglas Gregor Out.write(OutputBuffer.data(), OutputBuffer.size()); 8135e306b12SDouglas Gregor Out.close(); 8145e306b12SDouglas Gregor if (Out.has_error()) 8155e306b12SDouglas Gregor return EC_IOError; 8165e306b12SDouglas Gregor 8175e306b12SDouglas Gregor // Remove the old index file. It isn't relevant any more. 8182a008784SRafael Espindola llvm::sys::fs::remove(IndexPath.str()); 8195e306b12SDouglas Gregor 8205e306b12SDouglas Gregor // Rename the newly-written index file to the proper name. 8215e306b12SDouglas Gregor if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { 8225e306b12SDouglas Gregor // Rename failed; just remove the 8232a008784SRafael Espindola llvm::sys::fs::remove(IndexTmpPath.str()); 8245e306b12SDouglas Gregor return EC_IOError; 8255e306b12SDouglas Gregor } 8265e306b12SDouglas Gregor 8275e306b12SDouglas Gregor // We're done. 8285e306b12SDouglas Gregor return EC_None; 8295e306b12SDouglas Gregor } 8309aca3c61SArgyrios Kyrtzidis 8319aca3c61SArgyrios Kyrtzidis namespace { 8329aca3c61SArgyrios Kyrtzidis class GlobalIndexIdentifierIterator : public IdentifierIterator { 8339aca3c61SArgyrios Kyrtzidis /// \brief The current position within the identifier lookup table. 8349aca3c61SArgyrios Kyrtzidis IdentifierIndexTable::key_iterator Current; 8359aca3c61SArgyrios Kyrtzidis 8369aca3c61SArgyrios Kyrtzidis /// \brief The end position within the identifier lookup table. 8379aca3c61SArgyrios Kyrtzidis IdentifierIndexTable::key_iterator End; 8389aca3c61SArgyrios Kyrtzidis 8399aca3c61SArgyrios Kyrtzidis public: 8409aca3c61SArgyrios Kyrtzidis explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) { 8419aca3c61SArgyrios Kyrtzidis Current = Idx.key_begin(); 8429aca3c61SArgyrios Kyrtzidis End = Idx.key_end(); 8439aca3c61SArgyrios Kyrtzidis } 8449aca3c61SArgyrios Kyrtzidis 8453e89dfeeSCraig Topper StringRef Next() override { 8469aca3c61SArgyrios Kyrtzidis if (Current == End) 8479aca3c61SArgyrios Kyrtzidis return StringRef(); 8489aca3c61SArgyrios Kyrtzidis 8499aca3c61SArgyrios Kyrtzidis StringRef Result = *Current; 8509aca3c61SArgyrios Kyrtzidis ++Current; 8519aca3c61SArgyrios Kyrtzidis return Result; 8529aca3c61SArgyrios Kyrtzidis } 8539aca3c61SArgyrios Kyrtzidis }; 8549aca3c61SArgyrios Kyrtzidis } 8559aca3c61SArgyrios Kyrtzidis 8569aca3c61SArgyrios Kyrtzidis IdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const { 8579aca3c61SArgyrios Kyrtzidis IdentifierIndexTable &Table = 8589aca3c61SArgyrios Kyrtzidis *static_cast<IdentifierIndexTable *>(IdentifierIndex); 8599aca3c61SArgyrios Kyrtzidis return new GlobalIndexIdentifierIterator(Table); 8609aca3c61SArgyrios Kyrtzidis } 861