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

Commit 321b1a2

Browse files
authored
Merge pull request #11 from alexcrichton/binary
Start a binary encoding document
2 parents 2f41ae3 + fdbf2e5 commit 321b1a2

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed

proposals/module-linking/Binary.md

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# Module Linking Binary Format
2+
3+
This document is intended to be a reference for the current state of the binary
4+
encoding of the module linking proposal. This is kept in sync with [the
5+
explainer](Explainer.md) and that is also recommended reading to understand this
6+
document. Currently this isn't striving to have a spec-level of detail, but
7+
hopefully it should be enough to get implementations off the ground and agreeing
8+
with each other!
9+
10+
## Module-level updates
11+
12+
At a high-level two new index spaces are added: modules and instances. Index
13+
spaces are also updated to be built incrementally as they are defined.
14+
15+
Four new sections are added
16+
17+
* Module section, `modulesec`, declares nested modules whose code comes
18+
later. Only types are mentioned in this section.
19+
* Module Code section, `modulecodesec`, defines the nested modules.
20+
* Instance section, `instancesec`, declares and defines local instances.
21+
* Alias section, `aliassec`, brings in exports from nested instances or items
22+
from the parent module into the local index space.
23+
24+
The Type, Import, Module, Instance, and Alias sections can appear in any order
25+
at the beginning of a module. Each item defined in these sections can only refer
26+
to previously defined items. For example instance 4 cannot reference instance 5,
27+
and similarly no instance can refer to the module's own functions. Similarly
28+
instance 4 can only access module 3 if module 3 precedes instance 4 in binary
29+
format order.
30+
31+
## Type Section updates
32+
33+
Updates to
34+
[`typesec`](https://webassembly.github.io/spec/core/binary/modules.html#binary-typesec):
35+
36+
```
37+
typesec ::= t*:section_1(vec(type))
38+
39+
type ::=
40+
0x60 ft:functype -> ft
41+
0x61 mt:moduletype -> mt
42+
0x62 it:instancetype -> it
43+
44+
functype ::= rt_1:resulttype rt_2:resulttype -> rt_1 -> rt-2
45+
46+
moduletype ::=
47+
i*:vec(import) e*:vec(exporttype) -> {imports i, exports e}
48+
49+
instancetype ::= e*:vec(exporttype) -> {exports e}
50+
51+
exporttype ::= nm:name d:importdesc -> {name nm, desc d}
52+
```
53+
54+
referencing:
55+
56+
* [`resulttype`](https://webassembly.github.io/spec/core/binary/types.html#binary-resulttype)
57+
* [`import`](https://webassembly.github.io/spec/core/binary/modules.html#binary-import)
58+
* [`importdesc`](https://webassembly.github.io/spec/core/binary/modules.html#binary-importdesc) -
59+
although note that this is updated below as well.
60+
61+
**Validation**
62+
63+
* each `importdesc` is valid according to import section
64+
* Types can only reference preceding type definitions. This forces everything to
65+
be a DAG and forbids cyclic types.
66+
67+
## Import Section updates
68+
69+
Updates to
70+
[`importdesc`](https://webassembly.github.io/spec/core/binary/modules.html#binary-importdesc)
71+
72+
```
73+
# note that `0x01 0xc0` in MVP-wasm specifies a 1-byte module field of the
74+
# string 0xc0, but the 0xc0 byte is not valid utf-8, so this was not a valid
75+
# MVP import
76+
import ::=
77+
...
78+
mod:name 0x01 0xc0 d:importdesc -> {module mod, desc d}
79+
80+
importdesc ::=
81+
...
82+
0x05 x:typeidx -> module x
83+
0x06 x:typeidx -> instance x
84+
```
85+
86+
**Validation**
87+
88+
* the `func x` production ensures the type `x` is indeed a function type
89+
* the `module x` production ensures the type `x` is indeed a module type
90+
* the `instance x` production ensures the type `x` is indeed an instance type
91+
92+
## Module section (100)
93+
94+
A new module section is added
95+
96+
```
97+
modulesec ::= t*:section_100(vec(typeidx)) -> t*
98+
```
99+
100+
**Validation**
101+
102+
* Each type index `t` points to a module type (e.g. not a function type)
103+
* This defines the locally defined set of modules, adding to the module index
104+
space.
105+
106+
## Instance section (101)
107+
108+
A new section defining local instances
109+
110+
```
111+
instancesec ::= i*:section_101(vec(instancedef)) -> i*
112+
113+
instancedef ::= 0x00 m:moduleidx e*:vec(exportdesc) -> {instantiate m, imports e}
114+
```
115+
116+
This defines instances in the module, appending to the instance index space.
117+
Each instance definition declares the module it's instantiating as well as the
118+
items used to instantiate that instance. Note that the leading 0x00 is intended
119+
to allow different forms of instantiation in the future if added. This is also a
120+
placeholder value for now since if an `instantiate` instruction will be added in
121+
the future we'll likely want this binary value to match that.
122+
123+
**Validation**
124+
125+
* The type index `m` must point to a module type.
126+
* Indices of items referred to by `exportdesc` are all in-bounds. Can only refer
127+
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`.
136+
137+
## Alias section (102)
138+
139+
A new module section is added
140+
141+
```
142+
aliassec ::= a*:section_102(vec(alias)) -> a*
143+
144+
alias ::=
145+
0x00 i:instanceidx 0x00 e:exportidx -> (alias (instance $i) (func $e))
146+
0x00 i:instanceidx 0x01 e:exportidx -> (alias (instance $i) (table $e))
147+
0x00 i:instanceidx 0x02 e:exportidx -> (alias (instance $i) (memory $e))
148+
0x00 i:instanceidx 0x03 e:exportidx -> (alias (instance $i) (global $e))
149+
0x00 i:instanceidx 0x05 e:exportidx -> (alias (instance $i) (module $e))
150+
0x00 i:instanceidx 0x06 e:exportidx -> (alias (instance $i) (instance $e))
151+
0x01 0x05 m:moduleidx -> (alias parent (module $m))
152+
0x01 0x07 t:typeidx -> (alias parent (type $t))
153+
```
154+
155+
**Validation**
156+
157+
* Aliased instance indexes are all in bounds
158+
* Aliased instance export indices are in bounds relative to the instance's
159+
*locally-declared* (via module or instance type) list of exports
160+
* Export indices match the actual type of the export
161+
* Aliases append to the respective index space.
162+
* Parent aliases can only happen in submodules (not the top-level module) and
163+
the index specifies is the entry, in the parent's raw index space, for that
164+
item.
165+
* Parent aliases can only refer to preceeding module/type definitions, relative
166+
to the binary location where the inline module's type was declared. Note that
167+
when the module code section is defined all of the parent's modules/types are
168+
available, but inline modules still may not have access to all of these if the
169+
items were declared after the module's type in the corresponding module
170+
section.
171+
172+
## Function section
173+
174+
**Validation**
175+
176+
* Type indices must point to function types.
177+
178+
## Export section
179+
180+
update
181+
[`exportdesc`](https://webassembly.github.io/spec/core/binary/modules.html#binary-exportdesc)
182+
183+
```
184+
exportdesc ::=
185+
...
186+
0x05 x:moduleidx -> module x
187+
0x06 x:instanceidx -> instance x
188+
```
189+
190+
**Validation**
191+
192+
* Module/instance indexes must be in-bounds.
193+
194+
## Module Code Section (103)
195+
196+
```
197+
modulecodesec ::= m*:section_103(vec(modulecode)) -> m*
198+
199+
modulecode ::= size:u32 mod:module -> mod, size = ||mod||
200+
```
201+
202+
Note that this is intentionally a recursive production where `module` refers to
203+
the top-level
204+
[`module`](https://webassembly.github.io/spec/core/binary/modules.html#binary-module)
205+
206+
**Validation**
207+
208+
* Module definitions must match their module type exactly, no subtyping (or
209+
maybe subtyping, see WebAssembly/module-linking#9).
210+
* 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

0 commit comments

Comments
 (0)