fix(gen): 常量适配限定为位运算,算术一律按 C 语义拓宽(修 i8 乘法回绕致 memhub 不变式误报)

This commit is contained in:
TermiNexus committed 2026-10-12 19:40:13 +08:00
1 parent e7b05c6a3d
commit 001f8afc37
1 file changed
+7 -4
+7 -4
View File
@@ -1268,14 +1268,17 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
else: rhs = mlirlite.build_trunc(builder, rhs, lhs.Ty)
rhs_bits = lhs_bits
else:
# 「常量适配」只对**位运算(& | ^)**生效:位运算结果不会超出参与值的位宽,把能无损落进另一侧的
# 常量降下来是安全的。**算术(+ - * / %)不做适配**——窄位宽下会回绕(如 define 的
# `(MEMBUDDY_MAX_ORDERS + 1) * 8`:i8(32)+1 → 33、再 ×8 溢出成 8),必须按 C 语义把窄操作数拓宽。
is_bitwise_op: int = 0
if op == ast.OpKind.BitAnd or op == ast.OpKind.BitOr or op == ast.OpKind.BitXor: is_bitwise_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_bitwise_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_bitwise_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)