mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 21:51:32 +00:00
Initial typed func rewrite
This commit is contained in:
@ -9,7 +9,7 @@ use crate::{
|
|||||||
module::{ExportIndex, Module, ModuleInner},
|
module::{ExportIndex, Module, ModuleInner},
|
||||||
sig_registry::SigRegistry,
|
sig_registry::SigRegistry,
|
||||||
table::Table,
|
table::Table,
|
||||||
typed_func::{Func, Safe, WasmTypeList},
|
typed_func::{Func, Wasm, WasmTypeList},
|
||||||
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value},
|
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
@ -107,7 +107,7 @@ impl Instance {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn func<Args, Rets>(&self, name: &str) -> ResolveResult<Func<Args, Rets, Safe>>
|
pub fn func<Args, Rets>(&self, name: &str) -> ResolveResult<Func<Args, Rets, Wasm>>
|
||||||
where
|
where
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
@ -157,8 +157,8 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let typed_func: Func<Args, Rets, Safe> =
|
let typed_func: Func<Args, Rets, Wasm> =
|
||||||
unsafe { Func::new_from_ptr(func_ptr as _, ctx) };
|
unsafe { Func::from_raw_parts(trampoline, invoke, f as _, ctx, invoke_env) };
|
||||||
|
|
||||||
Ok(typed_func)
|
Ok(typed_func)
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,24 +6,79 @@ use crate::{
|
|||||||
types::{FuncSig, Type, WasmExternType},
|
types::{FuncSig, Type, WasmExternType},
|
||||||
vm::Ctx,
|
vm::Ctx,
|
||||||
};
|
};
|
||||||
use std::{any::Any, cell::UnsafeCell, marker::PhantomData, mem, panic, ptr, sync::Arc};
|
use std::{
|
||||||
|
any::Any, cell::UnsafeCell, ffi::c_void, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub static EARLY_TRAPPER: UnsafeCell<Option<Box<dyn UserTrapper>>> = UnsafeCell::new(None);
|
pub static EARLY_TRAPPER: UnsafeCell<Option<Box<dyn UserTrapper>>> = UnsafeCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Safeness {}
|
#[repr(C)]
|
||||||
pub struct Safe;
|
pub enum WasmTrapInfo {
|
||||||
pub struct Unsafe;
|
Unreachable = 0,
|
||||||
impl Safeness for Safe {}
|
IncorrectCallIndirectSignature = 1,
|
||||||
impl Safeness for Unsafe {}
|
MemoryOutOfBounds = 2,
|
||||||
|
CallIndirectOOB = 3,
|
||||||
|
IllegalArithmetic = 4,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for WasmTrapInfo {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
WasmTrapInfo::Unreachable => "unreachable",
|
||||||
|
WasmTrapInfo::IncorrectCallIndirectSignature => {
|
||||||
|
"incorrect `call_indirect` signature"
|
||||||
|
}
|
||||||
|
WasmTrapInfo::MemoryOutOfBounds => "memory out-of-bounds access",
|
||||||
|
WasmTrapInfo::CallIndirectOOB => "`call_indirect` out-of-bounds",
|
||||||
|
WasmTrapInfo::IllegalArithmetic => "illegal arithmetic operation",
|
||||||
|
WasmTrapInfo::Unknown => "unknown",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Kind {}
|
||||||
|
|
||||||
|
type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
|
||||||
|
type Invoke = extern "C" fn(
|
||||||
|
Trampoline,
|
||||||
|
*mut Ctx,
|
||||||
|
*const c_void,
|
||||||
|
*const u64,
|
||||||
|
*mut u64,
|
||||||
|
&mut WasmTrapInfo,
|
||||||
|
) -> bool;
|
||||||
|
|
||||||
|
pub struct Wasm {
|
||||||
|
trampoline: Trampoline,
|
||||||
|
invoke: Invoke,
|
||||||
|
invoke_env: *mut c_void,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Host(());
|
||||||
|
impl Kind for Wasm {}
|
||||||
|
impl Kind for Host {}
|
||||||
|
|
||||||
pub trait WasmTypeList {
|
pub trait WasmTypeList {
|
||||||
type CStruct;
|
type CStruct;
|
||||||
|
type RetArray: AsMut<[u64]>;
|
||||||
|
fn from_ret_array(array: Self::RetArray) -> Self;
|
||||||
|
fn empty_ret_array() -> Self::RetArray;
|
||||||
fn from_c_struct(c_struct: Self::CStruct) -> Self;
|
fn from_c_struct(c_struct: Self::CStruct) -> Self;
|
||||||
fn into_c_struct(self) -> Self::CStruct;
|
fn into_c_struct(self) -> Self::CStruct;
|
||||||
fn types() -> &'static [Type];
|
fn types() -> &'static [Type];
|
||||||
unsafe fn call<Rets>(self, f: *const (), ctx: *mut Ctx) -> Rets
|
unsafe fn call<Rets>(
|
||||||
|
self,
|
||||||
|
f: *const c_void,
|
||||||
|
wasm: Wasm,
|
||||||
|
ctx: *mut Ctx,
|
||||||
|
) -> Result<Rets, WasmTrapInfo>
|
||||||
where
|
where
|
||||||
Rets: WasmTypeList;
|
Rets: WasmTypeList;
|
||||||
}
|
}
|
||||||
@ -33,7 +88,7 @@ where
|
|||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
fn to_raw(&self) -> *const ();
|
fn to_raw(&self) -> *const c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TrapEarly<Rets>
|
pub trait TrapEarly<Rets>
|
||||||
@ -71,19 +126,31 @@ where
|
|||||||
// Func::new(f)
|
// Func::new(f)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub struct Func<'a, Args = (), Rets = (), Safety: Safeness = Safe> {
|
pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
|
||||||
f: *const (),
|
inner: Inner,
|
||||||
|
f: *const c_void,
|
||||||
ctx: *mut Ctx,
|
ctx: *mut Ctx,
|
||||||
_phantom: PhantomData<(&'a (), Safety, Args, Rets)>,
|
_phantom: PhantomData<(&'a (), Args, Rets)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Args, Rets> Func<'a, Args, Rets, Safe>
|
impl<'a, Args, Rets> Func<'a, Args, Rets, Wasm>
|
||||||
where
|
where
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
pub(crate) unsafe fn new_from_ptr(f: *const (), ctx: *mut Ctx) -> Func<'a, Args, Rets, Safe> {
|
pub(crate) unsafe fn from_raw_parts(
|
||||||
|
trampoline: Trampoline,
|
||||||
|
invoke: Invoke,
|
||||||
|
f: *const c_void,
|
||||||
|
ctx: *mut Ctx,
|
||||||
|
invoke_env: *mut c_void,
|
||||||
|
) -> Func<'a, Args, Rets, Wasm> {
|
||||||
Func {
|
Func {
|
||||||
|
inner: Wasm {
|
||||||
|
trampoline,
|
||||||
|
invoke,
|
||||||
|
invoke_env,
|
||||||
|
},
|
||||||
f,
|
f,
|
||||||
ctx,
|
ctx,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
@ -91,16 +158,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Args, Rets> Func<'a, Args, Rets, Unsafe>
|
impl<'a, Args, Rets> Func<'a, Args, Rets, Host>
|
||||||
where
|
where
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
pub fn new<F>(f: F) -> Func<'a, Args, Rets, Unsafe>
|
pub fn new<F>(f: F) -> Func<'a, Args, Rets, Host>
|
||||||
where
|
where
|
||||||
F: ExternalFunction<Args, Rets>,
|
F: ExternalFunction<Args, Rets>,
|
||||||
{
|
{
|
||||||
Func {
|
Func {
|
||||||
|
inner: Host(()),
|
||||||
f: f.to_raw(),
|
f: f.to_raw(),
|
||||||
ctx: ptr::null_mut(),
|
ctx: ptr::null_mut(),
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
@ -108,11 +176,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Args, Rets, Safety> Func<'a, Args, Rets, Safety>
|
impl<'a, Args, Rets, Inner> Func<'a, Args, Rets, Inner>
|
||||||
where
|
where
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
Safety: Safeness,
|
Inner: Kind,
|
||||||
{
|
{
|
||||||
pub fn params(&self) -> &'static [Type] {
|
pub fn params(&self) -> &'static [Type] {
|
||||||
Args::types()
|
Args::types()
|
||||||
@ -124,6 +192,13 @@ where
|
|||||||
|
|
||||||
impl<A: WasmExternType> WasmTypeList for (A,) {
|
impl<A: WasmExternType> WasmTypeList for (A,) {
|
||||||
type CStruct = S1<A>;
|
type CStruct = S1<A>;
|
||||||
|
type RetArray = [u64; 1];
|
||||||
|
fn from_ret_array(array: Self::RetArray) -> Self {
|
||||||
|
(WasmExternType::from_bits(array[0]),)
|
||||||
|
}
|
||||||
|
fn empty_ret_array() -> Self::RetArray {
|
||||||
|
[0u64]
|
||||||
|
}
|
||||||
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
||||||
let S1(a) = c_struct;
|
let S1(a) = c_struct;
|
||||||
(a,)
|
(a,)
|
||||||
@ -137,19 +212,45 @@ impl<A: WasmExternType> WasmTypeList for (A,) {
|
|||||||
&[A::TYPE]
|
&[A::TYPE]
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe fn call<Rets: WasmTypeList>(self, f: *const (), ctx: *mut Ctx) -> Rets {
|
unsafe fn call<Rets: WasmTypeList>(
|
||||||
let f: extern "C" fn(*mut Ctx, A) -> Rets = mem::transmute(f);
|
self,
|
||||||
|
f: *const c_void,
|
||||||
|
wasm: Wasm,
|
||||||
|
ctx: *mut Ctx,
|
||||||
|
) -> Result<Rets, WasmTrapInfo> {
|
||||||
|
// type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
|
||||||
|
// type Invoke = extern "C" fn(Trampoline, *mut Ctx, *const c_void, *const u64, *mut u64, &mut WasmTrapInfo) -> bool;
|
||||||
|
|
||||||
let (a,) = self;
|
let (a,) = self;
|
||||||
f(ctx, a)
|
let args = [a.to_bits()];
|
||||||
|
let mut rets = Rets::empty_ret_array();
|
||||||
|
let mut trap = WasmTrapInfo::Unknown;
|
||||||
|
|
||||||
|
if (wasm.invoke)(
|
||||||
|
wasm.trampoline,
|
||||||
|
ctx,
|
||||||
|
f,
|
||||||
|
args.as_ptr(),
|
||||||
|
rets.as_mut().as_mut_ptr(),
|
||||||
|
&mut trap,
|
||||||
|
) {
|
||||||
|
Ok(Rets::from_ret_array(rets))
|
||||||
|
} else {
|
||||||
|
Err(trap)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A: WasmExternType, Rets> Func<'a, (A,), Rets, Safe>
|
impl<'a, A: WasmExternType, Rets> Func<'a, (A,), Rets, Wasm>
|
||||||
where
|
where
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
pub fn call(&self, a: A) -> Result<Rets, RuntimeError> {
|
pub fn call(&self, a: A) -> Result<Rets, RuntimeError> {
|
||||||
Ok(unsafe { <A as WasmTypeList>::call(a, self.f, self.ctx) })
|
unsafe { <A as WasmTypeList>::call(a, self.f, self.inner, self.ctx) }.map_err(|e| {
|
||||||
|
RuntimeError::Trap {
|
||||||
|
msg: e.to_string().into(),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +261,14 @@ macro_rules! impl_traits {
|
|||||||
|
|
||||||
impl< $( $x: WasmExternType, )* > WasmTypeList for ( $( $x ),* ) {
|
impl< $( $x: WasmExternType, )* > WasmTypeList for ( $( $x ),* ) {
|
||||||
type CStruct = $struct_name<$( $x ),*>;
|
type CStruct = $struct_name<$( $x ),*>;
|
||||||
|
type RetArray = [u64; count_idents!( $( $x ),* )];
|
||||||
|
fn from_ret_array(array: Self::RetArray) -> Self {
|
||||||
|
let [ $( $x ),* ] = array;
|
||||||
|
( $( WasmExternType::from_bits($x) ),* )
|
||||||
|
}
|
||||||
|
fn empty_ret_array() -> Self::RetArray {
|
||||||
|
[0; count_idents!( $( $x ),* )]
|
||||||
|
}
|
||||||
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let $struct_name ( $( $x ),* ) = c_struct;
|
let $struct_name ( $( $x ),* ) = c_struct;
|
||||||
@ -174,18 +283,33 @@ macro_rules! impl_traits {
|
|||||||
&[$( $x::TYPE, )*]
|
&[$( $x::TYPE, )*]
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe fn call<Rets: WasmTypeList>(self, f: *const (), ctx: *mut Ctx) -> Rets {
|
unsafe fn call<Rets: WasmTypeList>(self, f: *const c_void, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, WasmTrapInfo> {
|
||||||
let f: extern fn(*mut Ctx $( ,$x )*) -> Rets::CStruct = mem::transmute(f);
|
// type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
|
||||||
|
// type Invoke = extern "C" fn(Trampoline, *mut Ctx, *const c_void, *const u64, *mut u64, &mut WasmTrapInfo) -> bool;
|
||||||
|
|
||||||
#[allow(unused_parens)]
|
#[allow(unused_parens)]
|
||||||
let ( $( $x ),* ) = self;
|
let ( $( $x ),* ) = self;
|
||||||
let c_struct = f(ctx $( ,$x )*);
|
let args = [ $( $x.to_bits() ),* ];
|
||||||
Rets::from_c_struct(c_struct)
|
let mut rets = Rets::empty_ret_array();
|
||||||
|
let mut trap = WasmTrapInfo::Unknown;
|
||||||
|
|
||||||
|
if (wasm.invoke)(wasm.trampoline, ctx, f, args.as_ptr(), rets.as_mut().as_mut_ptr(), &mut trap) {
|
||||||
|
Ok(Rets::from_ret_array(rets))
|
||||||
|
} else {
|
||||||
|
Err(trap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// let f: extern fn(*mut Ctx $( ,$x )*) -> Rets::CStruct = mem::transmute(f);
|
||||||
|
// #[allow(unused_parens)]
|
||||||
|
// let ( $( $x ),* ) = self;
|
||||||
|
// let c_struct = f(ctx $( ,$x )*);
|
||||||
|
// Rets::from_c_struct(c_struct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN {
|
impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn to_raw(&self) -> *const () {
|
fn to_raw(&self) -> *const c_void {
|
||||||
assert_eq!(mem::size_of::<Self>(), 0, "you cannot use a closure that captures state for `Func`.");
|
assert_eq!(mem::size_of::<Self>(), 0, "you cannot use a closure that captures state for `Func`.");
|
||||||
|
|
||||||
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct {
|
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct {
|
||||||
@ -209,23 +333,36 @@ macro_rules! impl_traits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wrap::<$( $x, )* Rets, Trap, Self> as *const ()
|
wrap::<$( $x, )* Rets, Trap, Self> as *const c_void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, $( $x: WasmExternType, )* Rets> Func<'a, ( $( $x ),* ), Rets, Safe>
|
impl<'a, $( $x: WasmExternType, )* Rets> Func<'a, ( $( $x ),* ), Rets, Wasm>
|
||||||
where
|
where
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
|
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
|
||||||
#[allow(unused_parens)]
|
#[allow(unused_parens)]
|
||||||
Ok(unsafe { <( $( $x ),* ) as WasmTypeList>::call(( $($x),* ), self.f, self.ctx) })
|
unsafe { <( $( $x ),* ) as WasmTypeList>::call(( $($x),* ), self.f, self.inner, self.ctx) }.map_err(|e| {
|
||||||
|
RuntimeError::Trap {
|
||||||
|
msg: e.to_string().into(),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
impl_traits!([C] S0,);
|
impl_traits!([C] S0,);
|
||||||
impl_traits!([transparent] S1, A);
|
impl_traits!([transparent] S1, A);
|
||||||
impl_traits!([C] S2, A, B);
|
impl_traits!([C] S2, A, B);
|
||||||
@ -240,11 +377,11 @@ impl_traits!([C] S10, A, B, C, D, E, F, G, H, I, J);
|
|||||||
impl_traits!([C] S11, A, B, C, D, E, F, G, H, I, J, K);
|
impl_traits!([C] S11, A, B, C, D, E, F, G, H, I, J, K);
|
||||||
impl_traits!([C] S12, A, B, C, D, E, F, G, H, I, J, K, L);
|
impl_traits!([C] S12, A, B, C, D, E, F, G, H, I, J, K, L);
|
||||||
|
|
||||||
impl<'a, Args, Rets, Safety> IsExport for Func<'a, Args, Rets, Safety>
|
impl<'a, Args, Rets, Inner> IsExport for Func<'a, Args, Rets, Inner>
|
||||||
where
|
where
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
Safety: Safeness,
|
Inner: Kind,
|
||||||
{
|
{
|
||||||
fn to_export(&self) -> Export {
|
fn to_export(&self) -> Export {
|
||||||
let func = unsafe { FuncPointer::new(self.f as _) };
|
let func = unsafe { FuncPointer::new(self.f as _) };
|
||||||
|
@ -76,37 +76,99 @@ where
|
|||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
const TYPE: Type;
|
const TYPE: Type;
|
||||||
|
fn to_bits(self) -> u64;
|
||||||
|
fn from_bits(n: u64) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl WasmExternType for i8 {
|
unsafe impl WasmExternType for i8 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for u8 {
|
unsafe impl WasmExternType for u8 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for i16 {
|
unsafe impl WasmExternType for i16 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for u16 {
|
unsafe impl WasmExternType for u16 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for i32 {
|
unsafe impl WasmExternType for i32 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for u32 {
|
unsafe impl WasmExternType for u32 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for i64 {
|
unsafe impl WasmExternType for i64 {
|
||||||
const TYPE: Type = Type::I64;
|
const TYPE: Type = Type::I64;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for u64 {
|
unsafe impl WasmExternType for u64 {
|
||||||
const TYPE: Type = Type::I64;
|
const TYPE: Type = Type::I64;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for f32 {
|
unsafe impl WasmExternType for f32 {
|
||||||
const TYPE: Type = Type::F32;
|
const TYPE: Type = Type::F32;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self.to_bits() as u64
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
f32::from_bits(n as u32)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unsafe impl WasmExternType for f64 {
|
unsafe impl WasmExternType for f64 {
|
||||||
const TYPE: Type = Type::F64;
|
const TYPE: Type = Type::F64;
|
||||||
|
fn to_bits(self) -> u64 {
|
||||||
|
self.to_bits()
|
||||||
|
}
|
||||||
|
fn from_bits(n: u64) -> Self {
|
||||||
|
f64::from_bits(n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub trait IntegerAtomic
|
// pub trait IntegerAtomic
|
||||||
|
Reference in New Issue
Block a user