fix(mlir): 模块/函数输出缓冲截断响亮报错 + 缩进辅助缓冲 64 KiB → 1 MiB

dump_ir 的输出缓冲(8/16 MB)此前用 _append_cstr **静默**丢内容 —— MLIR 文本因
内联具名结构体完整字段体而明显长于 LLVM IR,一旦超出就得到被截断的半截模块,
mlir-opt 只会报难以定位的语法错。

- __module.vp:_append_cstr 写入被截断时置 _MlirModOutTrunc;LLVMModulePrint
  结束前检查并 MlirFail;模块缩进辅助缓冲 64 KiB → 1 MiB(tmp_cap),并把该
  缓冲分配失败也改为响亮报错(否则会静默漏印全部模块成员)
- __function.vp:_append_cstr 写入被截断时置 _MlirOutTrunc;FunctionPrint
  三个出口(declare / 无基本块 / 正常结束)均检查并 MlirFail
This commit is contained in:
TermiNexus committed 2026-10-03 21:15:34 +08:00
1 parent a502c7242f
commit bff0f20f51
2 files changed
+50 -11

No files matched your search

+25 -3
View File
@@ -20,7 +20,12 @@ IR_DUMP_CHAIN_LIMIT: t.CDefine = 100000
# 窥孔优化总开关(T2 转发/ret 归零、T3 no-op bitcast 消除)。
# TPV 命令行 --no-llvmpeephole 会将其置 0:FunctionPrint 序列化时跳过全部本地窥孔,
# 便于与关闭窥孔的 IR 对比调试(RenumberSSA 仍保留,保证输出 SSA 编号合法)。
G_PeepEnable: bool = True
G_PeepEnable: bool = True
# 函数文本输出截断标志:_append_cstr 写入被输出缓冲上限截断时置 1,
# FunctionPrint 结束前检查并 MlirFail —— 截断的 MLIR 会让 mlir-opt 报难以定位的
# 语法错(且此前是**静默**丢内容),必须响亮失败。
_MlirOutTrunc: int = 0
# ============================================================
@@ -3197,9 +3202,10 @@ def FunctionPrint(buf: str, size: sizet,
注意:与 llvmlite 版一致,本函数为追加写(供模块打印连续拼接多个函数),
调用方若要单函数文本需自行先置 buf[0]='\\0'。
"""
global _MLIR_Pass, _MLIR_Func, _MLIR_SrcBlk, _MLIR_CurLine
global _MLIR_Pass, _MLIR_Func, _MLIR_SrcBlk, _MLIR_CurLine, _MlirOutTrunc
if func is None or buf is None or size == 0:
return
_MlirOutTrunc = 0
# 先本地窥孔(ret zeroinitializer→0/null、入口槽 store→load 转发、
# no-op bitcast 消除):窥孔按"名称一致性"匹配、删除行置 Buf=None。
@@ -3220,12 +3226,14 @@ def FunctionPrint(buf: str, size: sizet,
# declare(无函数体)
_MlirFuncSig(buf, size, func, pool)
_append_cstr(buf, size, "\n")
_MlirOutTruncFail()
return
blocks: rawptr[GSList[BasicBlock]] = func.Blocks
if blocks is None:
_MlirFuncSig(buf, size, func, pool)
_append_cstr(buf, size, "\n")
_MlirOutTruncFail()
return
# ---- pass1:扫描(登记常量/别名 + 形态校验)----
@@ -3273,6 +3281,7 @@ def FunctionPrint(buf: str, size: sizet,
blk = blk.Next
first = 0
_append_cstr(buf, size, "}\n")
_MlirOutTruncFail()
# ============================================================
@@ -3308,18 +3317,31 @@ def _append_cstr(dst: str, dst_size: sizet, src: str):
# 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回,
# 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到缓冲外
if dlen >= dst_size:
_MlirOutTrunc = 1
return
slen: sizet = string.strlen(src)
remain: sizet = dst_size - dlen
if remain <= 0: return
if remain <= 0:
_MlirOutTrunc = 1
return
i: sizet = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
if i < slen:
_MlirOutTrunc = 1
dst[dlen + i] = '\0'
_g_last_pos = dlen + i
def _MlirOutTruncFail():
"""打印结束前的输出截断检查(截断即响亮报错,绝不静默输出半截 MLIR)"""
global _MlirOutTrunc
if _MlirOutTrunc != 0:
_MlirOutTrunc = 0
MlirFail("MLIR 渲染: 输出文本超出缓冲被截断(需增大 dump_ir/FunctionPrint 的缓冲)")
# ============================================================
# 字段访问器(供其他模块绕过 stub 类型限制使用)
#
+25 -8
View File
@@ -353,8 +353,15 @@ class LLVMModule:
_append_cstr(buf, size,
" // target triple / datalayout 由 mlir-translate / llc 阶段提供\n")
# 行缩进辅助缓冲(模块成员统一缩进 2 空格)
tmp: str = pool.alloc(65536)
# 行缩进辅助缓冲(模块成员统一缩进 2 空格)。
# 单函数/单全局的 MLIR 文本因内联具名结构体完整字段体而显著变长
# (旧 64 KiB 会截断;截断现由 FunctionPrint/LLVMModulePrint 的截断检查
# 响亮报错),这里给足 1 MiB,并把分配失败也变成响亮失败(否则会静默
# 漏印全部模块成员)。
tmp_cap: sizet = 1048576
tmp: str = pool.alloc(tmp_cap)
if tmp is None:
MlirFail("MLIR 渲染: 模块缩进辅助缓冲分配失败(1 MiB)")
# 全局变量(MLIR 无独立类型定义行:命名结构体类型在使用处内联,
# 故这里不再输出 NamedTypeHead 类型定义,仅登记供类型文本回查)
@@ -373,9 +380,9 @@ class LLVMModule:
if tmp is not None:
tmp[0] = '\0'
if mode == OUTPUT_STUB:
_MlirGlobalLine(tmp, 65536, pool, gv, 1)
_MlirGlobalLine(tmp, tmp_cap, pool, gv, 1)
else:
_MlirGlobalLine(tmp, 65536, pool, gv, 0)
_MlirGlobalLine(tmp, tmp_cap, pool, gv, 0)
_MlirAppendIndented(buf, size, tmp, 2, pool)
gv = gv.Next
@@ -399,7 +406,7 @@ class LLVMModule:
emit = 1
if emit != 0 and tmp is not None:
tmp[0] = '\0'
FunctionPrint(tmp, 65536, func, pool)
FunctionPrint(tmp, tmp_cap, func, pool)
_MlirAppendIndented(buf, size, tmp, 2, pool)
func = func.Next
@@ -760,7 +767,12 @@ IR_DUMP_CHAIN_LIMIT: t.CDefine = 100000
def LLVMModulePrint(buf: str, size: sizet,
mod: rawptr[LLVMModule], pool: memhub.MemBuddy*,
mode: int):
global _MlirModOutTrunc
_MlirModOutTrunc = 0
mod.PrintModule(buf, size, pool, mode)
if _MlirModOutTrunc != 0:
_MlirModOutTrunc = 0
MlirFail("MLIR 渲染: 模块文本超出输出缓冲被截断(需增大 dump_ir 缓冲)")
# ============================================================
@@ -1611,8 +1623,8 @@ _g_last_dst: t.CUInt64T = 0
_g_last_pos: sizet = 0
def _append_cstr(dst: str, dst_size: sizet, src: str):
"""将 C 字符串 src 追加到 dst 末尾"""
global _g_last_dst, _g_last_pos
"""将 C 字符串 src 追加到 dst 末尾;被输出缓冲上限截断时置截断标志"""
global _g_last_dst, _g_last_pos, _MlirModOutTrunc
if dst is None or src is None: return
dlen: sizet = 0
if _g_last_dst == t.CUInt64T(dst):
@@ -1636,13 +1648,18 @@ def _append_cstr(dst: str, dst_size: sizet, src: str):
# 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回,
# 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到缓冲外
if dlen >= dst_size:
_MlirModOutTrunc = 1
return
slen: sizet = string.strlen(src)
remain: sizet = dst_size - dlen
if remain <= 0: return
if remain <= 0:
_MlirModOutTrunc = 1
return
i: sizet = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
if i < slen:
_MlirModOutTrunc = 1
dst[dlen + i] = '\0'
_g_last_pos = dlen + i