diff --git a/App/lib/core/Gen/CallGenDispatch.vp b/App/lib/core/Gen/CallGenDispatch.vp index 552611c..4ff2c0e 100644 --- a/App/lib/core/Gen/CallGenDispatch.vp +++ b/App/lib/core/Gen/CallGenDispatch.vp @@ -806,8 +806,16 @@ class CallGenDispatch(CallGenBase.CallGenBase): trans: HT.Translator | t.CPtr, func_name: str, cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT) -> llvmlite.Value | t.CPtr: - """静态类/方法调用/表达式接收者/self.field/list 内置(未命中返回 None)""" + can: t.CSizeT, + hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr: + """静态类/方法调用/表达式接收者/self.field/list 内置(未命中返回 None) + + hit_box: 命中标记(t.CPtr,[0]=1 表示已识别为方法调用路径)。 + 编译器生成方法(如 __before_init__/__init__)恒返回 void, + _translate_method_call 处理后返回 None(无返回值)——若不标记, + translate_call 会误判"未命中"继续走跨模块函数路径(把对象名 + 当模块名查 SHA1 → "跨模块调用 'buf.__before_init__' 找不到模块 SHA1")。 + """ # 检测类名静态/类方法调用: ClassName.method(args) # 当 cl.func 是 Attribute、value 是已注册结构体类名(非普通变量)时, # 且方法带 @staticmethod/@classmethod 元数据,走静态调用路径 @@ -927,6 +935,8 @@ class CallGenDispatch(CallGenBase.CallGenBase): # vpi stub 均未命中)→ fail-fast。检测到 list 方法时 # 跳过 method_call,落到内置分支(NewAstTest body.append 根因)。 if ExprCallHandle._is_list_builtin_method(class_nm, func_name) == 0: + if hit_box is not None: + hit_box[0] = 1 return ExprCallCtor._translate_method_call( pool, builder, mod, class_nm, func_name, obj_var, cl, trans) @@ -942,6 +952,8 @@ class CallGenDispatch(CallGenBase.CallGenBase): obj_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load( builder, obj_struct_ty, obj_var) if obj_ptr is not None: + if hit_box is not None: + hit_box[0] = 1 return ExprCallCtor._translate_method_call( pool, builder, mod, inner_nm, func_name, obj_ptr, cl, trans) @@ -983,6 +995,8 @@ class CallGenDispatch(CallGenBase.CallGenBase): obj_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_load( builder, i8_ptr_ty2, obj_var) if obj_ptr2 is not None: + if hit_box is not None: + hit_box[0] = 1 return ExprCallCtor._translate_method_call( pool, builder, mod, cls_nm2, func_name, obj_ptr2, cl, trans) @@ -1056,6 +1070,30 @@ class CallGenDispatch(CallGenBase.CallGenBase): ret_ty3 = llvmlite.Void(pool) self._ensure_method_declare(pool, mod, mangled3, ret_ty3, head3, total3) return llvmlite.build_call(builder, mangled3, head3, total3, ret_ty3, 0) + else: + # 编译器生成特殊方法放行(__before_init__/__init__ 等): + # 结构体未注册 + 模块 SHA1 均不可查(Phase A 依赖未就绪)时, + # 方法返回类型由编译器确定性定义(_special_method_ret_ty), + # 不依赖结构体注册即可精确解析。走 _translate_method_call 处理 + # (内部含 _special_method_ret_ty + mc_entry/类型名 SHA1 提取), + # 绝不掉出返回 None 让 translate_call 把对象名当模块名 + # 报"跨模块调用 'buf.__before_init__' 找不到模块 SHA1" + # (memhub.alloc_buf buf.__before_init__() 根因)。 + sp_ty4: llvmlite.LLVMType | t.CPtr = self._special_method_ret_ty( + pool, cls_nm2, func_name) + if sp_ty4 is not None: + i8_ptr_ty4: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( + pool, llvmlite.Int8(pool)) + obj_ptr4: llvmlite.Value | t.CPtr = llvmlite.build_load( + builder, i8_ptr_ty4, obj_var) + if obj_ptr4 is not None: + if trans is not None: + trans._deps_pending = 1 + if hit_box is not None: + hit_box[0] = 1 + return ExprCallCtor._translate_method_call( + pool, builder, mod, cls_nm2, func_name, + obj_ptr4, cl, trans) # ============================================================ # 检测表达式接收者方法调用: (expr).method(args) @@ -1133,6 +1171,8 @@ class CallGenDispatch(CallGenBase.CallGenBase): builder, pool, mod, expr_method_at.value, trans) if expr_addr is not None: expr_obj = expr_addr + if hit_box is not None: + hit_box[0] = 1 return ExprCallCtor._translate_method_call( pool, builder, mod, expr_cls_nm, func_name, expr_obj, cl, trans) @@ -1206,6 +1246,8 @@ class CallGenDispatch(CallGenBase.CallGenBase): builder, pool, mod, attr_method_at.value, trans) if field_addr is not None: field_obj = field_addr + if hit_box is not None: + hit_box[0] = 1 return ExprCallCtor._translate_method_call( pool, builder, mod, field_cls_nm, func_name, field_obj, cl, trans) diff --git a/App/lib/core/Gen/CallGenMixin.vp b/App/lib/core/Gen/CallGenMixin.vp index 0a6e05a..57c68a1 100644 --- a/App/lib/core/Gen/CallGenMixin.vp +++ b/App/lib/core/Gen/CallGenMixin.vp @@ -190,10 +190,26 @@ class CallGenMixin(CallGenBase.CallGenBase): if _tc_h5_sizeof_len_isinst_res is not None: return _tc_h5_sizeof_len_isinst_res + # c.Asm/c.LLVMIR 等方法调用分派:方法调用识别成功但返回 None + # (如编译器生成方法 __before_init__/__init__ 恒返回 void,_translate_ + # method_call 或 _emit_eh_guarded_call 处理后可能返回 None)时,须用 + # hit_box 区分"已识别为方法调用"与"未命中",否则 translate_call 误判 + # 未命中继续走跨模块函数路径,把对象名当模块名查 SHA1 → + # "跨模块调用 'buf.__before_init__' 找不到模块 SHA1"(memhub.alloc_buf 根因)。 + h6_hit: t.CPtr = stdlib.malloc(4) + if h6_hit is not None: + h6_hit[0] = 0 _tc_h6_method_dispatch_res: llvmlite.Value | t.CPtr = ExprCallHandle._tc_h6_method_dispatch( - pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can) + pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h6_hit) + h6_hit_val: int = 0 + if h6_hit is not None: + h6_hit_val = h6_hit[0] + stdlib.free(h6_hit) if _tc_h6_method_dispatch_res is not None: return _tc_h6_method_dispatch_res + if h6_hit_val != 0: + # 命中方法调用路径但无返回值(编译器生成方法等 void 语义):视为已处理 + return None # 获取关键字参数 keywords: list[ast.AST | t.CPtr] | t.CPtr = cl.keywords diff --git a/App/lib/core/Handles/ExprCallHandle.vp b/App/lib/core/Handles/ExprCallHandle.vp index 7524d11..b2e1967 100644 --- a/App/lib/core/Handles/ExprCallHandle.vp +++ b/App/lib/core/Handles/ExprCallHandle.vp @@ -228,12 +228,13 @@ def _tc_h6_method_dispatch(pool: memhub.MemBuddy | t.CPtr, trans: HT.Translator | t.CPtr, func_name: str, cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT) -> llvmlite.Value | t.CPtr: + can: t.CSizeT, + hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr: """静态类/方法调用/表达式接收者/self.field/list 内置(委托到 gen._tc_h6_method_dispatch)""" import lib.core.Gen.Generator as Generator g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr)) if g is not None: - return g._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can) + return g._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box) return None # ============================================================ # FuncGen 跨 Mixin 委托(阶段 D:FuncGenMixin 拆 Base/Def 后顶层经