From 5f1d2c3300bf35ecb9abb9f0f9f259c196699438 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 14 Oct 2026 20:57:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpc):=20=E6=98=BE=E5=BC=8F=E5=BC=BA?= =?UTF-8?q?=E8=BD=AC=E5=8A=A0=E5=AE=BD=E7=94=A8=20sext=E3=80=81=E7=AA=84?= =?UTF-8?q?=E5=8C=96=E7=94=A8=20trunc=EF=BC=8C=E4=B8=8D=E5=86=8D=E8=A2=AB?= =?UTF-8?q?=E9=9A=90=E5=BC=8F=E7=AA=84=E5=8C=96=E7=A6=81=E4=BB=A4=E6=8B=A6?= =?UTF-8?q?=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上一轮把显式强转也统一走 _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)。 --- lib/core/Handles/HandlesExprCall.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index fa5a5a3..3ef2fa3 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -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):