wcc_ww/cgen: #55 tagged-source arg-widen into wider tagged slot (align-up)
wwstage pushargsrev treated a narrower tagged-union argument widened into
a wider tagged param slot as a concrete variant: taggedvariantindex<0
clamped the tag to 0 and pushed word0 only (deref/index/dot silent-wrong;
ident ran correct only by prefix-union tag-index luck). cstage is correct
(cg_widen_tagged_push routes src_is_tagged unconditionally); align ww UP.
Three arms in cgenutil.ww, all mirroring cstage cgen.c:
- slot-gate the ident aistagged short-circuit so a slot-differ tagged
ident falls to the widen path instead of the raw 2-word push;
- route a tagged source in the widensz>0 arm through @tagscr +
cgwidentaggedstore + push high->low (cgen.c cg_widen_tagged_push);
- cgwidentaggedstore cursor arm (<=32B INDEX/DOT) spills by source
width, zero-pads, and tag-remaps (cgen.c 2698-2714) — was dst-slot
spill of stale high regs with no pad and no remap.
Same-slot tagged->tagged is byte-id-neutral by construction (empty pad +
identity remap). cstage untouched; 4 legs x {aligned, misaligned-tag}
converge ww->cs byte-identical. Pin 944_tagged_widen_arg_run.
This commit is contained in:
@@ -16402,7 +16402,23 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node, memphase: bool) i32 = {
|
||||
if (arg.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, arg.str);
|
||||
if (lc != nil) {
|
||||
aistagged = istaggedtype(c, lc.tnode);
|
||||
// #55: only treat a tagged ident as
|
||||
// "already tagged" (natural push, no remap)
|
||||
// when its slot MATCHES the param. On slot-
|
||||
// DIFFER the source is a NARROWER union widened
|
||||
// into a wider one — fall to the widen scratch
|
||||
// + tag-remap below (the slot-gated INDEX/DOT/
|
||||
// STAR arms' twin). Pre-#55 the ungated TRUE
|
||||
// natural-pushed the narrower box's words with
|
||||
// no remap (aligned-tag LUCK, misaligned-tag
|
||||
// wrong). cstage routes every tagged source
|
||||
// through cg_widen_tagged_store (cmd/w6c/
|
||||
// cgen.c:2982 src_is_tagged).
|
||||
if (istaggedtype(c, lc.tnode)) {
|
||||
if (slotsize(c, lc.tnode) == slotsize(c, ptype)) {
|
||||
aistagged = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// #21: a CALL returning a tagged-union must
|
||||
@@ -16496,13 +16512,26 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node, memphase: bool) i32 = {
|
||||
let argtup: *tinfo = arg.type_: *tinfo;
|
||||
argtup = tichase(argtup);
|
||||
let argistuple: bool = false;
|
||||
// #55: a tagged SOURCE widened into a wider/reordered tagged param
|
||||
// (slot-DIFFER — the ident/deref/index/dot legs that fell past the
|
||||
// slot-gated aistagged arms above) has no direct-push shape: the
|
||||
// scalar fast arm below would box word0 with a tag clamped to 0,
|
||||
// dropping the real tag + high words and skipping the variant
|
||||
// remap. Route through the @tagscr store, whose ident/memread/
|
||||
// cursor arms copy the box + tag-remap. Mirrors cstage
|
||||
// cg_widen_tagged_push's unconditional src_is_tagged scratch
|
||||
// routing (cmd/w6c/cgen.c:2982).
|
||||
let argistagged: bool = false;
|
||||
if (argtup != nil) {
|
||||
if (argtup.kind == tykind.TY_TUPLE) {
|
||||
argistuple = true;
|
||||
};
|
||||
if (argtup.kind == tykind.TY_TAGGED) {
|
||||
argistagged = true;
|
||||
};
|
||||
};
|
||||
let pname: str = rhsstructpayload(c, arg);
|
||||
if (pname.len > 0 || argistuple) {
|
||||
if (pname.len > 0 || argistuple || argistagged) {
|
||||
let ptype: *node = param.lhs;
|
||||
let scroff: i32 = tagscradd(c, widensz);
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
@@ -20017,25 +20046,48 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
cgwidentagremap(c, dt, src.type_: *tinfo, slot_off);
|
||||
return;
|
||||
};
|
||||
// #55: spill the AX/DX/CX/R8 cursor by the SOURCE box width
|
||||
// (su.size), zero-pad to the dst slot, then tag-remap — the
|
||||
// cursor twin of the ident / memread arms above. Pre-#55 it
|
||||
// spilled by slot_sz (reading STALE high regs when the source is
|
||||
// narrower) and skipped the pad + remap, so an INDEX/DOT tagged
|
||||
// element widened into a wider/reordered union pushed a stale word
|
||||
// and the un-remapped source tag (silent cs!=ww). Mirrors cstage
|
||||
// cg_widen_tagged_store's cursor arm + shared pad/remap tail
|
||||
// (cmd/w6c/cgen.c:2695-2714). Same-slot source (ssz==slot_sz)
|
||||
// leaves the pad empty + an identity remap, so the emission is
|
||||
// byte-identical to the prior arm for the exact-slot callers.
|
||||
cgexpr(c, src);
|
||||
let ssz: i32 = su.size: i32;
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(slot_off: i64);
|
||||
emitline("(BP)\n");
|
||||
if (slot_sz > 8) {
|
||||
if (ssz > 8) {
|
||||
emitline("\tMOVQ\tDX, ");
|
||||
emitoff((slot_off + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (slot_sz > 16) {
|
||||
if (ssz > 16) {
|
||||
emitline("\tMOVQ\tCX, ");
|
||||
emitoff((slot_off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (slot_sz > 24) {
|
||||
if (ssz > 24) {
|
||||
emitline("\tMOVQ\tR8, ");
|
||||
emitoff((slot_off + 24): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (ssz < slot_sz) {
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let pp: i32 = ssz;
|
||||
for (pp < slot_sz) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((slot_off + pp): i64);
|
||||
emitline("(BP)\n");
|
||||
pp += 8;
|
||||
};
|
||||
};
|
||||
cgwidentagremap(c, dt, src.type_: *tinfo, slot_off);
|
||||
return;
|
||||
};
|
||||
// #37 (rule 7): a >32B TAGGED source of a kind the resolver arms
|
||||
|
||||
@@ -261,7 +261,23 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node, memphase: bool) i32 = {
|
||||
if (arg.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, arg.str);
|
||||
if (lc != nil) {
|
||||
aistagged = istaggedtype(c, lc.tnode);
|
||||
// #55: only treat a tagged ident as
|
||||
// "already tagged" (natural push, no remap)
|
||||
// when its slot MATCHES the param. On slot-
|
||||
// DIFFER the source is a NARROWER union widened
|
||||
// into a wider one — fall to the widen scratch
|
||||
// + tag-remap below (the slot-gated INDEX/DOT/
|
||||
// STAR arms' twin). Pre-#55 the ungated TRUE
|
||||
// natural-pushed the narrower box's words with
|
||||
// no remap (aligned-tag LUCK, misaligned-tag
|
||||
// wrong). cstage routes every tagged source
|
||||
// through cg_widen_tagged_store (cmd/w6c/
|
||||
// cgen.c:2982 src_is_tagged).
|
||||
if (istaggedtype(c, lc.tnode)) {
|
||||
if (slotsize(c, lc.tnode) == slotsize(c, ptype)) {
|
||||
aistagged = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// #21: a CALL returning a tagged-union must
|
||||
@@ -355,13 +371,26 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node, memphase: bool) i32 = {
|
||||
let argtup: *tinfo = arg.type_: *tinfo;
|
||||
argtup = tichase(argtup);
|
||||
let argistuple: bool = false;
|
||||
// #55: a tagged SOURCE widened into a wider/reordered tagged param
|
||||
// (slot-DIFFER — the ident/deref/index/dot legs that fell past the
|
||||
// slot-gated aistagged arms above) has no direct-push shape: the
|
||||
// scalar fast arm below would box word0 with a tag clamped to 0,
|
||||
// dropping the real tag + high words and skipping the variant
|
||||
// remap. Route through the @tagscr store, whose ident/memread/
|
||||
// cursor arms copy the box + tag-remap. Mirrors cstage
|
||||
// cg_widen_tagged_push's unconditional src_is_tagged scratch
|
||||
// routing (cmd/w6c/cgen.c:2982).
|
||||
let argistagged: bool = false;
|
||||
if (argtup != nil) {
|
||||
if (argtup.kind == tykind.TY_TUPLE) {
|
||||
argistuple = true;
|
||||
};
|
||||
if (argtup.kind == tykind.TY_TAGGED) {
|
||||
argistagged = true;
|
||||
};
|
||||
};
|
||||
let pname: str = rhsstructpayload(c, arg);
|
||||
if (pname.len > 0 || argistuple) {
|
||||
if (pname.len > 0 || argistuple || argistagged) {
|
||||
let ptype: *node = param.lhs;
|
||||
let scroff: i32 = tagscradd(c, widensz);
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
@@ -3876,25 +3905,48 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
cgwidentagremap(c, dt, src.type_: *tinfo, slot_off);
|
||||
return;
|
||||
};
|
||||
// #55: spill the AX/DX/CX/R8 cursor by the SOURCE box width
|
||||
// (su.size), zero-pad to the dst slot, then tag-remap — the
|
||||
// cursor twin of the ident / memread arms above. Pre-#55 it
|
||||
// spilled by slot_sz (reading STALE high regs when the source is
|
||||
// narrower) and skipped the pad + remap, so an INDEX/DOT tagged
|
||||
// element widened into a wider/reordered union pushed a stale word
|
||||
// and the un-remapped source tag (silent cs!=ww). Mirrors cstage
|
||||
// cg_widen_tagged_store's cursor arm + shared pad/remap tail
|
||||
// (cmd/w6c/cgen.c:2695-2714). Same-slot source (ssz==slot_sz)
|
||||
// leaves the pad empty + an identity remap, so the emission is
|
||||
// byte-identical to the prior arm for the exact-slot callers.
|
||||
cgexpr(c, src);
|
||||
let ssz: i32 = su.size: i32;
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(slot_off: i64);
|
||||
emitline("(BP)\n");
|
||||
if (slot_sz > 8) {
|
||||
if (ssz > 8) {
|
||||
emitline("\tMOVQ\tDX, ");
|
||||
emitoff((slot_off + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (slot_sz > 16) {
|
||||
if (ssz > 16) {
|
||||
emitline("\tMOVQ\tCX, ");
|
||||
emitoff((slot_off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (slot_sz > 24) {
|
||||
if (ssz > 24) {
|
||||
emitline("\tMOVQ\tR8, ");
|
||||
emitoff((slot_off + 24): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (ssz < slot_sz) {
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let pp: i32 = ssz;
|
||||
for (pp < slot_sz) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((slot_off + pp): i64);
|
||||
emitline("(BP)\n");
|
||||
pp += 8;
|
||||
};
|
||||
};
|
||||
cgwidentagremap(c, dt, src.type_: *tinfo, slot_off);
|
||||
return;
|
||||
};
|
||||
// #37 (rule 7): a >32B TAGGED source of a kind the resolver arms
|
||||
|
||||
@@ -16402,7 +16402,23 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node, memphase: bool) i32 = {
|
||||
if (arg.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, arg.str);
|
||||
if (lc != nil) {
|
||||
aistagged = istaggedtype(c, lc.tnode);
|
||||
// #55: only treat a tagged ident as
|
||||
// "already tagged" (natural push, no remap)
|
||||
// when its slot MATCHES the param. On slot-
|
||||
// DIFFER the source is a NARROWER union widened
|
||||
// into a wider one — fall to the widen scratch
|
||||
// + tag-remap below (the slot-gated INDEX/DOT/
|
||||
// STAR arms' twin). Pre-#55 the ungated TRUE
|
||||
// natural-pushed the narrower box's words with
|
||||
// no remap (aligned-tag LUCK, misaligned-tag
|
||||
// wrong). cstage routes every tagged source
|
||||
// through cg_widen_tagged_store (cmd/w6c/
|
||||
// cgen.c:2982 src_is_tagged).
|
||||
if (istaggedtype(c, lc.tnode)) {
|
||||
if (slotsize(c, lc.tnode) == slotsize(c, ptype)) {
|
||||
aistagged = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// #21: a CALL returning a tagged-union must
|
||||
@@ -16496,13 +16512,26 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node, memphase: bool) i32 = {
|
||||
let argtup: *tinfo = arg.type_: *tinfo;
|
||||
argtup = tichase(argtup);
|
||||
let argistuple: bool = false;
|
||||
// #55: a tagged SOURCE widened into a wider/reordered tagged param
|
||||
// (slot-DIFFER — the ident/deref/index/dot legs that fell past the
|
||||
// slot-gated aistagged arms above) has no direct-push shape: the
|
||||
// scalar fast arm below would box word0 with a tag clamped to 0,
|
||||
// dropping the real tag + high words and skipping the variant
|
||||
// remap. Route through the @tagscr store, whose ident/memread/
|
||||
// cursor arms copy the box + tag-remap. Mirrors cstage
|
||||
// cg_widen_tagged_push's unconditional src_is_tagged scratch
|
||||
// routing (cmd/w6c/cgen.c:2982).
|
||||
let argistagged: bool = false;
|
||||
if (argtup != nil) {
|
||||
if (argtup.kind == tykind.TY_TUPLE) {
|
||||
argistuple = true;
|
||||
};
|
||||
if (argtup.kind == tykind.TY_TAGGED) {
|
||||
argistagged = true;
|
||||
};
|
||||
};
|
||||
let pname: str = rhsstructpayload(c, arg);
|
||||
if (pname.len > 0 || argistuple) {
|
||||
if (pname.len > 0 || argistuple || argistagged) {
|
||||
let ptype: *node = param.lhs;
|
||||
let scroff: i32 = tagscradd(c, widensz);
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
@@ -20017,25 +20046,48 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
cgwidentagremap(c, dt, src.type_: *tinfo, slot_off);
|
||||
return;
|
||||
};
|
||||
// #55: spill the AX/DX/CX/R8 cursor by the SOURCE box width
|
||||
// (su.size), zero-pad to the dst slot, then tag-remap — the
|
||||
// cursor twin of the ident / memread arms above. Pre-#55 it
|
||||
// spilled by slot_sz (reading STALE high regs when the source is
|
||||
// narrower) and skipped the pad + remap, so an INDEX/DOT tagged
|
||||
// element widened into a wider/reordered union pushed a stale word
|
||||
// and the un-remapped source tag (silent cs!=ww). Mirrors cstage
|
||||
// cg_widen_tagged_store's cursor arm + shared pad/remap tail
|
||||
// (cmd/w6c/cgen.c:2695-2714). Same-slot source (ssz==slot_sz)
|
||||
// leaves the pad empty + an identity remap, so the emission is
|
||||
// byte-identical to the prior arm for the exact-slot callers.
|
||||
cgexpr(c, src);
|
||||
let ssz: i32 = su.size: i32;
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(slot_off: i64);
|
||||
emitline("(BP)\n");
|
||||
if (slot_sz > 8) {
|
||||
if (ssz > 8) {
|
||||
emitline("\tMOVQ\tDX, ");
|
||||
emitoff((slot_off + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (slot_sz > 16) {
|
||||
if (ssz > 16) {
|
||||
emitline("\tMOVQ\tCX, ");
|
||||
emitoff((slot_off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (slot_sz > 24) {
|
||||
if (ssz > 24) {
|
||||
emitline("\tMOVQ\tR8, ");
|
||||
emitoff((slot_off + 24): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
if (ssz < slot_sz) {
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let pp: i32 = ssz;
|
||||
for (pp < slot_sz) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((slot_off + pp): i64);
|
||||
emitline("(BP)\n");
|
||||
pp += 8;
|
||||
};
|
||||
};
|
||||
cgwidentagremap(c, dt, src.type_: *tinfo, slot_off);
|
||||
return;
|
||||
};
|
||||
// #37 (rule 7): a >32B TAGGED source of a kind the resolver arms
|
||||
|
||||
Reference in New Issue
Block a user