refactor(llvmlite): P0 对象化 - IRBuilder/LLVMModule 方法化(70 方法+一行委托兼容)

- IRBuilder 新增 62 个实例方法(load/store/gep/call/binop/cast 等), 顶层函数保留为一行委托, 调用方零改动
- LLVMModule 新增 8 个实例方法(add_function/add_global/add_named_type/PrintModule 等)
- 类字段/硬编码 SIZE/逻辑/IR 输出零变化, GetDiagnostics 无错误
- 新增 wiki/14-oo-refactor.md 对象化重构方案(P0-P6)
This commit is contained in:
TermiNexus committed 2026-08-09 22:54:01 +08:00
1 parent e1cb560df0
commit fc93a28ec6
3 files changed
+1620 -873

No files matched your search

File diff suppressed because it is too large. Load diff
+240 -205
View File
@@ -61,6 +61,238 @@ class LLVMModule:
NamedTypeCount: t.CSizeT # 命名结构体类型计数
# 总计: 12 字段 * 8 = 96 字节(无 vtable)
# ============================================================
# 实例方法(对象化重构:原 module_* 顶层函数改写为方法,
# 原顶层函数保留为一行委托)
# ============================================================
# ---- 链表操作 ----
def add_function(self, func: Function | t.CPtr):
"""将函数追加到模块函数链表(O(1))"""
if self is None or func is None: return
func.Next = None
if self.FuncHead is None:
self.FuncHead = func
else:
self.FuncTail.Next = func
self.FuncTail = func
self.FuncCount += 1
def add_global(self, gv: GlobalVariable | t.CPtr):
"""将全局变量追加到模块全局变量链表(O(1))"""
if self is None or gv is None: return
gv.Next = None
if self.GlobalHead is None:
self.GlobalHead = gv
else:
self.GlobalTail.Next = gv
self.GlobalTail = gv
self.GlobalCount += 1
# ---- 目标属性 ----
def set_target(self, triple: t.CChar | t.CPtr):
"""设置目标三元组"""
if self is None: return
self.TargetTriple = triple
def set_datalayout(self, layout: t.CChar | t.CPtr):
"""设置数据布局"""
if self is None: return
self.DataLayout = layout
# ---- 命名结构体类型管理 ----
def add_named_type(self, pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr):
"""将命名结构体类型添加到模块(用于输出 %"name" = type { ... } 定义行)
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
按 Name 去重;同名时 opaque 声明可被完整定义替换(供跨模块值类型 alloca)。
"""
if self 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 = self.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
# opaque 类型插入链表头部,确保在引用它的完整定义之前声明。
# 例如 TypeRegistry{HashTable*, ...} 中,HashTable 的 opaque 声明
# 必须在 TypeRegistry 定义之前,否则 llc 报 "use of undefined type"。
# 完整定义追加到链表尾部,保持原有顺序。
if _is_opaque_struct(ty) != 0:
node.Next = self.NamedTypeHead
if self.NamedTypeHead is None:
self.NamedTypeTail = node
self.NamedTypeHead = node
else:
node.Next = None
if self.NamedTypeHead is None:
self.NamedTypeHead = node
else:
self.NamedTypeTail.Next = node
self.NamedTypeTail = node
self.NamedTypeCount += 1
def _is_type_defined_in_module(self, name: t.CChar | t.CPtr) -> int:
"""检查模块中是否已定义指定名称的结构体类型,返回 1=已定义 / 0=未定义"""
if self is None or name is None:
return 0
cur: NamedTypeNode | t.CPtr = self.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:
return 1
cur = cur.Next
return 0
def ensure_opaque_for_type(self, pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
"""为类型中的跨模块结构体引用添加 opaque 声明
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
如果该名称未在模块中定义,则添加 opaque 声明。
"""
_scan_type_for_cross_module_refs(pool, self, ty)
# ---- 打印 ----
def PrintModule(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pool: memhub.MemBuddy | t.CPtr, mode: t.CInt):
"""将模块序列化为 .ll 文本写入 buf"""
if self is None or buf is None or size == 0: return
# 头部注释(stub 和 full 模式输出,text 模式不输出)
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
_append_cstr(buf, size, "; ModuleID = '")
if self.Name is not None:
_append_cstr(buf, size, self.Name)
_append_cstr(buf, size, "'\n")
# 目标三元组
if self.TargetTriple is not None:
_append_cstr(buf, size, "target triple = \"")
_append_cstr(buf, size, self.TargetTriple)
_append_cstr(buf, size, "\"\n")
# 数据布局
if self.DataLayout is not None:
_append_cstr(buf, size, "target datalayout = \"")
_append_cstr(buf, size, self.DataLayout)
_append_cstr(buf, size, "\"\n")
# 空行
_append_cstr(buf, size, "\n")
# 命名结构体类型定义(stub 和 full 模式输出,text 模式不输出)
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
# 修复:alloc_buf 返回 viperio.Buf,但 Buf 类型未在 NamedTypeHead 中注册
func_scan: Function | t.CPtr = self.FuncHead
while func_scan is not None:
if func_scan.RetTy is not None:
self.ensure_opaque_for_type(pool, func_scan.RetTy)
if func_scan.Params is not None:
param_scan: Param | t.CPtr = func_scan.Params.Head
while param_scan is not None:
if param_scan.Ty is not None:
self.ensure_opaque_for_type(pool, param_scan.Ty)
param_scan = param_scan.Next
func_scan = func_scan.Next
nt: NamedTypeNode | t.CPtr = self.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:
if ty_buf is not None:
ty_buf[0] = '\0'
PrintStructDefinition(ty_buf, 4096, nt.Ty, pool)
_append_cstr(buf, size, ty_buf)
_append_cstr(buf, size, "\n")
nt = nt.Next
if self.NamedTypeHead is not None:
_append_cstr(buf, size, "\n")
# 全局变量
gv: GlobalVariable | t.CPtr = self.GlobalHead
if mode == OUTPUT_STUB:
# stub 模式:输出 external global(无初值)
while gv is not None:
_print_global_stub(buf, size, gv, pool)
_append_cstr(buf, size, "\n")
gv = gv.Next
else:
# full 和 text 模式:输出完整全局变量
# text 模式跳过无初值的全局变量(纯声明)
gv_idx: t.CInt = 0
while gv is not None:
if mode == OUTPUT_TEXT and gv.Initializer is None:
gv = gv.Next
gv_idx += 1
continue
_print_global(buf, size, gv, pool)
_append_cstr(buf, size, "\n")
gv = gv.Next
gv_idx += 1
if self.GlobalHead is not None and (mode == OUTPUT_FULL or mode == OUTPUT_STUB):
_append_cstr(buf, size, "\n")
elif self.GlobalHead is not None and mode == OUTPUT_TEXT:
# text 模式下如果输出了全局变量,也加空行
had_global: t.CInt = 0
gv2: GlobalVariable | t.CPtr = self.GlobalHead
while gv2 is not None:
if gv2.Initializer is not None:
had_global = 1
break
gv2 = gv2.Next
if had_global != 0:
_append_cstr(buf, size, "\n")
# 遍历函数
func: Function | t.CPtr = self.FuncHead
func_idx: t.CInt = 0
while func is not None:
if mode == OUTPUT_STUB:
# stub 模式:仅输出 declare(IsDeclared==1)
if func.IsDeclared == 1:
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
elif mode == OUTPUT_TEXT:
# text 模式:仅输出 define(IsDeclared==0)
if func.IsDeclared == 0:
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
else:
# full 模式:输出所有函数
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
func = func.Next
func_idx += 1
# ============================================================
# 工厂函数
@@ -112,39 +344,19 @@ def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
# 链表操作(嵌入式 Head/Tail/Count,O(1) 追加)
# ============================================================
def module_add_function(mod: LLVMModule | t.CPtr, func: Function | t.CPtr):
"""将函数追加到模块函数链表(O(1))"""
if mod is None or func is None: return
func.Next = None
if mod.FuncHead is None:
mod.FuncHead = func
else:
mod.FuncTail.Next = func
mod.FuncTail = func
mod.FuncCount += 1
return mod.add_function(func)
def module_add_global(mod: LLVMModule | t.CPtr, gv: GlobalVariable | t.CPtr):
"""将全局变量追加到模块全局变量链表(O(1))"""
if mod is None or gv is None: return
gv.Next = None
if mod.GlobalHead is None:
mod.GlobalHead = gv
else:
mod.GlobalTail.Next = gv
mod.GlobalTail = gv
mod.GlobalCount += 1
return mod.add_global(gv)
def module_set_target(mod: LLVMModule | t.CPtr, triple: t.CChar | t.CPtr):
"""设置目标三元组"""
if mod is None: return
mod.TargetTriple = triple
return mod.set_target(triple)
def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
"""设置数据布局"""
if mod is None: return
mod.DataLayout = layout
return mod.set_datalayout(layout)
# ============================================================
@@ -177,56 +389,7 @@ def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
"""将命名结构体类型添加到模块(用于输出 %"name" = type { ... } 定义行)
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
按 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
# 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:
node.Next = None
if mod.NamedTypeHead is None:
mod.NamedTypeHead = node
else:
mod.NamedTypeTail.Next = node
mod.NamedTypeTail = node
mod.NamedTypeCount += 1
return mod.add_named_type(pool, ty)
# ============================================================
@@ -237,18 +400,7 @@ def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CP
# 这解决了跨模块结构体引用导致的 llc "use of undefined type" 错误。
# ============================================================
def _is_type_defined_in_module(mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr) -> int:
"""检查模块中是否已定义指定名称的结构体类型,返回 1=已定义 / 0=未定义"""
if mod is None or name is None:
return 0
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:
return 1
cur = cur.Next
return 0
return mod._is_type_defined_in_module(name)
def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
@@ -299,12 +451,7 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
def module_ensure_opaque_for_type(mod: LLVMModule | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
"""为类型中的跨模块结构体引用添加 opaque 声明
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
如果该名称未在模块中定义,则添加 opaque 声明。
"""
_scan_type_for_cross_module_refs(pool, mod, ty)
return mod.ensure_opaque_for_type(pool, ty)
# ============================================================
@@ -350,119 +497,7 @@ OUTPUT_TEXT: t.CDefine = 2 # 仅代码(define + global 带初值)
def LLVMModulePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
mode: t.CInt):
"""将模块 mod 序列化为 .ll 文本写入 buf"""
if mod is None or buf is None or size == 0: return
# 头部注释(stub 和 full 模式输出,text 模式不输出)
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
_append_cstr(buf, size, "; ModuleID = '")
if mod.Name is not None:
_append_cstr(buf, size, mod.Name)
_append_cstr(buf, size, "'\n")
# 目标三元组
if mod.TargetTriple is not None:
_append_cstr(buf, size, "target triple = \"")
_append_cstr(buf, size, mod.TargetTriple)
_append_cstr(buf, size, "\"\n")
# 数据布局
if mod.DataLayout is not None:
_append_cstr(buf, size, "target datalayout = \"")
_append_cstr(buf, size, mod.DataLayout)
_append_cstr(buf, size, "\"\n")
# 空行
_append_cstr(buf, size, "\n")
# 命名结构体类型定义(stub 和 full 模式输出,text 模式不输出)
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
# 修复:alloc_buf 返回 viperio.Buf,但 Buf 类型未在 NamedTypeHead 中注册
func_scan: Function | t.CPtr = mod.FuncHead
while func_scan is not None:
if func_scan.RetTy is not None:
module_ensure_opaque_for_type(mod, pool, func_scan.RetTy)
if func_scan.Params is not None:
param_scan: Param | t.CPtr = func_scan.Params.Head
while param_scan is not None:
if param_scan.Ty is not None:
module_ensure_opaque_for_type(mod, pool, param_scan.Ty)
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:
if ty_buf is not None:
ty_buf[0] = '\0'
PrintStructDefinition(ty_buf, 4096, nt.Ty, pool)
_append_cstr(buf, size, ty_buf)
_append_cstr(buf, size, "\n")
nt = nt.Next
if mod.NamedTypeHead is not None:
_append_cstr(buf, size, "\n")
# 全局变量
gv: GlobalVariable | t.CPtr = mod.GlobalHead
if mode == OUTPUT_STUB:
# stub 模式:输出 external global(无初值)
while gv is not None:
_print_global_stub(buf, size, gv, pool)
_append_cstr(buf, size, "\n")
gv = gv.Next
else:
# full 和 text 模式:输出完整全局变量
# text 模式跳过无初值的全局变量(纯声明)
gv_idx: t.CInt = 0
while gv is not None:
if mode == OUTPUT_TEXT and gv.Initializer is None:
gv = gv.Next
gv_idx += 1
continue
_print_global(buf, size, gv, pool)
_append_cstr(buf, size, "\n")
gv = gv.Next
gv_idx += 1
if mod.GlobalHead is not None and (mode == OUTPUT_FULL or mode == OUTPUT_STUB):
_append_cstr(buf, size, "\n")
elif mod.GlobalHead is not None and mode == OUTPUT_TEXT:
# text 模式下如果输出了全局变量,也加空行
had_global: t.CInt = 0
gv2: GlobalVariable | t.CPtr = mod.GlobalHead
while gv2 is not None:
if gv2.Initializer is not None:
had_global = 1
break
gv2 = gv2.Next
if had_global != 0:
_append_cstr(buf, size, "\n")
# 遍历函数
func: Function | t.CPtr = mod.FuncHead
func_idx: t.CInt = 0
while func is not None:
if mode == OUTPUT_STUB:
# stub 模式:仅输出 declare(IsDeclared==1)
if func.IsDeclared == 1:
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
elif mode == OUTPUT_TEXT:
# text 模式:仅输出 define(IsDeclared==0)
if func.IsDeclared == 0:
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
else:
# full 模式:输出所有函数
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
func = func.Next
func_idx += 1
return mod.PrintModule(buf, size, pool, mode)
# ============================================================