fix(tpv): 类型静默退化改编译期报错 + 统一整数拓宽 zext/sext

- FuncGenDef: 有返回注解但解析失败 → fatal_error(不再静默回退 i32;无注解函数保留 i32 默认)

- TypeGenResolve: 泛型类型实参污染(T→T 自映射 / 实参含类型参数名)→ fatal_error(不再 return None 静默退化)

- ExprGenBase: coerce_to_type 窄→宽接入 _zext_or_sext_val(i1/i8 默认 zext、无符号类型名 zext、否则 sext),修正 t.CUInt32T 等无符号值被符号扩展的隐蔽数据损坏
This commit is contained in:
TermiNexus committed 2026-08-28 14:57:46 +08:00
1 parent 24ae2dc966
commit a8eb7fe5fe
11 files changed
+56 -56

No files matched your search

+1 -4
View File
@@ -826,10 +826,7 @@ class AssignGenMixin:
if cur_val is None:
# fail-fast: 目标变量当前值加载失败
self.Gen.TypeGenErr.fatal_error(
target,
f"无法加载目标变量 '{nm.id}' 的当前值",
"TypeError")
self.Gen.TypeGenErr.fatal_error(target, f"无法加载目标变量 '{nm.id}' 的当前值", "TypeError")
# 3. 翻译 RHS 值
rhs_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
-2
View File
@@ -8,11 +8,9 @@ import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HT
import lib.Stub.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
+2 -10
View File
@@ -1,22 +1,14 @@
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HT
import lib.Stub.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.Call.CallGenBase as CallGenBase
import lib.core.Gen.GenApi as GenApi
import lib.core.Gen.GenTypes as GenTypes
from . import CallGenBase
# ============================================================
+2 -12
View File
@@ -1,4 +1,3 @@
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
@@ -7,23 +6,14 @@ import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HT
import lib.Stub.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.Call.CallGenBase as CallGenBase
import lib.core.Gen.GenTypes as GenTypes
from . import CallGenBase
# ============================================================
# CallGenCall - CallGenMixin 拆分(阶段 B):方法调用分派(含 super / 虚调用 / kwargs 名匹配)
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenCall(CallGenBase.CallGenBase):
+2 -6
View File
@@ -1,4 +1,3 @@
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
@@ -7,15 +6,12 @@ import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HT
import lib.Stub.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Call.CallGenBase as CallGenBase
from . import CallGenBase
# ============================================================
+1 -2
View File
@@ -17,8 +17,7 @@ import lib.core.VLogger as VLogger
import lib.core.Gen.Translator as HT
import lib.Stub.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.Call.CallGenBase as CallGenBase
from . import CallGenBase
import lib.core.Gen.GenApi as GenApi
+30 -3
View File
@@ -415,9 +415,12 @@ class ExprGenBase:
if val_bits == target_bits:
return val
if val_bits < target_bits:
# i1 (bool) → 更宽整数用 zext(bool 语义:1 保持 1,而非 sext 的 0xFF...)
# 与 HandlesReturn 中 return 语句的 i1 扩展规则保持一致
if val_bits == 1:
# 统一 zext/sext(问题2修正):i1/i8 默认 zext;AST 节点解析为
# 无符号类型(t.CUIntXXT 强转/无符号类型名)走 zext;否则 sext。
# 此前一律 sext(i1 除外)→ t.CUInt32T 等无符号值赋值/传参被符号
# 扩展(高位置 1,如 0xFFFFFFFF 变 0xFFFFFFFFFFFFFFFF),与比较路径
# should_zext_widen(i8 默认 zext)规则相反 → 隐蔽数据损坏。
if self._zext_or_sext_val(pool, val, node) != 0:
return llvmlite.build_zext(builder, val, target_ty)
return llvmlite.build_sext(builder, val, target_ty)
return llvmlite.build_trunc(builder, val, target_ty)
@@ -450,6 +453,30 @@ class ExprGenBase:
if self.is_ptr_type(val.Ty) != 0 and self.is_ptr_type(target_ty) != 0:
return llvmlite.build_bitcast(builder, val, target_ty)
return val
def _zext_or_sext_val(self, pool: memhub.MemBuddy | t.CPtr,
val: llvmlite.Value | t.CPtr,
node: ast.AST | t.CPtr = None) -> int:
"""统一整数拓宽方向:1=zext(无符号语义),0=sext
规则(对齐 ExprGenOps.should_zext_widen / _node_type_unsigned):
1. i1 (bool) → zext(1 保持 1,而非 sext 的 0xFF...)
2. i8 → zext(系统编程中 i8 几乎总是无符号字节)
3. AST 节点解析为无符号类型(t.CUIntXXT 强转/无符号类型名/BYTE 等)→ zext
4. 否则 sext
"""
if val is None or val.Ty is None:
return 0
bits: int = self.get_llvm_type_bits(val.Ty)
if bits == 1:
return 1
if bits == 8:
return 1
if node is not None:
if self.Gen.ExprGenOps._node_type_unsigned(pool, node) != 0:
return 1
return 0
# ============================================================
# translate_ptr_arith - 指针算术: ptr + int / ptr - int
#
+8
View File
@@ -110,6 +110,14 @@ class FuncGenDef(CallGenBase.CallGenBase):
if ret_ty is None:
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(
pool, fd, imported_modules, from_imports, trans)
if ret_ty is None and fd.returns is not None:
# 有返回注解但解析失败:编译期报错,不静默回退 i32。
# (i32 回退曾导致掉尾检查强制 return i32 / 跨模块调用返回类型错位,
# mm.vp free / GetMemoryStats 根因。)无返回注解函数(def foo():)
# 保留 i32 默认,不在此报错。
self.Gen.TypeGenErr.fatal_error(
fd, "函数返回类型解析失败:注解不可解析", "TypeError")
return 0
if ret_ty is None:
ret_ty = i32_ty
-9
View File
@@ -1,17 +1,8 @@
import t, c
from stdint import *
import ast
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.Stub.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import llvmlite
import memhub
import stdio
import stdlib
import string
import viperlib
import w32.fileio as fileio
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import lib.core.Gen.Translator as HT
-6
View File
@@ -23,12 +23,6 @@ import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
# _g_reexport_count/_g_current_file)→ 本类字段
# 模块级函数(add_imported_module/is_module_imported/...)→ 本类方法
#
# 迁移原则(与 P1-P5 Mixin 一致,行为零变化):
# 1. 方法保留原函数签名(含 pool 首参),仅函数体内的全局变量改为 self.字段
# 2. 本模块内部函数调用改为 self.方法;跨模块调用(StubMerger 等)保留模块前缀
# 3. HandlesImports.vp 原函数保留为"委托":本地模块级单例 _g_gen
# (BuildPipeline/main 注入)cast 成 Generator 类型后调本类方法
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
# ============================================================
+10 -2
View File
@@ -1256,7 +1256,11 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
# 直接返回 None 让上层回落(fail-fast:宁可类型退化
# 也不静默卡死)。
if string.strcmp(gp_ta, gp_tpn) == 0:
return None
# 泛型类型参数自映射(T→T):编译期报错,不静默退化。
# 此前 return None 让上层静默退化(i32/Ptr(i8)),
# 运行时数据损坏难定位(ListTest/DictTest 根因之一)。
self.Gen.TypeGenErr.fatal_error(
nm, f"泛型类型实参污染:类型参数 '{gp_tpn}' 自映射(实参='{gp_ta}'),无法特化", "TypeError")
polluted: int = 0
gp_j: t.CSizeT
for gp_j in range(gp_n):
@@ -1265,7 +1269,11 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
polluted = 1
break
if polluted != 0:
return None
# 实参串包含类型参数名(如 "T | t.CPtr"/"list[T]"):
# 解析后仍产出 Name(参数名) → 无条件自递归卡死。编译期
# 报错(此前 return None 静默退化)。
self.Gen.TypeGenErr.fatal_error(
nm, f"泛型类型实参污染:实参 '{gp_ta}' 包含类型参数名,无法特化", "TypeError")
# 用具体类型名递归解析(支持 BinOp/Attribute 类型实参)
gp_sub_node: ast.AST | t.CPtr = self._parse_type_string(pool, gp_ta, nm.ctx)
if gp_sub_node is not None: