- 现场二分定位:float(-10.0) / -float(10.0) 走「按目标类型直出 f32 常量」后,
MLIR 渲染阶段报 float 位模式位宽不匹配(VKernel 整个编不过);同一份 gfx.vp
只把负号字面量换成正号就渲染通过,故该路径回退为改动前行为(按操作数自身类型
出常量,f64 常量 + 使用处 fptrunc)。
- 保留两条已验证有效的修复:
1) 正号浮点字面量在 f32 目标下直接物化 f32 常量(translate_constant);
2) CDefine 记宽度种类(1=f64 / 2=f32),define PI: float = ... 的使用处直出 f32
常量(含 -PI —— 折叠按操作数类型出常量,操作数已是 f32,故仍是 f32)。
- define 常量补 ': int' 注解:无注解 define 按值的最小可存宽度物化(1/2 -> i8),
直接当实参传给 list[int].append(x: int) 会落成 i8 != i32 被 mlir-opt 拦下
(自举编译 TypeGenCDef 时必现)。
83 lines
5.8 KiB
Plaintext
83 lines
5.8 KiB
Plaintext
import t, c
|
|
from stdint import *
|
|
import ast
|
|
import memhub
|
|
import mlirlite
|
|
import lib.core.Gen.Translator as HT
|
|
import lib.core.Gen.Expr.ExprGenBase as ExprGenBase
|
|
|
|
|
|
# docstring registry capacities (__doc__ magic attribute support).
|
|
# DOC_MAX: max entries; DOC_KEY_SZ: key "{module_sha1}.{symbol}" width; DOC_VAL_SZ: content width.
|
|
define DOC_MAX = 512
|
|
define DOC_KEY_SZ = 192
|
|
define DOC_VAL_SZ = 4096
|
|
|
|
# f-string translation constants (aligned with TPC HandlesExprFormat).
|
|
# FSTR_BUF_SIZE: runtime stack buffer; FSTR_SPEC_MAX: format_spec parse width; FSTR_FMT_MAX: printf format width.
|
|
define FSTR_BUF_SIZE = 1024
|
|
define FSTR_SPEC_MAX = 64
|
|
define FSTR_FMT_MAX = 64
|
|
|
|
|
|
# ExprGenMixin - expression handling mixin (objectified P3).
|
|
|
|
|
|
# ExprGenMixin - expressions / constants / subscripts / attributes / operators.
|
|
novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
|
|
"""Expression-handling mixin (pure methods, no state fields)."""
|
|
|
|
# Translate a value expression (RHS dispatch) - module-level version.
|
|
def translate_value(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr = None, func_count: int = 0, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*:
|
|
"""Translate a value expression to an LLVM Value (depth-guard wrapper; see _translate_value_impl).
|
|
target_ty = assignment/parameter type context; use_ctx = real call site for CDefine width checks."""
|
|
if trans is not None:
|
|
if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "expression translation nested too deep (suspected AST self-reference cycle or translation bug)", "RecursionError")
|
|
trans.TranslateDepth += 1
|
|
rv: mlirlite.Value* = self._translate_value_impl(builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty, use_ctx)
|
|
if trans is not None: trans.TranslateDepth -= 1
|
|
return rv
|
|
|
|
def _translate_value_impl(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr = None, func_count: int = 0, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*:
|
|
"""Translate a value expression to an LLVM Value."""
|
|
if node is None: return None
|
|
k: int = node.kind()
|
|
if k == ast.ASTKind.Constant:
|
|
rv: mlirlite.Value* = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans, target_ty)
|
|
return rv
|
|
elif k == ast.ASTKind.Name: return self.Gen.ExprGenName.translate_name_value(builder, pool, node, trans, target_ty, use_ctx)
|
|
elif k == ast.ASTKind.BinOp: return self.Gen.ExprGenOps.translate_binop(pool, builder, mod, node, trans, target_ty)
|
|
elif k == ast.ASTKind.Call: return self.Gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
|
|
# 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.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)
|
|
elif k == ast.ASTKind.List: return self.Gen.ExprGenConst.translate_list_literal(builder, pool, mod, node, None, trans)
|
|
elif k == ast.ASTKind.IfExp: return self.Gen.ExprGenOps.translate_ifexp(builder, pool, mod, node, trans)
|
|
elif k == ast.ASTKind.Lambda: return self.Gen.FuncGen.translate_lambda(builder, pool, mod, node, trans)
|
|
elif k == ast.ASTKind.JoinedStr: return self.Gen.ExprGenFstr.translate_joined_str(builder, pool, mod, node, trans)
|
|
elif k == ast.ASTKind.FormattedValue: return self.Gen.ExprGenFstr.translate_formatted_value(builder, pool, mod, node, trans)
|
|
elif k == ast.ASTKind.Await:
|
|
# Coroutine await (VPC-M1): inline-translate when the await target is an async call.
|
|
# Returns the child coroutine's i32 ret; top-level await is handled by AsyncGen.
|
|
aw: ast.Await* = ast.Await*(node)
|
|
if aw is not None and aw.value is not None and aw.value.kind() == ast.ASTKind.Call:
|
|
aw_cl: ast.Call* = ast.Call*(aw.value)
|
|
if aw_cl.func is not None and aw_cl.func.kind() == ast.ASTKind.Name:
|
|
aw_nm: ast.Name* = ast.Name*(aw_cl.func)
|
|
if aw_nm.id is not None and trans is not None:
|
|
if self.Gen.AsyncGen.is_async_func(trans, aw_nm.id) != 0: return self.Gen.AsyncGen._emit_await(builder, pool, mod, trans, aw, aw_nm.id)
|
|
return None
|
|
elif k == ast.ASTKind.Starred:
|
|
# *x in a value context: the parser tags '*' as Starred, but Viper has no unpacking.
|
|
# Treat it as C unary deref (*ptr -> load pointee) by building a Deref UnaryOp.
|
|
st: ast.Starred* = ast.Starred*(node)
|
|
if st is None or st.value is None: return None
|
|
deref_node: ast.AST* = ast.UnaryOp(pool, ast.OpKind.Deref, st.value)
|
|
if deref_node is None: return None
|
|
return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, deref_node, trans)
|
|
return None
|