https://github.com/jeaye created https://github.com/llvm/llvm-project/pull/157359
This is an updated version of @vgvassilev's PR from last year here: https://github.com/llvm/llvm-project/pull/94166 In short, it includes: 1. The fix for a blocking issue where `clang::Interpreter` cannot resolve symbols defined in a PCH 2. A test to prove this is working 3. A new hidden flag for `clang-repl` so that `llvm-lit` can match the host JIT triple between the PCH and `clang-repl`; previously, they may differ in some cases 4. Everything based on the latest LLVM main >From 73669c01825214c51d0ddb79dce6ec0235633d08 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev <v.g.vassi...@gmail.com> Date: Thu, 30 May 2024 05:05:41 +0000 Subject: [PATCH 1/7] [clang-repl] Teach clang-repl how to load PCHs. --- clang/include/clang/CodeGen/ModuleBuilder.h | 6 ++++++ clang/lib/CodeGen/BackendConsumer.h | 5 ----- clang/lib/CodeGen/CodeGenAction.cpp | 13 +++++++------ clang/lib/CodeGen/ModuleBuilder.cpp | 8 ++++++++ clang/lib/Interpreter/IncrementalParser.cpp | 4 ++++ clang/test/Interpreter/execute-pch.cpp | 14 ++++++++++++++ 6 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 clang/test/Interpreter/execute-pch.cpp diff --git a/clang/include/clang/CodeGen/ModuleBuilder.h b/clang/include/clang/CodeGen/ModuleBuilder.h index 59b9840d02e08..f1b8229edd362 100644 --- a/clang/include/clang/CodeGen/ModuleBuilder.h +++ b/clang/include/clang/CodeGen/ModuleBuilder.h @@ -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 diff --git a/clang/lib/CodeGen/BackendConsumer.h b/clang/lib/CodeGen/BackendConsumer.h index ad3adfca36785..b7bbb81074836 100644 --- a/clang/lib/CodeGen/BackendConsumer.h +++ b/clang/lib/CodeGen/BackendConsumer.h @@ -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; diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index dc54c97eeae8e..0c61e3c070dc8 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -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. @@ -240,10 +238,13 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) { Gen->HandleTranslationUnit(C); - if (TimerIsEnabled && !--LLVMIRGenerationRefCount) - LLVMIRGeneration.yieldTo(CI.getFrontendTimer()); - IRGenFinished = true; + + if (TimerIsEnabled) { + LLVMIRGenerationRefCount -= 1; + if (LLVMIRGenerationRefCount == 0) + LLVMIRGeneration.stopTimer(); + } } // Silently ignore if we weren't initialized for some reason. diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 8c1fee8c974f1..b3c5bfce51739 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -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); @@ -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; @@ -282,6 +288,8 @@ namespace { } void HandleTranslationUnit(ASTContext &Ctx) override { + IRGenFinished = true; + // Release the Builder when there is no error. if (!Diags.hasUnrecoverableErrorOccurred() && Builder) Builder->Release(); diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 32d1663fbe1a9..a5e2295c94905 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -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(); } diff --git a/clang/test/Interpreter/execute-pch.cpp b/clang/test/Interpreter/execute-pch.cpp new file mode 100644 index 0000000000000..30390d02f8c5c --- /dev/null +++ b/clang/test/Interpreter/execute-pch.cpp @@ -0,0 +1,14 @@ +// REQUIRES: host-supports-jit +// UNSUPPORTED: system-aix + +// RUN: rm -f %t.pch +// RUN: %clang_cc1 -fmax-type-align=16 -pic-level 2 -fdeprecated-macro -stack-protector 1 -fblocks -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -triple=%target_triple -DPCH -fincremental-extensions -emit-pch -x c++-header -o %t.pch %s +// RUN: clang-repl -Xcc -fgnuc-version=0 -Xcc -triple=%target_triple -Xcc -include-pch -Xcc %t.pch '#include "%s"' | FileCheck %s + +#ifdef PCH +int f_pch() { return 5; } +#endif // PCH + +extern "C" int printf(const char *, ...); +auto r1 = printf("f_pch = %d\n", f_pch()); +// CHECK: f_pch = 5 >From f7fb56f2ac8d52c0e6fa5c490dc5949f9641cdd9 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev <v.g.vassi...@gmail.com> Date: Mon, 3 Jun 2024 16:03:44 +0000 Subject: [PATCH 2/7] Address comments --- clang/lib/CodeGen/ModuleBuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index b3c5bfce51739..3eb0595864c6c 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -288,7 +288,6 @@ namespace { } void HandleTranslationUnit(ASTContext &Ctx) override { - IRGenFinished = true; // Release the Builder when there is no error. if (!Diags.hasUnrecoverableErrorOccurred() && Builder) @@ -300,8 +299,9 @@ namespace { if (Builder) Builder->clear(); M.reset(); - return; } + + IRGenFinished = true; } void AssignInheritanceModel(CXXRecordDecl *RD) override { >From 78270e348585ce4219a4987a461d2cfceb4f94e0 Mon Sep 17 00:00:00 2001 From: jeaye <cont...@jeaye.com> Date: Thu, 12 Jun 2025 17:29:20 -0700 Subject: [PATCH 3/7] Fix test runner issues --- clang/test/Interpreter/execute-pch.cpp | 21 +++++++++++++++------ clang/test/lit.cfg.py | 4 ++++ clang/tools/clang-repl/ClangRepl.cpp | 7 +++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/clang/test/Interpreter/execute-pch.cpp b/clang/test/Interpreter/execute-pch.cpp index 30390d02f8c5c..1ee8221463977 100644 --- a/clang/test/Interpreter/execute-pch.cpp +++ b/clang/test/Interpreter/execute-pch.cpp @@ -1,14 +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 -pic-level -Xclang 2 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -fPIC -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 -fPIC -Xcc -fblocks -Xcc -fskip-odr-check-in-gmf -Xcc -fmax-type-align=8 -Xcc -include-pch -Xcc %t/include.pch \ +// RUN: | FileCheck %s -// RUN: rm -f %t.pch -// RUN: %clang_cc1 -fmax-type-align=16 -pic-level 2 -fdeprecated-macro -stack-protector 1 -fblocks -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -triple=%target_triple -DPCH -fincremental-extensions -emit-pch -x c++-header -o %t.pch %s -// RUN: clang-repl -Xcc -fgnuc-version=0 -Xcc -triple=%target_triple -Xcc -include-pch -Xcc %t.pch '#include "%s"' | FileCheck %s +//--- include.hpp -#ifdef PCH int f_pch() { return 5; } -#endif // PCH + +//--- main.cpp extern "C" int printf(const char *, ...); -auto r1 = printf("f_pch = %d\n", f_pch()); +printf("f_pch = %d\n", f_pch()); + // CHECK: f_pch = 5 diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index d34319131ab6d..bec7f70517471 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -191,6 +191,10 @@ 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") diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index 1d508816d7047..c7879422cd7df 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -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]")); @@ -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; >From ebcc54adaa10762f8b8c727d80e51cd5837933f6 Mon Sep 17 00:00:00 2001 From: Kyle Cesare <kces...@gmail.com> Date: Sat, 6 Sep 2025 17:04:38 -0600 Subject: [PATCH 4/7] Fix failure to execute PTU when -include-pch is provided but no -include. --- clang/lib/Interpreter/Interpreter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 043e0c1e5754e..8944937f19115 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -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 >From 6d54e2572cb8dd5629543ec074d55afe23468805 Mon Sep 17 00:00:00 2001 From: jeaye <cont...@jeaye.com> Date: Sun, 7 Sep 2025 10:39:59 -0700 Subject: [PATCH 5/7] Clean up assertions --- clang/include/clang/AST/ASTContext.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 1c17333b722f8..d09c091570f3e 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1199,8 +1199,6 @@ class ASTContext : public RefCountedBase<ASTContext> { bool isInSameModule(const Module *M1, const Module *M2) const; TranslationUnitDecl *getTranslationUnitDecl() const { - assert(TUDecl->getMostRecentDecl() == TUDecl && - "The active TU is not current one!"); return TUDecl->getMostRecentDecl(); } void addTranslationUnitDecl() { >From e94e1b41b3eae54c0e4f12a957f01a126331498c Mon Sep 17 00:00:00 2001 From: jeaye <cont...@jeaye.com> Date: Sun, 7 Sep 2025 11:02:30 -0700 Subject: [PATCH 6/7] Add missing assertion back --- clang/include/clang/AST/ASTContext.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index d09c091570f3e..1c17333b722f8 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1199,6 +1199,8 @@ class ASTContext : public RefCountedBase<ASTContext> { bool isInSameModule(const Module *M1, const Module *M2) const; TranslationUnitDecl *getTranslationUnitDecl() const { + assert(TUDecl->getMostRecentDecl() == TUDecl && + "The active TU is not current one!"); return TUDecl->getMostRecentDecl(); } void addTranslationUnitDecl() { >From f145608b5aff9299f3e2c54c234d8274bd54d394 Mon Sep 17 00:00:00 2001 From: jeaye <cont...@jeaye.com> Date: Sun, 7 Sep 2025 11:52:27 -0700 Subject: [PATCH 7/7] Fix merge issues --- clang/lib/CodeGen/CodeGenAction.cpp | 2 -- clang/lib/Interpreter/IncrementalAction.cpp | 3 ++- clang/lib/Interpreter/IncrementalParser.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 0c61e3c070dc8..db38351118f26 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -238,8 +238,6 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) { Gen->HandleTranslationUnit(C); - IRGenFinished = true; - if (TimerIsEnabled) { LLVMIRGenerationRefCount -= 1; if (LLVMIRGenerationRefCount == 0) diff --git a/clang/lib/Interpreter/IncrementalAction.cpp b/clang/lib/Interpreter/IncrementalAction.cpp index 4d1bc4c59e851..3d489fce54bc6 100644 --- a/clang/lib/Interpreter/IncrementalAction.cpp +++ b/clang/lib/Interpreter/IncrementalAction.cpp @@ -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() && diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index a5e2295c94905..bf08911e23533 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -38,7 +38,7 @@ IncrementalParser::IncrementalParser(CompilerInstance &Instance, Consumer = &S.getASTConsumer(); P.reset(new Parser(S.getPreprocessor(), S, /*SkipBodies=*/false)); - if (ExternalASTSource *External = S->getASTContext().getExternalSource()) + if (ExternalASTSource *External = S.getASTContext().getExternalSource()) External->StartTranslationUnit(Consumer); P->Initialize(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits