wwstage: load-combine-store local-field compound assign (#227)

A compound assign (`-=`/`+=`) on a local field silently dropped the
operator in wwstage, storing the bare rhs. Two same-class sites in
cgenexpr.ww lacked the `n.op != TK_ASSIGN` load-combine-store guard that
the pointer-to-struct path already had: the local str/slice pseudo-field
fall-through (`view.len -= 1` stored 1) and the direct struct-local
scalar field (`p.x -= 4` stored 4). Both now load the field, push, eval
rhs, pop, combine (ADDQ/SUBQ), and store — mirroring cstage
cmd/w6c/cgen.c:3235-3264 and :3477-3502. cstage was already correct;
this aligns wwstage up. PLUSEQ/MINUSEQ only, matching cstage's switch.

This is the missing-SUBQ half of fmt's cs/ww divergence (fmt's
view.len-=1). The remaining match-label-counter offset is separate, so
777/780/781 stay STAGE_CS until that lands.

test/wcc/data/attest_pass.ww: @test check_local_field_compound covers
both sites (str pseudo-field + struct scalar), run by 910_at_test
(cstage) and 997_at_test_ww (wwstage); pre-fix the dropped op aborts via
the 1/0 idiom.
This commit is contained in:
2026-06-01 03:52:06 +09:00
parent f8aebc045d
commit 9cf1560392
4 changed files with 152 additions and 0 deletions

View File

@@ -2,6 +2,8 @@
package data;
type point = struct { x: i32, y: i32 };
@test fn check_add() void = {
let a: i32 = 2;
let b: i32 = 3;
@@ -21,3 +23,24 @@ package data;
let _: i32 = 1 / 0;
};
};
// #227: compound assign (`-=`/`+=`) on a local field must
// load-combine-store, not drop the op. Pre-fix wwstage stored the bare
// rhs (p.x->4, p.y->5, view.len->1), so each mismatch aborts via 1/0.
@test fn check_local_field_compound() void = {
let p: point = point { x = 10i32, y = 3i32 };
p.x -= 4i32;
p.y += 5i32;
if (p.x != 6) {
let _: i32 = 1 / 0;
};
if (p.y != 8) {
let _: i32 = 1 / 0;
};
let view: str = "hello";
view.len -= 1;
let n: i32 = view.len: i32;
if (n != 4) {
let _: i32 = 1 / 0;
};
};