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