code wiki / _hdl_build / nx_ccdiag.nx
nx_ccdiag.nx source
↩ module page · 69 lines · 4619 B
1// nx_ccdiag.nx -- ONE-STEP build diagnostic (<10s): why did `nx_sov_build_run <name>` fail with "empty .s"?
2// The runner MUTES nx_cc's stderr (2>/dev/null) + retries 12x, so a plain source error (undefined function,
3// parse error, arg-count) surfaces only as a mysterious "COMPILE-FAIL (empty .s after retries)" -- which cost a
4// ~15-build blind hunt. This tool runs the SAME sovereign compiler on the SAME source with stderr VISIBLE, once,
5// and prints the exit code + .s size + the real diagnostic line. Eats the debt: turn opaque empty-.s into the
6// actual cause in one look. Usage: nx_ccdiag <module-name> license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
9const K_MAGIC_65536: i64 = 65536
10
11func cd_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
12// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
13// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
14// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
15// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
16func cd_putn(v: i64) -> i64 { nxi_out(v); return 0 }
17func cd_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){d[o+i]=s[i]; i=i+1} return o+i }
18func cd_exists(p: *u8) -> i64 { let fd: i64 = sys_openat_rd(p); if fd < 0 { return 0 } sys_close(fd); return 1 }
19func cd_filesize(p: *u8) -> i64 {
20 let fd: i64 = sys_openat_rd(p); if fd < 0 { return 0 }
21 let buf: *u8 = sys_mmap(K_MAGIC_65536); var tot: i64 = 0
22 var r: i64 = sys_read(fd, buf, K_MAGIC_65536)
23 while r > 0 { tot = tot + r; r = sys_read(fd, buf, K_MAGIC_65536) }
24 sys_close(fd); return tot
25}
26// fork+execve the compiler: stdout -> the .s fd; stderr LEFT VISIBLE (inherited fd 2). returns exit code.
27func cd_run_cc(cc: *u8, src: *u8, sfd: i64) -> i64 {
28 let pid: i64 = sys_fork()
29 if pid == 0 {
30 if sfd >= 0 { sys_dup3(sfd, 1, 0) } // stdout -> .s (stderr fd2 UNTOUCHED = visible)
31 let argv: *i64 = sys_mmap(8 * 4) as *i64
32 argv[0] = cc as i64; argv[1] = src as i64; argv[2] = 0
33 let envp: *i64 = sys_mmap(16) as *i64; envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
34 sys_execve(cc, argv, envp)
35 sys_exit(127)
36 }
37 let st: *i64 = sys_mmap(16) as *i64
38 sys_wait4(pid, st, 0)
39 let sig: i64 = st[0] & 0x7f
40 if sig != 0 { return 128 + sig }
41 return (st[0] >> 8) & 0xff
42}
43
44func main(argc: i64, argv: *i64) -> i64 {
45 if argc < 2 { cd_puts("usage: nx_ccdiag <module-name>\n" as *u8); sys_exit(2); return 2 }
46 let name: *u8 = argv[1] as *u8
47 // resolve the source the same way nx_sov_build_run does
48 let src: *u8 = sys_mmap(512)
49 var o: i64 = cd_cat(src, 0, "runtime/_hdl_build/" as *u8); o = cd_cat(src, o, name); o = cd_cat(src, o, ".nx" as *u8); src[o] = 0 as u8
50 if cd_exists(src) == 0 {
51 o = cd_cat(src, 0, "runtime/" as *u8); o = cd_cat(src, o, name); o = cd_cat(src, o, ".nx" as *u8); src[o] = 0 as u8
52 if cd_exists(src) == 0 {
53 o = cd_cat(src, 0, "nxasm/" as *u8); o = cd_cat(src, o, name); o = cd_cat(src, o, ".nx" as *u8); src[o] = 0 as u8
54 if cd_exists(src) == 0 { cd_puts("nx_ccdiag: SOURCE-NOT-FOUND for " as *u8); cd_puts(name); cd_puts(" (probed runtime/_hdl_build/, runtime/, nxasm/)\n" as *u8); sys_exit(3); return 3 }
55 }
56 }
57 let spath: *u8 = sys_mmap(512)
58 o = cd_cat(spath, 0, "/tmp/ccdiag_" as *u8); o = cd_cat(spath, o, name); o = cd_cat(spath, o, ".s" as *u8); spath[o] = 0 as u8
59
60 cd_puts("=== nx_ccdiag: " as *u8); cd_puts(src); cd_puts(" (nx_cc_sovereign, stderr VISIBLE below) ===\n" as *u8)
61 let sfd: i64 = sys_openat_wr(spath, 0x1a4) // O_CREAT|O_WRONLY|O_TRUNC -> fresh .s, never a stale mask
62 let rc: i64 = cd_run_cc("_offc/nx_cc_sovereign.elf" as *u8, src, sfd)
63 sys_close(sfd)
64 let sz: i64 = cd_filesize(spath)
65 cd_puts("--- nx_cc exit=" as *u8); cd_putn(rc); cd_puts(" .s bytes=" as *u8); cd_putn(sz); cd_puts(" ---\n" as *u8)
66 if sz > 128 { if rc == 0 { cd_puts("VERDICT: .s produced OK -> the source COMPILES; any failure is downstream (nxasm/link) or the known nondeterministic-empty (retry).\n" as *u8); sys_exit(0); return 0 } }
67 cd_puts("VERDICT: EMPTY/short .s -> the REAL cause is the compiler message printed ABOVE (undefined function / parse error / arg-count). Fix the source; it is NOT a mysterious codegen crash.\n" as *u8)
68 sys_exit(0); return 0
69}