kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 333f933dd57d8ea74433ff8b24ab2972b7660d07
parent f9ebea8f994b599258edb1f80ff8c84b247b672f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed,  3 Jun 2026 10:44:47 -0700

wasm: collapse five parallel instruction switches into one WASM_INSN table

WasmInsnKind was re-derived five times that had to stay in lockstep:
encode's opcode/sub-opcode switches, the WAT mnemonic table, the WAT
parser's mnemonic->kind strcmp chain, and the disassembler's operand-class
grouping. Build one source-of-truth WASM_INSN_TABLE of
{kind, prefix, opcode byte, operand class, mnemonic} rows and derive:

  - encode: O(1) row lookup for the single-byte / 0xfc / 0xfe opcode spaces
  - wasm_insn_mnemonic: reads the mnemonic column
  - wat_instr_kind: linear scan over the table (+ a 3-entry alias list),
    has_imm derived from the operand class
  - disasm render_operands: switch on the operand class

call_ref/return_call_ref get their own WASM_OC_TYPED_REF class so they
keep encoding/printing a uleb index while the WAT grammar (which takes the
type from context) still parses no trailing immediate.

decode keeps its hand-written byte->kind arms: the per-opcode operand
reads are genuinely irregular and stay the single decode authority via
decode_body_insn. Net -1087 LOC.

The table was cross-checked against the original switches: all 216
mnemonics, 166 single-byte opcodes, 32 threads sub-opcodes, 18 misc
sub-opcodes, 216 has_imm flags, and 216 disasm operand classes match.

(cherry picked from commit 5abd92402f8c1050293bc82f1c8f5dcafe172469)

Diffstat:
Msrc/arch/wasm/disasm.c | 62+++++++++++++++++++++++++++-----------------------------------
Msrc/wasm/encode.c | 459+++----------------------------------------------------------------------------
Msrc/wasm/insn.c | 230+++----------------------------------------------------------------------------
Asrc/wasm/wasm_insn_table.c | 349+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/wasm/wasm_insn_table.h | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/wasm/wat.c | 915++++---------------------------------------------------------------------------
6 files changed, 495 insertions(+), 1582 deletions(-)

