https://github.com/aaronj0 updated https://github.com/llvm/llvm-project/pull/217870
>From 9cda50552d8ba5b51c36cb7bbc967fdb13cdebbd Mon Sep 17 00:00:00 2001 From: Aaron Jomy <[email protected]> Date: Wed, 19 Aug 2026 16:04:50 +0200 Subject: [PATCH 1/2] [clang-repl] Honor -emit-llvm to print incremental IR clang-repl cannot currently emit the LLVM IR it generates. The command-line emit actions are accepted but folded into `EmitLLVMOnlyAction` (producing no output), and `frontend::EmitLLVM` is rejected by the incremental frontend action when `-emit-llvm` is passed. This prevents users from inspecting IR produced per-input PTU. This patch teaches clang-repl to honor `-emit-llvm` by allowing the IncrementalAction to accept `frontend::EmitLLVM` , making the driver print each input's `llvm::Modul` to stdout instead of executing it, similar to `clang -emit-llvm`. This enables a lit-level test to FileCheck the IR produced by clang-repl and the effect of a statement on it. Exposing this functionality beyond the driver level to allow library consumers of `clang::Interpreter` to use it is a planned follow-up. --- clang/lib/Interpreter/IncrementalAction.cpp | 1 + clang/test/Interpreter/emit-llvm.cpp | 20 ++++++++++++++++++++ clang/tools/clang-repl/ClangRepl.cpp | 21 +++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 clang/test/Interpreter/emit-llvm.cpp diff --git a/clang/lib/Interpreter/IncrementalAction.cpp b/clang/lib/Interpreter/IncrementalAction.cpp index d22031c8fa893..85f00c36dd5aa 100644 --- a/clang/lib/Interpreter/IncrementalAction.cpp +++ b/clang/lib/Interpreter/IncrementalAction.cpp @@ -47,6 +47,7 @@ IncrementalAction::IncrementalAction(CompilerInstance &Instance, case frontend::EmitBC: case frontend::EmitObj: case frontend::PrintPreprocessedInput: + case frontend::EmitLLVM: case frontend::EmitLLVMOnly: Act.reset(new EmitLLVMOnlyAction(&LLVMCtx)); break; diff --git a/clang/test/Interpreter/emit-llvm.cpp b/clang/test/Interpreter/emit-llvm.cpp new file mode 100644 index 0000000000000..9ed8013c22d03 --- /dev/null +++ b/clang/test/Interpreter/emit-llvm.cpp @@ -0,0 +1,20 @@ +// REQUIRES: host-supports-jit +// +// -emit-llvm prints the IR of each input instead of running it. +// +// RUN: cat %s | clang-repl -Xcc -Xclang -Xcc -emit-llvm | FileCheck %s + +extern "C" int add(int a, int b) { return a + b; } +// CHECK: define {{.*}}i32 @add( +// CHECK: ret i32 + +extern "C" int answer = 42; +// CHECK: @answer = {{.*}}i32 42 + +extern "C" int neg(int a) { return -a; } +// CHECK: define {{.*}}i32 @neg( + +// Not run, so the value is not printed. +extern "C" int r = add(19, 23); +r +// CHECK-NOT: (int) 42 diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index c9873540a5d66..c8d705056e879 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/IncrementalExecutor.h" #include "clang/Interpreter/Interpreter.h" @@ -24,6 +25,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" +#include "llvm/IR/Module.h" #include "llvm/LineEditor/LineEditor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -342,6 +344,10 @@ int main(int argc, const char **argv) { if (CudaEnabled) DeviceCI->LoadRequestedPlugins(); + // '-emit-llvm' prints the IR of each input instead of executing it. + const bool EmitLLVMIR = + CI->getFrontendOpts().ProgramAction == clang::frontend::EmitLLVM; + std::unique_ptr<clang::Interpreter> Interp; if (CudaEnabled) { @@ -361,8 +367,19 @@ int main(int argc, const char **argv) { bool HasError = false; + auto ProcessInput = [&](llvm::StringRef Input) -> llvm::Error { + if (!EmitLLVMIR) + return Interp->ParseAndExecute(Input); + auto PTU = Interp->Parse(Input); + if (!PTU) + return PTU.takeError(); + if (PTU->TheModule) + PTU->TheModule->print(llvm::outs(), /*AAW=*/nullptr); + return llvm::Error::success(); + }; + for (const std::string &input : OptInputs) { - if (auto Err = Interp->ParseAndExecute(input)) { + if (auto Err = ProcessInput(input)) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; } @@ -413,7 +430,7 @@ int main(int argc, const char **argv) { Input), std::error_code()); llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); - } else if (auto Err = Interp->ParseAndExecute(Input)) { + } else if (auto Err = ProcessInput(Input)) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); } >From 49d310a2221e7e51080146497faed2d4e62a16fd Mon Sep 17 00:00:00 2001 From: Aaron Jomy <[email protected]> Date: Fri, 21 Aug 2026 16:55:09 +0200 Subject: [PATCH 2/2] [clang-repl] Move -emit-llvm printing into Interpreter::Parse --- clang/lib/Interpreter/Interpreter.cpp | 7 +++++++ clang/test/Interpreter/emit-llvm.cpp | 7 ++++--- clang/tools/clang-repl/ClangRepl.cpp | 21 ++------------------- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 0536fdcd548a2..c9b127a360e5d 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -31,6 +31,7 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/FrontendTool/Utils.h" @@ -568,6 +569,12 @@ Interpreter::Parse(llvm::StringRef Code) { PartialTranslationUnit &LastPTU = IncrParser->RegisterPTU(*TuOrErr); + // Under -emit-llvm, print the module IR. + if (InitPTUSize && LastPTU.TheModule && + getCompilerInstance()->getFrontendOpts().ProgramAction == + frontend::EmitLLVM) + LastPTU.TheModule->print(llvm::outs(), /*AAW=*/nullptr); + return LastPTU; } diff --git a/clang/test/Interpreter/emit-llvm.cpp b/clang/test/Interpreter/emit-llvm.cpp index 9ed8013c22d03..96f18a6d0d34d 100644 --- a/clang/test/Interpreter/emit-llvm.cpp +++ b/clang/test/Interpreter/emit-llvm.cpp @@ -1,6 +1,6 @@ // REQUIRES: host-supports-jit // -// -emit-llvm prints the IR of each input instead of running it. +// -emit-llvm prints the IR of each input before running them. // // RUN: cat %s | clang-repl -Xcc -Xclang -Xcc -emit-llvm | FileCheck %s @@ -14,7 +14,8 @@ extern "C" int answer = 42; extern "C" int neg(int a) { return -a; } // CHECK: define {{.*}}i32 @neg( -// Not run, so the value is not printed. extern "C" int r = add(19, 23); +// CHECK: @r = {{.*}}global i32 +// CHECK: call i32 @add( r -// CHECK-NOT: (int) 42 +// CHECK: (int) 42 diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index c8d705056e879..c9873540a5d66 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -15,7 +15,6 @@ #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendOptions.h" #include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/IncrementalExecutor.h" #include "clang/Interpreter/Interpreter.h" @@ -25,7 +24,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" -#include "llvm/IR/Module.h" #include "llvm/LineEditor/LineEditor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -344,10 +342,6 @@ int main(int argc, const char **argv) { if (CudaEnabled) DeviceCI->LoadRequestedPlugins(); - // '-emit-llvm' prints the IR of each input instead of executing it. - const bool EmitLLVMIR = - CI->getFrontendOpts().ProgramAction == clang::frontend::EmitLLVM; - std::unique_ptr<clang::Interpreter> Interp; if (CudaEnabled) { @@ -367,19 +361,8 @@ int main(int argc, const char **argv) { bool HasError = false; - auto ProcessInput = [&](llvm::StringRef Input) -> llvm::Error { - if (!EmitLLVMIR) - return Interp->ParseAndExecute(Input); - auto PTU = Interp->Parse(Input); - if (!PTU) - return PTU.takeError(); - if (PTU->TheModule) - PTU->TheModule->print(llvm::outs(), /*AAW=*/nullptr); - return llvm::Error::success(); - }; - for (const std::string &input : OptInputs) { - if (auto Err = ProcessInput(input)) { + if (auto Err = Interp->ParseAndExecute(input)) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; } @@ -430,7 +413,7 @@ int main(int argc, const char **argv) { Input), std::error_code()); llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); - } else if (auto Err = ProcessInput(Input)) { + } else if (auto Err = Interp->ParseAndExecute(Input)) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
