From e9e1933a625d64f9cb229767bc9112105004b006 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 16 Oct 2026 12:04:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(mlirlite):=20=E5=85=A8=E5=B1=80=E6=95=B0?= =?UTF-8?q?=E7=BB=84=20dense=20=E6=B8=B2=E6=9F=93=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E6=8F=90=E5=88=B0=E5=BE=AA=E7=8E=AF=E5=A4=96=E5=A4=8D=E7=94=A8?= =?UTF-8?q?(=E6=B6=88=E6=AF=8F=E5=85=83=E7=B4=A0~5KB=E6=B3=84=E6=BC=8F)=20?= =?UTF-8?q?+=20=E8=81=9A=E5=90=88=E5=80=BC=E8=AF=BB=E5=8F=96=E5=BF=85?= =?UTF-8?q?=E5=89=8D=E8=BF=9B(=E4=BF=AE=20too=20many=20global=20array=20el?= =?UTF-8?q?ements)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlirlite/__module.vp | 69 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/mlirlite/__module.vp b/mlirlite/__module.vp index a8c88eb..98c6b37 100644 --- a/mlirlite/__module.vp +++ b/mlirlite/__module.vp @@ -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':