From 67667b10db5b2c2bf3f49b18ec0865e55910d5ee Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 10:26:57 +0800 Subject: [PATCH] =?UTF-8?q?fix(class):=20=5F=5Fbefore=5Finit=5F=5F=20?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=97=B6=E5=A4=8D=E7=94=A8=E5=90=8C=E5=90=8D?= =?UTF-8?q?=E5=89=8D=E5=90=91=E5=A3=B0=E6=98=8E=EF=BC=8C=E6=B6=88=E9=99=A4?= =?UTF-8?q?=E5=90=8C=E6=A8=A1=E5=9D=97=20declare+define?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本类方法体内构造自身(如 Vec2.__add__ 里 return Vec2(...))时,构造路径先经 _call_method_on_ptr → _ensure_method_declare 在本模块建好同名 __before_init__ 前向声明(IsDeclared=1);随后 _generate_before_init 又 create_function 追加一条同名 define,使同一模块 IR 同时出现 declare 与 define → llc 报 invalid redefinition of function(OopInheritTest 根因;④ 改用 full.ll 直喂 llc 后不再被旧 BuildCombinedIR 去重掩盖)。改为按名复用该前向声明(命名首参 %self、校准类型、清 IsDeclared 转 define),与 _generate_method/FuncGenDef 同构。 --- App/lib/core/Gen/Class/ClassGenVTable.vp | 37 ++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index 148e8f5..ffd11eb 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -1140,9 +1140,25 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): mangled_name: str = self.Gen.FuncGenBase._mangle_name(trans, full_name) - # 创建函数 - func: llvmlite.Function* = llvmlite.create_function(pool, mod, mangled_name, void_ty) - if func is None: return 0 + # 创建/复用 LLVM 函数。 + # 复用场景:本类方法体内构造自身时(如 Vec2.__add__ 里 `return Vec2(...)`), + # CallGenCtor._translate_struct_ctor 先经 CallGenCall._call_method_on_ptr → + # CallGenBase._ensure_method_declare 在本模块建好同名 __before_init__ 前向声明 + # (IsDeclared=1,形参无名且无函数体)。此刻本 define 尚未生成,若此处再 + # create_function 追加一条同名 define,同模块内 declare+define 并存 → llc + # "invalid redefinition of function"。故按名复用该声明,清零 IsDeclared 转 + # define——与 _generate_method(本文件 L686-705)、FuncGenDef(L552-555)同构。 + bi_func: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name) + bi_decl_reuse: int = 0 + if bi_func is not None: + if bi_func.IsDeclared == 0: + # 同名函数体已发射:禁止重复发射(duplicate symbol) + return 0 + bi_decl_reuse = 1 + else: + bi_func = llvmlite.create_function(pool, mod, mangled_name, void_ty) + if bi_func is None: return 0 + func: llvmlite.Function* = bi_func # 注册到函数表 max_funcs: int = 1024 @@ -1150,8 +1166,19 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if rc_add == 0: trans._func_count = func_count + 1 - # 添加 self 参数 - llvmlite.add_param(pool, func, self_ptr_ty, "%self") + if bi_decl_reuse != 0: + # 复用前向声明:self 参数已由 _ensure_method_declare 添加(无名), + # 此处只需命名首参 %self 并校准为定义侧类型——函数体以 %self 引用它, + # 无名形参会让函数体的 %self 无定义(llvmlite FunctionPrint 仅在 + # Param.Name 非空时打印参数名)。 + bi_first_param: llvmlite.Param* = llvmlite.function_get_param_head(func) + if bi_first_param is not None: + bi_first_param.Ty = self_ptr_ty + bi_first_param.Name = "%self" + func.IsDeclared = 0 + else: + # 添加 self 参数 + llvmlite.add_param(pool, func, self_ptr_ty, "%self") # 参数添加完成,补全全局函数表的 Spec rc_ut: int = self.Gen.CallGenLeafKit.update_global_func_spec(full_name, func)