fix(renum): 返回类型按结构体指针解析
REnum 预登记为 IsRenum/IsStruct;类型解析先判 REnum;_EmitREnumLlvm 复用已有结构体实例,修复 LLVMType* 退化为 i32*。
This commit is contained in:
1 parent
b6d6d5ac6b
commit
fe10e4dcd2
3 files changed
+59
-9
No files matched your search
@@ -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] = []
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user