wcc/ww: reject compound *p OP= v through a *tagged, like cstage (#18)
The wwstage compound-deref arm narrowed the store for scalar pointees and otherwise emitted a single MOVQ, so `*p OP= v` with p:*tagged clobbered one word (the tag) and returned -- silently miscompiling what cstage already rejects. A compound op on a whole union is nonsense. Gate the arm on a scalar pointee size and let a tagged pointee fall through to the existing assign-resolver reject, the byte-id twin of the cstage fatal. cstage is unchanged. This closes the deref member of the compound-on-tagged class; the index and ident members (gs[i] OP= v, g OP= v) reject in a follow-up (#20/#21).
This commit is contained in:
@@ -31931,7 +31931,18 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_UN) {
|
||||
if (lhs.op == tkind.TK_STAR) {
|
||||
if (n.op != tkind.TK_ASSIGN) {
|
||||
// Size gate (mirror cstage cgen.c handled=sz∈{1,2,4,8}):
|
||||
// a tagged (or any non-scalar) pointee is not a
|
||||
// meaningful compound target — skip this single-word
|
||||
// store-and-return arm so `*p OP= v` on *tagged falls
|
||||
// through to the assign-resolver's loud TY_TAGGED reject
|
||||
// (#18). Without it the MOVQ default below clobbers the
|
||||
// tag word and returns: a silent miscompile.
|
||||
let psz: i32 = 8;
|
||||
let lt: *tinfo = lhs.type_: *tinfo;
|
||||
if (lt != nil) { psz = lt.size: i32; };
|
||||
let scalarpointee: bool = (psz == 1 || psz == 2 || psz == 4 || psz == 8);
|
||||
if (n.op != tkind.TK_ASSIGN && scalarpointee) {
|
||||
let inner: *node = lhs.lhs;
|
||||
let loadop: str = "MOVQ";
|
||||
let storeop: str = "MOVQ";
|
||||
|
||||
Reference in New Issue
Block a user