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>
41using namespace serialization;
61 return Modules.lookup(
File);
64std::unique_ptr<llvm::MemoryBuffer>
70 return std::move(InMemoryBuffers[*Entry]);
75 std::string &ErrorStr) {
76 if (!ExpectedSignature || Signature == ExpectedSignature)
80 Signature ?
"signature mismatch" :
"could not read module signature";
88 ImportedBy->
Imports.insert(&MF);
101 off_t ExpectedSize, time_t ExpectedModTime,
105 std::string &ErrorStr) {
125 ErrorStr = IgnoreModTime ?
"module file has a different size than expected"
126 :
"module file has a different size or "
127 "modification time than expected";
132 ErrorStr =
"module file not found";
154 return Entry.getName() == MF->FileName;
158 if (
ModuleFile *ModuleEntry = Modules.lookup(*Entry)) {
159 if (implicitModuleNamesMatch(
Type, ModuleEntry, *Entry)) {
161 if (
checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
171 auto NewModule = std::make_unique<ModuleFile>(
Type, *Entry, Generation);
172 NewModule->Index = Chain.size();
173 NewModule->FileName =
FileName.str();
174 NewModule->ImportLoc = ImportLoc;
175 NewModule->InputFilesValidationTimestamp = 0;
178 NewModule->InputFilesValidationTimestamp =
179 ModCache->getModuleTimestamp(NewModule->FileName);
190 }
else if (llvm::MemoryBuffer *Buffer =
193 NewModule->Buffer = Buffer;
196 }
else if (
getModuleCache().getInMemoryModuleCache().shouldBuildPCM(
214 ErrorStr = Buf.getError().message();
223 NewModule->Data = PCHContainerRdr.
ExtractPCH(*NewModule->Buffer);
227 if (ExpectedSignature &&
checkSignature(ReadSignature(NewModule->Data),
228 ExpectedSignature, ErrorStr))
232 Module = Modules[*Entry] = NewModule.get();
236 if (!NewModule->isModule())
237 PCHChain.push_back(NewModule.get());
239 Roots.push_back(NewModule.get());
241 Chain.push_back(std::move(NewModule));
255 (llvm::pointer_iterator<ModuleIterator>(
First)),
256 (llvm::pointer_iterator<ModuleIterator>(
Last)));
259 return victimSet.count(MF);
263 I->Imports.remove_if(IsVictim);
264 I->ImportedBy.remove_if(IsVictim);
266 llvm::erase_if(Roots, IsVictim);
270 if (!I->isModule()) {
271 PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
278 Modules.erase(victim->File);
280 Chain.erase(Chain.begin() + (
First -
begin()), Chain.end());
285 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
288 InMemoryBuffers[Entry] = std::move(Buffer);
291std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
293 if (FirstVisitState) {
294 auto Result = std::move(FirstVisitState);
295 FirstVisitState = std::move(
Result->NextState);
300 return std::make_unique<VisitState>(
size());
303void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
304 assert(State->NextState ==
nullptr &&
"Visited state is in list?");
305 State->NextState = std::move(FirstVisitState);
306 FirstVisitState = std::move(State);
312 ModulesInCommonWithGlobalIndex.clear();
320 ModulesInCommonWithGlobalIndex.push_back(&M);
327 ModulesInCommonWithGlobalIndex.push_back(MF);
333 : FileMgr(FileMgr), ModCache(&ModCache), PCHContainerRdr(PCHContainerRdr),
334 HeaderSearchInfo(HeaderSearchInfo) {}
337 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
339 if (VisitOrder.size() != Chain.size()) {
342 VisitOrder.reserve(N);
350 UnusedIncomingEdges.resize(
size());
353 UnusedIncomingEdges[M.
Index] = Size;
360 while (!Queue.empty()) {
361 ModuleFile *CurrentModule = Queue.pop_back_val();
362 VisitOrder.push_back(CurrentModule);
371 unsigned &NumUnusedEdges = UnusedIncomingEdges[M->
Index];
372 if (NumUnusedEdges && (--NumUnusedEdges == 0))
377 assert(VisitOrder.size() == N &&
"Visitation order is wrong?");
379 FirstVisitState =
nullptr;
382 auto State = allocateVisitState();
383 unsigned VisitNumber = State->NextVisitNumber++;
388 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
389 for (
unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
391 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
392 if (!ModuleFilesHit->count(M))
393 State->VisitNumber[M->
Index] = VisitNumber;
397 for (
unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
400 if (State->VisitNumber[CurrentModule->
Index] == VisitNumber)
404 assert(State->VisitNumber[CurrentModule->
Index] == VisitNumber - 1);
405 State->VisitNumber[CurrentModule->
Index] = VisitNumber;
406 if (!Visitor(*CurrentModule))
416 for (llvm::SetVector<ModuleFile *>::iterator
417 M = NextModule->
Imports.begin(),
418 MEnd = NextModule->
Imports.end();
420 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
421 State->Stack.push_back(*M);
422 State->VisitNumber[(*M)->Index] = VisitNumber;
426 if (State->Stack.empty())
430 NextModule = State->Stack.pop_back_val();
434 returnVisitState(std::move(State));
438 time_t ExpectedModTime,
451 ((ExpectedSize && ExpectedSize !=
File->getSize()) ||
452 (ExpectedModTime && ExpectedModTime !=
File->getModificationTime())))
470 return Node->Imports.begin();
474 return Node->Imports.end();
501 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)
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Cached information about one file (either on disk or in the virtual file system).
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
llvm::Expected< FileEntryRef > getSTDIN()
Get the FileEntryRef for stdin, returning an error if stdin cannot be read.
FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, time_t ModificationTime)
Retrieve a file entry for a "virtual" file that acts as if there were a file with the given name on d...
A global index for a set of module files, providing information about the identifiers within those mo...
bool loadedModuleFile(ModuleFile *File)
Note that the given module file has been loaded.
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.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
Describes a module or submodule.
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const =0
Returns the serialized AST inside the PCH container Buffer.
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.
bool lookupModuleFile(StringRef FileName, off_t ExpectedSize, time_t ExpectedModTime, OptionalFileEntryRef &File)
Attempt to resolve the given module file name to a file entry.
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...
ModuleFile * lookup(const FileEntry *File) const
Returns the module associated with the given module file.
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.
ModuleFile * lookupByFileName(StringRef FileName) const
Returns the module associated with the given file name.
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.
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.
AddModuleResult addModule(StringRef 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.
ASTFileSignature(*)(StringRef) ASTFileSignatureReader
llvm::pointee_iterator< SmallVectorImpl< std::unique_ptr< ModuleFile > >::iterator > ModuleIterator
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.
@ 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)