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