wwstage: register error-structs in collectstructs so large-union struct-variant returns widen (#9)
collectstructs registered a struct only when the typedecl body is N_TSTRUCT, so an error-struct (type X = !struct{...}, whose body is N_TBANG{N_TSTRUCT}) never entered wwstage's c.structs table. The name-keyed structlookup then missed at the return-widen sites, and wwstage dropped the struct construction when returning a struct variant of a large (>4-eightbyte) union -- wrong runtime value and cs!=ww. cstage has no struct name-table (pure tinfo) and was correct. Peel the N_TBANG body in collectstructs so error-structs register; both existing cstage-mirrored widen arms then fire. Provably byte-id-inert: no committed source defines a !struct today. Adds test/wcc/785 (struct-variant return + named-void control, both-stage byte-id + runtime). The >4-eightbyte 5th-word truncation on return remains, symmetric (cs==ww) and unread by the tag/early-word path; #222's sret hidden-pointer cutover is the committed fix (table-retirement tracked as the wwstage->tinfo SSoT arc). Aligns wwstage up to cstage (rule-10).
This commit is contained in:
@@ -1838,6 +1838,20 @@ fn collectstructs(c: *cgen, file: *node) void = {
|
||||
for (d != nil) {
|
||||
if (d.kind == nkind.N_TYPEDECL) {
|
||||
let body: *node = d.lhs;
|
||||
// #9: an error-struct (`type X = !struct{...}`) carries an
|
||||
// N_TBANG-wrapped body; peel it so X registers like any
|
||||
// struct. cstage is tinfo-based and needs no table, but
|
||||
// wwstage's name-keyed widen dispatch (cgreturn needswiden
|
||||
// → cgwidentaggedstore) resolves struct layout through
|
||||
// c.structs; an unregistered error-struct made the
|
||||
// struct-variant-of-large-union return silently drop its
|
||||
// construction (cs!=ww). The strategic fix is #222's sret
|
||||
// cutover, which deletes this name-keyed dispatch outright;
|
||||
// until then the table must be complete (errors.opaque_ is
|
||||
// the first such type). #10 tracks retiring the table.
|
||||
if (body != nil && body.kind == nkind.N_TBANG) {
|
||||
body = body.lhs;
|
||||
};
|
||||
if (body != nil) {
|
||||
if (body.kind == nkind.N_TSTRUCT) {
|
||||
registerstruct(c, d.str, d.nmod, body);
|
||||
|
||||
Reference in New Issue
Block a user