修正了一些错误
This commit is contained in:
@@ -5,7 +5,7 @@ import stdio
|
||||
import viperlib
|
||||
import memhub
|
||||
from linkedlist import GSList, GSListNode
|
||||
from .__types import LLVMType, TypePrint, Array, PrintStructDefinition, get_struct_name, Struct
|
||||
from .__types import LLVMType, TypePrint, Array, PrintStructDefinition, get_struct_name, Struct, ParamNode
|
||||
from .__function import Function, FunctionPrint, _ll_name_needs_quote, Param
|
||||
|
||||
|
||||
@@ -150,39 +150,82 @@ def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
|
||||
# ============================================================
|
||||
# 命名结构体类型管理
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# _is_opaque_struct - 检查类型是否是 opaque 结构体
|
||||
#
|
||||
# opaque 结构体特征: Struct 类型,字段数为 0 且字段列表为 None。
|
||||
# 通过 Struct(pool, None, 0, name) 创建,IR 输出为 %"name" = type opaque。
|
||||
# 用于在 module_add_named_type 中区分 opaque 声明和完整定义,
|
||||
# 确保 opaque 声明插入链表头部(在使用之前声明)。
|
||||
#
|
||||
# Returns: 1=是 opaque / 0=否
|
||||
# ============================================================
|
||||
def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
|
||||
"""检查类型是否是 opaque 结构体(无字段的命名结构体)"""
|
||||
if ty is None:
|
||||
return 0
|
||||
match ty:
|
||||
case LLVMType.Struct(fields, fcount, name):
|
||||
# opaque: 字段数为 0 且字段列表为 None
|
||||
if fcount == 0 and fields is None:
|
||||
return 1
|
||||
return 0
|
||||
case _:
|
||||
return 0
|
||||
|
||||
|
||||
def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
||||
ty: LLVMType | t.CPtr):
|
||||
"""将命名结构体类型添加到模块(用于输出 %"name" = type { ... } 定义行)
|
||||
|
||||
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
|
||||
按 Name 去重,相同名称的类型只保留第一个。
|
||||
按 Name 去重;同名时 opaque 声明可被完整定义替换(供跨模块值类型 alloca)。
|
||||
"""
|
||||
if mod is None or pool is None or ty is None:
|
||||
return
|
||||
name: t.CChar | t.CPtr = get_struct_name(ty)
|
||||
if name is None:
|
||||
return
|
||||
# 去重检查
|
||||
# 去重检查(opaque 声明可被完整定义替换)
|
||||
cur: NamedTypeNode | t.CPtr = mod.NamedTypeHead
|
||||
while cur is not None:
|
||||
if cur.Ty is not None:
|
||||
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
|
||||
if existing_name is not None:
|
||||
if string.strcmp(existing_name, name) == 0:
|
||||
# 已有完整定义则无需替换
|
||||
if _is_opaque_struct(cur.Ty) == 0:
|
||||
return
|
||||
# 已有 opaque,新类型也是 opaque 则不重复
|
||||
if _is_opaque_struct(ty) != 0:
|
||||
return
|
||||
# 用完整定义替换 opaque 声明(原地替换 Ty 指针)
|
||||
cur.Ty = ty
|
||||
return
|
||||
cur = cur.Next
|
||||
# 创建新节点并追加到链表尾部
|
||||
# 创建新节点
|
||||
node: NamedTypeNode | t.CPtr = pool.alloc(NAMED_TYPE_NODE_SIZE)
|
||||
if node is None:
|
||||
return
|
||||
string.memset(node, 0, NAMED_TYPE_NODE_SIZE)
|
||||
node.Ty = ty
|
||||
node.Next = None
|
||||
if mod.NamedTypeHead is None:
|
||||
# opaque 类型插入链表头部,确保在引用它的完整定义之前声明。
|
||||
# 例如 TypeRegistry{HashTable*, ...} 中,HashTable 的 opaque 声明
|
||||
# 必须在 TypeRegistry 定义之前,否则 llc 报 "use of undefined type"。
|
||||
# 完整定义追加到链表尾部,保持原有顺序。
|
||||
if _is_opaque_struct(ty) != 0:
|
||||
node.Next = mod.NamedTypeHead
|
||||
if mod.NamedTypeHead is None:
|
||||
mod.NamedTypeTail = node
|
||||
mod.NamedTypeHead = node
|
||||
else:
|
||||
mod.NamedTypeTail.Next = node
|
||||
mod.NamedTypeTail = node
|
||||
node.Next = None
|
||||
if mod.NamedTypeHead is None:
|
||||
mod.NamedTypeHead = node
|
||||
else:
|
||||
mod.NamedTypeTail.Next = node
|
||||
mod.NamedTypeTail = node
|
||||
mod.NamedTypeCount += 1
|
||||
|
||||
|
||||
@@ -228,8 +271,24 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
|
||||
opaque_ty: LLVMType | t.CPtr = Struct(pool, None, 0, sname)
|
||||
if opaque_ty is not None:
|
||||
module_add_named_type(mod, pool, opaque_ty)
|
||||
# 递归扫描结构体字段中的跨模块引用
|
||||
# 例如 TypeRegistry{HashTable*, MemManager*} 中的 HashTable 引用
|
||||
if sfields is not None:
|
||||
fld: ParamNode | t.CPtr = sfields
|
||||
while fld is not None:
|
||||
if fld.Ty is not None:
|
||||
_scan_type_for_cross_module_refs(pool, mod, fld.Ty)
|
||||
fld = fld.Next
|
||||
case _:
|
||||
_scan_type_for_cross_module_refs(pool, mod, pointee)
|
||||
case LLVMType.Struct(sfields2, sfcount2, sname2):
|
||||
# 顶层结构体(非指针):递归扫描字段
|
||||
if sfields2 is not None:
|
||||
fld2: ParamNode | t.CPtr = sfields2
|
||||
while fld2 is not None:
|
||||
if fld2.Ty is not None:
|
||||
_scan_type_for_cross_module_refs(pool, mod, fld2.Ty)
|
||||
fld2 = fld2.Next
|
||||
case LLVMType.Array(elem_ty, acount):
|
||||
if elem_ty is not None:
|
||||
_scan_type_for_cross_module_refs(pool, mod, elem_ty)
|
||||
@@ -333,12 +392,14 @@ def LLVMModulePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
||||
param_scan = param_scan.Next
|
||||
func_scan = func_scan.Next
|
||||
nt: NamedTypeNode | t.CPtr = mod.NamedTypeHead
|
||||
# 结构体定义缓冲区:48 字段 × ~50 字节/字段类型名 ≈ 2400 字节,4096 足够
|
||||
# 在循环外分配一次并复用,减少 pool 碎片
|
||||
ty_buf: t.CChar | t.CPtr = pool.alloc(4096)
|
||||
while nt is not None:
|
||||
if nt.Ty is not None:
|
||||
ty_buf: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if ty_buf is not None:
|
||||
ty_buf[0] = '\0'
|
||||
PrintStructDefinition(ty_buf, 256, nt.Ty, pool)
|
||||
PrintStructDefinition(ty_buf, 4096, nt.Ty, pool)
|
||||
_append_cstr(buf, size, ty_buf)
|
||||
_append_cstr(buf, size, "\n")
|
||||
nt = nt.Next
|
||||
|
||||
Reference in New Issue
Block a user