wcc/ww: alloc of an alias struct literal chases the alias for size and fill

alloc(alias{...}) keyed the size and field-fill off the syntactic
alias name — it under-allocated and emitted zero field stores. Chase
the alias via structlookupchain to the resolved struct (depth-2
chains verified). The scalar else-branch keeps its pre-existing
benign cs!=ww divergence, surfaced here and deferred as task #57
(site note at the arm). Review item #26.
This commit is contained in:
2026-06-13 01:49:07 +09:00
parent 36e17b58f2
commit faf1a2908b
5 changed files with 202 additions and 24 deletions

View File

@@ -5707,14 +5707,14 @@ fn cgalloc(c: *cgen, n: *node) void = {
let sz: i32 = 8;
let si: *structinfo = nil;
if (v.kind == nkind.N_STRUCTLIT) {
let trefn: *node = v.lhs;
let sname: str;
sname.ptr = nil; sname.len = 0;
if (trefn != nil) {
if (trefn.kind == nkind.N_IDENT) { sname = trefn.str; }
else { if (trefn.kind == nkind.N_TNAME) { sname = trefn.str; }; };
};
si = structlookup(c, sname);
// #26: chase the alias chain on the literal's type ref so an
// alias head (`type pt = point; alloc(pt{...})`) resolves to
// the underlying struct's layout — name-keyed structlookup on
// the syntactic head missed it (under-alloc $8 + zero field
// stores). Mirrors cstage cgen.c:8223-8240 (type_default chases
// named before sizing/walking fields); same alias-chase helper
// the #22 sites use.
si = structlookupchain(c, v.lhs);
if (si != nil) { sz = si.totsize; };
};
let okl: str = mklabel(c, "alloc_ok");
@@ -5790,6 +5790,10 @@ fn cgalloc(c: *cgen, n: *node) void = {
};
};
} else {
// #57 (retained cs!=ww, deferred): scalar/ptr alloc keeps the
// default-8 size + MOVQ store; cstage sizes the scalar exactly
// ($1/MOVB for u8) and the latent alloc(str|slice) wants 24B not 8.
// Byte-id-visible, runtime-benign; not folded into the #26 arm.
cgexpr(c, v);
emitline("\tMOVQ\t(SP), BX\n");
let sop: str = "MOVQ";