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;
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();
99 PCHChain.push_back(New);
101 Roots.push_back(New);
121 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf(
122 (std::error_code()));
123 if (FileName ==
"-") {
124 Buf = llvm::MemoryBuffer::getSTDIN();
136 ErrorStr = Buf.getError().message();
140 New->
Buffer = std::move(*Buf);
147 if (ExpectedSignature) {
153 if (ModuleEntry->
Signature != ExpectedSignature) {
154 ErrorStr = ModuleEntry->
Signature ?
"signature mismatch"
155 :
"could not read module signature";
161 Modules.erase(Entry);
162 assert(Chain.back() == ModuleEntry);
166 if (Roots.back() == ModuleEntry)
178 ImportedBy->
Imports.insert(ModuleEntry);
186 Module = ModuleEntry;
192 llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
201 llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
204 return victimSet.count(MF);
207 for (
unsigned i = 0, n = Chain.size(); i != n; ++i) {
208 Chain[i]->ImportedBy.remove_if(IsVictim);
210 Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
214 for (
auto I = first;
I != last; ++
I) {
215 if (!(*I)->isModule()) {
216 PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), *
I),
224 Modules.erase((*victim)->File);
227 StringRef ModuleName = (*victim)->ModuleName;
229 mod->setASTFile(
nullptr);
236 if (LoadedSuccessfully.count(*victim) == 0)
243 Chain.erase(first, last);
248 std::unique_ptr<llvm::MemoryBuffer>
Buffer) {
252 InMemoryBuffers[Entry] = std::move(Buffer);
255 ModuleManager::VisitState *ModuleManager::allocateVisitState() {
257 if (FirstVisitState) {
258 VisitState *
Result = FirstVisitState;
259 FirstVisitState = FirstVisitState->NextState;
260 Result->NextState =
nullptr;
265 return new VisitState(
size());
268 void ModuleManager::returnVisitState(VisitState *
State) {
269 assert(State->NextState ==
nullptr &&
"Visited state is in list?");
270 State->NextState = FirstVisitState;
271 FirstVisitState =
State;
277 ModulesInCommonWithGlobalIndex.clear();
283 for (
unsigned I = 0, N = Chain.size();
I != N; ++
I) {
285 ModulesInCommonWithGlobalIndex.push_back(Chain[I]);
294 ModulesInCommonWithGlobalIndex.push_back(MF);
299 : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr), GlobalIndex(),
300 FirstVisitState(nullptr) {}
303 for (
unsigned i = 0, e = Chain.size(); i != e; ++i)
304 delete Chain[e - i - 1];
305 delete FirstVisitState;
309 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
311 if (VisitOrder.size() != Chain.size()) {
314 VisitOrder.reserve(N);
322 UnusedIncomingEdges.resize(
size());
325 UnusedIncomingEdges[M->
Index] = Size;
332 while (!Queue.empty()) {
333 ModuleFile *CurrentModule = Queue.pop_back_val();
334 VisitOrder.push_back(CurrentModule);
338 for (
auto M = CurrentModule->
Imports.rbegin(),
339 MEnd = CurrentModule->
Imports.rend();
345 unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
346 if (NumUnusedEdges && (--NumUnusedEdges == 0))
351 assert(VisitOrder.size() == N &&
"Visitation order is wrong?");
353 delete FirstVisitState;
354 FirstVisitState =
nullptr;
357 VisitState *
State = allocateVisitState();
358 unsigned VisitNumber = State->NextVisitNumber++;
363 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
364 for (
unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size();
I != N; ++
I)
367 if (!ModuleFilesHit->count(M))
368 State->VisitNumber[M->
Index] = VisitNumber;
372 for (
unsigned I = 0, N = VisitOrder.size();
I != N; ++
I) {
375 if (State->VisitNumber[CurrentModule->
Index] == VisitNumber)
379 assert(State->VisitNumber[CurrentModule->
Index] == VisitNumber - 1);
380 State->VisitNumber[CurrentModule->
Index] = VisitNumber;
381 if (!Visitor(*CurrentModule))
392 M = NextModule->
Imports.begin(),
393 MEnd = NextModule->
Imports.end();
395 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
396 State->Stack.push_back(*M);
397 State->VisitNumber[(*M)->Index] = VisitNumber;
401 if (State->Stack.empty())
405 NextModule = State->Stack.pop_back_val();
409 returnVisitState(State);
414 time_t ExpectedModTime,
418 File = FileMgr.
getFile(FileName,
true,
false);
420 if (!File && FileName !=
"-") {
424 if ((ExpectedSize && ExpectedSize != File->
getSize()) ||
450 return Manager.
begin();
454 return Manager.
end();
474 llvm::ViewGraph(*
this,
"Modules");
ModuleManager::ModuleConstIterator nodes_iterator
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.
bool isModule() const
Is this a module file for a module (rather than a PCH or similar).
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
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...
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.
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.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
void viewGraph()
View the graphviz representation of the module graph.
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.
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.
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.
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
Initialize an llvm::BitstreamReader with the serialized AST inside the PCH container Buffer...
static nodes_iterator nodes_begin(const ModuleManager &Manager)
Encodes a location in the source.
const TemplateArgument * iterator
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.
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.
std::string getNodeLabel(ModuleFile *M, const ModuleManager &)
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.