From f813c0543b93a3603c4bb5e704083ea372dde95f Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 20:35:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(mlir):=20=E6=B5=AE=E7=82=B9=E5=B8=B8?= =?UTF-8?q?=E9=87=8F=E4=BD=8D=E6=A8=A1=E5=BC=8F=E5=8E=9F=E6=A0=B7=E7=9B=B4?= =?UTF-8?q?=E9=80=9A=EF=BC=8C=E6=B6=88=E9=99=A4=20%e=20=E6=88=AA=E6=96=AD?= =?UTF-8?q?=E7=B2=BE=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MLIR FloatAttr 语法支持十六进制位模式(Builtin Dialect: `hexadecimal-literal ':' float-type`,按底层二进制位解释),故 ConstFloat 产出的 `0x…` 无需转十进制。此前 _MlirFloatLiteral 把它转成 `%e`(默认 7 位有效数字): 3.141592653589793 → 3.141593e+00,静默截断,与 __values.vp 选位模式的初衷相悖。 - _MlirFloatLiteral:hex 且 mt 为 f32/f64 → 原样返回(无损); f16/f128 仍响亮报错(ConstFloat 只产出 64 位位模式,宽度与该两类型不符) - 删除因此失效的 _MlirParseHexU64 - README §2.3 常量表 / §5 打印阶段转换说明同步 --- mlirlite/README.md | 4 +-- mlirlite/__function.vp | 56 +++++++++++------------------------------- 2 files changed, 17 insertions(+), 43 deletions(-) diff --git a/mlirlite/README.md b/mlirlite/README.md index a898213..c8e3c83 100644 --- a/mlirlite/README.md +++ b/mlirlite/README.md @@ -158,7 +158,7 @@ MLIR 的操作数不能是字面量。**扫描阶段**(pass 1)遍历函数 | 常量 | 物化 op | |------|---------| | `i32 42` | `%c0 = llvm.mlir.constant(42 : i32) : i32` | -| `f64 0x40091EB851EB851F` | `%c0 = llvm.mlir.constant(3.140000e+00 : f64) : f64`(位模式 → 十进制科学计数法) | +| `f64 0x40091EB851EB851F` | `%c0 = llvm.mlir.constant(0x40091EB851EB851F : f64) : f64`(位模式**原样直通**:MLIR FloatAttr 支持十六进制位模式,按底层二进制位解释,无精度损失) | | `null` / `zeroinitializer` | `%c0 = llvm.mlir.zero : !llvm.ptr`(或 `: i32` 等) | | `@f` / `@"sha1.x"` | `%c0 = llvm.mlir.addressof @f : !llvm.ptr` | @@ -552,7 +552,7 @@ packed"的组合,无需(也无处)为其单独报错。登记表每槽 16 | 5 | `IRBuilder.build_bitcast(val,to_ty)` | 返回的 `Value` 名字仍会出现在中间文本里,但打印时若两端都是指针则**整个指令消失**、名字被别名替换(`Value` 对象本身不变) | | 6 | `IRBuilder.build_phi` / `build_br` | builder 语义不变(仍写 phi 行);MLIR 打印时 phi 行消失、br 追加实参 | | 7 | `IRBuilder.build_alloca` | 打印时个数按常量 `1`(i32)物化;`build_alloca_aligned` 的 `, align N` 转写为 `{alignment = N : i64}` 属性(N 必须是 2 的幂常量,否则响亮报错) | -| 8 | `const_int` / `ConstFloat` | `Name` 文本仍是 llvmlite 形态(十进制 / `0x` 位模式);**转换发生在打印阶段**(浮点位模式→十进制科学计数法) | +| 8 | `const_int` / `ConstFloat` | `Name` 文本仍是 llvmlite 形态(十进制 / `0x` 位模式);**转换发生在打印阶段**(浮点 `0x` 位模式**原样直通**,MLIR 按底层位解释;f16/f128 位模式宽度不符 → 响亮报错) | | 9 | `create_global_string` | `Initializer` 仍是 `c"…\00"`;打印时转成 `"…"`(**去掉尾随 `\00`**,见 §5 待确认) | | 10 | `verify_function` / `verify_module` | 校验内部模型 + 中间文本(与 llvmlite 完全一致);**不**校验 MLIR 文本合法性(交给 mlir-opt) | | 11 | `PrintStructDefinition` | 输出空串(MLIR 无类型定义行),llvmlite 版输出 `%"name" = type {…}`;具名结构体只在**使用处**内联出现(§2.10) | diff --git a/mlirlite/__function.vp b/mlirlite/__function.vp index a2eccc0..b53bc97 100644 --- a/mlirlite/__function.vp +++ b/mlirlite/__function.vp @@ -1371,49 +1371,23 @@ def _MlirCxResName(resname: str, suffix: str) -> str: return nm -def _MlirParseHexU64(s: str) -> t.CUInt64T: - """解析 0x 十六进制字面量为 u64""" - p: str = s - if p[0] == '0' and (p[1] == 'x' or p[1] == 'X'): - p = p + 2 - v: t.CUInt64T = 0 - g: int = 0 - while p[0] != '\0' and g < 32: - ch: int = p[0] - d: int = -1 - if ch >= '0' and ch <= '9': - d = ch - 48 - elif ch >= 'a' and ch <= 'f': - d = ch - 87 - elif ch >= 'A' and ch <= 'F': - d = ch - 55 - else: - break - v = v * 16 + t.CUInt64T(d) - p = p + 1 - g += 1 - return v - - def _MlirFloatLiteral(val: str, mt: str) -> str: - """浮点常量文本 → MLIR 十进制科学计数法文本(f16/f128 不支持)""" + """浮点常量文本 → MLIR 浮点字面量文本 + + MLIR 的浮点字面量支持两种形态(Builtin Dialect「FloatAttr」语法: + `float-literal (':' float-type)?` | `hexadecimal-literal ':' float-type`): + - 十进制浮点字面量(如 `3.14 : f64`); + - **十六进制位模式**(如 `0x40091EB851EB851F : f64`,按底层二进制位解释)。 + + 故 ConstFloat 给出的 `0x…` 位模式**原样直通**:位模式无精度损失。 + 此前把它转成 `%e`(默认 7 位有效数字)会截断 + (3.141592653589793 → 3.141593e+00),与 __values.vp 选位模式的初衷相悖。 + f16/f128 仍响亮报错:ConstFloat 只产出 64 位位模式,宽度与这两种类型不符。 + """ if val[0] == '0' and (val[1] == 'x' or val[1] == 'X'): - bits: t.CUInt64T = _MlirParseHexU64(val) - buf: str = _MLIR_Pool.alloc(64) - if buf is None: - MlirFail("MLIR 渲染: 浮点常量缓冲分配失败") - if mt[1] == '3' and mt[2] == '2': - f32v: t.CFloat = 0.0 - c.DerefAs((rawptr[t.CUInt32T])(c.Addr(f32v)), t.CUInt32T(bits)) - dv32: t.CDouble = t.CDouble(f32v) - viperlib.snprintf(buf, 64, "%e", dv32) - return buf - if mt[1] == '6' and mt[2] == '4': - f64v: t.CDouble = 0.0 - c.DerefAs((rawptr[t.CUInt64T])(c.Addr(f64v)), bits) - viperlib.snprintf(buf, 64, "%e", f64v) - return buf - MlirFail("MLIR 渲染: v1 不支持 f16/f128 十六进制浮点常量物化") + if string.strcmp(mt, "f32") == 0 or string.strcmp(mt, "f64") == 0: + return val + MlirFail("MLIR 渲染: v1 不支持 f16/f128 十六进制浮点常量物化(ConstFloat 只产出 64 位位模式)") # 已是十进制文本:原样使用 return val