Skip to content

Commit

Permalink
Accept Into<FunctionType> as signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 committed Dec 14, 2020
1 parent 96abcb3 commit 69f834a
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 20 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* [#1881](https://github.com/wasmerio/wasmer/pull/1881) Added `UnsupportedTarget` error to `CompileError`
* [#1908](https://github.com/wasmerio/wasmer/pull/1908) Implemented `TryFrom<Value<T>>` for `i32`/`u32`/`i64`/`u64`/`f32`/`f64`
* [#1927](https://github.com/wasmerio/wasmer/pull/1927) Added mmap support in `Engine::deserialize_from_file` to speed up artifact loading
* Implement `From<([Type; $N], [Type; $M])>` for `FunctionType`
* [#1911](https://github.com/wasmerio/wasmer/pull/1911) Generalized signature type in `Function::new` and `Function::new_with_env` to accept owned and reference `FunctionType` as well as array pairs. This allows users to define signatures as constants. Implemented `From<([Type; $N], [Type; $M])>` for `FunctionType` to support this.

### Changed

Expand Down
49 changes: 43 additions & 6 deletions lib/api/src/externals/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub struct Function {
impl Function {
/// Creates a new host `Function` (dynamic) with the provided signature.
///
/// # Example
/// # Examples
///
/// ```
/// # use wasmer::{Function, FunctionType, Type, Store, Value};
Expand All @@ -82,11 +82,27 @@ impl Function {
/// Ok(vec![Value::I32(sum)])
/// });
/// ```
///
/// With constant signature:
///
/// ```
/// # use wasmer::{Function, FunctionType, Type, Store, Value};
/// # let store = Store::default();
/// #
/// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]);
///
/// let f = Function::new(&store, I32_I32_TO_I32, |args| {
/// let sum = args[0].unwrap_i32() + args[1].unwrap_i32();
/// Ok(vec![Value::I32(sum)])
/// });
/// ```
#[allow(clippy::cast_ptr_alignment)]
pub fn new<F>(store: &Store, ty: &FunctionType, func: F) -> Self
pub fn new<FT, F>(store: &Store, ty: FT, func: F) -> Self
where
FT: Into<FunctionType>,
F: Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
{
let ty: FunctionType = ty.into();
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithoutEnv {
func: Box::new(func),
function_type: ty.clone(),
Expand All @@ -108,7 +124,7 @@ impl Function {
address,
kind: VMFunctionKind::Dynamic,
vmctx,
signature: ty.clone(),
signature: ty,
call_trampoline: None,
instance_allocator: None,
},
Expand All @@ -118,7 +134,7 @@ impl Function {

/// Creates a new host `Function` (dynamic) with the provided signature and environment.
///
/// # Example
/// # Examples
///
/// ```
/// # use wasmer::{Function, FunctionType, Type, Store, Value, WasmerEnv};
Expand All @@ -137,12 +153,33 @@ impl Function {
/// Ok(vec![Value::I32(result)])
/// });
/// ```
///
/// With constant signature:
///
/// ```
/// # use wasmer::{Function, FunctionType, Type, Store, Value, WasmerEnv};
/// # let store = Store::default();
/// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]);
///
/// #[derive(WasmerEnv)]
/// struct Env {
/// multiplier: i32,
/// };
/// let env = Env { multiplier: 2 };
///
/// let f = Function::new_with_env(&store, I32_I32_TO_I32, env, |env, args| {
/// let result = env.multiplier * (args[0].unwrap_i32() + args[1].unwrap_i32());
/// Ok(vec![Value::I32(result)])
/// });
/// ```
#[allow(clippy::cast_ptr_alignment)]
pub fn new_with_env<F, Env>(store: &Store, ty: &FunctionType, env: Env, func: F) -> Self
pub fn new_with_env<FT, F, Env>(store: &Store, ty: FT, env: Env, func: F) -> Self
where
FT: Into<FunctionType>,
F: Fn(&Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
Env: Sized + WasmerEnv + 'static,
{
let ty: FunctionType = ty.into();
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithEnv {
env: Box::new(env),
func: Box::new(func),
Expand Down Expand Up @@ -171,7 +208,7 @@ impl Function {
address,
kind: VMFunctionKind::Dynamic,
vmctx,
signature: ty.clone(),
signature: ty,
call_trampoline: None,
instance_allocator: None,
},
Expand Down
22 changes: 22 additions & 0 deletions lib/api/tests/externals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ fn function_new_env() -> Result<()> {
#[test]
fn function_new_dynamic() -> Result<()> {
let store = Store::default();

// Using &FunctionType signature
let function_type = FunctionType::new(vec![], vec![]);
let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
assert_eq!(function.ty().clone(), function_type);
Expand All @@ -265,6 +267,13 @@ fn function_new_dynamic() -> Result<()> {
let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]);
let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
assert_eq!(function.ty().clone(), function_type);

// Using array signature
let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
let function = Function::new(&store, function_type, |_values: &[Value]| unimplemented!());
assert_eq!(function.ty().params(), [Type::V128]);
assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]);

Ok(())
}

Expand All @@ -275,6 +284,7 @@ fn function_new_dynamic_env() -> Result<()> {
struct MyEnv {};
let my_env = MyEnv {};

// Using &FunctionType signature
let function_type = FunctionType::new(vec![], vec![]);
let function = Function::new_with_env(
&store,
Expand Down Expand Up @@ -315,6 +325,18 @@ fn function_new_dynamic_env() -> Result<()> {
|_env: &MyEnv, _values: &[Value]| unimplemented!(),
);
assert_eq!(function.ty().clone(), function_type);

// Using array signature
let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
let function = Function::new_with_env(
&store,
function_type,
my_env.clone(),
|_env: &MyEnv, _values: &[Value]| unimplemented!(),
);
assert_eq!(function.ty().params(), [Type::V128]);
assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]);

Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions lib/deprecated/runtime-core/src/typed_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ impl DynamicFunc {

Self {
new_function: new::wasmer::Function::new_with_env::<
_,
fn(&DynamicCtx, &[Value]) -> Result<Vec<Value>, RuntimeError>,
DynamicCtx,
>(&get_global_store(), signature, ctx, inner),
Expand Down
2 changes: 1 addition & 1 deletion lib/wasi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ fn get_path_open_for_store(store: &Store, env: WasiEnv) -> Function {
#[cfg(all(target_os = "macos", target_arch = "aarch64",))]
let path_open = Function::new_with_env(
store,
&FunctionType::new(
FunctionType::new(
vec![
ValType::I32,
ValType::I32,
Expand Down
6 changes: 6 additions & 0 deletions lib/wasmer-types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ implement_from_pair_to_functiontype! {
9,0 9,1 9,2 9,3 9,4 9,5 9,6 9,7 9,8 9,9
}

impl From<&FunctionType> for FunctionType {
fn from(as_ref: &FunctionType) -> Self {
as_ref.clone()
}
}

/// Indicator of whether a global is mutable or not
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
Expand Down
18 changes: 9 additions & 9 deletions tests/compilers/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,22 @@ fn dynamic_function() -> Result<()> {
&module,
&imports! {
"host" => {
"0" => Function::new(&store, &FunctionType::new(vec![], vec![]), |_values| {
"0" => Function::new(&store, FunctionType::new(vec![], vec![]), |_values| {
assert_eq!(HITS.fetch_add(1, SeqCst), 0);
Ok(vec![])
}),
"1" => Function::new(&store, &FunctionType::new(vec![ValType::I32], vec![ValType::I32]), |values| {
"1" => Function::new(&store, FunctionType::new(vec![ValType::I32], vec![ValType::I32]), |values| {
assert_eq!(values[0], Value::I32(0));
assert_eq!(HITS.fetch_add(1, SeqCst), 1);
Ok(vec![Value::I32(1)])
}),
"2" => Function::new(&store, &FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), |values| {
"2" => Function::new(&store, FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), |values| {
assert_eq!(values[0], Value::I32(2));
assert_eq!(values[1], Value::I64(3));
assert_eq!(HITS.fetch_add(1, SeqCst), 2);
Ok(vec![])
}),
"3" => Function::new(&store, &FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), |values| {
"3" => Function::new(&store, FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), |values| {
assert_eq!(values[0], Value::I32(100));
assert_eq!(values[1], Value::I64(200));
assert_eq!(values[2], Value::I32(300));
Expand Down Expand Up @@ -107,22 +107,22 @@ fn dynamic_function_with_env() -> Result<()> {
&module,
&imports! {
"host" => {
"0" => Function::new_with_env(&store, &FunctionType::new(vec![], vec![]), env.clone(), |env, _values| {
"0" => Function::new_with_env(&store, FunctionType::new(vec![], vec![]), env.clone(), |env, _values| {
assert_eq!(env.fetch_add(1, SeqCst), 0);
Ok(vec![])
}),
"1" => Function::new_with_env(&store, &FunctionType::new(vec![ValType::I32], vec![ValType::I32]), env.clone(), |env, values| {
"1" => Function::new_with_env(&store, FunctionType::new(vec![ValType::I32], vec![ValType::I32]), env.clone(), |env, values| {
assert_eq!(values[0], Value::I32(0));
assert_eq!(env.fetch_add(1, SeqCst), 1);
Ok(vec![Value::I32(1)])
}),
"2" => Function::new_with_env(&store, &FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), env.clone(), |env, values| {
"2" => Function::new_with_env(&store, FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), env.clone(), |env, values| {
assert_eq!(values[0], Value::I32(2));
assert_eq!(values[1], Value::I64(3));
assert_eq!(env.fetch_add(1, SeqCst), 2);
Ok(vec![])
}),
"3" => Function::new_with_env(&store, &FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), env.clone(), |env, values| {
"3" => Function::new_with_env(&store, FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), env.clone(), |env, values| {
assert_eq!(values[0], Value::I32(100));
assert_eq!(values[1], Value::I64(200));
assert_eq!(values[2], Value::I32(300));
Expand Down Expand Up @@ -332,7 +332,7 @@ fn dynamic_function_with_env_wasmer_env_init_works() -> Result<()> {
&module,
&imports! {
"host" => {
"fn" => Function::new_with_env(&store, &FunctionType::new(vec![], vec![]), env.clone(), |env, _values| {
"fn" => Function::new_with_env(&store, FunctionType::new(vec![], vec![]), env.clone(), |env, _values| {
assert!(env.memory_ref().is_some());
Ok(vec![])
}),
Expand Down
6 changes: 3 additions & 3 deletions tests/compilers/native_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ fn native_function_works_for_wasm_function_manyparams_dynamic() -> Result<()> {

let import_object = imports! {
"env" => {
"longf" => Function::new(&store, &FunctionType::new(vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I64 , ValType::I64 ,ValType::I32, ValType::I32], vec![ValType::I64]), long_f_dynamic),
"longf" => Function::new(&store, FunctionType::new(vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I64 , ValType::I64 ,ValType::I32, ValType::I32], vec![ValType::I64]), long_f_dynamic),
},
};

Expand Down Expand Up @@ -377,7 +377,7 @@ fn dynamic_host_function_without_env() -> anyhow::Result<()> {

let f = Function::new(
&store,
&FunctionType::new(
FunctionType::new(
vec![ValType::I32, ValType::I64, ValType::F32, ValType::F64],
vec![ValType::F64, ValType::F32, ValType::I64, ValType::I32],
),
Expand Down Expand Up @@ -415,7 +415,7 @@ fn dynamic_host_function_with_env() -> anyhow::Result<()> {
let env = Env(Rc::new(RefCell::new(100)));
let f = Function::new_with_env(
&store,
&FunctionType::new(
FunctionType::new(
vec![ValType::I32, ValType::I64, ValType::F32, ValType::F64],
vec![ValType::F64, ValType::F32, ValType::I64, ValType::I32],
),
Expand Down

0 comments on commit 69f834a

Please sign in to comment.