refactor(call): 跨模块返回类型解析改以 .vpi 为权威,text.ll 降为回退

将 8 处跨模块方法/函数返回类型解析的 text.ll → vpi 顺序对调为 vpi → text.ll:
- CallGenProp:属性方法调用
- CallGenMixin:跨模块裸名 CExport、from-import 函数
- CallGenCall:跨模块方法、类方法调用、self 方法调用(含 MRO 祖先链重试段整体搬移)
- CallGenDispatch:__len__ 跨模块、泛型 Mixin 方法

本模块 found_func / local_fn 取当前 IR 声明类型的路径保持不变。
去 IR 化步骤②;未编译验证。
This commit is contained in:
TermiNexus committed 2026-10-03 08:10:34 +08:00
1 parent 94d2bf5047
commit 78d3941f7d
4 files changed
+58 -58

No files matched your search

+32 -32
View File
@@ -365,9 +365,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
if lrt_cm2 is not None:
ret_cm = lrt_cm2
if cls_sha1 is not None:
ret_cm = self._LookupMethodRetTyFromTextLL(pool, cls_sha1, class_name, method_name)
if ret_cm is None and cls_sha1 is not None:
ret_cm = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1, class_name, method_name)
if ret_cm is None and cls_sha1 is not None:
ret_cm = self._LookupMethodRetTyFromTextLL(pool, cls_sha1, class_name, method_name)
if ret_cm is not None:
call_ret_ty = ret_cm
else:
@@ -1006,32 +1006,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
if lrt_lm is not None:
call_ret_ty = lrt_lm
gen_done = 1
# 尝试从 text.ll 查找实际返回类型
# 避免指针返回值被默认 i32 导致 inttoptr 截断
looked_up_ty = self._LookupMethodRetTyFromTextLL(pool, ret_anc_sha1, ret_anc_name, method_name)
# 尝试从 vpi 查找实际返回类型(权威来源:方法定义处注解,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, ret_anc_sha1, ret_anc_name, method_name)
# 沿 MRO 祖先链重试:方法可能定义在基类(如 Module.append →
# AST.append,函数名 {ast_sha1}.AST.append,且基类在另一模块文件
# 如 ast/stmts.vp 的 Module vs ast/base.vp 的 AST),按调用类名
# 及其 sha1 查不到,需用每个祖先类的类名 + 祖先类所属模块 sha1
# 查 text.ll(NewAstTest mod.append 根因)
if looked_up_ty is None:
mro_t2: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name)
mi_t2: int = 1
while mro_t2 is not None and mro_t2[mi_t2] != 0 and looked_up_ty is None:
anc_t2: str = rawptr(mro_t2[mi_t2])
if anc_t2 is not None and string.strcmp(anc_t2, class_name) != 0:
anc_sha1_t2: str = self.Gen.StructGen.get_struct_sha1(anc_t2)
looked_up_ty = self._LookupMethodRetTyFromTextLL(pool, anc_sha1_t2, anc_t2, method_name)
if looked_up_ty is not None:
ret_anc_name = anc_t2
ret_anc_sha1 = anc_sha1_t2
mi_t2 += 1
if gen_done == 0 and looked_up_ty is not None:
call_ret_ty = looked_up_ty
elif gen_done == 0:
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, ret_anc_sha1, ret_anc_name, method_name)
# vpi 同样沿 MRO 祖先链重试(基类方法注解,用祖先类自身 sha1)
# 查 vpi(NewAstTest mod.append 根因)
if vpi_ret_ty is None:
mro_v2: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name)
mi_v2: int = 1
@@ -1044,8 +1025,27 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
ret_anc_name = anc_v2
ret_anc_sha1 = anc_sha1_v2
mi_v2 += 1
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
if gen_done == 0 and vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
elif gen_done == 0:
# 回退:从 text.ll 的 define 行查找实际返回类型
# 避免指针返回值被默认 i32 导致 inttoptr 截断
looked_up_ty = self._LookupMethodRetTyFromTextLL(pool, ret_anc_sha1, ret_anc_name, method_name)
# 沿 MRO 祖先链重试(同上,用每个祖先类的类名 + 所属模块 sha1)
if looked_up_ty is None:
mro_t2: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name)
mi_t2: int = 1
while mro_t2 is not None and mro_t2[mi_t2] != 0 and looked_up_ty is None:
anc_t2: str = rawptr(mro_t2[mi_t2])
if anc_t2 is not None and string.strcmp(anc_t2, class_name) != 0:
anc_sha1_t2: str = self.Gen.StructGen.get_struct_sha1(anc_t2)
looked_up_ty = self._LookupMethodRetTyFromTextLL(pool, anc_sha1_t2, anc_t2, method_name)
if looked_up_ty is not None:
ret_anc_name = anc_t2
ret_anc_sha1 = anc_sha1_t2
mi_t2 += 1
if looked_up_ty is not None:
call_ret_ty = looked_up_ty
else:
# Phase A 依赖 text.ll 未生成(方法定义模块尚未翻译):保持默认
# 类型继续。BuildPipeline.vp L216 gen.extract_module_docstrings
@@ -1930,13 +1930,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
if sp_ty_sp is not None:
ret_ty_sp = sp_ty_sp
else:
looked_sp: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, anc_sha1_sp, anc, method_name)
if looked_sp is not None:
ret_ty_sp = looked_sp
vpi_ret_sp: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, anc_sha1_sp, anc, method_name)
if vpi_ret_sp is not None:
ret_ty_sp = vpi_ret_sp
else:
vpi_ret_sp: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, anc_sha1_sp, anc, method_name)
if vpi_ret_sp is not None:
ret_ty_sp = vpi_ret_sp
looked_sp: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, anc_sha1_sp, anc, method_name)
if looked_sp is not None:
ret_ty_sp = looked_sp
else:
# Phase A 依赖未就绪(anc_sha1_sp None / 定义模块 text.ll 未生成):
# 保持默认 i32(build_call(Void) 返回 None 会破坏表达式翻译)。
+5 -5
View File
@@ -879,9 +879,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
len_mangled_x: str = pool.alloc(len_ml_x)
if len_mangled_x is not None:
viperlib.snprintf(len_mangled_x, len_ml_x, "%s.%s.__len__", len_cls_sha1_x, len_cls_nm)
len_ret_x: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, len_cls_sha1_x, len_cls_nm, "__len__")
len_ret_x: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, len_cls_sha1_x, len_cls_nm, "__len__")
if len_ret_x is None:
len_ret_x = self._lookup_method_ret_ty_via_vpi(pool, len_cls_sha1_x, len_cls_nm, "__len__")
len_ret_x = self._LookupMethodRetTyFromTextLL(pool, len_cls_sha1_x, len_cls_nm, "__len__")
if len_ret_x is not None:
# self 参数按对象实际类型 Ptr(len_struct_ty)(与定义侧
# 同名类型链接匹配);len_val 已是 load 后的对象指针。
@@ -1412,10 +1412,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
total3: int = 1 + can
ret_ty3: llvmlite.LLVMType* = self._special_method_ret_ty(pool, cls_nm2, func_name)
if ret_ty3 is None:
ret_ty3 = self._LookupMethodRetTyFromTextLL(pool, sha1_fc, cls_nm2, func_name)
if ret_ty3 is None:
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
# 权威来源:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
ret_ty3 = self._lookup_method_ret_ty_via_vpi(pool, sha1_fc, cls_nm2, func_name)
if ret_ty3 is None:
ret_ty3 = self._LookupMethodRetTyFromTextLL(pool, sha1_fc, cls_nm2, func_name)
if ret_ty3 is None:
# 本分支仅在"注解类结构体未注册"时到达(L6932 else):
# 类未注册 → 无法沿 MRO 解析 Mixin 方法定义模块。
+13 -14
View File
@@ -889,14 +889,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
call_ret_ty = vpi_ret_ty
elif mod_ret_sha1 is not None:
# 跨模块裸名 CExport 函数(如 mm.malloc → @malloc):found_func=None
# 且 vpi 返回注解缓存未命中时,仍从依赖模块 text.ll/vpi 精确解析
# 返回类型(对齐 mangled 路径),避免静默默认 i32 截断指针/i64
# (uhci.vp mm.malloc 根因:call i32 @malloc 截断 0xbb69000 → null)。
cross_ret: llvmlite.LLVMType* = None
if trans is not None and trans._declare_only == 0:
cross_ret = self._LookupMethodRetTyFromTextLL(pool, mod_ret_sha1, None, func_name, 1)
# 时从依赖模块精确解析返回类型(对齐 mangled 路径),避免静默默认
# i32 截断指针/i64(uhci.vp mm.malloc 根因:call i32 @malloc 截断
# 0xbb69000 → null)。权威来源:vpi 注解缓存;未命中回退 text.ll。
cross_ret: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, mod_ret_sha1, None, func_name)
if cross_ret is None:
cross_ret = self._lookup_method_ret_ty_via_vpi(pool, mod_ret_sha1, None, func_name)
if trans is not None and trans._declare_only == 0:
cross_ret = self._LookupMethodRetTyFromTextLL(pool, mod_ret_sha1, None, func_name, 1)
if cross_ret is not None:
call_ret_ty = cross_ret
else:
@@ -1594,19 +1593,19 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
if local_fn is not None and local_fn.RetTy is not None:
call_ret_ty = local_fn.RetTy
else:
cf_ret: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, None, cf_bare, 1)
if cf_ret is not None:
call_ret_ty = cf_ret
cf_vpi: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, None, cf_bare)
if cf_vpi is not None:
call_ret_ty = cf_vpi
else:
cf_vpi: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, None, cf_bare)
if cf_vpi is not None:
call_ret_ty = cf_vpi
cf_ret: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, None, cf_bare, 1)
if cf_ret is not None:
call_ret_ty = cf_ret
else:
# 依赖模块 text.ll 不存在(模块尚未翻译)→ Phase A 按文件
# 顺序翻译,main.vp 先于其 import 的 mbuddytest.vp(同项目
# 多源文件):本遍保持默认类型,不 fail-fast。
if self._dep_text_ll_exists(pool, cf_sha1) != 0:
self.Gen.TypeGenErr.fatal_error(node, f"跨模块函数返回类型无法精确获取(text.ll/vpi 均未命中),默认 i32 会截断指针: {call_name}", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"跨模块函数返回类型无法精确获取(vpi/text.ll 均未命中),默认 i32 会截断指针: {call_name}", "TypeError")
stdlib.free(cf_sha1)
stdlib.free(cf_bare)
# 裸名 C 库函数(string.memset → @memset):实参按标准签名提升
+8 -7
View File
@@ -85,14 +85,15 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
call_ret_ty = sp_ty1
else:
cls_sha1_rt: str = self.Gen.StructGen.get_struct_sha1(class_name)
looked_up_ty: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cls_sha1_rt, class_name, method_name)
if looked_up_ty is not None:
call_ret_ty = looked_up_ty
# 权威来源:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1_rt, class_name, method_name)
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
else:
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1_rt, class_name, method_name)
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
# 回退:依赖模块 text.ll 的 define 行解析(vpi 未覆盖的历史形态)
looked_up_ty: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cls_sha1_rt, class_name, method_name)
if looked_up_ty is not None:
call_ret_ty = looked_up_ty
else:
# Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成):
# 保持默认 i32(build_call(Void) 返回 None 会破坏表达式翻译)。