Store WasmFuncType in FuncType (#2365)
This commit updates `wasmtime::FuncType` to exactly store an internal `WasmFuncType` from the cranelift crates. This allows us to remove a translation layer when we are given a `FuncType` and want to get an internal cranelift type out as a result. The other major change from this commit was changing the constructor and accessors of `FuncType` to be iterator-based instead of exposing implementation details.
This commit is contained in:
@@ -54,17 +54,9 @@ pub extern "C" fn wasm_functype_new(
|
|||||||
params: &mut wasm_valtype_vec_t,
|
params: &mut wasm_valtype_vec_t,
|
||||||
results: &mut wasm_valtype_vec_t,
|
results: &mut wasm_valtype_vec_t,
|
||||||
) -> Box<wasm_functype_t> {
|
) -> Box<wasm_functype_t> {
|
||||||
let params = params
|
let params = params.take().into_iter().map(|vt| vt.unwrap().ty.clone());
|
||||||
.take()
|
let results = results.take().into_iter().map(|vt| vt.unwrap().ty.clone());
|
||||||
.into_iter()
|
let functype = FuncType::new(params, results);
|
||||||
.map(|vt| vt.unwrap().ty.clone())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let results = results
|
|
||||||
.take()
|
|
||||||
.into_iter()
|
|
||||||
.map(|vt| vt.unwrap().ty.clone())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let functype = FuncType::new(params.into_boxed_slice(), results.into_boxed_slice());
|
|
||||||
Box::new(wasm_functype_t::new(functype))
|
Box::new(wasm_functype_t::new(functype))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +66,6 @@ pub extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> &wasm_valtype_ve
|
|||||||
ft.params_cache.get_or_init(|| {
|
ft.params_cache.get_or_init(|| {
|
||||||
ft.ty
|
ft.ty
|
||||||
.params()
|
.params()
|
||||||
.iter()
|
|
||||||
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
|
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into()
|
.into()
|
||||||
@@ -87,7 +78,6 @@ pub extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> &wasm_valtype_v
|
|||||||
ft.returns_cache.get_or_init(|| {
|
ft.returns_cache.get_or_init(|| {
|
||||||
ft.ty
|
ft.ty
|
||||||
.results()
|
.results()
|
||||||
.iter()
|
|
||||||
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
|
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into()
|
.into()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub fn dummy_imports<'module>(
|
|||||||
/// Construct a dummy function for the given function type
|
/// Construct a dummy function for the given function type
|
||||||
pub fn dummy_func(store: &Store, ty: FuncType) -> Func {
|
pub fn dummy_func(store: &Store, ty: FuncType) -> Func {
|
||||||
Func::new(store, ty.clone(), move |_, _, results| {
|
Func::new(store, ty.clone(), move |_, _, results| {
|
||||||
for (ret_ty, result) in ty.results().iter().zip(results) {
|
for (ret_ty, result) in ty.results().zip(results) {
|
||||||
*result = dummy_value(ret_ty)?;
|
*result = dummy_value(ret_ty)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -33,7 +33,7 @@ pub fn dummy_func(store: &Store, ty: FuncType) -> Func {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy value for the given value type.
|
/// Construct a dummy value for the given value type.
|
||||||
pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
|
pub fn dummy_value(val_ty: ValType) -> Result<Val, Trap> {
|
||||||
Ok(match val_ty {
|
Ok(match val_ty {
|
||||||
ValType::I32 => Val::I32(0),
|
ValType::I32 => Val::I32(0),
|
||||||
ValType::I64 => Val::I64(0),
|
ValType::I64 => Val::I64(0),
|
||||||
@@ -58,19 +58,19 @@ pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a sequence of dummy values for the given types.
|
/// Construct a sequence of dummy values for the given types.
|
||||||
pub fn dummy_values(val_tys: &[ValType]) -> Result<Vec<Val>, Trap> {
|
pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Result<Vec<Val>, Trap> {
|
||||||
val_tys.iter().map(dummy_value).collect()
|
val_tys.into_iter().map(dummy_value).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy global for the given global type.
|
/// Construct a dummy global for the given global type.
|
||||||
pub fn dummy_global(store: &Store, ty: GlobalType) -> Result<Global, Trap> {
|
pub fn dummy_global(store: &Store, ty: GlobalType) -> Result<Global, Trap> {
|
||||||
let val = dummy_value(ty.content())?;
|
let val = dummy_value(ty.content().clone())?;
|
||||||
Ok(Global::new(store, ty, val).unwrap())
|
Ok(Global::new(store, ty, val).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy table for the given table type.
|
/// Construct a dummy table for the given table type.
|
||||||
pub fn dummy_table(store: &Store, ty: TableType) -> Result<Table, Trap> {
|
pub fn dummy_table(store: &Store, ty: TableType) -> Result<Table, Trap> {
|
||||||
let init_val = dummy_value(&ty.element())?;
|
let init_val = dummy_value(ty.element().clone())?;
|
||||||
Ok(Table::new(store, ty, init_val).unwrap())
|
Ok(Table::new(store, ty, init_val).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ use wasmtime_runtime::{
|
|||||||
/// // Here we need to define the type signature of our `Double` function and
|
/// // Here we need to define the type signature of our `Double` function and
|
||||||
/// // then wrap it up in a `Func`
|
/// // then wrap it up in a `Func`
|
||||||
/// let double_type = wasmtime::FuncType::new(
|
/// let double_type = wasmtime::FuncType::new(
|
||||||
/// Box::new([wasmtime::ValType::I32]),
|
/// [wasmtime::ValType::I32].iter().cloned(),
|
||||||
/// Box::new([wasmtime::ValType::I32])
|
/// [wasmtime::ValType::I32].iter().cloned(),
|
||||||
/// );
|
/// );
|
||||||
/// let double = Func::new(&store, double_type, |_, params, results| {
|
/// let double = Func::new(&store, double_type, |_, params, results| {
|
||||||
/// let mut value = params[0].unwrap_i32();
|
/// let mut value = params[0].unwrap_i32();
|
||||||
@@ -163,7 +163,7 @@ macro_rules! getters {
|
|||||||
// Verify all the paramers match the expected parameters, and that
|
// Verify all the paramers match the expected parameters, and that
|
||||||
// there are no extra parameters...
|
// there are no extra parameters...
|
||||||
let ty = self.ty();
|
let ty = self.ty();
|
||||||
let mut params = ty.params().iter().cloned();
|
let mut params = ty.params();
|
||||||
let n = 0;
|
let n = 0;
|
||||||
$(
|
$(
|
||||||
let n = n + 1;
|
let n = n + 1;
|
||||||
@@ -173,7 +173,7 @@ macro_rules! getters {
|
|||||||
ensure!(params.next().is_none(), "Type mismatch: too many arguments (expected {})", n);
|
ensure!(params.next().is_none(), "Type mismatch: too many arguments (expected {})", n);
|
||||||
|
|
||||||
// ... then do the same for the results...
|
// ... then do the same for the results...
|
||||||
let mut results = ty.results().iter().cloned();
|
let mut results = ty.results();
|
||||||
R::matches(&mut results)
|
R::matches(&mut results)
|
||||||
.context("Type mismatch in return type")?;
|
.context("Type mismatch in return type")?;
|
||||||
ensure!(results.next().is_none(), "Type mismatch: too many return values (expected 1)");
|
ensure!(results.next().is_none(), "Type mismatch: too many return values (expected 1)");
|
||||||
@@ -274,7 +274,7 @@ impl Func {
|
|||||||
let mut args: SmallVec<[Val; STACK_ARGS]> =
|
let mut args: SmallVec<[Val; STACK_ARGS]> =
|
||||||
SmallVec::with_capacity(ty_clone.params().len());
|
SmallVec::with_capacity(ty_clone.params().len());
|
||||||
let store = Store::upgrade(&store_weak).unwrap();
|
let store = Store::upgrade(&store_weak).unwrap();
|
||||||
for (i, ty) in ty_clone.params().iter().enumerate() {
|
for (i, ty) in ty_clone.params().enumerate() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let val = Val::read_value_from(&store, values_vec.add(i), ty);
|
let val = Val::read_value_from(&store, values_vec.add(i), ty);
|
||||||
args.push(val);
|
args.push(val);
|
||||||
@@ -298,7 +298,7 @@ impl Func {
|
|||||||
// produces the wrong number or wrong types of values, and we need
|
// produces the wrong number or wrong types of values, and we need
|
||||||
// to catch that here.
|
// to catch that here.
|
||||||
for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() {
|
for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() {
|
||||||
if ret.ty() != *ty {
|
if ret.ty() != ty {
|
||||||
return Err(Trap::new(
|
return Err(Trap::new(
|
||||||
"function attempted to return an incompatible value",
|
"function attempted to return an incompatible value",
|
||||||
));
|
));
|
||||||
@@ -596,9 +596,9 @@ impl Func {
|
|||||||
let mut values_vec = vec![0; max(params.len(), my_ty.results().len())];
|
let mut values_vec = vec![0; max(params.len(), my_ty.results().len())];
|
||||||
|
|
||||||
// Store the argument values into `values_vec`.
|
// Store the argument values into `values_vec`.
|
||||||
let param_tys = my_ty.params().iter();
|
let param_tys = my_ty.params();
|
||||||
for ((arg, slot), ty) in params.iter().cloned().zip(&mut values_vec).zip(param_tys) {
|
for ((arg, slot), ty) in params.iter().cloned().zip(&mut values_vec).zip(param_tys) {
|
||||||
if arg.ty() != *ty {
|
if arg.ty() != ty {
|
||||||
bail!(
|
bail!(
|
||||||
"argument type mismatch: found {} but expected {}",
|
"argument type mismatch: found {} but expected {}",
|
||||||
arg.ty(),
|
arg.ty(),
|
||||||
@@ -628,7 +628,7 @@ impl Func {
|
|||||||
|
|
||||||
// Load the return values out of `values_vec`.
|
// Load the return values out of `values_vec`.
|
||||||
let mut results = Vec::with_capacity(my_ty.results().len());
|
let mut results = Vec::with_capacity(my_ty.results().len());
|
||||||
for (index, ty) in my_ty.results().iter().enumerate() {
|
for (index, ty) in my_ty.results().enumerate() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = values_vec.as_ptr().add(index);
|
let ptr = values_vec.as_ptr().add(index);
|
||||||
results.push(Val::read_value_from(&self.instance.store, ptr, ty));
|
results.push(Val::read_value_from(&self.instance.store, ptr, ty));
|
||||||
@@ -876,7 +876,7 @@ pub unsafe trait WasmTy {
|
|||||||
|
|
||||||
// Add this type to the given vec of expected valtypes.
|
// Add this type to the given vec of expected valtypes.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn push(dst: &mut Vec<ValType>);
|
fn valtype() -> Option<ValType>;
|
||||||
|
|
||||||
// Does the next valtype(s) match this type?
|
// Does the next valtype(s) match this type?
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -923,7 +923,7 @@ pub unsafe trait WasmRet {
|
|||||||
|
|
||||||
// Same as `WasmTy::push`.
|
// Same as `WasmTy::push`.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn push(dst: &mut Vec<ValType>);
|
fn valtype() -> Option<ValType>;
|
||||||
|
|
||||||
// Same as `WasmTy::matches`.
|
// Same as `WasmTy::matches`.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -952,7 +952,9 @@ unsafe impl WasmTy for () {
|
|||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_abi<'a>(_abi: Self::Abi, _store: WeakStore<'a>) -> Self {}
|
unsafe fn from_abi<'a>(_abi: Self::Abi, _store: WeakStore<'a>) -> Self {}
|
||||||
|
|
||||||
fn push(_dst: &mut Vec<ValType>) {}
|
fn valtype() -> Option<ValType> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn matches(_tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(_tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -983,8 +985,8 @@ unsafe impl WasmTy for i32 {
|
|||||||
abi
|
abi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
dst.push(ValType::I32);
|
Some(ValType::I32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1028,8 +1030,8 @@ unsafe impl WasmTy for u32 {
|
|||||||
abi as Self
|
abi as Self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
<i32 as WasmTy>::push(dst)
|
<i32 as WasmTy>::valtype()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1065,8 +1067,8 @@ unsafe impl WasmTy for i64 {
|
|||||||
abi
|
abi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
dst.push(ValType::I64);
|
Some(ValType::I64)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1110,8 +1112,8 @@ unsafe impl WasmTy for u64 {
|
|||||||
abi as Self
|
abi as Self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
<i64 as WasmTy>::push(dst)
|
<i64 as WasmTy>::valtype()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1147,8 +1149,8 @@ unsafe impl WasmTy for f32 {
|
|||||||
abi
|
abi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
dst.push(ValType::F32);
|
Some(ValType::F32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1192,8 +1194,8 @@ unsafe impl WasmTy for f64 {
|
|||||||
abi
|
abi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
dst.push(ValType::F64);
|
Some(ValType::F64)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1254,8 +1256,8 @@ unsafe impl WasmTy for Option<ExternRef> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
dst.push(ValType::ExternRef);
|
Some(ValType::ExternRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1307,8 +1309,8 @@ unsafe impl WasmTy for Option<Func> {
|
|||||||
Func::from_caller_checked_anyfunc(&store, abi)
|
Func::from_caller_checked_anyfunc(&store, abi)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
dst.push(ValType::FuncRef);
|
Some(ValType::FuncRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1353,9 +1355,8 @@ where
|
|||||||
<Self as WasmTy>::from_abi(abi, store)
|
<Self as WasmTy>::from_abi(abi, store)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn valtype() -> Option<ValType> {
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
<Self as WasmTy>::valtype()
|
||||||
<Self as WasmTy>::push(dst)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1405,8 +1406,8 @@ where
|
|||||||
Ok(<T as WasmTy>::from_abi(abi, store))
|
Ok(<T as WasmTy>::from_abi(abi, store))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(dst: &mut Vec<ValType>) {
|
fn valtype() -> Option<ValType> {
|
||||||
<T as WasmTy>::push(dst)
|
<T as WasmTy>::valtype()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
|
||||||
@@ -1657,11 +1658,12 @@ macro_rules! impl_into_func {
|
|||||||
R::store_to_args(ret, args);
|
R::store_to_args(ret, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut _args = Vec::new();
|
let ty = FuncType::new(
|
||||||
$($args::push(&mut _args);)*
|
None::<ValType>.into_iter()
|
||||||
let mut ret = Vec::new();
|
$(.chain($args::valtype()))*
|
||||||
R::push(&mut ret);
|
,
|
||||||
let ty = FuncType::new(_args.into(), ret.into());
|
R::valtype(),
|
||||||
|
);
|
||||||
|
|
||||||
let store_weak = store.weak();
|
let store_weak = store.weak();
|
||||||
let trampoline = host_trampoline::<$($args,)* R>;
|
let trampoline = host_trampoline::<$($args,)* R>;
|
||||||
|
|||||||
@@ -716,7 +716,7 @@ impl Linker {
|
|||||||
// Otherwise return a no-op function.
|
// Otherwise return a no-op function.
|
||||||
Ok(Func::new(
|
Ok(Func::new(
|
||||||
&self.store,
|
&self.store,
|
||||||
FuncType::new(Vec::new().into_boxed_slice(), Vec::new().into_boxed_slice()),
|
FuncType::new(None, None),
|
||||||
move |_, _, _| Ok(()),
|
move |_, _, _| Ok(()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ pub fn create_handle_with_function(
|
|||||||
|
|
||||||
let pointer_type = isa.pointer_type();
|
let pointer_type = isa.pointer_type();
|
||||||
let sig = ft.get_wasmtime_signature(pointer_type);
|
let sig = ft.get_wasmtime_signature(pointer_type);
|
||||||
let wft = ft.to_wasm_func_type();
|
let wft = ft.as_wasm_func_type();
|
||||||
|
|
||||||
let mut fn_builder_ctx = FunctionBuilderContext::new();
|
let mut fn_builder_ctx = FunctionBuilderContext::new();
|
||||||
let mut module = Module::new();
|
let mut module = Module::new();
|
||||||
@@ -241,7 +241,7 @@ pub fn create_handle_with_function(
|
|||||||
&sig,
|
&sig,
|
||||||
mem::size_of::<u128>(),
|
mem::size_of::<u128>(),
|
||||||
)?;
|
)?;
|
||||||
store.signatures().borrow_mut().register(&wft, trampoline);
|
store.signatures().borrow_mut().register(wft, trampoline);
|
||||||
|
|
||||||
// Next up we wrap everything up into an `InstanceHandle` by publishing our
|
// Next up we wrap everything up into an `InstanceHandle` by publishing our
|
||||||
// code memory (makes it executable) and ensuring all our various bits of
|
// code memory (makes it executable) and ensuring all our various bits of
|
||||||
@@ -265,7 +265,7 @@ pub unsafe fn create_handle_with_raw_function(
|
|||||||
store: &Store,
|
store: &Store,
|
||||||
state: Box<dyn Any>,
|
state: Box<dyn Any>,
|
||||||
) -> Result<StoreInstanceHandle> {
|
) -> Result<StoreInstanceHandle> {
|
||||||
let wft = ft.to_wasm_func_type();
|
let wft = ft.as_wasm_func_type();
|
||||||
|
|
||||||
let mut module = Module::new();
|
let mut module = Module::new();
|
||||||
let mut finished_functions = PrimaryMap::new();
|
let mut finished_functions = PrimaryMap::new();
|
||||||
@@ -276,7 +276,7 @@ pub unsafe fn create_handle_with_raw_function(
|
|||||||
.exports
|
.exports
|
||||||
.insert(String::new(), EntityIndex::Function(func_id));
|
.insert(String::new(), EntityIndex::Function(func_id));
|
||||||
finished_functions.push(func);
|
finished_functions.push(func);
|
||||||
store.signatures().borrow_mut().register(&wft, trampoline);
|
store.signatures().borrow_mut().register(wft, trampoline);
|
||||||
|
|
||||||
create_handle(module, store, finished_functions, state, &[])
|
create_handle(module, store, finished_functions, state, &[])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use wasmtime_environ::wasm::WasmFuncType;
|
||||||
use wasmtime_environ::{ir, wasm, EntityIndex};
|
use wasmtime_environ::{ir, wasm, EntityIndex};
|
||||||
|
|
||||||
// Type Representations
|
// Type Representations
|
||||||
@@ -217,8 +218,7 @@ impl From<TableType> for ExternType {
|
|||||||
/// WebAssembly functions can have 0 or more parameters and results.
|
/// WebAssembly functions can have 0 or more parameters and results.
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct FuncType {
|
pub struct FuncType {
|
||||||
params: Box<[ValType]>,
|
sig: WasmFuncType,
|
||||||
results: Box<[ValType]>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncType {
|
impl FuncType {
|
||||||
@@ -226,25 +226,30 @@ impl FuncType {
|
|||||||
///
|
///
|
||||||
/// The function descriptor returned will represent a function which takes
|
/// The function descriptor returned will represent a function which takes
|
||||||
/// `params` as arguments and returns `results` when it is finished.
|
/// `params` as arguments and returns `results` when it is finished.
|
||||||
pub fn new(params: Box<[ValType]>, results: Box<[ValType]>) -> FuncType {
|
pub fn new(
|
||||||
FuncType { params, results }
|
params: impl IntoIterator<Item = ValType>,
|
||||||
|
results: impl IntoIterator<Item = ValType>,
|
||||||
|
) -> FuncType {
|
||||||
|
FuncType {
|
||||||
|
sig: WasmFuncType {
|
||||||
|
params: params.into_iter().map(|t| t.to_wasm_type()).collect(),
|
||||||
|
returns: results.into_iter().map(|t| t.to_wasm_type()).collect(),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the list of parameter types for this function.
|
/// Returns the list of parameter types for this function.
|
||||||
pub fn params(&self) -> &[ValType] {
|
pub fn params(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
|
||||||
&self.params
|
self.sig.params.iter().map(ValType::from_wasm_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the list of result types for this function.
|
/// Returns the list of result types for this function.
|
||||||
pub fn results(&self) -> &[ValType] {
|
pub fn results(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
|
||||||
&self.results
|
self.sig.returns.iter().map(ValType::from_wasm_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_wasm_func_type(&self) -> wasm::WasmFuncType {
|
pub(crate) fn as_wasm_func_type(&self) -> &wasm::WasmFuncType {
|
||||||
wasm::WasmFuncType {
|
&self.sig
|
||||||
params: self.params.iter().map(|p| p.to_wasm_type()).collect(),
|
|
||||||
returns: self.results.iter().map(|r| r.to_wasm_type()).collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the Cranelift-compatible function signature.
|
/// Get the Cranelift-compatible function signature.
|
||||||
@@ -256,14 +261,9 @@ impl FuncType {
|
|||||||
AbiParam::special(pointer_type, ArgumentPurpose::VMContext),
|
AbiParam::special(pointer_type, ArgumentPurpose::VMContext),
|
||||||
AbiParam::new(pointer_type),
|
AbiParam::new(pointer_type),
|
||||||
];
|
];
|
||||||
params.extend(
|
params.extend(self.params().map(|p| AbiParam::new(p.get_wasmtime_type())));
|
||||||
self.params
|
|
||||||
.iter()
|
|
||||||
.map(|p| AbiParam::new(p.get_wasmtime_type())),
|
|
||||||
);
|
|
||||||
let returns = self
|
let returns = self
|
||||||
.results
|
.results()
|
||||||
.iter()
|
|
||||||
.map(|p| AbiParam::new(p.get_wasmtime_type()))
|
.map(|p| AbiParam::new(p.get_wasmtime_type()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@@ -274,24 +274,8 @@ impl FuncType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `None` if any types in the signature can't be converted to the
|
pub(crate) fn from_wasm_func_type(sig: &wasm::WasmFuncType) -> FuncType {
|
||||||
/// types in this crate, but that should very rarely happen and largely only
|
FuncType { sig: sig.clone() }
|
||||||
/// indicate a bug in our cranelift integration.
|
|
||||||
pub(crate) fn from_wasm_func_type(signature: &wasm::WasmFuncType) -> FuncType {
|
|
||||||
let params = signature
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.map(|p| ValType::from_wasm_type(p))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let results = signature
|
|
||||||
.returns
|
|
||||||
.iter()
|
|
||||||
.map(|r| ValType::from_wasm_type(r))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
FuncType {
|
|
||||||
params: params.into_boxed_slice(),
|
|
||||||
results: results.into_boxed_slice(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ impl Val {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn read_value_from(store: &Store, p: *const u128, ty: &ValType) -> Val {
|
pub(crate) unsafe fn read_value_from(store: &Store, p: *const u128, ty: ValType) -> Val {
|
||||||
match ty {
|
match ty {
|
||||||
ValType::I32 => Val::I32(ptr::read(p as *const i32)),
|
ValType::I32 => Val::I32(ptr::read(p as *const i32)),
|
||||||
ValType::I64 => Val::I64(ptr::read(p as *const i64)),
|
ValType::I64 => Val::I64(ptr::read(p as *const i64)),
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ fn main() -> Result<()> {
|
|||||||
// Create external print functions.
|
// Create external print functions.
|
||||||
println!("Creating callback...");
|
println!("Creating callback...");
|
||||||
let callback_type = FuncType::new(
|
let callback_type = FuncType::new(
|
||||||
Box::new([ValType::I32, ValType::I64]),
|
[ValType::I32, ValType::I64].iter().cloned(),
|
||||||
Box::new([ValType::I64, ValType::I32]),
|
[ValType::I64, ValType::I32].iter().cloned(),
|
||||||
);
|
);
|
||||||
let callback_func = Func::new(&store, callback_type, |_, args, results| {
|
let callback_func = Func::new(&store, callback_type, |_, args, results| {
|
||||||
println!("Calling back...");
|
println!("Calling back...");
|
||||||
|
|||||||
@@ -8,18 +8,14 @@ use wasmtime::*;
|
|||||||
const N_THREADS: i32 = 10;
|
const N_THREADS: i32 = 10;
|
||||||
const N_REPS: i32 = 3;
|
const N_REPS: i32 = 3;
|
||||||
|
|
||||||
fn print_message(_: Caller<'_>, args: &[Val], _: &mut [Val]) -> Result<(), Trap> {
|
|
||||||
println!("> Thread {} is running", args[0].unwrap_i32());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(engine: &Engine, module: Module, id: i32) -> Result<()> {
|
fn run(engine: &Engine, module: Module, id: i32) -> Result<()> {
|
||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
// Create external print functions.
|
// Create external print functions.
|
||||||
println!("Creating callback...");
|
println!("Creating callback...");
|
||||||
let callback_type = FuncType::new(Box::new([ValType::I32]), Box::new([]));
|
let callback_func = Func::wrap(&store, |arg: i32| {
|
||||||
let callback_func = Func::new(&store, callback_type, print_message);
|
println!("> Thread {} is running", arg);
|
||||||
|
});
|
||||||
|
|
||||||
let id_type = GlobalType::new(ValType::I32, Mutability::Const);
|
let id_type = GlobalType::new(ValType::I32, Mutability::Const);
|
||||||
let id_global = Global::new(&store, id_type, Val::I32(id))?;
|
let id_global = Global::new(&store, id_type, Val::I32(id))?;
|
||||||
|
|||||||
@@ -78,26 +78,26 @@ fn signatures_match() {
|
|||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
|
|
||||||
let f = Func::wrap(&store, || {});
|
let f = Func::wrap(&store, || {});
|
||||||
assert_eq!(f.ty().params(), &[]);
|
assert_eq!(f.ty().params().collect::<Vec<_>>(), &[]);
|
||||||
assert_eq!(f.param_arity(), 0);
|
assert_eq!(f.param_arity(), 0);
|
||||||
assert_eq!(f.ty().results(), &[]);
|
assert_eq!(f.ty().results().collect::<Vec<_>>(), &[]);
|
||||||
assert_eq!(f.result_arity(), 0);
|
assert_eq!(f.result_arity(), 0);
|
||||||
|
|
||||||
let f = Func::wrap(&store, || -> i32 { loop {} });
|
let f = Func::wrap(&store, || -> i32 { loop {} });
|
||||||
assert_eq!(f.ty().params(), &[]);
|
assert_eq!(f.ty().params().collect::<Vec<_>>(), &[]);
|
||||||
assert_eq!(f.ty().results(), &[ValType::I32]);
|
assert_eq!(f.ty().results().collect::<Vec<_>>(), &[ValType::I32]);
|
||||||
|
|
||||||
let f = Func::wrap(&store, || -> i64 { loop {} });
|
let f = Func::wrap(&store, || -> i64 { loop {} });
|
||||||
assert_eq!(f.ty().params(), &[]);
|
assert_eq!(f.ty().params().collect::<Vec<_>>(), &[]);
|
||||||
assert_eq!(f.ty().results(), &[ValType::I64]);
|
assert_eq!(f.ty().results().collect::<Vec<_>>(), &[ValType::I64]);
|
||||||
|
|
||||||
let f = Func::wrap(&store, || -> f32 { loop {} });
|
let f = Func::wrap(&store, || -> f32 { loop {} });
|
||||||
assert_eq!(f.ty().params(), &[]);
|
assert_eq!(f.ty().params().collect::<Vec<_>>(), &[]);
|
||||||
assert_eq!(f.ty().results(), &[ValType::F32]);
|
assert_eq!(f.ty().results().collect::<Vec<_>>(), &[ValType::F32]);
|
||||||
|
|
||||||
let f = Func::wrap(&store, || -> f64 { loop {} });
|
let f = Func::wrap(&store, || -> f64 { loop {} });
|
||||||
assert_eq!(f.ty().params(), &[]);
|
assert_eq!(f.ty().params().collect::<Vec<_>>(), &[]);
|
||||||
assert_eq!(f.ty().results(), &[ValType::F64]);
|
assert_eq!(f.ty().results().collect::<Vec<_>>(), &[ValType::F64]);
|
||||||
|
|
||||||
let f = Func::wrap(
|
let f = Func::wrap(
|
||||||
&store,
|
&store,
|
||||||
@@ -106,7 +106,7 @@ fn signatures_match() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
f.ty().params(),
|
f.ty().params().collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
ValType::F32,
|
ValType::F32,
|
||||||
ValType::F64,
|
ValType::F64,
|
||||||
@@ -117,7 +117,7 @@ fn signatures_match() {
|
|||||||
ValType::FuncRef,
|
ValType::FuncRef,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(f.ty().results(), &[ValType::F64]);
|
assert_eq!(f.ty().results().collect::<Vec<_>>(), &[ValType::F64]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -283,13 +283,13 @@ fn get_from_wrapper() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn get_from_signature() {
|
fn get_from_signature() {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let ty = FuncType::new(Box::new([]), Box::new([]));
|
let ty = FuncType::new(None, None);
|
||||||
let f = Func::new(&store, ty, |_, _, _| panic!());
|
let f = Func::new(&store, ty, |_, _, _| panic!());
|
||||||
assert!(f.get0::<()>().is_ok());
|
assert!(f.get0::<()>().is_ok());
|
||||||
assert!(f.get0::<i32>().is_err());
|
assert!(f.get0::<i32>().is_err());
|
||||||
assert!(f.get1::<i32, ()>().is_err());
|
assert!(f.get1::<i32, ()>().is_err());
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::I32]), Box::new([ValType::F64]));
|
let ty = FuncType::new(Some(ValType::I32), Some(ValType::F64));
|
||||||
let f = Func::new(&store, ty, |_, _, _| panic!());
|
let f = Func::new(&store, ty, |_, _, _| panic!());
|
||||||
assert!(f.get0::<()>().is_err());
|
assert!(f.get0::<()>().is_err());
|
||||||
assert!(f.get0::<i32>().is_err());
|
assert!(f.get0::<i32>().is_err());
|
||||||
@@ -434,7 +434,7 @@ fn caller_memory() -> anyhow::Result<()> {
|
|||||||
#[test]
|
#[test]
|
||||||
fn func_write_nothing() -> anyhow::Result<()> {
|
fn func_write_nothing() -> anyhow::Result<()> {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let ty = FuncType::new(Box::new([]), Box::new([ValType::I32]));
|
let ty = FuncType::new(None, Some(ValType::I32));
|
||||||
let f = Func::new(&store, ty, |_, _, _| Ok(()));
|
let f = Func::new(&store, ty, |_, _, _| Ok(()));
|
||||||
let err = f.call(&[]).unwrap_err().downcast::<Trap>()?;
|
let err = f.call(&[]).unwrap_err().downcast::<Trap>()?;
|
||||||
assert!(err
|
assert!(err
|
||||||
@@ -515,8 +515,8 @@ fn externref_signature_no_reference_types() -> anyhow::Result<()> {
|
|||||||
Func::new(
|
Func::new(
|
||||||
&store,
|
&store,
|
||||||
FuncType::new(
|
FuncType::new(
|
||||||
Box::new([ValType::FuncRef, ValType::ExternRef]),
|
[ValType::FuncRef, ValType::ExternRef].iter().cloned(),
|
||||||
Box::new([ValType::FuncRef, ValType::ExternRef]),
|
[ValType::FuncRef, ValType::ExternRef].iter().cloned(),
|
||||||
),
|
),
|
||||||
|_, _, _| Ok(()),
|
|_, _, _| Ok(()),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,21 +22,17 @@ fn test_import_calling_export() {
|
|||||||
let other = Rc::new(RefCell::new(None::<Func>));
|
let other = Rc::new(RefCell::new(None::<Func>));
|
||||||
let other2 = Rc::downgrade(&other);
|
let other2 = Rc::downgrade(&other);
|
||||||
|
|
||||||
let callback_func = Func::new(
|
let callback_func = Func::new(&store, FuncType::new(None, None), move |_, _, _| {
|
||||||
&store,
|
other2
|
||||||
FuncType::new(Box::new([]), Box::new([])),
|
.upgrade()
|
||||||
move |_, _, _| {
|
.unwrap()
|
||||||
other2
|
.borrow()
|
||||||
.upgrade()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("expected a function ref")
|
||||||
.borrow()
|
.call(&[])
|
||||||
.as_ref()
|
.expect("expected function not to trap");
|
||||||
.expect("expected a function ref")
|
Ok(())
|
||||||
.call(&[])
|
});
|
||||||
.expect("expected function not to trap");
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let imports = vec![callback_func.into()];
|
let imports = vec![callback_func.into()];
|
||||||
let instance =
|
let instance =
|
||||||
@@ -71,7 +67,7 @@ fn test_returns_incorrect_type() -> Result<()> {
|
|||||||
|
|
||||||
let callback_func = Func::new(
|
let callback_func = Func::new(
|
||||||
&store,
|
&store,
|
||||||
FuncType::new(Box::new([]), Box::new([ValType::I32])),
|
FuncType::new(None, Some(ValType::I32)),
|
||||||
|_, _, results| {
|
|_, _, results| {
|
||||||
// Evil! Returns I64 here instead of promised in the signature I32.
|
// Evil! Returns I64 here instead of promised in the signature I32.
|
||||||
results[0] = Val::I64(228);
|
results[0] = Val::I64(228);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
|
|||||||
let imports = [
|
let imports = [
|
||||||
Func::new(
|
Func::new(
|
||||||
&store,
|
&store,
|
||||||
FuncType::new(Box::new([]), Box::new([ValType::I32])),
|
FuncType::new(None, Some(ValType::I32)),
|
||||||
|_, params, results| {
|
|_, params, results| {
|
||||||
assert!(params.is_empty());
|
assert!(params.is_empty());
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
@@ -31,7 +31,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
|
|||||||
.into(),
|
.into(),
|
||||||
Func::new(
|
Func::new(
|
||||||
&store,
|
&store,
|
||||||
FuncType::new(Box::new([]), Box::new([ValType::F32])),
|
FuncType::new(None, Some(ValType::F32)),
|
||||||
|_, params, results| {
|
|_, params, results| {
|
||||||
assert!(params.is_empty());
|
assert!(params.is_empty());
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ fn test_trap_return() -> Result<()> {
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
let module = Module::new(store.engine(), wat)?;
|
let module = Module::new(store.engine(), wat)?;
|
||||||
let hello_type = FuncType::new(Box::new([]), Box::new([]));
|
let hello_type = FuncType::new(None, None);
|
||||||
let hello_func = Func::new(&store, hello_type, |_, _, _| Err(Trap::new("test 123")));
|
let hello_func = Func::new(&store, hello_type, |_, _, _| Err(Trap::new("test 123")));
|
||||||
|
|
||||||
let instance = Instance::new(&store, &module, &[hello_func.into()])?;
|
let instance = Instance::new(&store, &module, &[hello_func.into()])?;
|
||||||
@@ -86,7 +86,7 @@ fn test_trap_trace_cb() -> Result<()> {
|
|||||||
)
|
)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let fn_type = FuncType::new(Box::new([]), Box::new([]));
|
let fn_type = FuncType::new(None, None);
|
||||||
let fn_func = Func::new(&store, fn_type, |_, _, _| Err(Trap::new("cb throw")));
|
let fn_func = Func::new(&store, fn_type, |_, _, _| Err(Trap::new("cb throw")));
|
||||||
|
|
||||||
let module = Module::new(store.engine(), wat)?;
|
let module = Module::new(store.engine(), wat)?;
|
||||||
@@ -237,7 +237,7 @@ fn trap_start_function_import() -> Result<()> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let module = Module::new(store.engine(), &binary)?;
|
let module = Module::new(store.engine(), &binary)?;
|
||||||
let sig = FuncType::new(Box::new([]), Box::new([]));
|
let sig = FuncType::new(None, None);
|
||||||
let func = Func::new(&store, sig, |_, _, _| Err(Trap::new("user trap")));
|
let func = Func::new(&store, sig, |_, _, _| Err(Trap::new("user trap")));
|
||||||
let err = Instance::new(&store, &module, &[func.into()])
|
let err = Instance::new(&store, &module, &[func.into()])
|
||||||
.err()
|
.err()
|
||||||
@@ -267,7 +267,7 @@ fn rust_panic_import() -> Result<()> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let module = Module::new(store.engine(), &binary)?;
|
let module = Module::new(store.engine(), &binary)?;
|
||||||
let sig = FuncType::new(Box::new([]), Box::new([]));
|
let sig = FuncType::new(None, None);
|
||||||
let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic"));
|
let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic"));
|
||||||
let instance = Instance::new(
|
let instance = Instance::new(
|
||||||
&store,
|
&store,
|
||||||
@@ -311,7 +311,7 @@ fn rust_panic_start_function() -> Result<()> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let module = Module::new(store.engine(), &binary)?;
|
let module = Module::new(store.engine(), &binary)?;
|
||||||
let sig = FuncType::new(Box::new([]), Box::new([]));
|
let sig = FuncType::new(None, None);
|
||||||
let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic"));
|
let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic"));
|
||||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||||
drop(Instance::new(&store, &module, &[func.into()]));
|
drop(Instance::new(&store, &module, &[func.into()]));
|
||||||
|
|||||||
Reference in New Issue
Block a user