fix(codegen): zero-extend unsigned 16-bit widening in every coercion path
A uint16 value that is widened to int/uint32/uint64 must be zero-extended (movzwl), and an int16 value must be sign-extended (movswl). coerce_to_type picks the direction from the source AST node's declared signedness, which requires the translator; several call sites omitted it and therefore fell back to sext, so a big-endian uint16 such as 0xDCBC became 0xFFFF...DCBC (numGlyphs 56508 read as -9028 and every glyph range collapsed to zero). - pass trans at the assignment, annotated-assignment, augmented-assignment, global-array initializer, index, element-store, constructor-argument, conditional-expression and return coercion sites - printf argument promotion now receives the argument expression and trans, so uint16/uint8 promote with zext like any other widening - print selects the format token and extension from the source signedness (%u/%llu + zext for unsigned, %d/%lld + sext for signed) instead of a hardcoded %d + sext for 8/16-bit values
This commit is contained in:
1 parent
1adc61e3c2
commit
19f9c53a5f
10 files changed
+74
-58
No files matched your search
@@ -1947,7 +1947,7 @@ novirtual class AssignGenMixin:
|
||||
bp_s: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, array_alloca, bidx_s)
|
||||
if bp_s is None: break
|
||||
bvv: mlirlite.Value* = mlirlite.const_int32(pool, sv_s[bi_s])
|
||||
bsv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, bvv, elem_ty, e0_s)
|
||||
bsv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, bvv, elem_ty, e0_s, trans)
|
||||
mlirlite.build_store(builder, bsv, bp_s)
|
||||
return 0
|
||||
|
||||
@@ -1999,7 +1999,7 @@ novirtual class AssignGenMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(elem_node, "global array initializer element translation failed", "TypeError")
|
||||
# Type coercion (e.g. i32 -> i8); Pointee is statically i64 so compare with != 0
|
||||
store_val: mlirlite.Value* = elem_val
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, elem_val, elem_ptr.Ty.Pointee, elem_node)
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, elem_val, elem_ptr.Ty.Pointee, elem_node, trans)
|
||||
# BigEndian array: store each element byte-swapped (pairs the un-swap on element read).
|
||||
store_val = self.Gen.ExprGenBase.apply_byte_order_bswap(pool, builder, store_val, byte_order)
|
||||
mlirlite.build_store(builder, store_val, elem_ptr)
|
||||
@@ -2039,8 +2039,8 @@ novirtual class AssignGenMixin:
|
||||
target_float_ty: mlirlite.LLVMType* = mlirlite.Double(pool)
|
||||
if target_fbits == 32: target_float_ty = mlirlite.Float(pool)
|
||||
# Coerce both operands to the target float type
|
||||
lhs = self.Gen.ExprGenBase.coerce_to_type(builder, lhs, target_float_ty, node)
|
||||
rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, target_float_ty, node)
|
||||
lhs = self.Gen.ExprGenBase.coerce_to_type(builder, lhs, target_float_ty, node, trans)
|
||||
rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, target_float_ty, node, trans)
|
||||
if op == ast.OpKind.Add: return mlirlite.build_fadd(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Sub: return mlirlite.build_fsub(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mult: return mlirlite.build_fmul(builder, lhs, rhs)
|
||||
@@ -2232,7 +2232,7 @@ novirtual class AssignGenMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(target, f"attribute binary op failed op={aug.op}", "TypeError")
|
||||
|
||||
# 5. Coerce the type and store
|
||||
result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node)
|
||||
result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node, trans)
|
||||
if result is None:
|
||||
# fail-fast: type coercion failed
|
||||
self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError")
|
||||
@@ -2307,7 +2307,7 @@ novirtual class AssignGenMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(target, f"subscript binary op failed op={aug.op}", "TypeError")
|
||||
|
||||
# 5. Coerce the type and store
|
||||
result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node)
|
||||
result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node, trans)
|
||||
if result is None:
|
||||
# fail-fast: type coercion failed
|
||||
self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError")
|
||||
@@ -2455,7 +2455,7 @@ novirtual class AssignGenMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(target, f"applying binary op to variable '{nm.id}' failed op={aug.op}", "TypeError")
|
||||
|
||||
# 5. Store the result
|
||||
result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node)
|
||||
result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node, trans)
|
||||
if result is None:
|
||||
# fail-fast: type coercion failed
|
||||
self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError")
|
||||
@@ -2919,7 +2919,7 @@ novirtual class AssignGenMixin:
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
self.Gen.ExprGenBase.fail_if_str_annot_ast_agg_ptr(rhs_val, aa.annotation, node)
|
||||
rhs_coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, nl_target_ty, node)
|
||||
rhs_coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, nl_target_ty, node, trans)
|
||||
mlirlite.build_store(builder, rhs_coerced, nl_ptr)
|
||||
# Clear the assignment context (all four branches must stay in sync)
|
||||
trans.CurAssignAnnot = None
|
||||
@@ -2970,7 +2970,7 @@ novirtual class AssignGenMixin:
|
||||
if target_ty_mg is not None:
|
||||
# str/bytes is not a generic pointer: bare str/bytes annotation with an aggregate-pointer RHS
|
||||
self.Gen.ExprGenBase.fail_if_str_annot_ast_agg_ptr(rhs_val_mg, aa.annotation, node)
|
||||
rhs_val_mg = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val_mg, target_ty_mg, node)
|
||||
rhs_val_mg = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val_mg, target_ty_mg, node, trans)
|
||||
# t.VolatileT module-level global: the initializing store carries volatile
|
||||
vol_mga: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
|
||||
mlirlite.build_store(builder, rhs_val_mg, mod_glob, vol_mga)
|
||||
@@ -3689,7 +3689,7 @@ novirtual class AssignGenMixin:
|
||||
case _:
|
||||
elem_ptr_gen = mlirlite.build_gep(builder, elem_gen, obj_val_gen, key_val_gen)
|
||||
if elem_ptr_gen is not None and elem_ptr_gen.Ty is not None:
|
||||
if elem_ptr_gen.Ty.Pointee != 0: store_val_gen = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, elem_ptr_gen.Ty.Pointee, node)
|
||||
if elem_ptr_gen.Ty.Pointee != 0: store_val_gen = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, elem_ptr_gen.Ty.Pointee, node, trans)
|
||||
mlirlite.build_store(builder, store_val_gen, elem_ptr_gen)
|
||||
setitem_done = 1
|
||||
if setitem_done == 0: self.Gen.TypeGenErr.fatal_error(target, "subscript ptr is None")
|
||||
@@ -3768,7 +3768,7 @@ novirtual class AssignGenMixin:
|
||||
if fd_fe_w is not None and fd_fe_w.Ty is not None:
|
||||
fd_fp_w: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty_w, fd_fe_w.Ty, fd_meta_vw, fd_fe_w.Index)
|
||||
if fd_fp_w is not None:
|
||||
sv_fd: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, fd_fe_w.Ty, node)
|
||||
sv_fd: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, fd_fe_w.Ty, node, trans)
|
||||
mlirlite.build_store(builder, sv_fd, fd_fp_w)
|
||||
continue
|
||||
# VTABLE write: obj.method = func writes the vtable slot instead of a field
|
||||
|
||||
@@ -526,7 +526,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
if pc_param is not None:
|
||||
pty_pc: mlirlite.LLVMType* = mlirlite.param_get_ty(pc_param)
|
||||
if pty_pc is not None:
|
||||
c_pc: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pc_node, pty_pc, pc_arg_node)
|
||||
c_pc: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pc_node, pty_pc, pc_arg_node, trans)
|
||||
if c_pc is not None: coerced_pc = c_pc
|
||||
pc_param = mlirlite.param_get_next(pc_param)
|
||||
coerced_pc.Next = None
|
||||
@@ -1429,7 +1429,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
g_idx_node: ast.AST* = cargs.get(0)
|
||||
g_idx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, g_idx_node, None, 0, trans)
|
||||
if g_data is not None and g_esize is not None and g_idx_val is not None:
|
||||
g_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, g_idx_val, i64_ty, g_idx_node)
|
||||
g_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, g_idx_val, i64_ty, g_idx_node, trans)
|
||||
g_offset: mlirlite.Value* = mlirlite.build_mul(builder, g_idx_i64, g_esize)
|
||||
g_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, g_data, g_offset)
|
||||
if g_addr is not None:
|
||||
@@ -1450,11 +1450,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
s_idx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, s_idx_node, None, 0, trans)
|
||||
s_val_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, s_val_node, None, 0, trans)
|
||||
if s_data is not None and s_esize is not None and s_idx_val is not None and s_val_val is not None:
|
||||
s_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_idx_val, i64_ty, s_idx_node)
|
||||
s_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_idx_val, i64_ty, s_idx_node, trans)
|
||||
s_offset: mlirlite.Value* = mlirlite.build_mul(builder, s_idx_i64, s_esize)
|
||||
s_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s_data, s_offset)
|
||||
if s_addr is not None:
|
||||
s_val_elem: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_val_val, lm_elem_ty, s_val_node)
|
||||
s_val_elem: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_val_val, lm_elem_ty, s_val_node, trans)
|
||||
s_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, s_addr, mlirlite.Ptr(pool, lm_elem_ty))
|
||||
if s_ep is not None:
|
||||
mlirlite.build_store(builder, s_val_elem, s_ep)
|
||||
@@ -1698,7 +1698,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
# before the coercion below (cross-module vpi addressing is applied in bulk for the whole chain).
|
||||
arg_val_sp: mlirlite.Value* = self.Gen.CallGenBase.translate_call_arg(builder, pool, mod, trans, call_name, int(ai_sp) + 1, arg_node_sp, pty_sp, None)
|
||||
if arg_val_sp is None: continue
|
||||
if pty_sp is not None: arg_val_sp = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val_sp, pty_sp, arg_node_sp)
|
||||
if pty_sp is not None: arg_val_sp = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val_sp, pty_sp, arg_node_sp, trans)
|
||||
else:
|
||||
# found_func=None: decay array args to element pointers per C semantics
|
||||
# (consistent with _translate_method_call).
|
||||
|
||||
@@ -103,7 +103,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
# fail-fast: GEP failed (struct_ty and fe.Ty mismatch)
|
||||
VLogger.error(f"Field GEP failed, type mismatch: {class_name}", "HandlesExprCall")
|
||||
continue
|
||||
default_val = self.Gen.ExprGenBase.coerce_to_type(builder, default_val, fe.Ty, fe.DefaultVal)
|
||||
default_val = self.Gen.ExprGenBase.coerce_to_type(builder, default_val, fe.Ty, fe.DefaultVal, trans)
|
||||
mlirlite.build_store(builder, default_val, field_ptr, is_volatile)
|
||||
# _translate_struct_ctor - struct constructor Point(10, 20): alloca, zeroinit, per-field
|
||||
# GEP + store (or __new__/__before_init__/__init__ for OOP structs), then load.
|
||||
@@ -288,7 +288,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
# fail-fast: GEP failed (struct_ty and fe.Ty mismatch)
|
||||
VLogger.error(f"Constructor field GEP failed: {class_name}", "HandlesExprCall")
|
||||
continue
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg, trans)
|
||||
mlirlite.build_store(builder, arg_val, field_ptr, is_volatile)
|
||||
|
||||
# return a pointer (not a struct value); coerce_to_type decides whether to load on assign
|
||||
@@ -327,7 +327,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
VLogger.error(f"Constructor field GEP failed: {class_name}", "HandlesExprCall")
|
||||
continue
|
||||
# coerce and store
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg, trans)
|
||||
mlirlite.build_store(builder, arg_val, field_ptr, is_volatile)
|
||||
|
||||
# return a pointer (not a struct value); coerce_to_type decides whether to load on assign
|
||||
@@ -398,7 +398,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if casted_arg is None: continue
|
||||
arg_val = casted_arg
|
||||
# coerce and store (the payload slot may be i32 or i64; coerce by field type)
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pfe.Ty, arg)
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pfe.Ty, arg, trans)
|
||||
mlirlite.build_store(builder, arg_val, payload_ptr, is_volatile)
|
||||
|
||||
# return a pointer (same as _translate_struct_ctor; coerce_to_type decides whether to load)
|
||||
@@ -813,7 +813,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if arg_val is None: continue
|
||||
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
|
||||
if field_ptr is None: continue
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg)
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg, trans)
|
||||
mlirlite.build_store(builder, arg_val, field_ptr, is_volatile)
|
||||
|
||||
# Handle keyword args (lookup by field name).
|
||||
@@ -832,7 +832,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if kw_val is None: continue
|
||||
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index)
|
||||
if field_ptr is None: continue
|
||||
kw_val = self.Gen.ExprGenBase.coerce_to_type(builder, kw_val, fe.Ty, kw.value)
|
||||
kw_val = self.Gen.ExprGenBase.coerce_to_type(builder, kw_val, fe.Ty, kw.value, trans)
|
||||
mlirlite.build_store(builder, kw_val, field_ptr, is_volatile)
|
||||
|
||||
# return a pointer (not a struct value); coerce_to_type decides whether to load on assign
|
||||
@@ -1286,7 +1286,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if av_sf is None: continue
|
||||
fp_sf: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe_sf.Ty, storage_ptr, fe_sf.Index)
|
||||
if fp_sf is None: continue
|
||||
av_sf = self.Gen.ExprGenBase.coerce_to_type(builder, av_sf, fe_sf.Ty, arg_sf)
|
||||
av_sf = self.Gen.ExprGenBase.coerce_to_type(builder, av_sf, fe_sf.Ty, arg_sf, trans)
|
||||
mlirlite.build_store(builder, av_sf, fp_sf, gc_volatile)
|
||||
|
||||
return storage_ptr
|
||||
@@ -1313,7 +1313,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
g_idx_node: ast.AST* = cargs.get(0)
|
||||
g_idx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, g_idx_node, None, 0, trans)
|
||||
if g_data is not None and g_esize is not None and g_idx_val is not None:
|
||||
g_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, g_idx_val, i64_ty, g_idx_node)
|
||||
g_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, g_idx_val, i64_ty, g_idx_node, trans)
|
||||
g_offset: mlirlite.Value* = mlirlite.build_mul(builder, g_idx_i64, g_esize)
|
||||
g_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, g_data, g_offset)
|
||||
if g_addr is not None:
|
||||
@@ -1334,11 +1334,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
s_idx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, s_idx_node, None, 0, trans)
|
||||
s_val_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, s_val_node, None, 0, trans)
|
||||
if s_data is not None and s_esize is not None and s_idx_val is not None and s_val_val is not None:
|
||||
s_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_idx_val, i64_ty, s_idx_node)
|
||||
s_idx_i64: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_idx_val, i64_ty, s_idx_node, trans)
|
||||
s_offset: mlirlite.Value* = mlirlite.build_mul(builder, s_idx_i64, s_esize)
|
||||
s_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s_data, s_offset)
|
||||
if s_addr is not None:
|
||||
s_val_elem: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_val_val, lm_elem_ty, s_val_node)
|
||||
s_val_elem: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, s_val_val, lm_elem_ty, s_val_node, trans)
|
||||
s_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, s_addr, mlirlite.Ptr(pool, lm_elem_ty))
|
||||
if s_ep is not None:
|
||||
mlirlite.build_store(builder, s_val_elem, s_ep)
|
||||
|
||||
@@ -700,9 +700,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
# pure_str value: printf consumes the payload, not the struct.
|
||||
ps_pv: mlirlite.Value* = self.Gen.ExprGenBase._pure_str_payload(builder, pool, arg_val)
|
||||
if ps_pv is not None: arg_val = ps_pv
|
||||
# C ABI integer promotion: i8/i16 -> i32 (required by printf varargs)
|
||||
# C ABI integer promotion: i8/i16 -> i32 (required by printf varargs).
|
||||
# Pass the argument expression and trans so uint16/uint8 zext (movzwl) instead
|
||||
# of the default sext: the source signedness comes from the AST annotation.
|
||||
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty)
|
||||
if arg_bits != 0 and arg_bits < 32: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, i32_ty, arg)
|
||||
if arg_bits != 0 and arg_bits < 32: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, i32_ty, arg, trans)
|
||||
# C ABI float promotion: float -> double (required by printf varargs)
|
||||
arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(arg_val.Ty)
|
||||
if arg_fbits != 0 and arg_fbits < 64:
|
||||
@@ -798,17 +800,31 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
token = "0x%llx"
|
||||
arg_val = mlirlite.build_ptrtoint(builder, arg_val, i64_ty)
|
||||
elif arg_bits != 0:
|
||||
# Format/extension follow the source signedness: a uint16/uint8 printed with %d
|
||||
# plus sext shows negative values (-9028 for 0xDCBC), so unsigned sources use
|
||||
# %u/%llu and zext.
|
||||
is_u_pr: int = 0
|
||||
if arg is not None and trans is not None:
|
||||
if self.Gen.ExprGenOps._node_type_unsigned(pool, arg, trans) != 0: is_u_pr = 1
|
||||
if arg_bits == 1:
|
||||
token = "%d"
|
||||
arg_val = mlirlite.build_zext(builder, arg_val, i32_ty)
|
||||
elif arg_bits == 8:
|
||||
token = "%d"
|
||||
arg_val = mlirlite.build_sext(builder, arg_val, i32_ty)
|
||||
if is_u_pr != 0:
|
||||
token = "%u"
|
||||
arg_val = mlirlite.build_zext(builder, arg_val, i32_ty)
|
||||
else:
|
||||
token = "%d"
|
||||
arg_val = mlirlite.build_sext(builder, arg_val, i32_ty)
|
||||
elif arg_bits == 16:
|
||||
token = "%d"
|
||||
arg_val = mlirlite.build_sext(builder, arg_val, i32_ty)
|
||||
elif arg_bits == 32: token = "%d"
|
||||
else: token = "%lld"
|
||||
if is_u_pr != 0:
|
||||
token = "%u"
|
||||
arg_val = mlirlite.build_zext(builder, arg_val, i32_ty)
|
||||
else:
|
||||
token = "%d"
|
||||
arg_val = mlirlite.build_sext(builder, arg_val, i32_ty)
|
||||
elif arg_bits == 32: token = "%u" if is_u_pr != 0 else "%d"
|
||||
else: token = "%llu" if is_u_pr != 0 else "%lld"
|
||||
elif arg_fbits != 0:
|
||||
token = "%f"
|
||||
if arg_fbits < 64: arg_val = mlirlite.build_fpext(builder, arg_val, dbl_ty)
|
||||
|
||||
@@ -1159,7 +1159,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
# Known vararg C functions (snprintf/sprintf/vsprintf): coerce fixed args by signature
|
||||
# (C ABI requires i64 size), else call/declare mismatch and Win64 leaves stack garbage in the high 4 bytes.
|
||||
kvc_ty: mlirlite.LLVMType* = self.Gen.CallGenVa._get_known_vararg_cfunc_param_ty(pool, func_name, ai)
|
||||
if kvc_ty is not None: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, kvc_ty, arg)
|
||||
if kvc_ty is not None: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, kvc_ty, arg, trans)
|
||||
# Prefer the definition-side vpi param annotation for module-qualified calls: the
|
||||
# whitelist treats all non-pointer Win32 args as i64, but ULONG is now i32 (call/declare mismatch).
|
||||
ext_param_ty: mlirlite.LLVMType* = None
|
||||
@@ -1188,10 +1188,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
# pointer targets through coerce_to_type too: it materializes the compile-time constant
|
||||
# 0 as a null pointer and fails fast on any other implicit int<->ptr conversion.
|
||||
if self.Gen.ExprGenBase.is_ptr_type(ext_param_ty) != 0:
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg)
|
||||
arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg, trans)
|
||||
elif val_bits_ap != 0 and tgt_bits_ap != 0 and val_bits_ap != tgt_bits_ap:
|
||||
if val_bits_ap == 1 and val_bits_ap < tgt_bits_ap: arg_val = mlirlite.build_zext(builder, arg_val, ext_param_ty)
|
||||
else: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg)
|
||||
else: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg, trans)
|
||||
elif found_func is not None:
|
||||
# found_func present: coerce to the param type (e.g. stdlib.malloc(size: sizet)); a
|
||||
# DefineT/i32 literal passed to an i64 param would otherwise leave call(i32) vs define(i64) mismatched.
|
||||
|
||||
@@ -105,7 +105,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
|
||||
while cur_arg_pc is not None and cur_param_pc is not None:
|
||||
param_ty_pc: mlirlite.LLVMType* = mlirlite.param_get_ty(cur_param_pc)
|
||||
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
|
||||
coerced_pc: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, cur_arg_pc, param_ty_pc)
|
||||
coerced_pc: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, cur_arg_pc, param_ty_pc, None, trans)
|
||||
if coerced_pc is not None and coerced_pc != cur_arg_pc:
|
||||
# Keep the list intact: the new Value inherits the node's Next; predecessor points to it
|
||||
mlirlite.value_set_next(coerced_pc, cur_arg_pc.Next)
|
||||
|
||||
@@ -1200,7 +1200,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index)
|
||||
if field_ptr is None: continue
|
||||
# Coerce and store.
|
||||
default_val = self.Gen.ExprGenBase.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal)
|
||||
default_val = self.Gen.ExprGenBase.coerce_to_type(func_builder, default_val, fe.Ty, fe.DefaultVal, trans)
|
||||
mlirlite.build_store(func_builder, default_val, field_ptr)
|
||||
|
||||
# 3. ret void
|
||||
|
||||
@@ -81,30 +81,30 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
# Ptr.bits == 0 skips the next three branches. body_val.Ty becomes phi_ty and orelse_val is coerced to it.
|
||||
if body_is_ptr != orelse_is_ptr:
|
||||
mlirlite.position_at_end(builder, else_blk_for_phi)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node, trans)
|
||||
elif body_bits > orelse_bits and orelse_bits > 0:
|
||||
# 宽侧是「能无损落进窄侧」的编译期常量时,把**常量**降到窄侧(与二元运算同一口径),
|
||||
# 避免 `tab[..] if c else '='`(i8 元素 vs i32 字符字面量)被抬成 i32、再赋回 i8 时误报窄化。
|
||||
if self._const_fits_int_type(body_val, orelse_val.Ty) != 0:
|
||||
mlirlite.position_at_end(builder, then_blk_for_phi)
|
||||
body_val = self.coerce_to_type(builder, body_val, orelse_val.Ty, node)
|
||||
body_val = self.coerce_to_type(builder, body_val, orelse_val.Ty, node, trans)
|
||||
else:
|
||||
mlirlite.position_at_end(builder, else_blk_for_phi)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node, trans)
|
||||
elif orelse_bits > body_bits and body_bits > 0:
|
||||
# 同口径:宽侧(orelse)是能落进窄侧的常量时,把它降下来(在 else 块内完成强转)
|
||||
if self._const_fits_int_type(orelse_val, body_val.Ty) != 0:
|
||||
mlirlite.position_at_end(builder, else_blk_for_phi)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node, trans)
|
||||
else:
|
||||
mlirlite.position_at_end(builder, then_blk_for_phi)
|
||||
body_val = self.coerce_to_type(builder, body_val, orelse_val.Ty, node)
|
||||
body_val = self.coerce_to_type(builder, body_val, orelse_val.Ty, node, trans)
|
||||
elif body_bits == orelse_bits and body_bits > 0:
|
||||
# Same bits but different types (e.g. i64 vs Ptr): null cannot be used in an i64 PHI.
|
||||
# This branch should not trigger (case 0 covers it); kept as a defensive guard.
|
||||
if self.is_ptr_type(body_val.Ty) != self.is_ptr_type(orelse_val.Ty):
|
||||
mlirlite.position_at_end(builder, else_blk_for_phi)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node)
|
||||
orelse_val = self.coerce_to_type(builder, orelse_val, body_val.Ty, node, trans)
|
||||
|
||||
# Now br to merge from the then/else blocks (after type coercion)
|
||||
mlirlite.position_at_end(builder, then_blk_for_phi)
|
||||
@@ -1506,8 +1506,8 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
target_float_ty: mlirlite.LLVMType* = mlirlite.Double(pool)
|
||||
if target_fbits == 32: target_float_ty = mlirlite.Float(pool)
|
||||
# Convert both operands to the target float type (int->float via si2fp, float->float via fpext/fptrunc)
|
||||
lhs = self.coerce_to_type(builder, lhs, target_float_ty, node)
|
||||
rhs = self.coerce_to_type(builder, rhs, target_float_ty, node)
|
||||
lhs = self.coerce_to_type(builder, lhs, target_float_ty, node, trans)
|
||||
rhs = self.coerce_to_type(builder, rhs, target_float_ty, node, trans)
|
||||
if op == ast.OpKind.Add: return mlirlite.build_fadd(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Sub: return mlirlite.build_fsub(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mult: return mlirlite.build_fmul(builder, lhs, rhs)
|
||||
|
||||
@@ -645,7 +645,7 @@ novirtual class StmtGenCifMixin:
|
||||
match ret_ty_rt:
|
||||
case mlirlite.LLVMType.Ptr(r_inner):
|
||||
ret_pointee = r_inner
|
||||
if val_pointee is not None and ret_pointee is not None and uint64(val_pointee) != uint64(ret_pointee): val = self.Gen.ExprGenBase.coerce_to_type(builder, val, ret_ty_rt, node)
|
||||
if val_pointee is not None and ret_pointee is not None and uint64(val_pointee) != uint64(ret_pointee): val = self.Gen.ExprGenBase.coerce_to_type(builder, val, ret_ty_rt, node, trans)
|
||||
elif val_bits != 0 and ret_bits != 0 and val_bits != ret_bits:
|
||||
if val_bits == 1 and val_bits < ret_bits: val = mlirlite.build_zext(builder, val, ret_ty_rt)
|
||||
else:
|
||||
@@ -1441,9 +1441,9 @@ novirtual class StmtGenCifMixin:
|
||||
r1_start = mlirlite.const_int(pool, r1_bits, 0)
|
||||
r1_step = mlirlite.const_int(pool, r1_bits, 1)
|
||||
r1_stop = mlirlite.const_int(pool, r1_bits, 0)
|
||||
if a1 is not None: r1_stop = self.Gen.ExprGenBase.coerce_to_type(builder, a1, r1_wty, cargs1.get(0))
|
||||
if b1 is not None: r1_start = self.Gen.ExprGenBase.coerce_to_type(builder, b1, r1_wty, cargs1.get(1))
|
||||
if c1 is not None: r1_step = self.Gen.ExprGenBase.coerce_to_type(builder, c1, r1_wty, cargs1.get(2))
|
||||
if a1 is not None: r1_stop = self.Gen.ExprGenBase.coerce_to_type(builder, a1, r1_wty, cargs1.get(0), trans)
|
||||
if b1 is not None: r1_start = self.Gen.ExprGenBase.coerce_to_type(builder, b1, r1_wty, cargs1.get(1), trans)
|
||||
if c1 is not None: r1_step = self.Gen.ExprGenBase.coerce_to_type(builder, c1, r1_wty, cargs1.get(2), trans)
|
||||
elif kind1 == GenTypes.SEQ_KIND_STR:
|
||||
elem1_ty = i8_ty
|
||||
s1_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src1, trans._funcs, trans._func_count, trans)
|
||||
@@ -1504,9 +1504,9 @@ novirtual class StmtGenCifMixin:
|
||||
r2_start = mlirlite.const_int(pool, r2_bits, 0)
|
||||
r2_step = mlirlite.const_int(pool, r2_bits, 1)
|
||||
r2_stop = mlirlite.const_int(pool, r2_bits, 0)
|
||||
if a2 is not None: r2_stop = self.Gen.ExprGenBase.coerce_to_type(builder, a2, r2_wty, cargs2.get(0))
|
||||
if b2 is not None: r2_start = self.Gen.ExprGenBase.coerce_to_type(builder, b2, r2_wty, cargs2.get(1))
|
||||
if c2 is not None: r2_step = self.Gen.ExprGenBase.coerce_to_type(builder, c2, r2_wty, cargs2.get(2))
|
||||
if a2 is not None: r2_stop = self.Gen.ExprGenBase.coerce_to_type(builder, a2, r2_wty, cargs2.get(0), trans)
|
||||
if b2 is not None: r2_start = self.Gen.ExprGenBase.coerce_to_type(builder, b2, r2_wty, cargs2.get(1), trans)
|
||||
if c2 is not None: r2_step = self.Gen.ExprGenBase.coerce_to_type(builder, c2, r2_wty, cargs2.get(2), trans)
|
||||
elif kind2 == GenTypes.SEQ_KIND_STR:
|
||||
elem2_ty = i8_ty
|
||||
s2_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src2, trans._funcs, trans._func_count, trans)
|
||||
@@ -1618,11 +1618,11 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_store(builder, idx32, t1_alloca)
|
||||
if t2_alloca is not None and t2_alloca.Ty is not None and v1 is not None:
|
||||
t2_ty: mlirlite.LLVMType* = t2_alloca.Ty.Pointee
|
||||
v1c: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, v1, t2_ty, src1)
|
||||
v1c: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, v1, t2_ty, src1, trans)
|
||||
mlirlite.build_store(builder, v1c, t2_alloca)
|
||||
else:
|
||||
if v1 is not None:
|
||||
v1c: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, v1, t1_ty, src1)
|
||||
v1c: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, v1, t1_ty, src1, trans)
|
||||
mlirlite.build_store(builder, v1c, t1_alloca)
|
||||
# source-2 element → t2
|
||||
v2: mlirlite.Value* = None
|
||||
@@ -1640,7 +1640,7 @@ novirtual class StmtGenCifMixin:
|
||||
v2 = mlirlite.build_load(builder, i8_ptr_ty, addr2)
|
||||
if t2_alloca is not None and t2_alloca.Ty is not None and v2 is not None:
|
||||
t2_ty2: mlirlite.LLVMType* = t2_alloca.Ty.Pointee
|
||||
v2c: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, v2, t2_ty2, src2)
|
||||
v2c: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, v2, t2_ty2, src2, trans)
|
||||
mlirlite.build_store(builder, v2c, t2_alloca)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
@@ -1975,7 +1975,7 @@ novirtual class StmtGenCifMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an [INVALID OBJECT] AST element (vptr is 0): element {i} pointer is nonzero" f"(address {uint64(el_node)}) but the first word of its object (vtable pointer) is 0, element count {elts_count};" f"something upstream produced an [uninitialized vptr AST node] (typical source: a deep copy that moved fields but not the vptr), compilation aborted.", "ValueError")
|
||||
el_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, el_node, trans._funcs, trans._func_count, trans)
|
||||
if el_val is not None:
|
||||
el_val = self.Gen.ExprGenBase.coerce_to_type(builder, el_val, elem_ty, el_node)
|
||||
el_val = self.Gen.ExprGenBase.coerce_to_type(builder, el_val, elem_ty, el_node, trans)
|
||||
el_ptr: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, tmp_alloca, mlirlite.const_int32(pool, i))
|
||||
if el_ptr is not None: mlirlite.build_store(builder, el_val, el_ptr)
|
||||
i += 1
|
||||
|
||||
Reference in new issue
Block a user