nx_fnptr_arity_probe.nx
buildroot/runtime/nx_fnptr_arity_probe.nx
about
nx_fnptr_arity_probe.nx -- ARITY PROBE for struct-field function pointers.
The struct fn-ptr postfix-call fix (2026-05-19) was smoke-proven at arity 0/1/2/3 only. An OOP
vtable with a real signature needs more: a describe method is (self, gray, rgb, w, h, out) = SIX
arguments, which is exactly where the System V AMD64 integer argument registers run out
(rdi, rsi, rdx, rcx, r8, r9). An INDIRECT call must also materialise the callee address in a
register, so if the code generator picks one of those six the highest argument is clobbered --
a failure mode a direct call can never exhibit, and one that produces WRONG VALUES rather than a
crash or a compile error. This probe walks arity 3..8 through a struct field and prints the
arithmetic each callee performs on its arguments, so a clobbered slot is visible as a wrong sum
rather than inferred.
license_tier: ORIGINAL
dependencies 1 imports · 0 importers
imports: syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 23 | struct Probe |
consts
| 14 | const PROBE_MAGIC_10000: i64 = 10000 |
| 15 | const PROBE_MAGIC_100000: i64 = 100000 |
| 16 | const PROBE_MAGIC_1241: i64 = 1241 |
| 17 | const PROBE_MAGIC_12352: i64 = 12352 |
| 18 | const PROBE_MAGIC_123463: i64 = 123463 |
| 31 | const PROBE_BYTES: i64 = 48 |
functions
| 20 | func p_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 |
| 21 | func p_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 |
| 33 | func imp3(p: *Probe, a: i64, b: i64) -> i64 { return p.tag + a * 10 + b } |
| 34 | func imp4(p: *Probe, a: i64, b: i64, c: i64) -> i64 { return p.tag + a * 100 + b * 10 + c } |
| 35 | func imp5(p: *Probe, a: i64, b: i64, c: i64, d: i64) -> i64 { return p.tag + a * 1000 + b * 100 + c * 10 + d } |
| 36 | func imp6(p: *Probe, a: i64, b: i64, c: i64, d: i64, e: i64) -> i64 { return p.tag + a * PROBE_MAGIC_10000 + b * 1000 + c * 100 + d * 10 + e } called by 1: main |
| 37 | func imp7(p: *Probe, a: i64, b: i64, c: i64, d: i64, e: i64, f: i64) -> i64 { return p.tag + a * PROBE_MAGIC_100000 + b * PROBE_MAGIC_10000 + c * 1000 + d * 100 + e * 10 + f } |
| 39 | func main() -> i64 |