From 8e86eea15998045b3d9746616ce3668051dc014b Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 27 Oct 2026 21:33:48 +0800 Subject: [PATCH] fix(codegen): keep unary constant folding within the operand width --- App/lib/core/Gen/Expr/ExprGenOps.vp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 96f02ce..e5496cd 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -781,7 +781,15 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 触发“隐式窄化禁止”,尽管其数值完全落在 i8 内(隐式窄化的“编译期常量”豁免失效)。 operand_bits: int = self.get_llvm_type_bits(operand.Ty) if operand_bits != 0 and operand.IsConst == 1: - return mlirlite.const_int(pool, operand_bits, -operand.IntVal) + # Keep the folded value inside the operand's accepted literal range + # [-2^(N-1), 2^N-1]: -1 stays -1, while -(-128) / -200 wrap to the N-bit pattern + # instead of emitting an unparsable wide value. + neg_c: int64 = -operand.IntVal + if operand_bits < 64: + neg_lo: int64 = -(int64(1) << (operand_bits - 1)) + neg_hi: int64 = (int64(1) << operand_bits) - 1 + if neg_c < neg_lo or neg_c > neg_hi: neg_c = neg_c & neg_hi + return mlirlite.const_int(pool, operand_bits, neg_c) # Integer: -x = 0 - x;0 常量必须与**当前**操作数同宽(u 类不提升后可能是 i8/i16/i32/i64) zero: mlirlite.Value* = mlirlite.const_int32(pool, 0) if operand_bits != 0 and operand_bits != 32: zero = mlirlite.const_int(pool, operand_bits, 0) @@ -800,7 +808,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): operand_bits_inv: int = self.get_llvm_type_bits(operand.Ty) # 编译期常量折叠:~c 直接产出常量并保持 IsConst(与 -c 相同的窄化豁免口径) if operand_bits_inv != 0 and operand.IsConst == 1: - return mlirlite.const_int(pool, operand_bits_inv, operand.IntVal ^ -1) + # ~0x80 is -129 in the wide domain; for i8 emit 0x7F (127) instead. Values that + # already fit the literal range (e.g. ~0 = -1) are left untouched. + inv_c: int64 = operand.IntVal ^ -1 + if operand_bits_inv < 64: + inv_lo: int64 = -(int64(1) << (operand_bits_inv - 1)) + inv_hi: int64 = (int64(1) << operand_bits_inv) - 1 + if inv_c < inv_lo or inv_c > inv_hi: inv_c = inv_c & inv_hi + return mlirlite.const_int(pool, operand_bits_inv, inv_c) # -1 掩码必须与**当前**操作数同宽(u 类不提升后可能是 i8/i16/i32/i64) neg1: mlirlite.Value* = mlirlite.const_int32(pool, -1) if operand_bits_inv != 0 and operand_bits_inv != 32: neg1 = mlirlite.const_int(pool, operand_bits_inv, -1)