aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ModuleManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Serialization/ModuleManager.cpp')
-rw-r--r--lib/Serialization/ModuleManager.cpp93
1 files changed, 69 insertions, 24 deletions
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index ac98ca0b8720..30d9c89a1244 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -58,8 +58,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
unsigned Generation,
off_t ExpectedSize, time_t ExpectedModTime,
ASTFileSignature ExpectedSignature,
- std::function<ASTFileSignature(llvm::BitstreamReader &)>
- ReadSignature,
+ ASTFileSignatureReader ReadSignature,
ModuleFile *&Module,
std::string &ErrorStr) {
Module = nullptr;
@@ -95,6 +94,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
New->File = Entry;
New->ImportLoc = ImportLoc;
Chain.push_back(New);
+ if (!ImportedBy)
+ Roots.push_back(New);
NewModule = true;
ModuleEntry = New;
@@ -156,7 +157,12 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// invalidate the file cache for Entry, and that is not safe if this
// module is *itself* up to date, but has an out-of-date importer.
Modules.erase(Entry);
+ assert(Chain.back() == ModuleEntry);
Chain.pop_back();
+ if (Roots.back() == ModuleEntry)
+ Roots.pop_back();
+ else
+ assert(ImportedBy);
delete ModuleEntry;
}
return OutOfDate;
@@ -187,12 +193,15 @@ void ModuleManager::removeModules(
// Collect the set of module file pointers that we'll be removing.
llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
+ auto IsVictim = [&](ModuleFile *MF) {
+ return victimSet.count(MF);
+ };
// Remove any references to the now-destroyed modules.
for (unsigned i = 0, n = Chain.size(); i != n; ++i) {
- Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) {
- return victimSet.count(MF);
- });
+ Chain[i]->ImportedBy.remove_if(IsVictim);
}
+ Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
+ Roots.end());
// Delete the modules and erase them from the various structures.
for (ModuleIterator victim = first; victim != last; ++victim) {
@@ -227,6 +236,15 @@ ModuleManager::addInMemoryBuffer(StringRef FileName,
InMemoryBuffers[Entry] = std::move(Buffer);
}
+bool ModuleManager::addKnownModuleFile(StringRef FileName) {
+ const FileEntry *File;
+ if (lookupModuleFile(FileName, 0, 0, File))
+ return true;
+ if (!Modules.count(File))
+ AdditionalKnownModuleFiles.insert(File);
+ return false;
+}
+
ModuleManager::VisitState *ModuleManager::allocateVisitState() {
// Fast path: if we have a cached state, use it.
if (FirstVisitState) {
@@ -263,6 +281,8 @@ void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
}
void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
+ AdditionalKnownModuleFiles.remove(MF->File);
+
if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
return;
@@ -388,16 +408,38 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
returnVisitState(State);
}
+static void markVisitedDepthFirst(ModuleFile &M,
+ SmallVectorImpl<bool> &Visited) {
+ for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
+ IMEnd = M.Imports.end();
+ IM != IMEnd; ++IM) {
+ if (Visited[(*IM)->Index])
+ continue;
+ Visited[(*IM)->Index] = true;
+ if (!M.DirectlyImported)
+ markVisitedDepthFirst(**IM, Visited);
+ }
+}
+
/// \brief Perform a depth-first visit of the current module.
-static bool visitDepthFirst(ModuleFile &M,
- bool (*Visitor)(ModuleFile &M, bool Preorder,
- void *UserData),
- void *UserData,
- SmallVectorImpl<bool> &Visited) {
- // Preorder visitation
- if (Visitor(M, /*Preorder=*/true, UserData))
- return true;
-
+static bool visitDepthFirst(
+ ModuleFile &M,
+ ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
+ void *UserData),
+ bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData,
+ SmallVectorImpl<bool> &Visited) {
+ if (PreorderVisitor) {
+ switch (PreorderVisitor(M, UserData)) {
+ case ModuleManager::Abort:
+ return true;
+ case ModuleManager::SkipImports:
+ markVisitedDepthFirst(M, Visited);
+ return false;
+ case ModuleManager::Continue:
+ break;
+ }
+ }
+
// Visit children
for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
IMEnd = M.Imports.end();
@@ -406,24 +448,27 @@ static bool visitDepthFirst(ModuleFile &M,
continue;
Visited[(*IM)->Index] = true;
- if (visitDepthFirst(**IM, Visitor, UserData, Visited))
+ if (visitDepthFirst(**IM, PreorderVisitor, PostorderVisitor, UserData, Visited))
return true;
}
- // Postorder visitation
- return Visitor(M, /*Preorder=*/false, UserData);
+ if (PostorderVisitor)
+ return PostorderVisitor(M, UserData);
+
+ return false;
}
-void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder,
- void *UserData),
- void *UserData) {
+void ModuleManager::visitDepthFirst(
+ ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
+ void *UserData),
+ bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData) {
SmallVector<bool, 16> Visited(size(), false);
- for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
- if (Visited[Chain[I]->Index])
+ for (unsigned I = 0, N = Roots.size(); I != N; ++I) {
+ if (Visited[Roots[I]->Index])
continue;
- Visited[Chain[I]->Index] = true;
+ Visited[Roots[I]->Index] = true;
- if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
+ if (::visitDepthFirst(*Roots[I], PreorderVisitor, PostorderVisitor, UserData, Visited))
return;
}
}