198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===// 298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// 398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// The LLVM Compiler Infrastructure 498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// 598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// This file is distributed under the University of Illinois Open Source 698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// License. See LICENSE.TXT for details. 798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// 898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor//===----------------------------------------------------------------------===// 998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// 1098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// This file defines the ModuleManager class, which manages a set of loaded 1198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// modules for the ASTReader. 1298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor// 1398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor//===----------------------------------------------------------------------===// 146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Lex/HeaderSearch.h" 15677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor#include "clang/Lex/ModuleMap.h" 16188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor#include "clang/Serialization/GlobalModuleIndex.h" 17ae0cdff0b83e59c7fe769baf171d1ba194ad8b88Benjamin Kramer#include "clang/Serialization/ModuleManager.h" 1898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include "llvm/Support/MemoryBuffer.h" 198229d22e6449851b89361bf2f41804557328be63Rafael Espindola#include "llvm/Support/Path.h" 2098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include "llvm/Support/raw_ostream.h" 21ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include <system_error> 2298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 232492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#ifndef NDEBUG 242492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#include "llvm/Support/GraphWriter.h" 252492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#endif 262492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 2798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorusing namespace clang; 2898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorusing namespace serialization; 2998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 301a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas GregorModuleFile *ModuleManager::lookup(StringRef Name) { 31ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, 32ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor /*cacheFailure=*/false); 33c544ba09695e300f31355af342258bd57619e737Douglas Gregor if (Entry) 34c544ba09695e300f31355af342258bd57619e737Douglas Gregor return lookup(Entry); 35c544ba09695e300f31355af342258bd57619e737Douglas Gregor 366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 37c544ba09695e300f31355af342258bd57619e737Douglas Gregor} 38c544ba09695e300f31355af342258bd57619e737Douglas Gregor 39c544ba09695e300f31355af342258bd57619e737Douglas GregorModuleFile *ModuleManager::lookup(const FileEntry *File) { 40c544ba09695e300f31355af342258bd57619e737Douglas Gregor llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known 41c544ba09695e300f31355af342258bd57619e737Douglas Gregor = Modules.find(File); 42c544ba09695e300f31355af342258bd57619e737Douglas Gregor if (Known == Modules.end()) 436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 44c544ba09695e300f31355af342258bd57619e737Douglas Gregor 45c544ba09695e300f31355af342258bd57619e737Douglas Gregor return Known->second; 4698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 4798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 4898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorllvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { 49ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, 50ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor /*cacheFailure=*/false); 5198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor return InMemoryBuffers[Entry]; 5298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 5398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 54677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorModuleManager::AddModuleResult 5587e2cfcec7231daaa3f367dc32df74b411251e46Douglas GregorModuleManager::addModule(StringRef FileName, ModuleKind Type, 5687e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor SourceLocation ImportLoc, ModuleFile *ImportedBy, 57677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor unsigned Generation, 58677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor off_t ExpectedSize, time_t ExpectedModTime, 59677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor ModuleFile *&Module, 60677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor std::string &ErrorStr) { 616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Module = nullptr; 62677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 63677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Look for the file entry. This only fails if the expected size or 64677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // modification time differ. 65677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor const FileEntry *Entry; 66edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) { 67edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman ErrorStr = "module file out of date"; 68677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return OutOfDate; 69edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman } 70677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 7198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (!Entry && FileName != "-") { 72edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman ErrorStr = "module file not found"; 73677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return Missing; 7498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 75677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 76677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor // Check whether we already loaded this module, before 771a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor ModuleFile *&ModuleEntry = Modules[Entry]; 7898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor bool NewModule = false; 7998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (!ModuleEntry) { 8098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Allocate a new module. 81057df20b3107cef764052d271c89b8591b98b3ceDouglas Gregor ModuleFile *New = new ModuleFile(Type, Generation); 82cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor New->Index = Chain.size(); 8398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor New->FileName = FileName.str(); 84d64c26f6676eef69d1713f353ca8a3c2fe963f17Argyrios Kyrtzidis New->File = Entry; 8587e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor New->ImportLoc = ImportLoc; 8698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor Chain.push_back(New); 8798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor NewModule = true; 8898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor ModuleEntry = New; 8987e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor 90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines New->InputFilesValidationTimestamp = 0; 91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (New->Kind == MK_Module) { 92651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string TimestampFilename = New->getTimestampFilename(); 93651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines vfs::Status Status; 94651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // A cached stat value would be fine as well. 95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status)) 96651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines New->InputFilesValidationTimestamp = 97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Status.getLastModificationTime().toEpochTime(); 98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 10098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Load the contents of the module 10198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { 10298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // The buffer was already provided for us. 10398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor assert(Buffer && "Passed null buffer"); 10498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor New->Buffer.reset(Buffer); 10598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } else { 10698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Open the AST file. 107ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::error_code ec; 10898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (FileName == "-") { 109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf = 110ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::MemoryBuffer::getSTDIN(); 111ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ec = Buf.getError(); 11298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (ec) 11398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor ErrorStr = ec.message(); 114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines else 115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines New->Buffer = std::move(Buf.get()); 116ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } else { 117ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Leave the FileEntry open so if it gets read again by another 118ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // ModuleManager it must be the same underlying file. 119ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // FIXME: Because FileManager::getFile() doesn't guarantee that it will 120ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // give us an open file, this may not be 100% reliable. 121ef8225444452a1486bd721f3285301fe84643b00Stephen Hines New->Buffer.reset(FileMgr.getBufferForFile(New->File, &ErrorStr, 122ef8225444452a1486bd721f3285301fe84643b00Stephen Hines /*IsVolatile*/false, 123ef8225444452a1486bd721f3285301fe84643b00Stephen Hines /*ShouldClose*/false)); 124ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 12598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 12698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (!New->Buffer) 127677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return Missing; 12898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 12998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 13098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Initialize the stream 13198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), 132677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor (const unsigned char *)New->Buffer->getBufferEnd()); 133677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 13498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 13598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (ImportedBy) { 13698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor ModuleEntry->ImportedBy.insert(ImportedBy); 13798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor ImportedBy->Imports.insert(ModuleEntry); 13898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } else { 13987e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor if (!ModuleEntry->DirectlyImported) 14087e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor ModuleEntry->ImportLoc = ImportLoc; 14187e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor 14298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor ModuleEntry->DirectlyImported = true; 14398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 144677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 145677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor Module = ModuleEntry; 146677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return NewModule? NewlyLoaded : AlreadyLoaded; 14798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 14898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 149ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid ModuleManager::removeModules( 150ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ModuleIterator first, ModuleIterator last, 151ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, 152ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ModuleMap *modMap) { 1537cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor if (first == last) 1547cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor return; 1557cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor 1567cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor // Collect the set of module file pointers that we'll be removing. 1577cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last); 1587cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor 1597cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor // Remove any references to the now-destroyed modules. 1607cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor for (unsigned i = 0, n = Chain.size(); i != n; ++i) { 161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) { 162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return victimSet.count(MF); 163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }); 1647cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor } 1657cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor 1667cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor // Delete the modules and erase them from the various structures. 1677cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor for (ModuleIterator victim = first; victim != last; ++victim) { 1687cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor Modules.erase((*victim)->File); 169677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 170677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (modMap) { 1716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StringRef ModuleName = (*victim)->ModuleName; 172677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (Module *mod = modMap->findModule(ModuleName)) { 1736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines mod->setASTFile(nullptr); 174677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 175677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 176ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 177ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Files that didn't make it through ReadASTCore successfully will be 178ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // rebuilt (or there was an error). Invalidate them so that we can load the 179ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // new files that will be renamed over the old ones. 180ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (LoadedSuccessfully.count(*victim) == 0) 181ef8225444452a1486bd721f3285301fe84643b00Stephen Hines FileMgr.invalidateCache((*victim)->File); 182ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 1837cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor delete *victim; 1847cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor } 1857cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor 1867cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor // Remove the modules from the chain. 1877cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor Chain.erase(first, last); 1887cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor} 1897cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor 19098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorvoid ModuleManager::addInMemoryBuffer(StringRef FileName, 19198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor llvm::MemoryBuffer *Buffer) { 19298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 19398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor const FileEntry *Entry = FileMgr.getVirtualFile(FileName, 19498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor Buffer->getBufferSize(), 0); 19598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor InMemoryBuffers[Entry] = Buffer; 19698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 19798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 198d3cf5fba332fc77f7e72ef58077822606718671dDouglas GregorModuleManager::VisitState *ModuleManager::allocateVisitState() { 199d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor // Fast path: if we have a cached state, use it. 200d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor if (FirstVisitState) { 201d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor VisitState *Result = FirstVisitState; 202d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor FirstVisitState = FirstVisitState->NextState; 2036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Result->NextState = nullptr; 204d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor return Result; 205d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor } 206d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor 207d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor // Allocate and return a new state. 208d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor return new VisitState(size()); 209d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor} 210d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor 211d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregorvoid ModuleManager::returnVisitState(VisitState *State) { 2126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines assert(State->NextState == nullptr && "Visited state is in list?"); 213d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor State->NextState = FirstVisitState; 214d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor FirstVisitState = State; 215d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor} 216d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor 217188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregorvoid ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) { 218188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor GlobalIndex = Index; 219fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (!GlobalIndex) { 220fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModulesInCommonWithGlobalIndex.clear(); 221fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor return; 222677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 223fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 224fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // Notify the global module index about all of the modules we've already 225fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor // loaded. 226fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor for (unsigned I = 0, N = Chain.size(); I != N; ++I) { 227fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (!GlobalIndex->loadedModuleFile(Chain[I])) { 228fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModulesInCommonWithGlobalIndex.push_back(Chain[I]); 229fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor } 230fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor } 231fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor} 232fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 233fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregorvoid ModuleManager::moduleFileAccepted(ModuleFile *MF) { 234fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF)) 235fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor return; 236fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor 237fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor ModulesInCommonWithGlobalIndex.push_back(MF); 238188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor} 239188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor 240188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas GregorModuleManager::ModuleManager(FileManager &FileMgr) 2416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(nullptr) {} 24298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 24398339b96a8089a6da715487e432c5abfca0ca0dfDouglas GregorModuleManager::~ModuleManager() { 24498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor for (unsigned i = 0, e = Chain.size(); i != e; ++i) 24598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor delete Chain[e - i - 1]; 246d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor delete FirstVisitState; 24798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 24898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 249188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregorvoid 250188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas GregorModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), 251188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor void *UserData, 252677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit) { 253188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor // If the visitation order vector is the wrong size, recompute the order. 254d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor if (VisitOrder.size() != Chain.size()) { 255d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor unsigned N = size(); 256d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor VisitOrder.clear(); 257d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor VisitOrder.reserve(N); 258d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 259d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // Record the number of incoming edges for each module. When we 260d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // encounter a module with no incoming edges, push it into the queue 261d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // to seed the queue. 262d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor SmallVector<ModuleFile *, 4> Queue; 263d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor Queue.reserve(N); 264d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor llvm::SmallVector<unsigned, 4> UnusedIncomingEdges; 265d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor UnusedIncomingEdges.reserve(size()); 266d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { 267d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor if (unsigned Size = (*M)->ImportedBy.size()) 268d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor UnusedIncomingEdges.push_back(Size); 269d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor else { 270d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor UnusedIncomingEdges.push_back(0); 271d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor Queue.push_back(*M); 272d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor } 273cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor } 274d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 275d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // Traverse the graph, making sure to visit a module before visiting any 276d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // of its dependencies. 277d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor unsigned QueueStart = 0; 278d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor while (QueueStart < Queue.size()) { 279d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor ModuleFile *CurrentModule = Queue[QueueStart++]; 280d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor VisitOrder.push_back(CurrentModule); 281d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 282d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // For any module that this module depends on, push it on the 283d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // stack (if it hasn't already been marked as visited). 284d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor for (llvm::SetVector<ModuleFile *>::iterator 285d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor M = CurrentModule->Imports.begin(), 286d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor MEnd = CurrentModule->Imports.end(); 287d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor M != MEnd; ++M) { 288d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // Remove our current module as an impediment to visiting the 289d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // module we depend on. If we were the last unvisited module 290d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // that depends on this particular module, push it into the 291d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // queue to be visited. 292d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index]; 293d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor if (NumUnusedEdges && (--NumUnusedEdges == 0)) 294d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor Queue.push_back(*M); 295d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor } 296d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor } 297d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 298d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor assert(VisitOrder.size() == N && "Visitation order is wrong?"); 299188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor 300d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor delete FirstVisitState; 3016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines FirstVisitState = nullptr; 30298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 303cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor 304d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor VisitState *State = allocateVisitState(); 305d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor unsigned VisitNumber = State->NextVisitNumber++; 306d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 307188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor // If the caller has provided us with a hit-set that came from the global 308188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor // module index, mark every module file in common with the global module 309188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor // index that is *not* in that set as 'visited'. 310188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) { 311188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I) 312188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor { 313188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor ModuleFile *M = ModulesInCommonWithGlobalIndex[I]; 314677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (!ModuleFilesHit->count(M)) 315d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor State->VisitNumber[M->Index] = VisitNumber; 316188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor } 317188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor } 318188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor 319d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) { 320d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor ModuleFile *CurrentModule = VisitOrder[I]; 321d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // Should we skip this module file? 322d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor if (State->VisitNumber[CurrentModule->Index] == VisitNumber) 32398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor continue; 324d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 325d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // Visit the module. 326d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1); 327d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor State->VisitNumber[CurrentModule->Index] = VisitNumber; 328d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor if (!Visitor(*CurrentModule, UserData)) 329d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor continue; 330d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 331d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // The visitor has requested that cut off visitation of any 332d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // module that the current module depends on. To indicate this 333d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // behavior, we mark all of the reachable modules as having been visited. 334d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor ModuleFile *NextModule = CurrentModule; 335d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor do { 336d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // For any module that this module depends on, push it on the 337d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // stack (if it hasn't already been marked as visited). 338d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor for (llvm::SetVector<ModuleFile *>::iterator 339d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor M = NextModule->Imports.begin(), 340d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor MEnd = NextModule->Imports.end(); 341d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor M != MEnd; ++M) { 342d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor if (State->VisitNumber[(*M)->Index] != VisitNumber) { 343d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor State->Stack.push_back(*M); 344d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor State->VisitNumber[(*M)->Index] = VisitNumber; 34598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 34698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 347d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 348d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor if (State->Stack.empty()) 349d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor break; 350d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor 351d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor // Pop the next module off the stack. 352344472ebeded2fca2ed5013b9e87f81d09bfa908Robert Wilhelm NextModule = State->Stack.pop_back_val(); 353d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor } while (true); 35498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 355d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor 356d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor returnVisitState(State); 35798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 35898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 35998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor/// \brief Perform a depth-first visit of the current module. 3601a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregorstatic bool visitDepthFirst(ModuleFile &M, 3611a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor bool (*Visitor)(ModuleFile &M, bool Preorder, 36298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor void *UserData), 36398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor void *UserData, 364cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor SmallVectorImpl<bool> &Visited) { 36598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Preorder visitation 36698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (Visitor(M, /*Preorder=*/true, UserData)) 36798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor return true; 36898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 36998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Visit children 3701a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), 371cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor IMEnd = M.Imports.end(); 37298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor IM != IMEnd; ++IM) { 373cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor if (Visited[(*IM)->Index]) 37498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor continue; 375cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor Visited[(*IM)->Index] = true; 376cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor 37798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (visitDepthFirst(**IM, Visitor, UserData, Visited)) 37898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor return true; 37998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 38098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 38198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor // Postorder visitation 38298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor return Visitor(M, /*Preorder=*/false, UserData); 38398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 38498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor 3851a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregorvoid ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, 38698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor void *UserData), 38798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor void *UserData) { 388cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor SmallVector<bool, 16> Visited(size(), false); 38998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor for (unsigned I = 0, N = Chain.size(); I != N; ++I) { 390cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor if (Visited[Chain[I]->Index]) 39198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor continue; 392cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor Visited[Chain[I]->Index] = true; 393cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor 39498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) 39598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor return; 39698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor } 39798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor} 3982492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 399677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregorbool ModuleManager::lookupModuleFile(StringRef FileName, 400677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor off_t ExpectedSize, 401677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor time_t ExpectedModTime, 402677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor const FileEntry *&File) { 4036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Open the file immediately to ensure there is no race between stat'ing and 4046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // opening the file. 4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false); 406677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 407677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if (!File && FileName != "-") { 408677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return false; 409677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor } 410677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 411677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor if ((ExpectedSize && ExpectedSize != File->getSize()) || 4126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (ExpectedModTime && ExpectedModTime != File->getModificationTime())) 4136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Do not destroy File, as it may be referenced. If we need to rebuild it, 4146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // it will be destroyed by removeModules. 415677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return true; 416677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 417677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor return false; 418677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor} 419677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor 4202492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#ifndef NDEBUG 4212492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregornamespace llvm { 4222492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor template<> 4232492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor struct GraphTraits<ModuleManager> { 4241a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor typedef ModuleFile NodeType; 4251a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType; 4262492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor typedef ModuleManager::ModuleConstIterator nodes_iterator; 4272492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4282492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor static ChildIteratorType child_begin(NodeType *Node) { 4292492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor return Node->Imports.begin(); 4302492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor } 4312492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4322492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor static ChildIteratorType child_end(NodeType *Node) { 4332492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor return Node->Imports.end(); 4342492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor } 4352492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4362492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor static nodes_iterator nodes_begin(const ModuleManager &Manager) { 4372492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor return Manager.begin(); 4382492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor } 4392492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4402492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor static nodes_iterator nodes_end(const ModuleManager &Manager) { 4412492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor return Manager.end(); 4422492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor } 4432492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor }; 4442492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4452492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor template<> 4462492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits { 4472492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor explicit DOTGraphTraits(bool IsSimple = false) 4482492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor : DefaultDOTGraphTraits(IsSimple) { } 4492492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4502492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor static bool renderGraphFromBottomUp() { 4512492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor return true; 4522492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor } 4532492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4541a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { 4556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return M->ModuleName; 4562492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor } 4572492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor }; 4582492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor} 4592492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor 4602492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregorvoid ModuleManager::viewGraph() { 4612492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor llvm::ViewGraph(*this, "Modules"); 4622492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor} 4632492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#endif 464