fix(gen): 编译器生成方法 __before_init__ 跨模块调用放行,修复找不到模块 SHA1

- _tc_h6_method_dispatch 增加 hit_box 命中标记:_translate_method_call 返回 None(void 语义)不再被误判未命中,translate_call 不再把对象名当模块名查 SHA1
- AnnotClassName 回退分支新增编译器特殊方法放行:结构体未注册 + 模块 SHA1 不可查(Phase A 依赖未就绪)时,__before_init__/__init__ 由 _special_method_ret_ty 固定返回类型,走 _translate_method_call 处理并标记 _deps_pending 下遍重试
- ExprCallHandle._tc_h6_method_dispatch 委托透传 hit_box,对齐 c.Asm/c.LLVMIR hit_box 修复(2f3320f)
This commit is contained in:
TermiNexus committed 2026-08-17 18:19:15 +08:00
1 parent 2f3320ffde
commit 51ae18a160
3 files changed
+64 -5

No files matched your search

+44 -2
View File
@@ -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)
+17 -1
View File
@@ -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
+3 -2
View File
@@ -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 后顶层经