diagnose(tpv): Phase A pending 置位点全量 [DEPDBG] 诊断 + 别名解析修复 - 9 处 _deps_pending 置位点加 [DEPDBG] printf(CallGenCall×4/CallGenMixin/CallGenDispatch×2/CallGenProp/ExprGenName),一次构建即可定位 ClassGenVTable 永久 pending 的具体调用点 - StubMergerStore 新增 LookupSha1ByAlias:经 from_imports 别名映射(import X as Y → Y:X)解析模块 SHA1 - LoadDepVpiIntoModule 与 Phase A 依赖探针接入别名解析,HT 等改名别名不再误报未解析

This commit is contained in:
TermiNexus committed 2026-08-23 14:21:44 +08:00
1 parent 6cd8adc54c
commit 27f2a53c15
8 files changed
+118 -6

No files matched your search

+3
View File
@@ -740,6 +740,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
im_dp_sha1: str = StubMergerStore.LookupSha1ByModName(im_dp_buf)
if im_dp_sha1 is None:
im_dp_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(im_dp_buf)
if im_dp_sha1 is None:
# 改名别名(import X as Y):从 _from_imports 查 Y→X 再查 SHA1
im_dp_sha1 = StubMergerStore.LookupSha1ByAlias(tr_a._from_imports, im_dp_buf)
im_dp_resolved: int = 0
im_dp_missing: int = 0
if im_dp_sha1 is not None:
@@ -1204,6 +1204,12 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy | t.CPtr,
# 用 LookupSha1ByModName 查找模块的 SHA1
sha1_val: str = StubMergerStore.LookupSha1ByModName(mod_nm_buf)
# 改名别名(import X as Y,如 HT→lib.core.Handles.HandlesTranslator):
# 精确/包名回退均失败时从 from_imports 查别名映射再查 SHA1,
# 否则该类模块的 vpi/stub 不注入 → 跨模块符号解析失败
if sha1_val is None and from_imports is not None:
sha1_val = StubMergerStore.LookupSha1ByAlias(from_imports, mod_nm_buf)
# 如果精确查找失败,尝试包名回退(如 "ast" → "ast.__init__")
# LookupSha1ByModName 内部已处理包名回退,此处无需重复
+61 -6
View File
@@ -18,19 +18,15 @@ import lib.Stub.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
import lib.Stub.StubMerger.StubMergerTopo as StubMergerTopo
import lib.Stub.StubMerger.StubMergerIR as StubMergerIR
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
import lib.Stub.StubMerger as StubMerger
# ============================================================
# StubMergerStore - StubMerger 拆分(阶段 E):StubMergerStore
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
@@ -273,6 +269,64 @@ def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
return StubMerger._sha1_store_arr + sidx_rev_sf
return None
# ============================================================
# LookupSha1ByAlias - 从 from_imports 别名映射解析模块 SHA1
#
# from_imports 条目格式: "local:module" 或 "local:module:orig"(空格分隔),
# 由 ImportsGenMixin.add_from_import 写入(import X as Y → "Y:X")。
# 命中 local==alias 时,对 module 执行 LookupSha1ByModName 返回 SHA1。
#
# Returns:
# SHA1 字符串指针(指向全局存储器内部),None 未找到
# ============================================================
def LookupSha1ByAlias(from_imports: str, alias: str) -> str:
"""从 from_imports 别名映射解析模块 SHA1(改名别名 import X as Y 场景)"""
if from_imports is None or alias is None:
return None
alias_len: t.CSizeT = string.strlen(alias)
if alias_len == 0:
return None
total_len: t.CSizeT = string.strlen(from_imports)
ci: t.CSizeT = 0
while ci < total_len:
# 跳过前导空格
while ci < total_len and from_imports[ci] == ' ':
ci += 1
if ci >= total_len:
break
# 条目起点 ci,找 ':'(local_name 结束)
colon: t.CSizeT = ci
while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ':
colon += 1
local_len: t.CSizeT = colon - ci
if colon < total_len and from_imports[colon] == ':' and local_len == alias_len:
# 比较 local_name == alias
match: int = 1
li: t.CSizeT = 0
while li < alias_len:
if from_imports[ci + li] != alias[li]:
match = 0
break
li += 1
if match == 1:
# 提取 module(colon+1 到下一个 ':' 或空格)
m_start: t.CSizeT = colon + 1
m_end: t.CSizeT = m_start
while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ':
m_end += 1
if m_end > m_start:
mbuf: str = stdlib.malloc(m_end - m_start + 1)
if mbuf is not None:
string.strncpy(mbuf, from_imports + m_start, m_end - m_start)
mbuf[m_end - m_start] = '\0'
res: str = LookupSha1ByModName(mbuf)
stdlib.free(mbuf)
return res
return None
# 跳到下一条目
while ci < total_len and from_imports[ci] != ' ':
ci += 1
return None
# ============================================================
# PopulateIncludesDeps - 将 includes 文件的依赖存入内存
#
# Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules
@@ -371,7 +425,7 @@ def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CP
return -1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None:
return -1
sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr))
sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr)) # 存疑
if sp is not None:
sp[0] = StubMerger._sha1_store_arr
mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr))
@@ -381,6 +435,7 @@ def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CP
if rp is not None:
rp[0] = StubMerger._sha1_store_rel
return StubMerger._sha1_store_count
# ============================================================
# LookupSha1RelPath - 通过 SHA1 查找相对路径
#
+23
View File
@@ -362,6 +362,11 @@ class CallGenCall(CallGenBase.CallGenBase):
and self._dep_text_ll_exists(pool, cls_sha1) == 0):
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:方法返回类型解析依赖未就绪即 pending 的根因(用后移除)
dbg_ms1: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(method_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms1, class_name, method_name,
cls_sha1 if cls_sha1 is not None else "none")
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None 会
# 破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
call_ret_ty = llvmlite.Int32(pool)
@@ -867,6 +872,12 @@ class CallGenCall(CallGenBase.CallGenBase):
and self._dep_text_ll_exists(pool, ret_anc_sha1) == 0):
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:方法祖先模块依赖未就绪即 pending 的根因(用后移除)
dbg_ms2: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(mro_ret): mod=%s cls=%s method=%s ret_sha1=%s text=%d\n",
dbg_ms2, class_name, method_name,
ret_anc_sha1 if ret_anc_sha1 is not None else "none",
self._dep_text_ll_exists(pool, ret_anc_sha1) if ret_anc_sha1 is not None else -1)
# 依赖未就绪:保持默认 i32 继续而非 Void——build_call(Void)
# 返回 None,方法调用结果喂进表达式(if 条件/比较)时 fatal
# "if 条件表达式翻译失败"(ExprGenAttr._get_cderef_attr_base
@@ -898,6 +909,12 @@ class CallGenCall(CallGenBase.CallGenBase):
if anc_missing_p2 != 0:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:MRO 祖先模块依赖未就绪即 pending 的根因(用后移除)
dbg_ms3: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(mro_anc): mod=%s cls=%s method=%s anc=%s anc_sha1=%s\n",
dbg_ms3, class_name, method_name,
anc_p2 if anc_p2 is not None else "none",
anc_sha1_p2 if anc_sha1_p2 is not None else "none")
# 依赖未就绪:保持默认 i32(同上,build_call(Void) 返回
# None 会破坏表达式翻译,pending 文件本遍不写盘)
call_ret_ty = llvmlite.Int32(pool)
@@ -1523,6 +1540,12 @@ class CallGenCall(CallGenBase.CallGenBase):
or self._dep_text_ll_exists(pool, anc_sha1_sp) == 0:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:特殊方法依赖未就绪即 pending 的根因(用后移除)
dbg_ms4: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(special_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms4, anc if anc is not None else "?",
method_name,
anc_sha1_sp if anc_sha1_sp is not None else "none")
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
ret_ty_sp = llvmlite.Int32(pool)
+9
View File
@@ -1097,6 +1097,11 @@ class CallGenDispatch(CallGenBase.CallGenBase):
# 中断多遍收敛(对齐追加77/77b 类 defer 原则)。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:方法返回类型解析依赖未就绪即 pending 的根因(用后移除)
dbg_ms6: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(dispatch_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms6, cls_nm2, func_name,
sha1_fc if sha1_fc is not None else "none")
# 依赖未就绪:保持默认 i32(build_call(Void)
# 返回 None 破坏表达式翻译;本遍不写盘)
ret_ty3 = llvmlite.Int32(pool)
@@ -1121,6 +1126,10 @@ class CallGenDispatch(CallGenBase.CallGenBase):
if obj_ptr4 is not None:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:特殊方法依赖未就绪即 pending 的根因(用后移除)
dbg_ms7: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(dispatch_sp): mod=%s cls=%s method=%s\n",
dbg_ms7, cls_nm2, func_name)
if hit_box is not None:
hit_box[0] = 1
return self.Gen.CallGenCall._translate_method_call(
+6
View File
@@ -1164,6 +1164,12 @@ class CallGenMixin(CallGenBase.CallGenBase):
else:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:跨模块函数依赖未就绪即 pending 的根因(用后移除)
dbg_ms5: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(cross_fn): mod=%s call=%s sha1=%s text=%d\n",
dbg_ms5, call_name,
cf_sha1 if cf_sha1 is not None else "none",
self._dep_text_ll_exists(pool, cf_sha1) if cf_sha1 is not None else -1)
cf_dbg: str = VLogger.fmt_buf()
if cf_dbg is not None:
viperlib.snprintf(
+5
View File
@@ -125,6 +125,11 @@ class CallGenProp(CallGenBase.CallGenBase):
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:属性方法依赖未就绪即 pending 的根因(用后移除)
dbg_ms8: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(prop_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms8, class_name, method_name,
cls_sha1_rt if cls_sha1_rt is not None else "none")
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
call_ret_ty = llvmlite.Int32(pool)
+5
View File
@@ -337,6 +337,11 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# lexer 先于 tokens 翻译必然误报 "stub 未注入"。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:全局 stub 未注入即 pending 的根因(用后移除)
dbg_ms9: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(global_stub): mod=%s name=%s mod_src=%s sha1=%s\n",
dbg_ms9, nm_id, fi_mod_cut2,
StubMergerStore.LookupSha1ByModName(fi_mod_cut2) if fi_mod_cut2 is not None else "none")
return None
if ref_fi is not None and ref_fi.Ty is not None:
lty_fi: llvmlite.LLVMType | t.CPtr = ref_fi.Ty.Pointee