fix(gen): 移位按 C 语义把左操作数提升到 int,且移位数不参与常量适配(修 uchar<<8 误报)
This commit is contained in:
1 parent
65c72fd55c
commit
9d02cc4684
1 file changed
+16
-2
@@ -1229,14 +1229,28 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
lhs_bits = 32
|
||||
rhs_bits = 32
|
||||
|
||||
# 移位:C 语义先按**左操作数**做整数提升到 int(与右操作数宽度无关)。
|
||||
# 否则 `uchar(x) << 8`(8 位左操作数 + 32 位计数字面量)在下面等宽化里若被“常量适配”改了方向,
|
||||
# 会误报「移位数 8 >= 左操作数位宽 8」。
|
||||
if (op == ast.OpKind.LShift or op == ast.OpKind.RShift) and lhs_bits != 0 and lhs_bits < 32:
|
||||
i32_ty_sh: mlirlite.LLVMType* = mlirlite.Int32(pool)
|
||||
sh_probe: mlirlite.Value* = mlirlite.const_int32(pool, 0)
|
||||
if self.should_zext_widen(pool, lhs, sh_probe, lhs_node, trans) != 0: lhs = mlirlite.build_zext(builder, lhs, i32_ty_sh)
|
||||
else: lhs = self.coerce_to_type(builder, lhs, i32_ty_sh, node, trans)
|
||||
lhs_bits = 32
|
||||
|
||||
# 移位运算的右操作数是「移位数」,其宽度不参与结果类型判定(C 语义:左操作数提升到 int 即可)。
|
||||
is_shift_op: int = 0
|
||||
if op == ast.OpKind.LShift or op == ast.OpKind.RShift: is_shift_op = 1
|
||||
|
||||
if lhs_bits > rhs_bits:
|
||||
# 宽侧是「值能无损落进窄侧」的编译期常量时,把**常量**降到窄侧类型(C 语义:常量优先适配另一侧),
|
||||
# 否则 `crc(u32) ^ 0xFFFFFFFF(i64)` 会把 crc 抬成 64 位,结果再赋回 32 位时报隐式窄化。
|
||||
if self._const_fits_int_type(lhs, rhs.Ty) != 0: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans)
|
||||
if is_shift_op == 0 and self._const_fits_int_type(lhs, rhs.Ty) != 0: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans)
|
||||
elif self.should_zext_widen(pool, rhs, lhs, rhs_node, trans) != 0: rhs = mlirlite.build_zext(builder, rhs, lhs.Ty)
|
||||
else: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans)
|
||||
elif rhs_bits > lhs_bits:
|
||||
if self._const_fits_int_type(rhs, lhs.Ty) != 0: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans)
|
||||
if is_shift_op == 0 and self._const_fits_int_type(rhs, lhs.Ty) != 0: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans)
|
||||
elif self.should_zext_widen(pool, lhs, rhs, lhs_node, trans) != 0: lhs = mlirlite.build_zext(builder, lhs, rhs.Ty)
|
||||
else: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans)
|
||||
|
||||
|
||||
Reference in new issue
Block a user