* Improve the `component_api` fuzzer on a few dimensions * Update the generated component to use an adapter module. This involves two core wasm instances communicating with each other to test that data flows through everything correctly. The intention here is to fuzz the fused adapter compiler. String encoding options have been plumbed here to exercise differences in string encodings. * Use `Cow<'static, ...>` and `static` declarations for each static test case to try to cut down on rustc codegen time. * Add `Copy` to derivation of fuzzed enums to make `derive(Clone)` smaller. * Use `Store<Box<dyn Any>>` to try to cut down on codegen by monomorphizing fewer `Store<T>` implementation. * Add debug logging to print out what's flowing in and what's flowing out for debugging failures. * Improve `Debug` representation of dynamic value types to more closely match their Rust counterparts. * Fix a variant issue with adapter trampolines Previously the offset of the payload was calculated as the discriminant aligned up to the alignment of a singular case, but instead this needs to be aligned up to the alignment of all cases to ensure all cases start at the same location. * Fix a copy/paste error when copying masked integers A 32-bit load was actually doing a 16-bit load by accident since it was copied from the 16-bit load-and-mask case. * Fix f32/i64 conversions in adapter modules The adapter previously erroneously converted the f32 to f64 and then to i64, where instead it should go from f32 to i32 to i64. * Fix zero-sized flags in adapter modules This commit corrects the size calculation for zero-sized flags in adapter modules. cc #4592 * Fix a variant size calculation bug in adapters This fixes the same issue found with variants during normal host-side fuzzing earlier where the size of a variant needs to align up the summation of the discriminant and the maximum case size. * Implement memory growth in libc bump realloc Some fuzz-generated test cases are copying lists large enough to exceed one page of memory so bake in a `memory.grow` to the bump allocator as well. * Avoid adapters of exponential size This commit is an attempt to avoid adapters being exponentially sized with respect to the type hierarchy of the input. Previously all adaptation was done inline within each adapter which meant that if something was structured as `tuple<T, T, T, T, ...>` the translation of `T` would be inlined N times. For very deeply nested types this can quickly create an exponentially sized adapter with types of the form: (type $t0 (list u8)) (type $t1 (tuple $t0 $t0)) (type $t2 (tuple $t1 $t1)) (type $t3 (tuple $t2 $t2)) ;; ... where the translation of `t4` has 8 different copies of translating `t0`. This commit changes the translation of types through memory to almost always go through a helper function. The hope here is that it doesn't lose too much performance because types already reside in memory. This can still lead to exponentially sized adapter modules to a lesser degree where if the translation all happens on the "stack", e.g. via `variant`s and their flat representation then many copies of one translation could still be made. For now this commit at least gets the problem under control for fuzzing where fuzzing doesn't trivially find type hierarchies that take over a minute to codegen the adapter module. One of the main tricky parts of this implementation is that when a function is generated the index that it will be placed at in the final module is not known at that time. To solve this the encoded form of the `Call` instruction is saved in a relocation-style format where the `Call` isn't encoded but instead saved into a different area for encoding later. When the entire adapter module is encoded to wasm these pseudo-`Call` instructions are encoded as real instructions at that time. * Fix some memory64 issues with string encodings Introduced just before #4623 I had a few mistakes related to 64-bit memories and mixing 32/64-bit memories. * Actually insert into the `translate_mem_funcs` map This... was the whole point of having the map! * Assert memory growth succeeds in bump allocator
1437 lines
45 KiB
Plaintext
1437 lines
45 KiB
Plaintext
;; smoke test with no arguments and no results
|
|
(component
|
|
(core module $m
|
|
(func (export ""))
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func $foo (canon lift (core func $m "")))
|
|
|
|
(component $c
|
|
(import "" (func $foo))
|
|
|
|
(core func $foo (canon lower (func $foo)))
|
|
(core module $m2
|
|
(import "" "" (func))
|
|
(start 0)
|
|
)
|
|
(core instance $m2 (instantiate $m2 (with "" (instance (export "" (func $foo))))))
|
|
)
|
|
|
|
(instance $c (instantiate $c (with "" (func $foo))))
|
|
)
|
|
|
|
;; boolean parameters
|
|
(component
|
|
(core module $m
|
|
(func (export "assert_true") (param i32)
|
|
local.get 0
|
|
i32.const 1
|
|
i32.eq
|
|
i32.eqz
|
|
if unreachable end
|
|
)
|
|
(func (export "assert_false") (param i32)
|
|
local.get 0
|
|
if unreachable end
|
|
)
|
|
(func (export "ret-bool") (param i32) (result i32)
|
|
local.get 0
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func $assert_true (param bool) (canon lift (core func $m "assert_true")))
|
|
(func $assert_false (param bool) (canon lift (core func $m "assert_false")))
|
|
(func $ret_bool (param u32) (result bool) (canon lift (core func $m "ret-bool")))
|
|
|
|
(component $c
|
|
(import "assert-true" (func $assert_true (param bool)))
|
|
(import "assert-false" (func $assert_false (param bool)))
|
|
(import "ret-bool" (func $ret_bool (param u32) (result bool)))
|
|
|
|
(core func $assert_true (canon lower (func $assert_true)))
|
|
(core func $assert_false (canon lower (func $assert_false)))
|
|
(core func $ret_bool (canon lower (func $ret_bool)))
|
|
|
|
(core module $m2
|
|
(import "" "assert-true" (func $assert_true (param i32)))
|
|
(import "" "assert-false" (func $assert_false (param i32)))
|
|
(import "" "ret-bool" (func $ret_bool (param i32) (result i32)))
|
|
|
|
(func $start
|
|
(call $assert_true (i32.const 1))
|
|
(call $assert_true (i32.const 2))
|
|
(call $assert_true (i32.const -1))
|
|
(call $assert_false (i32.const 0))
|
|
|
|
(if (i32.ne (call $ret_bool (i32.const 1)) (i32.const 1))
|
|
(unreachable))
|
|
(if (i32.ne (call $ret_bool (i32.const 2)) (i32.const 1))
|
|
(unreachable))
|
|
(if (i32.ne (call $ret_bool (i32.const -1)) (i32.const 1))
|
|
(unreachable))
|
|
(if (i32.ne (call $ret_bool (i32.const 0)) (i32.const 0))
|
|
(unreachable))
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance $m2 (instantiate $m2
|
|
(with "" (instance
|
|
(export "assert-true" (func $assert_true))
|
|
(export "assert-false" (func $assert_false))
|
|
(export "ret-bool" (func $ret_bool))
|
|
))
|
|
))
|
|
)
|
|
|
|
(instance $c (instantiate $c
|
|
(with "assert-true" (func $assert_true))
|
|
(with "assert-false" (func $assert_false))
|
|
(with "ret-bool" (func $ret_bool))
|
|
))
|
|
)
|
|
|
|
;; lots of parameters and results
|
|
(component
|
|
(type $roundtrip (func
|
|
;; 20 u32 params
|
|
(param u32) (param u32) (param u32) (param u32) (param u32)
|
|
(param u32) (param u32) (param u32) (param u32) (param u32)
|
|
(param u32) (param u32) (param u32) (param u32) (param u32)
|
|
(param u32) (param u32) (param u32) (param u32) (param u32)
|
|
|
|
;; 10 u32 results
|
|
(result (tuple u32 u32 u32 u32 u32 u32 u32 u32 u32 u32))
|
|
))
|
|
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "roundtrip") (param $src i32) (result i32)
|
|
(local $dst i32)
|
|
(if (i32.ne (local.get $src) (i32.const 16))
|
|
(unreachable))
|
|
|
|
(if (i32.ne (i32.load offset=0 (local.get $src)) (i32.const 1)) (unreachable))
|
|
(if (i32.ne (i32.load offset=4 (local.get $src)) (i32.const 2)) (unreachable))
|
|
(if (i32.ne (i32.load offset=8 (local.get $src)) (i32.const 3)) (unreachable))
|
|
(if (i32.ne (i32.load offset=12 (local.get $src)) (i32.const 4)) (unreachable))
|
|
(if (i32.ne (i32.load offset=16 (local.get $src)) (i32.const 5)) (unreachable))
|
|
(if (i32.ne (i32.load offset=20 (local.get $src)) (i32.const 6)) (unreachable))
|
|
(if (i32.ne (i32.load offset=24 (local.get $src)) (i32.const 7)) (unreachable))
|
|
(if (i32.ne (i32.load offset=28 (local.get $src)) (i32.const 8)) (unreachable))
|
|
(if (i32.ne (i32.load offset=32 (local.get $src)) (i32.const 9)) (unreachable))
|
|
(if (i32.ne (i32.load offset=36 (local.get $src)) (i32.const 10)) (unreachable))
|
|
(if (i32.ne (i32.load offset=40 (local.get $src)) (i32.const 11)) (unreachable))
|
|
(if (i32.ne (i32.load offset=44 (local.get $src)) (i32.const 12)) (unreachable))
|
|
(if (i32.ne (i32.load offset=48 (local.get $src)) (i32.const 13)) (unreachable))
|
|
(if (i32.ne (i32.load offset=52 (local.get $src)) (i32.const 14)) (unreachable))
|
|
(if (i32.ne (i32.load offset=56 (local.get $src)) (i32.const 15)) (unreachable))
|
|
(if (i32.ne (i32.load offset=60 (local.get $src)) (i32.const 16)) (unreachable))
|
|
(if (i32.ne (i32.load offset=64 (local.get $src)) (i32.const 17)) (unreachable))
|
|
(if (i32.ne (i32.load offset=68 (local.get $src)) (i32.const 18)) (unreachable))
|
|
(if (i32.ne (i32.load offset=72 (local.get $src)) (i32.const 19)) (unreachable))
|
|
(if (i32.ne (i32.load offset=76 (local.get $src)) (i32.const 20)) (unreachable))
|
|
|
|
(local.set $dst (i32.const 500))
|
|
|
|
(i32.store offset=0 (local.get $dst) (i32.const 21))
|
|
(i32.store offset=4 (local.get $dst) (i32.const 22))
|
|
(i32.store offset=8 (local.get $dst) (i32.const 23))
|
|
(i32.store offset=12 (local.get $dst) (i32.const 24))
|
|
(i32.store offset=16 (local.get $dst) (i32.const 25))
|
|
(i32.store offset=20 (local.get $dst) (i32.const 26))
|
|
(i32.store offset=24 (local.get $dst) (i32.const 27))
|
|
(i32.store offset=28 (local.get $dst) (i32.const 28))
|
|
(i32.store offset=32 (local.get $dst) (i32.const 29))
|
|
(i32.store offset=36 (local.get $dst) (i32.const 30))
|
|
|
|
local.get $dst
|
|
)
|
|
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32)
|
|
i32.const 16)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
|
|
(func $roundtrip (type $roundtrip)
|
|
(canon lift (core func $m "roundtrip") (memory $m "memory")
|
|
(realloc (func $m "realloc")))
|
|
)
|
|
|
|
(component $c
|
|
(import "roundtrip" (func $roundtrip (type $roundtrip)))
|
|
|
|
(core module $libc
|
|
(memory (export "memory") 1)
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable)
|
|
)
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $roundtrip
|
|
(canon lower (func $roundtrip)
|
|
(memory $libc "memory")
|
|
(realloc (func $libc "realloc")) ;; FIXME(wasm-tools#693) should not be necessary
|
|
)
|
|
)
|
|
|
|
(core module $m2
|
|
(import "libc" "memory" (memory 1))
|
|
(import "" "roundtrip" (func $roundtrip (param i32 i32)))
|
|
|
|
(func $start
|
|
(local $addr i32)
|
|
(local $retaddr i32)
|
|
|
|
(local.set $addr (i32.const 100))
|
|
(call $store_many (i32.const 20) (local.get $addr))
|
|
|
|
(local.set $retaddr (i32.const 200))
|
|
(call $roundtrip (local.get $addr) (local.get $retaddr))
|
|
|
|
(if (i32.ne (i32.load offset=0 (local.get $retaddr)) (i32.const 21)) (unreachable))
|
|
(if (i32.ne (i32.load offset=4 (local.get $retaddr)) (i32.const 22)) (unreachable))
|
|
(if (i32.ne (i32.load offset=8 (local.get $retaddr)) (i32.const 23)) (unreachable))
|
|
(if (i32.ne (i32.load offset=12 (local.get $retaddr)) (i32.const 24)) (unreachable))
|
|
(if (i32.ne (i32.load offset=16 (local.get $retaddr)) (i32.const 25)) (unreachable))
|
|
(if (i32.ne (i32.load offset=20 (local.get $retaddr)) (i32.const 26)) (unreachable))
|
|
(if (i32.ne (i32.load offset=24 (local.get $retaddr)) (i32.const 27)) (unreachable))
|
|
(if (i32.ne (i32.load offset=28 (local.get $retaddr)) (i32.const 28)) (unreachable))
|
|
(if (i32.ne (i32.load offset=32 (local.get $retaddr)) (i32.const 29)) (unreachable))
|
|
(if (i32.ne (i32.load offset=36 (local.get $retaddr)) (i32.const 30)) (unreachable))
|
|
)
|
|
|
|
(func $store_many (param $amt i32) (param $addr i32)
|
|
(local $c i32)
|
|
(loop $loop
|
|
(local.set $c (i32.add (local.get $c) (i32.const 1)))
|
|
(i32.store (local.get $addr) (local.get $c))
|
|
(local.set $addr (i32.add (local.get $addr) (i32.const 4)))
|
|
|
|
(if (i32.ne (local.get $amt) (local.get $c)) (br $loop))
|
|
)
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance $m2 (instantiate $m2
|
|
(with "libc" (instance $libc))
|
|
(with "" (instance (export "roundtrip" (func $roundtrip))))
|
|
))
|
|
)
|
|
|
|
(instance $c (instantiate $c
|
|
(with "roundtrip" (func $roundtrip))
|
|
))
|
|
)
|
|
|
|
;; this will require multiple adapter modules to get generated
|
|
(component
|
|
(core module $root (func (export "") (result i32)
|
|
i32.const 0
|
|
))
|
|
(core instance $root (instantiate $root))
|
|
(func $root (result u32) (canon lift (core func $root "")))
|
|
|
|
(component $c
|
|
(import "thunk" (func $import (result u32)))
|
|
(core func $import (canon lower (func $import)))
|
|
(core module $reexport
|
|
(import "" "" (func $thunk (result i32)))
|
|
(func (export "thunk") (result i32)
|
|
call $thunk
|
|
i32.const 1
|
|
i32.add)
|
|
)
|
|
(core instance $reexport (instantiate $reexport
|
|
(with "" (instance
|
|
(export "" (func $import))
|
|
))
|
|
))
|
|
(func $export (export "thunk") (result u32)
|
|
(canon lift (core func $reexport "thunk"))
|
|
)
|
|
)
|
|
|
|
(instance $c1 (instantiate $c (with "thunk" (func $root))))
|
|
(instance $c2 (instantiate $c (with "thunk" (func $c1 "thunk"))))
|
|
(instance $c3 (instantiate $c (with "thunk" (func $c2 "thunk"))))
|
|
(instance $c4 (instantiate $c (with "thunk" (func $c3 "thunk"))))
|
|
(instance $c5 (instantiate $c (with "thunk" (func $c4 "thunk"))))
|
|
(instance $c6 (instantiate $c (with "thunk" (func $c5 "thunk"))))
|
|
|
|
(component $verify
|
|
(import "thunk" (func $thunk (result u32)))
|
|
(core func $thunk (canon lower (func $thunk)))
|
|
(core module $verify
|
|
(import "" "" (func $thunk (result i32)))
|
|
|
|
(func $start
|
|
call $thunk
|
|
i32.const 6
|
|
i32.ne
|
|
if unreachable end
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $verify
|
|
(with "" (instance
|
|
(export "" (func $thunk))
|
|
))
|
|
))
|
|
)
|
|
(instance (instantiate $verify (with "thunk" (func $c6 "thunk"))))
|
|
)
|
|
|
|
;; Fancy case of an adapter using an adapter. Note that this is silly and
|
|
;; doesn't actually make any sense at runtime, we just shouldn't panic on a
|
|
;; valid component.
|
|
(component
|
|
(type $tuple20 (tuple
|
|
u32 u32 u32 u32 u32
|
|
u32 u32 u32 u32 u32
|
|
u32 u32 u32 u32 u32
|
|
u32 u32 u32 u32 u32))
|
|
|
|
(component $realloc
|
|
(core module $realloc
|
|
(memory (export "memory") 1)
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32)
|
|
unreachable)
|
|
)
|
|
(core instance $realloc (instantiate $realloc))
|
|
(func $realloc (param (tuple u32 u32 u32 u32)) (result u32)
|
|
(canon lift (core func $realloc "realloc"))
|
|
)
|
|
(export "realloc" (func $realloc))
|
|
)
|
|
(instance $realloc (instantiate $realloc))
|
|
(core func $realloc (canon lower (func $realloc "realloc")))
|
|
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "foo") (param i32))
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func $foo (param $tuple20)
|
|
(canon lift
|
|
(core func $m "foo")
|
|
(memory $m "memory")
|
|
(realloc (func $realloc))
|
|
)
|
|
)
|
|
|
|
(component $c
|
|
(import "foo" (func $foo (param $tuple20)))
|
|
|
|
(core module $libc
|
|
(memory (export "memory") 1)
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32)
|
|
unreachable)
|
|
)
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $foo
|
|
(canon lower (func $foo)
|
|
(memory $libc "memory")
|
|
(realloc (func $libc "realloc")) ;; FIXME(wasm-tools#693) should not be necessary
|
|
)
|
|
)
|
|
(core module $something
|
|
(import "" "foo" (func (param i32)))
|
|
)
|
|
(core instance (instantiate $something
|
|
(with "" (instance
|
|
(export "foo" (func $foo))
|
|
))
|
|
))
|
|
)
|
|
(instance (instantiate $c
|
|
(with "foo" (func $foo))
|
|
))
|
|
)
|
|
|
|
;; Don't panic or otherwise create extraneous adapter modules when the same
|
|
;; adapter is used twice for a module's argument.
|
|
(component
|
|
(core module $m
|
|
(func (export "foo") (param))
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func $foo (canon lift (core func $m "foo")))
|
|
|
|
(component $c
|
|
(import "foo" (func $foo))
|
|
(core func $foo (canon lower (func $foo)))
|
|
|
|
(core module $something
|
|
(import "" "a" (func))
|
|
(import "" "b" (func))
|
|
)
|
|
(core instance (instantiate $something
|
|
(with "" (instance
|
|
(export "a" (func $foo))
|
|
(export "b" (func $foo))
|
|
))
|
|
))
|
|
)
|
|
(instance (instantiate $c (with "foo" (func $foo))))
|
|
)
|
|
|
|
;; post-return should get invoked by the generated adapter, if specified
|
|
(component
|
|
(core module $m
|
|
(global $post_called (mut i32) (i32.const 0))
|
|
(func (export "foo")
|
|
;; assert `foo-post` not called yet
|
|
global.get $post_called
|
|
i32.const 1
|
|
i32.eq
|
|
if unreachable end
|
|
)
|
|
(func (export "foo-post")
|
|
;; assert `foo-post` not called before
|
|
global.get $post_called
|
|
i32.const 1
|
|
i32.eq
|
|
if unreachable end
|
|
;; ... then flag as called
|
|
i32.const 1
|
|
global.set $post_called
|
|
)
|
|
(func (export "assert-post")
|
|
global.get $post_called
|
|
i32.const 1
|
|
i32.ne
|
|
if unreachable end
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func $foo (canon lift (core func $m "foo") (post-return (func $m "foo-post"))))
|
|
(func $assert_post (canon lift (core func $m "assert-post")))
|
|
|
|
(component $c
|
|
(import "foo" (func $foo))
|
|
(import "assert-post" (func $assert_post))
|
|
(core func $foo (canon lower (func $foo)))
|
|
(core func $assert_post (canon lower (func $assert_post)))
|
|
|
|
(core module $something
|
|
(import "" "foo" (func $foo))
|
|
(import "" "assert-post" (func $assert_post))
|
|
|
|
(func $start
|
|
call $foo
|
|
call $assert_post
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $something
|
|
(with "" (instance
|
|
(export "foo" (func $foo))
|
|
(export "assert-post" (func $assert_post))
|
|
))
|
|
))
|
|
)
|
|
(instance (instantiate $c
|
|
(with "foo" (func $foo))
|
|
(with "assert-post" (func $assert_post))
|
|
))
|
|
)
|
|
|
|
;; post-return passes the results
|
|
(component
|
|
(core module $m
|
|
(func (export "foo") (result i32) i32.const 100)
|
|
(func (export "foo-post") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 100)) (unreachable)))
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func $foo (result u32)
|
|
(canon lift (core func $m "foo") (post-return (func $m "foo-post"))))
|
|
|
|
(component $c
|
|
(import "foo" (func $foo (result u32)))
|
|
(core func $foo (canon lower (func $foo)))
|
|
|
|
(core module $something
|
|
(import "" "foo" (func $foo (result i32)))
|
|
(func $start
|
|
(if (i32.ne (call $foo) (i32.const 100)) (unreachable)))
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $something
|
|
(with "" (instance
|
|
(export "foo" (func $foo))
|
|
))
|
|
))
|
|
)
|
|
(instance (instantiate $c
|
|
(with "foo" (func $foo))
|
|
))
|
|
)
|
|
|
|
;; struct field reordering
|
|
(component
|
|
(component $c1
|
|
(type $in (record
|
|
(field "a" u32)
|
|
(field "b" bool)
|
|
(field "c" u8)
|
|
))
|
|
(type $out (record
|
|
(field "x" u8)
|
|
(field "y" u32)
|
|
(field "z" bool)
|
|
))
|
|
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "r") (param i32 i32 i32) (result i32)
|
|
(if (i32.ne (local.get 0) (i32.const 3)) (unreachable)) ;; a == 3
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable)) ;; b == true
|
|
(if (i32.ne (local.get 2) (i32.const 2)) (unreachable)) ;; c == 2
|
|
|
|
|
|
(i32.store8 offset=0 (i32.const 200) (i32.const 0xab)) ;; x == 0xab
|
|
(i32.store offset=4 (i32.const 200) (i32.const 200)) ;; y == 200
|
|
(i32.store8 offset=8 (i32.const 200) (i32.const 0)) ;; z == false
|
|
i32.const 200
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (param $in) (result $out)
|
|
(canon lift (core func $m "r") (memory $m "memory"))
|
|
)
|
|
)
|
|
(component $c2
|
|
;; note the different field orderings than the records specified above
|
|
(type $in (record
|
|
(field "b" bool)
|
|
(field "c" u8)
|
|
(field "a" u32)
|
|
))
|
|
(type $out (record
|
|
(field "z" bool)
|
|
(field "x" u8)
|
|
(field "y" u32)
|
|
))
|
|
(import "r" (func $r (param $in) (result $out)))
|
|
(core module $libc (memory (export "memory") 1))
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $r (canon lower (func $r) (memory $libc "memory")))
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32 i32 i32 i32)))
|
|
(import "libc" "memory" (memory 0))
|
|
(func $start
|
|
i32.const 100 ;; b: bool
|
|
i32.const 2 ;; c: u8
|
|
i32.const 3 ;; a: u32
|
|
i32.const 100 ;; retptr
|
|
call $r
|
|
|
|
;; z == false
|
|
(if (i32.ne (i32.load8_u offset=0 (i32.const 100)) (i32.const 0)) (unreachable))
|
|
;; x == 0xab
|
|
(if (i32.ne (i32.load8_u offset=1 (i32.const 100)) (i32.const 0xab)) (unreachable))
|
|
;; y == 200
|
|
(if (i32.ne (i32.load offset=4 (i32.const 100)) (i32.const 200)) (unreachable))
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "libc" (instance $libc))
|
|
(with "" (instance
|
|
(export "r" (func $r))
|
|
))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
|
|
;; callee retptr misaligned
|
|
(assert_trap
|
|
(component
|
|
(component $c1
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "r") (result i32) i32.const 1)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (result (tuple u32 u32))
|
|
(canon lift (core func $m "r") (memory $m "memory"))
|
|
)
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (result (tuple u32 u32))))
|
|
(core module $libc (memory (export "memory") 1))
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $r (canon lower (func $r) (memory $libc "memory")))
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32)))
|
|
(func $start
|
|
i32.const 4
|
|
call $r
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
"unreachable")
|
|
|
|
;; caller retptr misaligned
|
|
(assert_trap
|
|
(component
|
|
(component $c1
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "r") (result i32) i32.const 0)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (result (tuple u32 u32))
|
|
(canon lift (core func $m "r") (memory $m "memory"))
|
|
)
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (result (tuple u32 u32))))
|
|
(core module $libc (memory (export "memory") 1))
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $r (canon lower (func $r) (memory $libc "memory")))
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32)))
|
|
(func $start
|
|
i32.const 1
|
|
call $r
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
"unreachable")
|
|
|
|
;; callee argptr misaligned
|
|
(assert_trap
|
|
(component
|
|
(type $big (tuple u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "r") (param i32))
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32)
|
|
i32.const 1)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (param $big)
|
|
(canon lift (core func $m "r") (memory $m "memory") (realloc (func $m "realloc")))
|
|
)
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (param $big)))
|
|
(core module $libc
|
|
(memory (export "memory") 1)
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable)
|
|
)
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $r
|
|
(canon lower (func $r)
|
|
(memory $libc "memory")
|
|
(realloc (func $libc "realloc")) ;; FIXME(wasm-tools#693) should not be necessary
|
|
)
|
|
)
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32)))
|
|
(func $start
|
|
i32.const 4
|
|
call $r
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
"unreachable")
|
|
|
|
;; caller argptr misaligned
|
|
(assert_trap
|
|
(component
|
|
(type $big (tuple u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(memory (export "memory") 1)
|
|
(func (export "r") (param i32))
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32)
|
|
i32.const 4)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (param $big)
|
|
(canon lift (core func $m "r") (memory $m "memory") (realloc (func $m "realloc")))
|
|
)
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (param $big)))
|
|
(core module $libc
|
|
(memory (export "memory") 1)
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable)
|
|
)
|
|
(core instance $libc (instantiate $libc))
|
|
(core func $r
|
|
(canon lower (func $r)
|
|
(memory $libc "memory")
|
|
(realloc (func $libc "realloc")) ;; FIXME(wasm-tools#693) should not be necessary
|
|
)
|
|
)
|
|
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32)))
|
|
(func $start
|
|
i32.const 1
|
|
call $r
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
"unreachable")
|
|
|
|
;; simple variant translation
|
|
(component
|
|
(type $a (variant (case "x" unit)))
|
|
(type $b (variant (case "y" unit)))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "r") (param i32) (result i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0)) (unreachable))
|
|
i32.const 0
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (param $a) (result $b) (canon lift (core func $m "r")))
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (param $a) (result $b)))
|
|
(core func $r (canon lower (func $r)))
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32) (result i32)))
|
|
(func $start
|
|
i32.const 0
|
|
call $r
|
|
i32.const 0
|
|
i32.ne
|
|
if unreachable end
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
|
|
;; invalid variant discriminant in a parameter
|
|
(assert_trap
|
|
(component
|
|
(type $a (variant (case "x" unit)))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "r") (param i32))
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (param $a) (canon lift (core func $m "r")))
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (param $a)))
|
|
(core func $r (canon lower (func $r)))
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (param i32)))
|
|
(func $start
|
|
i32.const 1
|
|
call $r
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
"unreachable")
|
|
|
|
;; invalid variant discriminant in a result
|
|
(assert_trap
|
|
(component
|
|
(type $a (variant (case "x" unit)))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "r") (result i32) i32.const 1)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "r") (result $a) (canon lift (core func $m "r")))
|
|
)
|
|
(component $c2
|
|
(import "r" (func $r (result $a)))
|
|
(core func $r (canon lower (func $r)))
|
|
|
|
(core module $m
|
|
(import "" "r" (func $r (result i32)))
|
|
(func $start call $r drop)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance (export "r" (func $r))))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "r" (func $c1 "r"))))
|
|
)
|
|
"unreachable")
|
|
|
|
|
|
;; extra bits are chopped off
|
|
(component
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "u") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0)) (unreachable))
|
|
)
|
|
(func (export "s") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const -1)) (unreachable))
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "u8") (param u8) (canon lift (core func $m "u")))
|
|
(func (export "u16") (param u16) (canon lift (core func $m "u")))
|
|
(func (export "s8") (param s8) (canon lift (core func $m "s")))
|
|
(func (export "s16") (param s16) (canon lift (core func $m "s")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i
|
|
(export "u8" (func (param u8)))
|
|
(export "s8" (func (param s8)))
|
|
(export "u16" (func (param u16)))
|
|
(export "s16" (func (param s16)))
|
|
))
|
|
|
|
(core func $u8 (canon lower (func $i "u8")))
|
|
(core func $s8 (canon lower (func $i "s8")))
|
|
(core func $u16 (canon lower (func $i "u16")))
|
|
(core func $s16 (canon lower (func $i "s16")))
|
|
|
|
(core module $m
|
|
(import "" "u8" (func $u8 (param i32)))
|
|
(import "" "s8" (func $s8 (param i32)))
|
|
(import "" "u16" (func $u16 (param i32)))
|
|
(import "" "s16" (func $s16 (param i32)))
|
|
|
|
(func $start
|
|
(call $u8 (i32.const 0))
|
|
(call $u8 (i32.const 0xff00))
|
|
(call $s8 (i32.const -1))
|
|
(call $s8 (i32.const 0xff))
|
|
(call $s8 (i32.const 0xffff))
|
|
|
|
(call $u16 (i32.const 0))
|
|
(call $u16 (i32.const 0xff0000))
|
|
(call $s16 (i32.const -1))
|
|
(call $s16 (i32.const 0xffff))
|
|
(call $s16 (i32.const 0xffffff))
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance
|
|
(export "u8" (func $u8))
|
|
(export "s8" (func $s8))
|
|
(export "u16" (func $u16))
|
|
(export "s16" (func $s16))
|
|
))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
|
|
;; translation of locals between different types
|
|
(component
|
|
(type $a (variant (case "a" u8) (case "b" float32)))
|
|
(type $b (variant (case "a" u16) (case "b" s64)))
|
|
(type $c (variant (case "a" u64) (case "b" float64)))
|
|
(type $d (variant (case "a" float32) (case "b" float64)))
|
|
(type $e (variant (case "a" float32) (case "b" s64)))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "a") (param i32 i32 i32)
|
|
(i32.eqz (local.get 0))
|
|
if
|
|
(if (i32.ne (local.get 1) (i32.const 0)) (unreachable))
|
|
(if (i32.ne (local.get 2) (i32.const 2)) (unreachable))
|
|
else
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable))
|
|
(if (f32.ne (f32.reinterpret_i32 (local.get 2)) (f32.const 3)) (unreachable))
|
|
end
|
|
)
|
|
(func (export "b") (param i32 i32 i64)
|
|
(i32.eqz (local.get 0))
|
|
if
|
|
(if (i32.ne (local.get 1) (i32.const 0)) (unreachable))
|
|
(if (i64.ne (local.get 2) (i64.const 4)) (unreachable))
|
|
else
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable))
|
|
(if (i64.ne (local.get 2) (i64.const 5)) (unreachable))
|
|
end
|
|
)
|
|
(func (export "c") (param i32 i32 i64)
|
|
(i32.eqz (local.get 0))
|
|
if
|
|
(if (i32.ne (local.get 1) (i32.const 0)) (unreachable))
|
|
(if (i64.ne (local.get 2) (i64.const 6)) (unreachable))
|
|
else
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable))
|
|
(if (f64.ne (f64.reinterpret_i64 (local.get 2)) (f64.const 7)) (unreachable))
|
|
end
|
|
)
|
|
(func (export "d") (param i32 i32 i64)
|
|
(i32.eqz (local.get 0))
|
|
if
|
|
(if (i32.ne (local.get 1) (i32.const 0)) (unreachable))
|
|
(if (f32.ne (f32.reinterpret_i32 (i32.wrap_i64 (local.get 2))) (f32.const 8)) (unreachable))
|
|
else
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable))
|
|
(if (f64.ne (f64.reinterpret_i64 (local.get 2)) (f64.const 9)) (unreachable))
|
|
end
|
|
)
|
|
(func (export "e") (param i32 i32 i64)
|
|
(i32.eqz (local.get 0))
|
|
if
|
|
(if (i32.ne (local.get 1) (i32.const 0)) (unreachable))
|
|
(if (f32.ne (f32.reinterpret_i32 (i32.wrap_i64 (local.get 2))) (f32.const 10)) (unreachable))
|
|
else
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable))
|
|
(if (i64.ne (local.get 2) (i64.const 11)) (unreachable))
|
|
end
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "a") (param bool) (param $a) (canon lift (core func $m "a")))
|
|
(func (export "b") (param bool) (param $b) (canon lift (core func $m "b")))
|
|
(func (export "c") (param bool) (param $c) (canon lift (core func $m "c")))
|
|
(func (export "d") (param bool) (param $d) (canon lift (core func $m "d")))
|
|
(func (export "e") (param bool) (param $e) (canon lift (core func $m "e")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i
|
|
(export "a" (func (param bool) (param $a)))
|
|
(export "b" (func (param bool) (param $b)))
|
|
(export "c" (func (param bool) (param $c)))
|
|
(export "d" (func (param bool) (param $d)))
|
|
(export "e" (func (param bool) (param $e)))
|
|
))
|
|
|
|
(core func $a (canon lower (func $i "a")))
|
|
(core func $b (canon lower (func $i "b")))
|
|
(core func $c (canon lower (func $i "c")))
|
|
(core func $d (canon lower (func $i "d")))
|
|
(core func $e (canon lower (func $i "e")))
|
|
|
|
(core module $m
|
|
(import "" "a" (func $a (param i32 i32 i32)))
|
|
(import "" "b" (func $b (param i32 i32 i64)))
|
|
(import "" "c" (func $c (param i32 i32 i64)))
|
|
(import "" "d" (func $d (param i32 i32 i64)))
|
|
(import "" "e" (func $e (param i32 i32 i64)))
|
|
|
|
(func $start
|
|
;; upper bits should get masked
|
|
(call $a (i32.const 0) (i32.const 0) (i32.const 0xff_02))
|
|
(call $a (i32.const 1) (i32.const 1) (i32.reinterpret_f32 (f32.const 3)))
|
|
|
|
;; upper bits should get masked
|
|
(call $b (i32.const 0) (i32.const 0) (i64.const 0xff_00_04))
|
|
(call $b (i32.const 1) (i32.const 1) (i64.const 5))
|
|
|
|
(call $c (i32.const 0) (i32.const 0) (i64.const 6))
|
|
(call $c (i32.const 1) (i32.const 1) (i64.reinterpret_f64 (f64.const 7)))
|
|
|
|
(call $d (i32.const 0) (i32.const 0) (i64.extend_i32_u (i32.reinterpret_f32 (f32.const 8))))
|
|
(call $d (i32.const 1) (i32.const 1) (i64.reinterpret_f64 (f64.const 9)))
|
|
|
|
(call $e (i32.const 0) (i32.const 0) (i64.extend_i32_u (i32.reinterpret_f32 (f32.const 10))))
|
|
(call $e (i32.const 1) (i32.const 1) (i64.const 11))
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance
|
|
(export "a" (func $a))
|
|
(export "b" (func $b))
|
|
(export "c" (func $c))
|
|
(export "d" (func $d))
|
|
(export "e" (func $e))
|
|
))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
|
|
;; different size variants
|
|
(component
|
|
(type $a (variant
|
|
(case "a" unit)
|
|
(case "b" float32)
|
|
(case "c" (tuple float32 u32))
|
|
(case "d" (tuple float32 unit u64 u8))
|
|
))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "a") (param i32 i32 f32 i64 i32)
|
|
(if (i32.eq (local.get 0) (i32.const 0))
|
|
(block
|
|
(if (i32.ne (local.get 1) (i32.const 0)) (unreachable))
|
|
(if (f32.ne (local.get 2) (f32.const 0)) (unreachable))
|
|
(if (i64.ne (local.get 3) (i64.const 0)) (unreachable))
|
|
(if (i32.ne (local.get 4) (i32.const 0)) (unreachable))
|
|
)
|
|
)
|
|
(if (i32.eq (local.get 0) (i32.const 1))
|
|
(block
|
|
(if (i32.ne (local.get 1) (i32.const 1)) (unreachable))
|
|
(if (f32.ne (local.get 2) (f32.const 1)) (unreachable))
|
|
(if (i64.ne (local.get 3) (i64.const 0)) (unreachable))
|
|
(if (i32.ne (local.get 4) (i32.const 0)) (unreachable))
|
|
)
|
|
)
|
|
(if (i32.eq (local.get 0) (i32.const 2))
|
|
(block
|
|
(if (i32.ne (local.get 1) (i32.const 2)) (unreachable))
|
|
(if (f32.ne (local.get 2) (f32.const 2)) (unreachable))
|
|
(if (i64.ne (local.get 3) (i64.const 2)) (unreachable))
|
|
(if (i32.ne (local.get 4) (i32.const 0)) (unreachable))
|
|
)
|
|
)
|
|
(if (i32.eq (local.get 0) (i32.const 3))
|
|
(block
|
|
(if (i32.ne (local.get 1) (i32.const 3)) (unreachable))
|
|
(if (f32.ne (local.get 2) (f32.const 3)) (unreachable))
|
|
(if (i64.ne (local.get 3) (i64.const 3)) (unreachable))
|
|
(if (i32.ne (local.get 4) (i32.const 3)) (unreachable))
|
|
)
|
|
)
|
|
(if (i32.gt_u (local.get 0) (i32.const 3))
|
|
(unreachable))
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "a") (param u8) (param $a) (canon lift (core func $m "a")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i
|
|
(export "a" (func (param u8) (param $a)))
|
|
))
|
|
|
|
(core func $a (canon lower (func $i "a")))
|
|
|
|
(core module $m
|
|
(import "" "a" (func $a (param i32 i32 f32 i64 i32)))
|
|
|
|
(func $start
|
|
;; variant a
|
|
(call $a
|
|
(i32.const 0)
|
|
(i32.const 0)
|
|
(f32.const 0)
|
|
(i64.const 0)
|
|
(i32.const 0))
|
|
;; variant b
|
|
(call $a
|
|
(i32.const 1)
|
|
(i32.const 1)
|
|
(f32.const 1)
|
|
(i64.const 0)
|
|
(i32.const 0))
|
|
;; variant c
|
|
(call $a
|
|
(i32.const 2)
|
|
(i32.const 2)
|
|
(f32.const 2)
|
|
(i64.const 2)
|
|
(i32.const 0))
|
|
;; variant d
|
|
(call $a
|
|
(i32.const 3)
|
|
(i32.const 3)
|
|
(f32.const 3)
|
|
(i64.const 3)
|
|
(i32.const 3))
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m
|
|
(with "" (instance
|
|
(export "a" (func $a))
|
|
))
|
|
))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
|
|
;; roundtrip some valid chars
|
|
(component
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "a") (param i32) (result i32) local.get 0)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "a") (param char) (result char) (canon lift (core func $m "a")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i
|
|
(export "a" (func (param char) (result char)))
|
|
))
|
|
|
|
(core func $a (canon lower (func $i "a")))
|
|
|
|
(core module $m
|
|
(import "" "a" (func $a (param i32) (result i32)))
|
|
|
|
(func $start
|
|
(call $roundtrip (i32.const 0))
|
|
(call $roundtrip (i32.const 0xab))
|
|
(call $roundtrip (i32.const 0xd7ff))
|
|
(call $roundtrip (i32.const 0xe000))
|
|
(call $roundtrip (i32.const 0x10ffff))
|
|
)
|
|
(func $roundtrip (export "roundtrip") (param i32)
|
|
local.get 0
|
|
call $a
|
|
local.get 0
|
|
i32.ne
|
|
if unreachable end
|
|
)
|
|
(start $start)
|
|
)
|
|
(core instance $m (instantiate $m
|
|
(with "" (instance
|
|
(export "a" (func $a))
|
|
))
|
|
))
|
|
|
|
(func (export "roundtrip") (param char) (canon lift (core func $m "roundtrip")))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
|
|
(export "roundtrip" (func $c2 "roundtrip"))
|
|
)
|
|
|
|
(assert_return (invoke "roundtrip" (char.const "x")) (unit.const))
|
|
(assert_return (invoke "roundtrip" (char.const "⛳")) (unit.const))
|
|
(assert_return (invoke "roundtrip" (char.const "🍰")) (unit.const))
|
|
|
|
;; invalid chars
|
|
(assert_trap
|
|
(component
|
|
(component $c1
|
|
(core module $m (func (export "a") (param i32)))
|
|
(core instance $m (instantiate $m))
|
|
(func (export "a") (param char) (canon lift (core func $m "a")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i (export "a" (func (param char)))))
|
|
(core func $a (canon lower (func $i "a")))
|
|
(core module $m
|
|
(import "" "a" (func $a (param i32)))
|
|
(func $start (call $a (i32.const 0xd800)))
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m (with "" (instance (export "a" (func $a))))))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
"unreachable")
|
|
(assert_trap
|
|
(component
|
|
(component $c1
|
|
(core module $m (func (export "a") (param i32)))
|
|
(core instance $m (instantiate $m))
|
|
(func (export "a") (param char) (canon lift (core func $m "a")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i (export "a" (func (param char)))))
|
|
(core func $a (canon lower (func $i "a")))
|
|
(core module $m
|
|
(import "" "a" (func $a (param i32)))
|
|
(func $start (call $a (i32.const 0xdfff)))
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m (with "" (instance (export "a" (func $a))))))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
"unreachable")
|
|
(assert_trap
|
|
(component
|
|
(component $c1
|
|
(core module $m (func (export "a") (param i32)))
|
|
(core instance $m (instantiate $m))
|
|
(func (export "a") (param char) (canon lift (core func $m "a")))
|
|
)
|
|
(component $c2
|
|
(import "" (instance $i (export "a" (func (param char)))))
|
|
(core func $a (canon lower (func $i "a")))
|
|
(core module $m
|
|
(import "" "a" (func $a (param i32)))
|
|
(func $start (call $a (i32.const 0x110000)))
|
|
(start $start)
|
|
)
|
|
(core instance (instantiate $m (with "" (instance (export "a" (func $a))))))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
(instance $c2 (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
"unreachable")
|
|
|
|
;; test that flags get their upper bits all masked off
|
|
(component
|
|
(type $f0 (flags))
|
|
(type $f1 (flags "f1"))
|
|
(type $f8 (flags "f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"))
|
|
(type $f9 (flags "f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8" "f9"))
|
|
(type $f16 (flags
|
|
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"
|
|
"g1" "g2" "g3" "g4" "g5" "g6" "g7" "g8"
|
|
))
|
|
(type $f17 (flags
|
|
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"
|
|
"g1" "g2" "g3" "g4" "g5" "g6" "g7" "g8"
|
|
"g9"
|
|
))
|
|
(type $f32 (flags
|
|
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"
|
|
"g1" "g2" "g3" "g4" "g5" "g6" "g7" "g8"
|
|
"h1" "h2" "h3" "h4" "h5" "h6" "h7" "h8"
|
|
"i1" "i2" "i3" "i4" "i5" "i6" "i7" "i8"
|
|
))
|
|
(type $f33 (flags
|
|
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"
|
|
"g1" "g2" "g3" "g4" "g5" "g6" "g7" "g8"
|
|
"h1" "h2" "h3" "h4" "h5" "h6" "h7" "h8"
|
|
"i1" "i2" "i3" "i4" "i5" "i6" "i7" "i8"
|
|
"i9"
|
|
))
|
|
(type $f64 (flags
|
|
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"
|
|
"g1" "g2" "g3" "g4" "g5" "g6" "g7" "g8"
|
|
"h1" "h2" "h3" "h4" "h5" "h6" "h7" "h8"
|
|
"i1" "i2" "i3" "i4" "i5" "i6" "i7" "i8"
|
|
"j1" "j2" "j3" "j4" "j5" "j6" "j7" "j8"
|
|
"k1" "k2" "k3" "k4" "k5" "k6" "k7" "k8"
|
|
"l1" "l2" "l3" "l4" "l5" "l6" "l7" "l8"
|
|
"m1" "m2" "m3" "m4" "m5" "m6" "m7" "m8"
|
|
))
|
|
(type $f65 (flags
|
|
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8"
|
|
"g1" "g2" "g3" "g4" "g5" "g6" "g7" "g8"
|
|
"h1" "h2" "h3" "h4" "h5" "h6" "h7" "h8"
|
|
"i1" "i2" "i3" "i4" "i5" "i6" "i7" "i8"
|
|
"j1" "j2" "j3" "j4" "j5" "j6" "j7" "j8"
|
|
"k1" "k2" "k3" "k4" "k5" "k6" "k7" "k8"
|
|
"l1" "l2" "l3" "l4" "l5" "l6" "l7" "l8"
|
|
"m1" "m2" "m3" "m4" "m5" "m6" "m7" "m8"
|
|
"m9"
|
|
))
|
|
|
|
(component $c1
|
|
(core module $m
|
|
(func (export "f0"))
|
|
(func (export "f1") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x1)) (unreachable))
|
|
)
|
|
(func (export "f8") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x11)) (unreachable))
|
|
)
|
|
(func (export "f9") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x111)) (unreachable))
|
|
)
|
|
(func (export "f16") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x1111)) (unreachable))
|
|
)
|
|
(func (export "f17") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x11111)) (unreachable))
|
|
)
|
|
(func (export "f32") (param i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x11111111)) (unreachable))
|
|
)
|
|
(func (export "f33") (param i32 i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x11111111)) (unreachable))
|
|
(if (i32.ne (local.get 1) (i32.const 0x1)) (unreachable))
|
|
)
|
|
(func (export "f64") (param i32 i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x11111111)) (unreachable))
|
|
(if (i32.ne (local.get 1) (i32.const 0x11111111)) (unreachable))
|
|
)
|
|
(func (export "f65") (param i32 i32 i32)
|
|
(if (i32.ne (local.get 0) (i32.const 0x11111111)) (unreachable))
|
|
(if (i32.ne (local.get 1) (i32.const 0x11111111)) (unreachable))
|
|
(if (i32.ne (local.get 2) (i32.const 0x1)) (unreachable))
|
|
)
|
|
)
|
|
(core instance $m (instantiate $m))
|
|
(func (export "f0") (param $f0) (canon lift (core func $m "f0")))
|
|
(func (export "f1") (param $f1) (canon lift (core func $m "f1")))
|
|
(func (export "f8") (param $f8) (canon lift (core func $m "f8")))
|
|
(func (export "f9") (param $f9) (canon lift (core func $m "f9")))
|
|
(func (export "f16") (param $f16) (canon lift (core func $m "f16")))
|
|
(func (export "f17") (param $f17) (canon lift (core func $m "f17")))
|
|
(func (export "f32") (param $f32) (canon lift (core func $m "f32")))
|
|
(func (export "f33") (param $f33) (canon lift (core func $m "f33")))
|
|
(func (export "f64") (param $f64) (canon lift (core func $m "f64")))
|
|
(func (export "f65") (param $f65) (canon lift (core func $m "f65")))
|
|
)
|
|
(instance $c1 (instantiate $c1))
|
|
|
|
(component $c2
|
|
(import "" (instance $i
|
|
(export "f0" (func (param $f0)))
|
|
(export "f1" (func (param $f1)))
|
|
(export "f8" (func (param $f8)))
|
|
(export "f9" (func (param $f9)))
|
|
(export "f16" (func (param $f16)))
|
|
(export "f17" (func (param $f17)))
|
|
(export "f32" (func (param $f32)))
|
|
(export "f33" (func (param $f33)))
|
|
(export "f64" (func (param $f64)))
|
|
(export "f65" (func (param $f65)))
|
|
))
|
|
(core func $f0 (canon lower (func $i "f0")))
|
|
(core func $f1 (canon lower (func $i "f1")))
|
|
(core func $f8 (canon lower (func $i "f8")))
|
|
(core func $f9 (canon lower (func $i "f9")))
|
|
(core func $f16 (canon lower (func $i "f16")))
|
|
(core func $f17 (canon lower (func $i "f17")))
|
|
(core func $f32 (canon lower (func $i "f32")))
|
|
(core func $f33 (canon lower (func $i "f33")))
|
|
(core func $f64 (canon lower (func $i "f64")))
|
|
(core func $f65 (canon lower (func $i "f65")))
|
|
|
|
(core module $m
|
|
(import "" "f0" (func $f0))
|
|
(import "" "f1" (func $f1 (param i32)))
|
|
(import "" "f8" (func $f8 (param i32)))
|
|
(import "" "f9" (func $f9 (param i32)))
|
|
(import "" "f16" (func $f16 (param i32)))
|
|
(import "" "f17" (func $f17 (param i32)))
|
|
(import "" "f32" (func $f32 (param i32)))
|
|
(import "" "f33" (func $f33 (param i32 i32)))
|
|
(import "" "f64" (func $f64 (param i32 i32)))
|
|
(import "" "f65" (func $f65 (param i32 i32 i32)))
|
|
|
|
(func $start
|
|
(call $f0)
|
|
(call $f1 (i32.const 0xffffff01))
|
|
(call $f8 (i32.const 0xffffff11))
|
|
(call $f9 (i32.const 0xffffff11))
|
|
(call $f16 (i32.const 0xffff1111))
|
|
(call $f17 (i32.const 0xffff1111))
|
|
(call $f32 (i32.const 0x11111111))
|
|
(call $f33 (i32.const 0x11111111) (i32.const 0xffffffff))
|
|
(call $f64 (i32.const 0x11111111) (i32.const 0x11111111))
|
|
(call $f65 (i32.const 0x11111111) (i32.const 0x11111111) (i32.const 0xffffffff))
|
|
)
|
|
|
|
(start $start)
|
|
)
|
|
(core instance $m (instantiate $m
|
|
(with "" (instance
|
|
(export "f0" (func $f0))
|
|
(export "f1" (func $f1))
|
|
(export "f8" (func $f8))
|
|
(export "f9" (func $f9))
|
|
(export "f16" (func $f16))
|
|
(export "f17" (func $f17))
|
|
(export "f32" (func $f32))
|
|
(export "f33" (func $f33))
|
|
(export "f64" (func $f64))
|
|
(export "f65" (func $f65))
|
|
))
|
|
))
|
|
)
|
|
(instance (instantiate $c2 (with "" (instance $c1))))
|
|
)
|
|
|
|
;; Adapters are used slightly out-of-order here to stress the internals of
|
|
;; dependencies between adapters.
|
|
(component
|
|
(core module $m
|
|
(func (export "execute"))
|
|
(func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable)
|
|
(memory (export "memory") 1)
|
|
)
|
|
|
|
(component $root
|
|
(core instance $m (instantiate $m))
|
|
(func (export "execute")
|
|
(canon lift (core func $m "execute"))
|
|
)
|
|
)
|
|
(component $c
|
|
(import "backend" (instance $i
|
|
(export "execute" (func))
|
|
))
|
|
(core module $shim2 (import "" "0" (func)))
|
|
(core instance $m (instantiate $m))
|
|
|
|
;; This adapter, when fused with itself on the second instantiation of this
|
|
;; component, will dependend on the prior instance `$m` so it which means
|
|
;; that the adapter module containing this must be placed in the right
|
|
;; location.
|
|
(core func $execute
|
|
(canon lower (func $i "execute") (memory $m "memory") (realloc (func $m "realloc")))
|
|
)
|
|
(core instance (instantiate $shim2
|
|
(with "" (instance
|
|
(export "0" (func $execute))
|
|
))
|
|
))
|
|
(func (export "execute") (canon lift (core func $m "execute")))
|
|
)
|
|
(instance $root (instantiate $root))
|
|
(instance $c1 (instantiate $c (with "backend" (instance $root))))
|
|
(instance $c2 (instantiate $c (with "backend" (instance $c1))))
|
|
)
|