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/ErrorOr.h"
32#include "llvm/Support/GraphWriter.h"
33#include "llvm/Support/MemoryBuffer.h"
34#include "llvm/Support/VirtualFileSystem.h"
38#include <system_error>
44 if (
const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
52 std::optional<ModuleFileKey> Key = Name.
makeKey(FileMgr);
53 return Key ?
lookup(*Key) :
nullptr;
57 return Modules.lookup(Key);
60std::unique_ptr<llvm::MemoryBuffer>
62 auto Entry = FileMgr.getOptionalFileRef(Name,
false,
66 return std::move(InMemoryBuffers[*Entry]);
70 time_t ExpectedModTime, std::string &ErrorStr) {
71 if (ExpectedSize && ExpectedSize != Size) {
72 ErrorStr =
"module file has a different size than expected";
76 if (ExpectedModTime && ExpectedModTime != ModTime) {
77 ErrorStr =
"module file has a different modification time than expected";
86 std::string &ErrorStr) {
87 if (!ExpectedSignature || Signature == ExpectedSignature)
91 Signature ?
"signature mismatch" :
"could not read module signature";
99 ImportedBy->
Imports.insert(&MF);
110 ModuleFile *ImportedBy,
unsigned Generation, off_t ExpectedSize,
113 std::string &ErrorStr) {
116 uint64_t InputFilesValidationTimestamp = 0;
118 InputFilesValidationTimestamp = ModCache.getModuleTimestamp(
FileName);
132 std::optional<ModuleFileKey> FileKey =
FileName.makeKey(FileMgr);
134 ErrorStr =
"module file not found";
141 if (
checkModuleFile(ModuleEntry->Size, ModuleEntry->ModTime, ExpectedSize,
142 ExpectedModTime, ErrorStr))
146 if (
checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
155 off_t Size = ExpectedSize;
156 time_t ModTime = ExpectedModTime;
157 llvm::MemoryBuffer *ModuleBuffer =
nullptr;
158 std::unique_ptr<llvm::MemoryBuffer> NewFileBuffer =
nullptr;
163 }
else if (llvm::MemoryBuffer *Buffer =
166 ModuleBuffer = Buffer;
167 if (!
FileName.getImplicitModuleSuffixLength()) {
176 FileMgr.getOptionalFileRef(
FileName,
true,
179 ErrorStr =
"module file not found";
185 }
else if (
getModuleCache().getInMemoryModuleCache().shouldBuildPCM(
192 expectedToOptional(
FileName == StringRef(
"-")
194 : FileMgr.getFileRef(
FileName,
true,
197 ErrorStr =
"module file not found";
207 auto Buf = FileMgr.getBufferForFile(*Entry,
212 ErrorStr = Buf.getError().message();
218 NewFileBuffer = std::move(*Buf);
219 ModuleBuffer = NewFileBuffer.get();
223 auto NewModule = std::make_unique<ModuleFile>(
Type, *FileKey, Generation);
224 NewModule->Index = Chain.size();
226 NewModule->ImportLoc = ImportLoc;
227 NewModule->InputFilesValidationTimestamp = InputFilesValidationTimestamp;
228 NewModule->Size = Size;
229 NewModule->ModTime = ModTime;
230 NewModule->Buffer = ModuleBuffer;
232 NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
235 if (
checkModuleFile(Size, ModTime, ExpectedSize, ExpectedModTime, ErrorStr))
240 if (ExpectedSignature &&
checkSignature(ReadSignature(NewModule->Data),
241 ExpectedSignature, ErrorStr))
246 std::move(NewFileBuffer));
249 Module = Modules[*FileKey] = NewModule.get();
253 if (!NewModule->isModule())
254 PCHChain.push_back(NewModule.get());
256 Roots.push_back(NewModule.get());
258 Chain.push_back(std::move(NewModule));
272 (llvm::pointer_iterator<ModuleIterator>(
First)),
273 (llvm::pointer_iterator<ModuleIterator>(
Last)));
276 return victimSet.count(MF);
280 I->Imports.remove_if(IsVictim);
281 I->ImportedBy.remove_if(IsVictim);
283 llvm::erase_if(Roots, IsVictim);
287 if (!I->isModule()) {
288 PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
295 Modules.erase(victim->FileKey);
297 Chain.erase(Chain.begin() + (
First -
begin()), Chain.end());
302 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
304 FileMgr.getVirtualFileRef(
FileName, Buffer->getBufferSize(), 0);
305 InMemoryBuffers[Entry] = std::move(Buffer);
308std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
310 if (FirstVisitState) {
311 auto Result = std::move(FirstVisitState);
312 FirstVisitState = std::move(
Result->NextState);
317 return std::make_unique<VisitState>(
size());
320void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
321 assert(State->NextState ==
nullptr &&
"Visited state is in list?");
322 State->NextState = std::move(FirstVisitState);
323 FirstVisitState = std::move(State);
329 ModulesInCommonWithGlobalIndex.clear();
336 if (!GlobalIndex->loadedModuleFile(&M))
337 ModulesInCommonWithGlobalIndex.push_back(&M);
341 if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
344 ModulesInCommonWithGlobalIndex.push_back(MF);
350 : FileMgr(FileMgr), ModCache(ModCache), PCHContainerRdr(PCHContainerRdr),
351 HeaderSearchInfo(HeaderSearchInfo) {}
354 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
356 if (VisitOrder.size() != Chain.size()) {
359 VisitOrder.reserve(N);
367 UnusedIncomingEdges.resize(
size());
370 UnusedIncomingEdges[M.
Index] = Size;
377 while (!Queue.empty()) {
378 ModuleFile *CurrentModule = Queue.pop_back_val();
379 VisitOrder.push_back(CurrentModule);
388 unsigned &NumUnusedEdges = UnusedIncomingEdges[M->
Index];
389 if (NumUnusedEdges && (--NumUnusedEdges == 0))
394 assert(VisitOrder.size() == N &&
"Visitation order is wrong?");
396 FirstVisitState =
nullptr;
399 auto State = allocateVisitState();
400 unsigned VisitNumber = State->NextVisitNumber++;
405 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
406 for (
unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
408 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
409 if (!ModuleFilesHit->count(M))
410 State->VisitNumber[M->
Index] = VisitNumber;
414 for (
unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
417 if (State->VisitNumber[CurrentModule->
Index] == VisitNumber)
421 assert(State->VisitNumber[CurrentModule->
Index] == VisitNumber - 1);
422 State->VisitNumber[CurrentModule->
Index] = VisitNumber;
423 if (!Visitor(*CurrentModule))
433 for (llvm::SetVector<ModuleFile *>::iterator
434 M = NextModule->
Imports.begin(),
435 MEnd = NextModule->
Imports.end();
437 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
438 State->Stack.push_back(*M);
439 State->VisitNumber[(*M)->Index] = VisitNumber;
443 if (State->Stack.empty())
447 NextModule = State->Stack.pop_back_val();
451 returnVisitState(std::move(State));
495 llvm::ViewGraph(*
this,
"Modules");
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool checkSignature(ASTFileSignature Signature, ASTFileSignature ExpectedSignature, std::string &ErrorStr)
static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy, SourceLocation ImportLoc)
static bool checkModuleFile(off_t Size, time_t ModTime, off_t ExpectedSize, time_t ExpectedModTime, std::string &ErrorStr)
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
time_t getModificationTime() const
Implements support for file system lookup, file system caching, and directory search management.
A global index for a set of module files, providing information about the identifiers within those mo...
llvm::MemoryBuffer & addBuiltPCM(llvm::StringRef Filename, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Store a just-built PCM under the Filename.
llvm::MemoryBuffer & addPCM(llvm::StringRef Filename, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Store the PCM under the Filename.
The module cache used for compiling modules implicitly.
virtual InMemoryModuleCache & getInMemoryModuleCache()=0
Returns this process's view of the module cache.
Deduplication key for a loaded module file in ModuleManager.
Identifies a module file to be loaded.
std::optional< ModuleFileKey > makeKey(FileManager &FileMgr) const
Creates the deduplication key for use in ModuleManager.
Describes a module or submodule.
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.
Information about a module that has been loaded by the ASTReader.
bool DirectlyImported
Whether this module has been directly imported by the user.
llvm::SetVector< ModuleFile * > ImportedBy
List of modules which depend on this module.
SourceLocation ImportLoc
The source location where this module was first imported.
unsigned Index
The index of this module in the list of modules.
llvm::SetVector< ModuleFile * > Imports
List of modules which this module directly imported.
ModuleKind Kind
The type of this module.
std::string ModuleName
The name of the module.
Manages the set of modules loaded by an AST reader.
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
AddModuleResult
The result of attempting to add a new module.
@ Missing
The module file is missing.
@ OutOfDate
The module file is out-of-date.
@ NewlyLoaded
The module file was just loaded in response to this call.
@ AlreadyLoaded
The module file had already been loaded.
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.
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.
std::unique_ptr< llvm::MemoryBuffer > lookupBuffer(StringRef Name)
Returns the in-memory (virtual file) buffer with the given name.
void addInMemoryBuffer(StringRef FileName, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Add an in-memory buffer the list of known buffers.
AddModuleResult addModule(ModuleFileName FileName, ModuleKind Type, SourceLocation ImportLoc, ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, ASTFileSignature ExpectedSignature, ASTFileSignatureReader ReadSignature, ModuleFile *&Module, std::string &ErrorStr)
Attempts to create a new module and add it to the list of known 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.
ModuleKind
Specifies the kind of module that has been loaded.
@ MK_ExplicitModule
File is an explicitly-loaded module.
@ MK_ImplicitModule
File is an implicitly-loaded module.
@ MK_PrebuiltModule
File is from a prebuilt module path.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
@ Result
The result type of a method or function.
Diagnostic wrappers for TextAPI types for error reporting.
The signature of a module, which is a hash of the AST content.
DOTGraphTraits(bool IsSimple=false)
std::string getNodeLabel(ModuleFile *M, const ModuleManager &)
static bool renderGraphFromBottomUp()
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)