1e5dd7070Spatrick //===- ModuleManager.cpp - Module Manager -----------------------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file defines the ModuleManager class, which manages a set of loaded 10e5dd7070Spatrick // modules for the ASTReader. 11e5dd7070Spatrick // 12e5dd7070Spatrick //===----------------------------------------------------------------------===// 13e5dd7070Spatrick 14e5dd7070Spatrick #ifndef LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H 15e5dd7070Spatrick #define LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H 16e5dd7070Spatrick 17e5dd7070Spatrick #include "clang/Basic/LLVM.h" 18e5dd7070Spatrick #include "clang/Basic/Module.h" 19e5dd7070Spatrick #include "clang/Basic/SourceLocation.h" 20e5dd7070Spatrick #include "clang/Serialization/ModuleFile.h" 21e5dd7070Spatrick #include "llvm/ADT/DenseMap.h" 22e5dd7070Spatrick #include "llvm/ADT/IntrusiveRefCntPtr.h" 23e5dd7070Spatrick #include "llvm/ADT/STLExtras.h" 24e5dd7070Spatrick #include "llvm/ADT/SmallPtrSet.h" 25e5dd7070Spatrick #include "llvm/ADT/SmallVector.h" 26e5dd7070Spatrick #include "llvm/ADT/StringRef.h" 27e5dd7070Spatrick #include "llvm/ADT/iterator.h" 28e5dd7070Spatrick #include "llvm/ADT/iterator_range.h" 29e5dd7070Spatrick #include <cstdint> 30e5dd7070Spatrick #include <ctime> 31e5dd7070Spatrick #include <memory> 32e5dd7070Spatrick #include <string> 33e5dd7070Spatrick #include <utility> 34e5dd7070Spatrick 35e5dd7070Spatrick namespace clang { 36e5dd7070Spatrick 37e5dd7070Spatrick class FileEntry; 38e5dd7070Spatrick class FileManager; 39e5dd7070Spatrick class GlobalModuleIndex; 40e5dd7070Spatrick class HeaderSearch; 41e5dd7070Spatrick class InMemoryModuleCache; 42e5dd7070Spatrick class ModuleMap; 43e5dd7070Spatrick class PCHContainerReader; 44e5dd7070Spatrick 45e5dd7070Spatrick namespace serialization { 46e5dd7070Spatrick 47e5dd7070Spatrick /// Manages the set of modules loaded by an AST reader. 48e5dd7070Spatrick class ModuleManager { 49e5dd7070Spatrick /// The chain of AST files, in the order in which we started to load 50e5dd7070Spatrick /// them (this order isn't really useful for anything). 51e5dd7070Spatrick SmallVector<std::unique_ptr<ModuleFile>, 2> Chain; 52e5dd7070Spatrick 53e5dd7070Spatrick /// The chain of non-module PCH files. The first entry is the one named 54e5dd7070Spatrick /// by the user, the last one is the one that doesn't depend on anything 55e5dd7070Spatrick /// further. 56e5dd7070Spatrick SmallVector<ModuleFile *, 2> PCHChain; 57e5dd7070Spatrick 58e5dd7070Spatrick // The roots of the dependency DAG of AST files. This is used 59e5dd7070Spatrick // to implement short-circuiting logic when running DFS over the dependencies. 60e5dd7070Spatrick SmallVector<ModuleFile *, 2> Roots; 61e5dd7070Spatrick 62e5dd7070Spatrick /// All loaded modules, indexed by name. 63e5dd7070Spatrick llvm::DenseMap<const FileEntry *, ModuleFile *> Modules; 64e5dd7070Spatrick 65e5dd7070Spatrick /// FileManager that handles translating between filenames and 66e5dd7070Spatrick /// FileEntry *. 67e5dd7070Spatrick FileManager &FileMgr; 68e5dd7070Spatrick 69e5dd7070Spatrick /// Cache of PCM files. 70e5dd7070Spatrick IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache; 71e5dd7070Spatrick 72e5dd7070Spatrick /// Knows how to unwrap module containers. 73e5dd7070Spatrick const PCHContainerReader &PCHContainerRdr; 74e5dd7070Spatrick 75e5dd7070Spatrick /// Preprocessor's HeaderSearchInfo containing the module map. 76e5dd7070Spatrick const HeaderSearch &HeaderSearchInfo; 77e5dd7070Spatrick 78e5dd7070Spatrick /// A lookup of in-memory (virtual file) buffers 79e5dd7070Spatrick llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>> 80e5dd7070Spatrick InMemoryBuffers; 81e5dd7070Spatrick 82e5dd7070Spatrick /// The visitation order. 83e5dd7070Spatrick SmallVector<ModuleFile *, 4> VisitOrder; 84e5dd7070Spatrick 85e5dd7070Spatrick /// The list of module files that both we and the global module index 86e5dd7070Spatrick /// know about. 87e5dd7070Spatrick /// 88e5dd7070Spatrick /// Either the global index or the module manager may have modules that the 89e5dd7070Spatrick /// other does not know about, because the global index can be out-of-date 90e5dd7070Spatrick /// (in which case the module manager could have modules it does not) and 91e5dd7070Spatrick /// this particular translation unit might not have loaded all of the modules 92e5dd7070Spatrick /// known to the global index. 93e5dd7070Spatrick SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex; 94e5dd7070Spatrick 95e5dd7070Spatrick /// The global module index, if one is attached. 96e5dd7070Spatrick /// 97e5dd7070Spatrick /// The global module index will actually be owned by the ASTReader; this is 98e5dd7070Spatrick /// just an non-owning pointer. 99e5dd7070Spatrick GlobalModuleIndex *GlobalIndex = nullptr; 100e5dd7070Spatrick 101e5dd7070Spatrick /// State used by the "visit" operation to avoid malloc traffic in 102e5dd7070Spatrick /// calls to visit(). 103e5dd7070Spatrick struct VisitState { 104e5dd7070Spatrick explicit VisitState(unsigned N) : VisitNumber(N, 0) { 105e5dd7070Spatrick Stack.reserve(N); 106e5dd7070Spatrick } 107e5dd7070Spatrick 108e5dd7070Spatrick ~VisitState() { 109e5dd7070Spatrick delete NextState; 110e5dd7070Spatrick } 111e5dd7070Spatrick 112e5dd7070Spatrick /// The stack used when marking the imports of a particular module 113e5dd7070Spatrick /// as not-to-be-visited. 114e5dd7070Spatrick SmallVector<ModuleFile *, 4> Stack; 115e5dd7070Spatrick 116e5dd7070Spatrick /// The visit number of each module file, which indicates when 117e5dd7070Spatrick /// this module file was last visited. 118e5dd7070Spatrick SmallVector<unsigned, 4> VisitNumber; 119e5dd7070Spatrick 120e5dd7070Spatrick /// The next visit number to use to mark visited module files. 121e5dd7070Spatrick unsigned NextVisitNumber = 1; 122e5dd7070Spatrick 123e5dd7070Spatrick /// The next visit state. 124e5dd7070Spatrick VisitState *NextState = nullptr; 125e5dd7070Spatrick }; 126e5dd7070Spatrick 127e5dd7070Spatrick /// The first visit() state in the chain. 128e5dd7070Spatrick VisitState *FirstVisitState = nullptr; 129e5dd7070Spatrick 130e5dd7070Spatrick VisitState *allocateVisitState(); 131e5dd7070Spatrick void returnVisitState(VisitState *State); 132e5dd7070Spatrick 133e5dd7070Spatrick public: 134e5dd7070Spatrick using ModuleIterator = llvm::pointee_iterator< 135e5dd7070Spatrick SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator>; 136e5dd7070Spatrick using ModuleConstIterator = llvm::pointee_iterator< 137e5dd7070Spatrick SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator>; 138e5dd7070Spatrick using ModuleReverseIterator = llvm::pointee_iterator< 139e5dd7070Spatrick SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>; 140e5dd7070Spatrick using ModuleOffset = std::pair<uint32_t, StringRef>; 141e5dd7070Spatrick 142e5dd7070Spatrick explicit ModuleManager(FileManager &FileMgr, InMemoryModuleCache &ModuleCache, 143e5dd7070Spatrick const PCHContainerReader &PCHContainerRdr, 144e5dd7070Spatrick const HeaderSearch &HeaderSearchInfo); 145e5dd7070Spatrick ~ModuleManager(); 146e5dd7070Spatrick 147e5dd7070Spatrick /// Forward iterator to traverse all loaded modules. 148e5dd7070Spatrick ModuleIterator begin() { return Chain.begin(); } 149e5dd7070Spatrick 150e5dd7070Spatrick /// Forward iterator end-point to traverse all loaded modules 151e5dd7070Spatrick ModuleIterator end() { return Chain.end(); } 152e5dd7070Spatrick 153e5dd7070Spatrick /// Const forward iterator to traverse all loaded modules. 154e5dd7070Spatrick ModuleConstIterator begin() const { return Chain.begin(); } 155e5dd7070Spatrick 156e5dd7070Spatrick /// Const forward iterator end-point to traverse all loaded modules 157e5dd7070Spatrick ModuleConstIterator end() const { return Chain.end(); } 158e5dd7070Spatrick 159e5dd7070Spatrick /// Reverse iterator to traverse all loaded modules. 160e5dd7070Spatrick ModuleReverseIterator rbegin() { return Chain.rbegin(); } 161e5dd7070Spatrick 162e5dd7070Spatrick /// Reverse iterator end-point to traverse all loaded modules. 163e5dd7070Spatrick ModuleReverseIterator rend() { return Chain.rend(); } 164e5dd7070Spatrick 165e5dd7070Spatrick /// A range covering the PCH and preamble module files loaded. 166e5dd7070Spatrick llvm::iterator_range<SmallVectorImpl<ModuleFile *>::const_iterator> 167e5dd7070Spatrick pch_modules() const { 168e5dd7070Spatrick return llvm::make_range(PCHChain.begin(), PCHChain.end()); 169e5dd7070Spatrick } 170e5dd7070Spatrick 171e5dd7070Spatrick /// Returns the primary module associated with the manager, that is, 172e5dd7070Spatrick /// the first module loaded 173e5dd7070Spatrick ModuleFile &getPrimaryModule() { return *Chain[0]; } 174e5dd7070Spatrick 175e5dd7070Spatrick /// Returns the primary module associated with the manager, that is, 176e5dd7070Spatrick /// the first module loaded. 177e5dd7070Spatrick ModuleFile &getPrimaryModule() const { return *Chain[0]; } 178e5dd7070Spatrick 179e5dd7070Spatrick /// Returns the module associated with the given index 180e5dd7070Spatrick ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; } 181e5dd7070Spatrick 182e5dd7070Spatrick /// Returns the module associated with the given file name. 183e5dd7070Spatrick ModuleFile *lookupByFileName(StringRef FileName) const; 184e5dd7070Spatrick 185e5dd7070Spatrick /// Returns the module associated with the given module name. 186e5dd7070Spatrick ModuleFile *lookupByModuleName(StringRef ModName) const; 187e5dd7070Spatrick 188e5dd7070Spatrick /// Returns the module associated with the given module file. 189e5dd7070Spatrick ModuleFile *lookup(const FileEntry *File) const; 190e5dd7070Spatrick 191e5dd7070Spatrick /// Returns the in-memory (virtual file) buffer with the given name 192e5dd7070Spatrick std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name); 193e5dd7070Spatrick 194e5dd7070Spatrick /// Number of modules loaded 195e5dd7070Spatrick unsigned size() const { return Chain.size(); } 196e5dd7070Spatrick 197e5dd7070Spatrick /// The result of attempting to add a new module. 198e5dd7070Spatrick enum AddModuleResult { 199e5dd7070Spatrick /// The module file had already been loaded. 200e5dd7070Spatrick AlreadyLoaded, 201e5dd7070Spatrick 202e5dd7070Spatrick /// The module file was just loaded in response to this call. 203e5dd7070Spatrick NewlyLoaded, 204e5dd7070Spatrick 205e5dd7070Spatrick /// The module file is missing. 206e5dd7070Spatrick Missing, 207e5dd7070Spatrick 208e5dd7070Spatrick /// The module file is out-of-date. 209e5dd7070Spatrick OutOfDate 210e5dd7070Spatrick }; 211e5dd7070Spatrick 212e5dd7070Spatrick using ASTFileSignatureReader = ASTFileSignature (*)(StringRef); 213e5dd7070Spatrick 214e5dd7070Spatrick /// Attempts to create a new module and add it to the list of known 215e5dd7070Spatrick /// modules. 216e5dd7070Spatrick /// 217e5dd7070Spatrick /// \param FileName The file name of the module to be loaded. 218e5dd7070Spatrick /// 219e5dd7070Spatrick /// \param Type The kind of module being loaded. 220e5dd7070Spatrick /// 221e5dd7070Spatrick /// \param ImportLoc The location at which the module is imported. 222e5dd7070Spatrick /// 223e5dd7070Spatrick /// \param ImportedBy The module that is importing this module, or NULL if 224e5dd7070Spatrick /// this module is imported directly by the user. 225e5dd7070Spatrick /// 226e5dd7070Spatrick /// \param Generation The generation in which this module was loaded. 227e5dd7070Spatrick /// 228e5dd7070Spatrick /// \param ExpectedSize The expected size of the module file, used for 229e5dd7070Spatrick /// validation. This will be zero if unknown. 230e5dd7070Spatrick /// 231e5dd7070Spatrick /// \param ExpectedModTime The expected modification time of the module 232e5dd7070Spatrick /// file, used for validation. This will be zero if unknown. 233e5dd7070Spatrick /// 234e5dd7070Spatrick /// \param ExpectedSignature The expected signature of the module file, used 235e5dd7070Spatrick /// for validation. This will be zero if unknown. 236e5dd7070Spatrick /// 237e5dd7070Spatrick /// \param ReadSignature Reads the signature from an AST file without actually 238e5dd7070Spatrick /// loading it. 239e5dd7070Spatrick /// 240e5dd7070Spatrick /// \param Module A pointer to the module file if the module was successfully 241e5dd7070Spatrick /// loaded. 242e5dd7070Spatrick /// 243e5dd7070Spatrick /// \param ErrorStr Will be set to a non-empty string if any errors occurred 244e5dd7070Spatrick /// while trying to load the module. 245e5dd7070Spatrick /// 246e5dd7070Spatrick /// \return A pointer to the module that corresponds to this file name, 247e5dd7070Spatrick /// and a value indicating whether the module was loaded. 248e5dd7070Spatrick AddModuleResult addModule(StringRef FileName, ModuleKind Type, 249e5dd7070Spatrick SourceLocation ImportLoc, 250e5dd7070Spatrick ModuleFile *ImportedBy, unsigned Generation, 251e5dd7070Spatrick off_t ExpectedSize, time_t ExpectedModTime, 252e5dd7070Spatrick ASTFileSignature ExpectedSignature, 253e5dd7070Spatrick ASTFileSignatureReader ReadSignature, 254e5dd7070Spatrick ModuleFile *&Module, 255e5dd7070Spatrick std::string &ErrorStr); 256e5dd7070Spatrick 257e5dd7070Spatrick /// Remove the modules starting from First (to the end). 258e5dd7070Spatrick void removeModules(ModuleIterator First, ModuleMap *modMap); 259e5dd7070Spatrick 260e5dd7070Spatrick /// Add an in-memory buffer the list of known buffers 261e5dd7070Spatrick void addInMemoryBuffer(StringRef FileName, 262e5dd7070Spatrick std::unique_ptr<llvm::MemoryBuffer> Buffer); 263e5dd7070Spatrick 264e5dd7070Spatrick /// Set the global module index. 265e5dd7070Spatrick void setGlobalIndex(GlobalModuleIndex *Index); 266e5dd7070Spatrick 267e5dd7070Spatrick /// Notification from the AST reader that the given module file 268e5dd7070Spatrick /// has been "accepted", and will not (can not) be unloaded. 269e5dd7070Spatrick void moduleFileAccepted(ModuleFile *MF); 270e5dd7070Spatrick 271e5dd7070Spatrick /// Visit each of the modules. 272e5dd7070Spatrick /// 273e5dd7070Spatrick /// This routine visits each of the modules, starting with the 274e5dd7070Spatrick /// "root" modules that no other loaded modules depend on, and 275e5dd7070Spatrick /// proceeding to the leaf modules, visiting each module only once 276e5dd7070Spatrick /// during the traversal. 277e5dd7070Spatrick /// 278e5dd7070Spatrick /// This traversal is intended to support various "lookup" 279e5dd7070Spatrick /// operations that can find data in any of the loaded modules. 280e5dd7070Spatrick /// 281e5dd7070Spatrick /// \param Visitor A visitor function that will be invoked with each 282e5dd7070Spatrick /// module. The return value must be convertible to bool; when false, the 283e5dd7070Spatrick /// visitation continues to modules that the current module depends on. When 284e5dd7070Spatrick /// true, the visitation skips any modules that the current module depends on. 285e5dd7070Spatrick /// 286e5dd7070Spatrick /// \param ModuleFilesHit If non-NULL, contains the set of module files 287e5dd7070Spatrick /// that we know we need to visit because the global module index told us to. 288e5dd7070Spatrick /// Any module that is known to both the global module index and the module 289e5dd7070Spatrick /// manager that is *not* in this set can be skipped. 290e5dd7070Spatrick void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor, 291e5dd7070Spatrick llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr); 292e5dd7070Spatrick 293e5dd7070Spatrick /// Attempt to resolve the given module file name to a file entry. 294e5dd7070Spatrick /// 295e5dd7070Spatrick /// \param FileName The name of the module file. 296e5dd7070Spatrick /// 297e5dd7070Spatrick /// \param ExpectedSize The size that the module file is expected to have. 298e5dd7070Spatrick /// If the actual size differs, the resolver should return \c true. 299e5dd7070Spatrick /// 300e5dd7070Spatrick /// \param ExpectedModTime The modification time that the module file is 301e5dd7070Spatrick /// expected to have. If the actual modification time differs, the resolver 302e5dd7070Spatrick /// should return \c true. 303e5dd7070Spatrick /// 304e5dd7070Spatrick /// \param File Will be set to the file if there is one, or null 305e5dd7070Spatrick /// otherwise. 306e5dd7070Spatrick /// 307e5dd7070Spatrick /// \returns True if a file exists but does not meet the size/ 308e5dd7070Spatrick /// modification time criteria, false if the file is either available and 309e5dd7070Spatrick /// suitable, or is missing. 310*a9ac8606Spatrick bool lookupModuleFile(StringRef FileName, off_t ExpectedSize, 311*a9ac8606Spatrick time_t ExpectedModTime, Optional<FileEntryRef> &File); 312e5dd7070Spatrick 313e5dd7070Spatrick /// View the graphviz representation of the module graph. 314e5dd7070Spatrick void viewGraph(); 315e5dd7070Spatrick 316e5dd7070Spatrick InMemoryModuleCache &getModuleCache() const { return *ModuleCache; } 317e5dd7070Spatrick }; 318e5dd7070Spatrick 319e5dd7070Spatrick } // namespace serialization 320e5dd7070Spatrick 321e5dd7070Spatrick } // namespace clang 322e5dd7070Spatrick 323e5dd7070Spatrick #endif // LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H 324