fix(mlir): 浮点常量位模式原样直通,消除 %e 截断精度

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 打印阶段转换说明同步
This commit is contained in:
TermiNexus committed 2026-10-03 20:35:37 +08:00
1 parent 751e7e7ef7
commit f813c0543b
2 files changed
+17 -43

No files matched your search

+2 -2
View File
@@ -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) |
+15 -41
View File
@@ -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