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:
@@ -20212,21 +20212,19 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
let ttotal: i32 = 0;
|
||||
let ce: *node = tupsrc.list;
|
||||
for (ce != nil) {
|
||||
// #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. Mirrors cstage.
|
||||
// #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.ww:1640-1646);
|
||||
// the store loop below boxes it recursively
|
||||
// (two-level widen). Symmetric with cstage.
|
||||
let ceti: *tinfo = ce.type_: *tinfo;
|
||||
ceti = tichase(ceti);
|
||||
if (ceti != nil && ceti.kind == tykind.TY_TAGGED) {
|
||||
let m22: str = "cgwidentaggedstore: tagged element in a tuple-in-union payload unwired (see #242/#22b)\n";
|
||||
os.write(2, m22.ptr, m22.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (nodeisstr(c, ce) || nodeisslice(c, ce)) {
|
||||
ttotal += (ceti.size: i32 + 7) & ~7;
|
||||
} else { if (nodeisstr(c, ce) || nodeisslice(c, ce)) {
|
||||
ttotal += 24;
|
||||
} else { ttotal += 8; };
|
||||
} else { ttotal += 8; }; };
|
||||
ce = ce.next;
|
||||
};
|
||||
if (8 + ttotal > slot_sz) {
|
||||
@@ -20245,6 +20243,24 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
let tfoff: i32 = 0;
|
||||
let te: *node = tupsrc.list;
|
||||
for (te != nil) {
|
||||
// #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). Symmetric
|
||||
// with cstage cg_widen_tagged_store.
|
||||
let teti: *tinfo = te.type_: *tinfo;
|
||||
teti = tichase(teti);
|
||||
if (teti != nil && teti.kind == tykind.TY_TAGGED) {
|
||||
let ebox: i32 = (teti.size: i32 + 7) & ~7;
|
||||
cgwidentaggedstore(c, te.type_: *tinfo, te,
|
||||
"BP", slot_off + 8 + tfoff, ebox);
|
||||
tfoff += ebox;
|
||||
te = te.next;
|
||||
continue;
|
||||
};
|
||||
let isflt: bool = isfloattype(c, te);
|
||||
let wide: bool = nodeisstr(c, te) || nodeisslice(c, te);
|
||||
let esz: i32 = 8;
|
||||
|
||||
@@ -4071,21 +4071,19 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
let ttotal: i32 = 0;
|
||||
let ce: *node = tupsrc.list;
|
||||
for (ce != nil) {
|
||||
// #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. Mirrors cstage.
|
||||
// #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.ww:1640-1646);
|
||||
// the store loop below boxes it recursively
|
||||
// (two-level widen). Symmetric with cstage.
|
||||
let ceti: *tinfo = ce.type_: *tinfo;
|
||||
ceti = tichase(ceti);
|
||||
if (ceti != nil && ceti.kind == tykind.TY_TAGGED) {
|
||||
let m22: str = "cgwidentaggedstore: tagged element in a tuple-in-union payload unwired (see #242/#22b)\n";
|
||||
os.write(2, m22.ptr, m22.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (nodeisstr(c, ce) || nodeisslice(c, ce)) {
|
||||
ttotal += (ceti.size: i32 + 7) & ~7;
|
||||
} else { if (nodeisstr(c, ce) || nodeisslice(c, ce)) {
|
||||
ttotal += 24;
|
||||
} else { ttotal += 8; };
|
||||
} else { ttotal += 8; }; };
|
||||
ce = ce.next;
|
||||
};
|
||||
if (8 + ttotal > slot_sz) {
|
||||
@@ -4104,6 +4102,24 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
let tfoff: i32 = 0;
|
||||
let te: *node = tupsrc.list;
|
||||
for (te != nil) {
|
||||
// #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). Symmetric
|
||||
// with cstage cg_widen_tagged_store.
|
||||
let teti: *tinfo = te.type_: *tinfo;
|
||||
teti = tichase(teti);
|
||||
if (teti != nil && teti.kind == tykind.TY_TAGGED) {
|
||||
let ebox: i32 = (teti.size: i32 + 7) & ~7;
|
||||
cgwidentaggedstore(c, te.type_: *tinfo, te,
|
||||
"BP", slot_off + 8 + tfoff, ebox);
|
||||
tfoff += ebox;
|
||||
te = te.next;
|
||||
continue;
|
||||
};
|
||||
let isflt: bool = isfloattype(c, te);
|
||||
let wide: bool = nodeisstr(c, te) || nodeisslice(c, te);
|
||||
let esz: i32 = 8;
|
||||
|
||||
@@ -20212,21 +20212,19 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
let ttotal: i32 = 0;
|
||||
let ce: *node = tupsrc.list;
|
||||
for (ce != nil) {
|
||||
// #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. Mirrors cstage.
|
||||
// #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.ww:1640-1646);
|
||||
// the store loop below boxes it recursively
|
||||
// (two-level widen). Symmetric with cstage.
|
||||
let ceti: *tinfo = ce.type_: *tinfo;
|
||||
ceti = tichase(ceti);
|
||||
if (ceti != nil && ceti.kind == tykind.TY_TAGGED) {
|
||||
let m22: str = "cgwidentaggedstore: tagged element in a tuple-in-union payload unwired (see #242/#22b)\n";
|
||||
os.write(2, m22.ptr, m22.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (nodeisstr(c, ce) || nodeisslice(c, ce)) {
|
||||
ttotal += (ceti.size: i32 + 7) & ~7;
|
||||
} else { if (nodeisstr(c, ce) || nodeisslice(c, ce)) {
|
||||
ttotal += 24;
|
||||
} else { ttotal += 8; };
|
||||
} else { ttotal += 8; }; };
|
||||
ce = ce.next;
|
||||
};
|
||||
if (8 + ttotal > slot_sz) {
|
||||
@@ -20245,6 +20243,24 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
let tfoff: i32 = 0;
|
||||
let te: *node = tupsrc.list;
|
||||
for (te != nil) {
|
||||
// #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). Symmetric
|
||||
// with cstage cg_widen_tagged_store.
|
||||
let teti: *tinfo = te.type_: *tinfo;
|
||||
teti = tichase(teti);
|
||||
if (teti != nil && teti.kind == tykind.TY_TAGGED) {
|
||||
let ebox: i32 = (teti.size: i32 + 7) & ~7;
|
||||
cgwidentaggedstore(c, te.type_: *tinfo, te,
|
||||
"BP", slot_off + 8 + tfoff, ebox);
|
||||
tfoff += ebox;
|
||||
te = te.next;
|
||||
continue;
|
||||
};
|
||||
let isflt: bool = isfloattype(c, te);
|
||||
let wide: bool = nodeisstr(c, te) || nodeisslice(c, te);
|
||||
let esz: i32 = 8;
|
||||
|
||||
Reference in New Issue
Block a user