From 146b9a9652f0e62ef41b452f8b5d806a4ecd7313 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 23 Aug 2026 14:50:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20=E5=85=84=E5=BC=9F=20Mixin=20?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E6=94=AF=E6=8C=81=E8=B7=A8=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E2=80=94=E2=80=94=E4=BF=AE=E5=A4=8D=E8=87=AA=E8=BA=AB=20text.l?= =?UTF-8?q?l=20=E6=B0=B8=E4=B9=85=20pending=20=E6=AD=BB=E9=94=81=20-=20Cla?= =?UTF-8?q?ssGenVTable.=5Fmangle=5Fname=20=E5=AE=9A=E4=B9=89=E5=9C=A8=20Fu?= =?UTF-8?q?ncGenBase=EF=BC=88=E8=B7=A8=E6=A8=A1=E5=9D=97=20Mixin=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E7=B1=BB=E4=B8=8D=E7=BB=A7=E6=89=BF=E5=AE=83?= =?UTF-8?q?=EF=BC=89=EF=BC=8C=E5=85=84=E5=BC=9F=20Mixin=20=E5=85=9C?= =?UTF-8?q?=E5=BA=95=E5=8F=AA=E5=9C=A8=E6=9C=AC=E5=9C=B0=20IR=20=E6=89=BE?= =?UTF-8?q?=20define=20=E6=9C=AA=E5=91=BD=E4=B8=AD=20=E2=86=92=20ret=5Fanc?= =?UTF-8?q?=5Fsha1=20=E5=81=9C=E5=9C=A8=E8=B0=83=E7=94=A8=E7=B1=BB?= =?UTF-8?q?=E8=87=AA=E8=BA=AB=20sha1=20=E2=86=92=20=5Fdep=5Ftext=5Fll=5Fex?= =?UTF-8?q?ists(=E8=87=AA=E8=BA=AB)=20=E6=81=92=200=EF=BC=88Phase=20A=20?= =?UTF-8?q?=E7=BF=BB=E8=AF=91=E4=B8=AD=E8=87=AA=E8=BA=AB=20text.ll=20?= =?UTF-8?q?=E6=9C=AA=E7=94=9F=E6=88=90=EF=BC=89=E2=86=92=20=5Fdeps=5Fpendi?= =?UTF-8?q?ng=3D1=20=E6=AD=BB=E9=94=81=EF=BC=8CPhase=20A=20=E6=B0=B8?= =?UTF-8?q?=E4=B8=8D=E6=94=B6=E6=95=9B=20-=20=E4=BF=AE=E5=A4=8D=EF=BC=9A?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E9=81=8D=E5=8E=86=E5=B7=B2=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=20struct=20=E6=97=B6=E5=A2=9E=E5=8A=A0=E8=B7=A8=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=9F=A5=E6=89=BE=EF=BC=88get=5Fstruct=5Fsha1=20+=20?= =?UTF-8?q?=5FLookupMethodRetTyFromTextLL=20=E6=9F=A5=E8=AF=A5=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=20text.ll=EF=BC=89=EF=BC=8C=E5=91=BD=E4=B8=AD?= =?UTF-8?q?=E5=8D=B3=E9=94=81=E5=AE=9A=E5=AE=9A=E4=B9=89=E7=B1=BB=EF=BC=88?= =?UTF-8?q?ret=5Fanc=5Fsha1/ret=5Fanc=5Fname/=E8=BF=94=E5=9B=9E=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=EF=BC=89=EF=BC=8C=E8=B7=B3=E8=BF=87=20text.ll/vpi/pen?= =?UTF-8?q?ding=20=E9=87=8D=E6=9F=A5=E6=AE=B5=EF=BC=8C=E6=8C=89=20{?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=B1=BBsha1}.{=E5=AE=9A=E4=B9=89=E7=B1=BB}.?= =?UTF-8?q?{=E6=96=B9=E6=B3=95}=20=E6=9E=84=E9=80=A0=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/CallGenCall.vp | 38 +++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/CallGenCall.vp b/App/lib/core/Gen/CallGenCall.vp index b2984d3..411cb00 100644 --- a/App/lib/core/Gen/CallGenCall.vp +++ b/App/lib/core/Gen/CallGenCall.vp @@ -640,10 +640,17 @@ class CallGenCall(CallGenBase.CallGenBase): # 普通方法调用在 found_func 未命中时会误绑定到 list 特化函数, # this 按 list 布局前移 sizeof(list) → 运行期读 -1 崩溃 # (Config.vp Load_project_config root.__getitem__ 根因)。 + # 跨模块兄弟 Mixin 兜底命中记录:方法定义类在另一文件(如 + # FuncGenBase._mangle_name——调用类 ClassGenVTable 不继承它), + # 本地 IR 无 define,需经候选类模块 sha1 查 text.ll 返回类型。 + mixin_hit: int = 0 + mixin_ret_ty: llvmlite.LLVMType | t.CPtr = None + mixin_anc_name: str = None + mixin_anc_sha1: str = None if found_func is None: sc_i: int = 0 sc_n: int = self.Gen.StructGen.get_struct_count() - while sc_i < sc_n and found_func is None: + while sc_i < sc_n and found_func is None and mixin_hit == 0: cand_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen._get_struct_entry(sc_i) if cand_entry is not None and cand_entry.Name is not None: cand_name: str = cand_entry.Name @@ -661,6 +668,24 @@ class CallGenCall(CallGenBase.CallGenBase): if cand_func is not None: found_func = cand_func mc_anc = cand_name + else: + # 跨模块 Mixin(定义类在另一文件,本地 IR 无 define): + # 用候选类模块 sha1 查 text.ll 返回类型,命中即锁定定义类, + # 后续 ret_anc_* 据此构造 {sha1}.{class}.{method} 调用名。 + # 否则 ret_anc_sha1 停在调用类自身 sha1,_dep_text_ll_exists + # 查自身 text.ll(Phase A 翻译中未生成)→ 永久 pending 死锁 + # (ClassGenVTable._mangle_name → 7871cc1aabebfc33 根因)。 + if mixin_hit == 0: + cand_sha1_cx: str = self.Gen.StructGen.get_struct_sha1(cand_name) + if cand_sha1_cx is not None \ + and self._dep_text_ll_exists(pool, cand_sha1_cx) != 0: + cand_ret_cx: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL( + pool, cand_sha1_cx, cand_name, method_name) + if cand_ret_cx is not None: + mixin_hit = 1 + mixin_ret_ty = cand_ret_cx + mixin_anc_name = cand_name + mixin_anc_sha1 = cand_sha1_cx sc_i += 1 # 确定调用名(默认 "ClassName.method";found_func 未命中时沿 MRO 用 @@ -725,6 +750,13 @@ class CallGenCall(CallGenBase.CallGenBase): ret_anc_sha1 = mc_entry.ModuleSha1 else: ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) + # 跨模块兄弟 Mixin 兜底命中:定义类锁定为候选类(如 FuncGenBase), + # 返回类型与调用名前缀以其模块 sha1 为准,避免 ret_anc_sha1 停在 + # 调用类自身 sha1 → 查自身 text.ll(未生成)→ 永久 pending 死锁 + if mixin_hit != 0: + ret_anc_name = mixin_anc_name + ret_anc_sha1 = mixin_anc_sha1 + call_ret_ty = mixin_ret_ty if ret_anc_sha1 is None: # 沿 MRO 找第一个有 SHA1 的类 mro_s0: t.CSizeT | t.CPtr = self.Gen.StructGen.get_mro_chain(pool, class_name) @@ -810,7 +842,9 @@ class CallGenCall(CallGenBase.CallGenBase): call_ret_ty = frt_g found_func = spec_found_g gen_done = 1 - if gen_done == 0: + # mixin_hit:跨模块 Mixin 兜底已锁定定义类与返回类型,跳过 + # text.ll/vpi/pending 重查段,直接构造 {sha1}.{class}.{method} 调用名 + if gen_done == 0 and mixin_hit == 0: # 尝试从 text.ll 查找实际返回类型 # 避免指针返回值被默认 i32 导致 inttoptr 截断 looked_up_ty = self._LookupMethodRetTyFromTextLL(