fix(tpc): 显式强转加宽用 sext、窄化用 trunc,不再被隐式窄化禁令拦下

上一轮把显式强转也统一走 _coerce_value 后,显式窄化(如 ViperC 里 LONG(BUF_B),Windows LLP64 下 sizeof(long)==4,即 sizet/u64 -> int32)被当成隐式窄化而触发 FailFastError,导致 TPC 重编 ViperC 中断。'隐式窄化禁止' 只约束隐式路径,显式转换必须允许 trunc;同时加宽保持 sext 以免 int64(int32(-1)) 变成 4294967295。Test/IntWidthTest 新增 Test 7 覆盖该形态(12/12 PASS)。
This commit is contained in:
TermiNexus committed 2026-10-14 20:57:47 +08:00
1 parent 6b87a78239
commit 5f1d2c3300
1 file changed
+14 -15
+14 -15
View File
@@ -2473,14 +2473,13 @@ class ExprCallHandle(BaseHandle):
if ArgVal.type == TargetType:
return ArgVal
if isinstance(TargetType, ir.IntType) and isinstance(ArgVal.type, ir.IntType):
# 统一走 `_coerce_value`(隐式/显式转换的唯一收敛点):此前手写 `zext`,
# 整型加宽一律零扩展 ⇒ 负值被当无符号(现场:`int64(-1)` 里 -1 的 i32 位型
# 变成 4294967295 ⇒ `x ^ int64(-1)` 变号 ⇒ IntWidthTest Test 5 第三条
# 循环不收敛)。`_coerce_value` 加宽用 `sext` 保符号,窄化按其规则 fail-fast。
_coerced_td: ir.Value | None = Gen._coerce_value(ArgVal, TargetType, Node)
if _coerced_td is not None:
return _coerced_td
return ArgVal
if ArgVal.type.width < TargetType.width:
# **显式**强转的加宽必须保符号:此前手写 zext,负值/负数常量会被零扩展
# (现场:`int64(-1)` 变 4294967295;IntWidthTest Test 5)。
return Gen.builder.sext(ArgVal, TargetType, name=f"sext_{TypedefName}_cast")
elif ArgVal.type.width > TargetType.width:
# 显式窄化 = 截断(“隐式窄化禁止”只针对**隐式**路径,不拦显式转换)
return Gen.builder.trunc(ArgVal, TargetType, name=f"trunc_{TypedefName}_cast")
if isinstance(TargetType, ir.PointerType):
if isinstance(ArgVal.type, ir.PointerType):
return Gen.builder.bitcast(ArgVal, TargetType, name=f"bitcast_{TypedefName}_cast")
@@ -2541,13 +2540,13 @@ class ExprCallHandle(BaseHandle):
if ArgVal.type == TargetType:
return ArgVal
if isinstance(TargetType, ir.IntType) and isinstance(ArgVal.type, ir.IntType):
# 统一走 `_coerce_value`(隐式/显式转换的唯一收敛点):此前手写 `zext`,
# 整型加宽一律零扩展 ⇒ 负值被当无符号。
# 现场:`int64(-1)` → i64 4294967295 ⇒ `x ^ int64(-1)` 变号、循环不收敛
# (IntWidthTest Test 5 第三条);`_coerce_value` 加宽用 `sext` 保符号。
_coerced_b: ir.Value | None = Gen._coerce_value(ArgVal, TargetType, Node)
if _coerced_b is not None:
return _coerced_b
# builtins typedef 数值转换(int64(bool) / uint64(i32) 等):加宽保符号(sext),
# 窄化=截断(显式转换不受“隐式窄化禁止”约束)。
# 此前加宽用 zext,`int64(-1)` 会变成 4294967295(IntWidthTest Test 5)。
if ArgVal.type.width < TargetType.width:
return Gen.builder.sext(ArgVal, TargetType, name="sext_typedef_cast")
elif ArgVal.type.width > TargetType.width:
return Gen.builder.trunc(ArgVal, TargetType, name="trunc_typedef_cast")
return ArgVal
if isinstance(TargetType, ir.PointerType):
if isinstance(ArgVal.type, ir.PointerType):