diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index 80155bd..1734010 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -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 (")