Skip to content

Commit 2df83a9

Browse files
kr-2003kr-2003Vipul-Cariappa
authored
Support Out-Of-Process JIT (#717)
* Implement Out-Of-Process JIT for CppInterOp * Backport LLVM clang-repl's out-of-process JIT patches for clang 20 * Update `StreamCaptureInfo` to work with out-of-process JIT In out-of-process JIT, stream capture does not work out of the box. Therefore, at the time of creation of the JIT process, we customise it to redirect `stdout` and `stderr` to specific temporary files. The parent process creates these files and has a reference to them. The parent process can now dynamically read the contents of these temporary files, replicating the stream redirection. Note that `stdin` needs special care and does not work as expected right now. Ideally, the child process should just redirect to the parent process's streams, but this could not be implemented. * Update Documentation Add build instructions for out-of-process JIT. * Update tests to use Parameterised Test fixtures This enables reusing the existing tests without duplication for in-process and out-of-process JIT. Introduces multiple test configurations (InProcess & OutOfProcess right now), that can be used to customise the creation of the interpreter in the test suite. * Add valgrind suppression file for out-of-process JIT These suppressions are from LLVM. Needs to be fixed upstream. --------- Co-authored-by: kr-2003 <[email protected]> Co-authored-by: Vipul Cariappa <[email protected]>
1 parent 1baeb31 commit 2df83a9

24 files changed

+1861
-264
lines changed

.github/actions/Build_LLVM/action.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ runs:
4343
ninja LLVMOrcDebugging -j ${{ env.ncpus }}
4444
ninja clingInterpreter -j ${{ env.ncpus }}
4545
else
46+
if [[ "${{ matrix.oop-jit }}" == "On" ]]; then
47+
git apply -v ../patches/llvm/clang20-1-out-of-process.patch
48+
echo "Apply clang20-1-out-of-process.patch:"
49+
fi
4650
cd build
4751
cmake -DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects}}" \
4852
-DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" \
@@ -57,7 +61,15 @@ runs:
5761
-DLLVM_INCLUDE_EXAMPLES=OFF \
5862
-DLLVM_INCLUDE_TESTS=OFF \
5963
../llvm
60-
ninja clang clangInterpreter clangStaticAnalyzerCore -j ${{ env.ncpus }}
64+
ninja clang clangInterpreter clangStaticAnalyzerCore
65+
if [[ "${{ matrix.oop-jit }}" == "On" ]]; then
66+
if [[ "${{ matrix.os }}" == macos* ]]; then
67+
SUFFIX="_osx"
68+
elif [[ "${{ matrix.os }}" == ubuntu* ]]; then
69+
SUFFIX="-x86_64"
70+
fi
71+
ninja llvm-jitlink-executor orc_rt${SUFFIX} -j ${{ env.ncpus }}
72+
fi
6173
cd ./tools/
6274
rm -rf $(find . -maxdepth 1 ! -name "clang" ! -name ".")
6375
cd ..

.github/actions/Build_and_Test_CppInterOp/action.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ runs:
4848
-DCODE_COVERAGE=${{ env.CODE_COVERAGE }} \
4949
-DCMAKE_INSTALL_PREFIX=$CPPINTEROP_DIR \
5050
-DLLVM_ENABLE_WERROR=On \
51+
-DLLVM_BUILT_WITH_OOP_JIT=${{ matrix.oop-jit }} \
5152
../
5253
fi
5354
docs_on=$(echo "${{ matrix.documentation }}" | tr '[:lower:]' '[:upper:]')
@@ -58,7 +59,18 @@ runs:
5859
cmake --build . --target check-cppinterop --parallel ${{ env.ncpus }}
5960
os="${{ matrix.os }}"
6061
if [[ "${os}" != "macos"* ]]; then
61-
valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests
62+
CLANG_VERSION="${{ matrix.clang-runtime }}"
63+
if [[ "$CLANG_VERSION" == "20" && "${{ matrix.cling }}" == "Off" ]]; then
64+
SUPPRESSION_FILE="../etc/clang${CLANG_VERSION}-valgrind.supp"
65+
valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 \
66+
--show-leak-kinds=definite,possible \
67+
--suppressions="${SUPPRESSION_FILE}" \
68+
unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests
69+
else
70+
valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 \
71+
--show-leak-kinds=definite,possible \
72+
unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests
73+
fi
6274
fi
6375
fi
6476
echo "CB_PYTHON_DIR=$CB_PYTHON_DIR" >> $GITHUB_ENV

