diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 332a343..4f315db 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -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)