skip to content
==> include/wasm/opcodes.h <==
1/* @ajax/wasm-opcodes: the instruction set as data.
2 *
3 * An instruction's id is its opcode byte, or for a prefixed one (prefix << 16) | sub-opcode:
4 * i32.trunc_sat_f32_s is 0xfc0000, v128.load 0xfd0000, memory.atomic.notify 0xfe0000. For each
5 * known id wasm_op_info gives the immediates that follow it in the binary, its operand signature
6 * when it is a plain one ("ii>i": pops i32 i32, pushes i32; NULL: the validator handles it), the
7 * proposal that introduced it, and wasmparser's name for it (its Operator variant, as meshd's float
8 * guard prints it: "F32Add"). SIMD and atomics are known by their immediates only (name "Simd",
9 * "RelaxedSimd", "Atomic"): enough to walk and refuse them, not to run them. */
10#ifndef WASM_OPCODES_H
11#define WASM_OPCODES_H
12
13#include "wasm/types.h"
14
15#include <stdint.h>
16
17/* Prefixes. */
18#define WASM_PREFIX_FC 0xfc
19#define WASM_PREFIX_SIMD 0xfd
20#define WASM_PREFIX_ATOMIC 0xfe
21#define WASM_OP_FC(sub) (0xfc0000u | (sub))
22#define WASM_OP_SIMD(sub) (0xfd0000u | (sub))
23#define WASM_OP_ATOMIC(sub) (0xfe0000u | (sub))
24
25/* What follows the opcode. */
26typedef enum {
27    WASM_IMM_NONE,
28    WASM_IMM_BLOCK,         /* block type: 0x40, a value type, or an s33 type index */
29    WASM_IMM_LABEL,         /* u32 label depth */
30    WASM_IMM_BR_TABLE,      /* vec(u32) then u32 */
31    WASM_IMM_FUNC,          /* u32 function index */
32    WASM_IMM_CALL_INDIRECT, /* u32 type index, u32 table index */
33    WASM_IMM_LOCAL,         /* u32 */
34    WASM_IMM_GLOBAL,        /* u32 */
35    WASM_IMM_TABLE,         /* u32 table index */
36    WASM_IMM_MEMARG,        /* u32 align (bit 6: a memory index follows), u32 offset */
37    WASM_IMM_MEMIDX,        /* u32 memory index (memory.size, memory.grow, memory.fill) */
38    WASM_IMM_I32,           /* s32 */
39    WASM_IMM_I64,           /* s64 */
40    WASM_IMM_F32,           /* 4 bytes */
41    WASM_IMM_F64,           /* 8 bytes */
42    WASM_IMM_SELECT_T,      /* vec(valtype) */
43    WASM_IMM_REFTYPE,       /* one reference type byte */
44    WASM_IMM_MEMORY_INIT,   /* u32 data index, u32 memory index */
45    WASM_IMM_DATA,          /* u32 data index */
46    WASM_IMM_MEMORY_COPY,   /* u32 memory index, u32 memory index */
47    WASM_IMM_TABLE_INIT,    /* u32 element index, u32 table index */
48    WASM_IMM_ELEM,          /* u32 element index */
49    WASM_IMM_TABLE_COPY,    /* u32 table index, u32 table index */
50    WASM_IMM_V128,          /* 16 bytes */
51    WASM_IMM_SHUFFLE,       /* 16 lane bytes */
52    WASM_IMM_LANE,          /* 1 lane byte */
53    WASM_IMM_MEMARG_LANE,   /* memarg, then 1 lane byte */
54    WASM_IMM_ZERO_BYTE,     /* one 0x00 byte (atomic.fence) */
55} wasm_imm;
56
57typedef struct {
58    uint32_t op;
59    const char *name;     /* wasmparser's Operator variant */
60    uint8_t imm;          /* wasm_imm */
61    uint32_t feature;     /* WASM_F_* bit that introduced it; 0: the MVP */
62    const char *sig;      /* "ab>c" over i (i32) l (i64) f (f32) d (f64), or NULL */
63    uint8_t mem_bytes;    /* loads and stores: the access size in bytes; else 0 */
64} wasm_opinfo;
65
66/* The instruction with this id into *out; false when no proposal we know defines it. */
67bool wasm_op_info(uint32_t op, wasm_opinfo *out);
68
69/* The value type of a signature letter (i l f d), or 0. */
70static inline wasm_valtype wasm_sig_type(char c) {
71    switch (c) {
72    case 'i': return WASM_I32;
73    case 'l': return WASM_I64;
74    case 'f': return WASM_F32;
75    case 'd': return WASM_F64;
76    default: return 0;
77    }
78}
79
80/* The opcodes the interpreter and validator name directly. */
81enum {
82    WASM_OP_UNREACHABLE = 0x00,
83    WASM_OP_NOP = 0x01,
84    WASM_OP_BLOCK = 0x02,
85    WASM_OP_LOOP = 0x03,
86    WASM_OP_IF = 0x04,
87    WASM_OP_ELSE = 0x05,
88    WASM_OP_END = 0x0b,
89    WASM_OP_BR = 0x0c,
90    WASM_OP_BR_IF = 0x0d,
91    WASM_OP_BR_TABLE = 0x0e,
92    WASM_OP_RETURN = 0x0f,
93    WASM_OP_CALL = 0x10,
94    WASM_OP_CALL_INDIRECT = 0x11,
95    WASM_OP_DROP = 0x1a,
96    WASM_OP_SELECT = 0x1b,
97    WASM_OP_SELECT_T = 0x1c,
98    WASM_OP_LOCAL_GET = 0x20,
99    WASM_OP_LOCAL_SET = 0x21,
100    WASM_OP_LOCAL_TEE = 0x22,
101    WASM_OP_GLOBAL_GET = 0x23,
102    WASM_OP_GLOBAL_SET = 0x24,
103    WASM_OP_TABLE_GET = 0x25,
104    WASM_OP_TABLE_SET = 0x26,
105    WASM_OP_MEMORY_SIZE = 0x3f,
106    WASM_OP_MEMORY_GROW = 0x40,
107    WASM_OP_I32_CONST = 0x41,
108    WASM_OP_I64_CONST = 0x42,
109    WASM_OP_F32_CONST = 0x43,
110    WASM_OP_F64_CONST = 0x44,
111    WASM_OP_REF_NULL = 0xd0,
112    WASM_OP_REF_IS_NULL = 0xd1,
113    WASM_OP_REF_FUNC = 0xd2,
114};
115
116#define WASM_OP_MEMORY_INIT WASM_OP_FC(8)
117#define WASM_OP_DATA_DROP WASM_OP_FC(9)
118#define WASM_OP_MEMORY_COPY WASM_OP_FC(10)
119#define WASM_OP_MEMORY_FILL WASM_OP_FC(11)
120#define WASM_OP_TABLE_INIT WASM_OP_FC(12)
121#define WASM_OP_ELEM_DROP WASM_OP_FC(13)
122#define WASM_OP_TABLE_COPY WASM_OP_FC(14)
123#define WASM_OP_TABLE_GROW WASM_OP_FC(15)
124#define WASM_OP_TABLE_SIZE WASM_OP_FC(16)
125#define WASM_OP_TABLE_FILL WASM_OP_FC(17)
126
127#endif