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
return t = I32 || t = I64 || t = F32 || t = F64 || t = Unknown
32
+
33
+
func is_ref(t : val_type | Unknown) : bool =
34
+
return t = Funcref || t = Externref || t = Unknown
35
+
36
+
The algorithm uses two separate stacks: the *value stack* and the *control stack*.
25
37
The former tracks the :ref:`types <syntax-valtype>` of operand values on the :ref:`stack <stack>`,
26
38
the latter surrounding :ref:`structured control instructions <syntax-instr-control>` and their associated :ref:`blocks <syntax-instr-control>`.
27
39
28
40
.. code-block:: pseudo
29
41
30
-
type val_type = I32 | I64 | F32 | F64
31
-
32
-
type opd_stack = stack(val_type | Unknown)
42
+
type val_stack = stack(val_type | Unknown)
33
43
34
44
type ctrl_stack = stack(ctrl_frame)
35
45
type ctrl_frame = {
@@ -40,79 +50,82 @@ the latter surrounding :ref:`structured control instructions <syntax-instr-contr
40
50
unreachable : bool
41
51
}
42
52
43
-
For each value, the operand stack records its :ref:`value type <syntax-valtype>`, or :code:`Unknown` when the type is not known.
53
+
For each value, the value stack records its :ref:`value type <syntax-valtype>`, or :code:`Unknown` when the type is not known.
44
54
45
55
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).
46
56
47
57
For the purpose of presenting the algorithm, the operand and control stacks are simply maintained as global variables:
48
58
49
59
.. code-block:: pseudo
50
60
51
-
var opds : opd_stack
61
+
var vals : val_stack
52
62
var ctrls : ctrl_stack
53
63
54
64
However, these variables are not manipulated directly by the main checking function, but through a set of auxiliary functions:
55
65
56
66
.. code-block:: pseudo
57
67
58
-
func push_opd(type : val_type | Unknown) =
59
-
opds.push(type)
68
+
func push_val(type : val_type | Unknown) =
69
+
vals.push(type)
60
70
61
-
func pop_opd() : val_type | Unknown =
62
-
if (opds.size() = ctrls[0].height && ctrls[0].unreachable) return Unknown
63
-
error_if(opds.size() = ctrls[0].height)
64
-
return opds.pop()
71
+
func pop_val() : val_type | Unknown =
72
+
if (vals.size() = ctrls[0].height && ctrls[0].unreachable) return Unknown
return (if frame.opcode == loop then frame.start_types else frame.end_types)
113
126
114
127
func unreachable() =
115
-
opds.resize(ctrls[0].height)
128
+
vals.resize(ctrls[0].height)
116
129
ctrls[0].unreachable := true
117
130
118
131
Pushing a control frame takes the types of the label and result values.
@@ -125,7 +138,7 @@ Afterwards, it checks that the stack has shrunk back to its initial height.
125
138
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
139
127
140
Finally, the current frame can be marked as unreachable.
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.
141
+
In that case, all existing operand types are purged from the value stack, in order to allow for the :ref:`stack-polymorphism <polymorphism>` logic in :code:`pop_val` to take effect.
129
142
130
143
.. note::
131
144
Even with the unreachable flag set, consecutive operands are still pushed to and popped from the operand stack.
@@ -150,38 +163,46 @@ Other instructions are checked in a similar manner.
0 commit comments