wcc/cgen: #47 gap-A tuple-in-union tagged-element store (both-stage)
A tuple containing a tagged-union element, used as a union member (e.g. ((void|size),(void|size),size) | error), loud-stopped in the cgen return-store: the tuple-in-union store walk had scalar/float/ str/slice element arms but no TY_TAGGED-element arm. A PLAIN tuple-in-union already worked -- the blocker was the tagged element. Add the recursive two-level widen arm at both stages (cg_widen_tagged_store / cgwidentaggedstorebp): for each tagged element, re-enter the tagged-box store (inner tag@slot+0, payload@slot+8) at the element's tuple-payload offset, then stamp the outer tuple tag. Slot strides come from the type table (roundup8(eu->size)) -- the checker already sizes the shape correctly (tuple->size measured 40, union box 48; check.c:715-720). The recursion descends a finite type tree (a tagged element is never a tuple literal, so it can't re-enter the tuple arm); unsupported deeper nesting still louds via the existing size/tag guards. Both stages get the same arm -> byte-id (990-997 green; additive, bootstrap-neutral). cstage runs the full b1c shape (construct+return+match-extract) as the runtime reference; wwstage's store rides on byte-id until gap-B. gap-B (wwstage checker match-acceptance of the tuple-with-tagged case pattern) is a separate commit -- wwstage still louds the match honestly at the checker. Pin 944_tuple_tagged_union_run.
This commit is contained in:
@@ -2768,16 +2768,18 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src,
|
||||
* SysV eightbyte tuple classification is a deferred follow-up. */
|
||||
int total = 0;
|
||||
for (Node *e = tupsrc->list; e; e = e->next) {
|
||||
/* #22a (rule 7): a tagged element's box can't ride
|
||||
* the scalar/wide store arms below — pre-guard it
|
||||
* silently stored word0. Nested tagged-in-tuple-in-
|
||||
* union packing is the #242/#22b family. */
|
||||
/* #47 gap-A: a tagged element rides its OWN box
|
||||
* (tag + payload, roundup8) per tuple slot — NOT one
|
||||
* 8B word. Mirror the checker's N_TTUPLE accumulation
|
||||
* (check.c:715-720): aggregate/tagged elem += its
|
||||
* box size rounded to 8; the store loop below boxes it
|
||||
* recursively (two-level widen). */
|
||||
Type *eu = type_chase_named(e->type);
|
||||
if (eu && eu->kind == TY_TAGGED)
|
||||
fatal("cg_widen_tagged_store: tagged element "
|
||||
"in a tuple-in-union payload unwired "
|
||||
"(see #242/#22b)");
|
||||
total += (node_isstr(e) || node_isslice(e)) ? 24 : 8;
|
||||
total += ((int)eu->size + 7) & ~7;
|
||||
else
|
||||
total += (node_isstr(e) || node_isslice(e)) ?
|
||||
24 : 8;
|
||||
}
|
||||
if (8 + total > sz)
|
||||
fatal("cg_widen_tagged_store: tuple-in-union payload needs "
|
||||
@@ -2789,6 +2791,20 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src,
|
||||
amem(D_BP, write_off + k));
|
||||
int foff = 0;
|
||||
for (Node *e = tupsrc->list; e; e = e->next) {
|
||||
/* #47 gap-A: a tagged element is its own tag+payload
|
||||
* box. Recurse so the inner box (tag@slot+0,
|
||||
* payload@slot+8) is built at the element's tuple-
|
||||
* payload offset, exactly as a top-level tagged-store
|
||||
* does — two-level widen (inner boxes here, outer tuple
|
||||
* tag stamped below). slot stride = roundup8(box). */
|
||||
Type *eu = type_chase_named(e->type);
|
||||
if (eu && eu->kind == TY_TAGGED) {
|
||||
int ebox = ((int)eu->size + 7) & ~7;
|
||||
cg_widen_tagged_store(c, locals_p, e->type, e,
|
||||
D_BP, write_off + 8 + foff, ebox);
|
||||
foff += ebox;
|
||||
continue;
|
||||
}
|
||||
int e_isf32 = 0;
|
||||
int isflt = fld_isfloat(e->type, &e_isf32);
|
||||
int wide = node_isstr(e) || node_isslice(e);
|
||||
|
||||
Reference in New Issue
Block a user