Initial skeleton of some component model processing (#4005)
* Initial skeleton of some component model processing This commit is the first of what will likely be many to implement the component model proposal in Wasmtime. This will be structured as a series of incremental commits, most of which haven't been written yet. My hope is to make this incremental and over time to make this easier to review and easier to test each step in isolation. Here much of the skeleton of how components are going to work in Wasmtime is sketched out. This is not a complete implementation of the component model so it's not all that useful yet, but some things you can do are: * Process the type section into a representation amenable for working with in Wasmtime. * Process the module section and register core wasm modules. * Process the instance section for core wasm modules. * Process core wasm module imports. * Process core wasm instance aliasing. * Ability to compile a component with core wasm embedded. * Ability to instantiate a component with no imports. * Ability to get functions from this component. This is already starting to diverge from the previous module linking representation where a `Component` will try to avoid unnecessary metadata about the component and instead internally only have the bare minimum necessary to instantiate the module. My hope is we can avoid constructing most of the index spaces during instantiation only for it to all ge thrown away. Additionally I'm predicting that we'll need to see through processing where possible to know how to generate adapters and where they are fused. At this time you can't actually call a component's functions, and that's the next PR that I would like to make. * Add tests for the component model support This commit uses the recently updated wasm-tools crates to add tests for the component model added in the previous commit. This involved updating the `wasmtime-wast` crate for component-model changes. Currently the component support there is quite primitive, but enough to at least instantiate components and verify the internals of Wasmtime are all working correctly. Additionally some simple tests for the embedding API have also been added.
This commit is contained in:
54
tests/misc_testsuite/component-model/adapter.wast
Normal file
54
tests/misc_testsuite/component-model/adapter.wast
Normal file
@@ -0,0 +1,54 @@
|
||||
;; basic function lifting
|
||||
(component
|
||||
(module $m
|
||||
(func (export ""))
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(func (export "thunk")
|
||||
(canon.lift (func) (func $i ""))
|
||||
)
|
||||
)
|
||||
|
||||
;; use an aliased type
|
||||
(component $c
|
||||
(module $m
|
||||
(func (export ""))
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(type $to_alias (func))
|
||||
(alias outer $c $to_alias (type $alias))
|
||||
|
||||
(func (export "thunk")
|
||||
(canon.lift (type $alias) (func $i ""))
|
||||
)
|
||||
)
|
||||
|
||||
;; test out some various canonical abi
|
||||
(component $c
|
||||
(module $m
|
||||
(func (export "") (param i32 i32))
|
||||
(memory (export "memory") 1)
|
||||
(func (export "canonical_abi_realloc") (param i32 i32 i32 i32) (result i32)
|
||||
unreachable)
|
||||
(func (export "canonical_abi_free") (param i32 i32 i32))
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(func (export "thunk")
|
||||
(canon.lift (func (param string)) (into $i) (func $i ""))
|
||||
)
|
||||
|
||||
(func (export "thunk8")
|
||||
(canon.lift (func (param string)) string=utf8 (into $i) (func $i ""))
|
||||
)
|
||||
|
||||
(func (export "thunk16")
|
||||
(canon.lift (func (param string)) string=utf16 (into $i) (func $i ""))
|
||||
)
|
||||
|
||||
(func (export "thunklatin16")
|
||||
(canon.lift (func (param string)) string=latin1+utf16 (into $i) (func $i ""))
|
||||
)
|
||||
)
|
||||
121
tests/misc_testsuite/component-model/instance.wast
Normal file
121
tests/misc_testsuite/component-model/instance.wast
Normal file
@@ -0,0 +1,121 @@
|
||||
(component
|
||||
(module $m)
|
||||
(instance (instantiate (module $m)))
|
||||
)
|
||||
|
||||
(component
|
||||
(module $m
|
||||
(func (export ""))
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(module $m2
|
||||
(func (import "" ""))
|
||||
)
|
||||
(instance (instantiate (module $m2) (with "" (instance $i))))
|
||||
)
|
||||
|
||||
(component
|
||||
(module $m
|
||||
(func (export "a"))
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(module $m2
|
||||
(func (import "" "b"))
|
||||
)
|
||||
(instance (instantiate (module $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
|
||||
(module $m
|
||||
(func (export "a"))
|
||||
(table (export "b") 1 funcref)
|
||||
(memory (export "c") 1)
|
||||
(global (export "d") i32 i32.const 1)
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(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)
|
||||
)
|
||||
(instance (instantiate (module $m2)
|
||||
(with "" (instance $i))
|
||||
))
|
||||
)
|
||||
|
||||
;; 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
|
||||
(module $m
|
||||
(global (export "g") i32 i32.const 1)
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(module $m2
|
||||
(import "" "g" (global $g i32))
|
||||
|
||||
(func $start
|
||||
global.get $g
|
||||
i32.const 0
|
||||
i32.ne
|
||||
if
|
||||
unreachable
|
||||
end
|
||||
)
|
||||
|
||||
(start $start)
|
||||
)
|
||||
(instance (instantiate (module $m2) (with "" (instance $i))))
|
||||
)
|
||||
"unreachable")
|
||||
|
||||
;; shuffle around imports to get to what the target core wasm module needs
|
||||
(component
|
||||
(module $m
|
||||
(func (export "1"))
|
||||
(table (export "2") 1 funcref)
|
||||
(memory (export "3") 1)
|
||||
(global (export "4") i32 i32.const 1)
|
||||
)
|
||||
(instance $i (instantiate (module $m)))
|
||||
|
||||
(module $m2
|
||||
(import "" "a" (func $f))
|
||||
(import "" "b" (table 1 funcref))
|
||||
(import "" "c" (memory 1))
|
||||
(import "" "d" (global $g i32))
|
||||
)
|
||||
(instance (instantiate (module $m2)
|
||||
(with "" (instance
|
||||
(export "a" (func $i "1"))
|
||||
(export "b" (table $i "2"))
|
||||
(export "c" (memory $i "3"))
|
||||
(export "d" (global $i "4"))
|
||||
))
|
||||
))
|
||||
)
|
||||
22
tests/misc_testsuite/component-model/simple.wast
Normal file
22
tests/misc_testsuite/component-model/simple.wast
Normal file
@@ -0,0 +1,22 @@
|
||||
(component)
|
||||
|
||||
(component
|
||||
(module)
|
||||
)
|
||||
|
||||
(component
|
||||
(module)
|
||||
(module)
|
||||
(module)
|
||||
)
|
||||
|
||||
(component
|
||||
(module
|
||||
(func (export "a") (result i32) i32.const 0)
|
||||
(func (export "b") (result i64) i64.const 0)
|
||||
)
|
||||
(module
|
||||
(func (export "c") (result f32) f32.const 0)
|
||||
(func (export "d") (result f64) f64.const 0)
|
||||
)
|
||||
)
|
||||
87
tests/misc_testsuite/component-model/types.wast
Normal file
87
tests/misc_testsuite/component-model/types.wast
Normal file
@@ -0,0 +1,87 @@
|
||||
(component
|
||||
(type string)
|
||||
(type (func (param string)))
|
||||
(type $r (record (field "x" unit) (field "y" string)))
|
||||
(type $u (union $r string))
|
||||
(type $e (expected $u u32))
|
||||
|
||||
(type (func (param $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 bool)
|
||||
(param u8)
|
||||
(param s8)
|
||||
(param u16)
|
||||
(param s16)
|
||||
(param u32)
|
||||
(param s32)
|
||||
(param u64)
|
||||
(param s64)
|
||||
(param char)
|
||||
(param 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 string) (result u32)))
|
||||
(type (component))
|
||||
(type (module))
|
||||
(type (instance))
|
||||
|
||||
(type (component
|
||||
(import "" (func (type $empty)))
|
||||
(import "y" (func))
|
||||
(import "z" (component))
|
||||
|
||||
(type $t (instance))
|
||||
|
||||
(export "a" (module))
|
||||
(export "b" (instance (type $t)))
|
||||
))
|
||||
|
||||
(type (instance
|
||||
(export "" (func (type $empty)))
|
||||
(export "y" (func))
|
||||
(export "z" (component))
|
||||
|
||||
(type $t (instance))
|
||||
|
||||
(export "a" (module))
|
||||
(export "b" (instance (type $t)))
|
||||
))
|
||||
|
||||
(type (module
|
||||
(import "" "" (func (param i32)))
|
||||
(import "" "1" (func (result i32)))
|
||||
(export "1" (global i32))
|
||||
(export "2" (memory 1))
|
||||
(export "3" (table 1 funcref))
|
||||
))
|
||||
)
|
||||
Reference in New Issue
Block a user