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}