code wiki / _hdl_build / nx_codegen_exec.nx

nx_codegen_exec.nx source

↩ module page · 78 lines · 3222 B

1// nx_codegen_exec.nx -- shared build/run primitives for the team's codegen- 2// integration capabilities (the differential gate + the candidate self-host 3// verifier both build on this). Pure NishiLang fork/exec: invoke a compiler, link 4// with gcc, run an ELF, capture exit codes -- the sovereign build pipeline the 5// team drives to improve codegen WITHOUT a human running shell. DRY (Cardinal #15). 6 7import "nx_syscalls.nx" 8 9func gd_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 10func gd_emit(name: *u8, v: i64) -> i64 { 11 gd_puts(name) 12 let b: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 13 let t: *u8 = sys_mmap(28); var k: i64 = 0 14 if m == 0 { t[0] = 48; k = 1 } 15 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 16 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 17 b[k] = 10; sys_write(1, b, k + 1); return 0 18} 19 20// fork/exec argv (null-terminated *u8 ptr array). stdout -> out_path if non-null; 21// stderr -> /dev/null if quiet. A minimal PATH is passed so gcc finds cc1/as/ld; 22// the static compilers/ELFs ignore it. Returns the child's exit code (<0 on fork). 23func gd_exec(argv: *i64, out_path: *u8, quiet: i64) -> i64 { 24 let envp: *i64 = sys_mmap(16) as *i64 25 envp[0] = ("PATH=/usr/bin:/bin:/usr/local/bin" as *u8) as i64 26 envp[1] = 0 27 let pid: i64 = sys_fork() 28 if pid < 0 { return 0 - 1000 } 29 if pid == 0 { 30 if out_path != (0 as *u8) { 31 let fd: i64 = sys_openat_wr(out_path, 0x1a4) 32 if fd >= 0 { sys_dup3(fd, 1, 0); sys_close(fd) } 33 } 34 if quiet == 1 { 35 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 36 if dn >= 0 { sys_dup3(dn, 2, 0); sys_close(dn) } 37 } 38 sys_execve(argv[0] as *u8, argv, envp) 39 sys_exit(127) 40 } 41 let status: *i64 = sys_mmap(16) as *i64 42 status[0] = 0 43 sys_wait4(pid, status, 0) 44 return wait_exit_code(status[0]) 45} 46 47// compile <src> with <compiler> -> sout (.s) ; link -> eout (.elf). Returns 0 on a 48// clean build, or a negative sentinel (-1 compile, -2 link). Does NOT run. 49func gd_build(compiler: *u8, src: *u8, sout: *u8, eout: *u8) -> i64 { 50 let av: *i64 = sys_mmap(8 * 8) as *i64 51 av[0] = compiler as i64; av[1] = src as i64; av[2] = 0 52 if gd_exec(av, sout, 1) != 0 { return 0 - 1 } 53 av[0] = ("/usr/bin/gcc" as *u8) as i64 54 av[1] = ("-nostdlib" as *u8) as i64 55 av[2] = ("-no-pie" as *u8) as i64 56 av[3] = ("-static" as *u8) as i64 57 av[4] = sout as i64 58 av[5] = ("-o" as *u8) as i64 59 av[6] = eout as i64 60 av[7] = 0 61 if gd_exec(av, 0 as *u8, 1) != 0 { return 0 - 2 } 62 return 0 63} 64 65// run a built ELF, return its exit code (its self-verifying verdict). 66func gd_run(eout: *u8) -> i64 { 67 let av: *i64 = sys_mmap(16) as *i64 68 av[0] = eout as i64; av[1] = 0 69 return gd_exec(av, ("/dev/null" as *u8), 1) 70} 71 72// compile+link+run <src> with <compiler>: returns the run exit code, or a negative 73// sentinel on a pipeline failure. 74func gd_build_run(compiler: *u8, src: *u8, sout: *u8, eout: *u8) -> i64 { 75 let rc: i64 = gd_build(compiler, src, sout, eout) 76 if rc != 0 { return rc } 77 return gd_run(eout) 78}