diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-ast-checker.c | 4 | ||||
-rw-r--r-- | src/wasm-binary-reader-interpreter.c | 26 | ||||
-rw-r--r-- | src/wasm-interpreter.c | 24 |
3 files changed, 36 insertions, 18 deletions
diff --git a/src/wasm-ast-checker.c b/src/wasm-ast-checker.c index 6b659965..e6f25c9d 100644 --- a/src/wasm-ast-checker.c +++ b/src/wasm-ast-checker.c @@ -645,6 +645,10 @@ static void check_expr(Context* ctx, const WasmExpr* expr) { case WASM_EXPR_TYPE_CALL_INDIRECT: { const WasmFuncType* func_type; + if (!ctx->current_module->table) { + print_error(ctx, CHECK_STYLE_FULL, &expr->loc, + "found call_indirect operator, but no table"); + } if (WASM_SUCCEEDED( check_func_type_var(ctx, &expr->call_indirect.var, &func_type))) { WasmCheckType type = pop_type(ctx); diff --git a/src/wasm-binary-reader-interpreter.c b/src/wasm-binary-reader-interpreter.c index ad11bccb..bcc8193d 100644 --- a/src/wasm-binary-reader-interpreter.c +++ b/src/wasm-binary-reader-interpreter.c @@ -607,12 +607,14 @@ static void pop_typecheck_label(Context* ctx) { } static void push_expr(Context* ctx, WasmType type, WasmOpcode opcode) { - LOGF("%3" PRIzd ": push %s:%s (#%u)\n", ctx->expr_stack.size, - s_opcode_name[opcode], s_type_names[type], ctx->expr_count); - ExprNode* expr; - expr = wasm_append_expr_node(ctx->allocator, &ctx->expr_stack); - expr->index = ctx->expr_count; - expr->type = type; + if (type != WASM_TYPE_VOID) { + LOGF("%3" PRIzd ": push %s:%s (#%u)\n", ctx->expr_stack.size, + s_opcode_name[opcode], s_type_names[type], ctx->expr_count); + ExprNode* expr; + expr = wasm_append_expr_node(ctx->allocator, &ctx->expr_stack); + expr->index = ctx->expr_count; + expr->type = type; + } ctx->expr_count++; } @@ -944,6 +946,9 @@ static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) { Context* ctx = user_data; WasmInterpreterFuncSignature* sig = get_signature(ctx, sig_index); + WasmType entry_index = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, entry_index, "call_indirect")); + uint32_t i; for (i = sig->param_types.size; i > 0; --i) { WasmType arg = pop_expr(ctx); @@ -951,8 +956,6 @@ static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) { check_type(ctx, sig->param_types.data[i - 1], arg, "call_indirect")); } - WasmType entry_index = pop_expr(ctx); - CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, entry_index, "call_indirect")); push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_INDIRECT); return WASM_OK; } @@ -1608,11 +1611,8 @@ static WasmResult on_emit_call_indirect_expr(uint32_t sig_index, WasmInterpreterFuncSignature* sig = get_signature(ctx, sig_index); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_INDIRECT)); CHECK_RESULT(emit_i32(ctx, sig_index)); - uint32_t result_count = get_value_count(sig->result_type); - /* the callee cleans up the params for us, but we have to clean up the - * function table index */ - adjust_value_stack(ctx, result_count - sig->param_types.size); - CHECK_RESULT(emit_discard_keep(ctx, 1, result_count)); + adjust_value_stack(ctx, + get_value_count(sig->result_type) - sig->param_types.size); adjust_value_stack(ctx, -1); CHECK_RESULT(maybe_emit_discard(ctx, ctx->expr_count)); ctx->expr_count++; diff --git a/src/wasm-interpreter.c b/src/wasm-interpreter.c index 5e33aea5..4a8813f5 100644 --- a/src/wasm-interpreter.c +++ b/src/wasm-interpreter.c @@ -594,6 +594,22 @@ static WASM_INLINE void read_table_entry_at(const uint8_t* pc, *out_keep = *(pc + WASM_TABLE_ENTRY_KEEP_OFFSET); } +static WasmBool signatures_are_equal(WasmInterpreterModule* module, + uint32_t sig_index_0, + uint32_t sig_index_1) { + WasmInterpreterFuncSignature* sig_0 = &module->sigs.data[sig_index_0]; + WasmInterpreterFuncSignature* sig_1 = &module->sigs.data[sig_index_1]; + if (sig_0->result_type != sig_1->result_type) + return WASM_FALSE; + if (sig_0->param_types.size != sig_1->param_types.size) + return WASM_FALSE; + size_t i; + for (i = 0; i < sig_0->param_types.size; ++i) + if (sig_0->param_types.data[i] != sig_1->param_types.data[i]) + return WASM_FALSE; + return WASM_TRUE; +} + WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module, WasmInterpreterThread* thread, uint32_t num_instructions, @@ -718,14 +734,12 @@ WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module, case WASM_OPCODE_CALL_INDIRECT: { uint32_t sig_index = read_u32(&pc); assert(sig_index < module->sigs.size); - WasmInterpreterFuncSignature* sig = &module->sigs.data[sig_index]; - uint32_t num_args = sig->param_types.size; - VALUE_TYPE_I32 entry_index = PICK(num_args + 1).i32; + VALUE_TYPE_I32 entry_index = POP_I32(); TRAP_IF(entry_index >= module->func_table.size, UNDEFINED_TABLE_INDEX); WasmInterpreterFuncTableEntry* entry = &module->func_table.data[entry_index]; - TRAP_IF(entry->sig_index != sig_index, - INDIRECT_CALL_SIGNATURE_MISMATCH); + TRAP_UNLESS(signatures_are_equal(module, entry->sig_index, sig_index), + INDIRECT_CALL_SIGNATURE_MISMATCH); PUSH_CALL(); GOTO(entry->func_offset); break; |