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