nx_chkarith_jo_gate.nx
buildroot/runtime/nx_chkarith_jo_gate.nx
about
nx_chkarith_jo_gate.nx -- THE PROOF GATE for LN18 (x86ctx_ovf_fuse): checked integer arithmetic at
add+jo cost. Sibling of nx_bck_iv_gate, built from the same parts (nx_ccbuild_lib, gv_*): sources
assembled at RUNTIME under /tmp, compiled by the compiler named in argv[1] (there is NO default
compiler), the emitted ASSEMBLY as the oracle for "the long form is gone", and overflow WITNESSES
whose only protection is the trap the fuse was asked to keep.
WHAT THE FUSE MUST DO (measured on the /compare/lang receipt 2026-09-01: the daily mode cost 2.4x the
default build because every checked add was six instructions with spills): under --chkarith the LN1
shape r = a + b; x1 = a ^ r; x2 = b ^ r; a1 = x1 & x2; c = a1 < 0; br_cond c becomes `addq` + `jo`.
F1 a checked accumulate loop (sum 1..1000 = 500500, mod 251 = 6): the --chkarith assembly carries
jo/jno branches, the plain assembly carries none, and the checked build adds NO xorq to the plain
one (every checked add and sub site fused -- a single surviving long form would show as +2 xorq);
exit 6 under plain, --chkarith AND --mode=daily (the fuse composes with the full daily bundle).
F2 an add that overflows i64 at run time (MAX + argc): traps 72 under --chkarith, wraps to 91 plain.
F3 a sub that overflows (MIN - argc): traps 72 under --chkarith, wraps to 159 plain.
F4 __wrap_add(MAX, argc): the declared wrap-around intent stays exempt, exit 91 under --chkarith.
gv_bite ties the halves: the trap fires on F2 and stays silent on F1 under the same flag.
The overflow fixtures take their second operand from argc so no constant folds (the parser REFUSES a
constant overflow at parse time, which would test the wrong rung).
Products land in _build/ because NAS /tmp is mounted noexec (the sibling gate's measured lesson).
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 2 imports · 0 importers
imports: nx_gate_verdict.nxnx_ccbuild_lib.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 25 | const CJG_TRAP_OVERFLOW: i64 = 72 |
| 26 | const CJG_F1_EXIT: i64 = 6 // 500500 mod 251 |
| 27 | const CJG_WRAP_ADD_EXIT: i64 = 91 // (-2^63 mod 251 + 251) mod 251, the wrapped MAX+1 reduced |
| 28 | const CJG_WRAP_SUB_EXIT: i64 = 159 // (2^63-1) mod 251, the wrapped MIN-1 reduced |
| 29 | const CJG_MODE_644: i64 = 420 |
| 30 | const CJG_MODE_755: i64 = 493 |
| 31 | const CJG_WAIT_SIGMASK: i64 = 128 |
| 32 | const CJG_WAIT_CODESHIFT: i64 = 256 |
| 33 | const CJG_SCRATCH: i64 = 64 |
| 34 | const CJG_N_SOURCES: i64 = 4 |
| 35 | const CJG_MIN_FUSED: i64 = 2 // the F1 loop has two checked adds (the accumulate and the counter) |
functions
| 37 | func cjg_resolve_cc(argc: i64, argv: *i64, out: *i64) -> i64 called by 1: main |
| 45 | func cjg_exit_code(st: i64) -> i64 called by 1: main |
| 49 | func cjg_write_src(path: *u8, body: *u8) -> i64 called by 1: main |
| 59 | func cjg_run0(elf: *u8, out_path: *u8, envp: *i64, errfd: i64) -> i64 |
| 70 | func cjg_count(path: *u8, pat: *u8) -> i64 called by 1: main |
| 86 | func cjg_kv(label: *u8, v: i64) -> i64 |
| 91 | func main(argc: i64, argv: *i64) -> i64 |