w6c+selfhost: cgen N_CAST signed narrow + peel !T on unsigned narrow
TY_RUNE excluded — wwstage primsize skips it; task #5 will collapse both gates back to symmetric once type_isunsigned recurses TY_ENUM.
This commit is contained in:
@@ -3490,13 +3490,15 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* width (mod 2^n). Without this, `(big_u64): u32` left the
|
||||
* upper 32 bits intact and CMPQ/DIVQ misread the value.
|
||||
*
|
||||
* Unsigned targets only here. Signed-narrow targets (i8/
|
||||
* i16/i32) need MOVSBQ / MOVSWQ / MOVSXD in their reg-reg
|
||||
* form which the assembler doesn't expose yet; callers
|
||||
* that need a clean signed-narrow value either keep the
|
||||
* value in range before the cast (as strconv does with
|
||||
* an explicit bounds check) or AND the low bits manually.
|
||||
* Tracking this gap is part of the same TODO. */
|
||||
* Unsigned targets use MOVL/ANDQ to clear the high bits.
|
||||
* Signed-narrow targets (i8/i16/i32) sign-extend via
|
||||
* MOVSBQ/MOVSWQ/MOVSXD reg-reg so the sign bit propagates;
|
||||
* this is what lets `(0xFF80i64): i8` compare equal to
|
||||
* -128i64 after a widening read-back. Gated on the literal
|
||||
* TY_I8/TY_I16/TY_I32 kinds so the wwstage cgen path
|
||||
* (cgcast in cgenexpr.ww, which keys off primsize on the
|
||||
* type-name node) emits the same instructions for the same
|
||||
* inputs — that byte-identity gate is what test 993 pins. */
|
||||
if (!from_f && !to_f && n->type) {
|
||||
Type *tt = n->type;
|
||||
Type *tu = (tt && tt->kind == TY_NAMED) ? tt->under : tt;
|
||||
@@ -3509,6 +3511,15 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
ins2(c, A_ANDQ, aimm((i64)mask),
|
||||
areg(D_AX));
|
||||
}
|
||||
} else if (tu && (tu->kind == TY_I8
|
||||
|| tu->kind == TY_I16 || tu->kind == TY_I32)) {
|
||||
/* Literal-kind gate excludes TY_RUNE on purpose:
|
||||
* runes are unsigned Unicode scalars, owed to the
|
||||
* MOVL path once task #5 lands. */
|
||||
int op = A_MOVSXD;
|
||||
if (tu->kind == TY_I8) op = A_MOVSBQ;
|
||||
else if (tu->kind == TY_I16) op = A_MOVSWQ;
|
||||
ins2(c, op, areg(D_AX), areg(D_AX));
|
||||
}
|
||||
/* TY_BOOL is size 1 too; clamp to a single byte so
|
||||
* `(u32_val): bool` produces 0 or a low-byte value
|
||||
|
||||
Reference in New Issue
Block a user