w6c: widen of a module-global tagged ident copies the whole box
cstage spilled frame garbage as the box; mirror the landed wwstage emission (copy from gi(SB)). The F8-era divergence-only rows gain pinned cs==ww values. Task #44.
This commit is contained in:
@@ -2611,7 +2611,8 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src,
|
||||
for (int k = 0; k < sz; k += 8)
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_BP, write_off + k));
|
||||
if (src->kind == N_IDENT) {
|
||||
if (src->kind == N_IDENT
|
||||
&& localfind(*locals_p, src->str) != 0) {
|
||||
int soff = localfind(*locals_p, src->str);
|
||||
for (int k = 0; k < ssz; k += 8) {
|
||||
ins2(c, A_MOVQ, amem(D_BP, soff + k),
|
||||
@@ -2619,6 +2620,21 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src,
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_BP, write_off + 8 + k));
|
||||
}
|
||||
} else if (src->kind == N_IDENT) {
|
||||
/* #44 (#263): a module-global tagged ident
|
||||
* source has no BP slot — land gi(SB) in SI
|
||||
* (aggarg_srcaddr) and copy the inner box into
|
||||
* slot+8. Pre-fix the BP copy read frame garbage
|
||||
* off 0(BP). ww half landed F8-c8. */
|
||||
if (aggarg_srcaddr(c, src, D_SI, *locals_p)) {
|
||||
for (int k = 0; k < ssz; k += 8) {
|
||||
ins2(c, A_MOVQ,
|
||||
amem(D_SI, k), areg(D_AX));
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_BP,
|
||||
write_off + 8 + k));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* #38b: an sret-classified call result is in
|
||||
* memory (AX = dest pointer), not the cursor —
|
||||
|
||||
@@ -4,29 +4,20 @@
|
||||
* must copy gi's whole box as the nested payload, not store its tag as the
|
||||
* payload.
|
||||
*
|
||||
* THE BUG (cat-A silent miscompile, #263 BOTH-WRONG): cgwidentaggedstorebp's
|
||||
* #218 nested-tagged-source arm is gated on rhstaggedident, which returns nil
|
||||
* for a module-global tagged ident (local-only). So srctagged was false and a
|
||||
* global tagged source fell to the scalar word0 widen arm — gi's TAG word
|
||||
* landed as the box payload, the real value lost. cstage is ALSO wrong: it
|
||||
* copies frame garbage (saved-BP / return-address), never gi(SB). Both wrong,
|
||||
* divergent (#263); the cstage half is filed as task #44.
|
||||
* THE BUG (cat-A silent miscompile, #263 BOTH-WRONG, now CLOSED both stages):
|
||||
* the #218 nested-tagged-source arm was gated local-only, so a module-global
|
||||
* tagged source fell to the scalar word0 widen arm — gi's TAG word landed as
|
||||
* the box payload (wwstage), or frame garbage was copied, never gi(SB)
|
||||
* (cstage). The ww half landed in F8-c8; the cstage half (the nested arm's
|
||||
* N_IDENT copy grows a global branch — LEAQ gi(SB),SI via aggarg_srcaddr, copy
|
||||
* the inner box into slot+8) landed in ww-core TASK #44. Both stages now copy
|
||||
* the whole box and the .s is byte-identical.
|
||||
*
|
||||
* THE WWSTAGE FIX (ww-runtime-correct): srctagged also recognises a global
|
||||
* tagged ident, and the nested arm's N_IDENT copy grows a global branch —
|
||||
* LEAQ gi(SB),SI via aggargsrcaddr, then copy the inner box (ssz bytes) into
|
||||
* slot+8 with the outer tag at slot+0. Local sources keep the BP copy
|
||||
* (byte-id). cstage stays wrong → cs≠ww residual.
|
||||
*
|
||||
* cstage's residual is FRAME GARBAGE (non-deterministic across stack
|
||||
* layouts), so — unlike the deterministic #263 members — the cstage rows
|
||||
* assert only that cstage DIVERGES (got != the runtime-correct value and the
|
||||
* build succeeded), not a pinned value. The wwstage rows assert the exact
|
||||
* runtime-correct value. (#44 closes the cs side → cstage will then match.)
|
||||
* row | shape | ww | cs
|
||||
* ----------+-----------------------------------------+----+--------
|
||||
* nest_47 | gi:inner=47; (inner|str)=gi; match→v | 47 | != 47 (garbage)
|
||||
* nest_99 | gi:inner=99; (inner|str)=gi; match→v | 99 | != 99 (garbage)
|
||||
* Rows assert the exact runtime-correct value on both stages (cs==ww).
|
||||
* row | shape | exit
|
||||
* ----------+-----------------------------------------+-----
|
||||
* nest_47 | gi:inner=47; (inner|str)=gi; match→v | 47
|
||||
* nest_99 | gi:inner=99; (inner|str)=gi; match→v | 99
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -154,28 +145,16 @@ main(void)
|
||||
drivers[d].name, drivers[d].drv);
|
||||
continue;
|
||||
}
|
||||
int is_ww = (d == 1);
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int got = run_build(drivers[d].drv, &rows[i], i);
|
||||
if (is_ww) {
|
||||
/* align-to-runtime-correct: exact value. */
|
||||
if (got != rows[i].want_ww) {
|
||||
fprintf(stderr, "globtagwiden_run[wwstage][%s]:"
|
||||
" exit=%d want=%d\n", rows[i].label,
|
||||
got, rows[i].want_ww);
|
||||
fail++;
|
||||
}
|
||||
} else {
|
||||
/* #263 residual: cstage built but diverges from the
|
||||
* runtime-correct value (frame garbage, #44). */
|
||||
if (got == -1 || got == rows[i].want_ww) {
|
||||
fprintf(stderr, "globtagwiden_run[cstage][%s]:"
|
||||
" exit=%d expected build-ok and !=%d "
|
||||
"(#263 residual, task #44)\n",
|
||||
rows[i].label, got, rows[i].want_ww);
|
||||
fail++;
|
||||
}
|
||||
/* #44 CLOSED: cs==ww at the exact runtime-correct value
|
||||
* on both drivers (the .s is byte-identical). */
|
||||
if (got != rows[i].want_ww) {
|
||||
fprintf(stderr, "globtagwiden_run[%s][%s]:"
|
||||
" exit=%d want=%d\n", drivers[d].name,
|
||||
rows[i].label, got, rows[i].want_ww);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user