feat(types): 禁止隐式窄化(整数 高→低)——_coerce_value 与 pointee 判据同步
与 TransPyV 同口径:_coerce_value 的 int→int 窄化分支改为 fail-fast(隐式窄化禁止),仅豁免 ① 目标 i1 真值归一化 ② 编译期常量且值落进目标位宽;_ScalarConvertLossless 的 int↔int 改为 Dst.width>=Src.width。
This commit is contained in:
1 parent
4f9c234ea8
commit
3b16334f5d
1 file changed
+17
-4
@@ -198,7 +198,7 @@ class MemoryOpsMixin:
|
||||
@staticmethod
|
||||
def _ScalarConvertLossless(Src: Any, Dst: Any) -> bool:
|
||||
"""基本标量「无损」判定(与 TransPyV `_scalar_convert_reason` 同口径,逐条照搬):
|
||||
- 整数 ↔ 整数:**所有方向都允许**(高→低是安全降级;低→高无损);
|
||||
- 整数 ↔ 整数:允许 ⇔ **目标位宽 ≥ 源位宽**(低→高无损;高→低是**有损窄化**,禁);
|
||||
- 浮点 ↔ 浮点:**所有方向都允许**;
|
||||
- 整数 → 浮点:允许 ⇔ **目标浮点位宽 ≥ 源整数位宽**(否则有损 → 禁);
|
||||
- 浮点 → 整数:**不允许**(有损 → 禁)。
|
||||
@@ -213,9 +213,9 @@ class MemoryOpsMixin:
|
||||
d_int: bool = isinstance(Dst, ir.IntType)
|
||||
s_flt: int = _FloatBits(Src)
|
||||
d_flt: int = _FloatBits(Dst)
|
||||
# 整数 ↔ 整数:高→低安全降级、低→高无损,均允许
|
||||
# 整数 ↔ 整数:低→高无损放行;高→低有损窄化,禁
|
||||
if s_int and d_int:
|
||||
return True
|
||||
return Dst.width >= Src.width
|
||||
# 浮点 ↔ 浮点:允许
|
||||
if s_flt and d_flt:
|
||||
return True
|
||||
@@ -656,7 +656,20 @@ class MemoryOpsMixin:
|
||||
# 目标 i1:真值归一化(与 bool(x)/if 条件同一判据),不是 trunc 取最低位
|
||||
if target_type.width == 1:
|
||||
return self._CoerceIntToI1(val, name="bool_norm_store")
|
||||
return self.builder.trunc(val, target_type, name="trunc_store")
|
||||
# 隐式窄化**禁止**(规则 2026-10-10 收紧,取代"整数↔整数 所有方向都允许"):
|
||||
# 位宽高→低会丢高位,必须显式 cast 或加宽目标类型。
|
||||
# 唯一豁免:源是**编译期常量且值落进目标位宽**(无信息损失)。
|
||||
if isinstance(val, ir.Constant) and isinstance(val.constant, int):
|
||||
Lo: int = -(1 << (target_type.width - 1))
|
||||
Hi: int = (1 << target_type.width) - 1
|
||||
if Lo <= val.constant <= Hi:
|
||||
return self.builder.trunc(val, target_type, name="trunc_const_store")
|
||||
from lib.core.LLVMCG.FuncGen import FailFastError
|
||||
raise FailFastError(
|
||||
f"隐式窄化禁止:{val.type.width} 位整数不能隐式赋给 {target_type.width} 位类型"
|
||||
f"(会丢高位);请显式转换(如 int32(x) / t.CInt32T(x))或把目标类型加宽"
|
||||
f"{self._DescribeValueNode(Node)}"
|
||||
)
|
||||
elif val.type.width == 1:
|
||||
# i1 是布尔值(来自 icmp/fcmp/__contains__ 归一化),无符号语义,
|
||||
# 必须用 zext 而非 sext,否则 i1 的 1 会被符号扩展为 -1
|
||||
|
||||
Reference in new issue
Block a user