xref: /aosp_15_r20/external/clang/lib/Serialization/ModuleManager.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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