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 auto Entry = FileMgr.getOptionalFileRef(Name,
false,
53 if (
const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
61 return Modules.lookup(
File);
64std::unique_ptr<llvm::MemoryBuffer>
66 auto Entry = FileMgr.getOptionalFileRef(Name,
false,
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) {
108 uint64_t InputFilesValidationTimestamp = 0;
110 InputFilesValidationTimestamp = ModCache.getModuleTimestamp(
FileName);
129 ErrorStr = IgnoreModTime ?
"module file has a different size than expected"
130 :
"module file has a different size or "
131 "modification time than expected";
136 ErrorStr =
"module file not found";
158 return Entry.getName() == MF->FileName;
162 if (
ModuleFile *ModuleEntry = Modules.lookup(*Entry)) {
163 if (implicitModuleNamesMatch(
Type, ModuleEntry, *Entry)) {
165 if (
checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
175 auto NewModule = std::make_unique<ModuleFile>(
Type, *Entry, Generation);
176 NewModule->Index = Chain.size();
177 NewModule->FileName =
FileName.str();
178 NewModule->ImportLoc = ImportLoc;
179 NewModule->InputFilesValidationTimestamp = InputFilesValidationTimestamp;
182 std::unique_ptr<llvm::MemoryBuffer> NewFileBuffer =
nullptr;
191 }
else if (llvm::MemoryBuffer *Buffer =
194 NewModule->Buffer = Buffer;
197 }
else if (
getModuleCache().getInMemoryModuleCache().shouldBuildPCM(
210 auto Buf = FileMgr.getBufferForFile(NewModule->File,
215 ErrorStr = Buf.getError().message();
219 NewFileBuffer = std::move(*Buf);
220 NewModule->Buffer = NewFileBuffer.get();
224 NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
228 if (ExpectedSignature &&
checkSignature(ReadSignature(NewModule->Data),
229 ExpectedSignature, ErrorStr))
234 std::move(NewFileBuffer));
237 Module = Modules[*Entry] = NewModule.get();
241 if (!NewModule->isModule())
242 PCHChain.push_back(NewModule.get());
244 Roots.push_back(NewModule.get());
246 Chain.push_back(std::move(NewModule));
260 (llvm::pointer_iterator<ModuleIterator>(
First)),
261 (llvm::pointer_iterator<ModuleIterator>(
Last)));
264 return victimSet.count(MF);
268 I->Imports.remove_if(IsVictim);
269 I->ImportedBy.remove_if(IsVictim);
271 llvm::erase_if(Roots, IsVictim);
275 if (!I->isModule()) {
276 PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
283 Modules.erase(victim->File);
285 Chain.erase(Chain.begin() + (
First -
begin()), Chain.end());
290 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
292 FileMgr.getVirtualFileRef(
FileName, Buffer->getBufferSize(), 0);
293 InMemoryBuffers[Entry] = std::move(Buffer);
296std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
298 if (FirstVisitState) {
299 auto Result = std::move(FirstVisitState);
300 FirstVisitState = std::move(
Result->NextState);
305 return std::make_unique<VisitState>(
size());
308void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
309 assert(State->NextState ==
nullptr &&
"Visited state is in list?");
310 State->NextState = std::move(FirstVisitState);
311 FirstVisitState = std::move(State);
317 ModulesInCommonWithGlobalIndex.clear();
324 if (!GlobalIndex->loadedModuleFile(&M))
325 ModulesInCommonWithGlobalIndex.push_back(&M);
329 if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
332 ModulesInCommonWithGlobalIndex.push_back(MF);
338 : FileMgr(FileMgr), ModCache(ModCache), PCHContainerRdr(PCHContainerRdr),
339 HeaderSearchInfo(HeaderSearchInfo) {}
342 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
344 if (VisitOrder.size() != Chain.size()) {
347 VisitOrder.reserve(N);
355 UnusedIncomingEdges.resize(
size());
358 UnusedIncomingEdges[M.
Index] = Size;
365 while (!Queue.empty()) {
366 ModuleFile *CurrentModule = Queue.pop_back_val();
367 VisitOrder.push_back(CurrentModule);
376 unsigned &NumUnusedEdges = UnusedIncomingEdges[M->
Index];
377 if (NumUnusedEdges && (--NumUnusedEdges == 0))
382 assert(VisitOrder.size() == N &&
"Visitation order is wrong?");
384 FirstVisitState =
nullptr;
387 auto State = allocateVisitState();
388 unsigned VisitNumber = State->NextVisitNumber++;
393 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
394 for (
unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
396 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
397 if (!ModuleFilesHit->count(M))
398 State->VisitNumber[M->
Index] = VisitNumber;
402 for (
unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
405 if (State->VisitNumber[CurrentModule->
Index] == VisitNumber)
409 assert(State->VisitNumber[CurrentModule->
Index] == VisitNumber - 1);
410 State->VisitNumber[CurrentModule->
Index] = VisitNumber;
411 if (!Visitor(*CurrentModule))
421 for (llvm::SetVector<ModuleFile *>::iterator
422 M = NextModule->
Imports.begin(),
423 MEnd = NextModule->
Imports.end();
425 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
426 State->Stack.push_back(*M);
427 State->VisitNumber[(*M)->Index] = VisitNumber;
431 if (State->Stack.empty())
435 NextModule = State->Stack.pop_back_val();
439 returnVisitState(std::move(State));
443 time_t ExpectedModTime,
446 File = expectedToOptional(FileMgr.getSTDIN());
456 ((ExpectedSize && ExpectedSize !=
File->getSize()) ||
457 (ExpectedModTime && ExpectedModTime !=
File->getModificationTime())))
506 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.
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.
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.
llvm::pointee_iterator< SmallVectorImpl< std::unique_ptr< ModuleFile > >::iterator > ModuleIterator
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
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)