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