forked from OSchip/llvm-project
Reland [Frontend] avoid copy of PCH data when PrecompiledPreamble stores it in memory
This reverts commit eadf352707
.
The reland fixes a couple of places in clang that were unneccesarily
requesting a null-terminated buffer of the PCH, and hitting assertions.
This commit is contained in:
parent
9534811aa8
commit
e80ee1829c
|
@ -234,9 +234,10 @@ private:
|
||||||
|
|
||||||
class PrecompilePreambleAction : public ASTFrontendAction {
|
class PrecompilePreambleAction : public ASTFrontendAction {
|
||||||
public:
|
public:
|
||||||
PrecompilePreambleAction(std::string *InMemStorage,
|
PrecompilePreambleAction(std::shared_ptr<PCHBuffer> Buffer, bool WritePCHFile,
|
||||||
PreambleCallbacks &Callbacks)
|
PreambleCallbacks &Callbacks)
|
||||||
: InMemStorage(InMemStorage), Callbacks(Callbacks) {}
|
: Buffer(std::move(Buffer)), WritePCHFile(WritePCHFile),
|
||||||
|
Callbacks(Callbacks) {}
|
||||||
|
|
||||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||||
StringRef InFile) override;
|
StringRef InFile) override;
|
||||||
|
@ -244,6 +245,12 @@ public:
|
||||||
bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; }
|
bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; }
|
||||||
|
|
||||||
void setEmittedPreamblePCH(ASTWriter &Writer) {
|
void setEmittedPreamblePCH(ASTWriter &Writer) {
|
||||||
|
if (FileOS) {
|
||||||
|
*FileOS << Buffer->Data;
|
||||||
|
// Make sure it hits disk now.
|
||||||
|
FileOS->flush();
|
||||||
|
}
|
||||||
|
|
||||||
this->HasEmittedPreamblePCH = true;
|
this->HasEmittedPreamblePCH = true;
|
||||||
Callbacks.AfterPCHEmitted(Writer);
|
Callbacks.AfterPCHEmitted(Writer);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +269,9 @@ private:
|
||||||
friend class PrecompilePreambleConsumer;
|
friend class PrecompilePreambleConsumer;
|
||||||
|
|
||||||
bool HasEmittedPreamblePCH = false;
|
bool HasEmittedPreamblePCH = false;
|
||||||
std::string *InMemStorage;
|
std::shared_ptr<PCHBuffer> Buffer;
|
||||||
|
bool WritePCHFile; // otherwise the PCH is written into the PCHBuffer only.
|
||||||
|
std::unique_ptr<llvm::raw_pwrite_stream> FileOS; // null if in-memory
|
||||||
PreambleCallbacks &Callbacks;
|
PreambleCallbacks &Callbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,12 +281,11 @@ public:
|
||||||
const Preprocessor &PP,
|
const Preprocessor &PP,
|
||||||
InMemoryModuleCache &ModuleCache,
|
InMemoryModuleCache &ModuleCache,
|
||||||
StringRef isysroot,
|
StringRef isysroot,
|
||||||
std::unique_ptr<raw_ostream> Out)
|
std::shared_ptr<PCHBuffer> Buffer)
|
||||||
: PCHGenerator(PP, ModuleCache, "", isysroot,
|
: PCHGenerator(PP, ModuleCache, "", isysroot, std::move(Buffer),
|
||||||
std::make_shared<PCHBuffer>(),
|
|
||||||
ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
|
ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
|
||||||
/*AllowASTWithErrors=*/true),
|
/*AllowASTWithErrors=*/true),
|
||||||
Action(Action), Out(std::move(Out)) {}
|
Action(Action) {}
|
||||||
|
|
||||||
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
||||||
Action.Callbacks.HandleTopLevelDecl(DG);
|
Action.Callbacks.HandleTopLevelDecl(DG);
|
||||||
|
@ -288,15 +296,6 @@ public:
|
||||||
PCHGenerator::HandleTranslationUnit(Ctx);
|
PCHGenerator::HandleTranslationUnit(Ctx);
|
||||||
if (!hasEmittedPCH())
|
if (!hasEmittedPCH())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Write the generated bitstream to "Out".
|
|
||||||
*Out << getPCH();
|
|
||||||
// Make sure it hits disk now.
|
|
||||||
Out->flush();
|
|
||||||
// Free the buffer.
|
|
||||||
llvm::SmallVector<char, 0> Empty;
|
|
||||||
getPCH() = std::move(Empty);
|
|
||||||
|
|
||||||
Action.setEmittedPreamblePCH(getWriter());
|
Action.setEmittedPreamblePCH(getWriter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +305,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PrecompilePreambleAction &Action;
|
PrecompilePreambleAction &Action;
|
||||||
std::unique_ptr<raw_ostream> Out;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<ASTConsumer>
|
std::unique_ptr<ASTConsumer>
|
||||||
|
@ -316,21 +314,18 @@ PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
|
||||||
if (!GeneratePCHAction::ComputeASTConsumerArguments(CI, Sysroot))
|
if (!GeneratePCHAction::ComputeASTConsumerArguments(CI, Sysroot))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
std::unique_ptr<llvm::raw_ostream> OS;
|
if (WritePCHFile) {
|
||||||
if (InMemStorage) {
|
std::string OutputFile; // unused
|
||||||
OS = std::make_unique<llvm::raw_string_ostream>(*InMemStorage);
|
FileOS = GeneratePCHAction::CreateOutputFile(CI, InFile, OutputFile);
|
||||||
} else {
|
if (!FileOS)
|
||||||
std::string OutputFile;
|
return nullptr;
|
||||||
OS = GeneratePCHAction::CreateOutputFile(CI, InFile, OutputFile);
|
|
||||||
}
|
}
|
||||||
if (!OS)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (!CI.getFrontendOpts().RelocatablePCH)
|
if (!CI.getFrontendOpts().RelocatablePCH)
|
||||||
Sysroot.clear();
|
Sysroot.clear();
|
||||||
|
|
||||||
return std::make_unique<PrecompilePreambleConsumer>(
|
return std::make_unique<PrecompilePreambleConsumer>(
|
||||||
*this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, std::move(OS));
|
*this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
|
template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
|
||||||
|
@ -356,9 +351,9 @@ public:
|
||||||
S->File = std::move(File);
|
S->File = std::move(File);
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
static std::unique_ptr<PCHStorage> inMemory() {
|
static std::unique_ptr<PCHStorage> inMemory(std::shared_ptr<PCHBuffer> Buf) {
|
||||||
std::unique_ptr<PCHStorage> S(new PCHStorage());
|
std::unique_ptr<PCHStorage> S(new PCHStorage());
|
||||||
S->Memory.emplace();
|
S->Memory = std::move(Buf);
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,11 +371,7 @@ public:
|
||||||
}
|
}
|
||||||
llvm::StringRef memoryContents() const {
|
llvm::StringRef memoryContents() const {
|
||||||
assert(getKind() == Kind::InMemory);
|
assert(getKind() == Kind::InMemory);
|
||||||
return *Memory;
|
return StringRef(Memory->Data.data(), Memory->Data.size());
|
||||||
}
|
|
||||||
std::string &memoryBufferForWrite() {
|
|
||||||
assert(getKind() == Kind::InMemory);
|
|
||||||
return *Memory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -388,7 +379,7 @@ private:
|
||||||
PCHStorage(const PCHStorage &) = delete;
|
PCHStorage(const PCHStorage &) = delete;
|
||||||
PCHStorage &operator=(const PCHStorage &) = delete;
|
PCHStorage &operator=(const PCHStorage &) = delete;
|
||||||
|
|
||||||
llvm::Optional<std::string> Memory;
|
std::shared_ptr<PCHBuffer> Memory;
|
||||||
std::unique_ptr<TempPCHFile> File;
|
std::unique_ptr<TempPCHFile> File;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -411,9 +402,10 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
|
||||||
PreprocessorOptions &PreprocessorOpts =
|
PreprocessorOptions &PreprocessorOpts =
|
||||||
PreambleInvocation->getPreprocessorOpts();
|
PreambleInvocation->getPreprocessorOpts();
|
||||||
|
|
||||||
|
std::shared_ptr<PCHBuffer> Buffer = std::make_shared<PCHBuffer>();
|
||||||
std::unique_ptr<PCHStorage> Storage;
|
std::unique_ptr<PCHStorage> Storage;
|
||||||
if (StoreInMemory) {
|
if (StoreInMemory) {
|
||||||
Storage = PCHStorage::inMemory();
|
Storage = PCHStorage::inMemory(Buffer);
|
||||||
} else {
|
} else {
|
||||||
// Create a temporary file for the precompiled preamble. In rare
|
// Create a temporary file for the precompiled preamble. In rare
|
||||||
// circumstances, this can fail.
|
// circumstances, this can fail.
|
||||||
|
@ -495,9 +487,10 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
|
||||||
PreambleInputBuffer.release());
|
PreambleInputBuffer.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PrecompilePreambleAction> Act;
|
auto Act = std::make_unique<PrecompilePreambleAction>(
|
||||||
Act.reset(new PrecompilePreambleAction(
|
std::move(Buffer),
|
||||||
StoreInMemory ? &Storage->memoryBufferForWrite() : nullptr, Callbacks));
|
/*WritePCHFile=*/Storage->getKind() == PCHStorage::Kind::TempFile,
|
||||||
|
Callbacks);
|
||||||
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
|
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
|
||||||
return BuildPreambleError::BeginSourceFileFailed;
|
return BuildPreambleError::BeginSourceFileFailed;
|
||||||
|
|
||||||
|
@ -527,6 +520,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
|
||||||
|
|
||||||
if (!Act->hasEmittedPreamblePCH())
|
if (!Act->hasEmittedPreamblePCH())
|
||||||
return BuildPreambleError::CouldntEmitPCH;
|
return BuildPreambleError::CouldntEmitPCH;
|
||||||
|
Act.reset(); // Frees the PCH buffer frees, unless Storage keeps it in memory.
|
||||||
|
|
||||||
// Keep track of all of the files that the source manager knows about,
|
// Keep track of all of the files that the source manager knows about,
|
||||||
// so we can verify whether they have changed or not.
|
// so we can verify whether they have changed or not.
|
||||||
|
@ -790,7 +784,8 @@ void PrecompiledPreamble::setupPreambleStorage(
|
||||||
StringRef PCHPath = getInMemoryPreamblePath();
|
StringRef PCHPath = getInMemoryPreamblePath();
|
||||||
PreprocessorOpts.ImplicitPCHInclude = std::string(PCHPath);
|
PreprocessorOpts.ImplicitPCHInclude = std::string(PCHPath);
|
||||||
|
|
||||||
auto Buf = llvm::MemoryBuffer::getMemBuffer(Storage.memoryContents());
|
auto Buf = llvm::MemoryBuffer::getMemBuffer(
|
||||||
|
Storage.memoryContents(), PCHPath, /*RequiresNullTerminator=*/false);
|
||||||
VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS);
|
VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5071,7 +5071,8 @@ std::string ASTReader::getOriginalSourceFile(
|
||||||
const std::string &ASTFileName, FileManager &FileMgr,
|
const std::string &ASTFileName, FileManager &FileMgr,
|
||||||
const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags) {
|
const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags) {
|
||||||
// Open the AST file.
|
// Open the AST file.
|
||||||
auto Buffer = FileMgr.getBufferForFile(ASTFileName);
|
auto Buffer = FileMgr.getBufferForFile(ASTFileName, /*IsVolatile=*/false,
|
||||||
|
/*RequiresNullTerminator=*/false);
|
||||||
if (!Buffer) {
|
if (!Buffer) {
|
||||||
Diags.Report(diag::err_fe_unable_to_read_pch_file)
|
Diags.Report(diag::err_fe_unable_to_read_pch_file)
|
||||||
<< ASTFileName << Buffer.getError().message();
|
<< ASTFileName << Buffer.getError().message();
|
||||||
|
|
Loading…
Reference in New Issue