Skip to content
Merged
6 changes: 6 additions & 0 deletions clang/include/clang/CodeGen/ModuleBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ namespace CodeGen {
class CodeGenerator : public ASTConsumer {
virtual void anchor();

protected:
/// True if we've finished generating IR. This prevents us from generating
/// additional LLVM IR after emitting output in HandleTranslationUnit. This
/// can happen when Clang plugins trigger additional AST deserialization.
bool IRGenFinished = false;

public:
/// Return an opaque reference to the CodeGenModule object, which can
/// be used in various secondary APIs. It is valid as long as the
Expand Down
5 changes: 0 additions & 5 deletions clang/lib/CodeGen/BackendConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ class BackendConsumer : public ASTConsumer {
llvm::Timer LLVMIRGeneration;
unsigned LLVMIRGenerationRefCount = 0;

/// True if we've finished generating IR. This prevents us from generating
/// additional LLVM IR after emitting output in HandleTranslationUnit. This
/// can happen when Clang plugins trigger additional AST deserialization.
bool IRGenFinished = false;

bool TimerIsEnabled = false;

BackendAction Action;
Expand Down
6 changes: 1 addition & 5 deletions clang/lib/CodeGen/CodeGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,7 @@ void BackendConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
}

void BackendConsumer::HandleInterestingDecl(DeclGroupRef D) {
// Ignore interesting decls from the AST reader after IRGen is finished.
if (!IRGenFinished)
HandleTopLevelDecl(D);
HandleTopLevelDecl(D);
}

// Links each entry in LinkModules into our module. Returns true on error.
Expand Down Expand Up @@ -242,8 +240,6 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {

if (TimerIsEnabled && !--LLVMIRGenerationRefCount)
LLVMIRGeneration.yieldTo(CI.getFrontendTimer());

IRGenFinished = true;
}

// Silently ignore if we weren't initialized for some reason.
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/CodeGen/ModuleBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ namespace {
assert(!M && "Replacing existing Module?");
M.reset(new llvm::Module(ExpandModuleName(ModuleName, CodeGenOpts), C));

IRGenFinished = false;

std::unique_ptr<CodeGenModule> OldBuilder = std::move(Builder);

Initialize(*Ctx);
Expand Down Expand Up @@ -179,6 +181,10 @@ namespace {
}

bool HandleTopLevelDecl(DeclGroupRef DG) override {
// Ignore interesting decls from the AST reader after IRGen is finished.
if (IRGenFinished)
return true; // We can't CodeGen more but pass to other consumers.

// FIXME: Why not return false and abort parsing?
if (Diags.hasUnrecoverableErrorOccurred())
return true;
Expand Down Expand Up @@ -292,8 +298,9 @@ namespace {
if (Builder)
Builder->clear();
M.reset();
return;
}

IRGenFinished = true;
}

void AssignInheritanceModel(CXXRecordDecl *RD) override {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Interpreter/IncrementalAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ std::unique_ptr<llvm::Module> IncrementalAction::GenModule() {
// around we created an empty module to make CodeGen happy. We should make
// sure it always stays empty.
assert(((!CachedInCodeGenModule ||
!CI.getPreprocessorOpts().Includes.empty()) ||
!CI.getPreprocessorOpts().Includes.empty() ||
!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) ||
(CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ IncrementalParser::IncrementalParser(CompilerInstance &Instance,
llvm::ErrorAsOutParameter EAO(&Err);
Consumer = &S.getASTConsumer();
P.reset(new Parser(S.getPreprocessor(), S, /*SkipBodies=*/false));

if (ExternalASTSource *External = S.getASTContext().getExternalSource())
External->StartTranslationUnit(Consumer);

P->Initialize();
}

Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,10 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,

if (Act->getCodeGen()) {
Act->CacheCodeGenModule();
// The initial PTU is filled by `-include` or by CUDA includes
// automatically.
if (!CI->getPreprocessorOpts().Includes.empty()) {
// The initial PTU is filled by `-include`/`-include-pch` or by CUDA
// includes automatically.
if (!CI->getPreprocessorOpts().Includes.empty() ||
!CI->getPreprocessorOpts().ImplicitPCHInclude.empty()) {
// We can't really directly pass the CachedInCodeGenModule to the Jit
// because it will steal it, causing dangling references as explained in
// Interpreter::Execute
Expand Down
23 changes: 23 additions & 0 deletions clang/test/Interpreter/execute-pch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// REQUIRES: host-supports-jit
// UNSUPPORTED: system-aix
//
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: %clang -fmax-type-align=16 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -Xclang -fblocks -Xclang -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -target %host-jit-triple -Xclang -fblocks -Xclang -fmax-type-align=8 -Xclang -fincremental-extensions -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp
//
// RUN: cat %t/main.cpp \
// RUN: | clang-repl -Xcc -fgnuc-version=0 -Xcc -fno-stack-protector -Xcc -fwrapv -Xcc -fblocks -Xcc -fskip-odr-check-in-gmf -Xcc -fmax-type-align=8 -Xcc -include-pch -Xcc %t/include.pch \
// RUN: | FileCheck %s

//--- include.hpp

int f_pch() { return 5; }

//--- main.cpp

extern "C" int printf(const char *, ...);
printf("f_pch = %d\n", f_pch());

// CHECK: f_pch = 5
13 changes: 10 additions & 3 deletions clang/test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,16 @@ def have_host_out_of_process_jit_feature_support():

return False

def have_host_jit_feature_support(feature_name):

def run_clang_repl(args):
clang_repl_exe = lit.util.which("clang-repl", config.clang_tools_dir)

if not clang_repl_exe:
return False

try:
clang_repl_cmd = subprocess.Popen(
[clang_repl_exe, "--host-supports-" + feature_name], stdout=subprocess.PIPE
[clang_repl_exe, args], stdout=subprocess.PIPE
)
except OSError:
print("could not exec clang-repl")
Expand All @@ -157,7 +158,11 @@ def have_host_jit_feature_support(feature_name):
clang_repl_out = clang_repl_cmd.stdout.read().decode("ascii")
clang_repl_cmd.wait()

return "true" in clang_repl_out
return clang_repl_out


def have_host_jit_feature_support(feature_name):
return "true" in run_clang_repl("--host-supports-" + feature_name)

def have_host_clang_repl_cuda():
clang_repl_exe = lit.util.which('clang-repl', config.clang_tools_dir)
Expand Down Expand Up @@ -191,6 +196,8 @@ def have_host_clang_repl_cuda():

if have_host_clang_repl_cuda():
config.available_features.add('host-supports-cuda')
hosttriple = run_clang_repl("--host-jit-triple")
config.substitutions.append(("%host-jit-triple", hosttriple.strip()))

if have_host_out_of_process_jit_feature_support():
config.available_features.add("host-supports-out-of-process-jit")
Expand Down
7 changes: 7 additions & 0 deletions clang/tools/clang-repl/ClangRepl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ static llvm::cl::list<std::string>
llvm::cl::CommaSeparated);
static llvm::cl::opt<bool> OptHostSupportsJit("host-supports-jit",
llvm::cl::Hidden);
static llvm::cl::opt<bool> OptHostJitTriple("host-jit-triple",
llvm::cl::Hidden);
static llvm::cl::list<std::string> OptInputs(llvm::cl::Positional,
llvm::cl::desc("[code to run]"));

Expand Down Expand Up @@ -279,6 +281,11 @@ int main(int argc, const char **argv) {
llvm::outs() << "false\n";
}
return 0;
} else if (OptHostJitTriple) {
auto J = ExitOnErr(llvm::orc::LLJITBuilder().create());
auto T = J->getTargetTriple();
llvm::outs() << T.normalize() << '\n';
return 0;
}

clang::IncrementalCompilerBuilder CB;
Expand Down