1a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//===--- GlobalModuleIndex.h - 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 defines the GlobalModuleIndex class, which manages a global index
11894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor// containing all of the identifiers known to the various modules within a given
12894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor// subdirectory of the module cache. It is used to improve the performance of
13894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor// queries such as "do any modules know about this identifier?"
14a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//
15a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor//===----------------------------------------------------------------------===//
16a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#ifndef LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H
17a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#define LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H
18a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor#include "llvm/ADT/DenseMap.h"
201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor#include "llvm/ADT/SmallPtrSet.h"
21a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/SmallVector.h"
22fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor#include "llvm/ADT/StringMap.h"
23a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include "llvm/ADT/StringRef.h"
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory>
25a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#include <utility>
26a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
271a49d97d762570027863e9209af81d445e4f1502Douglas Gregornamespace llvm {
281a49d97d762570027863e9209af81d445e4f1502Douglas Gregorclass BitstreamCursor;
291a49d97d762570027863e9209af81d445e4f1502Douglas Gregorclass MemoryBuffer;
301a49d97d762570027863e9209af81d445e4f1502Douglas Gregor}
311a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
32a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregornamespace clang {
33a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
34a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorclass DirectoryEntry;
35a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorclass FileEntry;
36a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorclass FileManager;
37809d254c1f1521c141c8807638c29d67b50ebf29Benjamin Kramerclass IdentifierIterator;
38a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
39677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregornamespace serialization {
40677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  class ModuleFile;
41a5a3e01c504c00b1860286540090695ec0167531Douglas Gregor}
42677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
43a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing llvm::SmallVector;
44a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing llvm::SmallVectorImpl;
45a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorusing llvm::StringRef;
46677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregorusing serialization::ModuleFile;
47677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
48a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// \brief A global index for a set of module files, providing information about
49894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// the identifiers within those module files.
50a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor///
51a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor/// The global index is an aid for name lookup into modules, offering a central
52894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// place where one can look for identifiers determine which
53894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// module files contain any information about that identifier. This
54894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// allows the client to restrict the search to only those module files known
55894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// to have a information about that identifier, improving performance. Moreover,
56894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// the global module index may know about module files that have not been
57894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// imported, and can be queried to determine which modules the current
58894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor/// translation could or should load to fix a problem.
59a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorclass GlobalModuleIndex {
601a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief Buffer containing the index file, which is lazily accessed so long
611a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// as the global module index is live.
62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<llvm::MemoryBuffer> Buffer;
631a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
641a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief The hash table.
651a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  ///
661a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// This pointer actually points to a IdentifierIndexTable object,
671a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// but that type is only accessible within the implementation of
681a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// GlobalModuleIndex.
691a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  void *IdentifierIndex;
701a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
711a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief Information about a given module file.
721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  struct ModuleInfo {
73677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    ModuleInfo() : File(), Size(), ModTime() { }
74677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
75fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor    /// \brief The module file, once it has been resolved.
76677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    ModuleFile *File;
77677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
78677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /// \brief The module file name.
79677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    std::string FileName;
80677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
81677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /// \brief Size of the module file at the time the global index was built.
82677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    off_t Size;
831a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
84677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /// \brief Modification time of the module file at the time the global
85677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /// index was built.
86677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    time_t ModTime;
871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
88677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /// \brief The module IDs on which this module directly depends.
89677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /// FIXME: We don't really need a vector here.
90677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    llvm::SmallVector<unsigned, 4> Dependencies;
911a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  };
921a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
931a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief A mapping from module IDs to information about each module.
941a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  ///
951a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// This vector may have gaps, if module files have been removed or have
961a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// been updated since the index was built. A gap is indicated by an empty
97677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  /// file name.
981a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  llvm::SmallVector<ModuleInfo, 16> Modules;
991a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
100677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  /// \brief Lazily-populated mapping from module files to their
1011a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// corresponding index into the \c Modules vector.
102677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile;
1031a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
104fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  /// \brief The set of modules that have not yet been resolved.
105fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  ///
106fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  /// The string is just the name of the module itself, which maps to the
107fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  /// module ID.
108fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  llvm::StringMap<unsigned> UnresolvedModules;
109fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor
1101a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief The number of identifier lookups we performed.
1111a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  unsigned NumIdentifierLookups;
1121a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
1131a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief The number of identifier lookup hits, where we recognize the
1141a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// identifier.
1151a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  unsigned NumIdentifierLookupHits;
116fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor
117a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \brief Internal constructor. Use \c readIndex() to read an index.
118677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  explicit GlobalModuleIndex(llvm::MemoryBuffer *Buffer,
1191a49d97d762570027863e9209af81d445e4f1502Douglas Gregor                             llvm::BitstreamCursor Cursor);
1201a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
1219ef9b8540a608a93efaaae1d26d94e8087c30b55David Blaikie  GlobalModuleIndex(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION;
1229ef9b8540a608a93efaaae1d26d94e8087c30b55David Blaikie  GlobalModuleIndex &operator=(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION;
123a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
124a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregorpublic:
1251a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  ~GlobalModuleIndex();
1261a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
127a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \brief An error code returned when trying to read an index.
128a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  enum ErrorCode {
129a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    /// \brief No error occurred.
130a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    EC_None,
131a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    /// \brief No index was found.
132a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    EC_NotFound,
133a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    /// \brief Some other process is currently building the index; it is not
134a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    /// available yet.
135a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    EC_Building,
136a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    /// \brief There was an unspecified I/O error reading or writing the index.
137a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor    EC_IOError
138a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  };
139a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
140a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \brief Read a global index file for the given directory.
141a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
142a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \param Path The path to the specific module cache where the module files
143a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// for the intended configuration reside.
144a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
145a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \returns A pair containing the global module index (if it exists) and
146a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// the error code.
147a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  static std::pair<GlobalModuleIndex *, ErrorCode>
148677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  readIndex(StringRef Path);
149a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
15087f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis  /// \brief Returns an iterator for identifiers stored in the index table.
15187f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis  ///
15287f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis  /// The caller accepts ownership of the returned object.
15387f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis  IdentifierIterator *createIdentifierIterator() const;
15487f9d81d0ab806dcf6ca50a0c068dcb2ba7f51b3Argyrios Kyrtzidis
155a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \brief Retrieve the set of modules that have up-to-date indexes.
156a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
157a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \param ModuleFiles Will be populated with the set of module files that
158a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// have been indexed.
159677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles);
160a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
161a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \brief Retrieve the set of module files on which the given module file
162a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// directly depends.
163677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  void getModuleDependencies(ModuleFile *File,
164677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor                             SmallVectorImpl<ModuleFile *> &Dependencies);
165a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
166188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor  /// \brief A set of module files in which we found a result.
167677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor  typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet;
168188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor
169894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor  /// \brief Look for all of the module files with information about the given
170894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor  /// identifier, e.g., a global function, variable, or type with that name.
171a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
1721a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \param Name The identifier to look for.
173a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
174894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor  /// \param Hits Will be populated with the set of module files that have
175894719bf99cf0131d954c714179bb47eee472b91Douglas Gregor  /// information about this name.
176a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
177188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor  /// \returns true if the identifier is known to the index, false otherwise.
178188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor  bool lookupIdentifier(StringRef Name, HitSet &Hits);
1791a49d97d762570027863e9209af81d445e4f1502Douglas Gregor
180fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  /// \brief Note that the given module file has been loaded.
181fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  ///
182fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  /// \returns false if the global module index has information about this
183fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  /// module file, and true otherwise.
184fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor  bool loadedModuleFile(ModuleFile *File);
185677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
1861a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  /// \brief Print statistics to standard error.
1871a49d97d762570027863e9209af81d445e4f1502Douglas Gregor  void printStats();
188a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
1896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  /// \brief Print debugging view to standard error.
1906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void dump();
1916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
192a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \brief Write a global index into the given
193a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
194a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \param FileMgr The file manager to use to load module files.
195a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  ///
196a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// \param Path The path to the directory containing module files, into
197a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  /// which the global index will be written.
198a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor  static ErrorCode writeIndex(FileManager &FileMgr, StringRef Path);
199a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor};
200a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
201a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor}
202a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor
203a6b00fc97669aa25d89ae9f202b05dfadfd0e324Douglas Gregor#endif
204