xref: /llvm-project/clang/lib/Serialization/ModuleManager.cpp (revision 8bef5cd49a8bb66b777cc3c51f9fb31bffeaa580)
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/Lex/HeaderSearch.h"
18 #include "clang/Lex/ModuleMap.h"
19 #include "clang/Serialization/GlobalModuleIndex.h"
20 #include "clang/Serialization/InMemoryModuleCache.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 = &ModuleCache->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 =
168                  getModuleCache().lookupBuffer(FileName)) {
169     NewModule->Buffer = Buffer;
170     // As above, the file descriptor is no longer needed.
171     Entry->closeFile();
172   } else {
173     // Open the AST file.
174     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
175     if (FileName == "-") {
176       Buf = llvm::MemoryBuffer::getSTDIN();
177     } else {
178       // Get a buffer of the file and close the file descriptor when done.
179       Buf = FileMgr.getBufferForFile(NewModule->File,
180                                      /*IsVolatile=*/false,
181                                      /*ShouldClose=*/true);
182     }
183 
184     if (!Buf) {
185       ErrorStr = Buf.getError().message();
186       return Missing;
187     }
188 
189     NewModule->Buffer = &getModuleCache().addBuffer(FileName, std::move(*Buf));
190   }
191 
192   // Initialize the stream.
193   NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
194 
195   // Read the signature eagerly now so that we can check it.  Avoid calling
196   // ReadSignature unless there's something to check though.
197   if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
198                                           ExpectedSignature, ErrorStr)) {
199     // Try to remove the buffer.  If it can't be removed, then it was already
200     // validated by this process.
201     if (!getModuleCache().tryToRemoveBuffer(NewModule->FileName))
202       FileMgr.invalidateCache(NewModule->File);
203     return OutOfDate;
204   }
205 
206   // We're keeping this module.  Store it everywhere.
207   Module = Modules[Entry] = NewModule.get();
208 
209   updateModuleImports(*NewModule, ImportedBy, ImportLoc);
210 
211   if (!NewModule->isModule())
212     PCHChain.push_back(NewModule.get());
213   if (!ImportedBy)
214     Roots.push_back(NewModule.get());
215 
216   Chain.push_back(std::move(NewModule));
217   return NewlyLoaded;
218 }
219 
220 void ModuleManager::removeModules(
221     ModuleIterator First,
222     llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
223     ModuleMap *modMap) {
224   auto Last = end();
225   if (First == Last)
226     return;
227 
228   // Explicitly clear VisitOrder since we might not notice it is stale.
229   VisitOrder.clear();
230 
231   // Collect the set of module file pointers that we'll be removing.
232   llvm::SmallPtrSet<ModuleFile *, 4> victimSet(
233       (llvm::pointer_iterator<ModuleIterator>(First)),
234       (llvm::pointer_iterator<ModuleIterator>(Last)));
235 
236   auto IsVictim = [&](ModuleFile *MF) {
237     return victimSet.count(MF);
238   };
239   // Remove any references to the now-destroyed modules.
240   for (auto I = begin(); I != First; ++I) {
241     I->Imports.remove_if(IsVictim);
242     I->ImportedBy.remove_if(IsVictim);
243   }
244   Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
245               Roots.end());
246 
247   // Remove the modules from the PCH chain.
248   for (auto I = First; I != Last; ++I) {
249     if (!I->isModule()) {
250       PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), &*I),
251                      PCHChain.end());
252       break;
253     }
254   }
255 
256   // Delete the modules and erase them from the various structures.
257   for (ModuleIterator victim = First; victim != Last; ++victim) {
258     Modules.erase(victim->File);
259 
260     if (modMap) {
261       StringRef ModuleName = victim->ModuleName;
262       if (Module *mod = modMap->findModule(ModuleName)) {
263         mod->setASTFile(nullptr);
264       }
265     }
266 
267     // Files that didn't make it through ReadASTCore successfully will be
268     // rebuilt (or there was an error). Invalidate them so that we can load the
269     // new files that will be renamed over the old ones.
270     //
271     // The ModuleCache tracks whether the module was successfully loaded in
272     // another thread/context; in that case, it won't need to be rebuilt (and
273     // we can't safely invalidate it anyway).
274     if (LoadedSuccessfully.count(&*victim) == 0 &&
275         !getModuleCache().tryToRemoveBuffer(victim->FileName))
276       FileMgr.invalidateCache(victim->File);
277   }
278 
279   // Delete the modules.
280   Chain.erase(Chain.begin() + (First - begin()), Chain.end());
281 }
282 
283 void
284 ModuleManager::addInMemoryBuffer(StringRef FileName,
285                                  std::unique_ptr<llvm::MemoryBuffer> Buffer) {
286   const FileEntry *Entry =
287       FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
288   InMemoryBuffers[Entry] = std::move(Buffer);
289 }
290 
291 ModuleManager::VisitState *ModuleManager::allocateVisitState() {
292   // Fast path: if we have a cached state, use it.
293   if (FirstVisitState) {
294     VisitState *Result = FirstVisitState;
295     FirstVisitState = FirstVisitState->NextState;
296     Result->NextState = nullptr;
297     return Result;
298   }
299 
300   // Allocate and return a new state.
301   return new VisitState(size());
302 }
303 
304 void ModuleManager::returnVisitState(VisitState *State) {
305   assert(State->NextState == nullptr && "Visited state is in list?");
306   State->NextState = FirstVisitState;
307   FirstVisitState = State;
308 }
309 
310 void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
311   GlobalIndex = Index;
312   if (!GlobalIndex) {
313     ModulesInCommonWithGlobalIndex.clear();
314     return;
315   }
316 
317   // Notify the global module index about all of the modules we've already
318   // loaded.
319   for (ModuleFile &M : *this)
320     if (!GlobalIndex->loadedModuleFile(&M))
321       ModulesInCommonWithGlobalIndex.push_back(&M);
322 }
323 
324 void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
325   if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
326     return;
327 
328   ModulesInCommonWithGlobalIndex.push_back(MF);
329 }
330 
331 ModuleManager::ModuleManager(FileManager &FileMgr,
332                              InMemoryModuleCache &ModuleCache,
333                              const PCHContainerReader &PCHContainerRdr,
334                              const HeaderSearch &HeaderSearchInfo)
335     : FileMgr(FileMgr), ModuleCache(&ModuleCache),
336       PCHContainerRdr(PCHContainerRdr), HeaderSearchInfo(HeaderSearchInfo) {}
337 
338 ModuleManager::~ModuleManager() { delete FirstVisitState; }
339 
340 void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
341                           llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
342   // If the visitation order vector is the wrong size, recompute the order.
343   if (VisitOrder.size() != Chain.size()) {
344     unsigned N = size();
345     VisitOrder.clear();
346     VisitOrder.reserve(N);
347 
348     // Record the number of incoming edges for each module. When we
349     // encounter a module with no incoming edges, push it into the queue
350     // to seed the queue.
351     SmallVector<ModuleFile *, 4> Queue;
352     Queue.reserve(N);
353     llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
354     UnusedIncomingEdges.resize(size());
355     for (ModuleFile &M : llvm::reverse(*this)) {
356       unsigned Size = M.ImportedBy.size();
357       UnusedIncomingEdges[M.Index] = Size;
358       if (!Size)
359         Queue.push_back(&M);
360     }
361 
362     // Traverse the graph, making sure to visit a module before visiting any
363     // of its dependencies.
364     while (!Queue.empty()) {
365       ModuleFile *CurrentModule = Queue.pop_back_val();
366       VisitOrder.push_back(CurrentModule);
367 
368       // For any module that this module depends on, push it on the
369       // stack (if it hasn't already been marked as visited).
370       for (auto M = CurrentModule->Imports.rbegin(),
371                 MEnd = CurrentModule->Imports.rend();
372            M != MEnd; ++M) {
373         // Remove our current module as an impediment to visiting the
374         // module we depend on. If we were the last unvisited module
375         // that depends on this particular module, push it into the
376         // queue to be visited.
377         unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
378         if (NumUnusedEdges && (--NumUnusedEdges == 0))
379           Queue.push_back(*M);
380       }
381     }
382 
383     assert(VisitOrder.size() == N && "Visitation order is wrong?");
384 
385     delete FirstVisitState;
386     FirstVisitState = nullptr;
387   }
388 
389   VisitState *State = allocateVisitState();
390   unsigned VisitNumber = State->NextVisitNumber++;
391 
392   // If the caller has provided us with a hit-set that came from the global
393   // module index, mark every module file in common with the global module
394   // index that is *not* in that set as 'visited'.
395   if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
396     for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
397     {
398       ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
399       if (!ModuleFilesHit->count(M))
400         State->VisitNumber[M->Index] = VisitNumber;
401     }
402   }
403 
404   for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
405     ModuleFile *CurrentModule = VisitOrder[I];
406     // Should we skip this module file?
407     if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
408       continue;
409 
410     // Visit the module.
411     assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
412     State->VisitNumber[CurrentModule->Index] = VisitNumber;
413     if (!Visitor(*CurrentModule))
414       continue;
415 
416     // The visitor has requested that cut off visitation of any
417     // module that the current module depends on. To indicate this
418     // behavior, we mark all of the reachable modules as having been visited.
419     ModuleFile *NextModule = CurrentModule;
420     do {
421       // For any module that this module depends on, push it on the
422       // stack (if it hasn't already been marked as visited).
423       for (llvm::SetVector<ModuleFile *>::iterator
424              M = NextModule->Imports.begin(),
425              MEnd = NextModule->Imports.end();
426            M != MEnd; ++M) {
427         if (State->VisitNumber[(*M)->Index] != VisitNumber) {
428           State->Stack.push_back(*M);
429           State->VisitNumber[(*M)->Index] = VisitNumber;
430         }
431       }
432 
433       if (State->Stack.empty())
434         break;
435 
436       // Pop the next module off the stack.
437       NextModule = State->Stack.pop_back_val();
438     } while (true);
439   }
440 
441   returnVisitState(State);
442 }
443 
444 bool ModuleManager::lookupModuleFile(StringRef FileName,
445                                      off_t ExpectedSize,
446                                      time_t ExpectedModTime,
447                                      const FileEntry *&File) {
448   if (FileName == "-") {
449     File = nullptr;
450     return false;
451   }
452 
453   // Open the file immediately to ensure there is no race between stat'ing and
454   // opening the file.
455   File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false);
456   if (!File)
457     return false;
458 
459   if ((ExpectedSize && ExpectedSize != File->getSize()) ||
460       (ExpectedModTime && ExpectedModTime != File->getModificationTime()))
461     // Do not destroy File, as it may be referenced. If we need to rebuild it,
462     // it will be destroyed by removeModules.
463     return true;
464 
465   return false;
466 }
467 
468 #ifndef NDEBUG
469 namespace llvm {
470 
471   template<>
472   struct GraphTraits<ModuleManager> {
473     using NodeRef = ModuleFile *;
474     using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
475     using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
476 
477     static ChildIteratorType child_begin(NodeRef Node) {
478       return Node->Imports.begin();
479     }
480 
481     static ChildIteratorType child_end(NodeRef Node) {
482       return Node->Imports.end();
483     }
484 
485     static nodes_iterator nodes_begin(const ModuleManager &Manager) {
486       return nodes_iterator(Manager.begin());
487     }
488 
489     static nodes_iterator nodes_end(const ModuleManager &Manager) {
490       return nodes_iterator(Manager.end());
491     }
492   };
493 
494   template<>
495   struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
496     explicit DOTGraphTraits(bool IsSimple = false)
497         : DefaultDOTGraphTraits(IsSimple) {}
498 
499     static bool renderGraphFromBottomUp() { return true; }
500 
501     std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
502       return M->ModuleName;
503     }
504   };
505 
506 } // namespace llvm
507 
508 void ModuleManager::viewGraph() {
509   llvm::ViewGraph(*this, "Modules");
510 }
511 #endif
512