[clang] [Clang-Repl] Sinking RemoteJITUtils into Interpreter class(Refactoring) (PR #155140)
Abhinav Kumar via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 5 10:15:38 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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));
>From f1b913501afe1d94fd70e0c8da05d35ca6f320d1 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Wed, 27 Aug 2025 21:40:57 +0530
Subject: [PATCH 21/35] Sinking JitBuilder into Interpreter
---
clang/include/clang/Interpreter/Interpreter.h | 18 ++-
.../clang/Interpreter/OutOfProcessJITConfig.h | 45 ++++++
clang/lib/Interpreter/Interpreter.cpp | 129 +++++++++++++-----
clang/tools/clang-repl/ClangRepl.cpp | 51 +++----
.../OutOfProcessInterpreterTests.cpp | 83 ++---------
5 files changed, 178 insertions(+), 148 deletions(-)
create mode 100644 clang/include/clang/Interpreter/OutOfProcessJITConfig.h
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 5add9c8a8166d..cfc5ead85e79b 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -15,6 +15,8 @@
#define LLVM_CLANG_INTERPRETER_INTERPRETER_H
#include "clang/AST/GlobalDecl.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Interpreter/OutOfProcessJITConfig.h"
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Interpreter/Value.h"
@@ -56,8 +58,7 @@ class IncrementalCompilerBuilder {
void SetTargetTriple(std::string TT) { TargetTriple = TT; }
// General C++
- llvm::Expected<std::unique_ptr<CompilerInstance>>
- CreateCpp(std::string *OrcRuntimePath = nullptr, bool IsOutOfProcess = false);
+ llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp();
// Offload options
void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; };
@@ -70,8 +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, bool IsOutOfProcess = false);
+ create(std::string TT, std::vector<const char *> &ClangArgv);
llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device);
@@ -138,15 +138,19 @@ class Interpreter {
public:
virtual ~Interpreter();
- static llvm::Expected<std::unique_ptr<Interpreter>>
- create(std::unique_ptr<CompilerInstance> CI,
- std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr);
+ static llvm::Expected<std::unique_ptr<Interpreter>> create(
+ std::unique_ptr<CompilerInstance> CI,
+ std::optional<OutOfProcessJITConfig> OutOfProcessConfig = std::nullopt);
static llvm::Expected<std::unique_ptr<Interpreter>>
createWithCUDA(std::unique_ptr<CompilerInstance> CI,
std::unique_ptr<CompilerInstance> DCI);
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
llvm::StringRef OrcRuntimePath);
+ static std::unique_ptr<llvm::orc::LLJITBuilder>
+ outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig);
+ static llvm::Expected<std::string>
+ getOrcRuntimePath(const driver::ToolChain &TC);
const ASTContext &getASTContext() const;
ASTContext &getASTContext();
const CompilerInstance *getCompilerInstance() const;
diff --git a/clang/include/clang/Interpreter/OutOfProcessJITConfig.h b/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
new file mode 100644
index 0000000000000..0996e758bab41
--- /dev/null
+++ b/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
@@ -0,0 +1,45 @@
+//===-- OutOfProcessJITConfig.h - Struct for Out-Of-Process JIT--*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a struct that holds configuration options for
+// out-of-process JIT execution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INTERPRETER_OUTOFPROCESSJITCONFIG_H
+#define LLVM_CLANG_INTERPRETER_OUTOFPROCESSJITCONFIG_H
+
+#include <functional>
+#include <string>
+#include <utility>
+
+namespace clang {
+
+/// \brief Configuration options for out-of-process JIT execution.
+struct OutOfProcessJITConfig {
+ /// Indicates whether out-of-process JIT execution is enabled.
+ bool IsOutOfProcess = false;
+
+ /// Path to the out-of-process JIT executor.
+ std::string OOPExecutor;
+
+ std::string OOPExecutorConnect;
+
+ /// Indicates whether to use shared memory for communication.
+ bool UseSharedMemory;
+
+ /// String representing the slab allocation size for memory management.
+ std::string SlabAllocateSizeString;
+
+ /// Path to the ORC runtime library.
+ std::string OrcRuntimePath;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_INTERPRETER_OUTOFPROCESSJITCONFIG_H
\ No newline at end of file
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 88f50e117eea1..b9a81bb4ebae1 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -41,6 +41,8 @@
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/FrontendTool/Utils.h"
#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/OutOfProcessJITConfig.h"
+#include "clang/Interpreter/RemoteJITUtils.h"
#include "clang/Interpreter/Value.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/Lookup.h"
@@ -55,6 +57,8 @@
#include "llvm/TargetParser/Host.h"
#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule
+#include <iostream>
+
#define DEBUG_TYPE "clang-repl"
using namespace clang;
@@ -149,9 +153,7 @@ namespace clang {
llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::create(std::string TT,
- std::vector<const char *> &ClangArgv,
- std::string *OrcRuntimePath,
- bool IsOutOfProcess) {
+ std::vector<const char *> &ClangArgv) {
// 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).
@@ -192,36 +194,11 @@ IncrementalCompilerBuilder::create(std::string TT,
if (auto Err = ErrOrCC1Args.takeError())
return std::move(Err);
- 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,
- bool IsOutOfProcess) {
+IncrementalCompilerBuilder::CreateCpp() {
std::vector<const char *> Argv;
Argv.reserve(5 + 1 + UserArgs.size());
Argv.push_back("-xc++");
@@ -233,8 +210,7 @@ IncrementalCompilerBuilder::CreateCpp(std::string *OrcRuntimePath,
llvm::append_range(Argv, UserArgs);
std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
- return IncrementalCompilerBuilder::create(TT, Argv, OrcRuntimePath,
- IsOutOfProcess);
+ return IncrementalCompilerBuilder::create(TT, Argv);
}
llvm::Expected<std::unique_ptr<CompilerInstance>>
@@ -488,10 +464,99 @@ const char *const Runtimes = R"(
EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
)";
+llvm::ExitOnError ExitOnErr;
+
+std::unique_ptr<llvm::orc::LLJITBuilder>
+Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
+ std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
+ if (OutOfProcessConfig.OOPExecutor != "") {
+ // Launch an out-of-process executor locally in a child process.
+ EPC = ExitOnErr(launchExecutor(OutOfProcessConfig.OOPExecutor,
+ OutOfProcessConfig.UseSharedMemory,
+ OutOfProcessConfig.SlabAllocateSizeString));
+ } else if (OutOfProcessConfig.OOPExecutorConnect != "") {
+ EPC =
+ ExitOnErr(connectTCPSocket(OutOfProcessConfig.OOPExecutorConnect,
+ OutOfProcessConfig.UseSharedMemory,
+ OutOfProcessConfig.SlabAllocateSizeString));
+ }
+
+ std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+ if (EPC) {
+ JB = ExitOnErr(clang::Interpreter::createLLJITBuilder(
+ std::move(EPC), OutOfProcessConfig.OrcRuntimePath));
+ }
+
+ return JB;
+}
+
+llvm::Expected<std::string>
+Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
+ std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
+ if (!CompilerRTPath) {
+ return llvm::make_error<llvm::StringError>("CompilerRT path not found",
+ std::error_code());
+ }
+ llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
+ "clang-repl", reinterpret_cast<void *>(&getOrcRuntimePath)));
+ // Remove paths until you find /build at last
+ while (!(llvm::sys::path::filename(BasePath) == "build") &&
+ !BasePath.empty()) {
+ llvm::sys::path::remove_filename(BasePath);
+ }
+
+ llvm::sys::path::append(BasePath, *CompilerRTPath);
+
+ if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt.a")) {
+ llvm::sys::path::append(BasePath, "liborc_rt.a");
+ } else if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt_osx.a")) {
+ llvm::sys::path::append(BasePath, "liborc_rt_osx.a");
+ } else if (llvm::sys::fs::exists(BasePath.str().str() +
+ "/liborc_rt-x86_64.a")) {
+ llvm::sys::path::append(BasePath, "liborc_rt-x86_64.a");
+ } else {
+ return llvm::make_error<llvm::StringError>("OrcRuntime library not found",
+ std::error_code());
+ }
+
+ return BasePath.str().str();
+}
+
llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::create(std::unique_ptr<CompilerInstance> CI,
- std::unique_ptr<llvm::orc::LLJITBuilder> JB) {
+ std::optional<OutOfProcessJITConfig> OutOfProcessConfig) {
llvm::Error Err = llvm::Error::success();
+
+ std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+
+ if (OutOfProcessConfig != std::nullopt &&
+ OutOfProcessConfig->IsOutOfProcess) {
+ const TargetInfo &TI = CI->getTarget();
+ const llvm::Triple &Triple = TI.getTriple();
+
+ DiagnosticsEngine &Diags = CI->getDiagnostics();
+ driver::Driver Driver("clang", Triple.str(), Diags);
+
+ std::vector<const char *> Args = {"clang", "--version"};
+ std::unique_ptr<clang::driver::Compilation> C(
+ Driver.BuildCompilation(Args));
+ if (!C) {
+ return llvm::make_error<llvm::StringError>(
+ "Failed to create driver compilation for out-of-process JIT",
+ std::error_code());
+ }
+
+ const clang::driver::ToolChain &TC = C->getDefaultToolChain();
+
+ auto OrcRuntimePathOrErr = getOrcRuntimePath(TC);
+ if (!OrcRuntimePathOrErr) {
+ return OrcRuntimePathOrErr.takeError();
+ }
+
+ OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
+ JB = outOfProcessJITBuilder(*OutOfProcessConfig);
+ }
+
auto Interp = std::unique_ptr<Interpreter>(
new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr));
if (Err)
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 43ec0b780b8f5..29939610ec6f6 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -19,6 +19,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Interpreter/CodeCompletion.h"
#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/OutOfProcessJITConfig.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
@@ -91,8 +92,7 @@ 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 llvm::Error sanitizeOopArguments(const char *ArgV0,
- std::string _OrcRuntimePath) {
+static llvm::Error sanitizeOopArguments(const char *ArgV0) {
// Only one of -oop-executor and -oop-executor-connect can be used.
if (!!OOPExecutor.getNumOccurrences() &&
!!OOPExecutorConnect.getNumOccurrences())
@@ -125,11 +125,8 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0,
llvm::inconvertibleErrorCode());
}
- // Out-of-process executors require the ORC runtime.
- if (OrcRuntimePath.empty() && (OOPExecutor.getNumOccurrences() ||
- OOPExecutorConnect.getNumOccurrences())) {
- OrcRuntimePath = _OrcRuntimePath;
- }
+ // Out-of-process executors require the ORC runtime. ORC Runtime Path
+ // resolution is done in Interpreter.cpp.
// If -oop-executor was used but no value was specified then use a sensible
// default.
@@ -280,10 +277,14 @@ int main(int argc, const char **argv) {
DeviceCI = ExitOnErr(CB.CreateCudaDevice());
}
- bool IsOutOfProcess = !!OOPExecutor.getNumOccurrences() ||
- !!OOPExecutorConnect.getNumOccurrences();
+ ExitOnErr(sanitizeOopArguments(argv[0]));
- std::string _OrcRuntimePath;
+ clang::OutOfProcessJITConfig OutOfProcessConfig;
+ OutOfProcessConfig.IsOutOfProcess = !OOPExecutor.getNumOccurrences() ||
+ !OOPExecutorConnect.getNumOccurrences();
+ OutOfProcessConfig.OOPExecutor = OOPExecutor;
+ OutOfProcessConfig.SlabAllocateSizeString = SlabAllocateSizeString;
+ OutOfProcessConfig.UseSharedMemory = UseSharedMemory;
// FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
// can replace the boilerplate code for creation of the compiler instance.
@@ -291,26 +292,7 @@ int main(int argc, const char **argv) {
if (CudaEnabled) {
CI = ExitOnErr(CB.CreateCudaHost());
} else {
- CI = ExitOnErr(CB.CreateCpp(&_OrcRuntimePath, IsOutOfProcess));
- }
-
- ExitOnErr(sanitizeOopArguments(argv[0], _OrcRuntimePath));
-
- std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
- if (OOPExecutor.getNumOccurrences()) {
- // Launch an out-of-process executor locally in a child process.
- EPC = ExitOnErr(
- launchExecutor(OOPExecutor, UseSharedMemory, SlabAllocateSizeString));
- } else if (OOPExecutorConnect.getNumOccurrences()) {
- EPC = ExitOnErr(connectTCPSocket(OOPExecutorConnect, UseSharedMemory,
- SlabAllocateSizeString));
- }
-
- std::unique_ptr<llvm::orc::LLJITBuilder> JB;
- if (EPC) {
- CB.SetTargetTriple(EPC->getTargetTriple().getTriple());
- JB = ExitOnErr(
- clang::Interpreter::createLLJITBuilder(std::move(EPC), OrcRuntimePath));
+ CI = ExitOnErr(CB.CreateCpp());
}
// Set an error handler, so that any LLVM backend diagnostics go through our
@@ -335,11 +317,10 @@ int main(int argc, const char **argv) {
auto CudaRuntimeLibPath = CudaPath + "/lib/libcudart.so";
ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str()));
}
- } else if (JB) {
- Interp =
- ExitOnErr(clang::Interpreter::create(std::move(CI), std::move(JB)));
- } else
- Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+ } else {
+ Interp = ExitOnErr(
+ clang::Interpreter::create(std::move(CI), OutOfProcessConfig));
+ }
bool HasError = false;
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 35292d173b2c0..bf1c9f355578b 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -27,6 +27,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/OutOfProcessJITConfig.h"
#include "clang/Interpreter/RemoteJITUtils.h"
#include "clang/Interpreter/Value.h"
#include "clang/Sema/Lookup.h"
@@ -72,45 +73,6 @@ static std::string getExecutorPath() {
return ExecutorPath.str().str();
}
-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(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>
createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
DiagnosticConsumer *Client = nullptr) {
@@ -122,43 +84,16 @@ createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
if (Client)
CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
+ OutOfProcessJITConfig OutOfProcessConfig;
+ OutOfProcessConfig.OOPExecutor = getExecutorPath();
+ OutOfProcessConfig.UseSharedMemory = false;
+ OutOfProcessConfig.SlabAllocateSizeString = "";
+ OutOfProcessConfig.IsOutOfProcess = true;
+
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
- llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
-
- std::string CompilerRTPath = getCompilerRTPath();
-
- if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) {
- std::string OOPExecutor = getExecutorPath();
- std::string OrcRuntimePath = getOrcRuntimePath(CompilerRTPath);
- 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)));
+ return cantFail(
+ clang::Interpreter::create(std::move(CI), OutOfProcessConfig));
}
static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
>From dd730525c31e33d35dbde4f2041ce6ad6d1911dd Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 31 Aug 2025 19:01:59 +0530
Subject: [PATCH 22/35] RemoteJITUtils shifted to IncrementalExecutor
---
clang/include/clang/Interpreter/Interpreter.h | 8 +-
.../clang/Interpreter/OutOfProcessJITConfig.h | 3 +
clang/lib/Driver/ToolChain.cpp | 52 ++--
clang/lib/Interpreter/IncrementalExecutor.cpp | 279 ++++++++++++++++++
clang/lib/Interpreter/IncrementalExecutor.h | 22 ++
clang/lib/Interpreter/Interpreter.cpp | 133 +++++----
clang/tools/clang-repl/ClangRepl.cpp | 5 +-
.../OutOfProcessInterpreterTests.cpp | 59 ++++
8 files changed, 472 insertions(+), 89 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index cfc5ead85e79b..f9b7e9ffaec69 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -126,11 +126,11 @@ class Interpreter {
// Derived classes can use an extended interface of the Interpreter.
Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
- std::unique_ptr<clang::ASTConsumer> Consumer = nullptr);
+ std::unique_ptr<clang::ASTConsumer> Consumer = nullptr, OutOfProcessJITConfig OOPConfig = {});
// Create the internal IncrementalExecutor, or re-create it after calling
// ResetExecutor().
- llvm::Error CreateExecutor();
+ llvm::Error CreateExecutor(OutOfProcessJITConfig OOPConfig = {});
// Delete the internal IncrementalExecutor. This causes a hard shutdown of the
// JIT engine. In particular, it doesn't run cleanup or destructors.
@@ -147,7 +147,7 @@ class Interpreter {
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
llvm::StringRef OrcRuntimePath);
- static std::unique_ptr<llvm::orc::LLJITBuilder>
+ static llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig);
static llvm::Expected<std::string>
getOrcRuntimePath(const driver::ToolChain &TC);
@@ -186,6 +186,8 @@ class Interpreter {
std::unique_ptr<llvm::Module> M = {},
IncrementalAction *Action = nullptr);
+ pid_t getOutOfProcessExecutorPID() const;
+
private:
size_t getEffectivePTUSize() const;
void markUserCodeStart();
diff --git a/clang/include/clang/Interpreter/OutOfProcessJITConfig.h b/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
index 0996e758bab41..7d950abc80f4e 100644
--- a/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
+++ b/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
@@ -38,6 +38,9 @@ struct OutOfProcessJITConfig {
/// Path to the ORC runtime library.
std::string OrcRuntimePath;
+
+ /// Custom lambda function to customize the fork behavior.
+ std::function<void()> CustomizeFork = nullptr;
};
} // namespace clang
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 7667dbddb0ca2..d00fffaf06340 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -167,10 +167,9 @@ static void processMultilibCustomFlags(Multilib::flags_list &List,
}
}
-static void getAArch64MultilibFlags(const Driver &D,
- const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- Multilib::flags_list &Result) {
+static void getAArch64MultilibFlags(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ Multilib::flags_list &Result) {
std::vector<StringRef> Features;
tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features,
/*ForAS=*/false,
@@ -500,8 +499,7 @@ static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
return DS;
}
-ParsedClangName
-ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
+ParsedClangName ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
std::string ProgName = normalizeProgramName(PN);
size_t SuffixPos;
const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
@@ -512,8 +510,8 @@ ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
size_t LastComponent = ProgName.rfind('-', SuffixPos);
if (LastComponent == std::string::npos)
return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
- std::string ModeSuffix = ProgName.substr(LastComponent + 1,
- SuffixEnd - LastComponent - 1);
+ std::string ModeSuffix =
+ ProgName.substr(LastComponent + 1, SuffixEnd - LastComponent - 1);
// Infer target from the prefix.
StringRef Prefix(ProgName);
@@ -570,9 +568,7 @@ Tool *ToolChain::getFlang() const {
return Flang.get();
}
-Tool *ToolChain::buildAssembler() const {
- return new tools::ClangAs(*this);
-}
+Tool *ToolChain::buildAssembler() const { return new tools::ClangAs(*this); }
Tool *ToolChain::buildLinker() const {
llvm_unreachable("Linking is not supported by this toolchain");
@@ -1077,8 +1073,10 @@ bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
}
Tool *ToolChain::SelectTool(const JobAction &JA) const {
- if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
- if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
+ if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA))
+ return getFlang();
+ if (getDriver().ShouldUseClangCompiler(JA))
+ return getClang();
Action::ActionClass AC = JA.getKind();
if (AC == Action::AssembleJobClass && useIntegratedAs() &&
!getTriple().isOSAIX())
@@ -1100,7 +1098,7 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
// considered as the linker flavor, e.g. "bfd", "gold", or "lld".
- const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+ const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
StringRef UseLinker = A ? A->getValue() : getDriver().getPreferredLinker();
// --ld-path= takes precedence over -fuse-ld= and specifies the executable
@@ -1185,9 +1183,7 @@ types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
return id;
}
-bool ToolChain::HasNativeLLVMSupport() const {
- return false;
-}
+bool ToolChain::HasNativeLLVMSupport() const { return false; }
bool ToolChain::isCrossCompiling() const {
llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
@@ -1199,7 +1195,8 @@ bool ToolChain::isCrossCompiling() const {
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
- getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
+ getArch() != llvm::Triple::armeb &&
+ getArch() != llvm::Triple::thumbeb;
default:
return HostTriple.getArch() != getArch();
}
@@ -1288,9 +1285,7 @@ std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
return ComputeLLVMTriple(Args, InputType);
}
-std::string ToolChain::computeSysRoot() const {
- return D.SysRoot;
-}
+std::string ToolChain::computeSysRoot() const { return D.SysRoot; }
void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
@@ -1314,12 +1309,12 @@ void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
}
-ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
- const ArgList &Args) const {
+ToolChain::RuntimeLibType
+ToolChain::GetRuntimeLibType(const ArgList &Args) const {
if (runtimeLibType)
return *runtimeLibType;
- const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
+ const Arg *A = Args.getLastArg(options::OPT_rtlib_EQ);
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
// Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
@@ -1340,8 +1335,8 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
return *runtimeLibType;
}
-ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
- const ArgList &Args) const {
+ToolChain::UnwindLibType
+ToolChain::GetUnwindLibType(const ArgList &Args) const {
if (unwindLibType)
return *unwindLibType;
@@ -1376,7 +1371,8 @@ ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
return *unwindLibType;
}
-ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
+ToolChain::CXXStdlibType
+ToolChain::GetCXXStdlibType(const ArgList &Args) const {
if (cxxStdlibType)
return *cxxStdlibType;
@@ -1548,7 +1544,7 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
void ToolChain::AddFilePathLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
for (const auto &LibPath : getFilePaths())
- if(LibPath.length() > 0)
+ if (LibPath.length() > 0)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
}
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 4d2adecaafce7..6f77b18b5b845 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -28,6 +28,26 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
+#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+#ifdef LLVM_ON_UNIX
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif // LLVM_ON_UNIX
+
+using namespace llvm;
+using namespace llvm::orc;
// Force linking some of the runtimes that helps attaching to a debugger.
LLVM_ATTRIBUTE_USED void linkComponents() {
@@ -68,6 +88,22 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
}
}
+IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
+ llvm::orc::LLJITBuilder &JITBuilder,
+ llvm::Error &Err,
+ pid_t ChildPid)
+ : TSCtx(TSC), OutOfProcessChildPid(ChildPid) {
+ using namespace llvm::orc;
+ llvm::ErrorAsOutParameter EAO(&Err);
+
+ if (auto JitOrErr = JITBuilder.create())
+ Jit = std::move(*JitOrErr);
+ else {
+ Err = JitOrErr.takeError();
+ return;
+ }
+}
+
IncrementalExecutor::~IncrementalExecutor() {}
llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
@@ -118,4 +154,247 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
return SymOrErr->getAddress();
}
+Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
+ SizeString = SizeString.trim();
+
+ uint64_t Units = 1024;
+
+ if (SizeString.ends_with_insensitive("kb"))
+ SizeString = SizeString.drop_back(2).rtrim();
+ else if (SizeString.ends_with_insensitive("mb")) {
+ Units = 1024 * 1024;
+ SizeString = SizeString.drop_back(2).rtrim();
+ } else if (SizeString.ends_with_insensitive("gb")) {
+ Units = 1024 * 1024 * 1024;
+ SizeString = SizeString.drop_back(2).rtrim();
+ }
+
+ uint64_t SlabSize = 0;
+ if (SizeString.getAsInteger(10, SlabSize))
+ return make_error<StringError>("Invalid numeric format for slab size",
+ inconvertibleErrorCode());
+
+ return SlabSize * Units;
+}
+
+Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+createSharedMemoryManager(SimpleRemoteEPC &SREPC,
+ StringRef SlabAllocateSizeString) {
+ SharedMemoryMapper::SymbolAddrs SAs;
+ if (auto Err = SREPC.getBootstrapSymbols(
+ {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
+ {SAs.Reserve,
+ rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
+ {SAs.Initialize,
+ rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},
+ {SAs.Deinitialize,
+ rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
+ {SAs.Release,
+ rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
+ return std::move(Err);
+
+#ifdef _WIN32
+ size_t SlabSize = 1024 * 1024;
+#else
+ size_t SlabSize = 1024 * 1024 * 1024;
+#endif
+
+ if (!SlabAllocateSizeString.empty()) {
+ if (Expected<uint64_t> S = getSlabAllocSize(SlabAllocateSizeString))
+ SlabSize = *S;
+ else
+ return S.takeError();
+ }
+
+ return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
+ SlabSize, SREPC, SAs);
+}
+
+
+llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
+IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
+ bool UseSharedMemory,
+ llvm::StringRef SlabAllocateSizeString,
+ std::function<void()> CustomizeFork) {
+#ifndef LLVM_ON_UNIX
+ // FIXME: Add support for Windows.
+ return make_error<StringError>("-" + ExecutablePath +
+ " not supported on non-unix platforms",
+ inconvertibleErrorCode());
+#elif !LLVM_ENABLE_THREADS
+ // Out of process mode using SimpleRemoteEPC depends on threads.
+ return make_error<StringError>(
+ "-" + ExecutablePath +
+ " requires threads, but LLVM was built with "
+ "LLVM_ENABLE_THREADS=Off",
+ inconvertibleErrorCode());
+#else
+
+ if (!sys::fs::can_execute(ExecutablePath))
+ return make_error<StringError>(
+ formatv("Specified executor invalid: {0}", ExecutablePath),
+ inconvertibleErrorCode());
+
+ constexpr int ReadEnd = 0;
+ constexpr int WriteEnd = 1;
+
+ // Pipe FDs.
+ int ToExecutor[2];
+ int FromExecutor[2];
+
+ pid_t ChildPID;
+
+ // Create pipes to/from the executor..
+ if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
+ return make_error<StringError>("Unable to create pipe for executor",
+ inconvertibleErrorCode());
+
+ ChildPID = fork();
+
+ if (ChildPID == 0) {
+ // In the child...
+
+ // Close the parent ends of the pipes
+ close(ToExecutor[WriteEnd]);
+ close(FromExecutor[ReadEnd]);
+
+ if (CustomizeFork)
+ CustomizeFork();
+
+ // Execute the child process.
+ std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
+ {
+ ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
+ strcpy(ExecutorPath.get(), ExecutablePath.data());
+
+ std::string FDSpecifierStr("filedescs=");
+ FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
+ FDSpecifierStr += ',';
+ FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
+ FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
+ strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
+ }
+
+ char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
+ int RC = execvp(ExecutorPath.get(), Args);
+ if (RC != 0) {
+ errs() << "unable to launch out-of-process executor \""
+ << ExecutorPath.get() << "\"\n";
+ exit(1);
+ }
+ }
+ // else we're the parent...
+
+ // Close the child ends of the pipes
+ close(ToExecutor[ReadEnd]);
+ close(FromExecutor[WriteEnd]);
+
+ SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
+ if (UseSharedMemory)
+ S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
+ return createSharedMemoryManager(EPC, SlabAllocateSizeString);
+ };
+
+ auto EPCOrErr = SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
+ std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
+ std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+ if (!EPCOrErr)
+ return EPCOrErr.takeError();
+ return std::make_pair(std::move(*EPCOrErr), ChildPID);
+#endif
+}
+
+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
+
+static Expected<int> connectTCPSocketImpl(std::string Host,
+ std::string PortStr) {
+ addrinfo *AI;
+ addrinfo Hints{};
+ Hints.ai_family = AF_INET;
+ Hints.ai_socktype = SOCK_STREAM;
+ Hints.ai_flags = AI_NUMERICSERV;
+
+ if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
+ return make_error<StringError>(
+ formatv("address resolution failed ({0})", strerror(EC)),
+ inconvertibleErrorCode());
+ // Cycle through the returned addrinfo structures and connect to the first
+ // reachable endpoint.
+ int SockFD;
+ addrinfo *Server;
+ for (Server = AI; Server != nullptr; Server = Server->ai_next) {
+ // socket might fail, e.g. if the address family is not supported. Skip to
+ // the next addrinfo structure in such a case.
+ if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
+ continue;
+
+ // If connect returns null, we exit the loop with a working socket.
+ if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
+ break;
+
+ close(SockFD);
+ }
+ freeaddrinfo(AI);
+
+ // If we reached the end of the loop without connecting to a valid endpoint,
+ // dump the last error that was logged in socket() or connect().
+ if (Server == nullptr)
+ return make_error<StringError>("invalid hostname",
+ inconvertibleErrorCode());
+
+ return SockFD;
+}
+#endif
+
+llvm::Expected<std::unique_ptr<SimpleRemoteEPC>>
+IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
+ bool UseSharedMemory,
+ llvm::StringRef SlabAllocateSizeString) {
+#ifndef LLVM_ON_UNIX
+ // FIXME: Add TCP support for Windows.
+ return make_error<StringError>("-" + NetworkAddress +
+ " not supported on non-unix platforms",
+ inconvertibleErrorCode());
+#elif !LLVM_ENABLE_THREADS
+ // Out of process mode using SimpleRemoteEPC depends on threads.
+ return make_error<StringError>(
+ "-" + NetworkAddress +
+ " requires threads, but LLVM was built with "
+ "LLVM_ENABLE_THREADS=Off",
+ inconvertibleErrorCode());
+#else
+
+ auto CreateErr = [NetworkAddress](Twine Details) {
+ return make_error<StringError>(
+ formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
+ Details),
+ inconvertibleErrorCode());
+ };
+
+ StringRef Host, PortStr;
+ std::tie(Host, PortStr) = NetworkAddress.split(':');
+ if (Host.empty())
+ return CreateErr("Host name for -" + NetworkAddress + " can not be empty");
+ if (PortStr.empty())
+ return CreateErr("Port number in -" + NetworkAddress + " can not be empty");
+ int Port = 0;
+ if (PortStr.getAsInteger(10, Port))
+ return CreateErr("Port number '" + PortStr + "' is not a valid integer");
+
+ Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
+ if (!SockFD)
+ return SockFD.takeError();
+
+ SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
+ if (UseSharedMemory)
+ S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
+ return createSharedMemoryManager(EPC, SlabAllocateSizeString);
+ };
+
+ return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
+ std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
+ std::move(S), *SockFD, *SockFD);
+#endif
+}
+
} // namespace clang
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index 71d71bc3883e2..7ad5ef0d31cf3 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -15,10 +15,16 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
#include <memory>
+#include <string>
namespace llvm {
class Error;
@@ -39,6 +45,7 @@ class IncrementalExecutor {
using CtorDtorIterator = llvm::orc::CtorDtorIterator;
std::unique_ptr<llvm::orc::LLJIT> Jit;
llvm::orc::ThreadSafeContext &TSCtx;
+ pid_t OutOfProcessChildPid = -1;
llvm::DenseMap<const PartialTranslationUnit *, llvm::orc::ResourceTrackerSP>
ResourceTrackers;
@@ -51,6 +58,9 @@ class IncrementalExecutor {
IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err);
+ IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
+ llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err,
+ pid_t ChildPid);
virtual ~IncrementalExecutor();
virtual llvm::Error addModule(PartialTranslationUnit &PTU);
@@ -62,8 +72,20 @@ class IncrementalExecutor {
llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; }
+ pid_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; }
+
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB);
+
+ static llvm::Expected<
+ std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
+ launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
+ llvm::StringRef SlabAllocateSizeString,
+ std::function<void()> CustomizeFork = nullptr);
+
+ static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
+ connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
+ llvm::StringRef SlabAllocateSizeString);
};
} // end namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index b9a81bb4ebae1..225aeb260afd0 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -57,8 +57,6 @@
#include "llvm/TargetParser/Host.h"
#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule
-#include <iostream>
-
#define DEBUG_TYPE "clang-repl"
using namespace clang;
@@ -369,7 +367,7 @@ class IncrementalAction : public WrapperFrontendAction {
Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
llvm::Error &ErrOut,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,
- std::unique_ptr<clang::ASTConsumer> Consumer)
+ std::unique_ptr<clang::ASTConsumer> Consumer, OutOfProcessJITConfig OOPConfig)
: JITBuilder(std::move(JITBuilder)) {
CI = std::move(Instance);
llvm::ErrorAsOutParameter EAO(&ErrOut);
@@ -402,7 +400,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
ASTContext &C = CI->getASTContext();
RegisterPTU(C.getTranslationUnitDecl(), std::move(M));
}
- if (llvm::Error Err = CreateExecutor()) {
+ if (llvm::Error Err = CreateExecutor(OOPConfig)) {
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
return;
}
@@ -464,62 +462,65 @@ const char *const Runtimes = R"(
EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
)";
-llvm::ExitOnError ExitOnErr;
-
-std::unique_ptr<llvm::orc::LLJITBuilder>
+llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
+ pid_t childPid = -1;
if (OutOfProcessConfig.OOPExecutor != "") {
// Launch an out-of-process executor locally in a child process.
- EPC = ExitOnErr(launchExecutor(OutOfProcessConfig.OOPExecutor,
+ auto ResultOrErr = IncrementalExecutor::launchExecutor(OutOfProcessConfig.OOPExecutor,
OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString));
+ OutOfProcessConfig.SlabAllocateSizeString, OutOfProcessConfig.CustomizeFork);
+ if (!ResultOrErr)
+ return ResultOrErr.takeError();
+ childPid = ResultOrErr->second;
+ auto EPCOrErr = std::move(ResultOrErr->first);
+ EPC = std::move(EPCOrErr);
} else if (OutOfProcessConfig.OOPExecutorConnect != "") {
- EPC =
- ExitOnErr(connectTCPSocket(OutOfProcessConfig.OOPExecutorConnect,
- OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString));
+ auto EPCOrErr = IncrementalExecutor::connectTCPSocket(OutOfProcessConfig.OOPExecutorConnect,
+ OutOfProcessConfig.UseSharedMemory,
+ OutOfProcessConfig.SlabAllocateSizeString);
+ if (!EPCOrErr)
+ return EPCOrErr.takeError();
+ EPC = std::move(*EPCOrErr);
}
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
if (EPC) {
- JB = ExitOnErr(clang::Interpreter::createLLJITBuilder(
- std::move(EPC), OutOfProcessConfig.OrcRuntimePath));
+ auto JBOrErr = clang::Interpreter::createLLJITBuilder(
+ std::move(EPC), OutOfProcessConfig.OrcRuntimePath);
+ if (!JBOrErr)
+ return JBOrErr.takeError();
+ JB = std::move(*JBOrErr);
}
- return JB;
+ return std::make_pair(std::move(JB), childPid);
}
-
llvm::Expected<std::string>
Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
+ std::optional<std::string> ResourceDir = TC.getRuntimePath();
+
if (!CompilerRTPath) {
return llvm::make_error<llvm::StringError>("CompilerRT path not found",
std::error_code());
}
- llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
- "clang-repl", reinterpret_cast<void *>(&getOrcRuntimePath)));
- // Remove paths until you find /build at last
- while (!(llvm::sys::path::filename(BasePath) == "build") &&
- !BasePath.empty()) {
- llvm::sys::path::remove_filename(BasePath);
- }
- llvm::sys::path::append(BasePath, *CompilerRTPath);
-
- if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt.a")) {
- llvm::sys::path::append(BasePath, "liborc_rt.a");
- } else if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt_osx.a")) {
- llvm::sys::path::append(BasePath, "liborc_rt_osx.a");
- } else if (llvm::sys::fs::exists(BasePath.str().str() +
- "/liborc_rt-x86_64.a")) {
- llvm::sys::path::append(BasePath, "liborc_rt-x86_64.a");
- } else {
- return llvm::make_error<llvm::StringError>("OrcRuntime library not found",
- std::error_code());
+ const std::array<const char *, 3> OrcRTLibNames = {
+ "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"};
+
+ for (const char *LibName : OrcRTLibNames) {
+ llvm::SmallString<256> CandidatePath((*CompilerRTPath).c_str());
+ llvm::sys::path::append(CandidatePath, LibName);
+
+ if (llvm::sys::fs::exists(CandidatePath)) {
+ return CandidatePath.str().str();
+ }
}
- return BasePath.str().str();
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("OrcRuntime library not found in: ") + (*CompilerRTPath),
+ std::error_code());
}
llvm::Expected<std::unique_ptr<Interpreter>>
@@ -535,8 +536,9 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
const llvm::Triple &Triple = TI.getTriple();
DiagnosticsEngine &Diags = CI->getDiagnostics();
- driver::Driver Driver("clang", Triple.str(), Diags);
-
+ std::string BinaryName =
+ llvm::sys::fs::getMainExecutable(nullptr, nullptr);
+ driver::Driver Driver(BinaryName, Triple.str(), Diags);
std::vector<const char *> Args = {"clang", "--version"};
std::unique_ptr<clang::driver::Compilation> C(
Driver.BuildCompilation(Args));
@@ -545,30 +547,30 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
"Failed to create driver compilation for out-of-process JIT",
std::error_code());
}
+ if (OutOfProcessConfig->OrcRuntimePath == "") {
+ const clang::driver::ToolChain &TC = C->getDefaultToolChain();
- const clang::driver::ToolChain &TC = C->getDefaultToolChain();
+ auto OrcRuntimePathOrErr = getOrcRuntimePath(TC);
+ if (!OrcRuntimePathOrErr) {
+ return OrcRuntimePathOrErr.takeError();
+ }
- auto OrcRuntimePathOrErr = getOrcRuntimePath(TC);
- if (!OrcRuntimePathOrErr) {
- return OrcRuntimePathOrErr.takeError();
+ OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
}
- OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
- JB = outOfProcessJITBuilder(*OutOfProcessConfig);
}
auto Interp = std::unique_ptr<Interpreter>(
- new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr));
- if (Err)
- return std::move(Err);
+ new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
+ OutOfProcessConfig ? *OutOfProcessConfig
+ : OutOfProcessJITConfig()));
+ if (auto E = std::move(Err))
+ return std::move(E);
// Add runtime code and set a marker to hide it from user code. Undo will not
// go through that.
- Err = Interp->ParseAndExecute(Runtimes);
- if (Err)
- return std::move(Err);
-
- Interp->markUserCodeStart();
+ if (auto E = Interp->ParseAndExecute(Runtimes))
+ return std::move(E);
return std::move(Interp);
}
@@ -674,6 +676,12 @@ Interpreter::RegisterPTU(TranslationUnitDecl *TU,
return LastPTU;
}
+pid_t Interpreter::getOutOfProcessExecutorPID() const {
+ if (IncrExecutor)
+ return IncrExecutor->getOutOfProcessChildPid();
+ return -1;
+}
+
llvm::Expected<PartialTranslationUnit &>
Interpreter::Parse(llvm::StringRef Code) {
// If we have a device parser, parse it first. The generated code will be
@@ -742,7 +750,7 @@ Interpreter::createLLJITBuilder(
return std::move(*JB);
}
-llvm::Error Interpreter::CreateExecutor() {
+llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
if (IncrExecutor)
return llvm::make_error<llvm::StringError>("Operation failed. "
"Execution engine exists",
@@ -751,6 +759,21 @@ llvm::Error Interpreter::CreateExecutor() {
return llvm::make_error<llvm::StringError>("Operation failed. "
"No code generator available",
std::error_code());
+ pid_t OOPChildPid = -1;
+ if (OOPConfig.IsOutOfProcess) {
+ if (!JITBuilder) {
+ auto ResOrErr = outOfProcessJITBuilder(OOPConfig);
+ if (!ResOrErr)
+ return ResOrErr.takeError();
+ JITBuilder = std::move(ResOrErr->first);
+ OOPChildPid = ResOrErr->second;
+ }
+ if (!JITBuilder)
+ return llvm::make_error<llvm::StringError>(
+ "Operation failed. No LLJITBuilder for out-of-process JIT",
+ std::error_code());
+ }
+
if (!JITBuilder) {
const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
auto JTMB = createJITTargetMachineBuilder(TT);
@@ -767,7 +790,7 @@ llvm::Error Interpreter::CreateExecutor() {
auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
#else
auto Executor =
- std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
+ std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err, OOPChildPid);
#endif
if (!Err)
IncrExecutor = std::move(Executor);
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 29939610ec6f6..126312fbacf61 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -37,7 +37,6 @@
#include "llvm/TargetParser/Triple.h"
#include <optional>
-#include <iostream>
#include <string>
#include <vector>
@@ -280,8 +279,8 @@ int main(int argc, const char **argv) {
ExitOnErr(sanitizeOopArguments(argv[0]));
clang::OutOfProcessJITConfig OutOfProcessConfig;
- OutOfProcessConfig.IsOutOfProcess = !OOPExecutor.getNumOccurrences() ||
- !OOPExecutorConnect.getNumOccurrences();
+ OutOfProcessConfig.IsOutOfProcess = !OOPExecutor.empty() ||
+ !OOPExecutorConnect.empty();
OutOfProcessConfig.OOPExecutor = OOPExecutor;
OutOfProcessConfig.SlabAllocateSizeString = SlabAllocateSizeString;
OutOfProcessConfig.UseSharedMemory = UseSharedMemory;
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index bf1c9f355578b..81f44ee591166 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -41,6 +41,20 @@
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.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/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"
#include "gmock/gmock.h"
@@ -73,6 +87,47 @@ static std::string getExecutorPath() {
return ExecutorPath.str().str();
}
+static std::string getOrcRuntimePath() {
+ 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();
+
+ // Fallback: Calculate base path similar to clang-repl logic.
+ llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
+ "clang", reinterpret_cast<void *>(&getOrcRuntimePath)));
+ removePathComponent(5, BasePath);
+
+ // Append libdir, clang, and version.
+
+ llvm::sys::path::append(BasePath, *CompilerRTPath);
+
+ std::cout << "BasePath: " << BasePath.str().str() << "\n";
+
+ if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt_osx.a")) {
+ return BasePath.str().str() + "/liborc_rt_osx.a";
+ } else if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt.a")) {
+ return BasePath.str().str() + "/liborc_rt.a";
+ } else if (llvm::sys::fs::exists(BasePath.str().str() +
+ "/liborc_rt-x86_64.a")) {
+ return BasePath.str().str() + "liborc_rt-x86_64.a";
+ } else
+ return "";
+}
+
static std::unique_ptr<Interpreter>
createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
DiagnosticConsumer *Client = nullptr) {
@@ -89,6 +144,10 @@ createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
OutOfProcessConfig.UseSharedMemory = false;
OutOfProcessConfig.SlabAllocateSizeString = "";
OutOfProcessConfig.IsOutOfProcess = true;
+ OutOfProcessConfig.OrcRuntimePath = getOrcRuntimePath();
+
+ std::cout << "OrcRuntimePath: " << OutOfProcessConfig.OrcRuntimePath
+ << "\n";
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
>From e90df553fef89544b875e7147d2c95dd39c9b31c Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 31 Aug 2025 22:44:35 +0530
Subject: [PATCH 23/35] RemoteJITUtils shifted to IncrementalExecutor
---
clang/include/clang/Interpreter/Interpreter.h | 6 ++--
clang/lib/Interpreter/IncrementalExecutor.cpp | 27 +++++++---------
clang/lib/Interpreter/Interpreter.cpp | 32 +++++++++----------
clang/test/Interpreter/out-of-process.cpp | 2 +-
clang/tools/clang-repl/ClangRepl.cpp | 4 +--
.../OutOfProcessInterpreterTests.cpp | 4 +--
6 files changed, 37 insertions(+), 38 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index f9b7e9ffaec69..7ba205ead019d 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -126,7 +126,8 @@ class Interpreter {
// Derived classes can use an extended interface of the Interpreter.
Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
- std::unique_ptr<clang::ASTConsumer> Consumer = nullptr, OutOfProcessJITConfig OOPConfig = {});
+ std::unique_ptr<clang::ASTConsumer> Consumer = nullptr,
+ OutOfProcessJITConfig OOPConfig = {});
// Create the internal IncrementalExecutor, or re-create it after calling
// ResetExecutor().
@@ -147,7 +148,8 @@ class Interpreter {
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
llvm::StringRef OrcRuntimePath);
- static llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
+ static llvm::Expected<
+ std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig);
static llvm::Expected<std::string>
getOrcRuntimePath(const driver::ToolChain &TC);
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 6f77b18b5b845..bc1c8e68461da 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -15,29 +15,28 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Interpreter/PartialTranslationUnit.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
-#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
-#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetSelect.h"
#ifdef LLVM_ON_UNIX
#include <netdb.h>
@@ -90,8 +89,7 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder,
- llvm::Error &Err,
- pid_t ChildPid)
+ llvm::Error &Err, pid_t ChildPid)
: TSCtx(TSC), OutOfProcessChildPid(ChildPid) {
using namespace llvm::orc;
llvm::ErrorAsOutParameter EAO(&Err);
@@ -210,10 +208,9 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
SlabSize, SREPC, SAs);
}
-
llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
- bool UseSharedMemory,
+ bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString,
std::function<void()> CustomizeFork) {
#ifndef LLVM_ON_UNIX
@@ -348,7 +345,7 @@ static Expected<int> connectTCPSocketImpl(std::string Host,
llvm::Expected<std::unique_ptr<SimpleRemoteEPC>>
IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
- bool UseSharedMemory,
+ bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString) {
#ifndef LLVM_ON_UNIX
// FIXME: Add TCP support for Windows.
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 225aeb260afd0..a5985cf1fc7a7 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -367,7 +367,8 @@ class IncrementalAction : public WrapperFrontendAction {
Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
llvm::Error &ErrOut,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,
- std::unique_ptr<clang::ASTConsumer> Consumer, OutOfProcessJITConfig OOPConfig)
+ std::unique_ptr<clang::ASTConsumer> Consumer,
+ OutOfProcessJITConfig OOPConfig)
: JITBuilder(std::move(JITBuilder)) {
CI = std::move(Instance);
llvm::ErrorAsOutParameter EAO(&ErrOut);
@@ -468,18 +469,20 @@ Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
pid_t childPid = -1;
if (OutOfProcessConfig.OOPExecutor != "") {
// Launch an out-of-process executor locally in a child process.
- auto ResultOrErr = IncrementalExecutor::launchExecutor(OutOfProcessConfig.OOPExecutor,
- OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString, OutOfProcessConfig.CustomizeFork);
+ auto ResultOrErr = IncrementalExecutor::launchExecutor(
+ OutOfProcessConfig.OOPExecutor, OutOfProcessConfig.UseSharedMemory,
+ OutOfProcessConfig.SlabAllocateSizeString,
+ OutOfProcessConfig.CustomizeFork);
if (!ResultOrErr)
return ResultOrErr.takeError();
childPid = ResultOrErr->second;
auto EPCOrErr = std::move(ResultOrErr->first);
EPC = std::move(EPCOrErr);
} else if (OutOfProcessConfig.OOPExecutorConnect != "") {
- auto EPCOrErr = IncrementalExecutor::connectTCPSocket(OutOfProcessConfig.OOPExecutorConnect,
- OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString);
+ auto EPCOrErr = IncrementalExecutor::connectTCPSocket(
+ OutOfProcessConfig.OOPExecutorConnect,
+ OutOfProcessConfig.UseSharedMemory,
+ OutOfProcessConfig.SlabAllocateSizeString);
if (!EPCOrErr)
return EPCOrErr.takeError();
EPC = std::move(*EPCOrErr);
@@ -536,8 +539,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
const llvm::Triple &Triple = TI.getTriple();
DiagnosticsEngine &Diags = CI->getDiagnostics();
- std::string BinaryName =
- llvm::sys::fs::getMainExecutable(nullptr, nullptr);
+ std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, nullptr);
driver::Driver Driver(BinaryName, Triple.str(), Diags);
std::vector<const char *> Args = {"clang", "--version"};
std::unique_ptr<clang::driver::Compilation> C(
@@ -557,13 +559,11 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
}
-
}
- auto Interp = std::unique_ptr<Interpreter>(
- new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
- OutOfProcessConfig ? *OutOfProcessConfig
- : OutOfProcessJITConfig()));
+ auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
+ std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
+ OutOfProcessConfig ? *OutOfProcessConfig : OutOfProcessJITConfig()));
if (auto E = std::move(Err))
return std::move(E);
@@ -789,8 +789,8 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
#ifdef __EMSCRIPTEN__
auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
#else
- auto Executor =
- std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err, OOPChildPid);
+ auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder,
+ Err, OOPChildPid);
#endif
if (!Err)
IncrExecutor = std::move(Executor);
diff --git a/clang/test/Interpreter/out-of-process.cpp b/clang/test/Interpreter/out-of-process.cpp
index 6922ca6e82053..2c576de468f6e 100644
--- a/clang/test/Interpreter/out-of-process.cpp
+++ b/clang/test/Interpreter/out-of-process.cpp
@@ -1,4 +1,4 @@
-// REQUIRES: host-supports-jit, host-supports-out-of-process-jit, x86_64-linux
+// REQUIRES: host-supports-jit, host-supports-out-of-process-jit, x86_64
// RUN: cat %s | clang-repl -oop-executor -orc-runtime | FileCheck %s
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 126312fbacf61..044a93b4b5a28 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -279,8 +279,8 @@ int main(int argc, const char **argv) {
ExitOnErr(sanitizeOopArguments(argv[0]));
clang::OutOfProcessJITConfig OutOfProcessConfig;
- OutOfProcessConfig.IsOutOfProcess = !OOPExecutor.empty() ||
- !OOPExecutorConnect.empty();
+ OutOfProcessConfig.IsOutOfProcess =
+ !OOPExecutor.empty() || !OOPExecutorConnect.empty();
OutOfProcessConfig.OOPExecutor = OOPExecutor;
OutOfProcessConfig.SlabAllocateSizeString = SlabAllocateSizeString;
OutOfProcessConfig.UseSharedMemory = UseSharedMemory;
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 81f44ee591166..68b3fcd356db8 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -146,8 +146,8 @@ createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
OutOfProcessConfig.IsOutOfProcess = true;
OutOfProcessConfig.OrcRuntimePath = getOrcRuntimePath();
- std::cout << "OrcRuntimePath: " << OutOfProcessConfig.OrcRuntimePath
- << "\n";
+
+ std::cout << "OrcRuntimePath: " << OutOfProcessConfig.OrcRuntimePath << "\n";
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
>From 521be31ba015e3d20aa839033c573df5aabe677b Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 31 Aug 2025 23:38:05 +0530
Subject: [PATCH 24/35] Removed custom fork in launchExecutor lambda
---
clang/include/clang/Interpreter/Interpreter.h | 33 +++-
.../clang/Interpreter/OutOfProcessJITConfig.h | 48 -----
clang/lib/Driver/ToolChain.cpp | 52 ++---
clang/lib/Interpreter/CMakeLists.txt | 1 -
clang/lib/Interpreter/IncrementalExecutor.cpp | 8 +-
clang/lib/Interpreter/IncrementalExecutor.h | 7 +-
clang/lib/Interpreter/Interpreter.cpp | 10 +-
clang/tools/clang-repl/ClangRepl.cpp | 5 +-
clang/unittests/Interpreter/CMakeLists.txt | 7 -
.../unittests/Interpreter/InterpreterTest.cpp | 1 -
.../OutOfProcessInterpreterTests.cpp | 177 ------------------
11 files changed, 72 insertions(+), 277 deletions(-)
delete mode 100644 clang/include/clang/Interpreter/OutOfProcessJITConfig.h
delete mode 100644 clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 7ba205ead019d..e66e4c77e9a66 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -16,7 +16,6 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/Driver/ToolChain.h"
-#include "clang/Interpreter/OutOfProcessJITConfig.h"
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Interpreter/Value.h"
@@ -122,16 +121,39 @@ class Interpreter {
/// An optional compiler instance for CUDA offloading
std::unique_ptr<CompilerInstance> DeviceCI;
+public:
+ struct OutOfProcessJITConfig {
+ /// Indicates whether out-of-process JIT execution is enabled.
+ bool IsOutOfProcess;
+ /// Path to the out-of-process JIT executor.
+ std::string OOPExecutor;
+ std::string OOPExecutorConnect;
+ /// Indicates whether to use shared memory for communication.
+ bool UseSharedMemory;
+ /// String representing the slab allocation size for memory management.
+ std::string SlabAllocateSizeString;
+ /// Path to the ORC runtime library.
+ std::string OrcRuntimePath;
+
+ OutOfProcessJITConfig()
+ : IsOutOfProcess(false),
+ OOPExecutor(""),
+ OOPExecutorConnect(""),
+ UseSharedMemory(false),
+ SlabAllocateSizeString(""),
+ OrcRuntimePath("") {}
+ };
+
protected:
// Derived classes can use an extended interface of the Interpreter.
Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
std::unique_ptr<clang::ASTConsumer> Consumer = nullptr,
- OutOfProcessJITConfig OOPConfig = {});
+ OutOfProcessJITConfig OOPConfig = OutOfProcessJITConfig());
// Create the internal IncrementalExecutor, or re-create it after calling
// ResetExecutor().
- llvm::Error CreateExecutor(OutOfProcessJITConfig OOPConfig = {});
+ llvm::Error CreateExecutor(OutOfProcessJITConfig OOPConfig = OutOfProcessJITConfig());
// Delete the internal IncrementalExecutor. This causes a hard shutdown of the
// JIT engine. In particular, it doesn't run cleanup or destructors.
@@ -148,11 +170,13 @@ class Interpreter {
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
llvm::StringRef OrcRuntimePath);
+#ifndef _WIN32
static llvm::Expected<
std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig);
static llvm::Expected<std::string>
getOrcRuntimePath(const driver::ToolChain &TC);
+#endif
const ASTContext &getASTContext() const;
ASTContext &getASTContext();
const CompilerInstance *getCompilerInstance() const;
@@ -187,8 +211,9 @@ class Interpreter {
PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
std::unique_ptr<llvm::Module> M = {},
IncrementalAction *Action = nullptr);
-
+#ifndef _WIN32
pid_t getOutOfProcessExecutorPID() const;
+#endif
private:
size_t getEffectivePTUSize() const;
diff --git a/clang/include/clang/Interpreter/OutOfProcessJITConfig.h b/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
deleted file mode 100644
index 7d950abc80f4e..0000000000000
--- a/clang/include/clang/Interpreter/OutOfProcessJITConfig.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//===-- OutOfProcessJITConfig.h - Struct for Out-Of-Process JIT--*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a struct that holds configuration options for
-// out-of-process JIT execution.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INTERPRETER_OUTOFPROCESSJITCONFIG_H
-#define LLVM_CLANG_INTERPRETER_OUTOFPROCESSJITCONFIG_H
-
-#include <functional>
-#include <string>
-#include <utility>
-
-namespace clang {
-
-/// \brief Configuration options for out-of-process JIT execution.
-struct OutOfProcessJITConfig {
- /// Indicates whether out-of-process JIT execution is enabled.
- bool IsOutOfProcess = false;
-
- /// Path to the out-of-process JIT executor.
- std::string OOPExecutor;
-
- std::string OOPExecutorConnect;
-
- /// Indicates whether to use shared memory for communication.
- bool UseSharedMemory;
-
- /// String representing the slab allocation size for memory management.
- std::string SlabAllocateSizeString;
-
- /// Path to the ORC runtime library.
- std::string OrcRuntimePath;
-
- /// Custom lambda function to customize the fork behavior.
- std::function<void()> CustomizeFork = nullptr;
-};
-
-} // namespace clang
-
-#endif // LLVM_CLANG_INTERPRETER_OUTOFPROCESSJITCONFIG_H
\ No newline at end of file
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index d00fffaf06340..7667dbddb0ca2 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -167,9 +167,10 @@ static void processMultilibCustomFlags(Multilib::flags_list &List,
}
}
-static void getAArch64MultilibFlags(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- Multilib::flags_list &Result) {
+static void getAArch64MultilibFlags(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ Multilib::flags_list &Result) {
std::vector<StringRef> Features;
tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features,
/*ForAS=*/false,
@@ -499,7 +500,8 @@ static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
return DS;
}
-ParsedClangName ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
+ParsedClangName
+ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
std::string ProgName = normalizeProgramName(PN);
size_t SuffixPos;
const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
@@ -510,8 +512,8 @@ ParsedClangName ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
size_t LastComponent = ProgName.rfind('-', SuffixPos);
if (LastComponent == std::string::npos)
return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
- std::string ModeSuffix =
- ProgName.substr(LastComponent + 1, SuffixEnd - LastComponent - 1);
+ std::string ModeSuffix = ProgName.substr(LastComponent + 1,
+ SuffixEnd - LastComponent - 1);
// Infer target from the prefix.
StringRef Prefix(ProgName);
@@ -568,7 +570,9 @@ Tool *ToolChain::getFlang() const {
return Flang.get();
}
-Tool *ToolChain::buildAssembler() const { return new tools::ClangAs(*this); }
+Tool *ToolChain::buildAssembler() const {
+ return new tools::ClangAs(*this);
+}
Tool *ToolChain::buildLinker() const {
llvm_unreachable("Linking is not supported by this toolchain");
@@ -1073,10 +1077,8 @@ bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
}
Tool *ToolChain::SelectTool(const JobAction &JA) const {
- if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA))
- return getFlang();
- if (getDriver().ShouldUseClangCompiler(JA))
- return getClang();
+ if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
+ if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
Action::ActionClass AC = JA.getKind();
if (AC == Action::AssembleJobClass && useIntegratedAs() &&
!getTriple().isOSAIX())
@@ -1098,7 +1100,7 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
// considered as the linker flavor, e.g. "bfd", "gold", or "lld".
- const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+ const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
StringRef UseLinker = A ? A->getValue() : getDriver().getPreferredLinker();
// --ld-path= takes precedence over -fuse-ld= and specifies the executable
@@ -1183,7 +1185,9 @@ types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
return id;
}
-bool ToolChain::HasNativeLLVMSupport() const { return false; }
+bool ToolChain::HasNativeLLVMSupport() const {
+ return false;
+}
bool ToolChain::isCrossCompiling() const {
llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
@@ -1195,8 +1199,7 @@ bool ToolChain::isCrossCompiling() const {
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
- getArch() != llvm::Triple::armeb &&
- getArch() != llvm::Triple::thumbeb;
+ getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
default:
return HostTriple.getArch() != getArch();
}
@@ -1285,7 +1288,9 @@ std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
return ComputeLLVMTriple(Args, InputType);
}
-std::string ToolChain::computeSysRoot() const { return D.SysRoot; }
+std::string ToolChain::computeSysRoot() const {
+ return D.SysRoot;
+}
void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
@@ -1309,12 +1314,12 @@ void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
}
-ToolChain::RuntimeLibType
-ToolChain::GetRuntimeLibType(const ArgList &Args) const {
+ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
+ const ArgList &Args) const {
if (runtimeLibType)
return *runtimeLibType;
- const Arg *A = Args.getLastArg(options::OPT_rtlib_EQ);
+ const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
// Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
@@ -1335,8 +1340,8 @@ ToolChain::GetRuntimeLibType(const ArgList &Args) const {
return *runtimeLibType;
}
-ToolChain::UnwindLibType
-ToolChain::GetUnwindLibType(const ArgList &Args) const {
+ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
+ const ArgList &Args) const {
if (unwindLibType)
return *unwindLibType;
@@ -1371,8 +1376,7 @@ ToolChain::GetUnwindLibType(const ArgList &Args) const {
return *unwindLibType;
}
-ToolChain::CXXStdlibType
-ToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
if (cxxStdlibType)
return *cxxStdlibType;
@@ -1544,7 +1548,7 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
void ToolChain::AddFilePathLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
for (const auto &LibPath : getFilePaths())
- if (LibPath.length() > 0)
+ if(LibPath.length() > 0)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
}
diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt
index 70de4a2aaa541..2766293b8b3cb 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -27,7 +27,6 @@ add_clang_library(clangInterpreter
Interpreter.cpp
InterpreterValuePrinter.cpp
InterpreterUtils.cpp
- RemoteJITUtils.cpp
Value.cpp
InterpreterValuePrinter.cpp
${WASM_SRC}
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index bc1c8e68461da..28166c40e70cf 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -208,11 +208,11 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
SlabSize, SREPC, SAs);
}
+#ifndef _WIN32
llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString,
- std::function<void()> CustomizeFork) {
+ llvm::StringRef SlabAllocateSizeString) {
#ifndef LLVM_ON_UNIX
// FIXME: Add support for Windows.
return make_error<StringError>("-" + ExecutablePath +
@@ -255,9 +255,6 @@ IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
close(ToExecutor[WriteEnd]);
close(FromExecutor[ReadEnd]);
- if (CustomizeFork)
- CustomizeFork();
-
// Execute the child process.
std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
{
@@ -393,5 +390,6 @@ IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
std::move(S), *SockFD, *SockFD);
#endif
}
+#endif // _WIN32
} // namespace clang
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index 7ad5ef0d31cf3..ff76cc0ed47b0 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -72,20 +72,23 @@ class IncrementalExecutor {
llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; }
+#ifndef _WIN32
pid_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; }
+#endif
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB);
+#ifndef _WIN32
static llvm::Expected<
std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString,
- std::function<void()> CustomizeFork = nullptr);
+ llvm::StringRef SlabAllocateSizeString);
static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString);
+#endif
};
} // end namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index a5985cf1fc7a7..180fb4751b58f 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -41,8 +41,6 @@
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/FrontendTool/Utils.h"
#include "clang/Interpreter/Interpreter.h"
-#include "clang/Interpreter/OutOfProcessJITConfig.h"
-#include "clang/Interpreter/RemoteJITUtils.h"
#include "clang/Interpreter/Value.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/Lookup.h"
@@ -463,6 +461,7 @@ const char *const Runtimes = R"(
EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
)";
+#ifndef _WIN32
llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
@@ -471,8 +470,7 @@ Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
// Launch an out-of-process executor locally in a child process.
auto ResultOrErr = IncrementalExecutor::launchExecutor(
OutOfProcessConfig.OOPExecutor, OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString,
- OutOfProcessConfig.CustomizeFork);
+ OutOfProcessConfig.SlabAllocateSizeString);
if (!ResultOrErr)
return ResultOrErr.takeError();
childPid = ResultOrErr->second;
@@ -499,6 +497,7 @@ Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
return std::make_pair(std::move(JB), childPid);
}
+
llvm::Expected<std::string>
Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
@@ -525,6 +524,7 @@ Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
llvm::Twine("OrcRuntime library not found in: ") + (*CompilerRTPath),
std::error_code());
}
+#endif
llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::create(std::unique_ptr<CompilerInstance> CI,
@@ -759,6 +759,7 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
return llvm::make_error<llvm::StringError>("Operation failed. "
"No code generator available",
std::error_code());
+#ifndef _WIN32
pid_t OOPChildPid = -1;
if (OOPConfig.IsOutOfProcess) {
if (!JITBuilder) {
@@ -773,6 +774,7 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
"Operation failed. No LLJITBuilder for out-of-process JIT",
std::error_code());
}
+#endif
if (!JITBuilder) {
const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 044a93b4b5a28..e1f2f465e5f38 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -10,8 +10,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Interpreter/RemoteJITUtils.h"
-
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@@ -19,7 +17,6 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Interpreter/CodeCompletion.h"
#include "clang/Interpreter/Interpreter.h"
-#include "clang/Interpreter/OutOfProcessJITConfig.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
@@ -278,7 +275,7 @@ int main(int argc, const char **argv) {
ExitOnErr(sanitizeOopArguments(argv[0]));
- clang::OutOfProcessJITConfig OutOfProcessConfig;
+ clang::Interpreter::OutOfProcessJITConfig OutOfProcessConfig;
OutOfProcessConfig.IsOutOfProcess =
!OOPExecutor.empty() || !OOPExecutorConnect.empty();
OutOfProcessConfig.OOPExecutor = OOPExecutor;
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 7e44b5a7f954d..dd88a95b6b5ec 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -37,13 +37,6 @@ set(CLANG_REPL_TEST_SOURCES
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}
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 79c8c63105a76..62e9d03f634b0 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -20,7 +20,6 @@
#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"
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
deleted file mode 100644
index 68b3fcd356db8..0000000000000
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-//===- 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.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Unit tests for Clang's Interpreter library.
-//
-//===----------------------------------------------------------------------===//
-
-#include "InterpreterTestFixture.h"
-
-#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"
-#include "clang/Interpreter/OutOfProcessJITConfig.h"
-#include "clang/Interpreter/RemoteJITUtils.h"
-#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 "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/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"
-
-#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 {
-
-using Args = std::vector<const char *>;
-
-static void removePathComponent(unsigned N, llvm::SmallString<256> &Path) {
- for (unsigned 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)));
- removePathComponent(5, ExecutorPath);
- llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
- return ExecutorPath.str().str();
-}
-
-static std::string getOrcRuntimePath() {
- 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();
-
- // Fallback: Calculate base path similar to clang-repl logic.
- llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
- "clang", reinterpret_cast<void *>(&getOrcRuntimePath)));
- removePathComponent(5, BasePath);
-
- // Append libdir, clang, and version.
-
- llvm::sys::path::append(BasePath, *CompilerRTPath);
-
- std::cout << "BasePath: " << BasePath.str().str() << "\n";
-
- if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt_osx.a")) {
- return BasePath.str().str() + "/liborc_rt_osx.a";
- } else if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt.a")) {
- return BasePath.str().str() + "/liborc_rt.a";
- } else if (llvm::sys::fs::exists(BasePath.str().str() +
- "/liborc_rt-x86_64.a")) {
- return BasePath.str().str() + "liborc_rt-x86_64.a";
- } else
- return "";
-}
-
-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);
-
- OutOfProcessJITConfig OutOfProcessConfig;
- OutOfProcessConfig.OOPExecutor = getExecutorPath();
- OutOfProcessConfig.UseSharedMemory = false;
- OutOfProcessConfig.SlabAllocateSizeString = "";
- OutOfProcessConfig.IsOutOfProcess = true;
- OutOfProcessConfig.OrcRuntimePath = getOrcRuntimePath();
-
-
- std::cout << "OrcRuntimePath: " << OutOfProcessConfig.OrcRuntimePath << "\n";
-
- std::unique_ptr<llvm::orc::LLJITBuilder> JB;
-
- return cantFail(
- clang::Interpreter::create(std::move(CI), OutOfProcessConfig));
-}
-
-static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
- return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
-}
-
-TEST_F(InterpreterTestBase, 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
>From 44cde65fa335f093254c5f3f7564d87a28e21168 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Sun, 31 Aug 2025 23:43:50 +0530
Subject: [PATCH 25/35] refactoring changes
---
clang/include/clang/Interpreter/Interpreter.h | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index e66e4c77e9a66..6a099ffb06621 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -136,12 +136,9 @@ class Interpreter {
std::string OrcRuntimePath;
OutOfProcessJITConfig()
- : IsOutOfProcess(false),
- OOPExecutor(""),
- OOPExecutorConnect(""),
- UseSharedMemory(false),
- SlabAllocateSizeString(""),
- OrcRuntimePath("") {}
+ : IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""),
+ UseSharedMemory(false), SlabAllocateSizeString(""),
+ OrcRuntimePath("") {}
};
protected:
@@ -153,7 +150,8 @@ class Interpreter {
// Create the internal IncrementalExecutor, or re-create it after calling
// ResetExecutor().
- llvm::Error CreateExecutor(OutOfProcessJITConfig OOPConfig = OutOfProcessJITConfig());
+ llvm::Error
+ CreateExecutor(OutOfProcessJITConfig OOPConfig = OutOfProcessJITConfig());
// Delete the internal IncrementalExecutor. This causes a hard shutdown of the
// JIT engine. In particular, it doesn't run cleanup or destructors.
>From c49ec552bf3eec523a3e91631ca10c2403e998fb Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 00:21:11 +0530
Subject: [PATCH 26/35] Refactoring
---
clang/include/clang/Interpreter/Interpreter.h | 4 ---
.../clang/Interpreter/RemoteJITUtils.h | 3 +--
clang/lib/Interpreter/IncrementalExecutor.h | 2 ++
clang/lib/Interpreter/Interpreter.cpp | 26 ++-----------------
clang/lib/Interpreter/RemoteJITUtils.cpp | 11 ++------
5 files changed, 7 insertions(+), 39 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 7f23c56db1976..4abf721c6e222 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -200,10 +200,6 @@ class Interpreter {
llvm::Expected<llvm::orc::ExecutorAddr>
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
- std::unique_ptr<llvm::Module> GenModule(IncrementalAction *Action = nullptr);
- PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
- std::unique_ptr<llvm::Module> M = {},
- IncrementalAction *Action = nullptr);
#ifndef _WIN32
pid_t getOutOfProcessExecutorPID() const;
#endif
diff --git a/clang/include/clang/Interpreter/RemoteJITUtils.h b/clang/include/clang/Interpreter/RemoteJITUtils.h
index bc71232a5cad8..67425c812381c 100644
--- a/clang/include/clang/Interpreter/RemoteJITUtils.h
+++ b/clang/include/clang/Interpreter/RemoteJITUtils.h
@@ -26,8 +26,7 @@
llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString,
- std::function<void()> CustomizeFork = nullptr);
+ llvm::StringRef SlabAllocateSizeString);
/// Create a JITLinkExecutor that connects to the given network address
/// through a TCP socket. A valid NetworkAddress provides hostname and port,
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index ff76cc0ed47b0..3f33eb77f42d4 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -45,7 +45,9 @@ class IncrementalExecutor {
using CtorDtorIterator = llvm::orc::CtorDtorIterator;
std::unique_ptr<llvm::orc::LLJIT> Jit;
llvm::orc::ThreadSafeContext &TSCtx;
+#ifndef _WIN32
pid_t OutOfProcessChildPid = -1;
+#endif
llvm::DenseMap<const PartialTranslationUnit *, llvm::orc::ResourceTrackerSP>
ResourceTrackers;
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 93fde9f40ff44..398a9c27eadcb 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -539,35 +539,13 @@ size_t Interpreter::getEffectivePTUSize() const {
return PTUs.size() - InitPTUSize;
}
-PartialTranslationUnit &
-Interpreter::RegisterPTU(TranslationUnitDecl *TU,
- std::unique_ptr<llvm::Module> M /*={}*/,
- IncrementalAction *Action) {
- PTUs.emplace_back(PartialTranslationUnit());
- PartialTranslationUnit &LastPTU = PTUs.back();
- LastPTU.TUPart = TU;
-
- if (!M)
- M = GenModule(Action);
-
- assert((!getCodeGen(Action) || M) &&
- "Must have a llvm::Module at this point");
-
- LastPTU.TheModule = std::move(M);
- LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1
- << ": [TU=" << LastPTU.TUPart);
- if (LastPTU.TheModule)
- LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " ("
- << LastPTU.TheModule->getName() << ")");
- LLVM_DEBUG(llvm::dbgs() << "]\n");
- return LastPTU;
-}
-
+#ifndef _WIN32
pid_t Interpreter::getOutOfProcessExecutorPID() const {
if (IncrExecutor)
return IncrExecutor->getOutOfProcessChildPid();
return -1;
}
+#endif
llvm::Expected<PartialTranslationUnit &>
Interpreter::Parse(llvm::StringRef Code) {
diff --git a/clang/lib/Interpreter/RemoteJITUtils.cpp b/clang/lib/Interpreter/RemoteJITUtils.cpp
index c100f46931b6d..fe69a84ec79d4 100644
--- a/clang/lib/Interpreter/RemoteJITUtils.cpp
+++ b/clang/lib/Interpreter/RemoteJITUtils.cpp
@@ -93,14 +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.
+// Launches an out-of-process executor for remote JIT.
Expected<std::unique_ptr<SimpleRemoteEPC>>
launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString,
- std::function<void()> CustomizeFork) {
+ llvm::StringRef SlabAllocateSizeString) {
#ifndef LLVM_ON_UNIX
// FIXME: Add support for Windows.
return make_error<StringError>("-" + ExecutablePath +
@@ -143,9 +139,6 @@ launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
close(ToExecutor[WriteEnd]);
close(FromExecutor[ReadEnd]);
- if (CustomizeFork)
- CustomizeFork();
-
// Execute the child process.
std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
{
>From a6a05ead95e2ae338ac49b85874efa692d5f6a80 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 00:24:57 +0530
Subject: [PATCH 27/35] Deleted RemoteJITUtils.h & .cpp
---
.../clang/Interpreter/RemoteJITUtils.h | 47 ---
clang/lib/Interpreter/RemoteJITUtils.cpp | 289 ------------------
2 files changed, 336 deletions(-)
delete mode 100644 clang/include/clang/Interpreter/RemoteJITUtils.h
delete mode 100644 clang/lib/Interpreter/RemoteJITUtils.cpp
diff --git a/clang/include/clang/Interpreter/RemoteJITUtils.h b/clang/include/clang/Interpreter/RemoteJITUtils.h
deleted file mode 100644
index 67425c812381c..0000000000000
--- a/clang/include/clang/Interpreter/RemoteJITUtils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===-- RemoteJITUtils.h - Utilities for remote-JITing ----------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Utilities for ExecutorProcessControl-based remote JITing with Orc and
-// JITLink.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H
-#define LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/Layer.h"
-#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
-#include "llvm/Support/Error.h"
-
-#include <cstdint>
-#include <memory>
-#include <string>
-
-llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
-launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString);
-
-/// Create a JITLinkExecutor that connects to the given network address
-/// through a TCP socket. A valid NetworkAddress provides hostname and port,
-/// e.g. localhost:20000.
-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
deleted file mode 100644
index fe69a84ec79d4..0000000000000
--- a/clang/lib/Interpreter/RemoteJITUtils.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-//===-- RemoteJITUtils.cpp - Utilities for remote-JITing --------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// FIXME: Unify this code with similar functionality in llvm-jitlink.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Interpreter/RemoteJITUtils.h"
-
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
-#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
-#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
-#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
-#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
-#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-
-#ifdef LLVM_ON_UNIX
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#endif // LLVM_ON_UNIX
-
-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();
-
- uint64_t Units = 1024;
-
- if (SizeString.ends_with_insensitive("kb"))
- SizeString = SizeString.drop_back(2).rtrim();
- else if (SizeString.ends_with_insensitive("mb")) {
- Units = 1024 * 1024;
- SizeString = SizeString.drop_back(2).rtrim();
- } else if (SizeString.ends_with_insensitive("gb")) {
- Units = 1024 * 1024 * 1024;
- SizeString = SizeString.drop_back(2).rtrim();
- }
-
- uint64_t SlabSize = 0;
- if (SizeString.getAsInteger(10, SlabSize))
- return make_error<StringError>("Invalid numeric format for slab size",
- inconvertibleErrorCode());
-
- return SlabSize * Units;
-}
-
-Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
-createSharedMemoryManager(SimpleRemoteEPC &SREPC,
- StringRef SlabAllocateSizeString) {
- SharedMemoryMapper::SymbolAddrs SAs;
- if (auto Err = SREPC.getBootstrapSymbols(
- {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
- {SAs.Reserve,
- rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
- {SAs.Initialize,
- rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},
- {SAs.Deinitialize,
- rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
- {SAs.Release,
- rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
- return std::move(Err);
-
-#ifdef _WIN32
- size_t SlabSize = 1024 * 1024;
-#else
- size_t SlabSize = 1024 * 1024 * 1024;
-#endif
-
- if (!SlabAllocateSizeString.empty()) {
- if (Expected<uint64_t> S = getSlabAllocSize(SlabAllocateSizeString))
- SlabSize = *S;
- else
- return S.takeError();
- }
-
- return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
- SlabSize, SREPC, SAs);
-}
-
-// Launches an out-of-process executor for remote JIT.
-Expected<std::unique_ptr<SimpleRemoteEPC>>
-launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString) {
-#ifndef LLVM_ON_UNIX
- // FIXME: Add support for Windows.
- return make_error<StringError>("-" + ExecutablePath +
- " not supported on non-unix platforms",
- inconvertibleErrorCode());
-#elif !LLVM_ENABLE_THREADS
- // Out of process mode using SimpleRemoteEPC depends on threads.
- return make_error<StringError>(
- "-" + ExecutablePath +
- " requires threads, but LLVM was built with "
- "LLVM_ENABLE_THREADS=Off",
- inconvertibleErrorCode());
-#else
-
- if (!sys::fs::can_execute(ExecutablePath))
- return make_error<StringError>(
- formatv("Specified executor invalid: {0}", ExecutablePath),
- inconvertibleErrorCode());
-
- constexpr int ReadEnd = 0;
- constexpr int WriteEnd = 1;
-
- // Pipe FDs.
- int ToExecutor[2];
- int FromExecutor[2];
-
- pid_t ChildPID;
-
- // Create pipes to/from the executor..
- if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
- return make_error<StringError>("Unable to create pipe for executor",
- inconvertibleErrorCode());
-
- ChildPID = fork();
-
- if (ChildPID == 0) {
- // In the child...
-
- // Close the parent ends of the pipes
- close(ToExecutor[WriteEnd]);
- close(FromExecutor[ReadEnd]);
-
- // Execute the child process.
- std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
- {
- ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
- strcpy(ExecutorPath.get(), ExecutablePath.data());
-
- std::string FDSpecifierStr("filedescs=");
- FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
- FDSpecifierStr += ',';
- FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
- FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
- strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
- }
-
- char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
- int RC = execvp(ExecutorPath.get(), Args);
- if (RC != 0) {
- errs() << "unable to launch out-of-process executor \""
- << ExecutorPath.get() << "\"\n";
- exit(1);
- }
- }
- // else we're the parent...
-
- LaunchedExecutorPID.push_back(ChildPID);
-
- // Close the child ends of the pipes
- close(ToExecutor[ReadEnd]);
- close(FromExecutor[WriteEnd]);
-
- SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
- if (UseSharedMemory)
- S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
- return createSharedMemoryManager(EPC, SlabAllocateSizeString);
- };
-
- return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
- std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
- std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
-#endif
-}
-
-#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
-
-static Expected<int> connectTCPSocketImpl(std::string Host,
- std::string PortStr) {
- addrinfo *AI;
- addrinfo Hints{};
- Hints.ai_family = AF_INET;
- Hints.ai_socktype = SOCK_STREAM;
- Hints.ai_flags = AI_NUMERICSERV;
-
- if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
- return make_error<StringError>(
- formatv("address resolution failed ({0})", gai_strerror(EC)),
- inconvertibleErrorCode());
- // Cycle through the returned addrinfo structures and connect to the first
- // reachable endpoint.
- int SockFD;
- addrinfo *Server;
- for (Server = AI; Server != nullptr; Server = Server->ai_next) {
- // socket might fail, e.g. if the address family is not supported. Skip to
- // the next addrinfo structure in such a case.
- if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
- continue;
-
- // If connect returns null, we exit the loop with a working socket.
- if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
- break;
-
- close(SockFD);
- }
- freeaddrinfo(AI);
-
- // If we reached the end of the loop without connecting to a valid endpoint,
- // dump the last error that was logged in socket() or connect().
- if (Server == nullptr)
- return make_error<StringError>("invalid hostname",
- inconvertibleErrorCode());
-
- return SockFD;
-}
-#endif
-
-Expected<std::unique_ptr<SimpleRemoteEPC>>
-connectTCPSocket(StringRef NetworkAddress, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString) {
-#ifndef LLVM_ON_UNIX
- // FIXME: Add TCP support for Windows.
- return make_error<StringError>("-" + NetworkAddress +
- " not supported on non-unix platforms",
- inconvertibleErrorCode());
-#elif !LLVM_ENABLE_THREADS
- // Out of process mode using SimpleRemoteEPC depends on threads.
- return make_error<StringError>(
- "-" + NetworkAddress +
- " requires threads, but LLVM was built with "
- "LLVM_ENABLE_THREADS=Off",
- inconvertibleErrorCode());
-#else
-
- auto CreateErr = [NetworkAddress](Twine Details) {
- return make_error<StringError>(
- formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
- Details),
- inconvertibleErrorCode());
- };
-
- StringRef Host, PortStr;
- std::tie(Host, PortStr) = NetworkAddress.split(':');
- if (Host.empty())
- return CreateErr("Host name for -" + NetworkAddress + " can not be empty");
- if (PortStr.empty())
- return CreateErr("Port number in -" + NetworkAddress + " can not be empty");
- int Port = 0;
- if (PortStr.getAsInteger(10, Port))
- return CreateErr("Port number '" + PortStr + "' is not a valid integer");
-
- Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
- if (!SockFD)
- return SockFD.takeError();
-
- SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
- if (UseSharedMemory)
- S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
- return createSharedMemoryManager(EPC, SlabAllocateSizeString);
- };
-
- return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
- std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
- 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
>From f2ca64ecb1b9df68620e06c42ce31c542e53ea18 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 00:28:49 +0530
Subject: [PATCH 28/35] Refactoring
---
clang/lib/Interpreter/Interpreter.cpp | 2 ++
clang/test/Interpreter/out-of-process.cpp | 2 +-
clang/unittests/Interpreter/InterpreterTest.cpp | 10 ----------
3 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 398a9c27eadcb..422079f7bf827 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -459,6 +459,8 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
if (auto E = Interp->ParseAndExecute(Runtimes))
return std::move(E);
+ Interp->markUserCodeStart();
+
return std::move(Interp);
}
diff --git a/clang/test/Interpreter/out-of-process.cpp b/clang/test/Interpreter/out-of-process.cpp
index 2c576de468f6e..6922ca6e82053 100644
--- a/clang/test/Interpreter/out-of-process.cpp
+++ b/clang/test/Interpreter/out-of-process.cpp
@@ -1,4 +1,4 @@
-// REQUIRES: host-supports-jit, host-supports-out-of-process-jit, x86_64
+// REQUIRES: host-supports-jit, host-supports-out-of-process-jit, x86_64-linux
// RUN: cat %s | clang-repl -oop-executor -orc-runtime | FileCheck %s
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 62e9d03f634b0..9ff9092524d21 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -15,16 +15,12 @@
#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/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"
@@ -38,12 +34,6 @@ int Global = 42;
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 {
>From 0c99b67a48bf58743d7ce136c512ce93578a1562 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 00:48:13 +0530
Subject: [PATCH 29/35] Refactoring
---
clang/lib/Interpreter/IncrementalExecutor.cpp | 2 ++
clang/lib/Interpreter/IncrementalExecutor.h | 2 ++
2 files changed, 4 insertions(+)
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 28166c40e70cf..4eda06aeadadb 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -87,6 +87,7 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
}
}
+#ifndef _WIN32
IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder,
llvm::Error &Err, pid_t ChildPid)
@@ -101,6 +102,7 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
return;
}
}
+#endif
IncrementalExecutor::~IncrementalExecutor() {}
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index 3f33eb77f42d4..ac7fb8c1c7db1 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -60,9 +60,11 @@ class IncrementalExecutor {
IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err);
+#ifndef _WIN32
IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err,
pid_t ChildPid);
+#endif
virtual ~IncrementalExecutor();
virtual llvm::Error addModule(PartialTranslationUnit &PTU);
>From 51d66572a1d864d4ffd855bd69ff54c51d6c2202 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 01:04:36 +0530
Subject: [PATCH 30/35] Refactoring
---
clang/lib/Interpreter/Interpreter.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 422079f7bf827..44fee57624422 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -658,8 +658,11 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
#ifdef __EMSCRIPTEN__
auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
#else
- auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder,
- Err, OOPChildPid);
+#ifndef _WIN32
+ auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err, OOPChildPid);
+#else
+ auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
+#endif
#endif
if (!Err)
IncrExecutor = std::move(Executor);
>From a71c546be032058bf318049171b66b9852874543 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 01:08:22 +0530
Subject: [PATCH 31/35] formatting
---
clang/lib/Interpreter/Interpreter.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 44fee57624422..17641f6527da6 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -659,9 +659,11 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
#else
#ifndef _WIN32
- auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err, OOPChildPid);
+ auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder,
+ Err, OOPChildPid);
#else
- auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
+ auto Executor =
+ std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
#endif
#endif
if (!Err)
>From 37a9f3d6bcb7d15beb8559820e9ebde9b949764c Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Mon, 1 Sep 2025 01:21:49 +0530
Subject: [PATCH 32/35] formatting
---
clang/lib/Interpreter/Interpreter.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 17641f6527da6..11e96d0e9f424 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -420,6 +420,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+#ifndef _WIN32
if (OutOfProcessConfig != std::nullopt &&
OutOfProcessConfig->IsOutOfProcess) {
const TargetInfo &TI = CI->getTarget();
@@ -447,6 +448,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
}
}
+#endif
auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
>From 2cdb2105ef305cc388383491a2d5ad3459e426df Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 5 Sep 2025 09:57:18 +0530
Subject: [PATCH 33/35] Addressing reviews
---
clang/include/clang/Interpreter/Interpreter.h | 31 ++--
clang/lib/Interpreter/IncrementalExecutor.cpp | 144 +++++++++---------
clang/lib/Interpreter/IncrementalExecutor.h | 14 +-
clang/lib/Interpreter/Interpreter.cpp | 54 +++----
clang/tools/clang-repl/ClangRepl.cpp | 14 +-
5 files changed, 121 insertions(+), 136 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 4abf721c6e222..66020e19f7f35 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -15,7 +15,6 @@
#define LLVM_CLANG_INTERPRETER_INTERPRETER_H
#include "clang/AST/GlobalDecl.h"
-#include "clang/Driver/ToolChain.h"
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Interpreter/Value.h"
@@ -24,6 +23,7 @@
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/Support/Error.h"
+#include <cstdint>
#include <memory>
#include <vector>
@@ -37,6 +37,10 @@ class ThreadSafeContext;
namespace clang {
+namespace driver {
+class ToolChain;
+} // namespace driver
+
class CompilerInstance;
class CXXRecordDecl;
class Decl;
@@ -117,7 +121,7 @@ class Interpreter {
std::unique_ptr<CompilerInstance> DeviceCI;
public:
- struct OutOfProcessJITConfig {
+ struct JITConfig {
/// Indicates whether out-of-process JIT execution is enabled.
bool IsOutOfProcess;
/// Path to the out-of-process JIT executor.
@@ -130,7 +134,7 @@ class Interpreter {
/// Path to the ORC runtime library.
std::string OrcRuntimePath;
- OutOfProcessJITConfig()
+ JITConfig()
: IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""),
UseSharedMemory(false), SlabAllocateSizeString(""),
OrcRuntimePath("") {}
@@ -141,12 +145,11 @@ class Interpreter {
Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
std::unique_ptr<clang::ASTConsumer> Consumer = nullptr,
- OutOfProcessJITConfig OOPConfig = OutOfProcessJITConfig());
+ JITConfig Config = JITConfig());
// Create the internal IncrementalExecutor, or re-create it after calling
// ResetExecutor().
- llvm::Error
- CreateExecutor(OutOfProcessJITConfig OOPConfig = OutOfProcessJITConfig());
+ llvm::Error CreateExecutor(JITConfig Config = JITConfig());
// Delete the internal IncrementalExecutor. This causes a hard shutdown of the
// JIT engine. In particular, it doesn't run cleanup or destructors.
@@ -154,22 +157,20 @@ class Interpreter {
public:
virtual ~Interpreter();
- static llvm::Expected<std::unique_ptr<Interpreter>> create(
- std::unique_ptr<CompilerInstance> CI,
- std::optional<OutOfProcessJITConfig> OutOfProcessConfig = std::nullopt);
+ static llvm::Expected<std::unique_ptr<Interpreter>>
+ create(std::unique_ptr<CompilerInstance> CI, JITConfig Config = {});
static llvm::Expected<std::unique_ptr<Interpreter>>
createWithCUDA(std::unique_ptr<CompilerInstance> CI,
std::unique_ptr<CompilerInstance> DCI);
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
llvm::StringRef OrcRuntimePath);
-#ifndef _WIN32
static llvm::Expected<
- std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
- outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig);
+ std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>
+ outOfProcessJITBuilder(JITConfig Config);
static llvm::Expected<std::string>
getOrcRuntimePath(const driver::ToolChain &TC);
-#endif
+
const ASTContext &getASTContext() const;
ASTContext &getASTContext();
const CompilerInstance *getCompilerInstance() const;
@@ -200,9 +201,7 @@ class Interpreter {
llvm::Expected<llvm::orc::ExecutorAddr>
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
-#ifndef _WIN32
- pid_t getOutOfProcessExecutorPID() const;
-#endif
+ uint32_t getOutOfProcessExecutorPID() const;
private:
size_t getEffectivePTUSize() const;
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 4eda06aeadadb..69baf0ca5a052 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -37,6 +37,7 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/TargetParser/Host.h"
#ifdef LLVM_ON_UNIX
#include <netdb.h>
@@ -45,9 +46,6 @@
#include <unistd.h>
#endif // LLVM_ON_UNIX
-using namespace llvm;
-using namespace llvm::orc;
-
// Force linking some of the runtimes that helps attaching to a debugger.
LLVM_ATTRIBUTE_USED void linkComponents() {
llvm::errs() << (void *)&llvm_orc_registerJITLoaderGDBWrapper
@@ -87,10 +85,9 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
}
}
-#ifndef _WIN32
IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder,
- llvm::Error &Err, pid_t ChildPid)
+ llvm::Error &Err, uint32_t ChildPid)
: TSCtx(TSC), OutOfProcessChildPid(ChildPid) {
using namespace llvm::orc;
llvm::ErrorAsOutParameter EAO(&Err);
@@ -102,7 +99,6 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
return;
}
}
-#endif
IncrementalExecutor::~IncrementalExecutor() {}
@@ -171,33 +167,37 @@ Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
uint64_t SlabSize = 0;
if (SizeString.getAsInteger(10, SlabSize))
- return make_error<StringError>("Invalid numeric format for slab size",
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ "Invalid numeric format for slab size", llvm::inconvertibleErrorCode());
return SlabSize * Units;
}
-Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
-createSharedMemoryManager(SimpleRemoteEPC &SREPC,
+Expected<std::unique_ptr<llvm::jitlink::JITLinkMemoryManager>>
+createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
StringRef SlabAllocateSizeString) {
- SharedMemoryMapper::SymbolAddrs SAs;
+ llvm::orc::SharedMemoryMapper::SymbolAddrs SAs;
if (auto Err = SREPC.getBootstrapSymbols(
- {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
+ {{SAs.Instance,
+ llvm::orc::rt::ExecutorSharedMemoryMapperServiceInstanceName},
{SAs.Reserve,
- rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
+ llvm::orc::rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
{SAs.Initialize,
- rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},
+ llvm::orc::rt::
+ ExecutorSharedMemoryMapperServiceInitializeWrapperName},
{SAs.Deinitialize,
- rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
+ llvm::orc::rt::
+ ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
{SAs.Release,
- rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
+ llvm::orc::rt::
+ ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
return std::move(Err);
-#ifdef _WIN32
- size_t SlabSize = 1024 * 1024;
-#else
- size_t SlabSize = 1024 * 1024 * 1024;
-#endif
+ size_t SlabSize;
+ if (llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows())
+ SlabSize = 1024 * 1024;
+ else
+ SlabSize = 1024 * 1024 * 1024;
if (!SlabAllocateSizeString.empty()) {
if (Expected<uint64_t> S = getSlabAllocSize(SlabAllocateSizeString))
@@ -206,33 +206,32 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
return S.takeError();
}
- return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
- SlabSize, SREPC, SAs);
+ return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
+ llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs);
}
-#ifndef _WIN32
-llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
+llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString) {
#ifndef LLVM_ON_UNIX
// FIXME: Add support for Windows.
- return make_error<StringError>("-" + ExecutablePath +
- " not supported on non-unix platforms",
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ "-" + ExecutablePath + " not supported on non-unix platforms",
+ llvm::inconvertibleErrorCode());
#elif !LLVM_ENABLE_THREADS
// Out of process mode using SimpleRemoteEPC depends on threads.
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"-" + ExecutablePath +
" requires threads, but LLVM was built with "
"LLVM_ENABLE_THREADS=Off",
- inconvertibleErrorCode());
+ llvm::inconvertibleErrorCode());
#else
- if (!sys::fs::can_execute(ExecutablePath))
- return make_error<StringError>(
- formatv("Specified executor invalid: {0}", ExecutablePath),
- inconvertibleErrorCode());
+ if (!llvm::sys::fs::can_execute(ExecutablePath))
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("Specified executor invalid: {0}", ExecutablePath),
+ llvm::inconvertibleErrorCode());
constexpr int ReadEnd = 0;
constexpr int WriteEnd = 1;
@@ -241,12 +240,12 @@ IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
int ToExecutor[2];
int FromExecutor[2];
- pid_t ChildPID;
+ uint32_t ChildPID;
// Create pipes to/from the executor..
if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
- return make_error<StringError>("Unable to create pipe for executor",
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ "Unable to create pipe for executor", llvm::inconvertibleErrorCode());
ChildPID = fork();
@@ -264,9 +263,9 @@ IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
strcpy(ExecutorPath.get(), ExecutablePath.data());
std::string FDSpecifierStr("filedescs=");
- FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
+ FDSpecifierStr += llvm::utostr(ToExecutor[ReadEnd]);
FDSpecifierStr += ',';
- FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
+ FDSpecifierStr += llvm::utostr(FromExecutor[WriteEnd]);
FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
}
@@ -274,8 +273,8 @@ IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
int RC = execvp(ExecutorPath.get(), Args);
if (RC != 0) {
- errs() << "unable to launch out-of-process executor \""
- << ExecutorPath.get() << "\"\n";
+ llvm::errs() << "unable to launch out-of-process executor \""
+ << ExecutorPath.get() << "\"\n";
exit(1);
}
}
@@ -285,15 +284,18 @@ IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
close(ToExecutor[ReadEnd]);
close(FromExecutor[WriteEnd]);
- SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
+ llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
if (UseSharedMemory)
- S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
- return createSharedMemoryManager(EPC, SlabAllocateSizeString);
- };
-
- auto EPCOrErr = SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
- std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
- std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+ S.CreateMemoryManager =
+ [SlabAllocateSizeString](llvm::orc::SimpleRemoteEPC &EPC) {
+ return createSharedMemoryManager(EPC, SlabAllocateSizeString);
+ };
+
+ auto EPCOrErr =
+ llvm::orc::SimpleRemoteEPC::Create<llvm::orc::FDSimpleRemoteEPCTransport>(
+ std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
+ std::nullopt),
+ std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
if (!EPCOrErr)
return EPCOrErr.takeError();
return std::make_pair(std::move(*EPCOrErr), ChildPID);
@@ -311,9 +313,9 @@ static Expected<int> connectTCPSocketImpl(std::string Host,
Hints.ai_flags = AI_NUMERICSERV;
if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
- return make_error<StringError>(
- formatv("address resolution failed ({0})", strerror(EC)),
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("address resolution failed ({0})", strerror(EC)),
+ llvm::inconvertibleErrorCode());
// Cycle through the returned addrinfo structures and connect to the first
// reachable endpoint.
int SockFD;
@@ -335,36 +337,35 @@ static Expected<int> connectTCPSocketImpl(std::string Host,
// If we reached the end of the loop without connecting to a valid endpoint,
// dump the last error that was logged in socket() or connect().
if (Server == nullptr)
- return make_error<StringError>("invalid hostname",
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>("invalid hostname",
+ llvm::inconvertibleErrorCode());
return SockFD;
}
-#endif
-llvm::Expected<std::unique_ptr<SimpleRemoteEPC>>
+llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString) {
#ifndef LLVM_ON_UNIX
// FIXME: Add TCP support for Windows.
- return make_error<StringError>("-" + NetworkAddress +
- " not supported on non-unix platforms",
- inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ "-" + NetworkAddress + " not supported on non-unix platforms",
+ llvm::inconvertibleErrorCode());
#elif !LLVM_ENABLE_THREADS
// Out of process mode using SimpleRemoteEPC depends on threads.
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
"-" + NetworkAddress +
" requires threads, but LLVM was built with "
"LLVM_ENABLE_THREADS=Off",
- inconvertibleErrorCode());
+ llvm::inconvertibleErrorCode());
#else
auto CreateErr = [NetworkAddress](Twine Details) {
- return make_error<StringError>(
+ return llvm::make_error<llvm::StringError>(
formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
Details),
- inconvertibleErrorCode());
+ llvm::inconvertibleErrorCode());
};
StringRef Host, PortStr;
@@ -381,14 +382,17 @@ IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
if (!SockFD)
return SockFD.takeError();
- SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
+ llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
if (UseSharedMemory)
- S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
- return createSharedMemoryManager(EPC, SlabAllocateSizeString);
- };
-
- return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
- std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
+ S.CreateMemoryManager =
+ [SlabAllocateSizeString](llvm::orc::SimpleRemoteEPC &EPC) {
+ return createSharedMemoryManager(EPC, SlabAllocateSizeString);
+ };
+
+ return llvm::orc::SimpleRemoteEPC::Create<
+ llvm::orc::FDSimpleRemoteEPCTransport>(
+ std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
+ std::nullopt),
std::move(S), *SockFD, *SockFD);
#endif
}
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index ac7fb8c1c7db1..8b4c3856d4d0e 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -45,9 +45,7 @@ class IncrementalExecutor {
using CtorDtorIterator = llvm::orc::CtorDtorIterator;
std::unique_ptr<llvm::orc::LLJIT> Jit;
llvm::orc::ThreadSafeContext &TSCtx;
-#ifndef _WIN32
- pid_t OutOfProcessChildPid = -1;
-#endif
+ uint32_t OutOfProcessChildPid = -1;
llvm::DenseMap<const PartialTranslationUnit *, llvm::orc::ResourceTrackerSP>
ResourceTrackers;
@@ -60,11 +58,9 @@ class IncrementalExecutor {
IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err);
-#ifndef _WIN32
IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err,
- pid_t ChildPid);
-#endif
+ uint32_t ChildPid);
virtual ~IncrementalExecutor();
virtual llvm::Error addModule(PartialTranslationUnit &PTU);
@@ -77,22 +73,20 @@ class IncrementalExecutor {
llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; }
#ifndef _WIN32
- pid_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; }
+ uint32_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; }
#endif
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB);
-#ifndef _WIN32
static llvm::Expected<
- std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
+ std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString);
static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
llvm::StringRef SlabAllocateSizeString);
-#endif
};
} // end namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 11e96d0e9f424..a50887e95ce9c 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -252,7 +252,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
llvm::Error &ErrOut,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,
std::unique_ptr<clang::ASTConsumer> Consumer,
- OutOfProcessJITConfig OOPConfig)
+ JITConfig Config)
: JITBuilder(std::move(JITBuilder)) {
CI = std::move(Instance);
llvm::ErrorAsOutParameter EAO(&ErrOut);
@@ -286,7 +286,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
ASTContext &C = CI->getASTContext();
IncrParser->RegisterPTU(C.getTranslationUnitDecl(), std::move(M));
}
- if (llvm::Error Err = CreateExecutor(OOPConfig)) {
+ if (llvm::Error Err = CreateExecutor(Config)) {
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
return;
}
@@ -348,26 +348,24 @@ const char *const Runtimes = R"(
EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
)";
-#ifndef _WIN32
-llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
-Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
+llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>
+Interpreter::outOfProcessJITBuilder(JITConfig Config) {
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
- pid_t childPid = -1;
- if (OutOfProcessConfig.OOPExecutor != "") {
+ uint32_t childPid = -1;
+ if (!Config.OOPExecutor.empty()) {
// Launch an out-of-process executor locally in a child process.
auto ResultOrErr = IncrementalExecutor::launchExecutor(
- OutOfProcessConfig.OOPExecutor, OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString);
+ Config.OOPExecutor, Config.UseSharedMemory,
+ Config.SlabAllocateSizeString);
if (!ResultOrErr)
return ResultOrErr.takeError();
childPid = ResultOrErr->second;
auto EPCOrErr = std::move(ResultOrErr->first);
EPC = std::move(EPCOrErr);
- } else if (OutOfProcessConfig.OOPExecutorConnect != "") {
+ } else if (Config.OOPExecutorConnect != "") {
auto EPCOrErr = IncrementalExecutor::connectTCPSocket(
- OutOfProcessConfig.OOPExecutorConnect,
- OutOfProcessConfig.UseSharedMemory,
- OutOfProcessConfig.SlabAllocateSizeString);
+ Config.OOPExecutorConnect, Config.UseSharedMemory,
+ Config.SlabAllocateSizeString);
if (!EPCOrErr)
return EPCOrErr.takeError();
EPC = std::move(*EPCOrErr);
@@ -376,7 +374,7 @@ Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
if (EPC) {
auto JBOrErr = clang::Interpreter::createLLJITBuilder(
- std::move(EPC), OutOfProcessConfig.OrcRuntimePath);
+ std::move(EPC), Config.OrcRuntimePath);
if (!JBOrErr)
return JBOrErr.takeError();
JB = std::move(*JBOrErr);
@@ -411,18 +409,14 @@ Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
llvm::Twine("OrcRuntime library not found in: ") + (*CompilerRTPath),
std::error_code());
}
-#endif
llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI,
- std::optional<OutOfProcessJITConfig> OutOfProcessConfig) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) {
llvm::Error Err = llvm::Error::success();
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
-#ifndef _WIN32
- if (OutOfProcessConfig != std::nullopt &&
- OutOfProcessConfig->IsOutOfProcess) {
+ if (Config.IsOutOfProcess) {
const TargetInfo &TI = CI->getTarget();
const llvm::Triple &Triple = TI.getTriple();
@@ -437,7 +431,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
"Failed to create driver compilation for out-of-process JIT",
std::error_code());
}
- if (OutOfProcessConfig->OrcRuntimePath == "") {
+ if (Config.OrcRuntimePath == "") {
const clang::driver::ToolChain &TC = C->getDefaultToolChain();
auto OrcRuntimePathOrErr = getOrcRuntimePath(TC);
@@ -445,14 +439,12 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
return OrcRuntimePathOrErr.takeError();
}
- OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
+ Config.OrcRuntimePath = *OrcRuntimePathOrErr;
}
}
-#endif
auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
- std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
- OutOfProcessConfig ? *OutOfProcessConfig : OutOfProcessJITConfig()));
+ std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr, Config));
if (auto E = std::move(Err))
return std::move(E);
@@ -543,13 +535,11 @@ size_t Interpreter::getEffectivePTUSize() const {
return PTUs.size() - InitPTUSize;
}
-#ifndef _WIN32
-pid_t Interpreter::getOutOfProcessExecutorPID() const {
+uint32_t Interpreter::getOutOfProcessExecutorPID() const {
if (IncrExecutor)
return IncrExecutor->getOutOfProcessChildPid();
return -1;
}
-#endif
llvm::Expected<PartialTranslationUnit &>
Interpreter::Parse(llvm::StringRef Code) {
@@ -619,7 +609,7 @@ Interpreter::createLLJITBuilder(
return std::move(*JB);
}
-llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
+llvm::Error Interpreter::CreateExecutor(JITConfig Config) {
if (IncrExecutor)
return llvm::make_error<llvm::StringError>("Operation failed. "
"Execution engine exists",
@@ -629,10 +619,10 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
"No code generator available",
std::error_code());
#ifndef _WIN32
- pid_t OOPChildPid = -1;
- if (OOPConfig.IsOutOfProcess) {
+ uint32_t OOPChildPid = -1;
+ if (Config.IsOutOfProcess) {
if (!JITBuilder) {
- auto ResOrErr = outOfProcessJITBuilder(OOPConfig);
+ auto ResOrErr = outOfProcessJITBuilder(Config);
if (!ResOrErr)
return ResOrErr.takeError();
JITBuilder = std::move(ResOrErr->first);
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index e1f2f465e5f38..11d8f5bc09040 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -275,12 +275,11 @@ int main(int argc, const char **argv) {
ExitOnErr(sanitizeOopArguments(argv[0]));
- clang::Interpreter::OutOfProcessJITConfig OutOfProcessConfig;
- OutOfProcessConfig.IsOutOfProcess =
- !OOPExecutor.empty() || !OOPExecutorConnect.empty();
- OutOfProcessConfig.OOPExecutor = OOPExecutor;
- OutOfProcessConfig.SlabAllocateSizeString = SlabAllocateSizeString;
- OutOfProcessConfig.UseSharedMemory = UseSharedMemory;
+ clang::Interpreter::JITConfig Config;
+ Config.IsOutOfProcess = !OOPExecutor.empty() || !OOPExecutorConnect.empty();
+ Config.OOPExecutor = OOPExecutor;
+ Config.SlabAllocateSizeString = SlabAllocateSizeString;
+ Config.UseSharedMemory = UseSharedMemory;
// FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
// can replace the boilerplate code for creation of the compiler instance.
@@ -314,8 +313,7 @@ int main(int argc, const char **argv) {
ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str()));
}
} else {
- Interp = ExitOnErr(
- clang::Interpreter::create(std::move(CI), OutOfProcessConfig));
+ Interp = ExitOnErr(clang::Interpreter::create(std::move(CI), Config));
}
bool HasError = false;
>From 129a62b1d2ddbaa3aa6c7e288f3a72a6275e1a33 Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 5 Sep 2025 10:42:20 +0530
Subject: [PATCH 34/35] Addressing reviews
---
clang/lib/Interpreter/IncrementalExecutor.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index 8b4c3856d4d0e..9455a2d61af2f 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -72,9 +72,7 @@ class IncrementalExecutor {
llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; }
-#ifndef _WIN32
uint32_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; }
-#endif
static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB);
>From c856255dac472388f623cca334ce707cd5399b4c Mon Sep 17 00:00:00 2001
From: kr-2003 <kumar.kr.abhinav at gmail.com>
Date: Fri, 5 Sep 2025 22:44:59 +0530
Subject: [PATCH 35/35] Addressing reviews
---
clang/include/clang/Interpreter/Interpreter.h | 17 ++++---
clang/lib/Interpreter/IncrementalExecutor.cpp | 45 ++++---------------
clang/lib/Interpreter/IncrementalExecutor.h | 4 +-
clang/lib/Interpreter/Interpreter.cpp | 35 ++++++++-------
clang/tools/clang-repl/ClangRepl.cpp | 31 ++++++++++++-
5 files changed, 69 insertions(+), 63 deletions(-)
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 66020e19f7f35..eee80a273c7f5 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -123,21 +123,20 @@ class Interpreter {
public:
struct JITConfig {
/// Indicates whether out-of-process JIT execution is enabled.
- bool IsOutOfProcess;
+ bool IsOutOfProcess = false;
/// Path to the out-of-process JIT executor.
- std::string OOPExecutor;
- std::string OOPExecutorConnect;
+ std::string OOPExecutor = "";
+ std::string OOPExecutorConnect = "";
/// Indicates whether to use shared memory for communication.
- bool UseSharedMemory;
- /// String representing the slab allocation size for memory management.
- std::string SlabAllocateSizeString;
+ bool UseSharedMemory = false;
+ /// Representing the slab allocation size for memory management in kb.
+ unsigned SlabAllocateSize = 0;
/// Path to the ORC runtime library.
- std::string OrcRuntimePath;
+ std::string OrcRuntimePath = "";
JITConfig()
: IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""),
- UseSharedMemory(false), SlabAllocateSizeString(""),
- OrcRuntimePath("") {}
+ UseSharedMemory(false), SlabAllocateSize(0), OrcRuntimePath("") {}
};
protected:
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 69baf0ca5a052..e5510b7409ca9 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -150,32 +150,9 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
return SymOrErr->getAddress();
}
-Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
- SizeString = SizeString.trim();
-
- uint64_t Units = 1024;
-
- if (SizeString.ends_with_insensitive("kb"))
- SizeString = SizeString.drop_back(2).rtrim();
- else if (SizeString.ends_with_insensitive("mb")) {
- Units = 1024 * 1024;
- SizeString = SizeString.drop_back(2).rtrim();
- } else if (SizeString.ends_with_insensitive("gb")) {
- Units = 1024 * 1024 * 1024;
- SizeString = SizeString.drop_back(2).rtrim();
- }
-
- uint64_t SlabSize = 0;
- if (SizeString.getAsInteger(10, SlabSize))
- return llvm::make_error<llvm::StringError>(
- "Invalid numeric format for slab size", llvm::inconvertibleErrorCode());
-
- return SlabSize * Units;
-}
-
Expected<std::unique_ptr<llvm::jitlink::JITLinkMemoryManager>>
createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
- StringRef SlabAllocateSizeString) {
+ unsigned SlabAllocateSize) {
llvm::orc::SharedMemoryMapper::SymbolAddrs SAs;
if (auto Err = SREPC.getBootstrapSymbols(
{{SAs.Instance,
@@ -199,12 +176,8 @@ createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
else
SlabSize = 1024 * 1024 * 1024;
- if (!SlabAllocateSizeString.empty()) {
- if (Expected<uint64_t> S = getSlabAllocSize(SlabAllocateSizeString))
- SlabSize = *S;
- else
- return S.takeError();
- }
+ if (SlabAllocateSize > 0)
+ SlabSize = SlabAllocateSize;
return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs);
@@ -213,7 +186,7 @@ createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString) {
+ unsigned SlabAllocateSize) {
#ifndef LLVM_ON_UNIX
// FIXME: Add support for Windows.
return llvm::make_error<llvm::StringError>(
@@ -287,8 +260,8 @@ IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
if (UseSharedMemory)
S.CreateMemoryManager =
- [SlabAllocateSizeString](llvm::orc::SimpleRemoteEPC &EPC) {
- return createSharedMemoryManager(EPC, SlabAllocateSizeString);
+ [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
+ return createSharedMemoryManager(EPC, SlabAllocateSize);
};
auto EPCOrErr =
@@ -346,7 +319,7 @@ static Expected<int> connectTCPSocketImpl(std::string Host,
llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString) {
+ unsigned SlabAllocateSize) {
#ifndef LLVM_ON_UNIX
// FIXME: Add TCP support for Windows.
return llvm::make_error<llvm::StringError>(
@@ -385,8 +358,8 @@ IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
if (UseSharedMemory)
S.CreateMemoryManager =
- [SlabAllocateSizeString](llvm::orc::SimpleRemoteEPC &EPC) {
- return createSharedMemoryManager(EPC, SlabAllocateSizeString);
+ [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
+ return createSharedMemoryManager(EPC, SlabAllocateSize);
};
return llvm::orc::SimpleRemoteEPC::Create<
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index 9455a2d61af2f..28531b98f7a06 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -80,11 +80,11 @@ class IncrementalExecutor {
static llvm::Expected<
std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString);
+ unsigned SlabAllocateSize);
static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
- llvm::StringRef SlabAllocateSizeString);
+ unsigned SlabAllocateSize);
};
} // end namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index a50887e95ce9c..248ab2f7e37ba 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -355,8 +355,7 @@ Interpreter::outOfProcessJITBuilder(JITConfig Config) {
if (!Config.OOPExecutor.empty()) {
// Launch an out-of-process executor locally in a child process.
auto ResultOrErr = IncrementalExecutor::launchExecutor(
- Config.OOPExecutor, Config.UseSharedMemory,
- Config.SlabAllocateSizeString);
+ Config.OOPExecutor, Config.UseSharedMemory, Config.SlabAllocateSize);
if (!ResultOrErr)
return ResultOrErr.takeError();
childPid = ResultOrErr->second;
@@ -365,7 +364,7 @@ Interpreter::outOfProcessJITBuilder(JITConfig Config) {
} else if (Config.OOPExecutorConnect != "") {
auto EPCOrErr = IncrementalExecutor::connectTCPSocket(
Config.OOPExecutorConnect, Config.UseSharedMemory,
- Config.SlabAllocateSizeString);
+ Config.SlabAllocateSize);
if (!EPCOrErr)
return EPCOrErr.takeError();
EPC = std::move(*EPCOrErr);
@@ -423,6 +422,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) {
DiagnosticsEngine &Diags = CI->getDiagnostics();
std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, nullptr);
driver::Driver Driver(BinaryName, Triple.str(), Diags);
+ // Need fake args to get the driver to create a compilation.
std::vector<const char *> Args = {"clang", "--version"};
std::unique_ptr<clang::driver::Compilation> C(
Driver.BuildCompilation(Args));
@@ -618,9 +618,13 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) {
return llvm::make_error<llvm::StringError>("Operation failed. "
"No code generator available",
std::error_code());
-#ifndef _WIN32
+
+ const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
+ llvm::Triple TargetTriple(TT);
+ bool IsWindowsTarget = TargetTriple.isOSWindows();
+
uint32_t OOPChildPid = -1;
- if (Config.IsOutOfProcess) {
+ if (!IsWindowsTarget && Config.IsOutOfProcess) {
if (!JITBuilder) {
auto ResOrErr = outOfProcessJITBuilder(Config);
if (!ResOrErr)
@@ -633,10 +637,8 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) {
"Operation failed. No LLJITBuilder for out-of-process JIT",
std::error_code());
}
-#endif
if (!JITBuilder) {
- const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
auto JTMB = createJITTargetMachineBuilder(TT);
if (!JTMB)
return JTMB.takeError();
@@ -647,16 +649,19 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) {
}
llvm::Error Err = llvm::Error::success();
+
+ // Fix: Declare Executor as the appropriate unique_ptr type
+ std::unique_ptr<IncrementalExecutor> Executor;
+
#ifdef __EMSCRIPTEN__
- auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
-#else
-#ifndef _WIN32
- auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder,
- Err, OOPChildPid);
+ Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
#else
- auto Executor =
- std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
-#endif
+ if (IsWindowsTarget) {
+ Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
+ } else {
+ Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err,
+ OOPChildPid);
+ }
#endif
if (!Err)
IncrExecutor = std::move(Executor);
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 11d8f5bc09040..7f63b366e2291 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -137,6 +137,30 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0) {
return llvm::Error::success();
}
+static llvm::Expected<unsigned> getSlabAllocSize(StringRef SizeString) {
+ SizeString = SizeString.trim();
+
+ uint64_t Units = 1024;
+
+ if (SizeString.ends_with_insensitive("kb"))
+ SizeString = SizeString.drop_back(2).rtrim();
+ else if (SizeString.ends_with_insensitive("mb")) {
+ Units = 1024 * 1024;
+ SizeString = SizeString.drop_back(2).rtrim();
+ } else if (SizeString.ends_with_insensitive("gb")) {
+ Units = 1024 * 1024 * 1024;
+ SizeString = SizeString.drop_back(2).rtrim();
+ } else if (SizeString.empty())
+ return 0;
+
+ uint64_t SlabSize = 0;
+ if (SizeString.getAsInteger(10, SlabSize))
+ return llvm::make_error<llvm::StringError>(
+ "Invalid numeric format for slab size", llvm::inconvertibleErrorCode());
+
+ return SlabSize * Units;
+}
+
static void LLVMErrorHandler(void *UserData, const char *Message,
bool GenCrashDiag) {
auto &Diags = *static_cast<clang::DiagnosticsEngine *>(UserData);
@@ -278,7 +302,12 @@ int main(int argc, const char **argv) {
clang::Interpreter::JITConfig Config;
Config.IsOutOfProcess = !OOPExecutor.empty() || !OOPExecutorConnect.empty();
Config.OOPExecutor = OOPExecutor;
- Config.SlabAllocateSizeString = SlabAllocateSizeString;
+ auto SizeOrErr = getSlabAllocSize(SlabAllocateSizeString);
+ if (!SizeOrErr) {
+ llvm::logAllUnhandledErrors(SizeOrErr.takeError(), llvm::errs(), "error: ");
+ return EXIT_FAILURE;
+ }
+ Config.SlabAllocateSize = *SizeOrErr;
Config.UseSharedMemory = UseSharedMemory;
// FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
More information about the cfe-commits
mailing list