You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Validation requires a :ref:`context <context>` for checking uses of :ref:`indices <syntax-index>`.
83
+
For the purpose of presenting the algorithm, it is maintained in a set of global variables:
84
+
85
+
.. code-block:: pseudo
86
+
87
+
var locals : array(val_type)
88
+
var locals_init : array(bool)
89
+
var globals : array(global_type)
90
+
var funcs : array(func_type)
91
+
var tables : array(table_type)
92
+
var mems : array(mem_type)
93
+
94
+
This assumes suitable representations for the various :ref:`types <syntax-type>` besides :code:`val_type`, which are omitted here.
95
+
96
+
For locals, there is an additional array recording the initialization status of each local.
97
+
98
+
Stacks
99
+
......
73
100
74
-
The algorithm uses two separate stacks: the *value stack* and the *control stack*.
75
-
The former tracks the :ref:`types <syntax-valtype>` of operand values on the :ref:`stack <stack>`,
76
-
the latter surrounding :ref:`structured control instructions <syntax-instr-control>` and their associated :ref:`blocks <syntax-instr-control>`.
101
+
The algorithm uses three separate stacks: the *value stack*, the *control stack*, and the *initialization stack*.
102
+
The value stack tracks the :ref:`types <syntax-valtype>` of operand values on the :ref:`stack <stack>`.
103
+
The control stack tracks surrounding :ref:`structured control instructions <syntax-instr-control>` and their associated :ref:`blocks <syntax-instr-control>`.
104
+
The initialization stack records all :ref:`locals <syntax-local>` that have been initialized since the beginning of the function.
77
105
78
106
.. code-block:: pseudo
79
107
80
108
type val_stack = stack(val_type)
109
+
type init_stack = stack(u32)
81
110
82
111
type ctrl_stack = stack(ctrl_frame)
83
112
type ctrl_frame = {
84
113
opcode : opcode
85
114
start_types : list(val_type)
86
115
end_types : list(val_type)
87
-
height : nat
116
+
val_height : nat
117
+
init_height : nat
88
118
unreachable : bool
89
119
}
90
120
91
-
For each value, the value stack records its :ref:`value type <syntax-valtype>`.
92
-
For each entered block, the control stack records a *control frame* with the originating opcode, the types on the top of the operand stack at the start and end of the block (used to check its result as well as branches), the height of the operand stack at the start of the block (used to check that operands do not underflow the current block), and a flag recording whether the remainder of the block is unreachable (used to handle :ref:`stack-polymorphic <polymorphism>` typing after branches).
121
+
For each entered block, the control stack records a *control frame* with the originating opcode, the types on the top of the operand stack at the start and end of the block (used to check its result as well as branches), the height of the operand stack at the start of the block (used to check that operands do not underflow the current block), the height of the initialization stack at the start of the block (used to reset initialization status at the end of the block), and a flag recording whether the remainder of the block is unreachable (used to handle :ref:`stack-polymorphic <polymorphism>` typing after branches).
93
122
94
-
For the purpose of presenting the algorithm, the operand and control stacks are simply maintained as global variables:
123
+
For the purpose of presenting the algorithm, these stacks are simply maintained as global variables:
95
124
96
125
.. code-block:: pseudo
97
126
98
127
var vals : val_stack
128
+
var inits : init_stack
99
129
var ctrls : ctrl_stack
100
130
101
131
However, these variables are not manipulated directly by the main checking function, but through a set of auxiliary functions:
@@ -123,7 +153,7 @@ However, these variables are not manipulated directly by the main checking funct
123
153
func pop_ref() : ref_type =
124
154
let actual = pop_val()
125
155
error_if(not is_ref(actual))
126
-
if actual = Bot then return Ref(Bot, false)
156
+
if (actual = Bot) return Ref(Bot, false)
127
157
return actual
128
158
129
159
func push_vals(types : list(val_type)) = foreach (t in types) push_val(t)
@@ -150,25 +180,49 @@ Finally, there are accumulative functions for pushing or popping multiple operan
150
180
so that, e.g., :code:`ctrls[0]` accesses the element pushed last.
151
181
152
182
183
+
The initialization stack and the initialization status of locals is manipulated through the following functions:
@@ -180,6 +234,7 @@ It allocates a new frame record recording them along with the current height of
180
234
Popping a frame first checks that the control stack is not empty.
181
235
It then verifies that the operand stack contains the right types of values expected at the end of the exited block and pops them off the operand stack.
182
236
Afterwards, it checks that the stack has shrunk back to its initial height.
237
+
Finally, it undoes all changes to the initialization status of locals that happend inside the block.
183
238
184
239
The type of the :ref:`label <syntax-label>` associated with a control frame is either that of the stack at the start or the end of the frame, determined by the opcode that it originates from.
185
240
@@ -192,6 +247,7 @@ In that case, all existing operand types are purged from the value stack, in ord
192
247
However, a polymorphic stack cannot underflow, but instead generates :code:`Bot` types as needed.
193
248
194
249
250
+
195
251
.. index:: opcode
196
252
197
253
Validation of Opcode Sequences
@@ -200,10 +256,6 @@ Validation of Opcode Sequences
200
256
The following function shows the validation of a number of representative instructions that manipulate the stack.
201
257
Other instructions are checked in a similar manner.
202
258
203
-
.. note::
204
-
Various instructions not shown here will additionally require the presence of a validation :ref:`context <context>` for checking uses of :ref:`indices <syntax-index>`.
205
-
That is an easy addition and therefore omitted from this presentation.
206
-
207
259
.. code-block:: pseudo
208
260
209
261
func validate(opcode) =
@@ -222,7 +274,7 @@ Other instructions are checked in a similar manner.
Copy file name to clipboardExpand all lines: document/core/exec/runtime.rst
+7-4Lines changed: 7 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -51,14 +51,16 @@ or *external references* pointing to an uninterpreted form of :ref:`extern addre
51
51
52
52
.. _default-val:
53
53
54
-
Each :ref:`value type <syntax-valtype>` has an associated *default value*;
55
-
it is the respective value :math:`0` for :ref:`number types <syntax-numtype>`, :math:`0` for :ref:`vector types <syntax-vectype>`, and null for :ref:`reference types <syntax-reftype>`.
54
+
:ref:`Value types <syntax-valtype>` can have an associated *default value*;
55
+
it is the respective value :math:`0` for :ref:`number types <syntax-numtype>`, :math:`0` for :ref:`vector types <syntax-vectype>`, and null for nullable :ref:`reference types <syntax-reftype>`.
56
+
For other references, no default value is defined, :math:`\default_t` hence is an optional value :math:`\val^?`.
56
57
57
58
.. math::
58
59
\begin{array}{lcl@{\qquad}l}
59
60
\default_t &=& t{.}\CONST~0 & (\iff t = \numtype) \\
60
61
\default_t &=& t{.}\CONST~0 & (\iff t = \vectype) \\
61
62
\default_t &=& \REFNULL~t & (\iff t = (\REF~\NULL~\heaptype)) \\
63
+
\default_t &=& \epsilon & (\iff t = (\REF~\heaptype)) \\
62
64
\end{array}
63
65
64
66
@@ -493,10 +495,11 @@ and a reference to the function's own :ref:`module instance <syntax-moduleinst>`
0 commit comments