diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 9e73006..5985c58 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -569,9 +569,16 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # -x # Float type uses fneg (emit fneg directly to avoid 0.0 - x type mismatch) operand_fbits: int = self.get_llvm_float_bits(operand.Ty) - if operand_fbits > 0: return mlirlite.build_fneg(builder, operand) - # Integer: -x = 0 - x, choosing the zero constant by bit width (avoid i32/i64 mismatch) + if operand_fbits > 0: + # 编译期常量折叠:-c 直接产出常量并保持 IsConst + if operand.IsConst == 1: return mlirlite.ConstFloat(pool, operand.Ty, -operand.FloatVal) + return mlirlite.build_fneg(builder, operand) + # 编译期常量折叠:-c 直接产出常量(IsConst=1)。否则 `v: int8 = -50` 会被当成运行时 i32 值, + # 触发“隐式窄化禁止”,尽管其数值完全落在 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) + # Integer: -x = 0 - x, choosing the zero constant by bit width (avoid i32/i64 mismatch) zero: mlirlite.Value* = mlirlite.const_int32(pool, 0) if operand_bits == 64: zero = mlirlite.const_int64(pool, 0) elif operand_bits > 0 and operand_bits != 32: @@ -590,6 +597,9 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif uo.op == ast.OpKind.Invert: # ~x = x ^ -1 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) neg1: mlirlite.Value* = mlirlite.const_int32(pool, -1) if operand_bits_inv == 64: neg1 = mlirlite.const_int64(pool, -1) return mlirlite.build_xor(builder, operand, neg1)