code wiki / _hdl_build / nx_diff_gen.nx

nx_diff_gen.nx source

↩ module page · 311 lines · 11029 B

1// nx_diff_gen.nx -- R1-T1-001: the differential-testing CORPUS GENERATOR 2// (the PREVENT instrument for the miscompile class; spec arc T1). Emits N 3// deterministic random programs in the SUPPORTED dialect envelope, so any 4// build/run failure is a NEW toolchain bug by construction, never a known 5// landmine: 6// counted while loops only (literal bound <=10 -> termination by 7// construction); ifs <=2 deep; i64 + - * only (no division); every shift 8// masked (LM-005); literals non-negative (LM-004); sys_exit((sum)&1) so 9// legal exits are EXACTLY {0,1} -- lane rc 3/4 = toolchain fail, >128 = 10// crash, anything else loud. 11// DETERMINISM: same conf (knowledge/registry/diff_corpus.conf: n/seed/ 12// max_stmts) = byte-identical corpus (LCG PRNG, no time, no env) -- proven 13// by the gate via corpus-hash equality across runs. Programs land in 14// runtime/_hdl_build/<prefix><i>.nx because expand_imports resolves only 15// there (probed 2026-06-11: /tmp sources fail expand_imports) -- which also 16// means the DURABLE LANE builds any corpus program by basename, retry guard 17// included. Every file is PADDED to a fixed 3072 bytes with trailing 18// newlines: rewrites always cover prior content (LM-022 stale-tail killer 19// even across seed changes). 20// argv[1]=conf override argv[2]=name-prefix override (default _dgp) 21// argv[3]=hash-file override (default /tmp/_dg_hash.txt) 22// Evidence: DIFFGEN row -> stdout + knowledge/status/diff_gen.log. 23// license_tier: ORIGINAL 24 25import "nx_syscalls.nx" 26import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 27const DG_MAGIC_1103515245: i64 = 1103515245 28const DG_MAGIC_12345: i64 = 12345 29const DG_MAGIC_2800: i64 = 2800 30const DG_MAGIC_4096: i64 = 4096 31const DG_MAGIC_4095: i64 = 4095 32const DG_MAGIC_1106202601: i64 = 1106202601 33const DG_MAGIC_1469598103: i64 = 1469598103 34 35const DG_FILEPAD: i64 = 3072 36const DG_BUFCAP: i64 = 4096 37 38func dg_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 39func dg_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 40// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 41// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 42// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 43// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 44func dg_fn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 } 45 46func dg_cat(dst: *u8, off: i64, s: *u8) -> i64 { 47 var i: i64 = 0 48 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 49 return off + i 50} 51 52func dg_catn(dst: *u8, off: i64, v: i64) -> i64 { 53 var m: i64 = v 54 if m < 0 { m = 0 } 55 let t: *u8 = sys_mmap(28) 56 var k: i64 = 0 57 if m == 0 { t[0] = 48 as u8; k = 1 } 58 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 59 var o: i64 = off 60 var i: i64 = 0 61 while i < k { dst[o] = t[k - 1 - i]; o = o + 1; i = i + 1 } 62 return o 63} 64 65// classic LCG, 31-bit state: deterministic, overflow-free 66func dg_rnd(st: *i64, k: i64) -> i64 { 67 st[0] = (st[0] * DG_MAGIC_1103515245 + DG_MAGIC_12345) & 0x7fffffff 68 return (st[0] >> 16) % k 69} 70 71// append "v<idx>" (idx 0..3) 72func dg_catv(dst: *u8, off: i64, idx: i64) -> i64 { 73 dst[off] = 118 as u8 74 dst[off + 1] = (48 + idx) as u8 75 return off + 2 76} 77 78// one straight-line arithmetic statement 79func dg_st_arith(b: *u8, off: i64, st: *i64) -> i64 { 80 let a: i64 = dg_rnd(st, 4) 81 let c: i64 = dg_rnd(st, 4) 82 let kind: i64 = dg_rnd(st, 4) 83 var o: i64 = dg_cat(b, off, " " as *u8) 84 o = dg_catv(b, o, a) 85 o = dg_cat(b, o, " = " as *u8) 86 if kind == 0 { 87 o = dg_catv(b, o, a) 88 o = dg_cat(b, o, " + " as *u8) 89 o = dg_catv(b, o, c) 90 } 91 if kind == 1 { 92 o = dg_catv(b, o, a) 93 o = dg_cat(b, o, " * 3 + " as *u8) 94 o = dg_catn(b, o, dg_rnd(st, 17)) 95 } 96 if kind == 2 { 97 o = dg_cat(b, o, "(" as *u8) 98 o = dg_catv(b, o, a) 99 o = dg_cat(b, o, " >> " as *u8) 100 o = dg_catn(b, o, 1 + dg_rnd(st, 5)) 101 o = dg_cat(b, o, ") & 0xffff" as *u8) 102 } 103 if kind == 3 { 104 o = dg_cat(b, o, "(" as *u8) 105 o = dg_catv(b, o, a) 106 o = dg_cat(b, o, " << " as *u8) 107 o = dg_catn(b, o, 1 + dg_rnd(st, 3)) 108 o = dg_cat(b, o, ") & 0xfffffff" as *u8) 109 } 110 o = dg_cat(b, o, "\n" as *u8) 111 return o 112} 113 114// if / if-else / 2-deep if 115func dg_st_branch(b: *u8, off: i64, st: *i64) -> i64 { 116 let a: i64 = dg_rnd(st, 4) 117 let c: i64 = dg_rnd(st, 4) 118 let d: i64 = dg_rnd(st, 4) 119 let kind: i64 = dg_rnd(st, 2) 120 var o: i64 = dg_cat(b, off, " if " as *u8) 121 o = dg_catv(b, o, a) 122 o = dg_cat(b, o, " > " as *u8) 123 o = dg_catv(b, o, c) 124 o = dg_cat(b, o, " { " as *u8) 125 o = dg_catv(b, o, d) 126 o = dg_cat(b, o, " = " as *u8) 127 o = dg_catv(b, o, d) 128 o = dg_cat(b, o, " + 1 }" as *u8) 129 if kind == 1 { 130 o = dg_cat(b, o, " else { " as *u8) 131 o = dg_catv(b, o, d) 132 o = dg_cat(b, o, " = " as *u8) 133 o = dg_catv(b, o, d) 134 o = dg_cat(b, o, " - 1 }" as *u8) 135 } 136 o = dg_cat(b, o, "\n" as *u8) 137 return o 138} 139 140// counted loop: termination by construction (literal bound) 141func dg_st_loop(b: *u8, off: i64, st: *i64, sidx: i64) -> i64 { 142 let a: i64 = dg_rnd(st, 4) 143 let bound: i64 = 2 + dg_rnd(st, 9) 144 var o: i64 = dg_cat(b, off, " var i" as *u8) 145 o = dg_catn(b, o, sidx) 146 o = dg_cat(b, o, ": i64 = 0\n while i" as *u8) 147 o = dg_catn(b, o, sidx) 148 o = dg_cat(b, o, " < " as *u8) 149 o = dg_catn(b, o, bound) 150 o = dg_cat(b, o, " { " as *u8) 151 o = dg_catv(b, o, a) 152 o = dg_cat(b, o, " = " as *u8) 153 o = dg_catv(b, o, a) 154 o = dg_cat(b, o, " + 2; i" as *u8) 155 o = dg_catn(b, o, sidx) 156 o = dg_cat(b, o, " = i" as *u8) 157 o = dg_catn(b, o, sidx) 158 o = dg_cat(b, o, " + 1 }\n" as *u8) 159 return o 160} 161 162// whole program text into b; returns length 163func dg_program(b: *u8, st: *i64, idx: i64, max_stmts: i64) -> i64 { 164 var o: i64 = dg_cat(b, 0, "// generated corpus program idx=" as *u8) 165 o = dg_catn(b, o, idx) 166 o = dg_cat(b, o, " (nx_diff_gen, deterministic)\nimport \"nx_syscalls.nx\"\nfunc main() -> i64 {\n" as *u8) 167 var v: i64 = 0 168 while v < 4 { 169 o = dg_cat(b, o, " var " as *u8) 170 o = dg_catv(b, o, v) 171 o = dg_cat(b, o, ": i64 = " as *u8) 172 o = dg_catn(b, o, dg_rnd(st, 100)) 173 o = dg_cat(b, o, "\n" as *u8) 174 v = v + 1 175 } 176 var span: i64 = max_stmts - 3 177 if span < 1 { span = 1 } 178 let nst: i64 = 4 + dg_rnd(st, span) 179 var s: i64 = 0 180 while s < nst { 181 let kind: i64 = dg_rnd(st, 4) 182 if kind <= 1 { o = dg_st_arith(b, o, st) } 183 if kind == 2 { o = dg_st_branch(b, o, st) } 184 if kind == 3 { o = dg_st_loop(b, o, st, s) } 185 s = s + 1 186 if o > DG_MAGIC_2800 { s = nst } 187 } 188 o = dg_cat(b, o, " sys_exit((((v0 + v1) + v2) + v3) & 1)\n return 0\n}\n" as *u8) 189 return o 190} 191 192// write program file padded to DG_FILEPAD bytes (stale-tail killer) 193func dg_write(path: *u8, b: *u8, len: i64) -> i64 { 194 var o: i64 = len 195 while o < DG_FILEPAD { b[o] = 10 as u8; o = o + 1 } 196 let fd: i64 = sys_openat_wr(path, 0x1a4) 197 if fd < 0 { return 0 } 198 var off: i64 = 0 199 while off < DG_FILEPAD { 200 let w: i64 = sys_write(fd, b + off, DG_FILEPAD - off) 201 if w <= 0 { sys_close(fd); return 0 } 202 off = off + w 203 } 204 sys_close(fd) 205 return 1 206} 207 208// conf key=N reader (wd_conf_deadline shape, shared scan) 209func dg_conf(buf: *u8, n: i64, key: *u8, kl: i64, dflt: i64) -> i64 { 210 var i: i64 = 0 211 var at: i64 = 0 - 1 212 while i < n { 213 if i + kl <= n { 214 var k: i64 = 0 215 var hit: i64 = 1 216 while k < kl { 217 if buf[i + k] != key[k] { hit = 0; k = kl } else { k = k + 1 } 218 } 219 if hit == 1 { at = i + kl; i = n } 220 } 221 i = i + 1 222 } 223 if at < 0 { return dflt } 224 var v: i64 = 0 225 var any: i64 = 0 226 var go: i64 = 1 227 while go == 1 { 228 if at >= n { go = 0 } else { 229 let ch: i64 = buf[at] as i64 230 if ch >= 48 { 231 if ch <= 57 { v = v * 10 + (ch - 48); any = 1; at = at + 1 } else { go = 0 } 232 } else { go = 0 } 233 } 234 } 235 if any == 0 { return dflt } 236 return v 237} 238 239func main(argc: i64, argv: *i64) -> i64 { 240 var confp: *u8 = "knowledge/registry/diff_corpus.conf" as *u8 241 var prefix: *u8 = "_dgp" as *u8 242 var hashp: *u8 = "/tmp/_dg_hash.txt" as *u8 243 if argc >= 2 { confp = argv[1] as *u8 } 244 if argc >= 3 { prefix = argv[2] as *u8 } 245 if argc >= 4 { hashp = argv[3] as *u8 } 246 247 let cbuf: *u8 = sys_mmap(DG_MAGIC_4096) 248 var cn: i64 = 0 249 let cfd: i64 = sys_openat_rd(confp) 250 if cfd >= 0 { 251 var r: i64 = sys_read(cfd, cbuf, DG_MAGIC_4095) 252 while r > 0 { cn = cn + r; r = sys_read(cfd, cbuf + cn, DG_MAGIC_4095 - cn) } 253 sys_close(cfd) 254 } 255 let n: i64 = dg_conf(cbuf, cn, "n=" as *u8, 2, 200) 256 let seed: i64 = dg_conf(cbuf, cn, "seed=" as *u8, 5, DG_MAGIC_1106202601) 257 let mx: i64 = dg_conf(cbuf, cn, "max_stmts=" as *u8, 10, 12) 258 259 let st: *i64 = sys_mmap(16) as *i64 260 st[0] = seed & 0x7fffffff 261 let b: *u8 = sys_mmap(DG_BUFCAP) 262 let path: *u8 = sys_mmap(256) 263 var hash: i64 = DG_MAGIC_1469598103 264 var total: i64 = 0 265 var wrote: i64 = 0 266 var i: i64 = 0 267 while i < n { 268 let len: i64 = dg_program(b, st, i, mx) 269 var po: i64 = dg_cat(path, 0, "runtime/_hdl_build/" as *u8) 270 po = dg_cat(path, po, prefix) 271 po = dg_catn(path, po, i) 272 po = dg_cat(path, po, ".nx" as *u8) 273 path[po] = 0 as u8 274 if dg_write(path, b, len) == 1 { wrote = wrote + 1 } 275 var h: i64 = 0 276 while h < DG_FILEPAD { hash = (hash * 131 + (b[h] as i64)) & 0x7fffffffffff; h = h + 1 } 277 total = total + len 278 i = i + 1 279 } 280 281 let hf: i64 = sys_openat_wr(hashp, 0x1a4) 282 if hf >= 0 { 283 dg_fn(hf, hash) 284 dg_fp(hf, " \n" as *u8) 285 sys_close(hf) 286 } 287 288 let lfd: i64 = sys_openat_append("knowledge/status/diff_gen.log" as *u8, 0x1a4) 289 var verdict: *u8 = "GREEN" as *u8 290 var rc: i64 = 0 291 if wrote != n { verdict = "RED" as *u8; rc = 1 } 292 var p2: i64 = 0 293 while p2 < 2 { 294 var fd: i64 = 1 295 if p2 == 1 { fd = lfd } 296 if fd >= 0 { 297 dg_fp(fd, "DIFFGEN n=" as *u8); dg_fn(fd, n) 298 dg_fp(fd, " wrote=" as *u8); dg_fn(fd, wrote) 299 dg_fp(fd, " seed=" as *u8); dg_fn(fd, seed) 300 dg_fp(fd, " hash=" as *u8); dg_fn(fd, hash) 301 dg_fp(fd, " bytes=" as *u8); dg_fn(fd, total) 302 dg_fp(fd, " epoch=" as *u8); dg_fn(fd, sys_now_realtime_sec()) 303 dg_fp(fd, " verdict=" as *u8); dg_fp(fd, verdict) 304 dg_fp(fd, "\n" as *u8) 305 } 306 p2 = p2 + 1 307 } 308 if lfd >= 0 { sys_close(lfd) } 309 sys_exit(rc) 310 return rc 311}