GlobalModuleIndex.cpp revision 4967a710c84587c654b56c828382219c3937dacb
1a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//===--- GlobalModuleIndex.cpp - Global Module Index ------------*- C++ -*-===// 2a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// 3a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// The LLVM Compiler Infrastructure 4a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// 5a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// This file is distributed under the University of Illinois Open Source 6a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// License. See LICENSE.TXT for details. 7a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// 8a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//===----------------------------------------------------------------------===// 9a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// 10a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// This file implements the GlobalModuleIndex class. 11a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// 12a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//===----------------------------------------------------------------------===// 13a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 14a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "ASTReaderInternals.h" 1587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar#include "clang/Frontend/PCHContainerOperations.h" 16a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Basic/FileManager.h" 176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Lex/HeaderSearch.h" 18a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Serialization/ASTBitCodes.h" 19a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Serialization/GlobalModuleIndex.h" 20fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor#include "clang/Serialization/Module.h" 21a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/DenseMap.h" 22a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/MapVector.h" 23a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/SmallString.h" 24a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/StringExtras.h" 25a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Bitcode/BitstreamReader.h" 26a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Bitcode/BitstreamWriter.h" 275100135ecf29d4246e6bd34318da9eb22c16b86aDouglas Gregor#include "llvm/Support/FileSystem.h" 28a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Support/LockFileManager.h" 29a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Support/MemoryBuffer.h" 306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/Support/OnDiskHashTable.h" 318229d22e6449851b89361bf2f41804557328be63Rafael Espindola#include "llvm/Support/Path.h" 321d32133b44487d9e98412e373d693416b05920bbNAKAMURA Takumi#include <cstdio> 33a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing namespace clang; 34a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing namespace serialization; 35a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 36a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 37a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// Shared constants 38a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 39a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace { 40a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor enum { 41a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The block containing the index. 42a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID 43a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 44a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 45a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Describes the record types in the index. 46a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor enum IndexRecordTypes { 47a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Contains version information and potentially other metadata, 48a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// used to determine if we can read this global index file. 491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor INDEX_METADATA, 50a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Describes a module, including its file name and dependencies. 51a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor MODULE, 52a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The index for identifiers. 53a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IDENTIFIER_INDEX 54a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 55a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 56a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 57a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief The name of the global index file. 58a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic const char * const IndexFileName = "modules.idx"; 59a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 60a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief The global index file version. 61a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic const unsigned CurrentVersion = 1; 62a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 63a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor// Global module index reader. 651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor//----------------------------------------------------------------------------// 661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 671a49d97d762570027863e9209af81d445e4f1502Douglas Gregornamespace { 681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor/// \brief Trait used to read the identifier index from the on-disk hash 701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor/// table. 711a49d97d762570027863e9209af81d445e4f1502Douglas Gregorclass IdentifierIndexReaderTrait { 721a49d97d762570027863e9209af81d445e4f1502Douglas Gregorpublic: 731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor typedef StringRef external_key_type; 741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor typedef StringRef internal_key_type; 751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor typedef SmallVector<unsigned, 2> data_type; 766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned hash_value_type; 776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned offset_type; 781a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 801a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return a == b; 811a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 821a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines static hash_value_type ComputeHash(const internal_key_type& a) { 841a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return llvm::HashString(a); 851a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 861a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static std::pair<unsigned, unsigned> 881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ReadKeyDataLength(const unsigned char*& d) { 89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); 91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); 921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return std::make_pair(KeyLen, DataLen); 931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static const internal_key_type& 961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor GetInternalKey(const external_key_type& x) { return x; } 971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 981a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static const external_key_type& 991a49d97d762570027863e9209af81d445e4f1502Douglas Gregor GetExternalKey(const internal_key_type& x) { return x; } 1001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static internal_key_type ReadKey(const unsigned char* d, unsigned n) { 1021a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return StringRef((const char *)d, n); 1031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static data_type ReadData(const internal_key_type& k, 1061a49d97d762570027863e9209af81d445e4f1502Douglas Gregor const unsigned char* d, 1071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned DataLen) { 108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 1091a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor data_type Result; 1111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (DataLen > 0) { 112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned ID = endian::readNext<uint32_t, little, unaligned>(d); 1131a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Result.push_back(ID); 1141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor DataLen -= 4; 1151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return Result; 1181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor}; 1201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinestypedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> 1226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines IdentifierIndexTable; 1231a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1241a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 1251a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 126176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesGlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer, 1271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamCursor Cursor) 128176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines : Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(), 129176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines NumIdentifierLookupHits() { 1301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Read the global index. 1311a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bool InGlobalIndexBlock = false; 1321a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bool Done = false; 1331a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (!Done) { 1341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamEntry Entry = Cursor.advance(); 1351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor switch (Entry.Kind) { 1371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::Error: 1381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1391a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::EndBlock: 1411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (InGlobalIndexBlock) { 1421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor InGlobalIndexBlock = false; 1431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Done = true; 1441a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 1451a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1461a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::Record: 1501a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Entries in the global index block are handled below. 1511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (InGlobalIndexBlock) 1521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1531a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1541a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::SubBlock: 1571a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { 1581a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) 1591a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1601a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor InGlobalIndexBlock = true; 1621a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } else if (Cursor.SkipBlock()) { 1631a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 1661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1671a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor SmallVector<uint64_t, 64> Record; 1691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor StringRef Blob; 1701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { 1711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case INDEX_METADATA: 1721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Make sure that the version matches. 1731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Record.size() < 1 || Record[0] != CurrentVersion) 1741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1761a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1771a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case MODULE: { 1781a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned Idx = 0; 1791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned ID = Record[Idx++]; 180677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 181677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Make room for this module's information. 182677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (ID == Modules.size()) 183677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules.push_back(ModuleInfo()); 184677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor else 185677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules.resize(ID + 1); 186677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 187677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Size/modification time for this module file at the time the 188677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // global index was built. 189677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].Size = Record[Idx++]; 190677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].ModTime = Record[Idx++]; 1911a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // File name. 1931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned NameLen = Record[Idx++]; 194677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].FileName.assign(Record.begin() + Idx, 195677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Record.begin() + Idx + NameLen); 1961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Idx += NameLen; 1971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1981a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Dependencies 1991a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned NumDeps = Record[Idx++]; 200677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), 201677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Record.begin() + Idx, 202677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Record.begin() + Idx + NumDeps); 203677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Idx += NumDeps; 2041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 205677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Make sure we're at the end of the record. 206677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor assert(Idx == Record.size() && "More module info?"); 207fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 208fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Record this module as an unresolved module. 2096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // FIXME: this doesn't work correctly for module names containing path 2106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // separators. 2116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName); 2126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Remove the -<hash of ModuleMapPath> 2136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ModuleName = ModuleName.rsplit('-').first; 2146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines UnresolvedModules[ModuleName] = ID; 2151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 2161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case IDENTIFIER_INDEX: 2191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Wire up the identifier index. 2201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Record[0]) { 2211a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndex = IdentifierIndexTable::Create( 2226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (const unsigned char *)Blob.data() + Record[0], 2236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (const unsigned char *)Blob.data() + sizeof(uint32_t), 2246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait()); 2251a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 2271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2281a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2291a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesGlobalModuleIndex::~GlobalModuleIndex() { 2326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines delete static_cast<IdentifierIndexTable *>(IdentifierIndex); 2336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 2341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2351a49d97d762570027863e9209af81d445e4f1502Douglas Gregorstd::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> 236677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorGlobalModuleIndex::readIndex(StringRef Path) { 2371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Load the index file, if it's there. 2381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::SmallString<128> IndexPath; 2391a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IndexPath += Path; 2401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 2411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 242c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr = 243c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm::MemoryBuffer::getFile(IndexPath.c_str()); 244c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!BufferOrErr) 2456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return std::make_pair(nullptr, EC_NotFound); 246c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get()); 2471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /// \brief The bitstream reader from which we'll read the AST file. 2491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(), 2501a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 2511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /// \brief The main bitstream cursor for the main block. 2531a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamCursor Cursor(Reader); 2541a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Sniff for the signature. 2561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Cursor.Read(8) != 'B' || 2571a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Cursor.Read(8) != 'C' || 2581a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Cursor.Read(8) != 'G' || 2591a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Cursor.Read(8) != 'I') { 2606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return std::make_pair(nullptr, EC_IOError); 2611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 263176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), 264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EC_None); 2651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 267677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregorvoid 268677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorGlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { 2691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ModuleFiles.clear(); 2701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 271fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (ModuleFile *MF = Modules[I].File) 272fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModuleFiles.push_back(MF); 2731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2761a49d97d762570027863e9209af81d445e4f1502Douglas Gregorvoid GlobalModuleIndex::getModuleDependencies( 277677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor ModuleFile *File, 278677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor SmallVectorImpl<ModuleFile *> &Dependencies) { 2791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Look for information about this module file. 280677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor llvm::DenseMap<ModuleFile *, unsigned>::iterator Known 281677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor = ModulesByFile.find(File); 2821a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Known == ModulesByFile.end()) 2831a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 2841a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2851a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Record dependencies. 286677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Dependencies.clear(); 287677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; 288677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { 289fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (ModuleFile *MF = Modules[I].File) 290677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Dependencies.push_back(MF); 291677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 2921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 294188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregorbool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { 295188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor Hits.clear(); 2961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // If there's no identifier index, there is nothing we can do. 2981a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!IdentifierIndex) 2991a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return false; 3001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Look into the identifier index. 3021a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ++NumIdentifierLookups; 3031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndexTable &Table 3041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor = *static_cast<IdentifierIndexTable *>(IdentifierIndex); 3051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndexTable::iterator Known = Table.find(Name); 3061a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Known == Table.end()) { 3071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return true; 3081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3091a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor SmallVector<unsigned, 2> ModuleIDs = *Known; 3111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { 312fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (ModuleFile *MF = Modules[ModuleIDs[I]].File) 313fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor Hits.insert(MF); 3141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ++NumIdentifierLookupHits; 3171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return true; 3181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 3191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 320fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregorbool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { 321fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Look for the module in the global module index based on the module name. 3226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StringRef Name = File->ModuleName; 323fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); 324fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (Known == UnresolvedModules.end()) { 325fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor return true; 326677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 327677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 328fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Rectify this module with the global module index. 329fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModuleInfo &Info = Modules[Known->second]; 330fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 331fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // If the size and modification time match what we expected, record this 332fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // module file. 333fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor bool Failed = true; 334fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (File->File->getSize() == Info.Size && 335fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor File->File->getModificationTime() == Info.ModTime) { 336fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor Info.File = File; 337fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModulesByFile[File] = Known->second; 338fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 339fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor Failed = false; 340677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 341677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 342fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // One way or another, we have resolved this module file. 343fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor UnresolvedModules.erase(Known); 344fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor return Failed; 345677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor} 346677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 3471a49d97d762570027863e9209af81d445e4f1502Douglas Gregorvoid GlobalModuleIndex::printStats() { 3481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor std::fprintf(stderr, "*** Global Module Index Statistics:\n"); 3491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (NumIdentifierLookups) { 3501a49d97d762570027863e9209af81d445e4f1502Douglas Gregor fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n", 3511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor NumIdentifierLookupHits, NumIdentifierLookups, 3521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); 3531a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3541a49d97d762570027863e9209af81d445e4f1502Douglas Gregor std::fprintf(stderr, "\n"); 3551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 3561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3574967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarLLVM_DUMP_METHOD void GlobalModuleIndex::dump() { 3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::errs() << "*** Global Module Index Dump:\n"; 3596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::errs() << "Module files:\n"; 3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (auto &MI : Modules) { 3616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::errs() << "** " << MI.FileName << "\n"; 3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (MI.File) 3636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines MI.File->dump(); 3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines else 3656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::errs() << "\n"; 3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 3676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::errs() << "\n"; 3686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 3696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor//----------------------------------------------------------------------------// 371a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// Global module index writer. 372a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 373a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 374a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace { 375a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Provides information about a specific module file. 376a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct ModuleFileInfo { 377a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The numberic ID for this module file. 378a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned ID; 379a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 380a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The set of modules on which this module depends. Each entry is 381a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// a module ID. 382a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<unsigned, 4> Dependencies; 383a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 384a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 385a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Builder that generates the global module index file. 386a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor class GlobalModuleIndexBuilder { 387a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor FileManager &FileMgr; 38887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar const PCHContainerReader &PCHContainerRdr; 389a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 390a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Mapping from files to module file information. 391a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; 392a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 393a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Information about each of the known module files. 394a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ModuleFilesMap ModuleFiles; 395a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 396a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Mapping from identifiers to the list of module file IDs that 397a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// consider this identifier to be interesting. 398a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; 399a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 400a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief A mapping from all interesting identifiers to the set of module 401a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// files in which those identifiers are considered interesting. 402a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InterestingIdentifierMap InterestingIdentifiers; 403a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 404a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Write the block-info block for the global module index file. 405a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); 406a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 407a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Retrieve the module file information for the given file. 408a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { 409a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known 410a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor = ModuleFiles.find(File); 411a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Known != ModuleFiles.end()) 412a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return Known->second; 413a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 414a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned NewID = ModuleFiles.size(); 415a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ModuleFileInfo &Info = ModuleFiles[File]; 416a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Info.ID = NewID; 417a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return Info; 418a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 419a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 420a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor public: 42187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar explicit GlobalModuleIndexBuilder( 42287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr) 42387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {} 424a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 425a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Load the contents of the given module file into the builder. 426a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// 427a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \returns true if an error occurred, false otherwise. 428a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool loadModuleFile(const FileEntry *File); 429a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 430a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Write the index to the given bitstream. 431a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void writeIndex(llvm::BitstreamWriter &Stream); 432a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 433a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 434a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 435a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void emitBlockID(unsigned ID, const char *Name, 436a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamWriter &Stream, 437a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVectorImpl<uint64_t> &Record) { 438a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 439a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(ID); 440a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 441a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 442a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Emit the block name if present. 4436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Name || Name[0] == 0) return; 444a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 445a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (*Name) 446a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(*Name++); 447a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 448a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 449a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 450a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void emitRecordID(unsigned ID, const char *Name, 451a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamWriter &Stream, 452a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVectorImpl<uint64_t> &Record) { 453a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 454a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(ID); 455a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (*Name) 456a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(*Name++); 457a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 458a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 459a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 460a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorvoid 461a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorGlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { 462a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<uint64_t, 64> Record; 463a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); 464a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 465a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 466a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define RECORD(X) emitRecordID(X, #X, Stream, Record) 467a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor BLOCK(GLOBAL_INDEX_BLOCK); 4681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor RECORD(INDEX_METADATA); 469a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor RECORD(MODULE); 470a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor RECORD(IDENTIFIER_INDEX); 471a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#undef RECORD 472a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#undef BLOCK 473a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 474a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.ExitBlock(); 475a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 476a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 4771a49d97d762570027863e9209af81d445e4f1502Douglas Gregornamespace { 478a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor class InterestingASTIdentifierLookupTrait 479a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor : public serialization::reader::ASTIdentifierLookupTraitBase { 480a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 481a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor public: 482a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The identifier and whether it is "interesting". 483a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef std::pair<StringRef, bool> data_type; 484a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 485a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor data_type ReadData(const internal_key_type& k, 486a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const unsigned char* d, 487a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DataLen) { 488a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // The first bit indicates whether this identifier is interesting. 489a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // That's all we care about. 490651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 491651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); 492a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool IsInteresting = RawID & 0x01; 493a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return std::make_pair(k, IsInteresting); 494a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 495a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 496a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 497a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 498a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorbool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { 499a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Open the module file. 500176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 501176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true); 502a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!Buffer) { 503a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 504a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 505a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 506a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Initialize the input stream 507a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamReader InStreamFile; 50887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), InStreamFile); 509176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::BitstreamCursor InStream(InStreamFile); 510a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 511a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Sniff for the signature. 512a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.Read(8) != 'C' || 513a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.Read(8) != 'P' || 514a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.Read(8) != 'C' || 515a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.Read(8) != 'H') { 516a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 517a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 518a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 519a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Record this module file and assign it a unique ID (if it doesn't have 520a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // one already). 521a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned ID = getModuleFileInfo(File).ID; 522a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 523a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Search for the blocks and records we care about. 5241a49d97d762570027863e9209af81d445e4f1502Douglas Gregor enum { Other, ControlBlock, ASTBlock } State = Other; 525a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool Done = false; 526a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (!Done) { 5271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamEntry Entry = InStream.advance(); 528a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor switch (Entry.Kind) { 529a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::Error: 5301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Done = true; 5311a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 532a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 533a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::Record: 5341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // In the 'other' state, just skip the record. We don't care. 5351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (State == Other) { 536a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.skipRecord(Entry.ID); 537a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 538a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 539a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 540a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Handle potentially-interesting records below. 541a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor break; 542a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 543a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::SubBlock: 5441a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Entry.ID == CONTROL_BLOCK_ID) { 545a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) 546a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 547a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 548a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Found the control block. 549a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor State = ControlBlock; 550a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 551a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 552a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 5531a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Entry.ID == AST_BLOCK_ID) { 554a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.EnterSubBlock(AST_BLOCK_ID)) 555a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 556a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 557a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Found the AST block. 558a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor State = ASTBlock; 559a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 560a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 561a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 562a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.SkipBlock()) 563a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 564a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 565a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 566a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 567a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::EndBlock: 5681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor State = Other; 569a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 570a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 571a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 572a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Read the given record. 573a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<uint64_t, 64> Record; 574a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor StringRef Blob; 575a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); 576a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 577a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Handle module dependencies. 578a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (State == ControlBlock && Code == IMPORTS) { 579a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Load each of the imported PCH files. 580a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned Idx = 0, N = Record.size(); 581a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (Idx < N) { 582a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Read information about the AST file. 583a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 584a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Skip the imported kind 585a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ++Idx; 586a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 587a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Skip the import location 588a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ++Idx; 589a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 590677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Load stored size/modification time. 591677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor off_t StoredSize = (off_t)Record[Idx++]; 592677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor time_t StoredModTime = (time_t)Record[Idx++]; 593677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 594176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Skip the stored signature. 595176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: we could read the signature out of the import and validate it. 596176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Idx++; 597176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 598a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Retrieve the imported file name. 599a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned Length = Record[Idx++]; 600a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallString<128> ImportedFile(Record.begin() + Idx, 601a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.begin() + Idx + Length); 602a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Idx += Length; 603a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 604a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Find the imported module file. 605ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor const FileEntry *DependsOnFile 606ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor = FileMgr.getFile(ImportedFile, /*openFile=*/false, 607ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor /*cacheFailure=*/false); 608677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (!DependsOnFile || 609677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor (StoredSize != DependsOnFile->getSize()) || 610677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor (StoredModTime != DependsOnFile->getModificationTime())) 611a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 612a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 613a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Record the dependency. 614a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; 615a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor getModuleFileInfo(File).Dependencies.push_back(DependsOnID); 616a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 617a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 618a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 619a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 620a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 621a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Handle the identifier table 622a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { 6236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef llvm::OnDiskIterableChainedHashTable< 6246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines InterestingASTIdentifierLookupTrait> InterestingIdentifierTable; 625651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<InterestingIdentifierTable> Table( 626651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines InterestingIdentifierTable::Create( 627651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines (const unsigned char *)Blob.data() + Record[0], 6286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (const unsigned char *)Blob.data() + sizeof(uint32_t), 629651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines (const unsigned char *)Blob.data())); 630a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), 631a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor DEnd = Table->data_end(); 632a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor D != DEnd; ++D) { 633a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor std::pair<StringRef, bool> Ident = *D; 634a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Ident.second) 635a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InterestingIdentifiers[Ident.first].push_back(ID); 6361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor else 6371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (void)InterestingIdentifiers[Ident.first]; 638a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 639a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 640a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 641a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // We don't care about this record. 642a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 643a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 644a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return false; 645a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 646a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 647a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace { 648a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 649a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief Trait used to generate the identifier index as an on-disk hash 650a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// table. 651a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorclass IdentifierIndexWriterTrait { 652a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorpublic: 653a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef StringRef key_type; 654a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef StringRef key_type_ref; 655a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef SmallVector<unsigned, 2> data_type; 656a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef const SmallVector<unsigned, 2> &data_type_ref; 6576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned hash_value_type; 6586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned offset_type; 659a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 6606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines static hash_value_type ComputeHash(key_type_ref Key) { 661a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return llvm::HashString(Key); 662a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 663a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 664a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor std::pair<unsigned,unsigned> 665a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { 666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little> LE(Out); 668a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned KeyLen = Key.size(); 669a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DataLen = Data.size() * 4; 670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint16_t>(KeyLen); 671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint16_t>(DataLen); 672a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return std::make_pair(KeyLen, DataLen); 673a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 674a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 675a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { 676a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Out.write(Key.data(), KeyLen); 677a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 678a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 679a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, 680a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DataLen) { 681651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 682a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (unsigned I = 0, N = Data.size(); I != N; ++I) 683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint32_t>(Data[I]); 684a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 685a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor}; 686a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 687a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 688a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 689a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorvoid GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { 690a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor using namespace llvm; 691a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 692a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Emit the file header. 693a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'B', 8); 694a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'C', 8); 695a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'G', 8); 696a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'I', 8); 697a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 698a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the block-info block, which describes the records in this bitcode 699a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // file. 700a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor emitBlockInfoBlock(Stream); 701a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 702a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); 703a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 704a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the metadata. 705a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<uint64_t, 2> Record; 706a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(CurrentVersion); 7071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Stream.EmitRecord(INDEX_METADATA, Record); 708a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 709a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the set of known module files. 710a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (ModuleFilesMap::iterator M = ModuleFiles.begin(), 711a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor MEnd = ModuleFiles.end(); 712a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor M != MEnd; ++M) { 713a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 714a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->second.ID); 715a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->first->getSize()); 716a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->first->getModificationTime()); 717a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 718a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // File name 719a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor StringRef Name(M->first->getName()); 720a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(Name.size()); 721a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.append(Name.begin(), Name.end()); 722a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 723a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Dependencies 724a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->second.Dependencies.size()); 725a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); 726a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(MODULE, Record); 727a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 728a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 729a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the identifier -> module file mapping. 730a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor { 7316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; 732a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IdentifierIndexWriterTrait Trait; 733a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 734a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Populate the hash table. 735a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), 736a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IEnd = InterestingIdentifiers.end(); 737a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor I != IEnd; ++I) { 738a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Generator.insert(I->first(), I->second, Trait); 739a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 740a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 741a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Create the on-disk hash table in a buffer. 742a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallString<4096> IdentifierTable; 743a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor uint32_t BucketOffset; 744a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor { 745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 746a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::raw_svector_ostream Out(IdentifierTable); 747a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Make sure that no bucket is at offset 0 748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint32_t>(0); 749a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor BucketOffset = Generator.Emit(Out, Trait); 750a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 751a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 752a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Create a blob abbreviation 753a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 754a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); 755a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 756a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 757a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); 758a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 759a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the identifier table 76087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset}; 7613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); 762a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 763a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 764a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.ExitBlock(); 765a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 766a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 767a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorGlobalModuleIndex::ErrorCode 76887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarGlobalModuleIndex::writeIndex(FileManager &FileMgr, 76987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar const PCHContainerReader &PCHContainerRdr, 77087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar StringRef Path) { 771a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::SmallString<128> IndexPath; 772a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IndexPath += Path; 773a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 774a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 775a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Coordinate building the global index file with other processes that might 776a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // try to do the same. 777a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::LockFileManager Locked(IndexPath); 778a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor switch (Locked) { 779a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::LockFileManager::LFS_Error: 780a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 781a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 782a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::LockFileManager::LFS_Owned: 783a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // We're responsible for building the index ourselves. Do so below. 784a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor break; 785a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 786a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::LockFileManager::LFS_Shared: 787a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Someone else is responsible for building the index. We don't care 788a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // when they finish, so we're done. 789a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_Building; 790a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 791a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 792a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // The module index builder. 79387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr); 79487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 795a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Load each of the module files. 796c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::error_code EC; 797a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; 798a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor D != DEnd && !EC; 799a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor D.increment(EC)) { 800a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // If this isn't a module file, we don't care. 801a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (llvm::sys::path::extension(D->path()) != ".pcm") { 802a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // ... unless it's a .pcm.lock file, which indicates that someone is 803a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // in the process of rebuilding a module. They'll rebuild the index 804a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // at the end of that translation unit, so we don't have to. 805a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (llvm::sys::path::extension(D->path()) == ".pcm.lock") 806a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_Building; 807a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 808a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 809a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 810a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 811a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // If we can't find the module file, skip it. 812a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const FileEntry *ModuleFile = FileMgr.getFile(D->path()); 813a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!ModuleFile) 814a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 815a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 816a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Load this module file. 817a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Builder.loadModuleFile(ModuleFile)) 818a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 819a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 820a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 821a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // The output buffer, into which the global index will be written. 822a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<char, 16> OutputBuffer; 823a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor { 824a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamWriter OutputStream(OutputBuffer); 825a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Builder.writeIndex(OutputStream); 826a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 827a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 828a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the global index file to a temporary file. 829a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::SmallString<128> IndexTmpPath; 830a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int TmpFD; 83170e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, 83270e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola IndexTmpPath)) 833a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 834a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 835a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Open the temporary global index file for output. 836d2db16f59601bc028f4f973990cc6d4abe95b91aNAKAMURA Takumi llvm::raw_fd_ostream Out(TmpFD, true); 837a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Out.has_error()) 838a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 839a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 840a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the index. 841a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Out.write(OutputBuffer.data(), OutputBuffer.size()); 842a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Out.close(); 843a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Out.has_error()) 844a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 845a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 846a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Remove the old index file. It isn't relevant any more. 8473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar llvm::sys::fs::remove(IndexPath); 848a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 849a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Rename the newly-written index file to the proper name. 8503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { 851a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Rename failed; just remove the 8523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar llvm::sys::fs::remove(IndexTmpPath); 853a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 854a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 855a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 856a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // We're done. 857a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_None; 858a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 85987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 86087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidisnamespace { 86187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis class GlobalIndexIdentifierIterator : public IdentifierIterator { 86287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis /// \brief The current position within the identifier lookup table. 86387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis IdentifierIndexTable::key_iterator Current; 86487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 86587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis /// \brief The end position within the identifier lookup table. 86687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis IdentifierIndexTable::key_iterator End; 86787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 86887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis public: 86987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) { 87087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis Current = Idx.key_begin(); 87187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis End = Idx.key_end(); 87287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis } 87387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 874651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Next() override { 87587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis if (Current == End) 87687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return StringRef(); 87787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 87887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis StringRef Result = *Current; 87987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis ++Current; 88087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return Result; 88187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis } 88287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis }; 88387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis} 88487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 88587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios KyrtzidisIdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const { 88687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis IdentifierIndexTable &Table = 88787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis *static_cast<IdentifierIndexTable *>(IdentifierIndex); 88887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return new GlobalIndexIdentifierIterator(Table); 88987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis} 890