feat(mlirlite): 补齐 Debug Info 同形 API,导出名集与 llvmlite 一致(215=215)

- __module.vp: 新增 DINode/DINamedMeta 类、LLVMModule 追加 6 个 DI 字段(96->144B)、module_add_di_node/module_add_named_metadata 及实例方法、DI_NODE_SIZE/DI_NAMED_SIZE

- __function.vp: Function 追加 DbgRef(80->88B) + function_set_dbg

- __builder.vp: IRBuilder 追加 DbgLoc(32->40B) + set/clear_debug_location 方法 + 顶层 builder_set/clear_debug_location

- __init__.vp: 导出上述 7 个 DI 名字,恢复与 llvmlite 的逐名同形(215=215)

- MLIR 打印阶段忽略 DI:LLVMModulePrint 不输出 !N 元数据、_emit 不读 DbgLoc,保持 MLIR 语法合法(DI 只记录不输出)

- README: 记录 DI 为「同形保留/只记录不输出」,名字数更新为 215
This commit is contained in:
TermiNexus committed 2026-10-03 07:43:03 +08:00
1 parent 1e6082afe9
commit 7b006c96a0
5 files changed
+208 -13

No files matched your search

+10 -1
View File
@@ -25,7 +25,7 @@
| 文件 | 内容 | 与 llvmlite 的关系 |
|------|------|--------------------|
| `__init__.vp` | 公共导出 + 便捷工厂(`create_function`/`const_int*`/`create_global_*` 等)+ `LLVMTypeCore`/`LLVMModuleCore` | **导入清单逐名一致(208 个名字),代码逐行一致**,仅注释不同 |
| `__init__.vp` | 公共导出 + 便捷工厂(`create_function`/`const_int*`/`create_global_*` 等)+ `LLVMTypeCore`/`LLVMModuleCore` | **导入清单逐名一致(215 个名字,含 Debug Info 全套),代码逐行一致**,仅注释不同 |
| `__types.vp` | `LLVMType`(REnum) / `ParamNode` / 类型工厂 / `TypePrint` / `DeepCopyType` | 模型与工厂**逐名同形**;`TypePrint` 改为 MLIR 语义(具名结构体内联为 `!llvm.struct<"name", (…)>`),`PrintStructDefinition` 变为空操作,新增打印期命名结构体登记表(§2.10) |
| `__values.vp` | `Value` / `ConstInt`/`ConstNull`/`ConstZero`/`ConstFloat`/`SSAValue` / `ValuePrint` | 模型与工厂同形;仅 `ValuePrint` 改为 MLIR 语义 |
| `__function.vp` | `Line`/`BasicBlock`/`Param`/`Function` + 工厂 + `RenumberSSA` + 窥孔 + `FunctionPrint` | 模型、`RenumberSSA`、本地窥孔**逐行一致**;`FunctionPrint` 重写为 MLIR 渲染 |
@@ -528,6 +528,14 @@ packed"的组合,无需(也无处)为其单独报错。登记表每槽 16
类型定义行。`module_add_named_type` 保留模型语义(去重 / opaque 就地替换)并作为
打印期登记表的来源(`_MlirPublishNamedTypes`,见 §2.10),`PrintStructDefinition`
输出空串(保留 API 同形)。
- **Debug Info**(`module_add_di_node` / `module_add_named_metadata` /
`function_set_dbg` / `builder_set_(clear_)debug_location`、`DINode` /
`DINamedMeta`、`LLVMModule.DIMeta*`/`DINamed*`、`Function.DbgRef`、
`IRBuilder.DbgLoc`):为保持与 llvmlite **逐名同形**(并让 TransPyV 的
`DebugInfoGen` 在 `llvmlite.`→`mlirlite.` 改名后可编译),本库**完整保留这些名字
与模型字段/布局**(`LLVMModule` 144B、`Function` 88B、`IRBuilder` 40B,
与 llvmlite 同布局);但 MLIR 语法没有 `!N = …` 元数据与 `, !dbg !N` 后缀,
故**全部只记录、不输出**(`LLVMModulePrint` 不打印 DI 节点,`_emit` 不读 `DbgLoc`)。
---
@@ -549,6 +557,7 @@ packed"的组合,无需(也无处)为其单独报错。登记表每槽 16
| 12 | `G_PeepEnable` | 语义不变:窥孔作用在**中间文本**(`ret zeroinitializer→0/null`、入口槽 store→load 转发、no-op bitcast 消除),与 MLIR 渲染正交(T3 与 MLIR 的 no-op 折叠叠加,结果一致) |
| 13 | `module_set_named_type_packed` | 语义不变(记录 `NamedTypeNode.IsPacked`);MLIR 侧**已参与渲染**:具名结构体在使用处内联为 `!llvm.struct<"name", packed (…)>`(见 §2.10) |
| 14 | 中间指令文本(`Line.Buf`) | **内容与 llvmlite 不同**:builders 内嵌类型经 `_type_str` → `TypePrint` 已是 MLIR 形态(`load i32, !llvm.ptr %p` 而非 `load i32, i32* %p`)。文本层使用者(窥孔、verify)按名称/结构匹配,语义不受影响 |
| 15 | Debug Info 全套(`module_add_di_node` / `module_add_named_metadata` / `function_set_dbg` / `builder_set_(clear_)debug_location`、`DINode`/`DINamedMeta`、`DIMeta*`/`DINamed*`/`DbgRef`/`DbgLoc`) | **逐名同形、布局同形**(LLVMModule 144B / Function 88B / IRBuilder 40B),但 MLIR 无 `!N = …` 元数据与 `, !dbg !N` 后缀 ⇒ **只记录、不输出**(见 §3.3) |
---
+37 -4
View File
@@ -25,7 +25,7 @@ from .__function import Function, BasicBlock, block_append_text, block_set_termi
# r = builder.build_load(i32_ty, a)
# builder.build_ret(r)
#
# 注意: 加 @t.NoVTable 以与硬编码 BUILDER_SIZE=32 保持一致
# 注意: 加 @t.NoVTable 以与硬编码 BUILDER_SIZE=40 保持一致
# (方法以实例方法实现,无虚表;文件末尾的同名顶层函数为一行委托)。
# ============================================================
novirtual class IRBuilder:
@@ -33,6 +33,7 @@ novirtual class IRBuilder:
Func: rawptr[Function] # 所属函数
CurBlock: rawptr[BasicBlock] # 当前插入点
Counter: int # SSA 名计数器
DbgLoc: str # current DILocation ref(同形保留;MLIR 打印阶段忽略,不发 !dbg 后缀)
# ============================================================
# 内部辅助
@@ -75,11 +76,29 @@ novirtual class IRBuilder:
def _emit(self, text: str):
"""将指令文本追加到当前块"""
"""将指令文本追加到当前块
与 llvmlite 的差异:MLIR 语法没有 `, !dbg !N` 后缀,故本实现**故意不**读取
DbgLoc(set_debug_location 只记录模型,不改变输出)。其余调用方逻辑一致。
"""
if self is None or self.CurBlock is None: return
block_append_text(self.Pool, self.CurBlock, text)
def set_debug_location(self, ref: str):
"""Set the current DILocation ref(同形保留;MLIR 侧仅记录,不影响输出)
ref=None clears it.
"""
if self is None: return
self.DbgLoc = ref
def clear_debug_location(self):
"""Clear the current DILocation ref(同形保留;MLIR 侧仅记录)"""
if self is None: return
self.DbgLoc = None
def _mark_terminated(self):
"""标记当前块已终止"""
if self is None or self.CurBlock is None: return
@@ -1164,8 +1183,8 @@ novirtual class IRBuilder:
# ============================================================
# 工厂函数
# ============================================================
# IRBuilder 硬编码大小: Pool(8) + Func(8) + CurBlock(8) + Counter(4) = 32 字节
BUILDER_SIZE: t.CDefine = 32
# IRBuilder 硬编码大小: Pool(8) + Func(8) + CurBlock(8) + Counter(4) + DbgLoc(8) = 40 字节(与 llvmlite 同布局)
BUILDER_SIZE: t.CDefine = 40
def new_builder(pool: memhub.MemBuddy*, func: rawptr[Function]) -> rawptr[IRBuilder]:
"""创建 IRBuilder,关联到函数 func"""
@@ -1176,6 +1195,7 @@ def new_builder(pool: memhub.MemBuddy*, func: rawptr[Function]) -> rawptr[IRBuil
ptr.Func = func
ptr.CurBlock = None
ptr.Counter = 0
ptr.DbgLoc = None
return ptr
@@ -1228,6 +1248,19 @@ def builder_cur_block_is_terminated(builder: rawptr[IRBuilder]) -> int:
return builder.builder_cur_block_is_terminated()
# ============================================================
# 调试位置(同形保留;MLIR 打印阶段忽略)
# ============================================================
def builder_set_debug_location(builder: rawptr[IRBuilder], ref: str):
"""Set the current DILocation ref(同形保留;MLIR 侧仅记录,不影响输出)"""
builder.set_debug_location(ref)
def builder_clear_debug_location(builder: rawptr[IRBuilder]):
"""Clear the current DILocation ref(同形保留;MLIR 侧仅记录)"""
builder.clear_debug_location()
# ============================================================
# 内存指令
# ============================================================
+14 -3
View File
@@ -87,7 +87,8 @@ novirtual class Function(GSListNode[Function]):
Attrs: str # 函数属性文本(None=无属性)
AttrGroup: str # 字符串属性组内容(如 '"section"=".text.startup"',None=无)
AttrGroupId: int # 属性组编号(>0 时函数行输出 #N,模块尾输出 attributes #N)
NameLen: sizet # 函数名长度(创建时一次算好,恒等于 strlen(Name);追加在末尾,既有字段偏移不变)
NameLen: sizet # 函数名长度(创建时一次算好,恒等于 strlen(Name);追加在末尾,既有字段偏移不变)
DbgRef: str # DISubprogram ref(同形保留;MLIR 打印阶段忽略,如 "!3")
# ============================================================
@@ -148,8 +149,8 @@ def new_param(pool: memhub.MemBuddy*, ty: rawptr[LLVMType],
return ptr
# Function 硬编码大小: Next(8) + Name(8) + RetTy(8) + Params(8) + Blocks(8) + IsDeclared(4) + IsVarArg(4) + Attrs(8) + AttrGroup(8) + AttrGroupId(8) + NameLen(8) = 80 字节
FUNC_SIZE: t.CDefine = 80
# Function 硬编码大小: Next(8) + Name(8) + RetTy(8) + Params(8) + Blocks(8) + IsDeclared(4) + IsVarArg(4) + Attrs(8) + AttrGroup(8) + AttrGroupId(8) + NameLen(8) + DbgRef(8) = 88 字节(与 llvmlite 同布局)
FUNC_SIZE: t.CDefine = 88
def new_function(pool: memhub.MemBuddy*, name: str,
ret_ty: rawptr[LLVMType]) -> rawptr[Function]:
@@ -343,6 +344,16 @@ def param_set_attrs(param: rawptr[Param], attrs: str):
param.Attrs = attrs
def function_set_dbg(func: rawptr[Function], ref: str):
"""Set the function-level debug ref (DISubprogram node ref, e.g. "!3").
同形保留:MLIR 打印阶段忽略该引用(FunctionPrint 不输出 !dbg),
故本调用只记录模型、不改变输出。ref=None 清除。
"""
if func is None: return
func.DbgRef = ref
# ============================================================
# _ll_name_needs_quote - 检查符号名在 MLIR 中是否需要 @"…" 引号形式
#
+5 -1
View File
@@ -38,16 +38,19 @@ from .__function import (
block_append_line, block_append_text,
function_set_attrs, param_set_attrs,
function_set_attr_group,
function_set_dbg,
function_get_name, function_get_name_len, function_get_ret_ty, function_get_params,
function_get_param_head, function_get_next, function_is_declared,
param_get_name, param_get_ty, param_get_next,
FunctionPrint, G_PeepEnable,
)
from .__module import (
LLVMModule, GlobalVariable, NamedTypeNode, new_module, new_global_variable,
LLVMModule, GlobalVariable, NamedTypeNode, DINode, DINamedMeta,
new_module, new_global_variable,
module_add_function, module_add_global, module_add_named_type,
module_set_named_type_packed,
module_set_target, module_set_datalayout,
module_add_di_node, module_add_named_metadata,
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT,
module_ensure_opaque_for_type,
@@ -55,6 +58,7 @@ from .__module import (
from .__builder import (
IRBuilder, new_builder, position_at_end,
builder_cur_block_is_terminated,
builder_set_debug_location, builder_clear_debug_location,
build_alloca, build_alloca_aligned, build_alloca_at_entry, build_load, build_store,
build_add, build_sub, build_mul, build_sdiv, build_udiv, build_srem, build_urem,
build_and, build_or, build_xor, build_shl, build_lshr, build_ashr,
+142 -4
View File
@@ -48,6 +48,27 @@ class NamedTypeNode(GSListNode[NamedTypeNode]):
IsPacked: int # 1=packed 结构体(MLIR: !llvm.struct<"name", packed (…)>,无字段填充)
# ============================================================
# DINode: DI metadata node(同形保留;MLIR 打印阶段忽略)
#
# 与 includes/llvmlite 逐名同形:Debug Info 在 MLIR 后端无对应概念,故本库
# 仅记录模型(供 TransPyV 的 DebugInfoGen 在 llvmlite.→mlirlite. 改名后仍可
# 编译),LLVMModulePrint **不输出**这些节点(输出会破坏 MLIR 语法)。
# ============================================================
@t.NoVTable
class DINode(GSListNode[DINode]):
Text: str # node body, e.g. "!DIFile(filename: \"a.vp\", directory: \"/x\")"
# ============================================================
# DINamedMeta: named metadata(同形保留;MLIR 打印阶段忽略)
# ============================================================
@t.NoVTable
class DINamedMeta(GSListNode[DINamedMeta]):
Name: str # e.g. "llvm.dbg.cu" / "llvm.module.flags"
Refs: str # reference list text, e.g. "!1"
# ============================================================
# LLVMModule: LLVM IR 模块容器
#
@@ -70,7 +91,13 @@ class LLVMModule:
NamedTypeHead: rawptr[NamedTypeNode] # 命名结构体类型链表头
NamedTypeTail: rawptr[NamedTypeNode] # 命名结构体类型链表尾
NamedTypeCount: sizet # 命名结构体类型计数
# 总计: 12 字段 * 8 = 96 字节(无 vtable)
DIMetaHead: rawptr[DINode] # DI metadata node list head(同形保留;MLIR 不打印)
DIMetaTail: rawptr[DINode] # DI metadata node list tail
DIMetaCount: sizet # DI node count (= next !N id)
DINamedHead: rawptr[DINamedMeta] # named metadata list head
DINamedTail: rawptr[DINamedMeta] # named metadata list tail
DINamedCount: sizet # named metadata count
# 总计: 18 字段 * 8 = 144 字节(无 vtable;与 includes/llvmlite 同布局)
# ============================================================
# 实例方法(对象化重构:原 module_* 顶层函数改写为方法,
@@ -111,6 +138,89 @@ class LLVMModule:
if self is None: return
self.DataLayout = layout
# ---- DI debug metadata(同形保留;MLIR 打印阶段忽略,仅记录模型)----
def add_di_node(self, pool: memhub.MemBuddy*, text: str) -> int:
"""Append a DI metadata node; return its !N id (0-based, unique), -1 on failure.
text is the node body incl. !M references built from earlier ids.
MLIR 后端无 DI 概念:节点仅登记在模型里(LLVMModulePrint 不输出),
从而 TransPyV 的 DebugInfoGen 在改名后仍可编译、且不影响 MLIR 输出。
"""
if self is None or pool is None or text is None:
return -1
node: rawptr[DINode] = pool.alloc(DI_NODE_SIZE)
if node is None:
return -1
string.memset(node, 0, DI_NODE_SIZE)
# copy body (caller buffer may be reused)
tlen: sizet = string.strlen(text)
tcopy: str = pool.alloc(tlen + 1)
if tcopy is None:
return -1
string.strcpy(tcopy, text)
node.Text = tcopy
if self.DIMetaHead is None:
self.DIMetaHead = node
else:
self.DIMetaTail.Next = node
self.DIMetaTail = node
node_id: int = int(self.DIMetaCount)
self.DIMetaCount += 1
return node_id
def add_named_metadata(self, pool: memhub.MemBuddy*, name: str, refs: str):
"""Register named metadata "!<name> = !{ <refs> }"; merge into an existing
entry with the same name (refs is the brace body, e.g. "!3").
MLIR 侧仅记录模型,不产生输出(LLVMModulePrint 不输出 DI)。
"""
if self is None or pool is None or name is None:
return
cur: rawptr[DINamedMeta] = self.DINamedHead
cur_steps: sizet = 0
while cur is not None:
cur_steps += 1
if cur_steps > IR_DUMP_CHAIN_LIMIT:
stdio.printf("[IR-DUMP] 链表成环: module di named(DINamedCount=%zu,dump 终止)\n",
self.DINamedCount)
stdlib.exit(1)
if cur.Name is not None and string.strcmp(cur.Name, name) == 0:
if refs is not None:
old_len: sizet = 0
if cur.Refs is not None:
old_len = string.strlen(cur.Refs)
merged: str = pool.alloc(old_len + string.strlen(refs) + 3)
if merged is not None:
merged[0] = '\0'
if cur.Refs is not None:
string.strcat(merged, cur.Refs)
string.strcat(merged, ", ")
string.strcat(merged, refs)
cur.Refs = merged
return
cur = cur.Next
entry: rawptr[DINamedMeta] = pool.alloc(DI_NAMED_SIZE)
if entry is None:
return
string.memset(entry, 0, DI_NAMED_SIZE)
ncopy: str = pool.alloc(string.strlen(name) + 1)
if ncopy is None:
return
string.strcpy(ncopy, name)
entry.Name = ncopy
if refs is not None:
rcopy: str = pool.alloc(string.strlen(refs) + 1)
if rcopy is None:
return
string.strcpy(rcopy, refs)
entry.Refs = rcopy
if self.DINamedHead is None:
self.DINamedHead = entry
else:
self.DINamedTail.Next = entry
self.DINamedTail = entry
self.DINamedCount += 1
# ---- 命名结构体类型管理 ----
def add_named_type(self, pool: memhub.MemBuddy*, ty: rawptr[LLVMType]):
"""登记命名结构体类型到模块(MLIR 侧仅保留模型,不产生输出)
@@ -349,10 +459,11 @@ def _MlirPublishNamedTypes(mod: rawptr[LLVMModule], pool: memhub.MemBuddy*):
# ============================================================
def new_module(pool: memhub.MemBuddy*, name: str) -> rawptr[LLVMModule]:
"""创建一个模块"""
# 硬编码 96 字节:12 字段 * 8 字节(无 vtable,@t.NoVTable)
ptr: rawptr[LLVMModule] = pool.alloc(96)
# 硬编码 144 字节:18 字段 * 8 字节(无 vtable,@t.NoVTable)
# 含 DI 字段(DIMetaHead/Tail/Count、DINamedHead/Tail/Count),与 llvmlite 同布局。
ptr: rawptr[LLVMModule] = pool.alloc(144)
if ptr is None: return None
string.memset(ptr, 0, 96)
string.memset(ptr, 0, 144)
ptr.Name = name
ptr.FuncHead = None
ptr.FuncTail = None
@@ -365,6 +476,12 @@ def new_module(pool: memhub.MemBuddy*, name: str) -> rawptr[LLVMModule]:
ptr.NamedTypeHead = None
ptr.NamedTypeTail = None
ptr.NamedTypeCount = 0
ptr.DIMetaHead = None
ptr.DIMetaTail = None
ptr.DIMetaCount = 0
ptr.DINamedHead = None
ptr.DINamedTail = None
ptr.DINamedCount = 0
return ptr
@@ -374,6 +491,12 @@ GV_SIZE: t.CDefine = 72
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) + IsPacked(8) = 24 字节
NAMED_TYPE_NODE_SIZE: t.CDefine = 24
# DINode 硬编码大小: Next(8) + Text(8) = 16 字节(同 llvmlite)
DI_NODE_SIZE: t.CDefine = 16
# DINamedMeta 硬编码大小: Next(8) + Name(8) + Refs(8) = 24 字节(同 llvmlite)
DI_NAMED_SIZE: t.CDefine = 24
def new_global_variable(pool: memhub.MemBuddy*,
name: str, ty: rawptr[LLVMType]) -> rawptr[GlobalVariable]:
"""创建一个全局变量"""
@@ -417,6 +540,21 @@ def module_set_datalayout(mod: rawptr[LLVMModule], layout: str):
mod.set_datalayout(layout)
# ============================================================
# DI debug metadata(同形保留;MLIR 打印阶段忽略,仅记录模型)
# ============================================================
def module_add_di_node(mod: rawptr[LLVMModule], pool: memhub.MemBuddy*,
text: str) -> int:
"""Append a DI metadata node; return its !N id (-1 on failure)"""
return mod.add_di_node(pool, text)
def module_add_named_metadata(mod: rawptr[LLVMModule], pool: memhub.MemBuddy*,
name: str, refs: str):
"""Register named metadata "!<name> = !{ <refs> }" """
mod.add_named_metadata(pool, name, refs)
# ============================================================
# 命名结构体类型管理
# ============================================================