支持 tls 关键字,全面准备清退 t, c
This commit is contained in:
1 parent
6e17716a69
commit
3242560d02
74 files changed
+524
-576
No files matched your search
@@ -2,7 +2,6 @@ import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.Translator as HT
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -130,9 +129,9 @@ novirtual class CallGenBase:
|
||||
def _auto_addr_mode(self, name: str, idx: int) -> int:
|
||||
"""Return the value-reference mode for parameter idx of a callee symbol name (0 if none/unknown)."""
|
||||
if self.AutoAddrModes is None or name is None or idx < 0: return 0
|
||||
v: t.CPtr = self.AutoAddrModes.__getitem__(name)
|
||||
v: rawptr = self.AutoAddrModes.__getitem__(name)
|
||||
if v is None: return 0
|
||||
modes: str = t.CPtr(v)
|
||||
modes: str = rawptr(v)
|
||||
i: int = 0
|
||||
while i < idx and modes[i] != char(0): i += 1
|
||||
if i != idx: return 0
|
||||
@@ -1298,7 +1297,7 @@ novirtual class CallGenBase:
|
||||
if use_bare != 0: viperlib.snprintf(key_buf, key_len, "%s.%s", class_sha1, method_name)
|
||||
else:
|
||||
viperlib.snprintf(key_buf, key_len, "%s.%s.%s", class_sha1, class_name, method_name)
|
||||
v: t.CPtr = ht.__getitem__(key_buf)
|
||||
v: rawptr = ht.__getitem__(key_buf)
|
||||
stdlib.free(key_buf)
|
||||
if v is None: return None
|
||||
return rawptr(v)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -786,8 +785,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
string.memset(operands, 0, operand_size * ASM_MAX_OPERANDS)
|
||||
|
||||
# Clobber name array: 8 bytes/slot, capacity ASM_MAX_CLOBBERS, decoupled from
|
||||
# the operand limit; a single-level t.CPtr buffer with slots cast to str*.
|
||||
clobbers: t.CPtr = pool.alloc(8 * ASM_MAX_CLOBBERS)
|
||||
# the operand limit; a single-level rawptr buffer with slots cast to str*.
|
||||
clobbers: rawptr = pool.alloc(8 * ASM_MAX_CLOBBERS)
|
||||
if clobbers is None: return None
|
||||
string.memset(clobbers, 0, 8 * ASM_MAX_CLOBBERS)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -165,18 +164,18 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
# 跨模块:本文件指令表为空,改查对方模块 .vpi 的 esce=/escn=
|
||||
f_ci = self.Gen.CallGenBase.lookup_escape_dir_via_vpi(sha_ci, class_name, method_name, 0)
|
||||
n_ci = self.Gen.CallGenBase.lookup_escape_dir_via_vpi(sha_ci, class_name, method_name, 1)
|
||||
if f_ci != 0 or n_ci != 0: esc_mask_ci = (esc_mask_ci | f_ci) & (~n_ci)
|
||||
# 同命裁剪(构造器路径):被构造对象的生命期由**调用方**(CallGenCtor)算出并经
|
||||
# recv_life 传入 —— 这里只有 self_ptr(LLVM 值),拿不到 AST/生命期。
|
||||
# recv_life == -1 = 未知 → **不做裁剪**(与接这条之前的行为完全一致)。
|
||||
# 对象在本帧(裸 `T()` / `new stack` / `slife`)时,其余实参也都在本帧即可清位。
|
||||
if recv_life >= 0 and esc_mask_ci != 0:
|
||||
if recv_life == GenTypes.LIFE_FRAME or recv_life == GenTypes.LIFE_VALUE:
|
||||
hard_ci: int = GenApi.get_param_escapes_hard_method(pool, class_name, method_name)
|
||||
fld_ci: int = esc_mask_ci & (~hard_ci)
|
||||
if fld_ci != 0:
|
||||
can_ci2: sizet = len(arg_nodes)
|
||||
cl_ci: int = self.Gen.CallGen._FrameArgsEscapeClearsMethod(trans, None, arg_nodes, can_ci2, fld_ci)
|
||||
if f_ci != 0 or n_ci != 0: esc_mask_ci = (esc_mask_ci | f_ci) & (~n_ci)
|
||||
# 同命裁剪(构造器路径):被构造对象的生命期由**调用方**(CallGenCtor)算出并经
|
||||
# recv_life 传入 —— 这里只有 self_ptr(LLVM 值),拿不到 AST/生命期。
|
||||
# recv_life == -1 = 未知 → **不做裁剪**(与接这条之前的行为完全一致)。
|
||||
# 对象在本帧(裸 `T()` / `new stack` / `slife`)时,其余实参也都在本帧即可清位。
|
||||
if recv_life >= 0 and esc_mask_ci != 0:
|
||||
if recv_life == GenTypes.LIFE_FRAME or recv_life == GenTypes.LIFE_VALUE:
|
||||
hard_ci: int = GenApi.get_param_escapes_hard_method(pool, class_name, method_name)
|
||||
fld_ci: int = esc_mask_ci & (~hard_ci)
|
||||
if fld_ci != 0:
|
||||
can_ci2: sizet = len(arg_nodes)
|
||||
cl_ci: int = self.Gen.CallGen._FrameArgsEscapeClearsMethod(trans, None, arg_nodes, can_ci2, fld_ci)
|
||||
if cl_ci != 0: esc_mask_ci = esc_mask_ci & (~cl_ci)
|
||||
if esc_mask_ci != 0:
|
||||
dummy_ptr_ci: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
|
||||
@@ -343,7 +342,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
while tail is not None and mlirlite.value_get_next(tail) is not None: tail = mlirlite.value_get_next(tail)
|
||||
# Default-argument filling: if the call site supplies fewer args than the
|
||||
# definition, fill the missing ones (defined default, else zero).
|
||||
mdf_defaults: t.CPtr = None
|
||||
mdf_defaults: rawptr = None
|
||||
mdf_default_count: int = 0
|
||||
mdf_param_count: int = 0
|
||||
if trans is not None and trans._funcs is not None:
|
||||
@@ -555,17 +554,17 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
if uint64(self_ptr.Ty) != uint64(cmop_i8_ptr_ty): cmop_bar_ptr = mlirlite.build_bitcast(builder, self_ptr, cmop_i8_ptr_ty)
|
||||
if cmop_bar_ptr is not None: mlirlite.build_load(builder, cmop_i8_ty, cmop_bar_ptr, 1)
|
||||
return call_res_cmop
|
||||
def _MarkWillFreeArgName(self, trans: HT.Translator*, arg_node: ast.AST*) -> int:
|
||||
"""P2 willFree:把实参变量槽标为"已失效";只处理简单变量名(1=标记过 / 0=未处理)。
|
||||
|
||||
与模块级调用同一口径(VarEntry.Freed):该槽其后被读 / 取地址 / 再传时,由
|
||||
ExprGenName.translate_name_value 或 ExprGenOps 的 AddrOf 分支报 LifetimeError。"""
|
||||
if trans is None or arg_node is None: return 0
|
||||
if arg_node.kind() != ast.ASTKind.Name: return 0
|
||||
nm: ast.Name* = ast.Name*(arg_node)
|
||||
if nm.id is None: return 0
|
||||
return self.Gen.VarGen._FreedMark(self.Gen.VarGen.lookup_var(trans.SymTab, nm.id))
|
||||
|
||||
def _MarkWillFreeArgName(self, trans: HT.Translator*, arg_node: ast.AST*) -> int:
|
||||
"""P2 willFree:把实参变量槽标为"已失效";只处理简单变量名(1=标记过 / 0=未处理)。
|
||||
|
||||
与模块级调用同一口径(VarEntry.Freed):该槽其后被读 / 取地址 / 再传时,由
|
||||
ExprGenName.translate_name_value 或 ExprGenOps 的 AddrOf 分支报 LifetimeError。"""
|
||||
if trans is None or arg_node is None: return 0
|
||||
if arg_node.kind() != ast.ASTKind.Name: return 0
|
||||
nm: ast.Name* = ast.Name*(arg_node)
|
||||
if nm.id is None: return 0
|
||||
return self.Gen.VarGen._FreedMark(self.Gen.VarGen.lookup_var(trans.SymTab, nm.id))
|
||||
|
||||
# _translate_method_call - translate obj.method(args) into a call with the
|
||||
# object pointer (obj_ptr, an alloca of Ptr(StructTy)) as the self argument.
|
||||
|
||||
@@ -586,27 +585,27 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
# 跨模块回退(v3):本文件摘要表按文件重置,跨模块只能查 .vpi 落盘的摘要
|
||||
sha_mc = self.Gen.StructGen.get_struct_sha1(class_name)
|
||||
pk_mc: int = self.Gen.CallGenBase.lookup_escape_via_vpi(pool, sha_mc, class_name, method_name)
|
||||
if pk_mc != 0: esc_mask_mc = int(pk_mc & 4294967295)
|
||||
# 跨模块常量特化:用实参常量套用对方模块 .vpi 落盘的守卫记录(形参位含 self 偏移)
|
||||
if esc_mask_mc != 0:
|
||||
cl_mc: int = self.Gen.CallGenBase.lookup_escape_clears_via_vpi(pool, sha_mc, class_name, method_name, cargs_mc, len(cargs_mc), 1)
|
||||
if pk_mc != 0: esc_mask_mc = int(pk_mc & 4294967295)
|
||||
# 跨模块常量特化:用实参常量套用对方模块 .vpi 落盘的守卫记录(形参位含 self 偏移)
|
||||
if esc_mask_mc != 0:
|
||||
cl_mc: int = self.Gen.CallGenBase.lookup_escape_clears_via_vpi(pool, sha_mc, class_name, method_name, cargs_mc, len(cargs_mc), 1)
|
||||
if cl_mc != 0: esc_mask_mc = esc_mask_mc & (~cl_mc)
|
||||
# 跨过程常量特化(P3 收尾):同文件能拿到方法体时,用常量实参重算摘要(形参位含 self 偏移)
|
||||
if esc_mask_mc != 0:
|
||||
can_rf: sizet = len(cargs_mc)
|
||||
esc_mask_mc = GenApi.refine_escape_mask_method(pool, class_name, method_name, cargs_mc, can_rf, esc_mask_mc)
|
||||
# 同命裁剪(**方法路径,此前缺失**):只清"写进形参对象字段"那一类位 —— 若其余实参(含
|
||||
# 接收者)也都在本帧,则接收者与本帧同命、并不真的逃逸。现场:`h.set_q(l)`,h 是
|
||||
# `new heap slife S()`(生命期本就是 FRAME)、l 是栈数组 → 两都在本帧 → 不该报。
|
||||
if esc_mask_mc != 0:
|
||||
hard_mc: int = GenApi.get_param_escapes_hard_method(pool, class_name, method_name)
|
||||
fld_mc: int = esc_mask_mc & (~hard_mc)
|
||||
if fld_mc != 0:
|
||||
recv_mc: ast.AST* = None
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
recv_mc = ast.Attribute*(cl.func).value
|
||||
can_sf: sizet = len(cargs_mc)
|
||||
cl_sfm: int = self.Gen.CallGen._FrameArgsEscapeClearsMethod(trans, recv_mc, cargs_mc, can_sf, fld_mc)
|
||||
esc_mask_mc = GenApi.refine_escape_mask_method(pool, class_name, method_name, cargs_mc, can_rf, esc_mask_mc)
|
||||
# 同命裁剪(**方法路径,此前缺失**):只清"写进形参对象字段"那一类位 —— 若其余实参(含
|
||||
# 接收者)也都在本帧,则接收者与本帧同命、并不真的逃逸。现场:`h.set_q(l)`,h 是
|
||||
# `new heap slife S()`(生命期本就是 FRAME)、l 是栈数组 → 两都在本帧 → 不该报。
|
||||
if esc_mask_mc != 0:
|
||||
hard_mc: int = GenApi.get_param_escapes_hard_method(pool, class_name, method_name)
|
||||
fld_mc: int = esc_mask_mc & (~hard_mc)
|
||||
if fld_mc != 0:
|
||||
recv_mc: ast.AST* = None
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
recv_mc = ast.Attribute*(cl.func).value
|
||||
can_sf: sizet = len(cargs_mc)
|
||||
cl_sfm: int = self.Gen.CallGen._FrameArgsEscapeClearsMethod(trans, recv_mc, cargs_mc, can_sf, fld_mc)
|
||||
if cl_sfm != 0: esc_mask_mc = esc_mask_mc & (~cl_sfm)
|
||||
# 声明式指令最终裁决(@life(escape/noescape):unsafe 但强制),在推断/回退之后最后套用
|
||||
f_mc: int = GenApi.get_param_escape_force_method(pool, class_name, method_name)
|
||||
@@ -1191,7 +1190,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
|
||||
# Default-argument filling when the call supplies fewer args than the
|
||||
# definition; look up the function's defaults info.
|
||||
mdf_defaults: t.CPtr = None
|
||||
mdf_defaults: rawptr = None
|
||||
mdf_default_count: int = 0
|
||||
mdf_param_count: int = 0
|
||||
if trans is not None and trans._funcs is not None:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -149,7 +148,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile, cargs)
|
||||
if new_ptr is not None:
|
||||
storage_ptr = new_ptr
|
||||
# __new__ declares `-> t.CPtr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# __new__ declares `-> rawptr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# Using it directly degrades method dispatch; bitcast is a zero-cost type-layer fix.
|
||||
if new_ptr.Ty is not None:
|
||||
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
|
||||
@@ -711,7 +710,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile, cargs)
|
||||
if new_ptr is not None:
|
||||
storage_ptr = new_ptr
|
||||
# __new__ declares `-> t.CPtr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# __new__ declares `-> rawptr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# Using it directly degrades method dispatch; bitcast is a zero-cost type-layer fix.
|
||||
if new_ptr.Ty is not None:
|
||||
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
|
||||
@@ -1184,7 +1183,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans, None, gc_volatile, gc_arg_nodes)
|
||||
if new_ptr is not None:
|
||||
storage_ptr = new_ptr
|
||||
# __new__ declares `-> t.CPtr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# __new__ declares `-> rawptr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# Using it directly degrades method dispatch; bitcast is a zero-cost type-layer fix.
|
||||
if new_ptr.Ty is not None:
|
||||
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
|
||||
|
||||
@@ -2,7 +2,6 @@ import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Expr.ExprGenCls as ExprGenCls
|
||||
import lib.core.Gen.Expr.ExprGenName as ExprGenName
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -28,7 +27,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
|
||||
# _tc_h0_generic_func - generic function call: infer/specialize type args, then emit the call.
|
||||
# Must run before normal function/constructor dispatch; hit_box marks handled void calls.
|
||||
def _tc_h0_generic_func(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h0_generic_func(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
if cl is None or trans is None: return None
|
||||
if self.Gen.ClassGenGeneric.GenericFuncKeys is None: return None
|
||||
if cl.func is None: return None
|
||||
@@ -148,7 +147,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
if string.strcmp(kw.arg, ag.arg) == 0: return int(ki)
|
||||
return -1
|
||||
|
||||
def _emit_generic_func_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, cl: ast.Call*, spec_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _emit_generic_func_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, cl: ast.Call*, spec_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Emit the specialized-function call, coercing args to the specialized param types."""
|
||||
func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name)
|
||||
if func is None:
|
||||
@@ -189,7 +188,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
# reads its first field as a string and emits illegal IR. Use the looked-up symbol name.
|
||||
return mlirlite.build_call(builder, spec_name, head, int(can), ret_ty, 0)
|
||||
|
||||
def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Compile-time super()/ctraits detection; sets hit_box on interception, else returns None."""
|
||||
# super().method(args) -> static call to the parent method. Must intercept before attribute
|
||||
# dispatch, else Call(super) is treated as a plain function call and lookup hits self/vtable.
|
||||
@@ -221,7 +220,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return mlirlite.const_int32(pool, 0)
|
||||
return None
|
||||
|
||||
def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Special c.Deref/Asm/LLVMIR calls; marks hit_box for void calls, else returns None."""
|
||||
# __asm__(...) / __llvmir__(...) sugar: bare calls equal c.Asm(...) / c.LLVMIR(...). Must
|
||||
# intercept before the c.* attribute branch, since the bare cl.func is a Name.
|
||||
@@ -301,7 +300,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return self.Gen.AsyncGen.translate_coro_gather(builder, pool, mod, cl, trans)
|
||||
return None
|
||||
|
||||
def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
"""stdarg sugar and str/int/bool built-in casts; returns None when unmatched."""
|
||||
# stdarg sugar (va_arg / arg / va_start / va_end): these are declared as pass bodies in
|
||||
# stdarg.vp and handled here at translation time by emitting LLVM va_arg / intrinsic calls.
|
||||
@@ -362,16 +361,16 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return None
|
||||
return None
|
||||
|
||||
def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
"""t.XXX / typedef type casts; returns None when unmatched."""
|
||||
# Detect t.XXX type casts (uint64(ptr), t.CPtr(val), int(val), ...): when func is t.XXX and
|
||||
# Detect t.XXX type casts (uint64(ptr), rawptr(val), int(val), ...): when func is t.XXX and
|
||||
# XXX is a known type, treat it as a cast; once confirmed, never fall through to cross-module calls.
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
tc_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||||
if tc_at.value is not None and tc_at.value.kind() == ast.ASTKind.Name:
|
||||
tc_mod_nm: ast.Name* = ast.Name*(tc_at.value)
|
||||
if tc_mod_nm.id is not None and string.strcmp(tc_mod_nm.id, "t") == 0:
|
||||
# t.CType(value, TypeName, t.CPtr) casts value to TypeName*; TypeName is a type
|
||||
# t.CType(value, TypeName, rawptr) casts value to TypeName*; TypeName is a type
|
||||
# name (not a value), so it must be handled explicitly or it falls through to a FATAL.
|
||||
if string.strcmp(func_name, "CType") == 0 and can >= 2:
|
||||
cty_node: ast.AST* = cargs.get(1)
|
||||
@@ -388,7 +387,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
cty_arg3: ast.AST* = cargs.get(2)
|
||||
cty_is_cptr: int = 0
|
||||
if cty_arg3 is not None:
|
||||
# Form 1: t.CPtr (Attribute)
|
||||
# Form 1: rawptr (Attribute)
|
||||
if cty_arg3.kind() == ast.ASTKind.Attribute:
|
||||
cty_at3: ast.Attribute* = ast.Attribute*(cty_arg3)
|
||||
if cty_at3.attr is not None and string.strcmp(cty_at3.attr, "CPtr") == 0:
|
||||
@@ -413,7 +412,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
if cty_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cty_val, ctype_target, cty_arg0, trans)
|
||||
# t.CType confirmed: even if type resolution fails, do not fall through to a cross-module FATAL
|
||||
return None
|
||||
# CConst is a const marker: CConst(val, t.CPtr) -> Ptr(i8) (const void*). Without
|
||||
# CConst is a const marker: CConst(val, rawptr) -> Ptr(i8) (const void*). Without
|
||||
# this it emits an undefined @CConst; single-arg CConst(x) returns the value unchanged.
|
||||
if string.strcmp(func_name, "CConst") == 0:
|
||||
if can >= 2:
|
||||
@@ -425,13 +424,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
target_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name)
|
||||
if target_ty is not None:
|
||||
tc_effective_can: sizet = can
|
||||
# Two-arg form: int(val, t.CPtr) -> Ptr(target_ty). void* is illegal in LLVM,
|
||||
# Two-arg form: int(val, rawptr) -> Ptr(target_ty). void* is illegal in LLVM,
|
||||
# so CVoid* must be represented as i8*.
|
||||
if can == 2:
|
||||
tc_arg2_node: ast.AST* = cargs.get(1)
|
||||
tc_arg2_is_cptr: int = 0
|
||||
if tc_arg2_node is not None:
|
||||
# Form 1: t.CPtr (Attribute form)
|
||||
# Form 1: rawptr (Attribute form)
|
||||
if tc_arg2_node.kind() == ast.ASTKind.Attribute:
|
||||
tc_arg2_at: ast.Attribute* = ast.Attribute*(tc_arg2_node)
|
||||
if tc_arg2_at.attr is not None and string.strcmp(tc_arg2_at.attr, "CPtr") == 0:
|
||||
@@ -513,13 +512,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
imp_gp = trans._imported_modules
|
||||
fi_gp = trans._from_imports
|
||||
bare_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, gp_ast, imp_gp, fi_gp, trans, 0)
|
||||
# Generic two-arg form T(val, t.CPtr) -> Ptr(T), aligned with int(val, t.CPtr) -> Ptr(i32);
|
||||
# Generic two-arg form T(val, rawptr) -> Ptr(T), aligned with int(val, rawptr) -> Ptr(i32);
|
||||
# without it the two-arg call misses the can==1 branch and misreports an undefined bare call.
|
||||
if bare_ty is not None and can == 2:
|
||||
bare_arg2_node: ast.AST* = cargs.get(1)
|
||||
bare_arg2_is_cptr: int = 0
|
||||
if bare_arg2_node is not None:
|
||||
# Form 1: t.CPtr (Attribute form)
|
||||
# Form 1: rawptr (Attribute form)
|
||||
if bare_arg2_node.kind() == ast.ASTKind.Attribute:
|
||||
bare_arg2_at: ast.Attribute* = ast.Attribute*(bare_arg2_node)
|
||||
if bare_arg2_at.attr is not None and string.strcmp(bare_arg2_at.attr, "CPtr") == 0:
|
||||
@@ -552,7 +551,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
|
||||
return None
|
||||
|
||||
def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
"""__sizeof__/len/isinstance built-ins; returns None when unmatched."""
|
||||
# Detect ClassName.__sizeof__() and return the struct size constant (i64); it is a builtin,
|
||||
# not a cross-module call. Supports e.g. Argument.__sizeof__() and module-qualified classes.
|
||||
@@ -616,7 +615,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
# dot after a sha1 prefix. Union types (X*) and rawptr[X] both have pointer size 8.
|
||||
if string.strstr(sz_cls_name, "|") is not None: return mlirlite.const_int64(pool, 8)
|
||||
if string.strncmp(sz_cls_name, "rawptr[", 7) == 0: return mlirlite.const_int64(pool, 8)
|
||||
# A trailing '*' means pointer size 8 (rawptr[T] == t.CPtr[T] == T*). Must check
|
||||
# A trailing '*' means pointer size 8 (rawptr[T] == rawptr[T] == T*). Must check
|
||||
# trailing, not strrchr, since containers like list[{sha}.AST*] also contain '*'.
|
||||
_sz_len_s: sizet = string.strlen(sz_cls_name)
|
||||
while _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == ' ': _sz_len_s -= 1
|
||||
@@ -828,7 +827,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return mlirlite.build_call(builder, len_mangled_x, len_self_x, 1, len_ret_x, 0)
|
||||
# fail-fast: the class has no __len__ (compile-time error, matching TPC
|
||||
# HandlesExprBuiltin._FailFastLenUnsupported wording).
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use t.CPtr[Element] and maintain the element count explicitly", "TypeError")
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError")
|
||||
# Non-struct: str (Ptr(Int8)) uses strlen; other types fail fast
|
||||
len_arg_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(len_val)
|
||||
len_is_str: int = 0
|
||||
@@ -861,7 +860,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return mlirlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0)
|
||||
# fail-fast: not a string/array/object, so length is unavailable (matching TPC
|
||||
# HandlesExprBuiltin._FailFastLenUnsupported wording).
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use t.CPtr[Element] and maintain the element count explicitly", "TypeError")
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError")
|
||||
|
||||
# Detect isinstance(): runtime vtable subclass-set comparison. obj's head vtable pointer must
|
||||
# be in {Cls and all subclass vtables}; NoVTable targets fall back to a compile-time check.
|
||||
@@ -873,7 +872,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
|
||||
return None
|
||||
|
||||
def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Static class/method/receiver/self.field/list built-ins; sets hit_box, else returns None."""
|
||||
# REnum.kind() compiles to a __tag read (offset 0, type from the field declaration): bitcast obj
|
||||
# to __tag* + load. Four criteria detect REnum, incl. pointee __tag and X.field annotations.
|
||||
@@ -917,7 +916,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
rk_ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, rk_nm.id)
|
||||
rk_annot_raw: str = self.Gen.VarGen.var_annot_class_name(rk_ve)
|
||||
if rk_annot_raw is not None:
|
||||
# Truncate the union/generic suffix (" | t.CPtr" / "[...]")
|
||||
# Truncate the union/generic suffix (" | rawptr" / "[...]")
|
||||
rk_ae: sizet = 0
|
||||
while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[': rk_ae += 1
|
||||
rk_ab: str = pool.alloc(rk_ae + 1)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -863,7 +862,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
return None
|
||||
|
||||
|
||||
def add_func_to_table(self, funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: mlirlite.Function*, max_count: int, defaults: t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
|
||||
def add_func_to_table(self, funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: mlirlite.Function*, max_count: int, defaults: rawptr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
|
||||
"""Add a function to a func table; returns 0 on success"""
|
||||
if name is None or func is None or funcs is None: return 1
|
||||
if func_count >= max_count: return 1
|
||||
@@ -1021,7 +1020,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
return 1
|
||||
|
||||
|
||||
def _register_global_defaults(self, name: str, defaults: t.CPtr, default_count: int, param_count: int, def_sha1: str = None) -> int:
|
||||
def _register_global_defaults(self, name: str, defaults: rawptr, default_count: int, param_count: int, def_sha1: str = None) -> int:
|
||||
"""Register a function's default arguments in the global table; returns 0 on success"""
|
||||
if name is None or defaults is None: return 1
|
||||
if self._init_global_defaults_table() == 0: return 1
|
||||
@@ -1066,7 +1065,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
string.memset(kinds, 0, default_count * 4)
|
||||
string.memset(ints, 0, default_count * 8)
|
||||
string.memset(strs, 0, default_count * 8)
|
||||
dl: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(uint64(defaults))
|
||||
dl: list[ast.AST*]* = list[ast.AST*]*(uint64(defaults))
|
||||
di: int
|
||||
for di in range(int(default_count)):
|
||||
dnode: ast.AST* = dl.get(di)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -151,7 +150,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
|
||||
i2 += 1
|
||||
return new_head
|
||||
|
||||
# _coerce_args_to_def_params: coerce cross-module call args to vpi definition-side param
|
||||
# _coerce_args_to_def_params: coerce cross-module call args to vpi definition-side param
|
||||
# types so call/declare/define widths match; bare C-lib names use the C-lib path instead.
|
||||
def _coerce_args_to_def_params(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, call_name: str, head: mlirlite.Value*, count: int, cargs: list[ast.AST*]* = None, self_off: int = 0, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Coerce cross-module call args to vpi definition-side param types; returns the rebuilt chain"""
|
||||
@@ -231,7 +230,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
|
||||
if cls_nm is not None: stdlib.free(cls_nm)
|
||||
return new_head
|
||||
|
||||
# _coerce_arg_value_to_ty: convert one arg Value to the target param type -- same-width ints
|
||||
# _coerce_arg_value_to_ty: convert one arg Value to the target param type -- same-width ints
|
||||
# pass through, narrow/wide ints trunc/extend, mismatched pointers bitcast; else unchanged.
|
||||
def _coerce_arg_value_to_ty(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, val: mlirlite.Value*, tgt_ty: mlirlite.LLVMType*, node: ast.AST* = None, trans: HT.Translator* = None, tpl_src: int = 0) -> mlirlite.Value*:
|
||||
"""Convert one argument Value to the target param type; leaves it unchanged when unsafe"""
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
import lib.Stub.StubGen.VpiReader as VpiReader
|
||||
@@ -148,7 +145,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
cur_param = mlirlite.param_get_next(cur_param)
|
||||
return 0
|
||||
|
||||
def translate_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
def translate_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate a Call node and return the result Value."""
|
||||
cl: ast.Call* = ast.Call*(node)
|
||||
# Static symbols must not be used cross-module: fail fast on mod.fn(...) hitting another
|
||||
@@ -276,7 +273,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
if h0_hit_val != 0: return None
|
||||
# super()/ctraits detection: a void method yields None but is handled, so hit_box must
|
||||
# separate "handled" from "missed"; otherwise super() falls through and reports undefined.
|
||||
h1_hit: t.CPtr = stdlib.malloc(4)
|
||||
h1_hit: rawptr = stdlib.malloc(4)
|
||||
if h1_hit is not None: h1_hit[0] = 0
|
||||
_tc_h1_super_ctraits_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h1_hit)
|
||||
h1_hit_val: int = 0
|
||||
@@ -340,7 +337,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# c.Asm/c.LLVMIR special calls return None when void but are handled, so use hit_box to
|
||||
# separate "missed"; otherwise they fall through to the external-function path and mis-report.
|
||||
h2_hit: t.CPtr = stdlib.malloc(4)
|
||||
h2_hit: rawptr = stdlib.malloc(4)
|
||||
if h2_hit is not None: h2_hit[0] = 0
|
||||
_tc_h2_c_special_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h2_hit)
|
||||
h2_hit_val: int = 0
|
||||
@@ -363,7 +360,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# Method dispatch may succeed yet return None (e.g. void __before_init__/__init__), so hit_box
|
||||
# must separate "recognized method" from "missed"; otherwise the object name is looked up as a module.
|
||||
h6_hit: t.CPtr = stdlib.malloc(4)
|
||||
h6_hit: rawptr = stdlib.malloc(4)
|
||||
if h6_hit is not None: h6_hit[0] = 0
|
||||
_tc_h6_method_dispatch_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h6_hit)
|
||||
h6_hit_val: int = 0
|
||||
@@ -781,7 +778,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
found_func = bi_decl
|
||||
# Use accessors to bypass stub type restrictions.
|
||||
found_ret_ty: mlirlite.LLVMType* = None
|
||||
found_params: t.CPtr = None
|
||||
found_params: rawptr = None
|
||||
if found_func is not None:
|
||||
found_ret_ty = mlirlite.function_get_ret_ty(found_func)
|
||||
found_params = mlirlite.function_get_params(found_func)
|
||||
@@ -912,7 +909,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
return self.Gen.CallGenLeafKit.translate_closure_call(pool, builder, mod, fp_alloca, cargs, can, trans)
|
||||
# ---- M3: session-function table hit -> take the ctx function-pointer slot and call indirectly ----
|
||||
# Placed last in the found_func-is-None block so locals/closures shadow session functions; only foreign bare names reach the table.
|
||||
sfn_box: t.CPtr = None
|
||||
sfn_box: rawptr = None
|
||||
if trans is not None and trans.ReplCtx is not None and (cl.func is None or cl.func.kind() == ast.ASTKind.Name):
|
||||
sfn_box = stdlib.malloc(4)
|
||||
if sfn_box is not None:
|
||||
@@ -1069,7 +1066,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
# Default-argument filling: when fewer args than params, fill the gaps; the defaults array is
|
||||
# right-aligned to args (defaults[0] maps to args[offset], offset = param_count - default_count).
|
||||
if can > 0 or (can == 0 and cargs is not None):
|
||||
df_defaults: t.CPtr = None
|
||||
df_defaults: rawptr = None
|
||||
df_default_count: int = 0
|
||||
df_param_count: int = 0
|
||||
# Compute the callee module SHA1 as a qualifier key (module.func -> that module; bare -> current),
|
||||
@@ -1142,7 +1139,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
df_arg_val: mlirlite.Value* = None
|
||||
if gd_entry is not None: df_arg_val = self.Gen.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, df_di, trans, builder)
|
||||
if df_arg_val is None and df_defaults is not None:
|
||||
df_defaults_list: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(uint64(df_defaults))
|
||||
df_defaults_list: list[ast.AST*]* = list[ast.AST*]*(df_defaults)
|
||||
df_default_node: ast.AST* = df_defaults_list.get(df_di)
|
||||
if df_default_node is not None: df_arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, df_default_node, None, 0, trans)
|
||||
if df_arg_val is not None:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -74,10 +73,10 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
|
||||
if cls_sha1_rt is None or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0: call_ret_ty = mlirlite.Int32(pool)
|
||||
else: call_ret_ty = self._fail_method_ret_ty(method_name, None, class_name, None, cls_sha1_rt)
|
||||
|
||||
# Value-reference (&T / &temp T) params: auto-address the user args before param-type
|
||||
# coercion (self/obj or the classmethod cls occupies index 0, skipped via start_idx).
|
||||
call_head = self._apply_auto_addr_to_call_args(builder, pool, mod, trans, call_name, arg_nodes, call_head, call_count, start_idx)
|
||||
|
||||
# Value-reference (&T / &temp T) params: auto-address the user args before param-type
|
||||
# coercion (self/obj or the classmethod cls occupies index 0, skipped via start_idx).
|
||||
call_head = self._apply_auto_addr_to_call_args(builder, pool, mod, trans, call_name, arg_nodes, call_head, call_count, start_idx)
|
||||
|
||||
# Coerce args to the declared param types (same as _translate_method_call); target func: found_func,
|
||||
# else the mangled module declare. Otherwise call(i32) vs declare(i64) mismatches and llc errors.
|
||||
tgt_func_pc: mlirlite.Function* = found_func
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -17,7 +16,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
# _func_has_eh_params - whether callee signature has try-except EH out params (main excluded)
|
||||
# ============================================================
|
||||
|
||||
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, arg_node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, arg_node: ast.AST*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Return the alloca pointer of a va_list variable without loading it."""
|
||||
if arg_node is None: return None
|
||||
# Name node: look up the alloca pointer from the symbol table (no load)
|
||||
@@ -37,7 +36,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
# Type node present but unresolvable: fail-fast, never fall back to i32 (would read the vararg slot at the wrong width)
|
||||
self.Gen.TypeGenErr.fatal_error(type_node, "va_arg type resolution failed", "TypeError")
|
||||
return mlirlite.Int32(pool)
|
||||
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit a va_arg instruction reading the next variadic argument from the va_list."""
|
||||
if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -67,7 +66,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
|
||||
# Emit the va_arg instruction
|
||||
return mlirlite.build_va_arg(builder, ap_ptr, read_ty)
|
||||
def _translate_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit va_arg reading from the enclosing variadic's own va_list or a forwarded va_list."""
|
||||
# arg() has two forms:
|
||||
# (1) Own-variadic form: inside `def f(a, *args)`, trans._va_list_ptr is the i8* address of
|
||||
@@ -104,7 +103,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
|
||||
# Emit va_arg, using va_ptr as the va_list address (own buffer or forwarded pointer)
|
||||
return mlirlite.build_va_arg(builder, va_ptr, read_ty)
|
||||
def _translate_va_start_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_va_start_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit llvm.va_start to initialize the va_list (the second C-ABI argument is unused)."""
|
||||
if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -122,7 +121,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
void_ty_vs: mlirlite.LLVMType* = mlirlite.Void(pool)
|
||||
mlirlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
|
||||
return mlirlite.const_int32(pool, 0)
|
||||
def _translate_va_end_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_va_end_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit llvm.va_end to clean up the va_list (a no-op on most platforms)."""
|
||||
if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -180,7 +179,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
fixed_count: int = -1
|
||||
if func is not None and func.IsVarArg == 1: fixed_count = self._get_func_fixed_param_count(func)
|
||||
else:
|
||||
# Fall back to the known variadic C-lib signature table (snprintf etc.) when func is None (stub not yet injected)
|
||||
# Fall back to the known variadic C-lib signature table (snprintf etc.) when func is None (stub not yet injected)
|
||||
# or IsVarArg=0 (ad hoc declare); otherwise i32 varargs aren't promoted and the Win64 8-byte slot keeps only 4 bytes.
|
||||
fixed_count = self._get_known_vararg_cfunc_fixed_count(call_name)
|
||||
if fixed_count < 0: return 0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
Reference in new issue
Block a user