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