fix(mlir): 全局嵌套数组/聚合类型前缀走 region;补 MLIR 形态内层前缀剥离

生产者 TranslatorGenMixin._build_array_initializer_text 的嵌套数组初始化器写作
`[!llvm.array<16 x i8>[i8 0, …], …]`(内层类型前缀来自 mlirlite.TypePrint)。
两处缺口叠加导致渲染失败:
1) _MlirGlobalInitNeedsRegion 只按 '@'/'{' 判定是否走 region,嵌套数组被送进
   属性路径 _MlirArrayDenseAt —— 该路径只能表达"值 : 标量类型"的稠密数组,
   内层类型前缀与子 zeroinitializer 都无法表达;
2) _MlirGvWalk 只剥离 LLVM 形态前缀([N x T] / {…}),不认 MLIR 形态
   `!llvm.…` 前缀,元素被当叶子 → 报"全局初值叶子形态 v1 不支持"。

- _MlirGvHasSymOrStruct → _MlirGvArrayNeedsRegion:增认 '!' 前缀,路由到 region
- _MlirGvWalk:新增 MLIR 形态聚合类型前缀剥离(类型记号后紧跟 '[' / '{')
- README §2.5 同步初值两条路径与新增表项
This commit is contained in:
TermiNexus committed 2026-10-03 20:32:56 +08:00
1 parent b519269398
commit 751e7e7ef7
2 files changed
+32 -7

No files matched your search

+3 -1
View File
@@ -188,11 +188,13 @@ MLIR 的操作数不能是字面量。**扫描阶段**(pass 1)遍历函数
| 根级裸 `null` / `zeroinitializer` | **initializer region**:`@p() : !llvm.ptr` + `%v0 = llvm.mlir.zero : <顶层类型>` + `llvm.return`(属性形态 `(zeroinitializer)` 被 mlir-opt 拒绝:`expected attribute value`,实测 22.1.8) |
| 结构体 / vtable `{ i8* null, i8* bitcast (… @m0 …) }` | **initializer region**:`@vt()` + `: !llvm.struct<(…)>` + `{ <叶子 op>; undef; insertvalue 链; llvm.return }` |
| 指针数组 + GEP `[i8* getelementptr … @s0 …]` | region;GEP/bitcast 常量表达式整体等价 `llvm.mlir.addressof @s0 : !llvm.ptr` |
| 嵌套数组 `[ !llvm.array<16 x i8>[i8 0, …], … ]` | **region**(内层类型前缀按"类型记号后紧跟 `[` / `{` 即剥离"处理;元素 MLIR 类型仍取全局类型树,子 `zeroinitializer` 亦由 region 表达) |
| 指针型初值 `i8* @s0` / `i8* null` | region(顶层叶子:无 undef/insertvalue,直接 `llvm.return`) |
**初值两条路径**(判定见 `__module.vp:_MlirGlobalInitNeedsRegion`):
`c"…"` / `"…"` / 标量字面量 / **纯标量数组**走**属性路径**;
根级裸 `null` / `zeroinitializer`、结构体 `{…}`、含符号引用(`@`)或结构体的数组、
根级裸 `null` / `zeroinitializer`、结构体 `{…}`、含符号引用(`@`)/结构体(`{…}`)
/MLIR 类型前缀(`!llvm.…`,如嵌套数组子数组前缀)的数组、
顶层 `@name`、指针/聚合类型前缀开头的初值
(`i8* null`、`i8* bitcast (…)`、`i8* getelementptr …`)走 **region 路径**。
region 内元素 MLIR 类型并行取自**全局类型树**(`Struct` 字段链 / `Array` 元素类型),
+29 -6
View File
@@ -1028,8 +1028,9 @@ def _MlirGlobalInitNeedsRegion(x: str) -> int:
属性路径(已实测通过,不得回退)仅覆盖: c 字符串、字符串字面量、
标量字面量、**纯标量**数组。
其余形态一律 region: **根级裸 `null` / `zeroinitializer`**、结构体 `{…}`、
含符号引用(@)或结构体的数组、顶层裸符号引用 `@name`、指针/聚合类型前缀
开头的初值(如 `i8* null`、`i8* bitcast (…)`、`i8* getelementptr …`)。
含符号引用(@)/结构体/MLIR 类型前缀的数组、顶层裸符号引用 `@name`、
指针/聚合类型前缀开头的初值(如 `i8* null`、`i8* bitcast (…)`、
`i8* getelementptr …`)。
"""
if x is None or x[0] == '\0':
return 0
@@ -1038,7 +1039,7 @@ def _MlirGlobalInitNeedsRegion(x: str) -> int:
if x[0] == '"':
return 0
if x[0] == '[':
return _MlirGvHasSymOrStruct(x)
return _MlirGvArrayNeedsRegion(x)
if x[0] == '{':
return 1
if string.strcmp(x, "null") == 0 or string.strcmp(x, "zeroinitializer") == 0:
@@ -1054,8 +1055,17 @@ def _MlirGlobalInitNeedsRegion(x: str) -> int:
return 1
def _MlirGvHasSymOrStruct(x: str) -> int:
"""扫描初值文本(跳过字符串字面量): 出现符号引用 '@' 或结构体 '{' 返回 1"""
def _MlirGvArrayNeedsRegion(x: str) -> int:
"""数组初值是否必须走 initializer region(1=region / 0=属性路径)
出现以下任一记号即返回 1:
- 符号引用 '@':属性路径无法表达地址引用;
- 结构体 '{':聚合元素;
- MLIR 类型前缀 '!':如嵌套数组元素的子数组前缀 `!llvm.array<…>`。
属性路径(_MlirArrayDenseAt)只认"元素为 `值 : 标量类型`"的稠密数组,
内层类型前缀与子 `zeroinitializer` 都无法表达,必须交给 region 的
insertvalue 链。扫描跳过字符串字面量,避免把 LLVM 字符串里的 '{'/'!' 误判。
"""
p: str = x
while p[0] != '\0':
ch: int = p[0]
@@ -1069,7 +1079,7 @@ def _MlirGvHasSymOrStruct(x: str) -> int:
if p[0] == '"':
p = p + 1
continue
if ch == '@' or ch == '{':
if ch == '@' or ch == '{' or ch == '!':
return 1
p = p + 1
return 0
@@ -1170,6 +1180,19 @@ def _MlirGvWalk(p: str, ty: rawptr[LLVMType], path: str, depth: int) -> str:
MlirFail("MLIR 渲染: 结构体类型前缀缓冲分配失败")
p = _mlir_read_type(p, stb, 512)
p = _mlir_ws(p)
# MLIR 形态聚合类型前缀(`!llvm.array<…>` / `!llvm.struct<…>`)后紧跟聚合
# 字面量时先整体读掉:来自上层用 mlirlite.TypePrint 生成的内层类型(如嵌套
# 数组初始化器的子数组前缀 `!llvm.array<16 x i8>[i8 0, …]`,见
# TranslatorGenMixin._build_array_initializer_text),上方 LLVM 形态前缀
# 判据(_MlirGvIsArrayType/_MlirGvIsStructType)认不出 '!' 开头
if p[0] == '!':
mtb: str = _MlirGvPool.alloc(512)
if mtb is None:
MlirFail("MLIR 渲染: MLIR 类型前缀缓冲分配失败")
qm: str = _mlir_read_type(p, mtb, 512)
qm = _mlir_ws(qm)
if qm[0] == '[' or qm[0] == '{':
p = qm
if p[0] == '{':
return _MlirGvWalkStruct(p, ty, path, depth)
if p[0] == '[':