Files
wasmtime/tests/misc_testsuite/component-model/modules.wast
Alex Crichton b49c5c878e Implement module imports into components (#4208)
* Implement module imports into components

As a step towards implementing function imports into a component this
commit implements importing modules into a component. This fills out
missing pieces of functionality such as exporting modules as well. The
previous translation code had initial support for translating imported
modules but some of the AST type information was restructured with
feedback from this implementation, namely splitting the
`InstantiateModule` initializer into separate upvar/import variants to
clarify that the item orderings for imports are resolved differently at
runtime.

Much of this commit is also adding infrastructure for any imports at all
into a component. For example a `Linker` type (analagous to
`wasmtime::Linker`) was added here as well. For now this type is quite
limited due to the inability to define host functions (it can only work
with instances and instances-of-modules) but it's enough to start
writing `*.wast` tests which exercise lots of module-related functionality.

* Fix a warning
2022-06-03 09:33:18 -05:00

478 lines
9.9 KiB
Plaintext

(component $foo
(module (export "a-module"))
)
;; the above instance can be imported into this component
(component
(import "foo" (instance
(export "a-module" (module))
))
)
;; specifying extra imports is ok
(component
(import "foo" (instance
(export "a-module" (module
(import "foo" "bar" (func))
))
))
)
;; specifying extra exports is not ok
(assert_unlinkable
(component
(import "foo" (instance
(export "a-module" (module
(export "the-export" (func))
))
))
)
"module export `the-export` not defined")
(component $foo
(module (export "a-module")
(import "env" "something" (func))
)
)
;; imports must be specified
(assert_unlinkable
(component
(import "foo" (instance
(export "a-module" (module))
))
)
"module import `env::something` not defined")
(component
(import "foo" (instance
(export "a-module" (module
(import "env" "something" (func))
))
))
)
;; extra imports still ok
(component
(import "foo" (instance
(export "a-module" (module
(import "env" "something" (func))
(import "env" "other" (global i32))
))
))
)
(component $foo
(module (export "a-module")
(func (export "f"))
)
)
;; dropping exports is ok
(component
(import "foo" (instance
(export "a-module" (module))
))
)
(component
(import "foo" (instance
(export "a-module" (module
(export "f" (func))
))
))
)
(assert_unlinkable
(component
(import "foo" (instance
(export "a-module" (module
(export "f" (func (param i32)))
))
))
)
"expected func of type `(i32) -> ()`, found func of type `() -> ()`")
(assert_unlinkable
(component
(import "foo" (instance
(export "a-module" (module
(export "f" (global i32))
))
))
)
"expected global found func")
(component $foo
(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" (module (export "f" (global i32))))
))
)
"expected global found func")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "t" (func))))
))
)
"expected func found table")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "m" (func))))
))
)
"expected func found memory")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "g" (func))))
))
)
"expected func found global")
;; wrong item type
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "f" (func (param i32)))))
))
)
"export `f` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "t" (table 1 externref))))
))
)
"export `t` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "t" (table 2 funcref))))
))
)
"export `t` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "m" (memory 2))))
))
)
"export `m` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "g" (global f32))))
))
)
"export `g` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (export "g" (global (mut i32)))))
))
)
"export `g` has the wrong type")
;; subtyping ok
(component
(import "foo" (instance
(export "m" (module
(export "t" (table 0 funcref))
(export "m" (memory 0))
))
))
)
(component $foo
(module (export "f") (func (import "" "")))
(module (export "t") (table (import "" "") 1 funcref))
(module (export "m") (memory (import "" "") 1))
(module (export "g") (global (import "" "") i32))
)
;; wrong class of item
(assert_unlinkable
(component
(import "foo" (instance
(export "f" (module (import "" "" (global i32))))
))
)
"expected func found global")
(assert_unlinkable
(component
(import "foo" (instance
(export "t" (module (import "" "" (func))))
))
)
"expected table found func")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (import "" "" (func))))
))
)
"expected memory found func")
(assert_unlinkable
(component
(import "foo" (instance
(export "g" (module (import "" "" (func))))
))
)
"expected global found func")
;; wrong item type
(assert_unlinkable
(component
(import "foo" (instance
(export "f" (module (import "" "" (func (param i32)))))
))
)
"module import `::` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "t" (module (import "" "" (table 1 externref))))
))
)
"module import `::` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "t" (module (import "" "" (table 0 funcref))))
))
)
"module import `::` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "m" (module (import "" "" (memory 0))))
))
)
"module import `::` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "g" (module (import "" "" (global f32))))
))
)
"module import `::` has the wrong type")
(assert_unlinkable
(component
(import "foo" (instance
(export "g" (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" (module (import "" "" (table 2 funcref))))
(export "m" (module (import "" "" (memory 2))))
))
)
;; An instance can reexport a module, define a module, and everything can be
;; used by something else
(component $src
(module (export "m")
(global (export "g") i32 i32.const 2)
)
)
(component $reexport
(module $m1
(global (export "g") i32 i32.const 1)
)
(import "src" (instance $src
(export "m" (module (export "g" (global i32))))
))
(module $m3
(global (export "g") i32 i32.const 3)
)
(export "m1" (module $m1))
(export "m2" (module $src "m"))
(export "m3" (module $m3))
)
(component
(type $modulety (module (export "g" (global i32))))
(import "reexport" (instance $reexport
(export "m1" (module (type $modulety)))
(export "m2" (module (type $modulety)))
(export "m3" (module (type $modulety)))
))
(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)
)
(instance $m1 (instantiate (module $reexport "m1")))
(instance $m2 (instantiate (module $reexport "m2")))
(instance $m3 (instantiate (module $reexport "m3")))
(instance (instantiate (module $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
(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" (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))
))
))
(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))
)
(instance $imports (instantiate (module $imports)))
(instance $m (instantiate (module $provider "m")
(with "" (instance $imports))
))
(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)
)
(instance (instantiate (module $import_globals) (with "" (instance $m))))
)