Skip to content
This repository was archived by the owner on Nov 3, 2021. It is now read-only.

Commit 1f29a8e

Browse files
authored
[spec] First go at specification (#3)
1 parent 1d7785d commit 1f29a8e

19 files changed

+967
-206
lines changed

document/core/appendix/algorithm.rst

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,49 @@ The algorithm is expressed in typed pseudo code whose semantics is intended to b
2121
Data Structures
2222
~~~~~~~~~~~~~~~
2323

24+
Types are representable as an enumeration.
25+
In addition to the plain types from the WebAssembly validation semantics, an extended notion of operand type includes a bottom type `Unknown` that is used as the type of :ref:`polymorphic <polymorphism>` operands.
26+
27+
A simple subtyping check can be defined on these types.
28+
In addition, corresponding functions computing the join (least upper bound) and meet (greatest lower bound) of two types are used.
29+
Because there is no top type, a join does not exist in all cases.
30+
Similarly, a meet must always be defined on known value types that exclude the auxiliary bottom type `Unknown`,
31+
hence a meet does not exist in all cases either.
32+
A type error is encountered if a join or meet is required when it does not exist.
33+
34+
.. code-block:: pseudo
35+
36+
type val_type = I32 | I64 | F32 | F64 | Anyref | Anyfunc | Anyeqref | Nullref
37+
type opd_type = val_type | Unknown
38+
39+
func is_ref(t : opd_type) : bool =
40+
return t = Anyref || t = Anyfunc || t = Anyeqref || t = Nullref
41+
42+
func matches(t1 : opd_type, t2 : opd_type) : bool =
43+
return t1 = t2 || t1 = Unknown ||
44+
(t1 = Nullref && is_ref(t2)) || (is_ref(t1) && t2 = Anyref)
45+
46+
func join(t1 : opd_type, t2 : opd_type) : opd_type =
47+
if (t1 = t2) return t1
48+
if (matches(t1, t2)) return t2
49+
if (matches(t2, t1)) return t1
50+
error_if(not (is_ref(t1) && is_ref(t2)))
51+
return Anyref
52+
53+
func meet(t1 : val_type, t2 : val_type) : val_type =
54+
if (t1 = t2) return t1
55+
if (matches(t1, t2)) return t1
56+
if (matches(t2, t1)) return t2
57+
error_if(not (is_ref(t1) && is_ref(t2)))
58+
return Nullref
59+
2460
The algorithm uses two separate stacks: the *operand stack* and the *control stack*.
2561
The former tracks the :ref:`types <syntax-valtype>` of operand values on the :ref:`stack <stack>`,
2662
the latter surrounding :ref:`structured control instructions <syntax-instr-control>` and their associated :ref:`blocks <syntax-instr-control>`.
2763

2864
.. code-block:: pseudo
2965
30-
type val_type = I32 | I64 | F32 | F64
31-
32-
type opd_stack = stack(val_type | Unknown)
66+
type opd_stack = stack(opd_type)
3367
3468
type ctrl_stack = stack(ctrl_frame)
3569
type ctrl_frame = {
@@ -58,20 +92,17 @@ However, these variables are not manipulated directly by the main checking funct
5892

5993
.. code-block:: pseudo
6094
61-
func push_opd(type : val_type | Unknown) =
95+
func push_opd(type : opd_type) =
6296
opds.push(type)
6397
64-
func pop_opd() : val_type | Unknown =
98+
func pop_opd() : opd_type =
6599
if (opds.size() = ctrls[0].height && ctrls[0].unreachable) return Unknown
66100
error_if(opds.size() = ctrls[0].height)
67101
return opds.pop()
68102
69-
func pop_opd(expect : val_type | Unknown) : val_type | Unknown =
103+
func pop_opd(expect : val_type) =
70104
let actual = pop_opd()
71-
if (actual = Unknown) return expect
72-
if (expect = Unknown) return actual
73-
error_if(actual =/= expect)
74-
return actual
105+
error_if(not matches(actual, expect))
75106
76107
func push_opds(types : list(val_type)) = foreach (t in types) push_opd(t)
77108
func pop_opds(types : list(val_type)) = foreach (t in reverse(types)) pop_opd(t)
@@ -83,9 +114,8 @@ But first, a special case is handled where the block contains no known operands,
83114
That can occur after an unconditional branch, when the stack is typed :ref:`polymorphically <polymorphism>`.
84115
In that case, an unknown type is returned.
85116

86-
A second function for popping an operand takes an expected type, which the actual operand type is checked against.
87-
The types may differ in case one of them is Unknown.
88-
The more specific type is returned.
117+
A second function for popping an operand takes an expected (known) type, which the actual operand type is checked against.
118+
The types may differ by subtyping, inlcuding the case where the actual type is unknown.
89119

90120
Finally, there are accumulative functions for pushing or popping multiple operand types.
91121

@@ -150,14 +180,19 @@ Other instructions are checked in a similar manner.
150180
pop_opd(I32)
151181
push_opd(I32)
152182
183+
case (ref.eq)
184+
pop_opd(Anyeqref)
185+
pop_opd(Anyeqref)
186+
push_opd(I32)
187+
153188
case (drop)
154189
pop_opd()
155190
156191
case (select)
157192
pop_opd(I32)
158193
let t1 = pop_opd()
159-
let t2 = pop_opd(t1)
160-
push_opd(t2)
194+
let t2 = pop_opd()
195+
push_opd(join(t1, t2))
161196
162197
   case (unreachable)
163198
      unreachable()
@@ -193,10 +228,12 @@ Other instructions are checked in a similar manner.
193228
194229
   case (br_table n* m)
195230
      error_if(ctrls.size() < m)
231+
var ts = ctrls[m].label_types
196232
      foreach (n in n*)
197-
        error_if(ctrls.size() < n || ctrls[n].label_types =/= ctrls[m].label_types)
233+
        error_if(ctrls.size() < n)
234+
ts := meet(ts, ctrls[n].label_types)
198235
pop_opd(I32)
199-
      pop_opds(ctrls[m].label_types)
236+
      pop_opds(ts)
200237
      unreachable()
201238
202239
.. note::

document/core/appendix/index-instructions.rst

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Instruction Binary Opcode Type
2424
:math:`\BRTABLE~l^\ast~l` :math:`\hex{0E}` :math:`[t_1^\ast~t^?~\I32] \to [t_2^\ast]` :ref:`validation <valid-br_table>` :ref:`execution <exec-br_table>`
2525
:math:`\RETURN` :math:`\hex{0F}` :math:`[t_1^\ast~t^?] \to [t_2^\ast]` :ref:`validation <valid-return>` :ref:`execution <exec-return>`
2626
:math:`\CALL~x` :math:`\hex{10}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation <valid-call>` :ref:`execution <exec-call>`
27-
:math:`\CALLINDIRECT~x` :math:`\hex{11}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation <valid-call_indirect>` :ref:`execution <exec-call_indirect>`
27+
:math:`\CALLINDIRECT~x~y` :math:`\hex{11}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation <valid-call_indirect>` :ref:`execution <exec-call_indirect>`
2828
(reserved) :math:`\hex{12}`
2929
(reserved) :math:`\hex{13}`
3030
(reserved) :math:`\hex{14}`
@@ -44,8 +44,8 @@ Instruction Binary Opcode Type
4444
:math:`\TEELOCAL~x` :math:`\hex{22}` :math:`[t] \to [t]` :ref:`validation <valid-tee_local>` :ref:`execution <exec-tee_local>`
4545
:math:`\GETGLOBAL~x` :math:`\hex{23}` :math:`[] \to [t]` :ref:`validation <valid-get_global>` :ref:`execution <exec-get_global>`
4646
:math:`\SETGLOBAL~x` :math:`\hex{24}` :math:`[t] \to []` :ref:`validation <valid-set_global>` :ref:`execution <exec-set_global>`
47-
(reserved) :math:`\hex{25}`
48-
(reserved) :math:`\hex{26}`
47+
:math:`\GETTABLE~x` :math:`\hex{25}` :math:`[\I32] \to [t]` :ref:`validation <valid-get_table>` :ref:`execution <exec-get_table>`
48+
:math:`\SETTABLE~x` :math:`\hex{26}` :math:`[\I32~t] \to []` :ref:`validation <valid-set_table>` :ref:`execution <exec-set_table>`
4949
(reserved) :math:`\hex{27}`
5050
:math:`\I32.\LOAD~\memarg` :math:`\hex{28}` :math:`[\I32] \to [\I32]` :ref:`validation <valid-load>` :ref:`execution <exec-load>`
5151
:math:`\I64.\LOAD~\memarg` :math:`\hex{29}` :math:`[\I32] \to [\I64]` :ref:`validation <valid-load>` :ref:`execution <exec-load>`
@@ -199,5 +199,24 @@ Instruction Binary Opcode Type
199199
:math:`\I64.\REINTERPRET\K{/}\F64` :math:`\hex{BD}` :math:`[\F64] \to [\I64]` :ref:`validation <valid-cvtop>` :ref:`execution <exec-cvtop>`, :ref:`operator <op-reinterpret>`
200200
:math:`\F32.\REINTERPRET\K{/}\I32` :math:`\hex{BE}` :math:`[\I32] \to [\F32]` :ref:`validation <valid-cvtop>` :ref:`execution <exec-cvtop>`, :ref:`operator <op-reinterpret>`
201201
:math:`\F64.\REINTERPRET\K{/}\I64` :math:`\hex{BF}` :math:`[\I64] \to [\F64]` :ref:`validation <valid-cvtop>` :ref:`execution <exec-cvtop>`, :ref:`operator <op-reinterpret>`
202+
(reserved) :math:`\hex{C0}`
203+
(reserved) :math:`\hex{C1}`
204+
(reserved) :math:`\hex{C2}`
205+
(reserved) :math:`\hex{C3}`
206+
(reserved) :math:`\hex{C4}`
207+
(reserved) :math:`\hex{C5}`
208+
(reserved) :math:`\hex{C6}`
209+
(reserved) :math:`\hex{C7}`
210+
(reserved) :math:`\hex{C8}`
211+
(reserved) :math:`\hex{C9}`
212+
(reserved) :math:`\hex{CA}`
213+
(reserved) :math:`\hex{CB}`
214+
(reserved) :math:`\hex{CC}`
215+
(reserved) :math:`\hex{CD}`
216+
(reserved) :math:`\hex{CE}`
217+
(reserved) :math:`\hex{CF}`
218+
:math:`\REFNULL` :math:`\hex{D0}` :math:`[] \to [\NULLREF]` :ref:`validation <valid-ref_null>` :ref:`execution <exec-ref_null>`
219+
:math:`\REFISNULL` :math:`\hex{D1}` :math:`[\ANYREF] \to [\I32]` :ref:`validation <valid-ref_isnull>` :ref:`execution <exec-ref_isnull>`
220+
:math:`\REFEQ` :math:`\hex{D2}` :math:`[\ANYEQREF~\ANYEQREF] \to [\I32]` :ref:`validation <valid-ref_eq>` :ref:`execution <exec-ref_eq>`
202221
=================================== ================ ========================================== ======================================== ===============================================================
203222

document/core/appendix/index-rules.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ Construct Judgement
7171
=============================================== ===============================================================================
7272

7373

74-
Import Matching
75-
~~~~~~~~~~~~~~~
74+
Matching
75+
~~~~~~~~
7676

7777
=============================================== ===============================================================================
7878
Construct Judgement
7979
=============================================== ===============================================================================
80-
:ref:`Limits <match-limits>` :math:`\vdashlimitsmatch \limits_1 \matches \limits_2`
81-
:ref:`External type <match-externtype>` :math:`\vdashexterntypematch \externtype_1 \matches \externtype_2`
80+
:ref:`Value type <match-valtype>` :math:`\vdashvaltypematch \valtype_1 \matchesvaltype \valtype_2`
81+
:ref:`External type <match-externtype>` :math:`\vdashexterntypematch \externtype_1 \matchesexterntype \externtype_2`
82+
:ref:`Limits <match-limits>` :math:`\vdashlimitsmatch \limits_1 \matcheslimits \limits_2`
8283
=============================================== ===============================================================================
8384

8485

document/core/appendix/index-types.rst

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@ Index of Types
88
Category Constructor Binary Opcode
99
======================================== =========================================== ===============================================================================
1010
:ref:`Type index <syntax-typeidx>` :math:`x` (positive number as |Bs32| or |Bu32|)
11-
:ref:`Value type <syntax-valtype>` |I32| :math:`\hex{7F}` (-1 as |Bs7|)
12-
:ref:`Value type <syntax-valtype>` |I64| :math:`\hex{7E}` (-2 as |Bs7|)
13-
:ref:`Value type <syntax-valtype>` |F32| :math:`\hex{7D}` (-3 as |Bs7|)
14-
:ref:`Value type <syntax-valtype>` |F64| :math:`\hex{7C}` (-4 as |Bs7|)
15-
(reserved) :math:`\hex{7C}` .. :math:`\hex{71}`
16-
:ref:`Element type <syntax-elemtype>` |ANYFUNC| :math:`\hex{70}` (-16 as |Bs7|)
17-
(reserved) :math:`\hex{6F}` .. :math:`\hex{61}`
11+
:ref:`Number type <syntax-numtype>` |I32| :math:`\hex{7F}` (-1 as |Bs7|)
12+
:ref:`Number type <syntax-numtype>` |I64| :math:`\hex{7E}` (-2 as |Bs7|)
13+
:ref:`Number type <syntax-numtype>` |F32| :math:`\hex{7D}` (-3 as |Bs7|)
14+
:ref:`Number type <syntax-numtype>` |F64| :math:`\hex{7C}` (-4 as |Bs7|)
15+
(reserved) :math:`\hex{7B}` .. :math:`\hex{71}`
16+
:ref:`Reference type <syntax-reftype>` |ANYFUNC| :math:`\hex{70}` (-16 as |Bs7|)
17+
:ref:`Reference type <syntax-reftype>` |ANYREF| :math:`\hex{6F}` (-17 as |Bs7|)
18+
:ref:`Reference type <syntax-reftype>` |ANYEQREF| :math:`\hex{6E}` (-18 as |Bs7|)
19+
(reserved) :math:`\hex{6D}` .. :math:`\hex{61}`
1820
:ref:`Function type <syntax-functype>` :math:`[\valtype^\ast] \to [\valtype^\ast]` :math:`\hex{60}` (-32 as |Bs7|)
1921
(reserved) :math:`\hex{5F}` .. :math:`\hex{41}`
2022
:ref:`Result type <syntax-resulttype>` :math:`\epsilon` :math:`\hex{40}` (-64 as |Bs7|)
21-
:ref:`Table type <syntax-tabletype>` :math:`\limits~\elemtype` (none)
23+
:ref:`Table type <syntax-tabletype>` :math:`\limits~\reftype` (none)
2224
:ref:`Memory type <syntax-memtype>` :math:`\limits` (none)
2325
:ref:`Global type <syntax-globaltype>` :math:`\mut~\valtype` (none)
2426
======================================== =========================================== ===============================================================================

document/core/binary/instructions.rst

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,39 @@ Control Instructions
5454
&\Rightarrow& \BRTABLE~l^\ast~l_N \\ &&|&
5555
\hex{0F} &\Rightarrow& \RETURN \\ &&|&
5656
\hex{10}~~x{:}\Bfuncidx &\Rightarrow& \CALL~x \\ &&|&
57-
\hex{11}~~x{:}\Btypeidx~~\hex{00} &\Rightarrow& \CALLINDIRECT~x \\
57+
\hex{11}~~y{:}\Btypeidx~~x{:}\Btableidx &\Rightarrow& \CALLINDIRECT~x~y \\
5858
\end{array}
5959
6060
.. note::
6161
The |ELSE| opcode :math:`\hex{05}` in the encoding of an |IF| instruction can be omitted if the following instruction sequence is empty.
6262

63+
64+
.. index:: reference instruction
65+
pair: binary format; instruction
66+
.. _binary-instr-ref:
67+
68+
Reference Instructions
69+
~~~~~~~~~~~~~~~~~~~~~~
70+
71+
:ref:`Reference instructions <syntax-instr-ref>` are represented by single byte codes.
72+
73+
.. _binary-ref_null:
74+
.. _binary-ref_isnull:
75+
.. _binary-ref_eq:
76+
77+
.. math::
78+
\begin{array}{llclll}
79+
\production{instruction} & \Binstr &::=& \dots \\ &&|&
80+
\hex{D0} &\Rightarrow& \REFNULL \\ &&|&
81+
\hex{D1} &\Rightarrow& \REFISNULL \\ &&|&
82+
\hex{D2} &\Rightarrow& \REFEQ \\
83+
\end{array}
84+
6385
.. note::
64-
In future versions of WebAssembly, the zero byte occurring in the encoding
65-
of the |CALLINDIRECT| instruction may be used to index additional tables.
86+
These opcode assignments are preliminary.
87+
6688

67-
.. index:: value type, polymorphism
89+
.. index:: parametric instruction, value type, polymorphism
6890
pair: binary format; instruction
6991
.. _binary-instr-parametric:
7092

@@ -110,6 +132,29 @@ Variable Instructions
110132
\end{array}
111133
112134
135+
.. index:: table instruction, table index
136+
pair: binary format; instruction
137+
.. _binary-instr-table:
138+
139+
Table Instructions
140+
~~~~~~~~~~~~~~~~~~
141+
142+
:ref:`Table instructions <syntax-instr-table>` are represented by single byte codes.
143+
144+
.. _binary-get_table:
145+
.. _binary-set_table:
146+
147+
.. math::
148+
\begin{array}{llclll}
149+
\production{instruction} & \Binstr &::=& \dots \\ &&|&
150+
\hex{25}~~x{:}\Btableidx &\Rightarrow& \GETTABLE~x \\ &&|&
151+
\hex{26}~~x{:}\Btableidx &\Rightarrow& \SETTABLE~x \\
152+
\end{array}
153+
154+
.. note::
155+
These opcode assignments are preliminary.
156+
157+
113158
.. index:: memory instruction, memory index
114159
pair: binary format; instruction
115160
.. _binary-instr-memory:

0 commit comments

Comments
 (0)