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" 195e306b12SDouglas Gregor #include "llvm/ADT/DenseMap.h" 205e306b12SDouglas Gregor #include "llvm/ADT/MapVector.h" 215e306b12SDouglas Gregor #include "llvm/ADT/SmallString.h" 225e306b12SDouglas Gregor #include "llvm/ADT/StringExtras.h" 235e306b12SDouglas Gregor #include "llvm/Bitcode/BitstreamReader.h" 245e306b12SDouglas Gregor #include "llvm/Bitcode/BitstreamWriter.h" 258ec343ccSDouglas Gregor #include "llvm/Support/FileSystem.h" 265e306b12SDouglas Gregor #include "llvm/Support/LockFileManager.h" 275e306b12SDouglas Gregor #include "llvm/Support/MemoryBuffer.h" 285e306b12SDouglas Gregor #include "llvm/Support/PathV2.h" 295e306b12SDouglas Gregor using namespace clang; 305e306b12SDouglas Gregor using namespace serialization; 315e306b12SDouglas Gregor 325e306b12SDouglas Gregor //----------------------------------------------------------------------------// 335e306b12SDouglas Gregor // Shared constants 345e306b12SDouglas Gregor //----------------------------------------------------------------------------// 355e306b12SDouglas Gregor namespace { 365e306b12SDouglas Gregor enum { 375e306b12SDouglas Gregor /// \brief The block containing the index. 385e306b12SDouglas Gregor GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID 395e306b12SDouglas Gregor }; 405e306b12SDouglas Gregor 415e306b12SDouglas Gregor /// \brief Describes the record types in the index. 425e306b12SDouglas Gregor enum IndexRecordTypes { 435e306b12SDouglas Gregor /// \brief Contains version information and potentially other metadata, 445e306b12SDouglas Gregor /// used to determine if we can read this global index file. 45*e060e57bSDouglas Gregor INDEX_METADATA, 465e306b12SDouglas Gregor /// \brief Describes a module, including its file name and dependencies. 475e306b12SDouglas Gregor MODULE, 485e306b12SDouglas Gregor /// \brief The index for identifiers. 495e306b12SDouglas Gregor IDENTIFIER_INDEX 505e306b12SDouglas Gregor }; 515e306b12SDouglas Gregor } 525e306b12SDouglas Gregor 535e306b12SDouglas Gregor /// \brief The name of the global index file. 545e306b12SDouglas Gregor static const char * const IndexFileName = "modules.idx"; 555e306b12SDouglas Gregor 565e306b12SDouglas Gregor /// \brief The global index file version. 575e306b12SDouglas Gregor static const unsigned CurrentVersion = 1; 585e306b12SDouglas Gregor 595e306b12SDouglas Gregor //----------------------------------------------------------------------------// 60*e060e57bSDouglas Gregor // Global module index reader. 61*e060e57bSDouglas Gregor //----------------------------------------------------------------------------// 62*e060e57bSDouglas Gregor 63*e060e57bSDouglas Gregor namespace { 64*e060e57bSDouglas Gregor 65*e060e57bSDouglas Gregor /// \brief Trait used to read the identifier index from the on-disk hash 66*e060e57bSDouglas Gregor /// table. 67*e060e57bSDouglas Gregor class IdentifierIndexReaderTrait { 68*e060e57bSDouglas Gregor public: 69*e060e57bSDouglas Gregor typedef StringRef external_key_type; 70*e060e57bSDouglas Gregor typedef StringRef internal_key_type; 71*e060e57bSDouglas Gregor typedef SmallVector<unsigned, 2> data_type; 72*e060e57bSDouglas Gregor 73*e060e57bSDouglas Gregor static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 74*e060e57bSDouglas Gregor return a == b; 75*e060e57bSDouglas Gregor } 76*e060e57bSDouglas Gregor 77*e060e57bSDouglas Gregor static unsigned ComputeHash(const internal_key_type& a) { 78*e060e57bSDouglas Gregor return llvm::HashString(a); 79*e060e57bSDouglas Gregor } 80*e060e57bSDouglas Gregor 81*e060e57bSDouglas Gregor static std::pair<unsigned, unsigned> 82*e060e57bSDouglas Gregor ReadKeyDataLength(const unsigned char*& d) { 83*e060e57bSDouglas Gregor using namespace clang::io; 84*e060e57bSDouglas Gregor unsigned KeyLen = ReadUnalignedLE16(d); 85*e060e57bSDouglas Gregor unsigned DataLen = ReadUnalignedLE16(d); 86*e060e57bSDouglas Gregor return std::make_pair(KeyLen, DataLen); 87*e060e57bSDouglas Gregor } 88*e060e57bSDouglas Gregor 89*e060e57bSDouglas Gregor static const internal_key_type& 90*e060e57bSDouglas Gregor GetInternalKey(const external_key_type& x) { return x; } 91*e060e57bSDouglas Gregor 92*e060e57bSDouglas Gregor static const external_key_type& 93*e060e57bSDouglas Gregor GetExternalKey(const internal_key_type& x) { return x; } 94*e060e57bSDouglas Gregor 95*e060e57bSDouglas Gregor static internal_key_type ReadKey(const unsigned char* d, unsigned n) { 96*e060e57bSDouglas Gregor return StringRef((const char *)d, n); 97*e060e57bSDouglas Gregor } 98*e060e57bSDouglas Gregor 99*e060e57bSDouglas Gregor static data_type ReadData(const internal_key_type& k, 100*e060e57bSDouglas Gregor const unsigned char* d, 101*e060e57bSDouglas Gregor unsigned DataLen) { 102*e060e57bSDouglas Gregor using namespace clang::io; 103*e060e57bSDouglas Gregor 104*e060e57bSDouglas Gregor data_type Result; 105*e060e57bSDouglas Gregor while (DataLen > 0) { 106*e060e57bSDouglas Gregor unsigned ID = ReadUnalignedLE32(d); 107*e060e57bSDouglas Gregor Result.push_back(ID); 108*e060e57bSDouglas Gregor DataLen -= 4; 109*e060e57bSDouglas Gregor } 110*e060e57bSDouglas Gregor 111*e060e57bSDouglas Gregor return Result; 112*e060e57bSDouglas Gregor } 113*e060e57bSDouglas Gregor }; 114*e060e57bSDouglas Gregor 115*e060e57bSDouglas Gregor typedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable; 116*e060e57bSDouglas Gregor 117*e060e57bSDouglas Gregor /// \brief Module information as it was loaded from the index file. 118*e060e57bSDouglas Gregor struct LoadedModuleInfo { 119*e060e57bSDouglas Gregor const FileEntry *File; 120*e060e57bSDouglas Gregor SmallVector<unsigned, 2> Dependencies; 121*e060e57bSDouglas Gregor SmallVector<unsigned, 2> ImportedBy; 122*e060e57bSDouglas Gregor }; 123*e060e57bSDouglas Gregor 124*e060e57bSDouglas Gregor } 125*e060e57bSDouglas Gregor 126*e060e57bSDouglas Gregor GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr, 127*e060e57bSDouglas Gregor llvm::MemoryBuffer *Buffer, 128*e060e57bSDouglas Gregor llvm::BitstreamCursor Cursor) 129*e060e57bSDouglas Gregor : Buffer(Buffer), IdentifierIndex() 130*e060e57bSDouglas Gregor { 131*e060e57bSDouglas Gregor typedef llvm::DenseMap<unsigned, LoadedModuleInfo> LoadedModulesMap; 132*e060e57bSDouglas Gregor LoadedModulesMap LoadedModules; 133*e060e57bSDouglas Gregor 134*e060e57bSDouglas Gregor // Read the global index. 135*e060e57bSDouglas Gregor unsigned LargestID = 0; 136*e060e57bSDouglas Gregor bool InGlobalIndexBlock = false; 137*e060e57bSDouglas Gregor bool Done = false; 138*e060e57bSDouglas Gregor bool AnyOutOfDate = false; 139*e060e57bSDouglas Gregor while (!Done) { 140*e060e57bSDouglas Gregor llvm::BitstreamEntry Entry = Cursor.advance(); 141*e060e57bSDouglas Gregor 142*e060e57bSDouglas Gregor switch (Entry.Kind) { 143*e060e57bSDouglas Gregor case llvm::BitstreamEntry::Error: 144*e060e57bSDouglas Gregor return; 145*e060e57bSDouglas Gregor 146*e060e57bSDouglas Gregor case llvm::BitstreamEntry::EndBlock: 147*e060e57bSDouglas Gregor if (InGlobalIndexBlock) { 148*e060e57bSDouglas Gregor InGlobalIndexBlock = false; 149*e060e57bSDouglas Gregor Done = true; 150*e060e57bSDouglas Gregor continue; 151*e060e57bSDouglas Gregor } 152*e060e57bSDouglas Gregor return; 153*e060e57bSDouglas Gregor 154*e060e57bSDouglas Gregor 155*e060e57bSDouglas Gregor case llvm::BitstreamEntry::Record: 156*e060e57bSDouglas Gregor // Entries in the global index block are handled below. 157*e060e57bSDouglas Gregor if (InGlobalIndexBlock) 158*e060e57bSDouglas Gregor break; 159*e060e57bSDouglas Gregor 160*e060e57bSDouglas Gregor return; 161*e060e57bSDouglas Gregor 162*e060e57bSDouglas Gregor case llvm::BitstreamEntry::SubBlock: 163*e060e57bSDouglas Gregor if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { 164*e060e57bSDouglas Gregor if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) 165*e060e57bSDouglas Gregor return; 166*e060e57bSDouglas Gregor 167*e060e57bSDouglas Gregor InGlobalIndexBlock = true; 168*e060e57bSDouglas Gregor } else if (Cursor.SkipBlock()) { 169*e060e57bSDouglas Gregor return; 170*e060e57bSDouglas Gregor } 171*e060e57bSDouglas Gregor continue; 172*e060e57bSDouglas Gregor } 173*e060e57bSDouglas Gregor 174*e060e57bSDouglas Gregor SmallVector<uint64_t, 64> Record; 175*e060e57bSDouglas Gregor StringRef Blob; 176*e060e57bSDouglas Gregor switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { 177*e060e57bSDouglas Gregor case INDEX_METADATA: 178*e060e57bSDouglas Gregor // Make sure that the version matches. 179*e060e57bSDouglas Gregor if (Record.size() < 1 || Record[0] != CurrentVersion) 180*e060e57bSDouglas Gregor return; 181*e060e57bSDouglas Gregor break; 182*e060e57bSDouglas Gregor 183*e060e57bSDouglas Gregor case MODULE: { 184*e060e57bSDouglas Gregor unsigned Idx = 0; 185*e060e57bSDouglas Gregor unsigned ID = Record[Idx++]; 186*e060e57bSDouglas Gregor if (ID > LargestID) 187*e060e57bSDouglas Gregor LargestID = ID; 188*e060e57bSDouglas Gregor 189*e060e57bSDouglas Gregor off_t Size = Record[Idx++]; 190*e060e57bSDouglas Gregor time_t ModTime = Record[Idx++]; 191*e060e57bSDouglas Gregor 192*e060e57bSDouglas Gregor // File name. 193*e060e57bSDouglas Gregor unsigned NameLen = Record[Idx++]; 194*e060e57bSDouglas Gregor llvm::SmallString<64> FileName(Record.begin() + Idx, 195*e060e57bSDouglas Gregor Record.begin() + Idx + NameLen); 196*e060e57bSDouglas Gregor Idx += NameLen; 197*e060e57bSDouglas Gregor 198*e060e57bSDouglas Gregor // Dependencies 199*e060e57bSDouglas Gregor unsigned NumDeps = Record[Idx++]; 200*e060e57bSDouglas Gregor llvm::SmallVector<unsigned, 2> 201*e060e57bSDouglas Gregor Dependencies(Record.begin() + Idx, Record.begin() + Idx + NumDeps); 202*e060e57bSDouglas Gregor 203*e060e57bSDouglas Gregor // Find the file. If we can't find it, ignore it. 204*e060e57bSDouglas Gregor const FileEntry *File = FileMgr.getFile(FileName); 205*e060e57bSDouglas Gregor if (!File) { 206*e060e57bSDouglas Gregor AnyOutOfDate = true; 207*e060e57bSDouglas Gregor break; 208*e060e57bSDouglas Gregor } 209*e060e57bSDouglas Gregor 210*e060e57bSDouglas Gregor // If the module file is newer than the index, ignore it. 211*e060e57bSDouglas Gregor if (File->getSize() != Size || File->getModificationTime() != ModTime) { 212*e060e57bSDouglas Gregor AnyOutOfDate = true; 213*e060e57bSDouglas Gregor break; 214*e060e57bSDouglas Gregor } 215*e060e57bSDouglas Gregor 216*e060e57bSDouglas Gregor // Record this module. The dependencies will be resolved later. 217*e060e57bSDouglas Gregor LoadedModuleInfo &Info = LoadedModules[ID]; 218*e060e57bSDouglas Gregor Info.File = File; 219*e060e57bSDouglas Gregor Info.Dependencies.swap(Dependencies); 220*e060e57bSDouglas Gregor break; 221*e060e57bSDouglas Gregor } 222*e060e57bSDouglas Gregor 223*e060e57bSDouglas Gregor case IDENTIFIER_INDEX: 224*e060e57bSDouglas Gregor // Wire up the identifier index. 225*e060e57bSDouglas Gregor if (Record[0]) { 226*e060e57bSDouglas Gregor IdentifierIndex = IdentifierIndexTable::Create( 227*e060e57bSDouglas Gregor (const unsigned char *)Blob.data() + Record[0], 228*e060e57bSDouglas Gregor (const unsigned char *)Blob.data(), 229*e060e57bSDouglas Gregor IdentifierIndexReaderTrait()); 230*e060e57bSDouglas Gregor } 231*e060e57bSDouglas Gregor break; 232*e060e57bSDouglas Gregor } 233*e060e57bSDouglas Gregor } 234*e060e57bSDouglas Gregor 235*e060e57bSDouglas Gregor // If there are any modules that have gone out-of-date, prune out any modules 236*e060e57bSDouglas Gregor // that depend on them. 237*e060e57bSDouglas Gregor if (AnyOutOfDate) { 238*e060e57bSDouglas Gregor // First, build back links in the module dependency graph. 239*e060e57bSDouglas Gregor SmallVector<unsigned, 4> Stack; 240*e060e57bSDouglas Gregor for (LoadedModulesMap::iterator LM = LoadedModules.begin(), 241*e060e57bSDouglas Gregor LMEnd = LoadedModules.end(); 242*e060e57bSDouglas Gregor LM != LMEnd; ++LM) { 243*e060e57bSDouglas Gregor unsigned ID = LM->first; 244*e060e57bSDouglas Gregor 245*e060e57bSDouglas Gregor // If this module is out-of-date, push it onto the stack. 246*e060e57bSDouglas Gregor if (LM->second.File == 0) 247*e060e57bSDouglas Gregor Stack.push_back(ID); 248*e060e57bSDouglas Gregor 249*e060e57bSDouglas Gregor for (unsigned I = 0, N = LM->second.Dependencies.size(); I != N; ++I) { 250*e060e57bSDouglas Gregor unsigned DepID = LM->second.Dependencies[I]; 251*e060e57bSDouglas Gregor LoadedModulesMap::iterator Known = LoadedModules.find(DepID); 252*e060e57bSDouglas Gregor if (Known == LoadedModules.end() || !Known->second.File) { 253*e060e57bSDouglas Gregor // The dependency was out-of-date, so mark us as out of date. 254*e060e57bSDouglas Gregor // This is just an optimization. 255*e060e57bSDouglas Gregor if (LM->second.File) 256*e060e57bSDouglas Gregor Stack.push_back(ID); 257*e060e57bSDouglas Gregor 258*e060e57bSDouglas Gregor LM->second.File = 0; 259*e060e57bSDouglas Gregor continue; 260*e060e57bSDouglas Gregor } 261*e060e57bSDouglas Gregor 262*e060e57bSDouglas Gregor // Record this reverse dependency. 263*e060e57bSDouglas Gregor Known->second.ImportedBy.push_back(ID); 264*e060e57bSDouglas Gregor } 265*e060e57bSDouglas Gregor } 266*e060e57bSDouglas Gregor 267*e060e57bSDouglas Gregor // Second, walk the back links from out-of-date modules to those modules 268*e060e57bSDouglas Gregor // that depend on them, making those modules out-of-date as well. 269*e060e57bSDouglas Gregor while (!Stack.empty()) { 270*e060e57bSDouglas Gregor unsigned ID = Stack.back(); 271*e060e57bSDouglas Gregor Stack.pop_back(); 272*e060e57bSDouglas Gregor 273*e060e57bSDouglas Gregor LoadedModuleInfo &Info = LoadedModules[ID]; 274*e060e57bSDouglas Gregor for (unsigned I = 0, N = Info.ImportedBy.size(); I != N; ++I) { 275*e060e57bSDouglas Gregor unsigned FromID = Info.ImportedBy[I]; 276*e060e57bSDouglas Gregor if (LoadedModules[FromID].File) { 277*e060e57bSDouglas Gregor LoadedModules[FromID].File = 0; 278*e060e57bSDouglas Gregor Stack.push_back(FromID); 279*e060e57bSDouglas Gregor } 280*e060e57bSDouglas Gregor } 281*e060e57bSDouglas Gregor } 282*e060e57bSDouglas Gregor } 283*e060e57bSDouglas Gregor 284*e060e57bSDouglas Gregor // Allocate the vector containing information about all of the modules. 285*e060e57bSDouglas Gregor Modules.resize(LargestID + 1); 286*e060e57bSDouglas Gregor for (LoadedModulesMap::iterator LM = LoadedModules.begin(), 287*e060e57bSDouglas Gregor LMEnd = LoadedModules.end(); 288*e060e57bSDouglas Gregor LM != LMEnd; ++LM) { 289*e060e57bSDouglas Gregor if (!LM->second.File) 290*e060e57bSDouglas Gregor continue; 291*e060e57bSDouglas Gregor 292*e060e57bSDouglas Gregor Modules[LM->first].File = LM->second.File; 293*e060e57bSDouglas Gregor 294*e060e57bSDouglas Gregor // Resolve dependencies. Drop any we can't resolve due to out-of-date 295*e060e57bSDouglas Gregor // module files. 296*e060e57bSDouglas Gregor for (unsigned I = 0, N = LM->second.Dependencies.size(); I != N; ++I) { 297*e060e57bSDouglas Gregor unsigned DepID = LM->second.Dependencies[I]; 298*e060e57bSDouglas Gregor LoadedModulesMap::iterator Known = LoadedModules.find(DepID); 299*e060e57bSDouglas Gregor if (Known == LoadedModules.end() || !Known->second.File) 300*e060e57bSDouglas Gregor continue; 301*e060e57bSDouglas Gregor 302*e060e57bSDouglas Gregor Modules[LM->first].Dependencies.push_back(Known->second.File); 303*e060e57bSDouglas Gregor } 304*e060e57bSDouglas Gregor } 305*e060e57bSDouglas Gregor } 306*e060e57bSDouglas Gregor 307*e060e57bSDouglas Gregor GlobalModuleIndex::~GlobalModuleIndex() { } 308*e060e57bSDouglas Gregor 309*e060e57bSDouglas Gregor std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> 310*e060e57bSDouglas Gregor GlobalModuleIndex::readIndex(FileManager &FileMgr, StringRef Path) { 311*e060e57bSDouglas Gregor // Load the index file, if it's there. 312*e060e57bSDouglas Gregor llvm::SmallString<128> IndexPath; 313*e060e57bSDouglas Gregor IndexPath += Path; 314*e060e57bSDouglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 315*e060e57bSDouglas Gregor 316*e060e57bSDouglas Gregor llvm::OwningPtr<llvm::MemoryBuffer> Buffer( 317*e060e57bSDouglas Gregor FileMgr.getBufferForFile(IndexPath)); 318*e060e57bSDouglas Gregor if (!Buffer) 319*e060e57bSDouglas Gregor return std::make_pair((GlobalModuleIndex *)0, EC_NotFound); 320*e060e57bSDouglas Gregor 321*e060e57bSDouglas Gregor /// \brief The bitstream reader from which we'll read the AST file. 322*e060e57bSDouglas Gregor llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(), 323*e060e57bSDouglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 324*e060e57bSDouglas Gregor 325*e060e57bSDouglas Gregor /// \brief The main bitstream cursor for the main block. 326*e060e57bSDouglas Gregor llvm::BitstreamCursor Cursor(Reader); 327*e060e57bSDouglas Gregor 328*e060e57bSDouglas Gregor // Sniff for the signature. 329*e060e57bSDouglas Gregor if (Cursor.Read(8) != 'B' || 330*e060e57bSDouglas Gregor Cursor.Read(8) != 'C' || 331*e060e57bSDouglas Gregor Cursor.Read(8) != 'G' || 332*e060e57bSDouglas Gregor Cursor.Read(8) != 'I') { 333*e060e57bSDouglas Gregor return std::make_pair((GlobalModuleIndex *)0, EC_IOError); 334*e060e57bSDouglas Gregor } 335*e060e57bSDouglas Gregor 336*e060e57bSDouglas Gregor return std::make_pair(new GlobalModuleIndex(FileMgr, Buffer.take(), Cursor), 337*e060e57bSDouglas Gregor EC_None); 338*e060e57bSDouglas Gregor } 339*e060e57bSDouglas Gregor 340*e060e57bSDouglas Gregor void GlobalModuleIndex::getKnownModules( 341*e060e57bSDouglas Gregor SmallVectorImpl<const FileEntry *> &ModuleFiles) { 342*e060e57bSDouglas Gregor ModuleFiles.clear(); 343*e060e57bSDouglas Gregor for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 344*e060e57bSDouglas Gregor if (Modules[I].File) 345*e060e57bSDouglas Gregor ModuleFiles.push_back(Modules[I].File); 346*e060e57bSDouglas Gregor } 347*e060e57bSDouglas Gregor } 348*e060e57bSDouglas Gregor 349*e060e57bSDouglas Gregor void GlobalModuleIndex::getModuleDependencies( 350*e060e57bSDouglas Gregor const clang::FileEntry *ModuleFile, 351*e060e57bSDouglas Gregor SmallVectorImpl<const clang::FileEntry *> &Dependencies) { 352*e060e57bSDouglas Gregor // If the file -> index mapping is empty, populate it now. 353*e060e57bSDouglas Gregor if (ModulesByFile.empty()) { 354*e060e57bSDouglas Gregor for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 355*e060e57bSDouglas Gregor if (Modules[I].File) 356*e060e57bSDouglas Gregor ModulesByFile[Modules[I].File] = I; 357*e060e57bSDouglas Gregor } 358*e060e57bSDouglas Gregor } 359*e060e57bSDouglas Gregor 360*e060e57bSDouglas Gregor // Look for information about this module file. 361*e060e57bSDouglas Gregor llvm::DenseMap<const FileEntry *, unsigned>::iterator Known 362*e060e57bSDouglas Gregor = ModulesByFile.find(ModuleFile); 363*e060e57bSDouglas Gregor if (Known == ModulesByFile.end()) 364*e060e57bSDouglas Gregor return; 365*e060e57bSDouglas Gregor 366*e060e57bSDouglas Gregor // Record dependencies. 367*e060e57bSDouglas Gregor Dependencies = Modules[Known->second].Dependencies; 368*e060e57bSDouglas Gregor } 369*e060e57bSDouglas Gregor 370*e060e57bSDouglas Gregor bool GlobalModuleIndex::lookupIdentifier( 371*e060e57bSDouglas Gregor StringRef Name, 372*e060e57bSDouglas Gregor SmallVectorImpl<const FileEntry *> &ModuleFiles) { 373*e060e57bSDouglas Gregor ModuleFiles.clear(); 374*e060e57bSDouglas Gregor 375*e060e57bSDouglas Gregor // If there's no identifier index, there is nothing we can do. 376*e060e57bSDouglas Gregor if (!IdentifierIndex) 377*e060e57bSDouglas Gregor return false; 378*e060e57bSDouglas Gregor 379*e060e57bSDouglas Gregor // Look into the identifier index. 380*e060e57bSDouglas Gregor ++NumIdentifierLookups; 381*e060e57bSDouglas Gregor IdentifierIndexTable &Table 382*e060e57bSDouglas Gregor = *static_cast<IdentifierIndexTable *>(IdentifierIndex); 383*e060e57bSDouglas Gregor IdentifierIndexTable::iterator Known = Table.find(Name); 384*e060e57bSDouglas Gregor if (Known == Table.end()) { 385*e060e57bSDouglas Gregor return true; 386*e060e57bSDouglas Gregor } 387*e060e57bSDouglas Gregor 388*e060e57bSDouglas Gregor SmallVector<unsigned, 2> ModuleIDs = *Known; 389*e060e57bSDouglas Gregor for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { 390*e060e57bSDouglas Gregor unsigned ID = ModuleIDs[I]; 391*e060e57bSDouglas Gregor if (ID >= Modules.size() || !Modules[ID].File) 392*e060e57bSDouglas Gregor continue; 393*e060e57bSDouglas Gregor 394*e060e57bSDouglas Gregor ModuleFiles.push_back(Modules[ID].File); 395*e060e57bSDouglas Gregor } 396*e060e57bSDouglas Gregor 397*e060e57bSDouglas Gregor ++NumIdentifierLookupHits; 398*e060e57bSDouglas Gregor return true; 399*e060e57bSDouglas Gregor } 400*e060e57bSDouglas Gregor 401*e060e57bSDouglas Gregor GlobalModuleIndex::SkipSet 402*e060e57bSDouglas Gregor GlobalModuleIndex::computeSkipSet( 403*e060e57bSDouglas Gregor const SmallVectorImpl<const FileEntry *> &ModuleFiles) { 404*e060e57bSDouglas Gregor llvm::SmallPtrSet<const FileEntry *, 8> Found(ModuleFiles.begin(), 405*e060e57bSDouglas Gregor ModuleFiles.end()); 406*e060e57bSDouglas Gregor 407*e060e57bSDouglas Gregor SkipSet Result; 408*e060e57bSDouglas Gregor for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 409*e060e57bSDouglas Gregor if (Modules[I].File && !Found.count(Modules[I].File)) 410*e060e57bSDouglas Gregor Result.insert(Modules[I].File); 411*e060e57bSDouglas Gregor } 412*e060e57bSDouglas Gregor 413*e060e57bSDouglas Gregor NumIdentifierModulesSkipped += Result.size(); 414*e060e57bSDouglas Gregor return Result; 415*e060e57bSDouglas Gregor } 416*e060e57bSDouglas Gregor 417*e060e57bSDouglas Gregor void GlobalModuleIndex::printStats() { 418*e060e57bSDouglas Gregor std::fprintf(stderr, "*** Global Module Index Statistics:\n"); 419*e060e57bSDouglas Gregor if (NumIdentifierLookups) { 420*e060e57bSDouglas Gregor fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n", 421*e060e57bSDouglas Gregor NumIdentifierLookupHits, NumIdentifierLookups, 422*e060e57bSDouglas Gregor (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); 423*e060e57bSDouglas Gregor } 424*e060e57bSDouglas Gregor if (NumIdentifierLookups && NumIdentifierModulesSkipped) { 425*e060e57bSDouglas Gregor fprintf(stderr, " %f modules skipped per lookup (on average)\n", 426*e060e57bSDouglas Gregor (double)NumIdentifierModulesSkipped/NumIdentifierLookups); 427*e060e57bSDouglas Gregor } 428*e060e57bSDouglas Gregor std::fprintf(stderr, "\n"); 429*e060e57bSDouglas Gregor } 430*e060e57bSDouglas Gregor 431*e060e57bSDouglas Gregor //----------------------------------------------------------------------------// 4325e306b12SDouglas Gregor // Global module index writer. 4335e306b12SDouglas Gregor //----------------------------------------------------------------------------// 4345e306b12SDouglas Gregor 4355e306b12SDouglas Gregor namespace { 4365e306b12SDouglas Gregor /// \brief Provides information about a specific module file. 4375e306b12SDouglas Gregor struct ModuleFileInfo { 4385e306b12SDouglas Gregor /// \brief The numberic ID for this module file. 4395e306b12SDouglas Gregor unsigned ID; 4405e306b12SDouglas Gregor 4415e306b12SDouglas Gregor /// \brief The set of modules on which this module depends. Each entry is 4425e306b12SDouglas Gregor /// a module ID. 4435e306b12SDouglas Gregor SmallVector<unsigned, 4> Dependencies; 4445e306b12SDouglas Gregor }; 4455e306b12SDouglas Gregor 4465e306b12SDouglas Gregor /// \brief Builder that generates the global module index file. 4475e306b12SDouglas Gregor class GlobalModuleIndexBuilder { 4485e306b12SDouglas Gregor FileManager &FileMgr; 4495e306b12SDouglas Gregor 4505e306b12SDouglas Gregor /// \brief Mapping from files to module file information. 4515e306b12SDouglas Gregor typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; 4525e306b12SDouglas Gregor 4535e306b12SDouglas Gregor /// \brief Information about each of the known module files. 4545e306b12SDouglas Gregor ModuleFilesMap ModuleFiles; 4555e306b12SDouglas Gregor 4565e306b12SDouglas Gregor /// \brief Mapping from identifiers to the list of module file IDs that 4575e306b12SDouglas Gregor /// consider this identifier to be interesting. 4585e306b12SDouglas Gregor typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; 4595e306b12SDouglas Gregor 4605e306b12SDouglas Gregor /// \brief A mapping from all interesting identifiers to the set of module 4615e306b12SDouglas Gregor /// files in which those identifiers are considered interesting. 4625e306b12SDouglas Gregor InterestingIdentifierMap InterestingIdentifiers; 4635e306b12SDouglas Gregor 4645e306b12SDouglas Gregor /// \brief Write the block-info block for the global module index file. 4655e306b12SDouglas Gregor void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); 4665e306b12SDouglas Gregor 4675e306b12SDouglas Gregor /// \brief Retrieve the module file information for the given file. 4685e306b12SDouglas Gregor ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { 4695e306b12SDouglas Gregor llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known 4705e306b12SDouglas Gregor = ModuleFiles.find(File); 4715e306b12SDouglas Gregor if (Known != ModuleFiles.end()) 4725e306b12SDouglas Gregor return Known->second; 4735e306b12SDouglas Gregor 4745e306b12SDouglas Gregor unsigned NewID = ModuleFiles.size(); 4755e306b12SDouglas Gregor ModuleFileInfo &Info = ModuleFiles[File]; 4765e306b12SDouglas Gregor Info.ID = NewID; 4775e306b12SDouglas Gregor return Info; 4785e306b12SDouglas Gregor } 4795e306b12SDouglas Gregor 4805e306b12SDouglas Gregor public: 4815e306b12SDouglas Gregor explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){} 4825e306b12SDouglas Gregor 4835e306b12SDouglas Gregor /// \brief Load the contents of the given module file into the builder. 4845e306b12SDouglas Gregor /// 4855e306b12SDouglas Gregor /// \returns true if an error occurred, false otherwise. 4865e306b12SDouglas Gregor bool loadModuleFile(const FileEntry *File); 4875e306b12SDouglas Gregor 4885e306b12SDouglas Gregor /// \brief Write the index to the given bitstream. 4895e306b12SDouglas Gregor void writeIndex(llvm::BitstreamWriter &Stream); 4905e306b12SDouglas Gregor }; 4915e306b12SDouglas Gregor } 4925e306b12SDouglas Gregor 4935e306b12SDouglas Gregor static void emitBlockID(unsigned ID, const char *Name, 4945e306b12SDouglas Gregor llvm::BitstreamWriter &Stream, 4955e306b12SDouglas Gregor SmallVectorImpl<uint64_t> &Record) { 4965e306b12SDouglas Gregor Record.clear(); 4975e306b12SDouglas Gregor Record.push_back(ID); 4985e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 4995e306b12SDouglas Gregor 5005e306b12SDouglas Gregor // Emit the block name if present. 5015e306b12SDouglas Gregor if (Name == 0 || Name[0] == 0) return; 5025e306b12SDouglas Gregor Record.clear(); 5035e306b12SDouglas Gregor while (*Name) 5045e306b12SDouglas Gregor Record.push_back(*Name++); 5055e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 5065e306b12SDouglas Gregor } 5075e306b12SDouglas Gregor 5085e306b12SDouglas Gregor static void emitRecordID(unsigned ID, const char *Name, 5095e306b12SDouglas Gregor llvm::BitstreamWriter &Stream, 5105e306b12SDouglas Gregor SmallVectorImpl<uint64_t> &Record) { 5115e306b12SDouglas Gregor Record.clear(); 5125e306b12SDouglas Gregor Record.push_back(ID); 5135e306b12SDouglas Gregor while (*Name) 5145e306b12SDouglas Gregor Record.push_back(*Name++); 5155e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 5165e306b12SDouglas Gregor } 5175e306b12SDouglas Gregor 5185e306b12SDouglas Gregor void 5195e306b12SDouglas Gregor GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { 5205e306b12SDouglas Gregor SmallVector<uint64_t, 64> Record; 5215e306b12SDouglas Gregor Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); 5225e306b12SDouglas Gregor 5235e306b12SDouglas Gregor #define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 5245e306b12SDouglas Gregor #define RECORD(X) emitRecordID(X, #X, Stream, Record) 5255e306b12SDouglas Gregor BLOCK(GLOBAL_INDEX_BLOCK); 526*e060e57bSDouglas Gregor RECORD(INDEX_METADATA); 5275e306b12SDouglas Gregor RECORD(MODULE); 5285e306b12SDouglas Gregor RECORD(IDENTIFIER_INDEX); 5295e306b12SDouglas Gregor #undef RECORD 5305e306b12SDouglas Gregor #undef BLOCK 5315e306b12SDouglas Gregor 5325e306b12SDouglas Gregor Stream.ExitBlock(); 5335e306b12SDouglas Gregor } 5345e306b12SDouglas Gregor 535*e060e57bSDouglas Gregor namespace { 5365e306b12SDouglas Gregor class InterestingASTIdentifierLookupTrait 5375e306b12SDouglas Gregor : public serialization::reader::ASTIdentifierLookupTraitBase { 5385e306b12SDouglas Gregor 5395e306b12SDouglas Gregor public: 5405e306b12SDouglas Gregor /// \brief The identifier and whether it is "interesting". 5415e306b12SDouglas Gregor typedef std::pair<StringRef, bool> data_type; 5425e306b12SDouglas Gregor 5435e306b12SDouglas Gregor data_type ReadData(const internal_key_type& k, 5445e306b12SDouglas Gregor const unsigned char* d, 5455e306b12SDouglas Gregor unsigned DataLen) { 5465e306b12SDouglas Gregor // The first bit indicates whether this identifier is interesting. 5475e306b12SDouglas Gregor // That's all we care about. 5485e306b12SDouglas Gregor using namespace clang::io; 5495e306b12SDouglas Gregor unsigned RawID = ReadUnalignedLE32(d); 5505e306b12SDouglas Gregor bool IsInteresting = RawID & 0x01; 5515e306b12SDouglas Gregor return std::make_pair(k, IsInteresting); 5525e306b12SDouglas Gregor } 5535e306b12SDouglas Gregor }; 5545e306b12SDouglas Gregor } 5555e306b12SDouglas Gregor 5565e306b12SDouglas Gregor bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { 5575e306b12SDouglas Gregor // Open the module file. 5585e306b12SDouglas Gregor OwningPtr<llvm::MemoryBuffer> Buffer; 5595e306b12SDouglas Gregor Buffer.reset(FileMgr.getBufferForFile(File)); 5605e306b12SDouglas Gregor if (!Buffer) { 5615e306b12SDouglas Gregor return true; 5625e306b12SDouglas Gregor } 5635e306b12SDouglas Gregor 5645e306b12SDouglas Gregor // Initialize the input stream 5655e306b12SDouglas Gregor llvm::BitstreamReader InStreamFile; 5665e306b12SDouglas Gregor llvm::BitstreamCursor InStream; 5675e306b12SDouglas Gregor InStreamFile.init((const unsigned char *)Buffer->getBufferStart(), 5685e306b12SDouglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 5695e306b12SDouglas Gregor InStream.init(InStreamFile); 5705e306b12SDouglas Gregor 5715e306b12SDouglas Gregor // Sniff for the signature. 5725e306b12SDouglas Gregor if (InStream.Read(8) != 'C' || 5735e306b12SDouglas Gregor InStream.Read(8) != 'P' || 5745e306b12SDouglas Gregor InStream.Read(8) != 'C' || 5755e306b12SDouglas Gregor InStream.Read(8) != 'H') { 5765e306b12SDouglas Gregor return true; 5775e306b12SDouglas Gregor } 5785e306b12SDouglas Gregor 5795e306b12SDouglas Gregor // Record this module file and assign it a unique ID (if it doesn't have 5805e306b12SDouglas Gregor // one already). 5815e306b12SDouglas Gregor unsigned ID = getModuleFileInfo(File).ID; 5825e306b12SDouglas Gregor 5835e306b12SDouglas Gregor // Search for the blocks and records we care about. 584*e060e57bSDouglas Gregor enum { Other, ControlBlock, ASTBlock } State = Other; 5855e306b12SDouglas Gregor bool Done = false; 5865e306b12SDouglas Gregor while (!Done) { 587*e060e57bSDouglas Gregor llvm::BitstreamEntry Entry = InStream.advance(); 5885e306b12SDouglas Gregor switch (Entry.Kind) { 5895e306b12SDouglas Gregor case llvm::BitstreamEntry::Error: 590*e060e57bSDouglas Gregor Done = true; 591*e060e57bSDouglas Gregor continue; 5925e306b12SDouglas Gregor 5935e306b12SDouglas Gregor case llvm::BitstreamEntry::Record: 594*e060e57bSDouglas Gregor // In the 'other' state, just skip the record. We don't care. 595*e060e57bSDouglas Gregor if (State == Other) { 5965e306b12SDouglas Gregor InStream.skipRecord(Entry.ID); 5975e306b12SDouglas Gregor continue; 5985e306b12SDouglas Gregor } 5995e306b12SDouglas Gregor 6005e306b12SDouglas Gregor // Handle potentially-interesting records below. 6015e306b12SDouglas Gregor break; 6025e306b12SDouglas Gregor 6035e306b12SDouglas Gregor case llvm::BitstreamEntry::SubBlock: 604*e060e57bSDouglas Gregor if (Entry.ID == CONTROL_BLOCK_ID) { 6055e306b12SDouglas Gregor if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) 6065e306b12SDouglas Gregor return true; 6075e306b12SDouglas Gregor 6085e306b12SDouglas Gregor // Found the control block. 6095e306b12SDouglas Gregor State = ControlBlock; 6105e306b12SDouglas Gregor continue; 6115e306b12SDouglas Gregor } 6125e306b12SDouglas Gregor 613*e060e57bSDouglas Gregor if (Entry.ID == AST_BLOCK_ID) { 6145e306b12SDouglas Gregor if (InStream.EnterSubBlock(AST_BLOCK_ID)) 6155e306b12SDouglas Gregor return true; 6165e306b12SDouglas Gregor 6175e306b12SDouglas Gregor // Found the AST block. 6185e306b12SDouglas Gregor State = ASTBlock; 6195e306b12SDouglas Gregor continue; 6205e306b12SDouglas Gregor } 6215e306b12SDouglas Gregor 6225e306b12SDouglas Gregor if (InStream.SkipBlock()) 6235e306b12SDouglas Gregor return true; 6245e306b12SDouglas Gregor 6255e306b12SDouglas Gregor continue; 6265e306b12SDouglas Gregor 6275e306b12SDouglas Gregor case llvm::BitstreamEntry::EndBlock: 628*e060e57bSDouglas Gregor State = Other; 6295e306b12SDouglas Gregor continue; 6305e306b12SDouglas Gregor } 6315e306b12SDouglas Gregor 6325e306b12SDouglas Gregor // Read the given record. 6335e306b12SDouglas Gregor SmallVector<uint64_t, 64> Record; 6345e306b12SDouglas Gregor StringRef Blob; 6355e306b12SDouglas Gregor unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); 6365e306b12SDouglas Gregor 6375e306b12SDouglas Gregor // Handle module dependencies. 6385e306b12SDouglas Gregor if (State == ControlBlock && Code == IMPORTS) { 6395e306b12SDouglas Gregor // Load each of the imported PCH files. 6405e306b12SDouglas Gregor unsigned Idx = 0, N = Record.size(); 6415e306b12SDouglas Gregor while (Idx < N) { 6425e306b12SDouglas Gregor // Read information about the AST file. 6435e306b12SDouglas Gregor 6445e306b12SDouglas Gregor // Skip the imported kind 6455e306b12SDouglas Gregor ++Idx; 6465e306b12SDouglas Gregor 6475e306b12SDouglas Gregor // Skip the import location 6485e306b12SDouglas Gregor ++Idx; 6495e306b12SDouglas Gregor 6505e306b12SDouglas Gregor // Retrieve the imported file name. 6515e306b12SDouglas Gregor unsigned Length = Record[Idx++]; 6525e306b12SDouglas Gregor SmallString<128> ImportedFile(Record.begin() + Idx, 6535e306b12SDouglas Gregor Record.begin() + Idx + Length); 6545e306b12SDouglas Gregor Idx += Length; 6555e306b12SDouglas Gregor 6565e306b12SDouglas Gregor // Find the imported module file. 6575e306b12SDouglas Gregor const FileEntry *DependsOnFile = FileMgr.getFile(ImportedFile); 6585e306b12SDouglas Gregor if (!DependsOnFile) 6595e306b12SDouglas Gregor return true; 6605e306b12SDouglas Gregor 6615e306b12SDouglas Gregor // Record the dependency. 6625e306b12SDouglas Gregor unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; 6635e306b12SDouglas Gregor getModuleFileInfo(File).Dependencies.push_back(DependsOnID); 6645e306b12SDouglas Gregor } 6655e306b12SDouglas Gregor 6665e306b12SDouglas Gregor continue; 6675e306b12SDouglas Gregor } 6685e306b12SDouglas Gregor 6695e306b12SDouglas Gregor // Handle the identifier table 6705e306b12SDouglas Gregor if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { 6715e306b12SDouglas Gregor typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait> 6725e306b12SDouglas Gregor InterestingIdentifierTable; 6735e306b12SDouglas Gregor llvm::OwningPtr<InterestingIdentifierTable> 6745e306b12SDouglas Gregor Table(InterestingIdentifierTable::Create( 6755e306b12SDouglas Gregor (const unsigned char *)Blob.data() + Record[0], 6765e306b12SDouglas Gregor (const unsigned char *)Blob.data())); 6775e306b12SDouglas Gregor for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), 6785e306b12SDouglas Gregor DEnd = Table->data_end(); 6795e306b12SDouglas Gregor D != DEnd; ++D) { 6805e306b12SDouglas Gregor std::pair<StringRef, bool> Ident = *D; 6815e306b12SDouglas Gregor if (Ident.second) 6825e306b12SDouglas Gregor InterestingIdentifiers[Ident.first].push_back(ID); 683*e060e57bSDouglas Gregor else 684*e060e57bSDouglas Gregor (void)InterestingIdentifiers[Ident.first]; 6855e306b12SDouglas Gregor } 6865e306b12SDouglas Gregor } 6875e306b12SDouglas Gregor 6885e306b12SDouglas Gregor // FIXME: Handle the selector table. 6895e306b12SDouglas Gregor 6905e306b12SDouglas Gregor // We don't care about this record. 6915e306b12SDouglas Gregor } 6925e306b12SDouglas Gregor 6935e306b12SDouglas Gregor return false; 6945e306b12SDouglas Gregor } 6955e306b12SDouglas Gregor 6965e306b12SDouglas Gregor namespace { 6975e306b12SDouglas Gregor 6985e306b12SDouglas Gregor /// \brief Trait used to generate the identifier index as an on-disk hash 6995e306b12SDouglas Gregor /// table. 7005e306b12SDouglas Gregor class IdentifierIndexWriterTrait { 7015e306b12SDouglas Gregor public: 7025e306b12SDouglas Gregor typedef StringRef key_type; 7035e306b12SDouglas Gregor typedef StringRef key_type_ref; 7045e306b12SDouglas Gregor typedef SmallVector<unsigned, 2> data_type; 7055e306b12SDouglas Gregor typedef const SmallVector<unsigned, 2> &data_type_ref; 7065e306b12SDouglas Gregor 7075e306b12SDouglas Gregor static unsigned ComputeHash(key_type_ref Key) { 7085e306b12SDouglas Gregor return llvm::HashString(Key); 7095e306b12SDouglas Gregor } 7105e306b12SDouglas Gregor 7115e306b12SDouglas Gregor std::pair<unsigned,unsigned> 7125e306b12SDouglas Gregor EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { 7135e306b12SDouglas Gregor unsigned KeyLen = Key.size(); 7145e306b12SDouglas Gregor unsigned DataLen = Data.size() * 4; 7155e306b12SDouglas Gregor clang::io::Emit16(Out, KeyLen); 7165e306b12SDouglas Gregor clang::io::Emit16(Out, DataLen); 7175e306b12SDouglas Gregor return std::make_pair(KeyLen, DataLen); 7185e306b12SDouglas Gregor } 7195e306b12SDouglas Gregor 7205e306b12SDouglas Gregor void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { 7215e306b12SDouglas Gregor Out.write(Key.data(), KeyLen); 7225e306b12SDouglas Gregor } 7235e306b12SDouglas Gregor 7245e306b12SDouglas Gregor void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, 7255e306b12SDouglas Gregor unsigned DataLen) { 7265e306b12SDouglas Gregor for (unsigned I = 0, N = Data.size(); I != N; ++I) 7275e306b12SDouglas Gregor clang::io::Emit32(Out, Data[I]); 7285e306b12SDouglas Gregor } 7295e306b12SDouglas Gregor }; 7305e306b12SDouglas Gregor 7315e306b12SDouglas Gregor } 7325e306b12SDouglas Gregor 7335e306b12SDouglas Gregor void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { 7345e306b12SDouglas Gregor using namespace llvm; 7355e306b12SDouglas Gregor 7365e306b12SDouglas Gregor // Emit the file header. 7375e306b12SDouglas Gregor Stream.Emit((unsigned)'B', 8); 7385e306b12SDouglas Gregor Stream.Emit((unsigned)'C', 8); 7395e306b12SDouglas Gregor Stream.Emit((unsigned)'G', 8); 7405e306b12SDouglas Gregor Stream.Emit((unsigned)'I', 8); 7415e306b12SDouglas Gregor 7425e306b12SDouglas Gregor // Write the block-info block, which describes the records in this bitcode 7435e306b12SDouglas Gregor // file. 7445e306b12SDouglas Gregor emitBlockInfoBlock(Stream); 7455e306b12SDouglas Gregor 7465e306b12SDouglas Gregor Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); 7475e306b12SDouglas Gregor 7485e306b12SDouglas Gregor // Write the metadata. 7495e306b12SDouglas Gregor SmallVector<uint64_t, 2> Record; 7505e306b12SDouglas Gregor Record.push_back(CurrentVersion); 751*e060e57bSDouglas Gregor Stream.EmitRecord(INDEX_METADATA, Record); 7525e306b12SDouglas Gregor 7535e306b12SDouglas Gregor // Write the set of known module files. 7545e306b12SDouglas Gregor for (ModuleFilesMap::iterator M = ModuleFiles.begin(), 7555e306b12SDouglas Gregor MEnd = ModuleFiles.end(); 7565e306b12SDouglas Gregor M != MEnd; ++M) { 7575e306b12SDouglas Gregor Record.clear(); 7585e306b12SDouglas Gregor Record.push_back(M->second.ID); 7595e306b12SDouglas Gregor Record.push_back(M->first->getSize()); 7605e306b12SDouglas Gregor Record.push_back(M->first->getModificationTime()); 7615e306b12SDouglas Gregor 7625e306b12SDouglas Gregor // File name 7635e306b12SDouglas Gregor StringRef Name(M->first->getName()); 7645e306b12SDouglas Gregor Record.push_back(Name.size()); 7655e306b12SDouglas Gregor Record.append(Name.begin(), Name.end()); 7665e306b12SDouglas Gregor 7675e306b12SDouglas Gregor // Dependencies 7685e306b12SDouglas Gregor Record.push_back(M->second.Dependencies.size()); 7695e306b12SDouglas Gregor Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); 7705e306b12SDouglas Gregor Stream.EmitRecord(MODULE, Record); 7715e306b12SDouglas Gregor } 7725e306b12SDouglas Gregor 7735e306b12SDouglas Gregor // Write the identifier -> module file mapping. 7745e306b12SDouglas Gregor { 7755e306b12SDouglas Gregor OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; 7765e306b12SDouglas Gregor IdentifierIndexWriterTrait Trait; 7775e306b12SDouglas Gregor 7785e306b12SDouglas Gregor // Populate the hash table. 7795e306b12SDouglas Gregor for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), 7805e306b12SDouglas Gregor IEnd = InterestingIdentifiers.end(); 7815e306b12SDouglas Gregor I != IEnd; ++I) { 7825e306b12SDouglas Gregor Generator.insert(I->first(), I->second, Trait); 7835e306b12SDouglas Gregor } 7845e306b12SDouglas Gregor 7855e306b12SDouglas Gregor // Create the on-disk hash table in a buffer. 7865e306b12SDouglas Gregor SmallString<4096> IdentifierTable; 7875e306b12SDouglas Gregor uint32_t BucketOffset; 7885e306b12SDouglas Gregor { 7895e306b12SDouglas Gregor llvm::raw_svector_ostream Out(IdentifierTable); 7905e306b12SDouglas Gregor // Make sure that no bucket is at offset 0 7915e306b12SDouglas Gregor clang::io::Emit32(Out, 0); 7925e306b12SDouglas Gregor BucketOffset = Generator.Emit(Out, Trait); 7935e306b12SDouglas Gregor } 7945e306b12SDouglas Gregor 7955e306b12SDouglas Gregor // Create a blob abbreviation 7965e306b12SDouglas Gregor BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 7975e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); 7985e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 7995e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 8005e306b12SDouglas Gregor unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); 8015e306b12SDouglas Gregor 8025e306b12SDouglas Gregor // Write the identifier table 8035e306b12SDouglas Gregor Record.clear(); 8045e306b12SDouglas Gregor Record.push_back(IDENTIFIER_INDEX); 8055e306b12SDouglas Gregor Record.push_back(BucketOffset); 8065e306b12SDouglas Gregor Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); 8075e306b12SDouglas Gregor } 8085e306b12SDouglas Gregor 8095e306b12SDouglas Gregor // FIXME: Selectors. 8105e306b12SDouglas Gregor 8115e306b12SDouglas Gregor Stream.ExitBlock(); 8125e306b12SDouglas Gregor } 8135e306b12SDouglas Gregor 8145e306b12SDouglas Gregor GlobalModuleIndex::ErrorCode 8155e306b12SDouglas Gregor GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { 8165e306b12SDouglas Gregor llvm::SmallString<128> IndexPath; 8175e306b12SDouglas Gregor IndexPath += Path; 8185e306b12SDouglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 8195e306b12SDouglas Gregor 8205e306b12SDouglas Gregor // Coordinate building the global index file with other processes that might 8215e306b12SDouglas Gregor // try to do the same. 8225e306b12SDouglas Gregor llvm::LockFileManager Locked(IndexPath); 8235e306b12SDouglas Gregor switch (Locked) { 8245e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Error: 8255e306b12SDouglas Gregor return EC_IOError; 8265e306b12SDouglas Gregor 8275e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Owned: 8285e306b12SDouglas Gregor // We're responsible for building the index ourselves. Do so below. 8295e306b12SDouglas Gregor break; 8305e306b12SDouglas Gregor 8315e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Shared: 8325e306b12SDouglas Gregor // Someone else is responsible for building the index. We don't care 8335e306b12SDouglas Gregor // when they finish, so we're done. 8345e306b12SDouglas Gregor return EC_Building; 8355e306b12SDouglas Gregor } 8365e306b12SDouglas Gregor 8375e306b12SDouglas Gregor // The module index builder. 8385e306b12SDouglas Gregor GlobalModuleIndexBuilder Builder(FileMgr); 8395e306b12SDouglas Gregor 8405e306b12SDouglas Gregor // Load each of the module files. 8415e306b12SDouglas Gregor llvm::error_code EC; 8425e306b12SDouglas Gregor for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; 8435e306b12SDouglas Gregor D != DEnd && !EC; 8445e306b12SDouglas Gregor D.increment(EC)) { 8455e306b12SDouglas Gregor // If this isn't a module file, we don't care. 8465e306b12SDouglas Gregor if (llvm::sys::path::extension(D->path()) != ".pcm") { 8475e306b12SDouglas Gregor // ... unless it's a .pcm.lock file, which indicates that someone is 8485e306b12SDouglas Gregor // in the process of rebuilding a module. They'll rebuild the index 8495e306b12SDouglas Gregor // at the end of that translation unit, so we don't have to. 8505e306b12SDouglas Gregor if (llvm::sys::path::extension(D->path()) == ".pcm.lock") 8515e306b12SDouglas Gregor return EC_Building; 8525e306b12SDouglas Gregor 8535e306b12SDouglas Gregor continue; 8545e306b12SDouglas Gregor } 8555e306b12SDouglas Gregor 8565e306b12SDouglas Gregor // If we can't find the module file, skip it. 8575e306b12SDouglas Gregor const FileEntry *ModuleFile = FileMgr.getFile(D->path()); 8585e306b12SDouglas Gregor if (!ModuleFile) 8595e306b12SDouglas Gregor continue; 8605e306b12SDouglas Gregor 8615e306b12SDouglas Gregor // Load this module file. 8625e306b12SDouglas Gregor if (Builder.loadModuleFile(ModuleFile)) 8635e306b12SDouglas Gregor return EC_IOError; 8645e306b12SDouglas Gregor } 8655e306b12SDouglas Gregor 8665e306b12SDouglas Gregor // The output buffer, into which the global index will be written. 8675e306b12SDouglas Gregor SmallVector<char, 16> OutputBuffer; 8685e306b12SDouglas Gregor { 8695e306b12SDouglas Gregor llvm::BitstreamWriter OutputStream(OutputBuffer); 8705e306b12SDouglas Gregor Builder.writeIndex(OutputStream); 8715e306b12SDouglas Gregor } 8725e306b12SDouglas Gregor 8735e306b12SDouglas Gregor // Write the global index file to a temporary file. 8745e306b12SDouglas Gregor llvm::SmallString<128> IndexTmpPath; 8755e306b12SDouglas Gregor int TmpFD; 8765e306b12SDouglas Gregor if (llvm::sys::fs::unique_file(IndexPath + "-%%%%%%%%", TmpFD, IndexTmpPath)) 8775e306b12SDouglas Gregor return EC_IOError; 8785e306b12SDouglas Gregor 8795e306b12SDouglas Gregor // Open the temporary global index file for output. 880e00c9868SNAKAMURA Takumi llvm::raw_fd_ostream Out(TmpFD, true); 8815e306b12SDouglas Gregor if (Out.has_error()) 8825e306b12SDouglas Gregor return EC_IOError; 8835e306b12SDouglas Gregor 8845e306b12SDouglas Gregor // Write the index. 8855e306b12SDouglas Gregor Out.write(OutputBuffer.data(), OutputBuffer.size()); 8865e306b12SDouglas Gregor Out.close(); 8875e306b12SDouglas Gregor if (Out.has_error()) 8885e306b12SDouglas Gregor return EC_IOError; 8895e306b12SDouglas Gregor 8905e306b12SDouglas Gregor // Remove the old index file. It isn't relevant any more. 8915e306b12SDouglas Gregor bool OldIndexExisted; 8925e306b12SDouglas Gregor llvm::sys::fs::remove(IndexPath.str(), OldIndexExisted); 8935e306b12SDouglas Gregor 8945e306b12SDouglas Gregor // Rename the newly-written index file to the proper name. 8955e306b12SDouglas Gregor if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { 8965e306b12SDouglas Gregor // Rename failed; just remove the 8975e306b12SDouglas Gregor llvm::sys::fs::remove(IndexTmpPath.str(), OldIndexExisted); 8985e306b12SDouglas Gregor return EC_IOError; 8995e306b12SDouglas Gregor } 9005e306b12SDouglas Gregor 9015e306b12SDouglas Gregor // We're done. 9025e306b12SDouglas Gregor return EC_None; 9035e306b12SDouglas Gregor } 904