Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Wasmtime ABIs from Cranelift #6649

Merged
merged 5 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
// number of register values returned in the other class. That is,
// we can return values in up to 8 integer and
// 8 vector registers at once.
//
// In Wasmtime, we can only use one register for return
// value for all the register classes. That is, we can't
// return values in both one integer and one vector
// register; only one return value may be in a register.
ArgsOrRets::Rets => {
if call_conv.extends_wasmtime() {
(1, 1) // x0 or v0, but not both
} else {
(8, 16) // x0-x7 and v0-v7
}
(8, 16) // x0-x7 and v0-v7
}
};

Expand Down Expand Up @@ -290,10 +281,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
// Compute the stack slot's size.
let size = (ty_bits(param.value_type) / 8) as u32;

let size = if is_apple_cc
|| (call_conv.extends_wasmtime() && args_or_rets == ArgsOrRets::Rets)
{
// MacOS aarch64 and Wasmtime allow stack slots with
let size = if is_apple_cc {
// MacOS aarch64 allows stack slots with
// sizes less than 8 bytes. They still need to be
// properly aligned on their natural data alignment,
// though.
Expand Down
29 changes: 4 additions & 25 deletions cranelift/codegen/src/isa/call_conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,9 @@ pub enum CallConv {
Probestack,
/// Wasmtime equivalent of SystemV, not ABI-stable.
///
/// Currently only differs in how multiple return values are handled,
/// returning the first return value in a register and everything else
/// through a return-pointer.
/// FIXME: remove this when Wasmtime uses the "tail" calling convention for
/// all wasm functions.
WasmtimeSystemV,
/// Wasmtime equivalent of WindowsFastcall, not ABI-stable.
///
/// Differs from fastcall in the same way as `WasmtimeSystemV`.
WasmtimeFastcall,
/// Wasmtime equivalent of AppleAarch64, not ABI-stable.
///
/// Differs from apple-aarch64 in the same way as `WasmtimeSystemV`.
WasmtimeAppleAarch64,
}

impl CallConv {
Expand Down Expand Up @@ -81,23 +72,15 @@ impl CallConv {
/// Is the calling convention extending the Windows Fastcall ABI?
pub fn extends_windows_fastcall(self) -> bool {
match self {
Self::WindowsFastcall | Self::WasmtimeFastcall => true,
Self::WindowsFastcall => true,
_ => false,
}
}

/// Is the calling convention extending the Apple aarch64 ABI?
pub fn extends_apple_aarch64(self) -> bool {
match self {
Self::AppleAarch64 | Self::WasmtimeAppleAarch64 => true,
_ => false,
}
}

/// Is the calling convention extending the Wasmtime ABI?
pub fn extends_wasmtime(self) -> bool {
match self {
Self::WasmtimeSystemV | Self::WasmtimeFastcall | Self::WasmtimeAppleAarch64 => true,
Self::AppleAarch64 => true,
_ => false,
}
}
Expand All @@ -114,8 +97,6 @@ impl fmt::Display for CallConv {
Self::AppleAarch64 => "apple_aarch64",
Self::Probestack => "probestack",
Self::WasmtimeSystemV => "wasmtime_system_v",
Self::WasmtimeFastcall => "wasmtime_fastcall",
Self::WasmtimeAppleAarch64 => "wasmtime_apple_aarch64",
})
}
}
Expand All @@ -132,8 +113,6 @@ impl str::FromStr for CallConv {
"apple_aarch64" => Ok(Self::AppleAarch64),
"probestack" => Ok(Self::Probestack),
"wasmtime_system_v" => Ok(Self::WasmtimeSystemV),
"wasmtime_fastcall" => Ok(Self::WasmtimeFastcall),
"wasmtime_apple_aarch64" => Ok(Self::WasmtimeAppleAarch64),
_ => Err(()),
}
}
Expand Down
52 changes: 14 additions & 38 deletions cranelift/codegen/src/isa/riscv64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,12 @@ impl ABIMachineSpec for Riscv64MachineDeps {
let (x_start, x_end, f_start, f_end) = match (call_conv, args_or_rets) {
(isa::CallConv::Tail, _) => (9, 29, 0, 31),
(_, ArgsOrRets::Args) => (10, 17, 10, 17),
(_, ArgsOrRets::Rets) => {
let end = if call_conv.extends_wasmtime() { 10 } else { 11 };
(10, end, 10, end)
}
(_, ArgsOrRets::Rets) => (10, 11, 10, 11),
};
let mut next_x_reg = x_start;
let mut next_f_reg = f_start;
// Stack space.
let mut next_stack: u32 = 0;
let mut return_one_register_used = false;

for param in params {
if let ir::ArgumentPurpose::StructArgument(size) = param.purpose {
Expand All @@ -135,48 +131,28 @@ impl ABIMachineSpec for Riscv64MachineDeps {
let (rcs, reg_tys) = Inst::rc_for_type(param.value_type)?;
let mut slots = ABIArgSlotVec::new();
for (rc, reg_ty) in rcs.iter().zip(reg_tys.iter()) {
let next_reg =
if (next_x_reg <= x_end) && *rc == RegClass::Int && !return_one_register_used {
let x = Some(x_reg(next_x_reg));
if args_or_rets == ArgsOrRets::Rets && call_conv.extends_wasmtime() {
return_one_register_used = true;
}
next_x_reg += 1;
x
} else if (next_f_reg <= f_end)
&& *rc == RegClass::Float
&& !return_one_register_used
{
let x = Some(f_reg(next_f_reg));
if args_or_rets == ArgsOrRets::Rets && call_conv.extends_wasmtime() {
return_one_register_used = true;
}
next_f_reg += 1;
x
} else {
None
};
let next_reg = if (next_x_reg <= x_end) && *rc == RegClass::Int {
let x = Some(x_reg(next_x_reg));
next_x_reg += 1;
x
} else if (next_f_reg <= f_end) && *rc == RegClass::Float {
let x = Some(f_reg(next_f_reg));
next_f_reg += 1;
x
} else {
None
};
if let Some(reg) = next_reg {
slots.push(ABIArgSlot::Reg {
reg: reg.to_real_reg().unwrap(),
ty: *reg_ty,
extension: param.extension,
});
} else {
// Compute size. For the wasmtime ABI it differs from native
// ABIs in how multiple values are returned, so we take a
// leaf out of arm64's book by not rounding everything up to
// 8 bytes. For all ABI arguments, and other ABI returns,
// though, each slot takes a minimum of 8 bytes.
//
// Note that in all cases 16-byte stack alignment happens
// Compute size and 16-byte stack alignment happens
// separately after all args.
let size = reg_ty.bits() / 8;
let size = if args_or_rets == ArgsOrRets::Rets && call_conv.extends_wasmtime() {
size
} else {
std::cmp::max(size, 8)
};
let size = std::cmp::max(size, 8);
// Align.
debug_assert!(size.is_power_of_two());
next_stack = align_to(next_stack, size);
Expand Down
36 changes: 7 additions & 29 deletions cranelift/codegen/src/isa/s390x/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,12 @@ impl ABIMachineSpec for S390xMachineDeps {
}

// In the SystemV ABI, the return area pointer is the first argument,
// so we need to leave room for it if required. (In the Wasmtime ABI,
// the return area pointer is the last argument and is handled below.)
if add_ret_area_ptr && !call_conv.extends_wasmtime() {
// so we need to leave room for it if required.
if add_ret_area_ptr {
next_gpr += 1;
}

for (i, mut param) in params.into_iter().copied().enumerate() {
for mut param in params.into_iter().copied() {
let intreg = in_int_reg(param.value_type);
let fltreg = in_flt_reg(param.value_type);
let vecreg = in_vec_reg(param.value_type);
Expand All @@ -278,8 +277,6 @@ impl ABIMachineSpec for S390xMachineDeps {
ArgsOrRets::Rets => get_vecreg_for_ret(next_vr),
};
(&mut next_vr, candidate, None)
} else if call_conv.extends_wasmtime() {
panic!("i128 args/return values not supported in the Wasmtime ABI");
} else {
// We must pass this by implicit reference.
if args_or_rets == ArgsOrRets::Rets {
Expand All @@ -294,14 +291,6 @@ impl ABIMachineSpec for S390xMachineDeps {
}
};

// In the Wasmtime ABI only the first return value can be in a register.
let candidate =
if call_conv.extends_wasmtime() && args_or_rets == ArgsOrRets::Rets && i > 0 {
None
} else {
candidate
};

let slot = if let Some(reg) = candidate {
*next_reg += 1;
ABIArgSlot::Reg {
Expand All @@ -311,14 +300,9 @@ impl ABIMachineSpec for S390xMachineDeps {
}
} else {
// Compute size. Every argument or return value takes a slot of
// at least 8 bytes, except for return values in the Wasmtime ABI.
// at least 8 bytes.
let size = (ty_bits(param.value_type) / 8) as u32;
let slot_size = if call_conv.extends_wasmtime() && args_or_rets == ArgsOrRets::Rets
{
size
} else {
std::cmp::max(size, 8)
};
let slot_size = std::cmp::max(size, 8);

// Align the stack slot.
debug_assert!(slot_size.is_power_of_two());
Expand Down Expand Up @@ -372,14 +356,8 @@ impl ABIMachineSpec for S390xMachineDeps {

let extra_arg = if add_ret_area_ptr {
debug_assert!(args_or_rets == ArgsOrRets::Args);
// The return pointer is passed either as first argument
// (in the SystemV ABI) or as last argument (Wasmtime ABI).
let next_gpr = if call_conv.extends_wasmtime() {
next_gpr
} else {
0
};
if let Some(reg) = get_intreg_for_arg(next_gpr) {
// The return pointer is passed as first argument.
if let Some(reg) = get_intreg_for_arg(0) {
args.push(ABIArg::reg(
reg.to_real_reg().unwrap(),
types::I64,
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/s390x/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
/// Lane order to be used for a given calling convention.
#[inline]
fn lane_order_for_call_conv(call_conv: CallConv) -> LaneOrder {
if call_conv.extends_wasmtime() {
if call_conv == CallConv::WasmtimeSystemV {
LaneOrder::LittleEndian
} else {
LaneOrder::BigEndian
Expand Down
58 changes: 10 additions & 48 deletions cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,14 @@ impl ABIMachineSpec for X64ABIMachineSpec {
ArgsOrRets::Args => {
get_intreg_for_arg(&call_conv, next_gpr, next_param_idx)
}
ArgsOrRets::Rets => {
get_intreg_for_retval(&call_conv, next_gpr, next_param_idx)
}
ArgsOrRets::Rets => get_intreg_for_retval(&call_conv, next_gpr),
}
} else {
match args_or_rets {
ArgsOrRets::Args => {
get_fltreg_for_arg(&call_conv, next_vreg, next_param_idx)
}
ArgsOrRets::Rets => {
get_fltreg_for_retval(&call_conv, next_vreg, next_param_idx)
}
ArgsOrRets::Rets => get_fltreg_for_retval(&call_conv, next_vreg),
}
};
next_param_idx += 1;
Expand All @@ -227,20 +223,8 @@ impl ABIMachineSpec for X64ABIMachineSpec {
extension: param.extension,
});
} else {
// Compute size. For the wasmtime ABI it differs from native
// ABIs in how multiple values are returned, so we take a
// leaf out of arm64's book by not rounding everything up to
// 8 bytes. For all ABI arguments, and other ABI returns,
// though, each slot takes a minimum of 8 bytes.
//
// Note that in all cases 16-byte stack alignment happens
// separately after all args.
let size = reg_ty.bits() / 8;
let size = if args_or_rets == ArgsOrRets::Rets && call_conv.extends_wasmtime() {
size
} else {
std::cmp::max(size, 8)
};
let size = std::cmp::max(size, 8);
// Align.
debug_assert!(size.is_power_of_two());
next_stack = align_to(next_stack, size);
Expand Down Expand Up @@ -798,18 +782,18 @@ impl ABIMachineSpec for X64ABIMachineSpec {
// The `tail` calling convention doesn't have any callee-save
// registers.
CallConv::Tail => vec![],
CallConv::Fast | CallConv::Cold | CallConv::SystemV | CallConv::WasmtimeSystemV => regs
CallConv::Fast | CallConv::Cold | CallConv::SystemV => regs
.iter()
.cloned()
.filter(|r| is_callee_save_systemv(r.to_reg(), flags.enable_pinned_reg()))
.collect(),
CallConv::WindowsFastcall | CallConv::WasmtimeFastcall => regs
CallConv::WindowsFastcall => regs
.iter()
.cloned()
.filter(|r| is_callee_save_fastcall(r.to_reg(), flags.enable_pinned_reg()))
.collect(),
CallConv::Probestack => todo!("probestack?"),
CallConv::AppleAarch64 | CallConv::WasmtimeAppleAarch64 => unreachable!(),
CallConv::WasmtimeSystemV | CallConv::AppleAarch64 => unreachable!(),
};
// Sort registers for deterministic code output. We can do an unstable sort because the
// registers will be unique (there are no dups).
Expand Down Expand Up @@ -927,11 +911,7 @@ fn get_fltreg_for_arg(call_conv: &CallConv, idx: usize, arg_idx: usize) -> Optio
}
}

fn get_intreg_for_retval(
call_conv: &CallConv,
intreg_idx: usize,
retval_idx: usize,
) -> Option<Reg> {
fn get_intreg_for_retval(call_conv: &CallConv, intreg_idx: usize) -> Option<Reg> {
match call_conv {
CallConv::Tail => match intreg_idx {
0 => Some(regs::rax()),
Expand All @@ -955,28 +935,17 @@ fn get_intreg_for_retval(
1 => Some(regs::rdx()),
_ => None,
},
CallConv::WasmtimeSystemV | CallConv::WasmtimeFastcall => {
if intreg_idx == 0 && retval_idx == 0 {
Some(regs::rax())
} else {
None
}
}
CallConv::WindowsFastcall => match intreg_idx {
0 => Some(regs::rax()),
1 => Some(regs::rdx()), // The Rust ABI for i128s needs this.
_ => None,
},
CallConv::Probestack => todo!(),
CallConv::AppleAarch64 | CallConv::WasmtimeAppleAarch64 => unreachable!(),
CallConv::WasmtimeSystemV | CallConv::AppleAarch64 => unreachable!(),
}
}

fn get_fltreg_for_retval(
call_conv: &CallConv,
fltreg_idx: usize,
retval_idx: usize,
) -> Option<Reg> {
fn get_fltreg_for_retval(call_conv: &CallConv, fltreg_idx: usize) -> Option<Reg> {
match call_conv {
CallConv::Tail => match fltreg_idx {
0 => Some(regs::xmm0()),
Expand All @@ -994,19 +963,12 @@ fn get_fltreg_for_retval(
1 => Some(regs::xmm1()),
_ => None,
},
CallConv::WasmtimeFastcall | CallConv::WasmtimeSystemV => {
if fltreg_idx == 0 && retval_idx == 0 {
Some(regs::xmm0())
} else {
None
}
}
CallConv::WindowsFastcall => match fltreg_idx {
0 => Some(regs::xmm0()),
_ => None,
},
CallConv::Probestack => todo!(),
CallConv::AppleAarch64 | CallConv::WasmtimeAppleAarch64 => unreachable!(),
CallConv::WasmtimeSystemV | CallConv::AppleAarch64 => unreachable!(),
}
}

Expand Down
Loading