Refactored common WasmTypeList implementations

This commit is contained in:
Syrus Akbary
2023-03-01 11:47:18 -08:00
parent 770bb404b1
commit 4973be5ee2
3 changed files with 167 additions and 259 deletions

View File

@@ -10,8 +10,6 @@ use crate::store::{AsStoreMut, AsStoreRef, StoreMut};
use crate::value::Value;
use crate::Extern;
use crate::TypedFunction;
use std::array::TryFromSliceError;
use std::convert::TryInto;
use std::error::Error;
use std::fmt;
use std::iter::FromIterator;
@@ -349,121 +347,6 @@ macro_rules! impl_host_function {
$c_struct_name:ident,
$( $x:ident ),* ) => {
/// A structure with a C-compatible representation that can hold a set of Wasm values.
/// This type is used by `WasmTypeList::CStruct`.
#[repr($c_struct_representation)]
pub struct $c_struct_name< $( $x ),* > ( $( <<$x as FromToNativeWasmType>::Native as NativeWasmType>::Abi ),* )
where
$( $x: FromToNativeWasmType ),*;
// Implement `WasmTypeList` for a specific tuple.
#[allow(unused_parens, dead_code)]
impl< $( $x ),* >
WasmTypeList
for
( $( $x ),* )
where
$( $x: FromToNativeWasmType ),*
{
type CStruct = $c_struct_name< $( $x ),* >;
type Array = [RawValue; count_idents!( $( $x ),* )];
fn size() -> u32 {
count_idents!( $( $x ),* ) as _
}
#[allow(unused_mut)]
#[allow(clippy::unused_unit)]
#[allow(clippy::missing_safety_doc)]
unsafe fn from_array(mut _store: &mut impl AsStoreMut, array: Self::Array) -> Self {
// Unpack items of the array.
#[allow(non_snake_case)]
let [ $( $x ),* ] = array;
// Build the tuple.
(
$(
FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_store, $x))
),*
)
}
#[allow(clippy::missing_safety_doc)]
unsafe fn from_slice(store: &mut impl AsStoreMut, slice: &[RawValue]) -> Result<Self, TryFromSliceError> {
Ok(Self::from_array(store, slice.try_into()?))
}
#[allow(unused_mut)]
#[allow(clippy::missing_safety_doc)]
unsafe fn into_array(self, mut _store: &mut impl AsStoreMut) -> Self::Array {
// Unpack items of the tuple.
#[allow(non_snake_case)]
let ( $( $x ),* ) = self;
// Build the array.
[
$(
FromToNativeWasmType::to_native($x).into_raw(_store)
),*
]
}
fn empty_array() -> Self::Array {
// Build an array initialized with `0`.
[RawValue { i32: 0 }; count_idents!( $( $x ),* )]
}
#[allow(unused_mut)]
#[allow(clippy::unused_unit)]
#[allow(clippy::missing_safety_doc)]
unsafe fn from_c_struct(mut _store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self {
// Unpack items of the C structure.
#[allow(non_snake_case)]
let $c_struct_name( $( $x ),* ) = c_struct;
(
$(
FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_store, $x))
),*
)
}
#[allow(unused_parens, non_snake_case, unused_mut)]
#[allow(clippy::missing_safety_doc)]
unsafe fn into_c_struct(self, mut _store: &mut impl AsStoreMut) -> Self::CStruct {
// Unpack items of the tuple.
let ( $( $x ),* ) = self;
// Build the C structure.
$c_struct_name(
$(
FromToNativeWasmType::to_native($x).into_abi(_store)
),*
)
}
#[allow(non_snake_case)]
unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, _ptr: *mut RawValue) {
// Unpack items of the tuple.
let $c_struct_name( $( $x ),* ) = c_struct;
let mut _n = 0;
$(
*_ptr.add(_n).cast() = $x;
_n += 1;
)*
}
fn wasm_types() -> &'static [Type] {
&[
$(
$x::Native::WASM_TYPE
),*
]
}
}
// Implement `HostFunction` for a function with a [`FunctionEnvMut`] that has the same
// arity than the tuple.
#[allow(unused_parens)]
@@ -570,18 +453,6 @@ macro_rules! impl_host_function {
};
}
// Black-magic to count the number of identifiers at compile-time.
macro_rules! count_idents {
( $($idents:ident),* ) => {
{
#[allow(dead_code, non_camel_case_types)]
enum Idents { $( $idents, )* __CountIdentsLast }
const COUNT: usize = Idents::__CountIdentsLast as usize;
COUNT
}
};
}
// Here we go! Let's generate all the C struct, `WasmTypeList`
// implementations and `HostFunction` implementations.
impl_host_function!([C] S0,);

