cstage+selfhost+test: revert compound-assign div/mod workarounds (post-#16)
B1 (63332fe) landed CQO in both stages' assemblers and switched the
binary `/` and `%` paths to it. The compound-assign sisters (`/=`,
`%=`) were six explicit workarounds across both stages, all calling
out either "fallback for TK_SLASHEQ" or just falling through with no
case at all. With CQO available, every site mechanically ports to the
same "park rhs in CX, slot value into AX, CQO/IDIVQ CX, ferry result
back" sequence.
wwstage cgenexpr.ww:5381-5403 silently no-op'd IDENT-local signed
compound div/mod — `x /= y` and `x %= y` produced no IDIV emit at
all, just a load-bearing `MOVQ BX, off(BP)` that wrote the freshly
loaded slot value back unchanged. Bootstrap byte-id passed because
no selfhost-corpus path exercises signed compound. Latent miscompile
retired alongside the workaround revert.
cstage cgen.c:3735 (top-level-let global compound) was NOT in the
initial five-site bundle and surfaced via worker probing the
wwstage:5147 fix — `let gs: i32 = 100; gs /= 7;` returned 7 (divisor)
on cstage but 14 (correct quotient) on wwstage. Rule 10 caught the
would-be Class A divergence; the sixth site bundles in.
Six sites, one family:
cmd/w6c/cgen.c:3549 deref-compound `*p OP= v`
cmd/w6c/cgen.c:3735 top-level-let `gs OP= v`
cmd/w6c/cgen.c:3765 IDENT-local `x OP= v`
selfhost/cmd/wcc/cgenexpr.ww:3338 deref-compound
selfhost/cmd/wcc/cgenexpr.ww:5147 top-level-let
selfhost/cmd/wcc/cgenexpr.ww:5381 IDENT-local (silent-no-op)
test/wcc/978_intdiv_signed.c adds 7 compound rows × 2 drivers = 14
fixtures (now 68/68): IDENT-local /= /=- /=u, deref *p /= *p %= *p
/=u, with negative-dividend, negative-divisor, and unsigned-high-
bit-set coverage. Top-level-let compound coverage is deferred per
task #18 — single-file inline drivers hit a pre-existing linker
`undefined reference to '<file>.gs'` for LEAQ name(SB) targets.
cstage:3735 and wwstage:5147 are code-review-verified for rule-10
symmetry until #18 lands.
Grep-sweep (`if (n < 0) { neg = true; n = -n; }`) returned two sites
in lib/fmt/fmt.ww i64dec and lib/strconv/strconv.ww — both mirror
ref/hare/strconv/itos.ha's pre-negate idiom for INT64_MIN safety.
Per the Hare-faithful filter, both stay.
This commit is contained in:
@@ -283,6 +283,93 @@ static const struct row rows[] = {
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
|
||||
/* ---- COMPOUND ASSIGN rows ------------------------------------- *
|
||||
*
|
||||
* The siblings of the binary `/` and `%` paths above: `x /= v`,
|
||||
* `x %= v`, and `*p /= v`. Pre-#16's-B2 these emitted the worst
|
||||
* shape catalog:
|
||||
* - cstage cgen.c:3765 IDENT-local: silent no-op (BX held
|
||||
* loaded slot value, the trailing store wrote it back
|
||||
* unchanged — no IDIV emit at all).
|
||||
* - wwstage cgenexpr.ww:5381-5403 IDENT-local: identical silent
|
||||
* no-op shape; the load-bearing sentinel — a future regression
|
||||
* here passes byte-id (no asm = no divergence) AND passes the
|
||||
* selfhost corpus (no consumer of signed compound /=). The
|
||||
* semantic test below is the only catch.
|
||||
* - cstage cgen.c:3549 / wwstage cgenexpr.ww:3338 deref-compound
|
||||
* `*p OP= v`: silent rhs-only store, value of *p clobbered with
|
||||
* the divisor instead of computed quotient.
|
||||
*
|
||||
* Top-level-let compound coverage (cstage cgen.c:3735 / wwstage
|
||||
* cgenexpr.ww:5147) is deferred per task #18 — the inline-driver
|
||||
* 978 fixture can't currently exercise it because of a pre-existing
|
||||
* linker `undefined reference to '<file>.gs'` for single-file
|
||||
* top-level lets that flow through `LEAQ name(SB)`. The cstage:3735
|
||||
* and wwstage:5147 sites are code-review-verified for rule-10
|
||||
* symmetry; runtime coverage follows once #18 lands. */
|
||||
{ "compound_ident_local_div_neg_dividend",
|
||||
"fn main() i32 = {\n"
|
||||
" let a: i64 = -100i64;\n"
|
||||
" a /= 7i64;\n"
|
||||
" if (a == -14i64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
{ "compound_ident_local_mod_neg_dividend",
|
||||
"fn main() i32 = {\n"
|
||||
" let a: i64 = -100i64;\n"
|
||||
" a %= 7i64;\n"
|
||||
" if (a == -2i64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
{ "compound_ident_local_div_neg_divisor",
|
||||
"fn main() i32 = {\n"
|
||||
" let a: i64 = 100i64;\n"
|
||||
" a /= -7i64;\n"
|
||||
" if (a == -14i64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
{ "compound_ident_local_div_unsigned",
|
||||
"fn main() i32 = {\n"
|
||||
" let a: u64 = 0x8000000000000001u64;\n"
|
||||
" a /= 2u64;\n"
|
||||
" if (a == 0x4000000000000000u64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
{ "compound_deref_div_neg_dividend",
|
||||
"fn main() i32 = {\n"
|
||||
" let arr: [1]i64;\n"
|
||||
" arr[0] = -50i64;\n"
|
||||
" let p: *i64 = &arr[0];\n"
|
||||
" *p /= 3i64;\n"
|
||||
" if (arr[0] == -16i64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
{ "compound_deref_mod_neg_dividend",
|
||||
"fn main() i32 = {\n"
|
||||
" let arr: [1]i64;\n"
|
||||
" arr[0] = -50i64;\n"
|
||||
" let p: *i64 = &arr[0];\n"
|
||||
" *p %= 3i64;\n"
|
||||
" if (arr[0] == -2i64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
{ "compound_deref_div_unsigned",
|
||||
"fn main() i32 = {\n"
|
||||
" let arr: [1]u64;\n"
|
||||
" arr[0] = 0x8000000000000001u64;\n"
|
||||
" let p: *u64 = &arr[0];\n"
|
||||
" *p /= 2u64;\n"
|
||||
" if (arr[0] == 0x4000000000000000u64) { return 42; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
};
|
||||
|
||||
static int
|
||||
|
||||
Reference in New Issue
Block a user