protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit 5b3ba00987a8f2b4a8ef4f802d0857da971ac9c7
parent 7bfae94e7ab5e9ebc18d0004fdbec7f3e6f8a0a4
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 18 Jul 2021 11:01:49 -0700

parse non-control instructions before interp

Make for better debugging

Diffstat:
Msrc/debug.h | 2+-
Msrc/wasm.c | 503+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/wasm.h | 3++-
3 files changed, 292 insertions(+), 216 deletions(-)

diff --git a/src/debug.h b/src/debug.h @@ -7,7 +7,7 @@ #define unusual(...) fprintf(stderr, "UNUSUAL: " __VA_ARGS__) #ifdef DEBUG -#define debug(...) fprintf(stderr, __VA_ARGS__) +#define debug(...) printf(__VA_ARGS__) #else #define debug(...) #endif diff --git a/src/wasm.c b/src/wasm.c @@ -2370,24 +2370,14 @@ static INLINE int set_local(struct wasm_interp *interp, int ind, return set_fn_local(interp, frame->fn, ind, val); } -static int interp_local_tee(struct wasm_interp *interp) +static INLINE int interp_local_tee(struct wasm_interp *interp, int index) { struct val *val; - unsigned int index; - struct cursor *code; if (unlikely(!(val = stack_topval(interp)))) { return interp_error(interp, "pop"); } - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (unlikely(!leb128_read(code, &index))) { - return interp_error(interp, "read index"); - } - if (unlikely(!set_local(interp, index, val))) { return interp_error(interp, "set local"); } @@ -2395,11 +2385,11 @@ static int interp_local_tee(struct wasm_interp *interp) return 1; } -static int interp_local_set(struct wasm_interp *interp) +static int interp_local_set(struct wasm_interp *interp, int index) { struct val val; - if (unlikely(!interp_local_tee(interp))) { + if (unlikely(!interp_local_tee(interp, index))) { return interp_error(interp, "tee set"); } @@ -2410,25 +2400,12 @@ static int interp_local_set(struct wasm_interp *interp) return 1; } -static int interp_local_get(struct wasm_interp *interp) +static INLINE int interp_local_get(struct wasm_interp *interp, int index) { - unsigned int index; struct val *val; - struct cursor *code; - - if (unlikely(!(code = interp_codeptr(interp)))) { - interp_error(interp, "codeptr"); - return 0; - } - - if (unlikely(!leb128_read(code, &index))) { - interp_error(interp, "index"); - return 0; - } if (unlikely(!(val = get_local(interp, index)))) { - interp_error(interp, "get local"); - return 0; + return interp_error(interp, "get local"); } return stack_pushval(interp, val); @@ -2499,24 +2476,10 @@ static INLINE int interp_lt(struct wasm_interp *interp, enum valtype vt, int sgn return stack_pushval(interp, &c); } -static INLINE int interp_i32_const(struct wasm_interp *interp) +static INLINE int interp_i32_const(struct wasm_interp *interp, int c) { struct val val; - unsigned int read; - struct cursor *code; - - if (unlikely(!(code = interp_codeptr(interp)))) { - interp_error(interp, "codeptr"); - return 0; - } - - if (unlikely(!leb128_read(code, &read))) { - interp_error(interp, "invalid constant value"); - return 0; - } - - make_i32_val(&val, read); - + make_i32_val(&val, c); return cursor_pushval(&interp->stack, &val); } @@ -2678,22 +2641,10 @@ static int prepare_call(struct wasm_interp *interp, int func_index) int interp_code(struct wasm_interp *interp); -static int interp_call(struct wasm_interp *interp) +static int interp_call(struct wasm_interp *interp, int func_index) { - unsigned int func_index; - struct cursor *code; struct callframe frame; - if (unlikely(!(code = interp_codeptr(interp)))) { - interp_error(interp, "codeptr"); - return 0; - } - - if (unlikely(!leb128_read(code, &func_index))) { - interp_error(interp, "read func index"); - return 0; - } - if (unlikely(!prepare_call(interp, func_index))) { interp_error(interp, "prepare"); return 0; @@ -2970,6 +2921,7 @@ static int parse_block(struct expr_parser *p, struct block *block, u8 end_tag) return note_error(p->errs, p->code, "push checkpoint"); if (label && is_label_resolved(label)) { + debug("label is resolved, skipping block parse\n"); // TODO verify this is correct block->instrs = p->code->start + label_instr_pos(label); block->instrs_len = (p->code->start + label->jump) - block->instrs; @@ -2999,8 +2951,10 @@ static INLINE int parse_memarg(struct cursor *code, struct memarg *memarg) static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op) { + /* debug("%04lX parsing instr %s (0x%02x)\n", p->code->p - 1 - p->code->start, instr_name(tag), tag); + */ op->tag = tag; @@ -3013,7 +2967,7 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op) case i_block: case i_loop: case i_if: - return parse_block(p, &op->blocks[0], i_end); + return parse_block(p, &op->block, i_end); case i_else: case i_end: @@ -3025,6 +2979,10 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op) case i_local_tee: case i_global_get: case i_global_set: + case i_br: + case i_br_if: + case i_i32_const: + case i_i64_const: return leb128_read(p->code, &op->integer); case i_i32_load: @@ -3056,15 +3014,6 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op) case i_call_indirect: return note_error(p->errs, p->code, "consume dynamic-size op"); - case i_br: - case i_br_if: - case i_i32_const: - case i_i64_const: - if (unlikely(!leb128_read(p->code, &op->integer))) { - return note_error(p->errs, p->code, "failed to read integer"); - } - return 1; - case i_f32_const: case i_f64_const: return note_error(p->errs, p->code, "parse float const"); @@ -3181,9 +3130,9 @@ static int branch_jump(struct wasm_interp *interp, u8 end_tag) static int interp_block(struct wasm_interp *interp) { - struct blocktype blocktype; struct cursor *code; struct label *label; + struct blocktype blocktype; if (unlikely(!(code = interp_codeptr(interp)))) { interp_error(interp, "empty callstack?"); @@ -3321,35 +3270,15 @@ static int interp_br_jump(struct wasm_interp *interp, int index) return unresolved_break(interp, index); } -static int interp_br(struct wasm_interp *interp) +static INLINE int interp_br(struct wasm_interp *interp, int ind) { - struct cursor *code; - int ind; - - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (unlikely(!leb128_read(code, (unsigned int*)&ind))) - return interp_error(interp, "read br index"); - return interp_br_jump(interp, ind); } -static int interp_br_if(struct wasm_interp *interp) +static INLINE int interp_br_if(struct wasm_interp *interp, int ind) { - u32 ind; int cond = 0; - struct cursor *code; - - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (unlikely(!leb128_read(code, &ind))) - return interp_error(interp, "read br_if index"); - // TODO: can this be something other than an i32? if (unlikely(!stack_pop_i32(interp, &cond))) { return interp_error(interp, "pop br_if i32"); @@ -3361,37 +3290,6 @@ static int interp_br_if(struct wasm_interp *interp) return 1; } -static int interp_global_get(struct wasm_interp *interp) -{ - struct globalsec *section = &interp->module->global_section; - struct global *global; - struct cursor *code; - int ind; - - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (!leb128_read(code, (u32*)&ind)) { - return interp_error(interp, "read global index"); - } - - // TODO imported global indices? - if (unlikely(ind >= section->num_globals)) { - return interp_error(interp, "invalid global index %d / %d", - ind, section->num_globals-1); - } - - global = &section->globals[ind]; - - if (unlikely(!eval_const_expr(&global->init, &interp->errors, - &interp->stack))) { - return interp_error(interp, "init global"); - } - - return 1; -} - static INLINE u8 *global_init_state(struct wasm_interp *interp, int ind) { u8 *p; @@ -3448,6 +3346,24 @@ static struct val *get_global(struct wasm_interp *interp, int ind) return val; } +static int interp_global_get(struct wasm_interp *interp, int ind) +{ + struct globalsec *section = &interp->module->global_section; + struct val *global; + + // TODO imported global indices? + if (unlikely(ind >= section->num_globals)) { + return interp_error(interp, "invalid global index %d / %d", + ind, section->num_globals-1); + } + + if (!(global = get_global(interp, ind))) { + return interp_error(interp, "get global"); + } + + return stack_pushval(interp, global); +} + static INLINE int has_memory_section(struct module *module) { return was_section_parsed(module, section_memory) && @@ -3476,30 +3392,21 @@ static INLINE int bitwidth(enum valtype vt) } struct memtarget { - struct memarg memarg; int size; u8 *pos; }; static int interp_mem_offset(struct wasm_interp *interp, - int N, int i, enum valtype c, struct memtarget *t) + int N, int i, enum valtype c, struct memarg *memarg, + struct memtarget *t) { - struct cursor *code; int offset, bw; if (unlikely(!has_memory_section(interp->module))) { return interp_error(interp, "no memory section"); } - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (unlikely(!parse_memarg(code, &t->memarg))) { - return interp_error(interp, "memarg"); - } - - offset = i + t->memarg.offset; + offset = i + memarg->offset; bw = bitwidth(c); if (N == 0) { @@ -3532,7 +3439,8 @@ static int wrap_val(struct val *val, int size) { return 1; } -static int interp_store(struct wasm_interp *interp, enum valtype type, int N) +static int interp_store(struct wasm_interp *interp, struct memarg *memarg, + enum valtype type, int N) { struct val c; struct memtarget target; @@ -3546,7 +3454,7 @@ static int interp_store(struct wasm_interp *interp, enum valtype type, int N) return interp_error(interp, "pop stack"); } - if (unlikely(!interp_mem_offset(interp, N, i, type, &target))) { + if (unlikely(!interp_mem_offset(interp, N, i, type, memarg, &target))) { return interp_error(interp, "memory target"); } @@ -3563,7 +3471,8 @@ static int interp_store(struct wasm_interp *interp, enum valtype type, int N) return 1; } -static int interp_load(struct wasm_interp *interp, enum valtype type, int N, int sgn) +static int interp_load(struct wasm_interp *interp, struct memarg *memarg, + enum valtype type, int N, int sgn) { struct memtarget target; struct val out = {0}; @@ -3577,7 +3486,7 @@ static int interp_load(struct wasm_interp *interp, enum valtype type, int N, int return interp_error(interp, "pop stack"); } - if (unlikely(!interp_mem_offset(interp, N, i, type, &target))) { + if (unlikely(!interp_mem_offset(interp, N, i, type, memarg, &target))) { return interp_error(interp, "memory target"); } @@ -3591,19 +3500,9 @@ static int interp_load(struct wasm_interp *interp, enum valtype type, int N, int return 1; } -static int interp_global_set(struct wasm_interp *interp) +static INLINE int interp_global_set(struct wasm_interp *interp, int global_ind) { struct val *global, setval; - int global_ind; - struct cursor *code; - - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (unlikely(!leb128_read(code, (unsigned int*)&global_ind))) { - return interp_error(interp, "read global ind"); - } if (unlikely(!(global = get_global(interp, global_ind)))) { return interp_error(interp, "couldn't get global %d", global_ind); @@ -3623,20 +3522,12 @@ static INLINE int active_pages(struct wasm_interp *interp) return cursor_count(&interp->memory, WASM_PAGE_SIZE); } -static int interp_memory_grow(struct wasm_interp *interp) +static int interp_memory_grow(struct wasm_interp *interp, u8 memidx) { - struct cursor *code; int pages = 0, prev_size; unsigned int grow; - u8 memidx; - - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - if (!pull_byte(code, &memidx)) { - return interp_error(interp, "memidx"); - } + (void)memidx; if (unlikely(!has_memory_section(interp->module))) { return interp_error(interp, "no memory section"); @@ -3659,18 +3550,9 @@ static int interp_memory_grow(struct wasm_interp *interp) return stack_push_i32(interp, pages); } -static int interp_memory_size(struct wasm_interp *interp) +static INLINE int interp_memory_size(struct wasm_interp *interp, u8 memidx) { - struct cursor *code; - u8 memidx; - - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); - } - - if (!pull_byte(code, &memidx)) { - return interp_error(interp, "memidx"); - } + (void)memidx; if (unlikely(!has_memory_section(interp->module))) { return interp_error(interp, "no memory section"); @@ -3725,85 +3607,271 @@ static void print_linestack(struct cursor *stack) printf("\n"); } -static int interp_instr(struct wasm_interp *interp, u8 tag) +static const char *show_instr(struct instr *instr) +{ + struct cursor buf; + static char buffer[64]; + static char tmp[32]; + int len, i; + + buffer[sizeof(buffer)-1] = 0; + make_cursor((u8*)buffer, (u8*)buffer + sizeof(buffer) - 1, &buf); + + cursor_push_str(&buf, instr_name(instr->tag)); + len = buf.p - buf.start; + + for (i = 0; i < 12-len; i++) + cursor_push_byte(&buf, ' '); + + switch (instr->tag) { + // two-byte instrs + case i_memory_size: + case i_memory_grow: + sprintf(tmp, "0x%02x", instr->memidx); + cursor_push_str(&buf, tmp); + break; + + case i_block: + case i_loop: + case i_if: + break; + + case i_else: + case i_end: + break; + + case i_call: + case i_local_get: + case i_local_set: + case i_local_tee: + case i_global_get: + case i_global_set: + case i_br: + case i_br_if: + case i_i32_const: + case i_i64_const: + sprintf(tmp, "%d", instr->integer); + cursor_push_str(&buf, tmp); + break; + + case i_i32_load: + case i_i64_load: + case i_f32_load: + case i_f64_load: + case i_i32_load8_s: + case i_i32_load8_u: + case i_i32_load16_s: + case i_i32_load16_u: + case i_i64_load8_s: + case i_i64_load8_u: + case i_i64_load16_s: + case i_i64_load16_u: + case i_i64_load32_s: + case i_i64_load32_u: + case i_i32_store: + case i_i64_store: + case i_f32_store: + case i_f64_store: + case i_i32_store8: + case i_i32_store16: + case i_i64_store8: + case i_i64_store16: + case i_i64_store32: + sprintf(tmp, "%d:%d", instr->memarg.offset, instr->memarg.align); + cursor_push_str(&buf, tmp); + break; + + case i_br_table: + case i_call_indirect: + break; + + case i_f32_const: + sprintf(tmp, "%f", instr->fp_single); + cursor_push_str(&buf, tmp); + break; + + case i_f64_const: + sprintf(tmp, "%f", instr->fp_double); + cursor_push_str(&buf, tmp); + break; + + // single-tag ops + case i_unreachable: + case i_nop: + case i_return: + case i_drop: + case i_select: + case i_i32_eqz: + case i_i32_eq: + case i_i32_ne: + case i_i32_lt_s: + case i_i32_lt_u: + case i_i32_gt_s: + case i_i32_gt_u: + case i_i32_le_s: + case i_i32_le_u: + case i_i32_ge_s: + case i_i32_ge_u: + case i_i64_eqz: + case i_i64_eq: + case i_i64_ne: + case i_i64_lt_s: + case i_i64_lt_u: + case i_i64_gt_s: + case i_i64_gt_u: + case i_i64_le_s: + case i_i64_le_u: + case i_i64_ge_s: + case i_i64_ge_u: + case i_f32_eq: + case i_f32_ne: + case i_f32_lt: + case i_f32_gt: + case i_f32_le: + case i_f32_ge: + case i_f64_eq: + case i_f64_ne: + case i_f64_lt: + case i_f64_gt: + case i_f64_le: + case i_f64_ge: + case i_i32_clz: + case i_i32_add: + case i_i32_sub: + case i_i32_mul: + case i_i32_div_s: + case i_i32_div_u: + case i_i32_rem_s: + case i_i32_rem_u: + case i_i32_and: + case i_i32_or: + case i_i32_xor: + case i_i32_shl: + case i_i32_shr_s: + case i_i32_shr_u: + case i_i32_rotl: + case i_i32_rotr: + case i_i64_clz: + case i_i64_ctz: + case i_i64_popcnt: + case i_i64_add: + case i_i64_sub: + case i_i64_mul: + case i_i64_div_s: + case i_i64_div_u: + case i_i64_rem_s: + case i_i64_rem_u: + case i_i64_and: + case i_i64_or: + case i_i64_xor: + case i_i64_shl: + case i_i64_shr_s: + case i_i64_shr_u: + case i_i64_rotl: + case i_i64_rotr: + break; + } + + cursor_push_byte(&buf, 0); + return buffer; +} + +static int interp_instr(struct wasm_interp *interp, struct instr *instr) { interp->ops++; - debug("%04lX %s\t", + debug("%04lX %-30s | ", interp_codeptr(interp)->p - 1 - interp_codeptr(interp)->start, - instr_name(tag) - ); + show_instr(instr)); #if DEBUG print_linestack(&interp->stack); #endif - switch (tag) { + switch (instr->tag) { case i_unreachable: return 1; case i_nop: return 1; - case i_local_get: return interp_local_get(interp); - case i_local_set: return interp_local_set(interp); - case i_local_tee: return interp_local_tee(interp); - case i_global_get: return interp_global_get(interp); - case i_global_set: return interp_global_set(interp); + + case i_local_get: return interp_local_get(interp, instr->integer); + case i_local_set: return interp_local_set(interp, instr->integer); + case i_local_tee: return interp_local_tee(interp, instr->integer); + case i_global_get: return interp_global_get(interp, instr->integer); + case i_global_set: return interp_global_set(interp, instr->integer); case i_i32_eqz: return interp_i32_eqz(interp); case i_i32_add: return interp_i32_add(interp); case i_i32_sub: return interp_i32_sub(interp); - case i_i32_const: return interp_i32_const(interp); + case i_i32_const: return interp_i32_const(interp, instr->integer); + case i_i32_gt_u: return interp_gt(interp, val_i32, 0); case i_i32_lt_s: return interp_lt(interp, val_i32, 1); case i_i32_lt_u: return interp_lt(interp, val_i32, 0); case i_i32_shl: return interp_shl(interp, val_i32); - case i_i32_store: return interp_store(interp, val_i32, 0); - case i_i32_store8: return interp_store(interp, val_i32, 8); - case i_i32_store16: return interp_store(interp, val_i32, 16); - case i_f32_store: return interp_store(interp, val_f32, 0); - case i_f64_store: return interp_store(interp, val_f64, 0); - case i_i64_store: return interp_store(interp, val_i64, 0); - case i_i64_store8: return interp_store(interp, val_i64, 8); - case i_i64_store16: return interp_store(interp, val_i64, 16); - case i_i64_store32: return interp_store(interp, val_i64, 32); - - case i_i32_load: return interp_load(interp, val_i32, 0, -1); - case i_i32_load8_s: return interp_load(interp, val_i32, 8, 1); - case i_i32_load8_u: return interp_load(interp, val_i32, 8, 0); - case i_i32_load16_s: return interp_load(interp, val_i32, 16, 1); - case i_i32_load16_u: return interp_load(interp, val_i32, 16, 0); - case i_f32_load: return interp_load(interp, val_f32, 0, -1); - case i_f64_load: return interp_load(interp, val_f64, 0, -1); - case i_i64_load: return interp_load(interp, val_i64, 0, -1); - case i_i64_load8_s: return interp_load(interp, val_i64, 8, 1); - case i_i64_load8_u: return interp_load(interp, val_i64, 8, 0); - case i_i64_load16_s: return interp_load(interp, val_i64, 16, 1); - case i_i64_load16_u: return interp_load(interp, val_i64, 16, 0); - case i_i64_load32_s: return interp_load(interp, val_i64, 32, 1); - case i_i64_load32_u: return interp_load(interp, val_i64, 32, 0); + case i_i32_store: return interp_store(interp, &instr->memarg, val_i32, 0); + case i_i32_store8: return interp_store(interp, &instr->memarg, val_i32, 8); + case i_i32_store16: return interp_store(interp, &instr->memarg, val_i32, 16); + case i_f32_store: return interp_store(interp, &instr->memarg, val_f32, 0); + case i_f64_store: return interp_store(interp, &instr->memarg, val_f64, 0); + case i_i64_store: return interp_store(interp, &instr->memarg, val_i64, 0); + case i_i64_store8: return interp_store(interp, &instr->memarg, val_i64, 8); + case i_i64_store16: return interp_store(interp, &instr->memarg, val_i64, 16); + case i_i64_store32: return interp_store(interp, &instr->memarg, val_i64, 32); + + case i_i32_load: return interp_load(interp, &instr->memarg, val_i32, 0, -1); + case i_i32_load8_s: return interp_load(interp, &instr->memarg, val_i32, 8, 1); + case i_i32_load8_u: return interp_load(interp, &instr->memarg, val_i32, 8, 0); + case i_i32_load16_s: return interp_load(interp, &instr->memarg, val_i32, 16, 1); + case i_i32_load16_u: return interp_load(interp, &instr->memarg, val_i32, 16, 0); + case i_f32_load: return interp_load(interp, &instr->memarg, val_f32, 0, -1); + case i_f64_load: return interp_load(interp, &instr->memarg, val_f64, 0, -1); + case i_i64_load: return interp_load(interp, &instr->memarg, val_i64, 0, -1); + case i_i64_load8_s: return interp_load(interp, &instr->memarg, val_i64, 8, 1); + case i_i64_load8_u: return interp_load(interp, &instr->memarg, val_i64, 8, 0); + case i_i64_load16_s: return interp_load(interp, &instr->memarg, val_i64, 16, 1); + case i_i64_load16_u: return interp_load(interp, &instr->memarg, val_i64, 16, 0); + case i_i64_load32_s: return interp_load(interp, &instr->memarg, val_i64, 32, 1); + case i_i64_load32_u: return interp_load(interp, &instr->memarg, val_i64, 32, 0); case i_if: return interp_if(interp); case i_end: return pop_label_checkpoint(interp); - case i_call: return interp_call(interp); + case i_call: return interp_call(interp, instr->integer); case i_block: return interp_block(interp); - case i_br: return interp_br(interp); - case i_br_if: return interp_br_if(interp); - case i_memory_size: return interp_memory_size(interp); - case i_memory_grow: return interp_memory_grow(interp); + case i_br: return interp_br(interp, instr->integer); + case i_br_if: return interp_br_if(interp, instr->integer); + case i_memory_size: return interp_memory_size(interp, instr->memidx); + case i_memory_grow: return interp_memory_grow(interp, instr->memidx); case i_return: return 1; default: interp_error(interp, "unhandled instruction %s 0x%x", - instr_name(tag), tag); + instr_name(instr->tag), instr->tag); return 0; } return 0; } +static int is_control_instr(u8 tag) +{ + switch (tag) { + case i_if: + case i_block: + case i_loop: + case i_else: + return 1; + } + return 0; +} + int interp_code(struct wasm_interp *interp) { - unsigned char tag; int offset, num_resolvers = 0; struct cursor *code; + struct instr instr; + struct expr_parser parser; + u8 tag; + + make_interp_expr_parser(interp, &parser); for (;;) { if (unlikely(!(code = interp_codeptr(interp)))) { @@ -3814,7 +3882,14 @@ int interp_code(struct wasm_interp *interp) return interp_error(interp, "no more instrs to pull"); } - if (tag == i_end) { + instr.tag = tag; + + if (!is_control_instr(instr.tag) && + !parse_instr(&parser, instr.tag, &instr)) { + return interp_error(interp, "parse instr"); + } + + if (instr.tag == i_end) { if (unlikely(!count_local_resolvers(interp, &num_resolvers))) { return interp_error(interp, @@ -3831,9 +3906,9 @@ int interp_code(struct wasm_interp *interp) } } - if (unlikely(!interp_instr(interp, tag))) { + if (unlikely(!interp_instr(interp, &instr))) { return interp_error(interp, "interp instr %s", - instr_name(tag)); + instr_name(instr.tag)); } } diff --git a/src/wasm.h b/src/wasm.h @@ -416,7 +416,8 @@ struct instr { union { struct memarg memarg; struct block block; - struct block blocks[2]; + double fp_double; + float fp_single; unsigned int integer; unsigned char memidx; enum reftype reftype;