|
| 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