fix(gen): 泛型特化类记录触发文件,作废重译正确重置 MethodsEmitted
ld.lld undefined symbol list[ast.ClassDef|t.CPtr].* 根因:Phase A _deps_pending 作废重译时 reset_module_methods_emitted 按当前文件 sha1 精确匹配,特化类 ModuleSha1=模板 sha1(方法名带模板前缀)匹配不到,MethodsEmitted 残留 1 → 下遍 _specialize_generic_class 补译分支(==0 才补译)跳过 → text.ll 只有 call 无 define → 链接失败。 修复:StructEntry 新增 SpecTriggerSha1(特化类触发文件 sha1), _specialize_generic_class 全部返回路径经 _record_spec_trigger 记录, reset_module_methods_emitted 按 ModuleSha1 或 SpecTriggerSha1 匹配重置。
This commit is contained in:
1 parent
b68ae16639
commit
cf6c917e83
3 files changed
+49
-4
No files matched your search
@@ -473,6 +473,29 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
merged[cur_len] = ' '
|
||||
string.strcpy(merged + cur_len + 1, tdeps)
|
||||
trans._imported_modules = merged
|
||||
def _record_spec_trigger(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
spec_name: str, trigger_sha1: str) -> int:
|
||||
"""记录泛型特化类的触发文件 sha1(StructEntry.SpecTriggerSha1)
|
||||
|
||||
特化类 ModuleSha1=模板 sha1(方法名带模板前缀),Phase A _deps_pending
|
||||
作废重译时 reset_module_methods_emitted 按当前文件 sha1 匹配不到 →
|
||||
特化方法体 MethodsEmitted 残留 1 → 下遍不补译 → 链接 undefined symbol。
|
||||
记录触发文件 sha1 后按此精确重置(见 StructGenMixin.reset_module_methods_emitted)。
|
||||
"""
|
||||
if spec_name is None or trigger_sha1 is None:
|
||||
return 0
|
||||
entry_rt: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||||
if entry_rt is None:
|
||||
return 0
|
||||
if string.strcmp(entry_rt.Name, spec_name) != 0:
|
||||
return 0
|
||||
ts_len_r: t.CSizeT = string.strlen(trigger_sha1)
|
||||
ts_buf_r: str = CompilerFactory.get_perm_pool().alloc(ts_len_r + 1)
|
||||
if ts_buf_r is None:
|
||||
return 0
|
||||
string.strcpy(ts_buf_r, trigger_sha1)
|
||||
entry_rt.SpecTriggerSha1 = ts_buf_r
|
||||
return 1
|
||||
def _specialize_generic_class(self, trans: HT.Translator | t.CPtr,
|
||||
class_name: str,
|
||||
type_args: list[str] | t.CPtr) -> str:
|
||||
@@ -491,6 +514,10 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
# 泛型循环套用防护:递归深度 +1,超过上限立即报错终止(防 F-bounded
|
||||
# 等循环特化把编译变死循环)。所有返回路径都必须 -1(见各 return 前)。
|
||||
self.GenericSpecDepth += 1
|
||||
# 特化触发文件 sha1:进入函数时 trans.ModuleSha1 是触发方文件,
|
||||
# 翻译特化类时会被切换为模板 sha1(见下方),作废重译时按此重置
|
||||
# 特化类 MethodsEmitted(见 _record_spec_trigger / reset_module_methods_emitted)
|
||||
spec_trigger_sha1: str = trans.ModuleSha1
|
||||
if self.GenericSpecDepth > GENERIC_SPEC_MAX_DEPTH:
|
||||
err_spec: str = trans.Pool.alloc(256)
|
||||
if err_spec is not None:
|
||||
@@ -603,6 +630,7 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
string.strcat(spec_key, ">")
|
||||
cached: str = self._find_cached_spec(spec_key)
|
||||
if cached is not None:
|
||||
self._record_spec_trigger(pool, spec_name, spec_trigger_sha1)
|
||||
self.GenericSpecDepth -= 1
|
||||
return cached
|
||||
|
||||
@@ -610,6 +638,7 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||||
if existing is not None:
|
||||
self._cache_spec(pool, spec_key, spec_name)
|
||||
self._record_spec_trigger(pool, spec_name, spec_trigger_sha1)
|
||||
self.GenericSpecDepth -= 1
|
||||
return spec_name
|
||||
|
||||
@@ -681,5 +710,6 @@ class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
VLogger.error("SPEC 字段名缺失(字段表损坏)", "SPEC")
|
||||
HandlesType.fatal_error(None, "SPEC 字段名缺失(字段表损坏)", "TypeError")
|
||||
|
||||
self._record_spec_trigger(pool, spec_name, spec_trigger_sha1)
|
||||
self.GenericSpecDepth -= 1
|
||||
return spec_name
|
||||
@@ -523,10 +523,21 @@ class StructGenMixin:
|
||||
reset_count: int = 0
|
||||
for i in range(self.StructCount):
|
||||
entry: HandlesStruct.StructEntry | t.CPtr = self._get_struct_entry(i)
|
||||
if entry is not None and entry.ModuleSha1 is not None:
|
||||
if string.strcmp(entry.ModuleSha1, sha1) == 0:
|
||||
entry.MethodsEmitted = 0
|
||||
reset_count += 1
|
||||
if entry is not None:
|
||||
# 普通类按 ModuleSha1 匹配
|
||||
if entry.ModuleSha1 is not None:
|
||||
if string.strcmp(entry.ModuleSha1, sha1) == 0:
|
||||
entry.MethodsEmitted = 0
|
||||
reset_count += 1
|
||||
continue
|
||||
# 泛型特化类按触发文件 sha1 匹配:特化类 ModuleSha1 是模板 sha1
|
||||
# (方法名带模板前缀),无法匹配当前作废文件。不重置则特化方法体
|
||||
# 残留 MethodsEmitted=1,下遍不补译 → text.ll 只有 call 无 define
|
||||
# → ld.lld undefined symbol(list[ast.ClassDef|t.CPtr].* 根因)
|
||||
if entry.SpecTriggerSha1 is not None:
|
||||
if string.strcmp(entry.SpecTriggerSha1, sha1) == 0:
|
||||
entry.MethodsEmitted = 0
|
||||
reset_count += 1
|
||||
return reset_count
|
||||
|
||||
def find_struct_by_type(self, struct_ty: llvmlite.LLVMType | t.CPtr) -> HandlesStruct.StructEntry | t.CPtr:
|
||||
|
||||
@@ -74,6 +74,10 @@ class StructEntry:
|
||||
VTableMethods: str # 虚表方法名数组(每个方法名 str,VTableMethodCount 个)
|
||||
ModuleSha1: str # 定义该类的模块 SHA1(None=无 SHA1)
|
||||
MethodsEmitted: int # 1=方法体已翻译 / 0=未译(Phase 1a mark_only 未译,Phase B 据此补译)
|
||||
SpecTriggerSha1: str # 泛型特化类的触发文件 SHA1(None=非特化类)。特化类 ModuleSha1=模板
|
||||
# sha1(方法名带模板前缀),作废重译时 reset_module_methods_emitted
|
||||
# 按触发文件 sha1 精确重置 MethodsEmitted,防特化方法体残留 1 不补译
|
||||
# → 链接 undefined symbol(list[ast.ClassDef|t.CPtr].* 根因)
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
Reference in new issue
Block a user