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