diff options
-rw-r--r-- | src/wasm-binary-reader-interpreter.c | 72 | ||||
-rw-r--r-- | src/wasm-interp.c | 3 | ||||
-rw-r--r-- | test/interp/call-zero-args.txt | 19 | ||||
-rw-r--r-- | test/interp/callimport-zero-args.txt | 14 | ||||
-rw-r--r-- | test/interp/empty.txt | 2 | ||||
-rw-r--r-- | test/interp/return-void.txt | 6 | ||||
-rw-r--r-- | test/interp/trap-with-callstack.txt | 20 | ||||
-rw-r--r-- | test/interp/unreachable.txt | 2 |
8 files changed, 108 insertions, 30 deletions
diff --git a/src/wasm-binary-reader-interpreter.c b/src/wasm-binary-reader-interpreter.c index 33eb8fb8..6a453296 100644 --- a/src/wasm-binary-reader-interpreter.c +++ b/src/wasm-binary-reader-interpreter.c @@ -682,6 +682,7 @@ static WasmResult end_function_body(uint32_t index, void* user_data) { (int)ctx->expr_stack.size); return WASM_ERROR; } + assert(ctx->depth_stack.size == 0); WasmInterpreterFunc* func = ctx->current_func; WasmInterpreterFuncSignature* sig = get_signature(ctx, func->sig_index); if (ctx->last_expr.opcode != WASM_OPCODE_RETURN) { @@ -1095,23 +1096,18 @@ static WasmResult reduce(WasmReadInterpreterContext* ctx, static WasmResult shift(WasmReadInterpreterContext* ctx, WasmInterpreterExpr* expr, uint32_t count) { - if (count > 0) { + assert(count > 0); #if LOG - fprintf(stderr, "%3" PRIzd "(%d): shift: %s:%s %u\n", ctx->expr_stack.size, - ctx->value_stack_size, s_opcode_name[expr->opcode], - s_type_names[expr->type], count); + fprintf(stderr, "%3" PRIzd "(%d): shift: %s:%s %u\n", ctx->expr_stack.size, + ctx->value_stack_size, s_opcode_name[expr->opcode], + s_type_names[expr->type], count); #endif - WasmExprNode* node = - wasm_append_expr_node(ctx->allocator, &ctx->expr_stack); - CHECK_ALLOC_NULL(ctx, node); - node->expr = *expr; - node->index = 0; - node->total = count; - return WASM_OK; - } else { - adjust_value_stack(ctx, get_result_count(expr->type)); - return reduce(ctx, expr); - } + WasmExprNode* node = wasm_append_expr_node(ctx->allocator, &ctx->expr_stack); + CHECK_ALLOC_NULL(ctx, node); + node->expr = *expr; + node->index = 0; + node->total = count; + return WASM_OK; } static WasmResult on_unary_expr(WasmOpcode opcode, void* user_data) { @@ -1136,8 +1132,12 @@ static WasmResult on_block_expr(uint32_t count, void* user_data) { expr.type = count ? WASM_TYPE_ANY : WASM_TYPE_VOID; expr.opcode = WASM_OPCODE_BLOCK; expr.block.value_stack_size = ctx->value_stack_size; - CHECK_RESULT(push_depth(ctx, expr.type)); - return shift(ctx, &expr, count); + if (count > 0) { + CHECK_RESULT(push_depth(ctx, expr.type)); + return shift(ctx, &expr, count); + } else { + return reduce(ctx, &expr); + } } static WasmResult on_br_expr(uint32_t depth, void* user_data) { @@ -1203,7 +1203,14 @@ static WasmResult on_call_expr(uint32_t func_index, void* user_data) { expr.type = sig->result_type; expr.opcode = WASM_OPCODE_CALL_FUNCTION; expr.call.func_index = func_index; - return shift(ctx, &expr, sig->param_types.size); + if (sig->param_types.size > 0) { + return shift(ctx, &expr, sig->param_types.size); + } else { + int32_t num_results = get_result_count(sig->result_type); + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_FUNCTION, num_results)); + CHECK_RESULT(emit_func_offset(ctx, func, func_index)); + return reduce(ctx, &expr); + } } static WasmResult on_call_import_expr(uint32_t import_index, void* user_data) { @@ -1215,7 +1222,14 @@ static WasmResult on_call_import_expr(uint32_t import_index, void* user_data) { expr.type = sig->result_type; expr.opcode = WASM_OPCODE_CALL_IMPORT; expr.call_import.import_index = import_index; - return shift(ctx, &expr, sig->param_types.size); + if (sig->param_types.size > 0) { + return shift(ctx, &expr, sig->param_types.size); + } else { + int32_t num_results = get_result_count(sig->result_type); + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_IMPORT, num_results)); + CHECK_RESULT(emit_i32(ctx, import_index)); + return reduce(ctx, &expr); + } } static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) { @@ -1323,10 +1337,14 @@ static WasmResult on_loop_expr(uint32_t count, void* user_data) { expr.type = count ? WASM_TYPE_ANY : WASM_TYPE_VOID; expr.opcode = WASM_OPCODE_LOOP; expr.loop.value_stack_size = ctx->value_stack_size; - CHECK_RESULT(push_depth(ctx, expr.type)); /* exit */ - CHECK_RESULT(push_depth_with_offset(ctx, WASM_TYPE_VOID, - get_istream_offset(ctx))); /* continue */ - return shift(ctx, &expr, count); + if (count > 0) { + CHECK_RESULT(push_depth(ctx, expr.type)); /* exit */ + CHECK_RESULT(push_depth_with_offset( + ctx, WASM_TYPE_VOID, get_istream_offset(ctx))); /* continue */ + return shift(ctx, &expr, count); + } else { + return reduce(ctx, &expr); + } } static WasmResult on_memory_size_expr(void* user_data) { @@ -1353,7 +1371,13 @@ static WasmResult on_return_expr(void* user_data) { WasmInterpreterExpr expr; expr.type = WASM_TYPE_ANY; expr.opcode = WASM_OPCODE_RETURN; - return shift(ctx, &expr, get_result_count(sig->result_type)); + uint32_t result_count = get_result_count(sig->result_type); + if (result_count > 0) { + return shift(ctx, &expr, result_count); + } else { + CHECK_RESULT(emit_return(ctx, sig->result_type)); + return reduce(ctx, &expr); + } } static WasmResult on_select_expr(void* user_data) { diff --git a/src/wasm-interp.c b/src/wasm-interp.c index 3384b073..716a538c 100644 --- a/src/wasm-interp.c +++ b/src/wasm-interp.c @@ -271,7 +271,7 @@ static WasmInterpreterResult run_export(WasmInterpreterModule* module, if (sig->result_type != WASM_TYPE_VOID) printf(") => "); else - printf(")"); + printf(") "); if (result == WASM_INTERPRETER_RETURNED) { if (sig->result_type != WASM_TYPE_VOID) { @@ -290,6 +290,7 @@ static WasmInterpreterResult run_export(WasmInterpreterModule* module, printf("error: %s\n", s_trap_strings[result]); } thread->value_stack_top = 0; + thread->call_stack_top = 0; return result; } diff --git a/test/interp/call-zero-args.txt b/test/interp/call-zero-args.txt new file mode 100644 index 00000000..0fed237d --- /dev/null +++ b/test/interp/call-zero-args.txt @@ -0,0 +1,19 @@ +;;; TOOL: run-interp +(module + (func $f (result i32) + (i32.const 42)) + + (func $g (param i32 i32) (result i32) + (i32.add + (get_local 0) + (get_local 1))) + + (func $h (result i32) + (call $g + (i32.const 1) + (call $f))) + + (export "h" $h)) +(;; STDOUT ;;; +h() => i32:43 +;;; STDOUT ;;) diff --git a/test/interp/callimport-zero-args.txt b/test/interp/callimport-zero-args.txt new file mode 100644 index 00000000..1426e819 --- /dev/null +++ b/test/interp/callimport-zero-args.txt @@ -0,0 +1,14 @@ +;;; TOOL: run-interp +(module + (import "foo" "bar" (result i32)) + + (func $f (result i32) + (i32.add + (i32.const 13) + (call_import 0))) + + (export "f" $f)) +(;; STDOUT ;;; +called import foo.bar() => i32:0 +f() => i32:13 +;;; STDOUT ;;) diff --git a/test/interp/empty.txt b/test/interp/empty.txt index 3e43e05e..1f8c3787 100644 --- a/test/interp/empty.txt +++ b/test/interp/empty.txt @@ -3,5 +3,5 @@ (export "f" 0) (func)) (;; STDOUT ;;; -f() +f() ;;; STDOUT ;;) diff --git a/test/interp/return-void.txt b/test/interp/return-void.txt index 53020f43..8d89b64e 100644 --- a/test/interp/return-void.txt +++ b/test/interp/return-void.txt @@ -22,8 +22,8 @@ (i32.load (i32.const 0))) (export "check2" $check2)) (;; STDOUT ;;; -test1() -check1() => i32:1 -test2() +test1() +check1() => i32:0 +test2() check2() => i32:1 ;;; STDOUT ;;) diff --git a/test/interp/trap-with-callstack.txt b/test/interp/trap-with-callstack.txt new file mode 100644 index 00000000..b350d71d --- /dev/null +++ b/test/interp/trap-with-callstack.txt @@ -0,0 +1,20 @@ +;;; TOOL: run-interp +(module + (func $trap + (i32.div_s + (i32.const 1) + (i32.const 0))) + + (func $f (call $trap)) + (func $g (call $f)) + (func $h (call $g)) + (export "h" $h) + + ;; this function should run properly, even after h traps. + (func $i (result i32) + (i32.const 22)) + (export "i" $i)) +(;; STDOUT ;;; +h() error: integer divide by zero +i() => i32:22 +;;; STDOUT ;;) diff --git a/test/interp/unreachable.txt b/test/interp/unreachable.txt index 857e5cce..febe17b9 100644 --- a/test/interp/unreachable.txt +++ b/test/interp/unreachable.txt @@ -4,5 +4,5 @@ (func (unreachable))) (;; STDOUT ;;; -trap()error: unreachable executed +trap() error: unreachable executed ;;; STDOUT ;;) |