w6c: widen of a module-global struct ident copies the full payload
cstage zero-filled the payload; mirror the landed wwstage emission. Flips the residual row to cs==ww==correct. Task #43.
This commit is contained in:
@@ -2925,9 +2925,21 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src,
|
||||
if (src->kind == N_IDENT) {
|
||||
int soff = localfind(*locals_p, src->str);
|
||||
int ssz = (int)su->size;
|
||||
int srcreg = D_BP, srcbase = soff;
|
||||
if (soff == 0) {
|
||||
/* #43 (#263): a module-global struct ident has
|
||||
* no BP slot — land g(SB) in SI (aggarg_srcaddr)
|
||||
* and copy the struct words into slot+8. Pre-fix
|
||||
* the BP copy read frame garbage off 0(BP). ww
|
||||
* half landed F8-c7. */
|
||||
if (aggarg_srcaddr(c, src, D_SI, *locals_p)) {
|
||||
srcreg = D_SI;
|
||||
srcbase = 0;
|
||||
}
|
||||
}
|
||||
int k = 0;
|
||||
while (k + 8 <= ssz) {
|
||||
ins2(c, A_MOVQ, amem(D_BP, soff + k),
|
||||
ins2(c, A_MOVQ, amem(srcreg, srcbase + k),
|
||||
areg(D_AX));
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_BP, write_off + 8 + k));
|
||||
@@ -2942,7 +2954,7 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src,
|
||||
int lop = (tail == 4) ? A_MOVL :
|
||||
(tail == 1 ? A_MOVB : A_MOVQ);
|
||||
ins2(c, lop,
|
||||
amem(D_BP, soff + k), areg(D_AX));
|
||||
amem(srcreg, srcbase + k), areg(D_AX));
|
||||
ins2(c, lop, areg(D_AX),
|
||||
amem(D_BP, write_off + 8 + k));
|
||||
}
|
||||
|
||||
@@ -3,27 +3,20 @@
|
||||
* GLOBAL struct ident into a tagged union (`let x: (S | str) = gs;`) must
|
||||
* copy gs's full payload into the box, not just word0.
|
||||
*
|
||||
* THE BUG (cat-A silent miscompile, #263 BOTH-WRONG): cgwidentaggedstorebp's
|
||||
* struct-payload arm keys off rhsstructpayload, which returns a struct name
|
||||
* only for an N_STRUCTLIT or a LOCAL ident. A module-global struct ident
|
||||
* returned empty, so the value fell to the scalar word0 widen arm — only the
|
||||
* first 8 bytes reached the box, the rest stale/zero. cstage is ALSO wrong:
|
||||
* it zero-fills the payload (gs is never read). Both wrong (#263); the cstage
|
||||
* half is filed as task #43.
|
||||
* THE BUG (cat-A silent miscompile, #263 BOTH-WRONG, now CLOSED both stages):
|
||||
* the struct-payload widen arm keyed off a local/literal-only struct-name
|
||||
* lookup, so a module-global struct ident fell to the scalar word0 arm — only
|
||||
* the first 8 bytes reached the box (wwstage), or the payload zero-filled
|
||||
* (cstage, gs never read). The ww half landed in F8-c7; the cstage half (a
|
||||
* global-struct-source branch — LEAQ g(SB),SI via aggarg_srcaddr, byte-copy
|
||||
* into slot+8) landed in ww-core TASK #43. Both stages now copy the full
|
||||
* payload and the .s is byte-identical.
|
||||
*
|
||||
* THE WWSTAGE FIX (ww-runtime-correct): a dedicated global-struct-source arm
|
||||
* (gated on structlookupchain so str/slice/tagged globals don't trip it)
|
||||
* zero-fills the slot, lands g(SB) in SI via aggargsrcaddr, byte-copies the
|
||||
* struct words into slot+8, and writes the variant tag. Local/literal
|
||||
* sources keep their existing arms (byte-id). cstage stays wrong → cs≠ww.
|
||||
*
|
||||
* Rows assert ww runtime-correct (field-equality check → 0) AND pin cstage's
|
||||
* deterministic residual: cstage zero-fills the payload → the fields read 0,
|
||||
* never match → the match arm returns 2. (#43 closes cs → cs==ww.)
|
||||
* row | shape | cs | ww
|
||||
* -----------+---------------------------------------------+----+----
|
||||
* widen_16 | gp:{a=5,b=6}; (pt|str)=gp; match pt fields | 2 | 0
|
||||
* widen_24 | gp:{a=5,b=6,c=7}; (tri|str)=gp; match fields | 2 | 0
|
||||
* Rows assert the field-equality match returns 0 on both stages (cs==ww).
|
||||
* row | shape | exit
|
||||
* -----------+---------------------------------------------+-----
|
||||
* widen_16 | gp:{a=5,b=6}; (pt|str)=gp; match pt fields | 0
|
||||
* widen_24 | gp:{a=5,b=6,c=7}; (tri|str)=gp; match fields | 0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -60,7 +53,7 @@ static const struct row rows[] = {
|
||||
" case str => return 3;\n"
|
||||
" };\n"
|
||||
"};\n",
|
||||
2, 0 },
|
||||
0, 0 },
|
||||
|
||||
{ "widen_24",
|
||||
"package main;\n"
|
||||
@@ -73,7 +66,7 @@ static const struct row rows[] = {
|
||||
" case str => return 3;\n"
|
||||
" };\n"
|
||||
"};\n",
|
||||
2, 0 },
|
||||
0, 0 },
|
||||
};
|
||||
|
||||
/* run_build — build+run `src` via `driver`; returns the binary's exit
|
||||
|
||||
Reference in New Issue
Block a user