From cc3359faead5332bb158bfd4d96899fc69d2a920 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 11 Sep 2026 22:14:10 +0800 Subject: [PATCH] =?UTF-8?q?refactor(tpv):=20=E5=BD=A2=E5=8F=82=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=B3=A8=E8=A7=A3=E8=A7=A3=E6=9E=90=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=94=B9=20fail-fast=EF=BC=88=E4=B8=8D=E5=86=8D=E9=9D=99?= =?UTF-8?q?=E9=BB=98=E7=94=A8=20i32=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FuncGenDef 前向声明形参 / 定义签名形参:resolved is None 即 fatal - FuncGenBase create_function 形参:同上(暴露调用方未传 trans 上下文) - ClassGenVTable _translate_method 形参:同上(签名/调用点/实现体三方一致) - TypeGenCDef 整数 CDefine 值缓冲分配失败改 fatal(对齐同文件浮点/字符串分支) - FuncGenMixin._type_byte_size 类型缺失改 fatal(case _ 保留 8,注释说明无布局查询能力) --- App/lib/core/Gen/Class/ClassGenVTable.vp | 30 +++++++------ App/lib/core/Gen/Func/FuncGenBase.vp | 10 ++++- App/lib/core/Gen/Func/FuncGenDef.vp | 54 ++++++++++++++---------- App/lib/core/Gen/Func/FuncGenMixin.vp | 13 ++++-- App/lib/core/Gen/Type/TypeGenCDef.vp | 4 ++ 5 files changed, 72 insertions(+), 39 deletions(-) diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index 6c344cc..454fa46 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -754,18 +754,24 @@ class ClassGenVTable(ClassGenBase.ClassGenBase): if arg.annotation is not None: resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type( pool, arg.annotation, imported_modules, from_imports, trans, 0) - if resolved is not None: - # 裸类形参 → Ptr(struct):按"对象即指针"引用传参。 - # 若按 struct 值传参,self.Head = node 会取局部拷贝地址 - # (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。 - # CArray 形参 → 元素指针 ty*(数组衰减,C 语义,与函数形参一致)。 - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case llvmlite.LLVMType.Array(aelem_ty, _): - param_ty = llvmlite.Ptr(pool, aelem_ty) - case _: - param_ty = resolved + if resolved is None: + # [S4 fail-fast] 有注解但解析失败:不再静默用 i32 + # (方法签名与调用点/实现体三方不一致) + self.Gen.TypeGenErr.fatal_error( + arg, f"方法 '{class_name}.{method_name}' 形参 '{arg.arg}' 类型注解解析失败", + "NameError") + return 0 + # 裸类形参 → Ptr(struct):按"对象即指针"引用传参。 + # 若按 struct 值传参,self.Head = node 会取局部拷贝地址 + # (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。 + # CArray 形参 → 元素指针 ty*(数组衰减,C 语义,与函数形参一致)。 + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case llvmlite.LLVMType.Array(aelem_ty, _): + param_ty = llvmlite.Ptr(pool, aelem_ty) + case _: + param_ty = resolved pname: str = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) diff --git a/App/lib/core/Gen/Func/FuncGenBase.vp b/App/lib/core/Gen/Func/FuncGenBase.vp index 6bee056..11a45d6 100644 --- a/App/lib/core/Gen/Func/FuncGenBase.vp +++ b/App/lib/core/Gen/Func/FuncGenBase.vp @@ -453,8 +453,14 @@ class FuncGenBase(CallGenBase.CallGenBase): if arg.annotation is not None: resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type( pool, arg.annotation, None, None, None, 0) - if resolved is not None: - param_ty = resolved + if resolved is None: + # [S4 fail-fast] 有注解但解析失败:不再静默用 i32。 + # 本函数不传 trans/imports 上下文,解析失败即调用方 + # 未补齐上下文(暴露上游,不由本函数兜底)。 + self.Gen.TypeGenErr.fatal_error( + arg, f"函数 '{name}' 形参 '{arg.arg}' 类型注解解析失败", "NameError") + return None + param_ty = resolved pname: str = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 2d76f6f..b2ee8f9 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -259,16 +259,21 @@ class FuncGenDef(CallGenBase.CallGenBase): if arg.annotation is not None: resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type( pool, arg.annotation, imported_modules, from_imports, trans, 0) - if resolved is not None: - # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) - # CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致) - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case llvmlite.LLVMType.Array(aelem_ty, _): - param_ty = llvmlite.Ptr(pool, aelem_ty) - case _: - param_ty = resolved + if resolved is None: + # [S4 fail-fast] 有注解但解析失败:不再静默用 i32 + # (declare 与 define 签名不一致 → ABI 错位,运行期读栈垃圾) + self.Gen.TypeGenErr.fatal_error( + arg, f"前向声明形参 '{arg.arg}' 类型注解解析失败", "NameError") + return 0 + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + # CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case llvmlite.LLVMType.Array(aelem_ty, _): + param_ty = llvmlite.Ptr(pool, aelem_ty) + case _: + param_ty = resolved pname: str = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) @@ -623,18 +628,23 @@ class FuncGenDef(CallGenBase.CallGenBase): if arg.annotation is not None: resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type( pool, arg.annotation, imported_modules, from_imports, trans, 0) - if resolved is not None: - # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) - # CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N]) - # 的 out 指向调用方数组首元素;传 Ptr(数组) 会使 out[i] 的 - # GEP 以整个数组为步长错位,摘要垃圾根因) - match resolved: - case llvmlite.LLVMType.Struct(_, _, _): - param_ty = llvmlite.Ptr(pool, resolved) - case llvmlite.LLVMType.Array(aelem_ty, _): - param_ty = llvmlite.Ptr(pool, aelem_ty) - case _: - param_ty = resolved + if resolved is None: + # [S4 fail-fast] 有注解但解析失败:不再静默用 i32 + # (形参类型错 → ABI 错位/字段访问错) + self.Gen.TypeGenErr.fatal_error( + arg, f"形参 '{arg.arg}' 类型注解解析失败", "NameError") + return 0 + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + # CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N]) + # 的 out 指向调用方数组首元素;传 Ptr(数组) 会使 out[i] 的 + # GEP 以整个数组为步长错位,摘要垃圾根因) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case llvmlite.LLVMType.Array(aelem_ty, _): + param_ty = llvmlite.Ptr(pool, aelem_ty) + case _: + param_ty = resolved pname: str = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index b13e65a..8b84eab 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -861,13 +861,20 @@ class FuncGenMixin(CallGenBase.CallGenBase): # # 用于 nonlocal 共享堆存储分配:数组(如 [4 x i32]=16 字节)不能 # 用固定 8 字节(越界写破坏 canary/邻块 → 运行时崩溃, - # ClosureTest2 Test 4 非local 数组崩溃根因)。未知类型保守返回 8。 + # ClosureTest2 Test 4 非local 数组崩溃根因)。 + # + # 注:`case _`(Void/Struct/Func 等)仍返回 8 —— 这不是静默兜底掩盖错误, + # 而是**算不出**(结构体尺寸需查布局表,本函数只做 LLVMType 递归); + # 改 fatal 会拒绝 "nonlocal 结构体" 这一合法用法,需先补布局查询能力。 # ============================================================ def _type_byte_size(self, pool: memhub.MemBuddy | t.CPtr, ty: llvmlite.LLVMType | t.CPtr) -> int: - """计算 LLVM 类型占用的字节大小(递归),未知类型返回 8""" + """计算 LLVM 类型占用的字节大小(递归)""" if ty is None: - return 8 + # [S4 fail-fast] 类型缺失 → 不再保守 8 字节(分配不足会越界写邻块) + self.Gen.TypeGenErr.fatal_error( + None, "nonlocal 共享存储:类型缺失,无法计算尺寸", "TypeError") + return 0 match ty: case llvmlite.LLVMType.Int(bits): sz_i: int = (bits + 7) // 8 diff --git a/App/lib/core/Gen/Type/TypeGenCDef.vp b/App/lib/core/Gen/Type/TypeGenCDef.vp index f388642..fb5495b 100644 --- a/App/lib/core/Gen/Type/TypeGenCDef.vp +++ b/App/lib/core/Gen/Type/TypeGenCDef.vp @@ -47,6 +47,10 @@ class TypeGenCDef(TypeGenBase.TypeGenBase): self.CDefineValues.append(val_buf) else: self.CDefineValues.append("0") + # fail-fast:CDefine 值缓冲区分配失败必须终止编译 + # (与浮点/字符串分支口径一致,不再静默写 "0" 污染常量表) + if val_buf is None: + self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' 值缓冲区分配失败", "MemoryError") if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.append(0) if self.CDefineStrFlags is not None: