Skip to content
This repository was archived by the owner on Aug 17, 2022. It is now read-only.

Commit a66570b

Browse files
alexcrichtonlukewagner
authored andcommitted
Sync Explainer.md with Binary.md, add a Subtyping.md
This commit has a few high-level changes: * The `Binary.md` is sync'd a bit with `Explainer.md` in terms of content and links. * The textual syntax for `alias` directives was tweaked in `Explainer.md` to match `Binary.md` * Actual section numbers were chosen in the binary format. The exception handling proposal uses 13 for an event section so the four new sections here are getting 14-17. * Handling of subtyping between instances and modules is now codified in `Subtyping.md`. This goes into more detail about how imports are elaborated, how instantiation is expected to work, and how to test for subtypes. This is hoped to describe the intended status quo given the discussion on #7.
1 parent e6237fd commit a66570b

File tree

3 files changed

+241
-57
lines changed

3 files changed

+241
-57
lines changed

proposals/module-linking/Binary.md

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ referencing:
6262

6363
* each `importdesc` is valid according to import section
6464
* Types can only reference preceding type definitions. This forces everything to
65-
be a DAG and forbids cyclic types.
65+
be a DAG and forbids cyclic types. TODO: with type imports we may need cyclic
66+
types, so this validation will likely change in some form.
6667

6768
## Import Section updates
6869

@@ -89,12 +90,12 @@ importdesc ::=
8990
* the `module x` production ensures the type `x` is indeed a module type
9091
* the `instance x` production ensures the type `x` is indeed an instance type
9192

92-
## Module section (100)
93+
## Module section (14)
9394

9495
A new module section is added
9596

9697
```
97-
modulesec ::= t*:section_100(vec(typeidx)) -> t*
98+
modulesec ::= t*:section_14(vec(typeidx)) -> t*
9899
```
99100

100101
**Validation**
@@ -103,12 +104,12 @@ modulesec ::= t*:section_100(vec(typeidx)) -> t*
103104
* This defines the locally defined set of modules, adding to the module index
104105
space.
105106

106-
## Instance section (101)
107+
## Instance section (15)
107108

108109
A new section defining local instances
109110

110111
```
111-
instancesec ::= i*:section_101(vec(instancedef)) -> i*
112+
instancesec ::= i*:section_15(vec(instancedef)) -> i*
112113
113114
instancedef ::= 0x00 m:moduleidx e*:vec(exportdesc) -> {instantiate m, imports e*}
114115
```
@@ -125,21 +126,25 @@ the future we'll likely want this binary value to match that.
125126
* The type index `m` must point to a module type.
126127
* Indices of items referred to by `exportdesc` are all in-bounds. Can only refer
127128
to imports/previous aliases, since only those sections can precede.
128-
* The precise rules of how `e*` is validated against the module type's declare
129-
list of imports is being hashed out in
130-
[#7](https://github.com/WebAssembly/module-linking/issues/7). For now
131-
conservative order-dependent rules are used where the length of `e*` must be
132-
the same as the number of imports the module type has. Additionally the type
133-
of each element of `e*` must be a subtype of the type that it's being matched
134-
with. Matching happens pairwise with the list of imports on the module type
135-
for `m`.
129+
* The `e*` list is validated against the module type's declared list
130+
of [imports pairwise and in-order](Explainer.md#module-imports-and-nested-instances).
131+
The type of each item must be a supertype of the expected type listed in the
132+
module's type.
136133

137-
## Alias section (102)
134+
**Execution notes**
135+
136+
* The actual module being instantiated does not need to list imports in the
137+
exact same order as its type declaration. The `e*` has names based on the
138+
local module type's declaration.
139+
* Be sure to read up on [subtyping](./Subtyping.md) to ensure that instances
140+
with a single name can be used to match imports with a two-level namespace.
141+
142+
## Alias section (16)
138143

139144
A new module section is added
140145

141146
```
142-
aliassec ::= a*:section_102(vec(alias)) -> a*
147+
aliassec ::= a*:section_16(vec(alias)) -> a*
143148
144149
alias ::=
145150
0x00 i:instanceidx 0x00 e:exportidx -> (alias (instance $i) (func $e))
@@ -154,9 +159,10 @@ alias ::=
154159

155160
**Validation**
156161

157-
* Aliased instance indexes are all in bounds
162+
* Aliased instance indexes are all in bounds. Remember "in bounds" here means it
163+
can't refer to instances defined after the `alias` item.
158164
* Aliased instance export indices are in bounds relative to the instance's
159-
*locally-declared* (via module or instance type) list of exports
165+
*locally-declared* (via module or instance type) list of exports.
160166
* Export indices match the actual type of the export
161167
* Aliases append to the respective index space.
162168
* Parent aliases can only happen in submodules (not the top-level module) and
@@ -169,6 +175,12 @@ alias ::=
169175
items were declared after the module's type in the corresponding module
170176
section.
171177

178+
**Execution notes**
179+
180+
* Note for child aliases that while the export is referred to by index it's
181+
actually loaded from the specified instance by name. The name loaded
182+
corresponds to the `i`th export's name in the locally defined type.
183+
172184
## Function section
173185

174186
**Validation**
@@ -191,10 +203,10 @@ exportdesc ::=
191203

192204
* Module/instance indexes must be in-bounds.
193205

194-
## Module Code Section (103)
206+
## Module Code Section (17)
195207

196208
```
197-
modulecodesec ::= m*:section_103(vec(modulecode)) -> m*
209+
modulecodesec ::= m*:section_17(vec(modulecode)) -> m*
198210
199211
modulecode ::= size:u32 mod:module -> mod, size = ||mod||
200212
```
@@ -208,31 +220,9 @@ the top-level
208220
* Module definitions must match their module type exactly, no subtyping (or
209221
maybe subtyping, see WebAssembly/module-linking#9).
210222
* Modules themselves validate recursively.
211-
* Must have the same number of modules as the count of all local module
212-
sections.
213-
* Each submodule is validated with a subset of the parent's context, for example
214-
the set of types and instances the current module has defined are available
215-
for aliasing in the submodule.
216-
217-
## Subtyping
218-
219-
Subtyping will extend what's currently ["import
220-
matching"](https://webassembly.github.io/spec/core/exec/modules.html#import-matching)
221-
222-
**Instances**
223-
224-
Instance `{exports e1}` is a subtype of `{exports e2}` if and only if:
225-
226-
* Each name in `e1` is present in `e2`
227-
* For each corresponding name `n` in the sets
228-
* `e1[n]` is a subtype of `e2[n]`
229-
230-
**Instances**
231-
232-
Module `{imports i1, exports e1}` is a subtype of `{imports i2, exports e2}` if and only if:
233-
234-
* Each name in `e1` is present in `e2`
235-
* For each corresponding name `n` in the sets
236-
* `e1[n]` is a subtype of `e2[n]`
237-
* ... And some condition on imports. For now this is a bit up for debate on
238-
WebAssembly/module-linking#7
223+
* The module code section must have the same number of modules as the count of
224+
all local module sections.
225+
* Each submodule is validated with the parent's context at the time of
226+
declaration. For example the set of types and modules the current module
227+
has defined are available for aliasing in the submodule, but only those
228+
defined before the corresponding module's type declaration.

proposals/module-linking/Explainer.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ example, an instance type can be defined:
284284

285285
In many examples shown below, type definitions are needed for *both* a module
286286
type and the instance type produced when that module type is instantiated. In
287-
such cases, to avoid duplicating all the exports, a new "zero-level export"
287+
such cases, to avoid duplicating all the exports, a new "zero-level export"
288288
`(export $InstanceType)` form is added which injects all the exports of
289289
`$InstanceType` into the containing module type. For example, here is the type
290290
of a module which implements the above-defined `$WasiFile` interface via Win32
@@ -363,9 +363,9 @@ version of the same module can be written:
363363
(export "f1" (func $f1))
364364
(export "f2" (func $f2 (param i32)))
365365
))
366-
(alias $i.f1 (func $i $f1))
366+
(alias $i.$f1 (instance $i) (func $f1))
367367
(func (export "run")
368-
call $i.f1
368+
call $i.$f1
369369
)
370370
)
371371
```
@@ -377,17 +377,17 @@ how multiple uses of inline function types [desugar][typeuse-abbrev] to the same
377377
function type definition.
378378

379379
Aliases are not restricted to functions: all exportable definitions can be
380-
aliased. One situation where an explicit `alias` definition will be required is
381-
for a default memory or table: because there is no explicit `$i.$j` path used by
382-
instructions to refer to defaults, they must be explicitly aliased:
380+
aliased. One situation where an explicit `alias` definition may be required is
381+
for a default memory or table since if there is no explicit `$i.$j` path used
382+
by instructions to refer to defaults, they must be explicitly aliased:
383383
```wasm
384384
(module
385385
(import "libc" (instance $libc
386386
(export "memory" (memory $mem 1))
387387
(export "table" (table $tbl 0 funcref))
388388
))
389-
(alias (memory $libc $mem)) ;; memory index 0 = default memory
390-
(alias (table $libc $tbl)) ;; table index 0 = default table
389+
(alias (instance $libc) (memory $mem)) ;; memory index 0 = default memory
390+
(alias (instance $libc) (table $tbl)) ;; table index 0 = default table
391391
(func
392392
...
393393
i32.load ;; accesses $libc.$mem
@@ -544,11 +544,17 @@ the child's type index space:
544544
(export "read" (func (param i32 i32 i32) (result i32)))
545545
))
546546
(module $child
547-
(alias $WasiFile (parent (type $WasiFile)))
547+
(alias $WasiFile parent (type $WasiFile))
548548
(import "wasi_file" (instance (type $WasiFile)))
549549
)
550550
)
551551
```
552+
Note that `parent` aliases can only refer to previously-defined items relative
553+
to the module's own declaration in the module index space. This means that it
554+
can refer to previously defined imports, modules, instances, or aliases, but it
555+
cannot refer to imports (for example) that occur after the module's
556+
declaration. A module is declared with its type and defined later in the binary
557+
format.
552558

553559
In general, language-independent tools can easily merge multiple `.wasm` files
554560
in a dependency graph into one `.wasm` file by performing simple transformations
@@ -673,6 +679,9 @@ could be encoded with the binary section sequence:
673679
10. ModuleCode Section, defining `$M`
674680
11. Code Section, defining `$x`
675681

682+
This repository also contains an [initial proposal for the binary format
683+
updates](./Binary.md).
684+
676685

677686
### Summary
678687

@@ -764,7 +773,7 @@ More generally, when ESM-integration loads a module with a
764773

765774
With this extension, a single JS app will be able to load multiple wasm
766775
programs using ESM `import` statements and have these programs safely and
767-
transparently share library code as described in
776+
transparently share library code as described in
768777
[shared-everything dynamic linking example](Example-SharedEverythingDynamicLinking.md).
769778

770779

0 commit comments

Comments
 (0)