nx_chkarith_gate.nx source
↩ module page · 169 lines · 8729 B
1// nx_chkarith_gate.nx -- GATE for LN1 checked integer arithmetic (lang.plan rung LN1, symbol
2// chk_add_overflow). The rung's done-rule: i64 add and mul trap or refuse on overflow under a
3// declared mode (--chkarith); an overflowing add TRAPS; an in-range program is byte-identical
4// to today under the default (nothing is emitted unless the flag is on -- the equivalence net
5// nx_cc_equiv_gate is the byte ruler for that half, this gate is the behaviour ruler).
6// Subjects: the toolchain compiler (argv[1], default the live builder) + runtime/nx_checked_arith.nx
7// + runtime/nx_checked_arith_const.nx.
8//
9// Driver = nx_ccgate_lib (the ONE compiler-gate driver, extracted from the LN3 gate): data captures in
10// /tmp/nxchk/, RUNNABLES under _build/ (NAS /tmp is noexec), per-pid paths, phase exit codes PRINTED
11// before the teeth.
12//
13// Usage: nx_chkarith_gate [compiler_elf] (CWD = the tree root, like nx_cc_equiv_gate)
14// license_tier: ORIGINAL No hw writes (Rule 26).
15import "nx_syscalls.nx"
16import "nx_gate_verdict.nx"
17import "nx_ccgate_lib.nx"
18
19const CG_TRAP: i64 = 72 // NX_TRAP_OVERFLOW -- the injected trap's exit_group code
20
21func main(argc: i64, argv: *i64) -> i64 {
22 var cc: *u8 = "_offc/nx_cc_sovereign.elf\x00"
23 if argc >= 2 { cc = argv[1] as *u8 }
24 let CG_FLAG_CHKARITH: *u8 = "--chkarith\x00"
25 ccg_anchor_root()
26 sys_mkdir("/tmp/nxchk\x00" as *u8, CCG_MODE_X)
27 let pid: i64 = ccg_pid()
28
29 let p_ds: *u8 = ccg_path("/tmp/nxchk/d_\x00" as *u8, pid, ".s\x00" as *u8)
30 let p_de: *u8 = ccg_path("/tmp/nxchk/d_\x00" as *u8, pid, ".err\x00" as *u8)
31 let p_delf: *u8 = ccg_path("_build/nxchk_d_\x00" as *u8, pid, ".elf\x00" as *u8)
32 let p_cs: *u8 = ccg_path("/tmp/nxchk/c_\x00" as *u8, pid, ".s\x00" as *u8)
33 let p_ce: *u8 = ccg_path("/tmp/nxchk/c_\x00" as *u8, pid, ".err\x00" as *u8)
34 let p_celf: *u8 = ccg_path("_build/nxchk_c_\x00" as *u8, pid, ".elf\x00" as *u8)
35 let p_kds: *u8 = ccg_path("/tmp/nxchk/kd_\x00" as *u8, pid, ".s\x00" as *u8)
36 let p_kde: *u8 = ccg_path("/tmp/nxchk/kd_\x00" as *u8, pid, ".err\x00" as *u8)
37 let p_kdelf: *u8 = ccg_path("_build/nxchk_kd_\x00" as *u8, pid, ".elf\x00" as *u8)
38 let p_kcs: *u8 = ccg_path("/tmp/nxchk/kc_\x00" as *u8, pid, ".s\x00" as *u8)
39 let p_kce: *u8 = ccg_path("/tmp/nxchk/kc_\x00" as *u8, pid, ".err\x00" as *u8)
40 let p_kcelf: *u8 = ccg_path("_build/nxchk_kc_\x00" as *u8, pid, ".elf\x00" as *u8)
41 let p_asm: *u8 = ccg_path("_build/nxchk_asm_\x00" as *u8, pid, ".elf\x00" as *u8)
42 let p_wds: *u8 = ccg_path("/tmp/nxchk/wd_\x00" as *u8, pid, ".s\x00" as *u8)
43 let p_wde: *u8 = ccg_path("/tmp/nxchk/wd_\x00" as *u8, pid, ".err\x00" as *u8)
44 let p_wdelf: *u8 = ccg_path("_build/nxchk_wd_\x00" as *u8, pid, ".elf\x00" as *u8)
45 let p_wks: *u8 = ccg_path("/tmp/nxchk/wk_\x00" as *u8, pid, ".s\x00" as *u8)
46 let p_wke: *u8 = ccg_path("/tmp/nxchk/wk_\x00" as *u8, pid, ".err\x00" as *u8)
47 let p_wkelf: *u8 = ccg_path("_build/nxchk_wk_\x00" as *u8, pid, ".elf\x00" as *u8)
48
49 let ctr: *i64 = gv_ctr()
50 gv_head("=== nx_chkarith_gate -- LN1 checked integer arithmetic: --chkarith traps i64 + - * overflow (72), accepts in-range, exempts __wrap_*, refuses const overflow at compile time ===" as *u8)
51
52 let fix: *u8 = "runtime/nx_checked_arith.nx\x00"
53 let cfx: *u8 = "runtime/nx_checked_arith_const.nx\x00"
54 let wfx: *u8 = "runtime/nx_checked_arith_wrap.nx\x00"
55
56 // -- default-mode builds: the hazard record (everything wraps and survives) --
57 let bd: i64 = ccg_build(cc, 0 as *u8, fix, p_ds, p_delf, p_de, p_asm)
58 var t1: i64 = 0
59 if bd == 0 { t1 = 1 }
60 gv_check("T1 fixture-compiles-under-default (organ is a normal citizen of the tree)" as *u8, t1, ctr)
61 var d_ok: i64 = 0 - 1
62 var d_add: i64 = 0 - 1
63 var d_sub: i64 = 0 - 1
64 var d_mul: i64 = 0 - 1
65 var d_mm: i64 = 0 - 1
66 if bd == 0 {
67 d_ok = ccg_phase(p_delf, "ok\x00" as *u8)
68 d_add = ccg_phase(p_delf, "add\x00" as *u8)
69 d_sub = ccg_phase(p_delf, "sub\x00" as *u8)
70 d_mul = ccg_phase(p_delf, "mul\x00" as *u8)
71 d_mm = ccg_phase(p_delf, "mulmin\x00" as *u8)
72 }
73 // wrap-intrinsic witness, default mode -- its OWN build: a pre-LN1 compiler has no __wrap_*,
74 // and keeping it out of the main fixture is what makes the bite attributable tooth by tooth.
75 let bw: i64 = ccg_build(cc, 0 as *u8, wfx, p_wds, p_wdelf, p_wde, p_asm)
76 var d_wr: i64 = 0 - 1
77 if bw == 0 { d_wr = ccg_phase(p_wdelf, "x\x00" as *u8) }
78 ccg_val("d_build_rc" as *u8, bd)
79 ccg_val("w_build_rc" as *u8, bw)
80 ccg_val("d_ok_exit" as *u8, d_ok)
81 ccg_val("d_add_exit" as *u8, d_add)
82 ccg_val("d_sub_exit" as *u8, d_sub)
83 ccg_val("d_mul_exit" as *u8, d_mul)
84 ccg_val("d_mulmin_exit" as *u8, d_mm)
85 ccg_val("d_wrap_exit" as *u8, d_wr)
86 var t2: i64 = 0
87 if d_ok == 0 { t2 = 1 }
88 gv_check("T2 default-inrange-control-exit0" as *u8, t2, ctr)
89 var t3: i64 = 0
90 if d_add == 0 { t3 = 1 }
91 gv_check("T3 neg-control-default-ADD-wraps-and-survives (anti-vacuity: the add T9 must trap demonstrably executes and wraps to MIN)" as *u8, t3, ctr)
92 var t4: i64 = 0
93 if d_sub == 0 { t4 = 1 }
94 gv_check("T4 neg-control-default-SUB-wraps-and-survives" as *u8, t4, ctr)
95 var t5: i64 = 0
96 if d_mul == 0 { t5 = 1 }
97 gv_check("T5 neg-control-default-MUL-wraps-to-zero-and-survives" as *u8, t5, ctr)
98 var t6: i64 = 0
99 if d_mm == 0 { t6 = 1 }
100 gv_check("T6 neg-control-default-MIN-times-minus1-wraps-and-survives" as *u8, t6, ctr)
101 var t7: i64 = 0
102 if d_wr == 0 { t7 = 1 }
103 gv_check("T7 default-wrap-intrinsics-reproduce-wrapped-values" as *u8, t7, ctr)
104
105 // -- chkarith-mode builds --
106 let bk: i64 = ccg_build(cc, CG_FLAG_CHKARITH, fix, p_kds, p_kdelf, p_kde, p_asm)
107 var t8: i64 = 0
108 if bk == 0 { t8 = 1 }
109 gv_check("T8 fixture-compiles-under-chkarith (runtime legs are legal source either mode)" as *u8, t8, ctr)
110 var k_ok: i64 = 0 - 1
111 var k_add: i64 = 0 - 1
112 var k_sub: i64 = 0 - 1
113 var k_mul: i64 = 0 - 1
114 var k_mm: i64 = 0 - 1
115 if bk == 0 {
116 k_ok = ccg_phase(p_kdelf, "ok\x00" as *u8)
117 k_add = ccg_phase(p_kdelf, "add\x00" as *u8)
118 k_sub = ccg_phase(p_kdelf, "sub\x00" as *u8)
119 k_mul = ccg_phase(p_kdelf, "mul\x00" as *u8)
120 k_mm = ccg_phase(p_kdelf, "mulmin\x00" as *u8)
121 }
122 let bwk: i64 = ccg_build(cc, CG_FLAG_CHKARITH, wfx, p_wks, p_wkelf, p_wke, p_asm)
123 var k_wr: i64 = 0 - 1
124 if bwk == 0 { k_wr = ccg_phase(p_wkelf, "x\x00" as *u8) }
125 ccg_val("k_build_rc" as *u8, bk)
126 ccg_val("wk_build_rc" as *u8, bwk)
127 ccg_val("k_ok_exit" as *u8, k_ok)
128 ccg_val("k_add_exit" as *u8, k_add)
129 ccg_val("k_sub_exit" as *u8, k_sub)
130 ccg_val("k_mul_exit" as *u8, k_mul)
131 ccg_val("k_mulmin_exit" as *u8, k_mm)
132 ccg_val("k_wrap_exit" as *u8, k_wr)
133 var t9: i64 = 0
134 if k_ok == 0 { t9 = 1 }
135 gv_check("T9 chkarith-inrange-control-exit0 (a deny mode that refuses everything fails HERE; every checker branch taken in-range in one program)" as *u8, t9, ctr)
136 var t10: i64 = 0
137 if k_add == CG_TRAP { t10 = 1 }
138 gv_check("T10 chkarith-ADD-overflow-traps-72 (CWE-190, the rung's done-rule)" as *u8, t10, ctr)
139 var t11: i64 = 0
140 if k_sub == CG_TRAP { t11 = 1 }
141 gv_check("T11 chkarith-SUB-overflow-traps-72" as *u8, t11, ctr)
142 var t12: i64 = 0
143 if k_mul == CG_TRAP { t12 = 1 }
144 gv_check("T12 chkarith-MUL-overflow-traps-72" as *u8, t12, ctr)
145 var t13: i64 = 0
146 if k_mm == CG_TRAP { t13 = 1 }
147 gv_check("T13 chkarith-MIN-times-minus1-traps-72-not-SIGFPE (the checker's own division is branched around)" as *u8, t13, ctr)
148 var t14: i64 = 0
149 if k_wr == 0 { t14 = 1 }
150 gv_check("T14 chkarith-wrap-intrinsics-exempt-exit0 (__wrap_add/sub/mul do not trap)" as *u8, t14, ctr)
151
152 // -- compile-time leg --
153 let cd: i64 = ccg_build(cc, 0 as *u8, cfx, p_cs, p_celf, p_ce, p_asm)
154 var t15: i64 = 0
155 if cd == 0 { t15 = 1 }
156 gv_check("T15 neg-control-const-overflow-compiles-under-default (the hazard record still builds)" as *u8, t15, ctr)
157 let ck: i64 = ccg_build(cc, CG_FLAG_CHKARITH, cfx, p_kcs, p_kcelf, p_kce, p_asm)
158 ccg_val("cd_build_rc" as *u8, cd)
159 ccg_val("ck_build_rc" as *u8, ck)
160 var t16: i64 = 0
161 if ck != 0 { t16 = 1 }
162 gv_check("T16 chkarith-const-overflow-refused-at-compile-time" as *u8, t16, ctr)
163 let t17: i64 = ccg_file_has(p_kce, "capability=checked-arith-const-overflow\x00" as *u8)
164 gv_check("T17 refusal-names-the-checked-arith-rule (not some other error wearing the refusal)" as *u8, t17, ctr)
165
166 let rc: i64 = gv_verdict("CHKARITH-LN1" as *u8, ctr, "chkarith declared mode" as *u8)
167 sys_exit(rc)
168 return rc
169}