nx_dom_oracle_gate.nx source
↩ module page · 316 lines · 11430 B
1// nx_dom_oracle_gate.nx -- BRUTE-FORCE DOMINANCE ORACLE for dom_fn.nx.
2//
3// The banked LICM awakening rung (nx_opt.nx DORMANT-COMPAT, 2026-06-10):
4// "Awakening rung = dominance brute-force oracle FIRST, then this load."
5// This gate IS that oracle. Definition-level ground truth: D dominates B iff
6// removing D makes B unreachable from entry. Compares that, pairwise, against
7// dom_compute_fn's idom chains over EVERY function of the FULL self-host
8// compiler source (the exact merge-heavy CFGs that broke the 06-10 awakening),
9// on the post-parse CFG AND the post-opt_run CFG (the shapes LICM actually
10// sees inside the fixpoint).
11//
12// Skips (reported, never silent): functions with any block n_preds > 3 (the
13// pred-truncation class -- opt_licm DECLINES these, so they are outside the
14// awakening's blast zone) and functions with n_blocks > DOR_MAX_B (brute cost).
15// NEGATIVE CONTROL: a deliberately corrupted idom entry must produce
16// mismatches -- proves the comparator can see a lie.
17// Verdict GREEN iff mismatches == 0 AND negctl fired. license_tier: ORIGINAL
18import "nx_syscalls.nx"
19import "nx_types.nx"
20import "nx_lex_kinds.nx"
21import "nx_outbuf.nx"
22import "nx_ir.nx"
23import "nx_tokenizer.nx"
24import "nx_parse.nx"
25import "nx_opt.nx"
26import "nx_ir_validate.nx"
27import "nx_import.nx"
28import "nx_gate_verdict.nx"
29
30const DOR_MAX_B: i64 = 256
31const DOR_EXPAND_CAP: i64 = 4194304
32
33func dor_w(s: *u8) -> i64 {
34 var n: i64 = 0
35 while s[n] != (0 as u8) { n = n + 1 }
36 sys_write(1, s, n)
37 return 0
38}
39func dor_wn(v: i64) -> i64 {
40 let t: *u8 = sys_mmap(32)
41 let o: *u8 = sys_mmap(32)
42 var m: i64 = v
43 var neg: i64 = 0
44 if m < 0 { neg = 1; m = 0 - m }
45 var k: i64 = 0
46 if m == 0 { t[0] = 48 as u8; k = 1 }
47 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
48 var w: i64 = 0
49 if neg == 1 { o[0] = 45 as u8; w = 1 }
50 var i: i64 = 0
51 while i < k { o[w + i] = t[k - 1 - i]; i = i + 1 }
52 sys_write(1, o, w + k)
53 return 0
54}
55
56// index of block pointer within f.blocks[]; -1 if absent.
57func dor_bidx(f: *Function, bb: *BasicBlock) -> i64 {
58 var i: i64 = 0
59 while i < f.n_blocks {
60 if block_at(f, i) == bb { return i }
61 i = i + 1
62 }
63 return 0 - 1
64}
65
66// Forward BFS from entry over succ0/succ1, skipping block `skip` (-1 = none).
67// Writes reach[i]=1 for visited. Iterative worklist (no recursion).
68func dor_reach(f: *Function, skip: i64, reach: *u8, wl: *i64) -> i64 {
69 let n: i64 = f.n_blocks
70 var i: i64 = 0
71 while i < n { reach[i] = 0 as u8; i = i + 1 }
72 let e: i64 = dor_bidx(f, f.entry)
73 if e < 0 { return 0 }
74 if e == skip { return 0 }
75 var head: i64 = 0
76 var tail: i64 = 0
77 wl[tail] = e
78 tail = tail + 1
79 reach[e] = 1 as u8
80 while head < tail {
81 let cur: i64 = wl[head]
82 head = head + 1
83 let b: *BasicBlock = block_at(f, cur)
84 let s0: *BasicBlock = b.succ0
85 if s0 != (0 as *BasicBlock) {
86 let i0: i64 = dor_bidx(f, s0)
87 if i0 >= 0 { if i0 != skip { if reach[i0] == 0 {
88 reach[i0] = 1 as u8
89 wl[tail] = i0
90 tail = tail + 1
91 } } }
92 }
93 let s1: *BasicBlock = b.succ1
94 if s1 != (0 as *BasicBlock) {
95 let i1: i64 = dor_bidx(f, s1)
96 if i1 >= 0 { if i1 != skip { if reach[i1] == 0 {
97 reach[i1] = 1 as u8
98 wl[tail] = i1
99 tail = tail + 1
100 } } }
101 }
102 }
103 return 0
104}
105
106// dominates-by-idom-chain using a PRE-INDEXED idom array (entry: idom==self).
107func dor_chain_dom(idom_idx: *i64, n: i64, d: i64, b: i64) -> i64 {
108 if d == b { return 1 }
109 var cur: i64 = b
110 var hops: i64 = 0
111 while hops < n {
112 let up: i64 = idom_idx[cur]
113 if up < 0 { return 0 }
114 if up == d { return 1 }
115 if up == cur { return 0 } // reached entry
116 cur = up
117 hops = hops + 1
118 }
119 return 0
120}
121
122// Check one function's CFG. Returns mismatch count; accumulates pair count
123// into cnt[0] and prints the first few mismatches.
124func dor_check_fn(f: *Function, fname: *u8, cnt: *i64, negctl: i64) -> i64 {
125 let n: i64 = f.n_blocks
126 if n < 2 { return 0 }
127 if n > DOR_MAX_B { cnt[1] = cnt[1] + 1; return 0 }
128 var tb: i64 = 0
129 while tb < n {
130 let tbb: *BasicBlock = block_at(f, tb)
131 if tbb.n_preds > 3 { cnt[2] = cnt[2] + 1; return 0 }
132 tb = tb + 1
133 }
134 let info_raw: *u8 = sys_mmap(128)
135 let info: *DomInfoFn = info_raw as *DomInfoFn
136 dom_compute_fn(f, info)
137 // idom as INDICES once (kills the O(n) pointer lookup inside pair loops).
138 let ii_raw: *u8 = sys_mmap(n * 8 + 16)
139 let idom_idx: *i64 = ii_raw as *i64
140 let ibase: i64 = info.idom as i64
141 var i: i64 = 0
142 while i < n {
143 let sl: *i64 = (ibase + i * 8) as *i64
144 let p: *BasicBlock = *sl as *BasicBlock
145 if p == (0 as *BasicBlock) { idom_idx[i] = 0 - 1 }
146 if p != (0 as *BasicBlock) { idom_idx[i] = dor_bidx(f, p) }
147 i = i + 1
148 }
149 // NEGCTL: corrupt one reachable non-entry idom to SELF (claims "I am a root"
150 // -> its dominators vanish from the chain -> brute must disagree).
151 let reach_raw: *u8 = sys_mmap(n + 16)
152 let reach: *u8 = reach_raw
153 let wl_raw: *u8 = sys_mmap(n * 8 + 16)
154 let wl: *i64 = wl_raw as *i64
155 dor_reach(f, 0 - 1, reach, wl)
156 let e: i64 = dor_bidx(f, f.entry)
157 if negctl == 1 {
158 // Corrupt an INTERMEDIATE dominator: a reachable block whose idom is a
159 // real NON-ENTRY block. Reparent it to entry (skipping its true idom) ->
160 // the pair (true_idom, vic) MUST mismatch (brute=1, chain misses it).
161 // Self-corruption on an entry-child never fires: entry is excluded from
162 // the D side of the pairwise check.
163 var vic: i64 = 0 - 1
164 var s: i64 = 0
165 while s < n {
166 if vic < 0 { if s != e { if reach[s] == 1 {
167 if idom_idx[s] != s { if idom_idx[s] != e { if idom_idx[s] >= 0 { vic = s } } }
168 } } }
169 s = s + 1
170 }
171 if vic >= 0 { idom_idx[vic] = e }
172 }
173 // Pairwise: for each reachable D != entry, brute = reach-without-D.
174 let rd_raw: *u8 = sys_mmap(n + 16)
175 let rd: *u8 = rd_raw
176 var mism: i64 = 0
177 var d: i64 = 0
178 while d < n {
179 if reach[d] == 1 { if d != e {
180 dor_reach(f, d, rd, wl)
181 var b: i64 = 0
182 while b < n {
183 if b != d { if reach[b] == 1 {
184 var brute: i64 = 0
185 if rd[b] == 0 { brute = 1 }
186 let claim: i64 = dor_chain_dom(idom_idx, n, d, b)
187 cnt[0] = cnt[0] + 1
188 if brute != claim {
189 mism = mism + 1
190 if mism <= 3 {
191 dor_w(" MISMATCH fn#" as *u8)
192 dor_wn(cnt[3])
193 dor_w(" D=" as *u8)
194 dor_wn(d)
195 dor_w(" B=" as *u8)
196 dor_wn(b)
197 dor_w(" brute=" as *u8)
198 dor_wn(brute)
199 dor_w(" dom_fn=" as *u8)
200 dor_wn(claim)
201 dor_w("\n" as *u8)
202 }
203 }
204 } }
205 b = b + 1
206 }
207 } }
208 d = d + 1
209 }
210 return mism
211}
212
213func main(argc: i64, argv: *i64) -> i64 {
214 dor_w("NX-DOM-ORACLE start\n" as *u8)
215 let expand_buf: *u8 = sys_mmap(DOR_EXPAND_CAP)
216 let ctx: *ExpandCtx = expand_ctx_new(expand_buf, DOR_EXPAND_CAP)
217 let rc: i64 = expand_imports(ctx, "runtime/nx_compile_x86.nx" as *u8)
218 if rc < 0 { dor_w("expand FAIL\n" as *u8); return 2 }
219 let op: *i64 = ctx.out_pos
220 let end: i64 = *op
221 expand_buf[end] = 0 as u8
222 let toks: *Tok = lex_source(expand_buf, 262144)
223 if toks == (0 as *Tok) { dor_w("lex FAIL\n" as *u8); return 3 }
224 let m: *Module = parse_module(toks, 0 as *Module)
225 if m == (0 as *Module) { dor_w("parse FAIL\n" as *u8); return 4 }
226 dor_w("parsed fns=" as *u8)
227 dor_wn(m.n_functions)
228 dor_w("\n" as *u8)
229
230 let cnt_raw: *u8 = sys_mmap(64)
231 let cnt: *i64 = cnt_raw as *i64 // [0]=pairs [1]=skip_big [2]=skip_pred
232 var mism_pp: i64 = 0
233 var mism_po: i64 = 0
234 var checked: i64 = 0
235
236 // PASS 1: post-parse CFGs.
237 var fi: i64 = 0
238 while fi < m.n_functions {
239 let fb: i64 = m.functions as i64
240 let f: *Function = (fb + fi * 176) as *Function
241 cnt[3] = fi
242 mism_pp = mism_pp + dor_check_fn(f, f.name_start as *u8, cnt, 0)
243 checked = checked + 1
244 fi = fi + 1
245 }
246 dor_w("post-parse: fns=" as *u8)
247 dor_wn(checked)
248 dor_w(" pairs=" as *u8)
249 dor_wn(cnt[0])
250 dor_w(" skip_big=" as *u8)
251 dor_wn(cnt[1])
252 dor_w(" skip_pred=" as *u8)
253 dor_wn(cnt[2])
254 dor_w(" mismatches=" as *u8)
255 dor_wn(mism_pp)
256 dor_w("\n" as *u8)
257
258 // PASS 2: post-opt CFGs (the shapes LICM sees). opt_run mutates in place.
259 // opt_run mutates in place, then cfg_rebuild_edges (the LICM fix) recomputes
260 // succ/pred from the terminators -- the EXACT graph LICM computes dominance
261 // on. This measures whether the rebuild makes post-opt dominance sound.
262 fi = 0
263 while fi < m.n_functions {
264 let fb2: i64 = m.functions as i64
265 let f2: *Function = (fb2 + fi * 176) as *Function
266 opt_run(f2)
267 cfg_rebuild_edges(f2)
268 cnt[3] = fi
269 mism_po = mism_po + dor_check_fn(f2, f2.name_start as *u8, cnt, 0)
270 fi = fi + 1
271 }
272 dor_w("post-opt: pairs_total=" as *u8)
273 dor_wn(cnt[0])
274 dor_w(" mismatches=" as *u8)
275 dor_wn(mism_po)
276 dor_w("\n" as *u8)
277
278 // NEGATIVE CONTROL on the first function with >= 3 blocks.
279 var neg_fired: i64 = 0
280 fi = 0
281 while fi < m.n_functions {
282 if neg_fired == 0 {
283 let fb3: i64 = m.functions as i64
284 let f3: *Function = (fb3 + fi * 176) as *Function
285 if f3.n_blocks >= 3 { if f3.n_blocks <= DOR_MAX_B {
286 var okpred: i64 = 1
287 var q: i64 = 0
288 while q < f3.n_blocks {
289 let qb: *BasicBlock = block_at(f3, q)
290 if qb.n_preds > 3 { okpred = 0 }
291 q = q + 1
292 }
293 if okpred == 1 {
294 let nm: i64 = dor_check_fn(f3, f3.name_start as *u8, cnt, 1)
295 if nm > 0 { neg_fired = 1 }
296 }
297 } }
298 }
299 fi = fi + 1
300 }
301 dor_w("negctl_fired=" as *u8)
302 dor_wn(neg_fired)
303 dor_w("\n" as *u8)
304
305 var green: i64 = 0
306 if mism_pp == 0 { if mism_po == 0 { if neg_fired == 1 { green = 1 } } }
307 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
308 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
309 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
310 let ctr__dry: *i64 = gv_ctr()
311 ctr__dry[0] = green
312 ctr__dry[1] = 1
313 let rc__dry: i64 = gv_verdict("DOM-ORACLE-GATE" as *u8, ctr__dry, "dom_fn matches brute-force dominance on the full self-host corpus, post-parse + post-opt; negctl fired)" as *u8)
314 sys_exit(rc__dry)
315 return rc__dry
316}