19a199699SDimitry Andric //===- ModuleManager.cpp - Module Manager ---------------------------------===//
26122f3e6SDimitry Andric //
36122f3e6SDimitry Andric //                     The LLVM Compiler Infrastructure
46122f3e6SDimitry Andric //
56122f3e6SDimitry Andric // This file is distributed under the University of Illinois Open Source
66122f3e6SDimitry Andric // License. See LICENSE.TXT for details.
76122f3e6SDimitry Andric //
86122f3e6SDimitry Andric //===----------------------------------------------------------------------===//
96122f3e6SDimitry Andric //
106122f3e6SDimitry Andric //  This file defines the ModuleManager class, which manages a set of loaded
116122f3e6SDimitry Andric //  modules for the ASTReader.
126122f3e6SDimitry Andric //
136122f3e6SDimitry Andric //===----------------------------------------------------------------------===//
149a199699SDimitry Andric 
1544290647SDimitry Andric #include "clang/Serialization/ModuleManager.h"
169a199699SDimitry Andric #include "clang/Basic/FileManager.h"
179a199699SDimitry Andric #include "clang/Basic/LLVM.h"
1820e90f04SDimitry Andric #include "clang/Basic/MemoryBufferCache.h"
1959d1ed5bSDimitry Andric #include "clang/Lex/HeaderSearch.h"
20139f7f9bSDimitry Andric #include "clang/Lex/ModuleMap.h"
21139f7f9bSDimitry Andric #include "clang/Serialization/GlobalModuleIndex.h"
229a199699SDimitry Andric #include "clang/Serialization/Module.h"
23*b5893f02SDimitry Andric #include "clang/Serialization/PCHContainerOperations.h"
249a199699SDimitry Andric #include "llvm/ADT/STLExtras.h"
259a199699SDimitry Andric #include "llvm/ADT/SetVector.h"
269a199699SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
279a199699SDimitry Andric #include "llvm/ADT/SmallVector.h"
289a199699SDimitry Andric #include "llvm/ADT/StringRef.h"
299a199699SDimitry Andric #include "llvm/ADT/iterator.h"
309a199699SDimitry Andric #include "llvm/Support/Chrono.h"
319a199699SDimitry Andric #include "llvm/Support/DOTGraphTraits.h"
329a199699SDimitry Andric #include "llvm/Support/ErrorOr.h"
336122f3e6SDimitry Andric #include "llvm/Support/GraphWriter.h"
349a199699SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
35*b5893f02SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
369a199699SDimitry Andric #include <algorithm>
379a199699SDimitry Andric #include <cassert>
389a199699SDimitry Andric #include <memory>
399a199699SDimitry Andric #include <string>
409a199699SDimitry Andric #include <system_error>
416122f3e6SDimitry Andric 
426122f3e6SDimitry Andric using namespace clang;
436122f3e6SDimitry Andric using namespace serialization;
446122f3e6SDimitry Andric 
lookupByFileName(StringRef Name) const459a199699SDimitry Andric ModuleFile *ModuleManager::lookupByFileName(StringRef Name) const {
46139f7f9bSDimitry Andric   const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
47139f7f9bSDimitry Andric                                            /*cacheFailure=*/false);
48139f7f9bSDimitry Andric   if (Entry)
49139f7f9bSDimitry Andric     return lookup(Entry);
50139f7f9bSDimitry Andric 
5159d1ed5bSDimitry Andric   return nullptr;
52139f7f9bSDimitry Andric }
53139f7f9bSDimitry Andric 
lookupByModuleName(StringRef Name) const549a199699SDimitry Andric ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const {
559a199699SDimitry Andric   if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
569a199699SDimitry Andric     if (const FileEntry *File = Mod->getASTFile())
579a199699SDimitry Andric       return lookup(File);
589a199699SDimitry Andric 
599a199699SDimitry Andric   return nullptr;
609a199699SDimitry Andric }
619a199699SDimitry Andric 
lookup(const FileEntry * File) const6220e90f04SDimitry Andric ModuleFile *ModuleManager::lookup(const FileEntry *File) const {
6320e90f04SDimitry Andric   auto Known = Modules.find(File);
64139f7f9bSDimitry Andric   if (Known == Modules.end())
6559d1ed5bSDimitry Andric     return nullptr;
66139f7f9bSDimitry Andric 
67139f7f9bSDimitry Andric   return Known->second;
686122f3e6SDimitry Andric }
696122f3e6SDimitry Andric 
7039d628a0SDimitry Andric std::unique_ptr<llvm::MemoryBuffer>
lookupBuffer(StringRef Name)7139d628a0SDimitry Andric ModuleManager::lookupBuffer(StringRef Name) {
72139f7f9bSDimitry Andric   const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
73139f7f9bSDimitry Andric                                            /*cacheFailure=*/false);
7439d628a0SDimitry Andric   return std::move(InMemoryBuffers[Entry]);
756122f3e6SDimitry Andric }
766122f3e6SDimitry Andric 
checkSignature(ASTFileSignature Signature,ASTFileSignature ExpectedSignature,std::string & ErrorStr)7720e90f04SDimitry Andric static bool checkSignature(ASTFileSignature Signature,
7820e90f04SDimitry Andric                            ASTFileSignature ExpectedSignature,
7920e90f04SDimitry Andric                            std::string &ErrorStr) {
8020e90f04SDimitry Andric   if (!ExpectedSignature || Signature == ExpectedSignature)
8120e90f04SDimitry Andric     return false;
8220e90f04SDimitry Andric 
8320e90f04SDimitry Andric   ErrorStr =
8420e90f04SDimitry Andric       Signature ? "signature mismatch" : "could not read module signature";
8520e90f04SDimitry Andric   return true;
8620e90f04SDimitry Andric }
8720e90f04SDimitry Andric 
updateModuleImports(ModuleFile & MF,ModuleFile * ImportedBy,SourceLocation ImportLoc)8820e90f04SDimitry Andric static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy,
8920e90f04SDimitry Andric                                 SourceLocation ImportLoc) {
9020e90f04SDimitry Andric   if (ImportedBy) {
9120e90f04SDimitry Andric     MF.ImportedBy.insert(ImportedBy);
9220e90f04SDimitry Andric     ImportedBy->Imports.insert(&MF);
9320e90f04SDimitry Andric   } else {
9420e90f04SDimitry Andric     if (!MF.DirectlyImported)
9520e90f04SDimitry Andric       MF.ImportLoc = ImportLoc;
9620e90f04SDimitry Andric 
9720e90f04SDimitry Andric     MF.DirectlyImported = true;
9820e90f04SDimitry Andric   }
9920e90f04SDimitry Andric }
10020e90f04SDimitry Andric 
101139f7f9bSDimitry 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)1026122f3e6SDimitry Andric ModuleManager::addModule(StringRef FileName, ModuleKind Type,
103139f7f9bSDimitry Andric                          SourceLocation ImportLoc, ModuleFile *ImportedBy,
104139f7f9bSDimitry Andric                          unsigned Generation,
105139f7f9bSDimitry Andric                          off_t ExpectedSize, time_t ExpectedModTime,
10639d628a0SDimitry Andric                          ASTFileSignature ExpectedSignature,
10733956c43SDimitry Andric                          ASTFileSignatureReader ReadSignature,
108139f7f9bSDimitry Andric                          ModuleFile *&Module,
109dff0c46cSDimitry Andric                          std::string &ErrorStr) {
11059d1ed5bSDimitry Andric   Module = nullptr;
111139f7f9bSDimitry Andric 
112139f7f9bSDimitry Andric   // Look for the file entry. This only fails if the expected size or
113139f7f9bSDimitry Andric   // modification time differ.
114139f7f9bSDimitry Andric   const FileEntry *Entry;
11544290647SDimitry Andric   if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) {
11639d628a0SDimitry Andric     // If we're not expecting to pull this file out of the module cache, it
11739d628a0SDimitry Andric     // might have a different mtime due to being moved across filesystems in
11839d628a0SDimitry Andric     // a distributed build. The size must still match, though. (As must the
11939d628a0SDimitry Andric     // contents, but we can't check that.)
12039d628a0SDimitry Andric     ExpectedModTime = 0;
12139d628a0SDimitry Andric   }
122f785676fSDimitry Andric   if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) {
123f785676fSDimitry Andric     ErrorStr = "module file out of date";
124139f7f9bSDimitry Andric     return OutOfDate;
125f785676fSDimitry Andric   }
126139f7f9bSDimitry Andric 
1276122f3e6SDimitry Andric   if (!Entry && FileName != "-") {
128f785676fSDimitry Andric     ErrorStr = "module file not found";
129139f7f9bSDimitry Andric     return Missing;
1306122f3e6SDimitry Andric   }
1316122f3e6SDimitry Andric 
1326122f3e6SDimitry Andric   // Check whether we already loaded this module, before
13320e90f04SDimitry Andric   if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) {
13420e90f04SDimitry Andric     // Check the stored signature.
13520e90f04SDimitry Andric     if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
13620e90f04SDimitry Andric       return OutOfDate;
1376122f3e6SDimitry Andric 
13820e90f04SDimitry Andric     Module = ModuleEntry;
13920e90f04SDimitry Andric     updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
14020e90f04SDimitry Andric     return AlreadyLoaded;
14120e90f04SDimitry Andric   }
14220e90f04SDimitry Andric 
14320e90f04SDimitry Andric   // Allocate a new module.
14420e90f04SDimitry Andric   auto NewModule = llvm::make_unique<ModuleFile>(Type, Generation);
14520e90f04SDimitry Andric   NewModule->Index = Chain.size();
14620e90f04SDimitry Andric   NewModule->FileName = FileName.str();
14720e90f04SDimitry Andric   NewModule->File = Entry;
14820e90f04SDimitry Andric   NewModule->ImportLoc = ImportLoc;
14920e90f04SDimitry Andric   NewModule->InputFilesValidationTimestamp = 0;
15020e90f04SDimitry Andric 
15120e90f04SDimitry Andric   if (NewModule->Kind == MK_ImplicitModule) {
15220e90f04SDimitry Andric     std::string TimestampFilename = NewModule->getTimestampFilename();
153*b5893f02SDimitry Andric     llvm::vfs::Status Status;
15459d1ed5bSDimitry Andric     // A cached stat value would be fine as well.
15559d1ed5bSDimitry Andric     if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
15620e90f04SDimitry Andric       NewModule->InputFilesValidationTimestamp =
15744290647SDimitry Andric           llvm::sys::toTimeT(Status.getLastModificationTime());
15859d1ed5bSDimitry Andric   }
15959d1ed5bSDimitry Andric 
1606122f3e6SDimitry Andric   // Load the contents of the module
16139d628a0SDimitry Andric   if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
1626122f3e6SDimitry Andric     // The buffer was already provided for us.
16320e90f04SDimitry Andric     NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(Buffer));
164*b5893f02SDimitry Andric     // Since the cached buffer is reused, it is safe to close the file
165*b5893f02SDimitry Andric     // descriptor that was opened while stat()ing the PCM in
166*b5893f02SDimitry Andric     // lookupModuleFile() above, it won't be needed any longer.
167*b5893f02SDimitry Andric     Entry->closeFile();
16820e90f04SDimitry Andric   } else if (llvm::MemoryBuffer *Buffer = PCMCache->lookupBuffer(FileName)) {
16920e90f04SDimitry Andric     NewModule->Buffer = Buffer;
170*b5893f02SDimitry Andric     // As above, the file descriptor is no longer needed.
171*b5893f02SDimitry Andric     Entry->closeFile();
1726122f3e6SDimitry Andric   } else {
1736122f3e6SDimitry Andric     // Open the AST file.
17420e90f04SDimitry Andric     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
1756122f3e6SDimitry Andric     if (FileName == "-") {
17639d628a0SDimitry Andric       Buf = llvm::MemoryBuffer::getSTDIN();
17759d1ed5bSDimitry Andric     } else {
178*b5893f02SDimitry Andric       // Get a buffer of the file and close the file descriptor when done.
17920e90f04SDimitry Andric       Buf = FileMgr.getBufferForFile(NewModule->File,
18039d628a0SDimitry Andric                                      /*IsVolatile=*/false,
181*b5893f02SDimitry Andric                                      /*ShouldClose=*/true);
18259d1ed5bSDimitry Andric     }
1836122f3e6SDimitry Andric 
18439d628a0SDimitry Andric     if (!Buf) {
18539d628a0SDimitry Andric       ErrorStr = Buf.getError().message();
186139f7f9bSDimitry Andric       return Missing;
1876122f3e6SDimitry Andric     }
1886122f3e6SDimitry Andric 
18920e90f04SDimitry Andric     NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(*Buf));
19039d628a0SDimitry Andric   }
19139d628a0SDimitry Andric 
1928f0fd8f6SDimitry Andric   // Initialize the stream.
19320e90f04SDimitry Andric   NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
1946122f3e6SDimitry Andric 
19520e90f04SDimitry Andric   // Read the signature eagerly now so that we can check it.  Avoid calling
19620e90f04SDimitry Andric   // ReadSignature unless there's something to check though.
19720e90f04SDimitry Andric   if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
19820e90f04SDimitry Andric                                           ExpectedSignature, ErrorStr)) {
19920e90f04SDimitry Andric     // Try to remove the buffer.  If it can't be removed, then it was already
20020e90f04SDimitry Andric     // validated by this process.
20120e90f04SDimitry Andric     if (!PCMCache->tryToRemoveBuffer(NewModule->FileName))
20220e90f04SDimitry Andric       FileMgr.invalidateCache(NewModule->File);
20339d628a0SDimitry Andric     return OutOfDate;
20439d628a0SDimitry Andric   }
20539d628a0SDimitry Andric 
20620e90f04SDimitry Andric   // We're keeping this module.  Store it everywhere.
20720e90f04SDimitry Andric   Module = Modules[Entry] = NewModule.get();
208139f7f9bSDimitry Andric 
20920e90f04SDimitry Andric   updateModuleImports(*NewModule, ImportedBy, ImportLoc);
2106122f3e6SDimitry Andric 
21120e90f04SDimitry Andric   if (!NewModule->isModule())
21220e90f04SDimitry Andric     PCHChain.push_back(NewModule.get());
21344290647SDimitry Andric   if (!ImportedBy)
21420e90f04SDimitry Andric     Roots.push_back(NewModule.get());
21544290647SDimitry Andric 
21620e90f04SDimitry Andric   Chain.push_back(std::move(NewModule));
21744290647SDimitry Andric   return NewlyLoaded;
2186122f3e6SDimitry Andric }
2196122f3e6SDimitry Andric 
removeModules(ModuleIterator First,llvm::SmallPtrSetImpl<ModuleFile * > & LoadedSuccessfully,ModuleMap * modMap)22059d1ed5bSDimitry Andric void ModuleManager::removeModules(
22120e90f04SDimitry Andric     ModuleIterator First,
22259d1ed5bSDimitry Andric     llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
223139f7f9bSDimitry Andric     ModuleMap *modMap) {
22420e90f04SDimitry Andric   auto Last = end();
22520e90f04SDimitry Andric   if (First == Last)
2263861d79fSDimitry Andric     return;
2273861d79fSDimitry Andric 
2280623d748SDimitry Andric   // Explicitly clear VisitOrder since we might not notice it is stale.
2290623d748SDimitry Andric   VisitOrder.clear();
2300623d748SDimitry Andric 
2313861d79fSDimitry Andric   // Collect the set of module file pointers that we'll be removing.
23220e90f04SDimitry Andric   llvm::SmallPtrSet<ModuleFile *, 4> victimSet(
23320e90f04SDimitry Andric       (llvm::pointer_iterator<ModuleIterator>(First)),
23420e90f04SDimitry Andric       (llvm::pointer_iterator<ModuleIterator>(Last)));
2353861d79fSDimitry Andric 
23633956c43SDimitry Andric   auto IsVictim = [&](ModuleFile *MF) {
23733956c43SDimitry Andric     return victimSet.count(MF);
23833956c43SDimitry Andric   };
2393861d79fSDimitry Andric   // Remove any references to the now-destroyed modules.
24020e90f04SDimitry Andric   for (auto I = begin(); I != First; ++I) {
24120e90f04SDimitry Andric     I->Imports.remove_if(IsVictim);
24220e90f04SDimitry Andric     I->ImportedBy.remove_if(IsVictim);
2433861d79fSDimitry Andric   }
24433956c43SDimitry Andric   Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
24533956c43SDimitry Andric               Roots.end());
2463861d79fSDimitry Andric 
2470623d748SDimitry Andric   // Remove the modules from the PCH chain.
24820e90f04SDimitry Andric   for (auto I = First; I != Last; ++I) {
24920e90f04SDimitry Andric     if (!I->isModule()) {
25020e90f04SDimitry Andric       PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), &*I),
2510623d748SDimitry Andric                      PCHChain.end());
2520623d748SDimitry Andric       break;
2530623d748SDimitry Andric     }
2540623d748SDimitry Andric   }
2550623d748SDimitry Andric 
2563861d79fSDimitry Andric   // Delete the modules and erase them from the various structures.
25720e90f04SDimitry Andric   for (ModuleIterator victim = First; victim != Last; ++victim) {
25820e90f04SDimitry Andric     Modules.erase(victim->File);
259139f7f9bSDimitry Andric 
260139f7f9bSDimitry Andric     if (modMap) {
26120e90f04SDimitry Andric       StringRef ModuleName = victim->ModuleName;
262139f7f9bSDimitry Andric       if (Module *mod = modMap->findModule(ModuleName)) {
26359d1ed5bSDimitry Andric         mod->setASTFile(nullptr);
264139f7f9bSDimitry Andric       }
265139f7f9bSDimitry Andric     }
26659d1ed5bSDimitry Andric 
26759d1ed5bSDimitry Andric     // Files that didn't make it through ReadASTCore successfully will be
26859d1ed5bSDimitry Andric     // rebuilt (or there was an error). Invalidate them so that we can load the
26959d1ed5bSDimitry Andric     // new files that will be renamed over the old ones.
27020e90f04SDimitry Andric     //
27120e90f04SDimitry Andric     // The PCMCache tracks whether the module was successfully loaded in another
27220e90f04SDimitry Andric     // thread/context; in that case, it won't need to be rebuilt (and we can't
27320e90f04SDimitry Andric     // safely invalidate it anyway).
27420e90f04SDimitry Andric     if (LoadedSuccessfully.count(&*victim) == 0 &&
27520e90f04SDimitry Andric         !PCMCache->tryToRemoveBuffer(victim->FileName))
27620e90f04SDimitry Andric       FileMgr.invalidateCache(victim->File);
2773861d79fSDimitry Andric   }
2783861d79fSDimitry Andric 
27920e90f04SDimitry Andric   // Delete the modules.
28020e90f04SDimitry Andric   Chain.erase(Chain.begin() + (First - begin()), Chain.end());
2813861d79fSDimitry Andric }
2823861d79fSDimitry Andric 
28339d628a0SDimitry Andric void
addInMemoryBuffer(StringRef FileName,std::unique_ptr<llvm::MemoryBuffer> Buffer)28439d628a0SDimitry Andric ModuleManager::addInMemoryBuffer(StringRef FileName,
28539d628a0SDimitry Andric                                  std::unique_ptr<llvm::MemoryBuffer> Buffer) {
28639d628a0SDimitry Andric   const FileEntry *Entry =
28739d628a0SDimitry Andric       FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
28839d628a0SDimitry Andric   InMemoryBuffers[Entry] = std::move(Buffer);
2896122f3e6SDimitry Andric }
2906122f3e6SDimitry Andric 
allocateVisitState()291139f7f9bSDimitry Andric ModuleManager::VisitState *ModuleManager::allocateVisitState() {
292139f7f9bSDimitry Andric   // Fast path: if we have a cached state, use it.
293139f7f9bSDimitry Andric   if (FirstVisitState) {
294139f7f9bSDimitry Andric     VisitState *Result = FirstVisitState;
295139f7f9bSDimitry Andric     FirstVisitState = FirstVisitState->NextState;
29659d1ed5bSDimitry Andric     Result->NextState = nullptr;
297139f7f9bSDimitry Andric     return Result;
298139f7f9bSDimitry Andric   }
299139f7f9bSDimitry Andric 
300139f7f9bSDimitry Andric   // Allocate and return a new state.
301139f7f9bSDimitry Andric   return new VisitState(size());
302139f7f9bSDimitry Andric }
303139f7f9bSDimitry Andric 
returnVisitState(VisitState * State)304139f7f9bSDimitry Andric void ModuleManager::returnVisitState(VisitState *State) {
30559d1ed5bSDimitry Andric   assert(State->NextState == nullptr && "Visited state is in list?");
306139f7f9bSDimitry Andric   State->NextState = FirstVisitState;
307139f7f9bSDimitry Andric   FirstVisitState = State;
308139f7f9bSDimitry Andric }
309139f7f9bSDimitry Andric 
setGlobalIndex(GlobalModuleIndex * Index)310139f7f9bSDimitry Andric void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
311139f7f9bSDimitry Andric   GlobalIndex = Index;
312139f7f9bSDimitry Andric   if (!GlobalIndex) {
313139f7f9bSDimitry Andric     ModulesInCommonWithGlobalIndex.clear();
314139f7f9bSDimitry Andric     return;
315139f7f9bSDimitry Andric   }
316139f7f9bSDimitry Andric 
317139f7f9bSDimitry Andric   // Notify the global module index about all of the modules we've already
318139f7f9bSDimitry Andric   // loaded.
31920e90f04SDimitry Andric   for (ModuleFile &M : *this)
32020e90f04SDimitry Andric     if (!GlobalIndex->loadedModuleFile(&M))
32120e90f04SDimitry Andric       ModulesInCommonWithGlobalIndex.push_back(&M);
322139f7f9bSDimitry Andric }
323139f7f9bSDimitry Andric 
moduleFileAccepted(ModuleFile * MF)324139f7f9bSDimitry Andric void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
325139f7f9bSDimitry Andric   if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
326139f7f9bSDimitry Andric     return;
327139f7f9bSDimitry Andric 
328139f7f9bSDimitry Andric   ModulesInCommonWithGlobalIndex.push_back(MF);
329139f7f9bSDimitry Andric }
330139f7f9bSDimitry Andric 
ModuleManager(FileManager & FileMgr,MemoryBufferCache & PCMCache,const PCHContainerReader & PCHContainerRdr,const HeaderSearch & HeaderSearchInfo)33120e90f04SDimitry Andric ModuleManager::ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache,
3329a199699SDimitry Andric                              const PCHContainerReader &PCHContainerRdr,
3339a199699SDimitry Andric                              const HeaderSearch& HeaderSearchInfo)
33420e90f04SDimitry Andric     : FileMgr(FileMgr), PCMCache(&PCMCache), PCHContainerRdr(PCHContainerRdr),
3359a199699SDimitry Andric       HeaderSearchInfo(HeaderSearchInfo) {}
3366122f3e6SDimitry Andric 
~ModuleManager()33720e90f04SDimitry Andric ModuleManager::~ModuleManager() { delete FirstVisitState; }
3386122f3e6SDimitry Andric 
visit(llvm::function_ref<bool (ModuleFile & M)> Visitor,llvm::SmallPtrSetImpl<ModuleFile * > * ModuleFilesHit)3390623d748SDimitry Andric void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
34039d628a0SDimitry Andric                           llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
341139f7f9bSDimitry Andric   // If the visitation order vector is the wrong size, recompute the order.
342139f7f9bSDimitry Andric   if (VisitOrder.size() != Chain.size()) {
3436122f3e6SDimitry Andric     unsigned N = size();
344139f7f9bSDimitry Andric     VisitOrder.clear();
345139f7f9bSDimitry Andric     VisitOrder.reserve(N);
3466122f3e6SDimitry Andric 
3476122f3e6SDimitry Andric     // Record the number of incoming edges for each module. When we
3486122f3e6SDimitry Andric     // encounter a module with no incoming edges, push it into the queue
3496122f3e6SDimitry Andric     // to seed the queue.
350dff0c46cSDimitry Andric     SmallVector<ModuleFile *, 4> Queue;
3516122f3e6SDimitry Andric     Queue.reserve(N);
352139f7f9bSDimitry Andric     llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
3530623d748SDimitry Andric     UnusedIncomingEdges.resize(size());
35420e90f04SDimitry Andric     for (ModuleFile &M : llvm::reverse(*this)) {
35520e90f04SDimitry Andric       unsigned Size = M.ImportedBy.size();
35620e90f04SDimitry Andric       UnusedIncomingEdges[M.Index] = Size;
3570623d748SDimitry Andric       if (!Size)
35820e90f04SDimitry Andric         Queue.push_back(&M);
3596122f3e6SDimitry Andric     }
3606122f3e6SDimitry Andric 
361139f7f9bSDimitry Andric     // Traverse the graph, making sure to visit a module before visiting any
362139f7f9bSDimitry Andric     // of its dependencies.
3630623d748SDimitry Andric     while (!Queue.empty()) {
3640623d748SDimitry Andric       ModuleFile *CurrentModule = Queue.pop_back_val();
365139f7f9bSDimitry Andric       VisitOrder.push_back(CurrentModule);
3666122f3e6SDimitry Andric 
367139f7f9bSDimitry Andric       // For any module that this module depends on, push it on the
368139f7f9bSDimitry Andric       // stack (if it hasn't already been marked as visited).
3690623d748SDimitry Andric       for (auto M = CurrentModule->Imports.rbegin(),
3700623d748SDimitry Andric                 MEnd = CurrentModule->Imports.rend();
371139f7f9bSDimitry Andric            M != MEnd; ++M) {
372139f7f9bSDimitry Andric         // Remove our current module as an impediment to visiting the
373139f7f9bSDimitry Andric         // module we depend on. If we were the last unvisited module
374139f7f9bSDimitry Andric         // that depends on this particular module, push it into the
375139f7f9bSDimitry Andric         // queue to be visited.
376139f7f9bSDimitry Andric         unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
377139f7f9bSDimitry Andric         if (NumUnusedEdges && (--NumUnusedEdges == 0))
378139f7f9bSDimitry Andric           Queue.push_back(*M);
379139f7f9bSDimitry Andric       }
380139f7f9bSDimitry Andric     }
381139f7f9bSDimitry Andric 
382139f7f9bSDimitry Andric     assert(VisitOrder.size() == N && "Visitation order is wrong?");
383139f7f9bSDimitry Andric 
384139f7f9bSDimitry Andric     delete FirstVisitState;
38559d1ed5bSDimitry Andric     FirstVisitState = nullptr;
386139f7f9bSDimitry Andric   }
387139f7f9bSDimitry Andric 
388139f7f9bSDimitry Andric   VisitState *State = allocateVisitState();
389139f7f9bSDimitry Andric   unsigned VisitNumber = State->NextVisitNumber++;
390139f7f9bSDimitry Andric 
391139f7f9bSDimitry Andric   // If the caller has provided us with a hit-set that came from the global
392139f7f9bSDimitry Andric   // module index, mark every module file in common with the global module
393139f7f9bSDimitry Andric   // index that is *not* in that set as 'visited'.
394139f7f9bSDimitry Andric   if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
395139f7f9bSDimitry Andric     for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
396139f7f9bSDimitry Andric     {
397139f7f9bSDimitry Andric       ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
398139f7f9bSDimitry Andric       if (!ModuleFilesHit->count(M))
399139f7f9bSDimitry Andric         State->VisitNumber[M->Index] = VisitNumber;
400139f7f9bSDimitry Andric     }
401139f7f9bSDimitry Andric   }
402139f7f9bSDimitry Andric 
403139f7f9bSDimitry Andric   for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
404139f7f9bSDimitry Andric     ModuleFile *CurrentModule = VisitOrder[I];
405139f7f9bSDimitry Andric     // Should we skip this module file?
406139f7f9bSDimitry Andric     if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
4076122f3e6SDimitry Andric       continue;
4086122f3e6SDimitry Andric 
409139f7f9bSDimitry Andric     // Visit the module.
410139f7f9bSDimitry Andric     assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
411139f7f9bSDimitry Andric     State->VisitNumber[CurrentModule->Index] = VisitNumber;
4120623d748SDimitry Andric     if (!Visitor(*CurrentModule))
413139f7f9bSDimitry Andric       continue;
414139f7f9bSDimitry Andric 
4156122f3e6SDimitry Andric     // The visitor has requested that cut off visitation of any
4166122f3e6SDimitry Andric     // module that the current module depends on. To indicate this
417139f7f9bSDimitry Andric     // behavior, we mark all of the reachable modules as having been visited.
418139f7f9bSDimitry Andric     ModuleFile *NextModule = CurrentModule;
419139f7f9bSDimitry Andric     do {
4206122f3e6SDimitry Andric       // For any module that this module depends on, push it on the
4216122f3e6SDimitry Andric       // stack (if it hasn't already been marked as visited).
422dff0c46cSDimitry Andric       for (llvm::SetVector<ModuleFile *>::iterator
4236122f3e6SDimitry Andric              M = NextModule->Imports.begin(),
4246122f3e6SDimitry Andric              MEnd = NextModule->Imports.end();
4256122f3e6SDimitry Andric            M != MEnd; ++M) {
426139f7f9bSDimitry Andric         if (State->VisitNumber[(*M)->Index] != VisitNumber) {
427139f7f9bSDimitry Andric           State->Stack.push_back(*M);
428139f7f9bSDimitry Andric           State->VisitNumber[(*M)->Index] = VisitNumber;
4296122f3e6SDimitry Andric         }
4306122f3e6SDimitry Andric       }
4316122f3e6SDimitry Andric 
432139f7f9bSDimitry Andric       if (State->Stack.empty())
433139f7f9bSDimitry Andric         break;
4346122f3e6SDimitry Andric 
435139f7f9bSDimitry Andric       // Pop the next module off the stack.
436f785676fSDimitry Andric       NextModule = State->Stack.pop_back_val();
437139f7f9bSDimitry Andric     } while (true);
4386122f3e6SDimitry Andric   }
439139f7f9bSDimitry Andric 
440139f7f9bSDimitry Andric   returnVisitState(State);
4416122f3e6SDimitry Andric }
4426122f3e6SDimitry Andric 
lookupModuleFile(StringRef FileName,off_t ExpectedSize,time_t ExpectedModTime,const FileEntry * & File)443139f7f9bSDimitry Andric bool ModuleManager::lookupModuleFile(StringRef FileName,
444139f7f9bSDimitry Andric                                      off_t ExpectedSize,
445139f7f9bSDimitry Andric                                      time_t ExpectedModTime,
446139f7f9bSDimitry Andric                                      const FileEntry *&File) {
44744290647SDimitry Andric   if (FileName == "-") {
44844290647SDimitry Andric     File = nullptr;
44944290647SDimitry Andric     return false;
45044290647SDimitry Andric   }
45144290647SDimitry Andric 
45259d1ed5bSDimitry Andric   // Open the file immediately to ensure there is no race between stat'ing and
45359d1ed5bSDimitry Andric   // opening the file.
45459d1ed5bSDimitry Andric   File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false);
45544290647SDimitry Andric   if (!File)
456139f7f9bSDimitry Andric     return false;
457139f7f9bSDimitry Andric 
458139f7f9bSDimitry Andric   if ((ExpectedSize && ExpectedSize != File->getSize()) ||
45959d1ed5bSDimitry Andric       (ExpectedModTime && ExpectedModTime != File->getModificationTime()))
46059d1ed5bSDimitry Andric     // Do not destroy File, as it may be referenced. If we need to rebuild it,
46159d1ed5bSDimitry Andric     // it will be destroyed by removeModules.
462139f7f9bSDimitry Andric     return true;
463139f7f9bSDimitry Andric 
464139f7f9bSDimitry Andric   return false;
465139f7f9bSDimitry Andric }
466139f7f9bSDimitry Andric 
4676122f3e6SDimitry Andric #ifndef NDEBUG
4686122f3e6SDimitry Andric namespace llvm {
4699a199699SDimitry Andric 
4706122f3e6SDimitry Andric   template<>
4716122f3e6SDimitry Andric   struct GraphTraits<ModuleManager> {
4729a199699SDimitry Andric     using NodeRef = ModuleFile *;
4739a199699SDimitry Andric     using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
4749a199699SDimitry Andric     using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
4756122f3e6SDimitry Andric 
child_beginllvm::GraphTraits47644290647SDimitry Andric     static ChildIteratorType child_begin(NodeRef Node) {
4776122f3e6SDimitry Andric       return Node->Imports.begin();
4786122f3e6SDimitry Andric     }
4796122f3e6SDimitry Andric 
child_endllvm::GraphTraits48044290647SDimitry Andric     static ChildIteratorType child_end(NodeRef Node) {
4816122f3e6SDimitry Andric       return Node->Imports.end();
4826122f3e6SDimitry Andric     }
4836122f3e6SDimitry Andric 
nodes_beginllvm::GraphTraits4846122f3e6SDimitry Andric     static nodes_iterator nodes_begin(const ModuleManager &Manager) {
48520e90f04SDimitry Andric       return nodes_iterator(Manager.begin());
4866122f3e6SDimitry Andric     }
4876122f3e6SDimitry Andric 
nodes_endllvm::GraphTraits4886122f3e6SDimitry Andric     static nodes_iterator nodes_end(const ModuleManager &Manager) {
48920e90f04SDimitry Andric       return nodes_iterator(Manager.end());
4906122f3e6SDimitry Andric     }
4916122f3e6SDimitry Andric   };
4926122f3e6SDimitry Andric 
4936122f3e6SDimitry Andric   template<>
4946122f3e6SDimitry Andric   struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits4956122f3e6SDimitry Andric     explicit DOTGraphTraits(bool IsSimple = false)
4966122f3e6SDimitry Andric         : DefaultDOTGraphTraits(IsSimple) {}
4976122f3e6SDimitry Andric 
renderGraphFromBottomUpllvm::DOTGraphTraits4989a199699SDimitry Andric     static bool renderGraphFromBottomUp() { return true; }
4996122f3e6SDimitry Andric 
getNodeLabelllvm::DOTGraphTraits500dff0c46cSDimitry Andric     std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
50159d1ed5bSDimitry Andric       return M->ModuleName;
5026122f3e6SDimitry Andric     }
5036122f3e6SDimitry Andric   };
5049a199699SDimitry Andric 
5059a199699SDimitry Andric } // namespace llvm
5066122f3e6SDimitry Andric 
viewGraph()5076122f3e6SDimitry Andric void ModuleManager::viewGraph() {
5086122f3e6SDimitry Andric   llvm::ViewGraph(*this, "Modules");
5096122f3e6SDimitry Andric }
5106122f3e6SDimitry Andric #endif
511