Skip to content

Simplify Out-Of-Process JIT case - #940

Merged
vgvassilev merged 2 commits into
compiler-research:mainfrom
vgvassilev:ci-bundle-oop-runtime-pr1
Apr 26, 2026
Merged

Simplify Out-Of-Process JIT case#940
vgvassilev merged 2 commits into
compiler-research:mainfrom
vgvassilev:ci-bundle-oop-runtime-pr1

Conversation

@vgvassilev

Copy link
Copy Markdown
Contributor

No description provided.

@vgvassilev
vgvassilev force-pushed the ci-bundle-oop-runtime-pr1 branch 2 times, most recently from cbd4779 to be8f32c Compare April 26, 2026 15:29
Out-of-process JIT needs `liborc_rt*.a` (fed to
`IncrementalExecutorBuilder::OrcRuntimePath`) and
`llvm-jitlink-executor`. Upstream's auto-discovery validates the
runtime path against `parent_path(D.Dir)`, which only matches when
`libclangCppInterOp.so` lives inside the LLVM install tree -- test
binaries under `<build>/unittests/...` trip the safety check.

Bundle both artifacts under `<libdir>/cppinterop-rt/` via a new
`FindLLVMOrcRuntime` cmake module and configure_file/install rules,
and hand the paths to `IncrementalExecutorBuilder` directly with a
no-op `UpdateOrcRuntimePathCB`. The locations are baked at build
time (`CPPINTEROP_RUNTIME_{BUILD,INSTALL}_DIR`); when the runtime
parts are missing the OOP path falls back to in-process JIT with a
logged warning. Relocatable-install support (sysadmin-overridable
runtime dir, `dladdr`-based self-DSO probe) is a separate follow-up
PR layered on top of this baked probe.

Drops the now-unused `LLVM_BUILT_WITH_OOP_JIT` cmake option and the
`LLVM_BINARY_LIB_DIR` define (its only consumer was the old
hand-built executor path); README, InstallationAndUsage.rst, and
DevelopersDocumentation.rst are updated to describe auto-detection.
Activates the bundling design from `[jit] Self-contain the OOP-JIT
runtime in CppInterOp's distribution.`:

- `Build_LLVM/action.yml`: for non-cling rows with `clang-runtime
  >= 22`, set `LLVM_ENABLE_PROJECTS="clang;compiler-rt"` and ninja
  `llvm-jitlink-executor` plus every `orc_rt*` target ninja exposes
  (other compiler-rt components are turned off so build cost is
  bounded to the ORC runtime). The matrix `llvm_enable_projects`
  override is no longer load-bearing: the projects list is now
  picked entirely from `NEED_OOP`.
- `Build_and_Test_CppInterOp/action.yml`: drop
  `-DLLVM_BUILT_WITH_OOP_JIT`; CppInterOp auto-detects via
  `find_package(LLVMOrcRuntime)`. The Valgrind suppression file
  selection moves from `matrix.oop-jit` to `clang-runtime >= 22`,
  matching the auto-detect condition that now drives OOP at
  runtime. Adds two post-build assertions: (a) the typed-test
  fixtures registered match the source-side gate -- the
  `OutOfProcessJIT` fixture must NOT be present on `clang-runtime
  <= 21`, catching accidental regressions of the
  `LLVM_VERSION_MAJOR > 21` guard in `unittests/CppInterOp/Utils.h`;
  (b) an install-layout smoke test that installs into a scratch
  prefix and asserts `<libdir>/cppinterop-rt/liborc_rt.a` is
  shipped and `llvm-jitlink-executor` retains its executable bit,
  catching install(FILES/PROGRAMS) destination/mode regressions.
- `main.yml`: drop the `-oop` cache-key suffix and the `oop-jit`
  matrix dimension along with its rows. `osx26-arm-clang-llvm22-oop`
  was a duplicate of `osx26-arm-clang-llvm22` once the OOP knob
  retired; `ubu24-x86-gcc12-llvm22-oop-vg` was unique only for its
  Valgrind axis and is renamed to `ubu24-x86-gcc12-llvm22-vg`. OOP
  and in-process rows on the same axes now share a cache slot;
  existing entries match the new key but need a refresh to gain
  the runtime parts -- transitional rows fall back to in-process
  JIT with a logged warning.
