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