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" 15a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Basic/FileManager.h" 16a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Basic/OnDiskHashTable.h" 17a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Serialization/ASTBitCodes.h" 18a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "clang/Serialization/GlobalModuleIndex.h" 19fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor#include "clang/Serialization/Module.h" 20a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/DenseMap.h" 21a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/MapVector.h" 22a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/SmallString.h" 23a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/StringExtras.h" 24a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Bitcode/BitstreamReader.h" 25a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Bitcode/BitstreamWriter.h" 265100135ecf29d4246e6bd34318da9eb22c16b86aDouglas Gregor#include "llvm/Support/FileSystem.h" 27a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Support/LockFileManager.h" 28a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/Support/MemoryBuffer.h" 298229d22e6449851b89361bf2f41804557328be63Rafael Espindola#include "llvm/Support/Path.h" 301d32133b44487d9e98412e373d693416b05920bbNAKAMURA Takumi#include <cstdio> 31a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing namespace clang; 32a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing namespace serialization; 33a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 34a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 35a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// Shared constants 36a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 37a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace { 38a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor enum { 39a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The block containing the index. 40a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID 41a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 42a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 43a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Describes the record types in the index. 44a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor enum IndexRecordTypes { 45a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Contains version information and potentially other metadata, 46a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// used to determine if we can read this global index file. 471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor INDEX_METADATA, 48a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Describes a module, including its file name and dependencies. 49a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor MODULE, 50a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The index for identifiers. 51a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IDENTIFIER_INDEX 52a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 53a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 54a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 55a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief The name of the global index file. 56a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic const char * const IndexFileName = "modules.idx"; 57a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 58a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief The global index file version. 59a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic const unsigned CurrentVersion = 1; 60a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 61a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 621a49d97d762570027863e9209af81d445e4f1502Douglas Gregor// Global module index reader. 631a49d97d762570027863e9209af81d445e4f1502Douglas Gregor//----------------------------------------------------------------------------// 641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 651a49d97d762570027863e9209af81d445e4f1502Douglas Gregornamespace { 661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 671a49d97d762570027863e9209af81d445e4f1502Douglas Gregor/// \brief Trait used to read the identifier index from the on-disk hash 681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor/// table. 691a49d97d762570027863e9209af81d445e4f1502Douglas Gregorclass IdentifierIndexReaderTrait { 701a49d97d762570027863e9209af81d445e4f1502Douglas Gregorpublic: 711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor typedef StringRef external_key_type; 721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor typedef StringRef internal_key_type; 731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor typedef SmallVector<unsigned, 2> data_type; 741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 761a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return a == b; 771a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 781a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static unsigned ComputeHash(const internal_key_type& a) { 801a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return llvm::HashString(a); 811a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 821a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 831a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static std::pair<unsigned, unsigned> 841a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ReadKeyDataLength(const unsigned char*& d) { 851a49d97d762570027863e9209af81d445e4f1502Douglas Gregor using namespace clang::io; 861a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned KeyLen = ReadUnalignedLE16(d); 871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned DataLen = ReadUnalignedLE16(d); 881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return std::make_pair(KeyLen, DataLen); 891a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 901a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 911a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static const internal_key_type& 921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor GetInternalKey(const external_key_type& x) { return x; } 931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static const external_key_type& 951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor GetExternalKey(const internal_key_type& x) { return x; } 961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static internal_key_type ReadKey(const unsigned char* d, unsigned n) { 981a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return StringRef((const char *)d, n); 991a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor static data_type ReadData(const internal_key_type& k, 1021a49d97d762570027863e9209af81d445e4f1502Douglas Gregor const unsigned char* d, 1031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned DataLen) { 1041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor using namespace clang::io; 1051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1061a49d97d762570027863e9209af81d445e4f1502Douglas Gregor data_type Result; 1071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (DataLen > 0) { 1081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned ID = ReadUnalignedLE32(d); 1091a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Result.push_back(ID); 1101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor DataLen -= 4; 1111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1121a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1131a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return Result; 1141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor}; 1161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1171a49d97d762570027863e9209af81d445e4f1502Douglas Gregortypedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable; 1181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 1201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 121677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorGlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer, 1221a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamCursor Cursor) 123fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor : Buffer(Buffer), IdentifierIndex(), 124188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor NumIdentifierLookups(), NumIdentifierLookupHits() 1251a49d97d762570027863e9209af81d445e4f1502Douglas Gregor{ 1261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Read the global index. 1271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bool InGlobalIndexBlock = false; 1281a49d97d762570027863e9209af81d445e4f1502Douglas Gregor bool Done = false; 1291a49d97d762570027863e9209af81d445e4f1502Douglas Gregor while (!Done) { 1301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamEntry Entry = Cursor.advance(); 1311a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1321a49d97d762570027863e9209af81d445e4f1502Douglas Gregor switch (Entry.Kind) { 1331a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::Error: 1341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::EndBlock: 1371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (InGlobalIndexBlock) { 1381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor InGlobalIndexBlock = false; 1391a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Done = true; 1401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 1411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1441a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1451a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::Record: 1461a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Entries in the global index block are handled below. 1471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (InGlobalIndexBlock) 1481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1501a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case llvm::BitstreamEntry::SubBlock: 1531a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) { 1541a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID)) 1551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1571a49d97d762570027863e9209af81d445e4f1502Douglas Gregor InGlobalIndexBlock = true; 1581a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } else if (Cursor.SkipBlock()) { 1591a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1601a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 1621a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 1631a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor SmallVector<uint64_t, 64> Record; 1651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor StringRef Blob; 1661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { 1671a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case INDEX_METADATA: 1681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Make sure that the version matches. 1691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Record.size() < 1 || Record[0] != CurrentVersion) 1701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 1711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 1721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1731a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case MODULE: { 1741a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned Idx = 0; 1751a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned ID = Record[Idx++]; 176677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 177677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Make room for this module's information. 178677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (ID == Modules.size()) 179677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules.push_back(ModuleInfo()); 180677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor else 181677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules.resize(ID + 1); 182677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 183677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Size/modification time for this module file at the time the 184677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // global index was built. 185677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].Size = Record[Idx++]; 186677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].ModTime = Record[Idx++]; 1871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // File name. 1891a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned NameLen = Record[Idx++]; 190677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].FileName.assign(Record.begin() + Idx, 191677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Record.begin() + Idx + NameLen); 1921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Idx += NameLen; 1931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 1941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Dependencies 1951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor unsigned NumDeps = Record[Idx++]; 196677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), 197677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Record.begin() + Idx, 198677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Record.begin() + Idx + NumDeps); 199677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Idx += NumDeps; 2001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 201677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Make sure we're at the end of the record. 202677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor assert(Idx == Record.size() && "More module info?"); 203fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 204fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Record this module as an unresolved module. 205fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor UnresolvedModules[llvm::sys::path::stem(Modules[ID].FileName)] = ID; 2061a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 2071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2091a49d97d762570027863e9209af81d445e4f1502Douglas Gregor case IDENTIFIER_INDEX: 2101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Wire up the identifier index. 2111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Record[0]) { 2121a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndex = IdentifierIndexTable::Create( 2131a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (const unsigned char *)Blob.data() + Record[0], 2141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (const unsigned char *)Blob.data(), 2151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndexReaderTrait()); 2161a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor break; 2181a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2211a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2221a49d97d762570027863e9209af81d445e4f1502Douglas GregorGlobalModuleIndex::~GlobalModuleIndex() { } 2231a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2241a49d97d762570027863e9209af81d445e4f1502Douglas Gregorstd::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> 225677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorGlobalModuleIndex::readIndex(StringRef Path) { 2261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Load the index file, if it's there. 2271a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::SmallString<128> IndexPath; 2281a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IndexPath += Path; 2291a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 2301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 231677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor llvm::OwningPtr<llvm::MemoryBuffer> Buffer; 232677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (llvm::MemoryBuffer::getFile(IndexPath, Buffer) != llvm::errc::success) 2331a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return std::make_pair((GlobalModuleIndex *)0, EC_NotFound); 2341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /// \brief The bitstream reader from which we'll read the AST file. 2361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(), 2371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 2381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2391a49d97d762570027863e9209af81d445e4f1502Douglas Gregor /// \brief The main bitstream cursor for the main block. 2401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamCursor Cursor(Reader); 2411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Sniff for the signature. 2431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Cursor.Read(8) != 'B' || 2441a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Cursor.Read(8) != 'C' || 2451a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Cursor.Read(8) != 'G' || 2461a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Cursor.Read(8) != 'I') { 2471a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return std::make_pair((GlobalModuleIndex *)0, EC_IOError); 2481a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2491a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 250677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return std::make_pair(new GlobalModuleIndex(Buffer.take(), Cursor), EC_None); 2511a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2521a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 253677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregorvoid 254677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorGlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { 2551a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ModuleFiles.clear(); 2561a49d97d762570027863e9209af81d445e4f1502Douglas Gregor for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 257fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (ModuleFile *MF = Modules[I].File) 258fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModuleFiles.push_back(MF); 2591a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2601a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2621a49d97d762570027863e9209af81d445e4f1502Douglas Gregorvoid GlobalModuleIndex::getModuleDependencies( 263677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor ModuleFile *File, 264677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor SmallVectorImpl<ModuleFile *> &Dependencies) { 2651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Look for information about this module file. 266677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor llvm::DenseMap<ModuleFile *, unsigned>::iterator Known 267677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor = ModulesByFile.find(File); 2681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Known == ModulesByFile.end()) 2691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return; 2701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Record dependencies. 272677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Dependencies.clear(); 273677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; 274677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { 275fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (ModuleFile *MF = Modules[I].File) 276677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Dependencies.push_back(MF); 277677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 2781a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 2791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 280188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregorbool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { 281188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor Hits.clear(); 2821a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2831a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // If there's no identifier index, there is nothing we can do. 2841a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (!IdentifierIndex) 2851a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return false; 2861a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // Look into the identifier index. 2881a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ++NumIdentifierLookups; 2891a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndexTable &Table 2901a49d97d762570027863e9209af81d445e4f1502Douglas Gregor = *static_cast<IdentifierIndexTable *>(IdentifierIndex); 2911a49d97d762570027863e9209af81d445e4f1502Douglas Gregor IdentifierIndexTable::iterator Known = Table.find(Name); 2921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Known == Table.end()) { 2931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return true; 2941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 2951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 2961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor SmallVector<unsigned, 2> ModuleIDs = *Known; 2971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { 298fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (ModuleFile *MF = Modules[ModuleIDs[I]].File) 299fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor Hits.insert(MF); 3001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3021a49d97d762570027863e9209af81d445e4f1502Douglas Gregor ++NumIdentifierLookupHits; 3031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor return true; 3041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 3051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 306fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregorbool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { 307fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Look for the module in the global module index based on the module name. 308fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor StringRef Name = llvm::sys::path::stem(File->FileName); 309fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); 310fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (Known == UnresolvedModules.end()) { 311fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor return true; 312677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 313677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 314fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Rectify this module with the global module index. 315fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModuleInfo &Info = Modules[Known->second]; 316fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 317fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // If the size and modification time match what we expected, record this 318fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // module file. 319fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor bool Failed = true; 320fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (File->File->getSize() == Info.Size && 321fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor File->File->getModificationTime() == Info.ModTime) { 322fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor Info.File = File; 323fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModulesByFile[File] = Known->second; 324fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 325fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor Failed = false; 326677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 327677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 328fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // One way or another, we have resolved this module file. 329fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor UnresolvedModules.erase(Known); 330fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor return Failed; 331677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor} 332677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 3331a49d97d762570027863e9209af81d445e4f1502Douglas Gregorvoid GlobalModuleIndex::printStats() { 3341a49d97d762570027863e9209af81d445e4f1502Douglas Gregor std::fprintf(stderr, "*** Global Module Index Statistics:\n"); 3351a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (NumIdentifierLookups) { 3361a49d97d762570027863e9209af81d445e4f1502Douglas Gregor fprintf(stderr, " %u / %u identifier lookups succeeded (%f%%)\n", 3371a49d97d762570027863e9209af81d445e4f1502Douglas Gregor NumIdentifierLookupHits, NumIdentifierLookups, 3381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); 3391a49d97d762570027863e9209af81d445e4f1502Douglas Gregor } 3401a49d97d762570027863e9209af81d445e4f1502Douglas Gregor std::fprintf(stderr, "\n"); 3411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor} 3421a49d97d762570027863e9209af81d445e4f1502Douglas Gregor 3431a49d97d762570027863e9209af81d445e4f1502Douglas Gregor//----------------------------------------------------------------------------// 344a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor// Global module index writer. 345a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//----------------------------------------------------------------------------// 346a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 347a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace { 348a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Provides information about a specific module file. 349a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor struct ModuleFileInfo { 350a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The numberic ID for this module file. 351a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned ID; 352a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 353a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The set of modules on which this module depends. Each entry is 354a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// a module ID. 355a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<unsigned, 4> Dependencies; 356a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 357a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 358a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Builder that generates the global module index file. 359a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor class GlobalModuleIndexBuilder { 360a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor FileManager &FileMgr; 361a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 362a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Mapping from files to module file information. 363a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; 364a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 365a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Information about each of the known module files. 366a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ModuleFilesMap ModuleFiles; 367a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 368a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Mapping from identifiers to the list of module file IDs that 369a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// consider this identifier to be interesting. 370a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; 371a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 372a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief A mapping from all interesting identifiers to the set of module 373a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// files in which those identifiers are considered interesting. 374a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InterestingIdentifierMap InterestingIdentifiers; 375a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 376a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Write the block-info block for the global module index file. 377a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); 378a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 379a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Retrieve the module file information for the given file. 380a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { 381a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known 382a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor = ModuleFiles.find(File); 383a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Known != ModuleFiles.end()) 384a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return Known->second; 385a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 386a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned NewID = ModuleFiles.size(); 387a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ModuleFileInfo &Info = ModuleFiles[File]; 388a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Info.ID = NewID; 389a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return Info; 390a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 391a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 392a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor public: 393a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){} 394a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 395a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Load the contents of the given module file into the builder. 396a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// 397a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \returns true if an error occurred, false otherwise. 398a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool loadModuleFile(const FileEntry *File); 399a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 400a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief Write the index to the given bitstream. 401a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void writeIndex(llvm::BitstreamWriter &Stream); 402a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 403a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 404a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 405a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void emitBlockID(unsigned ID, const char *Name, 406a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamWriter &Stream, 407a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVectorImpl<uint64_t> &Record) { 408a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 409a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(ID); 410a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 411a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 412a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Emit the block name if present. 413a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Name == 0 || Name[0] == 0) return; 414a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 415a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (*Name) 416a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(*Name++); 417a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 418a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 419a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 420a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorstatic void emitRecordID(unsigned ID, const char *Name, 421a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamWriter &Stream, 422a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVectorImpl<uint64_t> &Record) { 423a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 424a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(ID); 425a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (*Name) 426a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(*Name++); 427a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 428a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 429a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 430a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorvoid 431a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorGlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { 432a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<uint64_t, 64> Record; 433a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); 434a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 435a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) 436a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define RECORD(X) emitRecordID(X, #X, Stream, Record) 437a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor BLOCK(GLOBAL_INDEX_BLOCK); 4381a49d97d762570027863e9209af81d445e4f1502Douglas Gregor RECORD(INDEX_METADATA); 439a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor RECORD(MODULE); 440a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor RECORD(IDENTIFIER_INDEX); 441a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#undef RECORD 442a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#undef BLOCK 443a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 444a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.ExitBlock(); 445a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 446a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 4471a49d97d762570027863e9209af81d445e4f1502Douglas Gregornamespace { 448a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor class InterestingASTIdentifierLookupTrait 449a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor : public serialization::reader::ASTIdentifierLookupTraitBase { 450a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 451a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor public: 452a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor /// \brief The identifier and whether it is "interesting". 453a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef std::pair<StringRef, bool> data_type; 454a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 455a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor data_type ReadData(const internal_key_type& k, 456a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const unsigned char* d, 457a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DataLen) { 458a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // The first bit indicates whether this identifier is interesting. 459a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // That's all we care about. 460a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor using namespace clang::io; 461a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned RawID = ReadUnalignedLE32(d); 462a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool IsInteresting = RawID & 0x01; 463a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return std::make_pair(k, IsInteresting); 464a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 465a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor }; 466a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 467a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 468a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorbool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { 469a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Open the module file. 470a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor OwningPtr<llvm::MemoryBuffer> Buffer; 4718e31d064e7543dde6e4205d5b27a95c96a4c3a4eDouglas Gregor std::string ErrorStr; 4728e31d064e7543dde6e4205d5b27a95c96a4c3a4eDouglas Gregor Buffer.reset(FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)); 473a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!Buffer) { 474a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 475a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 476a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 477a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Initialize the input stream 478a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamReader InStreamFile; 479a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamCursor InStream; 480a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStreamFile.init((const unsigned char *)Buffer->getBufferStart(), 481a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor (const unsigned char *)Buffer->getBufferEnd()); 482a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.init(InStreamFile); 483a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 484a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Sniff for the signature. 485a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.Read(8) != 'C' || 486a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.Read(8) != 'P' || 487a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.Read(8) != 'C' || 488a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.Read(8) != 'H') { 489a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 490a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 491a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 492a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Record this module file and assign it a unique ID (if it doesn't have 493a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // one already). 494a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned ID = getModuleFileInfo(File).ID; 495a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 496a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Search for the blocks and records we care about. 4971a49d97d762570027863e9209af81d445e4f1502Douglas Gregor enum { Other, ControlBlock, ASTBlock } State = Other; 498a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool Done = false; 499a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (!Done) { 5001a49d97d762570027863e9209af81d445e4f1502Douglas Gregor llvm::BitstreamEntry Entry = InStream.advance(); 501a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor switch (Entry.Kind) { 502a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::Error: 5031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Done = true; 5041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor continue; 505a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 506a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::Record: 5071a49d97d762570027863e9209af81d445e4f1502Douglas Gregor // In the 'other' state, just skip the record. We don't care. 5081a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (State == Other) { 509a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InStream.skipRecord(Entry.ID); 510a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 511a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 512a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 513a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Handle potentially-interesting records below. 514a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor break; 515a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 516a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::SubBlock: 5171a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Entry.ID == CONTROL_BLOCK_ID) { 518a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) 519a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 520a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 521a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Found the control block. 522a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor State = ControlBlock; 523a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 524a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 525a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 5261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor if (Entry.ID == AST_BLOCK_ID) { 527a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.EnterSubBlock(AST_BLOCK_ID)) 528a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 529a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 530a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Found the AST block. 531a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor State = ASTBlock; 532a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 533a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 534a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 535a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (InStream.SkipBlock()) 536a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 537a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 538a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 539a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 540a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::BitstreamEntry::EndBlock: 5411a49d97d762570027863e9209af81d445e4f1502Douglas Gregor State = Other; 542a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 543a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 544a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 545a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Read the given record. 546a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<uint64_t, 64> Record; 547a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor StringRef Blob; 548a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); 549a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 550a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Handle module dependencies. 551a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (State == ControlBlock && Code == IMPORTS) { 552a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Load each of the imported PCH files. 553a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned Idx = 0, N = Record.size(); 554a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor while (Idx < N) { 555a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Read information about the AST file. 556a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 557a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Skip the imported kind 558a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ++Idx; 559a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 560a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Skip the import location 561a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor ++Idx; 562a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 563677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Load stored size/modification time. 564677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor off_t StoredSize = (off_t)Record[Idx++]; 565677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor time_t StoredModTime = (time_t)Record[Idx++]; 566677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 567a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Retrieve the imported file name. 568a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned Length = Record[Idx++]; 569a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallString<128> ImportedFile(Record.begin() + Idx, 570a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.begin() + Idx + Length); 571a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Idx += Length; 572a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 573a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Find the imported module file. 574ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor const FileEntry *DependsOnFile 575ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor = FileMgr.getFile(ImportedFile, /*openFile=*/false, 576ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor /*cacheFailure=*/false); 577677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (!DependsOnFile || 578677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor (StoredSize != DependsOnFile->getSize()) || 579677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor (StoredModTime != DependsOnFile->getModificationTime())) 580a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return true; 581a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 582a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Record the dependency. 583a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID; 584a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor getModuleFileInfo(File).Dependencies.push_back(DependsOnID); 585a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 586a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 587a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 588a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 589a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 590a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Handle the identifier table 591a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { 592a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait> 593a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InterestingIdentifierTable; 594a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::OwningPtr<InterestingIdentifierTable> 595a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Table(InterestingIdentifierTable::Create( 596a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor (const unsigned char *)Blob.data() + Record[0], 597a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor (const unsigned char *)Blob.data())); 598a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), 599a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor DEnd = Table->data_end(); 600a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor D != DEnd; ++D) { 601a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor std::pair<StringRef, bool> Ident = *D; 602a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Ident.second) 603a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor InterestingIdentifiers[Ident.first].push_back(ID); 6041a49d97d762570027863e9209af81d445e4f1502Douglas Gregor else 6051a49d97d762570027863e9209af81d445e4f1502Douglas Gregor (void)InterestingIdentifiers[Ident.first]; 606a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 607a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 608a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 609a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // We don't care about this record. 610a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 611a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 612a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return false; 613a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 614a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 615a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace { 616a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 617a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief Trait used to generate the identifier index as an on-disk hash 618a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// table. 619a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorclass IdentifierIndexWriterTrait { 620a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorpublic: 621a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef StringRef key_type; 622a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef StringRef key_type_ref; 623a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef SmallVector<unsigned, 2> data_type; 624a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor typedef const SmallVector<unsigned, 2> &data_type_ref; 625a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 626a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor static unsigned ComputeHash(key_type_ref Key) { 627a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return llvm::HashString(Key); 628a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 629a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 630a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor std::pair<unsigned,unsigned> 631a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { 632a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned KeyLen = Key.size(); 633a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DataLen = Data.size() * 4; 634a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clang::io::Emit16(Out, KeyLen); 635a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clang::io::Emit16(Out, DataLen); 636a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return std::make_pair(KeyLen, DataLen); 637a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 638a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 639a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { 640a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Out.write(Key.data(), KeyLen); 641a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 642a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 643a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, 644a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned DataLen) { 645a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (unsigned I = 0, N = Data.size(); I != N; ++I) 646a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clang::io::Emit32(Out, Data[I]); 647a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 648a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor}; 649a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 650a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 651a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 652a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorvoid GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { 653a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor using namespace llvm; 654a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 655a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Emit the file header. 656a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'B', 8); 657a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'C', 8); 658a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'G', 8); 659a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.Emit((unsigned)'I', 8); 660a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 661a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the block-info block, which describes the records in this bitcode 662a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // file. 663a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor emitBlockInfoBlock(Stream); 664a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 665a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); 666a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 667a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the metadata. 668a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<uint64_t, 2> Record; 669a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(CurrentVersion); 6701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor Stream.EmitRecord(INDEX_METADATA, Record); 671a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 672a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the set of known module files. 673a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (ModuleFilesMap::iterator M = ModuleFiles.begin(), 674a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor MEnd = ModuleFiles.end(); 675a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor M != MEnd; ++M) { 676a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 677a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->second.ID); 678a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->first->getSize()); 679a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->first->getModificationTime()); 680a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 681a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // File name 682a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor StringRef Name(M->first->getName()); 683a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(Name.size()); 684a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.append(Name.begin(), Name.end()); 685a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 686a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Dependencies 687a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(M->second.Dependencies.size()); 688a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); 689a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecord(MODULE, Record); 690a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 691a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 692a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the identifier -> module file mapping. 693a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor { 694a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; 695a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IdentifierIndexWriterTrait Trait; 696a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 697a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Populate the hash table. 698a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), 699a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IEnd = InterestingIdentifiers.end(); 700a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor I != IEnd; ++I) { 701a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Generator.insert(I->first(), I->second, Trait); 702a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 703a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 704a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Create the on-disk hash table in a buffer. 705a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallString<4096> IdentifierTable; 706a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor uint32_t BucketOffset; 707a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor { 708a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::raw_svector_ostream Out(IdentifierTable); 709a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Make sure that no bucket is at offset 0 710a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor clang::io::Emit32(Out, 0); 711a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor BucketOffset = Generator.Emit(Out, Trait); 712a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 713a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 714a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Create a blob abbreviation 715a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 716a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); 717a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 718a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 719a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); 720a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 721a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the identifier table 722a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.clear(); 723a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(IDENTIFIER_INDEX); 724a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Record.push_back(BucketOffset); 725a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); 726a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 727a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 728a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Stream.ExitBlock(); 729a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 730a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 731a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorGlobalModuleIndex::ErrorCode 732a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas GregorGlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { 733a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::SmallString<128> IndexPath; 734a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor IndexPath += Path; 735a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::sys::path::append(IndexPath, IndexFileName); 736a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 737a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Coordinate building the global index file with other processes that might 738a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // try to do the same. 739a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::LockFileManager Locked(IndexPath); 740a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor switch (Locked) { 741a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::LockFileManager::LFS_Error: 742a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 743a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 744a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::LockFileManager::LFS_Owned: 745a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // We're responsible for building the index ourselves. Do so below. 746a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor break; 747a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 748a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor case llvm::LockFileManager::LFS_Shared: 749a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Someone else is responsible for building the index. We don't care 750a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // when they finish, so we're done. 751a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_Building; 752a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 753a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 754a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // The module index builder. 755a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor GlobalModuleIndexBuilder Builder(FileMgr); 756a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 757a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Load each of the module files. 758a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::error_code EC; 759a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; 760a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor D != DEnd && !EC; 761a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor D.increment(EC)) { 762a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // If this isn't a module file, we don't care. 763a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (llvm::sys::path::extension(D->path()) != ".pcm") { 764a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // ... unless it's a .pcm.lock file, which indicates that someone is 765a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // in the process of rebuilding a module. They'll rebuild the index 766a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // at the end of that translation unit, so we don't have to. 767a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (llvm::sys::path::extension(D->path()) == ".pcm.lock") 768a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_Building; 769a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 770a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 771a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 772a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 773a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // If we can't find the module file, skip it. 774a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor const FileEntry *ModuleFile = FileMgr.getFile(D->path()); 775a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (!ModuleFile) 776a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor continue; 777a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 778a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Load this module file. 779a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Builder.loadModuleFile(ModuleFile)) 780a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 781a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 782a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 783a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // The output buffer, into which the global index will be written. 784a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor SmallVector<char, 16> OutputBuffer; 785a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor { 786a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::BitstreamWriter OutputStream(OutputBuffer); 787a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Builder.writeIndex(OutputStream); 788a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 789a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 790a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the global index file to a temporary file. 791a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::SmallString<128> IndexTmpPath; 792a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor int TmpFD; 79370e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, 79470e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola IndexTmpPath)) 795a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 796a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 797a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Open the temporary global index file for output. 798d2db16f59601bc028f4f973990cc6d4abe95b91aNAKAMURA Takumi llvm::raw_fd_ostream Out(TmpFD, true); 799a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Out.has_error()) 800a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 801a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 802a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Write the index. 803a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Out.write(OutputBuffer.data(), OutputBuffer.size()); 804a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor Out.close(); 805a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (Out.has_error()) 806a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 807a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 808a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Remove the old index file. It isn't relevant any more. 809a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor bool OldIndexExisted; 810a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::sys::fs::remove(IndexPath.str(), OldIndexExisted); 811a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 812a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Rename the newly-written index file to the proper name. 813a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { 814a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // Rename failed; just remove the 815a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor llvm::sys::fs::remove(IndexTmpPath.str(), OldIndexExisted); 816a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_IOError; 817a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor } 818a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor 819a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor // We're done. 820a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor return EC_None; 821a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor} 82287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 82387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidisnamespace { 82487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis class GlobalIndexIdentifierIterator : public IdentifierIterator { 82587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis /// \brief The current position within the identifier lookup table. 82687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis IdentifierIndexTable::key_iterator Current; 82787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 82887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis /// \brief The end position within the identifier lookup table. 82987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis IdentifierIndexTable::key_iterator End; 83087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 83187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis public: 83287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) { 83387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis Current = Idx.key_begin(); 83487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis End = Idx.key_end(); 83587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis } 83687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 83787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis virtual StringRef Next() { 83887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis if (Current == End) 83987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return StringRef(); 84087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 84187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis StringRef Result = *Current; 84287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis ++Current; 84387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return Result; 84487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis } 84587f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis }; 84687f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis} 84787f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis 84887f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios KyrtzidisIdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const { 84987f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis IdentifierIndexTable &Table = 85087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis *static_cast<IdentifierIndexTable *>(IdentifierIndex); 85187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis return new GlobalIndexIdentifierIterator(Table); 85287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis} 853