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