Section 03: Verification
Status: Not Started
Goal: Complete confidence that the personality function swap is correct: all existing tests pass, Ori’s generated LLVM IR references only ori_eh_personality (note: rust_eh_personality may still appear in libori_rt.a from embedded Rust std — this is expected), no behavioral regressions in eval or AOT paths, and no memory safety issues.
Context: The personality function is on the critical path of exception handling. If it’s implemented incorrectly, panics will crash instead of unwinding, ARC cleanup won’t run (causing leaks or use-after-free), and catch() will stop working. Testing must cover both the happy path (no exceptions) and the unwind path (panic, catch, ARC cleanup).
Depends on: Sections 01 and 02 (personality function exists and codegen references it).
03.1 Test Suite
File(s): N/A (running existing tests)
-
cargo build -p ori_rt— runtime builds cleanly (both rlib and staticlib) -
cargo b— compiler + runtime build succeeds (debug) -
cargo b --release— compiler + runtime build succeeds (release) -
./test-all.sh— full test suite passes- This covers: Rust unit tests, Ori spec tests (JIT), LLVM unit tests, AOT integration tests
- Key test categories that exercise exception handling:
tests/spec/patterns/catch.ori— catch/recover semanticstests/spec/functions/recursion.ori— invoke/landingpad for recursive callstests/spec/errors/— panic behaviorcompiler/ori_llvm/tests/aot/— AOT compilation + execution
-
./clippy-all.sh— no new warnings -
./fmt-all.sh— formatting clean
03.2 Symbol Audit
File(s): N/A (inspection commands)
Verify that the symbol swap is complete at every level.
-
Source code audit — zero references to
rust_eh_personality:grep -r "rust_eh_personality" compiler/ library/ tests/ # Expected: 0 matches -
LLVM IR audit — generated IR uses
ori_eh_personality:# Pick a program that generates invoke/landingpad ORI_DEBUG_LLVM=1 ori check tests/spec/functions/recursion.ori 2>&1 \ | grep "personality" # Expected: personality ptr @ori_eh_personality (one per function with invoke) # Expected: declare i32 @ori_eh_personality(i32) #N (one declaration) -
Static library audit — symbol exists in libori_rt.a:
nm target/debug/libori_rt.a | grep "ori_eh_personality" # Expected: T ori_eh_personality (T = text/code section) nm target/debug/libori_rt.a | grep "rust_eh_personality" # Expected: still present (from Rust std embedded in staticlib — this is OK) # The point is that OUR code references ori_eh_personality, not rust_eh_personalityNote:
rust_eh_personalitymay still appear in the staticlib because Rust’s std is embedded in it. This is expected — Rust’s internal unwinding uses its own personality. What matters is that Ori’s generated LLVM IR referencesori_eh_personality. -
AOT binary audit — compiled Ori program uses ori_eh_personality:
ori build tests/spec/functions/recursion.ori -o /tmp/test_personality nm /tmp/test_personality | grep "eh_personality" # Expected: ori_eh_personality in the symbol table # rust_eh_personality may also be present (from libori_rt.a's embedded Rust std)
03.3 Code Journey Regression
File(s): plans/code-journeys/
Re-run the code journeys that exercise exception handling to verify behavioral equivalence.
-
Journey 3 (“I am recursive”) — the journey that first identified the
rust_eh_personalitydependency:- Eval = 61 (must still be correct)
- AOT = 61 (must still be correct)
- IR now shows
@ori_eh_personalityinstead of@rust_eh_personality
-
Journey 9 (“I am a string”) — first journey with ARC runtime functions:
- Eval = 13, AOT = 13 (must still be correct)
- ARC cleanup paths exercise landing pads
-
Journey 10 (“I am a list”) — lists with ARC lifecycle:
- Eval = 33, AOT = 33 (must still be correct)
-
Journey 12 (“I am an option”) — uses
catch-style landing pads:- Eval = 33 (must still be correct)
- AOT = 144 (known bug C4 — must not get worse)
03.4 Memory Safety
-
Valgrind verification — no new memory errors from personality function:
diagnostics/valgrind-aot.sh # Expected: same results as before (no new errors) -
Leak check — ARC cleanup still works during unwind:
ORI_CHECK_LEAKS=1 ori run tests/spec/patterns/catch.ori # Expected: exit code 0 (no leaks)If catch tests allocate RC-managed values that are cleaned up during unwind, the personality function must correctly route through cleanup landing pads for RC decrements to happen.
-
Forced-unwind safety (x86-64 + aarch64 Linux) —
cargo test -p ori_rtforced-unwind tests pass:forced_unwind_personality_behavior— single serialized test verifying both: catch-all LP skipped during_Unwind_ForcedUnwind, cleanup LP executed during_Unwind_ForcedUnwind- These are C/assembly tests added in Section 01.4 that exercise the personality directly via
_Unwind_ForcedUnwind. Per-architecture assembly stubs (test_frames_x86_64.S,test_frames_aarch64.S) are selected bybuild.rsbased onCARGO_CFG_TARGET_ARCH. The Rust test file gates via#![cfg(all(target_os = "linux", any(target_arch = "x86_64", target_arch = "aarch64")))]. Skipped cleanly on non-Linux/unsupported-arch targets (0 tests, not failure). - ARM verification: spin up a preemptible GCP aarch64 instance, run
cargo test -p ori_rt, destroy when done. Cross-compilation alone is insufficient — the forced-unwind tests must execute natively to validate personality behavior. - CI follow-up: aarch64 verification is manual for this initial implementation. Adding an aarch64 CI runner (GCP spot instance in GitHub Actions, or
qemu-userwith binfmt) should be tracked as a follow-up to prevent regressions.
03.5 Completion Checklist
-
cargo build -p ori_rtsucceeds -
cargo bandcargo b --releasesucceed -
./test-all.shgreen -
./clippy-all.shgreen - Zero
rust_eh_personalityreferences incompiler/,library/,tests/ - LLVM IR shows
@ori_eh_personality -
nm libori_rt.ashowsori_eh_personalitysymbol - Code journeys J3, J9, J10, J12 produce same results as before
-
diagnostics/valgrind-aot.shno new errors -
ORI_CHECK_LEAKS=1catch tests pass -
cargo test -p ori_rtforced-unwind tests pass on x86-64 Linux (catch skipped, cleanup ran) -
cargo test -p ori_rtforced-unwind tests pass on aarch64 Linux (native execution on GCP preemptible instance) - Unsupported targets (non-Linux or unsupported arch): forced-unwind tests cleanly skipped (0 tests, not failure)
Exit Criteria: ./test-all.sh passes (all existing tests green, zero regressions). grep -r "rust_eh_personality" compiler/ library/ tests/ returns 0 matches. ORI_DEBUG_LLVM=1 on any invoke-bearing program shows @ori_eh_personality. Code journeys J3/J9/J10/J12 produce identical eval and AOT results as before this change. diagnostics/valgrind-aot.sh shows no new memory errors. On x86-64 and aarch64 Linux: cargo test -p ori_rt forced-unwind tests pass (catch-all pads skipped, cleanup pads run under _UA_FORCE_UNWIND). On unsupported targets (non-Linux or unsupported arch): forced-unwind tests are skipped (0 tests, not failure).