| .. index:: ! instruction, code, stack machine, operand, operand stack |
| pair: abstract syntax; instruction |
| .. _syntax-instr: |
| |
| Instructions |
| ------------ |
| |
| WebAssembly code consists of sequences of *instructions*. |
| Its computational model is based on a *stack machine* in that instructions manipulate values on an implicit *operand stack*, |
| consuming (popping) argument values and producing or returning (pushing) result values. |
| |
| .. note:: |
| In the current version of WebAssembly, |
| at most one result value can be pushed by a single instruction. |
| This restriction may be lifted in future versions. |
| |
| In addition to dynamic operands from the stack, some instructions also have static *immediate* arguments, |
| typically :ref:`indices <syntax-index>` or type annotations, |
| which are part of the instruction itself. |
| |
| Some instructions are :ref:`structured <syntax-instr-control>` in that they bracket nested sequences of instructions. |
| |
| The following sections group instructions into a number of different categories. |
| |
| |
| .. index:: ! numeric instruction, value, value type, integer, floating-point, two's complement |
| pair: abstract syntax; instruction |
| .. _syntax-sx: |
| .. _syntax-const: |
| .. _syntax-unop: |
| .. _syntax-binop: |
| .. _syntax-testop: |
| .. _syntax-relop: |
| .. _syntax-cvtop: |
| .. _syntax-iunop: |
| .. _syntax-ibinop: |
| .. _syntax-itestop: |
| .. _syntax-irelop: |
| .. _syntax-funop: |
| .. _syntax-fbinop: |
| .. _syntax-ftestop: |
| .. _syntax-frelop: |
| .. _syntax-instr-numeric: |
| |
| Numeric Instructions |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| Numeric instructions provide basic operations over numeric :ref:`values <syntax-value>` of specific :ref:`type <syntax-valtype>`. |
| These operations closely match respective operations available in hardware. |
| |
| .. math:: |
| \begin{array}{llcl} |
| \production{width} & \X{nn}, \X{mm} &::=& |
| \K{32} ~|~ \K{64} \\ |
| \production{signedness} & \sx &::=& |
| \K{u} ~|~ \K{s} \\ |
| \production{instruction} & \instr &::=& |
| \K{i}\X{nn}\K{.}\CONST~\xref{syntax/values}{syntax-int}{\iX{\X{nn}}} ~|~ |
| \K{f}\X{nn}\K{.}\CONST~\xref{syntax/values}{syntax-float}{\fX{\X{nn}}} \\&&|& |
| \K{i}\X{nn}\K{.}\iunop ~|~ |
| \K{f}\X{nn}\K{.}\funop \\&&|& |
| \K{i}\X{nn}\K{.}\ibinop ~|~ |
| \K{f}\X{nn}\K{.}\fbinop \\&&|& |
| \K{i}\X{nn}\K{.}\itestop \\&&|& |
| \K{i}\X{nn}\K{.}\irelop ~|~ |
| \K{f}\X{nn}\K{.}\frelop \\&&|& |
| \K{i32.}\WRAP\K{\_i64} ~|~ |
| \K{i64.}\EXTEND\K{\_i32}\K{\_}\sx ~|~ |
| \K{i}\X{nn}\K{.}\TRUNC\K{\_f}\X{mm}\K{\_}\sx \\&&|& |
| \K{f32.}\DEMOTE\K{\_f64} ~|~ |
| \K{f64.}\PROMOTE\K{\_f32} ~|~ |
| \K{f}\X{nn}\K{.}\CONVERT\K{\_i}\X{mm}\K{\_}\sx \\&&|& |
| \K{i}\X{nn}\K{.}\REINTERPRET\K{\_f}\X{nn} ~|~ |
| \K{f}\X{nn}\K{.}\REINTERPRET\K{\_i}\X{nn} \\&&|& |
| \dots \\ |
| \production{integer unary operator} & \iunop &::=& |
| \K{clz} ~|~ |
| \K{ctz} ~|~ |
| \K{popcnt} \\ |
| \production{integer binary operator} & \ibinop &::=& |
| \K{add} ~|~ |
| \K{sub} ~|~ |
| \K{mul} ~|~ |
| \K{div\_}\sx ~|~ |
| \K{rem\_}\sx \\&&|& |
| \K{and} ~|~ |
| \K{or} ~|~ |
| \K{xor} ~|~ |
| \K{shl} ~|~ |
| \K{shr\_}\sx ~|~ |
| \K{rotl} ~|~ |
| \K{rotr} \\ |
| \production{floating-point unary operator} & \funop &::=& |
| \K{abs} ~|~ |
| \K{neg} ~|~ |
| \K{sqrt} ~|~ |
| \K{ceil} ~|~ |
| \K{floor} ~|~ |
| \K{trunc} ~|~ |
| \K{nearest} \\ |
| \production{floating-point binary operator} & \fbinop &::=& |
| \K{add} ~|~ |
| \K{sub} ~|~ |
| \K{mul} ~|~ |
| \K{div} ~|~ |
| \K{min} ~|~ |
| \K{max} ~|~ |
| \K{copysign} \\ |
| \production{integer test operator} & \itestop &::=& |
| \K{eqz} \\ |
| \production{integer relational operator} & \irelop &::=& |
| \K{eq} ~|~ |
| \K{ne} ~|~ |
| \K{lt\_}\sx ~|~ |
| \K{gt\_}\sx ~|~ |
| \K{le\_}\sx ~|~ |
| \K{ge\_}\sx \\ |
| \production{floating-point relational operator} & \frelop &::=& |
| \K{eq} ~|~ |
| \K{ne} ~|~ |
| \K{lt} ~|~ |
| \K{gt} ~|~ |
| \K{le} ~|~ |
| \K{ge} \\ |
| \end{array} |
| |
| Numeric instructions are divided by :ref:`value type <syntax-valtype>`. |
| For each type, several subcategories can be distinguished: |
| |
| * *Constants*: return a static constant. |
| |
| * *Unary Operators*: consume one operand and produce one result of the respective type. |
| |
| * *Binary Operators*: consume two operands and produce one result of the respective type. |
| |
| * *Tests*: consume one operand of the respective type and produce a Boolean integer result. |
| |
| * *Comparisons*: consume two operands of the respective type and produce a Boolean integer result. |
| |
| * *Conversions*: consume a value of one type and produce a result of another |
| (the source type of the conversion is the one after the ":math:`\K{\_}`"). |
| |
| Some integer instructions come in two flavors, |
| where a signedness annotation |sx| distinguishes whether the operands are to be :ref:`interpreted <aux-signed>` as :ref:`unsigned <syntax-uint>` or :ref:`signed <syntax-sint>` integers. |
| For the other integer instructions, the use of two's complement for the signed interpretation means that they behave the same regardless of signedness. |
| |
| |
| Conventions |
| ........... |
| |
| Occasionally, it is convenient to group operators together according to the following grammar shorthands: |
| |
| .. math:: |
| \begin{array}{llll} |
| \production{unary operator} & \unop &::=& \iunop ~|~ \funop \\ |
| \production{binary operator} & \binop &::=& \ibinop ~|~ \fbinop \\ |
| \production{test operator} & \testop &::=& \itestop \\ |
| \production{relational operator} & \relop &::=& \irelop ~|~ \frelop \\ |
| \production{conversion operator} & \cvtop &::=& |
| \WRAP ~|~ |
| \EXTEND ~|~ |
| \TRUNC ~|~ |
| \CONVERT ~|~ |
| \DEMOTE ~|~ |
| \PROMOTE ~|~ |
| \REINTERPRET \\ |
| \end{array} |
| |
| |
| .. index:: ! parametric instruction, value type |
| pair: abstract syntax; instruction |
| .. _syntax-instr-parametric: |
| |
| Parametric Instructions |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Instructions in this group can operate on operands of any :ref:`value type <syntax-valtype>`. |
| |
| .. math:: |
| \begin{array}{llcl} |
| \production{instruction} & \instr &::=& |
| \dots \\&&|& |
| \DROP \\&&|& |
| \SELECT |
| \end{array} |
| |
| The |DROP| operator simply throws away a single operand. |
| |
| The |SELECT| operator selects one of its first two operands based on whether its third operand is zero or not. |
| |
| |
| .. index:: ! variable instruction, local, global, local index, global index |
| pair: abstract syntax; instruction |
| .. _syntax-instr-variable: |
| |
| Variable Instructions |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| Variable instructions are concerned with access to :ref:`local <syntax-local>` or :ref:`global <syntax-global>` variables. |
| |
| .. math:: |
| \begin{array}{llcl} |
| \production{instruction} & \instr &::=& |
| \dots \\&&|& |
| \LOCALGET~\localidx \\&&|& |
| \LOCALSET~\localidx \\&&|& |
| \LOCALTEE~\localidx \\&&|& |
| \GLOBALGET~\globalidx \\&&|& |
| \GLOBALSET~\globalidx \\ |
| \end{array} |
| |
| These instructions get or set the values of variables, respectively. |
| The |LOCALTEE| instruction is like |LOCALSET| but also returns its argument. |
| |
| |
| .. index:: ! memory instruction, memory, memory index, page size, little endian, trap |
| pair: abstract syntax; instruction |
| .. _syntax-loadn: |
| .. _syntax-storen: |
| .. _syntax-memarg: |
| .. _syntax-instr-memory: |
| |
| Memory Instructions |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| Instructions in this group are concerned with linear :ref:`memory <syntax-mem>`. |
| |
| .. math:: |
| \begin{array}{llcl} |
| \production{memory immediate} & \memarg &::=& |
| \{ \OFFSET~\u32, \ALIGN~\u32 \} \\ |
| \production{instruction} & \instr &::=& |
| \dots \\&&|& |
| \K{i}\X{nn}\K{.}\LOAD~\memarg ~|~ |
| \K{f}\X{nn}\K{.}\LOAD~\memarg \\&&|& |
| \K{i}\X{nn}\K{.}\STORE~\memarg ~|~ |
| \K{f}\X{nn}\K{.}\STORE~\memarg \\&&|& |
| \K{i}\X{nn}\K{.}\LOAD\K{8\_}\sx~\memarg ~|~ |
| \K{i}\X{nn}\K{.}\LOAD\K{16\_}\sx~\memarg ~|~ |
| \K{i64.}\LOAD\K{32\_}\sx~\memarg \\&&|& |
| \K{i}\X{nn}\K{.}\STORE\K{8}~\memarg ~|~ |
| \K{i}\X{nn}\K{.}\STORE\K{16}~\memarg ~|~ |
| \K{i64.}\STORE\K{32}~\memarg \\&&|& |
| \MEMORYSIZE \\&&|& |
| \MEMORYGROW \\ |
| \end{array} |
| |
| Memory is accessed with |LOAD| and |STORE| instructions for the different :ref:`value types <syntax-valtype>`. |
| They all take a *memory immediate* |memarg| that contains an address *offset* and the expected *alignment* (expressed as the exponent of a power of 2). |
| Integer loads and stores can optionally specify a *storage size* that is smaller than the :ref:`bit width <syntax-valtype>` of the respective value type. |
| In the case of loads, a sign extension mode |sx| is then required to select appropriate behavior. |
| |
| The static address offset is added to the dynamic address operand, yielding a 33 bit *effective address* that is the zero-based index at which the memory is accessed. |
| All values are read and written in |LittleEndian|_ byte order. |
| A :ref:`trap <trap>` results if any of the accessed memory bytes lies outside the address range implied by the memory's current size. |
| |
| .. note:: |
| Future version of WebAssembly might provide memory instructions with 64 bit address ranges. |
| |
| The |MEMORYSIZE| instruction returns the current size of a memory. |
| The |MEMORYGROW| instruction grows memory by a given delta and returns the previous size, or :math:`-1` if enough memory cannot be allocated. |
| Both instructions operate in units of :ref:`page size <page-size>`. |
| |
| .. note:: |
| In the current version of WebAssembly, |
| all memory instructions implicitly operate on :ref:`memory <syntax-mem>` :ref:`index <syntax-memidx>` :math:`0`. |
| This restriction may be lifted in future versions. |
| |
| |
| .. index:: ! control instruction, ! structured control, ! label, ! block, ! branch, ! unwinding, result type, label index, function index, type index, vector, trap, function, table, function type |
| pair: abstract syntax; instruction |
| .. _syntax-nop: |
| .. _syntax-unreachable: |
| .. _syntax-block: |
| .. _syntax-loop: |
| .. _syntax-if: |
| .. _syntax-br: |
| .. _syntax-br_if: |
| .. _syntax-br_table: |
| .. _syntax-return: |
| .. _syntax-call: |
| .. _syntax-call_indirect: |
| .. _syntax-instr-seq: |
| .. _syntax-instr-control: |
| |
| Control Instructions |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| Instructions in this group affect the flow of control. |
| |
| .. math:: |
| \begin{array}{llcl} |
| \production{instruction} & \instr &::=& |
| \dots \\&&|& |
| \NOP \\&&|& |
| \UNREACHABLE \\&&|& |
| \BLOCK~\resulttype~\instr^\ast~\END \\&&|& |
| \LOOP~\resulttype~\instr^\ast~\END \\&&|& |
| \IF~\resulttype~\instr^\ast~\ELSE~\instr^\ast~\END \\&&|& |
| \BR~\labelidx \\&&|& |
| \BRIF~\labelidx \\&&|& |
| \BRTABLE~\vec(\labelidx)~\labelidx \\&&|& |
| \RETURN \\&&|& |
| \CALL~\funcidx \\&&|& |
| \CALLINDIRECT~\typeidx \\ |
| \end{array} |
| |
| The |NOP| instruction does nothing. |
| |
| The |UNREACHABLE| instruction causes an unconditional :ref:`trap <trap>`. |
| |
| The |BLOCK|, |LOOP| and |IF| instructions are *structured* instructions. |
| They bracket nested sequences of instructions, called *blocks*, terminated with, or separated by, |END| or |ELSE| pseudo-instructions. |
| As the grammar prescribes, they must be well-nested. |
| A structured instruction can produce a value as described by the annotated :ref:`result type <syntax-resulttype>`. |
| |
| Each structured control instruction introduces an implicit *label*. |
| Labels are targets for branch instructions that reference them with :ref:`label indices <syntax-labelidx>`. |
| Unlike with other :ref:`index spaces <syntax-index>`, indexing of labels is relative by nesting depth, |
| that is, label :math:`0` refers to the innermost structured control instruction enclosing the referring branch instruction, |
| while increasing indices refer to those farther out. |
| Consequently, labels can only be referenced from *within* the associated structured control instruction. |
| This also implies that branches can only be directed outwards, |
| "breaking" from the block of the control construct they target. |
| The exact effect depends on that control construct. |
| In case of |BLOCK| or |IF| it is a *forward jump*, |
| resuming execution after the matching |END|. |
| In case of |LOOP| it is a *backward jump* to the beginning of the loop. |
| |
| .. note:: |
| This enforces *structured control flow*. |
| Intuitively, a branch targeting a |BLOCK| or |IF| behaves like a :math:`\K{break}` statement in most C-like languages, |
| while a branch targeting a |LOOP| behaves like a :math:`\K{continue}` statement. |
| |
| Branch instructions come in several flavors: |
| |BR| performs an unconditional branch, |
| |BRIF| performs a conditional branch, |
| and |BRTABLE| performs an indirect branch through an operand indexing into the label vector that is an immediate to the instruction, or to a default target if the operand is out of bounds. |
| The |RETURN| instruction is a shortcut for an unconditional branch to the outermost block, which implicitly is the body of the current function. |
| Taking a branch *unwinds* the operand stack up to the height where the targeted structured control instruction was entered. |
| However, forward branches that target a control instruction with a non-empty result type consume matching operands first and push them back on the operand stack after unwinding, as a result for the terminated structured instruction. |
| |
| The |CALL| instruction invokes another :ref:`function <syntax-func>`, consuming the necessary arguments from the stack and returning the result values of the call. |
| The |CALLINDIRECT| instruction calls a function indirectly through an operand indexing into a :ref:`table <syntax-table>`. |
| Since tables may contain function elements of heterogeneous type |FUNCREF|, |
| the callee is dynamically checked against the :ref:`function type <syntax-functype>` indexed by the instruction's immediate, and the call aborted with a :ref:`trap <trap>` if it does not match. |
| |
| .. note:: |
| In the current version of WebAssembly, |
| |CALLINDIRECT| implicitly operates on :ref:`table <syntax-table>` :ref:`index <syntax-tableidx>` :math:`0`. |
| This restriction may be lifted in future versions. |
| |
| |
| .. index:: ! expression, constant, global, offset, element, data, instruction |
| pair: abstract syntax; expression |
| single: expression; constant |
| .. _syntax-expr: |
| |
| Expressions |
| ~~~~~~~~~~~ |
| |
| :ref:`Function <syntax-func>` bodies, initialization values for :ref:`globals <syntax-global>`, and offsets of :ref:`element <syntax-elem>` or :ref:`data <syntax-data>` segments are given as expressions, which are sequences of :ref:`instructions <syntax-instr>` terminated by an |END| marker. |
| |
| .. math:: |
| \begin{array}{llll} |
| \production{expression} & \expr &::=& |
| \instr^\ast~\END \\ |
| \end{array} |
| |
| In some places, validation :ref:`restricts <valid-constant>` expressions to be *constant*, which limits the set of allowable instructions. |