diff --git a/break-drop.wast b/break-drop.wast deleted file mode 100644 index e10df6671..000000000 --- a/break-drop.wast +++ /dev/null @@ -1,9 +0,0 @@ -(module - (func (export "br") (block (br 0))) - (func (export "br_if") (block (br_if 0 (i32.const 1)))) - (func (export "br_table") (block (br_table 0 (i32.const 0)))) -) - -(assert_return (invoke "br")) -(assert_return (invoke "br_if")) -(assert_return (invoke "br_table")) diff --git a/globals.wast b/globals.wast deleted file mode 100644 index 0c8f6fbda..000000000 --- a/globals.wast +++ /dev/null @@ -1,482 +0,0 @@ -;; Test globals - -(module - (global $a i32 (i32.const -2)) - (global (;1;) f32 (f32.const -3)) - (global (;2;) f64 (f64.const -4)) - (global $b i64 (i64.const -5)) - - (global $x (mut i32) (i32.const -12)) - (global (;5;) (mut f32) (f32.const -13)) - (global (;6;) (mut f64) (f64.const -14)) - (global $y (mut i64) (i64.const -15)) - - (func (export "get-a") (result i32) (global.get $a)) - (func (export "get-b") (result i64) (global.get $b)) - (func (export "get-x") (result i32) (global.get $x)) - (func (export "get-y") (result i64) (global.get $y)) - (func (export "set-x") (param i32) (global.set $x (local.get 0))) - (func (export "set-y") (param i64) (global.set $y (local.get 0))) - - (func (export "get-1") (result f32) (global.get 1)) - (func (export "get-2") (result f64) (global.get 2)) - (func (export "get-5") (result f32) (global.get 5)) - (func (export "get-6") (result f64) (global.get 6)) - (func (export "set-5") (param f32) (global.set 5 (local.get 0))) - (func (export "set-6") (param f64) (global.set 6 (local.get 0))) - - ;; As the argument of control constructs and instructions - - (memory 1) - - (func $dummy) - - (func (export "as-select-first") (result i32) - (select (global.get $x) (i32.const 2) (i32.const 3)) - ) - (func (export "as-select-mid") (result i32) - (select (i32.const 2) (global.get $x) (i32.const 3)) - ) - (func (export "as-select-last") (result i32) - (select (i32.const 2) (i32.const 3) (global.get $x)) - ) - - (func (export "as-loop-first") (result i32) - (loop (result i32) - (global.get $x) (call $dummy) (call $dummy) - ) - ) - (func (export "as-loop-mid") (result i32) - (loop (result i32) - (call $dummy) (global.get $x) (call $dummy) - ) - ) - (func (export "as-loop-last") (result i32) - (loop (result i32) - (call $dummy) (call $dummy) (global.get $x) - ) - ) - - (func (export "as-if-condition") (result i32) - (if (result i32) (global.get $x) - (then (call $dummy) (i32.const 2)) - (else (call $dummy) (i32.const 3)) - ) - ) - (func (export "as-if-then") (result i32) - (if (result i32) (i32.const 1) - (then (global.get $x)) (else (i32.const 2)) - ) - ) - (func (export "as-if-else") (result i32) - (if (result i32) (i32.const 0) - (then (i32.const 2)) (else (global.get $x)) - ) - ) - - (func (export "as-br_if-first") (result i32) - (block (result i32) - (br_if 0 (global.get $x) (i32.const 2)) - (return (i32.const 3)) - ) - ) - (func (export "as-br_if-last") (result i32) - (block (result i32) - (br_if 0 (i32.const 2) (global.get $x)) - (return (i32.const 3)) - ) - ) - - (func (export "as-br_table-first") (result i32) - (block (result i32) - (global.get $x) (i32.const 2) (br_table 0 0) - ) - ) - (func (export "as-br_table-last") (result i32) - (block (result i32) - (i32.const 2) (global.get $x) (br_table 0 0) - ) - ) - - (func $func (param i32 i32) (result i32) (local.get 0)) - (type $check (func (param i32 i32) (result i32))) - (table funcref (elem $func)) - (func (export "as-call_indirect-first") (result i32) - (block (result i32) - (call_indirect (type $check) - (global.get $x) (i32.const 2) (i32.const 0) - ) - ) - ) - (func (export "as-call_indirect-mid") (result i32) - (block (result i32) - (call_indirect (type $check) - (i32.const 2) (global.get $x) (i32.const 0) - ) - ) - ) - (func (export "as-call_indirect-last") (result i32) - (block (result i32) - (call_indirect (type $check) - (i32.const 2) (i32.const 0) (global.get $x) - ) - ) - ) - - (func (export "as-store-first") - (global.get $x) (i32.const 1) (i32.store) - ) - (func (export "as-store-last") - (i32.const 0) (global.get $x) (i32.store) - ) - (func (export "as-load-operand") (result i32) - (i32.load (global.get $x)) - ) - (func (export "as-memory.grow-value") (result i32) - (memory.grow (global.get $x)) - ) - - (func $f (param i32) (result i32) (local.get 0)) - (func (export "as-call-value") (result i32) - (call $f (global.get $x)) - ) - - (func (export "as-return-value") (result i32) - (global.get $x) (return) - ) - (func (export "as-drop-operand") - (drop (global.get $x)) - ) - (func (export "as-br-value") (result i32) - (block (result i32) (br 0 (global.get $x))) - ) - - (func (export "as-local.set-value") (param i32) (result i32) - (local.set 0 (global.get $x)) - (local.get 0) - ) - (func (export "as-local.tee-value") (param i32) (result i32) - (local.tee 0 (global.get $x)) - ) - (func (export "as-global.set-value") (result i32) - (global.set $x (global.get $x)) - (global.get $x) - ) - - (func (export "as-unary-operand") (result i32) - (i32.eqz (global.get $x)) - ) - (func (export "as-binary-operand") (result i32) - (i32.mul - (global.get $x) (global.get $x) - ) - ) - (func (export "as-compare-operand") (result i32) - (i32.gt_u - (global.get 0) (i32.const 1) - ) - ) -) - -(assert_return (invoke "get-a") (i32.const -2)) -(assert_return (invoke "get-b") (i64.const -5)) -(assert_return (invoke "get-x") (i32.const -12)) -(assert_return (invoke "get-y") (i64.const -15)) - -(assert_return (invoke "get-1") (f32.const -3)) -(assert_return (invoke "get-2") (f64.const -4)) -(assert_return (invoke "get-5") (f32.const -13)) -(assert_return (invoke "get-6") (f64.const -14)) - -(assert_return (invoke "set-x" (i32.const 6))) -(assert_return (invoke "set-y" (i64.const 7))) -(assert_return (invoke "set-5" (f32.const 8))) -(assert_return (invoke "set-6" (f64.const 9))) - -(assert_return (invoke "get-x") (i32.const 6)) -(assert_return (invoke "get-y") (i64.const 7)) -(assert_return (invoke "get-5") (f32.const 8)) -(assert_return (invoke "get-6") (f64.const 9)) - -(assert_return (invoke "as-select-first") (i32.const 6)) -(assert_return (invoke "as-select-mid") (i32.const 2)) -(assert_return (invoke "as-select-last") (i32.const 2)) - -(assert_return (invoke "as-loop-first") (i32.const 6)) -(assert_return (invoke "as-loop-mid") (i32.const 6)) -(assert_return (invoke "as-loop-last") (i32.const 6)) - -(assert_return (invoke "as-if-condition") (i32.const 2)) -(assert_return (invoke "as-if-then") (i32.const 6)) -(assert_return (invoke "as-if-else") (i32.const 6)) - -(assert_return (invoke "as-br_if-first") (i32.const 6)) -(assert_return (invoke "as-br_if-last") (i32.const 2)) - -(assert_return (invoke "as-br_table-first") (i32.const 6)) -(assert_return (invoke "as-br_table-last") (i32.const 2)) - -(assert_return (invoke "as-call_indirect-first") (i32.const 6)) -(assert_return (invoke "as-call_indirect-mid") (i32.const 2)) -(assert_trap (invoke "as-call_indirect-last") "undefined element") - -(assert_return (invoke "as-store-first")) -(assert_return (invoke "as-store-last")) -(assert_return (invoke "as-load-operand") (i32.const 1)) -(assert_return (invoke "as-memory.grow-value") (i32.const 1)) - -(assert_return (invoke "as-call-value") (i32.const 6)) - -(assert_return (invoke "as-return-value") (i32.const 6)) -(assert_return (invoke "as-drop-operand")) -(assert_return (invoke "as-br-value") (i32.const 6)) - -(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 6)) -(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 6)) -(assert_return (invoke "as-global.set-value") (i32.const 6)) - -(assert_return (invoke "as-unary-operand") (i32.const 0)) -(assert_return (invoke "as-binary-operand") (i32.const 36)) -(assert_return (invoke "as-compare-operand") (i32.const 1)) - -(assert_invalid - (module (global f32 (f32.const 0)) (func (global.set 0 (f32.const 1)))) - "global is immutable" -) - -;; mutable globals can be exported -(module (global (mut f32) (f32.const 0)) (export "a" (global 0))) -(module (global (export "a") (mut f32) (f32.const 0))) - -(assert_invalid - (module (global f32 (f32.neg (f32.const 0)))) - "constant expression required" -) - -(assert_invalid - (module (global f32 (local.get 0))) - "constant expression required" -) - -(assert_invalid - (module (global f32 (f32.neg (f32.const 1)))) - "constant expression required" -) - -(assert_invalid - (module (global i32 (i32.const 0) (nop))) - "constant expression required" -) - -(assert_invalid - (module (global i32 (nop))) - "constant expression required" -) - -(assert_invalid - (module (global i32 (f32.const 0))) - "type mismatch" -) - -(assert_invalid - (module (global i32 (i32.const 0) (i32.const 0))) - "type mismatch" -) - -(assert_invalid - (module (global i32 (;empty instruction sequence;))) - "type mismatch" -) - -(assert_invalid - (module (global i32 (global.get 0))) - "unknown global" -) - -(assert_invalid - (module (global i32 (global.get 1)) (global i32 (i32.const 0))) - "unknown global" -) - -(module - (import "spectest" "global_i32" (global i32)) -) -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\02\98\80\80\80\00" ;; import section - "\01" ;; length 1 - "\08\73\70\65\63\74\65\73\74" ;; "spectest" - "\0a\67\6c\6f\62\61\6c\5f\69\33\32" ;; "global_i32" - "\03" ;; GlobalImport - "\7f" ;; i32 - "\02" ;; invalid mutability - ) - "invalid mutability" -) -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\02\98\80\80\80\00" ;; import section - "\01" ;; length 1 - "\08\73\70\65\63\74\65\73\74" ;; "spectest" - "\0a\67\6c\6f\62\61\6c\5f\69\33\32" ;; "global_i32" - "\03" ;; GlobalImport - "\7f" ;; i32 - "\ff" ;; invalid mutability - ) - "invalid mutability" -) - -(module - (global i32 (i32.const 0)) -) -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\06\86\80\80\80\00" ;; global section - "\01" ;; length 1 - "\7f" ;; i32 - "\02" ;; invalid mutability - "\41\00" ;; i32.const 0 - "\0b" ;; end - ) - "invalid mutability" -) -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\06\86\80\80\80\00" ;; global section - "\01" ;; length 1 - "\7f" ;; i32 - "\ff" ;; invalid mutability - "\41\00" ;; i32.const 0 - "\0b" ;; end - ) - "invalid mutability" -) - - -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty - (global.set $x) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-block - (i32.const 0) - (block (global.set $x)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-loop - (i32.const 0) - (loop (global.set $x)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-then - (i32.const 0) (i32.const 0) - (if (then (global.set $x))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-else - (i32.const 0) (i32.const 0) - (if (result i32) (then (i32.const 0)) (else (global.set $x))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-br - (i32.const 0) - (block (br 0 (global.set $x))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-br_if - (i32.const 0) - (block (br_if 0 (global.set $x))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-br_table - (i32.const 0) - (block (br_table 0 (global.set $x))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-return - (return (global.set $x)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-select - (select (global.set $x) (i32.const 1) (i32.const 2)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $type-global.set-value-empty-in-call - (call 1 (global.set $x)) - ) - (func (param i32) (result i32) (local.get 0)) - ) - "type mismatch" -) -(assert_invalid - (module - (global $x (mut i32) (i32.const 0)) - (func $f (param i32) (result i32) (local.get 0)) - (type $sig (func (param i32) (result i32))) - (table funcref (elem $f)) - (func $type-global.set-value-empty-in-call_indirect - (block (result i32) - (call_indirect (type $sig) - (global.set $x) (i32.const 0) - ) - ) - ) - ) - "type mismatch" -) diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index f0acbd383..a19aa174a 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -5,7 +5,7 @@ use crate::types::Val; use crate::FunctionType; use crate::NativeFunc; use crate::RuntimeError; -pub use inner::{HostFunction, WasmExternType, WasmTypeList, WithEnv, WithoutEnv}; +pub use inner::{FromToNativeWasmType, HostFunction, WasmTypeList, WithEnv, WithoutEnv}; use std::cell::RefCell; use std::cmp::max; use wasmer_runtime::{ @@ -505,43 +505,71 @@ mod inner { use wasm_common::{FunctionType, NativeWasmType, Type}; use wasmer_runtime::{raise_user_trap, resume_panic, VMFunctionBody}; - /// A trait to represent a wasm extern type. - pub unsafe trait WasmExternType: Copy + /// A trait to convert a Rust value to a `WasmNativeType` value, + /// or to convert `WasmNativeType` value to a Rust value. + /// + /// This trait should ideally be splitted into two traits: + /// `FromNativeWasmType` and `ToNativeWasmType` but it creates a + /// non-negligeable complexity in the `WasmTypeList` + /// implementation. + pub unsafe trait FromToNativeWasmType: Copy where Self: Sized, { - /// Native wasm type for this `WasmExternType`. + /// Native Wasm type. type Native: NativeWasmType; - /// Convert from given `Native` type to self. + /// Convert a value of kind `Self::Native` to `Self`. + /// + /// # Panics + /// + /// This method panics if `native` cannot fit in the `Self` + /// type`. fn from_native(native: Self::Native) -> Self; - /// Convert self to `Native` type. + /// Convert self to `Self::Native`. + /// + /// # Panics + /// + /// This method panics if `self` cannot fit in the + /// `Self::Native` type. fn to_native(self) -> Self::Native; } - macro_rules! wasm_extern_type { + macro_rules! from_to_native_wasm_type { ( $( $type:ty => $native_type:ty ),* ) => { $( #[allow(clippy::use_self)] - unsafe impl WasmExternType for $type { + unsafe impl FromToNativeWasmType for $type { type Native = $native_type; #[inline] fn from_native(native: Self::Native) -> Self { - native as _ + native.try_into().expect(concat!( + "out of range type conversion attempt (tried to convert `", + stringify!($native_type), + "` to `", + stringify!($type), + "`)", + )) } #[inline] fn to_native(self) -> Self::Native { - self as _ + self.try_into().expect(concat!( + "out of range type conversion attempt (tried to convert `", + stringify!($type), + "` to `", + stringify!($native_type), + "`)", + )) } } )* }; } - wasm_extern_type!( + from_to_native_wasm_type!( i8 => i32, u8 => i32, i16 => i32, @@ -554,6 +582,26 @@ mod inner { f64 => f64 ); + #[cfg(test)] + mod test_from_to_native_wasm_type { + use super::*; + + #[test] + fn test_to_native() { + assert_eq!(7i8.to_native(), 7i32); + } + + #[test] + #[should_panic( + expected = "out of range type conversion attempt (tried to convert `u32` to `i32`)" + )] + fn test_to_native_panics() { + use std::{i32, u32}; + + assert_eq!(u32::MAX.to_native(), i32::MAX); + } + } + /// The `WasmTypeList` trait represents a tuple (list) of Wasm /// typed values. It is used to get low-level representation of /// such a tuple. @@ -729,9 +777,9 @@ mod inner { /// 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 WasmExternType>::Native ),* ) + pub struct $c_struct_name< $( $x ),* > ( $( <$x as FromToNativeWasmType>::Native ),* ) where - $( $x: WasmExternType ),*; + $( $x: FromToNativeWasmType ),*; // Implement `WasmTypeList` for a specific tuple. #[allow(unused_parens, dead_code)] @@ -740,7 +788,7 @@ mod inner { for ( $( $x ),* ) where - $( $x: WasmExternType ),* + $( $x: FromToNativeWasmType ),* { type CStruct = $c_struct_name< $( $x ),* >; @@ -754,7 +802,7 @@ mod inner { // Build the tuple. ( $( - WasmExternType::from_native(NativeWasmType::from_binary($x)) + FromToNativeWasmType::from_native(NativeWasmType::from_binary($x)) ),* ) } @@ -771,7 +819,7 @@ mod inner { // Build the array. [ $( - WasmExternType::to_native($x).to_binary() + FromToNativeWasmType::to_native($x).to_binary() ),* ] } @@ -788,7 +836,7 @@ mod inner { ( $( - WasmExternType::from_native($x) + FromToNativeWasmType::from_native($x) ),* ) } @@ -801,7 +849,7 @@ mod inner { // Build the C structure. $c_struct_name( $( - WasmExternType::to_native($x) + FromToNativeWasmType::to_native($x) ),* ) } @@ -823,7 +871,7 @@ mod inner { for Func where - $( $x: WasmExternType, )* + $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, Func: Fn($( $x , )*) -> RetsAsResult + 'static + Send, @@ -835,14 +883,14 @@ mod inner { /// runtime. extern fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func>( _: usize, $($x: $x::Native, )* ) -> Rets::CStruct where - $( $x: WasmExternType, )* + $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, Func: Fn( $( $x ),* ) -> RetsAsResult + 'static { let func: &Func = unsafe { &*(&() as *const () as *const Func) }; let result = panic::catch_unwind(AssertUnwindSafe(|| { - func( $( WasmExternType::from_native($x) ),* ).into_result() + func( $( FromToNativeWasmType::from_native($x) ),* ).into_result() })); match result { @@ -862,7 +910,7 @@ mod inner { for Func where - $( $x: WasmExternType, )* + $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, Env: Sized, @@ -875,7 +923,7 @@ mod inner { /// runtime. extern fn func_wrapper<$( $x, )* Rets, RetsAsResult, Env, Func>( env: &mut Env, $( $x: $x::Native, )* ) -> Rets::CStruct where - $( $x: WasmExternType, )* + $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, Env: Sized, @@ -884,7 +932,7 @@ mod inner { let func: &Func = unsafe { &*(&() as *const () as *const Func) }; let result = panic::catch_unwind(AssertUnwindSafe(|| { - func(env, $( WasmExternType::from_native($x) ),* ).into_result() + func(env, $( FromToNativeWasmType::from_native($x) ),* ).into_result() })); match result { diff --git a/lib/api/src/externals/mod.rs b/lib/api/src/externals/mod.rs index 8579c1f9d..6a48a2ec2 100644 --- a/lib/api/src/externals/mod.rs +++ b/lib/api/src/externals/mod.rs @@ -4,7 +4,7 @@ mod memory; mod table; pub use self::function::{ - Function, HostFunction, WasmExternType, WasmTypeList, WithEnv, WithoutEnv, + FromToNativeWasmType, Function, HostFunction, WasmTypeList, WithEnv, WithoutEnv, }; pub use self::global::Global; pub use self::memory::Memory; diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index d31315c05..83f383949 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -17,10 +17,18 @@ mod tunables; mod types; mod utils; +pub mod internals { + //! We use the internals module for exporting types that are only + //! intended to use in internal crates such as the compatibility crate + //! `wasmer-runtime`. Please don't use any of this types directly, as + //! they might change frequently or be removed in the future. + + pub use crate::externals::{WithEnv, WithoutEnv}; +} + pub use crate::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::externals::{ - Extern, Function, Global, HostFunction, Memory, Table, WasmExternType, WasmTypeList, WithEnv, - WithoutEnv, + Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, Table, WasmTypeList, }; pub use crate::import_object::{ImportObject, ImportObjectIterator, LikeNamespace}; pub use crate::instance::Instance; diff --git a/lib/api/src/native.rs b/lib/api/src/native.rs index cc89da9af..09616b409 100644 --- a/lib/api/src/native.rs +++ b/lib/api/src/native.rs @@ -13,7 +13,7 @@ use crate::externals::function::{ FunctionDefinition, HostFunctionDefinition, VMDynamicFunction, VMDynamicFunctionWithEnv, VMDynamicFunctionWithoutEnv, WasmFunctionDefinition, }; -use crate::{Function, FunctionType, RuntimeError, Store, WasmExternType, WasmTypeList}; +use crate::{FromToNativeWasmType, Function, FunctionType, RuntimeError, Store, WasmTypeList}; use std::panic::{catch_unwind, AssertUnwindSafe}; use wasm_common::NativeWasmType; use wasmer_runtime::{ @@ -97,7 +97,7 @@ macro_rules! impl_native_traits { #[allow(unused_parens, non_snake_case)] impl<'a $( , $x )*, Rets> NativeFunc<'a, ( $( $x ),* ), Rets> where - $( $x: WasmExternType, )* + $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, { /// Call the typed func and return results. diff --git a/lib/api/src/ptr.rs b/lib/api/src/ptr.rs index 4d181e217..52ee823f9 100644 --- a/lib/api/src/ptr.rs +++ b/lib/api/src/ptr.rs @@ -6,7 +6,7 @@ //! Therefore, you should use this abstraction whenever possible to avoid memory //! related bugs when implementing an ABI. -use crate::{externals::Memory, WasmExternType}; +use crate::{externals::Memory, FromToNativeWasmType}; use std::{cell::Cell, fmt, marker::PhantomData, mem}; use wasm_common::ValueType; @@ -218,7 +218,7 @@ impl WasmPtr { } } -unsafe impl WasmExternType for WasmPtr { +unsafe impl FromToNativeWasmType for WasmPtr { type Native = i32; fn to_native(self) -> Self::Native { diff --git a/lib/emscripten/src/ptr.rs b/lib/emscripten/src/ptr.rs index 727b3541c..54d5fada6 100644 --- a/lib/emscripten/src/ptr.rs +++ b/lib/emscripten/src/ptr.rs @@ -6,7 +6,7 @@ #![allow(dead_code)] use std::{cell::Cell, fmt}; -pub use wasmer::{Array, Memory, ValueType, WasmExternType}; +pub use wasmer::{Array, FromToNativeWasmType, Memory, ValueType}; #[repr(transparent)] pub struct WasmPtr(wasmer::WasmPtr); @@ -26,8 +26,8 @@ impl fmt::Debug for WasmPtr { } } -unsafe impl WasmExternType for WasmPtr { - type Native = as WasmExternType>::Native; +unsafe impl FromToNativeWasmType for WasmPtr { + type Native = as FromToNativeWasmType>::Native; fn to_native(self) -> Self::Native { self.0.to_native() diff --git a/lib/emscripten/src/varargs.rs b/lib/emscripten/src/varargs.rs index 72f9f16ad..09344fed2 100644 --- a/lib/emscripten/src/varargs.rs +++ b/lib/emscripten/src/varargs.rs @@ -1,6 +1,6 @@ use crate::EmEnv; use std::mem; -use wasmer::WasmExternType; +use wasmer::FromToNativeWasmType; // use std::ffi::CStr; use std::os::raw::c_char; @@ -26,7 +26,7 @@ impl VarArgs { } } -unsafe impl WasmExternType for VarArgs { +unsafe impl FromToNativeWasmType for VarArgs { type Native = i32; fn to_native(self) -> Self::Native { diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index fd43ac644..32b769175 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -175,8 +175,9 @@ impl WasiEnv { } } -/// Create an [`ImportObject`] with an existing [`WasiState`]. [`WasiState`] -/// can be constructed from a [`WasiStateBuilder`](state::WasiStateBuilder). +/// Create an [`ImportObject`] with an existing [`WasiEnv`]. `WasiEnv` +/// needs a [`WasiState`], that can be constructed from a +/// [`WasiStateBuilder`](state::WasiStateBuilder). pub fn generate_import_object_from_env( store: &Store, wasi_env: WasiEnv, diff --git a/lib/wasi/src/ptr.rs b/lib/wasi/src/ptr.rs index 86780bb98..a4c76e3e3 100644 --- a/lib/wasi/src/ptr.rs +++ b/lib/wasi/src/ptr.rs @@ -3,7 +3,7 @@ use crate::syscalls::types::{__wasi_errno_t, __WASI_EFAULT}; use std::{cell::Cell, fmt}; -pub use wasmer::{Array, Item, Memory, ValueType, WasmExternType, WasmPtr as BaseWasmPtr}; +pub use wasmer::{Array, FromToNativeWasmType, Item, Memory, ValueType, WasmPtr as BaseWasmPtr}; #[repr(transparent)] pub struct WasmPtr(BaseWasmPtr); @@ -24,8 +24,8 @@ impl fmt::Debug for WasmPtr { } } -unsafe impl WasmExternType for WasmPtr { - type Native = as WasmExternType>::Native; +unsafe impl FromToNativeWasmType for WasmPtr { + type Native = as FromToNativeWasmType>::Native; fn to_native(self) -> Self::Native { self.0.to_native() diff --git a/lib/wasm-common/src/native.rs b/lib/wasm-common/src/native.rs index 1f20993cd..846599eb8 100644 --- a/lib/wasm-common/src/native.rs +++ b/lib/wasm-common/src/native.rs @@ -3,8 +3,11 @@ use crate::types::Type; use crate::values::Value; +use std::fmt; -/// `NativeWasmType` represents a native Wasm type. +/// `NativeWasmType` represents a Wasm type that has a direct +/// representation on the host (hence the “native” term). +/// /// It uses the Rust Type system to automatically detect the /// Wasm type associated with a native Rust type. /// @@ -19,7 +22,7 @@ use crate::values::Value; /// > automatically detect the signature of a Rust function. pub trait NativeWasmType: Sized { /// The ABI for this type (i32, i64, f32, f64) - type Abi: Copy + std::fmt::Debug; + type Abi: Copy + fmt::Debug; /// Type for this `NativeWasmType`. const WASM_TYPE: Type; @@ -33,9 +36,10 @@ pub trait NativeWasmType: Sized { /// Convert self to i128 binary representation. fn to_binary(self) -> i128; - /// Convert self to a `Value` + /// Convert self to a `Value`. fn to_value(self) -> Value { let binary = self.to_binary(); + unsafe { Value::read_value_from(&binary, Self::WASM_TYPE) } } @@ -57,10 +61,12 @@ impl NativeWasmType for i32 { self } + #[inline] fn to_binary(self) -> i128 { self as _ } + #[inline] fn from_binary(bits: i128) -> Self { bits as _ } @@ -150,6 +156,14 @@ mod test_native_type { assert_eq!(f32::WASM_TYPE, Type::F32); assert_eq!(f64::WASM_TYPE, Type::F64); } + + #[test] + fn test_roundtrip() { + assert_eq!(i32::from_binary(42i32.to_binary()), 42i32); + assert_eq!(i64::from_binary(42i64.to_binary()), 42i64); + assert_eq!(f32::from_binary(42f32.to_binary()), 42f32); + assert_eq!(f64::from_binary(42f64.to_binary()), 42f64); + } } // pub trait IntegerAtomic diff --git a/src/windows-installer/wasmer.iss b/src/windows-installer/wasmer.iss index 5bdc10e9a..f16458e10 100644 --- a/src/windows-installer/wasmer.iss +++ b/src/windows-installer/wasmer.iss @@ -16,9 +16,9 @@ DisableWelcomePage=no [Registry] Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "WASMER_DIR"; \ - ValueData: "{%USERPROFILE}\.wasmer"; Flags: preservestringtype + ValueData: "{app}"; Flags: preservestringtype Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "WASMER_CACHE_DIR"; \ - ValueData: "{%USERPROFILE}\.wasmer\cache"; Flags: preservestringtype + ValueData: "{app}\cache"; Flags: preservestringtype [Files] Source: "..\..\package\bin\*"; DestDir: "{app}\bin" @@ -29,7 +29,7 @@ Source: "..\..\package\ATTRIBUTIONS"; DestDir: "{app}" Source: "wax.cmd"; DestDir: "{app}\bin" [Dirs] -Name: "{%USERPROFILE}\.wasmer" +Name: "{app}\cache" [Code] const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; @@ -81,7 +81,7 @@ begin if CurStep = ssPostInstall then begin EnvAddPath(ExpandConstant('{app}') +'\bin'); - EnvAddPath(ExpandConstant('{%USERPROFILE}') +'\globals\wapm_packages\.bin'); + EnvAddPath(ExpandConstant('{app}') +'\globals\wapm_packages\.bin'); end end; @@ -90,6 +90,6 @@ begin if CurUninstallStep = usPostUninstall then begin EnvRemovePath(ExpandConstant('{app}') +'\bin'); - EnvAddPath(ExpandConstant('{%USERPROFILE}') +'\globals\wapm_packages\.bin'); + EnvAddPath(ExpandConstant('{app}') +'\globals\wapm_packages\.bin'); end end; diff --git a/typecheck.wast b/typecheck.wast deleted file mode 100644 index 13c00d843..000000000 --- a/typecheck.wast +++ /dev/null @@ -1,212 +0,0 @@ -;; TODO: move all tests in this file to appropriate operator-specific files. - -;; TODO(stack): more of the above - -;; if condition -(assert_invalid (module (func (if (f32.const 0) (then)))) "type mismatch") - -;; br_if condition -(assert_invalid (module (func (block (br_if 0 (f32.const 0))))) "type mismatch") - -;; br_table key -(assert_invalid - (module (func (block (br_table 0 (f32.const 0))))) - "type mismatch") - -;; call params -(assert_invalid (module (func (param i32)) (func (call 0 (f32.const 0)))) "type mismatch") -(assert_invalid - (module - (type (func (param i32))) - (func (type 0)) - (table 0 funcref) - (func - (call_indirect (type 0) (i32.const 0) (f32.const 0)))) - "type mismatch") - -;; call_indirect index -(assert_invalid - (module - (type (func)) - (func (type 0)) - (table 0 funcref) - (func (call_indirect (type 0) (f32.const 0)))) - "type mismatch") - -;; return -(assert_invalid (module (func (result i32) (return (f32.const 0)))) "type mismatch") - -;; local.set -(assert_invalid (module (func (local i32) (local.set 0 (f32.const 0)))) "type mismatch") - -;; load index -(assert_invalid (module (memory 1) (func (i32.load (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.load8_s (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.load8_u (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.load16_s (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.load16_u (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load8_s (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load8_u (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load16_s (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load16_u (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load32_s (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.load32_u (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (f32.load (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (f64.load (f32.const 0)))) "type mismatch") - -;; store index -(assert_invalid (module (memory 1) (func (i32.store (f32.const 0) (i32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.store8 (f32.const 0) (i32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.store16 (f32.const 0) (i32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store (f32.const 0) (i32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store8 (f32.const 0) (i64.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store16 (f32.const 0) (i64.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store32 (f32.const 0) (i64.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (f32.store (f32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (f64.store (f32.const 0) (f64.const 0)))) "type mismatch") - -;; store value -(assert_invalid (module (memory 1) (func (i32.store (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.store8 (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i32.store16 (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store8 (i32.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store16 (i32.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (i64.store32 (i32.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (f32.store (i32.const 0) (i32.const 0)))) "type mismatch") -(assert_invalid (module (memory 1) (func (f64.store (i32.const 0) (i64.const 0)))) "type mismatch") - -;; binary -(assert_invalid (module (func (i32.add (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.and (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.div_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.div_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.mul (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.or (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.rem_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.rem_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.rotl (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.rotr (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.shl (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.shr_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.shr_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.sub (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.xor (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.add (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.and (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.div_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.div_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.mul (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.or (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.rem_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.rem_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.rotl (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.rotr (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.shl (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.shr_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.shr_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.sub (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.xor (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.add (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.copysign (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.div (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.max (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.min (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.mul (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.sub (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.add (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.copysign (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.div (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.max (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.min (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.mul (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.sub (i64.const 0) (f32.const 0)))) "type mismatch") - -;; unary -(assert_invalid (module (func (i32.eqz (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.clz (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.ctz (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.popcnt (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.eqz (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.clz (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.ctz (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.popcnt (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.abs (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.ceil (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.floor (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.nearest (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.neg (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.sqrt (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.trunc (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.abs (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.ceil (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.floor (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.nearest (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.neg (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.sqrt (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.trunc (i64.const 0)))) "type mismatch") - -;; compare -(assert_invalid (module (func (i32.eq (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.ge_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.ge_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.gt_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.gt_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.le_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.le_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.lt_s (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.lt_u (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.ne (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.eq (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.ge_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.ge_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.gt_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.gt_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.le_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.le_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.lt_s (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.lt_u (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.ne (i32.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.eq (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.ge (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.gt (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.le (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.lt (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.ne (i64.const 0) (f64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.eq (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.ge (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.gt (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.le (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.lt (i64.const 0) (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.ne (i64.const 0) (f32.const 0)))) "type mismatch") - -;; convert -(assert_invalid (module (func (i32.wrap_i64 (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.trunc_f32_s (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.trunc_f32_u (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.trunc_f64_s (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.trunc_f64_u (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i32.reinterpret_f32 (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.extend_i32_s (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.extend_i32_u (f32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.trunc_f32_s (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.trunc_f32_u (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.trunc_f64_s (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.trunc_f64_u (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (i64.reinterpret_f64 (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.convert_i32_s (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.convert_i32_u (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.convert_i64_s (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.convert_i64_u (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.demote_f64 (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f32.reinterpret_i32 (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.convert_i32_s (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.convert_i32_u (i64.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.convert_i64_s (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.convert_i64_u (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.promote_f32 (i32.const 0)))) "type mismatch") -(assert_invalid (module (func (f64.reinterpret_i64 (i32.const 0)))) "type mismatch") - -;; memory.grow -(assert_invalid (module (memory 1) (func (memory.grow (f32.const 0)))) "type mismatch")