1*67e74705SXin Li //===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines the ModuleManager class, which manages a set of loaded
11*67e74705SXin Li // modules for the ASTReader.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li #include "clang/Frontend/PCHContainerOperations.h"
15*67e74705SXin Li #include "clang/Lex/HeaderSearch.h"
16*67e74705SXin Li #include "clang/Lex/ModuleMap.h"
17*67e74705SXin Li #include "clang/Serialization/GlobalModuleIndex.h"
18*67e74705SXin Li #include "clang/Serialization/ModuleManager.h"
19*67e74705SXin Li #include "llvm/Support/MemoryBuffer.h"
20*67e74705SXin Li #include "llvm/Support/Path.h"
21*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
22*67e74705SXin Li #include <system_error>
23*67e74705SXin Li
24*67e74705SXin Li #ifndef NDEBUG
25*67e74705SXin Li #include "llvm/Support/GraphWriter.h"
26*67e74705SXin Li #endif
27*67e74705SXin Li
28*67e74705SXin Li using namespace clang;
29*67e74705SXin Li using namespace serialization;
30*67e74705SXin Li
lookup(StringRef Name)31*67e74705SXin Li ModuleFile *ModuleManager::lookup(StringRef Name) {
32*67e74705SXin Li const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
33*67e74705SXin Li /*cacheFailure=*/false);
34*67e74705SXin Li if (Entry)
35*67e74705SXin Li return lookup(Entry);
36*67e74705SXin Li
37*67e74705SXin Li return nullptr;
38*67e74705SXin Li }
39*67e74705SXin Li
lookup(const FileEntry * File)40*67e74705SXin Li ModuleFile *ModuleManager::lookup(const FileEntry *File) {
41*67e74705SXin Li llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
42*67e74705SXin Li = Modules.find(File);
43*67e74705SXin Li if (Known == Modules.end())
44*67e74705SXin Li return nullptr;
45*67e74705SXin Li
46*67e74705SXin Li return Known->second;
47*67e74705SXin Li }
48*67e74705SXin Li
49*67e74705SXin Li std::unique_ptr<llvm::MemoryBuffer>
lookupBuffer(StringRef Name)50*67e74705SXin Li ModuleManager::lookupBuffer(StringRef Name) {
51*67e74705SXin Li const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
52*67e74705SXin Li /*cacheFailure=*/false);
53*67e74705SXin Li return std::move(InMemoryBuffers[Entry]);
54*67e74705SXin Li }
55*67e74705SXin Li
56*67e74705SXin Li ModuleManager::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)57*67e74705SXin Li ModuleManager::addModule(StringRef FileName, ModuleKind Type,
58*67e74705SXin Li SourceLocation ImportLoc, ModuleFile *ImportedBy,
59*67e74705SXin Li unsigned Generation,
60*67e74705SXin Li off_t ExpectedSize, time_t ExpectedModTime,
61*67e74705SXin Li ASTFileSignature ExpectedSignature,
62*67e74705SXin Li ASTFileSignatureReader ReadSignature,
63*67e74705SXin Li ModuleFile *&Module,
64*67e74705SXin Li std::string &ErrorStr) {
65*67e74705SXin Li Module = nullptr;
66*67e74705SXin Li
67*67e74705SXin Li // Look for the file entry. This only fails if the expected size or
68*67e74705SXin Li // modification time differ.
69*67e74705SXin Li const FileEntry *Entry;
70*67e74705SXin Li if (Type == MK_ExplicitModule) {
71*67e74705SXin Li // If we're not expecting to pull this file out of the module cache, it
72*67e74705SXin Li // might have a different mtime due to being moved across filesystems in
73*67e74705SXin Li // a distributed build. The size must still match, though. (As must the
74*67e74705SXin Li // contents, but we can't check that.)
75*67e74705SXin Li ExpectedModTime = 0;
76*67e74705SXin Li }
77*67e74705SXin Li if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) {
78*67e74705SXin Li ErrorStr = "module file out of date";
79*67e74705SXin Li return OutOfDate;
80*67e74705SXin Li }
81*67e74705SXin Li
82*67e74705SXin Li if (!Entry && FileName != "-") {
83*67e74705SXin Li ErrorStr = "module file not found";
84*67e74705SXin Li return Missing;
85*67e74705SXin Li }
86*67e74705SXin Li
87*67e74705SXin Li // Check whether we already loaded this module, before
88*67e74705SXin Li ModuleFile *&ModuleEntry = Modules[Entry];
89*67e74705SXin Li bool NewModule = false;
90*67e74705SXin Li if (!ModuleEntry) {
91*67e74705SXin Li // Allocate a new module.
92*67e74705SXin Li ModuleFile *New = new ModuleFile(Type, Generation);
93*67e74705SXin Li New->Index = Chain.size();
94*67e74705SXin Li New->FileName = FileName.str();
95*67e74705SXin Li New->File = Entry;
96*67e74705SXin Li New->ImportLoc = ImportLoc;
97*67e74705SXin Li Chain.push_back(New);
98*67e74705SXin Li if (!New->isModule())
99*67e74705SXin Li PCHChain.push_back(New);
100*67e74705SXin Li if (!ImportedBy)
101*67e74705SXin Li Roots.push_back(New);
102*67e74705SXin Li NewModule = true;
103*67e74705SXin Li ModuleEntry = New;
104*67e74705SXin Li
105*67e74705SXin Li New->InputFilesValidationTimestamp = 0;
106*67e74705SXin Li if (New->Kind == MK_ImplicitModule) {
107*67e74705SXin Li std::string TimestampFilename = New->getTimestampFilename();
108*67e74705SXin Li vfs::Status Status;
109*67e74705SXin Li // A cached stat value would be fine as well.
110*67e74705SXin Li if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
111*67e74705SXin Li New->InputFilesValidationTimestamp =
112*67e74705SXin Li Status.getLastModificationTime().toEpochTime();
113*67e74705SXin Li }
114*67e74705SXin Li
115*67e74705SXin Li // Load the contents of the module
116*67e74705SXin Li if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
117*67e74705SXin Li // The buffer was already provided for us.
118*67e74705SXin Li New->Buffer = std::move(Buffer);
119*67e74705SXin Li } else {
120*67e74705SXin Li // Open the AST file.
121*67e74705SXin Li llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf(
122*67e74705SXin Li (std::error_code()));
123*67e74705SXin Li if (FileName == "-") {
124*67e74705SXin Li Buf = llvm::MemoryBuffer::getSTDIN();
125*67e74705SXin Li } else {
126*67e74705SXin Li // Leave the FileEntry open so if it gets read again by another
127*67e74705SXin Li // ModuleManager it must be the same underlying file.
128*67e74705SXin Li // FIXME: Because FileManager::getFile() doesn't guarantee that it will
129*67e74705SXin Li // give us an open file, this may not be 100% reliable.
130*67e74705SXin Li Buf = FileMgr.getBufferForFile(New->File,
131*67e74705SXin Li /*IsVolatile=*/false,
132*67e74705SXin Li /*ShouldClose=*/false);
133*67e74705SXin Li }
134*67e74705SXin Li
135*67e74705SXin Li if (!Buf) {
136*67e74705SXin Li ErrorStr = Buf.getError().message();
137*67e74705SXin Li return Missing;
138*67e74705SXin Li }
139*67e74705SXin Li
140*67e74705SXin Li New->Buffer = std::move(*Buf);
141*67e74705SXin Li }
142*67e74705SXin Li
143*67e74705SXin Li // Initialize the stream.
144*67e74705SXin Li PCHContainerRdr.ExtractPCH(New->Buffer->getMemBufferRef(), New->StreamFile);
145*67e74705SXin Li }
146*67e74705SXin Li
147*67e74705SXin Li if (ExpectedSignature) {
148*67e74705SXin Li if (NewModule)
149*67e74705SXin Li ModuleEntry->Signature = ReadSignature(ModuleEntry->StreamFile);
150*67e74705SXin Li else
151*67e74705SXin Li assert(ModuleEntry->Signature == ReadSignature(ModuleEntry->StreamFile));
152*67e74705SXin Li
153*67e74705SXin Li if (ModuleEntry->Signature != ExpectedSignature) {
154*67e74705SXin Li ErrorStr = ModuleEntry->Signature ? "signature mismatch"
155*67e74705SXin Li : "could not read module signature";
156*67e74705SXin Li
157*67e74705SXin Li if (NewModule) {
158*67e74705SXin Li // Remove the module file immediately, since removeModules might try to
159*67e74705SXin Li // invalidate the file cache for Entry, and that is not safe if this
160*67e74705SXin Li // module is *itself* up to date, but has an out-of-date importer.
161*67e74705SXin Li Modules.erase(Entry);
162*67e74705SXin Li assert(Chain.back() == ModuleEntry);
163*67e74705SXin Li Chain.pop_back();
164*67e74705SXin Li if (!ModuleEntry->isModule())
165*67e74705SXin Li PCHChain.pop_back();
166*67e74705SXin Li if (Roots.back() == ModuleEntry)
167*67e74705SXin Li Roots.pop_back();
168*67e74705SXin Li else
169*67e74705SXin Li assert(ImportedBy);
170*67e74705SXin Li delete ModuleEntry;
171*67e74705SXin Li }
172*67e74705SXin Li return OutOfDate;
173*67e74705SXin Li }
174*67e74705SXin Li }
175*67e74705SXin Li
176*67e74705SXin Li if (ImportedBy) {
177*67e74705SXin Li ModuleEntry->ImportedBy.insert(ImportedBy);
178*67e74705SXin Li ImportedBy->Imports.insert(ModuleEntry);
179*67e74705SXin Li } else {
180*67e74705SXin Li if (!ModuleEntry->DirectlyImported)
181*67e74705SXin Li ModuleEntry->ImportLoc = ImportLoc;
182*67e74705SXin Li
183*67e74705SXin Li ModuleEntry->DirectlyImported = true;
184*67e74705SXin Li }
185*67e74705SXin Li
186*67e74705SXin Li Module = ModuleEntry;
187*67e74705SXin Li return NewModule? NewlyLoaded : AlreadyLoaded;
188*67e74705SXin Li }
189*67e74705SXin Li
removeModules(ModuleIterator first,ModuleIterator last,llvm::SmallPtrSetImpl<ModuleFile * > & LoadedSuccessfully,ModuleMap * modMap)190*67e74705SXin Li void ModuleManager::removeModules(
191*67e74705SXin Li ModuleIterator first, ModuleIterator last,
192*67e74705SXin Li llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
193*67e74705SXin Li ModuleMap *modMap) {
194*67e74705SXin Li if (first == last)
195*67e74705SXin Li return;
196*67e74705SXin Li
197*67e74705SXin Li // Explicitly clear VisitOrder since we might not notice it is stale.
198*67e74705SXin Li VisitOrder.clear();
199*67e74705SXin Li
200*67e74705SXin Li // Collect the set of module file pointers that we'll be removing.
201*67e74705SXin Li llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
202*67e74705SXin Li
203*67e74705SXin Li auto IsVictim = [&](ModuleFile *MF) {
204*67e74705SXin Li return victimSet.count(MF);
205*67e74705SXin Li };
206*67e74705SXin Li // Remove any references to the now-destroyed modules.
207*67e74705SXin Li for (unsigned i = 0, n = Chain.size(); i != n; ++i) {
208*67e74705SXin Li Chain[i]->ImportedBy.remove_if(IsVictim);
209*67e74705SXin Li }
210*67e74705SXin Li Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
211*67e74705SXin Li Roots.end());
212*67e74705SXin Li
213*67e74705SXin Li // Remove the modules from the PCH chain.
214*67e74705SXin Li for (auto I = first; I != last; ++I) {
215*67e74705SXin Li if (!(*I)->isModule()) {
216*67e74705SXin Li PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), *I),
217*67e74705SXin Li PCHChain.end());
218*67e74705SXin Li break;
219*67e74705SXin Li }
220*67e74705SXin Li }
221*67e74705SXin Li
222*67e74705SXin Li // Delete the modules and erase them from the various structures.
223*67e74705SXin Li for (ModuleIterator victim = first; victim != last; ++victim) {
224*67e74705SXin Li Modules.erase((*victim)->File);
225*67e74705SXin Li
226*67e74705SXin Li if (modMap) {
227*67e74705SXin Li StringRef ModuleName = (*victim)->ModuleName;
228*67e74705SXin Li if (Module *mod = modMap->findModule(ModuleName)) {
229*67e74705SXin Li mod->setASTFile(nullptr);
230*67e74705SXin Li }
231*67e74705SXin Li }
232*67e74705SXin Li
233*67e74705SXin Li // Files that didn't make it through ReadASTCore successfully will be
234*67e74705SXin Li // rebuilt (or there was an error). Invalidate them so that we can load the
235*67e74705SXin Li // new files that will be renamed over the old ones.
236*67e74705SXin Li if (LoadedSuccessfully.count(*victim) == 0)
237*67e74705SXin Li FileMgr.invalidateCache((*victim)->File);
238*67e74705SXin Li
239*67e74705SXin Li delete *victim;
240*67e74705SXin Li }
241*67e74705SXin Li
242*67e74705SXin Li // Remove the modules from the chain.
243*67e74705SXin Li Chain.erase(first, last);
244*67e74705SXin Li }
245*67e74705SXin Li
246*67e74705SXin Li void
addInMemoryBuffer(StringRef FileName,std::unique_ptr<llvm::MemoryBuffer> Buffer)247*67e74705SXin Li ModuleManager::addInMemoryBuffer(StringRef FileName,
248*67e74705SXin Li std::unique_ptr<llvm::MemoryBuffer> Buffer) {
249*67e74705SXin Li
250*67e74705SXin Li const FileEntry *Entry =
251*67e74705SXin Li FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
252*67e74705SXin Li InMemoryBuffers[Entry] = std::move(Buffer);
253*67e74705SXin Li }
254*67e74705SXin Li
allocateVisitState()255*67e74705SXin Li ModuleManager::VisitState *ModuleManager::allocateVisitState() {
256*67e74705SXin Li // Fast path: if we have a cached state, use it.
257*67e74705SXin Li if (FirstVisitState) {
258*67e74705SXin Li VisitState *Result = FirstVisitState;
259*67e74705SXin Li FirstVisitState = FirstVisitState->NextState;
260*67e74705SXin Li Result->NextState = nullptr;
261*67e74705SXin Li return Result;
262*67e74705SXin Li }
263*67e74705SXin Li
264*67e74705SXin Li // Allocate and return a new state.
265*67e74705SXin Li return new VisitState(size());
266*67e74705SXin Li }
267*67e74705SXin Li
returnVisitState(VisitState * State)268*67e74705SXin Li void ModuleManager::returnVisitState(VisitState *State) {
269*67e74705SXin Li assert(State->NextState == nullptr && "Visited state is in list?");
270*67e74705SXin Li State->NextState = FirstVisitState;
271*67e74705SXin Li FirstVisitState = State;
272*67e74705SXin Li }
273*67e74705SXin Li
setGlobalIndex(GlobalModuleIndex * Index)274*67e74705SXin Li void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
275*67e74705SXin Li GlobalIndex = Index;
276*67e74705SXin Li if (!GlobalIndex) {
277*67e74705SXin Li ModulesInCommonWithGlobalIndex.clear();
278*67e74705SXin Li return;
279*67e74705SXin Li }
280*67e74705SXin Li
281*67e74705SXin Li // Notify the global module index about all of the modules we've already
282*67e74705SXin Li // loaded.
283*67e74705SXin Li for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
284*67e74705SXin Li if (!GlobalIndex->loadedModuleFile(Chain[I])) {
285*67e74705SXin Li ModulesInCommonWithGlobalIndex.push_back(Chain[I]);
286*67e74705SXin Li }
287*67e74705SXin Li }
288*67e74705SXin Li }
289*67e74705SXin Li
moduleFileAccepted(ModuleFile * MF)290*67e74705SXin Li void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
291*67e74705SXin Li if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
292*67e74705SXin Li return;
293*67e74705SXin Li
294*67e74705SXin Li ModulesInCommonWithGlobalIndex.push_back(MF);
295*67e74705SXin Li }
296*67e74705SXin Li
ModuleManager(FileManager & FileMgr,const PCHContainerReader & PCHContainerRdr)297*67e74705SXin Li ModuleManager::ModuleManager(FileManager &FileMgr,
298*67e74705SXin Li const PCHContainerReader &PCHContainerRdr)
299*67e74705SXin Li : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr), GlobalIndex(),
300*67e74705SXin Li FirstVisitState(nullptr) {}
301*67e74705SXin Li
~ModuleManager()302*67e74705SXin Li ModuleManager::~ModuleManager() {
303*67e74705SXin Li for (unsigned i = 0, e = Chain.size(); i != e; ++i)
304*67e74705SXin Li delete Chain[e - i - 1];
305*67e74705SXin Li delete FirstVisitState;
306*67e74705SXin Li }
307*67e74705SXin Li
visit(llvm::function_ref<bool (ModuleFile & M)> Visitor,llvm::SmallPtrSetImpl<ModuleFile * > * ModuleFilesHit)308*67e74705SXin Li void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
309*67e74705SXin Li llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
310*67e74705SXin Li // If the visitation order vector is the wrong size, recompute the order.
311*67e74705SXin Li if (VisitOrder.size() != Chain.size()) {
312*67e74705SXin Li unsigned N = size();
313*67e74705SXin Li VisitOrder.clear();
314*67e74705SXin Li VisitOrder.reserve(N);
315*67e74705SXin Li
316*67e74705SXin Li // Record the number of incoming edges for each module. When we
317*67e74705SXin Li // encounter a module with no incoming edges, push it into the queue
318*67e74705SXin Li // to seed the queue.
319*67e74705SXin Li SmallVector<ModuleFile *, 4> Queue;
320*67e74705SXin Li Queue.reserve(N);
321*67e74705SXin Li llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
322*67e74705SXin Li UnusedIncomingEdges.resize(size());
323*67e74705SXin Li for (ModuleFile *M : llvm::reverse(*this)) {
324*67e74705SXin Li unsigned Size = M->ImportedBy.size();
325*67e74705SXin Li UnusedIncomingEdges[M->Index] = Size;
326*67e74705SXin Li if (!Size)
327*67e74705SXin Li Queue.push_back(M);
328*67e74705SXin Li }
329*67e74705SXin Li
330*67e74705SXin Li // Traverse the graph, making sure to visit a module before visiting any
331*67e74705SXin Li // of its dependencies.
332*67e74705SXin Li while (!Queue.empty()) {
333*67e74705SXin Li ModuleFile *CurrentModule = Queue.pop_back_val();
334*67e74705SXin Li VisitOrder.push_back(CurrentModule);
335*67e74705SXin Li
336*67e74705SXin Li // For any module that this module depends on, push it on the
337*67e74705SXin Li // stack (if it hasn't already been marked as visited).
338*67e74705SXin Li for (auto M = CurrentModule->Imports.rbegin(),
339*67e74705SXin Li MEnd = CurrentModule->Imports.rend();
340*67e74705SXin Li M != MEnd; ++M) {
341*67e74705SXin Li // Remove our current module as an impediment to visiting the
342*67e74705SXin Li // module we depend on. If we were the last unvisited module
343*67e74705SXin Li // that depends on this particular module, push it into the
344*67e74705SXin Li // queue to be visited.
345*67e74705SXin Li unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
346*67e74705SXin Li if (NumUnusedEdges && (--NumUnusedEdges == 0))
347*67e74705SXin Li Queue.push_back(*M);
348*67e74705SXin Li }
349*67e74705SXin Li }
350*67e74705SXin Li
351*67e74705SXin Li assert(VisitOrder.size() == N && "Visitation order is wrong?");
352*67e74705SXin Li
353*67e74705SXin Li delete FirstVisitState;
354*67e74705SXin Li FirstVisitState = nullptr;
355*67e74705SXin Li }
356*67e74705SXin Li
357*67e74705SXin Li VisitState *State = allocateVisitState();
358*67e74705SXin Li unsigned VisitNumber = State->NextVisitNumber++;
359*67e74705SXin Li
360*67e74705SXin Li // If the caller has provided us with a hit-set that came from the global
361*67e74705SXin Li // module index, mark every module file in common with the global module
362*67e74705SXin Li // index that is *not* in that set as 'visited'.
363*67e74705SXin Li if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
364*67e74705SXin Li for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
365*67e74705SXin Li {
366*67e74705SXin Li ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
367*67e74705SXin Li if (!ModuleFilesHit->count(M))
368*67e74705SXin Li State->VisitNumber[M->Index] = VisitNumber;
369*67e74705SXin Li }
370*67e74705SXin Li }
371*67e74705SXin Li
372*67e74705SXin Li for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
373*67e74705SXin Li ModuleFile *CurrentModule = VisitOrder[I];
374*67e74705SXin Li // Should we skip this module file?
375*67e74705SXin Li if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
376*67e74705SXin Li continue;
377*67e74705SXin Li
378*67e74705SXin Li // Visit the module.
379*67e74705SXin Li assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
380*67e74705SXin Li State->VisitNumber[CurrentModule->Index] = VisitNumber;
381*67e74705SXin Li if (!Visitor(*CurrentModule))
382*67e74705SXin Li continue;
383*67e74705SXin Li
384*67e74705SXin Li // The visitor has requested that cut off visitation of any
385*67e74705SXin Li // module that the current module depends on. To indicate this
386*67e74705SXin Li // behavior, we mark all of the reachable modules as having been visited.
387*67e74705SXin Li ModuleFile *NextModule = CurrentModule;
388*67e74705SXin Li do {
389*67e74705SXin Li // For any module that this module depends on, push it on the
390*67e74705SXin Li // stack (if it hasn't already been marked as visited).
391*67e74705SXin Li for (llvm::SetVector<ModuleFile *>::iterator
392*67e74705SXin Li M = NextModule->Imports.begin(),
393*67e74705SXin Li MEnd = NextModule->Imports.end();
394*67e74705SXin Li M != MEnd; ++M) {
395*67e74705SXin Li if (State->VisitNumber[(*M)->Index] != VisitNumber) {
396*67e74705SXin Li State->Stack.push_back(*M);
397*67e74705SXin Li State->VisitNumber[(*M)->Index] = VisitNumber;
398*67e74705SXin Li }
399*67e74705SXin Li }
400*67e74705SXin Li
401*67e74705SXin Li if (State->Stack.empty())
402*67e74705SXin Li break;
403*67e74705SXin Li
404*67e74705SXin Li // Pop the next module off the stack.
405*67e74705SXin Li NextModule = State->Stack.pop_back_val();
406*67e74705SXin Li } while (true);
407*67e74705SXin Li }
408*67e74705SXin Li
409*67e74705SXin Li returnVisitState(State);
410*67e74705SXin Li }
411*67e74705SXin Li
lookupModuleFile(StringRef FileName,off_t ExpectedSize,time_t ExpectedModTime,const FileEntry * & File)412*67e74705SXin Li bool ModuleManager::lookupModuleFile(StringRef FileName,
413*67e74705SXin Li off_t ExpectedSize,
414*67e74705SXin Li time_t ExpectedModTime,
415*67e74705SXin Li const FileEntry *&File) {
416*67e74705SXin Li // Open the file immediately to ensure there is no race between stat'ing and
417*67e74705SXin Li // opening the file.
418*67e74705SXin Li File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false);
419*67e74705SXin Li
420*67e74705SXin Li if (!File && FileName != "-") {
421*67e74705SXin Li return false;
422*67e74705SXin Li }
423*67e74705SXin Li
424*67e74705SXin Li if ((ExpectedSize && ExpectedSize != File->getSize()) ||
425*67e74705SXin Li (ExpectedModTime && ExpectedModTime != File->getModificationTime()))
426*67e74705SXin Li // Do not destroy File, as it may be referenced. If we need to rebuild it,
427*67e74705SXin Li // it will be destroyed by removeModules.
428*67e74705SXin Li return true;
429*67e74705SXin Li
430*67e74705SXin Li return false;
431*67e74705SXin Li }
432*67e74705SXin Li
433*67e74705SXin Li #ifndef NDEBUG
434*67e74705SXin Li namespace llvm {
435*67e74705SXin Li template<>
436*67e74705SXin Li struct GraphTraits<ModuleManager> {
437*67e74705SXin Li typedef ModuleFile NodeType;
438*67e74705SXin Li typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType;
439*67e74705SXin Li typedef ModuleManager::ModuleConstIterator nodes_iterator;
440*67e74705SXin Li
child_beginllvm::GraphTraits441*67e74705SXin Li static ChildIteratorType child_begin(NodeType *Node) {
442*67e74705SXin Li return Node->Imports.begin();
443*67e74705SXin Li }
444*67e74705SXin Li
child_endllvm::GraphTraits445*67e74705SXin Li static ChildIteratorType child_end(NodeType *Node) {
446*67e74705SXin Li return Node->Imports.end();
447*67e74705SXin Li }
448*67e74705SXin Li
nodes_beginllvm::GraphTraits449*67e74705SXin Li static nodes_iterator nodes_begin(const ModuleManager &Manager) {
450*67e74705SXin Li return Manager.begin();
451*67e74705SXin Li }
452*67e74705SXin Li
nodes_endllvm::GraphTraits453*67e74705SXin Li static nodes_iterator nodes_end(const ModuleManager &Manager) {
454*67e74705SXin Li return Manager.end();
455*67e74705SXin Li }
456*67e74705SXin Li };
457*67e74705SXin Li
458*67e74705SXin Li template<>
459*67e74705SXin Li struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits460*67e74705SXin Li explicit DOTGraphTraits(bool IsSimple = false)
461*67e74705SXin Li : DefaultDOTGraphTraits(IsSimple) { }
462*67e74705SXin Li
renderGraphFromBottomUpllvm::DOTGraphTraits463*67e74705SXin Li static bool renderGraphFromBottomUp() {
464*67e74705SXin Li return true;
465*67e74705SXin Li }
466*67e74705SXin Li
getNodeLabelllvm::DOTGraphTraits467*67e74705SXin Li std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
468*67e74705SXin Li return M->ModuleName;
469*67e74705SXin Li }
470*67e74705SXin Li };
471*67e74705SXin Li }
472*67e74705SXin Li
viewGraph()473*67e74705SXin Li void ModuleManager::viewGraph() {
474*67e74705SXin Li llvm::ViewGraph(*this, "Modules");
475*67e74705SXin Li }
476*67e74705SXin Li #endif
477