w6c+selfhost: cg_widen_tagged_store basereg + N_ASSIGN tagged field (closes #26)
Extended cg_widen_tagged_store (cstage) / cgwidentaggedstore (wwstage) to take a base_reg/basereg parameter so the primitive supports non-BP destinations. Cstage extends body in-place via via_outer gate + spill+scratch+copy-out; wwstage splits into wrapper (non-BP) + cgwidentaggedstorebp (BP-only) to dodge the no-goto constraint. New N_ASSIGN field TY_TAGGED branch routes through the primitive for all rhs shapes. Scope-adjacent: fieldsize recurses through N_TTAGGED via slotsize and TNAME-aliased-to-tagged via aliaslookup. Needed for the test fixtures. Wwstage read-side N_DOT-of-tagged-field source is filed as task #28; test rows use mark-canary verification until that lands.
This commit is contained in:
@@ -2745,7 +2745,7 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
let slot: i32 = doff + j * esz;
|
||||
if (velemtagged) {
|
||||
cgwidentaggedstore(c, varp.lhs,
|
||||
aa2, slot, esz);
|
||||
aa2, "BP", slot, esz);
|
||||
} else { if (velemstr) {
|
||||
cgexpr(c, aa2);
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
@@ -3001,7 +3001,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
if (istaggedtype(c, lc.tnode)) {
|
||||
let lsz: i32 = slotsize(c, lc.tnode);
|
||||
cgwidentaggedstore(c, lc.tnode,
|
||||
n.rhs, lc.off, lsz);
|
||||
n.rhs, "BP", lc.off, lsz);
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -3225,7 +3225,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
zz += 8;
|
||||
};
|
||||
cgwidentaggedstore(c, elemtn, n.rhs,
|
||||
scroff, slot_sz);
|
||||
"BP", scroff, slot_sz);
|
||||
cgexpr(c, idx);
|
||||
if (slot_sz > 1) {
|
||||
emitline("\tMOVQ\t$");
|
||||
@@ -3571,6 +3571,20 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// Tagged-union field via *struct base — full slot
|
||||
// rewrite via cgwidentaggedstore basereg="BX". Pre-#26
|
||||
// fell through to the scalar store and dropped tag
|
||||
// + payload.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& istaggedtype(c, fi.tnode)) {
|
||||
let fsz: i32 = slotsize(c, fi.tnode);
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(lc.off: i64);
|
||||
emitline("(BP), BX\n");
|
||||
cgwidentaggedstore(c, fi.tnode,
|
||||
n.rhs, "BX", fi.foff, fsz);
|
||||
return;
|
||||
};
|
||||
// struct-typed field, struct-ident rhs through
|
||||
// *struct base: cgexpr can't materialise a whole
|
||||
// struct value, so word-copy from the rhs slot
|
||||
@@ -3721,6 +3735,17 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// Tagged-union field in a direct struct local —
|
||||
// full slot rewrite at (lc.off + fi.foff)(BP)
|
||||
// via cgwidentaggedstore basereg="BP". Pre-#26
|
||||
// fell through and dropped tag + payload.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& istaggedtype(c, fi.tnode)) {
|
||||
let fsz: i32 = slotsize(c, fi.tnode);
|
||||
cgwidentaggedstore(c, fi.tnode,
|
||||
n.rhs, "BP", lc.off + fi.foff, fsz);
|
||||
return;
|
||||
};
|
||||
// struct-typed field, struct-ident rhs:
|
||||
// word-copy direct, skipping cgexpr (no
|
||||
// register convention for a whole struct
|
||||
|
||||
Reference in New Issue
Block a user