diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index d547d42..d019bc7 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -1332,6 +1332,42 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): lhs_fbits: int = self.get_llvm_float_bits(lhs.Ty) rhs_fbits: int = self.get_llvm_float_bits(rhs.Ty) + # 纯常量整型算式(两侧都是编译期整型常量):按**精确值**折叠并按值定宽, + # 禁止按操作数的最小宽度回绕(现场:`1024 * 1024 * 4` 按 i16 算成 0 ⇒ + # WINBUF_MAX_BYTES=0 ⇒ 窗口缓冲只剩几字节 ⇒ 内核 memcpy 240KB 越界读/三重故障)。 + if lhs_bits > 0 and rhs_bits > 0 and lhs.IsConst == 1 and rhs.IsConst == 1: + cf_ok: int = 1 + cf_v: int64 = 0 + if op == ast.OpKind.Add: cf_v = lhs.IntVal + rhs.IntVal + elif op == ast.OpKind.Sub: cf_v = lhs.IntVal - rhs.IntVal + elif op == ast.OpKind.Mult: cf_v = lhs.IntVal * rhs.IntVal + elif op == ast.OpKind.BitOr: cf_v = lhs.IntVal | rhs.IntVal + elif op == ast.OpKind.BitAnd: cf_v = lhs.IntVal & rhs.IntVal + elif op == ast.OpKind.BitXor: cf_v = lhs.IntVal ^ rhs.IntVal + elif op == ast.OpKind.LShift or op == ast.OpKind.RShift: + if rhs.IntVal >= 0 and rhs.IntVal < 64: + if op == ast.OpKind.LShift: cf_v = lhs.IntVal << rhs.IntVal + else: cf_v = lhs.IntVal >> rhs.IntVal + else: cf_ok = 0 + else: cf_ok = 0 + if cf_ok != 0: + # 定宽:下限取操作数较宽者,只有精确值装不下才加宽(避免把 `A + 1` 这类 + # 常量算式整体抬成 i64,引出新的“隐式窄化”报错)。 + cf_w: int = lhs_bits if lhs_bits > rhs_bits else rhs_bits + if cf_v != 0: + t_cf: int64 = cf_v + if cf_v < 0: t_cf = cf_v ^ int64(-1) + vw_cf: int = 1 # 符号位 + while t_cf != 0: + vw_cf += 1 + t_cf = t_cf >> 1 + if vw_cf > cf_w: cf_w = vw_cf + if cf_w <= 8: cf_w = 8 + elif cf_w <= 16: cf_w = 16 + elif cf_w <= 32: cf_w = 32 + else: cf_w = 64 + return mlirlite.const_int(pool, cf_w, cf_v) + # Float operation: use float instructions when either operand is float (must precede pointer arithmetic, since float has 0 int bits and would be mistaken for a pointer). if lhs_fbits != 0 or rhs_fbits != 0: # Determine the target float type (use the larger bit width)