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