[clang] [Clang-Repl] Add Lambda Support, PID Retrieval, and Dynamic liborc_rt Path in Clang-Repl (PR #155140)
Abhinav Kumar via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 26 08:09:13 PDT 2025
https://github.com/kr-2003 updated https://github.com/llvm/llvm-project/pull/155140
>From 79849c3ba76ebf66fd7856fa92cd98af56ac49a6 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Tue, 1 Jul 2025 18:55:21 +0530
Subject: [PATCH 01/20] pipes for redirection in oop jit
---
.../clang/Interpreter/RemoteJITUtils.h | 12 +-
clang/lib/Interpreter/RemoteJITUtils.cpp | 27 +++-
clang/unittests/Interpreter/CMakeLists.txt | 7 ++
.../unittests/Interpreter/InterpreterTest.cpp | 117 ++++++++++++++++++
4 files changed, 161 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Interpreter/RemoteJITUtils.h b/clang/include/clang/Interpreter/RemoteJITUtils.h
index 8705a3b1f669d..bc71232a5cad8 100644
--- a/clang/include/clang/Interpreter/RemoteJITUtils.h
+++ b/clang/include/clang/Interpreter/RemoteJITUtils.h
@@ -26,7 +26,8 @@
llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString);
+ llvm::StringRef SlabAllocateSizeString,
+ std::function<void()> CustomizeFork = nullptr);
/// Create a JITLinkExecutor that connects to the given network address
/// through a TCP socket. A valid NetworkAddress provides hostname and port,
@@ -35,4 +36,13 @@ llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString);
+#ifdef LLVM_ON_UNIX
+/// Returns PID of last launched executor.
+pid_t getLastLaunchedExecutorPID();
+
+/// Returns PID of nth launched executor.
+/// 1-based indexing.
+pid_t getNthLaunchedExecutorPID(int n);
+#endif
+
#endif // LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H
diff --git a/clang/lib/Interpreter/RemoteJITUtils.cpp b/clang/lib/Interpreter/RemoteJITUtils.cpp
index c0e663b764785..8f21ce7f936a4 100644
--- a/clang/lib/Interpreter/RemoteJITUtils.cpp
+++ b/clang/lib/Interpreter/RemoteJITUtils.cpp
@@ -33,6 +33,10 @@
using namespace llvm;
using namespace llvm::orc;
+#if LLVM_ON_UNIX
+static std::vector<pid_t> LaunchedExecutorPID;
+#endif
+
Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
SizeString = SizeString.trim();
@@ -91,7 +95,8 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
Expected<std::unique_ptr<SimpleRemoteEPC>>
launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString) {
+ llvm::StringRef SlabAllocateSizeString,
+ std::function<void()> CustomizeFork) {
#ifndef LLVM_ON_UNIX
// FIXME: Add support for Windows.
return make_error<StringError>("-" + ExecutablePath +
@@ -134,6 +139,9 @@ launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
close(ToExecutor[WriteEnd]);
close(FromExecutor[ReadEnd]);
+ if (CustomizeFork)
+ CustomizeFork();
+
// Execute the child process.
std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
{
@@ -155,6 +163,8 @@ launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
<< ExecutorPath.get() << "\"\n";
exit(1);
}
+ } else {
+ LaunchedExecutorPID.push_back(ChildPID);
}
// else we're the parent...
@@ -265,3 +275,18 @@ connectTCPSocket(StringRef NetworkAddress, bool UseSharedMemory,
std::move(S), *SockFD, *SockFD);
#endif
}
+
+#if LLVM_ON_UNIX
+
+pid_t getLastLaunchedExecutorPID() {
+ if (!LaunchedExecutorPID.size())
+ return -1;
+ return LaunchedExecutorPID.back();
+}
+
+pid_t getNthLaunchedExecutorPID(int n) {
+ if (n - 1 < 0 || n - 1 >= static_cast<int>(LaunchedExecutorPID.size()))
+ return -1;
+ return LaunchedExecutorPID.at(n - 1);
+}
+#endif
\ No newline at end of file
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 1dda9024075a1..388ebdce32dc1 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -26,6 +26,13 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
TargetParser
)
+if(TARGET llvm-jitlink-executor AND TARGET compiler-rt)
+ add_dependencies(ClangReplInterpreterTests
+ llvm-jitlink-executor
+ compiler-rt
+ )
+endif()
+
# Exceptions on Windows are not yet supported.
if(NOT WIN32)
add_subdirectory(ExceptionTests)
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index b97f5ae17c9f0..f451d2f17351c 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -15,23 +15,36 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Mangle.h"
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/RemoteJITUtils.h"
#include "clang/Interpreter/Value.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/Host.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace clang;
+llvm::ExitOnError ExitOnError;
+
int Global = 42;
// JIT reports symbol not found on Windows without the visibility attribute.
REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+#ifdef _WIN32
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#endif
+
namespace {
class InterpreterTest : public InterpreterTestBase {
@@ -52,6 +65,93 @@ createInterpreter(const Args &ExtraArgs = {},
return cantFail(clang::Interpreter::create(std::move(CI)));
}
+static std::string getExecutorPath() {
+ llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(
+ nullptr, reinterpret_cast<void *>(&getExecutorPath)));
+ llvm::sys::path::remove_filename(ExecutorPath);
+
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "Interpreter"
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "unittests"
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "clang"
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "tools"
+
+ llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
+ return ExecutorPath.str().str();
+}
+
+static std::string getOrcRuntimePath() {
+ llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
+ nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
+
+ llvm::sys::path::remove_filename(RuntimePath);
+
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "Interpreter"
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "unittests"
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "clang"
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "tools"
+
+ llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
+ CLANG_VERSION_MAJOR_STRING, "lib");
+
+ llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
+ if (SystemTriple.isOSBinFormatMachO()) {
+ llvm::sys::path::append(RuntimePath, "darwin", "liborc_rt_osx.a");
+ } else if (SystemTriple.isOSBinFormatELF()) {
+ llvm::sys::path::append(RuntimePath, "x86_64-unknown-linux-gnu",
+ "liborc_rt.a");
+ }
+
+ return RuntimePath.str().str();
+}
+
+static std::unique_ptr<Interpreter>
+createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
+ DiagnosticConsumer *Client = nullptr) {
+ Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
+ llvm::append_range(ClangArgs, ExtraArgs);
+ auto CB = clang::IncrementalCompilerBuilder();
+ CB.SetCompilerArgs(ClangArgs);
+ auto CI = cantFail(CB.CreateCpp());
+ if (Client)
+ CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
+
+ std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+
+ llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
+
+ if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) {
+ std::string OOPExecutor = getExecutorPath();
+ std::string OrcRuntimePath = getOrcRuntimePath();
+ bool UseSharedMemory = false;
+ std::string SlabAllocateSizeString = "";
+ std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
+ EPC = ExitOnError(launchExecutor(OOPExecutor, UseSharedMemory,
+ SlabAllocateSizeString,
+ [=] { // Lambda defined inline
+ auto redirect = [](int from, int to) {
+ if (from != to) {
+ dup2(from, to);
+ close(from);
+ }
+ };
+
+ redirect(0, STDIN_FILENO);
+ redirect(1, STDOUT_FILENO);
+ redirect(2, STDERR_FILENO);
+
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ setvbuf(stderr, nullptr, _IONBF, 0);
+ }));
+ if (EPC) {
+ CB.SetTargetTriple(EPC->getTargetTriple().getTriple());
+ JB = ExitOnError(clang::Interpreter::createLLJITBuilder(std::move(EPC),
+ OrcRuntimePath));
+ }
+ }
+
+ return cantFail(clang::Interpreter::create(std::move(CI), std::move(JB)));
+}
+
static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
}
@@ -68,6 +168,23 @@ TEST_F(InterpreterTest, Sanity) {
EXPECT_EQ(1U, DeclsSize(R2.TUPart));
}
+TEST_F(InterpreterTest, SanityWithRemoteExecution) {
+ if (!HostSupportsJIT())
+ GTEST_SKIP();
+
+ std::string OrcRuntimePath = getOrcRuntimePath();
+
+ std::unique_ptr<Interpreter> Interp = createInterpreterWithRemoteExecution();
+
+ using PTU = PartialTranslationUnit;
+
+ PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));
+ EXPECT_EQ(2U, DeclsSize(R1.TUPart));
+
+ PTU &R2(cantFail(Interp->Parse("int i;")));
+ EXPECT_EQ(1U, DeclsSize(R2.TUPart));
+}
+
static std::string DeclToString(Decl *D) {
return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString();
}
>From 52b09029c57b1db1c1ab44b206afe0e8fc574f8a Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Tue, 29 Jul 2025 13:40:27 +0530
Subject: [PATCH 02/20] refactoring
---
clang/unittests/Interpreter/InterpreterTest.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 15f8e32561ac8..286126133af4f 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -174,8 +174,6 @@ TEST_F(InterpreterTest, SanityWithRemoteExecution) {
if (!HostSupportsJIT())
GTEST_SKIP();
- std::string OrcRuntimePath = getOrcRuntimePath();
-
std::unique_ptr<Interpreter> Interp = createInterpreterWithRemoteExecution();
using PTU = PartialTranslationUnit;
>From 3b4fcadd97a2871579780b6f72e7728d8b15bc0b Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Tue, 29 Jul 2025 13:51:56 +0530
Subject: [PATCH 03/20] refactoring
---
clang/unittests/Interpreter/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 388ebdce32dc1..a2d52ba76021c 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -26,7 +26,7 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
TargetParser
)
-if(TARGET llvm-jitlink-executor AND TARGET compiler-rt)
+if(NOT WIN32)
add_dependencies(ClangReplInterpreterTests
llvm-jitlink-executor
compiler-rt
>From e174e9871d96744e5678b8fb36ca6da7399e68a8 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Tue, 29 Jul 2025 19:54:06 +0530
Subject: [PATCH 04/20] commenting & refactoring
---
clang/lib/Interpreter/RemoteJITUtils.cpp | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Interpreter/RemoteJITUtils.cpp b/clang/lib/Interpreter/RemoteJITUtils.cpp
index 8f21ce7f936a4..c100f46931b6d 100644
--- a/clang/lib/Interpreter/RemoteJITUtils.cpp
+++ b/clang/lib/Interpreter/RemoteJITUtils.cpp
@@ -93,6 +93,10 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
SlabSize, SREPC, SAs);
}
+// Launches an out-of-process executor for remote JIT. The calling program can
+// provide a CustomizeFork callback, which allows it to run custom code in the
+// child process before exec. This enables sending custom setup or code to be
+// executed in the child (out-of-process) executor.
Expected<std::unique_ptr<SimpleRemoteEPC>>
launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString,
@@ -163,11 +167,11 @@ launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
<< ExecutorPath.get() << "\"\n";
exit(1);
}
- } else {
- LaunchedExecutorPID.push_back(ChildPID);
}
// else we're the parent...
+ LaunchedExecutorPID.push_back(ChildPID);
+
// Close the child ends of the pipes
close(ToExecutor[ReadEnd]);
close(FromExecutor[WriteEnd]);
>From b744a9f9c7ca3f3df658b4cda95c9efe57789562 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 06:45:53 +0530
Subject: [PATCH 05/20] compiler-rt conditional addition
---
clang/unittests/Interpreter/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index a2d52ba76021c..1ba9cdc130be9 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -26,7 +26,7 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
TargetParser
)
-if(NOT WIN32)
+if(NOT WIN32 AND TARGET compiler-rt)
add_dependencies(ClangReplInterpreterTests
llvm-jitlink-executor
compiler-rt
>From 2cf71ede705a4d30e9e7019ace834d3bff7316bb Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 06:52:56 +0530
Subject: [PATCH 06/20] removed compiler-rt dep
---
clang/unittests/Interpreter/CMakeLists.txt | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 1ba9cdc130be9..654d03f336a0c 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -26,10 +26,9 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
TargetParser
)
-if(NOT WIN32 AND TARGET compiler-rt)
+if(NOT WIN32)
add_dependencies(ClangReplInterpreterTests
llvm-jitlink-executor
- compiler-rt
)
endif()
>From 41f8e54d24378718c1448a91350498338f76d03e Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 07:19:19 +0530
Subject: [PATCH 07/20] separate file for oop tests
---
clang/unittests/Interpreter/CMakeLists.txt | 12 ++
.../unittests/Interpreter/InterpreterTest.cpp | 102 -----------
.../Interpreter/InterpreterTestOOP.cpp | 163 ++++++++++++++++++
3 files changed, 175 insertions(+), 102 deletions(-)
create mode 100644 clang/unittests/Interpreter/InterpreterTestOOP.cpp
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 654d03f336a0c..ccd4ffb847c4b 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -5,6 +5,7 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
InterpreterExtensionsTest.cpp
CodeCompletionTest.cpp
+ PARTIAL_SOURCES_INTENDED
EXPORT_SYMBOLS
CLANG_LIBS
@@ -32,6 +33,17 @@ if(NOT WIN32)
)
endif()
+if(TARGET compiler-rt)
+ list(APPEND CLANG_REPL_TEST_SOURCES
+ OOPJITInterpreterTest.cpp
+ )
+ add_dependencies(ClangReplInterpreterTests compiler-rt)
+ message(STATUS "Compiler-RT found, enabling OOP JIT tests")
+ set(CLANG_HAS_COMPILER_RT TRUE)
+else()
+ set(CLANG_HAS_COMPILER_RT FALSE)
+endif()
+
# Exceptions on Windows are not yet supported.
if(NOT WIN32)
add_subdirectory(ExceptionTests)
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 286126133af4f..248ac112e8a7f 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -67,93 +67,6 @@ createInterpreter(const Args &ExtraArgs = {},
return cantFail(clang::Interpreter::create(std::move(CI)));
}
-static std::string getExecutorPath() {
- llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(
- nullptr, reinterpret_cast<void *>(&getExecutorPath)));
- llvm::sys::path::remove_filename(ExecutorPath);
-
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "Interpreter"
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "unittests"
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "clang"
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "tools"
-
- llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
- return ExecutorPath.str().str();
-}
-
-static std::string getOrcRuntimePath() {
- llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
- nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
-
- llvm::sys::path::remove_filename(RuntimePath);
-
- llvm::sys::path::remove_filename(RuntimePath); // Remove "Interpreter"
- llvm::sys::path::remove_filename(RuntimePath); // Remove "unittests"
- llvm::sys::path::remove_filename(RuntimePath); // Remove "clang"
- llvm::sys::path::remove_filename(RuntimePath); // Remove "tools"
-
- llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
- CLANG_VERSION_MAJOR_STRING, "lib");
-
- llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
- if (SystemTriple.isOSBinFormatMachO()) {
- llvm::sys::path::append(RuntimePath, "darwin", "liborc_rt_osx.a");
- } else if (SystemTriple.isOSBinFormatELF()) {
- llvm::sys::path::append(RuntimePath, "x86_64-unknown-linux-gnu",
- "liborc_rt.a");
- }
-
- return RuntimePath.str().str();
-}
-
-static std::unique_ptr<Interpreter>
-createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
- DiagnosticConsumer *Client = nullptr) {
- Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
- llvm::append_range(ClangArgs, ExtraArgs);
- auto CB = clang::IncrementalCompilerBuilder();
- CB.SetCompilerArgs(ClangArgs);
- auto CI = cantFail(CB.CreateCpp());
- if (Client)
- CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
-
- std::unique_ptr<llvm::orc::LLJITBuilder> JB;
-
- llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
-
- if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) {
- std::string OOPExecutor = getExecutorPath();
- std::string OrcRuntimePath = getOrcRuntimePath();
- bool UseSharedMemory = false;
- std::string SlabAllocateSizeString = "";
- std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
- EPC = ExitOnError(launchExecutor(OOPExecutor, UseSharedMemory,
- SlabAllocateSizeString,
- [=] { // Lambda defined inline
- auto redirect = [](int from, int to) {
- if (from != to) {
- dup2(from, to);
- close(from);
- }
- };
-
- redirect(0, STDIN_FILENO);
- redirect(1, STDOUT_FILENO);
- redirect(2, STDERR_FILENO);
-
- setvbuf(stdout, nullptr, _IONBF, 0);
- setvbuf(stderr, nullptr, _IONBF, 0);
- }));
- if (EPC) {
- CB.SetTargetTriple(EPC->getTargetTriple().getTriple());
- JB = ExitOnError(clang::Interpreter::createLLJITBuilder(std::move(EPC),
- OrcRuntimePath));
- }
- }
-
- return cantFail(clang::Interpreter::create(std::move(CI), std::move(JB)));
-}
-
static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
}
@@ -170,21 +83,6 @@ TEST_F(InterpreterTest, Sanity) {
EXPECT_EQ(1U, DeclsSize(R2.TUPart));
}
-TEST_F(InterpreterTest, SanityWithRemoteExecution) {
- if (!HostSupportsJIT())
- GTEST_SKIP();
-
- std::unique_ptr<Interpreter> Interp = createInterpreterWithRemoteExecution();
-
- using PTU = PartialTranslationUnit;
-
- PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));
- EXPECT_EQ(2U, DeclsSize(R1.TUPart));
-
- PTU &R2(cantFail(Interp->Parse("int i;")));
- EXPECT_EQ(1U, DeclsSize(R2.TUPart));
-}
-
static std::string DeclToString(Decl *D) {
return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString();
}
diff --git a/clang/unittests/Interpreter/InterpreterTestOOP.cpp b/clang/unittests/Interpreter/InterpreterTestOOP.cpp
new file mode 100644
index 0000000000000..d0ee3a6fc6ebf
--- /dev/null
+++ b/clang/unittests/Interpreter/InterpreterTestOOP.cpp
@@ -0,0 +1,163 @@
+//===- unittests/Interpreter/InterpreterTestOOP.cpp --- Interpreter tests when Out-of-Process ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for Clang's Interpreter library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef CLANG_HAS_COMPILER_RT
+
+#include "InterpreterTestFixture.h"
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Mangle.h"
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/RemoteJITUtils.h"
+#include "clang/Interpreter/Value.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/Host.h"
+
+#include "llvm/TargetParser/Host.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+
+llvm::ExitOnError ExitOnError;
+
+#ifdef _WIN32
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#endif
+
+namespace {
+
+class InterpreterTest : public InterpreterTestBase {
+ // TODO: Collect common variables and utility functions here
+};
+
+using Args = std::vector<const char *>;
+
+static std::string getExecutorPath() {
+ llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(
+ nullptr, reinterpret_cast<void *>(&getExecutorPath)));
+ llvm::sys::path::remove_filename(ExecutorPath);
+
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "Interpreter"
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "unittests"
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "clang"
+ llvm::sys::path::remove_filename(ExecutorPath); // Remove "tools"
+
+ llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
+ return ExecutorPath.str().str();
+}
+
+static std::string getOrcRuntimePath() {
+ llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
+ nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
+
+ llvm::sys::path::remove_filename(RuntimePath);
+
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "Interpreter"
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "unittests"
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "clang"
+ llvm::sys::path::remove_filename(RuntimePath); // Remove "tools"
+
+ llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
+ CLANG_VERSION_MAJOR_STRING, "lib");
+
+ llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
+ if (SystemTriple.isOSBinFormatMachO()) {
+ llvm::sys::path::append(RuntimePath, "darwin", "liborc_rt_osx.a");
+ } else if (SystemTriple.isOSBinFormatELF()) {
+ llvm::sys::path::append(RuntimePath, "x86_64-unknown-linux-gnu",
+ "liborc_rt.a");
+ }
+
+ return RuntimePath.str().str();
+}
+
+static std::unique_ptr<Interpreter>
+createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
+ DiagnosticConsumer *Client = nullptr) {
+ Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
+ llvm::append_range(ClangArgs, ExtraArgs);
+ auto CB = clang::IncrementalCompilerBuilder();
+ CB.SetCompilerArgs(ClangArgs);
+ auto CI = cantFail(CB.CreateCpp());
+ if (Client)
+ CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
+
+ std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+
+ llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
+
+ if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) {
+ std::string OOPExecutor = getExecutorPath();
+ std::string OrcRuntimePath = getOrcRuntimePath();
+ bool UseSharedMemory = false;
+ std::string SlabAllocateSizeString = "";
+ std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
+ EPC = ExitOnError(launchExecutor(OOPExecutor, UseSharedMemory,
+ SlabAllocateSizeString,
+ [=] { // Lambda defined inline
+ auto redirect = [](int from, int to) {
+ if (from != to) {
+ dup2(from, to);
+ close(from);
+ }
+ };
+
+ redirect(0, STDIN_FILENO);
+ redirect(1, STDOUT_FILENO);
+ redirect(2, STDERR_FILENO);
+
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ setvbuf(stderr, nullptr, _IONBF, 0);
+ }));
+ if (EPC) {
+ CB.SetTargetTriple(EPC->getTargetTriple().getTriple());
+ JB = ExitOnError(clang::Interpreter::createLLJITBuilder(std::move(EPC),
+ OrcRuntimePath));
+ }
+ }
+
+ return cantFail(clang::Interpreter::create(std::move(CI), std::move(JB)));
+}
+
+static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
+ return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
+}
+
+TEST_F(InterpreterTest, SanityWithRemoteExecution) {
+ if (!HostSupportsJIT())
+ GTEST_SKIP();
+
+ std::unique_ptr<Interpreter> Interp = createInterpreterWithRemoteExecution();
+
+ using PTU = PartialTranslationUnit;
+
+ PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));
+ EXPECT_EQ(2U, DeclsSize(R1.TUPart));
+
+ PTU &R2(cantFail(Interp->Parse("int i;")));
+ EXPECT_EQ(1U, DeclsSize(R2.TUPart));
+}
+
+} // end anonymous namespace
+
+#endif // CLANG_HAS_COMPILER_RT
>From 4f1d203df9aef48d8a393321ee0f49e356812c7a Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 07:43:40 +0530
Subject: [PATCH 08/20] separate file for oop tests
---
clang/unittests/Interpreter/CMakeLists.txt | 13 +++++--------
clang/unittests/Interpreter/InterpreterTestOOP.cpp | 3 ++-
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index ccd4ffb847c4b..f678b9d91f86c 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -27,17 +27,14 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
TargetParser
)
-if(NOT WIN32)
- add_dependencies(ClangReplInterpreterTests
- llvm-jitlink-executor
- )
-endif()
-
if(TARGET compiler-rt)
list(APPEND CLANG_REPL_TEST_SOURCES
- OOPJITInterpreterTest.cpp
+ InterpreterTestOOP.cpp
+ )
+ add_dependencies(ClangReplInterpreterTests
+ llvm-jitlink-executor
+ compiler-rt
)
- add_dependencies(ClangReplInterpreterTests compiler-rt)
message(STATUS "Compiler-RT found, enabling OOP JIT tests")
set(CLANG_HAS_COMPILER_RT TRUE)
else()
diff --git a/clang/unittests/Interpreter/InterpreterTestOOP.cpp b/clang/unittests/Interpreter/InterpreterTestOOP.cpp
index d0ee3a6fc6ebf..215912d39f03f 100644
--- a/clang/unittests/Interpreter/InterpreterTestOOP.cpp
+++ b/clang/unittests/Interpreter/InterpreterTestOOP.cpp
@@ -1,4 +1,5 @@
-//===- unittests/Interpreter/InterpreterTestOOP.cpp --- Interpreter tests when Out-of-Process ----===//
+//===- unittests/Interpreter/InterpreterTestOOP.cpp --- Interpreter tests when
+//Out-of-Process ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From a6a43698fd529527eb830be94bf91dc0ee3a7ec7 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 07:48:07 +0530
Subject: [PATCH 09/20] separate file for oop tests
---
clang/unittests/Interpreter/InterpreterTestOOP.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Interpreter/InterpreterTestOOP.cpp b/clang/unittests/Interpreter/InterpreterTestOOP.cpp
index 215912d39f03f..929bf7e669145 100644
--- a/clang/unittests/Interpreter/InterpreterTestOOP.cpp
+++ b/clang/unittests/Interpreter/InterpreterTestOOP.cpp
@@ -1,5 +1,5 @@
//===- unittests/Interpreter/InterpreterTestOOP.cpp --- Interpreter tests when
-//Out-of-Process ----===//
+// Out-of-Process ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 63de88621311ae3b066b76231c6ba9c300277edb Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 16:15:42 +0530
Subject: [PATCH 10/20] test file rename
---
clang/unittests/Interpreter/CMakeLists.txt | 2 +-
...{InterpreterTestOOP.cpp => OutOfProcessInterpreterTests.cpp} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename clang/unittests/Interpreter/{InterpreterTestOOP.cpp => OutOfProcessInterpreterTests.cpp} (100%)
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index f678b9d91f86c..2ac257597cfed 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -29,7 +29,7 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
if(TARGET compiler-rt)
list(APPEND CLANG_REPL_TEST_SOURCES
- InterpreterTestOOP.cpp
+ OutOfProcessInterpreterTests.cpp
)
add_dependencies(ClangReplInterpreterTests
llvm-jitlink-executor
diff --git a/clang/unittests/Interpreter/InterpreterTestOOP.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
similarity index 100%
rename from clang/unittests/Interpreter/InterpreterTestOOP.cpp
rename to clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
>From c24e84e3833ac235af58598ef58a73add90445ed Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 16:16:13 +0530
Subject: [PATCH 11/20] test file rename
---
clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 929bf7e669145..0a74a95fd4e2e 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -1,4 +1,4 @@
-//===- unittests/Interpreter/InterpreterTestOOP.cpp --- Interpreter tests when
+//===- unittests/Interpreter/OutOfProcessInterpreterTest.cpp --- Interpreter tests when
// Out-of-Process ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>From b114bb8853eec9e04836fd92551bca61a9a6ffa1 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 1 Aug 2025 16:19:56 +0530
Subject: [PATCH 12/20] test file rename
---
clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 0a74a95fd4e2e..eb871ffec6454 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -1,5 +1,5 @@
-//===- unittests/Interpreter/OutOfProcessInterpreterTest.cpp --- Interpreter tests when
-// Out-of-Process ----===//
+//===- unittests/Interpreter/OutOfProcessInterpreterTest.cpp --- Interpreter
+// tests when Out-of-Process ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 850b95322ec5dcbedecf829939d48b29fdb26915 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 3 Aug 2025 12:13:06 +0530
Subject: [PATCH 13/20] resolving comments & InterpreterRemoteTest
---
clang/unittests/Interpreter/CMakeLists.txt | 21 ++++++++++++-------
.../unittests/Interpreter/InterpreterTest.cpp | 2 --
.../OutOfProcessInterpreterTests.cpp | 8 ++-----
3 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 2ac257597cfed..24f65cab95d7a 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -1,9 +1,20 @@
-add_distinct_clang_unittest(ClangReplInterpreterTests
+set(CLANG_REPL_TEST_SOURCES
IncrementalCompilerBuilderTest.cpp
IncrementalProcessingTest.cpp
InterpreterTest.cpp
InterpreterExtensionsTest.cpp
CodeCompletionTest.cpp
+)
+
+if(TARGET compiler-rt)
+ list(APPEND CLANG_REPL_TEST_SOURCES
+ OutOfProcessInterpreterTests.cpp
+ )
+ message(STATUS "Compiler-RT found, enabling out of process JIT tests")
+endif()
+
+add_distinct_clang_unittest(ClangReplInterpreterTests
+ ${CLANG_REPL_TEST_SOURCES}
PARTIAL_SOURCES_INTENDED
EXPORT_SYMBOLS
@@ -28,17 +39,11 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
)
if(TARGET compiler-rt)
- list(APPEND CLANG_REPL_TEST_SOURCES
- OutOfProcessInterpreterTests.cpp
- )
add_dependencies(ClangReplInterpreterTests
llvm-jitlink-executor
compiler-rt
)
- message(STATUS "Compiler-RT found, enabling OOP JIT tests")
- set(CLANG_HAS_COMPILER_RT TRUE)
-else()
- set(CLANG_HAS_COMPILER_RT FALSE)
+ message(STATUS "Adding dependency on compiler-rt for out of process JIT tests")
endif()
# Exceptions on Windows are not yet supported.
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 248ac112e8a7f..5d49089dada87 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -34,8 +34,6 @@
using namespace clang;
-llvm::ExitOnError ExitOnError;
-
int Global = 42;
// JIT reports symbol not found on Windows without the visibility attribute.
REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index eb871ffec6454..0ac5fb09f5daa 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#ifdef CLANG_HAS_COMPILER_RT
-
#include "InterpreterTestFixture.h"
#include "clang/AST/Decl.h"
@@ -47,7 +45,7 @@ llvm::ExitOnError ExitOnError;
namespace {
-class InterpreterTest : public InterpreterTestBase {
+class InterpreterRemoteTest : public InterpreterTestBase {
// TODO: Collect common variables and utility functions here
};
@@ -144,7 +142,7 @@ static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
}
-TEST_F(InterpreterTest, SanityWithRemoteExecution) {
+TEST_F(InterpreterRemoteTest, SanityWithRemoteExecution) {
if (!HostSupportsJIT())
GTEST_SKIP();
@@ -160,5 +158,3 @@ TEST_F(InterpreterTest, SanityWithRemoteExecution) {
}
} // end anonymous namespace
-
-#endif // CLANG_HAS_COMPILER_RT
>From 956f3939f94648b9e312f22a8832422643df347b Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 3 Aug 2025 19:43:58 +0530
Subject: [PATCH 14/20] resolving comments
---
.../OutOfProcessInterpreterTests.cpp | 22 ++++++-------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 0ac5fb09f5daa..d918999e672d3 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -51,16 +51,15 @@ class InterpreterRemoteTest : public InterpreterTestBase {
using Args = std::vector<const char *>;
+void removeFilename(int count, llvm::SmallString<256> &Path) {
+ for (int i = 0; i < count; ++i)
+ llvm::sys::path::remove_filename(Path);
+}
+
static std::string getExecutorPath() {
llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(
nullptr, reinterpret_cast<void *>(&getExecutorPath)));
- llvm::sys::path::remove_filename(ExecutorPath);
-
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "Interpreter"
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "unittests"
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "clang"
- llvm::sys::path::remove_filename(ExecutorPath); // Remove "tools"
-
+ removeFilename(5, ExecutorPath);
llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
return ExecutorPath.str().str();
}
@@ -68,14 +67,7 @@ static std::string getExecutorPath() {
static std::string getOrcRuntimePath() {
llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
-
- llvm::sys::path::remove_filename(RuntimePath);
-
- llvm::sys::path::remove_filename(RuntimePath); // Remove "Interpreter"
- llvm::sys::path::remove_filename(RuntimePath); // Remove "unittests"
- llvm::sys::path::remove_filename(RuntimePath); // Remove "clang"
- llvm::sys::path::remove_filename(RuntimePath); // Remove "tools"
-
+ removeFilename(5, RuntimePath);
llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
CLANG_VERSION_MAJOR_STRING, "lib");
>From 14e5afd89e66a8217e47da4cdb8cb73eec712921 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 4 Aug 2025 19:41:01 +0530
Subject: [PATCH 15/20] resolving comments
---
.../Interpreter/OutOfProcessInterpreterTests.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index d918999e672d3..bde175180bb47 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -51,15 +51,15 @@ class InterpreterRemoteTest : public InterpreterTestBase {
using Args = std::vector<const char *>;
-void removeFilename(int count, llvm::SmallString<256> &Path) {
- for (int i = 0; i < count; ++i)
+static void removePathComponent(unsigned N, llvm::SmallString<256> &Path) {
+ for (int i = 0; i < N; ++i)
llvm::sys::path::remove_filename(Path);
}
static std::string getExecutorPath() {
llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(
nullptr, reinterpret_cast<void *>(&getExecutorPath)));
- removeFilename(5, ExecutorPath);
+ removePathComponent(5, ExecutorPath);
llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
return ExecutorPath.str().str();
}
@@ -67,7 +67,7 @@ static std::string getExecutorPath() {
static std::string getOrcRuntimePath() {
llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
- removeFilename(5, RuntimePath);
+ removePathComponent(5, RuntimePath);
llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
CLANG_VERSION_MAJOR_STRING, "lib");
>From 65afbffe3aef34413f72d9f4b7416a9c4f0561b4 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Tue, 5 Aug 2025 21:51:19 +0530
Subject: [PATCH 16/20] Custom lambda in launchExecutor and pid retrieval
---
.../Interpreter/OutOfProcessInterpreterTests.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index bde175180bb47..4d5ef5c70d135 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -45,14 +45,10 @@ llvm::ExitOnError ExitOnError;
namespace {
-class InterpreterRemoteTest : public InterpreterTestBase {
- // TODO: Collect common variables and utility functions here
-};
-
using Args = std::vector<const char *>;
static void removePathComponent(unsigned N, llvm::SmallString<256> &Path) {
- for (int i = 0; i < N; ++i)
+ for (unsigned i = 0; i < N; ++i)
llvm::sys::path::remove_filename(Path);
}
@@ -134,7 +130,7 @@ static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
}
-TEST_F(InterpreterRemoteTest, SanityWithRemoteExecution) {
+TEST_F(InterpreterTestBase, SanityWithRemoteExecution) {
if (!HostSupportsJIT())
GTEST_SKIP();
>From 095a63b9849620964ee34dd08884b3644c40ba01 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 24 Aug 2025 10:25:22 +0530
Subject: [PATCH 17/20] Dynamic path resolution
---
clang/tools/clang-repl/ClangRepl.cpp | 82 ++++++++++++++++++----
clang/unittests/Interpreter/CMakeLists.txt | 9 ++-
2 files changed, 77 insertions(+), 14 deletions(-)
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index b666959c33b73..7e6b67745baed 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -22,18 +22,36 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/LineEditor/LineEditor.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h" // llvm_shutdown
+#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include <optional>
+#include <iostream>
+#include <string>
+#include <vector>
+
#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
+using namespace clang;
+
// Disable LSan for this test.
// FIXME: Re-enable once we can assume GCC 13.2 or higher.
// https://llvm.org/github.com/llvm/llvm-project/issues/67586.
@@ -81,6 +99,40 @@ static llvm::cl::opt<bool> OptHostSupportsJit("host-supports-jit",
static llvm::cl::list<std::string> OptInputs(llvm::cl::Positional,
llvm::cl::desc("[code to run]"));
+static std::string getCompilerRTPath() {
+ clang::DiagnosticOptions DiagOpts;
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
+ new clang::DiagnosticIDs());
+
+ clang::IgnoringDiagConsumer DiagConsumer;
+ clang::DiagnosticsEngine Diags(DiagID, DiagOpts, &DiagConsumer, false);
+ std::vector<const char *> Args = {"clang", "--version"};
+ clang::driver::Driver D("clang", llvm::sys::getProcessTriple(), Diags);
+ D.setCheckInputsExist(false);
+
+ std::unique_ptr<clang::driver::Compilation> C(D.BuildCompilation(Args));
+ if (!C) {
+ return "";
+ }
+
+ const clang::driver::ToolChain &TC = C->getDefaultToolChain();
+ std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
+
+ return CompilerRTPath ? *CompilerRTPath : "";
+}
+
+static std::string getOrcRuntimePath() {
+ if (OrcRuntimePath.empty()) {
+ llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
+ "clang-repl", reinterpret_cast<void *>(&getOrcRuntimePath)));
+ llvm::sys::path::remove_filename(BasePath); // Remove clang-repl filename.
+ llvm::sys::path::remove_filename(BasePath); // Remove ./bin directory.
+ llvm::sys::path::append(BasePath, getCompilerRTPath());
+ return BasePath.str().str();
+ }
+ return OrcRuntimePath;
+}
+
static llvm::Error sanitizeOopArguments(const char *ArgV0) {
// Only one of -oop-executor and -oop-executor-connect can be used.
if (!!OOPExecutor.getNumOccurrences() &&
@@ -121,17 +173,21 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0) {
ArgV0, reinterpret_cast<void *>(&sanitizeOopArguments)));
llvm::sys::path::remove_filename(BasePath); // Remove clang-repl filename.
llvm::sys::path::remove_filename(BasePath); // Remove ./bin directory.
- llvm::sys::path::append(BasePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
- CLANG_VERSION_MAJOR_STRING);
- if (SystemTriple.isOSBinFormatELF())
- OrcRuntimePath =
- BasePath.str().str() + "/lib/x86_64-unknown-linux-gnu/liborc_rt.a";
- else if (SystemTriple.isOSBinFormatMachO())
- OrcRuntimePath = BasePath.str().str() + "/lib/darwin/liborc_rt_osx.a";
- else
+ std::string CompilerRTPath = getCompilerRTPath();
+ if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt.a")) {
+ llvm::sys::path::append(BasePath, CompilerRTPath);
+ OrcRuntimePath = BasePath.str().str() + "/liborc_rt.a";
+ } else if (!llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt_osx.a")) {
+ llvm::sys::path::append(BasePath, CompilerRTPath);
+ OrcRuntimePath = BasePath.str().str() + "/liborc_rt_osx.a";
+ } else if (!llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt-x86_64.a")) {
+ llvm::sys::path::append(BasePath, CompilerRTPath);
+ OrcRuntimePath = BasePath.str().str() + "/liborc_rt-x86_64.a";
+ } else {
return llvm::make_error<llvm::StringError>(
- "Out-of-process execution is not supported on non-unix platforms",
+ "ORC runtime not found in " + CompilerRTPath,
llvm::inconvertibleErrorCode());
+ }
}
// If -oop-executor was used but no value was specified then use a sensible
@@ -186,7 +242,7 @@ struct ReplListCompleter {
clang::Interpreter &MainInterp;
ReplListCompleter(clang::IncrementalCompilerBuilder &CB,
clang::Interpreter &Interp)
- : CB(CB), MainInterp(Interp){};
+ : CB(CB), MainInterp(Interp) {};
std::vector<llvm::LineEditor::Completion> operator()(llvm::StringRef Buffer,
size_t Pos) const;
@@ -275,10 +331,10 @@ int main(int argc, const char **argv) {
if (!CudaPath.empty())
CB.SetCudaSDK(CudaPath);
- if (OffloadArch.empty()) {
- OffloadArch = "sm_35";
+ if (::OffloadArch.empty()) {
+ ::OffloadArch = "sm_35";
}
- CB.SetOffloadArch(OffloadArch);
+ CB.SetOffloadArch(::OffloadArch);
DeviceCI = ExitOnErr(CB.CreateCudaDevice());
}
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 435a78c86ee7e..7e44b5a7f954d 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -29,7 +29,6 @@ set(CLANG_LIBS_TO_LINK
)
endif()
-add_distinct_clang_unittest(ClangReplInterpreterTests
set(CLANG_REPL_TEST_SOURCES
IncrementalCompilerBuilderTest.cpp
IncrementalProcessingTest.cpp
@@ -61,6 +60,14 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
${LLVM_COMPONENTS_TO_LINK}
)
+if(TARGET compiler-rt)
+ add_dependencies(ClangReplInterpreterTests
+ llvm-jitlink-executor
+ compiler-rt
+ )
+ message(STATUS "Adding dependency on compiler-rt for out of process JIT tests")
+endif()
+
if(EMSCRIPTEN)
# Without the above you try to link to LLVMSupport twice, and end
# up with a duplicate symbol error when creating the main module
>From 2b6dc6c1c82d5888ae6d0a08f069e1ab0c1e7687 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 25 Aug 2025 18:52:37 +0530
Subject: [PATCH 18/20] Dynamic path resolution using IncrementalCB
---
clang/include/clang/Interpreter/Interpreter.h | 6 +-
clang/lib/Interpreter/Interpreter.cpp | 13 ++-
clang/tools/clang-repl/ClangRepl.cpp | 85 +++++--------------
.../OutOfProcessInterpreterTests.cpp | 63 +++++++++++---
4 files changed, 82 insertions(+), 85 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 83d2962cbf3ba..dba4427fcd3a7 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -56,7 +56,8 @@ class IncrementalCompilerBuilder {
void SetTargetTriple(std::string TT) { TargetTriple = TT; }
// General C++
- llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp();
+ llvm::Expected<std::unique_ptr<CompilerInstance>>
+ CreateCpp(std::string *CompilerRTPath = nullptr);
// Offload options
void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; };
@@ -69,7 +70,8 @@ class IncrementalCompilerBuilder {
private:
static llvm::Expected<std::unique_ptr<CompilerInstance>>
- create(std::string TT, std::vector<const char *> &ClangArgv);
+ create(std::string TT, std::vector<const char *> &ClangArgv,
+ std::string *CompilerRTPath = nullptr);
llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device);
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 5e5ae81b9ba44..be5c49782e210 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -149,7 +149,8 @@ namespace clang {
llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::create(std::string TT,
- std::vector<const char *> &ClangArgv) {
+ std::vector<const char *> &ClangArgv,
+ std::string *CompilerRTPath) {
// If we don't know ClangArgv0 or the address of main() at this point, try
// to guess it anyway (it's possible on some platforms).
@@ -190,11 +191,17 @@ IncrementalCompilerBuilder::create(std::string TT,
if (auto Err = ErrOrCC1Args.takeError())
return std::move(Err);
+ const driver::ToolChain &TC = Compilation->getDefaultToolChain();
+ std::optional<std::string> Path = TC.getCompilerRTPath();
+ if (Path && CompilerRTPath) {
+ *CompilerRTPath = *Path;
+ }
+
return CreateCI(**ErrOrCC1Args);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
-IncrementalCompilerBuilder::CreateCpp() {
+IncrementalCompilerBuilder::CreateCpp(std::string *CompilerRTPath) {
std::vector<const char *> Argv;
Argv.reserve(5 + 1 + UserArgs.size());
Argv.push_back("-xc++");
@@ -206,7 +213,7 @@ IncrementalCompilerBuilder::CreateCpp() {
llvm::append_range(Argv, UserArgs);
std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
- return IncrementalCompilerBuilder::create(TT, Argv);
+ return IncrementalCompilerBuilder::create(TT, Argv, CompilerRTPath);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 7e6b67745baed..981414c985ed5 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -22,14 +22,6 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticIDs.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/ToolChain.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/LineEditor/LineEditor.h"
#include "llvm/Support/CommandLine.h"
@@ -99,41 +91,8 @@ static llvm::cl::opt<bool> OptHostSupportsJit("host-supports-jit",
static llvm::cl::list<std::string> OptInputs(llvm::cl::Positional,
llvm::cl::desc("[code to run]"));
-static std::string getCompilerRTPath() {
- clang::DiagnosticOptions DiagOpts;
- llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
- new clang::DiagnosticIDs());
-
- clang::IgnoringDiagConsumer DiagConsumer;
- clang::DiagnosticsEngine Diags(DiagID, DiagOpts, &DiagConsumer, false);
- std::vector<const char *> Args = {"clang", "--version"};
- clang::driver::Driver D("clang", llvm::sys::getProcessTriple(), Diags);
- D.setCheckInputsExist(false);
-
- std::unique_ptr<clang::driver::Compilation> C(D.BuildCompilation(Args));
- if (!C) {
- return "";
- }
-
- const clang::driver::ToolChain &TC = C->getDefaultToolChain();
- std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
-
- return CompilerRTPath ? *CompilerRTPath : "";
-}
-
-static std::string getOrcRuntimePath() {
- if (OrcRuntimePath.empty()) {
- llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
- "clang-repl", reinterpret_cast<void *>(&getOrcRuntimePath)));
- llvm::sys::path::remove_filename(BasePath); // Remove clang-repl filename.
- llvm::sys::path::remove_filename(BasePath); // Remove ./bin directory.
- llvm::sys::path::append(BasePath, getCompilerRTPath());
- return BasePath.str().str();
- }
- return OrcRuntimePath;
-}
-
-static llvm::Error sanitizeOopArguments(const char *ArgV0) {
+static llvm::Error sanitizeOopArguments(const char *ArgV0,
+ std::string CompilerRTPath) {
// Only one of -oop-executor and -oop-executor-connect can be used.
if (!!OOPExecutor.getNumOccurrences() &&
!!OOPExecutorConnect.getNumOccurrences())
@@ -169,20 +128,12 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0) {
// Out-of-process executors require the ORC runtime.
if (OrcRuntimePath.empty() && (OOPExecutor.getNumOccurrences() ||
OOPExecutorConnect.getNumOccurrences())) {
- llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
- ArgV0, reinterpret_cast<void *>(&sanitizeOopArguments)));
- llvm::sys::path::remove_filename(BasePath); // Remove clang-repl filename.
- llvm::sys::path::remove_filename(BasePath); // Remove ./bin directory.
- std::string CompilerRTPath = getCompilerRTPath();
if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt.a")) {
- llvm::sys::path::append(BasePath, CompilerRTPath);
- OrcRuntimePath = BasePath.str().str() + "/liborc_rt.a";
- } else if (!llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt_osx.a")) {
- llvm::sys::path::append(BasePath, CompilerRTPath);
- OrcRuntimePath = BasePath.str().str() + "/liborc_rt_osx.a";
- } else if (!llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt-x86_64.a")) {
- llvm::sys::path::append(BasePath, CompilerRTPath);
- OrcRuntimePath = BasePath.str().str() + "/liborc_rt-x86_64.a";
+ OrcRuntimePath = CompilerRTPath + "/liborc_rt.a";
+ } else if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt_osx.a")) {
+ OrcRuntimePath = CompilerRTPath + "/liborc_rt_osx.a";
+ } else if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt-x86_64.a")) {
+ OrcRuntimePath = CompilerRTPath + "/liborc_rt-x86_64.a";
} else {
return llvm::make_error<llvm::StringError>(
"ORC runtime not found in " + CompilerRTPath,
@@ -339,7 +290,18 @@ int main(int argc, const char **argv) {
DeviceCI = ExitOnErr(CB.CreateCudaDevice());
}
- ExitOnErr(sanitizeOopArguments(argv[0]));
+ std::string CompilerRTPath;
+
+ // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
+ // can replace the boilerplate code for creation of the compiler instance.
+ std::unique_ptr<clang::CompilerInstance> CI;
+ if (CudaEnabled) {
+ CI = ExitOnErr(CB.CreateCudaHost());
+ } else {
+ CI = ExitOnErr(CB.CreateCpp(&CompilerRTPath));
+ }
+
+ ExitOnErr(sanitizeOopArguments(argv[0], CompilerRTPath));
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
if (OOPExecutor.getNumOccurrences()) {
@@ -358,15 +320,6 @@ int main(int argc, const char **argv) {
clang::Interpreter::createLLJITBuilder(std::move(EPC), OrcRuntimePath));
}
- // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
- // can replace the boilerplate code for creation of the compiler instance.
- std::unique_ptr<clang::CompilerInstance> CI;
- if (CudaEnabled) {
- CI = ExitOnErr(CB.CreateCudaHost());
- } else {
- CI = ExitOnErr(CB.CreateCpp());
- }
-
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
llvm::install_fatal_error_handler(LLVMErrorHandler,
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 4d5ef5c70d135..35292d173b2c0 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -16,8 +16,14 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Mangle.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Interpreter/Interpreter.h"
@@ -25,8 +31,14 @@
#include "clang/Interpreter/Value.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/TargetParser/Host.h"
@@ -60,22 +72,43 @@ static std::string getExecutorPath() {
return ExecutorPath.str().str();
}
-static std::string getOrcRuntimePath() {
- llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
- nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
- removePathComponent(5, RuntimePath);
- llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
- CLANG_VERSION_MAJOR_STRING, "lib");
+static std::string getCompilerRTPath() {
+ clang::DiagnosticOptions DiagOpts;
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
+ new clang::DiagnosticIDs());
- llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
- if (SystemTriple.isOSBinFormatMachO()) {
- llvm::sys::path::append(RuntimePath, "darwin", "liborc_rt_osx.a");
- } else if (SystemTriple.isOSBinFormatELF()) {
- llvm::sys::path::append(RuntimePath, "x86_64-unknown-linux-gnu",
- "liborc_rt.a");
+ clang::IgnoringDiagConsumer DiagConsumer;
+ clang::DiagnosticsEngine Diags(DiagID, DiagOpts, &DiagConsumer, false);
+ std::vector<const char *> Args = {"clang", "--version"};
+ clang::driver::Driver D("clang", llvm::sys::getProcessTriple(), Diags);
+ D.setCheckInputsExist(false);
+
+ std::unique_ptr<clang::driver::Compilation> C(D.BuildCompilation(Args));
+ if (!C) {
+ return "";
}
- return RuntimePath.str().str();
+ const clang::driver::ToolChain &TC = C->getDefaultToolChain();
+ std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
+
+ return CompilerRTPath ? *CompilerRTPath : "";
+}
+
+static std::string getOrcRuntimePath(std::string CompilerRTPath) {
+ llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
+ nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
+ removePathComponent(5, BasePath);
+ llvm::sys::path::append(BasePath, CompilerRTPath);
+ std::string OrcRuntimePath;
+ if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt.a")) {
+ OrcRuntimePath = BasePath.str().str() + "/liborc_rt.a";
+ } else if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt_osx.a")) {
+ OrcRuntimePath = BasePath.str().str() + "/liborc_rt_osx.a";
+ } else if (llvm::sys::fs::exists(BasePath.str().str() +
+ "/liborc_rt-x86_64.a")) {
+ OrcRuntimePath = BasePath.str().str() + "/liborc_rt-x86_64.a";
+ }
+ return OrcRuntimePath;
}
static std::unique_ptr<Interpreter>
@@ -93,9 +126,11 @@ createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
+ std::string CompilerRTPath = getCompilerRTPath();
+
if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) {
std::string OOPExecutor = getExecutorPath();
- std::string OrcRuntimePath = getOrcRuntimePath();
+ std::string OrcRuntimePath = getOrcRuntimePath(CompilerRTPath);
bool UseSharedMemory = false;
std::string SlabAllocateSizeString = "";
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
>From 7ad10a676a2fe32d55c685ea03b37b8c65087868 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 25 Aug 2025 20:14:23 +0530
Subject: [PATCH 19/20] Dynamic path resolution using IncrementalCB
---
clang/include/clang/Interpreter/Interpreter.h | 4 ++--
clang/lib/Interpreter/Interpreter.cpp | 16 ++++++++++-----
clang/tools/clang-repl/ClangRepl.cpp | 20 +++++++------------
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index dba4427fcd3a7..7439c5b9479d6 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -57,7 +57,7 @@ class IncrementalCompilerBuilder {
// General C++
llvm::Expected<std::unique_ptr<CompilerInstance>>
- CreateCpp(std::string *CompilerRTPath = nullptr);
+ CreateCpp(std::string *OrcRuntimePath = nullptr);
// Offload options
void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; };
@@ -71,7 +71,7 @@ class IncrementalCompilerBuilder {
private:
static llvm::Expected<std::unique_ptr<CompilerInstance>>
create(std::string TT, std::vector<const char *> &ClangArgv,
- std::string *CompilerRTPath = nullptr);
+ std::string *OrcRuntimePath = nullptr);
llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device);
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index be5c49782e210..281cfe860d8d5 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -150,7 +150,7 @@ namespace clang {
llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::create(std::string TT,
std::vector<const char *> &ClangArgv,
- std::string *CompilerRTPath) {
+ std::string *OrcRuntimePath) {
// If we don't know ClangArgv0 or the address of main() at this point, try
// to guess it anyway (it's possible on some platforms).
@@ -193,15 +193,21 @@ IncrementalCompilerBuilder::create(std::string TT,
const driver::ToolChain &TC = Compilation->getDefaultToolChain();
std::optional<std::string> Path = TC.getCompilerRTPath();
- if (Path && CompilerRTPath) {
- *CompilerRTPath = *Path;
+ if (Path && OrcRuntimePath) {
+ *OrcRuntimePath = *Path;
+ if(llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt.a"))
+ *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt.a";
+ else if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt_osx.a"))
+ *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt_osx.a";
+ else if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt-x86_64.a"))
+ *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt-x86_64.a";
}
return CreateCI(**ErrOrCC1Args);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
-IncrementalCompilerBuilder::CreateCpp(std::string *CompilerRTPath) {
+IncrementalCompilerBuilder::CreateCpp(std::string *OrcRuntimePath) {
std::vector<const char *> Argv;
Argv.reserve(5 + 1 + UserArgs.size());
Argv.push_back("-xc++");
@@ -213,7 +219,7 @@ IncrementalCompilerBuilder::CreateCpp(std::string *CompilerRTPath) {
llvm::append_range(Argv, UserArgs);
std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
- return IncrementalCompilerBuilder::create(TT, Argv, CompilerRTPath);
+ return IncrementalCompilerBuilder::create(TT, Argv, OrcRuntimePath);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 981414c985ed5..fbd48f09b77fa 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -92,7 +92,7 @@ static llvm::cl::list<std::string> OptInputs(llvm::cl::Positional,
llvm::cl::desc("[code to run]"));
static llvm::Error sanitizeOopArguments(const char *ArgV0,
- std::string CompilerRTPath) {
+ std::string _OrcRuntimePath) {
// Only one of -oop-executor and -oop-executor-connect can be used.
if (!!OOPExecutor.getNumOccurrences() &&
!!OOPExecutorConnect.getNumOccurrences())
@@ -128,17 +128,11 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0,
// Out-of-process executors require the ORC runtime.
if (OrcRuntimePath.empty() && (OOPExecutor.getNumOccurrences() ||
OOPExecutorConnect.getNumOccurrences())) {
- if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt.a")) {
- OrcRuntimePath = CompilerRTPath + "/liborc_rt.a";
- } else if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt_osx.a")) {
- OrcRuntimePath = CompilerRTPath + "/liborc_rt_osx.a";
- } else if (llvm::sys::fs::exists(CompilerRTPath + "/liborc_rt-x86_64.a")) {
- OrcRuntimePath = CompilerRTPath + "/liborc_rt-x86_64.a";
- } else {
+ if(!llvm::sys::fs::exists(_OrcRuntimePath))
return llvm::make_error<llvm::StringError>(
- "ORC runtime not found in " + CompilerRTPath,
+ "The ORC runtime is required for out-of-process execution",
llvm::inconvertibleErrorCode());
- }
+ OrcRuntimePath = _OrcRuntimePath;
}
// If -oop-executor was used but no value was specified then use a sensible
@@ -290,7 +284,7 @@ int main(int argc, const char **argv) {
DeviceCI = ExitOnErr(CB.CreateCudaDevice());
}
- std::string CompilerRTPath;
+ std::string _OrcRuntimePath;
// FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
// can replace the boilerplate code for creation of the compiler instance.
@@ -298,10 +292,10 @@ int main(int argc, const char **argv) {
if (CudaEnabled) {
CI = ExitOnErr(CB.CreateCudaHost());
} else {
- CI = ExitOnErr(CB.CreateCpp(&CompilerRTPath));
+ CI = ExitOnErr(CB.CreateCpp(&_OrcRuntimePath));
}
- ExitOnErr(sanitizeOopArguments(argv[0], CompilerRTPath));
+ ExitOnErr(sanitizeOopArguments(argv[0], _OrcRuntimePath));
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
if (OOPExecutor.getNumOccurrences()) {
>From 6a58d5fa5b0da9899fd9a1139729495f84201fb0 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Tue, 26 Aug 2025 20:38:45 +0530
Subject: [PATCH 20/20] Addressing reviews
---
clang/include/clang/Interpreter/Interpreter.h | 4 +-
clang/lib/Interpreter/Interpreter.cpp | 41 +++++++++++++------
clang/tools/clang-repl/ClangRepl.cpp | 9 ++--
3 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 7439c5b9479d6..5add9c8a8166d 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -57,7 +57,7 @@ class IncrementalCompilerBuilder {
// General C++
llvm::Expected<std::unique_ptr<CompilerInstance>>
- CreateCpp(std::string *OrcRuntimePath = nullptr);
+ CreateCpp(std::string *OrcRuntimePath = nullptr, bool IsOutOfProcess = false);
// Offload options
void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; };
@@ -71,7 +71,7 @@ class IncrementalCompilerBuilder {
private:
static llvm::Expected<std::unique_ptr<CompilerInstance>>
create(std::string TT, std::vector<const char *> &ClangArgv,
- std::string *OrcRuntimePath = nullptr);
+ std::string *OrcRuntimePath = nullptr, bool IsOutOfProcess = false);
llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device);
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 281cfe860d8d5..88f50e117eea1 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -150,7 +150,8 @@ namespace clang {
llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::create(std::string TT,
std::vector<const char *> &ClangArgv,
- std::string *OrcRuntimePath) {
+ std::string *OrcRuntimePath,
+ bool IsOutOfProcess) {
// If we don't know ClangArgv0 or the address of main() at this point, try
// to guess it anyway (it's possible on some platforms).
@@ -191,23 +192,36 @@ IncrementalCompilerBuilder::create(std::string TT,
if (auto Err = ErrOrCC1Args.takeError())
return std::move(Err);
- const driver::ToolChain &TC = Compilation->getDefaultToolChain();
- std::optional<std::string> Path = TC.getCompilerRTPath();
- if (Path && OrcRuntimePath) {
- *OrcRuntimePath = *Path;
- if(llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt.a"))
- *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt.a";
- else if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt_osx.a"))
- *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt_osx.a";
- else if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt-x86_64.a"))
- *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt-x86_64.a";
+ if (IsOutOfProcess) {
+ const driver::ToolChain &TC = Compilation->getDefaultToolChain();
+ std::optional<std::string> Path = TC.getCompilerRTPath();
+ if (!Path) {
+ return llvm::createStringError(llvm::errc::not_supported,
+ "The compiler-rt library path is not set "
+ "in the default toolchain");
+ }
+ if (OrcRuntimePath) {
+ *OrcRuntimePath = *Path;
+ if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt.a"))
+ *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt.a";
+ else if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt_osx.a"))
+ *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt_osx.a";
+ else if (llvm::sys::fs::exists(*OrcRuntimePath + "/liborc_rt-x86_64.a"))
+ *OrcRuntimePath = *OrcRuntimePath + "/liborc_rt-x86_64.a";
+ else {
+ return llvm::createStringError(
+ llvm::errc::not_supported,
+ "The ORC runtime is required for out-of-process execution");
+ }
+ }
}
return CreateCI(**ErrOrCC1Args);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
-IncrementalCompilerBuilder::CreateCpp(std::string *OrcRuntimePath) {
+IncrementalCompilerBuilder::CreateCpp(std::string *OrcRuntimePath,
+ bool IsOutOfProcess) {
std::vector<const char *> Argv;
Argv.reserve(5 + 1 + UserArgs.size());
Argv.push_back("-xc++");
@@ -219,7 +233,8 @@ IncrementalCompilerBuilder::CreateCpp(std::string *OrcRuntimePath) {
llvm::append_range(Argv, UserArgs);
std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
- return IncrementalCompilerBuilder::create(TT, Argv, OrcRuntimePath);
+ return IncrementalCompilerBuilder::create(TT, Argv, OrcRuntimePath,
+ IsOutOfProcess);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index fbd48f09b77fa..43ec0b780b8f5 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -128,10 +128,6 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0,
// Out-of-process executors require the ORC runtime.
if (OrcRuntimePath.empty() && (OOPExecutor.getNumOccurrences() ||
OOPExecutorConnect.getNumOccurrences())) {
- if(!llvm::sys::fs::exists(_OrcRuntimePath))
- return llvm::make_error<llvm::StringError>(
- "The ORC runtime is required for out-of-process execution",
- llvm::inconvertibleErrorCode());
OrcRuntimePath = _OrcRuntimePath;
}
@@ -284,6 +280,9 @@ int main(int argc, const char **argv) {
DeviceCI = ExitOnErr(CB.CreateCudaDevice());
}
+ bool IsOutOfProcess = !!OOPExecutor.getNumOccurrences() ||
+ !!OOPExecutorConnect.getNumOccurrences();
+
std::string _OrcRuntimePath;
// FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
@@ -292,7 +291,7 @@ int main(int argc, const char **argv) {
if (CudaEnabled) {
CI = ExitOnErr(CB.CreateCudaHost());
} else {
- CI = ExitOnErr(CB.CreateCpp(&_OrcRuntimePath));
+ CI = ExitOnErr(CB.CreateCpp(&_OrcRuntimePath, IsOutOfProcess));
}
ExitOnErr(sanitizeOopArguments(argv[0], _OrcRuntimePath));
More information about the cfe-commits
mailing list