fix(mlir): 类型文本缓冲按长度给足 + 截断响亮报错(系统性)
根因:MLIR 把具名结构体内联为完整字段体(`!llvm.struct<"名", (i32, !llvm.ptr, …)>`),
单个类型文本可达数百字节,远长于 LLVM 形态的 `%"名"` 引用(十几字节);而 builders
仍按旧的短类型尺寸分配(128/256),指令行里的类型被截断 → 畸形 MLIR。
实测:alloca 行类型被 128 字节缓冲截断,mlir-opt 报
"unbalanced '(' character in pretty dialect name"。
- __types.vp:新增截断溢出标志 _MlirTypeTrunc(_strappend/_MlirAppendN 写入
被截断时置位),TypePrint / MlirTypeText 渲染后检查并 MlirFail —— 任何截断
都不再静默产出畸形 MLIR
- __builder.vp:新增 _TY_TEXT_CAP(512)/_LINE_CAP(2560),全部指令行缓冲(alloca
/ret/load/store/各类 cast/gep/icmp/fcmp/select/atomicrmw/cmpxchg/va_arg/switch
/case/inline_asm…)改为 _LINE_CAP;build_call / build_call_indirect 的实参表
与行缓冲按实参个数与实际长度动态分配(原固定 1024/2048 会在两个以上结构体
实参时静默截断)
- __values.vp:ValuePrint 的类型缓冲 256 → 512
This commit is contained in:
1 parent
33d5737f0c
commit
a502c7242f
3 files changed
+163
-110
No files matched your search
+124
-103
@@ -28,6 +28,19 @@ from .__function import Function, BasicBlock, block_append_text, block_set_termi
|
||||
# 注意: 加 @t.NoVTable 以与硬编码 BUILDER_SIZE=40 保持一致
|
||||
# (方法以实例方法实现,无虚表;文件末尾的同名顶层函数为一行委托)。
|
||||
# ============================================================
|
||||
# 指令文本缓冲尺寸
|
||||
#
|
||||
# MLIR 形态的类型文本会**内联具名结构体的完整字段体**
|
||||
# (如 `!llvm.struct<"sha1.Cls", (i32, !llvm.ptr, …)>`),单个类型可达数百字节,
|
||||
# 远长于 LLVM 形态的 `%"sha1.Cls"` 引用(十几字节)。故指令行缓冲必须按
|
||||
# "一行最多内嵌几个类型文本"给足:_LINE_CAP 覆盖 5 个类型文本 + 固定部分。
|
||||
# 渲染侧 TypePrint/MlirTypeText 已加溢出护栏:一旦截断即响亮报错,不再静默
|
||||
# 产出畸形 MLIR(历史故障:alloca 行类型被 128 字节缓冲截断 → mlir-opt 报
|
||||
# "unbalanced '(' character in pretty dialect name")。
|
||||
# ============================================================
|
||||
_TY_TEXT_CAP: sizet = 512
|
||||
_LINE_CAP: sizet = 2560
|
||||
|
||||
novirtual class IRBuilder:
|
||||
Pool: memhub.MemBuddy* # 内存池
|
||||
Func: rawptr[Function] # 所属函数
|
||||
@@ -49,16 +62,16 @@ novirtual class IRBuilder:
|
||||
|
||||
|
||||
def _type_str(self, ty: rawptr[LLVMType]) -> str:
|
||||
"""获取类型的 MLIR 文本(从 pool 分配 512 字节缓冲区)
|
||||
"""获取类型的 MLIR 文本(从 pool 分配 _TY_TEXT_CAP 字节缓冲区)
|
||||
|
||||
注意:复杂结构体类型(如 13 方法的虚表 !llvm.struct<(...)>)可能超过
|
||||
64 字节,必须使用足够大的缓冲区,否则 '>' 会被截断导致语法错误。
|
||||
MLIR 类型文本内联具名结构体的完整字段体,可达数百字节;超出
|
||||
_TY_TEXT_CAP 时 TypePrint 会**响亮报错**(不再静默截断)。
|
||||
"""
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
buf: str = pool.alloc(512)
|
||||
buf: str = pool.alloc(_TY_TEXT_CAP)
|
||||
if buf is None: return None
|
||||
buf[0] = '\0'
|
||||
TypePrint(buf, 512, ty, pool)
|
||||
TypePrint(buf, _TY_TEXT_CAP, ty, pool)
|
||||
# [IR-FAIL] 校验护栏:LLVMType 类型对象可能被 MemBuddy 覆盖/悬空
|
||||
# (跨遍 reset 回收后 pool 内存复用),此时 TypePrint 输出首字符
|
||||
# 变为垃圾(如 't')或为空。立即 fail-fast 终止,防止生成
|
||||
@@ -112,9 +125,9 @@ novirtual class IRBuilder:
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(lhs.Ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = %s %s %s, %s", name, op, ty_s, lhs.Name, rhs.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = %s %s %s, %s", name, op, ty_s, lhs.Name, rhs.Name)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, lhs.Ty, name)
|
||||
|
||||
@@ -160,9 +173,9 @@ novirtual class IRBuilder:
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(ty)
|
||||
line: str = pool.alloc(128)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 128, "%s = alloca %s", name, ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = alloca %s", name, ty_s)
|
||||
self._emit(line)
|
||||
|
||||
# 结果类型是 ty*
|
||||
@@ -185,9 +198,9 @@ novirtual class IRBuilder:
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(ty)
|
||||
line: str = pool.alloc(128)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 128, "%s = alloca %s, align %d", name, ty_s, align)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = alloca %s, align %d", name, ty_s, align)
|
||||
self._emit(line)
|
||||
|
||||
# 结果类型是 ty*
|
||||
@@ -216,9 +229,9 @@ novirtual class IRBuilder:
|
||||
return self.build_alloca(ty)
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(ty)
|
||||
line_text: str = pool.alloc(128)
|
||||
line_text: str = pool.alloc(_LINE_CAP)
|
||||
if line_text is None: return None
|
||||
viperlib.snprintf(line_text, 128, "%s = alloca %s", name, ty_s)
|
||||
viperlib.snprintf(line_text, _LINE_CAP, "%s = alloca %s", name, ty_s)
|
||||
# 在入口块终止指令之前插入:若入口块已以 br/ret 终止(如嵌套循环内
|
||||
# 再分配循环变量),block_append_text 会把 alloca 追加到终止指令之后,
|
||||
# 生成 "br 之后不可达指令" 的非法 IR(llc: "instruction expected to be
|
||||
@@ -248,12 +261,12 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(ty)
|
||||
ptr_ty_s: str = self._type_str(ptr.Ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
if is_volatile != 0:
|
||||
viperlib.snprintf(line, 256, "%s = load volatile %s, %s %s", name, ty_s, ptr_ty_s, ptr.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = load volatile %s, %s %s", name, ty_s, ptr_ty_s, ptr.Name)
|
||||
else:
|
||||
viperlib.snprintf(line, 256, "%s = load %s, %s %s", name, ty_s, ptr_ty_s, ptr.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = load %s, %s %s", name, ty_s, ptr_ty_s, ptr.Name)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, ty, name)
|
||||
|
||||
@@ -269,12 +282,12 @@ novirtual class IRBuilder:
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
val_ty_s: str = self._type_str(val.Ty)
|
||||
ptr_ty_s: str = self._type_str(ptr.Ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return
|
||||
if is_volatile != 0:
|
||||
viperlib.snprintf(line, 256, "store volatile %s %s, %s %s", val_ty_s, val.Name, ptr_ty_s, ptr.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "store volatile %s %s, %s %s", val_ty_s, val.Name, ptr_ty_s, ptr.Name)
|
||||
else:
|
||||
viperlib.snprintf(line, 256, "store %s %s, %s %s", val_ty_s, val.Name, ptr_ty_s, ptr.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "store %s %s, %s %s", val_ty_s, val.Name, ptr_ty_s, ptr.Name)
|
||||
self._emit(line)
|
||||
|
||||
|
||||
@@ -398,9 +411,9 @@ novirtual class IRBuilder:
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(val.Ty)
|
||||
line: str = pool.alloc(128)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 128, "%s = fneg %s %s", name, ty_s, val.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = fneg %s %s", name, ty_s, val.Name)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, val.Ty, name)
|
||||
|
||||
@@ -419,9 +432,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(lhs.Ty)
|
||||
pred_s: str = _icmp_pred_str(pred)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = icmp %s %s %s, %s", name, pred_s, ty_s, lhs.Name, rhs.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = icmp %s %s %s, %s", name, pred_s, ty_s, lhs.Name, rhs.Name)
|
||||
self._emit(line)
|
||||
|
||||
# 结果类型是 i1
|
||||
@@ -443,9 +456,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(lhs.Ty)
|
||||
pred_s: str = _fcmp_pred_str(pred)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = fcmp %s %s %s, %s", name, pred_s, ty_s, lhs.Name, rhs.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = fcmp %s %s %s, %s", name, pred_s, ty_s, lhs.Name, rhs.Name)
|
||||
self._emit(line)
|
||||
|
||||
# 结果类型是 i1
|
||||
@@ -475,9 +488,9 @@ novirtual class IRBuilder:
|
||||
"""br i1 <cond>, label %<then>, label %<else_>"""
|
||||
if self is None or cond is None or then_blk is None or else_blk is None: return
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
line: str = pool.alloc(128)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return
|
||||
viperlib.snprintf(line, 128, "br i1 %s, label %%%s, label %%%s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "br i1 %s, label %%%s, label %%%s",
|
||||
cond.Name, then_blk.Name, else_blk.Name)
|
||||
self._emit(line)
|
||||
self._mark_terminated()
|
||||
@@ -488,9 +501,9 @@ novirtual class IRBuilder:
|
||||
if self is None or val is None: return
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
ty_s: str = self._type_str(val.Ty)
|
||||
line: str = pool.alloc(128)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return
|
||||
viperlib.snprintf(line, 128, "ret %s %s", ty_s, val.Name)
|
||||
viperlib.snprintf(line, _LINE_CAP, "ret %s %s", ty_s, val.Name)
|
||||
self._emit(line)
|
||||
self._mark_terminated()
|
||||
|
||||
@@ -537,33 +550,36 @@ novirtual class IRBuilder:
|
||||
ret_ty_s: str = self._type_str(ret_ty)
|
||||
|
||||
# 构建参数列表文本 + 变参函数类型签名
|
||||
args_buf: str = pool.alloc(1024)
|
||||
# 实参类型文本内联具名结构体体(单个可达 _TY_TEXT_CAP 字节),故按
|
||||
# 实参个数给足容量;固定 1024 字节会在两个以上结构体实参时静默截断。
|
||||
arg_cap: sizet = sizet(arg_count + 1) * (_TY_TEXT_CAP + 32) + 32
|
||||
args_buf: str = pool.alloc(arg_cap)
|
||||
if args_buf is None: return None
|
||||
args_buf[0] = '\0'
|
||||
func_ty_buf: str = pool.alloc(1024)
|
||||
func_ty_buf: str = pool.alloc(arg_cap)
|
||||
if func_ty_buf is None: return None
|
||||
func_ty_buf[0] = '\0'
|
||||
cur: rawptr[Value] = args
|
||||
first: int = 1
|
||||
while cur is not None:
|
||||
if first == 0:
|
||||
_append_cstr(args_buf, 1024, ", ")
|
||||
_append_cstr(func_ty_buf, 1024, ", ")
|
||||
_append_cstr(args_buf, arg_cap, ", ")
|
||||
_append_cstr(func_ty_buf, arg_cap, ", ")
|
||||
arg_ty_s: str = self._type_str(cur.Ty)
|
||||
_append_cstr(args_buf, 1024, arg_ty_s)
|
||||
_append_cstr(args_buf, 1024, " ")
|
||||
_append_cstr(args_buf, arg_cap, arg_ty_s)
|
||||
_append_cstr(args_buf, arg_cap, " ")
|
||||
if cur.Name is not None:
|
||||
_append_cstr(args_buf, 1024, cur.Name)
|
||||
_append_cstr(func_ty_buf, 1024, arg_ty_s)
|
||||
_append_cstr(args_buf, arg_cap, cur.Name)
|
||||
_append_cstr(func_ty_buf, arg_cap, arg_ty_s)
|
||||
cur = cur.Next
|
||||
first = 0
|
||||
if is_variadic == 1:
|
||||
if first == 0:
|
||||
_append_cstr(func_ty_buf, 1024, ", ")
|
||||
_append_cstr(func_ty_buf, 1024, "...")
|
||||
_append_cstr(func_ty_buf, arg_cap, ", ")
|
||||
_append_cstr(func_ty_buf, arg_cap, "...")
|
||||
|
||||
# 构造带引号的 callee 名字(SHA1 前缀名含 '.' 或以数字开头需要加引号)
|
||||
callee_buf: str = pool.alloc(128)
|
||||
callee_buf: str = pool.alloc(_LINE_CAP)
|
||||
if callee_buf is None: return None
|
||||
callee_buf[0] = '\0'
|
||||
if _ll_name_needs_quote(callee) != 0:
|
||||
@@ -573,18 +589,20 @@ novirtual class IRBuilder:
|
||||
else:
|
||||
_append_cstr(callee_buf, 128, callee)
|
||||
|
||||
line: str = pool.alloc(2048)
|
||||
line_cap: sizet = string.strlen(ret_ty_s) + string.strlen(args_buf) \
|
||||
+ string.strlen(func_ty_buf) + string.strlen(callee_buf) + 64
|
||||
line: str = pool.alloc(line_cap)
|
||||
if line is None: return None
|
||||
if is_variadic == 1:
|
||||
if is_void == 1:
|
||||
viperlib.snprintf(line, 2048, "call %s (%s) @%s(%s)", ret_ty_s, func_ty_buf, callee_buf, args_buf)
|
||||
viperlib.snprintf(line, line_cap, "call %s (%s) @%s(%s)", ret_ty_s, func_ty_buf, callee_buf, args_buf)
|
||||
else:
|
||||
viperlib.snprintf(line, 2048, "%s = call %s (%s) @%s(%s)", name, ret_ty_s, func_ty_buf, callee_buf, args_buf)
|
||||
viperlib.snprintf(line, line_cap, "%s = call %s (%s) @%s(%s)", name, ret_ty_s, func_ty_buf, callee_buf, args_buf)
|
||||
else:
|
||||
if is_void == 1:
|
||||
viperlib.snprintf(line, 2048, "call %s @%s(%s)", ret_ty_s, callee_buf, args_buf)
|
||||
viperlib.snprintf(line, line_cap, "call %s @%s(%s)", ret_ty_s, callee_buf, args_buf)
|
||||
else:
|
||||
viperlib.snprintf(line, 2048, "%s = call %s @%s(%s)", name, ret_ty_s, callee_buf, args_buf)
|
||||
viperlib.snprintf(line, line_cap, "%s = call %s @%s(%s)", name, ret_ty_s, callee_buf, args_buf)
|
||||
self._emit(line)
|
||||
|
||||
if is_void == 1:
|
||||
@@ -620,29 +638,32 @@ novirtual class IRBuilder:
|
||||
|
||||
ret_ty_s: str = self._type_str(ret_ty)
|
||||
|
||||
# 构建参数列表文本
|
||||
args_buf: str = pool.alloc(1024)
|
||||
# 构建参数列表文本(容量按实参个数给足,理由同 build_call)
|
||||
arg_cap2: sizet = sizet(arg_count + 1) * (_TY_TEXT_CAP + 32) + 32
|
||||
args_buf: str = pool.alloc(arg_cap2)
|
||||
if args_buf is None: return None
|
||||
args_buf[0] = '\0'
|
||||
cur: rawptr[Value] = args
|
||||
first: int = 1
|
||||
while cur is not None:
|
||||
if first == 0:
|
||||
_append_cstr(args_buf, 1024, ", ")
|
||||
_append_cstr(args_buf, arg_cap2, ", ")
|
||||
arg_ty_s: str = self._type_str(cur.Ty)
|
||||
_append_cstr(args_buf, 1024, arg_ty_s)
|
||||
_append_cstr(args_buf, 1024, " ")
|
||||
_append_cstr(args_buf, arg_cap2, arg_ty_s)
|
||||
_append_cstr(args_buf, arg_cap2, " ")
|
||||
if cur.Name is not None:
|
||||
_append_cstr(args_buf, 1024, cur.Name)
|
||||
_append_cstr(args_buf, arg_cap2, cur.Name)
|
||||
cur = cur.Next
|
||||
first = 0
|
||||
|
||||
line: str = pool.alloc(2048)
|
||||
line_cap2: sizet = string.strlen(ret_ty_s) + string.strlen(args_buf) \
|
||||
+ string.strlen(callee_val.Name) + 64
|
||||
line: str = pool.alloc(line_cap2)
|
||||
if line is None: return None
|
||||
if is_void == 1:
|
||||
viperlib.snprintf(line, 2048, "call %s %s(%s)", ret_ty_s, callee_val.Name, args_buf)
|
||||
viperlib.snprintf(line, line_cap2, "call %s %s(%s)", ret_ty_s, callee_val.Name, args_buf)
|
||||
else:
|
||||
viperlib.snprintf(line, 2048, "%s = call %s %s(%s)", name, ret_ty_s, callee_val.Name, args_buf)
|
||||
viperlib.snprintf(line, line_cap2, "%s = call %s %s(%s)", name, ret_ty_s, callee_val.Name, args_buf)
|
||||
self._emit(line)
|
||||
|
||||
if is_void == 1:
|
||||
@@ -662,11 +683,11 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
if val.Name is None:
|
||||
return None
|
||||
viperlib.snprintf(line, 256, "%s = bitcast %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = bitcast %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
ret: rawptr[Value] = SSAValue(pool, to_ty, name)
|
||||
return ret
|
||||
@@ -680,9 +701,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = sext %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = sext %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -695,9 +716,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = trunc %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = trunc %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -710,9 +731,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = zext %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = zext %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -725,9 +746,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = ptrtoint %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = ptrtoint %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -740,9 +761,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = inttoptr %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = inttoptr %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -758,9 +779,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = fpext %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = fpext %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -773,9 +794,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = fptrunc %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = fptrunc %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -788,9 +809,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = fptosi %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = fptosi %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -803,9 +824,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = sitofp %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = sitofp %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -818,9 +839,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = fptoui %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = fptoui %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -833,9 +854,9 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
from_ty_s: str = self._type_str(val.Ty)
|
||||
to_ty_s: str = self._type_str(to_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = uitofp %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = uitofp %s %s to %s", name, from_ty_s, val.Name, to_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, to_ty, name)
|
||||
|
||||
@@ -891,9 +912,9 @@ novirtual class IRBuilder:
|
||||
elem_ty_s: str = self._type_str(elem_ty)
|
||||
ptr_ty_s: str = self._type_str(ptr.Ty)
|
||||
idx_ty_s: str = self._type_str(idx.Ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = getelementptr %s, %s %s, %s %s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = getelementptr %s, %s %s, %s %s",
|
||||
name, elem_ty_s, ptr_ty_s, ptr.Name, idx_ty_s, idx.Name)
|
||||
self._emit(line)
|
||||
|
||||
@@ -922,9 +943,9 @@ novirtual class IRBuilder:
|
||||
array_ty_s: str = self._type_str(array_ty)
|
||||
ptr_ty_s: str = self._type_str(ptr.Ty)
|
||||
idx_ty_s: str = self._type_str(idx.Ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = getelementptr %s, %s %s, i32 0, %s %s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = getelementptr %s, %s %s, i32 0, %s %s",
|
||||
name, array_ty_s, ptr_ty_s, ptr.Name, idx_ty_s, idx.Name)
|
||||
self._emit(line)
|
||||
|
||||
@@ -1032,18 +1053,18 @@ novirtual class IRBuilder:
|
||||
ty_s: str = self._type_str(val.Ty)
|
||||
|
||||
# 构建主体: switch <ty> <val>, label %default
|
||||
line: str = pool.alloc(512)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return
|
||||
viperlib.snprintf(line, 512, "switch %s %s, label %%%s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "switch %s %s, label %%%s",
|
||||
ty_s, val.Name, default_blk.Name)
|
||||
_append_cstr(line, 512, " [")
|
||||
_append_cstr(line, 512, "\n")
|
||||
_append_cstr(line, _LINE_CAP, " [")
|
||||
_append_cstr(line, _LINE_CAP, "\n")
|
||||
|
||||
# 遍历 case 列表
|
||||
cur: rawptr[SwitchCase] = cases_head
|
||||
case_ty_s: str = self._type_str(val.Ty)
|
||||
while cur is not None:
|
||||
case_line: str = pool.alloc(128)
|
||||
case_line: str = pool.alloc(_LINE_CAP)
|
||||
if case_line is not None:
|
||||
# 使用中间变量避免链式结构体成员访问被编译器丢弃
|
||||
cv: rawptr[Value] = cur.CaseVal
|
||||
@@ -1052,12 +1073,12 @@ novirtual class IRBuilder:
|
||||
cv_name: str = cv.Name
|
||||
cb_name: str = cb.Name
|
||||
if cv_name is not None and cb_name is not None:
|
||||
viperlib.snprintf(case_line, 128, " %s %s, label %%%s\n",
|
||||
viperlib.snprintf(case_line, _LINE_CAP, " %s %s, label %%%s\n",
|
||||
case_ty_s, cv_name, cb_name)
|
||||
_append_cstr(line, 512, case_line)
|
||||
_append_cstr(line, _LINE_CAP, case_line)
|
||||
cur = cur.Next
|
||||
|
||||
_append_cstr(line, 512, "]")
|
||||
_append_cstr(line, _LINE_CAP, "]")
|
||||
self._emit(line)
|
||||
self._mark_terminated()
|
||||
|
||||
@@ -1072,9 +1093,9 @@ novirtual class IRBuilder:
|
||||
pool: memhub.MemBuddy* = self.Pool
|
||||
name: str = self._alloc_ssa_name()
|
||||
ty_s: str = self._type_str(true_val.Ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = select i1 %s, %s %s, %s %s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = select i1 %s, %s %s, %s %s",
|
||||
name, cond.Name, ty_s, true_val.Name, ty_s, false_val.Name)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, true_val.Ty, name)
|
||||
@@ -1108,9 +1129,9 @@ novirtual class IRBuilder:
|
||||
val_ty_s: str = self._type_str(val.Ty)
|
||||
op_s: str = _atomic_op_str(op)
|
||||
ord_s: str = _atomic_order_str(order)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 256, "%s = atomicrmw %s %s %s, %s %s %s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = atomicrmw %s %s %s, %s %s %s",
|
||||
name, op_s, ptr_ty_s, ptr.Name, val_ty_s, val.Name, ord_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, val.Ty, name)
|
||||
@@ -1131,9 +1152,9 @@ novirtual class IRBuilder:
|
||||
new_ty_s: str = self._type_str(new_val.Ty)
|
||||
succ_s: str = _atomic_order_str(succ_order)
|
||||
fail_s: str = _atomic_order_str(fail_order)
|
||||
line: str = pool.alloc(384)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
viperlib.snprintf(line, 384, "%s = cmpxchg %s %s, %s %s, %s %s %s %s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = cmpxchg %s %s, %s %s, %s %s %s %s",
|
||||
name, ptr_ty_s, ptr.Name, cmp_ty_s, cmp_val.Name,
|
||||
new_ty_s, new_val.Name, succ_s, fail_s)
|
||||
self._emit(line)
|
||||
@@ -1154,11 +1175,11 @@ novirtual class IRBuilder:
|
||||
name: str = self._alloc_ssa_name()
|
||||
va_list_ty_s: str = self._type_str(va_list_ptr.Ty)
|
||||
arg_ty_s: str = self._type_str(arg_ty)
|
||||
line: str = pool.alloc(256)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
if va_list_ptr.Name is None:
|
||||
return None
|
||||
viperlib.snprintf(line, 256, "%s = va_arg %s %s, %s",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = va_arg %s %s, %s",
|
||||
name, va_list_ty_s, va_list_ptr.Name, arg_ty_s)
|
||||
self._emit(line)
|
||||
return SSAValue(pool, arg_ty, name)
|
||||
@@ -1190,22 +1211,22 @@ novirtual class IRBuilder:
|
||||
name = self._alloc_ssa_name()
|
||||
|
||||
ret_ty_s: str = self._type_str(ret_ty)
|
||||
line: str = pool.alloc(512)
|
||||
line: str = pool.alloc(_LINE_CAP)
|
||||
if line is None: return None
|
||||
|
||||
if has_side_effects != 0:
|
||||
if is_void == 1:
|
||||
viperlib.snprintf(line, 512, "call %s asm sideeffect \"%s\", \"%s\"()",
|
||||
viperlib.snprintf(line, _LINE_CAP, "call %s asm sideeffect \"%s\", \"%s\"()",
|
||||
ret_ty_s, asm_text, constraints)
|
||||
else:
|
||||
viperlib.snprintf(line, 512, "%s = call %s asm sideeffect \"%s\", \"%s\"()",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = call %s asm sideeffect \"%s\", \"%s\"()",
|
||||
name, ret_ty_s, asm_text, constraints)
|
||||
else:
|
||||
if is_void == 1:
|
||||
viperlib.snprintf(line, 512, "call %s asm \"%s\", \"%s\"()",
|
||||
viperlib.snprintf(line, _LINE_CAP, "call %s asm \"%s\", \"%s\"()",
|
||||
ret_ty_s, asm_text, constraints)
|
||||
else:
|
||||
viperlib.snprintf(line, 512, "%s = call %s asm \"%s\", \"%s\"()",
|
||||
viperlib.snprintf(line, _LINE_CAP, "%s = call %s asm \"%s\", \"%s\"()",
|
||||
name, ret_ty_s, asm_text, constraints)
|
||||
self._emit(line)
|
||||
|
||||
|
||||
+37
-5
@@ -402,7 +402,15 @@ def MlirFail(msg: str):
|
||||
# 类型转换失败报文再把它追加出来,一次定位到出错的那一行中间文本。
|
||||
# 依赖方向保持单向:本模块只存/读,不反向 import __function.vp。
|
||||
# ============================================================
|
||||
_MlirCtxLine: str = None
|
||||
_MlirCtxLine: str = None
|
||||
|
||||
# 类型文本渲染溢出标志:_strappend/_MlirAppendN 因缓冲上限截断时置 1,
|
||||
# 由 TypePrint / MlirTypeText 在渲染后检查并响亮报错。
|
||||
# 为什么必须响亮:MLIR 把具名结构体内联为**完整字段体**
|
||||
# (`!llvm.struct<"name", (13 个字段…)>`),类型文本远长于 LLVM 形态的
|
||||
# `%"name"` 引用,固定小缓冲(128/256)会被截断并产出畸形 MLIR
|
||||
# (实测:alloca 行类型截断 → mlir-opt 报 "unbalanced '(' character")。
|
||||
_MlirTypeTrunc: int = 0
|
||||
|
||||
|
||||
def MlirSetContextLine(line: str = None):
|
||||
@@ -673,11 +681,17 @@ def TypePrint(buf: str, size: sizet,
|
||||
"""将类型 ty 序列化为 MLIR 类型文本写入 buf(容量 size)
|
||||
|
||||
pool 用于递归打印子类型时分配临时缓冲区。
|
||||
溢出(类型文本超出 size)**响亮报错**:截断的类型文本会产出畸形 MLIR。
|
||||
"""
|
||||
global _MlirTypeTrunc
|
||||
if buf is None or size == 0:
|
||||
return
|
||||
buf[0] = '\0'
|
||||
_MlirTypeTrunc = 0
|
||||
_MlirTypePrintDepth(buf, size, ty, pool, 0)
|
||||
if _MlirTypeTrunc != 0:
|
||||
_MlirTypeTrunc = 0
|
||||
MlirFail("MLIR 渲染: 类型文本超出输出缓冲被截断(该处缓冲过小,需按类型长度增大)")
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -691,10 +705,18 @@ def TypePrint(buf: str, size: sizet,
|
||||
# / `double` / `%"name"`,由下方各分支转写为对应 MLIR 语法。
|
||||
# ============================================================
|
||||
def MlirTypeText(dst: str, dstsz: sizet, src: str, pool: memhub.MemBuddy*):
|
||||
"""把中间文本类型(MLIR 或 LLVM 形态)规范化为 MLIR 类型文本(追加到 dst)"""
|
||||
"""把中间文本类型(MLIR 或 LLVM 形态)规范化为 MLIR 类型文本(追加到 dst)
|
||||
|
||||
溢出(转换结果超出 dstsz)同样响亮报错。
|
||||
"""
|
||||
global _MlirTypeTrunc
|
||||
if dst is None or dstsz == 0 or src is None:
|
||||
return
|
||||
_MlirTypeTrunc = 0
|
||||
_MlirTypeAppend(dst, dstsz, src, pool, 0)
|
||||
if _MlirTypeTrunc != 0:
|
||||
_MlirTypeTrunc = 0
|
||||
MlirFail("MLIR 渲染: 类型文本转换结果超出输出缓冲被截断(该处缓冲过小,需按类型长度增大)")
|
||||
|
||||
|
||||
def MlirTypeTextIsPointer(src: str) -> int:
|
||||
@@ -740,17 +762,21 @@ def _MlirTextLen(p: str) -> sizet:
|
||||
|
||||
|
||||
def _MlirAppendN(dst: str, dstsz: sizet, src: str, n: sizet):
|
||||
"""把 src 的前 n 字节追加到 dst"""
|
||||
"""把 src 的前 n 字节追加到 dst;被截断时置溢出标志"""
|
||||
global _MlirTypeTrunc
|
||||
if dst is None or src is None or n == 0:
|
||||
return
|
||||
dl: sizet = string.strlen(dst)
|
||||
if dl >= dstsz:
|
||||
_MlirTypeTrunc = 1
|
||||
return
|
||||
rem: sizet = dstsz - dl
|
||||
i: sizet = 0
|
||||
while i < n and i + 1 < rem:
|
||||
dst[dl + i] = src[i]
|
||||
i += 1
|
||||
if i < n:
|
||||
_MlirTypeTrunc = 1
|
||||
dst[dl + i] = '\0'
|
||||
|
||||
|
||||
@@ -1182,20 +1208,26 @@ def _MlirStructFields(buf: str, size: sizet,
|
||||
# 内部辅助
|
||||
# ============================================================
|
||||
def _strappend(dst: str, dst_size: sizet, src: str):
|
||||
"""将 src 追加到 dst 末尾(不超过 dst_size)"""
|
||||
"""将 src 追加到 dst 末尾(不超过 dst_size);被截断时置溢出标志"""
|
||||
global _MlirTypeTrunc
|
||||
if dst is None or src is None: return
|
||||
dlen: sizet = string.strlen(dst)
|
||||
# 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回,
|
||||
# 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到 GB 外
|
||||
if dlen >= dst_size:
|
||||
_MlirTypeTrunc = 1
|
||||
return
|
||||
slen: sizet = string.strlen(src)
|
||||
remain: sizet = dst_size - dlen
|
||||
if remain <= 0: return
|
||||
if remain <= 0:
|
||||
_MlirTypeTrunc = 1
|
||||
return
|
||||
i: sizet = 0
|
||||
while i < slen and i + 1 < remain:
|
||||
dst[dlen + i] = src[i]
|
||||
i += 1
|
||||
if i < slen:
|
||||
_MlirTypeTrunc = 1
|
||||
dst[dlen + i] = '\0'
|
||||
|
||||
|
||||
|
||||
@@ -188,9 +188,9 @@ def ValuePrint(buf: str, size: sizet,
|
||||
# 常量: "<常量文本> : <MLIR 类型>"
|
||||
_append_str(buf, size, val.Name)
|
||||
_append_str(buf, size, " : ")
|
||||
tp: str = pool.alloc(256)
|
||||
tp: str = pool.alloc(512)
|
||||
if tp is not None:
|
||||
TypePrint(tp, 256, val.Ty, pool)
|
||||
TypePrint(tp, 512, val.Ty, pool)
|
||||
_append_str(buf, size, tp)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user