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