fix(mlir): 全局初值 region 草稿缓冲改为单次 PrintModule 复用,修子池耗尽
每个全局初值 region 逐全局 alloc leaf/ins 各 32 KiB、每个初值节点 alloc 4 KiB 类型/符号草稿且从不释放:结构体/vtable 全局多的模块(MLIRLiteTest #12)在约 2 MiB 模块子池上耗尽,报"零初值类型缓冲分配失败"。 改为按 PrintModule 惰性分配一组复用草稿(leaf/ins/类型/符号/路径栈), 跨全局、跨节点共享;PrintModule 入口 MlirGvResetScratch 使上次草稿失效, 下次按当前池重建(绝不复用已释放/被复用地址的池,避免悬空写穿 canary)。 下标路径改按递归深度分槽的复用栈,不再逐节点分配。
This commit is contained in:
1 parent
68fe839da9
commit
5dad869a40
1 file changed
+111
-59
+111
-59
@@ -340,6 +340,10 @@ class LLVMModule:
|
||||
# 打印期间有效,清空后不再解引用(避免 pool reset 后悬空)。
|
||||
_MlirPublishNamedTypes(self, pool)
|
||||
|
||||
# 使 region 渲染草稿失效:本次打印首次用到时按当前 pool 惰性重建(见
|
||||
# _MlirGvEnsureScratch)。跨打印绝不复用(上一次的池可能已释放/被复用)。
|
||||
MlirGvResetScratch()
|
||||
|
||||
_append_cstr(buf, size, "module {\n")
|
||||
|
||||
# 模式说明注释(MLIR 无 stub/text 二分)
|
||||
@@ -1028,7 +1032,13 @@ def _MlirArrayDenseAt(buf: str, size: sizet, src: str,
|
||||
# * 符号名一律经 _MlirSymRefAppend(先剥 LLVM 口径引号,再按 MLIR 口径重加);
|
||||
# * 不支持的叶子形态一律 MlirFail(带原始文本),绝不静默输出错误 MLIR。
|
||||
# ============================================================
|
||||
GV_REGION_BUF_SIZE: t.CDefine = 32768
|
||||
GV_REGION_BUF_SIZE: t.CDefine = 32768
|
||||
|
||||
# 下标路径复用栈:每个递归深度一个槽(顶层 path="" → 深度 d 的路径写在槽 d)。
|
||||
# 深度上限与 _MlirGvWalk 的 64 层守卫一致,留余量取 72;每槽 512 字节足够
|
||||
# (64 层 × " , NN" ≈ 400 字节)。
|
||||
GV_PATH_SLOT: t.CDefine = 512
|
||||
GV_PATH_MAX: t.CDefine = 72
|
||||
|
||||
# region 渲染期状态(单线程递归渲染,逐全局重置)
|
||||
_MlirGvLeafBuf: str = None # 叶子 op 缓冲
|
||||
@@ -1040,6 +1050,72 @@ _MlirGvPool: memhub.MemBuddy* = None
|
||||
_MlirGvLeafSeq: int = 0
|
||||
_MlirGvInsSeq: int = 0
|
||||
|
||||
# ---- region 渲染的**复用**草稿缓冲(惰性分配一次,跨全局/跨节点共享)----
|
||||
#
|
||||
# 此前每个全局、每个初值节点都从模块子分配器 alloc 新缓冲且从不释放:
|
||||
# 每全局 leaf/ins 各 32 KiB、每节点 4 KiB ⇒ 结构体/vtable 全局多的模块
|
||||
# (MLIRLiteTest #12)把 ~2 MiB 子池耗尽,报 "零初值类型缓冲分配失败"。
|
||||
# region 渲染是单线程顺序的,草稿内容用完即弃 ⇒ 分配一次复用即可。
|
||||
_MlirGvSbRead1: str = None # 512B:类型前缀记号读取草稿
|
||||
_MlirGvSbRead2: str = None # 512B:叶子类型记号读取草稿
|
||||
_MlirGvSbName: str = None # 512B:符号名 / 常量表达式符号名草稿
|
||||
_MlirGvSbVal: str = None # 512B:标量初值字面量草稿
|
||||
_MlirGvTyBuf: str = None # 4096B:元素 MLIR 类型文本(zero/const)
|
||||
_MlirGvNameBuf: str = None # 32B:SSA 名生成草稿
|
||||
_MlirGvPathStack: str = None # GV_PATH_MAX × GV_PATH_SLOT:下标路径复用栈
|
||||
|
||||
|
||||
def MlirGvResetScratch():
|
||||
"""使 region 渲染的复用草稿失效(下次 EnsureScratch 按当前池重新分配)
|
||||
|
||||
草稿只在**单次 PrintModule** 内经惰性分配复用(跨全局/跨节点共享);
|
||||
打印结束由 PrintModule 调用本函数置空 ⇒ 绝不复用上一次打印的指针
|
||||
(上一次的池可能已释放,或同一地址被新池复用 → 悬空写穿)。
|
||||
"""
|
||||
global _MlirGvLeafBuf
|
||||
_MlirGvLeafBuf = None
|
||||
|
||||
|
||||
def _MlirGvEnsureScratch(pool: memhub.MemBuddy*) -> int:
|
||||
"""惰性分配本次 PrintModule 的复用草稿缓冲(跨全局/跨节点共享),返回 1=就绪"""
|
||||
global _MlirGvLeafBuf, _MlirGvInsBuf, _MlirGvTopType, _MlirGvLast, _MlirGvPrev
|
||||
global _MlirGvSbRead1, _MlirGvSbRead2, _MlirGvSbName, _MlirGvSbVal
|
||||
global _MlirGvTyBuf, _MlirGvNameBuf, _MlirGvPathStack
|
||||
if _MlirGvLeafBuf is not None:
|
||||
return 1
|
||||
lb: str = pool.alloc(GV_REGION_BUF_SIZE)
|
||||
ib: str = pool.alloc(GV_REGION_BUF_SIZE)
|
||||
tb: str = pool.alloc(4096)
|
||||
la: str = pool.alloc(32)
|
||||
pr: str = pool.alloc(32)
|
||||
r1: str = pool.alloc(512)
|
||||
r2: str = pool.alloc(512)
|
||||
nm: str = pool.alloc(512)
|
||||
vl: str = pool.alloc(512)
|
||||
tyb: str = pool.alloc(4096)
|
||||
nb: str = pool.alloc(32)
|
||||
ps: str = pool.alloc(GV_PATH_SLOT * GV_PATH_MAX)
|
||||
if lb is None or ib is None or tb is None or la is None or pr is None \
|
||||
or r1 is None or r2 is None or nm is None or vl is None \
|
||||
or tyb is None or nb is None or ps is None:
|
||||
MlirFail("MLIR 渲染: 全局 region 缓冲分配失败")
|
||||
lb[0] = '\0'; ib[0] = '\0'; tb[0] = '\0'; la[0] = '\0'; pr[0] = '\0'
|
||||
r1[0] = '\0'; r2[0] = '\0'; nm[0] = '\0'; vl[0] = '\0'
|
||||
tyb[0] = '\0'; nb[0] = '\0'; ps[0] = '\0'
|
||||
_MlirGvLeafBuf = lb
|
||||
_MlirGvInsBuf = ib
|
||||
_MlirGvTopType = tb
|
||||
_MlirGvLast = la
|
||||
_MlirGvPrev = pr
|
||||
_MlirGvSbRead1 = r1
|
||||
_MlirGvSbRead2 = r2
|
||||
_MlirGvSbName = nm
|
||||
_MlirGvSbVal = vl
|
||||
_MlirGvTyBuf = tyb
|
||||
_MlirGvNameBuf = nb
|
||||
_MlirGvPathStack = ps
|
||||
return 1
|
||||
|
||||
|
||||
def _MlirGlobalInitNeedsRegion(x: str) -> int:
|
||||
"""判定全局初值是否改走 initializer region(1=region / 0=属性路径)
|
||||
@@ -1110,19 +1186,18 @@ def _MlirGlobalInitRegion(buf: str, size: sizet,
|
||||
|
||||
每行都带 '\\n';调用方在末尾补 '}',模块层再统一缩进 2 空格。
|
||||
"""
|
||||
global _MlirGvLeafBuf, _MlirGvInsBuf, _MlirGvTopType, _MlirGvLast
|
||||
global _MlirGvPrev, _MlirGvPool, _MlirGvLeafSeq, _MlirGvInsSeq
|
||||
global _MlirGvPool, _MlirGvLeafSeq, _MlirGvInsSeq
|
||||
x: str = gv.Initializer
|
||||
if x is None:
|
||||
return
|
||||
topbuf: str = pool.alloc(4096)
|
||||
leafbuf: str = pool.alloc(GV_REGION_BUF_SIZE)
|
||||
insbuf: str = pool.alloc(GV_REGION_BUF_SIZE)
|
||||
lastbuf: str = pool.alloc(32)
|
||||
prevbuf: str = pool.alloc(32)
|
||||
if topbuf is None or leafbuf is None or insbuf is None \
|
||||
or lastbuf is None or prevbuf is None:
|
||||
MlirFail("MLIR 渲染: 全局 region 缓冲分配失败")
|
||||
# 复用缓冲(惰性分配一次,跨全局共享)——此前逐全局 alloc 且不释放,
|
||||
# 结构体/vtable 全局多时耗尽模块子分配器。
|
||||
_MlirGvEnsureScratch(pool)
|
||||
topbuf: str = _MlirGvTopType
|
||||
leafbuf: str = _MlirGvLeafBuf
|
||||
insbuf: str = _MlirGvInsBuf
|
||||
lastbuf: str = _MlirGvLast
|
||||
prevbuf: str = _MlirGvPrev
|
||||
topbuf[0] = '\0'
|
||||
leafbuf[0] = '\0'
|
||||
insbuf[0] = '\0'
|
||||
@@ -1130,11 +1205,6 @@ def _MlirGlobalInitRegion(buf: str, size: sizet,
|
||||
prevbuf[0] = '\0'
|
||||
TypePrint(topbuf, 4096, gv.Ty, pool)
|
||||
|
||||
_MlirGvLeafBuf = leafbuf
|
||||
_MlirGvInsBuf = insbuf
|
||||
_MlirGvTopType = topbuf
|
||||
_MlirGvLast = lastbuf
|
||||
_MlirGvPrev = prevbuf
|
||||
_MlirGvPool = pool
|
||||
_MlirGvLeafSeq = 0
|
||||
_MlirGvInsSeq = 0
|
||||
@@ -1185,18 +1255,14 @@ def _MlirGvWalk(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> str:
|
||||
MlirFail("MLIR 渲染: 全局初值文本意外结束")
|
||||
# 显式数组类型前缀(如字段写成 "[3 x i8] [i8 1, i8 2]")先整体读掉
|
||||
if p[0] == '[' and _MlirGvIsArrayType(p) != 0:
|
||||
tb: str = _MlirGvPool.alloc(4096)
|
||||
if tb is None:
|
||||
MlirFail("MLIR 渲染: 数组类型前缀缓冲分配失败")
|
||||
tb: str = _MlirGvSbRead1
|
||||
p = _mlir_read_type(p, tb, 512)
|
||||
p = _mlir_ws(p)
|
||||
# 显式结构体类型前缀(如 llvm.global_ctors 元素的
|
||||
# "{ i32, void ()*, i8* } { i32 65535, … }")先整体读掉;`{…}` 既可能是
|
||||
# 类型也可能是字面量,靠"其后是否紧跟另一个 `{`"区分(见 _MlirGvIsStructType)
|
||||
if p[0] == '{' and _MlirGvIsStructType(p) != 0:
|
||||
stb: str = _MlirGvPool.alloc(4096)
|
||||
if stb is None:
|
||||
MlirFail("MLIR 渲染: 结构体类型前缀缓冲分配失败")
|
||||
stb: str = _MlirGvSbRead1
|
||||
p = _mlir_read_type(p, stb, 512)
|
||||
p = _mlir_ws(p)
|
||||
# MLIR 形态聚合类型前缀(`!llvm.array<…>` / `!llvm.struct<…>`)后紧跟聚合
|
||||
@@ -1205,9 +1271,7 @@ def _MlirGvWalk(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> str:
|
||||
# TranslatorGenMixin._build_array_initializer_text),上方 LLVM 形态前缀
|
||||
# 判据(_MlirGvIsArrayType/_MlirGvIsStructType)认不出 '!' 开头
|
||||
if p[0] == '!':
|
||||
mtb: str = _MlirGvPool.alloc(4096)
|
||||
if mtb is None:
|
||||
MlirFail("MLIR 渲染: MLIR 类型前缀缓冲分配失败")
|
||||
mtb: str = _MlirGvSbRead1
|
||||
qm: str = _mlir_read_type(p, mtb, 512)
|
||||
qm = _mlir_ws(qm)
|
||||
if qm[0] == '[' or qm[0] == '{':
|
||||
@@ -1276,15 +1340,19 @@ def _MlirGvIsStructType(p: str) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _MlirGvPathChild(path: str, idx: int) -> str:
|
||||
"""由父下标路径与子序号拼出子下标路径(顶层 path="" → "0")"""
|
||||
nb: str = _MlirGvPool.alloc(string.strlen(path) + 16)
|
||||
if nb is None:
|
||||
MlirFail("MLIR 渲染: 下标路径缓冲分配失败")
|
||||
def _MlirGvPathChild(path: str, idx: int, depth: int) -> str:
|
||||
"""由父下标路径与子序号拼出子下标路径(顶层 path="" → "0")
|
||||
|
||||
写入按递归深度分槽的复用栈(槽 = depth):祖先路径占 0..depth-1,
|
||||
本层写槽 depth、子层写槽 depth+1,互不覆盖;避免逐节点 alloc 泄漏。
|
||||
"""
|
||||
if depth < 0 or depth >= GV_PATH_MAX:
|
||||
MlirFail("MLIR 渲染: 下标路径深度越界")
|
||||
nb: str = _MlirGvPathStack + depth * GV_PATH_SLOT
|
||||
if path[0] == '\0':
|
||||
viperlib.snprintf(nb, string.strlen(path) + 16, "%d", idx)
|
||||
viperlib.snprintf(nb, GV_PATH_SLOT, "%d", idx)
|
||||
else:
|
||||
viperlib.snprintf(nb, string.strlen(path) + 16, "%s, %d", path, idx)
|
||||
viperlib.snprintf(nb, GV_PATH_SLOT, "%s, %d", path, idx)
|
||||
return nb
|
||||
|
||||
|
||||
@@ -1317,7 +1385,7 @@ def _MlirGvWalkStruct(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> st
|
||||
fty: rawptr[LLVMType] = None
|
||||
if cur is not None:
|
||||
fty = paramnode_get_ty(cur)
|
||||
p = _MlirGvWalk(p, fty, _MlirGvPathChild(path, idx), depth + 1)
|
||||
p = _MlirGvWalk(p, fty, _MlirGvPathChild(path, idx, depth), depth + 1)
|
||||
if cur is not None:
|
||||
cur = paramnode_get_next(cur)
|
||||
idx += 1
|
||||
@@ -1351,7 +1419,7 @@ def _MlirGvWalkArray(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> str
|
||||
elif p[0] == ',':
|
||||
p = p + 1
|
||||
else:
|
||||
p = _MlirGvWalk(p, elem_ty, _MlirGvPathChild(path, idx), depth + 1)
|
||||
p = _MlirGvWalk(p, elem_ty, _MlirGvPathChild(path, idx, depth), depth + 1)
|
||||
idx += 1
|
||||
if idx == 0:
|
||||
string.strcpy(_MlirGvLast, "%undef")
|
||||
@@ -1395,26 +1463,20 @@ def _MlirGvWalkLeaf(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> str:
|
||||
p = _mlir_ws(p)
|
||||
if _MlirGvIsBareValue(p) == 0:
|
||||
# 元素自带类型记号(`i8* null` / `!llvm.ptr null` 等):只用于推进游标
|
||||
tb: str = _MlirGvPool.alloc(4096)
|
||||
if tb is None:
|
||||
MlirFail("MLIR 渲染: 叶子类型记号缓冲分配失败")
|
||||
tb: str = _MlirGvSbRead2
|
||||
p = _mlir_read_type(p, tb, 512)
|
||||
p = _mlir_ws(p)
|
||||
if p[0] == '\0':
|
||||
MlirFail("MLIR 渲染: 叶子初值只有类型、缺少值")
|
||||
if p[0] == '@':
|
||||
# 裸符号引用(剥 LLVM 引号 → 经 _MlirSymRefAppend 按 MLIR 口径重加)
|
||||
nb: str = _MlirGvPool.alloc(4096)
|
||||
if nb is None:
|
||||
MlirFail("MLIR 渲染: 符号名缓冲分配失败")
|
||||
nb: str = _MlirGvSbName
|
||||
p = _MlirGvReadSymName(p, nb, 512)
|
||||
_MlirGvEmitAddressOf(nb)
|
||||
elif string.strncmp(p, "bitcast", 7) == 0 \
|
||||
or string.strncmp(p, "getelementptr", 13) == 0:
|
||||
# 常量表达式整体视为符号引用(bitcast 不透明指针下恒等;GEP 取首元素地址)
|
||||
nb2: str = _MlirGvPool.alloc(4096)
|
||||
if nb2 is None:
|
||||
MlirFail("MLIR 渲染: 常量表达式符号名缓冲分配失败")
|
||||
nb2: str = _MlirGvSbName
|
||||
p = _MlirGvScanConstExprSym(p, nb2, 512)
|
||||
_MlirGvEmitAddressOf(nb2)
|
||||
elif string.strncmp(p, "null", 4) == 0:
|
||||
@@ -1426,9 +1488,7 @@ def _MlirGvWalkLeaf(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> str:
|
||||
else:
|
||||
c0: int = p[0]
|
||||
if c0 == '-' or (c0 >= '0' and c0 <= '9') or c0 == '.':
|
||||
vb: str = _MlirGvPool.alloc(4096)
|
||||
if vb is None:
|
||||
MlirFail("MLIR 渲染: 标量初值缓冲分配失败")
|
||||
vb: str = _MlirGvSbVal
|
||||
p = _mlir_read_value(p, vb, 512)
|
||||
_MlirGvEmitConst(vb, ty)
|
||||
else:
|
||||
@@ -1513,11 +1573,9 @@ def _MlirGvSymNameEnd(ch: int) -> int:
|
||||
|
||||
|
||||
def _MlirGvNextLeafName() -> str:
|
||||
"""分配下一个叶子 SSA 名(%v0, %v1, …)"""
|
||||
"""分配下一个叶子 SSA 名(%v0, %v1, …;复用共享名缓冲,调用后立即取用)"""
|
||||
global _MlirGvLeafSeq
|
||||
ln: str = _MlirGvPool.alloc(32)
|
||||
if ln is None:
|
||||
MlirFail("MLIR 渲染: 叶子 SSA 名缓冲分配失败")
|
||||
ln: str = _MlirGvNameBuf
|
||||
viperlib.snprintf(ln, 32, "%%v%d", _MlirGvLeafSeq)
|
||||
_MlirGvLeafSeq += 1
|
||||
return ln
|
||||
@@ -1536,9 +1594,7 @@ def _MlirGvEmitAddressOf(name: str):
|
||||
|
||||
def _MlirGvEmitZero(ty: rawptr[LLVMType]):
|
||||
"""发射叶子 op: %vN = llvm.mlir.zero : <元素 MLIR 类型>"""
|
||||
mt: str = _MlirGvPool.alloc(4096)
|
||||
if mt is None:
|
||||
MlirFail("MLIR 渲染: 零初值类型缓冲分配失败")
|
||||
mt: str = _MlirGvTyBuf
|
||||
mt[0] = '\0'
|
||||
TypePrint(mt, 4096, ty, _MlirGvPool)
|
||||
ln: str = _MlirGvNextLeafName()
|
||||
@@ -1552,9 +1608,7 @@ def _MlirGvEmitZero(ty: rawptr[LLVMType]):
|
||||
|
||||
def _MlirGvEmitConst(val: str, ty: rawptr[LLVMType]):
|
||||
"""发射叶子 op: %vN = llvm.mlir.constant(<lit> : <元素 MLIR 类型>) : <同类型>"""
|
||||
mt: str = _MlirGvPool.alloc(4096)
|
||||
if mt is None:
|
||||
MlirFail("MLIR 渲染: 标量元素类型缓冲分配失败")
|
||||
mt: str = _MlirGvTyBuf
|
||||
mt[0] = '\0'
|
||||
TypePrint(mt, 4096, ty, _MlirGvPool)
|
||||
if mt[0] != 'i' and mt[0] != 'f':
|
||||
@@ -1580,9 +1634,7 @@ def _MlirGvInsertLeaf(path: str):
|
||||
"""发射 insertvalue(多下标路径;类型后缀始终是顶层聚合类型)"""
|
||||
global _MlirGvInsSeq
|
||||
_MlirGvInsSeq += 1
|
||||
sn: str = _MlirGvPool.alloc(32)
|
||||
if sn is None:
|
||||
MlirFail("MLIR 渲染: insertvalue SSA 名缓冲分配失败")
|
||||
sn: str = _MlirGvNameBuf
|
||||
viperlib.snprintf(sn, 32, "%%s%d", _MlirGvInsSeq)
|
||||
_append_cstr(_MlirGvInsBuf, GV_REGION_BUF_SIZE, " ")
|
||||
_append_cstr(_MlirGvInsBuf, GV_REGION_BUF_SIZE, sn)
|
||||
|
||||
Reference in new issue
Block a user