.github/workflows/main.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ jobs:
6363
clang-runtime: '20'
6464
cling: Off
6565
cppyy: Off
66-
llvm_enable_projects: "clang"
66+
llvm_enable_projects: "clang;compiler-rt"
6767
llvm_targets_to_build: "host;NVPTX"
6868
coverage: true
69+
oop-jit: On
6970
- name: ubu24-x86-gcc12-clang-repl-20
7071
os: ubuntu-24.04
7172
compiler: gcc-12
@@ -74,6 +75,15 @@ jobs:
7475
cppyy: Off
7576
llvm_enable_projects: "clang"
7677
llvm_targets_to_build: "host;NVPTX"
78+
- name: ubu24-x86-gcc12-clang-repl-20-out-of-process
79+
os: ubuntu-24.04
80+
compiler: gcc-12
81+
clang-runtime: '20'
82+
cling: Off
83+
cppyy: Off
84+
llvm_enable_projects: "clang;compiler-rt"
85+
llvm_targets_to_build: "host;NVPTX"
86+
oop-jit: On
7787
- name: ubu24-x86-gcc12-clang-repl-19-cppyy
7888
os: ubuntu-24.04
7989
compiler: gcc-12
@@ -100,6 +110,15 @@ jobs:
100110
llvm_enable_projects: "clang"
101111
llvm_targets_to_build: "host;NVPTX"
102112
# MacOS Arm Jobs
113+
- name: osx15-arm-clang-clang-repl-20-out-of-process
114+
os: macos-15
115+
compiler: clang
116+
clang-runtime: '20'
117+
cling: Off
118+
cppyy: Off
119+
llvm_enable_projects: "clang;compiler-rt"
120+
llvm_targets_to_build: "host"
121+
oop-jit: On
103122
- name: osx15-arm-clang-clang-repl-20
104123
os: macos-15
105124
compiler: clang
@@ -220,7 +239,7 @@ jobs:
220239
path: |
221240
llvm-project
222241
${{ matrix.cling=='On' && 'cling' || '' }}
223-
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' }}
242+
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' }}${{ matrix.oop-jit == 'On' && '-oop' || '' }}
224243

225244
- name: Setup default Build Type
226245
uses: ./.github/actions/Miscellaneous/Select_Default_Build_Type

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,18 @@ include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
298298
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
299299
add_definitions(${LLVM_DEFINITIONS_LIST})
300300

