From 5a1cac390c2c382113d7d7c4fb63f9cc39f09342 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Tue, 17 Jun 2025 16:56:25 +0530 Subject: [PATCH 01/11] addition of oop jit execution --- .github/actions/Build_LLVM/action.yml | 11 + .../Build_and_Test_CppInterOp/action.yml | 16 +- .github/workflows/MacOS-arm.yml | 8 +- .github/workflows/MacOS.yml | 8 +- .github/workflows/Ubuntu-arm.yml | 9 +- .github/workflows/Ubuntu.yml | 8 +- CMakeLists.txt | 7 + README.md | 33 + include/CppInterOp/CppInterOp.h | 2 +- lib/CppInterOp/Compatibility.h | 51 +- lib/CppInterOp/CppInterOp.cpp | 6 +- lib/CppInterOp/CppInterOpInterpreter.h | 4 +- .../llvm/out-of-process-jit-execution.patch | 710 ++++++++++++++++++ unittests/CppInterOp/InterpreterTest.cpp | 27 + 14 files changed, 888 insertions(+), 12 deletions(-) create mode 100644 patches/llvm/out-of-process-jit-execution.patch diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index 3d9461fe7..8eef77ea9 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -49,6 +49,10 @@ runs: git apply -v ../patches/llvm/clang${{ matrix.clang-runtime }}-*.patch echo "Apply clang${{ matrix.clang-runtime }}-*.patch patches:" fi + if [[ "${{ matrix.llvm_enable_runtimes }}" == "clang;compile-rt" ]]; then + git apply -v ../patches/llvm/out-of-process-jit-execution.patch + echo "Apply out-of-process-jit-execution.patch:" + fi cd build cmake -DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects}}" \ -DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" \ @@ -64,6 +68,13 @@ runs: -DLLVM_INCLUDE_TESTS=OFF \ ../llvm ninja clang clangInterpreter clangStaticAnalyzerCore -j ${{ env.ncpus }} + if [[ "${{ matrix.oop-jit }}" == "On" ]]; then + if [[ "${{ runner.os }}" == "Linux" ]]; then + ninja clang clang-repl llvm-jitlink-executor orc_rt -j $(nproc --all) + elif [[ "${{ runner.os }}" == "macOS" ]]; then + ninja clang clang-repl llvm-jitlink-executor orc_rt -j $(nproc --all) + fi + fi cd ./tools/ rm -rf $(find . -maxdepth 1 ! -name "clang" ! -name ".") cd .. diff --git a/.github/actions/Build_and_Test_CppInterOp/action.yml b/.github/actions/Build_and_Test_CppInterOp/action.yml index b97d2e8ae..e875b4af4 100644 --- a/.github/actions/Build_and_Test_CppInterOp/action.yml +++ b/.github/actions/Build_and_Test_CppInterOp/action.yml @@ -40,7 +40,8 @@ runs: -DLLVM_ENABLE_WERROR=On \ ../ else - cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ + if [[ "${{ matrix.oop-jit }}" == "On" ]]; then + cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCPPINTEROP_INCLUDE_DOCS=${{ matrix.documentation }} \ -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ @@ -48,7 +49,20 @@ runs: -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ -DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR \ -DLLVM_ENABLE_WERROR=On \ + -DCPPINTEROP_WITH_OOP_JIT=ON \ ../ + else + cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ + -DCPPINTEROP_INCLUDE_DOCS=${{ matrix.documentation }} \ + -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ + -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ + -DBUILD_SHARED_LIBS=ON \ + -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ + -DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR \ + -DLLVM_ENABLE_WERROR=On \ + -DCPPINTEROP_WITH_OOP_JIT=OFF \ + ../ + fi fi docs_on=$(echo "${{ matrix.documentation }}" | tr '[:lower:]' '[:upper:]') if [[ "${docs_on}" == "ON" ]]; then diff --git a/.github/workflows/MacOS-arm.yml b/.github/workflows/MacOS-arm.yml index 97c525906..0ee48bc98 100644 --- a/.github/workflows/MacOS-arm.yml +++ b/.github/workflows/MacOS-arm.yml @@ -28,8 +28,9 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" + oop-jit: On - name: osx15-arm-clang-clang-repl-19-cppyy os: macos-15 compiler: clang @@ -38,6 +39,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx15-arm-clang-clang-repl-18-cppyy os: macos-15 compiler: clang @@ -46,6 +48,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx15-arm-clang-clang-repl-17-cppyy os: macos-15 compiler: clang @@ -54,6 +57,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx15-arm-clang-clang-repl-16 os: macos-15 compiler: clang @@ -62,6 +66,7 @@ jobs: cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx15-arm-clang-clang18-cling-cppyy os: macos-15 compiler: clang @@ -71,6 +76,7 @@ jobs: cling-version: '1.2' llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index a06288c4c..5b2991ca9 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -28,8 +28,9 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" + oop-jit: On - name: osx13-x86-clang-clang-repl-19-cppyy os: macos-13 compiler: clang @@ -38,6 +39,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx13-x86-clang-clang-repl-18-cppyy os: macos-13 compiler: clang @@ -46,6 +48,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx13-x86-clang-clang-repl-17-cppyy os: macos-13 compiler: clang @@ -54,6 +57,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx13-x86-clang-clang-repl-16 os: macos-13 compiler: clang @@ -61,6 +65,7 @@ jobs: cling: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host" + oop-jit: Off - name: osx13-x86-clang-clang18-cling-cppyy os: macos-13 compiler: clang @@ -70,6 +75,7 @@ jobs: cling-version: '1.2' llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/Ubuntu-arm.yml b/.github/workflows/Ubuntu-arm.yml index 580ff5ea6..b63d1441f 100644 --- a/.github/workflows/Ubuntu-arm.yml +++ b/.github/workflows/Ubuntu-arm.yml @@ -28,9 +28,10 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" coverage: true + oop-jit: On - name: ubu24-arm-gcc12-clang-repl-20 os: ubuntu-24.04-arm compiler: gcc-12 @@ -39,6 +40,7 @@ jobs: cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-arm-gcc12-clang-repl-19-cppyy os: ubuntu-24.04-arm compiler: gcc-12 @@ -47,6 +49,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-arm-gcc12-clang-repl-18-cppyy os: ubuntu-24.04-arm compiler: gcc-12 @@ -55,6 +58,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-arm-gcc12-clang-repl-17-cppyy os: ubuntu-24.04-arm compiler: gcc-12 @@ -63,6 +67,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-arm-gcc12-clang-repl-16 os: ubuntu-24.04-arm compiler: gcc-12 @@ -71,6 +76,7 @@ jobs: cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-arm-gcc9-clang18-cling-cppyy os: ubuntu-24.04-arm compiler: gcc-9 @@ -80,6 +86,7 @@ jobs: cling-version: '1.2' llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index afcffe818..e11394da0 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -28,8 +28,9 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" + oop-jit: On - name: ubu24-x86-gcc12-clang-repl-19-cppyy os: ubuntu-24.04 compiler: gcc-12 @@ -38,6 +39,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-x86-gcc12-clang-repl-18-cppyy os: ubuntu-24.04 compiler: gcc-12 @@ -46,6 +48,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-x86-gcc12-clang-repl-17-cppyy os: ubuntu-24.04 compiler: gcc-12 @@ -54,6 +57,7 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-x86-gcc12-clang-repl-16 os: ubuntu-24.04 compiler: gcc-12 @@ -62,6 +66,7 @@ jobs: cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off - name: ubu24-x86-gcc9-clang18-cling-cppyy os: ubuntu-24.04 compiler: gcc-9 @@ -71,6 +76,7 @@ jobs: cling-version: '1.2' llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" + oop-jit: Off steps: - uses: actions/checkout@v4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b2df5b4f..71fc9aefc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,6 +305,13 @@ else() message(FATAL_ERROR "We need either CPPINTEROP_USE_CLING or CPPINTEROP_USE_REPL") endif() +if(CPPINTEROP_WITH_OOP_JIT) + add_definitions(-DCPPINTEROP_WITH_OOP_JIT) +endif() + +string(REGEX REPLACE "/build/lib/cmake/llvm$" "" LLVM_SOURCE_DIR "${LLVM_DIR}") +add_definitions(-DLLVM_SOURCE_DIR="${LLVM_SOURCE_DIR}") + include_directories(SYSTEM ${CLANG_INCLUDE_DIRS}) include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) diff --git a/README.md b/README.md index 37f36fe15..4d71c4106 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,13 @@ git apply -v clang{version}-*.patch on Windows. +If you want to have out-of-process JIT execution enabled in CppInterOp, then apply this patch on Linux and MacOS environment. +> Note that this patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux and MacOS only. + +```bash +git apply -v ../CppInterOp/patches/llvm/out-of-process-jit-execution.patch +``` + ##### Build Clang-REPL Clang-REPL is an interpreter that CppInterOp works alongside. Build Clang (and @@ -180,6 +187,30 @@ $env:LLVM_DIR= $PWD.Path cd ..\ ``` +##### Build Clang-REPL with Out-of-Process JIT Execution + +To have ``Out-of-Process JIT Execution`` enabled, run following commands to build clang and clang-repl to support this feature: +> Only for Linux and Macos +```bash +mkdir build +cd build +cmake -DLLVM_ENABLE_PROJECTS="clang;compiler-rt \ + -DLLVM_TARGETS_TO_BUILD="host;NVPTX" \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DCLANG_ENABLE_STATIC_ANALYZER=OFF \ + -DCLANG_ENABLE_ARCMT=OFF \ + -DCLANG_ENABLE_FORMAT=OFF \ + -DCLANG_ENABLE_BOOTSTRAP=OFF \ + ../llvm + +## For Linux +cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt --parallel $(nproc --all) + +## For MacOS +cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(nproc --all) +``` + #### Build Cling and related dependencies Besides the Clang-REPL interpreter, CppInterOp also works alongside the Cling @@ -329,6 +360,8 @@ cmake -DBUILD_SHARED_LIBS=ON -DLLVM_DIR=$LLVM_DIR/build/lib/cmake/llvm -DClang_D cmake --build . --target install --parallel $(nproc --all) ``` +> Do make sure to add ``-DCPPINTEROP_WITH_OOP_JIT=ON``, if you want to have out-of-process JIT execution feature enabled. + and ```powershell diff --git a/include/CppInterOp/CppInterOp.h b/include/CppInterOp/CppInterOp.h index dd091fdd4..970e21a51 100644 --- a/include/CppInterOp/CppInterOp.h +++ b/include/CppInterOp/CppInterOp.h @@ -609,7 +609,7 @@ CPPINTEROP_API void GetOperator(TCppScope_t scope, Operator op, ///\returns nullptr on failure. CPPINTEROP_API TInterp_t CreateInterpreter(const std::vector& Args = {}, - const std::vector& GpuArgs = {}); + const std::vector& GpuArgs = {}, bool outOfProcess = false); /// Deletes an instance of an interpreter. ///\param[in] I - the interpreter to be deleted, if nullptr, deletes the last. diff --git a/lib/CppInterOp/Compatibility.h b/lib/CppInterOp/Compatibility.h index 977603ea0..7c0653080 100644 --- a/lib/CppInterOp/Compatibility.h +++ b/lib/CppInterOp/Compatibility.h @@ -79,6 +79,7 @@ static inline char* GetEnv(const char* Var_Name) { // std::regex breaks pytorch's jit: pytorch/pytorch#49460 #include "llvm/Support/Regex.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #ifdef CPPINTEROP_USE_CLING @@ -200,10 +201,21 @@ inline void codeComplete(std::vector& Results, #include "llvm/Support/Error.h" +#ifdef CPPINTEROP_WITH_OOP_JIT +#include "clang/Interpreter/RemoteJITUtils.h" +#include "clang/Basic/Version.h" +#include "llvm/TargetParser/Host.h" + +#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" +#endif + + +static llvm::ExitOnError ExitOnError; + namespace compat { inline std::unique_ptr -createClangInterpreter(std::vector& args) { +createClangInterpreter(std::vector& args, bool outOfProcess) { auto has_arg = [](const char* x, llvm::StringRef match = "cuda") { llvm::StringRef Arg = x; Arg = Arg.trim().ltrim('-'); @@ -241,16 +253,53 @@ createClangInterpreter(std::vector& args) { (*ciOrErr)->LoadRequestedPlugins(); if (CudaEnabled) DeviceCI->LoadRequestedPlugins(); + + #ifdef CPPINTEROP_WITH_OOP_JIT + std::unique_ptr JB; + + if(outOfProcess) { + std::string OOPExecutor = std::string(LLVM_SOURCE_DIR) + "/build/bin/llvm-jitlink-executor"; + bool UseSharedMemory = false; + std::string SlabAllocateSizeString = ""; + std::unique_ptr EPC; + EPC = ExitOnError( + launchExecutor(OOPExecutor, UseSharedMemory, SlabAllocateSizeString)); + + #ifdef __APPLE__ + std::string OrcRuntimePath = std::string(LLVM_SOURCE_DIR) + "/build/lib/clang/20/lib/darwin/liborc_rt_osx.a"; + #else + std::string OrcRuntimePath = std::string(LLVM_SOURCE_DIR) + "/build/lib/x86_64-unknown-linux-gnu/liborc_rt.a"; + #endif + if (EPC) { + + CB.SetTargetTriple(EPC->getTargetTriple().getTriple()); + JB = ExitOnError( + clang::Interpreter::createLLJITBuilder(std::move(EPC), OrcRuntimePath)); + } + } + + auto innerOrErr = + CudaEnabled ? clang::Interpreter::createWithCUDA(std::move(*ciOrErr), + std::move(DeviceCI)) + : clang::Interpreter::create(std::move(*ciOrErr), std::move(JB)); + #else + if(outOfProcess) { + llvm::errs() << "[CreateClangInterpreter]: No compatibility with out-of-process JIT" + << "\n"; + return nullptr; + } auto innerOrErr = CudaEnabled ? clang::Interpreter::createWithCUDA(std::move(*ciOrErr), std::move(DeviceCI)) : clang::Interpreter::create(std::move(*ciOrErr)); + #endif if (!innerOrErr) { llvm::logAllUnhandledErrors(innerOrErr.takeError(), llvm::errs(), "Failed to build Interpreter:"); return nullptr; } + if (CudaEnabled) { if (auto Err = (*innerOrErr)->LoadDynamicLibrary("libcudart.so")) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index 78c95a307..67362520f 100755 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -2911,11 +2911,11 @@ static std::string MakeResourcesPath() { } // namespace TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, - const std::vector& GpuArgs /*={}*/) { + const std::vector& GpuArgs /*={}*/, bool is_out_of_process) { std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); std::string ResourceDir = MakeResourcesPath(); std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), - "-std=c++14"}; + "-std=c++14", "-gdwarf-4", "-O0"}; ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str()); #ifdef _WIN32 // FIXME : Workaround Sema::PushDeclContext assert on windows @@ -2955,7 +2955,7 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); #else auto Interp = compat::Interpreter::create(static_cast(ClingArgv.size()), - ClingArgv.data()); + ClingArgv.data(), nullptr, {}, nullptr, true, is_out_of_process); if (!Interp) return nullptr; auto* I = Interp.release(); diff --git a/lib/CppInterOp/CppInterOpInterpreter.h b/lib/CppInterOp/CppInterOpInterpreter.h index d87eb33e1..9f3ab9cc1 100644 --- a/lib/CppInterOp/CppInterOpInterpreter.h +++ b/lib/CppInterOp/CppInterOpInterpreter.h @@ -150,7 +150,7 @@ class Interpreter { create(int argc, const char* const* argv, const char* llvmdir = nullptr, const std::vector>& moduleExtensions = {}, - void* extraLibHandle = nullptr, bool noRuntime = true) { + void* extraLibHandle = nullptr, bool noRuntime = true, bool outOfProcess = false) { // Initialize all targets (required for device offloading) llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargets(); @@ -158,7 +158,7 @@ class Interpreter { llvm::InitializeAllAsmPrinters(); std::vector vargs(argv + 1, argv + argc); - auto CI = compat::createClangInterpreter(vargs); + auto CI = compat::createClangInterpreter(vargs, outOfProcess); if (!CI) { llvm::errs() << "Interpreter creation failed\n"; return nullptr; diff --git a/patches/llvm/out-of-process-jit-execution.patch b/patches/llvm/out-of-process-jit-execution.patch new file mode 100644 index 000000000..03a4620ba --- /dev/null +++ b/patches/llvm/out-of-process-jit-execution.patch @@ -0,0 +1,710 @@ +diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h +index f8663e3193a18..78dff1165dcf5 100644 +--- a/clang/include/clang/Interpreter/Interpreter.h ++++ b/clang/include/clang/Interpreter/Interpreter.h +@@ -20,6 +20,7 @@ + + #include "llvm/ADT/DenseMap.h" + #include "llvm/ExecutionEngine/JITSymbol.h" ++#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" + #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" + #include "llvm/Support/Error.h" + #include +@@ -136,10 +137,14 @@ protected: + public: + virtual ~Interpreter(); + static llvm::Expected> +- create(std::unique_ptr CI); ++ create(std::unique_ptr CI, ++ std::unique_ptr JITBuilder = nullptr); + static llvm::Expected> + createWithCUDA(std::unique_ptr CI, + std::unique_ptr DCI); ++ static llvm::Expected> ++ createLLJITBuilder(std::unique_ptr EPC, ++ llvm::StringRef OrcRuntimePath); + const ASTContext &getASTContext() const; + ASTContext &getASTContext(); + const CompilerInstance *getCompilerInstance() const; +diff --git a/clang/include/clang/Interpreter/RemoteJITUtils.h b/clang/include/clang/Interpreter/RemoteJITUtils.h +new file mode 100644 +index 0000000000000..8705a3b1f669d +--- /dev/null ++++ b/clang/include/clang/Interpreter/RemoteJITUtils.h +@@ -0,0 +1,38 @@ ++//===-- 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 ++#include ++#include ++ ++llvm::Expected> ++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> ++connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory, ++ llvm::StringRef SlabAllocateSizeString); ++ ++#endif // LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H +diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt +index bf70cdfbee01e..38cf139fa86a6 100644 +--- a/clang/lib/Interpreter/CMakeLists.txt ++++ b/clang/lib/Interpreter/CMakeLists.txt +@@ -27,6 +27,7 @@ add_clang_library(clangInterpreter + Interpreter.cpp + InterpreterValuePrinter.cpp + InterpreterUtils.cpp ++ RemoteJITUtils.cpp + Value.cpp + ${WASM_SRC} + PARTIAL_SOURCES_INTENDED +diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp +index 3b81f9d701b42..e59656f554f3d 100644 +--- a/clang/lib/Interpreter/Interpreter.cpp ++++ b/clang/lib/Interpreter/Interpreter.cpp +@@ -46,6 +46,7 @@ + #include "clang/Sema/Lookup.h" + #include "clang/Serialization/ObjectFilePCHContainerReader.h" + #include "llvm/ExecutionEngine/JITSymbol.h" ++#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" + #include "llvm/ExecutionEngine/Orc/LLJIT.h" + #include "llvm/IR/Module.h" + #include "llvm/Support/Errc.h" +@@ -455,10 +456,11 @@ const char *const Runtimes = R"( + )"; + + llvm::Expected> +-Interpreter::create(std::unique_ptr CI) { ++Interpreter::create(std::unique_ptr CI, ++ std::unique_ptr JB) { + llvm::Error Err = llvm::Error::success(); +- auto Interp = +- std::unique_ptr(new Interpreter(std::move(CI), Err)); ++ auto Interp = std::unique_ptr( ++ new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr)); + if (Err) + return std::move(Err); + +@@ -617,6 +619,25 @@ createJITTargetMachineBuilder(const std::string &TT) { + return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); + } + ++llvm::Expected> ++Interpreter::createLLJITBuilder( ++ std::unique_ptr EPC, ++ llvm::StringRef OrcRuntimePath) { ++ const std::string &TT = EPC->getTargetTriple().getTriple(); ++ auto JTMB = createJITTargetMachineBuilder(TT); ++ if (!JTMB) ++ return JTMB.takeError(); ++ auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); ++ if (!JB) ++ return JB.takeError(); ++ ++ (*JB)->setExecutorProcessControl(std::move(EPC)); ++ (*JB)->setPlatformSetUp( ++ llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str())); ++ ++ return std::move(*JB); ++} ++ + llvm::Error Interpreter::CreateExecutor() { + if (IncrExecutor) + return llvm::make_error("Operation failed. " +@@ -757,11 +778,11 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { + if (!EE) + return EE.takeError(); + +- auto &DL = EE->getDataLayout(); +- +- if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load( +- name, DL.getGlobalPrefix())) +- EE->getMainJITDylib().addGenerator(std::move(*DLSG)); ++ if (auto DLSG = llvm::orc::EPCDynamicLibrarySearchGenerator::Load( ++ EE->getExecutionSession(), name)) ++ // FIXME: Eventually we should put each library in its own JITDylib and ++ // turn off process symbols by default. ++ EE->getProcessSymbolsJITDylib()->addGenerator(std::move(*DLSG)); + else + return DLSG.takeError(); + #endif +diff --git a/clang/lib/Interpreter/RemoteJITUtils.cpp b/clang/lib/Interpreter/RemoteJITUtils.cpp +new file mode 100644 +index 0000000000000..24a5f729f2dcb +--- /dev/null ++++ b/clang/lib/Interpreter/RemoteJITUtils.cpp +@@ -0,0 +1,267 @@ ++//===-- 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 ++#include ++#include ++#include ++#endif // LLVM_ON_UNIX ++ ++using namespace llvm; ++using namespace llvm::orc; ++ ++Expected 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("Invalid numeric format for slab size", ++ inconvertibleErrorCode()); ++ ++ return SlabSize * Units; ++} ++ ++Expected> ++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 (auto S = getSlabAllocSize(SlabAllocateSizeString)) ++ SlabSize = *S; ++ else ++ return S.takeError(); ++ } ++ ++ return MapperJITLinkMemoryManager::CreateWithMapper( ++ SlabSize, SREPC, SAs); ++} ++ ++Expected> ++launchExecutor(StringRef ExecutablePath, bool UseSharedMemory, ++ llvm::StringRef SlabAllocateSizeString) { ++#ifndef LLVM_ON_UNIX ++ // FIXME: Add support for Windows. ++ return make_error("-" + ExecutablePath + ++ " not supported on non-unix platforms", ++ inconvertibleErrorCode()); ++#elif !LLVM_ENABLE_THREADS ++ // Out of process mode using SimpleRemoteEPC depends on threads. ++ return make_error( ++ "-" + ExecutablePath + ++ " requires threads, but LLVM was built with " ++ "LLVM_ENABLE_THREADS=Off", ++ inconvertibleErrorCode()); ++#else ++ ++ if (!sys::fs::can_execute(ExecutablePath)) ++ return make_error( ++ 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("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 ExecutorPath, FDSpecifier; ++ { ++ ExecutorPath = std::make_unique(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(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]); ++ ++ auto S = SimpleRemoteEPC::Setup(); ++ if (UseSharedMemory) ++ S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) { ++ return createSharedMemoryManager(EPC, SlabAllocateSizeString); ++ }; ++ ++ return SimpleRemoteEPC::Create( ++ std::make_unique(std::nullopt), ++ std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]); ++#endif ++} ++ ++#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS ++ ++static Expected 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( ++ 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("invalid hostname", ++ inconvertibleErrorCode()); ++ ++ return SockFD; ++} ++#endif ++ ++Expected> ++connectTCPSocket(StringRef NetworkAddress, bool UseSharedMemory, ++ llvm::StringRef SlabAllocateSizeString) { ++#ifndef LLVM_ON_UNIX ++ // FIXME: Add TCP support for Windows. ++ return make_error("-" + NetworkAddress + ++ " not supported on non-unix platforms", ++ inconvertibleErrorCode()); ++#elif !LLVM_ENABLE_THREADS ++ // Out of process mode using SimpleRemoteEPC depends on threads. ++ return make_error( ++ "-" + NetworkAddress + ++ " requires threads, but LLVM was built with " ++ "LLVM_ENABLE_THREADS=Off", ++ inconvertibleErrorCode()); ++#else ++ ++ auto CreateErr = [NetworkAddress](Twine Details) { ++ return make_error( ++ 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 SockFD = connectTCPSocketImpl(Host.str(), PortStr.str()); ++ if (!SockFD) ++ return SockFD.takeError(); ++ ++ auto S = SimpleRemoteEPC::Setup(); ++ if (UseSharedMemory) ++ S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) { ++ return createSharedMemoryManager(EPC, SlabAllocateSizeString); ++ }; ++ ++ return SimpleRemoteEPC::Create( ++ std::make_unique(std::nullopt), ++ std::move(S), *SockFD, *SockFD); ++#endif ++} +diff --git a/clang/test/Interpreter/out-of-process.cpp b/clang/test/Interpreter/out-of-process.cpp +new file mode 100644 +index 0000000000000..edc4c3fee0966 +--- /dev/null ++++ b/clang/test/Interpreter/out-of-process.cpp +@@ -0,0 +1,88 @@ ++// REQUIRES: host-supports-jit ++ ++// RUN: cat %s | clang-repl -oop-executor -orc-runtime | FileCheck %s ++ ++extern "C" int printf(const char *, ...); ++ ++int intVar = 0; ++double doubleVar = 3.14; ++%undo ++double doubleVar = 2.71; ++ ++auto r1 = printf("intVar = %d\n", intVar); ++// CHECK: intVar = 0 ++auto r2 = printf("doubleVar = %.2f\n", doubleVar); ++// CHECK: doubleVar = 2.71 ++ ++// Test redefinition with inline and static functions. ++int add(int a, int b, int c) { return a + b + c; } ++%undo // Revert to the initial version of add ++inline int add(int a, int b) { return a + b; } ++ ++auto r3 = printf("add(1, 2) = %d\n", add(1, 2)); ++// CHECK-NEXT: add(1, 2) = 3 ++ ++// Test inline and lambda functions with variations. ++inline int square(int x) { return x * x; } ++auto lambdaSquare = [](int x) { return x * x; }; ++auto lambdaMult = [](int a, int b) { return a * b; }; ++ ++auto r4 = printf("square(4) = %d\n", square(4)); ++// CHECK-NEXT: square(4) = 16 ++auto lambda_r1 = printf("lambdaSquare(5) = %d\n", lambdaSquare(5)); ++// CHECK-NEXT: lambdaSquare(5) = 25 ++auto lambda_r2 = printf("lambdaMult(2, 3) = %d\n", lambdaMult(2, 3)); ++// CHECK-NEXT: lambdaMult(2, 3) = 6 ++ ++%undo // Undo previous lambda assignments ++auto lambda_r3 = lambdaMult(3, 4); // Should fail or revert to the original lambda ++ ++// Test weak and strong symbol linkage. ++int __attribute__((weak)) weakFunc() { return 42; } ++int strongFunc() { return 100; } ++%undo // Revert the weak function ++ ++auto r5 = printf("weakFunc() = %d\n", weakFunc()); ++// CHECK: weakFunc() = 42 ++auto r6 = printf("strongFunc() = %d\n", strongFunc()); ++// CHECK-NEXT: strongFunc() = 100 ++ ++// Weak variable linkage with different types. ++int varA = 20; ++static __typeof(varA) weakVarA __attribute__((__weakref__("varA"))); ++char charVar = 'c'; ++static __typeof(charVar) weakCharVar __attribute__((__weakref__("charVar"))); ++auto r7 = printf("weakVarA = %d\n", weakVarA); ++// CHECK: weakVarA = 20 ++auto r8 = printf("weakCharVar = %c\n", weakCharVar); ++// CHECK-NEXT: weakCharVar = c ++ ++// Test complex lambdas with captures. ++int captureVar = 5; ++auto captureLambda = [](int x) { return x + captureVar; };` ++int result1 = captureLambda(10); ++%undo // Undo capture lambda ++ ++auto r9 = printf("captureLambda(10) = %d\n", result1); ++// CHECK: captureLambda(10) = 15 ++ ++// Multiline statement test with arithmetic operations. ++int sum = \ ++ 5 + \ ++ 10; ++int prod = sum * 2; ++auto r10 = printf("sum = %d, prod = %d\n", sum, prod); ++// CHECK: sum = 15, prod = 30 ++ ++// Test multiline functions and macro behavior. ++#define MULTIPLY(a, b) ((a) * (b)) ++ ++int complexFunc(int x) \ ++{ \ ++ return MULTIPLY(x, 2) + x; \ ++} ++ ++auto r11 = printf("complexFunc(5) = %d\n", complexFunc(5)); ++// CHECK: complexFunc(5) = 15 ++ ++%quit +diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt +index f9a911b0ae8e2..68d86dd98cac3 100644 +--- a/clang/tools/clang-repl/CMakeLists.txt ++++ b/clang/tools/clang-repl/CMakeLists.txt +@@ -4,7 +4,9 @@ set( LLVM_LINK_COMPONENTS + LineEditor + Option + OrcJIT ++ OrcShared + Support ++ TargetParser + ) + + add_clang_tool(clang-repl +diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp +index 7af8e4f25d99e..54b27782d3db3 100644 +--- a/clang/tools/clang-repl/ClangRepl.cpp ++++ b/clang/tools/clang-repl/ClangRepl.cpp +@@ -10,7 +10,11 @@ + // + //===----------------------------------------------------------------------===// + ++#include "clang/Interpreter/RemoteJITUtils.h" ++ + #include "clang/Basic/Diagnostic.h" ++#include "clang/Basic/Version.h" ++#include "clang/Config/config.h" + #include "clang/Frontend/CompilerInstance.h" + #include "clang/Frontend/FrontendDiagnostic.h" + #include "clang/Interpreter/CodeCompletion.h" +@@ -24,8 +28,11 @@ + #include "llvm/Support/ManagedStatic.h" // llvm_shutdown + #include "llvm/Support/Signals.h" + #include "llvm/Support/TargetSelect.h" ++#include "llvm/TargetParser/Host.h" + #include + ++#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" ++ + // 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. +@@ -34,10 +41,36 @@ + LLVM_ATTRIBUTE_USED int __lsan_is_turned_off() { return 1; } + #endif + ++#define DEBUG_TYPE "clang-repl" ++ + static llvm::cl::opt CudaEnabled("cuda", llvm::cl::Hidden); + static llvm::cl::opt CudaPath("cuda-path", llvm::cl::Hidden); + static llvm::cl::opt OffloadArch("offload-arch", llvm::cl::Hidden); +- ++static llvm::cl::OptionCategory OOPCategory("Out-of-process Execution Options"); ++static llvm::cl::opt SlabAllocateSizeString( ++ "slab-allocate", ++ llvm::cl::desc("Allocate from a slab of the given size " ++ "(allowable suffixes: Kb, Mb, Gb. default = " ++ "Kb)"), ++ llvm::cl::init(""), llvm::cl::cat(OOPCategory)); ++static llvm::cl::opt ++ OOPExecutor("oop-executor", ++ llvm::cl::desc("Launch an out-of-process executor to run code"), ++ llvm::cl::init(""), llvm::cl::ValueOptional, ++ llvm::cl::cat(OOPCategory)); ++static llvm::cl::opt OOPExecutorConnect( ++ "oop-executor-connect", ++ llvm::cl::desc( ++ "Connect to an out-of-process executor through a TCP socket"), ++ llvm::cl::value_desc(":")); ++static llvm::cl::opt ++ OrcRuntimePath("orc-runtime", llvm::cl::desc("Path to the ORC runtime"), ++ llvm::cl::init(""), llvm::cl::ValueOptional, ++ llvm::cl::cat(OOPCategory)); ++static llvm::cl::opt UseSharedMemory( ++ "use-shared-memory", ++ llvm::cl::desc("Use shared memory to transfer generated code and data"), ++ llvm::cl::init(false), llvm::cl::cat(OOPCategory)); + static llvm::cl::list + ClangArgs("Xcc", + llvm::cl::desc("Argument to pass to the CompilerInvocation"), +@@ -47,6 +80,72 @@ static llvm::cl::opt OptHostSupportsJit("host-supports-jit", + static llvm::cl::list OptInputs(llvm::cl::Positional, + llvm::cl::desc("[code to run]")); + ++static llvm::Error sanitizeOopArguments(const char *ArgV0) { ++ // Only one of -oop-executor and -oop-executor-connect can be used. ++ if (!!OOPExecutor.getNumOccurrences() && ++ !!OOPExecutorConnect.getNumOccurrences()) ++ return llvm::make_error( ++ "Only one of -" + OOPExecutor.ArgStr + " and -" + ++ OOPExecutorConnect.ArgStr + " can be specified", ++ llvm::inconvertibleErrorCode()); ++ ++ llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); ++ // TODO: Remove once out-of-process execution support is implemented for ++ // non-Unix platforms. ++ if ((!SystemTriple.isOSBinFormatELF() && ++ !SystemTriple.isOSBinFormatMachO()) && ++ (OOPExecutor.getNumOccurrences() || ++ OOPExecutorConnect.getNumOccurrences())) ++ return llvm::make_error( ++ "Out-of-process execution is only supported on Unix platforms", ++ llvm::inconvertibleErrorCode()); ++ ++ // If -slab-allocate is passed, check that we're not trying to use it in ++ // -oop-executor or -oop-executor-connect mode. ++ // ++ // FIXME: Remove once we enable remote slab allocation. ++ if (SlabAllocateSizeString != "") { ++ if (OOPExecutor.getNumOccurrences() || ++ OOPExecutorConnect.getNumOccurrences()) ++ return llvm::make_error( ++ "-slab-allocate cannot be used with -oop-executor or " ++ "-oop-executor-connect", ++ llvm::inconvertibleErrorCode()); ++ } ++ ++ // 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(&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 ++ return llvm::make_error( ++ "Out-of-process execution is not supported on non-unix platforms", ++ llvm::inconvertibleErrorCode()); ++ } ++ ++ // If -oop-executor was used but no value was specified then use a sensible ++ // default. ++ if (!!OOPExecutor.getNumOccurrences() && OOPExecutor.empty()) { ++ llvm::SmallString<256> OOPExecutorPath(llvm::sys::fs::getMainExecutable( ++ ArgV0, reinterpret_cast(&sanitizeOopArguments))); ++ llvm::sys::path::remove_filename(OOPExecutorPath); ++ llvm::sys::path::append(OOPExecutorPath, "llvm-jitlink-executor"); ++ OOPExecutor = OOPExecutorPath.str().str(); ++ } ++ ++ return llvm::Error::success(); ++} ++ + static void LLVMErrorHandler(void *UserData, const char *Message, + bool GenCrashDiag) { + auto &Diags = *static_cast(UserData); +@@ -183,6 +282,25 @@ int main(int argc, const char **argv) { + DeviceCI = ExitOnErr(CB.CreateCudaDevice()); + } + ++ ExitOnErr(sanitizeOopArguments(argv[0])); ++ ++ std::unique_ptr 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 JB; ++ if (EPC) { ++ CB.SetTargetTriple(EPC->getTargetTriple().getTriple()); ++ JB = ExitOnErr( ++ 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 CI; +@@ -214,6 +332,9 @@ 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))); + diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index 841913c54..f5f7eb934 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -146,6 +146,33 @@ TEST(InterpreterTest, Process) { clang_Interpreter_dispose(CXI); } +#ifdef CPPINTEROP_WITH_OOP_JIT +TEST(InterpreterTest, OopJITProcess) { +#ifdef _WIN32 + GTEST_SKIP() << "Disabled on Windows. Needs fixing."; +#endif + if (llvm::sys::RunningOnValgrind()) + GTEST_SKIP() << "XFAIL due to Valgrind report"; + std::vector interpreter_args = { "-include", "new" }; + auto* I = Cpp::CreateInterpreter(interpreter_args, {}, true); + EXPECT_TRUE(Cpp::Process("") == 0); + EXPECT_TRUE(Cpp::Process("int a = 12;") == 0); + EXPECT_FALSE(Cpp::Process("error_here;") == 0); + // Linker/JIT error. + EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0); + + // C API + auto* CXI = clang_createInterpreterFromRawPtr(I); + clang_Interpreter_declare(CXI, "#include ", false); + clang_Interpreter_process(CXI, "int c = 42;"); + auto* CXV = clang_createValue(); + auto Res = clang_Interpreter_evaluate(CXI, "c", CXV); + EXPECT_EQ(Res, CXError_Success); + clang_Value_dispose(CXV); + clang_Interpreter_dispose(CXI); +} +#endif + TEST(InterpreterTest, EmscriptenExceptionHandling) { #ifndef EMSCRIPTEN GTEST_SKIP() << "This test is intended to check exception handling for Emscripten builds."; From eea2a1c92f6826a1afd6063e450fcb0044f08eef Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Tue, 17 Jun 2025 16:59:15 +0530 Subject: [PATCH 02/11] minor change --- unittests/CppInterOp/InterpreterTest.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index f5f7eb934..36c128391 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -160,16 +160,6 @@ TEST(InterpreterTest, OopJITProcess) { EXPECT_FALSE(Cpp::Process("error_here;") == 0); // Linker/JIT error. EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0); - - // C API - auto* CXI = clang_createInterpreterFromRawPtr(I); - clang_Interpreter_declare(CXI, "#include ", false); - clang_Interpreter_process(CXI, "int c = 42;"); - auto* CXV = clang_createValue(); - auto Res = clang_Interpreter_evaluate(CXI, "c", CXV); - EXPECT_EQ(Res, CXError_Success); - clang_Value_dispose(CXV); - clang_Interpreter_dispose(CXI); } #endif From cc3f601117184809c4a6e4d474f3cb1d3dfe66d7 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Tue, 17 Jun 2025 17:07:17 +0530 Subject: [PATCH 03/11] deleting extra workflows --- .github/workflows/MacOS-arm.yml | 201 --------------------------- .github/workflows/MacOS.yml | 186 ------------------------- .github/workflows/Ubuntu-arm.yml | 227 ------------------------------- .github/workflows/Ubuntu.yml | 215 ----------------------------- 4 files changed, 829 deletions(-) delete mode 100644 .github/workflows/MacOS-arm.yml delete mode 100644 .github/workflows/MacOS.yml delete mode 100644 .github/workflows/Ubuntu-arm.yml delete mode 100644 .github/workflows/Ubuntu.yml diff --git a/.github/workflows/MacOS-arm.yml b/.github/workflows/MacOS-arm.yml deleted file mode 100644 index 0ee48bc98..000000000 --- a/.github/workflows/MacOS-arm.yml +++ /dev/null @@ -1,201 +0,0 @@ -name: OSX-arm - -on: - pull_request: - branches: [main] - push: - branches: [main] - release: - types: [published] - schedule: - - cron: '30 20 * * *' # Warning: Timezone dep - 20:00 is 1:00 - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - build: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: osx15-arm-clang-clang-repl-20 - os: macos-15 - compiler: clang - clang-runtime: '20' - cling: Off - cppyy: Off - llvm_enable_projects: "clang;compiler-rt" - llvm_targets_to_build: "host" - oop-jit: On - - name: osx15-arm-clang-clang-repl-19-cppyy - os: macos-15 - compiler: clang - clang-runtime: '19' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx15-arm-clang-clang-repl-18-cppyy - os: macos-15 - compiler: clang - clang-runtime: '18' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx15-arm-clang-clang-repl-17-cppyy - os: macos-15 - compiler: clang - clang-runtime: '17' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx15-arm-clang-clang-repl-16 - os: macos-15 - compiler: clang - clang-runtime: '16' - cling: Off - cppyy: Off - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx15-arm-clang-clang18-cling-cppyy - os: macos-15 - compiler: clang - clang-runtime: '18' - cling: On - cppyy: On - cling-version: '1.2' - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Save PR Info - run: | - mkdir -p ./pr - echo ${{ github.event.number }} > ./pr/NR - echo ${{ github.repository }} > ./pr/REPO - - cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]') - if [[ "$cling_on" == "ON" ]]; then - export CLING_HASH=$(git ls-remote https://github.com/root-project/cling.git refs/tags/v${{ matrix.cling-version }} | tr '\t' '-') - export LLVM_HASH=$(git ls-remote https://github.com/root-project/llvm-project.git cling-llvm${{ matrix.clang-runtime}} | tr '\t' '-') - else - export CLING_HASH="Repl" - # May need to revert back to both having same llvm_hash, as below cause llvm to be rebuilt everytime commit is made to llvm/llvm-project for release a.x - # which could be quite often for new releases - export LLVM_HASH=$(git ls-remote https://github.com/llvm/llvm-project.git refs/heads/release/${{ matrix.clang-runtime}}.x | tr '\t' '-') - fi - - echo "CLING_HASH=$CLING_HASH" >> $GITHUB_ENV - echo "LLVM_HASH=$LLVM_HASH" >> $GITHUB_ENV - - - name: Restore Cache LLVM/Clang runtime build directory - uses: actions/cache/restore@v4 - id: cache - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-${{ matrix.compiler }}-clang-${{ matrix.clang-runtime }}.x-patch-${{ hashFiles(format('patches/llvm/clang{0}-*.patch', matrix.clang-runtime)) || 'none' }} - - - name: Setup default Build Type - run: | - echo "BUILD_TYPE=Release" >> $GITHUB_ENV - echo "CODE_COVERAGE=0" >> $GITHUB_ENV - echo "ncpus=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV - - - name: Setup compiler - run: | - vers="${compiler#*-}" - if [[ "${{ matrix.compiler }}" == *"gcc"* ]]; then - brew install "gcc@$vers" - echo "CC=gcc-${vers}" >> $GITHUB_ENV - echo "CXX=g++-${vers}" >> $GITHUB_ENV - else - cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]') - if [[ "${cling_on}" == "ON" ]]; then - brew install llvm@15 - brew remove llvm@18 - brew cleanup - #FIXME: Do not believe setting all these environment variables are necessary - # They were set to avoid using Xcodes libc++ and to stop CppInterOp using llvm@18 in tests - echo 'LDFLAGS="-L/opt/homebrew/opt/llvm@15/lib/ -L/opt/homebrew/opt/llvm@15/c++/"' >> $GITHUB_ENV - echo 'CPPFLAGS="-I/opt/homebrew/opt/llvm@15/include"' >> $GITHUB_ENV - echo 'CPATH="/opt/homebrew/include/"' >> $GITHUB_ENV - echo 'LIBRARY_PATH="/opt/homebrew/lib/"' >> $GITHUB_ENV - echo "CC=$(brew --prefix llvm@15)/bin/clang" >> $GITHUB_ENV - echo "CXX=$(brew --prefix llvm@15)/bin/clang++" >> $GITHUB_ENV - else - echo "CC=$(brew --prefix llvm@18)/bin/clang" >> $GITHUB_ENV - echo "CXX=$(brew --prefix llvm@18)/bin/clang++" >> $GITHUB_ENV - fi - fi - echo "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV - env: - compiler: ${{ matrix.compiler }} - - - name: Install deps - run: | - brew update --force - brew remove unxip - # workaround for https://github.com/actions/setup-python/issues/577 - for pkg in $(brew list | grep '^python@'); do - brew unlink "$pkg" - brew link --overwrite "$pkg" - done - brew upgrade openssl >/dev/null 2>&1 - brew upgrade --force - brew install ninja - brew install eigen - brew install boost - brew install gnu-sed - pip install distro pytest - - - - uses: ./.github/actions/Build_LLVM - with: - cache-hit: ${{ steps.cache.outputs.cache-hit }} - - - name: Save Cache LLVM/Clang runtime build directory - uses: actions/cache/save@v4 - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ steps.cache.outputs.cache-primary-key }} - - - uses: ./.github/actions/Build_and_Test_CppInterOp - - - uses: ./.github/actions/Build_and_Test_cppyy - - - name: Show debug info - if: ${{ failure() }} - run: | - export - echo $GITHUB_ENV - - - name: Setup tmate session - if: ${{ failure() && runner.debug }} - uses: mxschmitt/action-tmate@v3 - # When debugging increase to a suitable value! - timeout-minutes: 30 diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml deleted file mode 100644 index 5b2991ca9..000000000 --- a/.github/workflows/MacOS.yml +++ /dev/null @@ -1,186 +0,0 @@ -name: OSX-x86 - -on: - pull_request: - branches: [main] - push: - branches: [main] - release: - types: [published] - schedule: - - cron: '30 20 * * *' # Warning: Timezone dep - 20:00 is 1:00 - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - build: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: osx13-x86-clang-clang-repl-20 - os: macos-13 - compiler: clang - clang-runtime: '20' - cling: Off - cppyy: Off - llvm_enable_projects: "clang;compiler-rt" - llvm_targets_to_build: "host" - oop-jit: On - - name: osx13-x86-clang-clang-repl-19-cppyy - os: macos-13 - compiler: clang - clang-runtime: '19' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx13-x86-clang-clang-repl-18-cppyy - os: macos-13 - compiler: clang - clang-runtime: '18' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx13-x86-clang-clang-repl-17-cppyy - os: macos-13 - compiler: clang - clang-runtime: '17' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx13-x86-clang-clang-repl-16 - os: macos-13 - compiler: clang - clang-runtime: '16' - cling: Off - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - oop-jit: Off - - name: osx13-x86-clang-clang18-cling-cppyy - os: macos-13 - compiler: clang - clang-runtime: '18' - cling: On - cppyy: On - cling-version: '1.2' - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Save PR Info - run: | - mkdir -p ./pr - echo ${{ github.event.number }} > ./pr/NR - echo ${{ github.repository }} > ./pr/REPO - - cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]') - if [[ "$cling_on" == "ON" ]]; then - export CLING_HASH=$(git ls-remote https://github.com/root-project/cling.git refs/tags/v${{ matrix.cling-version }} | tr '\t' '-') - export LLVM_HASH=$(git ls-remote https://github.com/root-project/llvm-project.git cling-llvm${{ matrix.clang-runtime}} | tr '\t' '-') - else - export CLING_HASH="Repl" - # May need to revert back to both having same llvm_hash, as below cause llvm to be rebuilt everytime commit is made to llvm/llvm-project for release a.x - # which could be quite often for new releases - export LLVM_HASH=$(git ls-remote https://github.com/llvm/llvm-project.git refs/heads/release/${{ matrix.clang-runtime}}.x | tr '\t' '-') - fi - - echo "CLING_HASH=$CLING_HASH" >> $GITHUB_ENV - echo "LLVM_HASH=$LLVM_HASH" >> $GITHUB_ENV - - - name: Restore Cache LLVM/Clang runtime build directory - uses: actions/cache/restore@v4 - id: cache - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-${{ matrix.compiler }}-clang-${{ matrix.clang-runtime }}.x-patch-${{ hashFiles(format('patches/llvm/clang{0}-*.patch', matrix.clang-runtime)) || 'none' }} - - - name: Setup default Build Type - run: | - echo "BUILD_TYPE=Release" >> $GITHUB_ENV - echo "CODE_COVERAGE=0" >> $GITHUB_ENV - echo "ncpus=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV - - - name: Setup compiler - run: | - vers="${compiler#*-}" - if [[ "${{ matrix.compiler }}" == *"gcc"* ]]; then - brew install "gcc@$vers" - echo "CC=gcc-${vers}" >> $GITHUB_ENV - echo "CXX=g++-${vers}" >> $GITHUB_ENV - else - echo "CC=$(brew --prefix llvm@15)/bin/clang" >> $GITHUB_ENV - echo "CXX=$(brew --prefix llvm@15)/bin/clang++" >> $GITHUB_ENV - fi - echo "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV - env: - compiler: ${{ matrix.compiler }} - - - name: Install deps - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - run: | - brew update --force - brew remove swiftlint - # workaround for https://github.com/actions/setup-python/issues/577 - for pkg in $(brew list | grep '^python@'); do - brew unlink "$pkg" - brew link --overwrite "$pkg" - done - brew upgrade openssl >/dev/null 2>&1 - brew upgrade --force - brew install ninja - brew install eigen - brew install boost - brew install gnu-sed - pip install distro pytest - - - - uses: ./.github/actions/Build_LLVM - with: - cache-hit: ${{ steps.cache.outputs.cache-hit }} - - - name: Save Cache LLVM/Clang runtime build directory - uses: actions/cache/save@v4 - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ steps.cache.outputs.cache-primary-key }} - - - uses: ./.github/actions/Build_and_Test_CppInterOp - - - uses: ./.github/actions/Build_and_Test_cppyy - - - name: Show debug info - if: ${{ failure() }} - run: | - export - echo $GITHUB_ENV - - - name: Setup tmate session - if: ${{ failure() && runner.debug }} - uses: mxschmitt/action-tmate@v3 - # When debugging increase to a suitable value! - timeout-minutes: 30 diff --git a/.github/workflows/Ubuntu-arm.yml b/.github/workflows/Ubuntu-arm.yml deleted file mode 100644 index b63d1441f..000000000 --- a/.github/workflows/Ubuntu-arm.yml +++ /dev/null @@ -1,227 +0,0 @@ -name: Ubuntu-arm - -on: - pull_request: - branches: [main] - push: - branches: [main] - release: - types: [published] - schedule: - - cron: '30 20 * * *' # Warning: Timezone dep - 20:00 is 1:00 - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - build: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: ubu22-arm-gcc12-clang-repl-20-coverage - os: ubuntu-22.04-arm - compiler: gcc-12 - clang-runtime: '20' - cling: Off - cppyy: Off - llvm_enable_projects: "clang;compiler-rt" - llvm_targets_to_build: "host;NVPTX" - coverage: true - oop-jit: On - - name: ubu24-arm-gcc12-clang-repl-20 - os: ubuntu-24.04-arm - compiler: gcc-12 - clang-runtime: '20' - cling: Off - cppyy: Off - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-arm-gcc12-clang-repl-19-cppyy - os: ubuntu-24.04-arm - compiler: gcc-12 - clang-runtime: '19' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-arm-gcc12-clang-repl-18-cppyy - os: ubuntu-24.04-arm - compiler: gcc-12 - clang-runtime: '18' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-arm-gcc12-clang-repl-17-cppyy - os: ubuntu-24.04-arm - compiler: gcc-12 - clang-runtime: '17' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-arm-gcc12-clang-repl-16 - os: ubuntu-24.04-arm - compiler: gcc-12 - clang-runtime: '16' - cling: Off - cppyy: Off - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-arm-gcc9-clang18-cling-cppyy - os: ubuntu-24.04-arm - compiler: gcc-9 - clang-runtime: '18' - cling: On - cppyy: Off - cling-version: '1.2' - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Save PR Info - run: | - mkdir -p ./pr - echo ${{ github.event.number }} > ./pr/NR - echo ${{ github.repository }} > ./pr/REPO - - cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]') - if [[ "$cling_on" == "ON" ]]; then - export CLING_HASH=$(git ls-remote https://github.com/root-project/cling.git refs/tags/v${{ matrix.cling-version }} | tr '\t' '-') - export LLVM_HASH=$(git ls-remote https://github.com/root-project/llvm-project.git cling-llvm${{ matrix.clang-runtime}} | tr '\t' '-') - else - export CLING_HASH="Repl" - # May need to revert back to both having same llvm_hash, as below cause llvm to be rebuilt everytime commit is made to llvm/llvm-project for release a.x - # which could be quite often for new releases - export LLVM_HASH=$(git ls-remote https://github.com/llvm/llvm-project.git refs/heads/release/${{ matrix.clang-runtime}}.x | tr '\t' '-') - fi - - echo "CLING_HASH=$CLING_HASH" >> $GITHUB_ENV - echo "LLVM_HASH=$LLVM_HASH" >> $GITHUB_ENV - - - name: Restore Cache LLVM/Clang runtime build directory - uses: actions/cache/restore@v4 - id: cache - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-${{ matrix.compiler }}-clang-${{ matrix.clang-runtime }}.x-patch-${{ hashFiles(format('patches/llvm/clang{0}-*.patch', matrix.clang-runtime)) || 'none' }} - - - name: Setup default Build Type - run: | - echo "BUILD_TYPE=Release" >> $GITHUB_ENV - echo "CODE_COVERAGE=0" >> $GITHUB_ENV - echo "ncpus=$(nproc --all)" >> $GITHUB_ENV - - - name: Setup compiler - run: | - # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html - vers="${compiler#*-}" - os_codename="`cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2`" - ##sudo apt update - if [[ "${{ matrix.compiler }}" == *"gcc"* ]]; then - sudo apt install -y gcc-${vers} g++-${vers} lld - echo "CC=gcc-${vers}" >> $GITHUB_ENV - echo "CXX=g++-${vers}" >> $GITHUB_ENV - else - if ! sudo apt install -y clang-${vers}; then - curl https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo "deb https://apt.llvm.org/${os_codename}/ llvm-toolchain-${os_codename}-${vers} main" | sudo tee -a /etc/apt/sources.list - sudo apt-get update - sudo apt-get install -y clang-${vers} - fi - echo "CC=clang-${vers}" >> $GITHUB_ENV - echo "CXX=clang++-${vers}" >> $GITHUB_ENV - fi - env: - compiler: ${{ matrix.compiler }} - - - name: Install deps - run: | - # Install deps - sudo apt-get update - sudo apt-get install valgrind ninja-build - sudo apt-get install git g++ debhelper devscripts gnupg python3 doxygen graphviz python3-sphinx - sudo apt-get install -y libc6-dbg - sudo apt-get install valgrind - sudo apt autoremove - sudo apt clean - # Install libraries used by the cppyy test suite - sudo apt install libeigen3-dev - sudo apt install libboost-all-dev - - - uses: ./.github/actions/Build_LLVM - with: - cache-hit: ${{ steps.cache.outputs.cache-hit }} - - - name: Save Cache LLVM/Clang runtime build directory - uses: actions/cache/save@v4 - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ steps.cache.outputs.cache-primary-key }} - - - name: Setup code coverage - if: ${{ success() && (matrix.coverage == true) }} - run: | - sudo apt install lcov - echo "CODE_COVERAGE=1" >> $GITHUB_ENV - echo "BUILD_TYPE=Debug" >> $GITHUB_ENV - - - uses: ./.github/actions/Build_and_Test_CppInterOp - - - name: Prepare code coverage report - if: ${{ success() && (matrix.coverage == true) }} - run: | - # Create lcov report - # capture coverage info - vers="${CC#*-}" - lcov --directory build/ --capture --output-file coverage.info --gcov-tool /usr/bin/gcov-${vers} - lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' ${{ github.workspace }}'/llvm-project/*' ${{ github.workspace }}'/unittests/*' --output-file coverage.info - # output coverage data for debugging (optional) - lcov --list coverage.info - - - name: Upload to codecov.io - if: ${{ success() && (matrix.coverage == true) }} - uses: codecov/codecov-action@v5 - with: - files: ./coverage.info - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - - - uses: ./.github/actions/Build_and_Test_cppyy - - - name: Show debug info - if: ${{ failure() }} - run: | - export - echo $GITHUB_ENV - - - name: Setup tmate session - if: ${{ failure() && runner.debug }} - uses: mxschmitt/action-tmate@v3 - # When debugging increase to a suitable value! - timeout-minutes: 30 diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml deleted file mode 100644 index e11394da0..000000000 --- a/.github/workflows/Ubuntu.yml +++ /dev/null @@ -1,215 +0,0 @@ -name: Ubuntu-x86 - -on: - pull_request: - branches: [main] - push: - branches: [main] - release: - types: [published] - schedule: - - cron: '30 20 * * *' # Warning: Timezone dep - 20:00 is 1:00 - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - build: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: ubu24-x86-gcc12-clang-repl-20 - os: ubuntu-24.04 - compiler: gcc-12 - clang-runtime: '20' - cling: Off - cppyy: Off - llvm_enable_projects: "clang;compiler-rt" - llvm_targets_to_build: "host;NVPTX" - oop-jit: On - - name: ubu24-x86-gcc12-clang-repl-19-cppyy - os: ubuntu-24.04 - compiler: gcc-12 - clang-runtime: '19' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-x86-gcc12-clang-repl-18-cppyy - os: ubuntu-24.04 - compiler: gcc-12 - clang-runtime: '18' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-x86-gcc12-clang-repl-17-cppyy - os: ubuntu-24.04 - compiler: gcc-12 - clang-runtime: '17' - cling: Off - cppyy: On - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-x86-gcc12-clang-repl-16 - os: ubuntu-24.04 - compiler: gcc-12 - clang-runtime: '16' - cling: Off - cppyy: Off - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - name: ubu24-x86-gcc9-clang18-cling-cppyy - os: ubuntu-24.04 - compiler: gcc-9 - clang-runtime: '18' - cling: On - cppyy: Off - cling-version: '1.2' - llvm_enable_projects: "clang" - llvm_targets_to_build: "host;NVPTX" - oop-jit: Off - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Save PR Info - run: | - mkdir -p ./pr - echo ${{ github.event.number }} > ./pr/NR - echo ${{ github.repository }} > ./pr/REPO - - cling_on=$(echo "${{ matrix.cling }}" | tr '[:lower:]' '[:upper:]') - if [[ "$cling_on" == "ON" ]]; then - export CLING_HASH=$(git ls-remote https://github.com/root-project/cling.git refs/tags/v${{ matrix.cling-version }} | tr '\t' '-') - export LLVM_HASH=$(git ls-remote https://github.com/root-project/llvm-project.git cling-llvm${{ matrix.clang-runtime}} | tr '\t' '-') - else - export CLING_HASH="Repl" - # May need to revert back to both having same llvm_hash, as below cause llvm to be rebuilt everytime commit is made to llvm/llvm-project for release a.x - # which could be quite often for new releases - export LLVM_HASH=$(git ls-remote https://github.com/llvm/llvm-project.git refs/heads/release/${{ matrix.clang-runtime}}.x | tr '\t' '-') - fi - - echo "CLING_HASH=$CLING_HASH" >> $GITHUB_ENV - echo "LLVM_HASH=$LLVM_HASH" >> $GITHUB_ENV - - - name: Restore Cache LLVM/Clang runtime build directory - uses: actions/cache/restore@v4 - id: cache - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ env.CLING_HASH }}-${{ runner.os }}-${{ matrix.os }}-${{ matrix.compiler }}-clang-${{ matrix.clang-runtime }}.x-patch-${{ hashFiles(format('patches/llvm/clang{0}-*.patch', matrix.clang-runtime)) || 'none' }} - - - name: Setup default Build Type - run: | - echo "BUILD_TYPE=Release" >> $GITHUB_ENV - echo "CODE_COVERAGE=0" >> $GITHUB_ENV - echo "ncpus=$(nproc --all)" >> $GITHUB_ENV - - - name: Setup compiler - run: | - # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html - vers="${compiler#*-}" - os_codename="`cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2`" - ##sudo apt update - if [[ "${{ matrix.compiler }}" == *"gcc"* ]]; then - sudo apt install -y gcc-${vers} g++-${vers} lld - echo "CC=gcc-${vers}" >> $GITHUB_ENV - echo "CXX=g++-${vers}" >> $GITHUB_ENV - else - if ! sudo apt install -y clang-${vers}; then - curl https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - echo "deb https://apt.llvm.org/${os_codename}/ llvm-toolchain-${os_codename}-${vers} main" | sudo tee -a /etc/apt/sources.list - sudo apt-get update - sudo apt-get install -y clang-${vers} - fi - echo "CC=clang-${vers}" >> $GITHUB_ENV - echo "CXX=clang++-${vers}" >> $GITHUB_ENV - fi - env: - compiler: ${{ matrix.compiler }} - - - name: Install deps - run: | - # Install deps - sudo apt-get update - sudo apt-get install valgrind ninja-build - sudo apt-get install git g++ debhelper devscripts gnupg python3 doxygen graphviz python3-sphinx - sudo apt-get install -y libc6-dbg - sudo apt autoremove - sudo apt clean - # Install libraries used by the cppyy test suite - sudo apt install libeigen3-dev - sudo apt install libboost-all-dev - - uses: ./.github/actions/Build_LLVM - with: - cache-hit: ${{ steps.cache.outputs.cache-hit }} - - - name: Save Cache LLVM/Clang runtime build directory - uses: actions/cache/save@v4 - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ steps.cache.outputs.cache-primary-key }} - - - name: Setup code coverage - if: ${{ success() && (matrix.coverage == true) }} - run: | - sudo apt install lcov - echo "CODE_COVERAGE=1" >> $GITHUB_ENV - echo "BUILD_TYPE=Debug" >> $GITHUB_ENV - - - uses: ./.github/actions/Build_and_Test_CppInterOp - - - name: Prepare code coverage report - if: ${{ success() && (matrix.coverage == true) }} - run: | - # Create lcov report - # capture coverage info - vers="${CC#*-}" - lcov --directory build/ --capture --output-file coverage.info --gcov-tool /usr/bin/gcov-${vers} - lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' ${{ github.workspace }}'/llvm-project/*' ${{ github.workspace }}'/unittests/*' --output-file coverage.info - # output coverage data for debugging (optional) - lcov --list coverage.info - - - name: Upload to codecov.io - if: ${{ success() && (matrix.coverage == true) }} - uses: codecov/codecov-action@v5 - with: - files: ./coverage.info - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - - - uses: ./.github/actions/Build_and_Test_cppyy - - - name: Show debug info - if: ${{ failure() }} - run: | - export - echo $GITHUB_ENV - - - name: Setup tmate session - if: ${{ failure() && runner.debug }} - uses: mxschmitt/action-tmate@v3 - # When debugging increase to a suitable value! - timeout-minutes: 30 From 439676507e4067c359356a1598946c9c4d8b058a Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Tue, 17 Jun 2025 17:24:42 +0530 Subject: [PATCH 04/11] adding compiler-rt --- .github/actions/Build_LLVM/action.yml | 4 ++-- .github/workflows/main.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index 8eef77ea9..070cc4b85 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -49,7 +49,7 @@ runs: git apply -v ../patches/llvm/clang${{ matrix.clang-runtime }}-*.patch echo "Apply clang${{ matrix.clang-runtime }}-*.patch patches:" fi - if [[ "${{ matrix.llvm_enable_runtimes }}" == "clang;compile-rt" ]]; then + if [[ "${{ matrix.oop-jit }}" == "On" ]]; then git apply -v ../patches/llvm/out-of-process-jit-execution.patch echo "Apply out-of-process-jit-execution.patch:" fi @@ -72,7 +72,7 @@ runs: if [[ "${{ runner.os }}" == "Linux" ]]; then ninja clang clang-repl llvm-jitlink-executor orc_rt -j $(nproc --all) elif [[ "${{ runner.os }}" == "macOS" ]]; then - ninja clang clang-repl llvm-jitlink-executor orc_rt -j $(nproc --all) + ninja clang clang-repl llvm-jitlink-executor orc_rt_osx -j $(nproc --all) fi fi cd ./tools/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bfae4f1ab..8b37b56f5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" coverage: true oop-jit: "On" @@ -39,7 +39,7 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" oop-jit: "On" - name: ubu24-arm-gcc12-clang-repl-19-cppyy @@ -140,7 +140,7 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" oop-jit: "On" - name: osx15-arm-clang-clang-repl-19-cppyy @@ -191,7 +191,7 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang" + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" oop-jit: "On" - name: osx13-x86-clang-clang-repl-19-cppyy From 5536edfc66fa5eb5a4aa9025676c07c3bc13c732 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Tue, 17 Jun 2025 20:25:07 +0530 Subject: [PATCH 05/11] request changes addressed --- .github/actions/Build_LLVM/action.yml | 2 +- .github/workflows/main.yml | 37 ++++++++-- CMakeLists.txt | 10 +-- lib/CppInterOp/Compatibility.h | 74 +++++++++++-------- lib/CppInterOp/CppInterOp.cpp | 6 +- ...ng20-1-out-of-process-jit-execution.patch} | 0 unittests/CppInterOp/InterpreterTest.cpp | 32 ++++---- 7 files changed, 97 insertions(+), 64 deletions(-) rename patches/llvm/{out-of-process-jit-execution.patch => clang20-1-out-of-process-jit-execution.patch} (100%) diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index 070cc4b85..babc4b428 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -50,7 +50,7 @@ runs: echo "Apply clang${{ matrix.clang-runtime }}-*.patch patches:" fi if [[ "${{ matrix.oop-jit }}" == "On" ]]; then - git apply -v ../patches/llvm/out-of-process-jit-execution.patch + git apply -v ../patches/llvm/clang20-1-out-of-process-jit-execution.patch echo "Apply out-of-process-jit-execution.patch:" fi cd build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8b37b56f5..2819ff7b5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,8 +32,7 @@ jobs: llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" coverage: true - oop-jit: "On" - - name: ubu24-arm-gcc12-clang-repl-20 + - name: ubu24-arm-gcc12-clang-repl-20-oop os: ubuntu-24.04-arm compiler: gcc-12 clang-runtime: '20' @@ -41,7 +40,15 @@ jobs: cppyy: Off llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" - oop-jit: "On" + oop-jit: On + - name: ubu24-arm-gcc12-clang-repl-20 + os: ubuntu-24.04-arm + compiler: gcc-12 + clang-runtime: '20' + cling: Off + cppyy: Off + llvm_enable_projects: "clang" + llvm_targets_to_build: "host;NVPTX" - name: ubu24-arm-gcc12-clang-repl-19-cppyy os: ubuntu-24.04-arm compiler: gcc-12 @@ -134,7 +141,7 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # MacOS Arm Jobs - - name: osx15-arm-clang-clang-repl-20 + - name: osx15-arm-clang-clang-repl-20-oop os: macos-15 compiler: clang clang-runtime: '20' @@ -142,7 +149,15 @@ jobs: cppyy: Off llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" - oop-jit: "On" + oop-jit: On + - name: osx15-arm-clang-clang-repl-20 + os: macos-15 + compiler: clang + clang-runtime: '20' + cling: Off + cppyy: Off + llvm_enable_projects: "clang" + llvm_targets_to_build: "host" - name: osx15-arm-clang-clang-repl-19-cppyy os: macos-15 compiler: clang @@ -185,7 +200,7 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # MacOS X86 Jobs - - name: osx13-x86-clang-clang-repl-20 + - name: osx13-x86-clang-clang-repl-20-oop os: macos-13 compiler: clang clang-runtime: '20' @@ -193,7 +208,15 @@ jobs: cppyy: Off llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" - oop-jit: "On" + oop-jit: On + - name: osx13-x86-clang-clang-repl-20 + os: macos-13 + compiler: clang + clang-runtime: '20' + cling: Off + cppyy: Off + llvm_enable_projects: "clang" + llvm_targets_to_build: "host" - name: osx13-x86-clang-clang-repl-19-cppyy os: macos-13 compiler: clang diff --git a/CMakeLists.txt b/CMakeLists.txt index 71fc9aefc..53bfa687e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,6 +305,11 @@ else() message(FATAL_ERROR "We need either CPPINTEROP_USE_CLING or CPPINTEROP_USE_REPL") endif() +include_directories(SYSTEM ${CLANG_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) +separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) +add_definitions(${LLVM_DEFINITIONS_LIST}) + if(CPPINTEROP_WITH_OOP_JIT) add_definitions(-DCPPINTEROP_WITH_OOP_JIT) endif() @@ -312,11 +317,6 @@ endif() string(REGEX REPLACE "/build/lib/cmake/llvm$" "" LLVM_SOURCE_DIR "${LLVM_DIR}") add_definitions(-DLLVM_SOURCE_DIR="${LLVM_SOURCE_DIR}") -include_directories(SYSTEM ${CLANG_INCLUDE_DIRS}) -include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) -separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) -add_definitions(${LLVM_DEFINITIONS_LIST}) - # If the llvm sources are present add them with higher priority. if (LLVM_BUILD_MAIN_SRC_DIR) # LLVM_INCLUDE_DIRS contains the include paths to both LLVM's source and diff --git a/lib/CppInterOp/Compatibility.h b/lib/CppInterOp/Compatibility.h index d72658829..cf0f283c9 100644 --- a/lib/CppInterOp/Compatibility.h +++ b/lib/CppInterOp/Compatibility.h @@ -206,16 +206,17 @@ inline void codeComplete(std::vector& Results, #include "llvm/Support/Error.h" +#include + #ifdef CPPINTEROP_WITH_OOP_JIT -#include "clang/Interpreter/RemoteJITUtils.h" #include "clang/Basic/Version.h" +#include "clang/Interpreter/RemoteJITUtils.h" #include "llvm/TargetParser/Host.h" #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" #endif - -static llvm::ExitOnError ExitOnError; +static const llvm::ExitOnError ExitOnError; namespace compat { @@ -259,45 +260,54 @@ createClangInterpreter(std::vector& args, bool outOfProcess) { if (CudaEnabled) DeviceCI->LoadRequestedPlugins(); - #ifdef CPPINTEROP_WITH_OOP_JIT +#ifdef CPPINTEROP_WITH_OOP_JIT std::unique_ptr JB; - if(outOfProcess) { - std::string OOPExecutor = std::string(LLVM_SOURCE_DIR) + "/build/bin/llvm-jitlink-executor"; - bool UseSharedMemory = false; - std::string SlabAllocateSizeString = ""; - std::unique_ptr EPC; - EPC = ExitOnError( - launchExecutor(OOPExecutor, UseSharedMemory, SlabAllocateSizeString)); - - #ifdef __APPLE__ - std::string OrcRuntimePath = std::string(LLVM_SOURCE_DIR) + "/build/lib/clang/20/lib/darwin/liborc_rt_osx.a"; - #else - std::string OrcRuntimePath = std::string(LLVM_SOURCE_DIR) + "/build/lib/x86_64-unknown-linux-gnu/liborc_rt.a"; - #endif - if (EPC) { - - CB.SetTargetTriple(EPC->getTargetTriple().getTriple()); - JB = ExitOnError( - clang::Interpreter::createLLJITBuilder(std::move(EPC), OrcRuntimePath)); - } + if (outOfProcess) { + std::string OOPExecutor = + std::string(LLVM_SOURCE_DIR) + "/build/bin/llvm-jitlink-executor"; + bool UseSharedMemory = false; + std::string SlabAllocateSizeString = ""; + std::unique_ptr EPC; + EPC = ExitOnError( + launchExecutor(OOPExecutor, UseSharedMemory, SlabAllocateSizeString)); + +#ifdef __APPLE__ + std::string OrcRuntimePath = + std::string(LLVM_SOURCE_DIR) + + "/build/lib/clang/20/lib/darwin/liborc_rt_osx.a"; +#else + std::string OrcRuntimePath = + std::string(LLVM_SOURCE_DIR) + + "/build/lib/x86_64-unknown-linux-gnu/liborc_rt.a"; +#endif + if (EPC) { + + CB.SetTargetTriple(EPC->getTargetTriple().getTriple()); + JB = ExitOnError(clang::Interpreter::createLLJITBuilder(std::move(EPC), + OrcRuntimePath)); + } } auto innerOrErr = - CudaEnabled ? clang::Interpreter::createWithCUDA(std::move(*ciOrErr), - std::move(DeviceCI)) - : clang::Interpreter::create(std::move(*ciOrErr), std::move(JB)); - #else - if(outOfProcess) { - llvm::errs() << "[CreateClangInterpreter]: No compatibility with out-of-process JIT" - << "\n"; + CudaEnabled + ? clang::Interpreter::createWithCUDA(std::move(*ciOrErr), + std::move(DeviceCI)) + : clang::Interpreter::create(std::move(*ciOrErr), std::move(JB)); +#else + if (outOfProcess) { + llvm::errs() + << "[CreateClangInterpreter]: No compatibility with out-of-process JIT" + << "(To enable recompile CppInterOp with " + "`-DCPPINTEROP_WITH_OOP_JIT=ON`)" + << "\n"; return nullptr; } auto innerOrErr = CudaEnabled ? clang::Interpreter::createWithCUDA(std::move(*ciOrErr), std::move(DeviceCI)) : clang::Interpreter::create(std::move(*ciOrErr)); - #endif +#endif if (!innerOrErr) { llvm::logAllUnhandledErrors(innerOrErr.takeError(), llvm::errs(), @@ -444,7 +454,7 @@ class SynthesizingCodeRAII { "Failed to generate PTU:"); } }; -} +} // namespace compat #endif // CPPINTEROP_USE_REPL diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index b0d817dfd..858407b70 100755 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -3031,11 +3031,11 @@ static std::string MakeResourcesPath() { } // namespace TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, - const std::vector& GpuArgs /*={}*/, bool is_out_of_process) { + const std::vector& GpuArgs /*={}*/, bool outOfProcess) { std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); std::string ResourceDir = MakeResourcesPath(); std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), - "-std=c++14", "-gdwarf-4", "-O0"}; + "-std=c++14"}; ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str()); #ifdef _WIN32 // FIXME : Workaround Sema::PushDeclContext assert on windows @@ -3075,7 +3075,7 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); #else auto Interp = compat::Interpreter::create(static_cast(ClingArgv.size()), - ClingArgv.data(), nullptr, {}, nullptr, true, is_out_of_process); + ClingArgv.data(), nullptr, {}, nullptr, true, outOfProcess); if (!Interp) return nullptr; auto* I = Interp.release(); diff --git a/patches/llvm/out-of-process-jit-execution.patch b/patches/llvm/clang20-1-out-of-process-jit-execution.patch similarity index 100% rename from patches/llvm/out-of-process-jit-execution.patch rename to patches/llvm/clang20-1-out-of-process-jit-execution.patch diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index 36c128391..d2dc0e06f 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -146,22 +146,22 @@ TEST(InterpreterTest, Process) { clang_Interpreter_dispose(CXI); } -#ifdef CPPINTEROP_WITH_OOP_JIT -TEST(InterpreterTest, OopJITProcess) { -#ifdef _WIN32 - GTEST_SKIP() << "Disabled on Windows. Needs fixing."; -#endif - if (llvm::sys::RunningOnValgrind()) - GTEST_SKIP() << "XFAIL due to Valgrind report"; - std::vector interpreter_args = { "-include", "new" }; - auto* I = Cpp::CreateInterpreter(interpreter_args, {}, true); - EXPECT_TRUE(Cpp::Process("") == 0); - EXPECT_TRUE(Cpp::Process("int a = 12;") == 0); - EXPECT_FALSE(Cpp::Process("error_here;") == 0); - // Linker/JIT error. - EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0); -} -#endif +// #ifdef CPPINTEROP_WITH_OOP_JIT +// TEST(InterpreterTest, OopJITProcess) { +// #ifdef _WIN32 +// GTEST_SKIP() << "Disabled on Windows. Needs fixing."; +// #endif +// if (llvm::sys::RunningOnValgrind()) +// GTEST_SKIP() << "XFAIL due to Valgrind report"; +// std::vector interpreter_args = { "-include", "new" }; +// auto* I = Cpp::CreateInterpreter(interpreter_args, {}, true); +// EXPECT_TRUE(Cpp::Process("") == 0); +// EXPECT_TRUE(Cpp::Process("int a = 12;") == 0); +// EXPECT_FALSE(Cpp::Process("error_here;") == 0); +// // Linker/JIT error. +// EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0); +// } +// #endif TEST(InterpreterTest, EmscriptenExceptionHandling) { #ifndef EMSCRIPTEN From fac8d384a62737c52b1d0ce7fd6f9fcb5ffcff13 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Tue, 17 Jun 2025 20:25:54 +0530 Subject: [PATCH 06/11] request changes addressed --- lib/CppInterOp/Compatibility.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/CppInterOp/Compatibility.h b/lib/CppInterOp/Compatibility.h index cf0f283c9..b260aff47 100644 --- a/lib/CppInterOp/Compatibility.h +++ b/lib/CppInterOp/Compatibility.h @@ -79,7 +79,6 @@ static inline char* GetEnv(const char* Var_Name) { // std::regex breaks pytorch's jit: pytorch/pytorch#49460 #include "llvm/Support/Regex.h" -#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #ifdef CPPINTEROP_USE_CLING From 95102411a7eabe278e14aa4520edbe960c2d892f Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Wed, 18 Jun 2025 09:35:19 +0530 Subject: [PATCH 07/11] change workflow --- .github/actions/Build_LLVM/action.yml | 4 ++-- .github/workflows/main.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index babc4b428..a6adc64f2 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -70,9 +70,9 @@ runs: ninja clang clangInterpreter clangStaticAnalyzerCore -j ${{ env.ncpus }} if [[ "${{ matrix.oop-jit }}" == "On" ]]; then if [[ "${{ runner.os }}" == "Linux" ]]; then - ninja clang clang-repl llvm-jitlink-executor orc_rt -j $(nproc --all) + ninja clang clang-repl llvm-jitlink-executor orc_rt -j ${{ env.ncpus }} elif [[ "${{ runner.os }}" == "macOS" ]]; then - ninja clang clang-repl llvm-jitlink-executor orc_rt_osx -j $(nproc --all) + ninja clang clang-repl llvm-jitlink-executor orc_rt_osx -j ${{ env.ncpus }} fi fi cd ./tools/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2819ff7b5..f60857849 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: clang-runtime: '20' cling: Off cppyy: Off - llvm_enable_projects: "clang;compiler-rt" + llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" coverage: true - name: ubu24-arm-gcc12-clang-repl-20-oop From 34d56704e1132a63b70f144d4beb6d8c79b122bf Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Fri, 20 Jun 2025 11:18:57 +0530 Subject: [PATCH 08/11] request changes addressed --- .github/actions/Build_LLVM/action.yml | 7 +-- .../Build_and_Test_CppInterOp/action.yml | 33 +++++--------- CMakeLists.txt | 3 ++ README.md | 4 +- docs/InstallationAndUsage.rst | 43 +++++++++++++++++++ include/CppInterOp/CppInterOp.h | 2 + lib/CppInterOp/Compatibility.h | 4 ++ lib/CppInterOp/CppInterOp.cpp | 4 ++ unittests/CppInterOp/InterpreterTest.cpp | 32 +++++++------- 9 files changed, 86 insertions(+), 46 deletions(-) diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index a6adc64f2..e6d4a31b2 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -69,11 +69,8 @@ runs: ../llvm ninja clang clangInterpreter clangStaticAnalyzerCore -j ${{ env.ncpus }} if [[ "${{ matrix.oop-jit }}" == "On" ]]; then - if [[ "${{ runner.os }}" == "Linux" ]]; then - ninja clang clang-repl llvm-jitlink-executor orc_rt -j ${{ env.ncpus }} - elif [[ "${{ runner.os }}" == "macOS" ]]; then - ninja clang clang-repl llvm-jitlink-executor orc_rt_osx -j ${{ env.ncpus }} - fi + if [ "${{ matrix.os }}}" = "macos"* ]; then SUFFIX="_osx"; fi + ninja clang_repl llvm-jitlink-executor orc_rt${SUFFIX} -j ${{ env.ncpus }} fi cd ./tools/ rm -rf $(find . -maxdepth 1 ! -name "clang" ! -name ".") diff --git a/.github/actions/Build_and_Test_CppInterOp/action.yml b/.github/actions/Build_and_Test_CppInterOp/action.yml index e875b4af4..c933ad8c3 100644 --- a/.github/actions/Build_and_Test_CppInterOp/action.yml +++ b/.github/actions/Build_and_Test_CppInterOp/action.yml @@ -40,29 +40,16 @@ runs: -DLLVM_ENABLE_WERROR=On \ ../ else - if [[ "${{ matrix.oop-jit }}" == "On" ]]; then - cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ - -DCPPINTEROP_INCLUDE_DOCS=${{ matrix.documentation }} \ - -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ - -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ - -DBUILD_SHARED_LIBS=ON \ - -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ - -DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR \ - -DLLVM_ENABLE_WERROR=On \ - -DCPPINTEROP_WITH_OOP_JIT=ON \ - ../ - else - cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ - -DCPPINTEROP_INCLUDE_DOCS=${{ matrix.documentation }} \ - -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ - -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ - -DBUILD_SHARED_LIBS=ON \ - -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ - -DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR \ - -DLLVM_ENABLE_WERROR=On \ - -DCPPINTEROP_WITH_OOP_JIT=OFF \ - ../ - fi + cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ + -DCPPINTEROP_INCLUDE_DOCS=${{ matrix.documentation }} \ + -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ + -DClang_DIR=$LLVM_BUILD_DIR/lib/cmake/clang \ + -DBUILD_SHARED_LIBS=ON \ + -DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \ + -DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR \ + -DLLVM_ENABLE_WERROR=On \ + -DCPPINTEROP_WITH_OOP_JIT=${{ matrix.oop-jit }} \ + ../ fi docs_on=$(echo "${{ matrix.documentation }}" | tr '[:lower:]' '[:upper:]') if [[ "${docs_on}" == "ON" ]]; then diff --git a/CMakeLists.txt b/CMakeLists.txt index 53bfa687e..57cc29342 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -311,6 +311,9 @@ separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) add_definitions(${LLVM_DEFINITIONS_LIST}) if(CPPINTEROP_WITH_OOP_JIT) + if(WIN32 OR EMSCRIPTEN) + message(FATAL_ERROR "CPPINTEROP_WITH_OOP_JIT is not supported on Windows or Emscripten platforms.") + endif() add_definitions(-DCPPINTEROP_WITH_OOP_JIT) endif() diff --git a/README.md b/README.md index fd736c6c7..fb3d549aa 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ If you want to have out-of-process JIT execution enabled in CppInterOp, then app > Note that this patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux and MacOS only. ```bash -git apply -v ../CppInterOp/patches/llvm/out-of-process-jit-execution.patch +git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process-jit-execution.patch ``` ##### Build Clang-REPL @@ -203,7 +203,7 @@ cmake -DLLVM_ENABLE_PROJECTS="clang;compiler-rt \ cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt --parallel $(nproc --all) ## For MacOS -cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(nproc --all) +cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(sysctl -n hw.ncpu) ``` #### Build Cling and related dependencies diff --git a/docs/InstallationAndUsage.rst b/docs/InstallationAndUsage.rst index 8063d9c61..f060ae8fd 100644 --- a/docs/InstallationAndUsage.rst +++ b/docs/InstallationAndUsage.rst @@ -58,6 +58,15 @@ and on Windows. +If you want to have out-of-process JIT execution enabled in CppInterOp, then apply this patch on Linux and MacOS environment. +.. note:: + + This patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux and MacOS only. + +.. code:: bash + + git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process-jit-execution.patch + ****************** Build Clang-REPL ****************** @@ -116,6 +125,36 @@ On Windows you execute the following $env:LLVM_DIR= $PWD.Path cd ..\ +*************************************************** +Build Clang-REPL with Out-of-Process JIT Execution +*************************************************** + +To have `Out-of-Process JIT Execution` enabled, run following commands to build clang and clang-repl to support this feature: + +.. note:: + + Only for Linux and Macos + +.. code:: bash + + mkdir build + cd build + cmake -DLLVM_ENABLE_PROJECTS="clang;compiler-rt \ + -DLLVM_TARGETS_TO_BUILD="host;NVPTX" \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DCLANG_ENABLE_STATIC_ANALYZER=OFF \ + -DCLANG_ENABLE_ARCMT=OFF \ + -DCLANG_ENABLE_FORMAT=OFF \ + -DCLANG_ENABLE_BOOTSTRAP=OFF \ + ../llvm + + # For Linux + cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt --parallel $(nproc --all) + + # For MacOS + cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(sysctl -n hw.ncpu) + ************************************** Build Cling and related dependencies ************************************** @@ -280,6 +319,10 @@ commands on Linux and MacOS cmake -DBUILD_SHARED_LIBS=ON -DLLVM_DIR=$LLVM_DIR/build/lib/cmake/llvm -DClang_DIR=$LLVM_DIR/build/lib/cmake/clang -DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR .. cmake --build . --target install --parallel $(nproc --all) +.. note:: + + Do make sure to add `-DCPPINTEROP_WITH_OOP_JIT=ON`, if you want to have out-of-process JIT execution feature enabled. + and .. code:: powershell diff --git a/include/CppInterOp/CppInterOp.h b/include/CppInterOp/CppInterOp.h index aba49059f..198b060bd 100644 --- a/include/CppInterOp/CppInterOp.h +++ b/include/CppInterOp/CppInterOp.h @@ -901,6 +901,8 @@ CPPINTEROP_API void CodeComplete(std::vector& Results, ///\returns 0 on success, non-zero on failure. CPPINTEROP_API int Undo(unsigned N = 1); +CPPINTEROP_API pid_t GetExecutorPID(); + } // end namespace Cpp #endif // CPPINTEROP_CPPINTEROP_H diff --git a/lib/CppInterOp/Compatibility.h b/lib/CppInterOp/Compatibility.h index b260aff47..acf65c244 100644 --- a/lib/CppInterOp/Compatibility.h +++ b/lib/CppInterOp/Compatibility.h @@ -429,6 +429,10 @@ inline void codeComplete(std::vector& Results, #endif } +inline pid_t getExecutorPID() { + return getLastLaunchedExecutorPID(); +} + } // namespace compat #include "CppInterOpInterpreter.h" diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index 858407b70..e0421cded 100755 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -3909,4 +3909,8 @@ int Undo(unsigned N) { #endif } +pid_t GetExecutorPID() { + return compat::getExecutorPID(); +} + } // end namespace Cpp diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index d2dc0e06f..36c128391 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -146,22 +146,22 @@ TEST(InterpreterTest, Process) { clang_Interpreter_dispose(CXI); } -// #ifdef CPPINTEROP_WITH_OOP_JIT -// TEST(InterpreterTest, OopJITProcess) { -// #ifdef _WIN32 -// GTEST_SKIP() << "Disabled on Windows. Needs fixing."; -// #endif -// if (llvm::sys::RunningOnValgrind()) -// GTEST_SKIP() << "XFAIL due to Valgrind report"; -// std::vector interpreter_args = { "-include", "new" }; -// auto* I = Cpp::CreateInterpreter(interpreter_args, {}, true); -// EXPECT_TRUE(Cpp::Process("") == 0); -// EXPECT_TRUE(Cpp::Process("int a = 12;") == 0); -// EXPECT_FALSE(Cpp::Process("error_here;") == 0); -// // Linker/JIT error. -// EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0); -// } -// #endif +#ifdef CPPINTEROP_WITH_OOP_JIT +TEST(InterpreterTest, OopJITProcess) { +#ifdef _WIN32 + GTEST_SKIP() << "Disabled on Windows. Needs fixing."; +#endif + if (llvm::sys::RunningOnValgrind()) + GTEST_SKIP() << "XFAIL due to Valgrind report"; + std::vector interpreter_args = { "-include", "new" }; + auto* I = Cpp::CreateInterpreter(interpreter_args, {}, true); + EXPECT_TRUE(Cpp::Process("") == 0); + EXPECT_TRUE(Cpp::Process("int a = 12;") == 0); + EXPECT_FALSE(Cpp::Process("error_here;") == 0); + // Linker/JIT error. + EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0); +} +#endif TEST(InterpreterTest, EmscriptenExceptionHandling) { #ifndef EMSCRIPTEN From e562d1308bd3ff3337694d0a275a13478d4f881d Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Fri, 20 Jun 2025 11:33:40 +0530 Subject: [PATCH 09/11] changed patch --- .github/actions/Build_LLVM/action.yml | 2 +- README.md | 2 +- docs/InstallationAndUsage.rst | 2 +- ...ng20-2-out-of-process-jit-execution.patch} | 122 ++++++++++++++---- 4 files changed, 99 insertions(+), 29 deletions(-) rename patches/llvm/{clang20-1-out-of-process-jit-execution.patch => clang20-2-out-of-process-jit-execution.patch} (89%) diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index e6d4a31b2..2e3336ab0 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -50,7 +50,7 @@ runs: echo "Apply clang${{ matrix.clang-runtime }}-*.patch patches:" fi if [[ "${{ matrix.oop-jit }}" == "On" ]]; then - git apply -v ../patches/llvm/clang20-1-out-of-process-jit-execution.patch + git apply -v ../patches/llvm/clang20-2-out-of-process-jit-execution.patch echo "Apply out-of-process-jit-execution.patch:" fi cd build diff --git a/README.md b/README.md index fb3d549aa..a367765a4 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ If you want to have out-of-process JIT execution enabled in CppInterOp, then app > Note that this patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux and MacOS only. ```bash -git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process-jit-execution.patch +git apply -v ../CppInterOp/patches/llvm/clang20-2-out-of-process-jit-execution.patch ``` ##### Build Clang-REPL diff --git a/docs/InstallationAndUsage.rst b/docs/InstallationAndUsage.rst index f060ae8fd..27ed4bfa0 100644 --- a/docs/InstallationAndUsage.rst +++ b/docs/InstallationAndUsage.rst @@ -65,7 +65,7 @@ If you want to have out-of-process JIT execution enabled in CppInterOp, then app .. code:: bash - git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process-jit-execution.patch + git apply -v ../CppInterOp/patches/llvm/clang20-2-out-of-process-jit-execution.patch ****************** Build Clang-REPL diff --git a/patches/llvm/clang20-1-out-of-process-jit-execution.patch b/patches/llvm/clang20-2-out-of-process-jit-execution.patch similarity index 89% rename from patches/llvm/clang20-1-out-of-process-jit-execution.patch rename to patches/llvm/clang20-2-out-of-process-jit-execution.patch index 03a4620ba..22dca3fae 100644 --- a/patches/llvm/clang20-1-out-of-process-jit-execution.patch +++ b/patches/llvm/clang20-2-out-of-process-jit-execution.patch @@ -1,5 +1,5 @@ diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h -index f8663e3193a18..78dff1165dcf5 100644 +index f8663e3193..78dff1165d 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -20,6 +20,7 @@ @@ -28,10 +28,10 @@ index f8663e3193a18..78dff1165dcf5 100644 const CompilerInstance *getCompilerInstance() const; diff --git a/clang/include/clang/Interpreter/RemoteJITUtils.h b/clang/include/clang/Interpreter/RemoteJITUtils.h new file mode 100644 -index 0000000000000..8705a3b1f669d +index 0000000000..ae978be2c8 --- /dev/null +++ b/clang/include/clang/Interpreter/RemoteJITUtils.h -@@ -0,0 +1,38 @@ +@@ -0,0 +1,43 @@ +//===-- RemoteJITUtils.h - Utilities for remote-JITing ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -69,9 +69,14 @@ index 0000000000000..8705a3b1f669d +connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory, + llvm::StringRef SlabAllocateSizeString); + ++ ++/// Get the PID of the last launched executor. ++/// This is useful for debugging or for cleanup purposes. ++pid_t getLastLaunchedExecutorPID(); ++ +#endif // LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt -index bf70cdfbee01e..38cf139fa86a6 100644 +index bf70cdfbee..38cf139fa8 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -27,6 +27,7 @@ add_clang_library(clangInterpreter @@ -83,7 +88,7 @@ index bf70cdfbee01e..38cf139fa86a6 100644 ${WASM_SRC} PARTIAL_SOURCES_INTENDED diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp -index 3b81f9d701b42..e59656f554f3d 100644 +index 3b81f9d701..eaa5c31cb6 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -46,6 +46,7 @@ @@ -109,7 +114,16 @@ index 3b81f9d701b42..e59656f554f3d 100644 if (Err) return std::move(Err); -@@ -617,6 +619,25 @@ createJITTargetMachineBuilder(const std::string &TT) { +@@ -467,6 +469,8 @@ Interpreter::create(std::unique_ptr CI) { + auto PTU = Interp->Parse(Runtimes); + if (!PTU) + return PTU.takeError(); ++ ++ if (llvm::Error Err = Interp->Execute(*PTU)) return Err; + Interp->markUserCodeStart(); + + Interp->ValuePrintingInfo.resize(4); +@@ -617,6 +621,25 @@ createJITTargetMachineBuilder(const std::string &TT) { return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); } @@ -135,7 +149,7 @@ index 3b81f9d701b42..e59656f554f3d 100644 llvm::Error Interpreter::CreateExecutor() { if (IncrExecutor) return llvm::make_error("Operation failed. " -@@ -757,11 +778,11 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { +@@ -757,11 +780,11 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { if (!EE) return EE.takeError(); @@ -154,10 +168,10 @@ index 3b81f9d701b42..e59656f554f3d 100644 #endif diff --git a/clang/lib/Interpreter/RemoteJITUtils.cpp b/clang/lib/Interpreter/RemoteJITUtils.cpp new file mode 100644 -index 0000000000000..24a5f729f2dcb +index 0000000000..2cc160625b --- /dev/null +++ b/clang/lib/Interpreter/RemoteJITUtils.cpp -@@ -0,0 +1,267 @@ +@@ -0,0 +1,319 @@ +//===-- RemoteJITUtils.cpp - Utilities for remote-JITing --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -184,6 +198,7 @@ index 0000000000000..24a5f729f2dcb +#include "llvm/Support/Path.h" + +#ifdef LLVM_ON_UNIX ++#include +#include +#include +#include @@ -193,6 +208,8 @@ index 0000000000000..24a5f729f2dcb +using namespace llvm; +using namespace llvm::orc; + ++static std::atomic LaunchedExecutorPID{-1}; ++ +Expected getSlabAllocSize(StringRef SizeString) { + SizeString = SizeString.trim(); + @@ -253,19 +270,16 @@ index 0000000000000..24a5f729f2dcb +launchExecutor(StringRef ExecutablePath, bool UseSharedMemory, + llvm::StringRef SlabAllocateSizeString) { +#ifndef LLVM_ON_UNIX -+ // FIXME: Add support for Windows. + return make_error("-" + ExecutablePath + + " not supported on non-unix platforms", + inconvertibleErrorCode()); +#elif !LLVM_ENABLE_THREADS -+ // Out of process mode using SimpleRemoteEPC depends on threads. + return make_error( + "-" + ExecutablePath + + " requires threads, but LLVM was built with " + "LLVM_ENABLE_THREADS=Off", + inconvertibleErrorCode()); +#else -+ + if (!sys::fs::can_execute(ExecutablePath)) + return make_error( + formatv("Specified executor invalid: {0}", ExecutablePath), @@ -274,15 +288,20 @@ index 0000000000000..24a5f729f2dcb + constexpr int ReadEnd = 0; + constexpr int WriteEnd = 1; + -+ // Pipe FDs. ++ // Pipe FDs for RPC + int ToExecutor[2]; + int FromExecutor[2]; + ++ // New pipes for stdout and stderr ++ int StdoutPipe[2]; ++ int StderrPipe[2]; ++ + pid_t ChildPID; + -+ // Create pipes to/from the executor.. -+ if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0) -+ return make_error("Unable to create pipe for executor", ++ // Create pipes ++ if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0 || ++ pipe(StdoutPipe) != 0 || pipe(StderrPipe) != 0) ++ return make_error("Unable to create pipes", + inconvertibleErrorCode()); + + ChildPID = fork(); @@ -290,11 +309,23 @@ index 0000000000000..24a5f729f2dcb + if (ChildPID == 0) { + // In the child... + -+ // Close the parent ends of the pipes ++ // Close parent ends of RPC pipes + close(ToExecutor[WriteEnd]); + close(FromExecutor[ReadEnd]); + -+ // Execute the child process. ++ // Close read ends of stdout and stderr pipes ++ close(StdoutPipe[ReadEnd]); ++ close(StderrPipe[ReadEnd]); ++ ++ // Redirect stdout and stderr to the pipes ++ dup2(StdoutPipe[WriteEnd], STDOUT_FILENO); ++ dup2(StderrPipe[WriteEnd], STDERR_FILENO); ++ ++ // Close write ends after redirection ++ close(StdoutPipe[WriteEnd]); ++ close(StderrPipe[WriteEnd]); ++ ++ // Execute the child process + std::unique_ptr ExecutorPath, FDSpecifier; + { + ExecutorPath = std::make_unique(ExecutablePath.size() + 1); @@ -315,22 +346,53 @@ index 0000000000000..24a5f729f2dcb + << ExecutorPath.get() << "\"\n"; + exit(1); + } ++ } else { ++ LaunchedExecutorPID = ChildPID; + } -+ // else we're the parent... + -+ // Close the child ends of the pipes ++ // Close child ends of RPC pipes + close(ToExecutor[ReadEnd]); + close(FromExecutor[WriteEnd]); + ++ // Close write ends of stdout and stderr pipes ++ close(StdoutPipe[WriteEnd]); ++ close(StderrPipe[WriteEnd]); ++ + auto S = SimpleRemoteEPC::Setup(); + if (UseSharedMemory) + S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) { + return createSharedMemoryManager(EPC, SlabAllocateSizeString); + }; + -+ return SimpleRemoteEPC::Create( ++ auto EPC = SimpleRemoteEPC::Create( + std::make_unique(std::nullopt), + std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]); ++ ++ // Read stdout ++ std::thread([readFd = StdoutPipe[ReadEnd]] { ++ char buffer[1024]; ++ ssize_t bytesRead; ++ while ((bytesRead = read(readFd, buffer, sizeof(buffer) - 1)) > 0) { ++ buffer[bytesRead] = '\0'; ++ fwrite(buffer, 1, bytesRead, stdout); ++ fflush(stdout); ++ } ++ close(readFd); ++ }).detach(); ++ ++ // Spawn a background thread to read stderr ++ std::thread([readFd = StderrPipe[ReadEnd]] { ++ char buffer[1024]; ++ ssize_t bytesRead; ++ while ((bytesRead = read(readFd, buffer, sizeof(buffer) - 1)) > 0) { ++ buffer[bytesRead] = '\0'; ++ fwrite(buffer, 1, bytesRead, stderr); ++ fflush(stderr); ++ } ++ close(readFd); ++ }).detach(); ++ ++ return EPC; +#endif +} + @@ -425,9 +487,13 @@ index 0000000000000..24a5f729f2dcb + std::move(S), *SockFD, *SockFD); +#endif +} ++ ++pid_t getLastLaunchedExecutorPID() { ++ return LaunchedExecutorPID; ++} diff --git a/clang/test/Interpreter/out-of-process.cpp b/clang/test/Interpreter/out-of-process.cpp new file mode 100644 -index 0000000000000..edc4c3fee0966 +index 0000000000..edc4c3fee0 --- /dev/null +++ b/clang/test/Interpreter/out-of-process.cpp @@ -0,0 +1,88 @@ @@ -520,7 +586,7 @@ index 0000000000000..edc4c3fee0966 + +%quit diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt -index f9a911b0ae8e2..68d86dd98cac3 100644 +index f9a911b0ae..68d86dd98c 100644 --- a/clang/tools/clang-repl/CMakeLists.txt +++ b/clang/tools/clang-repl/CMakeLists.txt @@ -4,7 +4,9 @@ set( LLVM_LINK_COMPONENTS @@ -534,7 +600,7 @@ index f9a911b0ae8e2..68d86dd98cac3 100644 add_clang_tool(clang-repl diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp -index 7af8e4f25d99e..54b27782d3db3 100644 +index 7af8e4f25d..6113cc2a99 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -10,7 +10,11 @@ @@ -672,7 +738,7 @@ index 7af8e4f25d99e..54b27782d3db3 100644 static void LLVMErrorHandler(void *UserData, const char *Message, bool GenCrashDiag) { auto &Diags = *static_cast(UserData); -@@ -183,6 +282,25 @@ int main(int argc, const char **argv) { +@@ -183,6 +282,29 @@ int main(int argc, const char **argv) { DeviceCI = ExitOnErr(CB.CreateCudaDevice()); } @@ -681,6 +747,9 @@ index 7af8e4f25d99e..54b27782d3db3 100644 + std::unique_ptr EPC; + if (OOPExecutor.getNumOccurrences()) { + // Launch an out-of-process executor locally in a child process. ++ std::cout << "OOPExecutor: " << OOPExecutor << std::endl; ++ std::cout << "UseSharedMemory: " << UseSharedMemory << std::endl; ++ std::cout << "SlabAllocateSizeString: " << SlabAllocateSizeString << std::endl; + EPC = ExitOnErr( + launchExecutor(OOPExecutor, UseSharedMemory, SlabAllocateSizeString)); + } else if (OOPExecutorConnect.getNumOccurrences()) { @@ -691,6 +760,7 @@ index 7af8e4f25d99e..54b27782d3db3 100644 + std::unique_ptr JB; + if (EPC) { + CB.SetTargetTriple(EPC->getTargetTriple().getTriple()); ++ std::cout << "OrcRuntimePath: " << OrcRuntimePath << std::endl; + JB = ExitOnErr( + clang::Interpreter::createLLJITBuilder(std::move(EPC), OrcRuntimePath)); + } @@ -698,7 +768,7 @@ index 7af8e4f25d99e..54b27782d3db3 100644 // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It // can replace the boilerplate code for creation of the compiler instance. std::unique_ptr CI; -@@ -214,6 +332,9 @@ int main(int argc, const char **argv) { +@@ -214,6 +336,9 @@ int main(int argc, const char **argv) { auto CudaRuntimeLibPath = CudaPath + "/lib/libcudart.so"; ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str())); } From 13a0cafd78758b3ed2a17b1cca084f2c56931630 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Fri, 20 Jun 2025 11:44:38 +0530 Subject: [PATCH 10/11] added oop jit check for executorpid func --- include/CppInterOp/CppInterOp.h | 2 ++ lib/CppInterOp/CppInterOp.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/CppInterOp/CppInterOp.h b/include/CppInterOp/CppInterOp.h index 198b060bd..431296986 100644 --- a/include/CppInterOp/CppInterOp.h +++ b/include/CppInterOp/CppInterOp.h @@ -901,7 +901,9 @@ CPPINTEROP_API void CodeComplete(std::vector& Results, ///\returns 0 on success, non-zero on failure. CPPINTEROP_API int Undo(unsigned N = 1); +#ifdef CPPINTEROP_WITH_OOP_JIT CPPINTEROP_API pid_t GetExecutorPID(); +#endif // CPPINTEROP_WITH_OOP_JIT } // end namespace Cpp diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index e0421cded..a6851ea90 100755 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -3909,8 +3909,10 @@ int Undo(unsigned N) { #endif } +#ifdef CPPINTEROP_WITH_OOP_JIT pid_t GetExecutorPID() { return compat::getExecutorPID(); } +#endif // CPPINTEROP_WITH_OOP_JIT } // end namespace Cpp From 43220d798622516ba06edf96f1d8ad568346e706 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Fri, 20 Jun 2025 11:55:15 +0530 Subject: [PATCH 11/11] added oop jit check for executorpid func --- .github/actions/Build_LLVM/action.yml | 2 +- lib/CppInterOp/Compatibility.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index 2e3336ab0..ea690fa20 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -69,7 +69,7 @@ runs: ../llvm ninja clang clangInterpreter clangStaticAnalyzerCore -j ${{ env.ncpus }} if [[ "${{ matrix.oop-jit }}" == "On" ]]; then - if [ "${{ matrix.os }}}" = "macos"* ]; then SUFFIX="_osx"; fi + if [ "${{ matrix.os }}}" == "macos"* ]; then SUFFIX="_osx"; fi ninja clang_repl llvm-jitlink-executor orc_rt${SUFFIX} -j ${{ env.ncpus }} fi cd ./tools/ diff --git a/lib/CppInterOp/Compatibility.h b/lib/CppInterOp/Compatibility.h index acf65c244..c31937de3 100644 --- a/lib/CppInterOp/Compatibility.h +++ b/lib/CppInterOp/Compatibility.h @@ -429,9 +429,11 @@ inline void codeComplete(std::vector& Results, #endif } +#ifdef CPPINTEROP_WITH_OOP_JIT inline pid_t getExecutorPID() { return getLastLaunchedExecutorPID(); } +#endif // CPPINTEROP_WITH_OOP_JIT } // namespace compat