From cf6c917e83046a2c715057107e61a28178b1dbf2 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 20 Aug 2026 04:04:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20=E6=B3=9B=E5=9E=8B=E7=89=B9?= =?UTF-8?q?=E5=8C=96=E7=B1=BB=E8=AE=B0=E5=BD=95=E8=A7=A6=E5=8F=91=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E4=BD=9C=E5=BA=9F=E9=87=8D=E8=AF=91=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E9=87=8D=E7=BD=AE=20MethodsEmitted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 匹配重置。 --- App/lib/core/Gen/ClassGenGeneric.vp | 30 +++++++++++++++++++++++++++ App/lib/core/Gen/StructGenMixin.vp | 19 +++++++++++++---- App/lib/core/Handles/HandlesStruct.vp | 4 ++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/App/lib/core/Gen/ClassGenGeneric.vp b/App/lib/core/Gen/ClassGenGeneric.vp index 880f092..87ea390 100644 --- a/App/lib/core/Gen/ClassGenGeneric.vp +++ b/App/lib/core/Gen/ClassGenGeneric.vp @@ -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 \ No newline at end of file diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 05927a3..bb78dd1 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -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: diff --git a/App/lib/core/Handles/HandlesStruct.vp b/App/lib/core/Handles/HandlesStruct.vp index 255f2ed..407a941 100644 --- a/App/lib/core/Handles/HandlesStruct.vp +++ b/App/lib/core/Handles/HandlesStruct.vp @@ -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].* 根因) # ============================================================