code wiki / _hdl_build / nx_alias_layout_gate.nx

nx_alias_layout_gate.nx source

↩ module page · 100 lines · 4537 B

1// nx_alias_layout_gate.nx -- MONITOR for the type-alias struct-layout parity class (seq521). 2// 3// THE CLASS: the C anchor (parse.c) resolves `type NAME = BASE` aliases; for a long time the 4// self-hosted parser did not, so a struct field typed with an alias fell through parse_type to the 5// TY_VOID size-0 placeholder. Every field of an aliased type then had size 0, later field offsets 6// collapsed onto each other, a pointer field landed at offset 0 and was overwritten by an int field, 7// and dereferencing that tiny integer segfaulted. It was found bits-up (NxMesh.verts read back as 8// the literal 4) and cost a SIGSEGV in nx_landmark_anatomy. 9// 10// WHY THIS FILE EXISTS: the artifact that proved seq521 -- nx_segfield_repro.nx -- only PRINTS. It 11// has no verdict, so no judge and no build driver can fail on it, and nothing guarded the class 12// afterwards. seq521 and seq715 were the SAME class (self-host parity gaps against the C anchor) and 13// one had been fixed while the other had not; nobody swept for siblings. This turns the probe into a 14// gate that the driver can reach, with the fn-pointer half deliberately left to nx_fnptr_call_gate 15// rather than duplicated here. 16// 17// DISCRIMINATING BY CONSTRUCTION: every tooth reads RAW i64 offsets off the struct base. That is 18// precisely what collapses under the defect, so a regressed compiler cannot make these pass. 19// 20// license_tier: ORIGINAL No hw writes (Rule 26). 21import "nx_syscalls.nx" 22import "nx_gate_verdict.nx" 23 24// Declared here rather than imported so the gate also exercises alias REGISTRATION itself. 25// Order matters: a chained alias resolves because names register in source order. 26type gi = i64 27type gi2 = gi 28 29struct AllA { a: gi, b: gi, c: gi } 30struct AthenP { n: gi, p: *AllA, w: gi } 31struct PthenA { p: *AllA, n: gi, w: gi } 32struct Chain { x: gi2, y: gi2 } 33 34const SBYTES: i64 = 64 35const GUARD_A: i64 = 11 36const GUARD_B: i64 = 22 37const GUARD_C: i64 = 33 38const GUARD_N: i64 = 7 39const CHAIN_X: i64 = 5 40const CHAIN_Y: i64 = 6 41 42func ret_alias() -> gi { return 77 } 43 44func main() -> i64 { 45 let ctr: *i64 = gv_ctr() 46 gv_head("nx_alias_layout_gate -- type-alias struct field layout (seq521 parity monitor)" as *u8) 47 48 // T1: an ALL-ALIAS struct must lay its fields out at 0/8/16. Under the defect every field 49 // collapsed to offset 0 and the last write won at all three slots. 50 let x: *AllA = sys_mmap(SBYTES) as *AllA 51 x.a = GUARD_A 52 x.b = GUARD_B 53 x.c = GUARD_C 54 let rx: *i64 = x as *i64 55 var t1: i64 = 0 56 if rx[0] == GUARD_A { if rx[1] == GUARD_B { if rx[2] == GUARD_C { t1 = 1 } } } 57 gv_check("T1 all-alias struct occupies distinct offsets 0/8/16" as *u8, t1, ctr) 58 59 // T2/T3: alias THEN pointer -- the shape that actually segfaulted. The pointer must not land 60 // on offset 0 and clobber the leading int, and must read back as the address stored. 61 let y: *AthenP = sys_mmap(SBYTES) as *AthenP 62 y.n = GUARD_N 63 y.p = x 64 let ry: *i64 = y as *i64 65 var t2: i64 = 0 66 if ry[0] == GUARD_N { t2 = 1 } 67 gv_check("T2 alias-then-pointer: the pointer does not land at offset 0" as *u8, t2, ctr) 68 var t3: i64 = 0 69 if (y.p as i64) == (x as i64) { t3 = 1 } 70 gv_check("T3 alias-then-pointer: the pointer field reads back the stored address" as *u8, t3, ctr) 71 72 // T4: pointer FIRST survived even under the defect, so it is the NEGATIVE CONTROL -- it proves 73 // the gate is exercising layout rather than trivially passing everything. 74 let z: *PthenA = sys_mmap(SBYTES) as *PthenA 75 z.p = x 76 z.n = 9 77 let rz: *i64 = z as *i64 78 var t4: i64 = 0 79 if rz[0] == (x as i64) { if rz[1] == 9 { t4 = 1 } } 80 gv_check("T4 pointer-first control: layout still correct (was the surviving case)" as *u8, t4, ctr) 81 82 // T5: a CHAINED alias (gi2 -> gi -> i64) must resolve to the concrete size too. 83 let c: *Chain = sys_mmap(SBYTES) as *Chain 84 c.x = CHAIN_X 85 c.y = CHAIN_Y 86 let rc: *i64 = c as *i64 87 var t5: i64 = 0 88 if rc[0] == CHAIN_X { if rc[1] == CHAIN_Y { t5 = 1 } } 89 gv_check("T5 chained alias resolves to the concrete size" as *u8, t5, ctr) 90 91 // T6: an alias as a RETURN type, the non-struct half of the same resolution path. 92 var t6: i64 = 0 93 if ret_alias() == 77 { t6 = 1 } 94 gv_check("T6 alias as a function return type" as *u8, t6, ctr) 95 96 let rc2: i64 = gv_verdict("ALIAS-LAYOUT-GATE" as *u8, ctr, 97 "alias field offsets, chained aliases, pointer-first control" as *u8) 98 sys_exit(rc2) 99 return rc2 100}