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