2011-12-09 09:45:42 +08:00
|
|
|
//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
|
2009-04-10 06:27:44 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-12-09 09:45:42 +08:00
|
|
|
// This file defines the PCHGenerator, which as a SemaConsumer that generates
|
|
|
|
// a PCH file.
|
2009-04-10 06:27:44 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2016-08-26 02:26:30 +08:00
|
|
|
#include "clang/Lex/HeaderSearch.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
#include "clang/Sema/SemaConsumer.h"
|
2016-07-19 03:02:11 +08:00
|
|
|
#include "clang/Serialization/ASTWriter.h"
|
2009-04-10 06:27:44 +08:00
|
|
|
#include "llvm/Bitcode/BitstreamWriter.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2015-11-04 02:33:07 +08:00
|
|
|
PCHGenerator::PCHGenerator(
|
2016-08-26 02:26:30 +08:00
|
|
|
const Preprocessor &PP, StringRef OutputFile, StringRef isysroot,
|
|
|
|
std::shared_ptr<PCHBuffer> Buffer,
|
2017-01-06 02:23:18 +08:00
|
|
|
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
|
2016-08-26 02:26:30 +08:00
|
|
|
bool AllowASTWithErrors, bool IncludeTimestamps)
|
|
|
|
: PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
|
2017-03-22 05:35:04 +08:00
|
|
|
SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
|
|
|
|
Writer(Stream, this->Buffer->Data, PP.getPCMCache(), Extensions,
|
Reapply "Modules: Cache PCMs in memory and avoid a use-after-free"
This reverts commit r298185, effectively reapplying r298165, after fixing the
new unit tests (PR32338). The memory buffer generator doesn't null-terminate
the MemoryBuffer it creates; this version of the commit informs getMemBuffer
about that to avoid the assert.
Original commit message follows:
----
Clang's internal build system for implicit modules uses lock files to
ensure that after a process writes a PCM it will read the same one back
in (without contention from other -cc1 commands). Since PCMs are read
from disk repeatedly while invalidating, building, and importing, the
lock is not released quickly. Furthermore, the LockFileManager is not
robust in every environment. Other -cc1 commands can stall until
timeout (after about eight minutes).
This commit changes the lock file from being necessary for correctness
to a (possibly dubious) performance hack. The remaining benefit is to
reduce duplicate work in competing -cc1 commands which depend on the
same module. Follow-up commits will change the internal build system to
continue after a timeout, and reduce the timeout. Perhaps we should
reconsider blocking at all.
This also fixes a use-after-free, when one part of a compilation
validates a PCM and starts using it, and another tries to swap out the
PCM for something new.
The PCMCache is a new type called MemoryBufferCache, which saves memory
buffers based on their filename. Its ownership is shared by the
CompilerInstance and ModuleManager.
- The ModuleManager stores PCMs there that it loads from disk, never
touching the disk if the cache is hot.
- When modules fail to validate, they're removed from the cache.
- When a CompilerInstance is spawned to build a new module, each
already-loaded PCM is assumed to be valid, and is frozen to avoid
the use-after-free.
- Any newly-built module is written directly to the cache to avoid the
round-trip to the filesystem, making lock files unnecessary for
correctness.
Original patch by Manman Ren; most testcases by Adrian Prantl!
llvm-svn: 298278
2017-03-21 01:58:26 +08:00
|
|
|
IncludeTimestamps),
|
2015-06-21 02:53:08 +08:00
|
|
|
AllowASTWithErrors(AllowASTWithErrors) {
|
2017-03-22 05:35:04 +08:00
|
|
|
this->Buffer->IsComplete = false;
|
2011-07-22 14:03:18 +08:00
|
|
|
}
|
|
|
|
|
2015-10-20 21:23:58 +08:00
|
|
|
PCHGenerator::~PCHGenerator() {
|
|
|
|
}
|
2009-04-28 02:38:38 +08:00
|
|
|
|
2009-04-10 06:27:44 +08:00
|
|
|
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
|
2013-06-11 08:36:55 +08:00
|
|
|
// Don't create a PCH if there were fatal failures during module loading.
|
|
|
|
if (PP.getModuleLoader().HadFatalFailure)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
|
|
|
|
if (hasErrors && !AllowASTWithErrors)
|
2009-04-10 06:27:44 +08:00
|
|
|
return;
|
2015-06-21 02:53:08 +08:00
|
|
|
|
2016-08-26 02:26:30 +08:00
|
|
|
Module *Module = nullptr;
|
2016-08-26 08:14:38 +08:00
|
|
|
if (PP.getLangOpts().isCompilingModule()) {
|
2016-08-26 02:26:30 +08:00
|
|
|
Module = PP.getHeaderSearchInfo().lookupModule(
|
|
|
|
PP.getLangOpts().CurrentModule, /*AllowSearch*/ false);
|
2016-08-26 08:14:38 +08:00
|
|
|
if (!Module) {
|
|
|
|
assert(hasErrors && "emitting module but current module doesn't exist");
|
|
|
|
return;
|
|
|
|
}
|
2016-08-26 02:26:30 +08:00
|
|
|
}
|
|
|
|
|
2015-06-21 02:53:08 +08:00
|
|
|
// Emit the PCH file to the Buffer.
|
2009-04-20 23:53:59 +08:00
|
|
|
assert(SemaPtr && "No Sema?");
|
2015-09-23 07:26:43 +08:00
|
|
|
Buffer->Signature =
|
2016-07-14 04:35:26 +08:00
|
|
|
Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
|
|
|
|
// For serialization we are lenient if the errors were
|
|
|
|
// only warn-as-error kind.
|
|
|
|
PP.getDiagnostics().hasUncompilableErrorOccurred());
|
2009-04-10 06:27:44 +08:00
|
|
|
|
2015-06-21 02:53:08 +08:00
|
|
|
Buffer->IsComplete = true;
|
2009-04-10 06:27:44 +08:00
|
|
|
}
|
|
|
|
|
2010-10-25 01:26:36 +08:00
|
|
|
ASTMutationListener *PCHGenerator::GetASTMutationListener() {
|
2011-08-26 06:35:51 +08:00
|
|
|
return &Writer;
|
2010-10-25 01:26:36 +08:00
|
|
|
}
|
|
|
|
|
2010-08-19 07:56:56 +08:00
|
|
|
ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
|
2010-07-30 08:29:29 +08:00
|
|
|
return &Writer;
|
|
|
|
}
|