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
Copy file name to clipboardExpand all lines: document/core/appendix/algorithm.rst
+32-25Lines changed: 32 additions & 25 deletions
Original file line number
Diff line number
Diff line change
@@ -33,19 +33,16 @@ the latter surrounding :ref:`structured control instructions <syntax-instr-contr
33
33
34
34
type ctrl_stack = stack(ctrl_frame)
35
35
type ctrl_frame = {
36
-
label_types : list(val_type)
36
+
opcode : opcode
37
+
start_types : list(val_type)
37
38
end_types : list(val_type)
38
39
height : nat
39
40
unreachable : bool
40
41
}
41
42
42
43
For each value, the operand stack records its :ref:`value type <syntax-valtype>`, or :code:`Unknown` when the type is not known.
43
44
44
-
For each entered block, the control stack records a *control frame* with the type of the associated :ref:`label <syntax-label>` (used to type-check branches), the result type of the block (used to check its result), 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).
45
-
46
-
.. note::
47
-
In the presentation of this algorithm, multiple values are supported for the :ref:`result types <syntax-resulttype>` classifying blocks and labels.
48
-
With the current version of WebAssembly, the :code:`list` could be simplified to an optional value.
45
+
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).
49
46
50
47
For the purpose of presenting the algorithm, the operand and control stacks are simply maintained as global variables:
51
48
@@ -98,17 +95,21 @@ The control stack is likewise manipulated through auxiliary functions:
98
95
99
96
.. code-block:: pseudo
100
97
101
-
func push_ctrl(label : list(val_type), out : list(val_type)) =
102
-
let frame = ctrl_frame(label, out, opds.size(), false)
98
+
func push_ctrl(opcode : opcode, in : list(val_type), out : list(val_type)) =
99
+
let frame = ctrl_frame(opcode, in, out, opds.size(), false)
return (if frame.opcode == loop then frame.start_types else frame.end_types)
112
113
113
114
func unreachable() =
114
115
opds.resize(ctrls[0].height)
@@ -121,6 +122,8 @@ Popping a frame first checks that the control stack is not empty.
121
122
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.
122
123
Afterwards, it checks that the stack has shrunk back to its initial height.
123
124
125
+
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.
126
+
124
127
Finally, the current frame can be marked as unreachable.
125
128
In that case, all existing operand types are purged from the operand stack, in order to allow for the :ref:`stack-polymorphism <polymorphism>` logic in :code:`pop_opd` to take effect.
126
129
@@ -163,41 +166,45 @@ Other instructions are checked in a similar manner.
0 commit comments