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 the native ABI calling convention from Wasmtime #8629

Merged
merged 2 commits into from
May 17, 2024
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
357 changes: 20 additions & 337 deletions crates/cranelift/src/compiler.rs

Large diffs are not rendered by default.

26 changes: 7 additions & 19 deletions crates/cranelift/src/compiler/component.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//! Compilation support for the component model.

use crate::{
compiler::{Compiler, NativeRet},
ALWAYS_TRAP_CODE, CANNOT_ENTER_CODE,
};
use crate::{compiler::Compiler, ALWAYS_TRAP_CODE, CANNOT_ENTER_CODE};
use anyhow::Result;
use cranelift_codegen::ir::{self, InstBuilder, MemFlags};
use cranelift_codegen::isa::{CallConv, TargetIsa};
Expand All @@ -28,7 +25,6 @@ struct TrampolineCompiler<'a> {
#[derive(Copy, Clone)]
enum Abi {
Wasm,
Native,
Array,
}

Expand All @@ -48,7 +44,6 @@ impl<'a> TrampolineCompiler<'a> {
ir::UserFuncName::user(0, 0),
match abi {
Abi::Wasm => crate::wasm_call_signature(isa, ty, &compiler.tunables),
Abi::Native => crate::native_call_signature(isa, ty),
Abi::Array => crate::array_call_signature(isa),
},
);
Expand Down Expand Up @@ -81,7 +76,7 @@ impl<'a> TrampolineCompiler<'a> {
}
// Transcoders can only actually be called by Wasm, so let's assert
// that here.
Abi::Native | Abi::Array => {
Abi::Array => {
self.builder
.ins()
.trap(ir::TrapCode::User(crate::DEBUG_ASSERT_TRAP_CODE));
Expand Down Expand Up @@ -129,16 +124,10 @@ impl<'a> TrampolineCompiler<'a> {
let vmctx = args[0];
let wasm_func_ty = self.types[self.signature].unwrap_func();

// More handling is necessary here if this changes
assert!(matches!(
NativeRet::classify(self.isa, wasm_func_ty),
NativeRet::Bare
));

// Start off by spilling all the wasm arguments into a stack slot to be
// passed to the host function.
let (values_vec_ptr, values_vec_len) = match self.abi {
Abi::Wasm | Abi::Native => {
Abi::Wasm => {
let (ptr, len) = self.compiler.allocate_stack_array_and_spill_args(
wasm_func_ty,
&mut self.builder,
Expand Down Expand Up @@ -255,7 +244,7 @@ impl<'a> TrampolineCompiler<'a> {
.call_indirect(host_sig, host_fn, &callee_args);

match self.abi {
Abi::Wasm | Abi::Native => {
Abi::Wasm => {
// After the host function has returned the results are loaded from
// `values_vec_ptr` and then returned.
let results = self.compiler.load_values_from_array(
Expand Down Expand Up @@ -536,7 +525,7 @@ impl<'a> TrampolineCompiler<'a> {

// These trampolines can only actually be called by Wasm, so
// let's assert that here.
Abi::Native | Abi::Array => {
Abi::Array => {
self.builder
.ins()
.trap(ir::TrapCode::User(crate::DEBUG_ASSERT_TRAP_CODE));
Expand Down Expand Up @@ -586,7 +575,7 @@ impl<'a> TrampolineCompiler<'a> {
match self.abi {
// Wasm and native ABIs pass parameters as normal function
// parameters.
Abi::Wasm | Abi::Native => block0_params,
Abi::Wasm => block0_params,

// The array ABI passes a pointer/length as the 3rd/4th arguments
// and those are used to load the actual wasm parameters.
Expand All @@ -607,7 +596,7 @@ impl<'a> TrampolineCompiler<'a> {
fn abi_store_results(&mut self, results: &[ir::Value]) {
match self.abi {
// Wasm/native ABIs return values as usual.
Abi::Wasm | Abi::Native => {
Abi::Wasm => {
self.builder.ins().return_(results);
}

Expand Down Expand Up @@ -684,7 +673,6 @@ impl ComponentCompiler for Compiler {
Ok(AllCallFunc {
wasm_call: compile(Abi::Wasm)?,
array_call: compile(Abi::Array)?,
native_call: compile(Abi::Native)?,
})
}
}
Expand Down
49 changes: 0 additions & 49 deletions crates/cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,55 +131,6 @@ fn value_type(isa: &dyn TargetIsa, ty: WasmValType) -> ir::types::Type {
}
}

/// Get the Cranelift signature with the native calling convention for the given
/// Wasm function type.
///
/// This parameters will start with the callee and caller VM contexts, followed
/// by the translation of each of the Wasm parameter types to native types. The
/// results are the Wasm result types translated to native types.
///
/// The signature uses the wasmtime variant of the target's default calling
/// convention. The only difference from the default calling convention is how
/// multiple results are handled.
///
/// When there is only a single result, or zero results, these signatures are
/// suitable for calling from the host via
///
/// ```ignore
/// unsafe extern "C" fn(
/// callee_vmctx: *mut VMOpaqueContext,
/// caller_vmctx: *mut VMOpaqueContext,
/// // ...wasm parameter types...
/// ) -> // ...wasm result type...
/// ```
///
/// When there are more than one results, these signatures are suitable for
/// calling from the host via
///
/// ```ignore
/// unsafe extern "C" fn(
/// callee_vmctx: *mut VMOpaqueContext,
/// caller_vmctx: *mut VMOpaqueContext,
/// // ...wasm parameter types...
/// retptr: *mut (),
/// ) -> // ...wasm result type 0...
/// ```
///
/// where the first result is returned directly and the rest via the return
/// pointer.
fn native_call_signature(isa: &dyn TargetIsa, wasm: &WasmFuncType) -> ir::Signature {
let mut sig = blank_sig(isa, CallConv::triple_default(isa.triple()));
let cvt = |ty: &WasmValType| ir::AbiParam::new(value_type(isa, *ty));
sig.params.extend(wasm.params().iter().map(&cvt));
if let Some(first_ret) = wasm.returns().get(0) {
sig.returns.push(cvt(first_ret));
}
if wasm.returns().len() > 1 {
sig.params.push(ir::AbiParam::new(isa.pointer_type()));
}
sig
}

/// Get the Cranelift signature for all array-call functions, that is:
///
/// ```ignore
Expand Down
49 changes: 2 additions & 47 deletions crates/environ/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,24 +209,12 @@ pub trait Compiler: Send + Sync {
index: DefinedFuncIndex,
) -> Result<Box<dyn Any + Send>, CompileError>;

/// Compile a trampoline for a native-call host function caller calling the
/// `index`th Wasm function.
///
/// The trampoline should save the necessary state to record the
/// host-to-Wasm transition (e.g. registers used for fast stack walking).
fn compile_native_to_wasm_trampoline(
&self,
translation: &ModuleTranslation<'_>,
types: &ModuleTypesBuilder,
index: DefinedFuncIndex,
) -> Result<Box<dyn Any + Send>, CompileError>;

/// Compile a trampoline for a Wasm caller calling a native callee with the
/// Compile a trampoline for a Wasm caller calling a array callee with the
/// given signature.
///
/// The trampoline should save the necessary state to record the
/// Wasm-to-host transition (e.g. registers used for fast stack walking).
fn compile_wasm_to_native_trampoline(
fn compile_wasm_to_array_trampoline(
&self,
wasm_func_ty: &WasmFuncType,
) -> Result<Box<dyn Any + Send>, CompileError>;
Expand Down Expand Up @@ -286,39 +274,6 @@ pub trait Compiler: Send + Sync {
resolve_reloc: &dyn Fn(usize, RelocationTarget) -> usize,
) -> Result<Vec<(SymbolId, FunctionLoc)>>;

/// Inserts two trampolines into `obj` for a array-call host function:
///
/// 1. A wasm-call trampoline: A trampoline that takes arguments in their
/// wasm-call locations, moves them to their array-call locations, calls
/// the array-call host function, and finally moves the return values
/// from the array-call locations to the wasm-call return
/// locations. Additionally, this trampoline manages the wasm-to-host
/// state transition for the runtime.
///
/// 2. A native-call trampoline: A trampoline that takes arguments in their
/// native-call locations, moves them to their array-call locations,
/// calls the array-call host function, and finally moves the return
/// values from the array-call locations to the native-call return
/// locations. Does not need to manage any wasm/host state transitions,
/// since both caller and callee are on the host side.
///
/// This will configure the same sections as `append_code`, but will likely
/// be much smaller.
///
/// The two returned `FunctionLoc` structures describe where to find these
/// trampolines in the text section, respectively.
///
/// These trampolines are only valid for in-process JIT usage. They bake in
/// the function pointer to the host code.
fn emit_trampolines_for_array_call_host_func(
&self,
ty: &WasmFuncType,
// Actually `host_fn: VMArrayCallFunction` but that type is not
// available in `wasmtime-environ`.
host_fn: usize,
obj: &mut Object<'static>,
) -> Result<(FunctionLoc, FunctionLoc)>;

/// Creates a new `Object` file which is used to build the results of a
/// compilation into.
///
Expand Down
8 changes: 4 additions & 4 deletions crates/environ/src/compile/module_artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ impl<'a> ObjectBuilder<'a> {
/// as well as where the functions are located in the text section and any
/// associated trampolines.
///
/// * `wasm_to_native_trampolines` - list of all trampolines necessary for
/// Wasm callers calling native callees (e.g. `Func::wrap`). One for each
/// * `wasm_to_array_trampolines` - list of all trampolines necessary for
/// Wasm callers calling array callees (e.g. `Func::wrap`). One for each
/// function signature in the module. Must be sorted by `SignatureIndex`.
///
/// Returns the `CompiledModuleInfo` corresponding to this core Wasm module
Expand All @@ -117,7 +117,7 @@ impl<'a> ObjectBuilder<'a> {
&mut self,
translation: ModuleTranslation<'_>,
funcs: PrimaryMap<DefinedFuncIndex, CompiledFunctionInfo>,
wasm_to_native_trampolines: Vec<(ModuleInternedTypeIndex, FunctionLoc)>,
wasm_to_array_trampolines: Vec<(ModuleInternedTypeIndex, FunctionLoc)>,
) -> Result<CompiledModuleInfo> {
let ModuleTranslation {
mut module,
Expand Down Expand Up @@ -220,7 +220,7 @@ impl<'a> ObjectBuilder<'a> {
Ok(CompiledModuleInfo {
module,
funcs,
wasm_to_native_trampolines,
wasm_to_array_trampolines,
func_names,
meta: Metadata {
native_debug_info_present: self.tunables.generate_native_debuginfo,
Expand Down
12 changes: 4 additions & 8 deletions crates/environ/src/component/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,19 @@ pub struct CompiledComponentInfo {
/// These are the
///
/// 1. Wasm-call,
/// 2. array-call, and
/// 3. native-call
/// 2. array-call
///
/// function pointers that end up in a `VMFuncRef` for each
/// lowering.
pub trampolines: PrimaryMap<TrampolineIndex, AllCallFunc<FunctionLoc>>,

/// The location of the wasm-to-native trampoline for the `resource.drop`
/// The location of the wasm-to-array trampoline for the `resource.drop`
/// intrinsic.
pub resource_drop_wasm_to_native_trampoline: Option<FunctionLoc>,
pub resource_drop_wasm_to_array_trampoline: Option<FunctionLoc>,
}

/// A triple of related functions/trampolines variants with differing calling
/// conventions: `{wasm,array,native}_call`.
/// conventions: `{wasm,array}_call`.
///
/// Generic so we can use this with either the `Box<dyn Any + Send>`s that
/// implementations of the compiler trait return or with `FunctionLoc`s inside
Expand All @@ -56,8 +55,6 @@ pub struct AllCallFunc<T> {
pub wasm_call: T,
/// The function exposing the array calling convention.
pub array_call: T,
/// The function exposing the native calling convention.
pub native_call: T,
}

impl<T> AllCallFunc<T> {
Expand All @@ -66,7 +63,6 @@ impl<T> AllCallFunc<T> {
AllCallFunc {
wasm_call: f(self.wasm_call),
array_call: f(self.array_call),
native_call: f(self.native_call),
}
}
}
6 changes: 2 additions & 4 deletions crates/environ/src/module_artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ pub struct CompiledFunctionInfo {
pub wasm_func_loc: FunctionLoc,
/// A trampoline for array callers (e.g. `Func::new`) calling into this function (if needed).
pub array_to_wasm_trampoline: Option<FunctionLoc>,
/// A trampoline for native callers (e.g. `Func::wrap`) calling into this function (if needed).
pub native_to_wasm_trampoline: Option<FunctionLoc>,
}

/// Information about a function, such as trap information, address map,
Expand Down Expand Up @@ -70,9 +68,9 @@ pub struct CompiledModuleInfo {
/// Sorted list, by function index, of names we have for this module.
pub func_names: Vec<FunctionName>,

/// Metadata about wasm-to-native trampolines. Used when exposing a native
/// Metadata about wasm-to-array trampolines. Used when exposing a native
/// callee (e.g. `Func::wrap`) to a Wasm caller. Sorted by signature index.
pub wasm_to_native_trampolines: Vec<(ModuleInternedTypeIndex, FunctionLoc)>,
pub wasm_to_array_trampolines: Vec<(ModuleInternedTypeIndex, FunctionLoc)>,

/// General compilation metadata.
pub meta: Metadata,
Expand Down
Loading
Loading