refactor(tpv): ClassGenVTable vtable 类型文本切到 SpecToLLVMText

- 删除 _format_func_type_str(512 缓冲 + >100 参截断的 TypePrint 重复实现)
- _generate_vtable 当前类方法分支改为 SpecToLLVMText 派生,回退全局表 TypeStr
- Spec/TypeStr 皆失败时 fail-fast
This commit is contained in:
TermiNexus committed 2026-09-11 21:21:01 +08:00
1 parent 0e973d5f23
commit a173ba0296
1 file changed
+19 -56
+19 -56
View File
@@ -1,4 +1,5 @@
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Type.TypeSpec as TSpec
import t, c
from stdint import *
import ast
@@ -65,56 +66,6 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
return 1
return 0
# ============================================================
# _format_func_type_str — 从 Function 对象生成函数类型字符串
#
# 格式: ret_ty (param1_ty, param2_ty, ...)
# 例如: void ({i32, i32}*, i32)
# ============================================================
def _format_func_type_str(self, pool: memhub.MemBuddy | t.CPtr,
buf: str, buf_size: sizet,
func: llvmlite.Function | t.CPtr) -> int:
"""从 Function 对象生成函数类型字符串"""
if buf is None or func is None or buf_size == 0:
return 0
buf[0] = '\0'
# 打印返回类型(使用访问器函数避免跨模块直接字段访问)
ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func)
ret_buf: str = pool.alloc(128)
if ret_buf is not None and ret_ty is not None:
ret_buf[0] = '\0'
llvmlite.TypePrint(ret_buf, 128, ret_ty, pool)
self._vtable_strcat(buf, buf_size, ret_buf)
self._vtable_strcat(buf, buf_size, " (")
# 遍历参数(使用访问器函数避免跨模块直接字段访问)
cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
first: int = 1
param_buf: str = pool.alloc(128)
_pc: int = 0
while cur is not None:
_pc += 1
if _pc > 100:
break
if first == 0:
self._vtable_strcat(buf, buf_size, ", ")
if param_buf is not None:
param_buf[0] = '\0'
param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur)
if param_ty is not None:
llvmlite.TypePrint(param_buf, 128, param_ty, pool)
self._vtable_strcat(buf, buf_size, param_buf)
cur = llvmlite.param_get_next(cur)
first = 0
# 变参函数追加 ...(对齐 llvmlite IR 打印规则与 CallGenLeafKit._build_func_type_str:
# 有参数时 ", ...",无参数时 "...")。此前遗漏 → 该回退文本生成的函数类型缺 ...。
if func.IsVarArg == 1:
if first != 0:
self._vtable_strcat(buf, buf_size, "...")
else:
self._vtable_strcat(buf, buf_size, ", ...")
self._vtable_strcat(buf, buf_size, ")")
return 1
# ============================================================
# _collect_vtable_methods — 收集类的虚方法信息
#
# 1. 继承父类虚方法(父类方法排在子类方法之前,保持槽位顺序一致)
@@ -416,9 +367,8 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
func = self.Gen.CallGenLeafKit.find_func_global(full_name)
# func 可能已被 1b reset_to(mark1) 回收(跨模块继承方法在定义文件翻译后被 reset)。
# 悬空指针非 NULL 但内容已被复用,_format_func_type_str 解引用会沿垃圾 Next 链
# 指针追逐导致无限分配(TypePrint 每次 pool.alloc(512) → 单文件暴涨 900MB OOM)。
# 因此 func 非 NULL 时也须用 _is_valid_ptr 校验,失败回退到 TypeStr。
# 悬空指针非 NULL 但内容已被复用,解引用会沿垃圾 Next 链指针追逐导致无限分配。
# 因此 func 非 NULL 时也须用 _is_valid_ptr 校验,失败回退到全局表 TypeStr。
func_valid: int = 0
if func is not None:
if trans.Pool is not None:
@@ -450,12 +400,25 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
cd, f"vtable 方法 '{full_name}' 找不到函数实现", "InternalCompilerError")
continue
# 构造函数类型字符串
func_ty_buf: str = pool.alloc(512)
# 构造函数类型字符串(S3 切读:优先 SpecToLLVMText 派生,回退全局表 TypeStr;
# 替代 _format_func_type_str 那份 512 缓冲 + >100 参截断的 TypePrint 重复实现)
func_ty_buf: str = pool.alloc(1024)
if func_ty_buf is None:
self._vtable_strcat(init_buf, 16384, "i8* null")
continue
self._format_func_type_str(pool, func_ty_buf, 512, func)
func_ty_buf[0] = '\0'
ty_ok: int = 0
spec_entry2: GenTypes.FuncEntry | t.CPtr = self.Gen.CallGenLeafKit.find_func_entry_global(full_name)
if spec_entry2 is not None and spec_entry2.Spec is not None:
if TSpec.SpecToLLVMText(spec_entry2.Spec, func_ty_buf, 1024) == 0:
ty_ok = 1
if ty_ok == 0 and spec_entry2 is not None and spec_entry2.TypeStr is not None:
string.strcpy(func_ty_buf, spec_entry2.TypeStr)
ty_ok = 1
if ty_ok == 0:
self.Gen.TypeGenErr.fatal_error(
cd, f"vtable 方法 '{full_name}' 找不到函数类型", "InternalCompilerError")
continue
# 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
self._vtable_strcat(init_buf, 16384, "i8* bitcast (")