View File

@@ -9,6 +9,7 @@ use crate::vm::{VMExternRef, VMFuncRef};
use crate::{ExternRef, Function, TypedFunction};
use std::array::TryFromSliceError;
use std::convert::Infallible;
use std::convert::TryInto;
use std::error::Error;
use crate::store::AsStoreMut;
@@ -563,6 +564,171 @@ impl WasmTypeList for Infallible {
}
}
macro_rules! impl_wasmtypelist {
( [$c_struct_representation:ident]
$c_struct_name:ident,
$( $x:ident ),* ) => {
/// A structure with a C-compatible representation that can hold a set of Wasm values.
/// This type is used by `WasmTypeList::CStruct`.
#[repr($c_struct_representation)]
pub struct $c_struct_name< $( $x ),* > ( $( <<$x as FromToNativeWasmType>::Native as NativeWasmType>::Abi ),* )
where
$( $x: FromToNativeWasmType ),*;
// Implement `WasmTypeList` for a specific tuple.
#[allow(unused_parens, dead_code)]
impl< $( $x ),* >
WasmTypeList
for
( $( $x ),* )
where
$( $x: FromToNativeWasmType ),*
{
type CStruct = $c_struct_name< $( $x ),* >;
type Array = [RawValue; count_idents!( $( $x ),* )];
fn size() -> u32 {
count_idents!( $( $x ),* ) as _
}
#[allow(unused_mut)]
#[allow(clippy::unused_unit)]
#[allow(clippy::missing_safety_doc)]
unsafe fn from_array(mut _store: &mut impl AsStoreMut, array: Self::Array) -> Self {
// Unpack items of the array.
#[allow(non_snake_case)]
let [ $( $x ),* ] = array;
// Build the tuple.
(
$(
FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_store, $x))
),*
)
}
#[allow(clippy::missing_safety_doc)]
unsafe fn from_slice(store: &mut impl AsStoreMut, slice: &[RawValue]) -> Result<Self, TryFromSliceError> {
Ok(Self::from_array(store, slice.try_into()?))
}
#[allow(unused_mut)]
#[allow(clippy::missing_safety_doc)]
unsafe fn into_array(self, mut _store: &mut impl AsStoreMut) -> Self::Array {
// Unpack items of the tuple.
#[allow(non_snake_case)]
let ( $( $x ),* ) = self;
// Build the array.
[
$(
FromToNativeWasmType::to_native($x).into_raw(_store)
),*
]
}
fn empty_array() -> Self::Array {
// Build an array initialized with `0`.
[RawValue { i32: 0 }; count_idents!( $( $x ),* )]
}
#[allow(unused_mut)]
#[allow(clippy::unused_unit)]
#[allow(clippy::missing_safety_doc)]
unsafe fn from_c_struct(mut _store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self {
// Unpack items of the C structure.
#[allow(non_snake_case)]
let $c_struct_name( $( $x ),* ) = c_struct;
(
$(
FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_store, $x))
),*
)
}
#[allow(unused_parens, non_snake_case, unused_mut)]
#[allow(clippy::missing_safety_doc)]
unsafe fn into_c_struct(self, mut _store: &mut impl AsStoreMut) -> Self::CStruct {
// Unpack items of the tuple.
let ( $( $x ),* ) = self;
// Build the C structure.
$c_struct_name(
$(
FromToNativeWasmType::to_native($x).into_abi(_store)
),*
)
}
#[allow(non_snake_case)]
unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, _ptr: *mut RawValue) {
// Unpack items of the tuple.
let $c_struct_name( $( $x ),* ) = c_struct;
let mut _n = 0;
$(
*_ptr.add(_n).cast() = $x;
_n += 1;
)*
}
fn wasm_types() -> &'static [Type] {
&[
$(
$x::Native::WASM_TYPE
),*
]
}
}
};
}
// Black-magic to count the number of identifiers at compile-time.
macro_rules! count_idents {
( $($idents:ident),* ) => {
{
#[allow(dead_code, non_camel_case_types)]
enum Idents { $( $idents, )* __CountIdentsLast }
const COUNT: usize = Idents::__CountIdentsLast as usize;
COUNT
}
};
}
// Here we go! Let's generate all the C struct and `WasmTypeList`
// implementations.
impl_wasmtypelist!([C] S0,);
impl_wasmtypelist!([transparent] S1, A1);
impl_wasmtypelist!([C] S2, A1, A2);
impl_wasmtypelist!([C] S3, A1, A2, A3);
impl_wasmtypelist!([C] S4, A1, A2, A3, A4);
impl_wasmtypelist!([C] S5, A1, A2, A3, A4, A5);
impl_wasmtypelist!([C] S6, A1, A2, A3, A4, A5, A6);
impl_wasmtypelist!([C] S7, A1, A2, A3, A4, A5, A6, A7);
impl_wasmtypelist!([C] S8, A1, A2, A3, A4, A5, A6, A7, A8);
impl_wasmtypelist!([C] S9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
impl_wasmtypelist!([C] S10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
impl_wasmtypelist!([C] S11, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
impl_wasmtypelist!([C] S12, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
impl_wasmtypelist!([C] S13, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
impl_wasmtypelist!([C] S14, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
impl_wasmtypelist!([C] S15, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
impl_wasmtypelist!([C] S16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
impl_wasmtypelist!([C] S17, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
impl_wasmtypelist!([C] S18, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18);
impl_wasmtypelist!([C] S19, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19);
impl_wasmtypelist!([C] S20, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20);
impl_wasmtypelist!([C] S21, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21);
impl_wasmtypelist!([C] S22, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22);
impl_wasmtypelist!([C] S23, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23);
impl_wasmtypelist!([C] S24, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24);
impl_wasmtypelist!([C] S25, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25);
impl_wasmtypelist!([C] S26, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26);
#[cfg(test)]
mod test_wasm_type_list {
use super::*;

View File

@@ -3,11 +3,9 @@ use crate::native_type::{FromToNativeWasmType, IntoResult, NativeWasmTypeInto, W
use crate::store::{AsStoreMut, AsStoreRef, StoreInner, StoreMut};
use crate::vm::VMExternFunction;
use crate::{FunctionEnv, FunctionEnvMut, FunctionType, RuntimeError, Value};
use std::array::TryFromSliceError;
use std::convert::TryInto;
use std::panic::{self, AssertUnwindSafe};
use std::{cell::UnsafeCell, cmp::max, ffi::c_void};
use wasmer_types::{NativeWasmType, RawValue, Type};
use wasmer_types::{NativeWasmType, RawValue};
use wasmer_vm::{
on_host_stack, raise_user_trap, resume_panic, wasmer_call_trampoline, MaybeInstanceOwned,
StoreHandle, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMExtern, VMFuncRef,
@@ -464,121 +462,6 @@ macro_rules! impl_host_function {
$c_struct_name:ident,
$( $x:ident ),* ) => {
/// A structure with a C-compatible representation that can hold a set of Wasm values.
/// This type is used by `WasmTypeList::CStruct`.
#[repr($c_struct_representation)]
pub struct $c_struct_name< $( $x ),* > ( $( <<$x as FromToNativeWasmType>::Native as NativeWasmType>::Abi ),* )
where
$( $x: FromToNativeWasmType ),*;
// Implement `WasmTypeList` for a specific tuple.
#[allow(unused_parens, dead_code)]
impl< $( $x ),* >
WasmTypeList
for
( $( $x ),* )
where
$( $x: FromToNativeWasmType ),*
{
type CStruct = $c_struct_name< $( $x ),* >;
type Array = [RawValue; count_idents!( $( $x ),* )];
fn size() -> u32 {
count_idents!( $( $x ),* ) as _
}
#[allow(unused_mut)]
#[allow(clippy::unused_unit)]
#[allow(clippy::missing_safety_doc)]
unsafe fn from_array(mut _store: &mut impl AsStoreMut, array: Self::Array) -> Self {
// Unpack items of the array.
#[allow(non_snake_case)]
let [ $( $x ),* ] = array;
// Build the tuple.
(
$(
FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_store, $x))
),*
)
}
#[allow(clippy::missing_safety_doc)]
unsafe fn from_slice(store: &mut impl AsStoreMut, slice: &[RawValue]) -> Result<Self, TryFromSliceError> {
Ok(Self::from_array(store, slice.try_into()?))
}
#[allow(unused_mut)]
#[allow(clippy::missing_safety_doc)]
unsafe fn into_array(self, mut _store: &mut impl AsStoreMut) -> Self::Array {
// Unpack items of the tuple.
#[allow(non_snake_case)]
let ( $( $x ),* ) = self;
// Build the array.
[
$(
FromToNativeWasmType::to_native($x).into_raw(_store)
),*
]
}
fn empty_array() -> Self::Array {
// Build an array initialized with `0`.
[RawValue { i32: 0 }; count_idents!( $( $x ),* )]
}
#[allow(unused_mut)]
#[allow(clippy::unused_unit)]
#[allow(clippy::missing_safety_doc)]
unsafe fn from_c_struct(mut _store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self {
// Unpack items of the C structure.
#[allow(non_snake_case)]
let $c_struct_name( $( $x ),* ) = c_struct;
(
$(
FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_store, $x))
),*
)
}
#[allow(unused_parens, non_snake_case, unused_mut)]
#[allow(clippy::missing_safety_doc)]
unsafe fn into_c_struct(self, mut _store: &mut impl AsStoreMut) -> Self::CStruct {
// Unpack items of the tuple.
let ( $( $x ),* ) = self;
// Build the C structure.
$c_struct_name(
$(
FromToNativeWasmType::to_native($x).into_abi(_store)
),*
)
}
#[allow(non_snake_case)]
unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, _ptr: *mut RawValue) {
// Unpack items of the tuple.
let $c_struct_name( $( $x ),* ) = c_struct;
let mut _n = 0;
$(
*_ptr.add(_n).cast() = $x;
_n += 1;
)*
}
fn wasm_types() -> &'static [Type] {
&[
$(
$x::Native::WASM_TYPE
),*
]
}
}
// Implement `HostFunction` for a function with a [`FunctionEnvMut`] that has the same
// arity than the tuple.
#[allow(unused_parens)]
@@ -743,18 +626,6 @@ macro_rules! impl_host_function {
};
}
// Black-magic to count the number of identifiers at compile-time.
macro_rules! count_idents {
( $($idents:ident),* ) => {
{
#[allow(dead_code, non_camel_case_types)]
enum Idents { $( $idents, )* __CountIdentsLast }
const COUNT: usize = Idents::__CountIdentsLast as usize;
COUNT
}
};
}
// Here we go! Let's generate all the C struct, `WasmTypeList`
// implementations and `HostFunction` implementations.
impl_host_function!([C] S0,);