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