From bff0f20f5149b1ae9e4eb2cf36e68eee62010099 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 21:15:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(mlir):=20=E6=A8=A1=E5=9D=97/=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=BE=93=E5=87=BA=E7=BC=93=E5=86=B2=E6=88=AA=E6=96=AD?= =?UTF-8?q?=E5=93=8D=E4=BA=AE=E6=8A=A5=E9=94=99=20+=20=E7=BC=A9=E8=BF=9B?= =?UTF-8?q?=E8=BE=85=E5=8A=A9=E7=BC=93=E5=86=B2=2064=20KiB=20=E2=86=92=201?= =?UTF-8?q?=20MiB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- mlirlite/__function.vp | 28 +++++++++++++++++++++++++--- mlirlite/__module.vp | 33 +++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/mlirlite/__function.vp b/mlirlite/__function.vp index bcce479..e1abe9a 100644 --- a/mlirlite/__function.vp +++ b/mlirlite/__function.vp @@ -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 类型限制使用) # diff --git a/mlirlite/__module.vp b/mlirlite/__module.vp index 26e0701..6fa2338 100644 --- a/mlirlite/__module.vp +++ b/mlirlite/__module.vp @@ -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 \ No newline at end of file