Skip to content

Commit

Permalink
Fix encoding of type information in wasm-compose (#1141)
Browse files Browse the repository at this point in the history
* Move wit-components component builder to wasm-encoder

This commit moves the `ComponentBuilder` type to the `wasm-encoder`
crate. I plan on using this shortly in the `wasm-compose` crate since
it's pretty useful for keeping track of all the indices for us and
automatically coalescing sections into one and such like that.

While here I decided to refactor and rename some of the interfaces for
consistency since the interface had become a bit ad-hoc over time. This
also involved slightly modifying how the producers section was handled
in the `wit-component` crate which moved the section to the end instead
of the previous next-to-last position.

* Fix encoding of type information in `wasm-compose`

This commit is a large refactoring and restructuring of how type
information for imports is encoded with `wasm-compose`. This was all
originally written in an era without resource types and without aliasing
of types between instances being well-defined, which means that composed
components end up not currently reflecting the correct type information
in terms of where types are defined and ensuring everything is defined
only once. The test cases added here in this PR either all fail to
generate a valid component today or generate a component that has an
incorrect structure of type information in that it's different from the
sources.

The new implementation of type encoding here is motivated by taking a
larger demo of composition and effectively fixing issues until the whole
thing is composed together. In that sense there's not really a rhyme or
reason to the changes here other than "this is what's necessary to fix
this one test case". All that to say that there are probably still
latent issues to fix and that this would make a fantastic fuzz target
(although I don't know how really myself). For now though the new tests
require most of the implementation here and new tests can be added over
time as well.

At a high level the main part of this restructuring is to follow the
exact definitions of `TypeId` rather than always dereferencing it and
looking at the underlying definition. This involves following alias
chains of exports and additionally adding support for pulling in types
from other instances and such. This is all very similar to what
`wit-component` is already doing when translating from WIT to wasm, but
it's distinct as well in the sense that `wasm-compose` is weaving
multiple components together, each with different type information,
where `wit-component` is translating a WIT document into wasm. All that
to say that while there's at a high level a good deal of shared code
here at a lower level there's not much acutal possible sharing without
what I would predict is quite odd contortions.

* Review comments

* Fix test after rebase
  • Loading branch information
alexcrichton authored Jul 26, 2023
1 parent 6f4508a commit dd6ddb3
Show file tree
Hide file tree
Showing 124 changed files with 1,861 additions and 1,077 deletions.
1,276 changes: 785 additions & 491 deletions crates/wasm-compose/src/encoding.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion crates/wasm-compose/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,10 @@ impl<'a> Component<'a> {
}

pub(crate) fn ty(&self) -> wasm_encoder::ComponentType {
let encoder = TypeEncoder::new(&self.types);
let encoder = TypeEncoder::new(self);

encoder.component(
&mut Default::default(),
self.imports()
.map(|(i, ..)| self.import_entity_type(i).unwrap()),
self.exports()
Expand Down
2 changes: 2 additions & 0 deletions crates/wasm-compose/tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
!*.wasm
!*.wat
1 change: 1 addition & 0 deletions crates/wasm-compose/tests/compose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn component_composing() -> Result<()> {
}

let test_case = path.file_stem().unwrap().to_str().unwrap();
println!("================ {test_case:30} ===============");
let root_path = path.join("root.wat");
let output_path = path.join("composed.wat");
let error_path = path.join("error.txt");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
)
)
(alias export 5 "m1" (func (;0;)))
(alias export 5 "m2" (func (;1;)))
(export (;2;) "m1" (func 0))
(export (;3;) "m2" (func 1))
(export (;1;) "m1" (func 0))
(alias export 5 "m2" (func (;2;)))
(export (;3;) "m2" (func 2))
)
78 changes: 0 additions & 78 deletions crates/wasm-compose/tests/compositions/complex/a.wit

This file was deleted.

1 change: 0 additions & 1 deletion crates/wasm-compose/tests/compositions/complex/b.wit

This file was deleted.

6 changes: 3 additions & 3 deletions crates/wasm-compose/tests/compositions/complex/composed.wat
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@
)
)
(alias export 5 "m1" (func (;0;)))
(alias export 5 "m2" (func (;1;)))
(export (;2;) "m1" (func 0))
(export (;3;) "m2" (func 1))
(export (;1;) "m1" (func 0))
(alias export 5 "m2" (func (;2;)))
(export (;3;) "m2" (func 2))
)
10 changes: 10 additions & 0 deletions crates/wasm-compose/tests/compositions/resort-imports/a.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(component
(import "dep1" (instance $dep1
(type $t' u32)
(export $t "t" (type (eq $t')))
))
(alias export $dep1 "t" (type $t-dep1))
(import "dep2" (instance
(export "f1" (func (result $t-dep1)))
))
)
10 changes: 10 additions & 0 deletions crates/wasm-compose/tests/compositions/resort-imports/b.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(component
(import "dep0" (instance $dep0
(type $t' u32)
(export $t "t" (type (eq $t')))
))
(alias export $dep0 "t" (type $t-dep0))
(import "dep2" (instance
(export "f2" (func (result $t-dep0)))
))
)
90 changes: 90 additions & 0 deletions crates/wasm-compose/tests/compositions/resort-imports/composed.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
(component
(type (;0;)
(instance
(type (;0;) u32)
(export (;1;) "t" (type (eq 0)))
)
)
(import "dep0" (instance (;0;) (type 0)))
(type (;1;)
(instance
(type (;0;) u32)
(export (;1;) "t" (type (eq 0)))
)
)
(import "dep1" (instance (;1;) (type 1)))
(alias export 0 "t" (type (;2;)))
(alias export 1 "t" (type (;3;)))
(type (;4;)
(instance
(alias outer 1 2 (type (;0;)))
(type (;1;) (func (result 0)))
(export (;0;) "f2" (func (type 1)))
(alias outer 1 3 (type (;2;)))
(type (;3;) (func (result 2)))
(export (;1;) "f1" (func (type 3)))
)
)
(import "dep2" (instance (;2;) (type 4)))
(component (;0;)
(type (;0;)
(instance)
)
(import "b" (instance (;0;) (type 0)))
(type (;1;)
(instance)
)
(import "a" (instance (;1;) (type 1)))
)
(component (;1;)
(type (;0;)
(instance
(type (;0;) u32)
(export (;1;) "t" (type (eq 0)))
)
)
(import "dep0" (instance $dep0 (;0;) (type 0)))
(alias export $dep0 "t" (type $t-dep0 (;1;)))
(type (;2;)
(instance
(alias outer 1 $t-dep0 (type (;0;)))
(type (;1;) (func (result 0)))
(export (;0;) "f2" (func (type 1)))
)
)
(import "dep2" (instance (;1;) (type 2)))
)
(component (;2;)
(type (;0;)
(instance
(type (;0;) u32)
(export (;1;) "t" (type (eq 0)))
)
)
(import "dep1" (instance $dep1 (;0;) (type 0)))
(alias export $dep1 "t" (type $t-dep1 (;1;)))
(type (;2;)
(instance
(alias outer 1 $t-dep1 (type (;0;)))
(type (;1;) (func (result 0)))
(export (;0;) "f1" (func (type 1)))
)
)
(import "dep2" (instance (;1;) (type 2)))
)
(instance (;3;) (instantiate 2
(with "dep1" (instance 1))
(with "dep2" (instance 2))
)
)
(instance (;4;) (instantiate 1
(with "dep0" (instance 0))
(with "dep2" (instance 2))
)
)
(instance (;5;) (instantiate 0
(with "b" (instance 4))
(with "a" (instance 3))
)
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(component
(import "b" (instance))
(import "a" (instance))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(component
(import "c" (instance
(type $dummy u32)
(type $t' u32)
(export $t "t" (type (eq $t')))
(export "f1" (func (result $t)))
))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(component
(import "c" (instance
(type $t' u32)
(export $t "t" (type (eq $t')))
(export "f2" (func (result $t)))
))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(component
(type (;0;)
(instance
(type (;0;) u32)
(export (;1;) "t" (type (eq 0)))
(type (;2;) (func (result 1)))
(export (;0;) "f2" (func (type 2)))
(type (;3;) (func (result 1)))
(export (;1;) "f1" (func (type 3)))
)
)
(import "c" (instance (;0;) (type 0)))
(component (;0;)
(type (;0;)
(instance)
)
(import "b" (instance (;0;) (type 0)))
(type (;1;)
(instance)
)
(import "a" (instance (;1;) (type 1)))
)
(component (;1;)
(type (;0;)
(instance
(type (;0;) u32)
(export (;1;) "t" (type (eq 0)))
(type (;2;) (func (result 1)))
(export (;0;) "f2" (func (type 2)))
)
)
(import "c" (instance (;0;) (type 0)))
)
(component (;2;)
(type (;0;)
(instance
(type (;0;) u32)
(type (;1;) u32)
(export (;2;) "t" (type (eq 1)))
(type (;3;) (func (result 2)))
(export (;0;) "f1" (func (type 3)))
)
)
(import "c" (instance (;0;) (type 0)))
)
(instance (;1;) (instantiate 2
(with "c" (instance 0))
)
)
(instance (;2;) (instantiate 1
(with "c" (instance 0))
)
)
(instance (;3;) (instantiate 0
(with "b" (instance 2))
(with "a" (instance 1))
)
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(component
(import "b" (instance))
(import "a" (instance))
)
41 changes: 41 additions & 0 deletions crates/wasm-compose/tests/compositions/type-use/a.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
(component
(import (interface "a:b/type-def") (instance $type-def
(type $r1' (record (field "f" u32)))
(export $r1 "r1" (type (eq $r1')))
(type $r2' (record (field "r1" $r1)))
(export $r2 "r2" (type (eq $r2')))
))
(alias export $type-def "r1" (type $r1))
(alias export $type-def "r2" (type $r2))
(import (interface "a:b/type-use") (instance
(export "r1" (type (eq $r1)))
(export "r2" (type (eq $r2)))
))

(import (interface "a:b/type-use-in-same-interface") (instance
(type $t1' u32)
(export $t1 "t1" (type (eq $t1')))
(export $t2 "t2" (type (eq $t1)))
))

(import (interface "a:b/diamond-base") (instance $diamond-base
(type $t u32)
(export "t" (type (eq $t)))
))
(alias export $diamond-base "t" (type $t-diamond-base))

(import (interface "a:b/diamond1") (instance $diamond1
(export "t" (type (eq $t-diamond-base)))
))
(import (interface "a:b/diamond2") (instance $diamond2
(export "t" (type (eq $t-diamond-base)))
))

(alias export $diamond1 "t" (type $t-diamond1))
(alias export $diamond2 "t" (type $t-diamond2))

(import (interface "a:b/diamond-join") (instance
(export "t1" (type (eq $t-diamond1)))
(export "t2" (type (eq $t-diamond2)))
))
)
Loading

0 comments on commit dd6ddb3

Please sign in to comment.