w6c+wwstage: aggregate let-init copy from a struct-DEF global (#268 reviewer)
The fold-1b unified arm (bb2f4e1) added an N_IDENT addressable-rhs source
setup, but the two stages gated the GLOBAL case differently: cstage used
let_islet || def_isarraydef, wwstage used isletvar || deflookup (ANY def).
On a struct-typed `def` used as an aggregate-copy rhs (`let c: T = G`)
wwstage copied the whole value (correct) while cstage truncated to the 8B
scalar tail — a cs!=ww divergence (rule-10). A struct-LET global already
copies on both, so the def gap was also an internal cstage inconsistency.
Struct defs are first-class laid-out aggregates (DATA storage + field
load, #129 A.2/A.3), so converge on the correct full copy on both: add
def_isstructdef to cstage's predicate and replace wwstage's broad
deflookup with the def_is{array,struct}def pairing already held identical
in defisaddressable. 949 +2 rows (array-def + struct-def global, full
readback, byteid=1).
This commit is contained in:
@@ -8793,8 +8793,15 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
|||||||
ins2(c, A_LEAQ, amem(D_BP, soff),
|
ins2(c, A_LEAQ, amem(D_BP, soff),
|
||||||
areg(D_SI));
|
areg(D_SI));
|
||||||
havesrc = 1;
|
havesrc = 1;
|
||||||
|
/* the laid-out-aggregate globals (#129
|
||||||
|
* A.2/A.3): a let, an array def, or a struct
|
||||||
|
* def. Struct defs copy here exactly as
|
||||||
|
* struct-let globals do; omitting def_is-
|
||||||
|
* structdef truncated the def case alone and
|
||||||
|
* diverged from wwstage (rule-10). */
|
||||||
} else if (let_islet(n->rhs->str)
|
} else if (let_islet(n->rhs->str)
|
||||||
|| def_isarraydef(n->rhs->str)) {
|
|| def_isarraydef(n->rhs->str)
|
||||||
|
|| def_isstructdef(n->rhs->str)) {
|
||||||
ins2(c, A_LEAQ, masym(c, n->rhs->str),
|
ins2(c, A_LEAQ, masym(c, n->rhs->str),
|
||||||
areg(D_SI));
|
areg(D_SI));
|
||||||
havesrc = 1;
|
havesrc = 1;
|
||||||
|
|||||||
@@ -28906,8 +28906,20 @@ fn cglet(c: *cgen, n: *node) void = {
|
|||||||
emitline("(BP), SI\n");
|
emitline("(BP), SI\n");
|
||||||
havesrc = true;
|
havesrc = true;
|
||||||
} else {
|
} else {
|
||||||
if (isletvar(c, rhs.str)
|
// rule-10: the addressable-def set must
|
||||||
|| deflookup(c, rhs.str)) {
|
// equal cstage's let_islet ||
|
||||||
|
// def_isarraydef || def_isstructdef —
|
||||||
|
// the laid-out-aggregate globals (#129
|
||||||
|
// A.2/A.3). Bare deflookup (any def)
|
||||||
|
// over-copies struct-defs on wwstage
|
||||||
|
// only; mirror the defisaddressable
|
||||||
|
// pairing instead.
|
||||||
|
let aggdtn: *node = defvartnode(c, rhs.str);
|
||||||
|
let aggisdef: bool = defvarstructinfo(c, rhs.str) != nil;
|
||||||
|
if (aggdtn != nil) {
|
||||||
|
if (aggdtn.kind == nkind.N_TARRAY) { aggisdef = true; };
|
||||||
|
};
|
||||||
|
if (isletvar(c, rhs.str) || aggisdef) {
|
||||||
emitline("\tLEAQ\t");
|
emitline("\tLEAQ\t");
|
||||||
emitsymname(c, rhs.str);
|
emitsymname(c, rhs.str);
|
||||||
emitline("(SB), SI\n");
|
emitline("(SB), SI\n");
|
||||||
|
|||||||
@@ -1766,8 +1766,20 @@ fn cglet(c: *cgen, n: *node) void = {
|
|||||||
emitline("(BP), SI\n");
|
emitline("(BP), SI\n");
|
||||||
havesrc = true;
|
havesrc = true;
|
||||||
} else {
|
} else {
|
||||||
if (isletvar(c, rhs.str)
|
// rule-10: the addressable-def set must
|
||||||
|| deflookup(c, rhs.str)) {
|
// equal cstage's let_islet ||
|
||||||
|
// def_isarraydef || def_isstructdef —
|
||||||
|
// the laid-out-aggregate globals (#129
|
||||||
|
// A.2/A.3). Bare deflookup (any def)
|
||||||
|
// over-copies struct-defs on wwstage
|
||||||
|
// only; mirror the defisaddressable
|
||||||
|
// pairing instead.
|
||||||
|
let aggdtn: *node = defvartnode(c, rhs.str);
|
||||||
|
let aggisdef: bool = defvarstructinfo(c, rhs.str) != nil;
|
||||||
|
if (aggdtn != nil) {
|
||||||
|
if (aggdtn.kind == nkind.N_TARRAY) { aggisdef = true; };
|
||||||
|
};
|
||||||
|
if (isletvar(c, rhs.str) || aggisdef) {
|
||||||
emitline("\tLEAQ\t");
|
emitline("\tLEAQ\t");
|
||||||
emitsymname(c, rhs.str);
|
emitsymname(c, rhs.str);
|
||||||
emitline("(SB), SI\n");
|
emitline("(SB), SI\n");
|
||||||
|
|||||||
@@ -28906,8 +28906,20 @@ fn cglet(c: *cgen, n: *node) void = {
|
|||||||
emitline("(BP), SI\n");
|
emitline("(BP), SI\n");
|
||||||
havesrc = true;
|
havesrc = true;
|
||||||
} else {
|
} else {
|
||||||
if (isletvar(c, rhs.str)
|
// rule-10: the addressable-def set must
|
||||||
|| deflookup(c, rhs.str)) {
|
// equal cstage's let_islet ||
|
||||||
|
// def_isarraydef || def_isstructdef —
|
||||||
|
// the laid-out-aggregate globals (#129
|
||||||
|
// A.2/A.3). Bare deflookup (any def)
|
||||||
|
// over-copies struct-defs on wwstage
|
||||||
|
// only; mirror the defisaddressable
|
||||||
|
// pairing instead.
|
||||||
|
let aggdtn: *node = defvartnode(c, rhs.str);
|
||||||
|
let aggisdef: bool = defvarstructinfo(c, rhs.str) != nil;
|
||||||
|
if (aggdtn != nil) {
|
||||||
|
if (aggdtn.kind == nkind.N_TARRAY) { aggisdef = true; };
|
||||||
|
};
|
||||||
|
if (isletvar(c, rhs.str) || aggisdef) {
|
||||||
emitline("\tLEAQ\t");
|
emitline("\tLEAQ\t");
|
||||||
emitsymname(c, rhs.str);
|
emitsymname(c, rhs.str);
|
||||||
emitline("(SB), SI\n");
|
emitline("(SB), SI\n");
|
||||||
|
|||||||
@@ -930,6 +930,30 @@ static const struct row rows[] = {
|
|||||||
" return (c.m[0]+c.m[1]+c.m[2]+c.m[3]\n"
|
" return (c.m[0]+c.m[1]+c.m[2]+c.m[3]\n"
|
||||||
" +c.m[4]+c.m[5]+c.m[6]+c.m[7]): i32;\n"
|
" +c.m[4]+c.m[5]+c.m[6]+c.m[7]): i32;\n"
|
||||||
"};\n", 36, 1 },
|
"};\n", 36, 1 },
|
||||||
|
/* #268 reviewer: the addressable-rhs N_IDENT axis also covers a
|
||||||
|
* laid-out-aggregate GLOBAL (#129 A.2/A.3) — an array `def` and a
|
||||||
|
* struct `def`, both DATA-stored and LEAQ'd by symbol. The struct-
|
||||||
|
* def case was the one cs!=ww divergence the unified arm shipped:
|
||||||
|
* wwstage's deflookup (any def) copied it while cstage's def_is-
|
||||||
|
* arraydef alone truncated, so they diverged (a struct-LET global
|
||||||
|
* already copied on both, making the def gap an inconsistency).
|
||||||
|
* Aligned both to copy via the def_is{array,struct}def pairing held
|
||||||
|
* identical to defisaddressable. Full readback; byteid=1. */
|
||||||
|
{ "arraydef_global",
|
||||||
|
"package main;\n"
|
||||||
|
"def G: [4]u32 = [11u32, 22u32, 33u32, 44u32];\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
" let c: [4]u32 = G;\n"
|
||||||
|
" return (c[0]+c[1]+c[2]+c[3]): i32;\n"
|
||||||
|
"};\n", 110, 1 },
|
||||||
|
{ "structdef_global",
|
||||||
|
"package main;\n"
|
||||||
|
"type T = struct { a: u32, b: u32, c: u32, d: u32 };\n"
|
||||||
|
"def G: T = T { a = 10u32, b = 20u32, c = 30u32, d = 40u32 };\n"
|
||||||
|
"export fn main() i32 = {\n"
|
||||||
|
" let c: T = G;\n"
|
||||||
|
" return (c.a+c.b+c.c+c.d): i32;\n"
|
||||||
|
"};\n", 100, 1 },
|
||||||
{ NULL, NULL, 0, 0 }
|
{ NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user