1*d44252ecSDouglas Gregor //===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===// 2*d44252ecSDouglas Gregor // 3*d44252ecSDouglas Gregor // The LLVM Compiler Infrastructure 4*d44252ecSDouglas Gregor // 5*d44252ecSDouglas Gregor // This file is distributed under the University of Illinois Open Source 6*d44252ecSDouglas Gregor // License. See LICENSE.TXT for details. 7*d44252ecSDouglas Gregor // 8*d44252ecSDouglas Gregor //===----------------------------------------------------------------------===// 9*d44252ecSDouglas Gregor // 10*d44252ecSDouglas Gregor // This file defines the ModuleManager class, which manages a set of loaded 11*d44252ecSDouglas Gregor // modules for the ASTReader. 12*d44252ecSDouglas Gregor // 13*d44252ecSDouglas Gregor //===----------------------------------------------------------------------===// 14*d44252ecSDouglas Gregor #include "clang/Serialization/ModuleManager.h" 15*d44252ecSDouglas Gregor #include "llvm/Support/MemoryBuffer.h" 16*d44252ecSDouglas Gregor #include "llvm/Support/raw_ostream.h" 17*d44252ecSDouglas Gregor #include "llvm/Support/system_error.h" 18*d44252ecSDouglas Gregor 19*d44252ecSDouglas Gregor using namespace clang; 20*d44252ecSDouglas Gregor using namespace serialization; 21*d44252ecSDouglas Gregor 22*d44252ecSDouglas Gregor Module *ModuleManager::lookup(StringRef Name) { 23*d44252ecSDouglas Gregor const FileEntry *Entry = FileMgr.getFile(Name); 24*d44252ecSDouglas Gregor return Modules[Entry]; 25*d44252ecSDouglas Gregor } 26*d44252ecSDouglas Gregor 27*d44252ecSDouglas Gregor llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { 28*d44252ecSDouglas Gregor const FileEntry *Entry = FileMgr.getFile(Name); 29*d44252ecSDouglas Gregor return InMemoryBuffers[Entry]; 30*d44252ecSDouglas Gregor } 31*d44252ecSDouglas Gregor 32*d44252ecSDouglas Gregor std::pair<Module *, bool> 33*d44252ecSDouglas Gregor ModuleManager::addModule(StringRef FileName, ModuleKind Type, 34*d44252ecSDouglas Gregor Module *ImportedBy, std::string &ErrorStr) { 35*d44252ecSDouglas Gregor const FileEntry *Entry = FileMgr.getFile(FileName); 36*d44252ecSDouglas Gregor if (!Entry && FileName != "-") { 37*d44252ecSDouglas Gregor ErrorStr = "file not found"; 38*d44252ecSDouglas Gregor return std::make_pair(static_cast<Module*>(0), false); 39*d44252ecSDouglas Gregor } 40*d44252ecSDouglas Gregor 41*d44252ecSDouglas Gregor // Check whether we already loaded this module, before 42*d44252ecSDouglas Gregor Module *&ModuleEntry = Modules[Entry]; 43*d44252ecSDouglas Gregor bool NewModule = false; 44*d44252ecSDouglas Gregor if (!ModuleEntry) { 45*d44252ecSDouglas Gregor // Allocate a new module. 46*d44252ecSDouglas Gregor Module *New = new Module(Type); 47*d44252ecSDouglas Gregor New->FileName = FileName.str(); 48*d44252ecSDouglas Gregor Chain.push_back(New); 49*d44252ecSDouglas Gregor NewModule = true; 50*d44252ecSDouglas Gregor ModuleEntry = New; 51*d44252ecSDouglas Gregor 52*d44252ecSDouglas Gregor // Load the contents of the module 53*d44252ecSDouglas Gregor if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { 54*d44252ecSDouglas Gregor // The buffer was already provided for us. 55*d44252ecSDouglas Gregor assert(Buffer && "Passed null buffer"); 56*d44252ecSDouglas Gregor New->Buffer.reset(Buffer); 57*d44252ecSDouglas Gregor } else { 58*d44252ecSDouglas Gregor // Open the AST file. 59*d44252ecSDouglas Gregor llvm::error_code ec; 60*d44252ecSDouglas Gregor if (FileName == "-") { 61*d44252ecSDouglas Gregor ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); 62*d44252ecSDouglas Gregor if (ec) 63*d44252ecSDouglas Gregor ErrorStr = ec.message(); 64*d44252ecSDouglas Gregor } else 65*d44252ecSDouglas Gregor New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); 66*d44252ecSDouglas Gregor 67*d44252ecSDouglas Gregor if (!New->Buffer) 68*d44252ecSDouglas Gregor return std::make_pair(static_cast<Module*>(0), false); 69*d44252ecSDouglas Gregor } 70*d44252ecSDouglas Gregor 71*d44252ecSDouglas Gregor // Initialize the stream 72*d44252ecSDouglas Gregor New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), 73*d44252ecSDouglas Gregor (const unsigned char *)New->Buffer->getBufferEnd()); } 74*d44252ecSDouglas Gregor 75*d44252ecSDouglas Gregor if (ImportedBy) { 76*d44252ecSDouglas Gregor ModuleEntry->ImportedBy.insert(ImportedBy); 77*d44252ecSDouglas Gregor ImportedBy->Imports.insert(ModuleEntry); 78*d44252ecSDouglas Gregor } else { 79*d44252ecSDouglas Gregor ModuleEntry->DirectlyImported = true; 80*d44252ecSDouglas Gregor } 81*d44252ecSDouglas Gregor 82*d44252ecSDouglas Gregor return std::make_pair(ModuleEntry, NewModule); 83*d44252ecSDouglas Gregor } 84*d44252ecSDouglas Gregor 85*d44252ecSDouglas Gregor void ModuleManager::addInMemoryBuffer(StringRef FileName, 86*d44252ecSDouglas Gregor llvm::MemoryBuffer *Buffer) { 87*d44252ecSDouglas Gregor 88*d44252ecSDouglas Gregor const FileEntry *Entry = FileMgr.getVirtualFile(FileName, 89*d44252ecSDouglas Gregor Buffer->getBufferSize(), 0); 90*d44252ecSDouglas Gregor InMemoryBuffers[Entry] = Buffer; 91*d44252ecSDouglas Gregor } 92*d44252ecSDouglas Gregor 93*d44252ecSDouglas Gregor ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { } 94*d44252ecSDouglas Gregor 95*d44252ecSDouglas Gregor ModuleManager::~ModuleManager() { 96*d44252ecSDouglas Gregor for (unsigned i = 0, e = Chain.size(); i != e; ++i) 97*d44252ecSDouglas Gregor delete Chain[e - i - 1]; 98*d44252ecSDouglas Gregor } 99*d44252ecSDouglas Gregor 100*d44252ecSDouglas Gregor void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), 101*d44252ecSDouglas Gregor void *UserData) { 102*d44252ecSDouglas Gregor unsigned N = size(); 103*d44252ecSDouglas Gregor 104*d44252ecSDouglas Gregor // Record the number of incoming edges for each module. When we 105*d44252ecSDouglas Gregor // encounter a module with no incoming edges, push it into the queue 106*d44252ecSDouglas Gregor // to seed the queue. 107*d44252ecSDouglas Gregor SmallVector<Module *, 4> Queue; 108*d44252ecSDouglas Gregor Queue.reserve(N); 109*d44252ecSDouglas Gregor llvm::DenseMap<Module *, unsigned> UnusedIncomingEdges; 110*d44252ecSDouglas Gregor for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { 111*d44252ecSDouglas Gregor if (unsigned Size = (*M)->ImportedBy.size()) 112*d44252ecSDouglas Gregor UnusedIncomingEdges[*M] = Size; 113*d44252ecSDouglas Gregor else 114*d44252ecSDouglas Gregor Queue.push_back(*M); 115*d44252ecSDouglas Gregor } 116*d44252ecSDouglas Gregor 117*d44252ecSDouglas Gregor llvm::SmallPtrSet<Module *, 4> Skipped; 118*d44252ecSDouglas Gregor unsigned QueueStart = 0; 119*d44252ecSDouglas Gregor while (QueueStart < Queue.size()) { 120*d44252ecSDouglas Gregor Module *CurrentModule = Queue[QueueStart++]; 121*d44252ecSDouglas Gregor 122*d44252ecSDouglas Gregor // Check whether this module should be skipped. 123*d44252ecSDouglas Gregor if (Skipped.count(CurrentModule)) 124*d44252ecSDouglas Gregor continue; 125*d44252ecSDouglas Gregor 126*d44252ecSDouglas Gregor if (Visitor(*CurrentModule, UserData)) { 127*d44252ecSDouglas Gregor // The visitor has requested that cut off visitation of any 128*d44252ecSDouglas Gregor // module that the current module depends on. To indicate this 129*d44252ecSDouglas Gregor // behavior, we mark all of the reachable modules as having N 130*d44252ecSDouglas Gregor // incoming edges (which is impossible otherwise). 131*d44252ecSDouglas Gregor SmallVector<Module *, 4> Stack; 132*d44252ecSDouglas Gregor Stack.push_back(CurrentModule); 133*d44252ecSDouglas Gregor Skipped.insert(CurrentModule); 134*d44252ecSDouglas Gregor while (!Stack.empty()) { 135*d44252ecSDouglas Gregor Module *NextModule = Stack.back(); 136*d44252ecSDouglas Gregor Stack.pop_back(); 137*d44252ecSDouglas Gregor 138*d44252ecSDouglas Gregor // For any module that this module depends on, push it on the 139*d44252ecSDouglas Gregor // stack (if it hasn't already been marked as visited). 140*d44252ecSDouglas Gregor for (llvm::SetVector<Module *>::iterator 141*d44252ecSDouglas Gregor M = NextModule->Imports.begin(), 142*d44252ecSDouglas Gregor MEnd = NextModule->Imports.end(); 143*d44252ecSDouglas Gregor M != MEnd; ++M) { 144*d44252ecSDouglas Gregor if (Skipped.insert(*M)) 145*d44252ecSDouglas Gregor Stack.push_back(*M); 146*d44252ecSDouglas Gregor } 147*d44252ecSDouglas Gregor } 148*d44252ecSDouglas Gregor continue; 149*d44252ecSDouglas Gregor } 150*d44252ecSDouglas Gregor 151*d44252ecSDouglas Gregor // For any module that this module depends on, push it on the 152*d44252ecSDouglas Gregor // stack (if it hasn't already been marked as visited). 153*d44252ecSDouglas Gregor for (llvm::SetVector<Module *>::iterator M = CurrentModule->Imports.begin(), 154*d44252ecSDouglas Gregor MEnd = CurrentModule->Imports.end(); 155*d44252ecSDouglas Gregor M != MEnd; ++M) { 156*d44252ecSDouglas Gregor 157*d44252ecSDouglas Gregor // Remove our current module as an impediment to visiting the 158*d44252ecSDouglas Gregor // module we depend on. If we were the last unvisited module 159*d44252ecSDouglas Gregor // that depends on this particular module, push it into the 160*d44252ecSDouglas Gregor // queue to be visited. 161*d44252ecSDouglas Gregor unsigned &NumUnusedEdges = UnusedIncomingEdges[*M]; 162*d44252ecSDouglas Gregor if (NumUnusedEdges && (--NumUnusedEdges == 0)) 163*d44252ecSDouglas Gregor Queue.push_back(*M); 164*d44252ecSDouglas Gregor } 165*d44252ecSDouglas Gregor } 166*d44252ecSDouglas Gregor } 167*d44252ecSDouglas Gregor 168*d44252ecSDouglas Gregor /// \brief Perform a depth-first visit of the current module. 169*d44252ecSDouglas Gregor static bool visitDepthFirst(Module &M, 170*d44252ecSDouglas Gregor bool (*Visitor)(Module &M, bool Preorder, 171*d44252ecSDouglas Gregor void *UserData), 172*d44252ecSDouglas Gregor void *UserData, 173*d44252ecSDouglas Gregor llvm::SmallPtrSet<Module *, 4> &Visited) { 174*d44252ecSDouglas Gregor // Preorder visitation 175*d44252ecSDouglas Gregor if (Visitor(M, /*Preorder=*/true, UserData)) 176*d44252ecSDouglas Gregor return true; 177*d44252ecSDouglas Gregor 178*d44252ecSDouglas Gregor // Visit children 179*d44252ecSDouglas Gregor for (llvm::SetVector<Module *>::iterator IM = M.Imports.begin(), 180*d44252ecSDouglas Gregor IMEnd = M.Imports.end(); 181*d44252ecSDouglas Gregor IM != IMEnd; ++IM) { 182*d44252ecSDouglas Gregor if (!Visited.insert(*IM)) 183*d44252ecSDouglas Gregor continue; 184*d44252ecSDouglas Gregor 185*d44252ecSDouglas Gregor if (visitDepthFirst(**IM, Visitor, UserData, Visited)) 186*d44252ecSDouglas Gregor return true; 187*d44252ecSDouglas Gregor } 188*d44252ecSDouglas Gregor 189*d44252ecSDouglas Gregor // Postorder visitation 190*d44252ecSDouglas Gregor return Visitor(M, /*Preorder=*/false, UserData); 191*d44252ecSDouglas Gregor } 192*d44252ecSDouglas Gregor 193*d44252ecSDouglas Gregor void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, 194*d44252ecSDouglas Gregor void *UserData), 195*d44252ecSDouglas Gregor void *UserData) { 196*d44252ecSDouglas Gregor llvm::SmallPtrSet<Module *, 4> Visited; 197*d44252ecSDouglas Gregor for (unsigned I = 0, N = Chain.size(); I != N; ++I) { 198*d44252ecSDouglas Gregor if (!Visited.insert(Chain[I])) 199*d44252ecSDouglas Gregor continue; 200*d44252ecSDouglas Gregor 201*d44252ecSDouglas Gregor if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) 202*d44252ecSDouglas Gregor return; 203*d44252ecSDouglas Gregor } 204*d44252ecSDouglas Gregor } 205