wcc: #99 alias-of-tuple — chase TY_NAMED in tuple coercion (cstage) + param spill (wwstage)
type pair = (int, int); let x: pair = (3, 4) -- an alias of a tuple initialized from an untyped literal, and passing such a value to a fn -- was a both-stage bug, mirror-twins of the same TY_NAMED-not-chased root: cstage CHECKER over-rejected the init (not assignable to declared pair): type.c's tuple-assignable arm gated on the un-chased dst kind, so a TY_NAMED alias skipped the per-element untyped->int coercion the direct tuple path applies. Fix: chase TY_NAMED both sides (mirrors the #258 slice-borrow arm). Direct and typed-alias tuples already worked; only alias+untyped was rejected. wwstage CGEN dropped the second word of an alias-tuple fn-arg: the tuple-param spill at cgendecl.ww gated on the syntactic N_TTUPLE, so an alias param (N_TNAME) fell to the scalar path and spilled one slot -> t.1 read frame garbage. Fix: chase the alias via aliaslookup to the resolved N_TTUPLE and spill all its slots. cstage cgen was already correct -- the bug was checker-only there. Converges cs==ww byte-id. One commit: same construct, the two halves must ship together (either alone leaves cs!=ww). test/wcc/826 (init/fn-arg/return, 2-field byte-id); test/wcc/944 4 rows graduated err->run-correct. byte-id 990-997 8/8.
This commit is contained in:
@@ -37878,7 +37878,22 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
p = p.next;
|
||||
continue;
|
||||
};
|
||||
if (p.lhs != nil) { if (p.lhs.kind == nkind.N_TTUPLE) {
|
||||
// #99: chase a TY_NAMED alias (multi-level) to its
|
||||
// underlying tuple — the param twin of the cstage type.c
|
||||
// type_chase_named tuple-arm. A bare (i64,i64) is N_TTUPLE
|
||||
// (no chase); `type tp=(i64,i64)` is an N_TNAME resolved via
|
||||
// aliaslookup. Without the chase the alias fell to the scalar
|
||||
// path → 1 slot, SI dropped, t.1 garbage. Slot size + element
|
||||
// walk source the RESOLVED node; localadd keeps the declared
|
||||
// p.lhs so field reads chase identically to cstage (byte-id).
|
||||
let tt99: *node = nil;
|
||||
if (p.lhs != nil) {
|
||||
tt99 = p.lhs;
|
||||
for (tt99 != nil && tt99.kind == nkind.N_TNAME) {
|
||||
tt99 = aliaslookup(c, tt99.str);
|
||||
};
|
||||
};
|
||||
if (p.lhs != nil) { if (tt99 != nil && tt99.kind == nkind.N_TTUPLE) {
|
||||
// #163: tuple PARAM receive (param twin of #164's
|
||||
// return). Walk the tuple's elements over the SysV
|
||||
// arg cursor — a float reads its XMM (X0..X7),
|
||||
@@ -37890,7 +37905,7 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
// partial-spill stitch is out of scope (twin of #164).
|
||||
let off: i32 = localadd(c, nm, slotsize(c, p.lhs), p.lhs);
|
||||
let eoff: i32 = 0;
|
||||
let te: *node = p.lhs.list;
|
||||
let te: *node = tt99.list;
|
||||
for (te != nil) {
|
||||
let et: *node = te.lhs;
|
||||
if (isfloattype(c, et)) {
|
||||
|
||||
@@ -103,7 +103,22 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
p = p.next;
|
||||
continue;
|
||||
};
|
||||
if (p.lhs != nil) { if (p.lhs.kind == nkind.N_TTUPLE) {
|
||||
// #99: chase a TY_NAMED alias (multi-level) to its
|
||||
// underlying tuple — the param twin of the cstage type.c
|
||||
// type_chase_named tuple-arm. A bare (i64,i64) is N_TTUPLE
|
||||
// (no chase); `type tp=(i64,i64)` is an N_TNAME resolved via
|
||||
// aliaslookup. Without the chase the alias fell to the scalar
|
||||
// path → 1 slot, SI dropped, t.1 garbage. Slot size + element
|
||||
// walk source the RESOLVED node; localadd keeps the declared
|
||||
// p.lhs so field reads chase identically to cstage (byte-id).
|
||||
let tt99: *node = nil;
|
||||
if (p.lhs != nil) {
|
||||
tt99 = p.lhs;
|
||||
for (tt99 != nil && tt99.kind == nkind.N_TNAME) {
|
||||
tt99 = aliaslookup(c, tt99.str);
|
||||
};
|
||||
};
|
||||
if (p.lhs != nil) { if (tt99 != nil && tt99.kind == nkind.N_TTUPLE) {
|
||||
// #163: tuple PARAM receive (param twin of #164's
|
||||
// return). Walk the tuple's elements over the SysV
|
||||
// arg cursor — a float reads its XMM (X0..X7),
|
||||
@@ -115,7 +130,7 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
// partial-spill stitch is out of scope (twin of #164).
|
||||
let off: i32 = localadd(c, nm, slotsize(c, p.lhs), p.lhs);
|
||||
let eoff: i32 = 0;
|
||||
let te: *node = p.lhs.list;
|
||||
let te: *node = tt99.list;
|
||||
for (te != nil) {
|
||||
let et: *node = te.lhs;
|
||||
if (isfloattype(c, et)) {
|
||||
|
||||
@@ -37878,7 +37878,22 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
p = p.next;
|
||||
continue;
|
||||
};
|
||||
if (p.lhs != nil) { if (p.lhs.kind == nkind.N_TTUPLE) {
|
||||
// #99: chase a TY_NAMED alias (multi-level) to its
|
||||
// underlying tuple — the param twin of the cstage type.c
|
||||
// type_chase_named tuple-arm. A bare (i64,i64) is N_TTUPLE
|
||||
// (no chase); `type tp=(i64,i64)` is an N_TNAME resolved via
|
||||
// aliaslookup. Without the chase the alias fell to the scalar
|
||||
// path → 1 slot, SI dropped, t.1 garbage. Slot size + element
|
||||
// walk source the RESOLVED node; localadd keeps the declared
|
||||
// p.lhs so field reads chase identically to cstage (byte-id).
|
||||
let tt99: *node = nil;
|
||||
if (p.lhs != nil) {
|
||||
tt99 = p.lhs;
|
||||
for (tt99 != nil && tt99.kind == nkind.N_TNAME) {
|
||||
tt99 = aliaslookup(c, tt99.str);
|
||||
};
|
||||
};
|
||||
if (p.lhs != nil) { if (tt99 != nil && tt99.kind == nkind.N_TTUPLE) {
|
||||
// #163: tuple PARAM receive (param twin of #164's
|
||||
// return). Walk the tuple's elements over the SysV
|
||||
// arg cursor — a float reads its XMM (X0..X7),
|
||||
@@ -37890,7 +37905,7 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
// partial-spill stitch is out of scope (twin of #164).
|
||||
let off: i32 = localadd(c, nm, slotsize(c, p.lhs), p.lhs);
|
||||
let eoff: i32 = 0;
|
||||
let te: *node = p.lhs.list;
|
||||
let te: *node = tt99.list;
|
||||
for (te != nil) {
|
||||
let et: *node = te.lhs;
|
||||
if (isfloattype(c, et)) {
|
||||
|
||||
Reference in New Issue
Block a user