@vgvassilev
vgvassilev force-pushed the ci-bundle-oop-runtime-pr1 branch from be8f32c to a039fbf Compare April 26, 2026 15:31
@codecov

codecov Bot commented Apr 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.67%. Comparing base (fb595ac) to head (a039fbf).
⚠️ Report is 106 commits behind head on main.

Files with missing lines Patch % Lines
lib/CppInterOp/Compatibility.h 80.00% 6 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #940      +/-   ##
==========================================
+ Coverage   80.87%   81.67%   +0.79%     
==========================================
  Files          15       15              
  Lines        4707     4743      +36     
==========================================
+ Hits         3807     3874      +67     
+ Misses        900      869      -31     
Files with missing lines Coverage Δ
lib/CppInterOp/CppInterOpInterpreter.h 86.22% <ø> (+13.00%) ⬆️
lib/CppInterOp/Compatibility.h 82.75% <80.00%> (-0.58%) ⬇️

... and 1 file with indirect coverage changes

Files with missing lines Coverage Δ
lib/CppInterOp/CppInterOpInterpreter.h 86.22% <ø> (+13.00%) ⬆️
lib/CppInterOp/Compatibility.h 82.75% <80.00%> (-0.58%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

#if defined(_WIN32) || !defined(LLVM_BUILT_WITH_OOP_JIT)
outOfProcess = false;
#else
#if LLVM_VERSION_MAJOR > 21 && !defined(_WIN32)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "LLVM_VERSION_MAJOR" is directly included [misc-include-cleaner]

lib/CppInterOp/CppInterOpInterpreter.h:38:

+ #include <llvm/Config/llvm-config.h>

@vgvassilev

Copy link
Copy Markdown
Contributor Author

The failure seems a glitch. Test coming in the next pr.

@vgvassilev
vgvassilev merged commit 2da895b into compiler-research:main Apr 26, 2026
26 of 28 checks passed
@vgvassilev
vgvassilev deleted the ci-bundle-oop-runtime-pr1 branch April 26, 2026 16:06
vgvassilev added a commit to vgvassilev/CppInterOp that referenced this pull request Apr 27, 2026
The asan-ubsan CI row started exercising the OOP-JIT path after
`[ci] Build the bundled OOP-JIT runtime in non-cling LLVM>=22
caches.` (compiler-research#940) made OOP run by default for every llvm22+ row.
`EnumReflection_GetEnums` then trips the assertion at
`llvm/lib/ExecutionEngine/Orc/Core.cpp:2800`:

    Resolving symbol with incorrect flags

ASan instruments globals with extra metadata that changes the
`JITSymbolFlags` declared in the host process; when the EPC-based
out-of-process executor reports back the resolved flags, they
don't match. The in-process JIT path doesn't compare across an
IPC boundary so it's unaffected, and other OOP tests don't define
the kinds of common symbols that hit the resolution path.

Skip just this test under OOP-when-sanitized rather than
disabling the OOP fixture wholesale -- the remaining OOP tests on
the asan-ubsan row keep running. Likely upstream LLVM bug; can be
removed once the EPC symbol-flag tracking is fixed.
vgvassilev added a commit to vgvassilev/CppInterOp that referenced this pull request Apr 27, 2026
The asan-ubsan CI row started exercising the OOP-JIT path after
`[ci] Build the bundled OOP-JIT runtime in non-cling LLVM>=22
caches.` (compiler-research#940) made OOP run by default for every llvm22+ row.
Two tests then trip the assertion at
`llvm/lib/ExecutionEngine/Orc/Core.cpp:2800`:

    Resolving symbol with incorrect flags

ASan instruments globals with extra metadata that changes the
`JITSymbolFlags` declared in the host process; when the EPC-based
out-of-process executor reports back the resolved flags, they
don't match. The in-process JIT path doesn't compare across an
IPC boundary so it's unaffected, and other OOP tests don't define
the kinds of common symbols that hit the resolution path.

Skip the failing tests under OOP-when-sanitized rather than
disabling the OOP fixture wholesale -- the remaining OOP tests on
the asan-ubsan row keep running:

  - `EnumReflection_GetEnums`
  - `FunctionReflection_InstantiateTemplateFunctionFromString`

Likely upstream LLVM bug; can be removed once the EPC symbol-flag
tracking is fixed.
vgvassilev added a commit that referenced this pull request Apr 27, 2026
#942)

* [jit] Add a layered probe chain for relocatable OOP runtime discovery.

The bake-at-build-time install path from `[jit] Self-contain the
OOP-JIT runtime in CppInterOp's distribution.` is fragile under
relocation: an installed CppInterOp moved to a different prefix
(rpm `--prefix`, conda relocation, AppImage) can't find the runtime
parts because the macro holds the original
`CMAKE_INSTALL_FULL_LIBDIR`.

`configureBundledOOPRuntime` now probes a layered list, most-reliable
first, before falling back to the baked path:

  1. `$CPPINTEROP_RUNTIME_DIR` -- sysadmin override; trumps every
     other source so packagers can point CppInterOp at a runtime
     extracted to a separate location.
  2. `<dir of libclangCppInterOp>/cppinterop-rt` -- self-DSO discovery
     via `dladdr` (POSIX). Works for any non-static link: if the
     `.so` moves, the runtime moves with it, no env-var needed.
  3. `CPPINTEROP_RUNTIME_BUILD_DIR` -- in-tree test runs.
  4. `CPPINTEROP_RUNTIME_INSTALL_DIR` -- baked install path; last
     resort when self-DSO discovery isn't available (Windows, or
     CppInterOp statically linked into a host binary).

Windows has no self-DSO discovery yet -- a `GetModuleHandleEx` port
can be added when Windows OOP support arrives. The clang resource
directory (`CLANG_RESOURCE_DIR`) suffers the same
bake-at-build-time-vs-relocation problem and would benefit from the
same layering; left as follow-up.

* [ci] Verify the OOP runtime probe chain via relocation + env-var.

The layered probe chain in `configureBundledOOPRuntime` from
`[jit] Add a layered probe chain for relocatable OOP runtime
discovery.` adds two new lookup layers (`CPPINTEROP_RUNTIME_DIR`
env-var override and `dladdr`-based self-DSO probe) that the
existing in-tree test path doesn't exercise -- in-tree the baked
`CPPINTEROP_RUNTIME_BUILD_DIR` probe wins first, so a regression
in either new layer would be silent.

After the install-layout assertion succeeds, move the install to
a fresh prefix and re-run the OOP-tagged tests with
`DYLD_LIBRARY_PATH`/`LD_LIBRARY_PATH` pointing at the moved tree:
the `dladdr` probe must follow the relocated `.so` and find the
runtime alongside it. Then stage the runtime parts at a third
location, wipe the moved `cppinterop-rt/` subdir, and re-run with
`CPPINTEROP_RUNTIME_DIR` set to the staged copy: only the env-var
probe can win.

Both runs assert that the
`[CreateClangInterpreter]: --use-oop-jit requested but the bundled
OOP runtime ... is missing` fallback warning does NOT appear in
the test output. Negative-control verified locally -- with all
probe locations wiped the warning does fire, confirming the
assertion isn't dead.

Filter is `CppInterOpTest/OutOfProcessJIT.Jit_StreamRedirectJIT`,
the only OOP-tagged test that calls `CreateInterpreter()` before
its skip check; the test itself fails with a preexisting
`stdio.h not found` issue in the OOP child interpreter, which is
orthogonal to the probe chain and doesn't trip the bundling
warning.

* [test] Skip OOP+sanitizer-incompatible reflection tests.

The asan-ubsan CI row started exercising the OOP-JIT path after
`[ci] Build the bundled OOP-JIT runtime in non-cling LLVM>=22
caches.` (#940) made OOP run by default for every llvm22+ row.
Two tests then trip the assertion at
`llvm/lib/ExecutionEngine/Orc/Core.cpp:2800`:

    Resolving symbol with incorrect flags

ASan instruments globals with extra metadata that changes the
`JITSymbolFlags` declared in the host process; when the EPC-based
out-of-process executor reports back the resolved flags, they
don't match. The in-process JIT path doesn't compare across an
IPC boundary so it's unaffected, and other OOP tests don't define
the kinds of common symbols that hit the resolution path.

Skip the failing tests under OOP-when-sanitized rather than
disabling the OOP fixture wholesale -- the remaining OOP tests on
the asan-ubsan row keep running:

  - `EnumReflection_GetEnums`
  - `FunctionReflection_InstantiateTemplateFunctionFromString`

Likely upstream LLVM bug; can be removed once the EPC symbol-flag
tracking is fixed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant