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