fix(core): 方法注册去重 + 跨模块多继承 MRO 按需加载
_HandleMethodCallLlvm fallback 创建函数前复用已有声明(vpi 合并) 避免 DuplicatedNameError;新增 _EnsureClassParentsLoaded 从 .vpi 按需加载 class_parents,使跨模块多继承类(如 Generator)的 MRO 回退能定位定义类(如 TypeGenMixin),修复 bootstrap 链接 undefined reference。
This commit is contained in:
1 parent
f6f8c4183c
commit
b2fa70ae4b
1 file changed
+35
-2
@@ -920,6 +920,10 @@ class ExprCallHandle(BaseHandle):
|
||||
and ClassName not in Gen._cross_module_vtable_classes
|
||||
and class_sha1):
|
||||
self._try_register_vtable_ondemand(ClassName, class_sha1, Gen)
|
||||
# 跨模块多继承:确保 class_parents 可用(MRO 回退需要)。
|
||||
# 如 HandlesType 委托调用 Generator 的方法——Generator 定义在
|
||||
# 另一模块,class_parents 未随 import 填充,需从 vpi 按需加载。
|
||||
self._EnsureClassParentsLoaded(ClassName, Gen)
|
||||
if (ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes) and ClassName in Gen.class_methods and CallArgs and not is_static_call:
|
||||
methods = Gen.class_methods[ClassName]
|
||||
if class_sha1:
|
||||
@@ -2404,6 +2408,28 @@ class ExprCallHandle(BaseHandle):
|
||||
return Gen.builder.bitcast(adj, ir.PointerType(Gen.structs[method_anc]),
|
||||
name=f"this_adjust_cast_{method_anc}")
|
||||
|
||||
def _EnsureClassParentsLoaded(self, ClassName: str, Gen: LlvmGeneratorMixin) -> None:
|
||||
"""跨模块多继承:class_parents 缺失时从 vpi 按需加载继承信息。
|
||||
|
||||
调用方(如 HandlesType 委托)引用的类定义在另一模块,其父类
|
||||
信息未随 import 填充。_TryLoadClassMembersFromPyi 读取 .vpi 中
|
||||
的 ClassDef 并经 _EmitExternalClassDeclLlvm 填充 class_parents,
|
||||
使 _get_mro_chain 能沿 MRO 回退到定义类(如 TypeGenMixin)。
|
||||
"""
|
||||
if not ClassName:
|
||||
return
|
||||
if Gen.class_parents.get(ClassName):
|
||||
return
|
||||
sha1_cls = Gen.ModuleSha1Map.get(ClassName)
|
||||
if not sha1_cls:
|
||||
sha1_cls = getattr(Gen, '_struct_sha1_map', {}).get(ClassName)
|
||||
if not sha1_cls:
|
||||
return
|
||||
try:
|
||||
self.Trans.ImportHandler._TryLoadClassMembersFromPyi(ClassName, f"{sha1_cls}.stub.ll", Gen)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _HandleMethodCallLlvm(self, Node: ast.Call) -> ir.Value:
|
||||
Gen = self.Trans.LlvmGen
|
||||
MethodName = Node.func.attr
|
||||
@@ -2862,6 +2888,9 @@ class ExprCallHandle(BaseHandle):
|
||||
and ClassName not in Gen._cross_module_vtable_classes
|
||||
and class_sha1):
|
||||
self._try_register_vtable_ondemand(ClassName, class_sha1, Gen)
|
||||
# 跨模块多继承:确保 class_parents 可用(MRO 回退需要),
|
||||
# 如 HandlesType 委托调用 Generator 的方法(定义类在 TypeGenMixin)。
|
||||
self._EnsureClassParentsLoaded(ClassName, Gen)
|
||||
|
||||
if (ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes) and ClassName in Gen.class_methods:
|
||||
methods = Gen.class_methods[ClassName]
|
||||
@@ -3003,8 +3032,12 @@ class ExprCallHandle(BaseHandle):
|
||||
sig_params = [self_ptr_type] + sig_params
|
||||
param_types = sig_params
|
||||
func_type = ir.FunctionType(ret_type, param_types)
|
||||
func = ir.Function(Gen.module, func_type, name=FullMethodName)
|
||||
Gen.functions[FullMethodName] = func
|
||||
# 复用已存在的声明(vpi 合并/LoadDepVpiIntoModule 可能已注册同名 declare),
|
||||
# 避免 llvmlite DuplicatedNameError(如 gen.__init__ / ImportsHandle.HandleImport)
|
||||
func = Gen._find_function(FullMethodName)
|
||||
if func is None:
|
||||
func = ir.Function(Gen.module, func_type, name=FullMethodName)
|
||||
Gen.functions[FullMethodName] = func
|
||||
if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == struct_type:
|
||||
call_self = ObjVal
|
||||
else:
|
||||
|
||||
Reference in new issue
Block a user