Fix tail-call handling in interpreter and wasm2c (#2563)
diff --git a/src/c-writer.cc b/src/c-writer.cc
index 9370dbd..656377f 100644
--- a/src/c-writer.cc
+++ b/src/c-writer.cc
@@ -1931,7 +1931,7 @@
Index num_results = func.GetNumResults();
if (num_params >= 1) {
Write(func.decl.sig.param_types, " params;", Newline());
- Write("wasm_rt_memcpy(params, tail_call_stack, sizeof(params));",
+ Write("wasm_rt_memcpy(¶ms, tail_call_stack, sizeof(params));",
Newline());
}
@@ -4201,7 +4201,7 @@
Write("next->fn = ", TailCallRef(func.name), ";", Newline());
if (IsImport(func.name)) {
- Write("*instance_ptr = ",
+ Write("*instance_ptr = instance->",
GlobalName(ModuleFieldType::Import,
import_module_sym_map_.at(func.name)),
";", Newline());
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 10b5a7d..9eb54d4 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -831,7 +831,10 @@
depth_fixups_.Clear();
label_stack_.clear();
- func_fixups_.Resolve(istream_, defined_index);
+ // The fixups map is keyed by actual function index (not defined_index)
+ // (function imports don't have code and won't appear in the fixups map,
+ // but they still use function indexes)
+ func_fixups_.Resolve(istream_, index);
CHECK_RESULT(validator_.BeginFunctionBody(GetLocation(), index));
diff --git a/test/spec/tail-call/return_call.txt b/test/spec/tail-call/return_call.txt
index 74145cd..246db8a 100644
--- a/test/spec/tail-call/return_call.txt
+++ b/test/spec/tail-call/return_call.txt
@@ -1,36 +1,40 @@
;;; TOOL: run-interp-spec
-;;; STDIN_FILE: third_party/testsuite/proposals/tail-call/return_call.wast
+;;; STDIN_FILE: third_party/testsuite/proposals/wasm-3.0/return_call.wast
;;; ARGS*: --enable-tail-call
(;; STDOUT ;;;
-out/test/spec/tail-call/return_call.wast:124: assert_invalid passed:
+called host spectest.print_i32_f32(i32:5, f32:91.000000) =>
+out/test/spec/tail-call/return_call.wast:141: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.1.wasm:000001e: error: return signatures have inconsistent types: expected [i32], got []
000001e: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:131: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:148: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.2.wasm:000001f: error: return signatures have inconsistent types: expected [i32], got [i64]
000001f: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:139: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:156: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.3.wasm:000001e: error: type mismatch in return_call, expected [i32] but got []
000001e: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:146: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:163: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.4.wasm:000001f: error: type mismatch in return_call, expected [f64, i32] but got []
000001f: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:164: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:181: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.7.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32]
0000022: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:171: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:188: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.8.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32]
0000022: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:178: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:195: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.9.wasm:000002a: error: type mismatch in return_call, expected [i32, f64] but got [f64, i32]
000002a: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:185: assert_invalid passed:
+out/test/spec/tail-call/return_call.wast:202: assert_invalid passed:
out/test/spec/tail-call/return_call/return_call.10.wasm:000002a: error: type mismatch in return_call, expected [f64, i32] but got [i32, f64]
000002a: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:196: assert_invalid passed:
- out/test/spec/tail-call/return_call/return_call.11.wasm:0000019: error: function variable out of range: 1 (max 1)
+out/test/spec/tail-call/return_call.wast:209: assert_invalid passed:
+ out/test/spec/tail-call/return_call/return_call.11.wasm:0000024: error: return signatures have inconsistent types: expected [i32], got [i32, i32]
+ 0000024: error: OnReturnCallExpr callback failed
+out/test/spec/tail-call/return_call.wast:221: assert_invalid passed:
+ out/test/spec/tail-call/return_call/return_call.12.wasm:0000019: error: function variable out of range: 1 (max 1)
0000019: error: OnReturnCallExpr callback failed
-out/test/spec/tail-call/return_call.wast:200: assert_invalid passed:
- out/test/spec/tail-call/return_call/return_call.12.wasm:000001d: error: function variable out of range: 1012321300 (max 1)
+out/test/spec/tail-call/return_call.wast:225: assert_invalid passed:
+ out/test/spec/tail-call/return_call/return_call.13.wasm:000001d: error: function variable out of range: 1012321300 (max 1)
000001d: error: OnReturnCallExpr callback failed
-44/44 tests passed.
+47/47 tests passed.
;;; STDOUT ;;)
diff --git a/test/spec/tail-call/return_call_indirect.txt b/test/spec/tail-call/return_call_indirect.txt
index d8b3df7..ee9f852 100644
--- a/test/spec/tail-call/return_call_indirect.txt
+++ b/test/spec/tail-call/return_call_indirect.txt
@@ -1,121 +1,128 @@
;;; TOOL: run-interp-spec
-;;; STDIN_FILE: third_party/testsuite/proposals/tail-call/return_call_indirect.wast
+;;; STDIN_FILE: third_party/testsuite/proposals/wasm-3.0/return_call_indirect.wast
;;; ARGS*: --enable-tail-call
(;; STDOUT ;;;
-out/test/spec/tail-call/return_call_indirect.wast:234: assert_trap passed: indirect call signature mismatch
-out/test/spec/tail-call/return_call_indirect.wast:235: assert_trap passed: indirect call signature mismatch
-out/test/spec/tail-call/return_call_indirect.wast:236: assert_trap passed: undefined table index
-out/test/spec/tail-call/return_call_indirect.wast:237: assert_trap passed: undefined table index
-out/test/spec/tail-call/return_call_indirect.wast:238: assert_trap passed: undefined table index
-out/test/spec/tail-call/return_call_indirect.wast:244: assert_trap passed: indirect call signature mismatch
-out/test/spec/tail-call/return_call_indirect.wast:245: assert_trap passed: indirect call signature mismatch
-out/test/spec/tail-call/return_call_indirect.wast:273: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:260: assert_trap passed: indirect call signature mismatch
+out/test/spec/tail-call/return_call_indirect.wast:261: assert_trap passed: indirect call signature mismatch
+out/test/spec/tail-call/return_call_indirect.wast:262: assert_trap passed: undefined table index
+out/test/spec/tail-call/return_call_indirect.wast:263: assert_trap passed: undefined table index
+out/test/spec/tail-call/return_call_indirect.wast:264: assert_trap passed: undefined table index
+out/test/spec/tail-call/return_call_indirect.wast:270: assert_trap passed: indirect call signature mismatch
+out/test/spec/tail-call/return_call_indirect.wast:271: assert_trap passed: indirect call signature mismatch
+called host spectest.print_i32_f32(i32:5, f32:91.000000) =>
+out/test/spec/tail-call/return_call_indirect.wast:301: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.1.wat:1:129: error: unexpected token "param", expected an expr.
...indirect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const ...
^^^^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.1.wat:1:173: error: unexpected token ), expected EOF.
...irect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const 0) ))
^
-out/test/spec/tail-call/return_call_indirect.wast:285: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:313: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.2.wat:1:116: error: unexpected token "type", expected an expr.
...(return_call_indirect (param i32) (type $sig) (result i32) (i32.const 0...
^^^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.2.wat:1:173: error: unexpected token ), expected EOF.
...irect (param i32) (type $sig) (result i32) (i32.const 0) (i32.const 0) ))
^
-out/test/spec/tail-call/return_call_indirect.wast:297: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:325: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.3.wat:1:129: error: unexpected token "type", expected an expr.
...indirect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const ...
^^^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.3.wat:1:173: error: unexpected token ), expected EOF.
...irect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const 0) ))
^
-out/test/spec/tail-call/return_call_indirect.wast:309: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:337: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.4.wat:1:117: error: unexpected token "type", expected an expr.
...return_call_indirect (result i32) (type $sig) (param i32) (i32.const 0)...
^^^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.4.wat:1:173: error: unexpected token ), expected EOF.
...irect (result i32) (type $sig) (param i32) (i32.const 0) (i32.const 0) ))
^
-out/test/spec/tail-call/return_call_indirect.wast:321: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:349: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.5.wat:1:117: error: unexpected token "param", expected an expr.
...return_call_indirect (result i32) (param i32) (type $sig) (i32.const 0)...
^^^^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.5.wat:1:173: error: unexpected token ), expected EOF.
...irect (result i32) (param i32) (type $sig) (i32.const 0) (i32.const 0) ))
^
-out/test/spec/tail-call/return_call_indirect.wast:333: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:361: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.6.wat:1:74: error: unexpected token "param", expected an expr.
...return_call_indirect (result i32) (param i32) (i32.const 0) (i32.const ...
^^^^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.6.wat:1:118: error: unexpected token ), expected EOF.
...urn_call_indirect (result i32) (param i32) (i32.const 0) (i32.const 0) ))
^
-out/test/spec/tail-call/return_call_indirect.wast:345: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:373: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.7.wat:1:53: error: unexpected token $x, expected ).
...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))
^^
out/test/spec/tail-call/return_call_indirect/return_call_indirect.7.wat:1:89: error: unexpected token ), expected EOF.
...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))
^
-out/test/spec/tail-call/return_call_indirect.wast:352: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:380: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.8.wat:1:57: error: expected 0 results, got 1
...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (...
^^^^^^^^^^^^^^^^^^^^
-out/test/spec/tail-call/return_call_indirect.wast:362: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:390: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.9.wat:1:82: error: expected 1 arguments, got 0
...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (...
^^^^^^^^^^^^^^^^^^^^
-out/test/spec/tail-call/return_call_indirect.wast:372: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:400: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.10.wat:1:69: error: expected 1 results, got 0
...))(table 0 funcref)(func (return_call_indirect (type $sig) (param i32) ...
^^^^^^^^^^^^^^^^^^^^
-out/test/spec/tail-call/return_call_indirect.wast:384: assert_malformed passed:
+out/test/spec/tail-call/return_call_indirect.wast:412: assert_malformed passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.11.wat:1:86: error: expected 2 arguments, got 1
...ncref)(func (result i32) (return_call_indirect (type $sig) (param i32) (r...
^^^^^^^^^^^^^^^^^^^^
-out/test/spec/tail-call/return_call_indirect.wast:399: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:427: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.12.wasm:000001c: error: table variable out of range: 0 (max 0)
out/test/spec/tail-call/return_call_indirect/return_call_indirect.12.wasm:000001c: error: type mismatch: return_call_indirect must reference table of funcref type
000001c: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:407: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:435: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.13.wasm:0000024: error: type mismatch at end of function, expected [] but got [i32]
0000024: error: EndFunctionBody callback failed
-out/test/spec/tail-call/return_call_indirect.wast:415: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:443: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.14.wasm:0000026: error: return signatures have inconsistent types: expected [], got [i64]
0000026: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:424: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:452: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.15.wasm:0000026: error: type mismatch in return_call_indirect, expected [i32] but got []
0000026: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:432: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:460: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.16.wasm:0000027: error: type mismatch in return_call_indirect, expected [f64, i32] but got []
0000027: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:455: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:483: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.19.wasm:0000027: error: type mismatch in return_call_indirect, expected [i32] but got []
0000027: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:463: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:491: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.20.wasm:0000028: error: type mismatch in return_call_indirect, expected [i32] but got [... i64]
0000028: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:472: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:500: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.21.wasm:000002a: error: type mismatch in return_call_indirect, expected [i32, i32] but got [i32]
000002a: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:482: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:510: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.22.wasm:000002a: error: type mismatch in return_call_indirect, expected [i32, i32] but got [i32]
000002a: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:492: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:520: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.23.wasm:0000032: error: type mismatch in return_call_indirect, expected [i32, f64] but got [f64, i32]
0000032: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:502: assert_invalid passed:
+out/test/spec/tail-call/return_call_indirect.wast:530: assert_invalid passed:
out/test/spec/tail-call/return_call_indirect/return_call_indirect.24.wasm:0000032: error: type mismatch in return_call_indirect, expected [f64, i32] but got [i32, f64]
0000032: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:516: assert_invalid passed:
- out/test/spec/tail-call/return_call_indirect/return_call_indirect.25.wasm:0000022: error: function type variable out of range: 1 (max 1)
+out/test/spec/tail-call/return_call_indirect.wast:540: assert_invalid passed:
+ out/test/spec/tail-call/return_call_indirect/return_call_indirect.25.wasm:0000034: error: return signatures have inconsistent types: expected [i32], got [i32, i32]
+ 0000034: error: OnReturnCallIndirectExpr callback failed
+out/test/spec/tail-call/return_call_indirect.wast:553: assert_invalid passed:
+ out/test/spec/tail-call/return_call_indirect/return_call_indirect.26.wasm:0000022: error: type mismatch: return_call_indirect must reference table of funcref type
0000022: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:523: assert_invalid passed:
- out/test/spec/tail-call/return_call_indirect/return_call_indirect.26.wasm:0000026: error: function type variable out of range: 1012321300 (max 1)
+out/test/spec/tail-call/return_call_indirect.wast:564: assert_invalid passed:
+ out/test/spec/tail-call/return_call_indirect/return_call_indirect.27.wasm:0000022: error: function type variable out of range: 1 (max 1)
+ 0000022: error: OnReturnCallIndirectExpr callback failed
+out/test/spec/tail-call/return_call_indirect.wast:571: assert_invalid passed:
+ out/test/spec/tail-call/return_call_indirect/return_call_indirect.28.wasm:0000026: error: function type variable out of range: 1012321300 (max 1)
0000026: error: OnReturnCallIndirectExpr callback failed
-out/test/spec/tail-call/return_call_indirect.wast:534: assert_invalid passed:
- out/test/spec/tail-call/return_call_indirect/return_call_indirect.27.wasm:0000018: error: function variable out of range: 0 (max 0)
+out/test/spec/tail-call/return_call_indirect.wast:582: assert_invalid passed:
+ out/test/spec/tail-call/return_call_indirect/return_call_indirect.29.wasm:0000018: error: function variable out of range: 0 (max 0)
0000018: error: OnRefFuncExpr callback failed
-75/75 tests passed.
+79/79 tests passed.
;;; STDOUT ;;)
diff --git a/test/wasm2c/spec/tail-call/return_call.txt b/test/wasm2c/spec/tail-call/return_call.txt
index 6218eea..b12b00b 100644
--- a/test/wasm2c/spec/tail-call/return_call.txt
+++ b/test/wasm2c/spec/tail-call/return_call.txt
@@ -1,6 +1,7 @@
;;; TOOL: run-spec-wasm2c
-;;; STDIN_FILE: third_party/testsuite/proposals/tail-call/return_call.wast
+;;; STDIN_FILE: third_party/testsuite/proposals/wasm-3.0/return_call.wast
;;; ARGS*: --enable-tail-call
(;; STDOUT ;;;
-31/31 tests passed.
+spectest.print_i32_f32(5 91)
+33/33 tests passed.
;;; STDOUT ;;)
diff --git a/test/wasm2c/spec/tail-call/return_call_indirect.txt b/test/wasm2c/spec/tail-call/return_call_indirect.txt
index 8cf46bd..ceb9a77 100644
--- a/test/wasm2c/spec/tail-call/return_call_indirect.txt
+++ b/test/wasm2c/spec/tail-call/return_call_indirect.txt
@@ -1,6 +1,7 @@
;;; TOOL: run-spec-wasm2c
-;;; STDIN_FILE: third_party/testsuite/proposals/tail-call/return_call_indirect.wast
+;;; STDIN_FILE: third_party/testsuite/proposals/wasm-3.0/return_call_indirect.wast
;;; ARGS*: --enable-tail-call
(;; STDOUT ;;;
-47/47 tests passed.
+spectest.print_i32_f32(5 91)
+49/49 tests passed.
;;; STDOUT ;;)
diff --git a/test/wasm2c/tail-calls.txt b/test/wasm2c/tail-calls.txt
index c34204b..a8bcc99 100644
--- a/test/wasm2c/tail-calls.txt
+++ b/test/wasm2c/tail-calls.txt
@@ -869,7 +869,7 @@
{
next->fn = NULL;
struct wasm_multi_if params;
- wasm_rt_memcpy(params, tail_call_stack, sizeof(params));
+ wasm_rt_memcpy(¶ms, tail_call_stack, sizeof(params));
w2c_spectest_print_i32_f32(*instance_ptr, params.i0, params.f1);
}
diff --git a/third_party/testsuite b/third_party/testsuite
index cbc54d7..d76759e 160000
--- a/third_party/testsuite
+++ b/third_party/testsuite
@@ -1 +1 @@
-Subproject commit cbc54d77065e5202bcb69e0d1c53ceccc29a7984
+Subproject commit d76759e746f3564a03f6106ae19679742f2a1831