diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 5f409bf..f23b851 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -700,10 +700,13 @@ class ClassHandle(BaseHandle): Gen._cross_module_vtable_classes.discard(ClassName) Gen._cross_module_novtable.add(ClassName) # 清除可能从导入 stub 加载的旧 struct body(含错误 vtable 指针), - # 让 _generate_structs 用本地 class_members 重新生成 + # 让 _generate_structs 用本地 class_members 重新生成。 + # 字段名必须是 llvmlite 的**公开属性 `elements`**(is_opaque = elements is None; + # set_body 仅在 elements is not None 时拒绝)——写 `_elements` 在本版本是空操作, + # 会让"权威重建点"永远无法刷新已冻结的错误布局。 _old_st = Gen.structs.get(ClassName) if isinstance(_old_st, ir.IdentifiedStructType) and _old_st.elements is not None: - _old_st._elements = None + _old_st.elements = None _ih = getattr(Gen, '_import_handler_ref', None) if _ih is not None: _ck = (id(Gen), ClassName) diff --git a/lib/core/LLVMCG/StructGen.py b/lib/core/LLVMCG/StructGen.py index 6cbde73..beef76a 100644 --- a/lib/core/LLVMCG/StructGen.py +++ b/lib/core/LLVMCG/StructGen.py @@ -499,7 +499,8 @@ class StructGenMixin: # 治本修复:检查 struct body 是否不完整(元素数少于 class_members + vtable 预期)。 # 常见于跨模块继承:子类 struct 在父类 class_members 加载前从 stub 生成, # stub 中的定义可能不完整或类型不正确(如 GSList* 代替 AST*、i8* 代替 i32)。 - # 此处检测到不完整后清除 _elements 和 stub 缓存,让后续代码重新从 stub 加载。 + # 此处检测到不完整后清除 elements(公开属性,见下方 Step 4 说明)和 + # stub 缓存,让后续代码重新从 stub 加载。 _has_vtable_precheck: bool = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes if not _has_vtable_precheck: _p_pre: str | None = self.class_parent.get(ClassName) @@ -554,19 +555,26 @@ class StructGenMixin: if ClassName in self.class_packed and not existing_st.packed: existing_st.packed = True continue - # struct body 不完整,清除 _elements 和 stub 缓存以便重新加载 - existing_st._elements = None - # 同时清除 sha1 全名 key 的 _elements: + # struct body 不完整,清除 elements 和 stub 缓存以便重新加载。 + # 注意:本仓 llvmlite 版本的字段名是**公开属性 `elements`** + # (types.py: `self.elements = None`;`is_opaque` = `elements is None`; + # `set_body` 只在 `elements is not None` 时拒绝)。此前写 + # `_elements = None` 在本版本**不存在该属性** ⇒ 清空是空操作 ⇒ + # 后续 `if struct_type.elements is None` 恒假 ⇒ set_body 永不执行 ⇒ + # 错误布局(现场 Generator elements[11]=i8**)被永久冻结,而 + # class_members 已被权威重建为正确类型 ⇒ 赋值时报"层数不同"。 + existing_st.elements = None + # 同时清除 sha1 全名 key 的 elements: # self.structs 中可能同时存在 'Value'(短名) 和 'f9e36e2cd6fa659f.Value'(sha1全名) 两个 key, # _TryLoadStructFromStub 调用 _get_or_create_struct 时会返回 sha1全名 key 的 struct。 - # 若只清除短名 key 的 _elements,sha1全名 key 的 struct 仍保持错误 body(is_opaque=False), + # 若只清除短名 key 的 elements,sha1全名 key 的 struct 仍保持错误 body(is_opaque=False), # 导致 _TryLoadStructFromStub 跳过 set_body,struct 保持不完整字段数。 _imported_sha1_pre: str = self.class_sha1_map.get(ClassName, '') if _imported_sha1_pre: _full_key_pre: str = f"{_imported_sha1_pre}.{ClassName}" _full_st_pre: ir.IdentifiedStructType | None = self.structs.get(_full_key_pre) if _full_st_pre is not None and isinstance(_full_st_pre, ir.IdentifiedStructType): - _full_st_pre._elements = None + _full_st_pre.elements = None _import_handler_pre: Any = self._import_handler_ref if _import_handler_pre is not None: _cache_key_pre: tuple = (id(self), ClassName) @@ -672,7 +680,8 @@ class StructGenMixin: struct_type = self.structs.get(ClassName, struct_type) # 检测 stub body 中的 T* 占位类型(未特化的泛型类型参数)。 # 若 stub 使用了未特化的基类(如 GSListNode 而非 GSListNode[BasicBlock]), - # 清除 _elements 让 set_body 用正确的 class_members 重新设置。 + # 清除 elements 让 set_body 用正确的 class_members 重新设置 + # (字段名必须是公开属性 `elements`,见上方 Step 4 的说明)。 if struct_type.elements is not None and member_types: _has_t_placeholder_post: bool = False for _elem_post in struct_type.elements: @@ -683,7 +692,7 @@ class StructGenMixin: _has_t_placeholder_post = True break if _has_t_placeholder_post: - struct_type._elements = None + struct_type.elements = None if struct_type.elements is None: # 防御性检查:member_types 为空时不调用 set_body。 # set_body(*[]) 会设置 elements=() 使 is_opaque=False,