code wiki / _hdl_build / nx_sext_wasm_kat_gate.nx
nx_sext_wasm_kat_gate.nx source
↩ module page · 88 lines · 5191 B
1// nx_sext_wasm_kat_gate.nx -- END-TO-END KAT for the WASM lane's subword sign-extend fix (2026-07-10):
2// forks the sovereign pipeline (nx_compile_wat: .nx -> wat; nx_wat_compiler: wat -> wasm) on
3// nx_sext_wasm_kat.nx, loads the wasm in nx_wasm_vm, and asserts the SEMANTICS in-VM:
4// T1 both tools rc=0 (pre-fix: nx_wat_compiler REFUSED -- i64.store32/load32_* were unknown atoms)
5// T2 exports resolve
6// T3 sext_kat() == 0 (*i32 negative+positive round-trip AND *u8 0xA0->160 witness, all in-VM)
7// T4 sext_load_neg() == -100 (the visible sign-extension number; a zero-extend lane returns 4294967196)
8// This is the WASM twin of nx_i32store_probe_gate (x86) -- one language semantic, every backend.
9// Stage first: nx_sov_build_run nx_compile_wat --build-only + nx_sov_build_run nx_wat_compiler --build-only.
10// expect_exit: 0 license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "nx_wasm_vm.nx"
13import "nx_gate_verdict.nx"
14
15const SW_CWAT: *u8 = "/tmp/nx_compile_wat.sov.elf"
16const SW_WATC: *u8 = "/tmp/nx_wat_compiler.sov.elf"
17const SW_SRC: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/runtime/nx_sext_wasm_kat.nx"
18const SW_OWAT: *u8 = "/tmp/sextkat.wat"
19const SW_OWASM: *u8 = "/tmp/sextkat.wasm"
20
21func sw_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
22func sw_pn(v: i64) -> i64 {
23 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
24 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}
25 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
26func sw_check(name: *u8, cond: i64) -> i64 {
27 if cond==1 { sw_puts(" PASS " as *u8) } else { sw_puts(" FAIL " as *u8) }
28 sw_puts(name); sw_puts("\n" as *u8); return cond }
29func sw_run_elf(elf: *u8, a1: *u8, a2: *u8) -> i64 {
30 let pid: i64 = sys_fork()
31 if pid == 0 {
32 let argv: *i64 = sys_mmap(64) as *i64
33 argv[0]=elf as i64; argv[1]=a1 as i64; argv[2]=a2 as i64; argv[3]=0
34 let envp: *i64 = sys_mmap(16) as *i64
35 envp[0]="PATH=/usr/bin:/bin" as *u8 as i64; envp[1]=0
36 sys_execve(elf, argv, envp); sys_exit(127)
37 }
38 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0)
39 return (st[0] >> 8) & 0xff }
40
41func main() -> i64 {
42 sw_puts("=== nx_sext_wasm_kat_gate: .nx -> wat -> wasm -> nx_wasm_vm, subword sign-extend semantics ===\n" as *u8)
43 var pass: i64 = 0; var total: i64 = 0
44
45 let rc1: i64 = sw_run_elf(SW_CWAT, SW_SRC, SW_OWAT)
46 sw_puts(" [build] nx_compile_wat rc=" as *u8); sw_pn(rc1); sw_puts("\n" as *u8)
47 let rc2: i64 = sw_run_elf(SW_WATC, SW_OWAT, SW_OWASM)
48 sw_puts(" [build] nx_wat_compiler rc=" as *u8); sw_pn(rc2); sw_puts("\n" as *u8)
49 var okb: i64 = 0
50 if rc1 == 0 { if rc2 == 0 { okb = 1 } }
51 pass = pass + sw_check("pipeline rc=0 (pre-fix: WATC REFUSED unknown i64.store32/load32_*)" as *u8, okb); total = total + 1
52 if okb == 0 { sw_puts("NX-SEXT-WASM-KAT-GATE verdict=RED (pipeline)\n" as *u8); return 1 }
53
54 let box: *i64 = sys_mmap(16) as *i64
55 let wasm: *u8 = sys_read_file(SW_OWASM, box)
56 if (wasm as i64)==0 { sw_puts(" FAIL cannot read sextkat.wasm\nNX-SEXT-WASM-KAT-GATE verdict=RED\n" as *u8); return 1 }
57 sw_puts(" [measure] wasm bytes=" as *u8); sw_pn(box[0]); sw_puts("\n" as *u8)
58 let mod: *WasmMod = wm_new(wasm, box[0])
59 if wm_parse(mod) != 0 { sw_puts(" FAIL wasm parse\nNX-SEXT-WASM-KAT-GATE verdict=RED\n" as *u8); return 1 }
60 mod.mem = sys_mmap(131072) as *u8
61
62 var oke: i64 = 0
63 if wm_find_export(mod, "sext_kat" as *u8) >= 0 { if wm_find_export(mod, "sext_load_neg" as *u8) >= 0 { oke = 1 } }
64 pass = pass + sw_check("exports sext_kat + sext_load_neg resolve" as *u8, oke); total = total + 1
65
66 let k: i64 = wm_run(mod, "sext_kat" as *u8, 0, 0, 0, 0, 0, 0)
67 sw_puts(" [run] sext_kat() fails=" as *u8); sw_pn(k); sw_puts("\n" as *u8)
68 var ok3: i64 = 0
69 if k == 0 { ok3 = 1 }
70 pass = pass + sw_check("in-VM semantics: *i32 neg+pos round-trip AND *u8 0xA0->160 (fails==0)" as *u8, ok3); total = total + 1
71
72 let nv: i64 = wm_run(mod, "sext_load_neg" as *u8, 0, 0, 0, 0, 0, 0)
73 sw_puts(" [run] sext_load_neg() = " as *u8); sw_pn(nv); sw_puts(" (want -100; zero-extend lane would say 4294967196)\n" as *u8)
74 var ok4: i64 = 0
75 if nv == (0 - 100) { ok4 = 1 }
76 pass = pass + sw_check("i64.load32_s sign-extends in the sovereign VM (== -100)" as *u8, ok4); total = total + 1
77
78 sw_puts("NX-SEXT-WASM-KAT-GATE passed " as *u8); sw_pn(pass); sw_puts("/" as *u8); sw_pn(total)
79 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
80 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
81 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
82 let ctr__dry: *i64 = gv_ctr()
83 ctr__dry[0] = pass
84 ctr__dry[1] = total
85 let rc__dry: i64 = gv_verdict("SEXT-WASM-KAT-GATE" as *u8, ctr__dry, "WASM lane sext-aligned with x86+RV64: signed loads sign-extend, u8 stays zero-extend)" as *u8)
86 sys_exit(rc__dry)
87 return rc__dry
88}