summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm-binary-reader-interpreter.c72
-rw-r--r--src/wasm-interp.c3
-rw-r--r--test/interp/call-zero-args.txt19
-rw-r--r--test/interp/callimport-zero-args.txt14
-rw-r--r--test/interp/empty.txt2
-rw-r--r--test/interp/return-void.txt6
-rw-r--r--test/interp/trap-with-callstack.txt20
-rw-r--r--test/interp/unreachable.txt2
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 ;;)