diff --git a/test/wasm-tools/adapt.wast b/test/wasm-tools/adapt.wast new file mode 100644 index 00000000..8cc76f8f --- /dev/null +++ b/test/wasm-tools/adapt.wast @@ -0,0 +1,287 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component definition + (import "log" (func $log (param "msg" string))) + (core module $libc + (memory (export "memory") 1) + (func (export "canonical_abi_realloc") (param i32 i32 i32 i32) (result i32) + unreachable) + ) + + (core module $my_module + (import "env" "log-utf8" (func $log_utf8 (param i32 i32))) + (import "env" "log-utf16" (func $log_utf16 (param i32 i32))) + (import "env" "log-compact-utf16" (func $log_compact_utf16 (param i32 i32))) + + (func (export "log-utf8") (param i32 i32) + local.get 0 + local.get 1 + call $log_utf8 + ) + (func (export "log-utf16") (param i32 i32) + local.get 0 + local.get 1 + call $log_utf16 + ) + (func (export "log-compact-utf16") (param i32 i32) + local.get 0 + local.get 1 + call $log_compact_utf16 + ) + ) + + (core instance $libc (instantiate $libc)) + + (alias core export $libc "canonical_abi_realloc" (core func $realloc)) + (alias core export $libc "memory" (core memory $memory)) + (core func $log_lower_utf8 (canon lower (func $log) string-encoding=utf8 (memory $memory) (realloc $realloc))) + (core func $log_lower_utf16 (canon lower (func $log) string-encoding=utf16 (memory $memory) (realloc $realloc))) + (core func $log_lower_compact_utf16 (canon lower (func $log) string-encoding=latin1+utf16 (memory $memory) (realloc $realloc))) + + (core instance $my_instance (instantiate $my_module + (with "libc" (instance $libc)) + (with "env" (instance + (export "log-utf8" (func $log_lower_utf8)) + (export "log-utf16" (func $log_lower_utf16)) + (export "log-compact-utf16" (func $log_lower_compact_utf16)) + )) + )) + + (func (export "log1") (param "msg" string) + (canon lift + (core func $my_instance "log-utf8") + string-encoding=utf8 + (memory $memory) + (realloc $realloc) + ) + ) + (func (export "log2") (param "msg" string) + (canon lift + (core func $my_instance "log-utf16") + string-encoding=utf16 + (memory $memory) + (realloc $realloc) + ) + ) + (func (export "log3") (param "msg" string) + (canon lift + (core func $my_instance "log-compact-utf16") + string-encoding=latin1+utf16 + (memory $memory) + (realloc $realloc) + ) + ) +) + +(assert_invalid + (component + (import "i" (func $f)) + (core func (canon lower (func $f) string-encoding=utf8 string-encoding=utf16)) + ) + "canonical encoding option `utf8` conflicts with option `utf16`") + +(assert_invalid + (component + (import "i" (func $f)) + (core func (canon lower (func $f) string-encoding=utf8 string-encoding=latin1+utf16)) + ) + "canonical encoding option `utf8` conflicts with option `latin1-utf16`") + +(assert_invalid + (component + (import "i" (func $f)) + (core func (canon lower (func $f) string-encoding=utf16 string-encoding=latin1+utf16)) + ) + "canonical encoding option `utf16` conflicts with option `latin1-utf16`") + +(assert_invalid + (component + (import "i" (func $f)) + (core func (canon lower (func $f) (memory 0))) + ) + "memory index out of bounds") + +(assert_invalid + (component + (import "i" (func $f)) + (core module $m (memory (export "memory") 1)) + (core instance $i (instantiate $m)) + (core func (canon lower (func $f) (memory $i "memory") (memory $i "memory"))) + ) + "`memory` is specified more than once") + +(assert_invalid + (component + (core module $m + (func (export "f") (param i32 i32)) + ) + (core instance $i (instantiate $m)) + (func (param "p1" (list u8)) (canon lift (core func $i "f"))) + ) + "canonical option `memory` is required") + +(assert_invalid + (component + (core module $m + (memory (export "m") 1) + (func (export "f") (param i32 i32)) + ) + (core instance $i (instantiate $m)) + (func (param "p1" (list u8)) + (canon lift (core func $i "f") + (memory $i "m") + ) + ) + ) + "canonical option `realloc` is required") + +(assert_invalid + (component + (core module $m + (memory (export "m") 1) + (func (export "f") (param i32 i32)) + (func (export "r") (param i32 i32 i32 i32) (result i32)) + ) + (core instance $i (instantiate $m)) + (func (param "p1" (list u8)) + (canon lift (core func $i "f") + (memory $i "m") + (realloc (func $i "r")) + (realloc (func $i "r")) + ) + ) + ) + "canonical option `realloc` is specified more than once") + +(assert_invalid + (component + (core module $m + (memory (export "m") 1) + (func (export "f") (param i32 i32)) + (func (export "r")) + ) + (core instance $i (instantiate $m)) + (func (param "p1" (list u8)) + (canon lift (core func $i "f") + (memory $i "m") + (realloc (func $i "r")) + ) + ) + ) + "canonical option `realloc` uses a core function with an incorrect signature") + +(assert_invalid + (component + (core module $m + (memory (export "m") 1) + (func (export "f") (result i32)) + (func (export "r") (param i32 i32 i32 i32) (result i32)) + (func (export "p")) + ) + (core instance $i (instantiate $m)) + (func (result string) + (canon lift (core func $i "f") + (memory $i "m") + (realloc (func $i "r")) + (post-return (func $i "p")) + ) + ) + ) + "canonical option `post-return` uses a core function with an incorrect signature") + +(assert_invalid + (component + (core module $m + (memory (export "m") 1) + (func (export "f") (result i32)) + (func (export "r") (param i32 i32 i32 i32) (result i32)) + (func (export "p") (param i32)) + ) + (core instance $i (instantiate $m)) + (func (result string) + (canon lift (core func $i "f") + (memory $i "m") + (realloc (func $i "r")) + (post-return (func $i "p")) + (post-return (func $i "p")) + ) + ) + ) + "canonical option `post-return` is specified more than once") + +(assert_invalid + (component + (import "i" (func $f (param "p1" string))) + (core module $m + (memory (export "m") 1) + (func (export "f") (result i32)) + (func (export "r") (param i32 i32 i32 i32) (result i32)) + (func (export "p") (param i32)) + ) + (core instance $i (instantiate $m)) + (core func + (canon lower (func $f) + (memory $i "m") + (realloc (func $i "r")) + (post-return (func $i "p")) + ) + ) + ) + "canonical option `post-return` cannot be specified for lowerings") + +(component + (core module $m + (memory (export "m") 1) + (func (export "f") (result i32) unreachable) + (func (export "r") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "p") (param i32)) + ) + (core instance $i (instantiate $m)) + (func (result string) + (canon lift (core func $i "f") + (memory $i "m") + (realloc (func $i "r")) + (post-return (func $i "p")) + ) + ) +) + +(assert_malformed + (component quote + "(core module $m (func (export \"\")))" + "(core instance $i (instantiate $m))" + "(core func (canon lower (func $i \"\")))" + ) + "unknown instance: failed to find name `$i`") + +(assert_invalid + (component + (core module $m (func (export "foo") (param i32))) + (core instance $i (instantiate $m)) + (func (export "foo") (canon lift (core func $i "foo"))) + ) + "lowered parameter types `[]` do not match parameter types `[I32]`") + +(assert_invalid + (component + (core module $m (func (export "foo") (result i32))) + (core instance $i (instantiate $m)) + (func (export "foo") (canon lift (core func $i "foo"))) + ) + "lowered result types `[]` do not match result types `[I32]`") + +(assert_invalid + (component + (type $f string) + (core module $m (func (export "foo"))) + (core instance $i (instantiate $m)) + (func (export "foo") (type $f) (canon lift (core func $i "foo"))) + ) + "not a function type") + +(assert_malformed + (component quote + "(import \"a\" (func $f))" + "(func (export \"foo\") (canon lift (core func $f)))" + ) + "unknown core func: failed to find name `$f`") diff --git a/test/wasm-tools/alias.wast b/test/wasm-tools/alias.wast new file mode 100644 index 00000000..dd9d1b37 --- /dev/null +++ b/test/wasm-tools/alias.wast @@ -0,0 +1,301 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (component + (import "i" (instance $i + (export "f1" (func)) + (export "f2" (func (param "p1" string))) + )) + (export "run" (func $i "f1")) + ) +) + +(component + (component + (import "i" (component $c + (export "f1" (func)) + (export "f2" (func (param "p1" string))) + )) + (instance $i (instantiate $c)) + (export "run" (func $i "f1")) + ) +) + +(component definition + (import "i" (core module $m + (export "f1" (func $f1)) + (export "f2" (func $f2 (param i32))) + )) + (core instance $i (instantiate $m)) + + (core module $m2 (import "" "" (func))) + + (core instance (instantiate $m2 (with "" (instance (export "" (func $i "f1")))))) +) + +(component definition + (import "a" (core module $libc + (export "memory" (memory 1)) + (export "table" (table 0 funcref)) + (export "func" (func)) + (export "global" (global i32)) + (export "global mut" (global (mut i64))) + )) + (core instance $libc (instantiate $libc)) + (alias core export $libc "memory" (core memory $mem)) + (alias core export $libc "table" (core table $tbl)) + (alias core export $libc "func" (core func $func)) + (alias core export $libc "global" (core global $global)) + (alias core export $libc "global mut" (core global $global_mut)) + + (import "x" (core module $needs_libc + (import "" "memory" (memory 1)) + (import "" "table" (table 0 funcref)) + (import "" "func" (func)) + (import "" "global" (global i32)) + (import "" "global mut" (global (mut i64))) + )) + + (core instance (instantiate $needs_libc (with "" (instance + (export "memory" (memory $mem)) + (export "table" (table $tbl)) + (export "func" (func $func)) + (export "global" (global $global)) + (export "global mut" (global $global_mut)) + )))) +) + +(component + (component + (import "a" (instance $i + (export "a" (func)) + (export "b" (core module)) + (export "c" (instance)) + )) + (export "b" (func $i "a")) + (export "c" (core module $i "b")) + (export "d" (instance $i "c")) + ) +) + + +(component definition + (import "a" (core module $libc + (export "memory" (memory 1)) + (export "table" (table 0 funcref)) + (export "func" (func)) + (export "global" (global i32)) + (export "global mut" (global (mut i64))) + )) + + (import "b" (core module $needs_libc + (import "" "memory" (memory 1)) + (import "" "table" (table 0 funcref)) + (import "" "func" (func)) + (import "" "global" (global i32)) + (import "" "global mut" (global (mut i64))) + )) + + (core instance $libc (instantiate $libc)) + (core instance (instantiate $needs_libc (with "" (instance + (export "memory" (memory $libc "memory")) + (export "table" (table $libc "table")) + (export "func" (func $libc "func")) + (export "global" (global $libc "global")) + (export "global mut" (global $libc "global mut")) + )))) +) + +(assert_invalid + (component + (import "a" (instance (export "a" (func)))) + (export "a" (core module 0 "a")) + ) + "export `a` for instance 0 is not a module") + +(assert_invalid + (component + (component + (component (export "a")) + ) + (instance (instantiate 0)) + (export "a" (core module 0 "a")) + ) + "export `a` for instance 0 is not a module") + +(assert_invalid + (component + (import "a" (core module)) + (core instance (instantiate 0)) + (alias core export 0 "a" (core func)) + ) + "core instance 0 has no export named `a`") + +(assert_invalid + (component + (core module) + (core instance (instantiate 0)) + (alias core export 0 "a" (core func)) + ) + "core instance 0 has no export named `a`") + +(assert_invalid + (component + (import "a" (component)) + (instance (instantiate 0)) + (alias export 0 "a" (func)) + ) + "instance 0 has no export named `a`") + +(assert_invalid + (component + (import "a" (core module $a (export "" (func)))) + (import "b" (core module $b (import "" "" (func (param i32))))) + + (core instance $a (instantiate $a)) + (core instance $b (instantiate $b (with "" (instance $a)))) + ) + "type mismatch") + +;; aliasing various items works + +(component $PARENT + (type $t (func (result string))) + (component + (import "a" (func (type $t))) + ) + (component + (alias outer $PARENT $t (type $my_type)) + (alias outer 0 $my_type (type $my_type_again)) + (import "a" (func (type $my_type_again))) + ) +) + +(component + (type $a (func (result string))) + (component + (type $b (func (result u32))) + (component + (type $c (func (result s32))) + + (component + (import "a" (func $a (type $a))) + (import "b" (func $b (type $b))) + (import "c" (func $c (type $c))) + + (import "d" (component $C + (import "a" (func (result string))) + (import "b" (func (result u32))) + (import "c" (func (result s32))) + )) + + (instance (instantiate $C + (with "a" (func $a)) + (with "b" (func $b)) + (with "c" (func $c)) + )) + ) + ) + ) +) + +;; multiple projections in alias sugar +(component + (component $a + (import "a" (instance $a + (export "a" (instance + (export "a" (instance + (export "a" (instance + (export "a" (func)) + )) + )) + )) + )) + + (import "b" (component $b (import "a" (func)))) + + (instance (instantiate $b + (with "a" (func $a "a" "a" "a" "a")) + )) + ) +) + +;; alias some constructs +(component + (component + (import "a" (instance $foo (export "v" (component)))) + (export "v" (component $foo "v")) + ) +) + +(component definition + (import "a" (instance $foo (export "v" (core module)))) + (export "v" (core module $foo "v")) +) + +(component $C + (core type $t (func)) + (component $C2 + (alias outer $C $t (core type $t2)) + (component + (alias outer $C $t (core type)) + (alias outer $C2 $t2 (core type)) + ) + ) +) + +(component $C + (core module $m) + (alias outer $C $m (core module $target)) + (export "v" (core module $target)) +) + +(component + (component $C + (component $m) + (alias outer $C $m (component $target)) + (export "v" (component $target)) + ) +) + +(assert_invalid + (component (alias outer 100 0 (core type))) + "invalid outer alias count of 100") + +(assert_invalid + (component (alias outer 0 0 (core type))) + "index out of bounds") + +(assert_invalid + (component (alias outer 100 0 (core module))) + "invalid outer alias count of 100") + +(assert_invalid + (component (alias outer 0 0 (core module))) + "index out of bounds") + +(assert_invalid + (component (alias outer 100 0 (component))) + "invalid outer alias count of 100") + +(assert_invalid + (component (alias outer 0 0 (component))) + "index out of bounds") + +(component definition + (import "a" (instance $i + (export "x" (core module)) + )) + ;; inline alias injection sugar works for module references + (core instance (instantiate (module $i "x"))) +) + +(component + (component + (import "a" (instance $i + (export "x" (component)) + )) + ;; inline alias injection sugar works for component references + (instance (instantiate (component $i "x"))) + ) +) diff --git a/test/wasm-tools/big.wast b/test/wasm-tools/big.wast new file mode 100644 index 00000000..770df0ab --- /dev/null +++ b/test/wasm-tools/big.wast @@ -0,0 +1,36 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component definition + (import "wasi-logging" (instance $logging + (export "log" (func (param "msg" string))) + )) + (import "libc" (core module $Libc + (export "memory" (memory 1)) + (export "realloc" (func (param i32 i32 i32 i32) (result i32))) + )) + (core instance $libc (instantiate $Libc)) + (core func $log (canon lower + (func $logging "log") + (memory $libc "memory") (realloc (func $libc "realloc")) + )) + (core module $Main + (import "libc" "memory" (memory 1)) + (import "libc" "realloc" (func (param i32 i32 i32 i32) (result i32))) + (import "wasi-logging" "log" (func $log (param i32 i32))) + (func (export "run") (param i32 i32) (result i32) + (local.get 0) + (local.get 1) + (call $log) + (unreachable) + ) + ) + (core instance $main (instantiate $Main + (with "libc" (instance $libc)) + (with "wasi-logging" (instance (export "log" (func $log)))) + )) + (func $run (param "in" string) (result string) (canon lift + (core func $main "run") + (memory $libc "memory") (realloc (func $libc "realloc")) + )) + (export "run" (func $run)) +) diff --git a/test/wasm-tools/definedtypes.wast b/test/wasm-tools/definedtypes.wast new file mode 100644 index 00000000..989ebcf2 --- /dev/null +++ b/test/wasm-tools/definedtypes.wast @@ -0,0 +1,162 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component $C + (type $A1 bool) + (type $A2 u8) + (type $A3 s8) + (type $A4 u16) + (type $A5 s16) + (type $A6 u32) + (type $A7 s32) + (type $A8 u64) + (type $A9 s64) + (type $A10a f32) + (type $A11a f64) + (type $A10b float32) + (type $A11b float64) + (type $A12 char) + (type $A13 string) + + (type $A14b (record (field "x" (tuple char)))) + (type $A14c (record (field "x" $A1))) + + (type $A15a (variant (case "x"))) + (type $A15b (variant (case "x" $A1))) + (type $A15c (variant (case $x "x") (case $y "y" string (refines $x)) (case "z" string (refines $y)))) + (type $A15d (variant (case "x") (case "y" string (refines 0)) (case "z" string (refines 1)))) + + (type $A16a (list (tuple u8))) + (type $A16b (list $A3)) + + (type $A17a (tuple u8)) + (type $A17b (tuple $A4)) + + (type $A18b (flags "x")) + + (type $A19b (enum "x")) + + (type $A21a (option (tuple u32))) + (type $A21b (option $A6)) + + (type $A22a (result)) + (type $A22b (result $A7)) + (type $A22c (result (error $A8))) + (type $A22d (result $A9 (error $A10a))) +) + +(assert_malformed + (component quote + "(type $t (variant (case $x \"x\" string (refines $x))))" + ) + "variant case cannot refine itself" +) + +(assert_malformed + (component quote + "(type $t (variant (case \"x\" (refines $y)) (case $y \"y\" string)))" + ) + "unknown variant case" +) + +(assert_malformed + (component quote + "(type $t string)" + "(type $v (variant (case \"x\" $t (refines $z))))" + ) + "unknown variant case" +) + + +(assert_invalid + (component + (type $t string) + (type $v (variant (case "x" $t (refines 1)))) + ) + "variant case can only refine a previously defined case" +) + +(assert_invalid + (component + (type $t string) + (type $v (variant (case "x" $t) (case "y" u64 (refines 2)) (case "z" string))) + ) + "variant case can only refine a previously defined case" +) + +(assert_malformed + (component quote + "(type $t string)" + "(type $v (variant (case $x \"x\" $t) (case $x \"y\" $t)))" + ) + "duplicate variant case identifier" +) + +(assert_invalid + (component + (type $t (func)) + (type (func (param "t" $t))) + ) + "type index 0 is not a defined type") + +(assert_invalid + (component + (type $t (instance)) + (type (func (result $t))) + ) + "type index 0 is not a defined type") + +(assert_invalid + (component + (type $t (component)) + (type (option $t)) + ) + "type index 0 is not a defined type") + +(assert_invalid + (component (type (option 0))) + "index out of bounds") +(assert_invalid + (component (type (list 0))) + "index out of bounds") +(assert_invalid + (component (type (record (field "x" 0)))) + "index out of bounds") +(assert_invalid + (component (type (variant (case "x" 0)))) + "index out of bounds") +(assert_invalid + (component (type (result 0 (error 1)))) + "index out of bounds") +(assert_invalid + (component (type (tuple 0))) + "index out of bounds") + +(assert_invalid + (component (type (record (field "a-B-c-D" string) (field "A-b-C-d" u8)))) + "record field name `A-b-C-d` conflicts with previous field name `a-B-c-D`") +(assert_invalid + (component (type (variant (case "x" s64) (case "x" s64)))) + "variant case name `x` conflicts with previous case name `x`") +(assert_invalid + (component (type (flags "x" "y" "X"))) + "flag name `X` conflicts with previous flag name `x`") +(assert_invalid + (component (type (enum "x" "y" "X"))) + "enum tag name `X` conflicts with previous tag name `x`") + +(assert_invalid + (component (type (record (field "" s32)))) + "name cannot be empty") +(assert_invalid + (component (type (variant (case "" s32)))) + "name cannot be empty") +(assert_invalid + (component (type (flags ""))) + "name cannot be empty") +(assert_invalid + (component (type (enum ""))) + "name cannot be empty") + +(assert_invalid + (component (type (variant))) + "variant type must have at least one case") diff --git a/test/wasm-tools/empty.wast b/test/wasm-tools/empty.wast new file mode 100644 index 00000000..7f22181b --- /dev/null +++ b/test/wasm-tools/empty.wast @@ -0,0 +1,4 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +;; The most minimal component. +(component) diff --git a/test/wasm-tools/example.wast b/test/wasm-tools/example.wast new file mode 100644 index 00000000..9ba429fe --- /dev/null +++ b/test/wasm-tools/example.wast @@ -0,0 +1,17 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +;; With what's defined so far, we can define the following component: + +(component + (component + (core module (func (export "one") (result i32) (i32.const 1))) + (core module (func (export "two") (result f32) (f32.const 2))) + ) + (core module (func (export "three") (result i64) (i64.const 3))) + (component + (component + (core module (func (export "four") (result f64) (f64.const 4))) + ) + ) + (component) +) diff --git a/test/wasm-tools/export-ascription.wast b/test/wasm-tools/export-ascription.wast new file mode 100644 index 00000000..ca70736e --- /dev/null +++ b/test/wasm-tools/export-ascription.wast @@ -0,0 +1,44 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (component + (import "f" (func $f)) + (export "f2" (func $f) (func)) + ) +) + +;; subtyping works +(component + (component + (import "f" (instance $i (export "f" (func)))) + (export "f2" (instance $i) (instance)) + ) +) + +;; make sure subtyping works in the right direction +(assert_invalid + (component + (import "f" (instance $i)) + (export "f2" (instance $i) (instance (export "f" (func)))) + ) + "ascribed type of export is not compatible") + +;; make sure the type is actually changed +(assert_invalid + (component + (import "f" (func $f)) + + (component $c + (import "f" (instance $i (export "f" (func)))) + (export "f2" (instance $i) (instance)) + ) + + (instance $c (instantiate $c (with "f" (instance (export "f" (func $f)))))) + + (component $consume + (import "arg" (instance $i (export "f" (func)))) + ) + + (instance (instantiate $consume (with "arg" (instance $c "f2")))) + ) + "missing expected export `f`") diff --git a/test/wasm-tools/export-introduces-alias.wast b/test/wasm-tools/export-introduces-alias.wast new file mode 100644 index 00000000..40d33efa --- /dev/null +++ b/test/wasm-tools/export-introduces-alias.wast @@ -0,0 +1,48 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (component + (import "x" (func $f)) + + (export $g "g" (func $f)) + (export $g2 "g2" (func $g)) + ) +) + +(component + (type (component + (type $t u8) + (import "x" (instance $i (export "t" (type (eq $t))))) + (alias export $i "t" (type $my-t)) + )) +) + +(component + (type (component + (type $t u8) + (import "x" (instance $i + (export "i" (instance + (export "t" (type (eq $t))) + )) + )) + (alias export $i "i" (instance $my-i)) + (alias export $my-i "t" (type $my-t)) + )) +) + +(assert_malformed + (component quote + "(type (instance" + "(type $t u8)" + "(export \"t\" (type $t (eq $t)))" + "))" + ) + "duplicate type identifier") + +(component + (type (instance + (type $t u8) + (export "t" (type $t2 (eq $t))) + (export "t2" (type $t3 (eq $t2))) + )) +) diff --git a/test/wasm-tools/export.wast b/test/wasm-tools/export.wast new file mode 100644 index 00000000..73d094c8 --- /dev/null +++ b/test/wasm-tools/export.wast @@ -0,0 +1,63 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component (export "" (instance 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (component 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (core module 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (func 0))) + "index out of bounds") + +(component + (component + (import "a" (instance $i)) + (import "b" (core module $m)) + (import "c" (component $c)) + (import "e" (func $f)) + + (export "f" (instance $i)) + (export "g" (core module $m)) + (export "h" (component $c)) + (export "j" (func $f)) + ) +) + +(component + (component + (import "a" (func)) + (export (interface "wasi:http/types@2.0.0") (func 0)) + ) +) + +;; import/exports can overlap on ids +(component + (component + (import (interface "wasi:http/types@2.0.0") (func)) + (export (interface "wasi:http/types@2.0.0") (func 0)) + ) +) + +;; cannot export some types of strings +(assert_invalid + (component (type (component (export "integrity=" (func))))) + "not a valid export name") +(assert_invalid + (component (type (component (export "url=" (func))))) + "not a valid export name") +(assert_invalid + (component (type (component (export "relative-url=" (func))))) + "not a valid extern name") +(assert_invalid + (component (type (component (export "locked-dep=" (func))))) + "not a valid export name") +(assert_invalid + (component (type (component (export "unlocked-dep=" (func))))) + "not a valid export name") diff --git a/test/wasm-tools/func.wast b/test/wasm-tools/func.wast new file mode 100644 index 00000000..4a207f99 --- /dev/null +++ b/test/wasm-tools/func.wast @@ -0,0 +1,146 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component definition + (import "a" (func (param "foo" string))) + (import "b" (func (param "foo" string) (param "bar" s32) (param "baz" u32))) + (import "c" (func (result (tuple u8)))) +) + +(component definition + (import "a" (func)) + (import "b" (func (param "p1" string))) + (import "c" (func (result u32))) + (import "d" (func (param "p1" bool) (result string))) +) + + +(assert_invalid + (component + (type (func (param "foo" string) (param "FOO" u32))) + ) + "function parameter name `FOO` conflicts with previous parameter name `foo`" +) + +(assert_invalid + (component + (core module $m + (memory (export "memory") 1) + (func (export "foo") (result i32) unreachable) + ) + (core instance $i (instantiate $m)) + + (func (export "tuple") (result (tuple s8 u8)) + (canon lift (core func $i "foo")) + ) + ) + "canonical option `memory` is required" +) + +(component definition + (import "a" (func $log (param "msg" string))) + (core module $libc + (memory (export "memory") 1) + ) + (core instance $libc (instantiate $libc)) + (core func (canon lower (func $log) (memory $libc "memory"))) +) + +(component + (core module $m + (memory (export "memory") 1) + (func (export "ret-list") (result i32) unreachable) + ) + (core instance $i (instantiate $m)) + + (func (export "ret-list") (result (list u8)) + (canon lift (core func $i "ret-list") (memory $i "memory")) + ) +) + +(component + (type $big (func + (param "p1" u32) (param "p2" u32) (param "p3" u32) (param "p4" u32) (param "p5" u32) + (param "p6" u32) (param "p7" u32) (param "p8" u32) (param "p9" u32) (param "p10" u32) + (param "p11" u32) (param "p12" u32) (param "p13" u32) (param "p14" u32) (param "p15" u32) + (param "p16" u32) (param "p17" u32) (param "p18" u32) (param "p19" u32) (param "p20" u32) + )) + + (component $c + (import "big" (func $big (type $big))) + (core module $libc (memory (export "memory") 1)) + (core instance $libc (instantiate $libc)) + (core func $big (canon lower (func $big) (memory $libc "memory"))) + ) +) + +(assert_invalid + (component + (core module $m + (memory (export "memory") 1) + (func (export "roundtrip") (param i32)) + ) + (core instance $m (instantiate $m)) + + (type $roundtrip (func + (param "p1" u32) (param "p2" u32) (param "p3" u32) (param "p4" u32) (param "p5" u32) + (param "p6" u32) (param "p7" u32) (param "p8" u32) (param "p9" u32) (param "p10" u32) + (param "p11" u32) (param "p12" u32) (param "p13" u32) (param "p14" u32) (param "p15" u32) + (param "p16" u32) (param "p17" u32) (param "p18" u32) (param "p19" u32) (param "p20" u32) + )) + + (func $roundtrip (type $roundtrip) + (canon lift (core func $m "roundtrip") (memory $m "memory")) + ) + (export "roundtrip" (func $roundtrip)) + ) + "canonical option `realloc` is required" +) + +(assert_invalid + (component + (import "a" (func $log (result string))) + (core module $libc + (memory (export "memory") 1) + ) + (core instance $libc (instantiate $libc)) + (core func (canon lower (func $log) (memory $libc "memory"))) + ) + "canonical option `realloc` is required" +) + +(assert_invalid + (component + (core module $m + (memory (export "memory") 1) + (func (export "param-list") (param i32 i32) unreachable) + ) + (core instance $i (instantiate $m)) + + (func (export "param-list") (param "bytes" (list u8)) + (canon lift (core func $i "param-list") (memory $i "memory")) + ) + ) + "canonical option `realloc` is required" +) + +(assert_malformed + (component binary + "\00asm" "\0d\00\01\00" ;; component header + "\07\05" ;; component type section, 5 bytes + "\01" ;; 1 count + "\40" ;; component function type + "\00" ;; 0 parameters + "\01\01" ;; invalid result encoding + ) + "invalid leading byte (0x1) for number of results") + +(assert_malformed + (component binary + "\00asm" "\0d\00\01\00" ;; component header + "\07\05" ;; component type section, 5 bytes + "\01" ;; 1 count + "\40" ;; component function type + "\00" ;; 0 parameters + "\02\00" ;; invalid result encoding + ) + "invalid leading byte (0x2) for component function results") diff --git a/test/wasm-tools/import.wast b/test/wasm-tools/import.wast new file mode 100644 index 00000000..b226157e --- /dev/null +++ b/test/wasm-tools/import.wast @@ -0,0 +1,359 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (component + (import "a" (func)) + (import "b" (instance)) + (import "c" (instance + (export "a" (func)) + )) + (import "d" (component + (import "a" (core module)) + (export "b" (func)) + )) + (type $t (func)) + (import "e" (type (eq $t))) + ) +) + +(assert_invalid + (component + (type $f (func)) + (import "a" (instance (type $f))) + ) + "type index 0 is not an instance type") + +(assert_invalid + (component + (core type $f (func)) + (import "a" (core module (type $f))) + ) + "core type index 0 is not a module type") + +(assert_invalid + (component + (type $f string) + (import "a" (func (type $f))) + ) + "type index 0 is not a function type") + +;; Disallow duplicate imports for core wasm modules +(assert_invalid + (component + (core type (module + (import "" "" (func)) + (import "" "" (func)) + )) + ) + "duplicate import name `:`") +(assert_invalid + (component + (core module + (import "" "" (func)) + (import "" "" (func)) + ) + ) + "duplicate import name `:`") +(assert_invalid + (component + (core type (module + (import "" "a" (func)) + (import "" "a" (func)) + )) + ) + "duplicate import name `:a`") +(assert_invalid + (component + (core module + (import "" "a" (func)) + (import "" "a" (func)) + ) + ) + "duplicate import name `:a`") + +(assert_invalid + (component + (import "a" (func)) + (import "a" (func)) + ) + "import name `a` conflicts with previous name `a`") + +(assert_invalid + (component + (type (component + (import "a" (func)) + (import "a" (func)) + )) + ) + "import name `a` conflicts with previous name `a`") + +(assert_invalid + (component + (import "a" (func (type 100))) + ) + "type index out of bounds") + +(assert_invalid + (component + (core module $m (func (export ""))) + (core instance $i (instantiate $m)) + (func (type 100) (canon lift (core func $i ""))) + ) + "type index out of bounds") + +(component definition + (import "wasi:http/types" (func)) + (import "wasi:http/types@1.0.0" (func)) + (import "wasi:http/types@2.0.0" (func)) + (import "a-b:c-d/e-f@123456.7890.488" (func)) + (import "a:b/c@1.2.3" (func)) + (import "a:b/c@0.0.0" (func)) + (import "a:b/c@0.0.0+abcd" (func)) + (import "a:b/c@0.0.0+abcd-efg" (func)) + (import "a:b/c@0.0.0-abcd+efg" (func)) + (import "a:b/c@0.0.0-abcd.1.2+efg.4.ee.5" (func)) +) + +(assert_invalid + (component + (import "wasi:http/types" (func)) + (import "wasi:http/types" (func)) + ) + "conflicts with previous name") + +(assert_invalid + (component (import "" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "wasi:" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "wasi:/" (func))) + "not in kebab case") +(assert_invalid + (component (import ":/" (func))) + "not in kebab case") +(assert_invalid + (component (import "wasi/http" (func))) + "`wasi/http` is not in kebab case") +(assert_invalid + (component (import "wasi:http/TyPeS" (func))) + "`TyPeS` is not in kebab case") +(assert_invalid + (component (import "WaSi:http/types" (func))) + "`WaSi` is not in kebab case") +(assert_invalid + (component (import "wasi:HtTp/types" (func))) + "`HtTp` is not in kebab case") +(assert_invalid + (component (import "wasi:http/types@" (func))) + "empty string") +(assert_invalid + (component (import "wasi:http/types@." (func))) + "unexpected character '.'") +(assert_invalid + (component (import "wasi:http/types@1." (func))) + "unexpected end of input") +(assert_invalid + (component (import "wasi:http/types@a.2" (func))) + "unexpected character 'a'") +(assert_invalid + (component (import "wasi:http/types@2.b" (func))) + "unexpected character 'b'") +(assert_invalid + (component (import "wasi:http/types@2.0x0" (func))) + "unexpected character 'x'") +(assert_invalid + (component (import "wasi:http/types@2.0.0+" (func))) + "empty identifier segment") +(assert_invalid + (component (import "wasi:http/types@2.0.0-" (func))) + "empty identifier segment") +(assert_invalid + (component (import "foo:bar:baz/qux" (func))) + "expected `/` after package name") +(assert_invalid + (component (import "foo:bar/baz/qux" (func))) + "trailing characters found: `/qux`") + +(component + (component + (import "a" (func $a)) + (export "a" (func $a)) + ) +) + +(component definition + (import "unlocked-dep=" (func)) + (import "unlocked-dep=" (func)) + (import "unlocked-dep==1.2.3}>" (func)) + (import "unlocked-dep==1.2.3-rc}>" (func)) + (import "unlocked-dep=" (func)) + (import "unlocked-dep=" (func)) + (import "unlocked-dep==1.2.3 <1.2.3}>" (func)) + (import "unlocked-dep==1.2.3-rc <1.2.3}>" (func)) +) + +(assert_invalid + (component (import "unlocked-dep=" (func))) + "expected `<` at ``") +(assert_invalid + (component (import "unlocked-dep=<" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "unlocked-dep=<>" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "unlocked-dep=<:>" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "unlocked-dep=" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "unlocked-dep=<:a>" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "unlocked-dep=" (func))) + "expected `{` at `>`") +(assert_invalid + (component (import "unlocked-dep=" (func))) + "expected `>=` or `<` at start of version range") +(assert_invalid + (component (import "unlocked-dep=" (func))) + "`xyz` is not a valid semver") +(assert_invalid + (component (import "unlocked-dep==2.3.4}>" (func))) + "`1.2.3 >=2.3.4` is not a valid semver") + +(component definition + (import "locked-dep=" (func)) + (import "locked-dep=" (func)) + (import "locked-dep=,integrity=" (func)) + (import "locked-dep=,integrity=" (func)) +) + +(assert_invalid + (component (import "locked-dep=" (func))) + "expected `<` at ``") +(assert_invalid + (component (import "locked-dep=<" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "locked-dep=<:" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "locked-dep=<:>" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "locked-dep=" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "locked-dep=<:a>" (func))) + "`` is not in kebab case") +(assert_invalid + (component (import "locked-dep=` at ``") +(assert_invalid + (component (import "locked-dep=" (func))) + "is not a valid semver") +(assert_invalid + (component (import "locked-dep=` at ``") +(assert_invalid + (component (import "locked-dep=," (func))) + "expected `integrity=<`") +(assert_invalid + (component (import "locked-dep=x" (func))) + "trailing characters found: `x`") + +(component definition + (import "url=<>" (func)) + (import "url=" (func)) + (import "url=,integrity=" (func)) +) + +(assert_invalid + (component (import "url=" (func))) + "expected `<` at ``") +(assert_invalid + (component (import "url=<" (func))) + "failed to find `>`") +(assert_invalid + (component (import "url=<<>" (func))) + "url cannot contain `<`") + +(assert_invalid + (component + (import "relative-url=<>" (func)) + (import "relative-url=" (func)) + (import "relative-url=,integrity=" (func)) + ) + "not a valid extern name") + +(assert_invalid + (component (import "relative-url=" (func))) + "not a valid extern name") +(assert_invalid + (component (import "relative-url=<" (func))) + "not a valid extern name") +(assert_invalid + (component (import "relative-url=<<>" (func))) + "not a valid extern name") + +(component definition + (import "integrity=" (func)) + (import "integrity=" (func)) + (import "integrity=" (func)) + (import "integrity=" (func)) + (import "integrity=< sha512-a sha256-b >" (func)) + (import "integrity=< sha512-a?abcd >" (func)) + (import "integrity=" (func)) + (import "integrity=" (func)) + (import "integrity=" (func)) + (import "integrity=" (func)) +) +(assert_invalid + (component (import "integrity=<>" (func))) + "integrity hash cannot be empty") +(assert_invalid + (component (import "integrity=" (func))) + "expected `-` after hash algorithm") +(assert_invalid + (component (import "integrity=" (func))) + "not valid base64") +(assert_invalid + (component (import "integrity=" (func))) + "not valid base64") +(assert_invalid + (component (import "integrity=" (func))) + "not valid base64") +(assert_invalid + (component (import "integrity=" (func))) + "not valid base64") +(assert_invalid + (component (import "integrity=" (func))) + "not valid base64") +(assert_invalid + (component (import "integrity=" (func))) + "unrecognized hash algorithm") + +;; Prior to WebAssembly/component-model#263 this was a valid component. +;; Specifically the 0x01 prefix byte on the import was valid. Nowadays that's +;; not valid in the spec but it's accepted for backwards compatibility. This +;; tests is here to ensure such compatibility. In the future this test should +;; be changed to `(assert_invalid ...)` +(component definition binary + "\00asm" "\0d\00\01\00" ;; component header + + "\07\05" ;; type section, 5 bytes large + "\01" ;; 1 count + "\40" ;; function + "\00" ;; parameters, 0 count + "\01\00" ;; results, named, 0 count + + "\0a\06" ;; import section, 6 bytes large + "\01" ;; 1 count + "\01" ;; prefix byte of 0x01 (invalid by the spec nowadays) + "\01a" ;; name = "a" + "\01\00" ;; type = func ($type 0) +) diff --git a/test/wasm-tools/imports-exports.wast b/test/wasm-tools/imports-exports.wast new file mode 100644 index 00000000..e650c8c8 --- /dev/null +++ b/test/wasm-tools/imports-exports.wast @@ -0,0 +1,26 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +;; With what's defined so far, we can define a component that imports, links and exports other components: + +(component + (component + (import "c" (instance $c + (export "f" (func (result string))) + )) + (import "d" (component $D + (import "c" (instance $c + (export "f" (func (result string))) + )) + (export "g" (func (result string))) + )) + (instance $d1 (instantiate $D + (with "c" (instance $c)) + )) + (instance $d2 (instantiate $D + (with "c" (instance + (export "f" (func $d1 "g")) + )) + )) + (export "d2" (instance $d2)) + ) +) diff --git a/test/wasm-tools/inline-exports.wast b/test/wasm-tools/inline-exports.wast new file mode 100644 index 00000000..2c3ff567 --- /dev/null +++ b/test/wasm-tools/inline-exports.wast @@ -0,0 +1,9 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (type (export "foo") u8) +) + +(assert_malformed + (component quote "(type (component (type (export \"\") (func))))") + "unexpected token") diff --git a/test/wasm-tools/instance-type.wast b/test/wasm-tools/instance-type.wast new file mode 100644 index 00000000..2f4b1404 --- /dev/null +++ b/test/wasm-tools/instance-type.wast @@ -0,0 +1,234 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +;; instances +(component + (type (instance)) + + (type $foo (func)) + + (type $t (func (result string))) + + (core type (module + (type $local_type (func)) + ;; functions + (export "a" (func)) + (export "b" (func $foo)) + (export "c" (func)) + (export "d" (func $foo)) + (export "e" (func (type $local_type))) + (export "f" (func (param i32))) + (export "g" (func (param i32) (result i32 i64))) + (export "h" (func (type $local_type) (result i32))) + + ;; globals + (export "i" (global i32)) + (export "j" (global $foo i32)) + (export "k" (global (mut i32))) + + ;; tables + (export "l" (table 1 funcref)) + (export "m" (table $foo 1 funcref)) + + ;; memory + (export "n" (memory 1)) + (export "o" (memory $foo 1)) + (export "p" (memory 1 2)) + (export "q" (memory 1 2 shared)) + )) + + (type $outer (instance + (type $local_type (func)) + ;; functions + (export "a" (func)) + (export "a2" (func (type $local_type))) + (export "b" (func)) + (export "c" (func)) + (export "d" (func)) + (export "e" (func (type $t))) + (export "f" (func (param "f" string))) + (export "g" (func (param "g" s32) (result u32))) + (export "h" (func (type $t))) + + ;; components + (type $component_type (component)) + (export "c1" (component)) + (export "c2" (component (import "i1" (func)))) + (export "c3" (component (export "e1" (func)))) + (export "c4" (component (type $component_type))) + (export "c5" (component + (type $nested_func_type (func)) + (alias outer $outer $local_type (type $my_type)) + (import "i1" (func (type $nested_func_type))) + (import "i2" (component)) + (export "e1" (func (type $my_type))) + (export "e2" (component)) + )) + )) +) + +;; expand inline types +(component + (type (instance (export "a" (instance)))) +) + +;; reference outer types +(component + (type (instance + (type $t (instance)) + (export "a" (instance (type $t))) + )) + (type $x (instance)) + (type (instance (export "a" (instance (type $x))))) +) + +;; recursive +(component + (type (instance (export "a" (core module + (type $functype (func)) + + (export "a" (func)) + (export "b" (func (type 0))) + (export "c" (func (param i32))) + (export "d" (func (type $functype))) + + ;; globals + (export "e" (global i32)) + (export "f" (global (mut i32))) + + ;; tables + (export "g" (table 1 funcref)) + + ;; memory + (export "h" (memory 1)) + (export "i" (memory 1 2)) + (export "j" (memory 1 2 shared)) + )))) +) + +;; modules +(component + (core type (module)) + + (core type $foo (module)) + + (type $empty (func)) + (type $i (instance)) + + (core type (module + (type $empty (func)) + (import "" "a" (func)) + (import "" "b" (func (type $empty))) + (import "" "c" (func (param i32))) + (import "" "d" (func (param i32) (result i32))) + + (import "" "e" (global i32)) + (import "" "f" (memory 1)) + (import "" "g" (table 1 funcref)) + + (export "a" (func)) + (export "b" (global i32)) + (export "c" (memory 1)) + (export "d" (table 1 funcref)) + + (export "e" (func (type $empty))) + (export "f" (func (param i32))) + )) + + (type (component + (import "a" (func)) + (import "b" (func (type $empty))) + (import "c" (func (param "c" s32))) + (import "d" (func (param "d" s32) (result s32))) + + (import "h" (instance)) + (import "i" (instance (type $i))) + (import "j" (instance + (export "a" (func)) + (export "b" (func (type $empty))) + (export "c" (func (param "c" s32))) + )) + + (import "k" (core module)) + (import "l" (core module + (type $empty (func)) + (import "" "a" (func (type $empty))) + (import "" "b" (func (param i32))) + (export "a" (func (type $empty))) + (export "b" (func (param i32))) + )) + + (export "m" (func)) + (export "n" (func (type $empty))) + (export "o" (func (param "f" s32))) + + (export "p" (instance + (export "a" (func)) + (export "b" (func (type $empty))) + (export "c" (func (param "c" s32))) + )) + + (export "q" (core module + (type $empty (func)) + (import "" "a" (func (type $empty))) + (import "" "b" (func (param i32))) + (export "a" (func (type $empty))) + (export "b" (func (param i32))) + )) + )) +) + +(assert_invalid + (component + (type (instance + (export "a" (func)) + (export "a" (func))))) + "export name `a` conflicts with previous name `a`") + +(assert_invalid + (component + (type $t (func)) + (type (instance + (export "a" (instance (type $t))) + ))) + "type index 0 is not an instance type") + +(assert_invalid + (component + (core type $t (func)) + (type (instance + (export "a" (core module (type $t))) + ))) + "core type index 0 is not a module type") + +(assert_malformed + (component quote + "(type $t (func))" + "(type (instance (export \"a\" (core module (type $t)))))" + ) + "unknown core type") + +(assert_invalid + (component + (type $t (record (field "a" string))) + (type (instance + (export "a" (func (type $t))) + ))) + "type index 0 is not a function type") + +(assert_invalid + (component + (type $t (instance)) + (type (instance + (export "a" (func (type $t))) + ))) + "type index 0 is not a function type") + +(assert_invalid + (component + (type $t (instance)) + (type (instance + (export "a" (instance + (export "a" (func (type $t))) + )) + ))) + "type index 0 is not a function type") diff --git a/test/wasm-tools/instantiate.wast b/test/wasm-tools/instantiate.wast new file mode 100644 index 00000000..cb992394 --- /dev/null +++ b/test/wasm-tools/instantiate.wast @@ -0,0 +1,976 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component definition + (import "a" (core module $m)) + (core instance $a (instantiate $m)) +) + +(component + (component + (import "a" (func $i)) + (import "b" (component $c (import "a" (func)))) + (instance (instantiate $c (with "a" (func $i)))) + ) +) + +(component + (component + (import "a" (component $i)) + (import "b" (component $c (import "a" (component)))) + (instance (instantiate $c (with "a" (component $i)))) + ) +) + +(component + (component + (import "a" (core module $i)) + (import "b" (component $c (import "a" (core module)))) + (instance (instantiate $c (with "a" (core module $i)))) + ) +) + +(component + (component + (import "a" (instance $i)) + (import "b" (component $c (import "a" (instance)))) + (instance (instantiate $c (with "a" (instance $i)))) + ) +) + +(component definition + (import "a" (core module $m + (import "" "a" (func)) + (import "" "b" (global i32)) + (import "" "c" (table 1 funcref)) + (import "" "d" (memory 1)) + )) + (import "b" (core module $m2 + (export "a" (func)) + (export "b" (global i32)) + (export "c" (table 1 funcref)) + (export "d" (memory 1)) + )) + (core instance $x (instantiate $m2)) + (core instance (instantiate $m (with "" (instance $x)))) +) + +(component definition + (import "a" (core module $m + (import "" "d" (func)) + (import "" "c" (global i32)) + (import "" "b" (table 1 funcref)) + (import "" "a" (memory 1)) + )) + (import "b" (core module $m2 + (export "a" (func)) + (export "b" (global i32)) + (export "c" (table 1 funcref)) + (export "d" (memory 1)) + )) + (core instance $x (instantiate $m2)) + + (core instance (instantiate $m (with "" (instance + (export "d" (func $x "a")) + (export "c" (global $x "b")) + (export "b" (table $x "c")) + (export "a" (memory $x "d")) + )))) +) + +(component + (component + (import "a" (component $m + (import "a" (instance + (export "a" (core module)) + )) + )) + (import "b" (component $m2 + (export "b" (core module)) + )) + (instance $x (instantiate $m2)) + + (instance (instantiate $m (with "a" (instance + (export "a" (core module $x "b")) + )))) + ) +) + +(component + (component + (import "a" (component $c + (import "a" (core module)) + (import "b" (func)) + (import "c" (component)) + (import "d" (instance)) + )) + (core module $m (import "b")) + (func $f (import "c")) + (component $c2 (import "d")) + (instance $i (import "e")) + + (instance + (instantiate $c + (with "a" (core module $m)) + (with "b" (func $f)) + (with "c" (component $c2)) + (with "d" (instance $i)) + ) + ) + + (core instance $c (instantiate $m)) + (core instance (instantiate $m)) + + ;; inline exports/imports + (type $empty (instance)) + (instance $d (import "g") (type $empty)) + (instance (import "h")) + (instance (import "i") + (export "x" (func))) + (instance (export "j") (export "k") (import "x")) + ) +) + +(assert_invalid + (component + (core instance (instantiate 0)) + ) + "unknown module") +(assert_invalid + (component + (instance (instantiate 0)) + ) + "unknown component") +(assert_invalid + (component + (import "a" (core module)) + (core instance (instantiate 1)) + ) + "unknown module") + +(component + (component + (import "a" (func $f)) + (import "b" (component $c)) + (instance (instantiate $c (with "a" (func $f)))) + ) +) +(assert_invalid + (component + (import "a" (core module $m (import "" "" (func)))) + (core instance (instantiate $m)) + ) + "missing module instantiation argument") +(assert_invalid + (component + (import "a" (component $m (import "a" (func)))) + (instance (instantiate $m)) + ) + "missing import named `a`") + +(assert_invalid + (component + (import "a" (component $m + (import "a" (func)) + )) + (import "b" (component $c)) + (instance $i (instantiate $m (with "a" (component $c)))) + ) + "expected func, found component") + +(assert_invalid + (component + (import "a" (component $m + (import "a" (func)) + )) + (import "b" (func $f (result string))) + (instance $i (instantiate $m (with "a" (func $f)))) + ) + "expected a result, found none") + +(assert_invalid + (component + (import "a" (component $m + (import "a" (func)) + )) + (import "b" (func (param "i" string))) + (instance $i (instantiate $m (with "a" (func 0)))) + ) + "expected 0 parameters, found 1") + +(assert_invalid + (component + (import "a" (component $m + (import "a" (core module + (import "" "" (func)) + )) + )) + (import "b" (core module $i + (import "" "" (global i32)) + )) + (instance $i (instantiate $m (with "a" (core module $i)))) + ) + "type mismatch in import `::`") + +(assert_invalid + (component + (import "a" (component $m + (import "a" (core module)) + )) + (import "b" (core module $i + (import "" "foobar" (global i32)) + )) + (instance $i (instantiate $m (with "a" (core module $i)))) + ) + "missing expected import `::foobar`") +(assert_invalid + (component + (import "a" (component $m + (import "a" (core module (export "x" (func)))) + )) + (import "b" (core module $i)) + (instance $i (instantiate $m (with "a" (core module $i)))) + ) + "missing expected export `x`") + +;; it's ok to give a module with fewer imports +(component + (component + (import "a" (component $m + (import "a" (core module + (import "" "" (global i32)) + (import "" "f" (func)) + )) + )) + (import "b" (core module $i + (import "" "" (global i32)) + )) + (instance $i (instantiate $m (with "a" (core module $i)))) + ) +) + +;; export subsets +(component + (component + (import "a" (component $m + (import "a" (core module + (export "" (func)) + )) + )) + (import "b" (core module $i + (export "" (func)) + (export "a" (func)) + )) + (instance $i (instantiate $m (with "a" (core module $i)))) + ) +) +(component + (component + (import "a" (component $m + (import "a" (instance + (export "a" (func)) + )) + )) + (import "b" (instance $i + (export "a" (func)) + (export "b" (func)) + )) + (instance (instantiate $m (with "a" (instance $i)))) + ) +) + + +;; ============================================================================ +;; core wasm type checking + +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (func)))) + (import "m2" (core module $m2 (export "" (func (param i32))))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "expected: (func)") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (func)))) + (import "m2" (core module $m2 (export "" (func (result i32))))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "expected: (func)") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (global i32)))) + (import "m2" (core module $m2 (export "" (global i64)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "expected global type i32, found i64") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (table 1 funcref)))) + (import "m2" (core module $m2 (export "" (table 2 externref)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "expected table element type funcref, found externref") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (table 1 2 funcref)))) + (import "m2" (core module $m2 (export "" (table 2 funcref)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "mismatch in table limits") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (table 2 2 funcref)))) + (import "m2" (core module $m2 (export "" (table 1 funcref)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "mismatch in table limits") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (table 2 2 funcref)))) + (import "m2" (core module $m2 (export "" (table 2 3 funcref)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "mismatch in table limits") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (memory 1 2 shared)))) + (import "m2" (core module $m2 (export "" (memory 1)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "mismatch in the shared flag for memories") +(assert_invalid + (component + (import "m1" (core module $m1 (import "" "" (memory 1)))) + (import "m2" (core module $m2 (export "" (memory 0)))) + (core instance $i (instantiate $m2)) + (core instance (instantiate $m1 (with "" (instance $i)))) + ) + "mismatch in memory limits") +(assert_invalid + (component + (import "m1" (core module $m1 (export "g" (func)))) + (component $c + (import "m" (core module (export "g" (global i32)))) + ) + (instance (instantiate $c (with "m" (core module $m1)))) + ) + "type mismatch in export `g`") + +(assert_invalid + (component + (core instance (instantiate 0)) + ) + "unknown module") + +(component + (component $m + (core module $sub (export "module") + (func $f (export "") (result i32) + i32.const 5)) + ) + (instance $a (instantiate $m)) + (alias export $a "module" (core module $sub)) + (core instance $b (instantiate $sub)) + + (core module $final + (import "" "" (func $b (result i32))) + (func (export "get") (result i32) + call $b)) + + (core instance (instantiate $final (with "" (instance $b)))) +) + +(assert_invalid + (component (instance $i (export "" (func 0)))) + "function index out of bounds") + +(assert_invalid + (component (instance (export "" (instance 0)))) + "index out of bounds") + +(assert_invalid + (component (instance $i (export "" (component 0)))) + "index out of bounds") + +(assert_invalid + (component (instance (export "" (instance 0)))) + "index out of bounds") + +(assert_invalid + (component (instance $i (export "" (core module 0)))) + "index out of bounds") + +(assert_invalid + (component (core instance (export "" (func 0)))) + "index out of bounds") + +(assert_invalid + (component (core instance (export "" (table 0)))) + "index out of bounds") + +(assert_invalid + (component (core instance (export "" (global 0)))) + "index out of bounds") + +(assert_invalid + (component (core instance (export "" (memory 0)))) + "index out of bounds") + +(assert_invalid + (component + (core module $m) + (core instance $i (instantiate $m)) + (core instance (instantiate $m + (with "" (instance $i)) + (with "" (instance $i)) + )) + ) + "duplicate module instantiation argument named ``" +) + +(assert_invalid + (component + (core module $m (func (export ""))) + (core instance $i (instantiate $m)) + (core instance (instantiate $m + (with "" (instance $i)) + (with "" (instance $i)) + )) + ) + "duplicate module instantiation argument named ``") + +(assert_invalid + (component + (core module $m1 (func (export ""))) + (core module $m2 (import "" "" (global i32))) + (core instance $i (instantiate $m1)) + (core instance (instantiate $m2 + (with "" (instance $i)) + )) + ) + "expected global, found func") + +(assert_invalid + (component + (component $m) + (instance $i (instantiate $m)) + (instance (instantiate $m + (with "a" (instance $i)) + (with "a" (instance $i)) + )) + ) + "instantiation argument `a` conflicts with previous argument `a`") + +(assert_invalid + (component + (component $c (import "a" (func))) + (instance (instantiate $c + (with "a" (component $c)) + )) + ) + "expected func, found component") + +(assert_invalid + (component + (component $c) + (instance (instantiate $c + (with "" (core module 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate $c + (with "" (instance 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate $c + (with "" (func 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate $c + (with "" (component 100)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance + (export "a" (component $c)) + (export "a" (component $c)) + ) + ) + "export name `a` conflicts with previous name `a`") + +(component + (component + (import "a" (instance $i)) + (import "b" (func $f)) + (import "c" (component $c)) + (import "d" (core module $m)) + (instance + (export "a" (instance $i)) + (export "b" (func $f)) + (export "c" (component $c)) + (export "d" (core module $m)) + ) + ) +) + +(component + (core module $m + (func (export "1")) + (memory (export "2") 1) + (table (export "3") 1 funcref) + (global (export "4") i32 i32.const 0) + ) + (core instance $i (instantiate $m)) + (core instance + (export "a" (func $i "1")) + (export "b" (memory $i "2")) + (export "c" (table $i "3")) + (export "d" (global $i "4")) + ) +) + +(assert_invalid + (component + (core module $m (func (export ""))) + (core instance $i (instantiate $m)) + (core instance + (export "" (func $i "")) + (export "" (func $i "")) + ) + ) + "export name `` already defined") + +(assert_invalid + (component + (component $c) + (instance $i (instantiate $c)) + (export "a" (instance $i "a")) + ) + "no export named `a`") + +(assert_invalid + (component + (export "a" (instance 100 "a")) + ) + "index out of bounds") + +(assert_invalid + (component + (import "a" (core module $libc + (export "memory" (memory 1)) + (export "table" (table 0 funcref)) + (export "func" (func)) + (export "global" (global i32)) + (export "global mut" (global (mut i64))) + )) + (core instance $libc (instantiate $libc)) + (alias core export $libc "memory" (core memory $mem)) + (alias core export $libc "table" (core table $tbl)) + (alias core export $libc "func" (core func $func)) + (alias core export $libc "global" (core global $global)) + (alias core export $libc "global mut" (core global $global_mut)) + + (import "x" (core module $needs_libc + (import "" "memory" (memory 1)) + (import "" "table" (table 0 funcref)) + (import "" "func" (func)) + (import "" "global" (global i32)) + (import "" "global mut" (global (mut i64))) + )) + + (core instance + (instantiate $needs_libc + (with "" (instance (export "memory" (memory $mem)))) + ) + ) + ) + "module instantiation argument `` does not export an item named `table`") + +;; Ensure a type can be an instantiation argument +(component + (type (tuple u32 u32)) + (import "a" (type (eq 0))) + (component + (type (tuple u32 u32)) + (import "a" (type (eq 0))) + ) + (instance (instantiate 0 + (with "a" (type 1)) + ) + ) +) + +(assert_invalid + (component + (type $t (tuple string string)) + (import "a" (type $a (eq $t))) + (component $c + (type $t (tuple u32 u32)) + (import "a" (type (eq $t))) + ) + (instance (instantiate $c + (with "a" (type $a)) + ) + ) + ) + "expected primitive `u32` found primitive `string`") + + +;; subtyping for module imports reverses order of imports/exports for the +;; subtyping check +;; +;; Here `C` imports a module, and the module itself imports a table of min size +;; 1. A module import which imports a min-size table of 0, however, is valid to +;; supply for this since it'll already be given at least 1 anyway. +;; +;; Similarly for exports `C` imports a module that exports a table of at least +;; size 1. If it's given a module that exports a larger table that's ok too. +(component + (core module $a + (import "" "" (table 0 funcref)) + (table (export "x") 2 funcref) + ) + (component $C + (import "a" (core module + (import "" "" (table 1 funcref)) + (export "x" (table 1 funcref)) + )) + ) + (instance (instantiate $C (with "a" (core module $a)))) +) + +;; same as above but for memories +(component + (core module $a1 (import "" "" (memory 0))) + (core module $a2 (memory (export "x") 2)) + (component $C + (import "a1" (core module (import "" "" (memory 1)))) + (import "a2" (core module (export "x" (memory 1)))) + ) + (instance (instantiate $C + (with "a1" (core module $a1)) + (with "a2" (core module $a2)) + )) +) + +(assert_invalid + (component + (import "x" (func $x (param "x" u32))) + (import "y" (component $c + (import "x" (func (param "y" u32))) + )) + + (instance (instantiate $c (with "x" (func $x)))) + ) + "expected parameter named `y`, found `x`") +(assert_invalid + (component + (import "x" (func $x (param "x" u32))) + (import "y" (component $c + (import "x" (func (param "x" s32))) + )) + + (instance (instantiate $c (with "x" (func $x)))) + ) + "type mismatch in function parameter `x`") +(assert_invalid + (component + (import "x" (func $x (result u32))) + (import "y" (component $c + (import "x" (func (result s32))) + )) + + (instance (instantiate $c (with "x" (func $x)))) + ) + "type mismatch with result type") + +(assert_invalid + (component + (import "x" (instance $x (export "a" (func)))) + (import "y" (component $c + (import "x" (instance $x (export "a" (component)))) + )) + + (instance (instantiate $c (with "x" (instance $x)))) + ) + "type mismatch in instance export `a`") + +(assert_invalid + (component + (import "y" (component $c + (type $t u32) + (import "x" (type (eq $t))) + )) + + (type $x (record (field "f" u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected primitive, found record") + +(assert_invalid + (component + (import "y" (component $c + (type $t (record (field "f" u32))) + (import "x" (type (eq $t))) + )) + + (type $x u32) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected record, found u32") + +(assert_invalid + (component + (import "y" (component $c + (type $t (record (field "x" u32))) + (import "x" (type (eq $t))) + )) + + (type $f (tuple u8)) + (type $x (record (field "x" $f))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected u32, found tuple") + +(assert_invalid + (component + (import "y" (component $c + (type $f (option s32)) + (type $t (record (field "x" $f))) + (import "x" (type (eq $t))) + )) + + (type $x (record (field "x" u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "type mismatch in record field `x`") + +(assert_invalid + (component + (import "y" (component $c + (type $t (record (field "x" u32))) + (import "x" (type (eq $t))) + )) + + (type $x (record (field "y" u32) (field "z" u64))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected 1 fields, found 2") + +(assert_invalid + (component + (import "y" (component $c + (type $t (record (field "a" u32))) + (import "x" (type (eq $t))) + )) + + (type $x (record (field "b" u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected field name `a`, found `b`") + +(assert_invalid + (component + (import "y" (component $c + (type $t (variant (case "x" u32))) + (import "x" (type (eq $t))) + )) + + (type $x (variant (case "x" u32) (case "y" u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected 1 cases, found 2") + +(assert_invalid + (component + (import "y" (component $c + (type $t (variant (case "x" u32))) + (import "x" (type (eq $t))) + )) + + (type $x (variant (case "y" u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected case named `x`, found `y`") + +(assert_invalid + (component + (import "y" (component $c + (type $t (variant (case "x" u32))) + (import "x" (type (eq $t))) + )) + + (type $x (variant (case "x"))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected case `x` to have a type, found none") + +(assert_invalid + (component + (import "y" (component $c + (type $t (variant (case "x"))) + (import "x" (type (eq $t))) + )) + + (type $x (variant (case "x" u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected case `x` to have no type") + +(assert_invalid + (component + (import "y" (component $c + (type $t (variant (case "x" u32))) + (import "x" (type (eq $t))) + )) + + (type $x (variant (case "x" s32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "type mismatch in variant case `x`") + +(assert_invalid + (component + (import "y" (component $c + (type $t (tuple u8)) + (import "x" (type (eq $t))) + )) + + (type $x (tuple u32 u32)) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected 1 types, found 2") + +(assert_invalid + (component + (import "y" (component $c + (type $t (tuple u8)) + (import "x" (type (eq $t))) + )) + + (type $x (tuple u16)) + (instance (instantiate $c (with "x" (type $x)))) + ) + "type mismatch in tuple field 0") + +(assert_invalid + (component + (import "y" (component $c + (type $t (flags "a")) + (import "x" (type (eq $t))) + )) + + (type $x (flags "x")) + (instance (instantiate $c (with "x" (type $x)))) + ) + "mismatch in flags elements") + +(assert_invalid + (component + (import "y" (component $c + (type $t (enum "a")) + (import "x" (type (eq $t))) + )) + + (type $x (enum "x")) + (instance (instantiate $c (with "x" (type $x)))) + ) + "mismatch in enum elements") + +(assert_invalid + (component + (import "y" (component $c + (type $t (result s32)) + (import "x" (type (eq $t))) + )) + + (type $x (result u32)) + (instance (instantiate $c (with "x" (type $x)))) + ) + "type mismatch in ok variant") + +(assert_invalid + (component + (import "y" (component $c + (type $t (result (error s32))) + (import "x" (type (eq $t))) + )) + + (type $x (result (error u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "type mismatch in err variant") + +(assert_invalid + (component + (import "y" (component $c + (type $t (result)) + (import "x" (type (eq $t))) + )) + + (type $x (result u32)) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected ok type to not be present") + +(assert_invalid + (component + (import "y" (component $c + (type $t (result u32)) + (import "x" (type (eq $t))) + )) + + (type $x (result)) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected ok type, but found none") + +(assert_invalid + (component + (import "y" (component $c + (type $t (result)) + (import "x" (type (eq $t))) + )) + + (type $x (result (error u32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected err type to not be present") + +(assert_invalid + (component + (import "y" (component $c + (type $t (result (error u32))) + (import "x" (type (eq $t))) + )) + + (type $x (result)) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected err type, but found none") diff --git a/test/wasm-tools/invalid.wast b/test/wasm-tools/invalid.wast new file mode 100644 index 00000000..267b31f8 --- /dev/null +++ b/test/wasm-tools/invalid.wast @@ -0,0 +1,34 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component + (core type (module + (import "" "" (func (type 1))) + )) + (type (func)) + ) + "type index out of bounds") + +(assert_malformed + (component quote + "(export \"\" (func $foo))" + ) + "unknown func") + +(assert_malformed + (component quote + "(alias outer 100 $foo (type $foo))" + ) + "outer count of `100` is too large") + +(assert_malformed + (component quote + "(alias outer $nonexistent $foo (type $foo))" + ) + "outer component `nonexistent` not found") + +(assert_malformed + (component quote + "(import \"x\" (func $x))" + "(component (export \"x\" (func $x)))") + "outer item `x` is not a module, type, or component") diff --git a/test/wasm-tools/link.wast b/test/wasm-tools/link.wast new file mode 100644 index 00000000..72023652 --- /dev/null +++ b/test/wasm-tools/link.wast @@ -0,0 +1,14 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +;; Based on this, we can link two modules $A and $B together with the following component: + +(component + (core module $A + (func (export "one") (result i32) (i32.const 1)) + ) + (core module $B + (func (import "a" "one") (result i32)) + ) + (core instance $a (instantiate $A)) + (core instance $b (instantiate $B (with "a" (instance $a)))) +) diff --git a/test/wasm-tools/lots-of-aliases.wast b/test/wasm-tools/lots-of-aliases.wast new file mode 100644 index 00000000..32e1a27a --- /dev/null +++ b/test/wasm-tools/lots-of-aliases.wast @@ -0,0 +1,179 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (core module $m + (memory (export "m") 1) + (table (export "t") 1 funcref) + (global (export "g") i32 i32.const 0) + (func (export "f")) + ) + (core instance $i (instantiate $m)) + + ;; 160 memories (4 per row 40 rows) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) (alias core export $i "m" (core memory)) + + ;; 160 tables (4 per row 40 rows) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) (alias core export $i "t" (core table)) + + ;; 160 globals (4 per row 40 rows) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) (alias core export $i "g" (core global)) + + ;; 160 functions (4 per row 40 rows) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) + (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) (alias core export $i "f" (core func)) +) diff --git a/test/wasm-tools/lower.wast b/test/wasm-tools/lower.wast new file mode 100644 index 00000000..5b9e13bf --- /dev/null +++ b/test/wasm-tools/lower.wast @@ -0,0 +1,17 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component + (import "f" (func $f (param "x" (list u8)))) + (core func $f (canon lower (func $f) + )) + ) + "canonical option `memory` is required") + +(assert_invalid + (component + (import "f" (func $f (result (list u8)))) + (core func $f (canon lower (func $f) + )) + ) + "canonical option `memory` is required") diff --git a/test/wasm-tools/memory64.wast b/test/wasm-tools/memory64.wast new file mode 100644 index 00000000..0ec55341 --- /dev/null +++ b/test/wasm-tools/memory64.wast @@ -0,0 +1,54 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component + (core module $A + (import "" "" (memory 1))) + (core module $B + (memory (export "") i64 1)) + (core instance $b (instantiate $B)) + (core instance $a (instantiate $A (with "" (instance $b)))) + ) + "mismatch in index type used for memories") + +(assert_invalid + (component + (core module $A + (import "" "" (memory i64 1))) + (core module $B + (memory (export "") 1)) + (core instance $b (instantiate $B)) + (core instance $a (instantiate $A (with "" (instance $b)))) + ) + "mismatch in index type used for memories") + +(component + (core module $A + (memory (export "m") i64 1)) + (core instance $A (instantiate $A)) + (alias core export $A "m" (core memory $m)) + + (core module $B (import "" "" (memory i64 1))) + (core instance (instantiate $B (with "" (instance (export "" (memory $m)))))) +) + +(component + (core module $A + (table (export "m") i64 1 funcref)) + (core instance $A (instantiate $A)) + (alias core export $A "m" (core table $m)) + + (core module $B (import "" "" (table i64 1 funcref))) + (core instance (instantiate $B (with "" (instance (export "" (table $m)))))) +) + +(assert_invalid + (component + (import "x" (func $x (param "x" string))) + (core module $A + (memory (export "m") i64 1)) + (core instance $A (instantiate $A)) + (alias core export $A "m" (core memory $m)) + (core func (canon lower (func $x) (memory $m))) + ) + "canonical ABI memory is not a 32-bit linear memory") diff --git a/test/wasm-tools/module-link.wast b/test/wasm-tools/module-link.wast new file mode 100644 index 00000000..119da23b --- /dev/null +++ b/test/wasm-tools/module-link.wast @@ -0,0 +1,98 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (type $Wasi (instance)) + (component $B) + (component $B_wrap + (import "wasi" (instance $wasi (type $Wasi))) + (instance $b (instantiate $B)) + ) +) + +(component + (type $Wasi (instance)) + (import "wasi" (instance $wasi (type $Wasi))) + + (component $A + (type $Wasi (instance)) + (import "wasi" (instance (type $Wasi))) + + (core module $m + (func (export "a")) + ) + + (core instance $i (instantiate $m)) + (func (export "a") + (canon lift (core func $i "a")) + ) + ) + + (component $B + (type $Wasi (instance)) + (import "wasi" (instance $wasi (type $Wasi))) + (import "a1-x" (component $A + (import "wasi" (instance (type $Wasi))) + (export "a" (func)) + )) + (instance $a (instantiate $A (with "wasi" (instance $wasi)))) + + (core func $lower (canon lower (func $a "a"))) + (core module $b + (import "a" "a" (func)) + (func (export "b")) + ) + (core instance $b (instantiate $b + (with "a" (instance (export "a" (func $lower)))) + )) + (func (export "b") + (canon lift (core func $b "b")) + ) + ) + (component $B_wrap + (type $Wasi (instance)) + (import "wasi" (instance $wasi (type $Wasi))) + (instance $b (instantiate $B + (with "wasi" (instance $wasi)) + (with "a1-x" (component $A))) + ) + (export "b" (func $b "b")) + ) + + (component $C + (type $Wasi (instance)) + (import "wasi" (instance $wasi (type $Wasi))) + (import "b1-x" (component $B + (import "wasi" (instance $wasi (type $Wasi))) + (export "b" (func)) + )) + (instance $b (instantiate $B (with "wasi" (instance $wasi)))) + (export "c" (func $b "b")) + ) + (component $C_wrap + (type $Wasi (instance)) + (import "wasi" (instance $wasi (type $Wasi))) + (instance $c (instantiate $C + (with "wasi" (instance $wasi)) + (with "b1-x" (component $B_wrap)) + )) + (export "c" (func $c "c")) + ) + + (component $D + (type $Wasi (instance)) + (import "wasi" (instance $wasi (type $Wasi))) + (import "c1-x" (component $C + (import "wasi" (instance $wasi (type $Wasi))) + (export "c" (func)) + )) + (instance $c (instantiate $C (with "wasi" (instance $wasi)))) + (export "d" (func $c "c")) + ) + + (instance $d (instantiate $D + (with "wasi" (instance $wasi)) + (with "c1-x" (component $C_wrap)) + )) + + (export "d" (func $d "d")) +) diff --git a/test/wasm-tools/more-flags.wast b/test/wasm-tools/more-flags.wast new file mode 100644 index 00000000..ebcced0f --- /dev/null +++ b/test/wasm-tools/more-flags.wast @@ -0,0 +1,41 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component + (type (flags + "f1" + "f2" + "f3" + "f4" + "f5" + "f6" + "f7" + "f8" + "f9" + "f10" + "f11" + "f12" + "f13" + "f14" + "f15" + "f16" + "f17" + "f18" + "f19" + "f20" + "f21" + "f22" + "f23" + "f24" + "f25" + "f26" + "f27" + "f28" + "f29" + "f30" + "f31" + "f32" + "f33" + )) + ) + "cannot have more than 32 flags") diff --git a/test/wasm-tools/naming.wast b/test/wasm-tools/naming.wast new file mode 100644 index 00000000..160df4d4 --- /dev/null +++ b/test/wasm-tools/naming.wast @@ -0,0 +1,130 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component definition + (func (import "a")) + (component) + (instance (instantiate 0 (with "NotKebab-Case" (func 0)))) +) + +(assert_invalid + (component + (import "f" (func)) + (instance (export "1" (func 0))) + ) + "`1` is not in kebab case" +) + +(assert_invalid + (component + (instance) + (alias export 0 "Xml" (func)) + ) + "instance 0 has no export named `Xml`" +) + +(assert_invalid + (component + (type (flags "a-1-c")) + ) + "flag name `a-1-c` is not in kebab case" +) + +(assert_invalid + (component + (type (enum "NevEr")) + ) + "enum tag name `NevEr` is not in kebab case" +) + +(assert_invalid + (component + (type (record (field "GoNnA" string))) + ) + "record field name `GoNnA` is not in kebab case" +) + +(assert_invalid + (component + (type (variant (case "GIVe" string))) + ) + "variant case name `GIVe` is not in kebab case" +) + + +(assert_invalid + (component + (type (func (param "yOu" string))) + ) + "function parameter name `yOu` is not in kebab case" +) + +(assert_invalid + (component + (type (component (export "NevEr" (func)))) + ) + "`NevEr` is not in kebab case" +) + +(assert_invalid + (component + (type (component (import "GonnA" (func)))) + ) + "`GonnA` is not in kebab case" +) + +(assert_invalid + (component + (type (instance (export "lET" (func)))) + ) + "`lET` is not in kebab case" +) + +(assert_invalid + (component + (instance (export "YoU")) + ) + "`YoU` is not in kebab case" +) + +(assert_invalid + (component + (instance (import "DOWn")) + ) + "`DOWn` is not in kebab case" +) + +(assert_invalid + (component + (instance (import "A:b/c")) + ) + "character `A` is not lowercase in package name/namespace" +) +(assert_invalid + (component + (instance (import "a:B/c")) + ) + "character `B` is not lowercase in package name/namespace" +) +(component + (instance (import "a:b/c")) + (instance (import "a1:b1/c")) +) + +(component definition + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (result (own $a)))) +) + +(assert_invalid + (component + (import "a" (type $a (sub resource))) + (import "[method]a.a" (func (param "self" (borrow $a)))) + ) + "import name `[method]a.a` conflicts with previous name `a`") + +(assert_invalid + (component + (import "a" (type $a (sub resource))) + (import "[static]a.a" (func)) + ) + "import name `[static]a.a` conflicts with previous name `a`") diff --git a/test/wasm-tools/nested-modules.wast b/test/wasm-tools/nested-modules.wast new file mode 100644 index 00000000..5e629ea5 --- /dev/null +++ b/test/wasm-tools/nested-modules.wast @@ -0,0 +1,50 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component definition + (import "i1" (core module)) + + (core module) + (core module) + + (core module (export "x")) + + (component + (core module) + ) + + (component + (core module $m) + (import "a" (func (param "p" string))) + (export "b" (core module $m)) + ) +) + +;; does the `import` use the type annotation specified later? +(component definition + (import "a" (core module)) + (core type (module)) +) + +;; be sure to typecheck nested modules +(assert_invalid + (component + (core module + (func + i32.add) + ) + ) + "type mismatch") + +;; interleave module definitions with imports/aliases and ensure that we +;; typecheck the module code section correctly +(component definition + (core module + (func (export "")) + ) + (import "a" (core module)) + (core module + (func (export "") (result i32) i32.const 5) + ) + (import "b" (instance (export "a" (core module)))) + (alias export 0 "a" (core module)) +) diff --git a/test/wasm-tools/resources.wast b/test/wasm-tools/resources.wast new file mode 100644 index 00000000..14509c54 --- /dev/null +++ b/test/wasm-tools/resources.wast @@ -0,0 +1,1195 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (type $x (resource (rep i32))) +) + +(component + (type $x (resource (rep i32))) + + (core func (canon resource.new $x)) + (core func (canon resource.rep $x)) + (core func (canon resource.drop $x)) +) + +(component definition + (import "x" (type $x (sub resource))) + + (core func (canon resource.drop $x)) +) + +(component + (core module $m + (func (export "dtor") (param i32)) + ) + (core instance $m (instantiate $m)) + (type $x (resource (rep i32) (dtor (func $m "dtor")))) + (core func (canon resource.new $x)) +) + +(component + (type $x (resource (rep i32))) + (core func $f1 (canon resource.new $x)) + (core func $f2 (canon resource.rep $x)) + (core func $f3 (canon resource.drop $x)) + + (core module $m + (import "" "f1" (func (param i32) (result i32))) + (import "" "f2" (func (param i32) (result i32))) + (import "" "f3" (func (param i32))) + ) + + (core instance (instantiate $m + (with "" (instance + (export "f1" (func $f1)) + (export "f2" (func $f2)) + (export "f3" (func $f3)) + )) + )) +) + +(assert_invalid + (component + (type $x (resource (rep i64))) + ) + "resources can only be represented by `i32`") + +(assert_invalid + (component + (type $x (own 100)) + ) + "type index out of bounds") + +(assert_invalid + (component + (type $x (borrow 100)) + ) + "type index out of bounds") + +(assert_invalid + (component + (type $t u8) + (type $x (borrow $t)) + ) + "not a resource type") + +(assert_invalid + (component + (type $t u8) + (type $x (own $t)) + ) + "not a resource type") + +(assert_invalid + (component + (import "x" (type $x (sub resource))) + (core func (canon resource.new $x)) + ) + "not a local resource") + +(assert_invalid + (component + (import "x" (type $x (sub resource))) + (core func (canon resource.rep $x)) + ) + "not a local resource") + +(assert_invalid + (component + (type $t (tuple u32)) + (core func (canon resource.drop $t)) + ) + "not a resource type") + +(assert_invalid + (component + (core func (canon resource.drop 100)) + ) + "type index out of bounds") + +(assert_invalid + (component + (type (component)) + (core func (canon resource.drop 0)) + ) + "not a resource type") + +(assert_invalid + (component + (type (component)) + (core func (canon resource.new 0)) + ) + "not a resource type") + +(assert_invalid + (component + (core module $m + (func (export "dtor")) + ) + (core instance $m (instantiate $m)) + (type $x (resource (rep i32) (dtor (func $m "dtor")))) + (core func (canon resource.new $x)) + ) + "wrong signature for a destructor") + +(assert_invalid + (component + (type (resource (rep i32) (dtor (func 100)))) + ) + "function index out of bounds") + +(assert_invalid + (component + (import "x" (type $x (sub resource))) + (import "y" (type $y (sub resource))) + (import "z" (func $z (param "x" (own $x)) (param "y" (own $y)))) + + (component $c + (import "x" (type $x (sub resource))) + (import "z" (func (param "x" (own $x)) (param "y" (own $x)))) + ) + + (instance (instantiate $c (with "x" (type $x)) (with "z" (func $z)))) + ) + "resource types are not the same") + +(component + (type (component + (import "x" (type $x (sub resource))) + (export "y" (type (eq $x))) + (export "z" (type (sub resource))) + )) +) + +(assert_invalid + (component + (type (component + (type $x (resource (rep i32))) + )) + ) + "resources can only be defined within a concrete component") + +(assert_invalid + (component + (type (instance + (type $x (resource (rep i32))) + )) + ) + "resources can only be defined within a concrete component") + +(component + (type (component + (import "x" (instance $i + (export "t" (type $t (sub resource))) + (export "f" (func (result (own $t)))) + )) + (alias export $i "t" (type $t)) + (export "f" (func (result (own $t)))) + )) +) + +(component definition + (import "fancy-fs" (instance $fancy-fs + (export "fs" (instance $fs + (export "file" (type (sub resource))) + )) + (alias export $fs "file" (type $file)) + (export "fancy-op" (func (param "f" (borrow $file)))) + )) +) + +(component $C + (type $T (list (tuple string bool))) + (type $U (option $T)) + (type $G (func (param "x" (list $T)) (result $U))) + (type $D (component + (alias outer $C $T (type $C_T)) + (type $L (list $C_T)) + (import "f" (func (param "x" $L) (result (list u8)))) + (import "g" (func (type $G))) + (export "g2" (func (type $G))) + (export "h" (func (result $U))) + (import "T" (type $T (sub resource))) + (import "i" (func (param "x" (list (own $T))))) + (export "T2" (type $T' (eq $T))) + (export "U" (type $U' (sub resource))) + (export "j" (func (param "x" (borrow $T')) (result (own $U')))) + )) +) + +(component definition + (import "T1" (type $T1 (sub resource))) + (import "T2" (type $T2 (sub resource))) +) + +(component definition $C + (import "T1" (type $T1 (sub resource))) + (import "T2" (type $T2 (sub resource))) + (import "T3" (type $T3 (eq $T2))) + (type $ListT1 (list (own $T1))) + (type $ListT2 (list (own $T2))) + (type $ListT3 (list (own $T3))) +) + +(component definition + (import "T" (type $T (sub resource))) + (import "U" (type $U (sub resource))) + (type $Own1 (own $T)) + (type $Own2 (own $T)) + (type $Own3 (own $U)) + (type $ListOwn1 (list $Own1)) + (type $ListOwn2 (list $Own2)) + (type $ListOwn3 (list $Own3)) + (type $Borrow1 (borrow $T)) + (type $Borrow2 (borrow $T)) + (type $Borrow3 (borrow $U)) + (type $ListBorrow1 (list $Borrow1)) + (type $ListBorrow2 (list $Borrow2)) + (type $ListBorrow3 (list $Borrow3)) +) + +(component + (component + (import "C" (component $C + (export "T1" (type (sub resource))) + (export "T2" (type $T2 (sub resource))) + (export "T3" (type (eq $T2))) + )) + (instance $c (instantiate $C)) + (alias export $c "T1" (type $T1)) + (alias export $c "T2" (type $T2)) + (alias export $c "T3" (type $T3)) + ) +) + +(component + (component $C + (type $r1 (export "r1") (resource (rep i32))) + (type $r2 (export "r2") (resource (rep i32))) + ) + (instance $c1 (instantiate $C)) + (instance $c2 (instantiate $C)) + (alias export $c1 "r1" (type $c1r1)) + (alias export $c1 "r2" (type $c1r2)) + (alias export $c2 "r1" (type $c2r1)) + (alias export $c2 "r2" (type $c2r2)) +) + +(component + (type $r (resource (rep i32))) + (export "r1" (type $r)) + (export "r2" (type $r)) +) + +(component + (type (component + (export "r1" (type (sub resource))) + (export "r2" (type (sub resource))) + )) +) + +(component + (type $r (resource (rep i32))) + (export $r1 "r1" (type $r)) + (export "r2" (type $r1)) +) + +(component + (type (component + (export "r1" (type $r1 (sub resource))) + (export "r2" (type (eq $r1))) + )) +) + +(component + (component $P + (import "C1" (component $C1 + (import "T" (type $T (sub resource))) + (export "foo" (func (param "t" (own $T)))) + )) + (import "C2" (component $C2 + (import "T" (type $T (sub resource))) + (import "foo" (func (param "t" (own $T)))) + )) + (type $R (resource (rep i32))) + (instance $c1 (instantiate $C1 (with "T" (type $R)))) + (instance $c2 (instantiate $C2 + (with "T" (type $R)) + (with "foo" (func $c1 "foo")) + )) + ) +) + +(component + (component + (import "C1" (component $C1 + (import "T1" (type $T1 (sub resource))) + (import "T2" (type $T2 (sub resource))) + (export "foo" (func (param "t" (tuple (own $T1) (own $T2))))) + )) + (import "C2" (component $C2 + (import "T" (type $T (sub resource))) + (export "foo" (func (param "t" (tuple (own $T) (own $T))))) + )) + (type $R (resource (rep i32))) + (instance $c1 (instantiate $C1 + (with "T1" (type $R)) + (with "T2" (type $R)) + )) + (instance $c2 (instantiate $C2 + (with "T" (type $R)) + (with "foo" (func $c1 "foo")) + )) + ) +) + +(assert_invalid + (component + (component $C + (type $R (resource (rep i32))) + (export "R" (type $R)) + ) + (instance $c (instantiate $C)) + (alias export $c "R" (type $R)) + (core func (canon resource.rep $R)) + ) + "not a local resource") + +(component + (component $C + (type $R (resource (rep i32))) + (export "R" (type $R)) + ) + (instance $c (instantiate $C)) + (alias export $c "R" (type $R)) + (core func (canon resource.drop $R)) +) + +(component + (component $C1 + (import "X" (type (sub resource))) + ) + (component $C2 + (import "C1" (component + (import "X" (type (sub resource))) + )) + ) + (instance $c (instantiate $C2 (with "C1" (component $C1)))) +) + +(component + (component $C1 + (import "X" (type $X (sub resource))) + (import "f" (func $f (result (own $X)))) + (export "g" (func $f)) + ) + (component $C2 + (import "C1" (component + (import "X" (type $X (sub resource))) + (import "f" (func (result (own $X)))) + (export "g" (func (result (own $X)))) + )) + ) + (instance $c (instantiate $C2 (with "C1" (component $C1)))) +) + +(component + (component $C1 + (type $X' (resource (rep i32))) + (export $X "X" (type $X')) + + (core func $f (canon resource.drop $X)) + (func (export "f") (param "X" (own $X)) (canon lift (core func $f))) + ) + (instance $c1 (instantiate $C1)) + + (component $C2 + (import "X" (type $X (sub resource))) + (import "f" (func (param "X" (own $X)))) + ) + (instance $c2 (instantiate $C2 + (with "X" (type $c1 "X")) + (with "f" (func $c1 "f")) + )) +) + +(assert_invalid + (component + (component $C1 + (type $X' (resource (rep i32))) + (export $X "X" (type $X')) + + (core func $f (canon resource.drop $X)) + (func (export "f") (param "X" (own $X)) (canon lift (core func $f))) + ) + (instance $c1 (instantiate $C1)) + (instance $c2 (instantiate $C1)) + + (component $C2 + (import "X" (type $X (sub resource))) + (import "f" (func (param "X" (own $X)))) + ) + (instance $c3 (instantiate $C2 + (with "X" (type $c1 "X")) + (with "f" (func $c2 "f")) + )) + ) + "resource types are not the same") + +(component + (component $C1 + (type $X (resource (rep i32))) + (export $X1 "X1" (type $X)) + (export $X2 "X2" (type $X)) + + (core func $f (canon resource.drop $X)) + (func (export "f1") (param "X" (own $X1)) (canon lift (core func $f))) + (func (export "f2") (param "X" (own $X2)) (canon lift (core func $f))) + ) + (instance $c1 (instantiate $C1)) + + (component $C2 + (import "X" (type $X (sub resource))) + (import "f" (func (param "X" (own $X)))) + ) + (instance $c2 (instantiate $C2 + (with "X" (type $c1 "X1")) + (with "f" (func $c1 "f1")) + )) + (instance $c3 (instantiate $C2 + (with "X" (type $c1 "X2")) + (with "f" (func $c1 "f2")) + )) +) + +(component + (component $C1 + (type $X (resource (rep i32))) + (export $X1 "X1" (type $X)) + (export $X2 "X2" (type $X)) + + (core func $f (canon resource.drop $X)) + (func (export "f1") (param "X" (own $X1)) (canon lift (core func $f))) + (func (export "f2") (param "X" (own $X2)) (canon lift (core func $f))) + ) + (instance $c1 (instantiate $C1)) + + (component $C2 + (import "X" (type $X (sub resource))) + (import "f" (func (param "X" (own $X)))) + ) + (instance $c2 (instantiate $C2 + (with "X" (type $c1 "X1")) + (with "f" (func $c1 "f2")) + )) + (instance $c3 (instantiate $C2 + (with "X" (type $c1 "X2")) + (with "f" (func $c1 "f1")) + )) +) + +(assert_invalid + (component + (component $c + (import "x" (type (sub resource))) + ) + (type $x u32) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected resource, found defined type") + +(assert_invalid + (component + (component $c + (type $t u32) + (import "x" (type (eq $t))) + ) + (type $x (resource (rep i32))) + (instance (instantiate $c (with "x" (type $x)))) + ) + "expected defined type, found resource") + +(assert_invalid + (component + (component $c + (import "x1" (type $x1 (sub resource))) + (import "x2" (type $x2 (eq $x1))) + ) + (type $x1 (resource (rep i32))) + (type $x2 (resource (rep i32))) + (instance (instantiate $c + (with "x1" (type $x1)) + (with "x2" (type $x2)) + )) + ) + "resource types are not the same") + +(component + (type $x (resource (rep i32))) + (component $c + (import "x" (type $t (sub resource))) + (export "y" (type $t)) + ) + (instance $c (instantiate $c (with "x" (type $x)))) + + (alias export $c "y" (type $x2)) + (core func (canon resource.rep $x2)) + +) + +(assert_invalid + (component + (type $r (resource (rep i32))) + (import "x" (func (result (own $r)))) + ) + "func not valid to be used as import") + +(assert_invalid + (component + (type (component + (export "x" (type $x (sub resource))) + (import "f" (func (result (own $x)))) + )) + ) + "func not valid to be used as import") + +(assert_invalid + (component + (type $r (resource (rep i32))) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) + ) + "func not valid to be used as export") + +;; direct exports count as "explicit in" for resources +(component + (type $r' (resource (rep i32))) + (export $r "r" (type $r')) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) +) + +;; instances-as-a-bundle count as "explicit in" for resources +(component + (type $r' (resource (rep i32))) + (instance $i' + (export "r" (type $r')) + ) + (export $i "i" (instance $i')) + (alias export $i "r" (type $r)) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) +) + +;; Transitive bundles count for "explicit in" +(component + (type $r' (resource (rep i32))) + (instance $i' + (export "r" (type $r')) + ) + (instance $i2' + (export "i" (instance $i')) + ) + (export $i2 "i2" (instance $i2')) + (alias export $i2 "i" (instance $i)) + (alias export $i "r" (type $r)) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) +) + +;; Component instantiations count for "explicit in" +(component + (type $r' (resource (rep i32))) + (component $C + (import "x" (type $x (sub resource))) + (export "y" (type $x)) + ) + (instance $c' (instantiate $C (with "x" (type $r')))) + (export $c "c" (instance $c')) + (alias export $c "y" (type $r)) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) +) + +;; Make sure threading things around is valid for "explicit in" +(component + (type $r' (resource (rep i32))) + (component $C + (import "x" (type $x (sub resource))) + (export "y" (type $x)) + ) + (instance $c (instantiate $C (with "x" (type $r')))) + (instance $i (export "x" (type $c "y"))) + + (component $C2 + (import "x" (instance $i + (export "i1" (instance + (export "i2" (type (sub resource))) + )) + )) + (export "y" (type $i "i1" "i2")) + ) + + (instance $i2 (export "i2" (type $i "x"))) + (instance $i1 (export "i1" (instance $i2))) + (instance $c2 (instantiate $C2 + (with "x" (instance $i1)) + )) + (export $r "x" (type $c2 "y")) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) +) + +;; Importing-and-exporting instances through instantiation counts for "explicit +;; in" +(component + (type $r' (resource (rep i32))) + (component $C + (import "x" (instance $x (export "t" (type (sub resource))))) + (export "y" (instance $x)) + ) + (instance $c' (instantiate $C + (with "x" (instance + (export "t" (type $r')) + )) + )) + (export $c "c" (instance $c')) + (alias export $c "y" (instance $y)) + (alias export $y "t" (type $r)) + + (core func $f (canon resource.drop $r)) + (func (export "f") (param "x" (own $r)) + (canon lift (core func $f))) +) + +(component definition + (type $i (instance + (export "r" (type $r (sub resource))) + (export "f" (func (result (own $r)))) + )) + (import "i1" (instance $i1 (type $i))) + (import "i2" (instance $i2 (type $i))) + + (component $c + (import "r" (type $t (sub resource))) + (import "f" (func (result (own $t)))) + ) + (instance (instantiate $c + (with "r" (type $i1 "r")) + (with "f" (func $i1 "f")) + )) + (instance (instantiate $c + (with "r" (type $i2 "r")) + (with "f" (func $i2 "f")) + )) +) + + +(assert_invalid + (component + (type $i (instance + (export "r" (type $r (sub resource))) + (export "f" (func (result (own $r)))) + )) + (import "i1" (instance $i1 (type $i))) + (import "i2" (instance $i2 (type $i))) + + (component $c + (import "r" (type $t (sub resource))) + (import "f" (func (result (own $t)))) + ) + (instance (instantiate $c + (with "r" (type $i1 "r")) + (with "f" (func $i2 "f")) + )) + ) + "resource types are not the same") + +;; substitution works +(component + (type $t (resource (rep i32))) + (component $c + (import "x" (type $t (sub resource))) + (export "y" (type $t)) + ) + (instance $c1 (instantiate $c (with "x" (type $t)))) + (instance $c2 (instantiate $c (with "x" (type $t)))) + + (component $c2 + (import "x1" (type $t (sub resource))) + (import "x2" (type (eq $t))) + (import "x3" (type (eq $t))) + ) + (instance (instantiate $c2 + (with "x1" (type $t)) + (with "x2" (type $c1 "y")) + (with "x3" (type $c2 "y")) + )) +) + +;; must supply a resource to instantiation +(assert_invalid + (component + (component $c + (import "x" (type (sub resource))) + ) + (instance (instantiate $c)) + ) + "missing import named `x`") +(assert_invalid + (component + (type $x (resource (rep i32))) + (component $c + (import "x" (type (sub resource))) + (import "y" (type (sub resource))) + ) + (instance (instantiate $c (with "x" (type $x)))) + ) + "missing import named `y`") + +;; supply the wrong resource +(assert_invalid + (component + (type $x (resource (rep i32))) + (type $y (resource (rep i32))) + (component $c + (import "x" (type $t (sub resource))) + (import "y" (type (eq $t))) + ) + (instance (instantiate $c + (with "x" (type $x)) + (with "y" (type $y)) + )) + ) + "resource types are not the same") + +;; aliasing outer resources is ok +(component $A + (type $C (component + (import "x" (type $x (sub resource))) + + (type $y (component + (alias outer $C $x (type $my-x)) + (import "x" (type (eq $my-x))) + )) + + (import "y" (component (type $y))) + (export "z" (component (type $y))) + )) + + (type $t (resource (rep i32))) + + (alias outer $A $t (type $other-t)) + + (type (instance (export "t" (type (eq $t))))) + (type (component (export "t" (type (eq $t))))) + (type (component (import "t" (type (eq $t))))) +) + +;; aliasing beyond components, however, is not ok +(assert_invalid + (component $A + (type $t (resource (rep i32))) + (component (alias outer $A $t (type $foo))) + ) + "refers to resources not defined in the current component") +(assert_invalid + (component $A + (type $t (resource (rep i32))) + (type $u (record (field "x" (own $t)))) + (component (alias outer $A $u (type $foo))) + ) + "refers to resources not defined in the current component") +(assert_invalid + (component $A + (type $t (resource (rep i32))) + (type $u (borrow $t)) + (component (alias outer $A $u (type $foo))) + ) + "refers to resources not defined in the current component") +(assert_invalid + (component $A + (type $t (resource (rep i32))) + (type $u (component (export "a" (type (eq $t))))) + (component (alias outer $A $u (type $foo))) + ) + "refers to resources not defined in the current component") +(assert_invalid + (component $A + (type $t (resource (rep i32))) + (type $u (component (import "a" (type (eq $t))))) + (component (alias outer $A $u (type $foo))) + ) + "refers to resources not defined in the current component") + +(assert_invalid + (component + (component $X + (type $t (resource (rep i32))) + (export "t" (type $t)) + ) + (component $F + (import "x" (component (export "t" (type $t (sub resource))))) + ) + (instance $x1 (instantiate $X)) + (instance $f1 (instantiate $F (with "x" (instance $x1)))) + ) + "expected component, found instance") + +;; Show that two instantiations of the same component produce unique exported +;; resource types. +(assert_invalid + (component + (component $F + (type $t1 (resource (rep i32))) + (export "t1" (type $t1)) + ) + (instance $f1 (instantiate $F)) + (instance $f2 (instantiate $F)) + (alias export $f1 "t1" (type $t1)) + (alias export $f2 "t1" (type $t2)) + (component $T + (import "x" (type $x (sub resource))) + (import "y" (type (eq $x))) + ) + (instance $test + (instantiate $T (with "x" (type $t1)) (with "y" (type $t2)))) + ) + "type mismatch for import `y`") + +;; Show that re-exporting imported resources from an imported component doesn't +;; change the identity of that resource. +(component + (component $X + (type $t (resource (rep i32))) + (export "t" (type $t)) + ) + (component $F + (import "x" (instance $i (export "t" (type $t (sub resource))))) + (alias export $i "t" (type $t)) + (export "t" (type $t)) + ) + (instance $x1 (instantiate $X)) + (instance $f1 (instantiate $F (with "x" (instance $x1)))) + (instance $f2 (instantiate $F (with "x" (instance $x1)))) + (alias export $f1 "t" (type $t1)) + (alias export $f2 "t" (type $t2)) + (component $T + (import "x" (type $x (sub resource))) + (import "y" (type (eq $x))) + ) + (instance $test + (instantiate $T (with "x" (type $t1)) (with "y" (type $t2)))) +) + +(assert_invalid + (component (import "[static]" (func))) + "failed to find `.` character") + +;; validation of `[constructor]foo` +(assert_invalid + (component (import "[constructor]" (func))) + "not in kebab case") +(assert_invalid + (component (import "[constructor]a" (func))) + "should return one value") +(assert_invalid + (component (import "[constructor]a" (func (result u32)))) + "should return `(own $T)`") +(assert_invalid + (component + (import "b" (type $a (sub resource))) + (import "[constructor]a" (func (result (own $a))))) + "import name `[constructor]a` is not valid") +(assert_invalid + (component + (import "b" (type $a (sub resource))) + (import "[constructor]a" (func (result (own $a))))) + "function does not match expected resource name `b`") +(assert_invalid + (component + (import "b" (type $a (sub resource))) + (import "[constructor]a" (func (result (result(own $a)))))) + "function does not match expected resource name `b`") +(component definition + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (result (own $a))))) +(component definition + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (result (result (own $a)))))) +(component definition + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (result (result (own $a) (error string)))))) +(component definition + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (param "x" u32) (result (own $a))))) +(assert_invalid + (component + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (result string)))) + "function should return `(own $T)` or `(result (own $T))`") +(assert_invalid + (component + (import "a" (type $a (sub resource))) + (import "[constructor]a" (func (result (result string))))) + "function should return `(own $T)` or `(result (own $T))`") + +;; validation of `[method]a.b` +(assert_invalid + (component (import "[method]" (func))) + "failed to find `.` character") +(assert_invalid + (component (import "[method]a" (func))) + "failed to find `.` character") +(assert_invalid + (component (import "[method]a." (func))) + "not in kebab case") +(assert_invalid + (component (import "[method].a" (func))) + "not in kebab case") +(assert_invalid + (component (import "[method]a.b.c" (func))) + "not in kebab case") +(assert_invalid + (component (import "[method]a.b" (instance))) + "is not a func") +(assert_invalid + (component (import "[method]a.b" (func))) + "should have at least one argument") +(assert_invalid + (component (import "[method]a.b" (func (param "x" u32)))) + "should have a first argument called `self`") +(assert_invalid + (component (import "[method]a.b" (func (param "self" u32)))) + "should take a first argument of `(borrow $T)`") +(assert_invalid + (component + (import "b" (type $T (sub resource))) + (import "[method]a.b" (func (param "self" (borrow $T))))) + "does not match expected resource name") +(component definition + (import "a" (type $T (sub resource))) + (import "[method]a.b" (func (param "self" (borrow $T))))) + +;; validation of `[static]a.b` +(assert_invalid + (component (import "[static]" (func))) + "failed to find `.` character") +(assert_invalid + (component (import "[static]a" (func))) + "failed to find `.` character") +(assert_invalid + (component (import "[static]a." (func))) + "not in kebab case") +(assert_invalid + (component (import "[static].a" (func))) + "not in kebab case") +(assert_invalid + (component (import "[static]a.b.c" (func))) + "not in kebab case") +(assert_invalid + (component (import "[static]a.b" (instance))) + "is not a func") +(assert_invalid + (component (import "[static]a.b" (func))) + "static resource name is not known in this context") + +(component definition + (import "a" (type (sub resource))) + (import "[static]a.b" (func))) + +;; exports/imports are disjoint +(assert_invalid + (component + (import "b" (type $T (sub resource))) + (import "f" (func $f (param "self" (borrow $T)))) + (export "[method]b.foo" (func $f)) + ) + "resource used in function does not have a name in this context") + +(component + (component + (import "b" (type $T (sub resource))) + (import "f" (func $f (param "self" (borrow $T)))) + (export $c "c" (type $T)) + (export "[method]c.foo" (func $f) (func (param "self" (borrow $c)))) + ) +) + +;; imports aren't transitive +(assert_invalid + (component + (import "i" (instance $i + (export "t" (type (sub resource))) + )) + (alias export $i "t" (type $t)) + (import "[method]t.foo" (func (param "self" (borrow $t)))) + ) + "resource used in function does not have a name in this context") + +;; validation happens in a type context +(assert_invalid + (component + (type (component + (import "b" (type $T (sub resource))) + (import "[constructor]a" (func (result (own $T)))) + )) + ) + "function does not match expected resource name `b`") + +;; bag-of-exports validation +(assert_invalid + (component + (type $T (resource (rep i32))) + (core module $m (func (export "a") (result i32) unreachable)) + (core instance $i (instantiate $m)) + (func $f (result (own $T)) (canon lift (core func $i "a"))) + (instance + (export "a" (type $T)) + (export "[constructor]a" (func $f)) + ) + ) + "resource used in function does not have a name in this context") + +(component + (component $C) + (instance (instantiate $C (with "this is not kebab case" (component $C)))) +) + +;; Test that unused arguments to instantiation are not validated to have +;; appropriate types with respect to kebab naming conventions which require +;; functions/interfaces/etc. +(component + (component $C) + (instance (instantiate $C (with "[method]foo.bar" (component $C)))) +) + +;; thread a resource through a few layers +(component + (component $C + (import "in" (type $r (sub resource))) + (export "out" (type $r)) + ) + + (type $r (resource (rep i32))) + + (instance $c1 (instantiate $C (with "in" (type $r)))) + (instance $c2 (instantiate $C (with "in" (type $c1 "out")))) + (instance $c3 (instantiate $C (with "in" (type $c2 "out")))) + (instance $c4 (instantiate $C (with "in" (type $c3 "out")))) + (instance $c5 (instantiate $C (with "in" (type $c4 "out")))) + + (component $C2 + (import "in1" (type $r (sub resource))) + (import "in2" (type (eq $r))) + (import "in3" (type (eq $r))) + (import "in4" (type (eq $r))) + (import "in5" (type (eq $r))) + (import "in6" (type (eq $r))) + ) + + (instance (instantiate $C2 + (with "in1" (type $r)) + (with "in2" (type $c1 "out")) + (with "in3" (type $c2 "out")) + (with "in4" (type $c3 "out")) + (with "in5" (type $c4 "out")) + (with "in6" (type $c5 "out")) + )) +) + +;; exporting an instance type "freshens" resources +(assert_invalid + (component + (import "x" (instance $i + (type $i (instance + (export "r" (type (sub resource))) + )) + (export "a" (instance (type $i))) + (export "b" (instance (type $i))) + )) + + (component $C + (import "x" (type $x (sub resource))) + (import "y" (type (eq $x))) + ) + (instance (instantiate $C + (with "x" (type $i "a" "r")) + (with "y" (type $i "b" "r")) + )) + ) + "resource types are not the same") + +(component + (type (export "x") (component + (type $t' (instance + (export "r" (type (sub resource))) + )) + (export "t" (instance $t (type $t'))) + (alias export $t "r" (type $r)) + (type $t2' (instance + (export "r2" (type (eq $r))) + (export "r" (type (sub resource))) + )) + (export "t2" (instance (type $t2'))) + )) +) + +(component + (type (component + (type (instance + (export "bar" (type (sub resource))) + (export "[static]bar.a" (func)) + )) + (export "x" (instance (type 0))) + )) +) + +(assert_invalid + (component + (type $r (resource (rep i32))) + (type (func (result (borrow $r)))) + ) + "function result cannot contain a `borrow` type") +(assert_invalid + (component + (type $r (resource (rep i32))) + (type (func (result (list (borrow $r))))) + ) + "function result cannot contain a `borrow` type") +(assert_invalid + (component + (type $r (resource (rep i32))) + (type (func (result (option (borrow $r))))) + ) + "function result cannot contain a `borrow` type") +(assert_invalid + (component + (type $r (resource (rep i32))) + (type $t (record (field "f" (borrow $r)))) + (type (func (result (option (list $t))))) + ) + "function result cannot contain a `borrow` type") + +;; forms of canon builtins +(component + (type $r (resource (rep i32))) + (core func (canon resource.new $r)) + (canon resource.new $r (core func)) + (core func (canon resource.drop $r)) + (canon resource.drop $r (core func)) + (core func (canon resource.rep $r)) + (canon resource.rep $r (core func)) +) diff --git a/test/wasm-tools/tags.wast b/test/wasm-tools/tags.wast new file mode 100644 index 00000000..5c70d3ab --- /dev/null +++ b/test/wasm-tools/tags.wast @@ -0,0 +1,30 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component + (core module $m (func (export ""))) + (core instance $i (instantiate $m)) + (alias core export $i "" (core tag $t)) + ) + "export `` for core instance 0 is not a tag") + +(component + (core module $m (tag (export ""))) + (core instance $i (instantiate $m)) + (alias core export $i "" (core tag $t)) +) + +(component + (core module $m (tag (export ""))) + (core instance $i (instantiate $m)) + (core instance + (export "" (tag $i "")))) + +(assert_invalid + (component + (core module $m (func (export ""))) + (core instance $i (instantiate $m)) + (core instance + (export "" (tag 0))) + ) + "unknown tag 0") diff --git a/test/wasm-tools/type-export-restrictions.wast b/test/wasm-tools/type-export-restrictions.wast new file mode 100644 index 00000000..d2971f8d --- /dev/null +++ b/test/wasm-tools/type-export-restrictions.wast @@ -0,0 +1,504 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +;; Test that unnamed types in various types are all detected + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (record (field "f" $t))) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (list $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (tuple $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (variant (case "c" $t))) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (option $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (result $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +;; Test that various types are all flagged as "requires a name" + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (list $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (enum "a")) + (type $f (list $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (flags "a")) + (type $f (list $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (variant (case "a"))) + (type $f (list $t)) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (resource (rep i32))) + (type $f (list (own $t))) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +;; Some types don't need names +(component + (type $t1 (tuple (tuple u32))) + (export "t1" (type $t1)) + + (type $t2 (option (tuple (list u8) (result (list u32) (error (option string)))))) + (export "t2" (type $t2)) + + (type $t3 u32) + (export "t3" (type $t3)) +) + +(component + (type $t' (record (field "f" u32))) + (export $t "t" (type $t')) + (type $t2 (record (field "x" $t))) + (export "t2" (type $t2)) +) + +;; imports are validated as well +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $t2 (record (field "f" $t))) + (import "x" (type (eq $t2))) + ) + "type not valid to be used as import") +(component + (type $t (record (field "f" u32))) + (import "t" (type $t' (eq $t))) + (type $t2 (record (field "f" $t'))) + (import "x" (type (eq $t2))) +) +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $t2 (record (field "f" $t))) + (import "x" (func (param "x" $t2))) + ) + "func not valid to be used as import") + +(assert_invalid + (component + (type $t (resource (rep i32))) + (export "t" (type $t)) + (type $f (list (own $t))) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +;; validate within the type context +(assert_invalid + (component + (type (component + (type $t (record (field "f" u32))) + (export "f" (func (param "x" $t))) + )) + ) + "func not valid to be used as export") +(assert_invalid + (component + (type (component + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + (export "f" (type (eq $f))) + )) + ) + "type not valid to be used as export") + +;; instances of unexported types is ok +(component + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + (instance + (export "f" (type $f)) + ) +) +;; .. but exporting them is not +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + (instance $i + (export "f" (type $f)) + ) + (export "i" (instance $i)) + ) + "instance not valid to be used as export") + +;; Can't export a lifted function with unexported types +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + + (core module $m (func $f (export "f") (param i32))) + (core instance $i (instantiate $m)) + (func $f (param "f" $f) (canon lift (core func $i "f"))) + (export "f" (func $f)) + ) + "func not valid to be used as export") + +;; Unexported instances don't work +(assert_invalid + (component + (type $t' (record (field "f" u32))) + (instance $i + (export "t" (type $t')) + ) + (alias export $i "t" (type $t)) + + (core module $m (func $f (export "f") (param i32))) + (core instance $i (instantiate $m)) + (func $f (param "f" $t) (canon lift (core func $i "f"))) + (export "f" (func $f)) + ) + "func not valid to be used as export") + +;; Even through a component it doesn't work +(assert_invalid + (component + (component $C + (type $t (record (field "f" u32))) + (export "t" (type $t)) + ) + (instance $i (instantiate $C)) + (alias export $i "t" (type $t)) + + (core module $m (func $f (export "f") (param i32))) + (core instance $i (instantiate $m)) + (func $f (param "f" $t) (canon lift (core func $i "f"))) + (export "f" (func $f)) + ) + "func not valid to be used as export") + +;; through exported instances is ok though +(component + (type $t' (record (field "f" u32))) + (instance $i' + (export "t" (type $t')) + ) + (export $i "i" (instance $i')) + (alias export $i "t" (type $t)) + + (core module $m (func $f (export "f") (param i32))) + (core instance $i (instantiate $m)) + (func $f (param "f" $t) (canon lift (core func $i "f"))) + (export "f" (func $f)) +) +(component + (component $C + (type $t (record (field "f" u32))) + (export "t" (type $t)) + ) + (instance $i' (instantiate $C)) + (export $i "i" (instance $i')) + (alias export $i "t" (type $t)) + + (core module $m (func $f (export "f") (param i32))) + (core instance $i (instantiate $m)) + (func $f (param "f" $t) (canon lift (core func $i "f"))) + (export "f" (func $f)) +) + +;; a type-ascribed export which is otherwise invalid can become valid +(component + (type $t (record (field "f" u32))) + + (core module $m (func (export "f") (param i32))) + (core instance $i (instantiate $m)) + (func $f (param "x" $t) (canon lift (core func $i "f"))) + + (export $t' "t" (type $t)) + (export "f" (func $f) (func (param "x" $t'))) +) + +;; imports can't reference exports +(assert_invalid + (component + (type $t1 (record (field "f" u32))) + (export $t2 "t1" (type $t1)) + (import "i" (func (result $t2))) + ) + "func not valid to be used as import") + +;; exports can reference imports +(component + (type $t1 (record (field "f" u32))) + (import "t1" (type $t2 (eq $t1))) + (export "e-t1" (type $t2)) +) +(component + (component + (type $t1 (record (field "f" u32))) + (import "t1" (type $t2 (eq $t1))) + (import "i" (func $f (result $t2))) + + (export "e-i" (func $f)) + ) +) + +;; outer aliases don't work for imports/exports +(assert_invalid + (component + (type $t1 (record (field "f" u32))) + (import "t1" (type $t2 (eq $t1))) + (component + (import "i" (func $f (result $t2))) + ) + ) + "func not valid to be used as import") +(assert_invalid + (component + (type $t1 (record (field "f" u32))) + (export $t2 "t1" (type $t1)) + (component + (core module $m (func (export "f") (result i32) unreachable)) + (core instance $i (instantiate $m)) + (func $f (export "i") (result $t2) (canon lift (core func $i "f"))) + ) + ) + "func not valid to be used as export") + +;; outer aliases work for components, modules, and resources +(component + (type $c (component)) + (type (component + (import "c" (component (type $c))) + )) + (component + (import "c" (component (type $c))) + ) + (type $i (instance)) + (type (component + (import "c" (instance (type $i))) + )) + + (type $r (resource (rep i32))) + (type (component + (import "r" (type (eq $r))) + )) +) + +;; reexport of an import is fine +(component + (component + (import "r" (func $r)) + (export "r2" (func $r)) + ) +) +(component + (type $t (record (field "f" u32))) + (import "r" (type $r (eq $t))) + (export "r2" (type $r)) +) +(component + (import "r" (instance $r)) + (export "r2" (instance $r)) +) +(component definition + (import "r" (type $r (sub resource))) + (export "r2" (type $r)) +) + +;; bag of exports cannot be exported by carrying through context that's not +;; otherwise exported +(assert_invalid + (component + (component $A + (type $t (record (field "f" u32))) + (export $t2 "t" (type $t)) + (core module $m (func (export "f") (result i32) unreachable)) + (core instance $i (instantiate $m)) + (func $f (result $t2) (canon lift (core func $i "f"))) + + (instance (export "i") + (export "f" (func $f)) + ) + ) + + (instance $a (instantiate $A)) + ;; this component only exports `f`, not the record type that is the result + ;; of `f`, so it should be invalid. + (export "a" (instance $a "i")) + ) + "instance not valid to be used as export") + +;; instance types can be "temporarily invalid", but not if they're attached +;; to a concrete component +(component + (type (instance + (type $t (record (field "f" u32))) + (export "f" (func (param "x" $t))) + )) +) +(assert_invalid + (component + (type $i (instance + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + (export "f" (type (eq $f))) + )) + (import "f" (instance (type $i))) + ) + "instance not valid to be used as import") + +;; allow for one import to refer to another +(component definition $C + (import "foo" (instance $i + (type $baz' (record (field "f" u32))) + (export "baz" (type $baz (eq $baz'))) + (type $bar' (record (field "baz" $baz))) + (export "bar" (type $bar (eq $bar'))) + )) + (alias export $i "bar" (type $bar)) + (import "bar" (instance + (alias outer $C $bar (type $bar')) + (export "bar" (type $bar (eq $bar'))) + (export "a" (func $f (result $bar))) + )) +) + +;; allow for one import to refer to another +(component + (type $r' (record (field "f" u32))) + (import "r" (type $r (eq $r'))) + (component $C + (type $r' (record (field "f" u32))) + (import "r" (type $r (eq $r'))) + (type $r2' (record (field "r" $r))) + (export "r2" (type $r2')) + ) + (instance $c (instantiate $C (with "r" (type $r)))) + (export "r2" (type $c "r2")) +) + +;; types are validated when they are exported +(assert_invalid + (component + (type $i (instance + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + (export "f" (type (eq $f))) + )) + (import "f" (type (eq $i))) + ) + "type not valid to be used as import") +(assert_invalid + (component + (type $i (instance + (type $t (record (field "f" u32))) + (type $f (record (field "t" $t))) + (export "f" (type (eq $f))) + )) + (export "f" (type $i)) + ) + "type not valid to be used as export") + +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (func (result $t))) + (import "f" (type (eq $f))) + ) + "type not valid to be used as import") +(assert_invalid + (component + (type $t (record (field "f" u32))) + (type $f (func (result $t))) + (export "f" (type $f)) + ) + "type not valid to be used as export") + +(component + (type (;0;) + (instance + (type (;0;) (enum "qux")) + (export (;1;) "baz" (type (eq 0))) + (type (;2;) (record (field "bar" 1) )) + (export (;3;) "foo" (type (eq 2))) + ) + ) + (import (interface "demo:component/types") (instance (;0;) (type 0))) + (component + (type (;0;) + (instance + (type (;0;) (enum "qux")) + (export (;1;) "baz" (type (eq 0))) + (type (;2;) (record (field "bar" 1) )) + (export (;3;) "foo" (type (eq 2))) + ) + ) + (import (interface "demo:component/types") (instance (;0;) (type 0))) + (component (;0;) + (type (;0;) (enum "qux")) + (import "import-type-baz" (type (;1;) (eq 0))) + (type (;2;) (record (field "bar" 1) )) + (import "import-type-bar" (type (;3;) (eq 2))) + (export (;4;) "foo" (type 3)) + ) + (instance (;1;) (instantiate 0 + (with "import-type-baz" (type 0 "baz")) + (with "import-type-bar" (type 0 "foo")) + ) + ) + (export (;0;) (interface "demo:component/types") (instance 1)) + ) + (instance (instantiate 0 (with "demo:component/types" (instance 0)))) + (export (interface "demo:component/types") (instance 1 "demo:component/types")) +) diff --git a/test/wasm-tools/types.wast b/test/wasm-tools/types.wast new file mode 100644 index 00000000..5df1ec9d --- /dev/null +++ b/test/wasm-tools/types.wast @@ -0,0 +1,374 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component + (type $t (instance)) + (import "a" (func (type $t))) + ) + "type index 0 is not a function type") + +(assert_invalid + (component + (core type $t (func)) + (import "a" (core module (type $t))) + ) + "core type index 0 is not a module type") + +(assert_invalid + (component + (type $t (func)) + (import "a" (instance (type $t))) + ) + "type index 0 is not an instance type") + +(assert_invalid + (component + (type $t (func)) + (type (component + (import "a" (instance (type $t))) + )) + ) + "type index 0 is not an instance type") + +(assert_invalid + (component + (core type $t (func)) + (type (component + (import "a" (core module (type $t))) + )) + ) + "core type index 0 is not a module type") + +(assert_invalid + (component + (type $t (instance)) + (type (component + (import "a" (func (type $t))) + )) + ) + "type index 0 is not a function type") + +(assert_invalid + (component + (export "a" (core module 0)) + ) + "module index out of bounds") + +(assert_invalid + (component + (export "a" (instance 0)) + ) + "instance index out of bounds") + +(assert_invalid + (component + (core type (module + (export "a" (func (type 0))) + )) + ) + "type index out of bounds") + +(assert_invalid + (component + (core type (module + (export "a" (func)) + (export "a" (func)) + )) + ) + "export name `a` already defined") + +(assert_invalid + (component + (core type (module + (import "" "" (func)) + (import "" "" (func)) + )) + ) + "duplicate import name") + +(assert_invalid + (component + (core type (module + (import "" "" (memory 70000)) + )) + ) + "memory size must be at most") + +(assert_invalid + (component + (type (component + (export "a" (func (type 0))) + )) + ) + "type index out of bounds") + +(assert_invalid + (component + (type (component + (export "a" (func)) + (export "A" (func)) + )) + ) + "export name `A` conflicts with previous name `a`") + +(assert_invalid + (component + (type (component + (import "A" (func)) + (import "a" (func)) + )) + ) + "import name `a` conflicts with previous name `A`") + +(assert_malformed + (component quote + "(component $c (core type $t (module (alias outer $c $t (type)))))" + ) + "unknown core type") + +(assert_invalid + (component + (core type (module + (alias outer 1 0 (type)) + )) + ) + "type index out of bounds") + +(component $c + (core type $f (func)) + (core type $t (module + (alias outer $c $f (type)) + )) +) + +(assert_malformed + (component quote + "(component $c (type $t (component (alias outer $c $t (type)))))" + ) + "unknown type") + +(assert_invalid + (component + (type (component + (alias outer 1 0 (type)) + )) + ) + "type index out of bounds") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (component + (alias outer 100 0 (type)) + )) + ) + "invalid outer alias count of 100") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (component + (core type (module + (export "" (func)) + (export "" (func)) + )) + )) + ) + "name `` already defined") + +(assert_invalid + (component + (type (instance + (export "" (func (type 0))) + )) + ) + "type index out of bounds") + +(assert_invalid + (component + (type (instance + (export "foo-BAR-baz" (func)) + (export "FOO-bar-BAZ" (func)) + )) + ) + "export name `FOO-bar-BAZ` conflicts with previous name `foo-BAR-baz`") + +(assert_malformed + (component quote + "(component $c (type $t (instance (alias outer $c $t (type)))))" + ) + "unknown type") + +(assert_invalid + (component + (type (instance + (alias outer 1 0 (type)) + )) + ) + "type index out of bounds") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (instance + (alias outer 100 0 (type)) + )) + ) + "invalid outer alias count of 100") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (instance + (core type (module + (export "" (func)) + (export "" (func)) + )) + )) + ) + "name `` already defined") + +(assert_invalid + (component $c + (type $f (func (param "" string))) + ) + "function parameter name cannot be empty") + +(component + (type $t (func (result (tuple (list u8) u32)))) +) + +(component $C + (core type $t (func)) + (core type (module + (alias outer $C $t (type $a)) + (import "" "" (func (type $a))) + )) +) + +(component $C + (component $C2 + (core type $t (func)) + (core type (module + (alias outer $C2 $t (type $a)) + (import "" "" (func (type $a))) + )) + ) +) + +(component $C + (core type $t (func)) + (component $C2 + (core type (module + (alias outer $C $t (type $a)) + (import "" "" (func (type $a))) + )) + ) +) + +(component + (type (instance + (type string) + (export "a" (type (eq 0))) + )) +) + +(component + (type (component + (type string) + (import "a" (type (eq 0))) + (export "b" (type (eq 0))) + )) +) + +(assert_invalid + (component + (type (variant)) + ) + "variant type must have at least one case") + +(assert_invalid + (component + (type (enum)) + ) + "enum type must have at least one variant") + +(assert_invalid + (component + (type (record)) + ) + "record type must have at least one field") + +(assert_invalid + (component + (type (flags)) + ) + "flags must have at least one entry") + +(assert_invalid + (component + (type (tuple)) + ) + "tuple type must have at least one type") + +(component $c + (core type $f (func)) + (component $c2 + (core type $t (module + (alias outer $c $f (type)) + )) + ) +) + +(assert_invalid + (component + (type (flags + "f1" + "f2" + "f3" + "f4" + "f5" + "f6" + "f7" + "f8" + "f9" + "f10" + "f11" + "f12" + "f13" + "f14" + "f15" + "f16" + "f17" + "f18" + "f19" + "f20" + "f21" + "f22" + "f23" + "f24" + "f25" + "f26" + "f27" + "f28" + "f29" + "f30" + "f31" + "f32" + "f33" + )) + ) + "cannot have more than 32 flags") + +(assert_invalid + (component + (core type $t (module)) + (core type (func (param (ref $t)))) + ) + "type index 0 is a module type") + +(assert_invalid + (component + (core type (func (param (ref 100)))) + ) + "type index out of bounds") diff --git a/test/wasm-tools/very-nested.wast b/test/wasm-tools/very-nested.wast new file mode 100644 index 00000000..42c5aede --- /dev/null +++ b/test/wasm-tools/very-nested.wast @@ -0,0 +1,1954 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_invalid + (component $$esl + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "00AGG554M******+*****e 4$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "anonmm-x23foinas-ASDOJASD") + ) + (component + (export "c t.****0*********") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "agds-ASF-TT-yy") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "0+AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00A$qq") + ) + (component + (export "c t.*************") + (export "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "15AG:GG!le*$$qq") + ) + (component + (export "c t.*") + (component + (export "c 3@EGGGG$qq**") + (export "bsdew2-sdbsdb") + ) + (component + (export "c t.********)*eleo &m Nx2GGGGle*$$qq") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "0*************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "00AGG554M******+*****e 4$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "anonmm-x23foinas-ASDOJASD") + ) + (component + (export "c t.****0*********") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "agds-ASF-TT-yy") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "0+AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00A$qq") + ) + (component + (export "c t.*************") + (export "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "15AG:GG!le*$$qq") + ) + (component + (export "c .t*") + (component + (export "c 3@EGGGG$qq**") + (export "bsdew2-sdbsdb") + ) + (component + (export "c t.********)*eleo &m Nx2GGGGle*$$qq") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle '$$qq") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 6@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c *****") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "00AGG554M******+*****e 4$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "anonmm-x23foinas-ASDOJASD") + ) + (component + (export "c t.****0*********") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "agds-ASF-TT-yy") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "0+AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00A$qq") + ) + (component + (export "c t.*************") + (export "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "15AG:GG!le*$$qq") + ) + (component + (export "c t.*") + (component + (export "c 3@EGGGG$qq**") + (export "bsdew2-sdbsdb") + ) + (component + (export "c t.********)*eleo &m Nx2GGGGle*$$qq") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "0*************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "00AGG554M******+*****e 4$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "anonmm-x23foinas-ASDOJASD") + ) + (component + (export "c t.****0*********") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "agds-ASF-TT-yy") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "0+AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00A$qq") + ) + (component + (export "c t.*************") + (export "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "15AG:GG!le*$$qq") + ) + (component + (export "c .t*") + (component + (export "c 3@EGGGG$qq**") + (export "bsdew2-sdbsdb") + ) + (component + (export "c t.********)*eleo &m Nx2GGGGle*$$qq") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "sdg-q12") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "jsjsjs") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle '$$qq") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 6@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGl4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E***0AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle '$$qq") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 6@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGl4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E**************777777777777777777777777777777777777777777777777777777777777771.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGl4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E***0AG") + (component + (export "c 3@EGG*****+*****e $$qq") + ) + (component + (export "q**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c=t.*************") + (export "00AG") + (component + (export "alskgn-mbnaj4-a33i5nf") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "afhinds-T39OIDN-f1jsj11") + (import "sf-gqo3ngin23ogin13g-bvcad") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle '$$qq") + ) + (component + (export "q") + ) + (component + (export "b 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 0.*************") + (export "00AGGWGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*********GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E************[******") + (import "bsdew2-sdbsdb") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 6@E$*************7777777777777777777777777777777777777777777MM~MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM777777777777777777777777777777777777777777*****") + (import "00e*$$qq") + ) + (component + (export "EGG-y-GG-qq") + (export "00AGGG.Gle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "bsdew2-sdbsdb") + ) + (component + (export "c 1.*************") + (export "00AGGGGle A*$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGl4@E****\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*****GG$qq**") + (export "dojgn-ejs9-nd188") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + (component + (export "q") + ) + (component + (export "c 3@E*******77777777777777777777777777777777GG)le 0AGGGGle $$qq") + ) + (component + (export "q") + ) + (component + (export "c 3@E*******************") + (import "00CGGGGle*$$qq") + ) + (component + (export "c t.*************") + (export "00AGGGGle *$$qq") + ) + (component) + ) + ) + "conflicts with previous name") + +(assert_invalid + (component + (type $m0 (component)) + (type $m1 (component + (import "i1" (component (type $m0))) + (import "i2" (component (type $m0))) + (import "i3" (component (type $m0))) + (import "i4" (component (type $m0))) + (import "i5" (component (type $m0))) + (import "i6" (component (type $m0))) + (import "i7" (component (type $m0))) + (import "i8" (component (type $m0))) + (import "i9" (component (type $m0))) + (import "i10" (component (type $m0))) + )) + (type $m2 (component + (import "i1" (component (type $m1))) + (import "i2" (component (type $m1))) + (import "i3" (component (type $m1))) + (import "i4" (component (type $m1))) + (import "i5" (component (type $m1))) + (import "i6" (component (type $m1))) + (import "i7" (component (type $m1))) + (import "i8" (component (type $m1))) + (import "i9" (component (type $m1))) + (import "i10" (component (type $m1))) + )) + (type $m3 (component + (import "i1" (component (type $m2))) + (import "i2" (component (type $m2))) + (import "i3" (component (type $m2))) + (import "i4" (component (type $m2))) + (import "i5" (component (type $m2))) + (import "i6" (component (type $m2))) + (import "i7" (component (type $m2))) + (import "i8" (component (type $m2))) + (import "i9" (component (type $m2))) + (import "i10" (component (type $m2))) + )) + (type $m4 (component + (import "i1" (component (type $m3))) + (import "i2" (component (type $m3))) + (import "i3" (component (type $m3))) + (import "i4" (component (type $m3))) + (import "i5" (component (type $m3))) + (import "i6" (component (type $m3))) + (import "i7" (component (type $m3))) + (import "i8" (component (type $m3))) + (import "i9" (component (type $m3))) + (import "i10" (component (type $m3))) + )) + (type $m5 (component + (import "i1" (component (type $m4))) + (import "i2" (component (type $m4))) + (import "i3" (component (type $m4))) + (import "i4" (component (type $m4))) + (import "i5" (component (type $m4))) + (import "i6" (component (type $m4))) + (import "i7" (component (type $m4))) + (import "i8" (component (type $m4))) + (import "i9" (component (type $m4))) + (import "i10" (component (type $m4))) + )) + (type $m6 (component + (import "i1" (component (type $m5))) + (import "i2" (component (type $m5))) + (import "i3" (component (type $m5))) + (import "i4" (component (type $m5))) + (import "i5" (component (type $m5))) + (import "i6" (component (type $m5))) + (import "i7" (component (type $m5))) + (import "i8" (component (type $m5))) + (import "i9" (component (type $m5))) + (import "i10" (component (type $m5))) + )) + (type $m7 (component + (import "i1" (component (type $m6))) + (import "i2" (component (type $m6))) + (import "i3" (component (type $m6))) + (import "i4" (component (type $m6))) + (import "i5" (component (type $m6))) + (import "i6" (component (type $m6))) + (import "i7" (component (type $m6))) + (import "i8" (component (type $m6))) + (import "i9" (component (type $m6))) + (import "i10" (component (type $m6))) + )) + (type $m8 (component + (import "i1" (component (type $m7))) + (import "i2" (component (type $m7))) + (import "i3" (component (type $m7))) + (import "i4" (component (type $m7))) + (import "i5" (component (type $m7))) + (import "i6" (component (type $m7))) + (import "i7" (component (type $m7))) + (import "i8" (component (type $m7))) + (import "i9" (component (type $m7))) + (import "i10" (component (type $m7))) + )) + (type $m9 (component + (import "i1" (component (type $m8))) + (import "i2" (component (type $m8))) + (import "i3" (component (type $m8))) + (import "i4" (component (type $m8))) + (import "i5" (component (type $m8))) + (import "i6" (component (type $m8))) + (import "i7" (component (type $m8))) + (import "i8" (component (type $m8))) + (import "i9" (component (type $m8))) + (import "i10" (component (type $m8))) + )) + + (type $m (component + (import "a" (component (type $m9))) + )) + (import "a" (component $a (type $m9))) + (import "b" (component $b (type $m))) + (instance (instantiate $b (with "a" (component $a)))) + ) + "effective type size exceeds the limit") + +(assert_invalid + (component + (component $m0) + (component $m1 + (instance (export "e0") (instantiate $m0)) + (instance (export "e1") (instantiate $m0)) + (instance (export "e2") (instantiate $m0)) + (instance (export "e3") (instantiate $m0)) + (instance (export "e4") (instantiate $m0)) + (instance (export "e5") (instantiate $m0)) + (instance (export "e6") (instantiate $m0)) + (instance (export "e7") (instantiate $m0)) + (instance (export "e8") (instantiate $m0)) + (instance (export "e9") (instantiate $m0)) + ) + (component $m2 + (instance (export "e0") (instantiate $m1)) + (instance (export "e1") (instantiate $m1)) + (instance (export "e2") (instantiate $m1)) + (instance (export "e3") (instantiate $m1)) + (instance (export "e4") (instantiate $m1)) + (instance (export "e5") (instantiate $m1)) + (instance (export "e6") (instantiate $m1)) + (instance (export "e7") (instantiate $m1)) + (instance (export "e8") (instantiate $m1)) + (instance (export "e9") (instantiate $m1)) + ) + (component $m3 + (instance (export "e0") (instantiate $m2)) + (instance (export "e1") (instantiate $m2)) + (instance (export "e2") (instantiate $m2)) + (instance (export "e3") (instantiate $m2)) + (instance (export "e4") (instantiate $m2)) + (instance (export "e5") (instantiate $m2)) + (instance (export "e6") (instantiate $m2)) + (instance (export "e7") (instantiate $m2)) + (instance (export "e8") (instantiate $m2)) + (instance (export "e9") (instantiate $m2)) + ) + (component $m4 + (instance (export "e0") (instantiate $m3)) + (instance (export "e1") (instantiate $m3)) + (instance (export "e2") (instantiate $m3)) + (instance (export "e3") (instantiate $m3)) + (instance (export "e4") (instantiate $m3)) + (instance (export "e5") (instantiate $m3)) + (instance (export "e6") (instantiate $m3)) + (instance (export "e7") (instantiate $m3)) + (instance (export "e8") (instantiate $m3)) + (instance (export "e9") (instantiate $m3)) + ) + (component $m5 + (instance (export "e0") (instantiate $m4)) + (instance (export "e1") (instantiate $m4)) + (instance (export "e2") (instantiate $m4)) + (instance (export "e3") (instantiate $m4)) + (instance (export "e4") (instantiate $m4)) + (instance (export "e5") (instantiate $m4)) + (instance (export "e6") (instantiate $m4)) + (instance (export "e7") (instantiate $m4)) + (instance (export "e8") (instantiate $m4)) + (instance (export "e9") (instantiate $m4)) + ) + (component $m6 + (instance (export "e0") (instantiate $m5)) + (instance (export "e1") (instantiate $m5)) + (instance (export "e2") (instantiate $m5)) + (instance (export "e3") (instantiate $m5)) + (instance (export "e4") (instantiate $m5)) + (instance (export "e5") (instantiate $m5)) + (instance (export "e6") (instantiate $m5)) + (instance (export "e7") (instantiate $m5)) + (instance (export "e8") (instantiate $m5)) + (instance (export "e9") (instantiate $m5)) + ) + (component $m7 + (instance (export "e0") (instantiate $m6)) + (instance (export "e1") (instantiate $m6)) + (instance (export "e2") (instantiate $m6)) + (instance (export "e3") (instantiate $m6)) + (instance (export "e4") (instantiate $m6)) + (instance (export "e5") (instantiate $m6)) + (instance (export "e6") (instantiate $m6)) + (instance (export "e7") (instantiate $m6)) + (instance (export "e8") (instantiate $m6)) + (instance (export "e9") (instantiate $m6)) + ) + ) + "effective type size exceeds the limit") + +(assert_invalid + (component + ;; size(t0) == 1 + (type $t0 (flags "x")) + + ;; size(t1) == 10 + (type $t1 (record + (field "f0" $t0) + (field "f1" $t0) + (field "f2" $t0) + (field "f3" $t0) + (field "f4" $t0) + (field "f5" $t0) + (field "f6" $t0) + (field "f7" $t0) + (field "f8" $t0) + (field "f9" $t0) + )) + + ;; size(t2) == 100 + (type $t2 (record + (field "f0" $t1) + (field "f1" $t1) + (field "f2" $t1) + (field "f3" $t1) + (field "f4" $t1) + (field "f5" $t1) + (field "f6" $t1) + (field "f7" $t1) + (field "f8" $t1) + (field "f9" $t1) + )) + + ;; size(t3) == 1000 + (type $t3 (record + (field "f0" $t2) + (field "f1" $t2) + (field "f2" $t2) + (field "f3" $t2) + (field "f4" $t2) + (field "f5" $t2) + (field "f6" $t2) + (field "f7" $t2) + (field "f8" $t2) + (field "f9" $t2) + )) + + ;; size(t4) == 10000 + (type $t4 (record + (field "f0" $t3) + (field "f1" $t3) + (field "f2" $t3) + (field "f3" $t3) + (field "f4" $t3) + (field "f5" $t3) + (field "f6" $t3) + (field "f7" $t3) + (field "f8" $t3) + (field "f9" $t3) + )) + + ;; size(t5) == 100000 + (type $t5 (record + (field "f0" $t4) + (field "f1" $t4) + (field "f2" $t4) + (field "f3" $t4) + (field "f4" $t4) + (field "f5" $t4) + (field "f6" $t4) + (field "f7" $t4) + (field "f8" $t4) + (field "f9" $t4) + )) + + (type $f (func + (param "a" $t5) + (param "b" $t5) + (param "c" $t5) + (param "d" $t5) + (param "e" $t5) + (param "f" $t5) + (param "g" $t5) + (param "h" $t5) + (param "i" $t5) + (param "j" $t5) + )) + ) + "effective type size exceeds the limit") + +(assert_malformed + (component quote + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + "(component(component(component(component(component(component(component" + ) + "nesting too deep") diff --git a/test/wasm-tools/virtualize.wast b/test/wasm-tools/virtualize.wast new file mode 100644 index 00000000..d60b73b9 --- /dev/null +++ b/test/wasm-tools/virtualize.wast @@ -0,0 +1,119 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(component + (core module $libc + (memory (export "mem") 0) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) + unreachable + ) + ) + (core instance $libc (instantiate $libc)) + + (component $child + (import "wasi-file" (instance $wasi-file + (export "read" (func (param "count" u32) (result (list u8)))) + (export "write" (func (param "bytes" (list u8)) (result u32))) + )) + + (core instance $libc (instantiate $libc)) + + (core module $m + (import "wasi-file" "read" (func $read (param i32 i32))) + (func $play (export "play") + unreachable + ) + ) + + (core func $wasi_file_read + (canon lower (func $wasi-file "read") + (memory $libc "mem") + (realloc (func $libc "realloc")) + ) + ) + + (core instance $i (instantiate $m + (with "wasi-file" (instance + (export "read" (func $wasi_file_read)) + )) + )) + + (func (export "play") + (canon lift (core func $i "play")) + ) + ) + + (component $virtualize + (import "wasi-file" (instance $wasi-file + (export "read" (func (param "len" u32) (result (list u8)))) + (export "write" (func (param "buf" (list u8)) (result u32))) + )) + (export "read" (func $wasi-file "read")) + (export "write" (func $wasi-file "write")) + ) + + (component + (type $WasiFile (instance + (export "read" (func (param "len" u32) (result (list u8)))) + (export "write" (func (param "buf" (list u8)) (result u32))) + )) + (import "wasi-file" (instance $real-wasi (type $WasiFile))) + (import "virtualize" (component $VIRTUALIZE + (import "wasi-file" (instance (type $WasiFile))) + (export "read" (func (param "len" u32) (result (list u8)))) + (export "write" (func (param "buf" (list u8)) (result u32))) + )) + (import "child" (component $CHILD + (import "wasi-file" (instance (type $WasiFile))) + (export "play" (func)) + ) + ) + + (instance $virt-wasi (instantiate $VIRTUALIZE (with "wasi-file" (instance $real-wasi)))) + (instance $child (instantiate $CHILD (with "wasi-file" (instance $virt-wasi)))) + + (export "work" (func $child "play")) + ) + + (component + (type $WasiFile (instance + (export "read" (func (param "len" u32) (result (list u8)))) + (export "write" (func (param "buf" (list u8)) (result u32))) + )) + (import "wasi-file" (instance $real-wasi (type $WasiFile))) + + (core instance $libc (instantiate $libc)) + + (core module $CHILD + (import "wasi-file" "read" (func $wasi-file (param i32 i32))) + (func $play (export "play") + unreachable + ) + ) + + (core module $VIRTUALIZE + (import "wasi-file" "read" (func (param i32 i32))) + (func (export "read") (param i32 i32) + unreachable + ) + (func (export "write") (param i32 i32 i32) + unreachable + ) + ) + + (core func $real-wasi-read + (canon lower (func $real-wasi "read") + (memory $libc "mem") + (realloc (func $libc "realloc")) + ) + ) + + (core instance $virt-wasi (instantiate $VIRTUALIZE (with "wasi-file" (instance (export "read" (func $real-wasi-read)))))) + (core instance $child (instantiate $CHILD (with "wasi-file" (instance $virt-wasi)))) + (func (export "work") + (canon lift (core func $child "play") + (memory $libc "mem") + (realloc (func $libc "realloc")) + ) + ) + ) +) diff --git a/test/wasm-tools/wrong-order.wast b/test/wasm-tools/wrong-order.wast new file mode 100644 index 00000000..098fc419 --- /dev/null +++ b/test/wasm-tools/wrong-order.wast @@ -0,0 +1,11 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % + +(assert_malformed + (module binary + "\00asm\01\00\00\00" + + "\01\01\00" ;; type section, 1 byte, 0 entries + "\0b\01\00" ;; data section, 1 byte, 0 entries + "\01\01\00" ;; type section, 1 byte, 0 entries + ) + "section out of order") diff --git a/test/wasmtime/adapter.wast b/test/wasmtime/adapter.wast new file mode 100644 index 00000000..0ca70a1d --- /dev/null +++ b/test/wasmtime/adapter.wast @@ -0,0 +1,137 @@ +;;! multi_memory = true + +;; basic function lifting +(component + (core module $m + (func (export "")) + ) + (core instance $i (instantiate $m)) + + (func (export "thunk") + (canon lift (core func $i "")) + ) +) + +;; use an aliased type +(component $c + (core module $m + (func (export "")) + ) + (core instance $i (instantiate $m)) + + (type $to_alias (func)) + (alias outer $c $to_alias (type $alias)) + + (func (export "thunk") (type $alias) + (canon lift (core func $i "")) + ) +) + +;; test out some various canonical abi +(component $c + (core module $m + (func (export "") (param i32 i32)) + (memory (export "memory") 1) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) + unreachable) + ) + (core instance $i (instantiate $m)) + + (func (export "thunk") (param "a" string) + (canon lift + (core func $i "") + (memory $i "memory") + (realloc (func $i "realloc")) + ) + ) + + (func (export "thunk8") (param "a" string) + (canon lift + (core func $i "") + string-encoding=utf8 + (memory $i "memory") + (realloc (func $i "realloc")) + ) + ) + + (func (export "thunk16") (param "a" string) + (canon lift + (core func $i "") + string-encoding=utf16 + (memory $i "memory") + (realloc (func $i "realloc")) + ) + ) + + (func (export "thunklatin16") (param "a" string) + (canon lift + (core func $i "") + string-encoding=latin1+utf16 + (memory $i "memory") + (realloc (func $i "realloc")) + ) + ) +) + +;; lower something then immediately lift it +(component $c + (import "host-return-two" (func $f (result u32))) + + (core func $f_lower + (canon lower (func $f)) + ) + (func $f2 (result s32) + (canon lift (core func $f_lower)) + ) + (export "f" (func $f2)) +) + +;; valid, but odd +(component + (core module $m (func (export ""))) + (core instance $m (instantiate $m)) + + (func $f1 (canon lift (core func $m ""))) + (core func $f2 (canon lower (func $f1))) +) +(assert_trap + (component + (core module $m (func (export ""))) + (core instance $m (instantiate $m)) + + (func $f1 (canon lift (core func $m ""))) + (core func $f2 (canon lower (func $f1))) + + (core module $m2 + (import "" "" (func $f)) + (func $start + call $f) + (start $start) + ) + (core instance (instantiate $m2 + (with "" (instance (export "" (func $f2)))) + )) + ) + "degenerate component adapter called") + +;; fiddling with 0-sized lists +(component $c + (core module $m + (func (export "x") (param i32 i32)) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) + i32.const -1) + (memory (export "memory") 0) + ) + (core instance $m (instantiate $m)) + (type $t' (result)) + (export $t "t" (type $t')) + (func $f (param "a" (list $t)) + (canon lift + (core func $m "x") + (realloc (func $m "realloc")) + (memory $m "memory") + ) + ) + (export "empty-list" (func $f)) +) +(assert_trap (invoke "empty-list" (list.const)) "realloc return: beyond end of memory") diff --git a/test/wasmtime/aliasing.wast b/test/wasmtime/aliasing.wast new file mode 100644 index 00000000..ad18f935 --- /dev/null +++ b/test/wasmtime/aliasing.wast @@ -0,0 +1,29 @@ +(component + (component + (component + (component) + (instance (instantiate 0)) + (export "a" (instance 0)) + ) + (instance (instantiate 0)) + (export "a" (instance 0)) + ) + + (instance (instantiate 0)) ;; instance 0 + (alias export 0 "a" (instance)) ;; instance 1 + (export "a" (instance 1)) ;; instance 2 + (alias export 2 "a" (instance)) ;; instance 3 + (export "inner-a" (instance 3)) ;; instance 4 +) + +(component + (component + (core module) + (export "a" (core module 0)) + ) + + (instance (instantiate 0)) + (alias export 0 "a" (core module)) ;; module 0 + (export "a" (core module 0)) ;; module 1 + (core instance (instantiate 1)) +) diff --git a/test/wasmtime/fused.wast b/test/wasmtime/fused.wast new file mode 100644 index 00000000..90f2ed4a --- /dev/null +++ b/test/wasmtime/fused.wast @@ -0,0 +1,1359 @@ +;;! multi_memory = true + +;; 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 "a" (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 "a" (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 "a" bool) (canon lift (core func $m "assert_true"))) + (func $assert_false (param "a" bool) (canon lift (core func $m "assert_false"))) + (func $ret_bool (param "a" u32) (result bool) (canon lift (core func $m "ret-bool"))) + + (component $c + (import "assert-true" (func $assert_true (param "a" bool))) + (import "assert-false" (func $assert_false (param "a" bool))) + (import "ret-bool" (func $ret_bool (param "a" 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)) + (then (unreachable))) + (if (i32.ne (call $ret_bool (i32.const 2)) (i32.const 1)) + (then (unreachable))) + (if (i32.ne (call $ret_bool (i32.const -1)) (i32.const 1)) + (then (unreachable))) + (if (i32.ne (call $ret_bool (i32.const 0)) (i32.const 0)) + (then (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 "a1" u32) (param "a2" u32) (param "a3" u32) (param "a4" u32) (param "a5" u32) + (param "a6" u32) (param "a7" u32) (param "a8" u32) (param "a9" u32) (param "a10" u32) + (param "a11" u32) (param "a12" u32) (param "a13" u32) (param "a14" u32) (param "a15" u32) + (param "a16" u32) (param "a17" u32) (param "a18" u32) (param "a19" u32) (param "a20" 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)) + (then (unreachable))) + + (if (i32.ne (i32.load offset=0 (local.get $src)) (i32.const 1)) (then (unreachable))) + (if (i32.ne (i32.load offset=4 (local.get $src)) (i32.const 2)) (then (unreachable))) + (if (i32.ne (i32.load offset=8 (local.get $src)) (i32.const 3)) (then (unreachable))) + (if (i32.ne (i32.load offset=12 (local.get $src)) (i32.const 4)) (then (unreachable))) + (if (i32.ne (i32.load offset=16 (local.get $src)) (i32.const 5)) (then (unreachable))) + (if (i32.ne (i32.load offset=20 (local.get $src)) (i32.const 6)) (then (unreachable))) + (if (i32.ne (i32.load offset=24 (local.get $src)) (i32.const 7)) (then (unreachable))) + (if (i32.ne (i32.load offset=28 (local.get $src)) (i32.const 8)) (then (unreachable))) + (if (i32.ne (i32.load offset=32 (local.get $src)) (i32.const 9)) (then (unreachable))) + (if (i32.ne (i32.load offset=36 (local.get $src)) (i32.const 10)) (then (unreachable))) + (if (i32.ne (i32.load offset=40 (local.get $src)) (i32.const 11)) (then (unreachable))) + (if (i32.ne (i32.load offset=44 (local.get $src)) (i32.const 12)) (then (unreachable))) + (if (i32.ne (i32.load offset=48 (local.get $src)) (i32.const 13)) (then (unreachable))) + (if (i32.ne (i32.load offset=52 (local.get $src)) (i32.const 14)) (then (unreachable))) + (if (i32.ne (i32.load offset=56 (local.get $src)) (i32.const 15)) (then (unreachable))) + (if (i32.ne (i32.load offset=60 (local.get $src)) (i32.const 16)) (then (unreachable))) + (if (i32.ne (i32.load offset=64 (local.get $src)) (i32.const 17)) (then (unreachable))) + (if (i32.ne (i32.load offset=68 (local.get $src)) (i32.const 18)) (then (unreachable))) + (if (i32.ne (i32.load offset=72 (local.get $src)) (i32.const 19)) (then (unreachable))) + (if (i32.ne (i32.load offset=76 (local.get $src)) (i32.const 20)) (then (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)) (then (unreachable))) + (if (i32.ne (i32.load offset=4 (local.get $retaddr)) (i32.const 22)) (then (unreachable))) + (if (i32.ne (i32.load offset=8 (local.get $retaddr)) (i32.const 23)) (then (unreachable))) + (if (i32.ne (i32.load offset=12 (local.get $retaddr)) (i32.const 24)) (then (unreachable))) + (if (i32.ne (i32.load offset=16 (local.get $retaddr)) (i32.const 25)) (then (unreachable))) + (if (i32.ne (i32.load offset=20 (local.get $retaddr)) (i32.const 26)) (then (unreachable))) + (if (i32.ne (i32.load offset=24 (local.get $retaddr)) (i32.const 27)) (then (unreachable))) + (if (i32.ne (i32.load offset=28 (local.get $retaddr)) (i32.const 28)) (then (unreachable))) + (if (i32.ne (i32.load offset=32 (local.get $retaddr)) (i32.const 29)) (then (unreachable))) + (if (i32.ne (i32.load offset=36 (local.get $retaddr)) (i32.const 30)) (then (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)) (then (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 "thunk2") (result u32) + (canon lift (core func $reexport "thunk")) + ) + ) + + (instance $c1 (instantiate $c (with "thunk" (func $root)))) + (instance $c2 (instantiate $c (with "thunk" (func $c1 "thunk2")))) + (instance $c3 (instantiate $c (with "thunk" (func $c2 "thunk2")))) + (instance $c4 (instantiate $c (with "thunk" (func $c3 "thunk2")))) + (instance $c5 (instantiate $c (with "thunk" (func $c4 "thunk2")))) + (instance $c6 (instantiate $c (with "thunk" (func $c5 "thunk2")))) + + (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 "thunk2")))) +) + +;; 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 "a" (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 "a" $tuple20) + (canon lift + (core func $m "foo") + (memory $m "memory") + (realloc (func $realloc)) + ) + ) + + (component $c + (import "foo" (func $foo (param "a" $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)) (then (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)) (then (unreachable)))) + (start $start) + ) + (core instance (instantiate $something + (with "" (instance + (export "foo" (func $foo)) + )) + )) + ) + (instance (instantiate $c + (with "foo" (func $foo)) + )) +) + +;; 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 "a" $big) + (canon lift (core func $m "r") (memory $m "memory") (realloc (func $m "realloc"))) + ) + ) + (component $c2 + (import "r" (func $r (param "a" $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 "a" $big) + (canon lift (core func $m "r") (memory $m "memory") (realloc (func $m "realloc"))) + ) + ) + (component $c2 + (import "r" (func $r (param "a" $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 + (component $c1 + (type $a' (variant (case "x"))) + (export $a "a" (type $a')) + (type $b' (variant (case "y"))) + (export $b "b" (type $b')) + + (core module $m + (func (export "r") (param i32) (result i32) + (if (i32.ne (local.get 0) (i32.const 0)) (then (unreachable))) + i32.const 0 + ) + ) + (core instance $m (instantiate $m)) + (func (export "r") (param "a" $a) (result $b) (canon lift (core func $m "r"))) + ) + (component $c2 + (type $a' (variant (case "x"))) + (import "a" (type $a (eq $a'))) + (type $b' (variant (case "y"))) + (import "b" (type $b (eq $b'))) + + (import "r" (func $r (param "a" $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 "a" (type $c1 "a")) + (with "b" (type $c1 "b")) + (with "r" (func $c1 "r")) + )) +) + +;; invalid variant discriminant in a parameter +(assert_trap + (component + (component $c1 + (type $a' (variant (case "x"))) + (export $a "a" (type $a')) + (core module $m + (func (export "r") (param i32)) + ) + (core instance $m (instantiate $m)) + (func (export "r") (param "a" $a) (canon lift (core func $m "r"))) + ) + (component $c2 + (type $a' (variant (case "x"))) + (import "a" (type $a (eq $a'))) + (import "r" (func $r (param "a" $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 "a" (type $c1 "a")) + (with "r" (func $c1 "r")) + )) + ) + "unreachable") + +;; invalid variant discriminant in a result +(assert_trap + (component + (component $c1 + (type $a' (variant (case "x"))) + (export $a "a" (type $a')) + (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 + (type $a' (variant (case "x"))) + (import "a" (type $a (eq $a'))) + (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 "a" (type $c1 "a")) + (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)) (then (unreachable))) + ) + (func (export "s") (param i32) + (if (i32.ne (local.get 0) (i32.const -1)) (then (unreachable))) + ) + ) + (core instance $m (instantiate $m)) + (func (export "u8") (param "a" u8) (canon lift (core func $m "u"))) + (func (export "u16") (param "a" u16) (canon lift (core func $m "u"))) + (func (export "s8") (param "a" s8) (canon lift (core func $m "s"))) + (func (export "s16") (param "a" s16) (canon lift (core func $m "s"))) + ) + (component $c2 + (import "a" (instance $i + (export "u8" (func (param "a" u8))) + (export "s8" (func (param "a" s8))) + (export "u16" (func (param "a" u16))) + (export "s16" (func (param "a" 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 "a" (instance $c1)))) +) + +;; translation of locals between different types +(component + (component $c1 + (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))) + (export $a "t-a" (type $a')) + (export $b "t-b" (type $b')) + (export $c "t-c" (type $c')) + (export $d "t-d" (type $d')) + (export $e "t-e" (type $e')) + + (type $func_a (func (param "x" bool) (param "a" $a))) + (type $func_b (func (param "x" bool) (param "b" $b))) + (type $func_c (func (param "x" bool) (param "c" $c))) + (type $func_d (func (param "x" bool) (param "d" $d))) + (type $func_e (func (param "x" bool) (param "e" $d))) + + (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)) (then (unreachable))) + (if (i32.ne (local.get 2) (i32.const 2)) (then (unreachable))) + else + (if (i32.ne (local.get 1) (i32.const 1)) (then (unreachable))) + (if (f32.ne (f32.reinterpret_i32 (local.get 2)) (f32.const 3)) (then (unreachable))) + end + ) + (func (export "b") (param i32 i32 i64) + (i32.eqz (local.get 0)) + if + (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable))) + (if (i64.ne (local.get 2) (i64.const 4)) (then (unreachable))) + else + (if (i32.ne (local.get 1) (i32.const 1)) (then (unreachable))) + (if (i64.ne (local.get 2) (i64.const 5)) (then (unreachable))) + end + ) + (func (export "c") (param i32 i32 i64) + (i32.eqz (local.get 0)) + if + (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable))) + (if (i64.ne (local.get 2) (i64.const 6)) (then (unreachable))) + else + (if (i32.ne (local.get 1) (i32.const 1)) (then (unreachable))) + (if (f64.ne (f64.reinterpret_i64 (local.get 2)) (f64.const 7)) (then (unreachable))) + end + ) + (func (export "d") (param i32 i32 i64) + (i32.eqz (local.get 0)) + if + (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable))) + (if (f32.ne (f32.reinterpret_i32 (i32.wrap_i64 (local.get 2))) (f32.const 8)) (then (unreachable))) + else + (if (i32.ne (local.get 1) (i32.const 1)) (then (unreachable))) + (if (f64.ne (f64.reinterpret_i64 (local.get 2)) (f64.const 9)) (then (unreachable))) + end + ) + (func (export "e") (param i32 i32 i64) + (i32.eqz (local.get 0)) + if + (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable))) + (if (f32.ne (f32.reinterpret_i32 (i32.wrap_i64 (local.get 2))) (f32.const 10)) (then (unreachable))) + else + (if (i32.ne (local.get 1) (i32.const 1)) (then (unreachable))) + (if (i64.ne (local.get 2) (i64.const 11)) (then (unreachable))) + end + ) + ) + (core instance $m (instantiate $m)) + (func (export "a") (type $func_a) (canon lift (core func $m "a"))) + (func (export "b") (type $func_b) (canon lift (core func $m "b"))) + (func (export "c") (type $func_c) (canon lift (core func $m "c"))) + (func (export "d") (type $func_d) (canon lift (core func $m "d"))) + (func (export "e") (type $func_e) (canon lift (core func $m "e"))) + ) + (component $c2 + (import "a" (instance $i + (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))) + (export "t-a" (type $a (eq $a'))) + (export "t-b" (type $b (eq $b'))) + (export "t-c" (type $c (eq $c'))) + (export "t-d" (type $d (eq $d'))) + (export "t-e" (type $e (eq $e'))) + (type $func_a (func (param "x" bool) (param "a" $a))) + (type $func_b (func (param "x" bool) (param "b" $b))) + (type $func_c (func (param "x" bool) (param "c" $c))) + (type $func_d (func (param "x" bool) (param "d" $d))) + (type $func_e (func (param "x" bool) (param "e" $d))) + + (export "a" (func (type $func_a))) + (export "b" (func (type $func_b))) + (export "c" (func (type $func_c))) + (export "d" (func (type $func_d))) + (export "e" (func (type $func_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 "a" (instance $c1)))) +) + +;; different size variants +(component + (component $c1 + (type $a' (variant + (case "a") + (case "b" float32) + (case "c" (tuple float32 u32)) + (case "d" (tuple float32 u64 u8)) + )) + (export $a "t-a" (type $a')) + + (core module $m + (func (export "a") (param i32 i32 f32 i64 i32) + (if (i32.eq (local.get 0) (i32.const 0)) + (then (block + (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable))) + (if (f32.ne (local.get 2) (f32.const 0)) (then (unreachable))) + (if (i64.ne (local.get 3) (i64.const 0)) (then (unreachable))) + (if (i32.ne (local.get 4) (i32.const 0)) (then (unreachable))) + )) + ) + (if (i32.eq (local.get 0) (i32.const 1)) + (then (block + (if (i32.ne (local.get 1) (i32.const 1)) (then (unreachable))) + (if (f32.ne (local.get 2) (f32.const 1)) (then (unreachable))) + (if (i64.ne (local.get 3) (i64.const 0)) (then (unreachable))) + (if (i32.ne (local.get 4) (i32.const 0)) (then (unreachable))) + )) + ) + (if (i32.eq (local.get 0) (i32.const 2)) + (then (block + (if (i32.ne (local.get 1) (i32.const 2)) (then (unreachable))) + (if (f32.ne (local.get 2) (f32.const 2)) (then (unreachable))) + (if (i64.ne (local.get 3) (i64.const 2)) (then (unreachable))) + (if (i32.ne (local.get 4) (i32.const 0)) (then (unreachable))) + )) + ) + (if (i32.eq (local.get 0) (i32.const 3)) + (then (block + (if (i32.ne (local.get 1) (i32.const 3)) (then (unreachable))) + (if (f32.ne (local.get 2) (f32.const 3)) (then (unreachable))) + (if (i64.ne (local.get 3) (i64.const 3)) (then (unreachable))) + (if (i32.ne (local.get 4) (i32.const 3)) (then (unreachable))) + )) + ) + (if (i32.gt_u (local.get 0) (i32.const 3)) + (then (unreachable))) + ) + ) + (core instance $m (instantiate $m)) + (func (export "a") (param "x" u8) (param "a" $a) (canon lift (core func $m "a"))) + ) + (component $c2 + (import "a" (instance $i + (type $a' (variant + (case "a") + (case "b" float32) + (case "c" (tuple float32 u32)) + (case "d" (tuple float32 u64 u8)) + )) + (export "t-a" (type $a (eq $a'))) + (export "a" (func (param "x" u8) (param "a" $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 "a" (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 "a" char) (result char) (canon lift (core func $m "a"))) + ) + (component $c2 + (import "a" (instance $i + (export "a" (func (param "a" 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 "a" char) (canon lift (core func $m "roundtrip"))) + ) + (instance $c1 (instantiate $c1)) + (instance $c2 (instantiate $c2 (with "a" (instance $c1)))) + + (export "roundtrip" (func $c2 "roundtrip")) +) + +(assert_return (invoke "roundtrip" (char.const "x"))) +(assert_return (invoke "roundtrip" (char.const "⛳"))) +(assert_return (invoke "roundtrip" (char.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 "a" char) (canon lift (core func $m "a"))) + ) + (component $c2 + (import "a" (instance $i (export "a" (func (param "a" 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 "a" (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 "a" char) (canon lift (core func $m "a"))) + ) + (component $c2 + (import "a" (instance $i (export "a" (func (param "a" 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 "a" (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 "a" char) (canon lift (core func $m "a"))) + ) + (component $c2 + (import "a" (instance $i (export "a" (func (param "a" 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 "a" (instance $c1)))) + ) + "unreachable") + +;; test that flags get their upper bits all masked off +(component + (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" + )) + + (component $c1 + (export $f1 "t-f1" (type $f1')) + (export $f8 "t-f8" (type $f8')) + (export $f9 "t-f9" (type $f9')) + (export $f16 "t-f16" (type $f16')) + (export $f17 "t-f17" (type $f17')) + (export $f32 "t-f32" (type $f32')) + (core module $m + (func (export "f1") (param i32) + (if (i32.ne (local.get 0) (i32.const 0x1)) (then (unreachable))) + ) + (func (export "f8") (param i32) + (if (i32.ne (local.get 0) (i32.const 0x11)) (then (unreachable))) + ) + (func (export "f9") (param i32) + (if (i32.ne (local.get 0) (i32.const 0x111)) (then (unreachable))) + ) + (func (export "f16") (param i32) + (if (i32.ne (local.get 0) (i32.const 0x1111)) (then (unreachable))) + ) + (func (export "f17") (param i32) + (if (i32.ne (local.get 0) (i32.const 0x11111)) (then (unreachable))) + ) + (func (export "f32") (param i32) + (if (i32.ne (local.get 0) (i32.const 0x11111111)) (then (unreachable))) + ) + ) + (core instance $m (instantiate $m)) + (func (export "f1") (param "a" $f1) (canon lift (core func $m "f1"))) + (func (export "f8") (param "a" $f8) (canon lift (core func $m "f8"))) + (func (export "f9") (param "a" $f9) (canon lift (core func $m "f9"))) + (func (export "f16") (param "a" $f16) (canon lift (core func $m "f16"))) + (func (export "f17") (param "a" $f17) (canon lift (core func $m "f17"))) + (func (export "f32") (param "a" $f32) (canon lift (core func $m "f32"))) + ) + (instance $c1 (instantiate $c1)) + + (component $c2 + (import "a" (instance $i + (export "t-f1" (type $f1 (eq $f1'))) + (export "t-f8" (type $f8 (eq $f8'))) + (export "t-f9" (type $f9 (eq $f9'))) + (export "t-f16" (type $f16 (eq $f16'))) + (export "t-f17" (type $f17 (eq $f17'))) + (export "t-f32" (type $f32 (eq $f32'))) + (export "f1" (func (param "a" $f1))) + (export "f8" (func (param "a" $f8))) + (export "f9" (func (param "a" $f9))) + (export "f16" (func (param "a" $f16))) + (export "f17" (func (param "a" $f17))) + (export "f32" (func (param "a" $f32))) + )) + (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 module $m + (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))) + + (func $start + (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)) + ) + + (start $start) + ) + (core instance $m (instantiate $m + (with "" (instance + (export "f1" (func $f1)) + (export "f8" (func $f8)) + (export "f9" (func $f9)) + (export "f16" (func $f16)) + (export "f17" (func $f17)) + (export "f32" (func $f32)) + )) + )) + ) + (instance (instantiate $c2 (with "a" (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 depended 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)))) +) diff --git a/test/wasmtime/import.wast b/test/wasmtime/import.wast new file mode 100644 index 00000000..20688efe --- /dev/null +++ b/test/wasmtime/import.wast @@ -0,0 +1,20 @@ +(assert_invalid + (component + (import "host-return-two" (func $f (result u32))) + (export "x" (func $f))) + "component export `x` is a reexport of an imported function which is not implemented") + +(assert_unlinkable + (component + (import "host-return-two" (instance)) + ) + "expected instance found func") + +;; empty instances don't need to be supplied by the host, even recursively +;; empty instances. +(component + (import "not-provided-by-the-host" (instance)) + (import "not-provided-by-the-host2" (instance + (export "x" (instance)) + )) +) diff --git a/test/wasmtime/instance.wast b/test/wasmtime/instance.wast new file mode 100644 index 00000000..4216cdc5 --- /dev/null +++ b/test/wasmtime/instance.wast @@ -0,0 +1,327 @@ +(component + (core module $m) + (core instance (instantiate $m)) +) + +(component + (core module $m + (func (export "")) + ) + (core instance $i (instantiate $m)) + + (core module $m2 + (func (import "" "")) + ) + (core instance (instantiate $m2 (with "" (instance $i)))) +) + +(component + (core module $m + (func (export "a")) + ) + (core instance $i (instantiate $m)) + + (core module $m2 + (func (import "" "b")) + ) + (core instance (instantiate $m2 + (with "" (instance (export "b" (func $i "a")))) + )) +) + +;; all kinds of imports for core wasm modules, and register a start function on +;; one module to ensure that everything is correct +(component + (core module $m + (func (export "a")) + (table (export "b") 1 funcref) + (memory (export "c") 1) + (global (export "d") i32 i32.const 1) + ) + (core instance $i (instantiate $m)) + + (core module $m2 + (import "" "a" (func $f)) + (import "" "b" (table 1 funcref)) + (import "" "c" (memory 1)) + (import "" "d" (global $g i32)) + + (func $start + global.get $g + i32.const 1 + i32.ne + if + unreachable + end + + call $f + ) + + (start $start) + + (data (i32.const 0) "hello") + (elem (i32.const 0) $start) + ) + (core instance (instantiate $m2 + (with "" (instance $i)) + )) +) + +;; Test to see if a component with a type export can be instantiated. +(component + (type string) + (export "a" (type 0)) +) + +;; double-check the start function runs by ensuring that a trap shows up and it +;; sees the wrong value for the global import +(assert_trap + (component + (core module $m + (global (export "g") i32 i32.const 1) + ) + (core instance $i (instantiate $m)) + + (core module $m2 + (import "" "g" (global $g i32)) + + (func $start + global.get $g + i32.const 0 + i32.ne + if + unreachable + end + ) + + (start $start) + ) + (core instance (instantiate $m2 (with "" (instance $i)))) + ) + "unreachable") + +;; shuffle around imports to get to what the target core wasm module needs +(component + (core module $m + (func (export "1")) + (table (export "2") 1 funcref) + (memory (export "3") 1) + (global (export "4") i32 i32.const 1) + ) + (core instance $i (instantiate $m)) + + (core module $m2 + (import "" "a" (func $f)) + (import "" "b" (table 1 funcref)) + (import "" "c" (memory 1)) + (import "" "d" (global $g i32)) + ) + (core instance (instantiate $m2 + (with "" (instance + (export "a" (func $i "1")) + (export "b" (table $i "2")) + (export "c" (memory $i "3")) + (export "d" (global $i "4")) + )) + )) +) + +;; indirect references through a synthetic instance +(component + (core module $m + (func (export "a")) + (table (export "b") 1 funcref) + (memory (export "c") 1) + (global (export "d") i32 i32.const 1) + ) + (core instance $i (instantiate $m)) + (core instance $i2 + (export "a1" (func $i "a")) + (export "a2" (table $i "b")) + (export "a3" (memory $i "c")) + (export "a4" (global $i "d")) + ) + + (core module $m2 + (import "" "1" (func $f)) + (import "" "2" (table 1 funcref)) + (import "" "3" (memory 1)) + (import "" "4" (global $g i32)) + ) + (core instance (instantiate $m2 + (with "" (instance + (export "1" (func $i2 "a1")) + (export "2" (table $i2 "a2")) + (export "3" (memory $i2 "a3")) + (export "4" (global $i2 "a4")) + )) + )) +) + +(component + (import "host" (instance $i (export "return-three" (func (result u32))))) + + (core module $m + (import "host" "return-three" (func $three (result i32))) + (func $start + call $three + i32.const 3 + i32.ne + if unreachable end + ) + (start $start) + ) + (core func $three_lower + (canon lower (func $i "return-three")) + ) + (core instance (instantiate $m + (with "host" (instance (export "return-three" (func $three_lower)))) + )) +) + +(component + (import "host" (instance $i + (type $x' (record (field "x" u32))) + (export "x" (type $x (eq $x'))) + (type $rec' (record (field "x" $x) (field "y" string))) + (export "rec" (type $rec (eq $rec'))) + (export "some-record" (type (eq $rec))))) +) + +(component + (import "host" (instance $i + (export "nested" (instance + (export "return-four" (func (result u32))) + )) + )) + + (core module $m + (import "host" "return-three" (func $three (result i32))) + (func $start + call $three + i32.const 4 + i32.ne + if unreachable end + ) + (start $start) + ) + (core func $three_lower + (canon lower (func $i "nested" "return-four")) + ) + (core instance (instantiate $m + (with "host" (instance (export "return-three" (func $three_lower)))) + )) +) + +(component + (import "host" (instance $i + (export "simple-module" (core module)) + )) + + (core instance (instantiate (module $i "simple-module"))) +) + +(component + (import "host" (instance $i + (export "simple-module" (core module + (export "f" (func (result i32))) + (export "g" (global i32)) + )) + )) + + (core instance $i (instantiate (module $i "simple-module"))) + (core module $verify + (import "host" "f" (func $f (result i32))) + (import "host" "g" (global $g i32)) + + (func $start + call $f + i32.const 101 + i32.ne + if unreachable end + + global.get $g + i32.const 100 + i32.ne + if unreachable end + ) + (start $start) + ) + + (core instance (instantiate $verify (with "host" (instance $i)))) +) + +;; export an instance +(component + (core module $m) + (instance $i (export "m" (core module $m))) + (export "i" (instance $i)) +) +(component + (component $c) + (instance $i (instantiate $c)) + (export "i" (instance $i)) +) +(component + (import "host" (instance $i)) + (export "i" (instance $i)) +) + + +(component definition $C1 + (type $r1 (resource (rep i32))) + (export "r" (type $r1)) +) +(component definition $C2 + (type $r1 (resource (rep i32))) + (export "r" (type $r1)) +) + +(component instance $I1 $C1) +(component instance $I2 $C1) +(component instance $I3 $C2) +(component instance $I4 $C2) + +;; all instances have different resource types +(assert_unlinkable + (component + (import "I1" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I2" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I1" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I3" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I1" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I4" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I2" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I3" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I2" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I4" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I3" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I4" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") diff --git a/test/wasmtime/linking.wast b/test/wasmtime/linking.wast new file mode 100644 index 00000000..966926f0 --- /dev/null +++ b/test/wasmtime/linking.wast @@ -0,0 +1,18 @@ +(assert_unlinkable + (component + (import "undefined-name" (core module)) + ) + "was not found") +(component $i) +(component + (import "i" (instance)) +) +(assert_unlinkable + (component (import "i" (core module))) + "expected module found instance") +(assert_unlinkable + (component (import "i" (func))) + "expected function found instance") +(assert_unlinkable + (component (import "i" (instance (export "x" (func))))) + "was not found") diff --git a/test/wasmtime/modules.wast b/test/wasmtime/modules.wast new file mode 100644 index 00000000..6014f94e --- /dev/null +++ b/test/wasmtime/modules.wast @@ -0,0 +1,479 @@ +;;! reference_types = true + +(component $foo + (core module (export "a-module")) +) + +;; the above instance can be imported into this component +(component + (import "foo" (instance + (export "a-module" (core module)) + )) +) + +;; specifying extra imports is ok +(component + (import "foo" (instance + (export "a-module" (core module + (import "foo" "bar" (func)) + )) + )) +) + +;; specifying extra exports is not ok +(assert_unlinkable + (component + (import "foo" (instance + (export "a-module" (core module + (export "the-export" (func)) + )) + )) + ) + "module export `the-export` not defined") + +(component $foo + (core module (export "a-module") + (import "env" "something" (func)) + ) +) + +;; imports must be specified +(assert_unlinkable + (component + (import "foo" (instance + (export "a-module" (core module)) + )) + ) + "module import `env::something` not defined") + +(component + (import "foo" (instance + (export "a-module" (core module + (import "env" "something" (func)) + )) + )) +) + +;; extra imports still ok +(component + (import "foo" (instance + (export "a-module" (core module + (import "env" "something" (func)) + (import "env" "other" (global i32)) + )) + )) +) + +(component $foo + (core module (export "a-module") + (func (export "f")) + ) +) + +;; dropping exports is ok +(component + (import "foo" (instance + (export "a-module" (core module)) + )) +) + +(component + (import "foo" (instance + (export "a-module" (core module + (export "f" (func)) + )) + )) +) + +(assert_unlinkable + (component + (import "foo" (instance + (export "a-module" (core module + (export "f" (func (param i32))) + )) + )) + ) + "expected type `(func (param i32))`, found type `(func)`") + +(assert_unlinkable + (component + (import "foo" (instance + (export "a-module" (core module + (export "f" (global i32)) + )) + )) + ) + "expected global found func") + +(component $foo + (core module (export "m") + (func (export "f")) + (table (export "t") 1 funcref) + (memory (export "m") 1) + (global (export "g") i32 i32.const 0) + ) +) + +;; wrong class of item +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "f" (global i32)))) + )) + ) + "expected global found func") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "t" (func)))) + )) + ) + "expected func found table") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "m" (func)))) + )) + ) + "expected func found memory") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "g" (func)))) + )) + ) + "expected func found global") + +;; wrong item type +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "f" (func (param i32))))) + )) + ) + "export `f` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "t" (table 1 externref)))) + )) + ) + "export `t` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "t" (table 2 funcref)))) + )) + ) + "export `t` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "m" (memory 2)))) + )) + ) + "export `m` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "g" (global f32)))) + )) + ) + "export `g` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (export "g" (global (mut i32))))) + )) + ) + "export `g` has the wrong type") + +;; subtyping ok +(component + (import "foo" (instance + (export "m" (core module + (export "t" (table 0 funcref)) + (export "m" (memory 0)) + )) + )) +) + +(component $foo + (core module (export "f") (func (import "" ""))) + (core module (export "t") (table (import "" "") 1 funcref)) + (core module (export "m") (memory (import "" "") 1)) + (core module (export "g") (global (import "" "") i32)) +) + +;; wrong class of item +(assert_unlinkable + (component + (import "foo" (instance + (export "f" (core module (import "" "" (global i32)))) + )) + ) + "expected func found global") +(assert_unlinkable + (component + (import "foo" (instance + (export "t" (core module (import "" "" (func)))) + )) + ) + "expected table found func") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (import "" "" (func)))) + )) + ) + "expected memory found func") +(assert_unlinkable + (component + (import "foo" (instance + (export "g" (core module (import "" "" (func)))) + )) + ) + "expected global found func") + +;; wrong item type +(assert_unlinkable + (component + (import "foo" (instance + (export "f" (core module (import "" "" (func (param i32))))) + )) + ) + "module import `::` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "t" (core module (import "" "" (table 1 externref)))) + )) + ) + "module import `::` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "t" (core module (import "" "" (table 0 funcref)))) + )) + ) + "module import `::` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "m" (core module (import "" "" (memory 0)))) + )) + ) + "module import `::` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "g" (core module (import "" "" (global f32)))) + )) + ) + "module import `::` has the wrong type") +(assert_unlinkable + (component + (import "foo" (instance + (export "g" (core module (import "" "" (global (mut i32))))) + )) + ) + "module import `::` has the wrong type") + +;; subtyping ok, but in the opposite direction of imports +(component + (import "foo" (instance + (export "t" (core module (import "" "" (table 2 funcref)))) + (export "m" (core module (import "" "" (memory 2)))) + )) +) + +;; An instance can reexport a module, define a module, and everything can be +;; used by something else +(component $src + (core module (export "m") + (global (export "g") i32 i32.const 2) + ) +) + +(component $reexport + (core module $m1 + (global (export "g") i32 i32.const 1) + ) + (import "src" (instance $src + (export "m" (core module (export "g" (global i32)))) + )) + + (core module $m3 + (global (export "g") i32 i32.const 3) + ) + + (export "m1" (core module $m1)) + (export "m2" (core module $src "m")) + (export "m3" (core module $m3)) +) + +(component + (core type $modulety (module (export "g" (global i32)))) + (import "reexport" (instance $reexport + (export "m1" (core module (type $modulety))) + (export "m2" (core module (type $modulety))) + (export "m3" (core module (type $modulety))) + )) + + (core module $assert_ok + (import "m1" "g" (global $m1 i32)) + (import "m2" "g" (global $m2 i32)) + (import "m3" "g" (global $m3 i32)) + + (func $assert_ok + block + global.get $m1 + i32.const 1 + i32.eq + br_if 0 + unreachable + end + block + global.get $m2 + i32.const 2 + i32.eq + br_if 0 + unreachable + end + block + global.get $m3 + i32.const 3 + i32.eq + br_if 0 + unreachable + end + ) + + (start $assert_ok) + ) + + (core instance $m1 (instantiate (module $reexport "m1"))) + (core instance $m2 (instantiate (module $reexport "m2"))) + (core instance $m3 (instantiate (module $reexport "m3"))) + + (core instance (instantiate $assert_ok + (with "m1" (instance $m1)) + (with "m2" (instance $m2)) + (with "m3" (instance $m3)) + )) +) + +;; order of imports and exports can be shuffled between definition site and +;; use-site +(component $provider + (core module (export "m") + (import "" "1" (global $i1 i32)) + (import "" "2" (global $i2 i32)) + (import "" "3" (global $i3 i32)) + (import "" "4" (global $i4 i32)) + + (global $g1 i32 i32.const 100) + (global $g2 i32 i32.const 101) + (global $g3 i32 i32.const 102) + (global $g4 i32 i32.const 103) + + (func $assert_imports + (block + global.get $i1 + i32.const 1 + i32.eq + br_if 0 + unreachable) + (block + global.get $i2 + i32.const 2 + i32.eq + br_if 0 + unreachable) + (block + global.get $i3 + i32.const 3 + i32.eq + br_if 0 + unreachable) + (block + global.get $i4 + i32.const 4 + i32.eq + br_if 0 + unreachable) + ) + + (start $assert_imports) + + (export "g1" (global $g1)) + (export "g2" (global $g2)) + (export "g3" (global $g3)) + (export "g4" (global $g4)) + ) +) + +(component + (import "provider" (instance $provider + (export "m" (core module + (import "" "4" (global i32)) + (import "" "3" (global i32)) + (import "" "2" (global i32)) + (import "" "1" (global i32)) + + (export "g4" (global i32)) + (export "g3" (global i32)) + (export "g2" (global i32)) + (export "g1" (global i32)) + )) + )) + + (core module $imports + (global (export "1") i32 (i32.const 1)) + (global (export "3") i32 (i32.const 3)) + (global (export "2") i32 (i32.const 2)) + (global (export "4") i32 (i32.const 4)) + ) + (core instance $imports (instantiate $imports)) + (core instance $m (instantiate (module $provider "m") + (with "" (instance $imports)) + )) + + (core module $import_globals + (import "" "g4" (global $g4 i32)) + (import "" "g3" (global $g3 i32)) + (import "" "g2" (global $g2 i32)) + (import "" "g1" (global $g1 i32)) + + (func $assert_imports + (block + global.get $g1 + i32.const 100 + i32.eq + br_if 0 + unreachable) + (block + global.get $g2 + i32.const 101 + i32.eq + br_if 0 + unreachable) + (block + global.get $g3 + i32.const 102 + i32.eq + br_if 0 + unreachable) + (block + global.get $g4 + i32.const 103 + i32.eq + br_if 0 + unreachable) + ) + + (start $assert_imports) + ) + + (core instance (instantiate $import_globals (with "" (instance $m)))) +) diff --git a/test/wasmtime/nested.wast b/test/wasmtime/nested.wast new file mode 100644 index 00000000..8cb4c381 --- /dev/null +++ b/test/wasmtime/nested.wast @@ -0,0 +1,451 @@ +;; simple nested component +(component + (component) +) + +;; simple nested component with a nested module +(component + (component + (core module) + ) +) + +;; simple instantiation of a nested component +(component + (component $c) + (instance (instantiate $c)) + (instance (instantiate $c + (with "x" (component $c)) + )) +) + +;; instantiate a module during a nested component, and also instantiate it +;; as an export of the nested component +(component + (component $c + (core module $m) + (core instance (instantiate $m)) + (export "m" (core module $m)) + ) + (instance $i (instantiate $c)) + (core instance $i (instantiate (module $i "m"))) +) + +;; instantiate an inner exported module with two different modules and +;; verify imports match +(component + (component $c + (core module $m + (import "" "g" (global $g i32)) + (import "" "f" (func $f (result i32))) + + (func $start + call $f + global.get $g + i32.ne + if unreachable end) + + (start $start) + ) + + (core module $m2 + (global (export "g") i32 i32.const 1) + (func (export "f") (result i32) i32.const 1) + ) + (core instance $i2 (instantiate $m2)) + (core instance (instantiate $m (with "" (instance $i2)))) + + (export "m" (core module $m)) + ) + (instance $i (instantiate $c)) + (core module $m2 + (global (export "g") i32 i32.const 5) + (func (export "f") (result i32) i32.const 5) + ) + (core instance $i2 (instantiate $m2)) + (core instance (instantiate (module $i "m") (with "" (instance $i2)))) +) + +;; instantiate an inner component with a module import +(component + (component $c + (import "m" (core module $m + (export "g" (global i32)) + )) + + (core instance $i (instantiate $m)) + + (core module $verify + (import "" "g" (global $g i32)) + + (func $start + global.get $g + i32.const 2 + i32.ne + if unreachable end + ) + + (start $start) + ) + (core instance (instantiate $verify (with "" (instance $i)))) + ) + + (core module $m + (global (export "g") i32 (i32.const 2)) + ) + (instance (instantiate $c (with "m" (core module $m)))) +) + +;; instantiate an inner component with a module import that itself has imports +(component + (component $c + (import "m" (core module $m + (import "" "g" (global i32)) + )) + (core module $m2 + (global (export "g") i32 i32.const 2100) + ) + (core instance $m2 (instantiate $m2)) + (core instance (instantiate $m (with "" (instance $m2)))) + ) + + (core module $verify + (import "" "g" (global $g i32)) + + (func $start + global.get $g + i32.const 2100 + i32.ne + if unreachable end + ) + + (start $start) + ) + (instance (instantiate $c (with "m" (core module $verify)))) +) + +;; instantiate an inner component with an export from the outer component +(component $c + (core module (export "m") + (import "" "g1" (global $g1 i32)) + (import "" "g2" (global $g2 i32)) + + (func $start + global.get $g1 + i32.const 10000 + i32.ne + if unreachable end + + global.get $g2 + i32.const 20000 + i32.ne + if unreachable end + ) + + (start $start) + ) +) + +(component + (import "c" (instance $i + (export "m" (core module + (import "" "g2" (global i32)) + (import "" "g1" (global i32)) + )) + )) + + (component $c + (import "m" (core module $verify + (import "" "g2" (global i32)) + (import "" "g1" (global i32)) + )) + + (core module $m + (global (export "g1") i32 i32.const 10000) + (global (export "g2") i32 i32.const 20000) + ) + (core instance $m (instantiate $m)) + (core instance (instantiate $verify (with "" (instance $m)))) + ) + + (instance (instantiate $c (with "m" (core module $i "m")))) +) + +;; instantiate a reexported module +(component + (core module $m + (global (export "g") i32 i32.const 7) + ) + (component $c + (import "i" (instance $i + (export "m" (core module + (import "" "" (func)) + (export "g" (global i32)) + )) + )) + + (export "m" (core module $i "m")) + ) + + (instance $c (instantiate $c (with "i" (instance (export "m" (core module $m)))))) + (core module $dummy + (func (export "")) + ) + (core instance $dummy (instantiate $dummy)) + + (core instance $m (instantiate (module $c "m") (with "" (instance $dummy)))) + + (core module $verify + (import "" "g" (global i32)) + (func $start + global.get 0 + i32.const 7 + i32.ne + if unreachable end + ) + + (start $start) + ) + (core instance (instantiate $verify (with "" (instance $m)))) +) + +;; module must be found through a few layers of imports +(component $c + (core module (export "m") + (global (export "g") i32 i32.const 101) + ) +) + +(component + (import "c" (instance $i + (export "m" (core module + (export "g" (global i32)) + )) + )) + (component $c1 + (import "c" (instance $i + (export "m" (core module + (export "g" (global i32)) + )) + )) + (core module $verify + (import "" "g" (global i32)) + (func $start + global.get 0 + i32.const 101 + i32.ne + if unreachable end + ) + + (start $start) + ) + (core instance $m (instantiate (module $i "m"))) + (core instance (instantiate $verify (with "" (instance $m)))) + ) + (instance (instantiate $c1 (with "c" (instance $i)))) +) + +;; instantiate outer alias to self +(component $C + (core module $m) + (alias outer $C $m (core module $other_m)) + (core instance (instantiate $other_m)) +) + +(component $C + (component $m) + (alias outer $C $m (component $other_m)) + (instance (instantiate $other_m)) +) + + +;; closing over an outer alias which is actually an argument to some +;; instantiation +(component + (component $c + (import "c" (core module $c + (export "a" (global i32)) + )) + + (component (export "c2") + (export "m" (core module $c)) + ) + ) + + (core module $m1 (global (export "a") i32 i32.const 1)) + (core module $m2 (global (export "a") i32 i32.const 2)) + + (instance $c1 (instantiate $c (with "c" (core module $m1)))) + (instance $c2 (instantiate $c (with "c" (core module $m2)))) + + (instance $m1_container (instantiate (component $c1 "c2"))) + (instance $m2_container (instantiate (component $c2 "c2"))) + + (core instance $core1 (instantiate (module $m1_container "m"))) + (core instance $core2 (instantiate (module $m2_container "m"))) + + (core module $verify + (import "core1" "a" (global $a i32)) + (import "core2" "a" (global $b i32)) + + (func $start + global.get $a + i32.const 1 + i32.ne + if unreachable end + + global.get $b + i32.const 2 + i32.ne + if unreachable end + ) + + (start $start) + ) + (core instance (instantiate $verify + (with "core1" (instance $core1)) + (with "core2" (instance $core2)) + )) +) + +;; simple importing of a component +(component + (component $C) + (component $other + (import "x" (component $c)) + (instance (instantiate $c)) + ) + (instance (instantiate $other (with "x" (component $C)))) +) + +;; deep nesting +(component $C + (core module $m + (global (export "g") i32 (i32.const 1)) + ) + (component $c + (core module (export "m") + (global (export "g") i32 (i32.const 2)) + ) + ) + + (component $c1 + (component $c2 (export "a") + (component $c3 (export "a") + (alias outer $C $m (core module $my_module)) + (alias outer $C $c (component $my_component)) + + (export "m" (core module $my_module)) + (export "c" (component $my_component)) + ) + ) + ) + + (instance $i1 (instantiate $c1)) + (instance $i2 (instantiate (component $i1 "a"))) + (instance $i3 (instantiate (component $i2 "a"))) + + (core instance $m1 (instantiate (module $i3 "m"))) + (instance $c (instantiate (component $i3 "c"))) + (core instance $m2 (instantiate (module $c "m"))) + + (core module $verify + (import "m1" "g" (global $m1 i32)) + (import "m2" "g" (global $m2 i32)) + + (func $start + global.get $m1 + i32.const 1 + i32.ne + if unreachable end + + global.get $m2 + i32.const 2 + i32.ne + if unreachable end + ) + (start $start) + ) + (core instance (instantiate $verify (with "m1" (instance $m1)) (with "m2" (instance $m2)))) +) + +;; Try threading through component instantiation arguments as various forms of +;; instances. +(component + (component $c + (core module $m (export "m")) + (component $c (export "c") + (core module (export "m")) + ) + (instance $i (instantiate $c)) + (instance $i2 + (export "m" (core module $m)) + (export "c" (component $c)) + (export "i" (instance $i)) + ) + (export "i" (instance $i)) + (export "i2" (instance $i2)) + ) + (instance $i (instantiate $c)) + + (component $another + (import "host" (instance + (export "m" (core module)) + (export "c" (component)) + (export "i" (instance)) + )) + ) + (instance (instantiate $another (with "host" (instance $i)))) + (instance (instantiate $another (with "host" (instance $i "i2")))) + + (instance $reexport + (export "c" (component $i "c")) + (export "m" (core module $i "m")) + (export "i" (instance $i "i")) + ) + (instance (instantiate $another (with "host" (instance $reexport)))) +) + +;; thread host functions around +(component + (import "host-return-two" (func $import (result u32))) + + ;; thread the host function through an instance + (component $c + (import "a" (func $f (result u32))) + (export "f" (func $f)) + ) + (instance $c (instantiate $c (with "a" (func $import)))) + (alias export $c "f" (func $import2)) + + ;; thread the host function into a nested component + (component $c2 + (import "host" (instance $i (export "return-two" (func (result u32))))) + + (core module $m + (import "host" "return-two" (func $host (result i32))) + (func $start + call $host + i32.const 2 + i32.ne + if unreachable end + ) + (start $start) + ) + + (core func $return_two + (canon lower (func $i "return-two")) + ) + (core instance (instantiate $m + (with "host" (instance + (export "return-two" (func $return_two)) + )) + )) + ) + + (instance (instantiate $c2 + (with "host" (instance + (export "return-two" (func $import2)) + )) + )) +) diff --git a/test/wasmtime/resources.wast b/test/wasmtime/resources.wast new file mode 100644 index 00000000..c9f94fec --- /dev/null +++ b/test/wasmtime/resources.wast @@ -0,0 +1,1091 @@ +;; bare bones "intrinsics work" +(component + (type $r (resource (rep i32))) + (core func $rep (canon resource.rep $r)) + (core func $new (canon resource.new $r)) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "rep" (func $rep (param i32) (result i32))) + (import "" "new" (func $new (param i32) (result i32))) + (import "" "drop" (func $drop (param i32))) + + (func $start + (local $r i32) + (local.set $r (call $new (i32.const 100))) + + (if (i32.ne (local.get $r) (i32.const 1)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r)) (i32.const 100)) (then (unreachable))) + + (call $drop (local.get $r)) + ) + + (start $start) + ) + (core instance (instantiate $m + (with "" (instance + (export "rep" (func $rep)) + (export "new" (func $new)) + (export "drop" (func $drop)) + )) + )) +) + +;; cannot call `resource.drop` on a nonexistent resource +(component + (type $r (resource (rep i32))) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "drop" (func $drop (param i32))) + + (func (export "r") + (call $drop (i32.const 0)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + )) + )) + + (func (export "r") (canon lift (core func $i "r"))) +) +(assert_trap (invoke "r") "unknown handle index 0") + +;; cannot call `resource.rep` on a nonexistent resource +(component + (type $r (resource (rep i32))) + (core func $rep (canon resource.rep $r)) + + (core module $m + (import "" "rep" (func $rep (param i32) (result i32))) + + (func (export "r") + (drop (call $rep (i32.const 0))) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "rep" (func $rep)) + )) + )) + + (func (export "r") (canon lift (core func $i "r"))) +) +(assert_trap (invoke "r") "unknown handle index 0") + +;; index reuse behavior of handles +(component + (type $r (resource (rep i32))) + (core func $rep (canon resource.rep $r)) + (core func $new (canon resource.new $r)) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "rep" (func $rep (param i32) (result i32))) + (import "" "new" (func $new (param i32) (result i32))) + (import "" "drop" (func $drop (param i32))) + + (func $start + (local $r1 i32) + (local $r2 i32) + (local $r3 i32) + (local $r4 i32) + + ;; resources assigned sequentially + (local.set $r1 (call $new (i32.const 100))) + (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) + + (local.set $r2 (call $new (i32.const 200))) + (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) + + (local.set $r3 (call $new (i32.const 300))) + (if (i32.ne (local.get $r3) (i32.const 3)) (then (unreachable))) + + ;; representations all look good + (if (i32.ne (call $rep (local.get $r1)) (i32.const 100)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r2)) (i32.const 200)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r3)) (i32.const 300)) (then (unreachable))) + + ;; reallocate r2 + (call $drop (local.get $r2)) + (local.set $r2 (call $new (i32.const 400))) + + ;; should have reused index 1 + (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) + + ;; representations all look good + (if (i32.ne (call $rep (local.get $r1)) (i32.const 100)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r2)) (i32.const 400)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r3)) (i32.const 300)) (then (unreachable))) + + ;; deallocate, then reallocate + (call $drop (local.get $r1)) + (call $drop (local.get $r2)) + (call $drop (local.get $r3)) + + (local.set $r1 (call $new (i32.const 500))) + (local.set $r2 (call $new (i32.const 600))) + (local.set $r3 (call $new (i32.const 700))) + + ;; representations all look good + (if (i32.ne (call $rep (local.get $r1)) (i32.const 500)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r2)) (i32.const 600)) (then (unreachable))) + (if (i32.ne (call $rep (local.get $r3)) (i32.const 700)) (then (unreachable))) + + ;; indices should be lifo + (if (i32.ne (local.get $r1) (i32.const 3)) (then (unreachable))) + (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) + (if (i32.ne (local.get $r3) (i32.const 1)) (then (unreachable))) + + ;; bump one more time + (local.set $r4 (call $new (i32.const 800))) + (if (i32.ne (local.get $r4) (i32.const 4)) (then (unreachable))) + + ;; deallocate everything + (call $drop (local.get $r1)) + (call $drop (local.get $r2)) + (call $drop (local.get $r3)) + (call $drop (local.get $r4)) + ) + + (start $start) + ) + (core instance (instantiate $m + (with "" (instance + (export "rep" (func $rep)) + (export "new" (func $new)) + (export "drop" (func $drop)) + )) + )) +) + +(assert_unlinkable + (component + (import "host" (instance + (export "missing" (type (sub resource))) + )) + ) + "was not found") +(assert_unlinkable + (component + (import "host" (instance + (export "return-three" (type (sub resource))) + )) + ) + "expected resource found func") + +;; all resources can be uniquely imported +(component + (import "host" (instance + (export "resource1" (type (sub resource))) + (export "resource2" (type (sub resource))) + (export "resource1-again" (type (sub resource))) + )) +) + +;; equality constraints also work +(component + (import "host" (instance + (export "resource1" (type $r1 (sub resource))) + (export "resource2" (type (sub resource))) + (export "resource1-again" (type (eq $r1))) + )) +) + +;; equality constraints are checked if resources are supplied +(assert_unlinkable + (component + (import "host" (instance + (export "resource1" (type (sub resource))) + (export "resource2" (type $r1 (sub resource))) + (export "resource1-again" (type (eq $r1))) + )) + ) + "mismatched resource types") + +;; equality constraints mean that types don't need to be supplied +(component + (import "host" (instance + (export "resource1" (type $r1 (sub resource))) + (export "resource2" (type (sub resource))) + (export "this-name-is-not-provided-in-the-wast-harness" (type (eq $r1))) + )) +) + +;; simple properties of handles +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + (export "[static]resource1.assert" (func (param "r" (own $r)) (param "rep" u32))) + )) + (alias export $host "resource1" (type $r)) + (alias export $host "[constructor]resource1" (func $ctor)) + (alias export $host "[static]resource1.assert" (func $assert)) + + (core func $drop (canon resource.drop $r)) + (core func $ctor (canon lower (func $ctor))) + (core func $assert (canon lower (func $assert))) + + (core module $m + (import "" "drop" (func $drop (param i32))) + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "assert" (func $assert (param i32 i32))) + + (func $start + (local $r1 i32) + (local $r2 i32) + (local.set $r1 (call $ctor (i32.const 100))) + (local.set $r2 (call $ctor (i32.const 200))) + + ;; assert r1/r2 are sequential + (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) + (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) + + ;; reallocate r1 and it should be reassigned the same index + (call $drop (local.get $r1)) + (local.set $r1 (call $ctor (i32.const 300))) + (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) + + ;; internal values should match + (call $assert (local.get $r1) (i32.const 300)) + (call $assert (local.get $r2) (i32.const 200)) + ) + + (start $start) + ) + (core instance (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + (export "ctor" (func $ctor)) + (export "assert" (func $assert)) + )) + )) +) + +;; Using an index that has never been valid is a trap +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[static]resource1.assert" (func (param "r" (own $r)) (param "rep" u32))) + )) + (alias export $host "resource1" (type $r)) + (alias export $host "[static]resource1.assert" (func $assert)) + (core func $assert (canon lower (func $assert))) + + (core module $m + (import "" "assert" (func $assert (param i32 i32))) + + (func (export "f") + (call $assert (i32.const 0) (i32.const 0)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "assert" (func $assert)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) +) + +(assert_trap (invoke "f") "unknown handle index") + +;; Using an index which was previously valid but no longer valid is also a trap. +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + (export "[static]resource1.assert" (func (param "r" (own $r)) (param "rep" u32))) + )) + (alias export $host "[constructor]resource1" (func $ctor)) + (alias export $host "[static]resource1.assert" (func $assert)) + + (core func $assert (canon lower (func $assert))) + (core func $ctor (canon lower (func $ctor))) + + (core module $m + (import "" "assert" (func $assert (param i32 i32))) + (import "" "ctor" (func $ctor (param i32) (result i32))) + + (global $handle (mut i32) i32.const 0) + + (func (export "f") + (global.set $handle (call $ctor (i32.const 100))) + (call $assert (global.get $handle) (i32.const 100)) + ) + + (func (export "f2") + (call $assert (global.get $handle) (i32.const 100)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "assert" (func $assert)) + (export "ctor" (func $ctor)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) + (func (export "f2") (canon lift (core func $i "f2"))) +) + +(assert_return (invoke "f")) +(assert_trap (invoke "f2") "unknown handle index") + +;; Also invalid to pass a previously valid handle to the drop intrinsic +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + )) + (alias export $host "resource1" (type $r)) + (alias export $host "[constructor]resource1" (func $ctor)) + + (core func $drop (canon resource.drop $r)) + (core func $ctor (canon lower (func $ctor))) + + (core module $m + (import "" "drop" (func $drop (param i32))) + (import "" "ctor" (func $ctor (param i32) (result i32))) + + (global $handle (mut i32) i32.const 0) + + (func (export "f") + (global.set $handle (call $ctor (i32.const 100))) + (call $drop (global.get $handle)) + ) + + (func (export "f2") + (call $drop (global.get $handle)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "ctor" (func $ctor)) + (export "drop" (func $drop)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) + (func (export "f2") (canon lift (core func $i "f2"))) +) + +(assert_return (invoke "f")) +(assert_trap (invoke "f2") "unknown handle index") + +;; If an inner component instantiates a resource then an outer component +;; should not implicitly have access to that resource. +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + )) + + ;; an inner component which upon instantiation will invoke the constructor, + ;; assert that it's zero, and then forget about it. + (component $inner + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + )) + (alias export $host "[constructor]resource1" (func $ctor)) + + (core func $ctor (canon lower (func $ctor))) + + (core module $m + (import "" "ctor" (func $ctor (param i32) (result i32))) + + (func $start + (if (i32.ne (call $ctor (i32.const 100)) (i32.const 0)) (then (unreachable))) + ) + ) + (core instance $i (instantiate $m + (with "" (instance (export "ctor" (func $ctor)))) + )) + ) + (instance $i (instantiate $inner (with "host" (instance $host)))) + + ;; the rest of this component which is a single function that invokes `drop` + ;; for index 0. The index 0 should be valid within the above component, but + ;; it is not valid within this component + (alias export $host "resource1" (type $r)) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "drop" (func $drop (param i32))) + + (func (export "f") + (call $drop (i32.const 0)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) +) + +(assert_trap (invoke "f") "unknown handle index") + +;; Same as the above test, but for resources defined within a component +(component + (component $inner + (type $r (resource (rep i32))) + + (core func $ctor (canon resource.new $r)) + + (core module $m + (import "" "ctor" (func $ctor (param i32) (result i32))) + + (func $start + (if (i32.ne (call $ctor (i32.const 100)) (i32.const 1)) (then (unreachable))) + ) + (start $start) + ) + (core instance $i (instantiate $m + (with "" (instance (export "ctor" (func $ctor)))) + )) + (export "r" (type $r)) + ) + (instance $i (instantiate $inner)) + + ;; the rest of this component which is a single function that invokes `drop` + ;; for index 1. The index 1 should be valid within the above component, but + ;; it is not valid within this component + (alias export $i "r" (type $r)) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "drop" (func $drop (param i32))) + + (func (export "f") + (call $drop (i32.const 1)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) +) + +(assert_trap (invoke "f") "unknown handle index 1") + +;; Each instantiation of a component generates a unique resource type, so +;; allocating in one component and deallocating in another should fail. +(component + (component $inner + (type $r (resource (rep i32))) + + (core func $ctor (canon resource.new $r)) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "drop" (func $drop (param i32))) + + (func (export "alloc") + (if (i32.ne (call $ctor (i32.const 100)) (i32.const 1)) (then (unreachable))) + ) + (func (export "dealloc") + (call $drop (i32.const 1)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "ctor" (func $ctor)) + (export "drop" (func $drop)) + )) + )) + (func (export "alloc") (canon lift (core func $i "alloc"))) + (func (export "dealloc") (canon lift (core func $i "dealloc"))) + ) + (instance $i1 (instantiate $inner)) + (instance $i2 (instantiate $inner)) + + (alias export $i1 "alloc" (func $alloc_in_1)) + (alias export $i1 "dealloc" (func $dealloc_in_1)) + (alias export $i2 "alloc" (func $alloc_in_2)) + (alias export $i2 "dealloc" (func $dealloc_in_2)) + + (export "alloc-in1" (func $alloc_in_1)) + (export "dealloc-in1" (func $dealloc_in_1)) + (export "alloc-in2" (func $alloc_in_2)) + (export "dealloc-in2" (func $dealloc_in_2)) +) + +(assert_return (invoke "alloc-in1")) +(assert_return (invoke "dealloc-in1")) +(assert_return (invoke "alloc-in1")) +(assert_return (invoke "alloc-in2")) +(assert_return (invoke "dealloc-in2")) +(assert_trap (invoke "dealloc-in2") "unknown handle index") + +;; Same as above, but the same host resource type is imported into a +;; component that is instantiated twice. Each component instance should +;; receive different tables tracking resources so a resource allocated in one +;; should not be visible in the other. +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + )) + (alias export $host "resource1" (type $r)) + (alias export $host "[constructor]resource1" (func $ctor)) + + (component $inner + (import "r" (type $r (sub resource))) + (import "[constructor]r" (func $ctor (param "r" u32) (result (own $r)))) + + (core func $ctor (canon lower (func $ctor))) + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "drop" (func $drop (param i32))) + + (func (export "alloc") + (if (i32.ne (call $ctor (i32.const 100)) (i32.const 1)) (then (unreachable))) + ) + (func (export "dealloc") + (call $drop (i32.const 1)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "ctor" (func $ctor)) + (export "drop" (func $drop)) + )) + )) + (func (export "alloc") (canon lift (core func $i "alloc"))) + (func (export "dealloc") (canon lift (core func $i "dealloc"))) + ) + (instance $i1 (instantiate $inner + (with "r" (type $r)) + (with "[constructor]r" (func $ctor)) + )) + (instance $i2 (instantiate $inner + (with "r" (type $r)) + (with "[constructor]r" (func $ctor)) + )) + + (alias export $i1 "alloc" (func $alloc_in_1)) + (alias export $i1 "dealloc" (func $dealloc_in_1)) + (alias export $i2 "alloc" (func $alloc_in_2)) + (alias export $i2 "dealloc" (func $dealloc_in_2)) + + (export "alloc-in1" (func $alloc_in_1)) + (export "dealloc-in1" (func $dealloc_in_1)) + (export "alloc-in2" (func $alloc_in_2)) + (export "dealloc-in2" (func $dealloc_in_2)) +) + +(assert_return (invoke "alloc-in1")) +(assert_return (invoke "dealloc-in1")) +(assert_return (invoke "alloc-in1")) +(assert_return (invoke "alloc-in2")) +(assert_return (invoke "dealloc-in2")) +(assert_trap (invoke "dealloc-in2") "unknown handle index") + +;; Multiple copies of intrinsics all work +(component + (type $r (resource (rep i32))) + + (core func $new1 (canon resource.new $r)) + (core func $new2 (canon resource.new $r)) + (core func $drop1 (canon resource.drop $r)) + (core func $drop2 (canon resource.drop $r)) + + (core module $m + (import "" "new1" (func $new1 (param i32) (result i32))) + (import "" "new2" (func $new2 (param i32) (result i32))) + (import "" "drop1" (func $drop1 (param i32))) + (import "" "drop2" (func $drop2 (param i32))) + + (func $start + ;; 2x2 matrix of pairing new/drop + (call $drop1 (call $new1 (i32.const 101))) + (call $drop2 (call $new1 (i32.const 102))) + (call $drop1 (call $new2 (i32.const 103))) + (call $drop2 (call $new2 (i32.const 104))) + + ;; should be referencing the same namespace + (if (i32.ne (call $new1 (i32.const 105)) (i32.const 1)) (then (unreachable))) + (if (i32.ne (call $new2 (i32.const 105)) (i32.const 2)) (then (unreachable))) + + ;; use different drops out of order + (call $drop2 (i32.const 1)) + (call $drop1 (i32.const 2)) + ) + + (start $start) + ) + + (core instance (instantiate $m + (with "" (instance + (export "new1" (func $new1)) + (export "new2" (func $new2)) + (export "drop1" (func $drop1)) + (export "drop2" (func $drop2)) + )) + )) +) + +;; u32::MAX isn't special in some weird way, it's just probably always invalid +;; because that's a lot of handles. +(component + (type $r (resource (rep i32))) + + (core func $drop (canon resource.drop $r)) + + (core module $m + (import "" "drop" (func $drop (param i32))) + + (func (export "f") + (call $drop (i32.const 0xffffffff)) + ) + ) + + (core instance $i (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + )) + )) + (func (export "f") (canon lift (core func $i "f"))) +) +(assert_trap (invoke "f") "unknown handle index") + +;; Test behavior of running a destructor for local resources +(component + (core module $m1 + (global $drops (mut i32) i32.const 0) + (global $last_drop (mut i32) i32.const -1) + + (func (export "dtor") (param i32) + (global.set $drops (i32.add (global.get $drops) (i32.const 1))) + (global.set $last_drop (local.get 0)) + ) + (func (export "drops") (result i32) global.get $drops) + (func (export "last-drop") (result i32) global.get $last_drop) + ) + (core instance $i1 (instantiate $m1)) + + (type $r1 (resource (rep i32))) + (type $r2 (resource (rep i32) (dtor (func $i1 "dtor")))) + + (core func $drop1 (canon resource.drop $r1)) + (core func $drop2 (canon resource.drop $r2)) + (core func $new1 (canon resource.new $r1)) + (core func $new2 (canon resource.new $r2)) + + (core module $m2 + (import "" "drop1" (func $drop1 (param i32))) + (import "" "drop2" (func $drop2 (param i32))) + (import "" "new1" (func $new1 (param i32) (result i32))) + (import "" "new2" (func $new2 (param i32) (result i32))) + (import "i1" "drops" (func $drops (result i32))) + (import "i1" "last-drop" (func $last-drop (result i32))) + + (func $start + (local $r1 i32) + (local $r2 i32) + + (local.set $r1 (call $new1 (i32.const 100))) + (local.set $r2 (call $new2 (i32.const 200))) + + ;; indexes start at 1 and while they have distinct types they should be + ;; within the same table. + (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) + (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) + + ;; nothing should be dropped yet + (if (i32.ne (call $drops) (i32.const 0)) (then (unreachable))) + (if (i32.ne (call $last-drop) (i32.const -1)) (then (unreachable))) + + ;; dropping a resource without a destructor is ok, but shouldn't tamper + ;; with anything. + (call $drop1 (local.get $r1)) + (if (i32.ne (call $drops) (i32.const 0)) (then (unreachable))) + (if (i32.ne (call $last-drop) (i32.const -1)) (then (unreachable))) + + ;; drop r2 which should record a drop and additionally record the private + ;; representation value which was dropped + (call $drop2 (local.get $r2)) + (if (i32.ne (call $drops) (i32.const 1)) (then (unreachable))) + (if (i32.ne (call $last-drop) (i32.const 200)) (then (unreachable))) + + ;; do it all over again + (local.set $r2 (call $new2 (i32.const 300))) + (call $drop2 (local.get $r2)) + (if (i32.ne (call $drops) (i32.const 2)) (then (unreachable))) + (if (i32.ne (call $last-drop) (i32.const 300)) (then (unreachable))) + ) + + (start $start) + ) + + (core instance $i2 (instantiate $m2 + (with "" (instance + (export "drop1" (func $drop1)) + (export "drop2" (func $drop2)) + (export "new1" (func $new1)) + (export "new2" (func $new2)) + )) + (with "i1" (instance $i1)) + )) +) + +;; Test dropping a host resource +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + (export "[static]resource1.last-drop" (func (result u32))) + (export "[static]resource1.drops" (func (result u32))) + )) + + (alias export $host "resource1" (type $r)) + (alias export $host "[constructor]resource1" (func $ctor)) + (alias export $host "[static]resource1.last-drop" (func $last-drop)) + (alias export $host "[static]resource1.drops" (func $drops)) + + (core func $drop (canon resource.drop $r)) + (core func $ctor (canon lower (func $ctor))) + (core func $last-drop (canon lower (func $last-drop))) + (core func $drops (canon lower (func $drops))) + + (core module $m + (import "" "drop" (func $drop (param i32))) + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "last-drop" (func $last-drop (result i32))) + (import "" "drops" (func $raw-drops (result i32))) + + (global $init-drop-cnt (mut i32) i32.const 0) + + (func $drops (result i32) + (i32.sub (call $raw-drops) (global.get $init-drop-cnt)) + ) + + (func $start + (local $r1 i32) + (global.set $init-drop-cnt (call $raw-drops)) + + (local.set $r1 (call $ctor (i32.const 100))) + + ;; should be no drops yet + (if (i32.ne (call $drops) (i32.const 0)) (then (unreachable))) + + ;; should count a drop + (call $drop (local.get $r1)) + (if (i32.ne (call $drops) (i32.const 1)) (then (unreachable))) + (if (i32.ne (call $last-drop) (i32.const 100)) (then (unreachable))) + + ;; do it again to be sure + (local.set $r1 (call $ctor (i32.const 200))) + (call $drop (local.get $r1)) + (if (i32.ne (call $drops) (i32.const 2)) (then (unreachable))) + (if (i32.ne (call $last-drop) (i32.const 200)) (then (unreachable))) + ) + + (start $start) + ) + (core instance (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + (export "ctor" (func $ctor)) + (export "last-drop" (func $last-drop)) + (export "drops" (func $drops)) + )) + )) +) + +;; Test some bare-bones basics of borrowed resources +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + (export "[method]resource1.simple" (func (param "self" (borrow $r)) (param "rep" u32))) + (export "[method]resource1.take-borrow" (func (param "self" (borrow $r)) (param "b" (borrow $r)))) + (export "[method]resource1.take-own" (func (param "self" (borrow $r)) (param "b" (own $r)))) + )) + + (alias export $host "resource1" (type $r)) + (alias export $host "[constructor]resource1" (func $ctor)) + (alias export $host "[method]resource1.simple" (func $simple)) + (alias export $host "[method]resource1.take-borrow" (func $take-borrow)) + (alias export $host "[method]resource1.take-own" (func $take-own)) + + (core func $drop (canon resource.drop $r)) + (core func $ctor (canon lower (func $ctor))) + (core func $simple (canon lower (func $simple))) + (core func $take-own (canon lower (func $take-own))) + (core func $take-borrow (canon lower (func $take-borrow))) + + (core module $m + (import "" "drop" (func $drop (param i32))) + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "simple" (func $simple (param i32 i32))) + (import "" "take-own" (func $take-own (param i32 i32))) + (import "" "take-borrow" (func $take-borrow (param i32 i32))) + + + (func $start + (local $r1 i32) + (local $r2 i32) + (local.set $r1 (call $ctor (i32.const 100))) + (local.set $r2 (call $ctor (i32.const 200))) + + (call $simple (local.get $r1) (i32.const 100)) + (call $simple (local.get $r1) (i32.const 100)) + (call $simple (local.get $r2) (i32.const 200)) + (call $simple (local.get $r1) (i32.const 100)) + (call $simple (local.get $r2) (i32.const 200)) + (call $simple (local.get $r2) (i32.const 200)) + + (call $drop (local.get $r1)) + (call $drop (local.get $r2)) + + + (local.set $r1 (call $ctor (i32.const 200))) + (local.set $r2 (call $ctor (i32.const 300))) + (call $take-borrow (local.get $r1) (local.get $r2)) + (call $take-borrow (local.get $r2) (local.get $r1)) + (call $take-borrow (local.get $r1) (local.get $r1)) + (call $take-borrow (local.get $r2) (local.get $r2)) + + (call $take-own (local.get $r1) (call $ctor (i32.const 400))) + (call $take-own (local.get $r2) (call $ctor (i32.const 500))) + (call $take-own (local.get $r2) (local.get $r1)) + (call $drop (local.get $r2)) + + ;; table should be empty at this point, so a fresh allocation should get + ;; index 0 + (if (i32.ne (call $ctor (i32.const 600)) (i32.const 1)) (then (unreachable))) + ) + + (start $start) + ) + (core instance (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + (export "ctor" (func $ctor)) + (export "simple" (func $simple)) + (export "take-own" (func $take-own)) + (export "take-borrow" (func $take-borrow)) + )) + )) +) + +;; Cannot pass out an owned resource when it's borrowed by the same call +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) + (export "[method]resource1.take-own" (func (param "self" (borrow $r)) (param "b" (own $r)))) + )) + + (alias export $host "resource1" (type $r)) + (alias export $host "[constructor]resource1" (func $ctor)) + (alias export $host "[method]resource1.take-own" (func $take-own)) + + (core func $drop (canon resource.drop $r)) + (core func $ctor (canon lower (func $ctor))) + (core func $take-own (canon lower (func $take-own))) + + (core module $m + (import "" "drop" (func $drop (param i32))) + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "take-own" (func $take-own (param i32 i32))) + + + (func (export "f") + (local $r i32) + (local.set $r (call $ctor (i32.const 100))) + (call $take-own (local.get $r) (local.get $r)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + (export "ctor" (func $ctor)) + (export "take-own" (func $take-own)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) +) + +(assert_trap (invoke "f") "cannot remove owned resource while borrowed") + +;; Borrows must actually exist +(component + (import "host" (instance $host + (export "resource1" (type $r (sub resource))) + (export "[method]resource1.simple" (func (param "self" (borrow $r)) (param "b" u32))) + )) + + (alias export $host "resource1" (type $r)) + (alias export $host "[method]resource1.simple" (func $simple)) + + (core func $drop (canon resource.drop $r)) + (core func $simple (canon lower (func $simple))) + + (core module $m + (import "" "drop" (func $drop (param i32))) + (import "" "simple" (func $simple (param i32 i32))) + + + (func (export "f") + (call $simple (i32.const 0) (i32.const 0)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "drop" (func $drop)) + (export "simple" (func $simple)) + )) + )) + + (func (export "f") (canon lift (core func $i "f"))) +) + +(assert_trap (invoke "f") "unknown handle index 0") + +(component + (component $A + (type $t' (resource (rep i32))) + (export $t "t" (type $t')) + + (core func $ctor (canon resource.new $t)) + (core func $dtor (canon resource.drop $t)) + (core func $rep (canon resource.rep $t)) + + (core module $m + (import "" "dtor" (func $dtor (param i32))) + (import "" "rep" (func $rep (param i32) (result i32))) + + (func (export "[method]t.assert") (param i32 i32) + (if (i32.ne (local.get 0) (local.get 1)) (then (unreachable))) + ) + (func (export "[static]t.assert-own") (param i32 i32) + (if (i32.ne (call $rep (local.get 0)) (local.get 1)) (then (unreachable))) + (call $dtor (local.get 0)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "dtor" (func $dtor)) + (export "rep" (func $rep)) + )) + )) + (func (export "[constructor]t") (param "x" u32) (result (own $t)) + (canon lift (core func $ctor))) + (func (export "[method]t.assert") (param "self" (borrow $t)) (param "x" u32) + (canon lift (core func $i "[method]t.assert"))) + (func (export "[static]t.assert-own") (param "self" (own $t)) (param "x" u32) + (canon lift (core func $i "[static]t.assert-own"))) + ) + (instance $a (instantiate $A)) + + (component $B + (import "a" (instance $i + (export "t" (type $t (sub resource))) + (export "[constructor]t" (func (param "x" u32) (result (own $t)))) + (export "[method]t.assert" (func (param "self" (borrow $t)) (param "x" u32))) + (export "[static]t.assert-own" (func (param "self" (own $t)) (param "x" u32))) + )) + + (alias export $i "t" (type $t)) + (alias export $i "[constructor]t" (func $ctor)) + (alias export $i "[method]t.assert" (func $assert-borrow)) + (alias export $i "[static]t.assert-own" (func $assert-own)) + + (core func $ctor (canon lower (func $ctor))) + (core func $dtor (canon resource.drop $t)) + (core func $assert-own (canon lower (func $assert-own))) + (core func $assert-borrow (canon lower (func $assert-borrow))) + + (core module $m + (import "" "ctor" (func $ctor (param i32) (result i32))) + (import "" "dtor" (func $dtor (param i32))) + (import "" "assert-own" (func $assert-own (param i32 i32))) + (import "" "assert-borrow" (func $assert-borrow (param i32 i32))) + + (func (export "f") + (local $r1 i32) + (local $r2 i32) + + (local.set $r1 (call $ctor (i32.const 100))) + (local.set $r2 (call $ctor (i32.const 200))) + + (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) + (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) + + (call $assert-borrow (local.get $r2) (i32.const 200)) + (call $assert-borrow (local.get $r1) (i32.const 100)) + + (call $assert-own (local.get $r2) (i32.const 200)) + (call $dtor (local.get $r1)) + ) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "ctor" (func $ctor)) + (export "dtor" (func $dtor)) + (export "assert-own" (func $assert-own)) + (export "assert-borrow" (func $assert-borrow)) + )) + )) + (func (export "f") (canon lift (core func $i "f"))) + ) + (instance $b (instantiate $B (with "a" (instance $a)))) + (export "f" (func $b "f")) +) + +(assert_return (invoke "f")) + +;; Test destructor behavior when using the wrong resource type +(component definition $C + (type $r1 (resource (rep i32))) + (type $r2 (resource (rep i32))) + + (core func $drop1 (canon resource.drop $r1)) + (core func $drop2 (canon resource.drop $r2)) + (core func $new1 (canon resource.new $r1)) + (core func $new2 (canon resource.new $r2)) + + (core module $m2 + (import "" "drop1" (func $drop1 (param i32))) + (import "" "drop2" (func $drop2 (param i32))) + (import "" "new1" (func $new1 (param i32) (result i32))) + (import "" "new2" (func $new2 (param i32) (result i32))) + + (func (export "drop-r1-as-r2") (call $drop2 (call $new1 (i32.const 100)))) + (func (export "return-r1-as-r2") (result i32) (call $new1 (i32.const 100))) + ) + + (core instance $i2 (instantiate $m2 + (with "" (instance + (export "drop1" (func $drop1)) + (export "drop2" (func $drop2)) + (export "new1" (func $new1)) + (export "new2" (func $new2)) + )) + )) + + (export $r2' "r2" (type $r2)) + (func (export "drop-r1-as-r2") (canon lift (core func $i2 "drop-r1-as-r2"))) + (func (export "return-r1-as-r2") (result (own $r2')) (canon lift (core func $i2 "return-r1-as-r2"))) +) + +(component instance $C1 $C) +(assert_trap (invoke "drop-r1-as-r2") "handle index 1 used with the wrong type, expected guest-defined resource but found a different guest-defined resource") +(component instance $C1 $C) +(assert_trap (invoke "return-r1-as-r2") "handle index 1 used with the wrong type, expected guest-defined resource but found a different guest-defined resource") diff --git a/test/wasmtime/restrictions.wast b/test/wasmtime/restrictions.wast new file mode 100644 index 00000000..9bd53e7e --- /dev/null +++ b/test/wasmtime/restrictions.wast @@ -0,0 +1,22 @@ +(assert_invalid + (component (import "x" (component))) + "root-level component imports are not supported") + +(assert_invalid + (component (component (export "x"))) + "exporting a component from the root component is not supported") + +(assert_invalid + (component + (import "f" (func $f)) + (export "f" (func $f)) + ) + "component export `f` is a reexport of an imported function which is not implemented") + +(assert_invalid + (component + (import "x" (component + (export "x" (type (sub resource))) + )) + ) + "root-level component imports are not supported") diff --git a/test/wasmtime/simple.wast b/test/wasmtime/simple.wast new file mode 100644 index 00000000..7bf2ab1e --- /dev/null +++ b/test/wasmtime/simple.wast @@ -0,0 +1,42 @@ +(component) + +(component + (core module) +) + +(component + (core module) + (core module) + (core module) +) + +(component + (core module + (func (export "a") (result i32) i32.const 0) + (func (export "b") (result i64) i64.const 0) + ) + (core module + (func (export "c") (result f32) f32.const 0) + (func (export "d") (result f64) f64.const 0) + ) +) + +(assert_invalid + (component + (import "a" (component)) + ) + "root-level component imports are not supported") + +(assert_invalid + (component + (component (export "a")) + ) + "exporting a component from the root component is not supported") + +(component + (core module $m (func (export ""))) + (core instance $m (instantiate $m)) + (func (export "a") (canon lift (core func $m ""))) +) + +(assert_return (invoke "a")) diff --git a/test/wasmtime/strings.wast b/test/wasmtime/strings.wast new file mode 100644 index 00000000..e53caa35 --- /dev/null +++ b/test/wasmtime/strings.wast @@ -0,0 +1,110 @@ +;;! multi_memory = true + +;; unaligned utf16 string +(assert_trap + (component + (component $c + (core module $m + (func (export "") (param i32 i32)) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) i32.const 0) + (memory (export "memory") 1) + ) + (core instance $m (instantiate $m)) + (func (export "a") (param "a" string) + (canon lift (core func $m "") (realloc (func $m "realloc")) (memory $m "memory")) + ) + ) + + (component $c2 + (import "a" (func $f (param "a" string))) + (core module $libc + (memory (export "memory") 1) + ) + (core instance $libc (instantiate $libc)) + (core func $f (canon lower (func $f) string-encoding=utf16 (memory $libc "memory"))) + (core module $m + (import "" "" (func $f (param i32 i32))) + + (func $start (call $f (i32.const 1) (i32.const 0))) + (start $start) + ) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + + (instance $c (instantiate $c)) + (instance $c2 (instantiate $c2 (with "a" (func $c "a")))) + ) + "unreachable") + +;; unaligned latin1+utf16 string, even with the latin1 encoding +(assert_trap + (component + (component $c + (core module $m + (func (export "") (param i32 i32)) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) i32.const 0) + (memory (export "memory") 1) + ) + (core instance $m (instantiate $m)) + (func (export "a") (param "a" string) + (canon lift (core func $m "") (realloc (func $m "realloc")) (memory $m "memory")) + ) + ) + + (component $c2 + (import "a" (func $f (param "a" string))) + (core module $libc + (memory (export "memory") 1) + ) + (core instance $libc (instantiate $libc)) + (core func $f (canon lower (func $f) string-encoding=latin1+utf16 (memory $libc "memory"))) + (core module $m + (import "" "" (func $f (param i32 i32))) + + (func $start (call $f (i32.const 1) (i32.const 0))) + (start $start) + ) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + + (instance $c (instantiate $c)) + (instance $c2 (instantiate $c2 (with "a" (func $c "a")))) + ) + "unreachable") + +;; out of bounds utf8->utf8 string +(assert_trap + (component + (component $c + (core module $m + (func (export "") (param i32 i32)) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) i32.const 0) + (memory (export "memory") 1) + ) + (core instance $m (instantiate $m)) + (func (export "a") (param "a" string) + (canon lift (core func $m "") (realloc (func $m "realloc")) (memory $m "memory") + string-encoding=utf8) + ) + ) + + (component $c2 + (import "a" (func $f (param "a" string))) + (core module $libc + (memory (export "memory") 1) + ) + (core instance $libc (instantiate $libc)) + (core func $f (canon lower (func $f) string-encoding=utf8 (memory $libc "memory"))) + (core module $m + (import "" "" (func $f (param i32 i32))) + + (func $start (call $f (i32.const 0x8000_0000) (i32.const 1))) + (start $start) + ) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + + (instance $c (instantiate $c)) + (instance $c2 (instantiate $c2 (with "a" (func $c "a")))) + ) + "unreachable") diff --git a/test/wasmtime/tags.wast b/test/wasmtime/tags.wast new file mode 100644 index 00000000..cac1fdec --- /dev/null +++ b/test/wasmtime/tags.wast @@ -0,0 +1,14 @@ +;;! exceptions = true + +(component + (core module $a (tag (export "t"))) + (core module $b (import "a" "t" (tag))) + + (core instance $a (instantiate $a)) + (core instance (instantiate $b (with "a" (instance $a)))) + (core instance (instantiate $b + (with "a" (instance + (export "t" (tag $a "t")) + )) + )) +) diff --git a/test/wasmtime/types.wast b/test/wasmtime/types.wast new file mode 100644 index 00000000..9596ebe6 --- /dev/null +++ b/test/wasmtime/types.wast @@ -0,0 +1,355 @@ +(component + (type string) + (type (func (param "a" string))) + (type $r (record (field "x" (result)) (field "y" string))) + (type $u (variant (case "r" $r) (case "s" string))) + (type $e (result $u (error u32))) + (type (result $u)) + (type (result (error $u))) + (type (result)) + + (type (func (param "a" $e) (result (option $r)))) + + (type (variant + (case "a" string) + (case "b" u32) + (case "c" float32) + (case "d" float64) + )) + + (type $errno (enum "a" "b" "e")) + (type (list $errno)) + (type $oflags (flags "read" "write" "exclusive")) + (type (tuple $oflags $errno $r)) + + ;; primitives in functions + (type (func + (param "a" bool) + (param "b" u8) + (param "c" s8) + (param "d" u16) + (param "e" s16) + (param "f" u32) + (param "g" s32) + (param "h" u64) + (param "i" s64) + (param "j" char) + (param "k" string) + )) + + ;; primitives in types + (type bool) + (type u8) + (type s8) + (type u16) + (type s16) + (type u32) + (type s32) + (type u64) + (type s64) + (type char) + (type string) +) + +(component + (type $empty (func)) + (type (func (param "a" string) (result u32))) + (type (component)) + (core type (module)) + (core type (func)) + (type (instance)) + + (type (component + (import "x" (func (type $empty))) + (import "y" (func)) + (import "z" (component)) + + (type $t (instance)) + + (export "a" (core module)) + (export "b" (instance (type $t))) + )) + + (type (instance + (export "x" (func (type $empty))) + (export "y" (func)) + (export "z" (component)) + + (type $t (instance)) + + (export "a" (core module)) + (export "b" (instance (type $t))) + )) + + (core type (module + (import "" "" (func (param i32))) + (import "" "1" (func (result i32))) + (export "1" (global i32)) + (export "2" (memory 1)) + (export "3" (table 1 funcref)) + )) +) + +;; outer core aliases work +(component $C + (core type $f (func)) + (core type $m (module)) + + (component $C2 + (alias outer $C $f (core type $my_f)) + (import "a" (core module (type $m))) + (import "x" (core module + (alias outer $C2 $my_f (type $my_f)) + (import "" "1" (func (type $my_f))) + )) + ) +) + +;; type exports work +(component $C + (component $C2 + (type string) + (export "x" (type 0)) + ) + (instance (instantiate 0)) + (alias export 0 "x" (type)) + (export "x" (type 0)) +) + +(component + (core module $m (func (export "") (param i32) (result i32) local.get 0)) + (core instance $m (instantiate $m)) + (func (export "i-to-b") (param "a" u32) (result bool) (canon lift (core func $m ""))) + (func (export "i-to-u8") (param "a" u32) (result u8) (canon lift (core func $m ""))) + (func (export "i-to-s8") (param "a" u32) (result s8) (canon lift (core func $m ""))) + (func (export "i-to-u16") (param "a" u32) (result u16) (canon lift (core func $m ""))) + (func (export "i-to-s16") (param "a" u32) (result s16) (canon lift (core func $m ""))) +) +(assert_return (invoke "i-to-b" (u32.const 0)) (bool.const false)) +(assert_return (invoke "i-to-b" (u32.const 1)) (bool.const true)) +(assert_return (invoke "i-to-b" (u32.const 2)) (bool.const true)) +(assert_return (invoke "i-to-u8" (u32.const 0x00)) (u8.const 0)) +(assert_return (invoke "i-to-u8" (u32.const 0x01)) (u8.const 1)) +(assert_return (invoke "i-to-u8" (u32.const 0xf01)) (u8.const 1)) +(assert_return (invoke "i-to-u8" (u32.const 0xf00)) (u8.const 0)) +(assert_return (invoke "i-to-s8" (u32.const 0xffffffff)) (s8.const -1)) +(assert_return (invoke "i-to-s8" (u32.const 127)) (s8.const 127)) +(assert_return (invoke "i-to-u16" (u32.const 0)) (u16.const 0)) +(assert_return (invoke "i-to-u16" (u32.const 1)) (u16.const 1)) +(assert_return (invoke "i-to-u16" (u32.const 0xffffffff)) (u16.const 0xffff)) +(assert_return (invoke "i-to-s16" (u32.const 0)) (s16.const 0)) +(assert_return (invoke "i-to-s16" (u32.const 1)) (s16.const 1)) +(assert_return (invoke "i-to-s16" (u32.const 0xffffffff)) (s16.const -1)) + +(assert_invalid + (component + (type $t1 string) + (type $t2 (list $t1)) + (type $t3 (list $t2)) + (type $t4 (list $t3)) + (type $t5 (list $t4)) + (type $t6 (list $t5)) + (type $t7 (list $t6)) + (type $t8 (list $t7)) + (type $t9 (list $t8)) + (type $t10 (list $t9)) + (type $t11 (list $t10)) + (type $t12 (list $t11)) + (type $t13 (list $t12)) + (type $t14 (list $t13)) + (type $t15 (list $t14)) + (type $t16 (list $t15)) + (type $t17 (list $t16)) + (type $t18 (list $t17)) + (type $t19 (list $t18)) + (type $t20 (list $t19)) + (type $t21 (list $t20)) + (type $t22 (list $t21)) + (type $t23 (list $t22)) + (type $t24 (list $t23)) + (type $t25 (list $t24)) + (type $t26 (list $t25)) + (type $t27 (list $t26)) + (type $t28 (list $t27)) + (type $t29 (list $t28)) + (type $t30 (list $t29)) + (type $t31 (list $t30)) + (type $t32 (list $t31)) + (type $t33 (list $t32)) + (type $t34 (list $t33)) + (type $t35 (list $t34)) + (type $t36 (list $t35)) + (type $t37 (list $t36)) + (type $t38 (list $t37)) + (type $t39 (list $t38)) + (type $t40 (list $t39)) + (type $t41 (list $t40)) + (type $t42 (list $t41)) + (type $t43 (list $t42)) + (type $t44 (list $t43)) + (type $t45 (list $t44)) + (type $t46 (list $t45)) + (type $t47 (list $t46)) + (type $t48 (list $t47)) + (type $t49 (list $t48)) + (type $t50 (list $t49)) + (type $t51 (list $t50)) + (type $t52 (list $t51)) + (type $t53 (list $t52)) + (type $t54 (list $t53)) + (type $t55 (list $t54)) + (type $t56 (list $t55)) + (type $t57 (list $t56)) + (type $t58 (list $t57)) + (type $t59 (list $t58)) + (type $t60 (list $t59)) + (type $t61 (list $t60)) + (type $t62 (list $t61)) + (type $t63 (list $t62)) + (type $t64 (list $t63)) + (type $t65 (list $t64)) + (type $t66 (list $t65)) + (type $t67 (list $t66)) + (type $t68 (list $t67)) + (type $t69 (list $t68)) + (type $t70 (list $t69)) + (type $t71 (list $t70)) + (type $t72 (list $t71)) + (type $t73 (list $t72)) + (type $t74 (list $t73)) + (type $t75 (list $t74)) + (type $t76 (list $t75)) + (type $t77 (list $t76)) + (type $t78 (list $t77)) + (type $t79 (list $t78)) + (type $t80 (list $t79)) + (type $t81 (list $t80)) + (type $t82 (list $t81)) + (type $t83 (list $t82)) + (type $t84 (list $t83)) + (type $t85 (list $t84)) + (type $t86 (list $t85)) + (type $t87 (list $t86)) + (type $t88 (list $t87)) + (type $t89 (list $t88)) + (type $t90 (list $t89)) + (type $t91 (list $t90)) + (type $t92 (list $t91)) + (type $t93 (list $t92)) + (type $t94 (list $t93)) + (type $t95 (list $t94)) + (type $t96 (list $t95)) + (type $t97 (list $t96)) + (type $t98 (list $t97)) + (type $t99 (list $t98)) + (type $t100 (list $t99)) + (type $t101 (list $t100)) + (export "t" (type $t101)) + ) + "type nesting is too deep") + +(component + (type (instance + (export "x" (instance $x + (type $t u32) + (export "y" (type (eq $t))) + )) + (alias export $x "y" (type $t)) + (export "my-y" (type (eq $t))) + )) + + (type (component + (import "x" (instance $x + (type $t u32) + (export "y" (type (eq $t))) + )) + (alias export $x "y" (type $t)) + (export "my-y" (type (eq $t))) + )) +) + +(component + (type $t u32) + (export $t2 "t" (type $t)) + (type $r (record (field "x" $t2))) + (export "r" (type $r)) +) + +(component + (component + (import "x" (instance $i + (type $i u32) + (export "i" (type (eq $i))) + )) + (alias export $i "i" (type $i)) + (export "i" (type $i)) + ) +) + +(component + (type $u u32) + (instance $i + (export "i" (type $u)) + ) + (alias export $i "i" (type $i)) + (export "i" (type $i)) +) + +(component + (component $c + (type $t u32) + (export "t" (type $t)) + ) + (instance $c (instantiate $c)) + (export "i" (type $c "t")) +) + +(component + (component $c + (import "x" (component $c + (type $t u32) + (export "t" (type (eq $t))) + )) + (instance $c (instantiate $c)) + (export "i" (type $c "t")) + ) + + (component $x + (type $t u32) + (export "t" (type $t)) + ) + + (instance $c (instantiate $c (with "x" (component $x)))) +) + +(component + (type $t1 u64) + (import "a" (type $t2 (eq $t1))) + (import "b" (type $t3 (eq $t2))) +) + +(component + (import "a" (instance + (type $t1 u64) + (export "a" (type $t2 (eq $t1))) + (export "b" (type (eq $t2))) + )) +) + +(component + (type (export "x") (component + (type $t' (instance + (export "r" (type (sub resource))) + )) + (export "t" (instance $t (type $t'))) + )) +) + +(component + (type (export "x") (instance + (type $t' (instance + (export "r" (type (sub resource))) + )) + (export "t" (instance $t (type $t'))) + )) +)