cgen: resolve local fn-ptr callees for variadic arg prep

The wwstage variadic call classification was name-keyed: a fn-ptr
FIELD call whose local base shadowed the current module name
(lib/log's log.println(log, args...)) picked the module fn's
signature — nfixed off by one, the fixed arg boxed into the gather,
the spread emitted as zeros — and a no-collision fn-ptr callee missed
the registry entirely, leaking the raw N_SPREAD as a single $0 word
(SIGSEGV / exit 255 in 8 of 11 logtest tests on the wwstage leg).
fnptrcalleetfn resolves a local fn-ptr callee (bare local or struct
field) to its N_TFN once, shared by the CALL-target choice,
callee_variadic_param (with the []T wrap registry params get from
installparams), calleecvariadic, and the widening param lookup, so
target and arg prep can never disagree. Graduates the #59.8 logtest
pin — DATABYTEID_DIVERGED-era M_DIVERGE count is now zero.
This commit is contained in:
2026-08-08 01:07:23 +09:00
parent c18005d833
commit 3f7452814b
5 changed files with 167 additions and 51 deletions

View File

@@ -169,8 +169,17 @@ static const struct ent ents[] = {
.mode = M_ID, .cite = "#59.5 graduated by the stamp-keyed recognizers" },
/* #59.6 fmt graduated to M_ID above (#129 fix) */
/* #59.7 siphash graduated to M_ID above (#61 fix) */
/* #59.8 graduated: the wwstage variadic call classification was
* name-keyed — a local fn-ptr field callee whose base shadowed the
* current module name (lib/log's `log.println(log, args...)`)
* picked the module fn's signature (nfixed off by one; the fixed
* arg boxed into the gather, the spread emitted as zeros), and a
* no-collision fn-ptr callee missed entirely (raw N_SPREAD leaked
* as one $0 word). fnptrcalleetfn now resolves local fn-ptr
* callees for CALL target and arg prep alike. Runtime pin:
* r598_fnptr_field_variadic. */
{ .fixture = "lib/log/logtest.ww",
.mode = M_DIVERGE, .cite = "#59.8" },
.mode = M_ID, .cite = "#59.8 graduated by the local-first callee resolver" },
/* #59.9 graduated: the wwstage checker never typed an N_BIN operand
* of `as`, so an enum OR-fold reached cgen unstamped and lowered as
* a phantom tagged assert (unconditional exit 1). checkisas now