code wiki / _hdl_build / _regalloc_lf_repro.nx

_regalloc_lf_repro.nx source

↩ module page · 54 lines · 2969 B

1// _regalloc_lf_repro.nx -- candidate TEN-SECOND repro for LM-REGALLOC: the 2// large-frame / high-register-pressure miscompile where the x86 regalloc 3// miscalculates an alloca-slot offset so a local write lands on a POINTER 4// ARG's spill slot, corrupting it (the parse_stmt in-source comment; the 5// same bug my && short-circuit change surfaced by enlarging the function). 6// RECIPE: pointer arg `p` read early + many if-expr ALLOCAS + CALLS (force p 7// to spill) + p re-read/written AFTER the allocas. If the bug fires, p is 8// corrupted -> p[1]=v1 segfaults or p[1]!=42. GREEN(exit0)=no bug here; 9// RED(segfault/!=42)=repro = the team's deterministic gate. license_tier: ORIGINAL 10import "nx_syscalls.nx" 11func rp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func rn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1}; sys_write(1,b,k); return 0 } 13// a real call so the regalloc must SPILL the pointer arg across it 14func work(x: i64) -> i64 { return x * 2 + 1 } 15// the victim: pointer arg + if-expr allocas + calls + re-read of p 16func bug(p: *i64) -> i64 { 17 let v0: i64 = p[0] 18 let a: i64 = work(v0) 19 let b: i64 = if a == 0 then work(1) else work(2) 20 let c: i64 = work(a + b) 21 let d: i64 = if b == 3 then work(3) else work(4) 22 let e: i64 = work(c + d) 23 let f: i64 = if c == 5 then work(5) else work(6) 24 let g: i64 = work(e + f) 25 let h: i64 = if d == 7 then work(7) else work(8) 26 let i2: i64 = work(g + h) 27 let j: i64 = if e == 9 then work(9) else work(10) 28 let k2: i64 = work(i2 + j) 29 let l: i64 = if f == 11 then work(11) else work(12) 30 let m2: i64 = work(k2 + l) 31 let n2: i64 = if g == 13 then work(13) else work(14) 32 let o: i64 = work(m2 + n2) 33 let q: i64 = if h == 15 then work(15) else work(16) 34 let r2: i64 = work(o + q) 35 let s2: i64 = if i2 == 17 then work(17) else work(18) 36 let acc: i64 = a + b + c + d + e + f + g + h + i2 + j + k2 + l + m2 + n2 + o + q + r2 + s2 37 // re-read the pointer AFTER all the allocas; if regalloc corrupted p's 38 // spill slot, this read/write goes wrong (the bug) 39 let v1: i64 = p[0] 40 p[1] = v1 41 return acc 42} 43func main() -> i64 { 44 rp("=== LM-REGALLOC large-frame repro: pointer-arg corruption under alloca pressure ===\n" as *u8) 45 let p: *i64 = sys_mmap(64) as *i64 46 p[0] = 42 47 p[1] = 0 48 let acc: i64 = bug(p) 49 rp(" acc=" as *u8); rn(acc); rp(" p[0]=" as *u8); rn(p[0]); rp(" p[1]=(re-read of p[0])=" as *u8); rn(p[1]); rp("\n" as *u8) 50 if p[1] == 42 { rp(" REGALLOC-REPRO: GREEN -- pointer arg INTACT (bug did NOT fire in this shape)\n" as *u8); sys_exit(0); return 0 } 51 rp(" REGALLOC-REPRO: RED -- pointer arg CORRUPTED (p[1] != 42) = LM-REGALLOC reproduced\n" as *u8) 52 sys_exit(1) 53 return 1 54}