wcc/ww: store through a *tagged pointer widens, both stages (#17)
The N_UN/TK_STAR plain-deref assign arm fell to a single fldstoreop for every pointee, so `*p = v` with p:*tagged wrote the rhs into the tag word and never the payload -- identically in both stages, leaving the byte-id gate green while the store corrupted the tag (#263-class, gate-blind). Gate on TY_TAGGED and route through cg_widen_tagged_store into a scratch slot, then word-copy to the destination -- the proven runtime-index arm. Scalar pointees keep the single-store path unchanged.
This commit is contained in:
@@ -8433,6 +8433,42 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
if (n.op == tkind.TK_ASSIGN && !placeslit
|
||||
&& !derefagg) {
|
||||
let inner: *node = lhs.lhs;
|
||||
// #17: tagged-union pointee. The single-store
|
||||
// tail below writes rhs into the tag word only,
|
||||
// dropping the payload and corrupting the union.
|
||||
// Materialise the widened value (tag + payload
|
||||
// words, nullable fold, tag remap) into the shared
|
||||
// @tagscr scratch via cgwidentaggedstore, then
|
||||
// word-copy scratch -> *p. Mirror of the runtime-
|
||||
// index tagged element arm (cgenexpr.ww:8768) and
|
||||
// the cstage twin (cmd/w6c/cgen.c #17 deref arm).
|
||||
let du: *tinfo = tichase(lhs.type_: *tinfo);
|
||||
if (du != nil && du.kind == tykind.TY_TAGGED) {
|
||||
let ssz: i32 = du.size: i32;
|
||||
let scr: i32 = tagscradd(c, ssz);
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let zk: i32 = 0;
|
||||
for (zk < ssz) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((scr + zk): i64);
|
||||
emitline("(BP)\n");
|
||||
zk += 8;
|
||||
};
|
||||
cgwidentaggedstore(c, du, n.rhs, "BP", scr, ssz);
|
||||
cgexpr(c, inner);
|
||||
emitline("\tMOVQ\tAX, BX\n");
|
||||
let ck: i32 = 0;
|
||||
for (ck < ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((scr + ck): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(ck: i64);
|
||||
emitline("(BX)\n");
|
||||
ck += 8;
|
||||
};
|
||||
return;
|
||||
};
|
||||
let elemstr: bool = false;
|
||||
let elemfloat: bool = false;
|
||||
let elemf32: bool = false;
|
||||
|
||||
Reference in New Issue
Block a user