wcc/cgen: route same-type tagged-cast return through the widener (wwstage align to cstage)

A same-type tagged cast return (`return x: u`, u == fnret) emitted tag=0
(a 2nd-variant value returned the wrong payload). Route it through the
widener (needswiden when N_CAST && ru1==fu1, beside S1's ru1!=fu1) which
peels the identity cast internally -> correct; same-type non-cast stays on
the passthrough. Byte-id-neutral. test/wcc/837.
This commit is contained in:
2026-06-09 19:07:57 +09:00
parent 08ccb734b2
commit 90452a8364
5 changed files with 251 additions and 0 deletions

View File

@@ -35057,6 +35057,24 @@ fn cgreturn(c: *cgen, n: *node) void = {
if (ru1.kind == tykind.TY_TAGGED && ru1 != fu1) {
needswiden = true;
};
// S3/#35: a SAME-TYPE tagged CAST (ru1 == fu1,
// rhs an N_CAST) routes through the widener too.
// cstage keeps the N_CAST out of the srcreg
// passthrough (kind != N_CALL/INDEX/DOT) and the
// widen branch peels the identity cast internally
// (cg_widen_tagged_store cg_tagged_castpeel,
// cgen.c:2553), so cs emits the scratch-widen (NOT
// passthrough) for `return v: u` over an ident/
// call/dot source. ww's forwardtagged keys on
// rhs.kind (N_CAST uncovered), so the same-type
// cast fell to the scalar shuffle and synthesized
// tag 0 (silent). The N_CAST guard mirrors cstage's
// "N_CAST defeats srcreg"; peeling here instead
// would reroute a call/dot source to passthrough
// and break byte-id.
if (rhs.kind == nkind.N_CAST && ru1.kind == tykind.TY_TAGGED && ru1 == fu1) {
needswiden = true;
};
};
};
};