From d09b79995d59fb3d8759460c2d62ffcb90d11b96 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 14 Oct 2026 19:39:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(viperc):=20=E8=BF=90=E8=A1=8C=E6=9C=9F?= =?UTF-8?q?=E7=BA=AF=E5=B8=B8=E9=87=8F=E6=95=B4=E5=9E=8B=E7=AE=97=E5=BC=8F?= =?UTF-8?q?=E6=8C=89=E7=B2=BE=E7=A1=AE=E5=80=BC=E6=8A=98=E5=8F=A0=E5=B9=B6?= =?UTF-8?q?=E6=8C=89=E5=80=BC=E5=AE=9A=E5=AE=BD=EF=BC=8C=E7=A6=81=E6=AD=A2?= =?UTF-8?q?=E6=9C=80=E5=B0=8F=E5=AE=BD=E5=BA=A6=E5=9B=9E=E7=BB=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 现场:`1024 * 1024 * 4` 在表达式侧按最小宽度(i16)运算,1024×1024 先回绕成 0 ⇒ 常量变 0(WINBUF_MAX_BYTES=0 ⇒ 窗口缓冲只剩几字节 ⇒ 内核 memcpy 240KB 越界读 → 三重故障) - 在 translate_binop 取到操作数类型后加入纯常量折叠:+ - * | & ^ << >> 两侧都是编译期整型常量时按精确值求结果,并按“能精确容纳该值的最小合法宽度(下限取操作数较宽者)”定宽、向上取 8/16/32/64;只有装不下才加宽(与 61f23d9 的静态求值器同口径) - 与 61f23d9 合起来:静态 define 求值与运行期常量算式都不再按最小宽度回绕 --- App/lib/core/Gen/Expr/ExprGenOps.vp | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) 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)