Skip to content
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
28 changes: 5 additions & 23 deletions crates/cranelift/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use std::sync::{Arc, Mutex};
use wasmparser::{FuncValidatorAllocations, FunctionBody};
use wasmtime_environ::{
AddressMapSection, BuiltinFunctionIndex, CacheStore, CompileError, DefinedFuncIndex, FlagValue,
FunctionBodyData, FunctionLoc, ModuleTranslation, ModuleTypesBuilder, PtrSize,
FunctionBodyData, FunctionLoc, HostCall, ModuleTranslation, ModuleTypesBuilder, PtrSize,
RelocationTarget, StackMapInformation, StaticModuleIndex, TrapEncodingBuilder, TrapSentinel,
Tunables, VMOffsets, WasmFuncType, WasmFunctionInfo, WasmValType,
};
Expand Down Expand Up @@ -135,6 +135,7 @@ impl Compiler {
fn call_indirect_host(
&self,
builder: &mut FunctionBuilder<'_>,
hostcall: impl Into<HostCall>,
sig: ir::SigRef,
addr: Value,
args: &[Value],
Expand Down Expand Up @@ -165,27 +166,7 @@ impl Compiler {
let name = ir::ExternalName::User(builder.func.declare_imported_user_function(
ir::UserExternalName {
namespace: crate::NS_PULLEY_HOSTCALL,
// FIXME: this'll require some more refactoring to get this
// working entirely. The goal is to enumerate all possible
// reasons to call the host in some sort of enum, probably
// something like:
//
// enum wasmtime_environ::HostCall {
// ArrayCall,
// Builtin(BuiltinFunctionIndex),
// ComponentCall,
// ComponentBuiltin(ComponentBuiltinFunctionIndex),
// }
//
// that doesn't exist yet though but would be pretty
// reasonable to encode within a `u32` here. Doing that work
// is left as a future refactoring for Pulley.
index: {
let pulley_hostcall_index = || {
unimplemented!();
};
pulley_hostcall_index()
},
index: hostcall.into().index(),
},
));
let func = builder.func.import_function(ir::ExtFuncData {
Expand Down Expand Up @@ -445,6 +426,7 @@ impl wasmtime_environ::Compiler for Compiler {
let callee_signature = builder.func.import_signature(array_call_sig);
let call = self.call_indirect_host(
&mut builder,
HostCall::ArrayCall,
callee_signature,
callee,
&[callee_vmctx, caller_vmctx, args_base, args_len],
Expand Down Expand Up @@ -950,7 +932,7 @@ impl Compiler {
.load(pointer_type, mem_flags, array_addr, body_offset);

let sig = builder.func.import_signature(sig);
self.call_indirect_host(builder, sig, func_addr, args)
self.call_indirect_host(builder, builtin, sig, func_addr, args)
}

pub fn isa(&self) -> &dyn TargetIsa {
Expand Down
169 changes: 68 additions & 101 deletions crates/cranelift/src/compiler/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use cranelift_codegen::isa::{CallConv, TargetIsa};
use cranelift_frontend::FunctionBuilder;
use std::any::Any;
use wasmtime_environ::component::*;
use wasmtime_environ::{ModuleInternedTypeIndex, PtrSize, Tunables, WasmValType};
use wasmtime_environ::{HostCall, ModuleInternedTypeIndex, PtrSize, Tunables, WasmValType};

struct TrampolineCompiler<'a> {
compiler: &'a Compiler,
Expand Down Expand Up @@ -247,9 +247,13 @@ impl<'a> TrampolineCompiler<'a> {
i32::try_from(self.offsets.lowering_callee(index)).unwrap(),
);
let host_sig = self.builder.import_signature(host_sig);
let call =
self.compiler
.call_indirect_host(&mut self.builder, host_sig, host_fn, &callee_args);
let call = self.compiler.call_indirect_host(
&mut self.builder,
HostCall::ComponentLowerImport,
host_sig,
host_fn,
&callee_args,
);
let succeeded = self.builder.func.dfg.inst_results(call)[0];

match self.abi {
Expand Down Expand Up @@ -280,15 +284,20 @@ impl<'a> TrampolineCompiler<'a> {
let args = self.abi_load_params();
let vmctx = args[0];

let (host_sig, offset) = host::trap(self.isa, &mut self.builder.func);
let host_fn = self.load_libcall(vmctx, offset);
let (host_sig, index) = host::trap(self.isa, &mut self.builder.func);
let host_fn = self.load_libcall(vmctx, index);

let code = self.builder.ins().iconst(
ir::types::I8,
i64::from(wasmtime_environ::Trap::AlwaysTrapAdapter as u8),
);
self.compiler
.call_indirect_host(&mut self.builder, host_sig, host_fn, &[vmctx, code]);
self.compiler.call_indirect_host(
&mut self.builder,
index,
host_sig,
host_fn,
&[vmctx, code],
);
let succeeded = self.builder.ins().iconst(ir::types::I8, 0);
self.raise_if_host_trapped(succeeded);
// debug trap in case execution actually falls through, but this
Expand Down Expand Up @@ -319,12 +328,7 @@ impl<'a> TrampolineCompiler<'a> {
self.types[self.signature].unwrap_func().params()[0],
WasmValType::I32
);
let (host_sig, offset) = host::resource_new32(self.isa, &mut self.builder.func);

let host_fn = self.load_libcall(vmctx, offset);
let call =
self.compiler
.call_indirect_host(&mut self.builder, host_sig, host_fn, &host_args);
let call = self.call_libcall(vmctx, host::resource_new32, &host_args);
let result = self.builder.func.dfg.inst_results(call)[0];
let result = self.raise_if_resource_trapped(result);
self.abi_store_results(&[result]);
Expand Down Expand Up @@ -353,12 +357,7 @@ impl<'a> TrampolineCompiler<'a> {
self.types[self.signature].unwrap_func().returns()[0],
WasmValType::I32
);
let (host_sig, offset) = host::resource_rep32(self.isa, &mut self.builder.func);

let host_fn = self.load_libcall(vmctx, offset);
let call =
self.compiler
.call_indirect_host(&mut self.builder, host_sig, host_fn, &host_args);
let call = self.call_libcall(vmctx, host::resource_rep32, &host_args);
let result = self.builder.func.dfg.inst_results(call)[0];
let result = self.raise_if_resource_trapped(result);
self.abi_store_results(&[result]);
Expand All @@ -384,11 +383,7 @@ impl<'a> TrampolineCompiler<'a> {
);
host_args.push(args[2]);

let (host_sig, offset) = host::resource_drop(self.isa, &mut self.builder.func);
let host_fn = self.load_libcall(vmctx, offset);
let call =
self.compiler
.call_indirect_host(&mut self.builder, host_sig, host_fn, &host_args);
let call = self.call_libcall(vmctx, host::resource_drop, &host_args);
let should_run_destructor = self.builder.func.dfg.inst_results(call)[0];

// Immediately raise a trap if requested by the host
Expand Down Expand Up @@ -557,7 +552,10 @@ impl<'a> TrampolineCompiler<'a> {
/// from the wasm abi to host.
fn translate_resource_libcall(
&mut self,
get_libcall: fn(&dyn TargetIsa, &mut ir::Function) -> (ir::SigRef, u32),
get_libcall: fn(
&dyn TargetIsa,
&mut ir::Function,
) -> (ir::SigRef, ComponentBuiltinFunctionIndex),
handle_results: fn(&mut Self, &mut Vec<ir::Value>),
) {
match self.abi {
Expand All @@ -575,11 +573,8 @@ impl<'a> TrampolineCompiler<'a> {
let vmctx = args[0];
let mut host_args = vec![vmctx];
host_args.extend(args[2..].iter().copied());
let (host_sig, offset) = get_libcall(self.isa, &mut self.builder.func);
let host_fn = self.load_libcall(vmctx, offset);
let call =
self.compiler
.call_indirect_host(&mut self.builder, host_sig, host_fn, &host_args);

let call = self.call_libcall(vmctx, get_libcall, &host_args);
let mut results = self.builder.func.dfg.inst_results(call).to_vec();
handle_results(self, &mut results);
self.builder.ins().return_(&results);
Expand All @@ -589,22 +584,26 @@ impl<'a> TrampolineCompiler<'a> {
/// provided in the libcalls array.
///
/// The offset is calculated in the `host` module below.
fn load_libcall(&mut self, vmctx: ir::Value, offset: u32) -> ir::Value {
fn load_libcall(
&mut self,
vmctx: ir::Value,
index: ComponentBuiltinFunctionIndex,
) -> ir::Value {
let pointer_type = self.isa.pointer_type();
// First load the pointer to the libcalls structure which is static
// First load the pointer to the builtins structure which is static
// per-process.
let libcalls_array = self.builder.ins().load(
let builtins_array = self.builder.ins().load(
pointer_type,
MemFlags::trusted().with_readonly(),
vmctx,
i32::try_from(self.offsets.libcalls()).unwrap(),
i32::try_from(self.offsets.builtins()).unwrap(),
);
// Next load the function pointer at `offset` and return that.
self.builder.ins().load(
pointer_type,
MemFlags::trusted().with_readonly(),
libcalls_array,
i32::try_from(offset * u32::from(self.offsets.ptr.size())).unwrap(),
builtins_array,
i32::try_from(index.index() * u32::from(self.offsets.ptr.size())).unwrap(),
)
}

Expand Down Expand Up @@ -679,6 +678,21 @@ impl<'a> TrampolineCompiler<'a> {
self.raise_if_host_trapped(succeeded);
self.builder.ins().ireduce(ir::types::I32, ret)
}

fn call_libcall(
&mut self,
vmctx: ir::Value,
get_libcall: fn(
&dyn TargetIsa,
&mut ir::Function,
) -> (ir::SigRef, ComponentBuiltinFunctionIndex),
args: &[ir::Value],
) -> ir::Inst {
let (host_sig, index) = get_libcall(self.isa, &mut self.builder.func);
let host_fn = self.load_libcall(vmctx, index);
self.compiler
.call_indirect_host(&mut self.builder, index, host_sig, host_fn, args)
}
}

impl ComponentCompiler for Compiler {
Expand Down Expand Up @@ -756,26 +770,21 @@ impl TrampolineCompiler<'_> {
// Determine the static signature of the host libcall for this transcode
// operation and additionally calculate the static offset within the
// transode libcalls array.
let func = &mut self.builder.func;
let (sig, offset) = match op {
Transcode::Copy(FixedEncoding::Utf8) => host::utf8_to_utf8(self.isa, func),
Transcode::Copy(FixedEncoding::Utf16) => host::utf16_to_utf16(self.isa, func),
Transcode::Copy(FixedEncoding::Latin1) => host::latin1_to_latin1(self.isa, func),
Transcode::Latin1ToUtf16 => host::latin1_to_utf16(self.isa, func),
Transcode::Latin1ToUtf8 => host::latin1_to_utf8(self.isa, func),
Transcode::Utf16ToCompactProbablyUtf16 => {
host::utf16_to_compact_probably_utf16(self.isa, func)
}
Transcode::Utf16ToCompactUtf16 => host::utf16_to_compact_utf16(self.isa, func),
Transcode::Utf16ToLatin1 => host::utf16_to_latin1(self.isa, func),
Transcode::Utf16ToUtf8 => host::utf16_to_utf8(self.isa, func),
Transcode::Utf8ToCompactUtf16 => host::utf8_to_compact_utf16(self.isa, func),
Transcode::Utf8ToLatin1 => host::utf8_to_latin1(self.isa, func),
Transcode::Utf8ToUtf16 => host::utf8_to_utf16(self.isa, func),
let get_libcall = match op {
Transcode::Copy(FixedEncoding::Utf8) => host::utf8_to_utf8,
Transcode::Copy(FixedEncoding::Utf16) => host::utf16_to_utf16,
Transcode::Copy(FixedEncoding::Latin1) => host::latin1_to_latin1,
Transcode::Latin1ToUtf16 => host::latin1_to_utf16,
Transcode::Latin1ToUtf8 => host::latin1_to_utf8,
Transcode::Utf16ToCompactProbablyUtf16 => host::utf16_to_compact_probably_utf16,
Transcode::Utf16ToCompactUtf16 => host::utf16_to_compact_utf16,
Transcode::Utf16ToLatin1 => host::utf16_to_latin1,
Transcode::Utf16ToUtf8 => host::utf16_to_utf8,
Transcode::Utf8ToCompactUtf16 => host::utf8_to_compact_utf16,
Transcode::Utf8ToLatin1 => host::utf8_to_latin1,
Transcode::Utf8ToUtf16 => host::utf8_to_utf16,
};

let libcall = self.load_libcall(vmctx, offset);

// Load the base pointers for the from/to linear memories.
let from_base = self.load_runtime_memory_base(vmctx, from);
let to_base = self.load_runtime_memory_base(vmctx, to);
Expand Down Expand Up @@ -831,9 +840,7 @@ impl TrampolineCompiler<'_> {
));
args.push(self.builder.ins().stack_addr(pointer_type, slot, 0));
}
let call = self
.compiler
.call_indirect_host(&mut self.builder, sig, libcall, &args);
let call = self.call_libcall(vmctx, get_libcall, &args);
let mut results = self.builder.func.dfg.inst_results(call).to_vec();
if uses_retptr {
results.push(self.builder.ins().load(
Expand Down Expand Up @@ -945,6 +952,7 @@ impl TrampolineCompiler<'_> {
mod host {
use cranelift_codegen::ir::{self, AbiParam};
use cranelift_codegen::isa::{CallConv, TargetIsa};
use wasmtime_environ::component::ComponentBuiltinFunctionIndex;

macro_rules! define {
(
Expand All @@ -954,7 +962,7 @@ mod host {
)*
) => {
$(
pub(super) fn $name(isa: &dyn TargetIsa, func: &mut ir::Function) -> (ir::SigRef, u32) {
pub(super) fn $name(isa: &dyn TargetIsa, func: &mut ir::Function) -> (ir::SigRef, ComponentBuiltinFunctionIndex) {
let pointer_type = isa.pointer_type();
let params = vec![
$( AbiParam::new(define!(@ty pointer_type $param)) ),*
Expand All @@ -968,7 +976,7 @@ mod host {
call_conv: CallConv::triple_default(isa.triple()),
});

(sig, offsets::$name)
(sig, ComponentBuiltinFunctionIndex::$name())
}
)*
};
Expand All @@ -984,46 +992,5 @@ mod host {
(@ty $ptr:ident vmctx) => ($ptr);
}

wasmtime_environ::foreach_transcoder!(define);
wasmtime_environ::foreach_builtin_component_function!(define);

mod offsets {
macro_rules! offsets {
(
$(
$( #[$attr:meta] )*
$name:ident($($t:tt)*) $( -> $result:ident )?;
)*
) => {
offsets!(@declare (0) $($name)*);
};

(@declare ($n:expr)) => (const LAST_BUILTIN: u32 = $n;);
(@declare ($n:expr) $name:ident $($rest:tt)*) => (
pub const $name: u32 = $n;
offsets!(@declare ($n + 1) $($rest)*);
);
}

wasmtime_environ::foreach_builtin_component_function!(offsets);

macro_rules! transcode_offsets {
(
$(
$( #[$attr:meta] )*
$name:ident($($t:tt)*) $( -> $result:ident )?;
)*
) => {
transcode_offsets!(@declare (0) $($name)*);
};

(@declare ($n:expr)) => ();
(@declare ($n:expr) $name:ident $($rest:tt)*) => (
pub const $name: u32 = LAST_BUILTIN + $n;
transcode_offsets!(@declare ($n + 1) $($rest)*);
);
}

wasmtime_environ::foreach_transcoder!(transcode_offsets);
}
}
5 changes: 2 additions & 3 deletions crates/cranelift/src/func_environ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ use wasmtime_environ::{FUNCREF_INIT_BIT, FUNCREF_MASK};
pub(crate) struct BuiltinFunctions {
types: BuiltinFunctionSignatures,

builtins:
[Option<ir::FuncRef>; BuiltinFunctionIndex::builtin_functions_total_number() as usize],
builtins: [Option<ir::FuncRef>; BuiltinFunctionIndex::len() as usize],
}

impl BuiltinFunctions {
fn new(compiler: &Compiler) -> Self {
Self {
types: BuiltinFunctionSignatures::new(compiler),
builtins: [None; BuiltinFunctionIndex::builtin_functions_total_number() as usize],
builtins: [None; BuiltinFunctionIndex::len() as usize],
}
}

Expand Down
Loading