fix(class): __before_init__ 定义时复用同名前向声明,消除同模块 declare+define

本类方法体内构造自身(如 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 同构。
This commit is contained in:
TermiNexus committed 2026-10-03 10:26:57 +08:00
1 parent 4c114d8875
commit 67667b10db
1 file changed
+32 -5
+32 -5
View File
@@ -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)