xref: /src/contrib/llvm-project/clang/lib/Serialization/ModuleManager.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1461a67faSDimitry Andric //===- ModuleManager.cpp - Module Manager ---------------------------------===//
236981b17SDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
636981b17SDimitry Andric //
736981b17SDimitry Andric //===----------------------------------------------------------------------===//
836981b17SDimitry Andric //
936981b17SDimitry Andric //  This file defines the ModuleManager class, which manages a set of loaded
1036981b17SDimitry Andric //  modules for the ASTReader.
1136981b17SDimitry Andric //
1236981b17SDimitry Andric //===----------------------------------------------------------------------===//
13461a67faSDimitry Andric 
14bab175ecSDimitry Andric #include "clang/Serialization/ModuleManager.h"
15461a67faSDimitry Andric #include "clang/Basic/FileManager.h"
16461a67faSDimitry Andric #include "clang/Basic/LLVM.h"
179f4dbff6SDimitry Andric #include "clang/Lex/HeaderSearch.h"
18809500fcSDimitry Andric #include "clang/Lex/ModuleMap.h"
19809500fcSDimitry Andric #include "clang/Serialization/GlobalModuleIndex.h"
2022989816SDimitry Andric #include "clang/Serialization/InMemoryModuleCache.h"
21706b4fc4SDimitry Andric #include "clang/Serialization/ModuleFile.h"
22676fbe81SDimitry Andric #include "clang/Serialization/PCHContainerOperations.h"
23461a67faSDimitry Andric #include "llvm/ADT/STLExtras.h"
24461a67faSDimitry Andric #include "llvm/ADT/SetVector.h"
25461a67faSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
26461a67faSDimitry Andric #include "llvm/ADT/SmallVector.h"
27461a67faSDimitry Andric #include "llvm/ADT/StringRef.h"
28461a67faSDimitry Andric #include "llvm/ADT/iterator.h"
29461a67faSDimitry Andric #include "llvm/Support/Chrono.h"
30461a67faSDimitry Andric #include "llvm/Support/DOTGraphTraits.h"
31461a67faSDimitry Andric #include "llvm/Support/ErrorOr.h"
3236981b17SDimitry Andric #include "llvm/Support/GraphWriter.h"
33461a67faSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
34676fbe81SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
35461a67faSDimitry Andric #include <algorithm>
36461a67faSDimitry Andric #include <cassert>
37461a67faSDimitry Andric #include <memory>
38461a67faSDimitry Andric #include <string>
39461a67faSDimitry Andric #include <system_error>
4036981b17SDimitry Andric 
4136981b17SDimitry Andric using namespace clang;
4236981b17SDimitry Andric using namespace serialization;
4336981b17SDimitry Andric 
lookupByFileName(StringRef Name) const44461a67faSDimitry Andric ModuleFile *ModuleManager::lookupByFileName(StringRef Name) const {
45519fc96cSDimitry Andric   auto Entry = FileMgr.getFile(Name, /*OpenFile=*/false,
4622989816SDimitry Andric                                /*CacheFailure=*/false);
47809500fcSDimitry Andric   if (Entry)
48519fc96cSDimitry Andric     return lookup(*Entry);
49809500fcSDimitry Andric 
509f4dbff6SDimitry Andric   return nullptr;
51809500fcSDimitry Andric }
52809500fcSDimitry Andric 
lookupByModuleName(StringRef Name) const53461a67faSDimitry Andric ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const {
54461a67faSDimitry Andric   if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
55b1c73532SDimitry Andric     if (OptionalFileEntryRef File = Mod->getASTFile())
56b1c73532SDimitry Andric       return lookup(*File);
57461a67faSDimitry Andric 
58461a67faSDimitry Andric   return nullptr;
59461a67faSDimitry Andric }
60461a67faSDimitry Andric 
lookup(const FileEntry * File) const617442d6faSDimitry Andric ModuleFile *ModuleManager::lookup(const FileEntry *File) const {
627fa27ce4SDimitry Andric   return Modules.lookup(File);
6336981b17SDimitry Andric }
6436981b17SDimitry Andric 
6506d4ba38SDimitry Andric std::unique_ptr<llvm::MemoryBuffer>
lookupBuffer(StringRef Name)6606d4ba38SDimitry Andric ModuleManager::lookupBuffer(StringRef Name) {
67519fc96cSDimitry Andric   auto Entry = FileMgr.getFile(Name, /*OpenFile=*/false,
6822989816SDimitry Andric                                /*CacheFailure=*/false);
69519fc96cSDimitry Andric   if (!Entry)
70519fc96cSDimitry Andric     return nullptr;
71519fc96cSDimitry Andric   return std::move(InMemoryBuffers[*Entry]);
7236981b17SDimitry Andric }
7336981b17SDimitry Andric 
checkSignature(ASTFileSignature Signature,ASTFileSignature ExpectedSignature,std::string & ErrorStr)747442d6faSDimitry Andric static bool checkSignature(ASTFileSignature Signature,
757442d6faSDimitry Andric                            ASTFileSignature ExpectedSignature,
767442d6faSDimitry Andric                            std::string &ErrorStr) {
777442d6faSDimitry Andric   if (!ExpectedSignature || Signature == ExpectedSignature)
787442d6faSDimitry Andric     return false;
797442d6faSDimitry Andric 
807442d6faSDimitry Andric   ErrorStr =
817442d6faSDimitry Andric       Signature ? "signature mismatch" : "could not read module signature";
827442d6faSDimitry Andric   return true;
837442d6faSDimitry Andric }
847442d6faSDimitry Andric 
updateModuleImports(ModuleFile & MF,ModuleFile * ImportedBy,SourceLocation ImportLoc)857442d6faSDimitry Andric static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy,
867442d6faSDimitry Andric                                 SourceLocation ImportLoc) {
877442d6faSDimitry Andric   if (ImportedBy) {
887442d6faSDimitry Andric     MF.ImportedBy.insert(ImportedBy);
897442d6faSDimitry Andric     ImportedBy->Imports.insert(&MF);
907442d6faSDimitry Andric   } else {
917442d6faSDimitry Andric     if (!MF.DirectlyImported)
927442d6faSDimitry Andric       MF.ImportLoc = ImportLoc;
937442d6faSDimitry Andric 
947442d6faSDimitry Andric     MF.DirectlyImported = true;
957442d6faSDimitry Andric   }
967442d6faSDimitry Andric }
977442d6faSDimitry Andric 
98809500fcSDimitry Andric 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)9936981b17SDimitry Andric ModuleManager::addModule(StringRef FileName, ModuleKind Type,
100809500fcSDimitry Andric                          SourceLocation ImportLoc, ModuleFile *ImportedBy,
101809500fcSDimitry Andric                          unsigned Generation,
102809500fcSDimitry Andric                          off_t ExpectedSize, time_t ExpectedModTime,
10306d4ba38SDimitry Andric                          ASTFileSignature ExpectedSignature,
1045e20cdd8SDimitry Andric                          ASTFileSignatureReader ReadSignature,
105809500fcSDimitry Andric                          ModuleFile *&Module,
106dbe13110SDimitry Andric                          std::string &ErrorStr) {
1079f4dbff6SDimitry Andric   Module = nullptr;
108809500fcSDimitry Andric 
109809500fcSDimitry Andric   // Look for the file entry. This only fails if the expected size or
110809500fcSDimitry Andric   // modification time differ.
111b1c73532SDimitry Andric   OptionalFileEntryRef Entry;
112bab175ecSDimitry Andric   if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) {
11306d4ba38SDimitry Andric     // If we're not expecting to pull this file out of the module cache, it
11406d4ba38SDimitry Andric     // might have a different mtime due to being moved across filesystems in
11506d4ba38SDimitry Andric     // a distributed build. The size must still match, though. (As must the
11606d4ba38SDimitry Andric     // contents, but we can't check that.)
11706d4ba38SDimitry Andric     ExpectedModTime = 0;
11806d4ba38SDimitry Andric   }
11922989816SDimitry Andric   // Note: ExpectedSize and ExpectedModTime will be 0 for MK_ImplicitModule
12022989816SDimitry Andric   // when using an ASTFileSignature.
121bfef3995SDimitry Andric   if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) {
122bfef3995SDimitry Andric     ErrorStr = "module file out of date";
123809500fcSDimitry Andric     return OutOfDate;
124bfef3995SDimitry Andric   }
125809500fcSDimitry Andric 
126b1c73532SDimitry Andric   if (!Entry) {
127bfef3995SDimitry Andric     ErrorStr = "module file not found";
128809500fcSDimitry Andric     return Missing;
12936981b17SDimitry Andric   }
13036981b17SDimitry Andric 
131b60736ecSDimitry Andric   // The ModuleManager's use of FileEntry nodes as the keys for its map of
132b60736ecSDimitry Andric   // loaded modules is less than ideal. Uniqueness for FileEntry nodes is
133b60736ecSDimitry Andric   // maintained by FileManager, which in turn uses inode numbers on hosts
134b60736ecSDimitry Andric   // that support that. When coupled with the module cache's proclivity for
135b60736ecSDimitry Andric   // turning over and deleting stale PCMs, this means entries for different
136b60736ecSDimitry Andric   // module files can wind up reusing the same underlying inode. When this
137b60736ecSDimitry Andric   // happens, subsequent accesses to the Modules map will disagree on the
138b60736ecSDimitry Andric   // ModuleFile associated with a given file. In general, it is not sufficient
139b60736ecSDimitry Andric   // to resolve this conundrum with a type like FileEntryRef that stores the
140b60736ecSDimitry Andric   // name of the FileEntry node on first access because of path canonicalization
141b60736ecSDimitry Andric   // issues. However, the paths constructed for implicit module builds are
142b60736ecSDimitry Andric   // fully under Clang's control. We *can*, therefore, rely on their structure
143b60736ecSDimitry Andric   // being consistent across operating systems and across subsequent accesses
144b60736ecSDimitry Andric   // to the Modules map.
145b60736ecSDimitry Andric   auto implicitModuleNamesMatch = [](ModuleKind Kind, const ModuleFile *MF,
146b1c73532SDimitry Andric                                      FileEntryRef Entry) -> bool {
147b60736ecSDimitry Andric     if (Kind != MK_ImplicitModule)
148b60736ecSDimitry Andric       return true;
149b1c73532SDimitry Andric     return Entry.getName() == MF->FileName;
150b60736ecSDimitry Andric   };
151b60736ecSDimitry Andric 
15236981b17SDimitry Andric   // Check whether we already loaded this module, before
153b1c73532SDimitry Andric   if (ModuleFile *ModuleEntry = Modules.lookup(*Entry)) {
154b1c73532SDimitry Andric     if (implicitModuleNamesMatch(Type, ModuleEntry, *Entry)) {
1557442d6faSDimitry Andric       // Check the stored signature.
1567442d6faSDimitry Andric       if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
1577442d6faSDimitry Andric         return OutOfDate;
15836981b17SDimitry Andric 
1597442d6faSDimitry Andric       Module = ModuleEntry;
1607442d6faSDimitry Andric       updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
1617442d6faSDimitry Andric       return AlreadyLoaded;
1627442d6faSDimitry Andric     }
163b60736ecSDimitry Andric   }
1647442d6faSDimitry Andric 
1657442d6faSDimitry Andric   // Allocate a new module.
166b1c73532SDimitry Andric   auto NewModule = std::make_unique<ModuleFile>(Type, *Entry, Generation);
1677442d6faSDimitry Andric   NewModule->Index = Chain.size();
1687442d6faSDimitry Andric   NewModule->FileName = FileName.str();
1697442d6faSDimitry Andric   NewModule->ImportLoc = ImportLoc;
1707442d6faSDimitry Andric   NewModule->InputFilesValidationTimestamp = 0;
1717442d6faSDimitry Andric 
1727442d6faSDimitry Andric   if (NewModule->Kind == MK_ImplicitModule) {
1737442d6faSDimitry Andric     std::string TimestampFilename = NewModule->getTimestampFilename();
174676fbe81SDimitry Andric     llvm::vfs::Status Status;
1759f4dbff6SDimitry Andric     // A cached stat value would be fine as well.
1769f4dbff6SDimitry Andric     if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
1777442d6faSDimitry Andric       NewModule->InputFilesValidationTimestamp =
178bab175ecSDimitry Andric           llvm::sys::toTimeT(Status.getLastModificationTime());
1799f4dbff6SDimitry Andric   }
1809f4dbff6SDimitry Andric 
18136981b17SDimitry Andric   // Load the contents of the module
18206d4ba38SDimitry Andric   if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
18336981b17SDimitry Andric     // The buffer was already provided for us.
18422989816SDimitry Andric     NewModule->Buffer = &ModuleCache->addBuiltPCM(FileName, std::move(Buffer));
185676fbe81SDimitry Andric     // Since the cached buffer is reused, it is safe to close the file
186676fbe81SDimitry Andric     // descriptor that was opened while stat()ing the PCM in
187676fbe81SDimitry Andric     // lookupModuleFile() above, it won't be needed any longer.
188676fbe81SDimitry Andric     Entry->closeFile();
18922989816SDimitry Andric   } else if (llvm::MemoryBuffer *Buffer =
19022989816SDimitry Andric                  getModuleCache().lookupPCM(FileName)) {
1917442d6faSDimitry Andric     NewModule->Buffer = Buffer;
192676fbe81SDimitry Andric     // As above, the file descriptor is no longer needed.
193676fbe81SDimitry Andric     Entry->closeFile();
19422989816SDimitry Andric   } else if (getModuleCache().shouldBuildPCM(FileName)) {
19522989816SDimitry Andric     // Report that the module is out of date, since we tried (and failed) to
19622989816SDimitry Andric     // import it earlier.
19722989816SDimitry Andric     Entry->closeFile();
19822989816SDimitry Andric     return OutOfDate;
19936981b17SDimitry Andric   } else {
200676fbe81SDimitry Andric     // Get a buffer of the file and close the file descriptor when done.
201cfca06d7SDimitry Andric     // The file is volatile because in a parallel build we expect multiple
202cfca06d7SDimitry Andric     // compiler processes to use the same module file rebuilding it if needed.
203cfca06d7SDimitry Andric     //
204cfca06d7SDimitry Andric     // RequiresNullTerminator is false because module files don't need it, and
205cfca06d7SDimitry Andric     // this allows the file to still be mmapped.
206b1c73532SDimitry Andric     auto Buf = FileMgr.getBufferForFile(NewModule->File,
207cfca06d7SDimitry Andric                                         /*IsVolatile=*/true,
208cfca06d7SDimitry Andric                                         /*RequiresNullTerminator=*/false);
20936981b17SDimitry Andric 
21006d4ba38SDimitry Andric     if (!Buf) {
21106d4ba38SDimitry Andric       ErrorStr = Buf.getError().message();
212809500fcSDimitry Andric       return Missing;
21336981b17SDimitry Andric     }
21436981b17SDimitry Andric 
21522989816SDimitry Andric     NewModule->Buffer = &getModuleCache().addPCM(FileName, std::move(*Buf));
21606d4ba38SDimitry Andric   }
21706d4ba38SDimitry Andric 
2182e645aa5SDimitry Andric   // Initialize the stream.
2197442d6faSDimitry Andric   NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
22036981b17SDimitry Andric 
2217442d6faSDimitry Andric   // Read the signature eagerly now so that we can check it.  Avoid calling
2227442d6faSDimitry Andric   // ReadSignature unless there's something to check though.
2237442d6faSDimitry Andric   if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
224519fc96cSDimitry Andric                                           ExpectedSignature, ErrorStr))
22506d4ba38SDimitry Andric     return OutOfDate;
22606d4ba38SDimitry Andric 
2277442d6faSDimitry Andric   // We're keeping this module.  Store it everywhere.
228b1c73532SDimitry Andric   Module = Modules[*Entry] = NewModule.get();
229809500fcSDimitry Andric 
2307442d6faSDimitry Andric   updateModuleImports(*NewModule, ImportedBy, ImportLoc);
23136981b17SDimitry Andric 
2327442d6faSDimitry Andric   if (!NewModule->isModule())
2337442d6faSDimitry Andric     PCHChain.push_back(NewModule.get());
234bab175ecSDimitry Andric   if (!ImportedBy)
2357442d6faSDimitry Andric     Roots.push_back(NewModule.get());
236bab175ecSDimitry Andric 
2377442d6faSDimitry Andric   Chain.push_back(std::move(NewModule));
238bab175ecSDimitry Andric   return NewlyLoaded;
23936981b17SDimitry Andric }
24036981b17SDimitry Andric 
removeModules(ModuleIterator First)241e3b55780SDimitry Andric void ModuleManager::removeModules(ModuleIterator First) {
2427442d6faSDimitry Andric   auto Last = end();
2437442d6faSDimitry Andric   if (First == Last)
24413cc256eSDimitry Andric     return;
24513cc256eSDimitry Andric 
24645b53394SDimitry Andric   // Explicitly clear VisitOrder since we might not notice it is stale.
24745b53394SDimitry Andric   VisitOrder.clear();
24845b53394SDimitry Andric 
24913cc256eSDimitry Andric   // Collect the set of module file pointers that we'll be removing.
2507442d6faSDimitry Andric   llvm::SmallPtrSet<ModuleFile *, 4> victimSet(
2517442d6faSDimitry Andric       (llvm::pointer_iterator<ModuleIterator>(First)),
2527442d6faSDimitry Andric       (llvm::pointer_iterator<ModuleIterator>(Last)));
25313cc256eSDimitry Andric 
2545e20cdd8SDimitry Andric   auto IsVictim = [&](ModuleFile *MF) {
2555e20cdd8SDimitry Andric     return victimSet.count(MF);
2565e20cdd8SDimitry Andric   };
25713cc256eSDimitry Andric   // Remove any references to the now-destroyed modules.
2587442d6faSDimitry Andric   for (auto I = begin(); I != First; ++I) {
2597442d6faSDimitry Andric     I->Imports.remove_if(IsVictim);
2607442d6faSDimitry Andric     I->ImportedBy.remove_if(IsVictim);
26113cc256eSDimitry Andric   }
262c0981da4SDimitry Andric   llvm::erase_if(Roots, IsVictim);
26313cc256eSDimitry Andric 
26445b53394SDimitry Andric   // Remove the modules from the PCH chain.
2657442d6faSDimitry Andric   for (auto I = First; I != Last; ++I) {
2667442d6faSDimitry Andric     if (!I->isModule()) {
26722989816SDimitry Andric       PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
26845b53394SDimitry Andric       break;
26945b53394SDimitry Andric     }
27045b53394SDimitry Andric   }
27145b53394SDimitry Andric 
272e3b55780SDimitry Andric   // Delete the modules.
273e3b55780SDimitry Andric   for (ModuleIterator victim = First; victim != Last; ++victim)
2747442d6faSDimitry Andric     Modules.erase(victim->File);
275809500fcSDimitry Andric 
2767442d6faSDimitry Andric   Chain.erase(Chain.begin() + (First - begin()), Chain.end());
27713cc256eSDimitry Andric }
27813cc256eSDimitry Andric 
27906d4ba38SDimitry Andric void
addInMemoryBuffer(StringRef FileName,std::unique_ptr<llvm::MemoryBuffer> Buffer)28006d4ba38SDimitry Andric ModuleManager::addInMemoryBuffer(StringRef FileName,
28106d4ba38SDimitry Andric                                  std::unique_ptr<llvm::MemoryBuffer> Buffer) {
28206d4ba38SDimitry Andric   const FileEntry *Entry =
28306d4ba38SDimitry Andric       FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
28406d4ba38SDimitry Andric   InMemoryBuffers[Entry] = std::move(Buffer);
28536981b17SDimitry Andric }
28636981b17SDimitry Andric 
allocateVisitState()2876f8fc217SDimitry Andric std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
288809500fcSDimitry Andric   // Fast path: if we have a cached state, use it.
289809500fcSDimitry Andric   if (FirstVisitState) {
2906f8fc217SDimitry Andric     auto Result = std::move(FirstVisitState);
2916f8fc217SDimitry Andric     FirstVisitState = std::move(Result->NextState);
292809500fcSDimitry Andric     return Result;
293809500fcSDimitry Andric   }
294809500fcSDimitry Andric 
295809500fcSDimitry Andric   // Allocate and return a new state.
2966f8fc217SDimitry Andric   return std::make_unique<VisitState>(size());
297809500fcSDimitry Andric }
298809500fcSDimitry Andric 
returnVisitState(std::unique_ptr<VisitState> State)2996f8fc217SDimitry Andric void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
3009f4dbff6SDimitry Andric   assert(State->NextState == nullptr && "Visited state is in list?");
3016f8fc217SDimitry Andric   State->NextState = std::move(FirstVisitState);
3026f8fc217SDimitry Andric   FirstVisitState = std::move(State);
303809500fcSDimitry Andric }
304809500fcSDimitry Andric 
setGlobalIndex(GlobalModuleIndex * Index)305809500fcSDimitry Andric void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
306809500fcSDimitry Andric   GlobalIndex = Index;
307809500fcSDimitry Andric   if (!GlobalIndex) {
308809500fcSDimitry Andric     ModulesInCommonWithGlobalIndex.clear();
309809500fcSDimitry Andric     return;
310809500fcSDimitry Andric   }
311809500fcSDimitry Andric 
312809500fcSDimitry Andric   // Notify the global module index about all of the modules we've already
313809500fcSDimitry Andric   // loaded.
3147442d6faSDimitry Andric   for (ModuleFile &M : *this)
3157442d6faSDimitry Andric     if (!GlobalIndex->loadedModuleFile(&M))
3167442d6faSDimitry Andric       ModulesInCommonWithGlobalIndex.push_back(&M);
317809500fcSDimitry Andric }
318809500fcSDimitry Andric 
moduleFileAccepted(ModuleFile * MF)319809500fcSDimitry Andric void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
320809500fcSDimitry Andric   if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
321809500fcSDimitry Andric     return;
322809500fcSDimitry Andric 
323809500fcSDimitry Andric   ModulesInCommonWithGlobalIndex.push_back(MF);
324809500fcSDimitry Andric }
325809500fcSDimitry Andric 
ModuleManager(FileManager & FileMgr,InMemoryModuleCache & ModuleCache,const PCHContainerReader & PCHContainerRdr,const HeaderSearch & HeaderSearchInfo)32622989816SDimitry Andric ModuleManager::ModuleManager(FileManager &FileMgr,
32722989816SDimitry Andric                              InMemoryModuleCache &ModuleCache,
328461a67faSDimitry Andric                              const PCHContainerReader &PCHContainerRdr,
329461a67faSDimitry Andric                              const HeaderSearch &HeaderSearchInfo)
33022989816SDimitry Andric     : FileMgr(FileMgr), ModuleCache(&ModuleCache),
33122989816SDimitry Andric       PCHContainerRdr(PCHContainerRdr), HeaderSearchInfo(HeaderSearchInfo) {}
33236981b17SDimitry Andric 
visit(llvm::function_ref<bool (ModuleFile & M)> Visitor,llvm::SmallPtrSetImpl<ModuleFile * > * ModuleFilesHit)33345b53394SDimitry Andric void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
33406d4ba38SDimitry Andric                           llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
335809500fcSDimitry Andric   // If the visitation order vector is the wrong size, recompute the order.
336809500fcSDimitry Andric   if (VisitOrder.size() != Chain.size()) {
33736981b17SDimitry Andric     unsigned N = size();
338809500fcSDimitry Andric     VisitOrder.clear();
339809500fcSDimitry Andric     VisitOrder.reserve(N);
34036981b17SDimitry Andric 
34136981b17SDimitry Andric     // Record the number of incoming edges for each module. When we
34236981b17SDimitry Andric     // encounter a module with no incoming edges, push it into the queue
34336981b17SDimitry Andric     // to seed the queue.
344dbe13110SDimitry Andric     SmallVector<ModuleFile *, 4> Queue;
34536981b17SDimitry Andric     Queue.reserve(N);
346809500fcSDimitry Andric     llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
34745b53394SDimitry Andric     UnusedIncomingEdges.resize(size());
3487442d6faSDimitry Andric     for (ModuleFile &M : llvm::reverse(*this)) {
3497442d6faSDimitry Andric       unsigned Size = M.ImportedBy.size();
3507442d6faSDimitry Andric       UnusedIncomingEdges[M.Index] = Size;
35145b53394SDimitry Andric       if (!Size)
3527442d6faSDimitry Andric         Queue.push_back(&M);
35336981b17SDimitry Andric     }
35436981b17SDimitry Andric 
355809500fcSDimitry Andric     // Traverse the graph, making sure to visit a module before visiting any
356809500fcSDimitry Andric     // of its dependencies.
35745b53394SDimitry Andric     while (!Queue.empty()) {
35845b53394SDimitry Andric       ModuleFile *CurrentModule = Queue.pop_back_val();
359809500fcSDimitry Andric       VisitOrder.push_back(CurrentModule);
36036981b17SDimitry Andric 
361809500fcSDimitry Andric       // For any module that this module depends on, push it on the
362809500fcSDimitry Andric       // stack (if it hasn't already been marked as visited).
363c0981da4SDimitry Andric       for (ModuleFile *M : llvm::reverse(CurrentModule->Imports)) {
364809500fcSDimitry Andric         // Remove our current module as an impediment to visiting the
365809500fcSDimitry Andric         // module we depend on. If we were the last unvisited module
366809500fcSDimitry Andric         // that depends on this particular module, push it into the
367809500fcSDimitry Andric         // queue to be visited.
368c0981da4SDimitry Andric         unsigned &NumUnusedEdges = UnusedIncomingEdges[M->Index];
369809500fcSDimitry Andric         if (NumUnusedEdges && (--NumUnusedEdges == 0))
370c0981da4SDimitry Andric           Queue.push_back(M);
371809500fcSDimitry Andric       }
372809500fcSDimitry Andric     }
373809500fcSDimitry Andric 
374809500fcSDimitry Andric     assert(VisitOrder.size() == N && "Visitation order is wrong?");
375809500fcSDimitry Andric 
3769f4dbff6SDimitry Andric     FirstVisitState = nullptr;
377809500fcSDimitry Andric   }
378809500fcSDimitry Andric 
3796f8fc217SDimitry Andric   auto State = allocateVisitState();
380809500fcSDimitry Andric   unsigned VisitNumber = State->NextVisitNumber++;
381809500fcSDimitry Andric 
382809500fcSDimitry Andric   // If the caller has provided us with a hit-set that came from the global
383809500fcSDimitry Andric   // module index, mark every module file in common with the global module
384809500fcSDimitry Andric   // index that is *not* in that set as 'visited'.
385809500fcSDimitry Andric   if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
386809500fcSDimitry Andric     for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
387809500fcSDimitry Andric     {
388809500fcSDimitry Andric       ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
389809500fcSDimitry Andric       if (!ModuleFilesHit->count(M))
390809500fcSDimitry Andric         State->VisitNumber[M->Index] = VisitNumber;
391809500fcSDimitry Andric     }
392809500fcSDimitry Andric   }
393809500fcSDimitry Andric 
394809500fcSDimitry Andric   for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
395809500fcSDimitry Andric     ModuleFile *CurrentModule = VisitOrder[I];
396809500fcSDimitry Andric     // Should we skip this module file?
397809500fcSDimitry Andric     if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
39836981b17SDimitry Andric       continue;
39936981b17SDimitry Andric 
400809500fcSDimitry Andric     // Visit the module.
401809500fcSDimitry Andric     assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
402809500fcSDimitry Andric     State->VisitNumber[CurrentModule->Index] = VisitNumber;
40345b53394SDimitry Andric     if (!Visitor(*CurrentModule))
404809500fcSDimitry Andric       continue;
405809500fcSDimitry Andric 
40636981b17SDimitry Andric     // The visitor has requested that cut off visitation of any
40736981b17SDimitry Andric     // module that the current module depends on. To indicate this
408809500fcSDimitry Andric     // behavior, we mark all of the reachable modules as having been visited.
409809500fcSDimitry Andric     ModuleFile *NextModule = CurrentModule;
410809500fcSDimitry Andric     do {
41136981b17SDimitry Andric       // For any module that this module depends on, push it on the
41236981b17SDimitry Andric       // stack (if it hasn't already been marked as visited).
413dbe13110SDimitry Andric       for (llvm::SetVector<ModuleFile *>::iterator
41436981b17SDimitry Andric              M = NextModule->Imports.begin(),
41536981b17SDimitry Andric              MEnd = NextModule->Imports.end();
41636981b17SDimitry Andric            M != MEnd; ++M) {
417809500fcSDimitry Andric         if (State->VisitNumber[(*M)->Index] != VisitNumber) {
418809500fcSDimitry Andric           State->Stack.push_back(*M);
419809500fcSDimitry Andric           State->VisitNumber[(*M)->Index] = VisitNumber;
42036981b17SDimitry Andric         }
42136981b17SDimitry Andric       }
42236981b17SDimitry Andric 
423809500fcSDimitry Andric       if (State->Stack.empty())
424809500fcSDimitry Andric         break;
42536981b17SDimitry Andric 
426809500fcSDimitry Andric       // Pop the next module off the stack.
427bfef3995SDimitry Andric       NextModule = State->Stack.pop_back_val();
428809500fcSDimitry Andric     } while (true);
42936981b17SDimitry Andric   }
430809500fcSDimitry Andric 
4316f8fc217SDimitry Andric   returnVisitState(std::move(State));
43236981b17SDimitry Andric }
43336981b17SDimitry Andric 
lookupModuleFile(StringRef FileName,off_t ExpectedSize,time_t ExpectedModTime,OptionalFileEntryRef & File)434b60736ecSDimitry Andric bool ModuleManager::lookupModuleFile(StringRef FileName, off_t ExpectedSize,
435809500fcSDimitry Andric                                      time_t ExpectedModTime,
436e3b55780SDimitry Andric                                      OptionalFileEntryRef &File) {
437b1c73532SDimitry Andric   if (FileName == "-") {
438b1c73532SDimitry Andric     File = expectedToOptional(FileMgr.getSTDIN());
439bab175ecSDimitry Andric     return false;
440b1c73532SDimitry Andric   }
441bab175ecSDimitry Andric 
4429f4dbff6SDimitry Andric   // Open the file immediately to ensure there is no race between stat'ing and
4439f4dbff6SDimitry Andric   // opening the file.
444b1c73532SDimitry Andric   File = FileMgr.getOptionalFileRef(FileName, /*OpenFile=*/true,
445b1c73532SDimitry Andric                                     /*CacheFailure=*/false);
446b60736ecSDimitry Andric 
447b1c73532SDimitry Andric   if (File &&
448b1c73532SDimitry Andric       ((ExpectedSize && ExpectedSize != File->getSize()) ||
449b1c73532SDimitry Andric        (ExpectedModTime && ExpectedModTime != File->getModificationTime())))
4509f4dbff6SDimitry Andric     // Do not destroy File, as it may be referenced. If we need to rebuild it,
4519f4dbff6SDimitry Andric     // it will be destroyed by removeModules.
452809500fcSDimitry Andric     return true;
453809500fcSDimitry Andric 
454809500fcSDimitry Andric   return false;
455809500fcSDimitry Andric }
456809500fcSDimitry Andric 
45736981b17SDimitry Andric #ifndef NDEBUG
45836981b17SDimitry Andric namespace llvm {
459461a67faSDimitry Andric 
46036981b17SDimitry Andric   template<>
46136981b17SDimitry Andric   struct GraphTraits<ModuleManager> {
462461a67faSDimitry Andric     using NodeRef = ModuleFile *;
463461a67faSDimitry Andric     using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
464461a67faSDimitry Andric     using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
46536981b17SDimitry Andric 
child_beginllvm::GraphTraits466bab175ecSDimitry Andric     static ChildIteratorType child_begin(NodeRef Node) {
46736981b17SDimitry Andric       return Node->Imports.begin();
46836981b17SDimitry Andric     }
46936981b17SDimitry Andric 
child_endllvm::GraphTraits470bab175ecSDimitry Andric     static ChildIteratorType child_end(NodeRef Node) {
47136981b17SDimitry Andric       return Node->Imports.end();
47236981b17SDimitry Andric     }
47336981b17SDimitry Andric 
nodes_beginllvm::GraphTraits47436981b17SDimitry Andric     static nodes_iterator nodes_begin(const ModuleManager &Manager) {
4757442d6faSDimitry Andric       return nodes_iterator(Manager.begin());
47636981b17SDimitry Andric     }
47736981b17SDimitry Andric 
nodes_endllvm::GraphTraits47836981b17SDimitry Andric     static nodes_iterator nodes_end(const ModuleManager &Manager) {
4797442d6faSDimitry Andric       return nodes_iterator(Manager.end());
48036981b17SDimitry Andric     }
48136981b17SDimitry Andric   };
48236981b17SDimitry Andric 
48336981b17SDimitry Andric   template<>
48436981b17SDimitry Andric   struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits48536981b17SDimitry Andric     explicit DOTGraphTraits(bool IsSimple = false)
48636981b17SDimitry Andric         : DefaultDOTGraphTraits(IsSimple) {}
48736981b17SDimitry Andric 
renderGraphFromBottomUpllvm::DOTGraphTraits488461a67faSDimitry Andric     static bool renderGraphFromBottomUp() { return true; }
48936981b17SDimitry Andric 
getNodeLabelllvm::DOTGraphTraits490dbe13110SDimitry Andric     std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
4919f4dbff6SDimitry Andric       return M->ModuleName;
49236981b17SDimitry Andric     }
49336981b17SDimitry Andric   };
494461a67faSDimitry Andric 
495461a67faSDimitry Andric } // namespace llvm
49636981b17SDimitry Andric 
viewGraph()49736981b17SDimitry Andric void ModuleManager::viewGraph() {
49836981b17SDimitry Andric   llvm::ViewGraph(*this, "Modules");
49936981b17SDimitry Andric }
50036981b17SDimitry Andric #endif
501