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