summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r--clang/lib/Serialization/ASTReader.cpp28
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp6
-rw-r--r--clang/lib/Serialization/InMemoryModuleCache.cpp63
-rw-r--r--clang/lib/Serialization/ModuleManager.cpp26
4 files changed, 87 insertions, 36 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index b8b390afc42..1ab6a75f8cd 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -92,6 +92,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -2359,6 +2360,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
RecordData Record;
unsigned NumInputs = 0;
unsigned NumUserInputs = 0;
+ StringRef BaseDirectoryAsWritten;
while (true) {
llvm::BitstreamEntry Entry = Stream.advance();
@@ -2559,7 +2561,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
ImportedName, /*FileMapOnly*/ true);
if (ImportedFile.empty())
- ImportedFile = ReadPath(F, Record, Idx);
+ // Use BaseDirectoryAsWritten to ensure we use the same path in the
+ // ModuleCache as when writing.
+ ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx);
else
SkipPath(Record, Idx);
@@ -2624,6 +2628,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
case MODULE_DIRECTORY: {
+ // Save the BaseDirectory as written in the PCM for computing the module
+ // filename for the ModuleCache.
+ BaseDirectoryAsWritten = Blob;
assert(!F.ModuleName.empty() &&
"MODULE_DIRECTORY found before MODULE_NAME");
// If we've already loaded a module map file covering this module, we may
@@ -4180,6 +4187,14 @@ ASTReader::ReadASTCore(StringRef FileName,
assert(M && "Missing module file");
+ bool ShouldFinalizePCM = false;
+ auto FinalizeOrDropPCM = llvm::make_scope_exit([&]() {
+ auto &MC = getModuleManager().getModuleCache();
+ if (ShouldFinalizePCM)
+ MC.finalizePCM(FileName);
+ else
+ MC.tryToDropPCM(FileName);
+ });
ModuleFile &F = *M;
BitstreamCursor &Stream = F.Stream;
Stream = BitstreamCursor(PCHContainerRdr.ExtractPCH(*F.Buffer));
@@ -4246,6 +4261,7 @@ ASTReader::ReadASTCore(StringRef FileName,
// Record that we've loaded this module.
Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc));
+ ShouldFinalizePCM = true;
return Success;
case UNHASHED_CONTROL_BLOCK_ID:
@@ -4309,7 +4325,7 @@ ASTReader::readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy,
// validation will fail during the as-system import since the PCM on disk
// doesn't guarantee that -Werror was respected. However, the -Werror
// flags were checked during the initial as-user import.
- if (getModuleManager().getModuleCache().isBufferFinal(F.FileName)) {
+ if (getModuleManager().getModuleCache().isPCMFinal(F.FileName)) {
Diag(diag::warn_module_system_bit_conflict) << F.FileName;
return Success;
}
@@ -9099,6 +9115,14 @@ std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
return Filename;
}
+std::string ASTReader::ReadPath(StringRef BaseDirectory,
+ const RecordData &Record, unsigned &Idx) {
+ std::string Filename = ReadString(Record, Idx);
+ if (!BaseDirectory.empty())
+ ResolveImportedPath(Filename, BaseDirectory);
+ return Filename;
+}
+
VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
unsigned &Idx) {
unsigned Major = Record[Idx++];
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a385eec2727..85bc2818395 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4622,9 +4622,9 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef,
WritingAST = false;
if (SemaRef.Context.getLangOpts().ImplicitModules && WritingModule) {
// Construct MemoryBuffer and update buffer manager.
- ModuleCache.addBuffer(OutputFile,
- llvm::MemoryBuffer::getMemBufferCopy(
- StringRef(Buffer.begin(), Buffer.size())));
+ ModuleCache.addBuiltPCM(OutputFile,
+ llvm::MemoryBuffer::getMemBufferCopy(
+ StringRef(Buffer.begin(), Buffer.size())));
}
return Signature;
}
diff --git a/clang/lib/Serialization/InMemoryModuleCache.cpp b/clang/lib/Serialization/InMemoryModuleCache.cpp
index 130ece01504..d35fa2a807f 100644
--- a/clang/lib/Serialization/InMemoryModuleCache.cpp
+++ b/clang/lib/Serialization/InMemoryModuleCache.cpp
@@ -11,39 +11,70 @@
using namespace clang;
+InMemoryModuleCache::State
+InMemoryModuleCache::getPCMState(llvm::StringRef Filename) const {
+ auto I = PCMs.find(Filename);
+ if (I == PCMs.end())
+ return Unknown;
+ if (I->second.IsFinal)
+ return Final;
+ return I->second.Buffer ? Tentative : ToBuild;
+}
+
llvm::MemoryBuffer &
-InMemoryModuleCache::addBuffer(llvm::StringRef Filename,
- std::unique_ptr<llvm::MemoryBuffer> Buffer) {
- auto Insertion = PCMs.insert({Filename, PCM{std::move(Buffer), NextIndex++}});
- assert(Insertion.second && "Already has a buffer");
+InMemoryModuleCache::addPCM(llvm::StringRef Filename,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ auto Insertion = PCMs.insert(std::make_pair(Filename, std::move(Buffer)));
+ assert(Insertion.second && "Already has a PCM");
return *Insertion.first->second.Buffer;
}
+llvm::MemoryBuffer &
+InMemoryModuleCache::addBuiltPCM(llvm::StringRef Filename,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ auto &PCM = PCMs[Filename];
+ assert(!PCM.IsFinal && "Trying to override finalized PCM?");
+ assert(!PCM.Buffer && "Trying to override tentative PCM?");
+ PCM.Buffer = std::move(Buffer);
+ PCM.IsFinal = true;
+ return *PCM.Buffer;
+}
+
llvm::MemoryBuffer *
-InMemoryModuleCache::lookupBuffer(llvm::StringRef Filename) {
+InMemoryModuleCache::lookupPCM(llvm::StringRef Filename) const {
auto I = PCMs.find(Filename);
if (I == PCMs.end())
return nullptr;
return I->second.Buffer.get();
}
-bool InMemoryModuleCache::isBufferFinal(llvm::StringRef Filename) {
- auto I = PCMs.find(Filename);
- if (I == PCMs.end())
- return false;
- return I->second.Index < FirstRemovableIndex;
+bool InMemoryModuleCache::isPCMFinal(llvm::StringRef Filename) const {
+ return getPCMState(Filename) == Final;
+}
+
+bool InMemoryModuleCache::shouldBuildPCM(llvm::StringRef Filename) const {
+ return getPCMState(Filename) == ToBuild;
}
-bool InMemoryModuleCache::tryToRemoveBuffer(llvm::StringRef Filename) {
+bool InMemoryModuleCache::tryToDropPCM(llvm::StringRef Filename) {
auto I = PCMs.find(Filename);
- assert(I != PCMs.end() && "No buffer to remove...");
- if (I->second.Index < FirstRemovableIndex)
+ assert(I != PCMs.end() && "PCM to remove is unknown...");
+
+ auto &PCM = I->second;
+ assert(PCM.Buffer && "PCM to remove is scheduled to be built...");
+
+ if (PCM.IsFinal)
return true;
- PCMs.erase(I);
+ PCM.Buffer.reset();
return false;
}
-void InMemoryModuleCache::finalizeCurrentBuffers() {
- FirstRemovableIndex = NextIndex;
+void InMemoryModuleCache::finalizePCM(llvm::StringRef Filename) {
+ auto I = PCMs.find(Filename);
+ assert(I != PCMs.end() && "PCM to finalize is unknown...");
+
+ auto &PCM = I->second;
+ assert(PCM.Buffer && "Trying to finalize a dropped PCM...");
+ PCM.IsFinal = true;
}
diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp
index 173fadcb76d..eb8e10acafe 100644
--- a/clang/lib/Serialization/ModuleManager.cpp
+++ b/clang/lib/Serialization/ModuleManager.cpp
@@ -118,6 +118,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// contents, but we can't check that.)
ExpectedModTime = 0;
}
+ // Note: ExpectedSize and ExpectedModTime will be 0 for MK_ImplicitModule
+ // when using an ASTFileSignature.
if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) {
ErrorStr = "module file out of date";
return OutOfDate;
@@ -159,16 +161,21 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// Load the contents of the module
if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us.
- NewModule->Buffer = &ModuleCache->addBuffer(FileName, std::move(Buffer));
+ NewModule->Buffer = &ModuleCache->addBuiltPCM(FileName, std::move(Buffer));
// Since the cached buffer is reused, it is safe to close the file
// descriptor that was opened while stat()ing the PCM in
// lookupModuleFile() above, it won't be needed any longer.
Entry->closeFile();
} else if (llvm::MemoryBuffer *Buffer =
- getModuleCache().lookupBuffer(FileName)) {
+ getModuleCache().lookupPCM(FileName)) {
NewModule->Buffer = Buffer;
// As above, the file descriptor is no longer needed.
Entry->closeFile();
+ } else if (getModuleCache().shouldBuildPCM(FileName)) {
+ // Report that the module is out of date, since we tried (and failed) to
+ // import it earlier.
+ Entry->closeFile();
+ return OutOfDate;
} else {
// Open the AST file.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
@@ -186,7 +193,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return Missing;
}
- NewModule->Buffer = &getModuleCache().addBuffer(FileName, std::move(*Buf));
+ NewModule->Buffer = &getModuleCache().addPCM(FileName, std::move(*Buf));
}
// Initialize the stream.
@@ -198,7 +205,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
ExpectedSignature, ErrorStr)) {
// Try to remove the buffer. If it can't be removed, then it was already
// validated by this process.
- if (!getModuleCache().tryToRemoveBuffer(NewModule->FileName))
+ if (!getModuleCache().tryToDropPCM(NewModule->FileName))
FileMgr.invalidateCache(NewModule->File);
return OutOfDate;
}
@@ -263,17 +270,6 @@ void ModuleManager::removeModules(
mod->setASTFile(nullptr);
}
}
-
- // Files that didn't make it through ReadASTCore successfully will be
- // rebuilt (or there was an error). Invalidate them so that we can load the
- // new files that will be renamed over the old ones.
- //
- // The ModuleCache tracks whether the module was successfully loaded in
- // another thread/context; in that case, it won't need to be rebuilt (and
- // we can't safely invalidate it anyway).
- if (LoadedSuccessfully.count(&*victim) == 0 &&
- !getModuleCache().tryToRemoveBuffer(victim->FileName))
- FileMgr.invalidateCache(victim->File);
}
// Delete the modules.
OpenPOWER on IntegriCloud