fix(tpv): REnum 别名表去指针化(class 槽位改 perm_pool 字符串 + strcmp 内容比较)
- _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 池拷贝指针恒不等)
This commit is contained in:
1 parent
a8eb7fe5fe
commit
27ba74c720
2 files changed
+29
-41
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user