2011-12-09 01:45:42 +00:00
|
|
|
//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
|
2009-04-09 22:27:44 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-04-09 22:27:44 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-12-09 01:45:42 +00:00
|
|
|
// This file defines the PCHGenerator, which as a SemaConsumer that generates
|
|
|
|
// a PCH file.
|
2009-04-09 22:27:44 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2016-08-25 18:26:30 +00:00
|
|
|
#include "clang/Lex/HeaderSearch.h"
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
#include "clang/Sema/SemaConsumer.h"
|
2016-07-18 19:02:11 +00:00
|
|
|
#include "clang/Serialization/ASTWriter.h"
|
2019-07-03 22:40:07 +00:00
|
|
|
#include "llvm/Bitstream/BitstreamWriter.h"
|
2009-04-09 22:27:44 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2015-11-03 18:33:07 +00:00
|
|
|
PCHGenerator::PCHGenerator(
|
2019-03-09 17:33:56 +00:00
|
|
|
const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
|
|
|
|
StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
|
2017-01-05 18:23:18 +00:00
|
|
|
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
|
2019-03-12 18:38:04 +00:00
|
|
|
bool AllowASTWithErrors, bool IncludeTimestamps,
|
2022-08-03 15:24:25 -07:00
|
|
|
bool ShouldCacheASTInMemory)
|
2016-08-25 18:26:30 +00:00
|
|
|
: PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
|
2017-03-21 21:35:04 +00:00
|
|
|
SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
|
2019-03-09 17:33:56 +00:00
|
|
|
Writer(Stream, this->Buffer->Data, ModuleCache, 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-20 17:58:26 +00:00
|
|
|
IncludeTimestamps),
|
2019-03-12 18:38:04 +00:00
|
|
|
AllowASTWithErrors(AllowASTWithErrors),
|
2022-08-03 15:24:25 -07:00
|
|
|
ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
|
2017-03-21 21:35:04 +00:00
|
|
|
this->Buffer->IsComplete = false;
|
2011-07-22 06:03:18 +00:00
|
|
|
}
|
|
|
|
|
2015-10-20 13:23:58 +00:00
|
|
|
PCHGenerator::~PCHGenerator() {
|
|
|
|
}
|
2009-04-27 18:38:38 +00:00
|
|
|
|
2009-04-09 22:27:44 +00:00
|
|
|
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
|
2013-06-11 00:36:55 +00: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-09 22:27:44 +00:00
|
|
|
return;
|
2015-06-20 18:53:08 +00:00
|
|
|
|
2016-08-25 18:26:30 +00:00
|
|
|
Module *Module = nullptr;
|
2016-08-26 00:14:38 +00:00
|
|
|
if (PP.getLangOpts().isCompilingModule()) {
|
2016-08-25 18:26:30 +00:00
|
|
|
Module = PP.getHeaderSearchInfo().lookupModule(
|
2021-10-12 09:04:37 +02:00
|
|
|
PP.getLangOpts().CurrentModule, SourceLocation(),
|
|
|
|
/*AllowSearch*/ false);
|
2016-08-26 00:14:38 +00:00
|
|
|
if (!Module) {
|
|
|
|
assert(hasErrors && "emitting module but current module doesn't exist");
|
|
|
|
return;
|
|
|
|
}
|
2016-08-25 18:26:30 +00:00
|
|
|
}
|
|
|
|
|
2020-03-31 09:26:59 -07:00
|
|
|
// Errors that do not prevent the PCH from being written should not cause the
|
|
|
|
// overall compilation to fail either.
|
|
|
|
if (AllowASTWithErrors)
|
|
|
|
PP.getDiagnostics().getClient()->clear();
|
|
|
|
|
2015-06-20 18:53:08 +00:00
|
|
|
// Emit the PCH file to the Buffer.
|
2009-04-20 15:53:59 +00:00
|
|
|
assert(SemaPtr && "No Sema?");
|
2015-09-22 23:26:43 +00:00
|
|
|
Buffer->Signature =
|
2016-07-13 20:35:26 +00:00
|
|
|
Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
|
|
|
|
// For serialization we are lenient if the errors were
|
|
|
|
// only warn-as-error kind.
|
2019-03-12 18:38:04 +00:00
|
|
|
PP.getDiagnostics().hasUncompilableErrorOccurred(),
|
2022-08-03 15:24:25 -07:00
|
|
|
ShouldCacheASTInMemory);
|
2009-04-09 22:27:44 +00:00
|
|
|
|
2015-06-20 18:53:08 +00:00
|
|
|
Buffer->IsComplete = true;
|
2009-04-09 22:27:44 +00:00
|
|
|
}
|
|
|
|
|
2010-10-24 17:26:36 +00:00
|
|
|
ASTMutationListener *PCHGenerator::GetASTMutationListener() {
|
2011-08-25 22:35:51 +00:00
|
|
|
return &Writer;
|
2010-10-24 17:26:36 +00:00
|
|
|
}
|
|
|
|
|
2010-08-18 23:56:56 +00:00
|
|
|
ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
|
2010-07-30 00:29:29 +00:00
|
|
|
return &Writer;
|
|
|
|
}
|