clang 23.0.0git
ModuleManager.cpp
Go to the documentation of this file.
1//===- ModuleManager.cpp - Module Manager ---------------------------------===//
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
16#include "clang/Basic/LLVM.h"
18#include "clang/Lex/ModuleMap.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SetVector.h"
26#include "llvm/ADT/SmallPtrSet.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/ADT/StringRef.h"
29#include "llvm/ADT/iterator.h"
30#include "llvm/Support/DOTGraphTraits.h"
31#include "llvm/Support/Error.h"
32#include "llvm/Support/ErrorOr.h"
33#include "llvm/Support/GraphWriter.h"
34#include "llvm/Support/MemoryBuffer.h"
35#include "llvm/Support/VirtualFileSystem.h"
36#include <cassert>
37#include <memory>
38#include <string>
39#include <system_error>
40
41using namespace clang;
42using namespace serialization;
43
44std::optional<ModuleFileKey>
46 if (unsigned SuffixLen = Name.getImplicitModuleSuffixLength()) {
47 StringRef ModuleCachePath = StringRef(Name).drop_back(SuffixLen);
48 StringRef ImplicitModuleSuffix = StringRef(Name).take_back(SuffixLen);
49 if (auto *ModuleCacheDir = ModCache.getDirectoryPtr(ModuleCachePath))
50 return ModuleFileKey(ModuleCacheDir, ImplicitModuleSuffix);
51 } else if (Name.isInMemory()) {
52 off_t Size;
53 time_t ModTime;
54 if (auto *Buf =
55 ModCache.getInMemoryModuleCache().lookupPCM(Name, Size, ModTime))
56 return ModuleFileKey(Buf);
57 } else {
58 if (auto ModuleFile = FileMgr.getOptionalFileRef(Name, /*OpenFile=*/true,
59 /*CacheFailure=*/false,
60 /*IsText=*/false))
62 }
63
64 return std::nullopt;
65}
66
68 if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
69 if (const ModuleFileName *FileName = Mod->getASTFileName())
71
72 return nullptr;
73}
74
76 std::optional<ModuleFileKey> Key = makeKey(Name);
77 return Key ? lookup(*Key) : nullptr;
78}
79
81 return Modules.lookup(Key);
82}
83
84bool ModuleManager::isModuleFileOutOfDate(off_t Size, time_t ModTime,
85 off_t ExpectedSize,
86 time_t ExpectedModTime,
88 bool OutOfDate = false;
89 if (ExpectedSize && ExpectedSize != Size) {
90 Result.Changes.push_back({Change::Size, ExpectedSize, Size});
91 OutOfDate = true;
92 }
93
94 if (ExpectedModTime && ExpectedModTime != ModTime) {
95 Result.Changes.push_back({Change::ModTime, ExpectedModTime, ModTime});
96 OutOfDate = true;
97 }
98
99 return OutOfDate;
100}
101
102bool ModuleManager::checkSignature(ASTFileSignature Signature,
103 ASTFileSignature ExpectedSignature,
105 if (!ExpectedSignature || Signature == ExpectedSignature)
106 return false;
107 Result.SignatureError =
108 Signature ? "signature mismatch" : "could not read module signature";
109 return true;
110}
111
112static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy,
113 SourceLocation ImportLoc) {
114 if (ImportedBy) {
115 MF.ImportedBy.insert(ImportedBy);
116 ImportedBy->Imports.insert(&MF);
117 } else {
118 if (!MF.DirectlyImported)
119 MF.ImportLoc = ImportLoc;
120
121 MF.DirectlyImported = true;
122 }
123}
124
127 ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize,
128 time_t ExpectedModTime, ASTFileSignature ExpectedSignature,
129 ASTFileSignatureReader ReadSignature) {
131
132 uint64_t InputFilesValidationTimestamp = 0;
133 if (Type == MK_ImplicitModule)
134 InputFilesValidationTimestamp = ModCache.getModuleTimestamp(FileName);
135
136 bool IgnoreModTime = Type == MK_ExplicitModule || Type == MK_PrebuiltModule;
137 if (ImportedBy)
138 IgnoreModTime &= ImportedBy->Kind == MK_ExplicitModule ||
139 ImportedBy->Kind == MK_PrebuiltModule;
140 if (IgnoreModTime) {
141 // If neither this file nor the importer are in the module cache, this file
142 // might have a different mtime due to being moved across filesystems in
143 // a distributed build. The size must still match, though. (As must the
144 // contents, but we can't check that.)
145 ExpectedModTime = 0;
146 }
147
148 std::optional<ModuleFileKey> FileKey = makeKey(FileName);
149 if (!FileKey) {
151 return Result;
152 }
153
154 // Check whether we already loaded this module before.
155 // Note: `isModuleFileOutOfDate` and `checkSignature` are mutually exclusive
156 // in practice. If a signature is stored, it means size/mtime values have been
157 // zeroed out. If size/mtime are non-NULL, the signature is empty.
158 if (ModuleFile *ModuleEntry = lookup(*FileKey)) {
159 if (isModuleFileOutOfDate(ModuleEntry->Size, ModuleEntry->ModTime,
160 ExpectedSize, ExpectedModTime, Result)) {
161 Result.setOutOfDate(ModuleEntry->InputFilesValidationStatus);
162 return Result;
163 }
164
165 // Check the stored signature.
166 if (checkSignature(ModuleEntry->Signature, ExpectedSignature, Result)) {
167 Result.setOutOfDate(ModuleEntry->InputFilesValidationStatus);
168 return Result;
169 }
170
171 Result.Module = ModuleEntry;
172 updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
174 return Result;
175 }
176
177 // Load the contents of the module
178 off_t Size = ExpectedSize;
179 time_t ModTime = ExpectedModTime;
180 llvm::MemoryBuffer *ModuleBuffer = nullptr;
181 std::unique_ptr<llvm::MemoryBuffer> NewFileBuffer = nullptr;
182 if (llvm::MemoryBuffer *Buffer =
183 getModuleCache().getInMemoryModuleCache().lookupPCM(FileName, Size,
184 ModTime)) {
185 ModuleBuffer = Buffer;
186 } else if (getModuleCache().getInMemoryModuleCache().shouldBuildPCM(
187 FileName)) {
188 // Report that the module is out of date, since we tried (and failed) to
189 // import it earlier. No ModuleFile exists yet, so derive the validation
190 // status from the module kind being loaded.
194 return Result;
195 } else {
196 auto Buf = [&]() -> Expected<std::unique_ptr<llvm::MemoryBuffer>> {
197 assert(!FileName.isInMemory() && "In-memory module not found");
198
199 // Implicit modules live in the module cache.
200 if (FileName.getImplicitModuleSuffixLength())
201 return ModCache.read(FileName, Size, ModTime);
202
203 // Explicit modules are treated as any other compiler input file, load
204 // them via FileManager.
206 FileName == StringRef("-")
207 ? FileMgr.getSTDIN()
208 : FileMgr.getFileRef(FileName, /*OpenFile=*/true,
209 /*CacheFailure=*/false,
210 /*IsText=*/false);
211 if (!Entry)
212 return Entry.takeError();
213
214 Size = Entry->getSize();
215 ModTime = Entry->getModificationTime();
216
217 // RequiresNullTerminator is false because module files don't need it, and
218 // this allows the file to still be mmapped.
219 return llvm::errorOrToExpected(
220 FileMgr.getBufferForFile(*Entry, /*IsVolatile=*/false,
221 /*RequiresNullTerminator=*/false,
222 /*MaybeLimit=*/std::nullopt,
223 /*IsText=*/false));
224 }();
225
226 if (!Buf) {
227 Result.BufferError = llvm::toString(Buf.takeError());
229 return Result;
230 }
231
232 NewFileBuffer = std::move(*Buf);
233 ModuleBuffer = NewFileBuffer.get();
234 }
235
236 // Allocate bookkeeping for a module file not yet loaded into this reader.
237 auto NewModule = std::make_unique<ModuleFile>(Type, *FileKey, Generation);
238 NewModule->Index = Chain.size();
239 NewModule->FileName = FileName;
240 NewModule->ImportLoc = ImportLoc;
241 NewModule->InputFilesValidationTimestamp = InputFilesValidationTimestamp;
242 NewModule->Size = Size;
243 NewModule->ModTime = ModTime;
244 NewModule->Buffer = ModuleBuffer;
245 // Initialize the stream.
246 NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
247
248 // Check file properties.
249 if (isModuleFileOutOfDate(Size, ModTime, ExpectedSize, ExpectedModTime,
250 Result)) {
251 Result.setOutOfDate(NewModule->InputFilesValidationStatus);
252 return Result;
253 }
254
255 // Read the signature eagerly now so that we can check it. Avoid calling
256 // ReadSignature unless there's something to check though.
257 if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
258 ExpectedSignature, Result)) {
259 Result.setOutOfDate(NewModule->InputFilesValidationStatus);
260 return Result;
261 }
262
263 if (NewFileBuffer)
265 FileName, std::move(NewFileBuffer), Size, ModTime);
266
267 // We're keeping this module. Store it in the map.
268 Result.Module = Modules[*FileKey] = NewModule.get();
269
270 updateModuleImports(*NewModule, ImportedBy, ImportLoc);
271
272 if (!NewModule->isModule())
273 PCHChain.push_back(NewModule.get());
274 if (!ImportedBy)
275 Roots.push_back(NewModule.get());
276
277 Chain.push_back(std::move(NewModule));
279 return Result;
280}
281
283 auto Last = end();
284 if (First == Last)
285 return;
286
287 // Explicitly clear VisitOrder since we might not notice it is stale.
288 VisitOrder.clear();
289
290 // Collect the set of module file pointers that we'll be removing.
292 (llvm::pointer_iterator<ModuleIterator>(First)),
293 (llvm::pointer_iterator<ModuleIterator>(Last)));
294
295 auto IsVictim = [&](ModuleFile *MF) {
296 return victimSet.count(MF);
297 };
298 // Remove any references to the now-destroyed modules.
299 for (auto I = begin(); I != First; ++I) {
300 I->Imports.remove_if(IsVictim);
301 I->ImportedBy.remove_if(IsVictim);
302 }
303 llvm::erase_if(Roots, IsVictim);
304
305 // Remove the modules from the PCH chain.
306 for (auto I = First; I != Last; ++I) {
307 if (!I->isModule()) {
308 PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
309 break;
310 }
311 }
312
313 // Delete the modules.
314 for (ModuleIterator victim = First; victim != Last; ++victim)
315 Modules.erase(victim->FileKey);
316
317 Chain.erase(Chain.begin() + (First - begin()), Chain.end());
318}
319
320std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
321 // Fast path: if we have a cached state, use it.
322 if (FirstVisitState) {
323 auto Result = std::move(FirstVisitState);
324 FirstVisitState = std::move(Result->NextState);
325 return Result;
326 }
327
328 // Allocate and return a new state.
329 return std::make_unique<VisitState>(size());
330}
331
332void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
333 assert(State->NextState == nullptr && "Visited state is in list?");
334 State->NextState = std::move(FirstVisitState);
335 FirstVisitState = std::move(State);
336}
337
339 GlobalIndex = Index;
340 if (!GlobalIndex) {
341 ModulesInCommonWithGlobalIndex.clear();
342 return;
343 }
344
345 // Notify the global module index about all of the modules we've already
346 // loaded.
347 for (ModuleFile &M : *this)
348 if (!GlobalIndex->loadedModuleFile(&M))
349 ModulesInCommonWithGlobalIndex.push_back(&M);
350}
351
353 if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
354 return;
355
356 ModulesInCommonWithGlobalIndex.push_back(MF);
357}
358
360 const PCHContainerReader &PCHContainerRdr,
361 const HeaderSearch &HeaderSearchInfo)
362 : FileMgr(FileMgr), ModCache(ModCache), PCHContainerRdr(PCHContainerRdr),
363 HeaderSearchInfo(HeaderSearchInfo) {}
364
365void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
366 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
367 // If the visitation order vector is the wrong size, recompute the order.
368 if (VisitOrder.size() != Chain.size()) {
369 unsigned N = size();
370 VisitOrder.clear();
371 VisitOrder.reserve(N);
372
373 // Record the number of incoming edges for each module. When we
374 // encounter a module with no incoming edges, push it into the queue
375 // to seed the queue.
377 Queue.reserve(N);
378 llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
379 UnusedIncomingEdges.resize(size());
380 for (ModuleFile &M : llvm::reverse(*this)) {
381 unsigned Size = M.ImportedBy.size();
382 UnusedIncomingEdges[M.Index] = Size;
383 if (!Size)
384 Queue.push_back(&M);
385 }
386
387 // Traverse the graph, making sure to visit a module before visiting any
388 // of its dependencies.
389 while (!Queue.empty()) {
390 ModuleFile *CurrentModule = Queue.pop_back_val();
391 VisitOrder.push_back(CurrentModule);
392
393 // For any module that this module depends on, push it on the
394 // stack (if it hasn't already been marked as visited).
395 for (ModuleFile *M : llvm::reverse(CurrentModule->Imports)) {
396 // Remove our current module as an impediment to visiting the
397 // module we depend on. If we were the last unvisited module
398 // that depends on this particular module, push it into the
399 // queue to be visited.
400 unsigned &NumUnusedEdges = UnusedIncomingEdges[M->Index];
401 if (NumUnusedEdges && (--NumUnusedEdges == 0))
402 Queue.push_back(M);
403 }
404 }
405
406 assert(VisitOrder.size() == N && "Visitation order is wrong?");
407
408 FirstVisitState = nullptr;
409 }
410
411 auto State = allocateVisitState();
412 unsigned VisitNumber = State->NextVisitNumber++;
413
414 // If the caller has provided us with a hit-set that came from the global
415 // module index, mark every module file in common with the global module
416 // index that is *not* in that set as 'visited'.
417 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
418 for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
419 {
420 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
421 if (!ModuleFilesHit->count(M))
422 State->VisitNumber[M->Index] = VisitNumber;
423 }
424 }
425
426 for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
427 ModuleFile *CurrentModule = VisitOrder[I];
428 // Should we skip this module file?
429 if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
430 continue;
431
432 // Visit the module.
433 assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
434 State->VisitNumber[CurrentModule->Index] = VisitNumber;
435 if (!Visitor(*CurrentModule))
436 continue;
437
438 // The visitor has requested that cut off visitation of any
439 // module that the current module depends on. To indicate this
440 // behavior, we mark all of the reachable modules as having been visited.
441 ModuleFile *NextModule = CurrentModule;
442 do {
443 // For any module that this module depends on, push it on the
444 // stack (if it hasn't already been marked as visited).
445 for (llvm::SetVector<ModuleFile *>::iterator
446 M = NextModule->Imports.begin(),
447 MEnd = NextModule->Imports.end();
448 M != MEnd; ++M) {
449 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
450 State->Stack.push_back(*M);
451 State->VisitNumber[(*M)->Index] = VisitNumber;
452 }
453 }
454
455 if (State->Stack.empty())
456 break;
457
458 // Pop the next module off the stack.
459 NextModule = State->Stack.pop_back_val();
460 } while (true);
461 }
462
463 returnVisitState(std::move(State));
464}
465
466#ifndef NDEBUG
467namespace llvm {
468
469 template<>
470 struct GraphTraits<ModuleManager> {
472 using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
473 using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
474
476 return Node->Imports.begin();
477 }
478
480 return Node->Imports.end();
481 }
482
483 static nodes_iterator nodes_begin(const ModuleManager &Manager) {
484 return nodes_iterator(Manager.begin());
485 }
486
487 static nodes_iterator nodes_end(const ModuleManager &Manager) {
488 return nodes_iterator(Manager.end());
489 }
490 };
491
492 template<>
494 explicit DOTGraphTraits(bool IsSimple = false)
495 : DefaultDOTGraphTraits(IsSimple) {}
496
497 static bool renderGraphFromBottomUp() { return true; }
498
499 std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
500 return M->ModuleName;
501 }
502 };
503
504} // namespace llvm
505
507 llvm::ViewGraph(*this, "Modules");
508}
509#endif
Defines the clang::FileManager interface and associated types.
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy, SourceLocation ImportLoc)
Implements support for file system lookup, file system caching, and directory search management.
Definition FileManager.h:54
A global index for a set of module files, providing information about the identifiers within those mo...
Encapsulates the information needed to find the file referenced by a #include or #include_next,...
llvm::MemoryBuffer & addPCM(llvm::StringRef Filename, std::unique_ptr< llvm::MemoryBuffer > Buffer, off_t Size, time_t ModTime)
Store the PCM under the Filename.
The module cache used for compiling modules implicitly.
Definition ModuleCache.h:37
virtual InMemoryModuleCache & getInMemoryModuleCache()=0
Returns this process's view of the module cache.
Deduplication key for a loaded module file in ModuleManager.
Definition Module.h:79
Identifies a module file to be loaded.
Definition Module.h:109
bool isInMemory() const
Returns true iff this is an in-memory module file, false otherwise.
Definition Module.h:182
unsigned getImplicitModuleSuffixLength() const
Returns the suffix length for an implicit module name, zero otherwise.
Definition Module.h:171
Describes a module or submodule.
Definition Module.h:340
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
Encodes a location in the source.
The base class of the type hierarchy.
Definition TypeBase.h:1875
The result of attempting to add a new module.
@ Missing
The module file is missing.
@ NewlyLoaded
The module file was just loaded in response to this call.
@ AlreadyLoaded
The module file had already been loaded.
Information about a module that has been loaded by the ASTReader.
Definition ModuleFile.h:158
bool DirectlyImported
Whether this module has been directly imported by the user.
Definition ModuleFile.h:241
llvm::SetVector< ModuleFile * > ImportedBy
List of modules which depend on this module.
Definition ModuleFile.h:552
SourceLocation ImportLoc
The source location where this module was first imported.
Definition ModuleFile.h:277
unsigned Index
The index of this module in the list of modules.
Definition ModuleFile.h:171
llvm::SetVector< ModuleFile * > Imports
List of modules which this module directly imported.
Definition ModuleFile.h:555
ModuleKind Kind
The type of this module.
Definition ModuleFile.h:174
std::string ModuleName
The name of the module.
Definition ModuleFile.h:183
Manages the set of modules loaded by an AST reader.
AddModuleResult addModule(ModuleFileName FileName, ModuleKind Type, SourceLocation ImportLoc, ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, ASTFileSignature ExpectedSignature, ASTFileSignatureReader ReadSignature)
Attempts to create a new module and add it to the list of known modules.
ModuleFile * lookup(ModuleFileKey Key) const
Returns the module associated with the given module file key.
llvm::pointee_iterator< SmallVectorImpl< std::unique_ptr< ModuleFile > >::iterator > ModuleIterator
void moduleFileAccepted(ModuleFile *MF)
Notification from the AST reader that the given module file has been "accepted", and will not (can no...
ModuleManager(FileManager &FileMgr, ModuleCache &ModCache, const PCHContainerReader &PCHContainerRdr, const HeaderSearch &HeaderSearchInfo)
void viewGraph()
View the graphviz representation of the module graph.
ModuleCache & getModuleCache() const
ModuleIterator begin()
Forward iterator to traverse all loaded modules.
std::optional< ModuleFileKey > makeKey(const ModuleFileName &Name) const
Creates the deduplication key for use in ModuleManager.
void setGlobalIndex(GlobalModuleIndex *Index)
Set the global module index.
void removeModules(ModuleIterator First)
Remove the modules starting from First (to the end).
ModuleIterator end()
Forward iterator end-point to traverse all loaded modules.
void visit(llvm::function_ref< bool(ModuleFile &M)> Visitor, llvm::SmallPtrSetImpl< ModuleFile * > *ModuleFilesHit=nullptr)
Visit each of the modules.
unsigned size() const
Number of modules loaded.
ModuleFile * lookupByFileName(ModuleFileName FileName) const
Returns the module associated with the given module file name.
ASTFileSignature(*)(StringRef) ASTFileSignatureReader
ModuleFile * lookupByModuleName(StringRef ModName) const
Returns the module associated with the given module name.
@ Disabled
When the validation is disabled. For example, for a precompiled header.
Definition ModuleFile.h:141
@ NotStarted
Initial value, before the validation has been performed.
Definition ModuleFile.h:139
ModuleKind
Specifies the kind of module that has been loaded.
Definition ModuleFile.h:44
@ MK_ExplicitModule
File is an explicitly-loaded module.
Definition ModuleFile.h:49
@ MK_ImplicitModule
File is an implicitly-loaded module.
Definition ModuleFile.h:46
@ MK_PrebuiltModule
File is from a prebuilt module path.
Definition ModuleFile.h:61
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
The signature of a module, which is a hash of the AST content.
Definition Module.h:198
std::string getNodeLabel(ModuleFile *M, const ModuleManager &)
static ChildIteratorType child_end(NodeRef Node)
static nodes_iterator nodes_begin(const ModuleManager &Manager)
static ChildIteratorType child_begin(NodeRef Node)
pointer_iterator< ModuleManager::ModuleConstIterator > nodes_iterator
llvm::SetVector< ModuleFile * >::const_iterator ChildIteratorType
static nodes_iterator nodes_end(const ModuleManager &Manager)