// Hostcall import trampoline layout planning.
//
// This belongs to Wasmoon JIT glue rather than generic machine-code emission:
// the buffer format is the ABI between JIT-generated Wasm code and
// `wasmoon_jit_hostcall`.
///|
pub(all) struct HostcallImportTrampolineLayout {
arg_slots : Int
result_slots : Int
values_vec_bytes : Int
int_overflow_count : Int
float_overflow_types : Array[@types.ValueType]
}
///|
pub fn hostcall_value_slot_count(ty : @types.ValueType) -> Int {
match ty {
V128 => 2
_ => 1
}
}
///|
pub fn hostcall_value_byte_count(ty : @types.ValueType) -> Int {
hostcall_value_slot_count(ty) * 8
}
///|
fn is_hostcall_int_class(ty : @types.ValueType) -> Bool {
match ty {
F32 | F64 | V128 => false
_ => true
}
}
///|
pub fn plan_hostcall_import_trampoline_layout(
param_types : Array[@types.ValueType],
result_types : Array[@types.ValueType],
max_int_regs : Int,
max_float_regs : Int,
) -> HostcallImportTrampolineLayout {
let mut total_int = 0
for ty in param_types {
if is_hostcall_int_class(ty) {
total_int = total_int + 1
}
}
let int_overflow_count = if total_int > max_int_regs {
total_int - max_int_regs
} else {
0
}
let float_overflow_types : Array[@types.ValueType] = []
let mut float_seen = 0
for ty in param_types {
if is_hostcall_int_class(ty) {
continue
}
if float_seen >= max_float_regs {
float_overflow_types.push(ty)
}
float_seen = float_seen + 1
}
let mut arg_slots = 0
for ty in param_types {
arg_slots = arg_slots + hostcall_value_slot_count(ty)
}
let mut result_slots = 0
for ty in result_types {
result_slots = result_slots + hostcall_value_slot_count(ty)
}
{
arg_slots,
result_slots,
values_vec_bytes: (arg_slots + result_slots) * 8,
int_overflow_count,
float_overflow_types,
}
}