code wiki / (root) / nx_g1_bridge_kat.nx

nx_g1_bridge_kat.nx source

↩ module page · 49 lines · 2299 B

1// nx_g1_bridge_kat.nx -- reusable register-survival KAT for codegen changes. 2// 3// Exercises the two correctness hazards that any callee-saved-register or 4// cross-call register-allocation change must not break: 5// (1) a value produced BEFORE a call and consumed AFTER it (the call, and 6// in particular a result-unused call, must not corrupt a resident value); 7// (2) a value in the CALLER that must survive a callee which itself performs 8// a TAIL call (the tail-call frame teardown must restore callee-saved regs 9// before jumping, or it corrupts the caller). 10// 11// Pure integer arithmetic with closed-form expected sums -> deterministic 12// exit 0 on pass, nonzero on any miscompile. Self-contained (no imports) so it 13// compiles under any backend. Used by bench/nx_codegen_selfhost_gauntlet.sh. 14// expect_exit: 0 15// license_tier: ORIGINAL 16 17func sink(x: i64) -> i64 { return x ^ 0x5a5a } // clobbers caller-saved regs 18func tail_target(x: i64) -> i64 { return x + 1 } 19func via_tail(x: i64) -> i64 { 20 let y: i64 = x * 3 // a value live across the tail call 21 return tail_target(y) // TAIL call: teardown must restore caller's callee-saved regs 22} 23 24func main() -> i64 { 25 // (1) cross-call survival of a pre-call value 26 var acc: i64 = 0 27 var i: i64 = 0 28 while i < 1000 { 29 let base: i64 = i * 7 // resident candidate 30 let d: i64 = sink(i) // a CALL between produce and consume 31 acc = acc + base + (d ^ 0x5a5a) // base + i ; (d ^ 0x5a5a) == i 32 i = i + 1 33 } 34 // sum_{i<1000} (7i + i) = 8 * (999*1000/2) = 3996000 35 if acc != 3996000 { return 1 } 36 37 // (2) caller's value must survive a callee that does a TAIL call 38 var total: i64 = 0 39 var k: i64 = 0 40 while k < 500 { 41 let keep: i64 = k * 11 + 1 // main's resident value 42 let t: i64 = via_tail(k) // via_tail tail-calls internally 43 total = total + keep + t // keep consumed AFTER via_tail returns 44 k = k + 1 45 } 46 // sum_{k<500} (11k+1)+(3k+1) = sum(14k+2) = 14*124750 + 1000 = 1747500 47 if total != 1747500 { return 2 } 48 return 0 49}