fix(viperc): 运行期纯常量整型算式按精确值折叠并按值定宽,禁止最小宽度回绕
- 现场:`1024 * 1024 * 4` 在表达式侧按最小宽度(i16)运算,1024×1024 先回绕成 0 ⇒ 常量变 0(WINBUF_MAX_BYTES=0 ⇒ 窗口缓冲只剩几字节 ⇒ 内核 memcpy 240KB 越界读 → 三重故障) - 在 translate_binop 取到操作数类型后加入纯常量折叠:+ - * | & ^ << >> 两侧都是编译期整型常量时按精确值求结果,并按“能精确容纳该值的最小合法宽度(下限取操作数较宽者)”定宽、向上取 8/16/32/64;只有装不下才加宽(与61f23d9的静态求值器同口径) - 与61f23d9合起来:静态 define 求值与运行期常量算式都不再按最小宽度回绕
This commit is contained in:
1 parent
61f23d99a1
commit
d09b79995d
1 file changed
+36
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user