Repository navigation
PERRY_LLVM_INPROCESS=native cannot build RS4GC ptr addrspace(1) roots; the unit corpora froze 151 codegen commits ago #7982
Description
Summary
The in-process LLVM backend's native construction path (PERRY_LLVM_INPROCESS=native)
cannot build any function containing RS4GC root slots. Every main execution of
llvm-inprocess's native-backend job fails here — runs 31461469705,
31461474406, 31461478986 (all 2026-08-11T05:23Z).
This is the defect behind #7971's "when it does execute, it fails". #7971 covers the
gate (vacuous green on PRs, no diagnostic on failure); this is the code.
Reproduction (local, deterministic)
export LLVM_SYS_221_PREFIX=/opt/homebrew/opt/llvm@22
cargo build --profile perry-dev -p perry -p perry-runtime-static \
-p perry-stdlib-static --features perry/llvm-inprocess
export PERRY_RUNTIME_DIR="$PWD/target/perry-dev" PERRY_NO_AUTO_OPTIMIZE=1
PERRY_LLVM_INPROCESS=native target/perry-dev/perry \
experiments/llvm-inprocess-spike/spike.ts -o /tmp/spike_nativeError compiling module 'spike.ts' ... native IR construction failed in
@perry_closure_spike_ts__8:
in line: %r5 = alloca ptr addrspace(1)
The textual path compiles the same program fine. Note the compiler's diagnostic is
already good — CI was redirecting it into /tmp/native.err and never printing it,
which is why three main failures looked like a bare exit 1 (fixed in #7971).
Root cause
crates/perry-codegen/src/dialect/mod.rs::basic_type has an arm for "ptr" but
none for ptr addrspace(N), so it reaches bail!("unknown type {tok}").
Today's codegen emits five addrspace(1) shapes (116 occurrences in spike.ts
alone):
%X = alloca ptr addrspace(1)
%X = load ptr addrspace(1)
store ptr addrspace(1) ...
%X = inttoptr i64 %X to ptr addrspace(1)
%X = ptrtoint ptr addrspace(1) %X to i64
It is not a one-line fix. I added an addrspace(N) arm to basic_type and
rebuilt: alloca then succeeds and the reader fails on the next shape,
store ptr addrspace(1) null, ptr %r5. The operand-side parsing needs the same
treatment. (That probe was reverted; it is diagnosis, not a proposed patch.)
Why the unit gate never caught it
llvm-inprocess asserts dialect::tests::corpus_spike ... ok and friends, with
the comment "a checkout missing the tracked .ll corpora would otherwise green
vacuously". That assert proves the tests ran; it does not prove the corpora
are current:
| corpus | last refreshed |
|---|---|
experiments/llvm-inprocess-spike/spike_text.ll |
b50e857c2, 2026-08-03 (#7310) |
experiments/llvm-inprocess-spike/batch_kernel.ll |
b50e857c2, 2026-08-03 (#7310) |
experiments/llvm-inprocess-spike/eh_text.ll |
4bf29f1bd, 2026-08-03 (#7307) |
151 crates/perry-codegen/src commits have landed since, and all three corpora
contain zero occurrences of addrspace(1):
$ grep -c 'addrspace(1)' experiments/llvm-inprocess-spike/*.ll
batch_kernel.ll:0
eh_text.ll:0
spike_text.ll:0
So the unit gate validates the reader against IR the compiler emitted nine days and
151 codegen commits ago. It is green, and its subject — the IR this commit emits —
never ran. That is CLAUDE.md's fourth way a gate cannot fail, inside the liveness
assert that was written to prevent exactly that.
RS4GC root-slot emission arrived over #7301 → #7314 → #7322 → #7348 → #7487 →
#7509 → #7636 → #7642, i.e. mostly after the corpora were frozen.
Suggested fix
- Teach the dialect reader
ptr addrspace(N)in type position and operand
position — at minimum the five shapes above. - Refresh the three tracked corpora, and add something that makes staleness
visible. A currency diagnostic is already printed byllvm-inprocessas of
llvm-inprocess reports green on PRs while skipping its only real job (hazard 4), and fails when it does run #7971; a stronger option is a test that regenerates a corpus and diffs it, so
"the reader handles today's IR" is asserted rather than assumed.
Until (1) lands, PERRY_LLVM_INPROCESS=native is broken for any program with GC
roots — which is effectively all of them. PERRY_LLVM_INPROCESS=diff and the
default in-process path are unaffected (they go through the textual reader).
Activity
ci: repair three broken gates — Windows cp1252, llvm-inprocess vacuou…
docs(gc-handoff): KNOBS-NOTES for the #7991/#7982/#7737 batch
fix(codegen): teach the in-process native backend today's RS4GC IR; u…
test(codegen): pin the GC strategy onto the define line, in BOTH root…
proggeramlug commentedon Aug 13, 2026
Fixed by #7998, with the non-vacuous GC-strategy regression pin added in #8000. Verified on current main: the corpus-currency checks pass and all three focused llvm-inprocess dialect corpus tests pass.
fix(runtime): claim action-zero landing pads as Perry catches again
test(eh): pin that an action-zero landing pad is still Perry's catch
test(eh): pin that an action-zero landing pad is still Perry's catch
fix(gc): root heap values held across JS-running calls in runtime and…
fix(runtime): drop this branch's landing-pad regression, and retarget…
merge origin/main into the production App Route branch
fix(next): pass production App Route dylib gate (#8082)