fix(mlirlite): 全局数组 dense 渲染缓冲提到循环外复用(消每元素~5KB泄漏) + 聚合值读取必前进(修 too many global array elements)
This commit is contained in:
1 parent
1eb46faa41
commit
e9e1933a62
1 file changed
+56
-13
+56
-13
@@ -878,18 +878,57 @@ def _MlirCStringToMlir(buf: str, size: sizet, src: str, pool: memhub.MemBuddy*):
|
||||
_append_cstr(buf, size, p)
|
||||
|
||||
|
||||
def _mlir_read_aggregate_token(p: str, out: str, outsz: sizet) -> str:
|
||||
"""读取一个聚合/复合值 token(括号配平),到**顶层**分隔符(`,` 或 `]`)为止,不消费分隔符。
|
||||
|
||||
用于 `_mlir_read_value` 覆盖不到的形态,例如 `[16 x i8] zeroinitializer`、`{ i32 1, i32 2 }`:
|
||||
这类值以 `[`/`{` 开头,`_mlir_read_value` 不会前进,会让外层数组解析原地打转。
|
||||
如果连一个字符都没读到(调用方随后会做"至少前进 1 字符"的兜底)。
|
||||
"""
|
||||
p = _mlir_ws(p)
|
||||
n: sizet = 0
|
||||
d: int = 0
|
||||
while p[0] != '\0':
|
||||
ch: int = p[0]
|
||||
if d == 0 and (ch == ',' or ch == ']'):
|
||||
break
|
||||
if ch == '[' or ch == '{' or ch == '(' or ch == '<':
|
||||
d += 1
|
||||
elif ch == ']' or ch == '}' or ch == ')' or ch == '>':
|
||||
if d == 0:
|
||||
break
|
||||
d -= 1
|
||||
if n + 1 < outsz:
|
||||
out[n] = char(ch)
|
||||
n += 1
|
||||
p = p + 1
|
||||
out[n] = '\0'
|
||||
return p
|
||||
|
||||
|
||||
def _MlirArrayDenseAt(buf: str, size: sizet, src: str,
|
||||
pool: memhub.MemBuddy*) -> str:
|
||||
"""LLVM array literal → MLIR dense content (nested recursive); returns the new cursor."""
|
||||
if src is None or src[0] != '[':
|
||||
MlirFail("MLIR render: global array initializer form unsupported in v1")
|
||||
# [修复] 三个临时缓冲**在进入时分配一次**并全程复用:原实现是"每个元素分配
|
||||
# 512(类型文本) + 512(值文本) + 4096(元素 MLIR 类型) ≈ 5KB 且从不释放",于是
|
||||
# `[256][16]uint8` 这类大表(4096 元素)单次就吃掉 ~20MB 编译池,多个全局数组叠加
|
||||
# 直接耗尽(现场:[MEM] alloc failed … order=5/8 占 943MB、attribution site=?)。
|
||||
tb: str = pool.alloc(512)
|
||||
vb: str = pool.alloc(512)
|
||||
mtb: str = pool.alloc(4096)
|
||||
if tb is None or vb is None or mtb is None:
|
||||
MlirFail("MLIR render: array element buffer allocation failed")
|
||||
p: str = src + 1
|
||||
_append_cstr(buf, size, "[")
|
||||
n: int = 0
|
||||
g: int = 0
|
||||
while p[0] != '\0':
|
||||
g += 1
|
||||
if g > 4096:
|
||||
# 上限只用于防"解析不收敛"的死循环,不是数组容量限制:位图字体表
|
||||
# `[256] x [16]uint8` 本身就 4352 个元素(外层 256 + 内层 4096),旧值 4096 会误报。
|
||||
if g > 1048576:
|
||||
MlirFail("MLIR render: too many global array elements")
|
||||
p = _mlir_ws(p)
|
||||
if p[0] == ']':
|
||||
@@ -902,23 +941,25 @@ def _MlirArrayDenseAt(buf: str, size: sizet, src: str,
|
||||
if p[0] == '[':
|
||||
p = _MlirArrayDenseAt(buf, size, p, pool)
|
||||
else:
|
||||
tb: str = pool.alloc(512)
|
||||
if tb is None:
|
||||
MlirFail("MLIR render: array element type buffer allocation failed")
|
||||
p = _mlir_read_type(p, tb, 512)
|
||||
p = _mlir_ws(p)
|
||||
vb: str = pool.alloc(512)
|
||||
if vb is None:
|
||||
MlirFail("MLIR render: array element value buffer allocation failed")
|
||||
p = _mlir_read_value(p, vb, 512)
|
||||
p2: str = _mlir_read_value(p, vb, 512)
|
||||
# [修复] 值不是 %name / @"name" / 字面量时(聚合值:`[16 x i8] zeroinitializer`、
|
||||
# `{ i32 1, i32 2 }`),`_mlir_read_value` 原地不前进 ⇒ 外层 while 不收敛 ⇒
|
||||
# g 冲到上限并误报 "too many global array elements"。这里回退为括号配平读取,
|
||||
# 并保证**至少前进 1 个字符**,绝不原地打转。
|
||||
if p2 == p:
|
||||
p2 = _mlir_read_aggregate_token(p, vb, 512)
|
||||
if p2 == p:
|
||||
vb[0] = char(p[0])
|
||||
vb[1] = '\0'
|
||||
p2 = p + 1
|
||||
p = p2
|
||||
_append_cstr(buf, size, vb)
|
||||
# Elements must carry a type annotation: MLIR array attributes default to i64, so
|
||||
# i8/i32/pointer elements would mismatch the global type (working form:
|
||||
# `[1 : i8, 2 : i8] : !llvm.array<2 x i8>`).
|
||||
_append_cstr(buf, size, " : ")
|
||||
mtb: str = pool.alloc(4096)
|
||||
if mtb is None:
|
||||
MlirFail("MLIR render: array element MLIR type buffer allocation failed")
|
||||
mtb[0] = '\0'
|
||||
MlirTypeText(mtb, 4096, tb, pool)
|
||||
_append_cstr(buf, size, mtb)
|
||||
@@ -1275,7 +1316,8 @@ def _MlirGvWalkStruct(p: str, ty: LLVMType*, path: str, depth: int) -> str:
|
||||
guard: int = 0
|
||||
while done == 0:
|
||||
guard += 1
|
||||
if guard > 4096:
|
||||
# 防解析不收敛的死循环,不是字段数上限(大结构体的初始化器可能很长)。
|
||||
if guard > 1048576:
|
||||
MlirFail("MLIR render: too many struct initializer elements")
|
||||
p = _mlir_ws(p)
|
||||
if p[0] == '\0':
|
||||
@@ -1312,7 +1354,8 @@ def _MlirGvWalkArray(p: str, ty: LLVMType*, path: str, depth: int) -> str:
|
||||
guard: int = 0
|
||||
while done == 0:
|
||||
guard += 1
|
||||
if guard > 65536:
|
||||
# 防解析不收敛的死循环,不是数组元素上限(大数组的初始化器可能很长)。
|
||||
if guard > 1048576:
|
||||
MlirFail("MLIR render: too many array initializer elements")
|
||||
p = _mlir_ws(p)
|
||||
if p[0] == '\0':
|
||||
|
||||
Reference in new issue
Block a user