From 74fafb3b567320ef153de2cf0f597e32fbcda432 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 12 Oct 2026 18:25:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20=E6=95=B4=E5=9E=8B=E5=AD=97?= =?UTF-8?q?=E9=9D=A2=E9=87=8F=E5=AE=BD=E5=BA=A6=E6=8C=89=E5=80=BC=E6=8E=A8?= =?UTF-8?q?=E5=AF=BC=EF=BC=88=E6=96=B0=E5=A2=9E=20u32=20=E6=A1=A3=EF=BC=89?= =?UTF-8?q?+=20=E6=98=BE=E5=BC=8F=E5=AE=BD=E5=BA=A6=E4=B8=A5=E6=A0=BC?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Expr/ExprGenConst.vp | 35 +++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Expr/ExprGenConst.vp b/App/lib/core/Gen/Expr/ExprGenConst.vp index c6427b7..36fff3c 100644 --- a/App/lib/core/Gen/Expr/ExprGenConst.vp +++ b/App/lib/core/Gen/Expr/ExprGenConst.vp @@ -24,7 +24,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): if escaped is None: return None slen: sizet = string.strlen(str_val) - count: int = slen + 1 + count: int = int(slen + 1) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) arr_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty, count) @@ -60,6 +60,25 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): bc: mlirlite.Value* = mlirlite.build_bitcast(builder, gv_ref, i8_ptr_ty) return bc + # _explicit_width_int_const - 显式宽度字面量(`123_int32` / `0xFFFFFFFF_uint32`): + # 按声明宽度出常量;值必须落在该宽度的可表示范围(有符号 [-2^(w-1), 2^(w-1)-1];无符号 [0, 2^w-1]), + # 越界编译期 fail-fast(不允许隐式截断)。w==64 时 int64 全域都合法。 + def _explicit_width_int_const(self, pool: memhub.MemBuddy*, node: ast.AST*, w: int, is_unsigned: int, iv: int64) -> mlirlite.Value*: + """Explicit-width integer literal: strict range check, then a constant of exactly w bits.""" + ok: int = 1 + if is_unsigned != 0: + if w < 64 and iv < 0: ok = 0 + elif w <= 62 and iv > (int64(1) << w) - 1: ok = 0 + else: + if w < 64: + lo: int64 = -(int64(1) << (w - 1)) + hi: int64 = (int64(1) << (w - 1)) - 1 + if iv < lo or iv > hi: ok = 0 + if ok == 0: + wname: str = "int" + if is_unsigned != 0: wname = "uint" + self.Gen.TypeGenErr.fatal_error(node, f"integer literal {iv} does not fit the explicit width {wname}{w} (it would truncate); use a wider suffix or an explicit cast", "OverflowError") + return mlirlite.const_int(pool, w, iv) # Translate constant expressions def translate_constant(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None) -> mlirlite.Value*: """Translate a constant node (int/str/bool).""" @@ -70,7 +89,19 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): # Bit width: (1) if the target context is >32-bit int, use i64 directly - required # since atoll wraps 0xFFFF... to -1 as signed int64; (2) else i64 if out of i32 range, otherwise i32. iv: int64 = cn.int_val + # 显式宽度后缀(_int/_uint/_i/_u):按声明宽度出常量并严格校验不截断 + if cn.int_width > 0: return self._explicit_width_int_const(pool, node, cn.int_width, cn.int_unsigned, iv) if target_ty is not None and self.is_ptr_type(target_ty) == 0 and self.get_llvm_type_bits(target_ty) > 32: return mlirlite.const_int64(pool, iv) + # 位宽按值推导:i32 放不下、但 u32 放得下的字面量归为 32 位(u32)常量,而不是一律落 64 位 + # (否则 `crc ^ 0xFFFFFFFF` 的异或会变成 64 位,赋值回 32 位 uint 时报“隐式窄化禁止”)。 + # 文本用有符号等价(LLVM/MLIR 惯例,避免越界字面量);IntVal 保留无符号真值, + # 使窄化检查按真实数值判定,不静默截断。 + if iv > 2147483647 and iv <= 4294967295: + ty32: mlirlite.LLVMType* = mlirlite.Int32(pool) + nm32: str = pool.alloc(32) + if nm32 is None: return mlirlite.const_int32(pool, iv) + viperlib.snprintf(nm32, 32, "%lld", iv - 4294967296) + return mlirlite.ConstInt(pool, ty32, iv, nm32) if iv > 2147483647 or iv < -2147483648: return mlirlite.const_int64(pool, iv) return mlirlite.const_int32(pool, iv) elif cn.const_kind == ast.CONST_FLOAT: @@ -267,7 +298,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans) # Translate the remaining elements - for i in range(1, elts_count): + for i in range(1, int(elts_count)): elem_node_i: ast.AST* = elts.get(i) elem_val_i: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node_i, None, 0, trans) if elem_val_i is not None: