diff options
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 95 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/GlobalModuleIndex.cpp | 237 | ||||
-rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 116 |
4 files changed, 265 insertions, 185 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index cc9b5d506ac..6530bae5094 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1616,8 +1616,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { || StoredTime != File->getModificationTime() #endif )) { - if (Complain) + if (Complain) { Error(diag::err_fe_pch_file_modified, Filename, F.FileName); + } + IsOutOfDate = true; } @@ -1774,6 +1776,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, // location info are setup. SourceLocation ImportLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); + off_t StoredSize = (off_t)Record[Idx++]; + time_t StoredModTime = (time_t)Record[Idx++]; unsigned Length = Record[Idx++]; SmallString<128> ImportedFile(Record.begin() + Idx, Record.begin() + Idx + Length); @@ -1781,9 +1785,11 @@ ASTReader::ReadControlBlock(ModuleFile &F, // Load the AST file. switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded, + StoredSize, StoredModTime, ClientLoadCapabilities)) { case Failure: return Failure; // If we have to ignore the dependency, we'll have to ignore this too. + case Missing: return Missing; case OutOfDate: return OutOfDate; case VersionMismatch: return VersionMismatch; case ConfigurationMismatch: return ConfigurationMismatch; @@ -2774,7 +2780,7 @@ bool ASTReader::loadGlobalIndex() { StringRef ModuleCachePath = getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> Result - = GlobalModuleIndex::readIndex(FileMgr, ModuleCachePath); + = GlobalModuleIndex::readIndex(ModuleCachePath); if (!Result.first) return true; @@ -2799,13 +2805,18 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, SmallVector<ImportedModule, 4> Loaded; switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc, /*ImportedBy=*/0, Loaded, + 0, 0, ClientLoadCapabilities)) { case Failure: + case Missing: case OutOfDate: case VersionMismatch: case ConfigurationMismatch: case HadErrors: - ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end()); + ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(), + Context.getLangOpts().Modules + ? &PP.getHeaderSearchInfo().getModuleMap() + : 0); // If we find that any modules are unusable, the global index is going // to be out-of-date. Just remove it. @@ -2923,27 +2934,54 @@ ASTReader::ReadASTCore(StringRef FileName, SourceLocation ImportLoc, ModuleFile *ImportedBy, SmallVectorImpl<ImportedModule> &Loaded, + off_t ExpectedSize, time_t ExpectedModTime, unsigned ClientLoadCapabilities) { ModuleFile *M; - bool NewModule; std::string ErrorStr; - llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportLoc, - ImportedBy, CurrentGeneration, - ErrorStr); - - if (!M) { - // We couldn't load the module. - std::string Msg = "Unable to load module \"" + FileName.str() + "\": " - + ErrorStr; - Error(Msg); - return Failure; - } + ModuleManager::AddModuleResult AddResult + = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, + CurrentGeneration, ExpectedSize, ExpectedModTime, + M, ErrorStr); - if (!NewModule) { - // We've already loaded this module. + switch (AddResult) { + case ModuleManager::AlreadyLoaded: return Success; + + case ModuleManager::NewlyLoaded: + // Load module file below. + break; + + case ModuleManager::Missing: + // The module file was missing; if the client handle handle, that, return + // it. + if (ClientLoadCapabilities & ARR_Missing) + return Missing; + + // Otherwise, return an error. + { + std::string Msg = "Unable to load module \"" + FileName.str() + "\": " + + ErrorStr; + Error(Msg); + } + return Failure; + + case ModuleManager::OutOfDate: + // We couldn't load the module file because it is out-of-date. If the + // client can handle out-of-date, return it. + if (ClientLoadCapabilities & ARR_OutOfDate) + return OutOfDate; + + // Otherwise, return an error. + { + std::string Msg = "Unable to load module \"" + FileName.str() + "\": " + + ErrorStr; + Error(Msg); + } + return Failure; } + assert(M && "Missing module file"); + // FIXME: This seems rather a hack. Should CurrentDir be part of the // module? if (FileName != "-") { @@ -2997,6 +3035,7 @@ ASTReader::ReadASTCore(StringRef FileName, break; case Failure: return Failure; + case Missing: return Missing; case OutOfDate: return OutOfDate; case VersionMismatch: return VersionMismatch; case ConfigurationMismatch: return ConfigurationMismatch; @@ -3467,18 +3506,22 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { return true; } - if (const FileEntry *CurFile = CurrentModule->getASTFile()) { - if (CurFile != F.File) { - if (!Diags.isDiagnosticInFlight()) { - Diag(diag::err_module_file_conflict) - << CurrentModule->getTopLevelModuleName() - << CurFile->getName() - << F.File->getName(); + if (!ParentModule) { + if (const FileEntry *CurFile = CurrentModule->getASTFile()) { + if (CurFile != F.File) { + if (!Diags.isDiagnosticInFlight()) { + Diag(diag::err_module_file_conflict) + << CurrentModule->getTopLevelModuleName() + << CurFile->getName() + << F.File->getName(); + } + return true; } - return true; } + + CurrentModule->setASTFile(F.File); } - CurrentModule->setASTFile(F.File); + CurrentModule->IsFromModuleFile = true; CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; CurrentModule->InferSubmodules = InferSubmodules; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 716b1fbb306..724c8cf8254 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1034,6 +1034,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding AddSourceLocation((*M)->ImportLoc, Record); + Record.push_back((*M)->File->getSize()); + Record.push_back((*M)->File->getModificationTime()); // FIXME: This writes the absolute path for AST files we depend on. const std::string &FileName = (*M)->FileName; Record.push_back(FileName.size()); diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index 7d34f85fd8b..8b5851dbe5d 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -57,6 +57,8 @@ static const char * const IndexFileName = "modules.idx"; /// \brief The global index file version. static const unsigned CurrentVersion = 1; +ModuleFileNameResolver::~ModuleFileNameResolver() { } + //----------------------------------------------------------------------------// // Global module index reader. //----------------------------------------------------------------------------// @@ -115,29 +117,16 @@ public: typedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable; -/// \brief Module information as it was loaded from the index file. -struct LoadedModuleInfo { - const FileEntry *File; - SmallVector<unsigned, 2> Dependencies; - SmallVector<unsigned, 2> ImportedBy; -}; - } -GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr, - llvm::MemoryBuffer *Buffer, +GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer, llvm::BitstreamCursor Cursor) - : Buffer(Buffer), IdentifierIndex(), + : Buffer(Buffer), Resolver(), IdentifierIndex(), NumIdentifierLookups(), NumIdentifierLookupHits() { - typedef llvm::DenseMap<unsigned, LoadedModuleInfo> LoadedModulesMap; - LoadedModulesMap LoadedModules; - // Read the global index. - unsigned LargestID = 0; bool InGlobalIndexBlock = false; bool Done = false; - bool AnyOutOfDate = false; while (!Done) { llvm::BitstreamEntry Entry = Cursor.advance(); @@ -185,41 +174,33 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr, case MODULE: { unsigned Idx = 0; unsigned ID = Record[Idx++]; - if (ID > LargestID) - LargestID = ID; - - off_t Size = Record[Idx++]; - time_t ModTime = Record[Idx++]; + + // Make room for this module's information. + if (ID == Modules.size()) + Modules.push_back(ModuleInfo()); + else + Modules.resize(ID + 1); + + // Size/modification time for this module file at the time the + // global index was built. + Modules[ID].Size = Record[Idx++]; + Modules[ID].ModTime = Record[Idx++]; // File name. unsigned NameLen = Record[Idx++]; - llvm::SmallString<64> FileName(Record.begin() + Idx, - Record.begin() + Idx + NameLen); + Modules[ID].FileName.assign(Record.begin() + Idx, + Record.begin() + Idx + NameLen); Idx += NameLen; // Dependencies unsigned NumDeps = Record[Idx++]; - llvm::SmallVector<unsigned, 2> - Dependencies(Record.begin() + Idx, Record.begin() + Idx + NumDeps); - - // Find the file. If we can't find it, ignore it. - const FileEntry *File = FileMgr.getFile(FileName, /*openFile=*/false, - /*cacheFailure=*/false); - if (!File) { - AnyOutOfDate = true; - break; - } - - // If the module file is newer than the index, ignore it. - if (File->getSize() != Size || File->getModificationTime() != ModTime) { - AnyOutOfDate = true; - break; - } + Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(), + Record.begin() + Idx, + Record.begin() + Idx + NumDeps); + Idx += NumDeps; - // Record this module. The dependencies will be resolved later. - LoadedModuleInfo &Info = LoadedModules[ID]; - Info.File = File; - Info.Dependencies.swap(Dependencies); + // Make sure we're at the end of the record. + assert(Idx == Record.size() && "More module info?"); break; } @@ -235,74 +216,11 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr, } } - // If there are any modules that have gone out-of-date, prune out any modules - // that depend on them. - if (AnyOutOfDate) { - // First, build back links in the module dependency graph. - SmallVector<unsigned, 4> Stack; - for (LoadedModulesMap::iterator LM = LoadedModules.begin(), - LMEnd = LoadedModules.end(); - LM != LMEnd; ++LM) { - unsigned ID = LM->first; - - // If this module is out-of-date, push it onto the stack. - if (LM->second.File == 0) - Stack.push_back(ID); - - for (unsigned I = 0, N = LM->second.Dependencies.size(); I != N; ++I) { - unsigned DepID = LM->second.Dependencies[I]; - LoadedModulesMap::iterator Known = LoadedModules.find(DepID); - if (Known == LoadedModules.end() || !Known->second.File) { - // The dependency was out-of-date, so mark us as out of date. - // This is just an optimization. - if (LM->second.File) - Stack.push_back(ID); - - LM->second.File = 0; - continue; - } - - // Record this reverse dependency. - Known->second.ImportedBy.push_back(ID); - } - } - - // Second, walk the back links from out-of-date modules to those modules - // that depend on them, making those modules out-of-date as well. - while (!Stack.empty()) { - unsigned ID = Stack.back(); - Stack.pop_back(); - - LoadedModuleInfo &Info = LoadedModules[ID]; - for (unsigned I = 0, N = Info.ImportedBy.size(); I != N; ++I) { - unsigned FromID = Info.ImportedBy[I]; - if (LoadedModules[FromID].File) { - LoadedModules[FromID].File = 0; - Stack.push_back(FromID); - } - } - } - } - - // Allocate the vector containing information about all of the modules. - Modules.resize(LargestID + 1); - for (LoadedModulesMap::iterator LM = LoadedModules.begin(), - LMEnd = LoadedModules.end(); - LM != LMEnd; ++LM) { - if (!LM->second.File) - continue; - - Modules[LM->first].File = LM->second.File; - - // Resolve dependencies. Drop any we can't resolve due to out-of-date - // module files. - for (unsigned I = 0, N = LM->second.Dependencies.size(); I != N; ++I) { - unsigned DepID = LM->second.Dependencies[I]; - LoadedModulesMap::iterator Known = LoadedModules.find(DepID); - if (Known == LoadedModules.end() || !Known->second.File) - continue; - - Modules[LM->first].Dependencies.push_back(Known->second.File); + // Compute imported-by relation. + for (unsigned ID = 0, IDEnd = Modules.size(); ID != IDEnd; ++ID) { + for (unsigned D = 0, DEnd = Modules[ID].Dependencies.size(); + D != DEnd; ++D) { + Modules[Modules[ID].Dependencies[D]].ImportedBy.push_back(ID); } } } @@ -310,15 +228,14 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr, GlobalModuleIndex::~GlobalModuleIndex() { } std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> -GlobalModuleIndex::readIndex(FileManager &FileMgr, StringRef Path) { +GlobalModuleIndex::readIndex(StringRef Path) { // Load the index file, if it's there. llvm::SmallString<128> IndexPath; IndexPath += Path; llvm::sys::path::append(IndexPath, IndexFileName); - llvm::OwningPtr<llvm::MemoryBuffer> Buffer( - FileMgr.getBufferForFile(IndexPath)); - if (!Buffer) + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + if (llvm::MemoryBuffer::getFile(IndexPath, Buffer) != llvm::errc::success) return std::make_pair((GlobalModuleIndex *)0, EC_NotFound); /// \brief The bitstream reader from which we'll read the AST file. @@ -336,38 +253,41 @@ GlobalModuleIndex::readIndex(FileManager &FileMgr, StringRef Path) { return std::make_pair((GlobalModuleIndex *)0, EC_IOError); } - return std::make_pair(new GlobalModuleIndex(FileMgr, Buffer.take(), Cursor), - EC_None); + return std::make_pair(new GlobalModuleIndex(Buffer.take(), Cursor), EC_None); } -void GlobalModuleIndex::getKnownModules( - SmallVectorImpl<const FileEntry *> &ModuleFiles) { +void +GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { ModuleFiles.clear(); for (unsigned I = 0, N = Modules.size(); I != N; ++I) { - if (Modules[I].File) - ModuleFiles.push_back(Modules[I].File); + if (ModuleFile *File = resolveModuleFile(I)) + ModuleFiles.push_back(File); } } void GlobalModuleIndex::getModuleDependencies( - const clang::FileEntry *ModuleFile, - SmallVectorImpl<const clang::FileEntry *> &Dependencies) { + ModuleFile *File, + SmallVectorImpl<ModuleFile *> &Dependencies) { // If the file -> index mapping is empty, populate it now. if (ModulesByFile.empty()) { for (unsigned I = 0, N = Modules.size(); I != N; ++I) { - if (Modules[I].File) - ModulesByFile[Modules[I].File] = I; + resolveModuleFile(I); } } // Look for information about this module file. - llvm::DenseMap<const FileEntry *, unsigned>::iterator Known - = ModulesByFile.find(ModuleFile); + llvm::DenseMap<ModuleFile *, unsigned>::iterator Known + = ModulesByFile.find(File); if (Known == ModulesByFile.end()) return; // Record dependencies. - Dependencies = Modules[Known->second].Dependencies; + Dependencies.clear(); + ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies; + for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) { + if (ModuleFile *MF = resolveModuleFile(I)) + Dependencies.push_back(MF); + } } bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { @@ -388,17 +308,62 @@ bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { SmallVector<unsigned, 2> ModuleIDs = *Known; for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) { - unsigned ID = ModuleIDs[I]; - if (ID >= Modules.size() || !Modules[ID].File) - continue; - - Hits.insert(Modules[ID].File); + if (ModuleFile *File = resolveModuleFile(ModuleIDs[I])) + Hits.insert(File); } ++NumIdentifierLookupHits; return true; } +ModuleFile *GlobalModuleIndex::resolveModuleFile(unsigned ID) { + assert(ID < Modules.size() && "Out-of-bounds module index"); + + // If we already have a module file, return it. + if (Modules[ID].File) + return Modules[ID].File; + + // If we don't have a file name, or if there is no resolver, we can't + // resolve this. + if (Modules[ID].FileName.empty() || !Resolver) + return 0; + + // Try to resolve this module file. + ModuleFile *File; + if (Resolver->resolveModuleFileName(Modules[ID].FileName, Modules[ID].Size, + Modules[ID].ModTime, File)) { + // Clear out the module files for anything that depends on this module. + llvm::SmallVector<unsigned, 8> Stack; + + Stack.push_back(ID); + while (!Stack.empty()) { + unsigned Victim = Stack.back(); + Stack.pop_back(); + + // Mark this file as ignored. + Modules[Victim].File = 0; + Modules[Victim].FileName.clear(); + + // Push any not-yet-ignored imported modules onto the stack. + for (unsigned I = 0, N = Modules[Victim].ImportedBy.size(); I != N; ++I) { + unsigned NextVictim = Modules[Victim].ImportedBy[I]; + if (!Modules[NextVictim].FileName.empty()) + Stack.push_back(NextVictim); + } + } + + return 0; + } + + // If we have a module file, record it. + if (File) { + Modules[ID].File = File; + ModulesByFile[File] = ID; + } + + return File; +} + void GlobalModuleIndex::printStats() { std::fprintf(stderr, "*** Global Module Index Statistics:\n"); if (NumIdentifierLookups) { @@ -629,6 +594,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Skip the import location ++Idx; + // Load stored size/modification time. + off_t StoredSize = (off_t)Record[Idx++]; + time_t StoredModTime = (time_t)Record[Idx++]; + // Retrieve the imported file name. unsigned Length = Record[Idx++]; SmallString<128> ImportedFile(Record.begin() + Idx, @@ -639,7 +608,9 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { const FileEntry *DependsOnFile = FileMgr.getFile(ImportedFile, /*openFile=*/false, /*cacheFailure=*/false); - if (!DependsOnFile) + if (!DependsOnFile || + (StoredSize != DependsOnFile->getSize()) || + (StoredModTime != DependsOnFile->getModificationTime())) return true; // Record the dependency. diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index b9f4d888f30..a9f4794e106 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -11,9 +11,11 @@ // modules for the ASTReader. // //===----------------------------------------------------------------------===// +#include "clang/Lex/ModuleMap.h" #include "clang/Serialization/ModuleManager.h" #include "clang/Serialization/GlobalModuleIndex.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PathV2.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" @@ -36,18 +38,28 @@ llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { return InMemoryBuffers[Entry]; } -std::pair<ModuleFile *, bool> +ModuleManager::AddModuleResult ModuleManager::addModule(StringRef FileName, ModuleKind Type, SourceLocation ImportLoc, ModuleFile *ImportedBy, - unsigned Generation, std::string &ErrorStr) { - const FileEntry *Entry = FileMgr.getFile(FileName, /*openFile=*/false, - /*cacheFailure=*/false); + unsigned Generation, + off_t ExpectedSize, time_t ExpectedModTime, + ModuleFile *&Module, + std::string &ErrorStr) { + Module = 0; + + // Look for the file entry. This only fails if the expected size or + // modification time differ. + const FileEntry *Entry; + if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) + return OutOfDate; + if (!Entry && FileName != "-") { ErrorStr = "file not found"; - return std::make_pair(static_cast<ModuleFile*>(0), false); + return Missing; } - - // Check whether we already loaded this module, before + + // Check whether we already loaded this module, before + AddModuleResult Result = AlreadyLoaded; ModuleFile *&ModuleEntry = Modules[Entry]; bool NewModule = false; if (!ModuleEntry) { @@ -77,12 +89,15 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); if (!New->Buffer) - return std::make_pair(static_cast<ModuleFile*>(0), false); + return Missing; } // Initialize the stream New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), - (const unsigned char *)New->Buffer->getBufferEnd()); } + (const unsigned char *)New->Buffer->getBufferEnd()); + + Result = NewlyLoaded; + } if (ImportedBy) { ModuleEntry->ImportedBy.insert(ImportedBy); @@ -93,8 +108,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, ModuleEntry->DirectlyImported = true; } - - return std::make_pair(ModuleEntry, NewModule); + + Module = ModuleEntry; + return NewModule? NewlyLoaded : AlreadyLoaded; } namespace { @@ -113,7 +129,8 @@ namespace { }; } -void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last) { +void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last, + ModuleMap *modMap) { if (first == last) return; @@ -129,6 +146,14 @@ void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last) { // Delete the modules and erase them from the various structures. for (ModuleIterator victim = first; victim != last; ++victim) { Modules.erase((*victim)->File); + + FileMgr.invalidateCache((*victim)->File); + if (modMap) { + StringRef ModuleName = llvm::sys::path::stem((*victim)->FileName); + if (Module *mod = modMap->findModule(ModuleName)) { + mod->setASTFile(0); + } + } delete *victim; } @@ -151,18 +176,8 @@ void ModuleManager::updateModulesInCommonWithGlobalIndex() { return; // Collect the set of modules known to the global index. - SmallVector<const FileEntry *, 16> KnownModules; - GlobalIndex->getKnownModules(KnownModules); - - // Map those modules to AST files known to the module manager. - for (unsigned I = 0, N = KnownModules.size(); I != N; ++I) { - llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known - = Modules.find(KnownModules[I]); - if (Known == Modules.end()) - continue; - - ModulesInCommonWithGlobalIndex.push_back(Known->second); - } + GlobalIndex->noteAdditionalModulesLoaded(); + GlobalIndex->getKnownModules(ModulesInCommonWithGlobalIndex); } ModuleManager::VisitState *ModuleManager::allocateVisitState() { @@ -186,6 +201,9 @@ void ModuleManager::returnVisitState(VisitState *State) { void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) { GlobalIndex = Index; + if (GlobalIndex) { + GlobalIndex->setResolver(this); + } updateModulesInCommonWithGlobalIndex(); } @@ -201,7 +219,7 @@ ModuleManager::~ModuleManager() { void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData, - llvm::SmallPtrSet<const FileEntry *, 4> *ModuleFilesHit) { + llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit) { // If the visitation order vector is the wrong size, recompute the order. if (VisitOrder.size() != Chain.size()) { unsigned N = size(); @@ -268,7 +286,7 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I) { ModuleFile *M = ModulesInCommonWithGlobalIndex[I]; - if (!ModuleFilesHit->count(M->File)) + if (!ModuleFilesHit->count(M)) State->VisitNumber[M->Index] = VisitNumber; } } @@ -354,6 +372,52 @@ void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder } } +bool ModuleManager::lookupModuleFile(StringRef FileName, + off_t ExpectedSize, + time_t ExpectedModTime, + const FileEntry *&File) { + File = FileMgr.getFile(FileName, /*openFile=*/false, /*cacheFailure=*/false); + + if (!File && FileName != "-") { + return false; + } + + if ((ExpectedSize && ExpectedSize != File->getSize()) || + (ExpectedModTime && ExpectedModTime != File->getModificationTime())) { + return true; + } + + return false; +} + +bool ModuleManager::resolveModuleFileName(StringRef FileName, + off_t ExpectedSize, + time_t ExpectedModTime, + ModuleFile *&File) { + File = 0; + + // Look for the file entry corresponding to this name. + const FileEntry *F; + if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, F)) + return true; + + // If there is no file, we've succeeded (trivially). + if (!F) + return false; + + // Determine whether we have a module file associated with this file entry. + llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known + = Modules.find(F); + if (Known == Modules.end()) { + // We don't know about this module file; invalidate the cache. + FileMgr.invalidateCache(F); + return false; + } + + File = Known->second; + return false; +} + #ifndef NDEBUG namespace llvm { template<> |