cgen: B6-c2 call-arg family single peels fold into type_chase_named — 8 lines, loud-preserving

The exact B6-c2 set (rob b6 spec §2): :8402 (callee fn-type resolve cu),
:8435 (variadic slice param vsu), :8561/:8563 + :8577/:8579 (tagged
widen-detect pu/au pairs, arg-class + #38b MEMORY-class) + the two
LOUD-PRESERVING chases :8829 (float-struct rule-7 fatal st) and :8934
(#32 tuple-arg rule-7 fatal targ). Raw `->under` in cgen.c 49→41.

LOUD-PRESERVING discipline: the :8829/:8934 chases widen what the gate
SEES, never what it ACCEPTS. DESIGNED ACCEPTANCE NARROWING (ken b6
oracle c2): kb6_fsarg2 — a 1-level-alias float-struct from a non-ident
source previously DODGED the #271/#165 fatal via the single peel; cs
accepted and GP-passed it runtime-correct by self-consistent luck
(caller+callee agreed on the wrong transport, no SSE eightbyte). Post-
c2 cs louds with the pinned #271/#165 text. ww's cell was already loud
at its own alias-return bound (#272/#276/#277 class) — fsarg2_bound
pins BOTH texts per-stage (experr_ww). fsarg0 plain control stays loud
both stages. :8934 is WATCH-ONLY (alias tuple-args are checker-blocked
upstream, #86/#99): kb5_tuparg_c two-key cells verified unmoved
(cs ok/0 + ww ok/1).

TRAIN INVARIANT: cs-only; w6c_ww/ww_ww bit-identical to the 4cac1cb
baselines (b6bddc8e…/4e9ca874…). cs movers bounded to exactly
kb6_fsarg2 (run-cell ok/0→ERR, no asm emitted — zero run-row movers);
rest of the corpus + five mains byte-NEUTRAL; kw1_101/fill2/tuparg_c/
xampdef/amplen1 detectors unmoved; 989 ratchet zero flips. kb6_sarg /
kb6_strarg / kb6_fsarg (ident twin) latent byte-NEUTRAL per ken's
structural bound.

944_alias_cgen_b6_run grows 3→8 rows, 9→22 checks: fsarg0_loud_ctl +
fsarg2_bound (per-stage experr pins; row struct gains experr_ww for
two-site loud pairs) + fsarg_ident_ctl/sarg_2lvl/strarg_2lvl controls.
All 944-family suites green; sizelint 0.
This commit is contained in:
2026-06-06 03:51:34 +09:00
parent 1f14becdf3
commit 9659a0dfbe
2 changed files with 106 additions and 18 deletions

View File

@@ -8398,8 +8398,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
* its declared parameter type — needed to detect implicit
* widening of a concrete variant into a tagged-union slot. */
Type *callee_t = n->lhs ? n->lhs->type : NULL;
Type *cu = (callee_t && callee_t->kind == TY_NAMED) ?
callee_t->under : callee_t;
Type *cu = type_chase_named(callee_t);
Tparam *callee_params = (cu && cu->kind == TY_FN) ?
cu->params : NULL;
/* Hare-style variadic last param: gather N tail args into a
@@ -8431,8 +8430,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
argcount = nfixed + 1;
} else {
Type *vst = var_p->type;
Type *vsu = (vst && vst->kind == TY_NAMED)
? vst->under : vst;
Type *vsu = type_chase_named(vst);
Type *velem = (vsu && vsu->kind == TY_SLICE)
? vsu->sub : NULL;
int esz = (velem && velem->size)
@@ -8557,10 +8555,8 @@ cgexpr(Cg *c, Node *n, Local *locals)
Type *at = args[i] ? args[i]->type : NULL;
int psz = tagged_arg_size(p->type);
if (psz > 0) {
Type *pu = (p->type && p->type->kind == TY_NAMED)
? p->type->under : p->type;
Type *au = (at && at->kind == TY_NAMED)
? at->under : at;
Type *pu = type_chase_named(p->type);
Type *au = type_chase_named(at);
int same = (pu == au) || type_eq(p->type, at);
if (!same) {
widen[i] = 1;
@@ -8573,10 +8569,8 @@ cgexpr(Cg *c, Node *n, Local *locals)
int msz = tagged_memarg_size(p->type);
if (msz > 0) {
memarg[i] = msz;
Type *pu = (p->type && p->type->kind == TY_NAMED)
? p->type->under : p->type;
Type *au = (at && at->kind == TY_NAMED)
? at->under : at;
Type *pu = type_chase_named(p->type);
Type *au = type_chase_named(at);
int same = (pu == au) || type_eq(p->type, at);
if (!same) {
widen[i] = 1;
@@ -8824,9 +8818,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
* ≤16B struct with any float field; the wwstage
* tinfo mirror uses the same predicate). */
{
Type *st = args[i]->type;
if (st && st->kind == TY_NAMED)
st = st->under;
Type *st = type_chase_named(args[i]->type);
if (st && st->kind == TY_STRUCT
&& st->size <= 16) {
int f32;
@@ -8929,9 +8921,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
* pre-fix it fell to the scalar single-PUSHQ default
* and silently skewed every later arg register. */
if (tuparg_push == NULL) {
Type *targ = args[i]->type;
if (targ && targ->kind == TY_NAMED)
targ = targ->under;
Type *targ = type_chase_named(args[i]->type);
if (targ && targ->kind == TY_TUPLE)
fatal("#32: tuple arg from unsupported "
"source shape %d (call/ident/"