301+
string(REGEX REPLACE "/lib/cmake/llvm$" "" LLVM_BINARY_LIB_DIR "${LLVM_DIR}")
302+
add_definitions(-DLLVM_BINARY_LIB_DIR="${LLVM_BINARY_LIB_DIR}")
303+
304+
if(LLVM_BUILT_WITH_OOP_JIT)
305+
if((CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") OR
306+
(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64"))
307+
add_definitions(-DLLVM_BUILT_WITH_OOP_JIT)
308+
else()
309+
message(FATAL_ERROR "LLVM_BUILT_WITH_OOP_JIT is only supported on MacOS arm64 or Linux x86_64. Build aborted.")
310+
endif()
311+
endif()
312+
301313
# If the llvm sources are present add them with higher priority.
302314
if (LLVM_BUILD_MAIN_SRC_DIR)
303315
# LLVM_INCLUDE_DIRS contains the include paths to both LLVM's source and

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ git clone --depth=1 --branch release/20.x https://github.com/llvm/llvm-project.g
111111
cd llvm-project
112112
```
113113

114+
If you want to have out-of-process JIT execution enabled in CppInterOp, then apply this patch on Linux-x86_64 and MacOS arm64 environment.
115+
> Note that this patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux-x86_64 and MacOS arm64 only.
116+
117+
```bash
118+
git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process.patch
119+
```
120+
114121
##### Build Clang-REPL
115122

116123
Clang-REPL is an interpreter that CppInterOp works alongside. Build Clang (and
@@ -140,6 +147,45 @@ export LLVM_DIR=$PWD
140147
cd ../
141148
```
142149

150+
##### Build Clang-REPL with Out-of-Process JIT Execution
151+
152+
To have ``Out-of-Process JIT Execution`` enabled, run following commands to build clang and clang-repl to support this feature:
153+
> Only for Linux x86_64 and MacOS arm64
154+
155+
```bash
156+
mkdir build
157+
cd build
158+
cmake -DLLVM_ENABLE_PROJECTS="clang;compiler-rt" \
159+
-DLLVM_TARGETS_TO_BUILD="host;NVPTX" \
160+
-DCMAKE_BUILD_TYPE=Release \
161+
-DLLVM_ENABLE_ASSERTIONS=ON \
162+
-DCLANG_ENABLE_STATIC_ANALYZER=OFF \
163+
-DCLANG_ENABLE_ARCMT=OFF \
164+
-DCLANG_ENABLE_FORMAT=OFF \
165+
-DCLANG_ENABLE_BOOTSTRAP=OFF \
166+
../llvm
167+
```
168+
169+
###### For Linux x86_64
170+
171+
```bash
172+
cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt-x86_64 --parallel $(nproc --all)
173+
```
174+
175+
###### For MacOS arm64
176+
177+
```bash
178+
cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(sysctl -n hw.ncpu)
179+
```
180+
181+
Note the 'llvm-project' directory location by executing
182+
183+
```bash
184+
cd ../
185+
export LLVM_DIR=$PWD
186+
cd ../
187+
```
188+
143189
#### Environment variables
144190

145191
You will need to define the following environment variables for the build of CppInterOp and cppyy (as they clear for a new session, it is recommended that you also add these to your .bashrc in linux, .bash_profile if on MacOS). On Linux and MacOS you define as follows
@@ -167,6 +213,10 @@ cmake -DBUILD_SHARED_LIBS=ON -DCPPINTEROP_USE_CLING=ON -DCPPINTEROP_USE_REPL=Off
167213
cmake --build . --target install --parallel $(nproc --all)
168214
```
169215

216+
and
217+
218+
> Do make sure to pass ``DLLVM_BUILT_WITH_OOP_JIT=ON``, if you want to have out-of-process JIT execution feature enabled.
219+
170220
#### Testing CppInterOp
171221

172222
To test the built CppInterOp execute the following command in the CppInterOP build folder on Linux and MacOS

docs/DevelopersDocumentation.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ Clone the 20.x release of the LLVM project repository.
4141
git clone --depth=1 --branch release/20.x https://github.com/llvm/llvm-project.git
4242
cd llvm-project
4343
44+
If you want to have out-of-process JIT execution enabled in CppInterOp, then apply this patch on Linux-x86_64 and MacOS arm64 environment.
45+
.. note::
46+
47+
This patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux and MacOS only.
48+
49+
.. code:: bash
50+
51+
git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process.patch
52+
4453
******************
4554
Build Clang-REPL
4655
******************
@@ -99,6 +108,34 @@ On Windows you execute the following
99108
$env:LLVM_DIR= $PWD.Path
100109
cd ..\
101110
111+
***************************************************
112+
Build Clang-REPL with Out-of-Process JIT Execution
113+
***************************************************
114+
115+
To have `Out-of-Process JIT Execution` enabled, run following commands to build clang and clang-repl to support this feature:
116+
117+
.. note::
118+
119+
Only for Linux x86_64 and MacOS arm64
120+
121+
.. code:: bash
122+
mkdir build
123+
cd build
124+
cmake -DLLVM_ENABLE_PROJECTS="clang;compiler-rt" \
125+
-DLLVM_TARGETS_TO_BUILD="host;NVPTX" \
126+
-DCMAKE_BUILD_TYPE=Release \
127+
-DLLVM_ENABLE_ASSERTIONS=ON \
128+
-DCLANG_ENABLE_STATIC_ANALYZER=OFF \
129+
-DCLANG_ENABLE_ARCMT=OFF \
130+
-DCLANG_ENABLE_FORMAT=OFF \
131+
-DCLANG_ENABLE_BOOTSTRAP=OFF \
132+
../llvm
133+
134+
# For Linux x86_64
135+
cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt-x86_64 --parallel $(nproc --all)
136+
# For MacOS arm64
137+
cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(sysctl -n hw.ncpu)
138+
102139
**************************************
103140
Build Cling and related dependencies
104141
**************************************
@@ -261,6 +298,10 @@ commands on Linux and MacOS
261298
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 ..
262299
cmake --build . --target install --parallel $(nproc --all)
263300
301+
.. note::
302+
303+
Do make sure to pass ``DLLVM_BUILT_WITH_OOP_JIT=ON``, if you want to have out-of-process JIT execution feature enabled.
304+
264305
and
265306

266307
.. code:: powershell

docs/InstallationAndUsage.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ Clone the 20.x release of the LLVM project repository.
4141
git clone --depth=1 --branch release/20.x https://github.com/llvm/llvm-project.git
4242
cd llvm-project
4343
44+
If you want to have out-of-process JIT execution enabled in CppInterOp, then apply this patch on Linux-x86_64 and MacOS arm64 environment.
45+
.. note::
46+
47+
This patch will not work for Windows because out-of-process JIT execution is currently implemented for Linux and MacOS only.
48+
49+
.. code:: bash
50+
51+
git apply -v ../CppInterOp/patches/llvm/clang20-1-out-of-process.patch
52+
4453
******************
4554
Build Clang-REPL
4655
******************
@@ -99,6 +108,34 @@ On Windows you execute the following
99108
$env:LLVM_DIR= $PWD.Path
100109
cd ..\
101110
111+
***************************************************
112+
Build Clang-REPL with Out-of-Process JIT Execution
113+
***************************************************
114+
115+
To have `Out-of-Process JIT Execution` enabled, run following commands to build clang and clang-repl to support this feature:
116+
117+
.. note::
118+
119+
Only for Linux x86_64 and MacOS arm64
120+
121+
.. code:: bash
122+
mkdir build
123+
cd build
124+
cmake -DLLVM_ENABLE_PROJECTS="clang;compiler-rt" \
125+
-DLLVM_TARGETS_TO_BUILD="host;NVPTX" \
126+
-DCMAKE_BUILD_TYPE=Release \
127+
-DLLVM_ENABLE_ASSERTIONS=ON \
128+
-DCLANG_ENABLE_STATIC_ANALYZER=OFF \
129+
-DCLANG_ENABLE_ARCMT=OFF \
130+
-DCLANG_ENABLE_FORMAT=OFF \
131+
-DCLANG_ENABLE_BOOTSTRAP=OFF \
132+
../llvm
133+
134+
# For Linux x86_64
135+
cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt-x86_64 --parallel $(nproc --all)
136+
# For MacOS arm64
137+
cmake --build . --target clang clang-repl llvm-jitlink-executor orc_rt_osx --parallel $(sysctl -n hw.ncpu)
138+
102139
**************************************
103140
Build Cling and related dependencies
104141
**************************************
@@ -263,6 +300,10 @@ commands on Linux and MacOS
263300
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 ..
264301
cmake --build . --target install --parallel $(nproc --all)
265302
303+
.. note::
304+
305+
Do make sure to pass ``DLLVM_BUILT_WITH_OOP_JIT=ON``, if you want to have out-of-process JIT execution feature enabled.
306+
266307
and
267308

268309
.. code:: powershell

etc/clang20-valgrind.supp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
Clang 20 Out of Process
3+
Memcheck:Param
4+
write(buf)
5+
fun:__libc_write
6+
fun:write
7+
fun:_ZN4llvm3orc26FDSimpleRemoteEPCTransport11sendMessageENS0_21SimpleRemoteEPCOpcodeEmNS0_12ExecutorAddrENS_8ArrayRefIcEE
8+
fun:_ZN4llvm3orc15SimpleRemoteEPC11sendMessageENS0_21SimpleRemoteEPCOpcodeEmNS0_12ExecutorAddrENS_8ArrayRefIcEE
9+
fun:_ZN4llvm3orc15SimpleRemoteEPC16callWrapperAsyncENS0_12ExecutorAddrENS0_22ExecutorProcessControl18IncomingWFRHandlerENS_8ArrayRefIcEE
10+
fun:_ZN4llvm3orc30EPCGenericJITLinkMemoryManager13InFlightAlloc8finalizeENS_15unique_functionIFvNS_8ExpectedINS_7jitlink20JITLinkMemoryManager14FinalizedAllocEEEEEE
11+
fun:_ZN4llvm7jitlink13JITLinkerBase10linkPhase3ESt10unique_ptrIS1_St14default_deleteIS1_EENS_8ExpectedINS_8DenseMapINS_3orc15SymbolStringPtrENS8_17ExecutorSymbolDefENS_12DenseMapInfoIS9_vEENS_6detail12DenseMapPairIS9_SA_EEEEEE
12+
fun:_ZZN4llvm7jitlink24createLookupContinuationIZNS0_13JITLinkerBase10linkPhase2ESt10unique_ptrIS2_St14default_deleteIS2_EENS_8ExpectedIS3_INS0_20JITLinkMemoryManager13InFlightAllocES4_IS9_EEEEEUlNS7_INS_8DenseMapINS_3orc15SymbolStringPtrENSE_17ExecutorSymbolDefENS_12DenseMapInfoISF_vEENS_6detail12DenseMapPairISF_SG_EEEEEEE_EES3_INS0_30JITLinkAsyncLookupContinuationES4_ISP_EET_EN4Impl3runESN_
13+
fun:_ZZN4llvm3orc21LinkGraphLinkingLayer10JITLinkCtx6lookupERKNS_8DenseMapINS0_15SymbolStringPtrENS_7jitlink17SymbolLookupFlagsENS_12DenseMapInfoIS4_vEENS_6detail12DenseMapPairIS4_S6_EEEESt10unique_ptrINS5_30JITLinkAsyncLookupContinuationESt14default_deleteISG_EEENUlNS_8ExpectedINS3_IS4_NS0_17ExecutorSymbolDefES8_NSA_IS4_SL_EEEEEEE0_clESO_
14+
fun:_ZN4llvm6detail18UniqueFunctionBaseIvJNS_8ExpectedINS_8DenseMapINS_3orc15SymbolStringPtrENS4_17ExecutorSymbolDefENS_12DenseMapInfoIS5_vEENS0_12DenseMapPairIS5_S6_EEEEEEEE8CallImplIZNS4_21LinkGraphLinkingLayer10JITLinkCtx6lookupERKNS3_IS5_NS_7jitlink17SymbolLookupFlagsES8_NS9_IS5_SI_EEEESt10unique_ptrINSH_30JITLinkAsyncLookupContinuationESt14default_deleteISO_EEEUlSC_E0_EEvPvRSC_
15+
fun:_ZZN4llvm3orc23AsynchronousSymbolQuery14handleCompleteERNS0_16ExecutionSessionEEN20RunQueryCompleteTask3runEv
16+
fun:_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJZN4llvm3orc31DynamicThreadPoolTaskDispatcher8dispatchESt10unique_ptrINS4_4TaskESt14default_deleteIS7_EEEUlvE_EEEEE6_M_runEv
17+
obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
18+
}

include/CppInterOp/CppInterOp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <cstdint>
2020
#include <set>
2121
#include <string>
22+
#include <sys/types.h>
2223
#include <vector>
2324

2425
// The cross-platform CPPINTEROP_API macro definition
@@ -935,6 +936,12 @@ CPPINTEROP_API void CodeComplete(std::vector<std::string>& Results,
935936
///\returns 0 on success, non-zero on failure.
936937
CPPINTEROP_API int Undo(unsigned N = 1);
937938

939+
#ifndef _WIN32
940+
/// Returns the process ID of the executor process.
941+
/// \returns the PID of the executor process.
942+
CPPINTEROP_API pid_t GetExecutorPID();
943+
#endif
944+
938945
} // end namespace Cpp
939946

940947
#endif // CPPINTEROP_CPPINTEROP_H

0 commit comments

Comments
 (0)