code wiki / (root) / nx_fnptr_slot_probe.nx

nx_fnptr_slot_probe.nx

buildroot/runtime/nx_fnptr_slot_probe.nx

3602 B82 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind probetopic fnptr
docsdependenciesstructsconstsfunctions

about

nx_fnptr_slot_probe.nx -- DECISIVE probe: does a struct with MORE THAN ONE function-pointer field dispatch to the right slot? The arity probe showed every struct-field fn-ptr call returning garbage while the same callees invoked directly (or through a let-copied local) return the right answer. Two hypotheses survive: H1 the indirect call-site mangles ARGUMENTS (arity/register related), or H2 the FIELD OFFSETS of fn-ptr-typed struct members collapse, so every vtable slot aliases and a call lands in whichever function was assigned last. H2 would be far more serious: it silently breaks every multi-method vtable in the tree. This probe discriminates them with ZERO argument passing. Five nullary functions, each returning a unique constant, stored in five separate fields. If each slot returns its own constant, offsets are fine and the fault is in argument passing. If they all return the SAME constant, the fields alias. license_tier: ORIGINAL

dependencies 1 imports · 0 importers

syscalls.nx nx_fnptr_slot_probe.nx

imports: syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main q_puts q_num

structs

26struct Slots

consts

35const SLOTS_BYTES: i64 = 56

functions

17func q_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
called by 1: main
18func q_num(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }; let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = (48 as u8); k = 1 }; while m > 0 { t[k] = ((48 + (m % 10)) as u8); m = m / 10; k = k + 1 }; var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }; sys_write(1, bb, k); return 0 }
called by 1: main
20func ret11() -> i64 { return 11 }
21func ret22() -> i64 { return 22 }
22func ret33() -> i64 { return 33 }
23func ret44() -> i64 { return 44 }
24func ret55() -> i64 { return 55 }
37func main() -> i64
calls 2: q_putsq_num