fix(viperc): 恢复一元负号字面量按目标类型直出 f32(位宽根因已修,路径不再有风险)

背景:负号字面量(float(-10.0) / x: float = -3.5)此前回退过——当时 MLIR 渲染报
「f32 类型配 16 位文本」,原因是 mlirlite.ConstFloat 用 snprintf 打印位型时,
高位置位的 32 位值会被按符号扩展后的 64 位打印。该根因已在 includes/mlirlite 侧修死
(提交 8dbad70:十六进制位数只由 MlirTypeText(ty) 定,与 MLIR 渲染器同源,构造上一致),
故此路径恢复为「正确路径」:f32 目标下直接物化 f32 常量,去掉 f64 常量 + fptrunc 的绕行。

- ExprGenOps.translate_unaryop 增加 target_ty 形参:目标为 32 位浮点时折叠直接出 f32 常量;
- ExprGenMixin 把 target_ty 透传给 translate_unaryop。
This commit is contained in:
TermiNexus committed 2026-10-15 19:43:15 +08:00
1 parent 3e52baa209
commit 5ea0ce094e
2 files changed
+10 -7

No files matched your search

+1 -1
View File
@@ -51,7 +51,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
# M2.4 `new stack|heap|memgr(x) [slife|hlife] T(args)`:只换"取存储",其余复用构造序列
elif k == ast.ASTKind.New: return self.Gen.CallGenCtor._translate_new_expr(pool, builder, mod, ast.New*(node), trans)
elif k == ast.ASTKind.Compare: return self.Gen.ExprGenOps.translate_compare(builder, pool, mod, node, trans)
elif k == ast.ASTKind.UnaryOp: return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans)
elif k == ast.ASTKind.UnaryOp: return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans, target_ty)
elif k == ast.ASTKind.BoolOp: return self.Gen.ExprGenOps.translate_boolop(builder, pool, mod, node, funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Subscript: return self.Gen.ExprGenName.translate_subscript(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Attribute: return self.Gen.ExprGenAttr.translate_attribute(builder, pool, mod, node, trans)
+9 -6
View File
@@ -654,7 +654,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
return mlirlite.build_icmp(builder, predicate, lhs, rhs)
# translate_unaryop - UnaryOp(op, operand)
# ============================================================
def translate_unaryop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
def translate_unaryop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None) -> mlirlite.Value*:
"""Translate unary operations (-x, +x, not x, ~x)."""
uo: ast.UnaryOp* = ast.UnaryOp*(node)
if uo is None: return None
@@ -688,11 +688,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
operand_fbits: int = self.get_llvm_float_bits(operand.Ty)
if operand_fbits > 0:
# 编译期常量折叠:-c 直接产出常量并保持 IsConst
# 保持"按操作数自身类型出常量"(f64 常量 → 由使用处 coerce 出 fptrunc):
# 这里**不允许**改成按使用处目标类型直接出 f32 常量 —— 现场验证该路径产出的
# f32 负常量在 MLIR 渲染阶段被判定为位宽不匹配(`_MlirFloatLiteral`),
# 整个 VKernel 编不过;正号字面量那条路(ExprGenConst.translate_constant)不受影响。
if operand.IsConst == 1: return mlirlite.ConstFloat(pool, operand.Ty, -operand.FloatVal)
if operand.IsConst == 1:
# 目标类型是 32 位浮点(`float(-3.5)` / `x: float = -3.5`)→ 直接出 f32 常量,
# 不再"f64 常量 + fptrunc"(与 ExprGenConst.translate_constant 的浮点字面量同口径)。
# 位宽安全:ConstFloat 的十六进制位数只由 MlirTypeText(ty) 决定(与 MLIR 渲染器
# 取类型文本同一个函数),故不会再出现"f32 类型配 16 位文本"那类位宽错配。
if target_ty is not None and self.get_llvm_float_bits(target_ty) == 32:
return mlirlite.ConstFloat(pool, target_ty, -operand.FloatVal)
return mlirlite.ConstFloat(pool, operand.Ty, -operand.FloatVal)
return mlirlite.build_fneg(builder, operand)
# 编译期常量折叠:-c 直接产出常量(IsConst=1)。否则 `v: int8 = -50` 会被当成运行时 i32 值,
# 触发“隐式窄化禁止”,尽管其数值完全落在 i8 内(隐式窄化的“编译期常量”豁免失效)。