winch(x64): Improve ABI support in trampolines (#6204)

This commit improves ABI support in Winch's trampolines mainly by:

* Adding support for the `fastcall` calling convention.
* By storing/restoring callee-saved registers.

One of the explicit goals of this change is to make tests available in the x86_64 target
as a whole and remove the need exclude the windows target.

This commit also introduces a `CallingConvention` enum, to better
reflect the subset of calling conventions that are supported by Winch.
This commit is contained in:
Saúl Cabrera
2023-04-14 17:13:23 -04:00
committed by GitHub
parent 9e1ff9726c
commit 9dd0b59c2a
11 changed files with 340 additions and 89 deletions

View File

@@ -70,6 +70,60 @@ pub(crate) enum LookupError {
SupportDisabled,
}
/// Calling conventions supported by Winch. Winch supports the `Wasmtime*`
/// variations of the system's ABI calling conventions and an internal default
/// calling convention.
///
/// This enum is a reduced subset of the calling conventions defined in
/// [cranelift_codegen::isa::CallConv]. Introducing this enum makes it easier
/// to enforce the invariant of all the calling conventions supported by Winch.
pub enum CallingConvention {
/// See [cranelift_codegen::isa::CallConv::WasmtimeSystemV]
WasmtimeSystemV,
/// See [cranelift_codegen::isa::CallConv::WasmtimeFastcall]
WasmtimeFastcall,
/// See [cranelift_codegen::isa::CallConv::WasmtimeAppleAarch64]
WasmtimeAppleAarch64,
/// The default calling convention for Winch. It largely follows SystemV
/// for parameter and result handling. This calling convention is part of
/// Winch's default ABI [crate::abi::ABI].
Default,
}
impl CallingConvention {
/// Returns true if the current calling convention is `WasmtimeFastcall`.
fn is_fastcall(&self) -> bool {
match &self {
CallingConvention::WasmtimeFastcall => true,
_ => false,
}
}
/// Returns true if the current calling convention is `WasmtimeSystemV`.
fn is_systemv(&self) -> bool {
match &self {
CallingConvention::WasmtimeSystemV => true,
_ => false,
}
}
/// Returns true if the current calling convention is `WasmtimeAppleAarch64`.
fn is_apple_aarch64(&self) -> bool {
match &self {
CallingConvention::WasmtimeAppleAarch64 => true,
_ => false,
}
}
/// Returns true if the current calling convention is `Default`.
fn is_default(&self) -> bool {
match &self {
CallingConvention::Default => true,
_ => false,
}
}
}
/// A trait representing commonalities between the supported
/// instruction set architectures.
pub trait TargetIsa: Send + Sync {
@@ -100,10 +154,21 @@ pub trait TargetIsa: Send + Sync {
) -> Result<MachBufferFinalized<Final>>;
/// Get the default calling convention of the underlying target triple.
fn call_conv(&self) -> CallConv {
fn default_call_conv(&self) -> CallConv {
CallConv::triple_default(&self.triple())
}
/// Derive Wasmtime's calling convention from the triple's default
/// calling convention.
fn wasmtime_call_conv(&self) -> CallingConvention {
match self.default_call_conv() {
CallConv::AppleAarch64 => CallingConvention::WasmtimeAppleAarch64,
CallConv::SystemV => CallingConvention::WasmtimeSystemV,
CallConv::WindowsFastcall => CallingConvention::WasmtimeFastcall,
cc => unimplemented!("calling convention: {:?}", cc),
}
}
/// Get the endianess of the underlying target triple.
fn endianness(&self) -> target_lexicon::Endianness {
self.triple().endianness().unwrap()
@@ -131,7 +196,7 @@ impl Debug for &dyn TargetIsa {
f,
"Target ISA {{ triple: {:?}, calling convention: {:?} }}",
self.triple(),
self.call_conv()
self.default_call_conv()
)
}
}