wasm_insn_table.h (3184B)
1 #ifndef KIT_WASM_INSN_TABLE_H 2 #define KIT_WASM_INSN_TABLE_H 3 4 /* Single source of truth for the Wasm instruction set. 5 * 6 * WasmInsnKind is the same logical instruction described five different ways: 7 * its opcode bytes (encode), its byte->kind map (decode), its WAT mnemonic 8 * (disassembler), its mnemonic->kind map (WAT parser), and the operand class 9 * that drives how immediates are read/written. Historically each of those was 10 * its own ~200-arm switch that had to stay in lockstep. WASM_INSN_TABLE below 11 * is that map, written once; encode/wat/disasm derive their behaviour from it 12 * by O(1) row lookup or a linear scan, and the mnemonic helper reads a column. 13 * 14 * Decode keeps its hand-written arms: the per-opcode operand reads are genuinely 15 * irregular (two index immediates, block-type bytes, br_table vectors, ...) and 16 * are not worth forcing into a table; it still shares decode_body_insn so the 17 * byte<->kind mapping lives in exactly one place there too. */ 18 19 #include "wasm/wasm.h" 20 21 /* Opcode-space prefix for an instruction's encoding. */ 22 typedef enum WasmInsnPrefix { 23 WASM_PREFIX_NONE = 0, /* single-byte opcode, `byte` is the opcode */ 24 WASM_PREFIX_FC = 1, /* 0xfc-prefixed (misc: trunc_sat + bulk memory/table) */ 25 WASM_PREFIX_FE = 2, /* 0xfe-prefixed (threads/atomics) */ 26 } WasmInsnPrefix; 27 28 /* Operand-class column: how an instruction's immediates are spelled. Drives 29 * encode (write), the disassembler's render_operands (read), and the WAT 30 * parser's has_imm. Classes with a trailing comment of "has_imm" are the ones 31 * for which the WAT grammar parses a single trailing immediate token. */ 32 typedef enum WasmOperandClass { 33 WASM_OC_NONE = 0, /* no immediate */ 34 WASM_OC_SLEB, /* i32/i64.const signed leb (has_imm) */ 35 WASM_OC_FP, /* f32/f64.const float literal (has_imm) */ 36 WASM_OC_IDX, /* one uleb index immediate (has_imm) */ 37 WASM_OC_TYPED_REF, /* call_ref/return_call_ref: uleb typeidx, but WAT 38 * takes the type from context, so no trailing token */ 39 WASM_OC_REF_NULL, /* ref.null valtype (has_imm) */ 40 WASM_OC_CALL_INDIRECT, /* typeidx + tableidx */ 41 WASM_OC_BR_TABLE, /* label vector + default */ 42 WASM_OC_BLOCK_TYPE, /* block/loop/if: 0x40 blocktype byte */ 43 WASM_OC_MEMARG, /* memory access: align/offset/memidx */ 44 WASM_OC_MEM_IDX, /* memory.size/grow: single memidx */ 45 WASM_OC_BULK, /* 0xfc bulk memory/table ops, irregular index slots */ 46 WASM_OC_FENCE, /* atomic.fence: a single 0x00 byte */ 47 } WasmOperandClass; 48 49 typedef struct WasmInsnInfo { 50 uint8_t kind; /* WasmInsnKind; rows are enum-indexed */ 51 uint8_t prefix; /* WasmInsnPrefix */ 52 uint8_t byte; /* opcode byte (PREFIX_NONE) or sub-opcode otherwise */ 53 uint8_t operand_class; /* WasmOperandClass */ 54 const char* mnemonic; /* canonical WAT spelling; never NULL in-table */ 55 } WasmInsnInfo; 56 57 /* Row for `kind`, or NULL if out of range. O(1). */ 58 const WasmInsnInfo* wasm_insn_info(WasmInsnKind kind); 59 /* WAT operand-token presence derived from the operand class. */ 60 int wasm_operand_class_has_imm(WasmOperandClass oc); 61 62 #endif