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:
@@ -204,6 +204,61 @@ fn scanlocals(c: *cgen, n: *node) i32 = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// Tagged-union struct-field write: `s.f = v` or `(*p).f = v`
|
||||
// where f is a tagged-union field. cgassign delegates to
|
||||
// cgwidentaggedstore; for pointer-rooted dst the wrapper
|
||||
// allocates @tagbase (8B) and @tagscr (slot_sz). Both names
|
||||
// dedup with other tagged scratch users in the same function.
|
||||
if (n.kind == nkind.N_ASSIGN) {
|
||||
let alhs: *node = n.lhs;
|
||||
if (alhs != nil) {
|
||||
if (alhs.kind == nkind.N_DOT) {
|
||||
let abase: *node = alhs.lhs;
|
||||
if (abase != nil) {
|
||||
if (abase.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, abase.str);
|
||||
let btn: *node = nil;
|
||||
if (lc != nil) { btn = lc.tnode; }
|
||||
else { btn = letvartnode(c, abase.str); };
|
||||
let isptr: bool = false;
|
||||
let stype: *node = nil;
|
||||
if (btn != nil) {
|
||||
if (btn.kind == nkind.N_TPTR) {
|
||||
isptr = true;
|
||||
stype = btn.lhs;
|
||||
};
|
||||
if (btn.kind == nkind.N_TNAME) { stype = btn; };
|
||||
};
|
||||
if (stype != nil) {
|
||||
if (stype.kind == nkind.N_TNAME) {
|
||||
let si: *structinfo = structlookup(c, stype.str);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, alhs.str)) {
|
||||
if (istaggedtype(c, fi.tnode)) {
|
||||
if (isptr) {
|
||||
if (!scanseenmark(c, "@tagbase")) {
|
||||
total += 8;
|
||||
};
|
||||
if (!scanseenmark(c, "@tagscr")) {
|
||||
total += 24;
|
||||
};
|
||||
};
|
||||
};
|
||||
fi = nil;
|
||||
} else {
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Tagged-union return with struct payload or tagged-subset
|
||||
// source — cgreturn materialises in @tagscr then loads
|
||||
// AX/DX/CX. Detect via the same rhsstructpayload predicate
|
||||
|
||||
Reference in New Issue
Block a user