code wiki / _hdl_build / nx_cand_build_run.nx
nx_cand_build_run.nx source
↩ module page · 101 lines · 5689 B
1// nx_cand_build_run.nx -- build a CANDIDATE sovereign compiler from current source and use it to
2// build+run a target module, WITHOUT swapping the live _offc/nx_cc_sovereign.elf. This is the
3// zero-risk way to exercise a NEW compiler intrinsic (here __mul256_wide): the live compiler that
4// ~7400 organs depend on is never touched; the candidate lives only at /tmp.
5// phase 1: live cc compiles runtime/nx_compile_x86.nx -> /tmp/candcc.s ; nxasm -> /tmp/candcc.elf
6// phase 2: candcc compiles runtime/<argv1>.nx -> /tmp/<argv1>.s ; nxasm -> /tmp/<argv1>.elf ; run it
7// Retry-guards nx_cc's empty/truncated-.s nondeterminism (same guard as nx_sov_build_run).
8// Usage: nx_cand_build_run <module-basename-in-runtime>. license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
11const CBR_MAGIC_65536: i64 = 65536
12
13const CBR_MIN_ASM: i64 = 128
14const CBR_RETRIES: i64 = 14
15const LIVE_CC: *u8 = "_offc/nx_cc_sovereign.elf"
16const ASM_TOOL: *u8 = "_offc/nxasm_x86_main.elf"
17const CAND_SRC: *u8 = "runtime/nx_compile_x86.nx"
18const CAND_S: *u8 = "/tmp/candcc.s"
19const CAND_CC: *u8 = "/tmp/candcc.elf"
20
21func cbr_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
22// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
23// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
24// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
25// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
26func cbr_putn(v: i64) -> i64 { nxi_out(v); return 0 }
27func cbr_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } return off + i }
28
29func cbr_run(path: *u8, argv: *i64, envp: *i64, redir_out: i64, redir_err: i64) -> i64 {
30 let pid: i64 = sys_fork()
31 if pid == 0 {
32 if redir_out >= 0 { sys_dup3(redir_out, 1, 0) }
33 if redir_err >= 0 { sys_dup3(redir_err, 2, 0) }
34 sys_execve(path, argv, envp); sys_exit(127)
35 }
36 let st: *i64 = sys_mmap(16) as *i64
37 sys_wait4(pid, st, 0)
38 let sig: i64 = st[0] & 0x7f
39 if sig != 0 { return 128 + sig }
40 return (st[0] >> 8) & 0xff
41}
42func cbr_filesize(path: *u8) -> i64 {
43 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 }
44 let buf: *u8 = sys_mmap(CBR_MAGIC_65536); var total: i64 = 0
45 var n: i64 = sys_read(fd, buf, CBR_MAGIC_65536); while n > 0 { total = total + n; n = sys_read(fd, buf, CBR_MAGIC_65536) }
46 sys_close(fd); return total
47}
48
49// compile src.nx with `compiler` -> sout (.s), assemble -> eout (.elf); retry-guarded. 1=ok 0=fail.
50func cbr_build(compiler: *u8, srcpath: *u8, sout: *u8, eout: *u8, envp: *i64, devnull: i64) -> i64 {
51 var tries: i64 = 0
52 while tries < CBR_RETRIES {
53 let sfd: i64 = sys_openat_wr(sout, 0x1a4)
54 let cc: *i64 = sys_mmap(8*4) as *i64
55 cc[0] = compiler as i64; cc[1] = srcpath as i64; cc[2] = 0
56 let rc_c: i64 = cbr_run(compiler, cc, envp, sfd, devnull)
57 sys_close(sfd)
58 if rc_c == 0 { if cbr_filesize(sout) > CBR_MIN_ASM {
59 let aa: *i64 = sys_mmap(8*4) as *i64
60 aa[0] = ASM_TOOL as i64; aa[1] = sout as i64; aa[2] = eout as i64; aa[3] = 0
61 let rc_a: i64 = cbr_run(ASM_TOOL, aa, envp, 0 - 1, 0 - 1)
62 if rc_a == 0 { return 1 }
63 } }
64 tries = tries + 1
65 }
66 return 0
67}
68
69func main(argc: i64, argv: *i64) -> i64 {
70 if argc < 2 { cbr_puts("usage: nx_cand_build_run <module-basename>\n" as *u8); return 2 }
71 let name: *u8 = argv[1] as *u8
72 let envp: *i64 = sys_mmap(8*4) as *i64
73 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
74 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
75
76 cbr_puts("[cand] phase1: building candidate compiler from " as *u8); cbr_puts(CAND_SRC); cbr_puts("\n" as *u8)
77 if cbr_build(LIVE_CC, CAND_SRC, CAND_S, CAND_CC, envp, devnull) == 0 {
78 cbr_puts("[cand] FAIL: candidate compiler did not build (source compile/asm error)\n" as *u8); sys_exit(3); return 3
79 }
80 cbr_puts("[cand] candidate compiler ready -> " as *u8); cbr_puts(CAND_CC); cbr_puts("\n" as *u8)
81
82 // resolve the target source: runtime/<name>.nx then runtime/_hdl_build/<name>.nx
83 let src: *u8 = sys_mmap(512); var o: i64 = 0
84 o = cbr_cat(src, 0, "runtime/" as *u8); o = cbr_cat(src, o, name); o = cbr_cat(src, o, ".nx" as *u8); src[o] = 0 as u8
85 let chk: i64 = sys_openat_rd(src)
86 if chk < 0 { o = cbr_cat(src, 0, "runtime/_hdl_build/" as *u8); o = cbr_cat(src, o, name); o = cbr_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 } else { sys_close(chk) }
87
88 let tsout: *u8 = sys_mmap(256); o = cbr_cat(tsout, 0, "/tmp/" as *u8); o = cbr_cat(tsout, o, name); o = cbr_cat(tsout, o, ".s" as *u8); tsout[o] = 0 as u8
89 let teout: *u8 = sys_mmap(256); o = cbr_cat(teout, 0, "/tmp/" as *u8); o = cbr_cat(teout, o, name); o = cbr_cat(teout, o, ".cand.elf" as *u8); teout[o] = 0 as u8
90
91 cbr_puts("[cand] phase2: building " as *u8); cbr_puts(name); cbr_puts(" with the candidate compiler\n" as *u8)
92 if cbr_build(CAND_CC, src, tsout, teout, envp, devnull) == 0 {
93 cbr_puts("[cand] FAIL: target did not build with the candidate compiler\n" as *u8); sys_exit(4); return 4
94 }
95 cbr_puts("[cand] running " as *u8); cbr_puts(teout); cbr_puts("\n" as *u8)
96 let rv: *i64 = sys_mmap(8*4) as *i64
97 rv[0] = teout as i64; rv[1] = 0
98 let rc: i64 = cbr_run(teout, rv, envp, 0 - 1, 0 - 1)
99 cbr_puts("[cand] target exit=" as *u8); cbr_putn(rc); cbr_puts("\n" as *u8)
100 sys_exit(rc); return rc
101}