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:
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user