wcc: indexed-field compound assignment wires all ten ops, both stages
arr[i].field /= %= <<= >>= silently dropped the op (load-combine-store
emitted plain assignment) in BOTH stages — gate-blind, the #133 class.
Route every compound op through the combine dispatch at the indexed-
field arm and hard-error the unhandled operand kinds (float/str/slice/
tagged), per the #133 template (3986818). The runtime-correct target is
the op's own algebra (a OP= b == a = a OP b). Review item #33.
Both stages move in one commit: the fix is a single emission contract —
splitting cstage cgen.c from selfhost cgenexpr.ww would leave the
byte-id gates red between the halves.
This commit is contained in:
@@ -9569,8 +9569,33 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// compound: rhs→push; compute struct
|
||||
// addr→BX (deref if *T); push addr;
|
||||
// load old field→AX; pop addr→BX,
|
||||
// rhs→CX; combine; store. Float/str
|
||||
// compound not wired.
|
||||
// rhs→CX; combine; store. #33/#263:
|
||||
// all 10 integer ops wired (was 6 →
|
||||
// SLASHEQ/PERCENTEQ/LSHIFTEQ/RSHIFTEQ
|
||||
// silently no-op'd in BOTH stages);
|
||||
// float/str/slice/tagged field hard-
|
||||
// errors LOUD. Mirrors cstage cgen.c
|
||||
// arr[i].field compound twin.
|
||||
if (istaggedtype(c, fi.tnode)) {
|
||||
let m: str = "arr[i].field compound on tagged field not wired (#33/rule-7)\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
let m: str = "arr[i].field compound on str field not wired (#33/rule-7)\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (isslicetype(c, fi.tnode)) {
|
||||
let m: str = "arr[i].field compound on slice field not wired (#33/rule-7)\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (isfloattype(c, fi.tnode)) {
|
||||
let m: str = "arr[i].field compound on float field not wired (#33/rule-7)\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
cgexpr(c, n.rhs);
|
||||
emitline("\tPUSHQ\tAX\n");
|
||||
cgexpr(c, idx);
|
||||
@@ -9600,12 +9625,41 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
emitline(", AX\n");
|
||||
emitline("\tPOPQ\tBX\n");
|
||||
emitline("\tPOPQ\tCX\n");
|
||||
if (n.op == tkind.TK_PLUSEQ) { emitline("\tADDQ\tCX, AX\n"); };
|
||||
if (n.op == tkind.TK_MINUSEQ) { emitline("\tSUBQ\tCX, AX\n"); };
|
||||
if (n.op == tkind.TK_STAREQ) { emitline("\tIMULQ\tCX, AX\n"); };
|
||||
if (n.op == tkind.TK_AMPEQ) { emitline("\tANDQ\tCX, AX\n"); };
|
||||
if (n.op == tkind.TK_PIPEEQ) { emitline("\tORQ\tCX, AX\n"); };
|
||||
if (n.op == tkind.TK_CARETEQ) { emitline("\tXORQ\tCX, AX\n"); };
|
||||
let unsignd_x: bool = false;
|
||||
if (fi.tnode != nil) {
|
||||
if (fi.tnode.type_ != nil) {
|
||||
unsignd_x = typeisunsigned(fi.tnode.type_: *tinfo);
|
||||
};
|
||||
};
|
||||
let wired_x: bool = false;
|
||||
if (n.op == tkind.TK_PLUSEQ) { emitline("\tADDQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_MINUSEQ) { emitline("\tSUBQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_STAREQ) { emitline("\tIMULQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_AMPEQ) { emitline("\tANDQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_PIPEEQ) { emitline("\tORQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_CARETEQ) { emitline("\tXORQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_SLASHEQ) {
|
||||
if (unsignd_x) { emitline("\tMOVQ\t$0, DX\n"); emitline("\tDIVQ\tCX\n"); }
|
||||
else { emitline("\tCQO\n"); emitline("\tIDIVQ\tCX\n"); };
|
||||
wired_x = true;
|
||||
};
|
||||
if (n.op == tkind.TK_PERCENTEQ) {
|
||||
if (unsignd_x) { emitline("\tMOVQ\t$0, DX\n"); emitline("\tDIVQ\tCX\n"); }
|
||||
else { emitline("\tCQO\n"); emitline("\tIDIVQ\tCX\n"); };
|
||||
emitline("\tMOVQ\tDX, AX\n");
|
||||
wired_x = true;
|
||||
};
|
||||
if (n.op == tkind.TK_LSHIFTEQ) { emitline("\tSHLQ\tCX, AX\n"); wired_x = true; };
|
||||
if (n.op == tkind.TK_RSHIFTEQ) {
|
||||
if (unsignd_x) { emitline("\tSHRQ\tCX, AX\n"); }
|
||||
else { emitline("\tSARQ\tCX, AX\n"); };
|
||||
wired_x = true;
|
||||
};
|
||||
if (!wired_x) {
|
||||
let m: str = "arr[i].field compound: unknown op (#33/rule-7)\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
let sop2: str = fieldstoreop(c, fi);
|
||||
emitline("\t");
|
||||
emitline(sop2);
|
||||
|
||||
Reference in New Issue
Block a user