aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/GlobalModuleIndex.cpp
diff options
context:
space:
mode:
authorEli Bendersky <eliben@chromium.org>2013-07-15 16:08:08 -0700
committerEli Bendersky <eliben@chromium.org>2013-07-15 16:08:08 -0700
commite789858899a7b36caf11b371a97411a1582a482b (patch)
treee8c28b178b32010f73b477b3c65b5ff74437530c /lib/Serialization/GlobalModuleIndex.cpp
parent99a5501f5ae5b75017dfc386d4abf648234e85df (diff)
parent20c7d45a4da9f58ad805ad1d37f92fe7dc232ec8 (diff)
Merge commit '20c7d45a4da9f58ad805ad1d37f92fe7dc232ec8'
Conflicts: lib/CodeGen/ItaniumCXXABI.cpp
Diffstat (limited to 'lib/Serialization/GlobalModuleIndex.cpp')
-rw-r--r--lib/Serialization/GlobalModuleIndex.cpp248
1 files changed, 108 insertions, 140 deletions
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index 7d34f85fd8..b6693e40e5 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/lib/Serialization/GlobalModuleIndex.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/GlobalModuleIndex.h"
+#include "clang/Serialization/Module.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
@@ -115,29 +116,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(),
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 +173,36 @@ 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;
- }
+ Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(),
+ Record.begin() + Idx,
+ Record.begin() + Idx + NumDeps);
+ Idx += NumDeps;
- // If the module file is newer than the index, ignore it.
- if (File->getSize() != Size || File->getModificationTime() != ModTime) {
- AnyOutOfDate = true;
- break;
- }
+ // Make sure we're at the end of the record.
+ assert(Idx == Record.size() && "More module info?");
- // Record this module. The dependencies will be resolved later.
- LoadedModuleInfo &Info = LoadedModules[ID];
- Info.File = File;
- Info.Dependencies.swap(Dependencies);
+ // Record this module as an unresolved module.
+ UnresolvedModules[llvm::sys::path::stem(Modules[ID].FileName)] = ID;
break;
}
@@ -234,91 +217,19 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr,
break;
}
}
-
- // 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);
- }
- }
}
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 +247,34 @@ 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 *MF = Modules[I].File)
+ ModuleFiles.push_back(MF);
}
}
void GlobalModuleIndex::getModuleDependencies(
- const clang::FileEntry *ModuleFile,
- SmallVectorImpl<const clang::FileEntry *> &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;
- }
- }
-
+ ModuleFile *File,
+ SmallVectorImpl<ModuleFile *> &Dependencies) {
// 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 = Modules[I].File)
+ Dependencies.push_back(MF);
+ }
}
bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) {
@@ -388,17 +295,41 @@ 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 *MF = Modules[ModuleIDs[I]].File)
+ Hits.insert(MF);
}
++NumIdentifierLookupHits;
return true;
}
+bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) {
+ // Look for the module in the global module index based on the module name.
+ StringRef Name = llvm::sys::path::stem(File->FileName);
+ llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name);
+ if (Known == UnresolvedModules.end()) {
+ return true;
+ }
+
+ // Rectify this module with the global module index.
+ ModuleInfo &Info = Modules[Known->second];
+
+ // If the size and modification time match what we expected, record this
+ // module file.
+ bool Failed = true;
+ if (File->File->getSize() == Info.Size &&
+ File->File->getModificationTime() == Info.ModTime) {
+ Info.File = File;
+ ModulesByFile[File] = Known->second;
+
+ Failed = false;
+ }
+
+ // One way or another, we have resolved this module file.
+ UnresolvedModules.erase(Known);
+ return Failed;
+}
+
void GlobalModuleIndex::printStats() {
std::fprintf(stderr, "*** Global Module Index Statistics:\n");
if (NumIdentifierLookups) {
@@ -629,6 +560,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 +574,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.
@@ -881,3 +818,34 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) {
// We're done.
return EC_None;
}
+
+namespace {
+ class GlobalIndexIdentifierIterator : public IdentifierIterator {
+ /// \brief The current position within the identifier lookup table.
+ IdentifierIndexTable::key_iterator Current;
+
+ /// \brief The end position within the identifier lookup table.
+ IdentifierIndexTable::key_iterator End;
+
+ public:
+ explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) {
+ Current = Idx.key_begin();
+ End = Idx.key_end();
+ }
+
+ virtual StringRef Next() {
+ if (Current == End)
+ return StringRef();
+
+ StringRef Result = *Current;
+ ++Current;
+ return Result;
+ }
+ };
+}
+
+IdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const {
+ IdentifierIndexTable &Table =
+ *static_cast<IdentifierIndexTable *>(IdentifierIndex);
+ return new GlobalIndexIdentifierIterator(Table);
+}