w6c/cgen: #61 alias-NAMED struct param classify — transitive chase at the ABI choke
A 2-level alias param (`type row = st; type st = struct{a,b,c}`) fell
through the single NAMED peel at every classify site, so BOTH ends of
the call moved one eightbyte of a multi-word struct: the caller's
node_isstructarg/node_isaggarg said scalar, the callee prologue spilled
ONLY DI, and s.b/s.c read 8(BP)/(BP) — saved-BP/return-address garbage.
SILENT runtime-wrong (F0 m5_arg/m8_arg1/m8b_arg1lit: cs exit 1, ww
correct, byte-id NO).
Route the four classify chokes through type_chase_named: struct_arg_size
+ aggarg_size (shared by caller push AND the size axes), struct_float_
class (the #165 SSE eightbyte leg), and the fn-prologue param classify
pu. Caller and callee key off the same helpers, so the pair cannot
half-land. cs converges to wwstage's already-correct asm — all probe
rows graduate to byte-id YES; bootstrap asm cmp-identical vs master
(2-level alias params unused in selfhost).
test: 944_alias_accept_run +5 rows — fwd-ref / lit-init / 40B
5-eightbyte aggarg leg / f64 struct_float_class leg, every row checking
the LAST field with distinct values, + base-named control. Mutation-
checked at 738d7f4: the four alias rows exit 1 (the silent-wrong
signature) and byte-id-diff there; 55/55 green here.
This commit is contained in:
@@ -558,8 +558,11 @@ localloadop(Type *t)
|
||||
static int
|
||||
struct_arg_size(Type *t)
|
||||
{
|
||||
if (t == NULL) return 0;
|
||||
if (t->kind == TY_NAMED) t = t->under;
|
||||
/* Transitive chase (#61): `type row = st; type st = struct` is two
|
||||
* NAMED layers — the single peel classified the param SCALAR, so
|
||||
* caller and callee both moved one eightbyte of a 3-word struct
|
||||
* (silent caller-frame garbage reads in the callee). */
|
||||
t = type_chase_named(t);
|
||||
if (t == NULL || t->kind != TY_STRUCT) return 0;
|
||||
return (int)t->size;
|
||||
}
|
||||
@@ -580,8 +583,8 @@ struct_arg_size(Type *t)
|
||||
static int
|
||||
struct_float_class(Type *t, int *cls)
|
||||
{
|
||||
if (t == NULL) return 0;
|
||||
if (t->kind == TY_NAMED) t = t->under;
|
||||
/* Transitive chase (#61) — same classify choke as struct_arg_size. */
|
||||
t = type_chase_named(t);
|
||||
if (t == NULL || t->kind != TY_STRUCT) return 0;
|
||||
int sz = (int)t->size;
|
||||
if (sz <= 0 || sz > 16) return 0;
|
||||
@@ -777,8 +780,8 @@ node_isstructarg(Node *n)
|
||||
static int
|
||||
aggarg_size(Type *t)
|
||||
{
|
||||
if (t == NULL) return 0;
|
||||
if (t->kind == TY_NAMED) t = t->under;
|
||||
/* Transitive chase (#61) — same classify choke as struct_arg_size. */
|
||||
t = type_chase_named(t);
|
||||
if (t == NULL) return 0;
|
||||
if (t->kind == TY_STRUCT || t->kind == TY_ARRAY)
|
||||
return (int)t->size;
|
||||
@@ -13837,7 +13840,10 @@ cgfn(Cg *c, FILE *out, Node *fn)
|
||||
continue;
|
||||
}
|
||||
Type *pt = tp ? tp->type : NULL;
|
||||
Type *pu = (pt && pt->kind == TY_NAMED) ? pt->under : pt;
|
||||
/* Transitive chase (#61): the callee-side classify twin of
|
||||
* struct_arg_size/aggarg_size — a 2-level alias param fell to
|
||||
* the scalar arm and spilled ONLY DI. */
|
||||
Type *pu = type_chase_named(pt);
|
||||
int slice = (pu && pu->kind == TY_SLICE);
|
||||
int is_str = type_isstr(pt);
|
||||
int is_struct = pu && pu->kind == TY_STRUCT && pu->size <= 16;
|
||||
|
||||
Reference in New Issue
Block a user