diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index 44ef49e..cafd24c 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -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 会破坏表达式翻译)。 diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 510e8de..6454b3e 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -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 方法定义模块。 diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index 4fce92c..9c96631 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -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):实参按标准签名提升 diff --git a/App/lib/core/Gen/Call/CallGenProp.vp b/App/lib/core/Gen/Call/CallGenProp.vp index d5d4058..4a2c281 100644 --- a/App/lib/core/Gen/Call/CallGenProp.vp +++ b/App/lib/core/Gen/Call/CallGenProp.vp @@ -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 会破坏表达式翻译)。