20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/Path.h"
22 #include <system_error>
25 #include "llvm/Support/GraphWriter.h"
28 using namespace clang;
29 using namespace serialization;
41 auto Known = Modules.find(File);
42 if (Known == Modules.end())
48 std::unique_ptr<llvm::MemoryBuffer>
52 return std::move(InMemoryBuffers[Entry]);
57 std::string &ErrorStr) {
58 if (!ExpectedSignature || Signature == ExpectedSignature)
62 Signature ?
"signature mismatch" :
"could not read module signature";
70 ImportedBy->
Imports.insert(&MF);
83 off_t ExpectedSize, time_t ExpectedModTime,
85 ASTFileSignatureReader ReadSignature,
87 std::string &ErrorStr) {
101 ErrorStr =
"module file out of date";
105 if (!Entry && FileName !=
"-") {
106 ErrorStr =
"module file not found";
111 if (
ModuleFile *ModuleEntry = Modules.lookup(Entry)) {
113 if (
checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
116 Module = ModuleEntry;
122 auto NewModule = llvm::make_unique<ModuleFile>(Type, Generation);
123 NewModule->Index = Chain.size();
124 NewModule->FileName = FileName.str();
125 NewModule->File = Entry;
126 NewModule->ImportLoc = ImportLoc;
127 NewModule->InputFilesValidationTimestamp = 0;
130 std::string TimestampFilename = NewModule->getTimestampFilename();
134 NewModule->InputFilesValidationTimestamp =
141 NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(
Buffer));
142 }
else if (llvm::MemoryBuffer *
Buffer = PCMCache->lookupBuffer(FileName)) {
143 NewModule->Buffer =
Buffer;
146 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
147 if (FileName ==
"-") {
148 Buf = llvm::MemoryBuffer::getSTDIN();
160 ErrorStr = Buf.getError().message();
164 NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(*Buf));
168 NewModule->Data = PCHContainerRdr.
ExtractPCH(*NewModule->Buffer);
172 if (ExpectedSignature &&
checkSignature(ReadSignature(NewModule->Data),
173 ExpectedSignature, ErrorStr)) {
176 if (!PCMCache->tryToRemoveBuffer(NewModule->FileName))
182 Module = Modules[Entry] = NewModule.get();
186 if (!NewModule->isModule())
187 PCHChain.push_back(NewModule.get());
189 Roots.push_back(NewModule.get());
191 Chain.push_back(std::move(NewModule));
197 llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
208 llvm::SmallPtrSet<ModuleFile *, 4> victimSet(
209 (llvm::pointer_iterator<ModuleIterator>(First)),
210 (llvm::pointer_iterator<ModuleIterator>(Last)));
213 return victimSet.count(MF);
216 for (
auto I =
begin();
I != First; ++
I) {
217 I->Imports.remove_if(IsVictim);
218 I->ImportedBy.remove_if(IsVictim);
220 Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
224 for (
auto I = First;
I != Last; ++
I) {
225 if (!
I->isModule()) {
226 PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), &*
I),
234 Modules.erase(victim->File);
237 StringRef ModuleName = victim->ModuleName;
239 mod->setASTFile(
nullptr);
250 if (LoadedSuccessfully.count(&*victim) == 0 &&
251 !PCMCache->tryToRemoveBuffer(victim->FileName))
256 Chain.erase(Chain.begin() + (First -
begin()), Chain.end());
261 std::unique_ptr<llvm::MemoryBuffer>
Buffer) {
265 InMemoryBuffers[Entry] = std::move(Buffer);
268 ModuleManager::VisitState *ModuleManager::allocateVisitState() {
270 if (FirstVisitState) {
271 VisitState *
Result = FirstVisitState;
272 FirstVisitState = FirstVisitState->NextState;
273 Result->NextState =
nullptr;
278 return new VisitState(
size());
281 void ModuleManager::returnVisitState(VisitState *
State) {
282 assert(State->NextState ==
nullptr &&
"Visited state is in list?");
283 State->NextState = FirstVisitState;
284 FirstVisitState =
State;
290 ModulesInCommonWithGlobalIndex.clear();
298 ModulesInCommonWithGlobalIndex.push_back(&M);
305 ModulesInCommonWithGlobalIndex.push_back(MF);
310 : FileMgr(FileMgr), PCMCache(&PCMCache), PCHContainerRdr(PCHContainerRdr),
311 GlobalIndex(), FirstVisitState(nullptr) {}
316 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
318 if (VisitOrder.size() != Chain.size()) {
321 VisitOrder.reserve(N);
329 UnusedIncomingEdges.resize(
size());
332 UnusedIncomingEdges[M.
Index] = Size;
339 while (!Queue.empty()) {
340 ModuleFile *CurrentModule = Queue.pop_back_val();
341 VisitOrder.push_back(CurrentModule);
345 for (
auto M = CurrentModule->
Imports.rbegin(),
346 MEnd = CurrentModule->
Imports.rend();
352 unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
353 if (NumUnusedEdges && (--NumUnusedEdges == 0))
358 assert(VisitOrder.size() == N &&
"Visitation order is wrong?");
360 delete FirstVisitState;
361 FirstVisitState =
nullptr;
364 VisitState *
State = allocateVisitState();
365 unsigned VisitNumber = State->NextVisitNumber++;
370 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
371 for (
unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size();
I != N; ++
I)
374 if (!ModuleFilesHit->count(M))
375 State->VisitNumber[M->
Index] = VisitNumber;
379 for (
unsigned I = 0, N = VisitOrder.size();
I != N; ++
I) {
382 if (State->VisitNumber[CurrentModule->
Index] == VisitNumber)
386 assert(State->VisitNumber[CurrentModule->
Index] == VisitNumber - 1);
387 State->VisitNumber[CurrentModule->
Index] = VisitNumber;
388 if (!Visitor(*CurrentModule))
398 for (llvm::SetVector<ModuleFile *>::iterator
399 M = NextModule->
Imports.begin(),
400 MEnd = NextModule->
Imports.end();
402 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
403 State->Stack.push_back(*M);
404 State->VisitNumber[(*M)->Index] = VisitNumber;
408 if (State->Stack.empty())
412 NextModule = State->Stack.pop_back_val();
416 returnVisitState(State);
421 time_t ExpectedModTime,
423 if (FileName ==
"-") {
430 File = FileMgr.
getFile(FileName,
true,
false);
434 if ((ExpectedSize && ExpectedSize != File->
getSize()) ||
484 llvm::ViewGraph(*
this,
"Modules");
Implements support for file system lookup, file system caching, and directory search management...
virtual StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const =0
Returns the serialized AST inside the PCH container Buffer.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
unsigned size() const
Number of modules loaded.
static bool renderGraphFromBottomUp()
std::string ModuleName
The name of the module.
The module file is out-of-date.
The base class of the type hierarchy.
DOTGraphTraits(bool IsSimple=false)
unsigned Index
The index of this module in the list of modules.
std::unique_ptr< llvm::MemoryBuffer > Buffer
void visit(llvm::function_ref< bool(ModuleFile &M)> Visitor, llvm::SmallPtrSetImpl< ModuleFile * > *ModuleFilesHit=nullptr)
Visit each of the modules.
Manages the set of modules loaded by an AST reader.
Manage memory buffers across multiple users.
SourceLocation ImportLoc
The source location where this module was first imported.
AddModuleResult
The result of attempting to add a new module.
ModuleIterator begin()
Forward iterator to traverse all loaded modules.
void viewGraph()
View the graphviz representation of the module graph.
The signature of a module, which is a hash of the AST content.
void setGlobalIndex(GlobalModuleIndex *Index)
Set the global module index.
Describes a module or submodule.
bool lookupModuleFile(StringRef FileName, off_t ExpectedSize, time_t ExpectedModTime, const FileEntry *&File)
Attempt to resolve the given module file name to a file entry.
ModuleIterator end()
Forward iterator end-point to traverse all loaded modules.
The module file is missing.
llvm::sys::TimePoint getLastModificationTime() const
The result of a status operation.
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
detail::InMemoryDirectory::const_iterator I
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
ModuleKind
Specifies the kind of module that has been loaded.
File is from a prebuilt module path.
llvm::pointee_iterator< SmallVectorImpl< std::unique_ptr< ModuleFile > >::iterator > ModuleIterator
static nodes_iterator nodes_end(const ModuleManager &Manager)
Information about a module that has been loaded by the ASTReader.
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.
void addInMemoryBuffer(StringRef FileName, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Add an in-memory buffer the list of known buffers.
static nodes_iterator nodes_begin(const ModuleManager &Manager)
Encodes a location in the source.
File is an implicitly-loaded module.
Cached information about one file (either on disk or in the virtual file system). ...
static ChildIteratorType child_begin(NodeRef Node)
ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache, const PCHContainerReader &PCHContainerRdr)
llvm::SetVector< ModuleFile * >::const_iterator ChildIteratorType
const FileEntry * getVirtualFile(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...
llvm::SetVector< ModuleFile * > ImportedBy
List of modules which depend on this module.
A global index for a set of module files, providing information about the identifiers within those mo...
The module file was just loaded in response to this call.
ast_type_traits::DynTypedNode Node
void removeModules(ModuleIterator First, llvm::SmallPtrSetImpl< ModuleFile * > &LoadedSuccessfully, ModuleMap *modMap)
Remove the modules starting from First (to the end).
pointer_iterator< ModuleManager::ModuleConstIterator > nodes_iterator
File is an explicitly-loaded module.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const FileEntry *Entry, bool isVolatile=false, bool ShouldCloseOpenFile=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy, SourceLocation ImportLoc)
void moduleFileAccepted(ModuleFile *MF)
Notification from the AST reader that the given module file has been "accepted", and will not (can no...
time_t getModificationTime() const
std::string getNodeLabel(ModuleFile *M, const ModuleManager &)
ModuleFile * lookup(StringRef Name) const
Returns the module associated with the given name.
bool getNoncachedStatValue(StringRef Path, vfs::Status &Result)
Get the 'stat' information for the given Path.
The module file had already been loaded.
void invalidateCache(const FileEntry *Entry)
Remove the real file Entry from the cache.
static ChildIteratorType child_end(NodeRef Node)
bool DirectlyImported
Whether this module has been directly imported by the user.
llvm::SetVector< ModuleFile * > Imports
List of modules which this module depends on.
std::unique_ptr< llvm::MemoryBuffer > lookupBuffer(StringRef Name)
Returns the in-memory (virtual file) buffer with the given name.
bool loadedModuleFile(ModuleFile *File)
Note that the given module file has been loaded.
static bool checkSignature(ASTFileSignature Signature, ASTFileSignature ExpectedSignature, std::string &ErrorStr)