From 27ba74c720e34ed733448ca13c7f3688fb11ae83 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 28 Aug 2026 15:00:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20REnum=20=E5=88=AB=E5=90=8D=E8=A1=A8?= =?UTF-8?q?=E5=8E=BB=E6=8C=87=E9=92=88=E5=8C=96=EF=BC=88class=20=E6=A7=BD?= =?UTF-8?q?=E4=BD=8D=E6=94=B9=20perm=5Fpool=20=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=20+=20strcmp=20=E5=86=85=E5=AE=B9=E6=AF=94=E8=BE=83=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _register_renum_field_alias: class_name strcpy 到 perm_pool,去重检查改 strcmp - _lookup_renum_field_alias/_lookup_renum_field_alias_ty/_lookup_renum_member_ty: 指针值比较改 strcmp 内容比较 - 删除 _update_renum_alias_class_ptr 及调用点(去指针化后无需指针统一) - 根治 'LLVMType 字段 Pointee 未找到' 反复报错(注册 AST 指针 vs 查找 entry.Name 池拷贝指针恒不等) --- App/lib/core/Gen/AssignGenMixin.vp | 3 +- App/lib/core/Gen/Class/ClassGenEnum.vp | 67 +++++++++++--------------- 2 files changed, 29 insertions(+), 41 deletions(-) diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 0e4a2a6..50a71b8 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -801,8 +801,7 @@ class AssignGenMixin: if scope_type == 1: # global 变量 - target_alloca = self.Gen.VarGen.lookup_module_var( - trans.SymTab, nm.id) + target_alloca = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) if target_alloca is not None: if target_alloca.Ty is None: # fail-fast: 变量类型信息缺失,禁止兜底 i32 diff --git a/App/lib/core/Gen/Class/ClassGenEnum.vp b/App/lib/core/Gen/Class/ClassGenEnum.vp index ce42e35..7f9f762 100644 --- a/App/lib/core/Gen/Class/ClassGenEnum.vp +++ b/App/lib/core/Gen/Class/ClassGenEnum.vp @@ -775,14 +775,6 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): VLogger.error(f"failed to register {class_name}", "RENUM") return 0 - # 修复 class_name 指针不匹配: - # 别名注册时用 class_name(= cd.name,AST 原始指针), - # 但查找时用 entry.Name(register_struct 通过 pool.alloc+strcpy 复制的副本指针)。 - # 两者是不同指针,CSizeT 指针值比较会失败。 - # 调用辅助函数将已注册别名的 class_name 统一更新为 entry.Name。 - if entry.Name is not None: - self._update_renum_alias_class_ptr(t.CSizeT(class_name), t.CSizeT(entry.Name)) - # 添加 __tag 字段(位置 0,i32) self.Gen.StructGen.add_field(pool, entry, "__tag", i32_ty, None, None) @@ -973,23 +965,29 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): if self.RenumAliasCount >= RENUM_ALIAS_MAX: return - # 检查是否已注册(避免重复)— class 用 CSizeT 指针值比较(契约不变), - # field 槽位是 perm_pool 拷贝、key 是原指针,指针比较恒不相等 → 改 strcmp - cls_key: t.CSizeT = t.CSizeT(class_name) + # 去重检查(去指针化):class 槽位存 perm_pool 字符串拷贝,用 strcmp + # 内容比较——不再依赖指针值统一("LLVMType 字段 Pointee 未找到"四次 + # 依旧根因:注册用 AST 指针、查找用 entry.Name 池拷贝,指针恒不等)。 for i in range(self.RenumAliasCount): - cls_existing: t.CSizeT = self.RenumAliasClass[i] - if cls_existing == cls_key: + cls_existing_ptr: str = (str | t.CPtr)( + t.CVoid(self.RenumAliasClass[i], t.CPtr)) + if cls_existing_ptr is not None and string.strcmp(cls_existing_ptr, class_name) == 0: fld_existing_ptr: str = (str | t.CPtr)( t.CVoid(self.RenumAliasField[i], t.CPtr)) if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: return idx: int = self.RenumAliasCount - self.RenumAliasClass[idx] = cls_key + # class_name 同样 strcpy 到 perm_pool(去指针化:查找方任何来源的 + # class_name 字符串都可用 strcmp 命中,无需 _update_renum_alias_class_ptr) + cls_len_rfa: t.CSizeT = string.strlen(class_name) + cls_buf_rfa: str = CompilerFactory.factory.PermPool.alloc(cls_len_rfa + 1) + if cls_buf_rfa is None: + return + string.strcpy(cls_buf_rfa, class_name) + self.RenumAliasClass[idx] = t.CSizeT(cls_buf_rfa) # field_name 存 AST 裸指针,1a 每文件 reset 后悬空;_lookup_renum_field_alias # 用 strcmp 内容比较 → strcpy 到 perm_pool 不影响查找。 - # class_name 槽位保持原指针:_update_renum_alias_class_ptr 会统一为 - # entry.Name(perm_pool 拷贝),指针值比较契约不变。 fn_len_rfa: t.CSizeT = string.strlen(field_name) fn_buf_rfa: str = CompilerFactory.factory.PermPool.alloc(fn_len_rfa + 1) if fn_buf_rfa is None: @@ -1014,27 +1012,18 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): string.strcpy(vn_buf_rfa, variant_name) self.RenumAliasVariant[idx] = t.CSizeT(vn_buf_rfa) self.RenumAliasCount = idx + 1 - def _update_renum_alias_class_ptr(self, old_ptr: t.CSizeT, new_ptr: t.CSizeT): - """更新别名表中的 class_name 指针,从 old_ptr 更新为 new_ptr""" - if old_ptr == new_ptr: - return - if self.RenumAliasClass is None: - return - for i in range(self.RenumAliasCount): - if self.RenumAliasClass[i] == old_ptr: - self.RenumAliasClass[i] = new_ptr def _lookup_renum_field_alias(self, class_name: str, field_name: str) -> int: """查找 REnum 变体字段名的 payload 索引,返回索引或 -1 - class_name: 用 CSizeT 指针值比较(_update_renum_alias_class_ptr 已统一指针) - field_name: 用 strcmp 内容比较(注册时 vnm.id 与查找时 at.attr 是不同指针) + class_name/field_name 均用 strcmp 内容比较(去指针化:槽位存 perm_pool + 字符串拷贝,任何来源的 class_name 字符串都可命中) """ if class_name is None or field_name is None or self.RenumAliasClass is None: return -1 - cls_key: t.CSizeT = t.CSizeT(class_name) for i in range(self.RenumAliasCount): - cls_existing: t.CSizeT = self.RenumAliasClass[i] - if cls_existing == cls_key: + cls_existing_ptr: str = (str | t.CPtr)( + t.CVoid(self.RenumAliasClass[i], t.CPtr)) + if cls_existing_ptr is not None and string.strcmp(cls_existing_ptr, class_name) == 0: # field_name 用 strcmp 内容比较(指针不同但内容相同) fld_existing_ptr: str = (str | t.CPtr)( t.CVoid(self.RenumAliasField[i], t.CPtr)) @@ -1045,15 +1034,15 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): field_name: str) -> llvmlite.LLVMType | t.CPtr: """查找 REnum 变体成员的实际 LLVM 类型,返回类型或 None - 与 _lookup_renum_field_alias 同表同键(class 指针值比较 + field strcmp)。 + 与 _lookup_renum_field_alias 同表同键(class/field 均 strcmp 内容比较)。 注册期未解析成功(自引用类型等)槽位为 0 → 返回 None,绑定回退槽位类型。 """ if class_name is None or field_name is None or self.RenumAliasTy is None: return None - cls_key: t.CSizeT = t.CSizeT(class_name) for i in range(self.RenumAliasCount): - cls_existing: t.CSizeT = self.RenumAliasClass[i] - if cls_existing == cls_key: + cls_existing_ptr: str = (str | t.CPtr)( + t.CVoid(self.RenumAliasClass[i], t.CPtr)) + if cls_existing_ptr is not None and string.strcmp(cls_existing_ptr, class_name) == 0: fld_existing_ptr: str = (str | t.CPtr)( t.CVoid(self.RenumAliasField[i], t.CPtr)) if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: @@ -1068,17 +1057,17 @@ class ClassGenEnum(ClassGenBase.ClassGenBase): """按 (class, 变体名, payload 位置) 查找变体成员的实际 LLVM 类型 match 绑定用:同一 payload 位置跨变体类型不同(Int.Bits=i32 vs - Struct.Fields=Ptr),必须带变体名定位。class 指针值比较 + 变体/位置 - 内容比较。返回类型或 None(未注册/未解析成功 → 绑定回退槽位类型)。 + Struct.Fields=Ptr),必须带变体名定位。class/变体均 strcmp 内容比较。 + 返回类型或 None(未注册/未解析成功 → 绑定回退槽位类型)。 """ if class_name is None or variant_name is None or self.RenumAliasVariant is None: return None if payload_idx < 1: return None - cls_key: t.CSizeT = t.CSizeT(class_name) for i in range(self.RenumAliasCount): - cls_existing: t.CSizeT = self.RenumAliasClass[i] - if cls_existing != cls_key: + cls_existing_ptr: str = (str | t.CPtr)( + t.CVoid(self.RenumAliasClass[i], t.CPtr)) + if cls_existing_ptr is None or string.strcmp(cls_existing_ptr, class_name) != 0: continue if self.RenumAliasVariant[i] == 0: continue