diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 80c7d79..1a265d1 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -1657,7 +1657,12 @@ class ClassHandle(BaseHandle): # 预注册 REnum opaque 结构体到 Gen.structs 和 SymbolTable, # 使自引用成员(如 CPtr[LLVMType] / rawptr[LLVMType])在收集成员时能正确解析为 %LLVMType*。 # 若不预注册,GetCTypeInfo 找不到 LLVMType → 回退到 IsEnum → i32 → 再加一层指针 → i32*(错误)。 - PreRenumType: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName) + # 【类型身份唯一】必须复用 `_get_or_create_struct` 的实例:前向声明/导入 stub + # (_get_or_create_struct / _TryLoadStructFromStub)按 `_struct_sha1_map` 建出的 + # 是 `%"{sha1}."`;此处若无条件 new 一个 `%`,同一类在本模块内 + # 出现两个 struct 实例 ⇒ 定义端返回 `%"{sha1}.T"*`、注解端 `%T*`, + # 触发"指针隐式转换已禁止(非基本类型(结构体/类/联合))"。 + PreRenumType: ir.IdentifiedStructType = Gen._get_or_create_struct(ClassName) Gen.structs[ClassName] = PreRenumType PreTypeInfo: CTypeInfo = CTypeInfo() PreTypeInfo.Name = ClassName @@ -1759,13 +1764,19 @@ class ClassHandle(BaseHandle): if not max_variant_struct: max_variant_struct = [ir.IntType(32), ir.IntType(32)] # 复用预注册的 opaque 结构体,设置 body 使其完整 - PreRenumType.set_body(*max_variant_struct) + if PreRenumType.is_opaque: + PreRenumType.set_body(*max_variant_struct) for VariantName, member_types, member_names, member_annotations, lineno, tag_value in variant_info: NestedStructName: str = f"{ClassName}_{VariantName}" if member_types: padded_member_types: list[ir.Type] = list(max_variant_struct) - nested_struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, NestedStructName) - nested_struct_type.set_body(*padded_member_types) + # 变体嵌套结构体与主 REnum 同一条命名规则(`_get_or_create_struct` + # → `_struct_sha1_map` → `%"{sha1}._"`), + # 否则导入端从 stub 拿到的是 sha1 前缀名,与定义端 `%_` + # 分裂成两个类型。 + nested_struct_type: ir.IdentifiedStructType = Gen._get_or_create_struct(NestedStructName) + if nested_struct_type.is_opaque: + nested_struct_type.set_body(*padded_member_types) Gen.structs[NestedStructName] = nested_struct_type if NestedStructName not in Gen.class_members: Gen.class_members[NestedStructName] = [] diff --git a/lib/core/Translator/PythonParser.py b/lib/core/Translator/PythonParser.py index cdac4ec..8f8dc87 100644 --- a/lib/core/Translator/PythonParser.py +++ b/lib/core/Translator/PythonParser.py @@ -276,15 +276,27 @@ class PythonParserMixin: # 先把类名加入 GeneratedTypes,这样 GetTypeName 可以正确识别 self.GeneratedTypes.add(ClassName) - # 检测是否是 CEnum + # 检测是否是 CEnum / REnum。REnum 必须与 CEnum 区分开: + # REnum 是带标签联合(结构体布局 { i32 __tag, }), + # 若这里只登记 IsEnum=True,前向声明阶段(类体尚未发射、 + # _EmitREnumLlvm 的 PreTypeInfo 尚未插入)解析 `T*` 注解时会 + # 命中 IsEnum 分支退化成 i32*,与 `new memgr(...) T.X(...)` + # 返回的 %"T"* 冲突(现场:includes/mlirlite/__types.vp)。 IsCenum: bool = False + IsRenum: bool = False for base in node.bases: if isinstance(base, ast.Attribute): - if base.attr in ('CEnum', 'REnum'): + if base.attr == 'REnum': + IsRenum = True + break + if base.attr == 'CEnum': IsCenum = True break elif isinstance(base, ast.Name): - if base.id in ('CEnum', 'REnum'): + if base.id == 'REnum': + IsRenum = True + break + if base.id == 'CEnum': IsCenum = True break @@ -323,11 +335,17 @@ class PythonParserMixin: IsCpythonObject = True break - if IsCenum: - # 注册为 enum 类型 + if IsCenum or IsRenum: + # 注册为 enum / renum 类型 EnumNode: CTypeInfo = CTypeInfo() EnumNode.Name = ClassName EnumNode.IsEnum = True + if IsRenum: + # 与 SymbolTable._InsertClassSymbol 的 'renum' 分支同口径: + # REnum 是结构体布局,不是整数枚举。 + EnumNode.BaseType = TypeSystem.REnum(ClassName) + EnumNode.IsRenum = True + EnumNode.IsStruct = True EnumNode.set('file', '') self.SymbolTable.insert(ClassName, EnumNode) diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index 045a84a..cdcd02b 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -662,6 +662,18 @@ class TypeAnnotationResolver: Result.Name = TypeName return Result return Entry + # REnum 优先于 IsEnum:REnum 条目的标志组合是 + # IsStruct=True + IsRenum=True + IsEnum=True(SymbolTable._InsertClassSymbol + # 的 'renum' 分支)。若先命中 IsEnum 会退化成 i32, + # 指针注解 `T*` 随之变成 i32*(现场:includes/mlirlite/__types.vp + # 的 `-> LLVMType*` 被编成 i32*,而 new memgr 构造返回 %"LLVMType"*)。 + if Entry.IsRenum: + Result = CTypeInfo() + Result.BaseType = TypeSystem.CStruct(name=TypeName) + Result.IsStruct = True + Result.IsRenum = True + Result.Name = TypeName + return Result if Entry.IsEnum: Result = CTypeInfo() Result.BaseType = TypeSystem.CInt() @@ -1008,6 +1020,15 @@ class TypeAnnotationResolver: if Resolved.BaseType is None: Resolved.BaseType = TypeSystem._CTypedef(TypeName) return Resolved + # REnum 优先于 IsEnum(同 _from_node_name:REnum 同时带 IsEnum=True, + # 先判 IsEnum 会把 `Mod.REnum` 注解退化成 i32,指针注解成 i32*)。 + if Entry and Entry.IsRenum: + Result: CTypeInfo = CTypeInfo() + Result.BaseType = TypeSystem.CStruct(name=TypeName) + Result.IsStruct = True + Result.IsRenum = True + Result.Name = TypeName + return Result if Entry and Entry.IsEnum: Result: CTypeInfo = CTypeInfo() Result.BaseType = TypeSystem.CInt()