fix(renum): 返回类型按结构体指针解析

REnum 预登记为 IsRenum/IsStruct;类型解析先判 REnum;_EmitREnumLlvm 复用已有结构体实例,修复 LLVMType* 退化为 i32*。
This commit is contained in:
TermiNexus committed 2026-10-18 21:17:03 +08:00
1 parent b6d6d5ac6b
commit fe10e4dcd2
3 files changed
+59 -9

No files matched your search

+15 -4
View File
@@ -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}.<Class>"`;此处若无条件 new 一个 `%<Class>`,同一类在本模块内
# 出现两个 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}.<REnum>_<Variant>"`),
# 否则导入端从 stub 拿到的是 sha1 前缀名,与定义端 `%<REnum>_<Variant>`
# 分裂成两个类型。
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] = []
+23 -5
View File
@@ -276,15 +276,27 @@ class PythonParserMixin:
# 先把类名加入 GeneratedTypes,这样 GetTypeName 可以正确识别
self.GeneratedTypes.add(ClassName)
# 检测是否是 CEnum
# 检测是否是 CEnum / REnum。REnum 必须与 CEnum 区分开:
# REnum 是带标签联合(结构体布局 { i32 __tag, <max payload> }),
# 若这里只登记 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', '<stdin>')
self.SymbolTable.insert(ClassName, EnumNode)
+21
View File
@@ -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()