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/Lex/ModuleMap.h" 15 #include "clang/Serialization/ModuleManager.h" 16 #include "clang/Serialization/GlobalModuleIndex.h" 17 #include "llvm/Support/MemoryBuffer.h" 18 #include "llvm/Support/PathV2.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include "llvm/Support/system_error.h" 21 22 #ifndef NDEBUG 23 #include "llvm/Support/GraphWriter.h" 24 #endif 25 26 using namespace clang; 27 using namespace serialization; 28 29 ModuleFile *ModuleManager::lookup(StringRef Name) { 30 const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, 31 /*cacheFailure=*/false); 32 return Modules[Entry]; 33 } 34 35 llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { 36 const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, 37 /*cacheFailure=*/false); 38 return InMemoryBuffers[Entry]; 39 } 40 41 ModuleManager::AddModuleResult 42 ModuleManager::addModule(StringRef FileName, ModuleKind Type, 43 SourceLocation ImportLoc, ModuleFile *ImportedBy, 44 unsigned Generation, 45 off_t ExpectedSize, time_t ExpectedModTime, 46 ModuleFile *&Module, 47 std::string &ErrorStr) { 48 Module = 0; 49 50 // Look for the file entry. This only fails if the expected size or 51 // modification time differ. 52 const FileEntry *Entry; 53 if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) 54 return OutOfDate; 55 56 if (!Entry && FileName != "-") { 57 ErrorStr = "file not found"; 58 return Missing; 59 } 60 61 // Check whether we already loaded this module, before 62 ModuleFile *&ModuleEntry = Modules[Entry]; 63 bool NewModule = false; 64 if (!ModuleEntry) { 65 // Allocate a new module. 66 ModuleFile *New = new ModuleFile(Type, Generation); 67 New->Index = Chain.size(); 68 New->FileName = FileName.str(); 69 New->File = Entry; 70 New->ImportLoc = ImportLoc; 71 Chain.push_back(New); 72 NewModule = true; 73 ModuleEntry = New; 74 75 // Load the contents of the module 76 if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { 77 // The buffer was already provided for us. 78 assert(Buffer && "Passed null buffer"); 79 New->Buffer.reset(Buffer); 80 } else { 81 // Open the AST file. 82 llvm::error_code ec; 83 if (FileName == "-") { 84 ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); 85 if (ec) 86 ErrorStr = ec.message(); 87 } else 88 New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); 89 90 if (!New->Buffer) 91 return Missing; 92 } 93 94 // Initialize the stream 95 New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), 96 (const unsigned char *)New->Buffer->getBufferEnd()); 97 } 98 99 if (ImportedBy) { 100 ModuleEntry->ImportedBy.insert(ImportedBy); 101 ImportedBy->Imports.insert(ModuleEntry); 102 } else { 103 if (!ModuleEntry->DirectlyImported) 104 ModuleEntry->ImportLoc = ImportLoc; 105 106 ModuleEntry->DirectlyImported = true; 107 } 108 109 Module = ModuleEntry; 110 return NewModule? NewlyLoaded : AlreadyLoaded; 111 } 112 113 namespace { 114 /// \brief Predicate that checks whether a module file occurs within 115 /// the given set. 116 class IsInModuleFileSet : public std::unary_function<ModuleFile *, bool> { 117 llvm::SmallPtrSet<ModuleFile *, 4> &Removed; 118 119 public: 120 IsInModuleFileSet(llvm::SmallPtrSet<ModuleFile *, 4> &Removed) 121 : Removed(Removed) { } 122 123 bool operator()(ModuleFile *MF) const { 124 return Removed.count(MF); 125 } 126 }; 127 } 128 129 void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last, 130 ModuleMap *modMap) { 131 if (first == last) 132 return; 133 134 // Collect the set of module file pointers that we'll be removing. 135 llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last); 136 137 // Remove any references to the now-destroyed modules. 138 IsInModuleFileSet checkInSet(victimSet); 139 for (unsigned i = 0, n = Chain.size(); i != n; ++i) { 140 Chain[i]->ImportedBy.remove_if(checkInSet); 141 } 142 143 // Delete the modules and erase them from the various structures. 144 for (ModuleIterator victim = first; victim != last; ++victim) { 145 Modules.erase((*victim)->File); 146 147 FileMgr.invalidateCache((*victim)->File); 148 if (modMap) { 149 StringRef ModuleName = llvm::sys::path::stem((*victim)->FileName); 150 if (Module *mod = modMap->findModule(ModuleName)) { 151 mod->setASTFile(0); 152 } 153 } 154 delete *victim; 155 } 156 157 // Remove the modules from the chain. 158 Chain.erase(first, last); 159 } 160 161 void ModuleManager::addInMemoryBuffer(StringRef FileName, 162 llvm::MemoryBuffer *Buffer) { 163 164 const FileEntry *Entry = FileMgr.getVirtualFile(FileName, 165 Buffer->getBufferSize(), 0); 166 InMemoryBuffers[Entry] = Buffer; 167 } 168 169 void ModuleManager::updateModulesInCommonWithGlobalIndex() { 170 ModulesInCommonWithGlobalIndex.clear(); 171 172 if (!GlobalIndex) 173 return; 174 175 // Collect the set of modules known to the global index. 176 GlobalIndex->noteAdditionalModulesLoaded(); 177 GlobalIndex->getKnownModules(ModulesInCommonWithGlobalIndex); 178 } 179 180 ModuleManager::VisitState *ModuleManager::allocateVisitState() { 181 // Fast path: if we have a cached state, use it. 182 if (FirstVisitState) { 183 VisitState *Result = FirstVisitState; 184 FirstVisitState = FirstVisitState->NextState; 185 Result->NextState = 0; 186 return Result; 187 } 188 189 // Allocate and return a new state. 190 return new VisitState(size()); 191 } 192 193 void ModuleManager::returnVisitState(VisitState *State) { 194 assert(State->NextState == 0 && "Visited state is in list?"); 195 State->NextState = FirstVisitState; 196 FirstVisitState = State; 197 } 198 199 void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) { 200 GlobalIndex = Index; 201 if (GlobalIndex) { 202 GlobalIndex->setResolver(this); 203 } 204 updateModulesInCommonWithGlobalIndex(); 205 } 206 207 ModuleManager::ModuleManager(FileManager &FileMgr) 208 : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(0) { } 209 210 ModuleManager::~ModuleManager() { 211 for (unsigned i = 0, e = Chain.size(); i != e; ++i) 212 delete Chain[e - i - 1]; 213 delete FirstVisitState; 214 } 215 216 void 217 ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), 218 void *UserData, 219 llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit) { 220 // If the visitation order vector is the wrong size, recompute the order. 221 if (VisitOrder.size() != Chain.size()) { 222 unsigned N = size(); 223 VisitOrder.clear(); 224 VisitOrder.reserve(N); 225 226 // Record the number of incoming edges for each module. When we 227 // encounter a module with no incoming edges, push it into the queue 228 // to seed the queue. 229 SmallVector<ModuleFile *, 4> Queue; 230 Queue.reserve(N); 231 llvm::SmallVector<unsigned, 4> UnusedIncomingEdges; 232 UnusedIncomingEdges.reserve(size()); 233 for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { 234 if (unsigned Size = (*M)->ImportedBy.size()) 235 UnusedIncomingEdges.push_back(Size); 236 else { 237 UnusedIncomingEdges.push_back(0); 238 Queue.push_back(*M); 239 } 240 } 241 242 // Traverse the graph, making sure to visit a module before visiting any 243 // of its dependencies. 244 unsigned QueueStart = 0; 245 while (QueueStart < Queue.size()) { 246 ModuleFile *CurrentModule = Queue[QueueStart++]; 247 VisitOrder.push_back(CurrentModule); 248 249 // For any module that this module depends on, push it on the 250 // stack (if it hasn't already been marked as visited). 251 for (llvm::SetVector<ModuleFile *>::iterator 252 M = CurrentModule->Imports.begin(), 253 MEnd = CurrentModule->Imports.end(); 254 M != MEnd; ++M) { 255 // Remove our current module as an impediment to visiting the 256 // module we depend on. If we were the last unvisited module 257 // that depends on this particular module, push it into the 258 // queue to be visited. 259 unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index]; 260 if (NumUnusedEdges && (--NumUnusedEdges == 0)) 261 Queue.push_back(*M); 262 } 263 } 264 265 assert(VisitOrder.size() == N && "Visitation order is wrong?"); 266 267 // We may need to update the set of modules we have in common with the 268 // global module index, since modules could have been added to the module 269 // manager since we loaded the global module index. 270 updateModulesInCommonWithGlobalIndex(); 271 272 delete FirstVisitState; 273 FirstVisitState = 0; 274 } 275 276 VisitState *State = allocateVisitState(); 277 unsigned VisitNumber = State->NextVisitNumber++; 278 279 // If the caller has provided us with a hit-set that came from the global 280 // module index, mark every module file in common with the global module 281 // index that is *not* in that set as 'visited'. 282 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) { 283 for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I) 284 { 285 ModuleFile *M = ModulesInCommonWithGlobalIndex[I]; 286 if (!ModuleFilesHit->count(M)) 287 State->VisitNumber[M->Index] = VisitNumber; 288 } 289 } 290 291 for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) { 292 ModuleFile *CurrentModule = VisitOrder[I]; 293 // Should we skip this module file? 294 if (State->VisitNumber[CurrentModule->Index] == VisitNumber) 295 continue; 296 297 // Visit the module. 298 assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1); 299 State->VisitNumber[CurrentModule->Index] = VisitNumber; 300 if (!Visitor(*CurrentModule, UserData)) 301 continue; 302 303 // The visitor has requested that cut off visitation of any 304 // module that the current module depends on. To indicate this 305 // behavior, we mark all of the reachable modules as having been visited. 306 ModuleFile *NextModule = CurrentModule; 307 do { 308 // For any module that this module depends on, push it on the 309 // stack (if it hasn't already been marked as visited). 310 for (llvm::SetVector<ModuleFile *>::iterator 311 M = NextModule->Imports.begin(), 312 MEnd = NextModule->Imports.end(); 313 M != MEnd; ++M) { 314 if (State->VisitNumber[(*M)->Index] != VisitNumber) { 315 State->Stack.push_back(*M); 316 State->VisitNumber[(*M)->Index] = VisitNumber; 317 } 318 } 319 320 if (State->Stack.empty()) 321 break; 322 323 // Pop the next module off the stack. 324 NextModule = State->Stack.back(); 325 State->Stack.pop_back(); 326 } while (true); 327 } 328 329 returnVisitState(State); 330 } 331 332 /// \brief Perform a depth-first visit of the current module. 333 static bool visitDepthFirst(ModuleFile &M, 334 bool (*Visitor)(ModuleFile &M, bool Preorder, 335 void *UserData), 336 void *UserData, 337 SmallVectorImpl<bool> &Visited) { 338 // Preorder visitation 339 if (Visitor(M, /*Preorder=*/true, UserData)) 340 return true; 341 342 // Visit children 343 for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), 344 IMEnd = M.Imports.end(); 345 IM != IMEnd; ++IM) { 346 if (Visited[(*IM)->Index]) 347 continue; 348 Visited[(*IM)->Index] = true; 349 350 if (visitDepthFirst(**IM, Visitor, UserData, Visited)) 351 return true; 352 } 353 354 // Postorder visitation 355 return Visitor(M, /*Preorder=*/false, UserData); 356 } 357 358 void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, 359 void *UserData), 360 void *UserData) { 361 SmallVector<bool, 16> Visited(size(), false); 362 for (unsigned I = 0, N = Chain.size(); I != N; ++I) { 363 if (Visited[Chain[I]->Index]) 364 continue; 365 Visited[Chain[I]->Index] = true; 366 367 if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) 368 return; 369 } 370 } 371 372 bool ModuleManager::lookupModuleFile(StringRef FileName, 373 off_t ExpectedSize, 374 time_t ExpectedModTime, 375 const FileEntry *&File) { 376 File = FileMgr.getFile(FileName, /*openFile=*/false, /*cacheFailure=*/false); 377 378 if (!File && FileName != "-") { 379 return false; 380 } 381 382 if ((ExpectedSize && ExpectedSize != File->getSize()) || 383 (ExpectedModTime && ExpectedModTime != File->getModificationTime())) { 384 return true; 385 } 386 387 return false; 388 } 389 390 bool ModuleManager::resolveModuleFileName(StringRef FileName, 391 off_t ExpectedSize, 392 time_t ExpectedModTime, 393 ModuleFile *&File) { 394 File = 0; 395 396 // Look for the file entry corresponding to this name. 397 const FileEntry *F; 398 if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, F)) 399 return true; 400 401 // If there is no file, we've succeeded (trivially). 402 if (!F) 403 return false; 404 405 // Determine whether we have a module file associated with this file entry. 406 llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known 407 = Modules.find(F); 408 if (Known == Modules.end()) { 409 // We don't know about this module file; invalidate the cache. 410 FileMgr.invalidateCache(F); 411 return false; 412 } 413 414 File = Known->second; 415 return false; 416 } 417 418 #ifndef NDEBUG 419 namespace llvm { 420 template<> 421 struct GraphTraits<ModuleManager> { 422 typedef ModuleFile NodeType; 423 typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType; 424 typedef ModuleManager::ModuleConstIterator nodes_iterator; 425 426 static ChildIteratorType child_begin(NodeType *Node) { 427 return Node->Imports.begin(); 428 } 429 430 static ChildIteratorType child_end(NodeType *Node) { 431 return Node->Imports.end(); 432 } 433 434 static nodes_iterator nodes_begin(const ModuleManager &Manager) { 435 return Manager.begin(); 436 } 437 438 static nodes_iterator nodes_end(const ModuleManager &Manager) { 439 return Manager.end(); 440 } 441 }; 442 443 template<> 444 struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits { 445 explicit DOTGraphTraits(bool IsSimple = false) 446 : DefaultDOTGraphTraits(IsSimple) { } 447 448 static bool renderGraphFromBottomUp() { 449 return true; 450 } 451 452 std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { 453 return llvm::sys::path::stem(M->FileName); 454 } 455 }; 456 } 457 458 void ModuleManager::viewGraph() { 459 llvm::ViewGraph(*this, "Modules"); 460 } 461 #endif 462