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