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" 25*8ec343ccSDouglas 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. 455e306b12SDouglas Gregor 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 //----------------------------------------------------------------------------// 605e306b12SDouglas Gregor // Global module index writer. 615e306b12SDouglas Gregor //----------------------------------------------------------------------------// 625e306b12SDouglas Gregor 635e306b12SDouglas Gregor namespace { 645e306b12SDouglas Gregor /// \brief Provides information about a specific module file. 655e306b12SDouglas Gregor struct ModuleFileInfo { 665e306b12SDouglas Gregor /// \brief The numberic ID for this module file. 675e306b12SDouglas Gregor unsigned ID; 685e306b12SDouglas Gregor 695e306b12SDouglas Gregor /// \brief The set of modules on which this module depends. Each entry is 705e306b12SDouglas Gregor /// a module ID. 715e306b12SDouglas Gregor SmallVector<unsigned, 4> Dependencies; 725e306b12SDouglas Gregor }; 735e306b12SDouglas Gregor 745e306b12SDouglas Gregor /// \brief Builder that generates the global module index file. 755e306b12SDouglas Gregor class GlobalModuleIndexBuilder { 765e306b12SDouglas Gregor FileManager &FileMgr; 775e306b12SDouglas Gregor 785e306b12SDouglas Gregor /// \brief Mapping from files to module file information. 795e306b12SDouglas Gregor typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; 805e306b12SDouglas Gregor 815e306b12SDouglas Gregor /// \brief Information about each of the known module files. 825e306b12SDouglas Gregor ModuleFilesMap ModuleFiles; 835e306b12SDouglas Gregor 845e306b12SDouglas Gregor /// \brief Mapping from identifiers to the list of module file IDs that 855e306b12SDouglas Gregor /// consider this identifier to be interesting. 865e306b12SDouglas Gregor typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; 875e306b12SDouglas Gregor 885e306b12SDouglas Gregor /// \brief A mapping from all interesting identifiers to the set of module 895e306b12SDouglas Gregor /// files in which those identifiers are considered interesting. 905e306b12SDouglas Gregor InterestingIdentifierMap InterestingIdentifiers; 915e306b12SDouglas Gregor 925e306b12SDouglas Gregor /// \brief Write the block-info block for the global module index file. 935e306b12SDouglas Gregor void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); 945e306b12SDouglas Gregor 955e306b12SDouglas Gregor /// \brief Retrieve the module file information for the given file. 965e306b12SDouglas Gregor ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { 975e306b12SDouglas Gregor llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known 985e306b12SDouglas Gregor = ModuleFiles.find(File); 995e306b12SDouglas Gregor if (Known != ModuleFiles.end()) 1005e306b12SDouglas Gregor return Known->second; 1015e306b12SDouglas Gregor 1025e306b12SDouglas Gregor unsigned NewID = ModuleFiles.size(); 1035e306b12SDouglas Gregor ModuleFileInfo &Info = ModuleFiles[File]; 1045e306b12SDouglas Gregor Info.ID = NewID; 1055e306b12SDouglas Gregor return Info; 1065e306b12SDouglas Gregor } 1075e306b12SDouglas Gregor 1085e306b12SDouglas Gregor public: 1095e306b12SDouglas Gregor explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){} 1105e306b12SDouglas Gregor 1115e306b12SDouglas Gregor /// \brief Load the contents of the given module file into the builder. 1125e306b12SDouglas Gregor /// 1135e306b12SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1145e306b12SDouglas Gregor bool loadModuleFile(const FileEntry *File); 1155e306b12SDouglas Gregor 1165e306b12SDouglas Gregor /// \brief Write the index to the given bitstream. 1175e306b12SDouglas Gregor void writeIndex(llvm::BitstreamWriter &Stream); 1185e306b12SDouglas Gregor }; 1195e306b12SDouglas Gregor } 1205e306b12SDouglas Gregor 1215e306b12SDouglas Gregor static void emitBlockID(unsigned ID, const char *Name, 1225e306b12SDouglas Gregor llvm::BitstreamWriter &Stream, 1235e306b12SDouglas Gregor SmallVectorImpl<uint64_t> &Record) { 1245e306b12SDouglas Gregor Record.clear(); 1255e306b12SDouglas Gregor Record.push_back(ID); 1265e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 1275e306b12SDouglas Gregor 1285e306b12SDouglas Gregor // Emit the block name if present. 1295e306b12SDouglas Gregor if (Name == 0 || Name[0] == 0) return; 1305e306b12SDouglas Gregor Record.clear(); 1315e306b12SDouglas Gregor while (*Name) 1325e306b12SDouglas Gregor Record.push_back(*Name++); 1335e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 1345e306b12SDouglas Gregor } 1355e306b12SDouglas Gregor 1365e306b12SDouglas Gregor static void emitRecordID(unsigned ID, const char *Name, 1375e306b12SDouglas Gregor llvm::BitstreamWriter &Stream, 1385e306b12SDouglas Gregor SmallVectorImpl<uint64_t> &Record) { 1395e306b12SDouglas Gregor Record.clear(); 1405e306b12SDouglas Gregor Record.push_back(ID); 1415e306b12SDouglas Gregor while (*Name) 1425e306b12SDouglas Gregor Record.push_back(*Name++); 1435e306b12SDouglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 1445e306b12SDouglas Gregor } 1455e306b12SDouglas Gregor 1465e306b12SDouglas Gregor void 1475e306b12SDouglas Gregor GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { 1485e306b12SDouglas Gregor SmallVector<uint64_t, 64> Record; 1495e306b12SDouglas Gregor Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); 1505e306b12SDouglas Gregor 1515e306b12SDouglas Gregor #define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 1525e306b12SDouglas Gregor #define RECORD(X) emitRecordID(X, #X, Stream, Record) 1535e306b12SDouglas Gregor BLOCK(GLOBAL_INDEX_BLOCK); 1545e306b12SDouglas Gregor RECORD(METADATA); 1555e306b12SDouglas Gregor RECORD(MODULE); 1565e306b12SDouglas Gregor RECORD(IDENTIFIER_INDEX); 1575e306b12SDouglas Gregor #undef RECORD 1585e306b12SDouglas Gregor #undef BLOCK 1595e306b12SDouglas Gregor 1605e306b12SDouglas Gregor Stream.ExitBlock(); 1615e306b12SDouglas Gregor } 1625e306b12SDouglas Gregor 1635e306b12SDouglas Gregor namespace clang { 1645e306b12SDouglas Gregor class InterestingASTIdentifierLookupTrait 1655e306b12SDouglas Gregor : public serialization::reader::ASTIdentifierLookupTraitBase { 1665e306b12SDouglas Gregor 1675e306b12SDouglas Gregor public: 1685e306b12SDouglas Gregor /// \brief The identifier and whether it is "interesting". 1695e306b12SDouglas Gregor typedef std::pair<StringRef, bool> data_type; 1705e306b12SDouglas Gregor 1715e306b12SDouglas Gregor data_type ReadData(const internal_key_type& k, 1725e306b12SDouglas Gregor const unsigned char* d, 1735e306b12SDouglas Gregor unsigned DataLen) { 1745e306b12SDouglas Gregor // The first bit indicates whether this identifier is interesting. 1755e306b12SDouglas Gregor // That's all we care about. 1765e306b12SDouglas Gregor using namespace clang::io; 1775e306b12SDouglas Gregor unsigned RawID = ReadUnalignedLE32(d); 1785e306b12SDouglas Gregor bool IsInteresting = RawID & 0x01; 1795e306b12SDouglas Gregor return std::make_pair(k, IsInteresting); 1805e306b12SDouglas Gregor } 1815e306b12SDouglas Gregor }; 1825e306b12SDouglas Gregor } 1835e306b12SDouglas Gregor 1845e306b12SDouglas Gregor bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { 1855e306b12SDouglas Gregor // Open the module file. 1865e306b12SDouglas Gregor OwningPtr<llvm::MemoryBuffer> Buffer; 1875e306b12SDouglas Gregor Buffer.reset(FileMgr.getBufferForFile(File)); 1885e306b12SDouglas Gregor if (!Buffer) { 1895e306b12SDouglas Gregor return true; 1905e306b12SDouglas Gregor } 1915e306b12SDouglas Gregor 1925e306b12SDouglas Gregor // Initialize the input stream 1935e306b12SDouglas Gregor llvm::BitstreamReader InStreamFile; 1945e306b12SDouglas Gregor llvm::BitstreamCursor InStream; 1955e306b12SDouglas Gregor InStreamFile.init((const unsigned char *)Buffer->getBufferStart(), 1965e306b12SDouglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 1975e306b12SDouglas Gregor InStream.init(InStreamFile); 1985e306b12SDouglas Gregor 1995e306b12SDouglas Gregor // Sniff for the signature. 2005e306b12SDouglas Gregor if (InStream.Read(8) != 'C' || 2015e306b12SDouglas Gregor InStream.Read(8) != 'P' || 2025e306b12SDouglas Gregor InStream.Read(8) != 'C' || 2035e306b12SDouglas Gregor InStream.Read(8) != 'H') { 2045e306b12SDouglas Gregor return true; 2055e306b12SDouglas Gregor } 2065e306b12SDouglas Gregor 2075e306b12SDouglas Gregor // Record this module file and assign it a unique ID (if it doesn't have 2085e306b12SDouglas Gregor // one already). 2095e306b12SDouglas Gregor unsigned ID = getModuleFileInfo(File).ID; 2105e306b12SDouglas Gregor 2115e306b12SDouglas Gregor // Search for the blocks and records we care about. 2125e306b12SDouglas Gregor enum { Outer, ControlBlock, ASTBlock } State = Outer; 2135e306b12SDouglas Gregor bool Done = false; 2145e306b12SDouglas Gregor while (!Done) { 2155e306b12SDouglas Gregor const unsigned Flags = llvm::BitstreamCursor::AF_DontPopBlockAtEnd; 2165e306b12SDouglas Gregor llvm::BitstreamEntry Entry = InStream.advance(Flags); 2175e306b12SDouglas Gregor switch (Entry.Kind) { 2185e306b12SDouglas Gregor case llvm::BitstreamEntry::Error: 2195e306b12SDouglas Gregor return true; 2205e306b12SDouglas Gregor 2215e306b12SDouglas Gregor case llvm::BitstreamEntry::Record: 2225e306b12SDouglas Gregor // In the outer state, just skip the record. We don't care. 2235e306b12SDouglas Gregor if (State == Outer) { 2245e306b12SDouglas Gregor InStream.skipRecord(Entry.ID); 2255e306b12SDouglas Gregor continue; 2265e306b12SDouglas Gregor } 2275e306b12SDouglas Gregor 2285e306b12SDouglas Gregor // Handle potentially-interesting records below. 2295e306b12SDouglas Gregor break; 2305e306b12SDouglas Gregor 2315e306b12SDouglas Gregor case llvm::BitstreamEntry::SubBlock: 2325e306b12SDouglas Gregor if (State == Outer && Entry.ID == CONTROL_BLOCK_ID) { 2335e306b12SDouglas Gregor if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) 2345e306b12SDouglas Gregor return true; 2355e306b12SDouglas Gregor 2365e306b12SDouglas Gregor // Found the control block. 2375e306b12SDouglas Gregor State = ControlBlock; 2385e306b12SDouglas Gregor continue; 2395e306b12SDouglas Gregor } 2405e306b12SDouglas Gregor 2415e306b12SDouglas Gregor if (State == Outer && Entry.ID == AST_BLOCK_ID) { 2425e306b12SDouglas Gregor if (InStream.EnterSubBlock(AST_BLOCK_ID)) 2435e306b12SDouglas Gregor return true; 2445e306b12SDouglas Gregor 2455e306b12SDouglas Gregor // Found the AST block. 2465e306b12SDouglas Gregor State = ASTBlock; 2475e306b12SDouglas Gregor continue; 2485e306b12SDouglas Gregor 2495e306b12SDouglas Gregor } 2505e306b12SDouglas Gregor 2515e306b12SDouglas Gregor if (InStream.SkipBlock()) 2525e306b12SDouglas Gregor return true; 2535e306b12SDouglas Gregor 2545e306b12SDouglas Gregor continue; 2555e306b12SDouglas Gregor 2565e306b12SDouglas Gregor case llvm::BitstreamEntry::EndBlock: 2575e306b12SDouglas Gregor if (State == Outer) { 2585e306b12SDouglas Gregor Done = true; 2595e306b12SDouglas Gregor } 2605e306b12SDouglas Gregor State = Outer; 2615e306b12SDouglas Gregor continue; 2625e306b12SDouglas Gregor } 2635e306b12SDouglas Gregor 2645e306b12SDouglas Gregor // Read the given record. 2655e306b12SDouglas Gregor SmallVector<uint64_t, 64> Record; 2665e306b12SDouglas Gregor StringRef Blob; 2675e306b12SDouglas Gregor unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); 2685e306b12SDouglas Gregor 2695e306b12SDouglas Gregor // Handle module dependencies. 2705e306b12SDouglas Gregor if (State == ControlBlock && Code == IMPORTS) { 2715e306b12SDouglas Gregor // Load each of the imported PCH files. 2725e306b12SDouglas Gregor unsigned Idx = 0, N = Record.size(); 2735e306b12SDouglas Gregor while (Idx < N) { 2745e306b12SDouglas Gregor // Read information about the AST file. 2755e306b12SDouglas Gregor 2765e306b12SDouglas Gregor // Skip the imported kind 2775e306b12SDouglas Gregor ++Idx; 2785e306b12SDouglas Gregor 2795e306b12SDouglas Gregor // Skip the import location 2805e306b12SDouglas Gregor ++Idx; 2815e306b12SDouglas Gregor 2825e306b12SDouglas Gregor // Retrieve the imported file name. 2835e306b12SDouglas Gregor unsigned Length = Record[Idx++]; 2845e306b12SDouglas Gregor SmallString<128> ImportedFile(Record.begin() + Idx, 2855e306b12SDouglas Gregor Record.begin() + Idx + Length); 2865e306b12SDouglas Gregor Idx += Length; 2875e306b12SDouglas Gregor 2885e306b12SDouglas Gregor // Find the imported module file. 2895e306b12SDouglas Gregor const FileEntry *DependsOnFile = FileMgr.getFile(ImportedFile); 2905e306b12SDouglas Gregor if (!DependsOnFile) 2915e306b12SDouglas Gregor return true; 2925e306b12SDouglas Gregor 2935e306b12SDouglas Gregor // Record the dependency. 2945e306b12SDouglas Gregor unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; 2955e306b12SDouglas Gregor getModuleFileInfo(File).Dependencies.push_back(DependsOnID); 2965e306b12SDouglas Gregor } 2975e306b12SDouglas Gregor 2985e306b12SDouglas Gregor continue; 2995e306b12SDouglas Gregor } 3005e306b12SDouglas Gregor 3015e306b12SDouglas Gregor // Handle the identifier table 3025e306b12SDouglas Gregor if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { 3035e306b12SDouglas Gregor typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait> 3045e306b12SDouglas Gregor InterestingIdentifierTable; 3055e306b12SDouglas Gregor llvm::OwningPtr<InterestingIdentifierTable> 3065e306b12SDouglas Gregor Table(InterestingIdentifierTable::Create( 3075e306b12SDouglas Gregor (const unsigned char *)Blob.data() + Record[0], 3085e306b12SDouglas Gregor (const unsigned char *)Blob.data())); 3095e306b12SDouglas Gregor for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), 3105e306b12SDouglas Gregor DEnd = Table->data_end(); 3115e306b12SDouglas Gregor D != DEnd; ++D) { 3125e306b12SDouglas Gregor std::pair<StringRef, bool> Ident = *D; 3135e306b12SDouglas Gregor if (Ident.second) 3145e306b12SDouglas Gregor InterestingIdentifiers[Ident.first].push_back(ID); 3155e306b12SDouglas Gregor } 3165e306b12SDouglas Gregor } 3175e306b12SDouglas Gregor 3185e306b12SDouglas Gregor // FIXME: Handle the selector table. 3195e306b12SDouglas Gregor 3205e306b12SDouglas Gregor // We don't care about this record. 3215e306b12SDouglas Gregor } 3225e306b12SDouglas Gregor 3235e306b12SDouglas Gregor return false; 3245e306b12SDouglas Gregor } 3255e306b12SDouglas Gregor 3265e306b12SDouglas Gregor namespace { 3275e306b12SDouglas Gregor 3285e306b12SDouglas Gregor /// \brief Trait used to generate the identifier index as an on-disk hash 3295e306b12SDouglas Gregor /// table. 3305e306b12SDouglas Gregor class IdentifierIndexWriterTrait { 3315e306b12SDouglas Gregor public: 3325e306b12SDouglas Gregor typedef StringRef key_type; 3335e306b12SDouglas Gregor typedef StringRef key_type_ref; 3345e306b12SDouglas Gregor typedef SmallVector<unsigned, 2> data_type; 3355e306b12SDouglas Gregor typedef const SmallVector<unsigned, 2> &data_type_ref; 3365e306b12SDouglas Gregor 3375e306b12SDouglas Gregor static unsigned ComputeHash(key_type_ref Key) { 3385e306b12SDouglas Gregor return llvm::HashString(Key); 3395e306b12SDouglas Gregor } 3405e306b12SDouglas Gregor 3415e306b12SDouglas Gregor std::pair<unsigned,unsigned> 3425e306b12SDouglas Gregor EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { 3435e306b12SDouglas Gregor unsigned KeyLen = Key.size(); 3445e306b12SDouglas Gregor unsigned DataLen = Data.size() * 4; 3455e306b12SDouglas Gregor clang::io::Emit16(Out, KeyLen); 3465e306b12SDouglas Gregor clang::io::Emit16(Out, DataLen); 3475e306b12SDouglas Gregor return std::make_pair(KeyLen, DataLen); 3485e306b12SDouglas Gregor } 3495e306b12SDouglas Gregor 3505e306b12SDouglas Gregor void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { 3515e306b12SDouglas Gregor Out.write(Key.data(), KeyLen); 3525e306b12SDouglas Gregor } 3535e306b12SDouglas Gregor 3545e306b12SDouglas Gregor void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, 3555e306b12SDouglas Gregor unsigned DataLen) { 3565e306b12SDouglas Gregor for (unsigned I = 0, N = Data.size(); I != N; ++I) 3575e306b12SDouglas Gregor clang::io::Emit32(Out, Data[I]); 3585e306b12SDouglas Gregor } 3595e306b12SDouglas Gregor }; 3605e306b12SDouglas Gregor 3615e306b12SDouglas Gregor } 3625e306b12SDouglas Gregor 3635e306b12SDouglas Gregor void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { 3645e306b12SDouglas Gregor using namespace llvm; 3655e306b12SDouglas Gregor 3665e306b12SDouglas Gregor // Emit the file header. 3675e306b12SDouglas Gregor Stream.Emit((unsigned)'B', 8); 3685e306b12SDouglas Gregor Stream.Emit((unsigned)'C', 8); 3695e306b12SDouglas Gregor Stream.Emit((unsigned)'G', 8); 3705e306b12SDouglas Gregor Stream.Emit((unsigned)'I', 8); 3715e306b12SDouglas Gregor 3725e306b12SDouglas Gregor // Write the block-info block, which describes the records in this bitcode 3735e306b12SDouglas Gregor // file. 3745e306b12SDouglas Gregor emitBlockInfoBlock(Stream); 3755e306b12SDouglas Gregor 3765e306b12SDouglas Gregor Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); 3775e306b12SDouglas Gregor 3785e306b12SDouglas Gregor // Write the metadata. 3795e306b12SDouglas Gregor SmallVector<uint64_t, 2> Record; 3805e306b12SDouglas Gregor Record.push_back(CurrentVersion); 3815e306b12SDouglas Gregor Stream.EmitRecord(METADATA, Record); 3825e306b12SDouglas Gregor 3835e306b12SDouglas Gregor // Write the set of known module files. 3845e306b12SDouglas Gregor for (ModuleFilesMap::iterator M = ModuleFiles.begin(), 3855e306b12SDouglas Gregor MEnd = ModuleFiles.end(); 3865e306b12SDouglas Gregor M != MEnd; ++M) { 3875e306b12SDouglas Gregor Record.clear(); 3885e306b12SDouglas Gregor Record.push_back(M->second.ID); 3895e306b12SDouglas Gregor Record.push_back(M->first->getSize()); 3905e306b12SDouglas Gregor Record.push_back(M->first->getModificationTime()); 3915e306b12SDouglas Gregor 3925e306b12SDouglas Gregor // File name 3935e306b12SDouglas Gregor StringRef Name(M->first->getName()); 3945e306b12SDouglas Gregor Record.push_back(Name.size()); 3955e306b12SDouglas Gregor Record.append(Name.begin(), Name.end()); 3965e306b12SDouglas Gregor 3975e306b12SDouglas Gregor // Dependencies 3985e306b12SDouglas Gregor Record.push_back(M->second.Dependencies.size()); 3995e306b12SDouglas Gregor Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); 4005e306b12SDouglas Gregor Stream.EmitRecord(MODULE, Record); 4015e306b12SDouglas Gregor } 4025e306b12SDouglas Gregor 4035e306b12SDouglas Gregor // Write the identifier -> module file mapping. 4045e306b12SDouglas Gregor { 4055e306b12SDouglas Gregor OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; 4065e306b12SDouglas Gregor IdentifierIndexWriterTrait Trait; 4075e306b12SDouglas Gregor 4085e306b12SDouglas Gregor // Populate the hash table. 4095e306b12SDouglas Gregor for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), 4105e306b12SDouglas Gregor IEnd = InterestingIdentifiers.end(); 4115e306b12SDouglas Gregor I != IEnd; ++I) { 4125e306b12SDouglas Gregor Generator.insert(I->first(), I->second, Trait); 4135e306b12SDouglas Gregor } 4145e306b12SDouglas Gregor 4155e306b12SDouglas Gregor // Create the on-disk hash table in a buffer. 4165e306b12SDouglas Gregor SmallString<4096> IdentifierTable; 4175e306b12SDouglas Gregor uint32_t BucketOffset; 4185e306b12SDouglas Gregor { 4195e306b12SDouglas Gregor llvm::raw_svector_ostream Out(IdentifierTable); 4205e306b12SDouglas Gregor // Make sure that no bucket is at offset 0 4215e306b12SDouglas Gregor clang::io::Emit32(Out, 0); 4225e306b12SDouglas Gregor BucketOffset = Generator.Emit(Out, Trait); 4235e306b12SDouglas Gregor } 4245e306b12SDouglas Gregor 4255e306b12SDouglas Gregor // Create a blob abbreviation 4265e306b12SDouglas Gregor BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 4275e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); 4285e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 4295e306b12SDouglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 4305e306b12SDouglas Gregor unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); 4315e306b12SDouglas Gregor 4325e306b12SDouglas Gregor // Write the identifier table 4335e306b12SDouglas Gregor Record.clear(); 4345e306b12SDouglas Gregor Record.push_back(IDENTIFIER_INDEX); 4355e306b12SDouglas Gregor Record.push_back(BucketOffset); 4365e306b12SDouglas Gregor Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); 4375e306b12SDouglas Gregor } 4385e306b12SDouglas Gregor 4395e306b12SDouglas Gregor // FIXME: Selectors. 4405e306b12SDouglas Gregor 4415e306b12SDouglas Gregor Stream.ExitBlock(); 4425e306b12SDouglas Gregor } 4435e306b12SDouglas Gregor 4445e306b12SDouglas Gregor GlobalModuleIndex::ErrorCode 4455e306b12SDouglas Gregor GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { 4465e306b12SDouglas Gregor llvm::SmallString<128> IndexPath; 4475e306b12SDouglas Gregor IndexPath += Path; 4485e306b12SDouglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 4495e306b12SDouglas Gregor 4505e306b12SDouglas Gregor // Coordinate building the global index file with other processes that might 4515e306b12SDouglas Gregor // try to do the same. 4525e306b12SDouglas Gregor llvm::LockFileManager Locked(IndexPath); 4535e306b12SDouglas Gregor switch (Locked) { 4545e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Error: 4555e306b12SDouglas Gregor return EC_IOError; 4565e306b12SDouglas Gregor 4575e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Owned: 4585e306b12SDouglas Gregor // We're responsible for building the index ourselves. Do so below. 4595e306b12SDouglas Gregor break; 4605e306b12SDouglas Gregor 4615e306b12SDouglas Gregor case llvm::LockFileManager::LFS_Shared: 4625e306b12SDouglas Gregor // Someone else is responsible for building the index. We don't care 4635e306b12SDouglas Gregor // when they finish, so we're done. 4645e306b12SDouglas Gregor return EC_Building; 4655e306b12SDouglas Gregor } 4665e306b12SDouglas Gregor 4675e306b12SDouglas Gregor // The module index builder. 4685e306b12SDouglas Gregor GlobalModuleIndexBuilder Builder(FileMgr); 4695e306b12SDouglas Gregor 4705e306b12SDouglas Gregor // Load each of the module files. 4715e306b12SDouglas Gregor llvm::error_code EC; 4725e306b12SDouglas Gregor for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; 4735e306b12SDouglas Gregor D != DEnd && !EC; 4745e306b12SDouglas Gregor D.increment(EC)) { 4755e306b12SDouglas Gregor // If this isn't a module file, we don't care. 4765e306b12SDouglas Gregor if (llvm::sys::path::extension(D->path()) != ".pcm") { 4775e306b12SDouglas Gregor // ... unless it's a .pcm.lock file, which indicates that someone is 4785e306b12SDouglas Gregor // in the process of rebuilding a module. They'll rebuild the index 4795e306b12SDouglas Gregor // at the end of that translation unit, so we don't have to. 4805e306b12SDouglas Gregor if (llvm::sys::path::extension(D->path()) == ".pcm.lock") 4815e306b12SDouglas Gregor return EC_Building; 4825e306b12SDouglas Gregor 4835e306b12SDouglas Gregor continue; 4845e306b12SDouglas Gregor } 4855e306b12SDouglas Gregor 4865e306b12SDouglas Gregor // If we can't find the module file, skip it. 4875e306b12SDouglas Gregor const FileEntry *ModuleFile = FileMgr.getFile(D->path()); 4885e306b12SDouglas Gregor if (!ModuleFile) 4895e306b12SDouglas Gregor continue; 4905e306b12SDouglas Gregor 4915e306b12SDouglas Gregor // Load this module file. 4925e306b12SDouglas Gregor if (Builder.loadModuleFile(ModuleFile)) 4935e306b12SDouglas Gregor return EC_IOError; 4945e306b12SDouglas Gregor } 4955e306b12SDouglas Gregor 4965e306b12SDouglas Gregor // The output buffer, into which the global index will be written. 4975e306b12SDouglas Gregor SmallVector<char, 16> OutputBuffer; 4985e306b12SDouglas Gregor { 4995e306b12SDouglas Gregor llvm::BitstreamWriter OutputStream(OutputBuffer); 5005e306b12SDouglas Gregor Builder.writeIndex(OutputStream); 5015e306b12SDouglas Gregor } 5025e306b12SDouglas Gregor 5035e306b12SDouglas Gregor // Write the global index file to a temporary file. 5045e306b12SDouglas Gregor llvm::SmallString<128> IndexTmpPath; 5055e306b12SDouglas Gregor int TmpFD; 5065e306b12SDouglas Gregor if (llvm::sys::fs::unique_file(IndexPath + "-%%%%%%%%", TmpFD, IndexTmpPath)) 5075e306b12SDouglas Gregor return EC_IOError; 5085e306b12SDouglas Gregor 5095e306b12SDouglas Gregor // Open the temporary global index file for output. 5105e306b12SDouglas Gregor std::string ErrorInfo; 5115e306b12SDouglas Gregor llvm::raw_fd_ostream Out(IndexTmpPath.c_str(), ErrorInfo, 5125e306b12SDouglas Gregor llvm::raw_fd_ostream::F_Binary); 5135e306b12SDouglas Gregor if (Out.has_error()) 5145e306b12SDouglas Gregor return EC_IOError; 5155e306b12SDouglas Gregor 5165e306b12SDouglas Gregor // Write the index. 5175e306b12SDouglas Gregor Out.write(OutputBuffer.data(), OutputBuffer.size()); 5185e306b12SDouglas Gregor Out.close(); 5195e306b12SDouglas Gregor if (Out.has_error()) 5205e306b12SDouglas Gregor return EC_IOError; 5215e306b12SDouglas Gregor 5225e306b12SDouglas Gregor // Remove the old index file. It isn't relevant any more. 5235e306b12SDouglas Gregor bool OldIndexExisted; 5245e306b12SDouglas Gregor llvm::sys::fs::remove(IndexPath.str(), OldIndexExisted); 5255e306b12SDouglas Gregor 5265e306b12SDouglas Gregor // Rename the newly-written index file to the proper name. 5275e306b12SDouglas Gregor if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { 5285e306b12SDouglas Gregor // Rename failed; just remove the 5295e306b12SDouglas Gregor llvm::sys::fs::remove(IndexTmpPath.str(), OldIndexExisted); 5305e306b12SDouglas Gregor return EC_IOError; 5315e306b12SDouglas Gregor } 5325e306b12SDouglas Gregor 5335e306b12SDouglas Gregor // We're done. 5345e306b12SDouglas Gregor return EC_None; 5355e306b12SDouglas Gregor } 536