19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <system_error>
25 #include "llvm/Support/GraphWriter.h"
28 using namespace clang;
29 using namespace serialization;
41 llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
43 if (Known == Modules.end())
49 std::unique_ptr<llvm::MemoryBuffer>
53 return std::move(InMemoryBuffers[Entry]);
60 off_t ExpectedSize, time_t ExpectedModTime,
62 ASTFileSignatureReader ReadSignature,
64 std::string &ErrorStr) {
78 ErrorStr =
"module file out of date";
82 if (!Entry && FileName !=
"-") {
83 ErrorStr =
"module file not found";
89 bool NewModule =
false;
93 New->
Index = Chain.size();
114 if (std::unique_ptr<llvm::MemoryBuffer> Buffer =
lookupBuffer(FileName)) {
116 New->
Buffer = std::move(Buffer);
119 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf(
120 (std::error_code()));
121 if (FileName ==
"-") {
122 Buf = llvm::MemoryBuffer::getSTDIN();
134 ErrorStr = Buf.getError().message();
138 New->
Buffer = std::move(*Buf);
145 if (ExpectedSignature) {
151 if (ModuleEntry->
Signature != ExpectedSignature) {
152 ErrorStr = ModuleEntry->
Signature ?
"signature mismatch"
153 :
"could not read module signature";
159 Modules.erase(Entry);
160 assert(Chain.back() == ModuleEntry);
162 if (Roots.back() == ModuleEntry)
174 ImportedBy->
Imports.insert(ModuleEntry);
182 Module = ModuleEntry;
188 llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
194 llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
197 return victimSet.count(MF);
200 for (
unsigned i = 0, n = Chain.size(); i != n; ++i) {
201 Chain[i]->ImportedBy.remove_if(IsVictim);
203 Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
208 Modules.erase((*victim)->File);
211 StringRef ModuleName = (*victim)->ModuleName;
213 mod->setASTFile(
nullptr);
220 if (LoadedSuccessfully.count(*victim) == 0)
227 Chain.erase(first, last);
232 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
236 InMemoryBuffers[Entry] = std::move(Buffer);
243 if (!Modules.count(File))
244 AdditionalKnownModuleFiles.insert(File);
248 ModuleManager::VisitState *ModuleManager::allocateVisitState() {
250 if (FirstVisitState) {
251 VisitState *
Result = FirstVisitState;
252 FirstVisitState = FirstVisitState->NextState;
253 Result->NextState =
nullptr;
258 return new VisitState(
size());
261 void ModuleManager::returnVisitState(VisitState *
State) {
262 assert(State->NextState ==
nullptr &&
"Visited state is in list?");
263 State->NextState = FirstVisitState;
264 FirstVisitState =
State;
270 ModulesInCommonWithGlobalIndex.clear();
276 for (
unsigned I = 0, N = Chain.size(); I != N; ++I) {
278 ModulesInCommonWithGlobalIndex.push_back(Chain[I]);
284 AdditionalKnownModuleFiles.remove(MF->
File);
289 ModulesInCommonWithGlobalIndex.push_back(MF);
294 : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr), GlobalIndex(),
295 FirstVisitState(nullptr) {}
298 for (
unsigned i = 0, e = Chain.size(); i != e; ++i)
299 delete Chain[e - i - 1];
300 delete FirstVisitState;
306 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
308 if (VisitOrder.size() != Chain.size()) {
311 VisitOrder.reserve(N);
319 UnusedIncomingEdges.reserve(
size());
321 if (
unsigned Size = (*M)->ImportedBy.size())
322 UnusedIncomingEdges.push_back(Size);
324 UnusedIncomingEdges.push_back(0);
331 unsigned QueueStart = 0;
332 while (QueueStart < Queue.size()) {
333 ModuleFile *CurrentModule = Queue[QueueStart++];
334 VisitOrder.push_back(CurrentModule);
338 for (llvm::SetVector<ModuleFile *>::iterator
339 M = CurrentModule->
Imports.begin(),
340 MEnd = CurrentModule->
Imports.end();
346 unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
347 if (NumUnusedEdges && (--NumUnusedEdges == 0))
352 assert(VisitOrder.size() == N &&
"Visitation order is wrong?");
354 delete FirstVisitState;
355 FirstVisitState =
nullptr;
358 VisitState *
State = allocateVisitState();
359 unsigned VisitNumber = State->NextVisitNumber++;
364 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
365 for (
unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
367 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
368 if (!ModuleFilesHit->count(M))
369 State->VisitNumber[M->
Index] = VisitNumber;
373 for (
unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
376 if (State->VisitNumber[CurrentModule->
Index] == VisitNumber)
380 assert(State->VisitNumber[CurrentModule->
Index] == VisitNumber - 1);
381 State->VisitNumber[CurrentModule->
Index] = VisitNumber;
382 if (!Visitor(*CurrentModule, UserData))
392 for (llvm::SetVector<ModuleFile *>::iterator
393 M = NextModule->
Imports.begin(),
394 MEnd = NextModule->
Imports.end();
396 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
397 State->Stack.push_back(*M);
398 State->VisitNumber[(*M)->Index] = VisitNumber;
402 if (State->Stack.empty())
406 NextModule = State->Stack.pop_back_val();
410 returnVisitState(State);
415 for (llvm::SetVector<ModuleFile *>::iterator IM = M.
Imports.begin(),
418 if (Visited[(*IM)->Index])
420 Visited[(*IM)->Index] =
true;
431 bool (*PostorderVisitor)(
ModuleFile &M,
void *UserData),
void *UserData,
433 if (PreorderVisitor) {
434 switch (PreorderVisitor(M, UserData)) {
446 for (llvm::SetVector<ModuleFile *>::iterator IM = M.
Imports.begin(),
449 if (Visited[(*IM)->Index])
451 Visited[(*IM)->Index] =
true;
453 if (
visitDepthFirst(**IM, PreorderVisitor, PostorderVisitor, UserData, Visited))
457 if (PostorderVisitor)
458 return PostorderVisitor(M, UserData);
466 bool (*PostorderVisitor)(
ModuleFile &M,
void *UserData),
void *UserData) {
468 for (
unsigned I = 0, N = Roots.size(); I != N; ++I) {
469 if (Visited[Roots[I]->Index])
471 Visited[Roots[I]->Index] =
true;
473 if (::
visitDepthFirst(*Roots[I], PreorderVisitor, PostorderVisitor, UserData, Visited))
480 time_t ExpectedModTime,
484 File = FileMgr.
getFile(FileName,
true,
false);
486 if (!File && FileName !=
"-") {
490 if ((ExpectedSize && ExpectedSize != File->
getSize()) ||
516 return Manager.
begin();
520 return Manager.
end();
540 llvm::ViewGraph(*
this,
"Modules");
ModuleManager::ModuleConstIterator nodes_iterator
bool addKnownModuleFile(StringRef FileName)
Notification from the frontend that the given module file is part of this compilation (even if not im...
Implements support for file system lookup, file system caching, and directory search management...
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
static ChildIteratorType child_end(NodeType *Node)
unsigned size() const
Number of modules loaded.
std::string getTimestampFilename() const
static bool renderGraphFromBottomUp()
ModuleKind Kind
The type of this module.
std::string ModuleName
The name of the module.
The module file is out-of-date.
DOTGraphTraits(bool IsSimple=false)
unsigned Index
The index of this module in the list of modules.
llvm::sys::TimeValue getLastModificationTime() const
ASTFileSignature Signature
The signature of the module file, which may be used along with size and modification time to identify...
Manages the set of modules loaded by an AST reader.
static ChildIteratorType child_begin(NodeType *Node)
SourceLocation ImportLoc
The source location where this module was first imported.
SmallVectorImpl< ModuleFile * >::const_iterator ModuleConstIterator
AddModuleResult
The result of attempting to add a new module.
ModuleIterator begin()
Forward iterator to traverse all loaded modules. This is reverse source-order.
void viewGraph()
View the graphviz representation of the module graph.
void setGlobalIndex(GlobalModuleIndex *Index)
Set the global module index.
Describes a module or submodule.
void visitDepthFirst(DFSPreorderControl(*PreorderVisitor)(ModuleFile &M, void *UserData), bool(*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData)
Visit each of the modules with a depth-first traversal.
Stop the visitation immediately.
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.
static bool visitDepthFirst(ModuleFile &M, ModuleManager::DFSPreorderControl(*PreorderVisitor)(ModuleFile &M, void *UserData), bool(*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData, SmallVectorImpl< bool > &Visited)
Perform a depth-first visit of the current module.
The module file is missing.
The result of a status operation.
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.
ModuleFile * lookup(StringRef Name)
Returns the module associated with the given name.
std::unique_ptr< llvm::MemoryBuffer > Buffer
The memory buffer that stores the data associated with this AST file.
static nodes_iterator nodes_end(const ModuleManager &Manager)
Information about a module that has been loaded by the ASTReader.
DFSPreorderControl
Control DFS behavior during preorder visitation.
void visit(bool(*Visitor)(ModuleFile &M, void *UserData), void *UserData, llvm::SmallPtrSetImpl< ModuleFile * > *ModuleFilesHit=nullptr)
Visit each of the modules.
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.
std::string FileName
The file name of the module file.
The result type of a method or function.
ModuleManager(FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr)
void addInMemoryBuffer(StringRef FileName, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Add an in-memory buffer the list of known buffers.
virtual void ExtractPCH(llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const =0
static nodes_iterator nodes_begin(const ModuleManager &Manager)
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
llvm::BitstreamReader StreamFile
The bitstream reader from which we'll read the AST file.
File is an implicitly-loaded module.
Cached information about one file (either on disk or in the virtual file system). ...
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.
uint64_t InputFilesValidationTimestamp
If non-zero, specifies the time when we last validated input files. Zero means we never validated the...
ast_type_traits::DynTypedNode Node
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.
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
void removeModules(ModuleIterator first, ModuleIterator last, llvm::SmallPtrSetImpl< ModuleFile * > &LoadedSuccessfully, ModuleMap *modMap)
Remove the given set of modules.
Continue visiting all nodes.
std::string getNodeLabel(ModuleFile *M, const ModuleManager &)
static void markVisitedDepthFirst(ModuleFile &M, SmallVectorImpl< bool > &Visited)
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.
SmallVectorImpl< ModuleFile * >::iterator ModuleIterator
bool DirectlyImported
Whether this module has been directly imported by the user.
const FileEntry * File
The file entry for the module file.
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.