cstage+test: skip redundant MOVL on u32 → enum-u32 cast (#25)
cstage's N_CAST narrow-clamp emitted `MOVL AX, AX` on u32 → enum-u32 casts. wwstage's cgcast walker steps through N_TBANG / N_TNAME alias links only; an enum's aliaslookup returns the N_TENUM body, which breaks the loop and skips the clamp. The asymmetry surfaced during #10 (lib/os/stat) when kstat.mode typed as u32 tripped the cross- stage diff; worker-stat sidestepped by typing kstat.mode as `mode`. Single-site gate: skip the narrow-clamp when the destination type is TY_ENUM. Mirrors wwstage's N_TENUM lacuna exactly. Predicate recursion (type_isint, type_isunsigned) over TY_ENUM stays intact — this is emit-side only. Wwstage unchanged. Test 710 (cast_enum_movl): 5 rows × {exit-code per driver, asm byte-id when w6c_ww built} = 10+ assertions. u32→enum-u32 headline, enum-u32→u32 reverse (pins direction-of-asymmetry), u32→enum-u8 different-width, i64→enum-i32 signed-narrow, struct-field rt mirror of `out.mode = k.mode` (the #10 trip-wire). A principled identity-width identity-sign skip across both stages is filed as #33. The lib/os.ww kstat.mode workaround revert is a sibling cleanup, not in #25 scope.
This commit is contained in:
@@ -4793,8 +4793,20 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
if (!from_f && !to_f && n->type) {
|
||||
Type *tt = n->type;
|
||||
Type *tu = (tt && tt->kind == TY_NAMED) ? tt->under : tt;
|
||||
/* Wwstage's cgcast walker only steps through N_TBANG /
|
||||
* N_TNAME alias links; an enum's `aliaslookup` returns
|
||||
* the N_TENUM body, which breaks the loop and skips the
|
||||
* clamp. Mirror that here so cstage agrees byte-for-byte
|
||||
* on a u32→enum-u32 cast (task #25). Predicate recursion
|
||||
* through TY_ENUM in `type_isint`/`type_isunsigned`
|
||||
* stays — other call sites rely on it; only this site
|
||||
* gates on TY_ENUM explicitly. Skip is by dst kind only:
|
||||
* `enum-u32 → u32` still emits the clamp, matching
|
||||
* wwstage's asymmetry. (See followup: identity-width
|
||||
* identity-sign hygiene across both stages.) */
|
||||
int dst_is_enum = tu && tu->kind == TY_ENUM;
|
||||
if (tu && type_isint(tu) && tu->size > 0
|
||||
&& tu->size < 8) {
|
||||
&& tu->size < 8 && !dst_is_enum) {
|
||||
if (type_isunsigned(tu)) {
|
||||
if (tu->size == 4) {
|
||||
ins2(c, A_MOVL,
|
||||
|
||||
Reference in New Issue
Block a user