fix(gen): 整型字面量宽度按值推导(新增 u32 档)+ 显式宽度严格校验
This commit is contained in:
1 parent
f044d94e90
commit
74fafb3b56
1 file changed
+33
-2
@@ -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<N>/_uint<N>/_i<N>/_u<N>):按声明宽度出常量并严格校验不截断
|
||||
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:
|
||||
|
||||
Reference in new issue
Block a user