diff --git a/src/arch/wasm/disasm.c b/src/arch/wasm/disasm.c @@ -18,6 +18,7 @@ #include "core/heap.h" #include "core/strbuf.h" #include "wasm/wasm.h" +#include "wasm/wasm_insn_table.h" #define WASM_DASM_MNEM_CAP 32u #define WASM_DASM_OPS_CAP 192u @@ -70,41 +71,31 @@ static const char* valtype_name(i64 b) { } } -/* Render an instruction's immediate operands into d->ops. */ +/* Render an instruction's immediate operands into d->ops, dispatched on the + * shared operand class from WASM_INSN_TABLE rather than re-listing kinds. */ static void render_operands(WasmDisasm* d, const WasmInsn* in) { - switch ((WasmInsnKind)in->kind) { - case WASM_INSN_I32_CONST: - case WASM_INSN_I64_CONST: + const WasmInsnInfo* info = wasm_insn_info((WasmInsnKind)in->kind); + WasmOperandClass oc = info ? (WasmOperandClass)info->operand_class : WASM_OC_NONE; + switch (oc) { + case WASM_OC_SLEB: strbuf_put_i64(&d->ops, in->imm); break; - case WASM_INSN_F32_CONST: - case WASM_INSN_F64_CONST: { + case WASM_OC_FP: { char buf[40]; (void)snprintf(buf, sizeof buf, "%g", in->fp); strbuf_puts(&d->ops, buf); break; } - case WASM_INSN_LOCAL_GET: - case WASM_INSN_LOCAL_SET: - case WASM_INSN_LOCAL_TEE: - case WASM_INSN_GLOBAL_GET: - case WASM_INSN_GLOBAL_SET: - case WASM_INSN_BR: - case WASM_INSN_BR_IF: - case WASM_INSN_CALL: - case WASM_INSN_RETURN_CALL: - case WASM_INSN_REF_FUNC: - case WASM_INSN_CALL_REF: - case WASM_INSN_RETURN_CALL_REF: + case WASM_OC_IDX: + case WASM_OC_TYPED_REF: strbuf_put_u64(&d->ops, (u64)in->imm); break; - case WASM_INSN_CALL_INDIRECT: - case WASM_INSN_RETURN_CALL_INDIRECT: + case WASM_OC_CALL_INDIRECT: strbuf_put_u64(&d->ops, (u64)in->imm); strbuf_puts(&d->ops, " "); strbuf_put_u64(&d->ops, (u64)in->aux_idx); break; - case WASM_INSN_BR_TABLE: { + case WASM_OC_BR_TABLE: { u32 i; for (i = 0; i < in->ntargets; ++i) { if (i) strbuf_putc(&d->ops, ' '); @@ -112,24 +103,25 @@ static void render_operands(WasmDisasm* d, const WasmInsn* in) { } break; } - case WASM_INSN_REF_NULL: + case WASM_OC_REF_NULL: strbuf_puts(&d->ops, valtype_name(in->imm)); break; - default: - if (wasm_insn_is_mem((WasmInsnKind)in->kind)) { - int wrote = 0; - if (in->offset64) { - strbuf_puts(&d->ops, "offset="); - strbuf_put_u64(&d->ops, in->offset64); - wrote = 1; - } - if (in->align) { - if (wrote) strbuf_putc(&d->ops, ' '); - strbuf_puts(&d->ops, "align="); - strbuf_put_u64(&d->ops, (u64)(1u << in->align)); - } + case WASM_OC_MEMARG: { + int wrote = 0; + if (in->offset64) { + strbuf_puts(&d->ops, "offset="); + strbuf_put_u64(&d->ops, in->offset64); + wrote = 1; + } + if (in->align) { + if (wrote) strbuf_putc(&d->ops, ' '); + strbuf_puts(&d->ops, "align="); + strbuf_put_u64(&d->ops, (u64)(1u << in->align)); } break; + } + default: + break; } } diff --git a/src/wasm/encode.c b/src/wasm/encode.c @@ -1,4 +1,5 @@ #include "wasm/wasm.h" +#include "wasm/wasm_insn_table.h" static void write_byte(KitWriter* w, uint8_t b) { w->write(w, &b, 1); } @@ -213,457 +214,27 @@ static void enc_global(KitWriter* w, const WasmModule* m) { } } +/* Single-byte opcode for `kind` (0 if prefixed or unknown), read off the one + * WASM_INSN_TABLE map. */ static uint8_t wasm_opcode(uint8_t kind) { - switch (kind) { - case WASM_INSN_UNREACHABLE: - return 0x00; - case WASM_INSN_NOP: - return 0x01; - case WASM_INSN_BLOCK: - return 0x02; - case WASM_INSN_LOOP: - return 0x03; - case WASM_INSN_IF: - return 0x04; - case WASM_INSN_ELSE: - return 0x05; - case WASM_INSN_END: - return 0x0b; - case WASM_INSN_BR: - return 0x0c; - case WASM_INSN_BR_IF: - return 0x0d; - case WASM_INSN_BR_TABLE: - return 0x0e; - case WASM_INSN_I32_CONST: - return 0x41; - case WASM_INSN_I64_CONST: - return 0x42; - case WASM_INSN_F32_CONST: - return 0x43; - case WASM_INSN_F64_CONST: - return 0x44; - case WASM_INSN_LOCAL_GET: - return 0x20; - case WASM_INSN_LOCAL_SET: - return 0x21; - case WASM_INSN_LOCAL_TEE: - return 0x22; - case WASM_INSN_CALL: - return 0x10; - case WASM_INSN_CALL_INDIRECT: - return 0x11; - case WASM_INSN_RETURN_CALL: - return 0x12; - case WASM_INSN_RETURN_CALL_INDIRECT: - return 0x13; - case WASM_INSN_CALL_REF: - return 0x14; - case WASM_INSN_RETURN_CALL_REF: - return 0x15; - case WASM_INSN_REF_NULL: - return 0xd0; - case WASM_INSN_REF_IS_NULL: - return 0xd1; - case WASM_INSN_REF_FUNC: - return 0xd2; - case WASM_INSN_GLOBAL_GET: - return 0x23; - case WASM_INSN_GLOBAL_SET: - return 0x24; - case WASM_INSN_RETURN: - return 0x0f; - case WASM_INSN_DROP: - return 0x1a; - case WASM_INSN_SELECT: - return 0x1b; - case WASM_INSN_I32_LOAD: - return 0x28; - case WASM_INSN_I64_LOAD: - return 0x29; - case WASM_INSN_F32_LOAD: - return 0x2a; - case WASM_INSN_F64_LOAD: - return 0x2b; - case WASM_INSN_I32_LOAD8_S: - return 0x2c; - case WASM_INSN_I32_LOAD8_U: - return 0x2d; - case WASM_INSN_I32_LOAD16_S: - return 0x2e; - case WASM_INSN_I32_LOAD16_U: - return 0x2f; - case WASM_INSN_I64_LOAD8_S: - return 0x30; - case WASM_INSN_I64_LOAD8_U: - return 0x31; - case WASM_INSN_I64_LOAD16_S: - return 0x32; - case WASM_INSN_I64_LOAD16_U: - return 0x33; - case WASM_INSN_I64_LOAD32_S: - return 0x34; - case WASM_INSN_I64_LOAD32_U: - return 0x35; - case WASM_INSN_I32_STORE: - return 0x36; - case WASM_INSN_I64_STORE: - return 0x37; - case WASM_INSN_F32_STORE: - return 0x38; - case WASM_INSN_F64_STORE: - return 0x39; - case WASM_INSN_I32_STORE8: - return 0x3a; - case WASM_INSN_I32_STORE16: - return 0x3b; - case WASM_INSN_I64_STORE8: - return 0x3c; - case WASM_INSN_I64_STORE16: - return 0x3d; - case WASM_INSN_I64_STORE32: - return 0x3e; - case WASM_INSN_MEMORY_SIZE: - return 0x3f; - case WASM_INSN_MEMORY_GROW: - return 0x40; - case WASM_INSN_I32_EQZ: - return 0x45; - case WASM_INSN_I32_EQ: - return 0x46; - case WASM_INSN_I32_NE: - return 0x47; - case WASM_INSN_I32_LT_S: - return 0x48; - case WASM_INSN_I32_LT_U: - return 0x49; - case WASM_INSN_I32_GT_S: - return 0x4a; - case WASM_INSN_I32_GT_U: - return 0x4b; - case WASM_INSN_I32_LE_S: - return 0x4c; - case WASM_INSN_I32_LE_U: - return 0x4d; - case WASM_INSN_I32_GE_S: - return 0x4e; - case WASM_INSN_I32_GE_U: - return 0x4f; - case WASM_INSN_I64_EQZ: - return 0x50; - case WASM_INSN_I64_EQ: - return 0x51; - case WASM_INSN_I64_NE: - return 0x52; - case WASM_INSN_I64_LT_S: - return 0x53; - case WASM_INSN_I64_LT_U: - return 0x54; - case WASM_INSN_I64_GT_S: - return 0x55; - case WASM_INSN_I64_GT_U: - return 0x56; - case WASM_INSN_I64_LE_S: - return 0x57; - case WASM_INSN_I64_LE_U: - return 0x58; - case WASM_INSN_I64_GE_S: - return 0x59; - case WASM_INSN_I64_GE_U: - return 0x5a; - case WASM_INSN_I32_ADD: - return 0x6a; - case WASM_INSN_I32_SUB: - return 0x6b; - case WASM_INSN_I32_MUL: - return 0x6c; - case WASM_INSN_I32_DIV_S: - return 0x6d; - case WASM_INSN_I32_DIV_U: - return 0x6e; - case WASM_INSN_I32_REM_S: - return 0x6f; - case WASM_INSN_I32_REM_U: - return 0x70; - case WASM_INSN_I32_AND: - return 0x71; - case WASM_INSN_I32_OR: - return 0x72; - case WASM_INSN_I32_XOR: - return 0x73; - case WASM_INSN_I32_SHL: - return 0x74; - case WASM_INSN_I32_SHR_S: - return 0x75; - case WASM_INSN_I32_SHR_U: - return 0x76; - case WASM_INSN_I32_CLZ: - return 0x67; - case WASM_INSN_I32_CTZ: - return 0x68; - case WASM_INSN_I32_POPCNT: - return 0x69; - case WASM_INSN_I32_ROTL: - return 0x77; - case WASM_INSN_I32_ROTR: - return 0x78; - case WASM_INSN_I64_CLZ: - return 0x79; - case WASM_INSN_I64_CTZ: - return 0x7a; - case WASM_INSN_I64_POPCNT: - return 0x7b; - case WASM_INSN_I64_ADD: - return 0x7c; - case WASM_INSN_I64_SUB: - return 0x7d; - case WASM_INSN_I64_MUL: - return 0x7e; - case WASM_INSN_I64_DIV_S: - return 0x7f; - case WASM_INSN_I64_DIV_U: - return 0x80; - case WASM_INSN_I64_REM_S: - return 0x81; - case WASM_INSN_I64_REM_U: - return 0x82; - case WASM_INSN_I64_AND: - return 0x83; - case WASM_INSN_I64_OR: - return 0x84; - case WASM_INSN_I64_XOR: - return 0x85; - case WASM_INSN_I64_SHL: - return 0x86; - case WASM_INSN_I64_SHR_S: - return 0x87; - case WASM_INSN_I64_SHR_U: - return 0x88; - case WASM_INSN_I64_ROTL: - return 0x89; - case WASM_INSN_I64_ROTR: - return 0x8a; - case WASM_INSN_F32_ADD: - return 0x92; - case WASM_INSN_F32_SUB: - return 0x93; - case WASM_INSN_F32_MUL: - return 0x94; - case WASM_INSN_F32_DIV: - return 0x95; - case WASM_INSN_F64_ADD: - return 0xa0; - case WASM_INSN_F64_SUB: - return 0xa1; - case WASM_INSN_F64_MUL: - return 0xa2; - case WASM_INSN_F64_DIV: - return 0xa3; - case WASM_INSN_F32_EQ: - return 0x5b; - case WASM_INSN_F32_NE: - return 0x5c; - case WASM_INSN_F32_LT: - return 0x5d; - case WASM_INSN_F32_GT: - return 0x5e; - case WASM_INSN_F32_LE: - return 0x5f; - case WASM_INSN_F32_GE: - return 0x60; - case WASM_INSN_F64_EQ: - return 0x61; - case WASM_INSN_F64_NE: - return 0x62; - case WASM_INSN_F64_LT: - return 0x63; - case WASM_INSN_F64_GT: - return 0x64; - case WASM_INSN_F64_LE: - return 0x65; - case WASM_INSN_F64_GE: - return 0x66; - case WASM_INSN_F32_NEG: - return 0x8c; - case WASM_INSN_F64_NEG: - return 0x9a; - case WASM_INSN_I32_WRAP_I64: - return 0xa7; - case WASM_INSN_I32_TRUNC_F32_S: - return 0xa8; - case WASM_INSN_I32_TRUNC_F32_U: - return 0xa9; - case WASM_INSN_I32_TRUNC_F64_S: - return 0xaa; - case WASM_INSN_I32_TRUNC_F64_U: - return 0xab; - case WASM_INSN_I64_EXTEND_I32_S: - return 0xac; - case WASM_INSN_I64_EXTEND_I32_U: - return 0xad; - case WASM_INSN_I64_TRUNC_F32_S: - return 0xae; - case WASM_INSN_I64_TRUNC_F32_U: - return 0xaf; - case WASM_INSN_I64_TRUNC_F64_S: - return 0xb0; - case WASM_INSN_I64_TRUNC_F64_U: - return 0xb1; - case WASM_INSN_F32_CONVERT_I32_S: - return 0xb2; - case WASM_INSN_F32_CONVERT_I32_U: - return 0xb3; - case WASM_INSN_F32_CONVERT_I64_S: - return 0xb4; - case WASM_INSN_F32_CONVERT_I64_U: - return 0xb5; - case WASM_INSN_F32_DEMOTE_F64: - return 0xb6; - case WASM_INSN_F64_CONVERT_I32_S: - return 0xb7; - case WASM_INSN_F64_CONVERT_I32_U: - return 0xb8; - case WASM_INSN_F64_CONVERT_I64_S: - return 0xb9; - case WASM_INSN_F64_CONVERT_I64_U: - return 0xba; - case WASM_INSN_F64_PROMOTE_F32: - return 0xbb; - case WASM_INSN_I32_REINTERPRET_F32: - return 0xbc; - case WASM_INSN_I64_REINTERPRET_F64: - return 0xbd; - case WASM_INSN_F32_REINTERPRET_I32: - return 0xbe; - case WASM_INSN_F64_REINTERPRET_I64: - return 0xbf; - case WASM_INSN_I32_EXTEND8_S: - return 0xc0; - case WASM_INSN_I32_EXTEND16_S: - return 0xc1; - case WASM_INSN_I64_EXTEND8_S: - return 0xc2; - case WASM_INSN_I64_EXTEND16_S: - return 0xc3; - case WASM_INSN_I64_EXTEND32_S: - return 0xc4; - } - return 0; + const WasmInsnInfo* info = wasm_insn_info((WasmInsnKind)kind); + if (!info || info->prefix != WASM_PREFIX_NONE) return 0; + return info->byte; } +/* 0xfe-prefixed (threads/atomics) sub-opcode for `kind`, or UINT32_MAX. */ static uint32_t wasm_threads_subopcode(uint8_t kind) { - switch (kind) { - case WASM_INSN_MEMORY_ATOMIC_NOTIFY: - return 0x00; - case WASM_INSN_I32_ATOMIC_WAIT: - return 0x01; - case WASM_INSN_I64_ATOMIC_WAIT: - return 0x02; - case WASM_INSN_ATOMIC_FENCE: - return 0x03; - case WASM_INSN_I32_ATOMIC_LOAD: - return 0x10; - case WASM_INSN_I64_ATOMIC_LOAD: - return 0x11; - case WASM_INSN_I32_ATOMIC_LOAD8_U: - return 0x12; - case WASM_INSN_I32_ATOMIC_LOAD16_U: - return 0x13; - case WASM_INSN_I64_ATOMIC_LOAD8_U: - return 0x14; - case WASM_INSN_I64_ATOMIC_LOAD16_U: - return 0x15; - case WASM_INSN_I64_ATOMIC_LOAD32_U: - return 0x16; - case WASM_INSN_I32_ATOMIC_STORE: - return 0x17; - case WASM_INSN_I64_ATOMIC_STORE: - return 0x18; - case WASM_INSN_I32_ATOMIC_STORE8: - return 0x19; - case WASM_INSN_I32_ATOMIC_STORE16: - return 0x1a; - case WASM_INSN_I64_ATOMIC_STORE8: - return 0x1b; - case WASM_INSN_I64_ATOMIC_STORE16: - return 0x1c; - case WASM_INSN_I64_ATOMIC_STORE32: - return 0x1d; - case WASM_INSN_I32_ATOMIC_RMW_ADD: - return 0x1e; - case WASM_INSN_I64_ATOMIC_RMW_ADD: - return 0x1f; - case WASM_INSN_I32_ATOMIC_RMW_SUB: - return 0x25; - case WASM_INSN_I64_ATOMIC_RMW_SUB: - return 0x26; - case WASM_INSN_I32_ATOMIC_RMW_AND: - return 0x2c; - case WASM_INSN_I64_ATOMIC_RMW_AND: - return 0x2d; - case WASM_INSN_I32_ATOMIC_RMW_OR: - return 0x33; - case WASM_INSN_I64_ATOMIC_RMW_OR: - return 0x34; - case WASM_INSN_I32_ATOMIC_RMW_XOR: - return 0x3a; - case WASM_INSN_I64_ATOMIC_RMW_XOR: - return 0x3b; - case WASM_INSN_I32_ATOMIC_RMW_XCHG: - return 0x41; - case WASM_INSN_I64_ATOMIC_RMW_XCHG: - return 0x42; - case WASM_INSN_I32_ATOMIC_RMW_CMPXCHG: - return 0x48; - case WASM_INSN_I64_ATOMIC_RMW_CMPXCHG: - return 0x49; - default: - return UINT32_MAX; - } + const WasmInsnInfo* info = wasm_insn_info((WasmInsnKind)kind); + if (!info || info->prefix != WASM_PREFIX_FE) return UINT32_MAX; + return info->byte; } -/* 0xfc-prefixed sub-opcodes: non-trapping FTOI and bulk memory ops. */ +/* 0xfc-prefixed sub-opcode (non-trapping FTOI + bulk memory/table) for `kind`, + * or UINT32_MAX. */ static uint32_t wasm_misc_subopcode(uint8_t kind) { - switch (kind) { - case WASM_INSN_I32_TRUNC_SAT_F32_S: - return 0x00; - case WASM_INSN_I32_TRUNC_SAT_F32_U: - return 0x01; - case WASM_INSN_I32_TRUNC_SAT_F64_S: - return 0x02; - case WASM_INSN_I32_TRUNC_SAT_F64_U: - return 0x03; - case WASM_INSN_I64_TRUNC_SAT_F32_S: - return 0x04; - case WASM_INSN_I64_TRUNC_SAT_F32_U: - return 0x05; - case WASM_INSN_I64_TRUNC_SAT_F64_S: - return 0x06; - case WASM_INSN_I64_TRUNC_SAT_F64_U: - return 0x07; - case WASM_INSN_MEMORY_INIT: - return 0x08; - case WASM_INSN_DATA_DROP: - return 0x09; - case WASM_INSN_MEMORY_COPY: - return 0x0a; - case WASM_INSN_MEMORY_FILL: - return 0x0b; - case WASM_INSN_TABLE_INIT: - return 0x0c; - case WASM_INSN_ELEM_DROP: - return 0x0d; - case WASM_INSN_TABLE_COPY: - return 0x0e; - case WASM_INSN_TABLE_GROW: - return 0x0f; - case WASM_INSN_TABLE_SIZE: - return 0x10; - case WASM_INSN_TABLE_FILL: - return 0x11; - default: - return UINT32_MAX; - } + const WasmInsnInfo* info = wasm_insn_info((WasmInsnKind)kind); + if (!info || info->prefix != WASM_PREFIX_FC) return UINT32_MAX; + return info->byte; } static void enc_code(KitWriter* w, const WasmModule* m) { diff --git a/src/wasm/insn.c b/src/wasm/insn.c @@ -1,4 +1,5 @@ #include "wasm/wasm.h" +#include "wasm/wasm_insn_table.h" int wasm_is_num_type(WasmValType vt) { return vt == WASM_VAL_I32 || vt == WASM_VAL_I64 || vt == WASM_VAL_F32 || @@ -434,229 +435,10 @@ int wasm_conversion_kind(uint8_t kind, WasmValType* src, WasmValType* dst) { } } -/* WAT mnemonic for an instruction kind. Spellings match the WAT parser in - * wat.c so the disassembler and assembler agree. Returns ".unknown" for any - * out-of-range kind rather than NULL so callers can print unconditionally. */ +/* WAT mnemonic for an instruction kind. Spellings live in WASM_INSN_TABLE so + * the encoder, disassembler, and WAT parser all agree. Returns ".unknown" for + * any out-of-range kind rather than NULL so callers can print unconditionally. */ const char* wasm_insn_mnemonic(WasmInsnKind kind) { - static const char* const names[] = { - [WASM_INSN_UNREACHABLE] = "unreachable", - [WASM_INSN_NOP] = "nop", - [WASM_INSN_BLOCK] = "block", - [WASM_INSN_LOOP] = "loop", - [WASM_INSN_IF] = "if", - [WASM_INSN_ELSE] = "else", - [WASM_INSN_END] = "end", - [WASM_INSN_BR] = "br", - [WASM_INSN_BR_IF] = "br_if", - [WASM_INSN_BR_TABLE] = "br_table", - [WASM_INSN_SELECT] = "select", - [WASM_INSN_F32_CONST] = "f32.const", - [WASM_INSN_F64_CONST] = "f64.const", - [WASM_INSN_I32_CONST] = "i32.const", - [WASM_INSN_I64_CONST] = "i64.const", - [WASM_INSN_LOCAL_GET] = "local.get", - [WASM_INSN_LOCAL_SET] = "local.set", - [WASM_INSN_LOCAL_TEE] = "local.tee", - [WASM_INSN_CALL] = "call", - [WASM_INSN_CALL_INDIRECT] = "call_indirect", - [WASM_INSN_RETURN_CALL] = "return_call", - [WASM_INSN_RETURN_CALL_INDIRECT] = "return_call_indirect", - [WASM_INSN_REF_NULL] = "ref.null", - [WASM_INSN_REF_FUNC] = "ref.func", - [WASM_INSN_REF_IS_NULL] = "ref.is_null", - [WASM_INSN_CALL_REF] = "call_ref", - [WASM_INSN_RETURN_CALL_REF] = "return_call_ref", - [WASM_INSN_GLOBAL_GET] = "global.get", - [WASM_INSN_GLOBAL_SET] = "global.set", - [WASM_INSN_RETURN] = "return", - [WASM_INSN_DROP] = "drop", - [WASM_INSN_I32_LOAD] = "i32.load", - [WASM_INSN_I64_LOAD] = "i64.load", - [WASM_INSN_F32_LOAD] = "f32.load", - [WASM_INSN_F64_LOAD] = "f64.load", - [WASM_INSN_I32_LOAD8_S] = "i32.load8_s", - [WASM_INSN_I32_LOAD8_U] = "i32.load8_u", - [WASM_INSN_I32_LOAD16_S] = "i32.load16_s", - [WASM_INSN_I32_LOAD16_U] = "i32.load16_u", - [WASM_INSN_I64_LOAD8_S] = "i64.load8_s", - [WASM_INSN_I64_LOAD8_U] = "i64.load8_u", - [WASM_INSN_I64_LOAD16_S] = "i64.load16_s", - [WASM_INSN_I64_LOAD16_U] = "i64.load16_u", - [WASM_INSN_I64_LOAD32_S] = "i64.load32_s", - [WASM_INSN_I64_LOAD32_U] = "i64.load32_u", - [WASM_INSN_I32_STORE] = "i32.store", - [WASM_INSN_I64_STORE] = "i64.store", - [WASM_INSN_F32_STORE] = "f32.store", - [WASM_INSN_F64_STORE] = "f64.store", - [WASM_INSN_I32_STORE8] = "i32.store8", - [WASM_INSN_I32_STORE16] = "i32.store16", - [WASM_INSN_I64_STORE8] = "i64.store8", - [WASM_INSN_I64_STORE16] = "i64.store16", - [WASM_INSN_I64_STORE32] = "i64.store32", - [WASM_INSN_MEMORY_SIZE] = "memory.size", - [WASM_INSN_MEMORY_GROW] = "memory.grow", - [WASM_INSN_ATOMIC_FENCE] = "atomic.fence", - [WASM_INSN_I32_ATOMIC_LOAD] = "i32.atomic.load", - [WASM_INSN_I64_ATOMIC_LOAD] = "i64.atomic.load", - [WASM_INSN_I32_ATOMIC_LOAD8_U] = "i32.atomic.load8_u", - [WASM_INSN_I32_ATOMIC_LOAD16_U] = "i32.atomic.load16_u", - [WASM_INSN_I64_ATOMIC_LOAD8_U] = "i64.atomic.load8_u", - [WASM_INSN_I64_ATOMIC_LOAD16_U] = "i64.atomic.load16_u", - [WASM_INSN_I64_ATOMIC_LOAD32_U] = "i64.atomic.load32_u", - [WASM_INSN_I32_ATOMIC_STORE] = "i32.atomic.store", - [WASM_INSN_I64_ATOMIC_STORE] = "i64.atomic.store", - [WASM_INSN_I32_ATOMIC_STORE8] = "i32.atomic.store8", - [WASM_INSN_I32_ATOMIC_STORE16] = "i32.atomic.store16", - [WASM_INSN_I64_ATOMIC_STORE8] = "i64.atomic.store8", - [WASM_INSN_I64_ATOMIC_STORE16] = "i64.atomic.store16", - [WASM_INSN_I64_ATOMIC_STORE32] = "i64.atomic.store32", - [WASM_INSN_I32_ATOMIC_RMW_ADD] = "i32.atomic.rmw.add", - [WASM_INSN_I64_ATOMIC_RMW_ADD] = "i64.atomic.rmw.add", - [WASM_INSN_I32_ATOMIC_RMW_SUB] = "i32.atomic.rmw.sub", - [WASM_INSN_I64_ATOMIC_RMW_SUB] = "i64.atomic.rmw.sub", - [WASM_INSN_I32_ATOMIC_RMW_AND] = "i32.atomic.rmw.and", - [WASM_INSN_I64_ATOMIC_RMW_AND] = "i64.atomic.rmw.and", - [WASM_INSN_I32_ATOMIC_RMW_OR] = "i32.atomic.rmw.or", - [WASM_INSN_I64_ATOMIC_RMW_OR] = "i64.atomic.rmw.or", - [WASM_INSN_I32_ATOMIC_RMW_XOR] = "i32.atomic.rmw.xor", - [WASM_INSN_I64_ATOMIC_RMW_XOR] = "i64.atomic.rmw.xor", - [WASM_INSN_I32_ATOMIC_RMW_XCHG] = "i32.atomic.rmw.xchg", - [WASM_INSN_I64_ATOMIC_RMW_XCHG] = "i64.atomic.rmw.xchg", - [WASM_INSN_I32_ATOMIC_RMW_CMPXCHG] = "i32.atomic.rmw.cmpxchg", - [WASM_INSN_I64_ATOMIC_RMW_CMPXCHG] = "i64.atomic.rmw.cmpxchg", - [WASM_INSN_I32_ATOMIC_WAIT] = "memory.atomic.wait32", - [WASM_INSN_I64_ATOMIC_WAIT] = "memory.atomic.wait64", - [WASM_INSN_MEMORY_ATOMIC_NOTIFY] = "memory.atomic.notify", - [WASM_INSN_I32_ADD] = "i32.add", - [WASM_INSN_I32_SUB] = "i32.sub", - [WASM_INSN_I32_MUL] = "i32.mul", - [WASM_INSN_I32_DIV_S] = "i32.div_s", - [WASM_INSN_I32_DIV_U] = "i32.div_u", - [WASM_INSN_I32_REM_S] = "i32.rem_s", - [WASM_INSN_I32_REM_U] = "i32.rem_u", - [WASM_INSN_I32_AND] = "i32.and", - [WASM_INSN_I32_OR] = "i32.or", - [WASM_INSN_I32_XOR] = "i32.xor", - [WASM_INSN_I32_SHL] = "i32.shl", - [WASM_INSN_I32_SHR_S] = "i32.shr_s", - [WASM_INSN_I32_SHR_U] = "i32.shr_u", - [WASM_INSN_I32_ROTL] = "i32.rotl", - [WASM_INSN_I32_ROTR] = "i32.rotr", - [WASM_INSN_I32_CLZ] = "i32.clz", - [WASM_INSN_I32_CTZ] = "i32.ctz", - [WASM_INSN_I32_POPCNT] = "i32.popcnt", - [WASM_INSN_I32_EQZ] = "i32.eqz", - [WASM_INSN_I32_EQ] = "i32.eq", - [WASM_INSN_I32_NE] = "i32.ne", - [WASM_INSN_I32_LT_S] = "i32.lt_s", - [WASM_INSN_I32_LT_U] = "i32.lt_u", - [WASM_INSN_I32_GT_S] = "i32.gt_s", - [WASM_INSN_I32_GT_U] = "i32.gt_u", - [WASM_INSN_I32_LE_S] = "i32.le_s", - [WASM_INSN_I32_LE_U] = "i32.le_u", - [WASM_INSN_I32_GE_S] = "i32.ge_s", - [WASM_INSN_I32_GE_U] = "i32.ge_u", - [WASM_INSN_I64_ADD] = "i64.add", - [WASM_INSN_I64_SUB] = "i64.sub", - [WASM_INSN_I64_MUL] = "i64.mul", - [WASM_INSN_I64_DIV_S] = "i64.div_s", - [WASM_INSN_I64_DIV_U] = "i64.div_u", - [WASM_INSN_I64_REM_S] = "i64.rem_s", - [WASM_INSN_I64_REM_U] = "i64.rem_u", - [WASM_INSN_I64_AND] = "i64.and", - [WASM_INSN_I64_OR] = "i64.or", - [WASM_INSN_I64_XOR] = "i64.xor", - [WASM_INSN_I64_SHL] = "i64.shl", - [WASM_INSN_I64_SHR_S] = "i64.shr_s", - [WASM_INSN_I64_SHR_U] = "i64.shr_u", - [WASM_INSN_I64_ROTL] = "i64.rotl", - [WASM_INSN_I64_ROTR] = "i64.rotr", - [WASM_INSN_I64_CLZ] = "i64.clz", - [WASM_INSN_I64_CTZ] = "i64.ctz", - [WASM_INSN_I64_POPCNT] = "i64.popcnt", - [WASM_INSN_I64_EQZ] = "i64.eqz", - [WASM_INSN_I64_EQ] = "i64.eq", - [WASM_INSN_I64_NE] = "i64.ne", - [WASM_INSN_I64_LT_S] = "i64.lt_s", - [WASM_INSN_I64_LT_U] = "i64.lt_u", - [WASM_INSN_I64_GT_S] = "i64.gt_s", - [WASM_INSN_I64_GT_U] = "i64.gt_u", - [WASM_INSN_I64_LE_S] = "i64.le_s", - [WASM_INSN_I64_LE_U] = "i64.le_u", - [WASM_INSN_I64_GE_S] = "i64.ge_s", - [WASM_INSN_I64_GE_U] = "i64.ge_u", - [WASM_INSN_F32_ADD] = "f32.add", - [WASM_INSN_F32_SUB] = "f32.sub", - [WASM_INSN_F32_MUL] = "f32.mul", - [WASM_INSN_F32_DIV] = "f32.div", - [WASM_INSN_F32_EQ] = "f32.eq", - [WASM_INSN_F32_NE] = "f32.ne", - [WASM_INSN_F32_LT] = "f32.lt", - [WASM_INSN_F32_GT] = "f32.gt", - [WASM_INSN_F32_LE] = "f32.le", - [WASM_INSN_F32_GE] = "f32.ge", - [WASM_INSN_F64_ADD] = "f64.add", - [WASM_INSN_F64_SUB] = "f64.sub", - [WASM_INSN_F64_MUL] = "f64.mul", - [WASM_INSN_F64_DIV] = "f64.div", - [WASM_INSN_F64_EQ] = "f64.eq", - [WASM_INSN_F64_NE] = "f64.ne", - [WASM_INSN_F64_LT] = "f64.lt", - [WASM_INSN_F64_GT] = "f64.gt", - [WASM_INSN_F64_LE] = "f64.le", - [WASM_INSN_F64_GE] = "f64.ge", - [WASM_INSN_F32_NEG] = "f32.neg", - [WASM_INSN_F64_NEG] = "f64.neg", - [WASM_INSN_I32_WRAP_I64] = "i32.wrap_i64", - [WASM_INSN_I32_TRUNC_F32_S] = "i32.trunc_f32_s", - [WASM_INSN_I32_TRUNC_F32_U] = "i32.trunc_f32_u", - [WASM_INSN_I32_TRUNC_F64_S] = "i32.trunc_f64_s", - [WASM_INSN_I32_TRUNC_F64_U] = "i32.trunc_f64_u", - [WASM_INSN_I64_EXTEND_I32_S] = "i64.extend_i32_s", - [WASM_INSN_I64_EXTEND_I32_U] = "i64.extend_i32_u", - [WASM_INSN_I64_TRUNC_F32_S] = "i64.trunc_f32_s", - [WASM_INSN_I64_TRUNC_F32_U] = "i64.trunc_f32_u", - [WASM_INSN_I64_TRUNC_F64_S] = "i64.trunc_f64_s", - [WASM_INSN_I64_TRUNC_F64_U] = "i64.trunc_f64_u", - [WASM_INSN_F32_CONVERT_I32_S] = "f32.convert_i32_s", - [WASM_INSN_F32_CONVERT_I32_U] = "f32.convert_i32_u", - [WASM_INSN_F32_CONVERT_I64_S] = "f32.convert_i64_s", - [WASM_INSN_F32_CONVERT_I64_U] = "f32.convert_i64_u", - [WASM_INSN_F32_DEMOTE_F64] = "f32.demote_f64", - [WASM_INSN_F64_CONVERT_I32_S] = "f64.convert_i32_s", - [WASM_INSN_F64_CONVERT_I32_U] = "f64.convert_i32_u", - [WASM_INSN_F64_CONVERT_I64_S] = "f64.convert_i64_s", - [WASM_INSN_F64_CONVERT_I64_U] = "f64.convert_i64_u", - [WASM_INSN_F64_PROMOTE_F32] = "f64.promote_f32", - [WASM_INSN_I32_REINTERPRET_F32] = "i32.reinterpret_f32", - [WASM_INSN_I64_REINTERPRET_F64] = "i64.reinterpret_f64", - [WASM_INSN_F32_REINTERPRET_I32] = "f32.reinterpret_i32", - [WASM_INSN_F64_REINTERPRET_I64] = "f64.reinterpret_i64", - [WASM_INSN_I32_EXTEND8_S] = "i32.extend8_s", - [WASM_INSN_I32_EXTEND16_S] = "i32.extend16_s", - [WASM_INSN_I64_EXTEND8_S] = "i64.extend8_s", - [WASM_INSN_I64_EXTEND16_S] = "i64.extend16_s", - [WASM_INSN_I64_EXTEND32_S] = "i64.extend32_s", - [WASM_INSN_I32_TRUNC_SAT_F32_S] = "i32.trunc_sat_f32_s", - [WASM_INSN_I32_TRUNC_SAT_F32_U] = "i32.trunc_sat_f32_u", - [WASM_INSN_I32_TRUNC_SAT_F64_S] = "i32.trunc_sat_f64_s", - [WASM_INSN_I32_TRUNC_SAT_F64_U] = "i32.trunc_sat_f64_u", - [WASM_INSN_I64_TRUNC_SAT_F32_S] = "i64.trunc_sat_f32_s", - [WASM_INSN_I64_TRUNC_SAT_F32_U] = "i64.trunc_sat_f32_u", - [WASM_INSN_I64_TRUNC_SAT_F64_S] = "i64.trunc_sat_f64_s", - [WASM_INSN_I64_TRUNC_SAT_F64_U] = "i64.trunc_sat_f64_u", - [WASM_INSN_MEMORY_INIT] = "memory.init", - [WASM_INSN_DATA_DROP] = "data.drop", - [WASM_INSN_MEMORY_COPY] = "memory.copy", - [WASM_INSN_MEMORY_FILL] = "memory.fill", - [WASM_INSN_TABLE_INIT] = "table.init", - [WASM_INSN_ELEM_DROP] = "elem.drop", - [WASM_INSN_TABLE_COPY] = "table.copy", - [WASM_INSN_TABLE_GROW] = "table.grow", - [WASM_INSN_TABLE_SIZE] = "table.size", - [WASM_INSN_TABLE_FILL] = "table.fill", - }; - if ((unsigned)kind >= sizeof(names) / sizeof(names[0]) || !names[kind]) - return ".unknown"; - return names[kind]; + const WasmInsnInfo* info = wasm_insn_info(kind); + return info ? info->mnemonic : ".unknown"; } diff --git a/src/wasm/wasm_insn_table.c b/src/wasm/wasm_insn_table.c @@ -0,0 +1,349 @@ +#include "wasm/wasm_insn_table.h" + +/* The one map. Each row is {kind, prefix, opcode-byte, operand-class, mnemonic}. + * Rows are designated-initialized by kind so the array stays enum-indexed (the + * mnemonic helper, encode's O(1) lookup, and the byte->kind reverse index all + * rely on that). Opcode bytes and prefixes mirror the Wasm binary format; + * operand classes mirror how encode writes / decode reads / WAT parses the + * immediates. */ +#define I(k, pfx, b, oc, mn) \ + [k] = {(uint8_t)(k), (uint8_t)(pfx), (uint8_t)(b), (uint8_t)(oc), mn} + +static const WasmInsnInfo WASM_INSN_TABLE[] = { + I(WASM_INSN_UNREACHABLE, WASM_PREFIX_NONE, 0x00, WASM_OC_NONE, + "unreachable"), + I(WASM_INSN_NOP, WASM_PREFIX_NONE, 0x01, WASM_OC_NONE, "nop"), + I(WASM_INSN_BLOCK, WASM_PREFIX_NONE, 0x02, WASM_OC_BLOCK_TYPE, "block"), + I(WASM_INSN_LOOP, WASM_PREFIX_NONE, 0x03, WASM_OC_BLOCK_TYPE, "loop"), + I(WASM_INSN_IF, WASM_PREFIX_NONE, 0x04, WASM_OC_BLOCK_TYPE, "if"), + I(WASM_INSN_ELSE, WASM_PREFIX_NONE, 0x05, WASM_OC_NONE, "else"), + I(WASM_INSN_END, WASM_PREFIX_NONE, 0x0b, WASM_OC_NONE, "end"), + I(WASM_INSN_BR, WASM_PREFIX_NONE, 0x0c, WASM_OC_IDX, "br"), + I(WASM_INSN_BR_IF, WASM_PREFIX_NONE, 0x0d, WASM_OC_IDX, "br_if"), + I(WASM_INSN_BR_TABLE, WASM_PREFIX_NONE, 0x0e, WASM_OC_BR_TABLE, "br_table"), + I(WASM_INSN_SELECT, WASM_PREFIX_NONE, 0x1b, WASM_OC_NONE, "select"), + I(WASM_INSN_F32_CONST, WASM_PREFIX_NONE, 0x43, WASM_OC_FP, "f32.const"), + I(WASM_INSN_F64_CONST, WASM_PREFIX_NONE, 0x44, WASM_OC_FP, "f64.const"), + I(WASM_INSN_I32_CONST, WASM_PREFIX_NONE, 0x41, WASM_OC_SLEB, "i32.const"), + I(WASM_INSN_I64_CONST, WASM_PREFIX_NONE, 0x42, WASM_OC_SLEB, "i64.const"), + I(WASM_INSN_LOCAL_GET, WASM_PREFIX_NONE, 0x20, WASM_OC_IDX, "local.get"), + I(WASM_INSN_LOCAL_SET, WASM_PREFIX_NONE, 0x21, WASM_OC_IDX, "local.set"), + I(WASM_INSN_LOCAL_TEE, WASM_PREFIX_NONE, 0x22, WASM_OC_IDX, "local.tee"), + I(WASM_INSN_CALL, WASM_PREFIX_NONE, 0x10, WASM_OC_IDX, "call"), + I(WASM_INSN_CALL_INDIRECT, WASM_PREFIX_NONE, 0x11, WASM_OC_CALL_INDIRECT, + "call_indirect"), + I(WASM_INSN_RETURN_CALL, WASM_PREFIX_NONE, 0x12, WASM_OC_IDX, + "return_call"), + I(WASM_INSN_RETURN_CALL_INDIRECT, WASM_PREFIX_NONE, 0x13, + WASM_OC_CALL_INDIRECT, "return_call_indirect"), + I(WASM_INSN_REF_NULL, WASM_PREFIX_NONE, 0xd0, WASM_OC_REF_NULL, "ref.null"), + I(WASM_INSN_REF_FUNC, WASM_PREFIX_NONE, 0xd2, WASM_OC_IDX, "ref.func"), + I(WASM_INSN_REF_IS_NULL, WASM_PREFIX_NONE, 0xd1, WASM_OC_NONE, + "ref.is_null"), + I(WASM_INSN_CALL_REF, WASM_PREFIX_NONE, 0x14, WASM_OC_TYPED_REF, + "call_ref"), + I(WASM_INSN_RETURN_CALL_REF, WASM_PREFIX_NONE, 0x15, WASM_OC_TYPED_REF, + "return_call_ref"), + I(WASM_INSN_GLOBAL_GET, WASM_PREFIX_NONE, 0x23, WASM_OC_IDX, "global.get"), + I(WASM_INSN_GLOBAL_SET, WASM_PREFIX_NONE, 0x24, WASM_OC_IDX, "global.set"), + I(WASM_INSN_RETURN, WASM_PREFIX_NONE, 0x0f, WASM_OC_NONE, "return"), + I(WASM_INSN_DROP, WASM_PREFIX_NONE, 0x1a, WASM_OC_NONE, "drop"), + I(WASM_INSN_I32_LOAD, WASM_PREFIX_NONE, 0x28, WASM_OC_MEMARG, "i32.load"), + I(WASM_INSN_I64_LOAD, WASM_PREFIX_NONE, 0x29, WASM_OC_MEMARG, "i64.load"), + I(WASM_INSN_F32_LOAD, WASM_PREFIX_NONE, 0x2a, WASM_OC_MEMARG, "f32.load"), + I(WASM_INSN_F64_LOAD, WASM_PREFIX_NONE, 0x2b, WASM_OC_MEMARG, "f64.load"), + I(WASM_INSN_I32_LOAD8_S, WASM_PREFIX_NONE, 0x2c, WASM_OC_MEMARG, + "i32.load8_s"), + I(WASM_INSN_I32_LOAD8_U, WASM_PREFIX_NONE, 0x2d, WASM_OC_MEMARG, + "i32.load8_u"), + I(WASM_INSN_I32_LOAD16_S, WASM_PREFIX_NONE, 0x2e, WASM_OC_MEMARG, + "i32.load16_s"), + I(WASM_INSN_I32_LOAD16_U, WASM_PREFIX_NONE, 0x2f, WASM_OC_MEMARG, + "i32.load16_u"), + I(WASM_INSN_I64_LOAD8_S, WASM_PREFIX_NONE, 0x30, WASM_OC_MEMARG, + "i64.load8_s"), + I(WASM_INSN_I64_LOAD8_U, WASM_PREFIX_NONE, 0x31, WASM_OC_MEMARG, + "i64.load8_u"), + I(WASM_INSN_I64_LOAD16_S, WASM_PREFIX_NONE, 0x32, WASM_OC_MEMARG, + "i64.load16_s"), + I(WASM_INSN_I64_LOAD16_U, WASM_PREFIX_NONE, 0x33, WASM_OC_MEMARG, + "i64.load16_u"), + I(WASM_INSN_I64_LOAD32_S, WASM_PREFIX_NONE, 0x34, WASM_OC_MEMARG, + "i64.load32_s"), + I(WASM_INSN_I64_LOAD32_U, WASM_PREFIX_NONE, 0x35, WASM_OC_MEMARG, + "i64.load32_u"), + I(WASM_INSN_I32_STORE, WASM_PREFIX_NONE, 0x36, WASM_OC_MEMARG, "i32.store"), + I(WASM_INSN_I64_STORE, WASM_PREFIX_NONE, 0x37, WASM_OC_MEMARG, "i64.store"), + I(WASM_INSN_F32_STORE, WASM_PREFIX_NONE, 0x38, WASM_OC_MEMARG, "f32.store"), + I(WASM_INSN_F64_STORE, WASM_PREFIX_NONE, 0x39, WASM_OC_MEMARG, "f64.store"), + I(WASM_INSN_I32_STORE8, WASM_PREFIX_NONE, 0x3a, WASM_OC_MEMARG, + "i32.store8"), + I(WASM_INSN_I32_STORE16, WASM_PREFIX_NONE, 0x3b, WASM_OC_MEMARG, + "i32.store16"), + I(WASM_INSN_I64_STORE8, WASM_PREFIX_NONE, 0x3c, WASM_OC_MEMARG, + "i64.store8"), + I(WASM_INSN_I64_STORE16, WASM_PREFIX_NONE, 0x3d, WASM_OC_MEMARG, + "i64.store16"), + I(WASM_INSN_I64_STORE32, WASM_PREFIX_NONE, 0x3e, WASM_OC_MEMARG, + "i64.store32"), + I(WASM_INSN_MEMORY_SIZE, WASM_PREFIX_NONE, 0x3f, WASM_OC_MEM_IDX, + "memory.size"), + I(WASM_INSN_MEMORY_GROW, WASM_PREFIX_NONE, 0x40, WASM_OC_MEM_IDX, + "memory.grow"), + I(WASM_INSN_ATOMIC_FENCE, WASM_PREFIX_FE, 0x03, WASM_OC_FENCE, + "atomic.fence"), + I(WASM_INSN_I32_ATOMIC_LOAD, WASM_PREFIX_FE, 0x10, WASM_OC_MEMARG, + "i32.atomic.load"), + I(WASM_INSN_I64_ATOMIC_LOAD, WASM_PREFIX_FE, 0x11, WASM_OC_MEMARG, + "i64.atomic.load"), + I(WASM_INSN_I32_ATOMIC_LOAD8_U, WASM_PREFIX_FE, 0x12, WASM_OC_MEMARG, + "i32.atomic.load8_u"), + I(WASM_INSN_I32_ATOMIC_LOAD16_U, WASM_PREFIX_FE, 0x13, WASM_OC_MEMARG, + "i32.atomic.load16_u"), + I(WASM_INSN_I64_ATOMIC_LOAD8_U, WASM_PREFIX_FE, 0x14, WASM_OC_MEMARG, + "i64.atomic.load8_u"), + I(WASM_INSN_I64_ATOMIC_LOAD16_U, WASM_PREFIX_FE, 0x15, WASM_OC_MEMARG, + "i64.atomic.load16_u"), + I(WASM_INSN_I64_ATOMIC_LOAD32_U, WASM_PREFIX_FE, 0x16, WASM_OC_MEMARG, + "i64.atomic.load32_u"), + I(WASM_INSN_I32_ATOMIC_STORE, WASM_PREFIX_FE, 0x17, WASM_OC_MEMARG, + "i32.atomic.store"), + I(WASM_INSN_I64_ATOMIC_STORE, WASM_PREFIX_FE, 0x18, WASM_OC_MEMARG, + "i64.atomic.store"), + I(WASM_INSN_I32_ATOMIC_STORE8, WASM_PREFIX_FE, 0x19, WASM_OC_MEMARG, + "i32.atomic.store8"), + I(WASM_INSN_I32_ATOMIC_STORE16, WASM_PREFIX_FE, 0x1a, WASM_OC_MEMARG, + "i32.atomic.store16"), + I(WASM_INSN_I64_ATOMIC_STORE8, WASM_PREFIX_FE, 0x1b, WASM_OC_MEMARG, + "i64.atomic.store8"), + I(WASM_INSN_I64_ATOMIC_STORE16, WASM_PREFIX_FE, 0x1c, WASM_OC_MEMARG, + "i64.atomic.store16"), + I(WASM_INSN_I64_ATOMIC_STORE32, WASM_PREFIX_FE, 0x1d, WASM_OC_MEMARG, + "i64.atomic.store32"), + I(WASM_INSN_I32_ATOMIC_RMW_ADD, WASM_PREFIX_FE, 0x1e, WASM_OC_MEMARG, + "i32.atomic.rmw.add"), + I(WASM_INSN_I64_ATOMIC_RMW_ADD, WASM_PREFIX_FE, 0x1f, WASM_OC_MEMARG, + "i64.atomic.rmw.add"), + I(WASM_INSN_I32_ATOMIC_RMW_SUB, WASM_PREFIX_FE, 0x25, WASM_OC_MEMARG, + "i32.atomic.rmw.sub"), + I(WASM_INSN_I64_ATOMIC_RMW_SUB, WASM_PREFIX_FE, 0x26, WASM_OC_MEMARG, + "i64.atomic.rmw.sub"), + I(WASM_INSN_I32_ATOMIC_RMW_AND, WASM_PREFIX_FE, 0x2c, WASM_OC_MEMARG, + "i32.atomic.rmw.and"), + I(WASM_INSN_I64_ATOMIC_RMW_AND, WASM_PREFIX_FE, 0x2d, WASM_OC_MEMARG, + "i64.atomic.rmw.and"), + I(WASM_INSN_I32_ATOMIC_RMW_OR, WASM_PREFIX_FE, 0x33, WASM_OC_MEMARG, + "i32.atomic.rmw.or"), + I(WASM_INSN_I64_ATOMIC_RMW_OR, WASM_PREFIX_FE, 0x34, WASM_OC_MEMARG, + "i64.atomic.rmw.or"), + I(WASM_INSN_I32_ATOMIC_RMW_XOR, WASM_PREFIX_FE, 0x3a, WASM_OC_MEMARG, + "i32.atomic.rmw.xor"), + I(WASM_INSN_I64_ATOMIC_RMW_XOR, WASM_PREFIX_FE, 0x3b, WASM_OC_MEMARG, + "i64.atomic.rmw.xor"), + I(WASM_INSN_I32_ATOMIC_RMW_XCHG, WASM_PREFIX_FE, 0x41, WASM_OC_MEMARG, + "i32.atomic.rmw.xchg"), + I(WASM_INSN_I64_ATOMIC_RMW_XCHG, WASM_PREFIX_FE, 0x42, WASM_OC_MEMARG, + "i64.atomic.rmw.xchg"), + I(WASM_INSN_I32_ATOMIC_RMW_CMPXCHG, WASM_PREFIX_FE, 0x48, WASM_OC_MEMARG, + "i32.atomic.rmw.cmpxchg"), + I(WASM_INSN_I64_ATOMIC_RMW_CMPXCHG, WASM_PREFIX_FE, 0x49, WASM_OC_MEMARG, + "i64.atomic.rmw.cmpxchg"), + I(WASM_INSN_I32_ATOMIC_WAIT, WASM_PREFIX_FE, 0x01, WASM_OC_MEMARG, + "memory.atomic.wait32"), + I(WASM_INSN_I64_ATOMIC_WAIT, WASM_PREFIX_FE, 0x02, WASM_OC_MEMARG, + "memory.atomic.wait64"), + I(WASM_INSN_MEMORY_ATOMIC_NOTIFY, WASM_PREFIX_FE, 0x00, WASM_OC_MEMARG, + "memory.atomic.notify"), + I(WASM_INSN_I32_ADD, WASM_PREFIX_NONE, 0x6a, WASM_OC_NONE, "i32.add"), + I(WASM_INSN_I32_SUB, WASM_PREFIX_NONE, 0x6b, WASM_OC_NONE, "i32.sub"), + I(WASM_INSN_I32_MUL, WASM_PREFIX_NONE, 0x6c, WASM_OC_NONE, "i32.mul"), + I(WASM_INSN_I32_DIV_S, WASM_PREFIX_NONE, 0x6d, WASM_OC_NONE, "i32.div_s"), + I(WASM_INSN_I32_DIV_U, WASM_PREFIX_NONE, 0x6e, WASM_OC_NONE, "i32.div_u"), + I(WASM_INSN_I32_REM_S, WASM_PREFIX_NONE, 0x6f, WASM_OC_NONE, "i32.rem_s"), + I(WASM_INSN_I32_REM_U, WASM_PREFIX_NONE, 0x70, WASM_OC_NONE, "i32.rem_u"), + I(WASM_INSN_I32_AND, WASM_PREFIX_NONE, 0x71, WASM_OC_NONE, "i32.and"), + I(WASM_INSN_I32_OR, WASM_PREFIX_NONE, 0x72, WASM_OC_NONE, "i32.or"), + I(WASM_INSN_I32_XOR, WASM_PREFIX_NONE, 0x73, WASM_OC_NONE, "i32.xor"), + I(WASM_INSN_I32_SHL, WASM_PREFIX_NONE, 0x74, WASM_OC_NONE, "i32.shl"), + I(WASM_INSN_I32_SHR_S, WASM_PREFIX_NONE, 0x75, WASM_OC_NONE, "i32.shr_s"), + I(WASM_INSN_I32_SHR_U, WASM_PREFIX_NONE, 0x76, WASM_OC_NONE, "i32.shr_u"), + I(WASM_INSN_I32_ROTL, WASM_PREFIX_NONE, 0x77, WASM_OC_NONE, "i32.rotl"), + I(WASM_INSN_I32_ROTR, WASM_PREFIX_NONE, 0x78, WASM_OC_NONE, "i32.rotr"), + I(WASM_INSN_I32_CLZ, WASM_PREFIX_NONE, 0x67, WASM_OC_NONE, "i32.clz"), + I(WASM_INSN_I32_CTZ, WASM_PREFIX_NONE, 0x68, WASM_OC_NONE, "i32.ctz"), + I(WASM_INSN_I32_POPCNT, WASM_PREFIX_NONE, 0x69, WASM_OC_NONE, "i32.popcnt"), + I(WASM_INSN_I32_EQZ, WASM_PREFIX_NONE, 0x45, WASM_OC_NONE, "i32.eqz"), + I(WASM_INSN_I32_EQ, WASM_PREFIX_NONE, 0x46, WASM_OC_NONE, "i32.eq"), + I(WASM_INSN_I32_NE, WASM_PREFIX_NONE, 0x47, WASM_OC_NONE, "i32.ne"), + I(WASM_INSN_I32_LT_S, WASM_PREFIX_NONE, 0x48, WASM_OC_NONE, "i32.lt_s"), + I(WASM_INSN_I32_LT_U, WASM_PREFIX_NONE, 0x49, WASM_OC_NONE, "i32.lt_u"), + I(WASM_INSN_I32_GT_S, WASM_PREFIX_NONE, 0x4a, WASM_OC_NONE, "i32.gt_s"), + I(WASM_INSN_I32_GT_U, WASM_PREFIX_NONE, 0x4b, WASM_OC_NONE, "i32.gt_u"), + I(WASM_INSN_I32_LE_S, WASM_PREFIX_NONE, 0x4c, WASM_OC_NONE, "i32.le_s"), + I(WASM_INSN_I32_LE_U, WASM_PREFIX_NONE, 0x4d, WASM_OC_NONE, "i32.le_u"), + I(WASM_INSN_I32_GE_S, WASM_PREFIX_NONE, 0x4e, WASM_OC_NONE, "i32.ge_s"), + I(WASM_INSN_I32_GE_U, WASM_PREFIX_NONE, 0x4f, WASM_OC_NONE, "i32.ge_u"), + I(WASM_INSN_I64_ADD, WASM_PREFIX_NONE, 0x7c, WASM_OC_NONE, "i64.add"), + I(WASM_INSN_I64_SUB, WASM_PREFIX_NONE, 0x7d, WASM_OC_NONE, "i64.sub"), + I(WASM_INSN_I64_MUL, WASM_PREFIX_NONE, 0x7e, WASM_OC_NONE, "i64.mul"), + I(WASM_INSN_I64_DIV_S, WASM_PREFIX_NONE, 0x7f, WASM_OC_NONE, "i64.div_s"), + I(WASM_INSN_I64_DIV_U, WASM_PREFIX_NONE, 0x80, WASM_OC_NONE, "i64.div_u"), + I(WASM_INSN_I64_REM_S, WASM_PREFIX_NONE, 0x81, WASM_OC_NONE, "i64.rem_s"), + I(WASM_INSN_I64_REM_U, WASM_PREFIX_NONE, 0x82, WASM_OC_NONE, "i64.rem_u"), + I(WASM_INSN_I64_AND, WASM_PREFIX_NONE, 0x83, WASM_OC_NONE, "i64.and"), + I(WASM_INSN_I64_OR, WASM_PREFIX_NONE, 0x84, WASM_OC_NONE, "i64.or"), + I(WASM_INSN_I64_XOR, WASM_PREFIX_NONE, 0x85, WASM_OC_NONE, "i64.xor"), + I(WASM_INSN_I64_SHL, WASM_PREFIX_NONE, 0x86, WASM_OC_NONE, "i64.shl"), + I(WASM_INSN_I64_SHR_S, WASM_PREFIX_NONE, 0x87, WASM_OC_NONE, "i64.shr_s"), + I(WASM_INSN_I64_SHR_U, WASM_PREFIX_NONE, 0x88, WASM_OC_NONE, "i64.shr_u"), + I(WASM_INSN_I64_ROTL, WASM_PREFIX_NONE, 0x89, WASM_OC_NONE, "i64.rotl"), + I(WASM_INSN_I64_ROTR, WASM_PREFIX_NONE, 0x8a, WASM_OC_NONE, "i64.rotr"), + I(WASM_INSN_I64_CLZ, WASM_PREFIX_NONE, 0x79, WASM_OC_NONE, "i64.clz"), + I(WASM_INSN_I64_CTZ, WASM_PREFIX_NONE, 0x7a, WASM_OC_NONE, "i64.ctz"), + I(WASM_INSN_I64_POPCNT, WASM_PREFIX_NONE, 0x7b, WASM_OC_NONE, "i64.popcnt"), + I(WASM_INSN_I64_EQZ, WASM_PREFIX_NONE, 0x50, WASM_OC_NONE, "i64.eqz"), + I(WASM_INSN_I64_EQ, WASM_PREFIX_NONE, 0x51, WASM_OC_NONE, "i64.eq"), + I(WASM_INSN_I64_NE, WASM_PREFIX_NONE, 0x52, WASM_OC_NONE, "i64.ne"), + I(WASM_INSN_I64_LT_S, WASM_PREFIX_NONE, 0x53, WASM_OC_NONE, "i64.lt_s"), + I(WASM_INSN_I64_LT_U, WASM_PREFIX_NONE, 0x54, WASM_OC_NONE, "i64.lt_u"), + I(WASM_INSN_I64_GT_S, WASM_PREFIX_NONE, 0x55, WASM_OC_NONE, "i64.gt_s"), + I(WASM_INSN_I64_GT_U, WASM_PREFIX_NONE, 0x56, WASM_OC_NONE, "i64.gt_u"), + I(WASM_INSN_I64_LE_S, WASM_PREFIX_NONE, 0x57, WASM_OC_NONE, "i64.le_s"), + I(WASM_INSN_I64_LE_U, WASM_PREFIX_NONE, 0x58, WASM_OC_NONE, "i64.le_u"), + I(WASM_INSN_I64_GE_S, WASM_PREFIX_NONE, 0x59, WASM_OC_NONE, "i64.ge_s"), + I(WASM_INSN_I64_GE_U, WASM_PREFIX_NONE, 0x5a, WASM_OC_NONE, "i64.ge_u"), + I(WASM_INSN_F32_ADD, WASM_PREFIX_NONE, 0x92, WASM_OC_NONE, "f32.add"), + I(WASM_INSN_F32_SUB, WASM_PREFIX_NONE, 0x93, WASM_OC_NONE, "f32.sub"), + I(WASM_INSN_F32_MUL, WASM_PREFIX_NONE, 0x94, WASM_OC_NONE, "f32.mul"), + I(WASM_INSN_F32_DIV, WASM_PREFIX_NONE, 0x95, WASM_OC_NONE, "f32.div"), + I(WASM_INSN_F32_EQ, WASM_PREFIX_NONE, 0x5b, WASM_OC_NONE, "f32.eq"), + I(WASM_INSN_F32_NE, WASM_PREFIX_NONE, 0x5c, WASM_OC_NONE, "f32.ne"), + I(WASM_INSN_F32_LT, WASM_PREFIX_NONE, 0x5d, WASM_OC_NONE, "f32.lt"), + I(WASM_INSN_F32_GT, WASM_PREFIX_NONE, 0x5e, WASM_OC_NONE, "f32.gt"), + I(WASM_INSN_F32_LE, WASM_PREFIX_NONE, 0x5f, WASM_OC_NONE, "f32.le"), + I(WASM_INSN_F32_GE, WASM_PREFIX_NONE, 0x60, WASM_OC_NONE, "f32.ge"), + I(WASM_INSN_F64_ADD, WASM_PREFIX_NONE, 0xa0, WASM_OC_NONE, "f64.add"), + I(WASM_INSN_F64_SUB, WASM_PREFIX_NONE, 0xa1, WASM_OC_NONE, "f64.sub"), + I(WASM_INSN_F64_MUL, WASM_PREFIX_NONE, 0xa2, WASM_OC_NONE, "f64.mul"), + I(WASM_INSN_F64_DIV, WASM_PREFIX_NONE, 0xa3, WASM_OC_NONE, "f64.div"), + I(WASM_INSN_F64_EQ, WASM_PREFIX_NONE, 0x61, WASM_OC_NONE, "f64.eq"), + I(WASM_INSN_F64_NE, WASM_PREFIX_NONE, 0x62, WASM_OC_NONE, "f64.ne"), + I(WASM_INSN_F64_LT, WASM_PREFIX_NONE, 0x63, WASM_OC_NONE, "f64.lt"), + I(WASM_INSN_F64_GT, WASM_PREFIX_NONE, 0x64, WASM_OC_NONE, "f64.gt"), + I(WASM_INSN_F64_LE, WASM_PREFIX_NONE, 0x65, WASM_OC_NONE, "f64.le"), + I(WASM_INSN_F64_GE, WASM_PREFIX_NONE, 0x66, WASM_OC_NONE, "f64.ge"), + I(WASM_INSN_F32_NEG, WASM_PREFIX_NONE, 0x8c, WASM_OC_NONE, "f32.neg"), + I(WASM_INSN_F64_NEG, WASM_PREFIX_NONE, 0x9a, WASM_OC_NONE, "f64.neg"), + I(WASM_INSN_I32_WRAP_I64, WASM_PREFIX_NONE, 0xa7, WASM_OC_NONE, + "i32.wrap_i64"), + I(WASM_INSN_I32_TRUNC_F32_S, WASM_PREFIX_NONE, 0xa8, WASM_OC_NONE, + "i32.trunc_f32_s"), + I(WASM_INSN_I32_TRUNC_F32_U, WASM_PREFIX_NONE, 0xa9, WASM_OC_NONE, + "i32.trunc_f32_u"), + I(WASM_INSN_I32_TRUNC_F64_S, WASM_PREFIX_NONE, 0xaa, WASM_OC_NONE, + "i32.trunc_f64_s"), + I(WASM_INSN_I32_TRUNC_F64_U, WASM_PREFIX_NONE, 0xab, WASM_OC_NONE, + "i32.trunc_f64_u"), + I(WASM_INSN_I64_EXTEND_I32_S, WASM_PREFIX_NONE, 0xac, WASM_OC_NONE, + "i64.extend_i32_s"), + I(WASM_INSN_I64_EXTEND_I32_U, WASM_PREFIX_NONE, 0xad, WASM_OC_NONE, + "i64.extend_i32_u"), + I(WASM_INSN_I64_TRUNC_F32_S, WASM_PREFIX_NONE, 0xae, WASM_OC_NONE, + "i64.trunc_f32_s"), + I(WASM_INSN_I64_TRUNC_F32_U, WASM_PREFIX_NONE, 0xaf, WASM_OC_NONE, + "i64.trunc_f32_u"), + I(WASM_INSN_I64_TRUNC_F64_S, WASM_PREFIX_NONE, 0xb0, WASM_OC_NONE, + "i64.trunc_f64_s"), + I(WASM_INSN_I64_TRUNC_F64_U, WASM_PREFIX_NONE, 0xb1, WASM_OC_NONE, + "i64.trunc_f64_u"), + I(WASM_INSN_F32_CONVERT_I32_S, WASM_PREFIX_NONE, 0xb2, WASM_OC_NONE, + "f32.convert_i32_s"), + I(WASM_INSN_F32_CONVERT_I32_U, WASM_PREFIX_NONE, 0xb3, WASM_OC_NONE, + "f32.convert_i32_u"), + I(WASM_INSN_F32_CONVERT_I64_S, WASM_PREFIX_NONE, 0xb4, WASM_OC_NONE, + "f32.convert_i64_s"), + I(WASM_INSN_F32_CONVERT_I64_U, WASM_PREFIX_NONE, 0xb5, WASM_OC_NONE, + "f32.convert_i64_u"), + I(WASM_INSN_F32_DEMOTE_F64, WASM_PREFIX_NONE, 0xb6, WASM_OC_NONE, + "f32.demote_f64"), + I(WASM_INSN_F64_CONVERT_I32_S, WASM_PREFIX_NONE, 0xb7, WASM_OC_NONE, + "f64.convert_i32_s"), + I(WASM_INSN_F64_CONVERT_I32_U, WASM_PREFIX_NONE, 0xb8, WASM_OC_NONE, + "f64.convert_i32_u"), + I(WASM_INSN_F64_CONVERT_I64_S, WASM_PREFIX_NONE, 0xb9, WASM_OC_NONE, + "f64.convert_i64_s"), + I(WASM_INSN_F64_CONVERT_I64_U, WASM_PREFIX_NONE, 0xba, WASM_OC_NONE, + "f64.convert_i64_u"), + I(WASM_INSN_F64_PROMOTE_F32, WASM_PREFIX_NONE, 0xbb, WASM_OC_NONE, + "f64.promote_f32"), + I(WASM_INSN_I32_REINTERPRET_F32, WASM_PREFIX_NONE, 0xbc, WASM_OC_NONE, + "i32.reinterpret_f32"), + I(WASM_INSN_I64_REINTERPRET_F64, WASM_PREFIX_NONE, 0xbd, WASM_OC_NONE, + "i64.reinterpret_f64"), + I(WASM_INSN_F32_REINTERPRET_I32, WASM_PREFIX_NONE, 0xbe, WASM_OC_NONE, + "f32.reinterpret_i32"), + I(WASM_INSN_F64_REINTERPRET_I64, WASM_PREFIX_NONE, 0xbf, WASM_OC_NONE, + "f64.reinterpret_i64"), + I(WASM_INSN_I32_EXTEND8_S, WASM_PREFIX_NONE, 0xc0, WASM_OC_NONE, + "i32.extend8_s"), + I(WASM_INSN_I32_EXTEND16_S, WASM_PREFIX_NONE, 0xc1, WASM_OC_NONE, + "i32.extend16_s"), + I(WASM_INSN_I64_EXTEND8_S, WASM_PREFIX_NONE, 0xc2, WASM_OC_NONE, + "i64.extend8_s"), + I(WASM_INSN_I64_EXTEND16_S, WASM_PREFIX_NONE, 0xc3, WASM_OC_NONE, + "i64.extend16_s"), + I(WASM_INSN_I64_EXTEND32_S, WASM_PREFIX_NONE, 0xc4, WASM_OC_NONE, + "i64.extend32_s"), + I(WASM_INSN_I32_TRUNC_SAT_F32_S, WASM_PREFIX_FC, 0x00, WASM_OC_NONE, + "i32.trunc_sat_f32_s"), + I(WASM_INSN_I32_TRUNC_SAT_F32_U, WASM_PREFIX_FC, 0x01, WASM_OC_NONE, + "i32.trunc_sat_f32_u"), + I(WASM_INSN_I32_TRUNC_SAT_F64_S, WASM_PREFIX_FC, 0x02, WASM_OC_NONE, + "i32.trunc_sat_f64_s"), + I(WASM_INSN_I32_TRUNC_SAT_F64_U, WASM_PREFIX_FC, 0x03, WASM_OC_NONE, + "i32.trunc_sat_f64_u"), + I(WASM_INSN_I64_TRUNC_SAT_F32_S, WASM_PREFIX_FC, 0x04, WASM_OC_NONE, + "i64.trunc_sat_f32_s"), + I(WASM_INSN_I64_TRUNC_SAT_F32_U, WASM_PREFIX_FC, 0x05, WASM_OC_NONE, + "i64.trunc_sat_f32_u"), + I(WASM_INSN_I64_TRUNC_SAT_F64_S, WASM_PREFIX_FC, 0x06, WASM_OC_NONE, + "i64.trunc_sat_f64_s"), + I(WASM_INSN_I64_TRUNC_SAT_F64_U, WASM_PREFIX_FC, 0x07, WASM_OC_NONE, + "i64.trunc_sat_f64_u"), + I(WASM_INSN_MEMORY_INIT, WASM_PREFIX_FC, 0x08, WASM_OC_BULK, + "memory.init"), + I(WASM_INSN_DATA_DROP, WASM_PREFIX_FC, 0x09, WASM_OC_BULK, "data.drop"), + I(WASM_INSN_MEMORY_COPY, WASM_PREFIX_FC, 0x0a, WASM_OC_BULK, + "memory.copy"), + I(WASM_INSN_MEMORY_FILL, WASM_PREFIX_FC, 0x0b, WASM_OC_BULK, + "memory.fill"), + I(WASM_INSN_TABLE_INIT, WASM_PREFIX_FC, 0x0c, WASM_OC_BULK, "table.init"), + I(WASM_INSN_ELEM_DROP, WASM_PREFIX_FC, 0x0d, WASM_OC_BULK, "elem.drop"), + I(WASM_INSN_TABLE_COPY, WASM_PREFIX_FC, 0x0e, WASM_OC_BULK, "table.copy"), + I(WASM_INSN_TABLE_GROW, WASM_PREFIX_FC, 0x0f, WASM_OC_BULK, "table.grow"), + I(WASM_INSN_TABLE_SIZE, WASM_PREFIX_FC, 0x10, WASM_OC_BULK, "table.size"), + I(WASM_INSN_TABLE_FILL, WASM_PREFIX_FC, 0x11, WASM_OC_BULK, "table.fill"), +}; + +#undef I + +#define WASM_INSN_TABLE_LEN \ + (sizeof(WASM_INSN_TABLE) / sizeof(WASM_INSN_TABLE[0])) + +const WasmInsnInfo* wasm_insn_info(WasmInsnKind kind) { + if ((unsigned)kind >= WASM_INSN_TABLE_LEN) return NULL; + if (!WASM_INSN_TABLE[kind].mnemonic) return NULL; + return &WASM_INSN_TABLE[kind]; +} + +int wasm_operand_class_has_imm(WasmOperandClass oc) { + switch (oc) { + case WASM_OC_SLEB: + case WASM_OC_FP: + case WASM_OC_IDX: + case WASM_OC_REF_NULL: + return 1; + default: + return 0; + } +} diff --git a/src/wasm/wasm_insn_table.h b/src/wasm/wasm_insn_table.h @@ -0,0 +1,62 @@ +#ifndef KIT_WASM_INSN_TABLE_H +#define KIT_WASM_INSN_TABLE_H + +/* Single source of truth for the Wasm instruction set. + * + * WasmInsnKind is the same logical instruction described five different ways: + * its opcode bytes (encode), its byte->kind map (decode), its WAT mnemonic + * (disassembler), its mnemonic->kind map (WAT parser), and the operand class + * that drives how immediates are read/written. Historically each of those was + * its own ~200-arm switch that had to stay in lockstep. WASM_INSN_TABLE below + * is that map, written once; encode/wat/disasm derive their behaviour from it + * by O(1) row lookup or a linear scan, and the mnemonic helper reads a column. + * + * Decode keeps its hand-written arms: the per-opcode operand reads are genuinely + * irregular (two index immediates, block-type bytes, br_table vectors, ...) and + * are not worth forcing into a table; it still shares decode_body_insn so the + * byte<->kind mapping lives in exactly one place there too. */ + +#include "wasm/wasm.h" + +/* Opcode-space prefix for an instruction's encoding. */ +typedef enum WasmInsnPrefix { + WASM_PREFIX_NONE = 0, /* single-byte opcode, `byte` is the opcode */ + WASM_PREFIX_FC = 1, /* 0xfc-prefixed (misc: trunc_sat + bulk memory/table) */ + WASM_PREFIX_FE = 2, /* 0xfe-prefixed (threads/atomics) */ +} WasmInsnPrefix; + +/* Operand-class column: how an instruction's immediates are spelled. Drives + * encode (write), the disassembler's render_operands (read), and the WAT + * parser's has_imm. Classes with a trailing comment of "has_imm" are the ones + * for which the WAT grammar parses a single trailing immediate token. */ +typedef enum WasmOperandClass { + WASM_OC_NONE = 0, /* no immediate */ + WASM_OC_SLEB, /* i32/i64.const signed leb (has_imm) */ + WASM_OC_FP, /* f32/f64.const float literal (has_imm) */ + WASM_OC_IDX, /* one uleb index immediate (has_imm) */ + WASM_OC_TYPED_REF, /* call_ref/return_call_ref: uleb typeidx, but WAT + * takes the type from context, so no trailing token */ + WASM_OC_REF_NULL, /* ref.null valtype (has_imm) */ + WASM_OC_CALL_INDIRECT, /* typeidx + tableidx */ + WASM_OC_BR_TABLE, /* label vector + default */ + WASM_OC_BLOCK_TYPE, /* block/loop/if: 0x40 blocktype byte */ + WASM_OC_MEMARG, /* memory access: align/offset/memidx */ + WASM_OC_MEM_IDX, /* memory.size/grow: single memidx */ + WASM_OC_BULK, /* 0xfc bulk memory/table ops, irregular index slots */ + WASM_OC_FENCE, /* atomic.fence: a single 0x00 byte */ +} WasmOperandClass; + +typedef struct WasmInsnInfo { + uint8_t kind; /* WasmInsnKind; rows are enum-indexed */ + uint8_t prefix; /* WasmInsnPrefix */ + uint8_t byte; /* opcode byte (PREFIX_NONE) or sub-opcode otherwise */ + uint8_t operand_class; /* WasmOperandClass */ + const char* mnemonic; /* canonical WAT spelling; never NULL in-table */ +} WasmInsnInfo; + +/* Row for `kind`, or NULL if out of range. O(1). */ +const WasmInsnInfo* wasm_insn_info(WasmInsnKind kind); +/* WAT operand-token presence derived from the operand class. */ +int wasm_operand_class_has_imm(WasmOperandClass oc); + +#endif diff --git a/src/wasm/wat.c b/src/wasm/wat.c @@ -1,6 +1,7 @@ #include <kit/source.h> #include "wasm/wasm.h" +#include "wasm/wasm_insn_table.h" typedef struct WasmTok { const char* p; @@ -329,888 +330,44 @@ static void wat_skip_list(WatParser* p) { } } +/* A handful of mnemonics have legacy spellings that map to the same kind as + * their canonical WASM_INSN_TABLE name; the table carries only the canonical + * spelling, so these aliases are checked separately. */ +static const struct { + const char* mnemonic; + WasmInsnKind kind; +} WAT_INSN_ALIASES[] = { + {"i32.atomic.wait", WASM_INSN_I32_ATOMIC_WAIT}, + {"i64.atomic.wait", WASM_INSN_I64_ATOMIC_WAIT}, + {"atomic.notify", WASM_INSN_MEMORY_ATOMIC_NOTIFY}, +}; + +/* Resolve a WAT mnemonic token to its instruction kind via a linear scan over + * the single WASM_INSN_TABLE map (same set, same semantics as the former + * 200-arm strcmp chain), plus a tiny alias list. `has_imm` reflects whether the + * grammar parses one trailing immediate token, derived from the operand + * class. */ static int wat_instr_kind(WasmTok t, WasmInsnKind* out, int* has_imm) { *has_imm = 0; - if (tok_is(t, "unreachable")) { - *out = WASM_INSN_UNREACHABLE; - return 1; - } - if (tok_is(t, "nop")) { - *out = WASM_INSN_NOP; - return 1; - } - if (tok_is(t, "block")) { - *out = WASM_INSN_BLOCK; - return 1; - } - if (tok_is(t, "loop")) { - *out = WASM_INSN_LOOP; - return 1; - } - if (tok_is(t, "if")) { - *out = WASM_INSN_IF; - return 1; - } - if (tok_is(t, "else")) { - *out = WASM_INSN_ELSE; - return 1; - } - if (tok_is(t, "end")) { - *out = WASM_INSN_END; - return 1; - } - if (tok_is(t, "br")) { - *out = WASM_INSN_BR; - *has_imm = 1; - return 1; - } - if (tok_is(t, "br_if")) { - *out = WASM_INSN_BR_IF; - *has_imm = 1; - return 1; - } - if (tok_is(t, "br_table")) { - *out = WASM_INSN_BR_TABLE; - return 1; - } - if (tok_is(t, "select")) { - *out = WASM_INSN_SELECT; - return 1; - } - if (tok_is(t, "f32.const")) { - *out = WASM_INSN_F32_CONST; - *has_imm = 1; - return 1; - } - if (tok_is(t, "f64.const")) { - *out = WASM_INSN_F64_CONST; - *has_imm = 1; - return 1; - } - if (tok_is(t, "i32.const")) { - *out = WASM_INSN_I32_CONST; - *has_imm = 1; - return 1; - } - if (tok_is(t, "i64.const")) { - *out = WASM_INSN_I64_CONST; - *has_imm = 1; - return 1; - } - if (tok_is(t, "local.get")) { - *out = WASM_INSN_LOCAL_GET; - *has_imm = 1; - return 1; - } - if (tok_is(t, "local.set")) { - *out = WASM_INSN_LOCAL_SET; - *has_imm = 1; - return 1; - } - if (tok_is(t, "local.tee")) { - *out = WASM_INSN_LOCAL_TEE; - *has_imm = 1; - return 1; - } - if (tok_is(t, "call")) { - *out = WASM_INSN_CALL; - *has_imm = 1; - return 1; - } - if (tok_is(t, "call_indirect")) { - *out = WASM_INSN_CALL_INDIRECT; - return 1; - } - if (tok_is(t, "call_ref")) { - *out = WASM_INSN_CALL_REF; - return 1; - } - if (tok_is(t, "return_call")) { - *out = WASM_INSN_RETURN_CALL; - *has_imm = 1; - return 1; - } - if (tok_is(t, "return_call_indirect")) { - *out = WASM_INSN_RETURN_CALL_INDIRECT; - return 1; - } - if (tok_is(t, "return_call_ref")) { - *out = WASM_INSN_RETURN_CALL_REF; - return 1; - } - if (tok_is(t, "ref.null")) { - *out = WASM_INSN_REF_NULL; - *has_imm = 1; - return 1; - } - if (tok_is(t, "ref.func")) { - *out = WASM_INSN_REF_FUNC; - *has_imm = 1; - return 1; - } - if (tok_is(t, "ref.is_null")) { - *out = WASM_INSN_REF_IS_NULL; - return 1; - } - if (tok_is(t, "global.get")) { - *out = WASM_INSN_GLOBAL_GET; - *has_imm = 1; - return 1; - } - if (tok_is(t, "global.set")) { - *out = WASM_INSN_GLOBAL_SET; - *has_imm = 1; - return 1; - } - if (tok_is(t, "return")) { - *out = WASM_INSN_RETURN; - return 1; - } - if (tok_is(t, "drop")) { - *out = WASM_INSN_DROP; - return 1; - } - if (tok_is(t, "atomic.fence")) { - *out = WASM_INSN_ATOMIC_FENCE; - return 1; - } - if (tok_is(t, "i32.load")) { - *out = WASM_INSN_I32_LOAD; - return 1; - } - if (tok_is(t, "i32.atomic.load")) { - *out = WASM_INSN_I32_ATOMIC_LOAD; - return 1; - } - if (tok_is(t, "i64.load")) { - *out = WASM_INSN_I64_LOAD; - return 1; - } - if (tok_is(t, "f32.load")) { - *out = WASM_INSN_F32_LOAD; - return 1; - } - if (tok_is(t, "f64.load")) { - *out = WASM_INSN_F64_LOAD; - return 1; - } - if (tok_is(t, "i64.atomic.load")) { - *out = WASM_INSN_I64_ATOMIC_LOAD; - return 1; - } - if (tok_is(t, "i32.load8_s")) { - *out = WASM_INSN_I32_LOAD8_S; - return 1; - } - if (tok_is(t, "i32.load8_u")) { - *out = WASM_INSN_I32_LOAD8_U; - return 1; - } - if (tok_is(t, "i32.atomic.load8_u")) { - *out = WASM_INSN_I32_ATOMIC_LOAD8_U; - return 1; - } - if (tok_is(t, "i32.load16_s")) { - *out = WASM_INSN_I32_LOAD16_S; - return 1; - } - if (tok_is(t, "i32.load16_u")) { - *out = WASM_INSN_I32_LOAD16_U; - return 1; - } - if (tok_is(t, "i32.atomic.load16_u")) { - *out = WASM_INSN_I32_ATOMIC_LOAD16_U; - return 1; - } - if (tok_is(t, "i64.load8_s")) { - *out = WASM_INSN_I64_LOAD8_S; - return 1; - } - if (tok_is(t, "i64.load8_u")) { - *out = WASM_INSN_I64_LOAD8_U; - return 1; - } - if (tok_is(t, "i64.atomic.load8_u")) { - *out = WASM_INSN_I64_ATOMIC_LOAD8_U; - return 1; - } - if (tok_is(t, "i64.load16_s")) { - *out = WASM_INSN_I64_LOAD16_S; - return 1; - } - if (tok_is(t, "i64.load16_u")) { - *out = WASM_INSN_I64_LOAD16_U; - return 1; - } - if (tok_is(t, "i64.atomic.load16_u")) { - *out = WASM_INSN_I64_ATOMIC_LOAD16_U; - return 1; - } - if (tok_is(t, "i64.load32_s")) { - *out = WASM_INSN_I64_LOAD32_S; - return 1; - } - if (tok_is(t, "i64.load32_u")) { - *out = WASM_INSN_I64_LOAD32_U; - return 1; - } - if (tok_is(t, "i64.atomic.load32_u")) { - *out = WASM_INSN_I64_ATOMIC_LOAD32_U; - return 1; - } - if (tok_is(t, "i32.store")) { - *out = WASM_INSN_I32_STORE; - return 1; - } - if (tok_is(t, "i32.atomic.store")) { - *out = WASM_INSN_I32_ATOMIC_STORE; - return 1; - } - if (tok_is(t, "i64.store")) { - *out = WASM_INSN_I64_STORE; - return 1; - } - if (tok_is(t, "f32.store")) { - *out = WASM_INSN_F32_STORE; - return 1; - } - if (tok_is(t, "f64.store")) { - *out = WASM_INSN_F64_STORE; - return 1; - } - if (tok_is(t, "i64.atomic.store")) { - *out = WASM_INSN_I64_ATOMIC_STORE; - return 1; - } - if (tok_is(t, "i32.store8")) { - *out = WASM_INSN_I32_STORE8; - return 1; - } - if (tok_is(t, "i32.atomic.store8")) { - *out = WASM_INSN_I32_ATOMIC_STORE8; - return 1; - } - if (tok_is(t, "i32.store16")) { - *out = WASM_INSN_I32_STORE16; - return 1; - } - if (tok_is(t, "i32.atomic.store16")) { - *out = WASM_INSN_I32_ATOMIC_STORE16; - return 1; - } - if (tok_is(t, "i64.store8")) { - *out = WASM_INSN_I64_STORE8; - return 1; - } - if (tok_is(t, "i64.atomic.store8")) { - *out = WASM_INSN_I64_ATOMIC_STORE8; - return 1; - } - if (tok_is(t, "i64.store16")) { - *out = WASM_INSN_I64_STORE16; - return 1; - } - if (tok_is(t, "i64.atomic.store16")) { - *out = WASM_INSN_I64_ATOMIC_STORE16; - return 1; - } - if (tok_is(t, "i64.store32")) { - *out = WASM_INSN_I64_STORE32; - return 1; - } - if (tok_is(t, "i64.atomic.store32")) { - *out = WASM_INSN_I64_ATOMIC_STORE32; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.add")) { - *out = WASM_INSN_I32_ATOMIC_RMW_ADD; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.add")) { - *out = WASM_INSN_I64_ATOMIC_RMW_ADD; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.sub")) { - *out = WASM_INSN_I32_ATOMIC_RMW_SUB; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.sub")) { - *out = WASM_INSN_I64_ATOMIC_RMW_SUB; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.and")) { - *out = WASM_INSN_I32_ATOMIC_RMW_AND; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.and")) { - *out = WASM_INSN_I64_ATOMIC_RMW_AND; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.or")) { - *out = WASM_INSN_I32_ATOMIC_RMW_OR; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.or")) { - *out = WASM_INSN_I64_ATOMIC_RMW_OR; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.xor")) { - *out = WASM_INSN_I32_ATOMIC_RMW_XOR; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.xor")) { - *out = WASM_INSN_I64_ATOMIC_RMW_XOR; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.xchg")) { - *out = WASM_INSN_I32_ATOMIC_RMW_XCHG; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.xchg")) { - *out = WASM_INSN_I64_ATOMIC_RMW_XCHG; - return 1; - } - if (tok_is(t, "i32.atomic.rmw.cmpxchg")) { - *out = WASM_INSN_I32_ATOMIC_RMW_CMPXCHG; - return 1; - } - if (tok_is(t, "i64.atomic.rmw.cmpxchg")) { - *out = WASM_INSN_I64_ATOMIC_RMW_CMPXCHG; - return 1; - } - if (tok_is(t, "memory.atomic.wait32") || tok_is(t, "i32.atomic.wait")) { - *out = WASM_INSN_I32_ATOMIC_WAIT; - return 1; - } - if (tok_is(t, "memory.atomic.wait64") || tok_is(t, "i64.atomic.wait")) { - *out = WASM_INSN_I64_ATOMIC_WAIT; - return 1; - } - if (tok_is(t, "memory.atomic.notify") || tok_is(t, "atomic.notify")) { - *out = WASM_INSN_MEMORY_ATOMIC_NOTIFY; - return 1; - } - if (tok_is(t, "memory.size")) { - *out = WASM_INSN_MEMORY_SIZE; - return 1; - } - if (tok_is(t, "memory.grow")) { - *out = WASM_INSN_MEMORY_GROW; - return 1; - } - /* Bulk memory and table ops (0xfc prefix). */ - if (tok_is(t, "memory.init")) { - *out = WASM_INSN_MEMORY_INIT; - return 1; - } - if (tok_is(t, "data.drop")) { - *out = WASM_INSN_DATA_DROP; - return 1; - } - if (tok_is(t, "memory.copy")) { - *out = WASM_INSN_MEMORY_COPY; - return 1; - } - if (tok_is(t, "memory.fill")) { - *out = WASM_INSN_MEMORY_FILL; - return 1; - } - if (tok_is(t, "table.init")) { - *out = WASM_INSN_TABLE_INIT; - return 1; - } - if (tok_is(t, "elem.drop")) { - *out = WASM_INSN_ELEM_DROP; - return 1; - } - if (tok_is(t, "table.copy")) { - *out = WASM_INSN_TABLE_COPY; - return 1; - } - if (tok_is(t, "table.grow")) { - *out = WASM_INSN_TABLE_GROW; - return 1; - } - if (tok_is(t, "table.size")) { - *out = WASM_INSN_TABLE_SIZE; - return 1; - } - if (tok_is(t, "table.fill")) { - *out = WASM_INSN_TABLE_FILL; - return 1; - } - /* Saturating float-to-int conversions. */ - if (tok_is(t, "i32.trunc_sat_f32_s")) { - *out = WASM_INSN_I32_TRUNC_SAT_F32_S; - return 1; - } - if (tok_is(t, "i32.trunc_sat_f32_u")) { - *out = WASM_INSN_I32_TRUNC_SAT_F32_U; - return 1; - } - if (tok_is(t, "i32.trunc_sat_f64_s")) { - *out = WASM_INSN_I32_TRUNC_SAT_F64_S; - return 1; - } - if (tok_is(t, "i32.trunc_sat_f64_u")) { - *out = WASM_INSN_I32_TRUNC_SAT_F64_U; - return 1; - } - if (tok_is(t, "i64.trunc_sat_f32_s")) { - *out = WASM_INSN_I64_TRUNC_SAT_F32_S; - return 1; - } - if (tok_is(t, "i64.trunc_sat_f32_u")) { - *out = WASM_INSN_I64_TRUNC_SAT_F32_U; - return 1; - } - if (tok_is(t, "i64.trunc_sat_f64_s")) { - *out = WASM_INSN_I64_TRUNC_SAT_F64_S; - return 1; - } - if (tok_is(t, "i64.trunc_sat_f64_u")) { - *out = WASM_INSN_I64_TRUNC_SAT_F64_U; - return 1; - } - if (tok_is(t, "i32.add")) { - *out = WASM_INSN_I32_ADD; - return 1; - } - if (tok_is(t, "i32.sub")) { - *out = WASM_INSN_I32_SUB; - return 1; - } - if (tok_is(t, "i32.mul")) { - *out = WASM_INSN_I32_MUL; - return 1; - } - if (tok_is(t, "i32.div_s")) { - *out = WASM_INSN_I32_DIV_S; - return 1; - } - if (tok_is(t, "i32.div_u")) { - *out = WASM_INSN_I32_DIV_U; - return 1; - } - if (tok_is(t, "i32.rem_s")) { - *out = WASM_INSN_I32_REM_S; - return 1; - } - if (tok_is(t, "i32.rem_u")) { - *out = WASM_INSN_I32_REM_U; - return 1; - } - if (tok_is(t, "i32.and")) { - *out = WASM_INSN_I32_AND; - return 1; - } - if (tok_is(t, "i32.or")) { - *out = WASM_INSN_I32_OR; - return 1; - } - if (tok_is(t, "i32.xor")) { - *out = WASM_INSN_I32_XOR; - return 1; - } - if (tok_is(t, "i32.shl")) { - *out = WASM_INSN_I32_SHL; - return 1; - } - if (tok_is(t, "i32.shr_s")) { - *out = WASM_INSN_I32_SHR_S; - return 1; - } - if (tok_is(t, "i32.shr_u")) { - *out = WASM_INSN_I32_SHR_U; - return 1; - } - if (tok_is(t, "i32.rotl")) { - *out = WASM_INSN_I32_ROTL; - return 1; - } - if (tok_is(t, "i32.rotr")) { - *out = WASM_INSN_I32_ROTR; - return 1; - } - if (tok_is(t, "i32.clz")) { - *out = WASM_INSN_I32_CLZ; - return 1; - } - if (tok_is(t, "i32.ctz")) { - *out = WASM_INSN_I32_CTZ; - return 1; - } - if (tok_is(t, "i32.popcnt")) { - *out = WASM_INSN_I32_POPCNT; - return 1; - } - if (tok_is(t, "i32.eqz")) { - *out = WASM_INSN_I32_EQZ; - return 1; - } - if (tok_is(t, "i32.eq")) { - *out = WASM_INSN_I32_EQ; - return 1; - } - if (tok_is(t, "i32.ne")) { - *out = WASM_INSN_I32_NE; - return 1; - } - if (tok_is(t, "i32.lt_s")) { - *out = WASM_INSN_I32_LT_S; - return 1; - } - if (tok_is(t, "i32.lt_u")) { - *out = WASM_INSN_I32_LT_U; - return 1; - } - if (tok_is(t, "i32.gt_s")) { - *out = WASM_INSN_I32_GT_S; - return 1; - } - if (tok_is(t, "i32.gt_u")) { - *out = WASM_INSN_I32_GT_U; - return 1; - } - if (tok_is(t, "i32.le_s")) { - *out = WASM_INSN_I32_LE_S; - return 1; - } - if (tok_is(t, "i32.le_u")) { - *out = WASM_INSN_I32_LE_U; - return 1; - } - if (tok_is(t, "i32.ge_s")) { - *out = WASM_INSN_I32_GE_S; - return 1; - } - if (tok_is(t, "i32.ge_u")) { - *out = WASM_INSN_I32_GE_U; - return 1; - } - if (tok_is(t, "i64.add")) { - *out = WASM_INSN_I64_ADD; - return 1; - } - if (tok_is(t, "i64.sub")) { - *out = WASM_INSN_I64_SUB; - return 1; - } - if (tok_is(t, "i64.mul")) { - *out = WASM_INSN_I64_MUL; - return 1; - } - if (tok_is(t, "i64.div_s")) { - *out = WASM_INSN_I64_DIV_S; - return 1; - } - if (tok_is(t, "i64.div_u")) { - *out = WASM_INSN_I64_DIV_U; - return 1; - } - if (tok_is(t, "i64.rem_s")) { - *out = WASM_INSN_I64_REM_S; - return 1; - } - if (tok_is(t, "i64.rem_u")) { - *out = WASM_INSN_I64_REM_U; - return 1; - } - if (tok_is(t, "i64.and")) { - *out = WASM_INSN_I64_AND; - return 1; - } - if (tok_is(t, "i64.or")) { - *out = WASM_INSN_I64_OR; - return 1; - } - if (tok_is(t, "i64.xor")) { - *out = WASM_INSN_I64_XOR; - return 1; - } - if (tok_is(t, "i64.shl")) { - *out = WASM_INSN_I64_SHL; - return 1; - } - if (tok_is(t, "i64.shr_s")) { - *out = WASM_INSN_I64_SHR_S; - return 1; - } - if (tok_is(t, "i64.shr_u")) { - *out = WASM_INSN_I64_SHR_U; - return 1; - } - if (tok_is(t, "i64.rotl")) { - *out = WASM_INSN_I64_ROTL; - return 1; - } - if (tok_is(t, "i64.rotr")) { - *out = WASM_INSN_I64_ROTR; - return 1; - } - if (tok_is(t, "i64.clz")) { - *out = WASM_INSN_I64_CLZ; - return 1; - } - if (tok_is(t, "i64.ctz")) { - *out = WASM_INSN_I64_CTZ; - return 1; - } - if (tok_is(t, "i64.popcnt")) { - *out = WASM_INSN_I64_POPCNT; - return 1; - } - if (tok_is(t, "i64.eqz")) { - *out = WASM_INSN_I64_EQZ; - return 1; - } - if (tok_is(t, "i64.eq")) { - *out = WASM_INSN_I64_EQ; - return 1; - } - if (tok_is(t, "i64.ne")) { - *out = WASM_INSN_I64_NE; - return 1; - } - if (tok_is(t, "i64.lt_s")) { - *out = WASM_INSN_I64_LT_S; - return 1; - } - if (tok_is(t, "i64.lt_u")) { - *out = WASM_INSN_I64_LT_U; - return 1; - } - if (tok_is(t, "i64.gt_s")) { - *out = WASM_INSN_I64_GT_S; - return 1; - } - if (tok_is(t, "i64.gt_u")) { - *out = WASM_INSN_I64_GT_U; - return 1; - } - if (tok_is(t, "i64.le_s")) { - *out = WASM_INSN_I64_LE_S; - return 1; - } - if (tok_is(t, "i64.le_u")) { - *out = WASM_INSN_I64_LE_U; - return 1; - } - if (tok_is(t, "i64.ge_s")) { - *out = WASM_INSN_I64_GE_S; - return 1; - } - if (tok_is(t, "i64.ge_u")) { - *out = WASM_INSN_I64_GE_U; - return 1; - } - if (tok_is(t, "f32.neg")) { - *out = WASM_INSN_F32_NEG; - return 1; - } - if (tok_is(t, "f64.neg")) { - *out = WASM_INSN_F64_NEG; - return 1; - } - if (tok_is(t, "f32.add")) { - *out = WASM_INSN_F32_ADD; - return 1; - } - if (tok_is(t, "f32.sub")) { - *out = WASM_INSN_F32_SUB; - return 1; - } - if (tok_is(t, "f32.mul")) { - *out = WASM_INSN_F32_MUL; - return 1; - } - if (tok_is(t, "f32.div")) { - *out = WASM_INSN_F32_DIV; - return 1; - } - if (tok_is(t, "f32.eq")) { - *out = WASM_INSN_F32_EQ; - return 1; - } - if (tok_is(t, "f32.ne")) { - *out = WASM_INSN_F32_NE; - return 1; - } - if (tok_is(t, "f32.lt")) { - *out = WASM_INSN_F32_LT; - return 1; - } - if (tok_is(t, "f32.gt")) { - *out = WASM_INSN_F32_GT; - return 1; - } - if (tok_is(t, "f32.le")) { - *out = WASM_INSN_F32_LE; - return 1; - } - if (tok_is(t, "f32.ge")) { - *out = WASM_INSN_F32_GE; - return 1; - } - if (tok_is(t, "f64.add")) { - *out = WASM_INSN_F64_ADD; - return 1; - } - if (tok_is(t, "f64.sub")) { - *out = WASM_INSN_F64_SUB; - return 1; - } - if (tok_is(t, "f64.mul")) { - *out = WASM_INSN_F64_MUL; - return 1; - } - if (tok_is(t, "f64.div")) { - *out = WASM_INSN_F64_DIV; - return 1; - } - if (tok_is(t, "f64.eq")) { - *out = WASM_INSN_F64_EQ; - return 1; - } - if (tok_is(t, "f64.ne")) { - *out = WASM_INSN_F64_NE; - return 1; - } - if (tok_is(t, "f64.lt")) { - *out = WASM_INSN_F64_LT; - return 1; - } - if (tok_is(t, "f64.gt")) { - *out = WASM_INSN_F64_GT; - return 1; - } - if (tok_is(t, "f64.le")) { - *out = WASM_INSN_F64_LE; - return 1; - } - if (tok_is(t, "f64.ge")) { - *out = WASM_INSN_F64_GE; - return 1; - } - if (tok_is(t, "i32.wrap_i64")) { - *out = WASM_INSN_I32_WRAP_I64; - return 1; - } - if (tok_is(t, "i32.trunc_f32_s")) { - *out = WASM_INSN_I32_TRUNC_F32_S; - return 1; - } - if (tok_is(t, "i32.trunc_f32_u")) { - *out = WASM_INSN_I32_TRUNC_F32_U; - return 1; - } - if (tok_is(t, "i32.trunc_f64_s")) { - *out = WASM_INSN_I32_TRUNC_F64_S; - return 1; - } - if (tok_is(t, "i32.trunc_f64_u")) { - *out = WASM_INSN_I32_TRUNC_F64_U; - return 1; - } - if (tok_is(t, "i64.extend_i32_s")) { - *out = WASM_INSN_I64_EXTEND_I32_S; - return 1; - } - if (tok_is(t, "i64.extend_i32_u")) { - *out = WASM_INSN_I64_EXTEND_I32_U; - return 1; - } - if (tok_is(t, "i64.trunc_f32_s")) { - *out = WASM_INSN_I64_TRUNC_F32_S; - return 1; - } - if (tok_is(t, "i64.trunc_f32_u")) { - *out = WASM_INSN_I64_TRUNC_F32_U; - return 1; - } - if (tok_is(t, "i64.trunc_f64_s")) { - *out = WASM_INSN_I64_TRUNC_F64_S; - return 1; - } - if (tok_is(t, "i64.trunc_f64_u")) { - *out = WASM_INSN_I64_TRUNC_F64_U; - return 1; - } - if (tok_is(t, "f32.convert_i32_s")) { - *out = WASM_INSN_F32_CONVERT_I32_S; - return 1; - } - if (tok_is(t, "f32.convert_i32_u")) { - *out = WASM_INSN_F32_CONVERT_I32_U; - return 1; - } - if (tok_is(t, "f32.convert_i64_s")) { - *out = WASM_INSN_F32_CONVERT_I64_S; - return 1; - } - if (tok_is(t, "f32.convert_i64_u")) { - *out = WASM_INSN_F32_CONVERT_I64_U; - return 1; - } - if (tok_is(t, "f32.demote_f64")) { - *out = WASM_INSN_F32_DEMOTE_F64; - return 1; - } - if (tok_is(t, "f64.convert_i32_s")) { - *out = WASM_INSN_F64_CONVERT_I32_S; - return 1; - } - if (tok_is(t, "f64.convert_i32_u")) { - *out = WASM_INSN_F64_CONVERT_I32_U; - return 1; - } - if (tok_is(t, "f64.convert_i64_s")) { - *out = WASM_INSN_F64_CONVERT_I64_S; - return 1; - } - if (tok_is(t, "f64.convert_i64_u")) { - *out = WASM_INSN_F64_CONVERT_I64_U; - return 1; - } - if (tok_is(t, "f64.promote_f32")) { - *out = WASM_INSN_F64_PROMOTE_F32; - return 1; - } - if (tok_is(t, "i32.reinterpret_f32")) { - *out = WASM_INSN_I32_REINTERPRET_F32; - return 1; - } - if (tok_is(t, "i64.reinterpret_f64")) { - *out = WASM_INSN_I64_REINTERPRET_F64; - return 1; - } - if (tok_is(t, "f32.reinterpret_i32")) { - *out = WASM_INSN_F32_REINTERPRET_I32; - return 1; - } - if (tok_is(t, "f64.reinterpret_i64")) { - *out = WASM_INSN_F64_REINTERPRET_I64; - return 1; - } - if (tok_is(t, "i32.extend8_s")) { - *out = WASM_INSN_I32_EXTEND8_S; - return 1; - } - if (tok_is(t, "i32.extend16_s")) { - *out = WASM_INSN_I32_EXTEND16_S; - return 1; - } - if (tok_is(t, "i64.extend8_s")) { - *out = WASM_INSN_I64_EXTEND8_S; - return 1; - } - if (tok_is(t, "i64.extend16_s")) { - *out = WASM_INSN_I64_EXTEND16_S; - return 1; + if (t.kind != WT_ATOM) return 0; + for (WasmInsnKind k = 0; k <= WASM_INSN_TABLE_FILL; ++k) { + const WasmInsnInfo* info = wasm_insn_info(k); + if (!info) continue; + if (tok_is(t, info->mnemonic)) { + *out = k; + *has_imm = wasm_operand_class_has_imm((WasmOperandClass)info->operand_class); + return 1; + } } - if (tok_is(t, "i64.extend32_s")) { - *out = WASM_INSN_I64_EXTEND32_S; - return 1; + for (size_t i = 0; i < sizeof(WAT_INSN_ALIASES) / sizeof(WAT_INSN_ALIASES[0]); + ++i) { + if (tok_is(t, WAT_INSN_ALIASES[i].mnemonic)) { + const WasmInsnInfo* info = wasm_insn_info(WAT_INSN_ALIASES[i].kind); + *out = WAT_INSN_ALIASES[i].kind; + *has_imm = + info && wasm_operand_class_has_imm((WasmOperandClass)info->operand_class); + return 1; + } } return 0; }