Skip to content

Commit 9ee3f00

Browse files
authored
Fix tail-call handling in interpreter and wasm2c (#2563)
1 parent e018404 commit 9ee3f00

File tree

8 files changed

+76
-60
lines changed

8 files changed

+76
-60
lines changed

src/c-writer.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,7 +1931,7 @@ void CWriter::WriteTailCallWeakImports() {
19311931
Index num_results = func.GetNumResults();
19321932
if (num_params >= 1) {
19331933
Write(func.decl.sig.param_types, " params;", Newline());
1934-
Write("wasm_rt_memcpy(params, tail_call_stack, sizeof(params));",
1934+
Write("wasm_rt_memcpy(&params, tail_call_stack, sizeof(params));",
19351935
Newline());
19361936
}
19371937

@@ -4201,7 +4201,7 @@ void CWriter::Write(const ExprList& exprs) {
42014201

42024202
Write("next->fn = ", TailCallRef(func.name), ";", Newline());
42034203
if (IsImport(func.name)) {
4204-
Write("*instance_ptr = ",
4204+
Write("*instance_ptr = instance->",
42054205
GlobalName(ModuleFieldType::Import,
42064206
import_module_sym_map_.at(func.name)),
42074207
";", Newline());

src/interp/binary-reader-interp.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,10 @@ Result BinaryReaderInterp::BeginFunctionBody(Index index, Offset size) {
831831
depth_fixups_.Clear();
832832
label_stack_.clear();
833833

834-
func_fixups_.Resolve(istream_, defined_index);
834+
// The fixups map is keyed by actual function index (not defined_index)
835+
// (function imports don't have code and won't appear in the fixups map,
836+
// but they still use function indexes)
837+
func_fixups_.Resolve(istream_, index);
835838

836839
CHECK_RESULT(validator_.BeginFunctionBody(GetLocation(), index));
837840

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
11
;;; TOOL: run-interp-spec
2-
;;; STDIN_FILE: third_party/testsuite/proposals/tail-call/return_call.wast
2+
;;; STDIN_FILE: third_party/testsuite/proposals/wasm-3.0/return_call.wast
33
;;; ARGS*: --enable-tail-call
44
(;; STDOUT ;;;
5-
out/test/spec/tail-call/return_call.wast:124: assert_invalid passed:
5+
called host spectest.print_i32_f32(i32:5, f32:91.000000) =>
6+
out/test/spec/tail-call/return_call.wast:141: assert_invalid passed:
67
out/test/spec/tail-call/return_call/return_call.1.wasm:000001e: error: return signatures have inconsistent types: expected [i32], got []
78
000001e: error: OnReturnCallExpr callback failed
8-
out/test/spec/tail-call/return_call.wast:131: assert_invalid passed:
9+
out/test/spec/tail-call/return_call.wast:148: assert_invalid passed:
910
out/test/spec/tail-call/return_call/return_call.2.wasm:000001f: error: return signatures have inconsistent types: expected [i32], got [i64]
1011
000001f: error: OnReturnCallExpr callback failed
11-
out/test/spec/tail-call/return_call.wast:139: assert_invalid passed:
12+
out/test/spec/tail-call/return_call.wast:156: assert_invalid passed:
1213
out/test/spec/tail-call/return_call/return_call.3.wasm:000001e: error: type mismatch in return_call, expected [i32] but got []
1314
000001e: error: OnReturnCallExpr callback failed
14-
out/test/spec/tail-call/return_call.wast:146: assert_invalid passed:
15+
out/test/spec/tail-call/return_call.wast:163: assert_invalid passed:
1516
out/test/spec/tail-call/return_call/return_call.4.wasm:000001f: error: type mismatch in return_call, expected [f64, i32] but got []
1617
000001f: error: OnReturnCallExpr callback failed
17-
out/test/spec/tail-call/return_call.wast:164: assert_invalid passed:
18+
out/test/spec/tail-call/return_call.wast:181: assert_invalid passed:
1819
out/test/spec/tail-call/return_call/return_call.7.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32]
1920
0000022: error: OnReturnCallExpr callback failed
20-
out/test/spec/tail-call/return_call.wast:171: assert_invalid passed:
21+
out/test/spec/tail-call/return_call.wast:188: assert_invalid passed:
2122
out/test/spec/tail-call/return_call/return_call.8.wasm:0000022: error: type mismatch in return_call, expected [i32, i32] but got [i32]
2223
0000022: error: OnReturnCallExpr callback failed
23-
out/test/spec/tail-call/return_call.wast:178: assert_invalid passed:
24+
out/test/spec/tail-call/return_call.wast:195: assert_invalid passed:
2425
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]
2526
000002a: error: OnReturnCallExpr callback failed
26-
out/test/spec/tail-call/return_call.wast:185: assert_invalid passed:
27+
out/test/spec/tail-call/return_call.wast:202: assert_invalid passed:
2728
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]
2829
000002a: error: OnReturnCallExpr callback failed
29-
out/test/spec/tail-call/return_call.wast:196: assert_invalid passed:
30-
out/test/spec/tail-call/return_call/return_call.11.wasm:0000019: error: function variable out of range: 1 (max 1)
30+
out/test/spec/tail-call/return_call.wast:209: assert_invalid passed:
31+
out/test/spec/tail-call/return_call/return_call.11.wasm:0000024: error: return signatures have inconsistent types: expected [i32], got [i32, i32]
32+
0000024: error: OnReturnCallExpr callback failed
33+
out/test/spec/tail-call/return_call.wast:221: assert_invalid passed:
34+
out/test/spec/tail-call/return_call/return_call.12.wasm:0000019: error: function variable out of range: 1 (max 1)
3135
0000019: error: OnReturnCallExpr callback failed
32-
out/test/spec/tail-call/return_call.wast:200: assert_invalid passed:
33-
out/test/spec/tail-call/return_call/return_call.12.wasm:000001d: error: function variable out of range: 1012321300 (max 1)
36+
out/test/spec/tail-call/return_call.wast:225: assert_invalid passed:
37+
out/test/spec/tail-call/return_call/return_call.13.wasm:000001d: error: function variable out of range: 1012321300 (max 1)
3438
000001d: error: OnReturnCallExpr callback failed
35-
44/44 tests passed.
39+
47/47 tests passed.
3640
;;; STDOUT ;;)
Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,128 @@
11
;;; TOOL: run-interp-spec
2-
;;; STDIN_FILE: third_party/testsuite/proposals/tail-call/return_call_indirect.wast
2+
;;; STDIN_FILE: third_party/testsuite/proposals/wasm-3.0/return_call_indirect.wast
33
;;; ARGS*: --enable-tail-call
44
(;; STDOUT ;;;
5-
out/test/spec/tail-call/return_call_indirect.wast:234: assert_trap passed: indirect call signature mismatch
6-
out/test/spec/tail-call/return_call_indirect.wast:235: assert_trap passed: indirect call signature mismatch
7-
out/test/spec/tail-call/return_call_indirect.wast:236: assert_trap passed: undefined table index
8-
out/test/spec/tail-call/return_call_indirect.wast:237: assert_trap passed: undefined table index
9-
out/test/spec/tail-call/return_call_indirect.wast:238: assert_trap passed: undefined table index
10-
out/test/spec/tail-call/return_call_indirect.wast:244: assert_trap passed: indirect call signature mismatch
11-
out/test/spec/tail-call/return_call_indirect.wast:245: assert_trap passed: indirect call signature mismatch
12-
out/test/spec/tail-call/return_call_indirect.wast:273: assert_malformed passed:
5+
out/test/spec/tail-call/return_call_indirect.wast:260: assert_trap passed: indirect call signature mismatch
6+
out/test/spec/tail-call/return_call_indirect.wast:261: assert_trap passed: indirect call signature mismatch
7+
out/test/spec/tail-call/return_call_indirect.wast:262: assert_trap passed: undefined table index
8+
out/test/spec/tail-call/return_call_indirect.wast:263: assert_trap passed: undefined table index
9+
out/test/spec/tail-call/return_call_indirect.wast:264: assert_trap passed: undefined table index
10+
out/test/spec/tail-call/return_call_indirect.wast:270: assert_trap passed: indirect call signature mismatch
11+
out/test/spec/tail-call/return_call_indirect.wast:271: assert_trap passed: indirect call signature mismatch
12+
called host spectest.print_i32_f32(i32:5, f32:91.000000) =>
13+
out/test/spec/tail-call/return_call_indirect.wast:301: assert_malformed passed:
1314
out/test/spec/tail-call/return_call_indirect/return_call_indirect.1.wat:1:129: error: unexpected token "param", expected an expr.
1415
...indirect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const ...
1516
^^^^^
1617
out/test/spec/tail-call/return_call_indirect/return_call_indirect.1.wat:1:173: error: unexpected token ), expected EOF.
1718
...irect (type $sig) (result i32) (param i32) (i32.const 0) (i32.const 0) ))
1819
^
19-
out/test/spec/tail-call/return_call_indirect.wast:285: assert_malformed passed:
20+
out/test/spec/tail-call/return_call_indirect.wast:313: assert_malformed passed:
2021
out/test/spec/tail-call/return_call_indirect/return_call_indirect.2.wat:1:116: error: unexpected token "type", expected an expr.
2122
...(return_call_indirect (param i32) (type $sig) (result i32) (i32.const 0...
2223
^^^^
2324
out/test/spec/tail-call/return_call_indirect/return_call_indirect.2.wat:1:173: error: unexpected token ), expected EOF.
2425
...irect (param i32) (type $sig) (result i32) (i32.const 0) (i32.const 0) ))
2526
^
26-
out/test/spec/tail-call/return_call_indirect.wast:297: assert_malformed passed:
27+
out/test/spec/tail-call/return_call_indirect.wast:325: assert_malformed passed:
2728
out/test/spec/tail-call/return_call_indirect/return_call_indirect.3.wat:1:129: error: unexpected token "type", expected an expr.
2829
...indirect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const ...
2930
^^^^
3031
out/test/spec/tail-call/return_call_indirect/return_call_indirect.3.wat:1:173: error: unexpected token ), expected EOF.
3132
...irect (param i32) (result i32) (type $sig) (i32.const 0) (i32.const 0) ))
3233
^
33-
out/test/spec/tail-call/return_call_indirect.wast:309: assert_malformed passed:
34+
out/test/spec/tail-call/return_call_indirect.wast:337: assert_malformed passed:
3435
out/test/spec/tail-call/return_call_indirect/return_call_indirect.4.wat:1:117: error: unexpected token "type", expected an expr.
3536
...return_call_indirect (result i32) (type $sig) (param i32) (i32.const 0)...
3637
^^^^
3738
out/test/spec/tail-call/return_call_indirect/return_call_indirect.4.wat:1:173: error: unexpected token ), expected EOF.
3839
...irect (result i32) (type $sig) (param i32) (i32.const 0) (i32.const 0) ))
3940
^
40-
out/test/spec/tail-call/return_call_indirect.wast:321: assert_malformed passed:
41+
out/test/spec/tail-call/return_call_indirect.wast:349: assert_malformed passed:
4142
out/test/spec/tail-call/return_call_indirect/return_call_indirect.5.wat:1:117: error: unexpected token "param", expected an expr.
4243
...return_call_indirect (result i32) (param i32) (type $sig) (i32.const 0)...
4344
^^^^^
4445
out/test/spec/tail-call/return_call_indirect/return_call_indirect.5.wat:1:173: error: unexpected token ), expected EOF.
4546
...irect (result i32) (param i32) (type $sig) (i32.const 0) (i32.const 0) ))
4647
^
47-
out/test/spec/tail-call/return_call_indirect.wast:333: assert_malformed passed:
48+
out/test/spec/tail-call/return_call_indirect.wast:361: assert_malformed passed:
4849
out/test/spec/tail-call/return_call_indirect/return_call_indirect.6.wat:1:74: error: unexpected token "param", expected an expr.
4950
...return_call_indirect (result i32) (param i32) (i32.const 0) (i32.const ...
5051
^^^^^
5152
out/test/spec/tail-call/return_call_indirect/return_call_indirect.6.wat:1:118: error: unexpected token ), expected EOF.
5253
...urn_call_indirect (result i32) (param i32) (i32.const 0) (i32.const 0) ))
5354
^
54-
out/test/spec/tail-call/return_call_indirect.wast:345: assert_malformed passed:
55+
out/test/spec/tail-call/return_call_indirect.wast:373: assert_malformed passed:
5556
out/test/spec/tail-call/return_call_indirect/return_call_indirect.7.wat:1:53: error: unexpected token $x, expected ).
5657
...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))
5758
^^
5859
out/test/spec/tail-call/return_call_indirect/return_call_indirect.7.wat:1:89: error: unexpected token ), expected EOF.
5960
...cref)(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))
6061
^
61-
out/test/spec/tail-call/return_call_indirect.wast:352: assert_malformed passed:
62+
out/test/spec/tail-call/return_call_indirect.wast:380: assert_malformed passed:
6263
out/test/spec/tail-call/return_call_indirect/return_call_indirect.8.wat:1:57: error: expected 0 results, got 1
6364
...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (...
6465
^^^^^^^^^^^^^^^^^^^^
65-
out/test/spec/tail-call/return_call_indirect.wast:362: assert_malformed passed:
66+
out/test/spec/tail-call/return_call_indirect.wast:390: assert_malformed passed:
6667
out/test/spec/tail-call/return_call_indirect/return_call_indirect.9.wat:1:82: error: expected 1 arguments, got 0
6768
...ncref)(func (result i32) (return_call_indirect (type $sig) (result i32) (...
6869
^^^^^^^^^^^^^^^^^^^^
69-
out/test/spec/tail-call/return_call_indirect.wast:372: assert_malformed passed:
70+
out/test/spec/tail-call/return_call_indirect.wast:400: assert_malformed passed:
7071
out/test/spec/tail-call/return_call_indirect/return_call_indirect.10.wat:1:69: error: expected 1 results, got 0
7172
...))(table 0 funcref)(func (return_call_indirect (type $sig) (param i32) ...
7273
^^^^^^^^^^^^^^^^^^^^
73-
out/test/spec/tail-call/return_call_indirect.wast:384: assert_malformed passed:
74+
out/test/spec/tail-call/return_call_indirect.wast:412: assert_malformed passed:
7475
out/test/spec/tail-call/return_call_indirect/return_call_indirect.11.wat:1:86: error: expected 2 arguments, got 1
7576
...ncref)(func (result i32) (return_call_indirect (type $sig) (param i32) (r...
7677
^^^^^^^^^^^^^^^^^^^^
77-
out/test/spec/tail-call/return_call_indirect.wast:399: assert_invalid passed:
78+
out/test/spec/tail-call/return_call_indirect.wast:427: assert_invalid passed:
7879
out/test/spec/tail-call/return_call_indirect/return_call_indirect.12.wasm:000001c: error: table variable out of range: 0 (max 0)
7980
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
8081
000001c: error: OnReturnCallIndirectExpr callback failed
81-
out/test/spec/tail-call/return_call_indirect.wast:407: assert_invalid passed:
82+
out/test/spec/tail-call/return_call_indirect.wast:435: assert_invalid passed:
8283
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]
8384
0000024: error: EndFunctionBody callback failed
84-
out/test/spec/tail-call/return_call_indirect.wast:415: assert_invalid passed:
85+
out/test/spec/tail-call/return_call_indirect.wast:443: assert_invalid passed:
8586
out/test/spec/tail-call/return_call_indirect/return_call_indirect.14.wasm:0000026: error: return signatures have inconsistent types: expected [], got [i64]
8687
0000026: error: OnReturnCallIndirectExpr callback failed
87-
out/test/spec/tail-call/return_call_indirect.wast:424: assert_invalid passed:
88+
out/test/spec/tail-call/return_call_indirect.wast:452: assert_invalid passed:
8889
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 []
8990
0000026: error: OnReturnCallIndirectExpr callback failed
90-
out/test/spec/tail-call/return_call_indirect.wast:432: assert_invalid passed:
91+
out/test/spec/tail-call/return_call_indirect.wast:460: assert_invalid passed:
9192
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 []
9293
0000027: error: OnReturnCallIndirectExpr callback failed
93-
out/test/spec/tail-call/return_call_indirect.wast:455: assert_invalid passed:
94+
out/test/spec/tail-call/return_call_indirect.wast:483: assert_invalid passed:
9495
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 []
9596
0000027: error: OnReturnCallIndirectExpr callback failed
96-
out/test/spec/tail-call/return_call_indirect.wast:463: assert_invalid passed:
97+
out/test/spec/tail-call/return_call_indirect.wast:491: assert_invalid passed:
9798
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]
9899
0000028: error: OnReturnCallIndirectExpr callback failed
99-
out/test/spec/tail-call/return_call_indirect.wast:472: assert_invalid passed:
100+
out/test/spec/tail-call/return_call_indirect.wast:500: assert_invalid passed:
100101
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]
101102
000002a: error: OnReturnCallIndirectExpr callback failed
102-
out/test/spec/tail-call/return_call_indirect.wast:482: assert_invalid passed:
103+
out/test/spec/tail-call/return_call_indirect.wast:510: assert_invalid passed:
103104
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]
104105
000002a: error: OnReturnCallIndirectExpr callback failed
105-
out/test/spec/tail-call/return_call_indirect.wast:492: assert_invalid passed:
106+
out/test/spec/tail-call/return_call_indirect.wast:520: assert_invalid passed:
106107
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]
107108
0000032: error: OnReturnCallIndirectExpr callback failed
108-
out/test/spec/tail-call/return_call_indirect.wast:502: assert_invalid passed:
109+
out/test/spec/tail-call/return_call_indirect.wast:530: assert_invalid passed:
109110
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]
110111
0000032: error: OnReturnCallIndirectExpr callback failed
111-
out/test/spec/tail-call/return_call_indirect.wast:516: assert_invalid passed:
112-
out/test/spec/tail-call/return_call_indirect/return_call_indirect.25.wasm:0000022: error: function type variable out of range: 1 (max 1)
112+
out/test/spec/tail-call/return_call_indirect.wast:540: assert_invalid passed:
113+
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]
114+
0000034: error: OnReturnCallIndirectExpr callback failed
115+
out/test/spec/tail-call/return_call_indirect.wast:553: assert_invalid passed:
116+
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
113117
0000022: error: OnReturnCallIndirectExpr callback failed
114-
out/test/spec/tail-call/return_call_indirect.wast:523: assert_invalid passed:
115-
out/test/spec/tail-call/return_call_indirect/return_call_indirect.26.wasm:0000026: error: function type variable out of range: 1012321300 (max 1)
118+
out/test/spec/tail-call/return_call_indirect.wast:564: assert_invalid passed:
119+
out/test/spec/tail-call/return_call_indirect/return_call_indirect.27.wasm:0000022: error: function type variable out of range: 1 (max 1)
120+
0000022: error: OnReturnCallIndirectExpr callback failed
121+
out/test/spec/tail-call/return_call_indirect.wast:571: assert_invalid passed:
122+
out/test/spec/tail-call/return_call_indirect/return_call_indirect.28.wasm:0000026: error: function type variable out of range: 1012321300 (max 1)
116123
0000026: error: OnReturnCallIndirectExpr callback failed
117-
out/test/spec/tail-call/return_call_indirect.wast:534: assert_invalid passed:
118-
out/test/spec/tail-call/return_call_indirect/return_call_indirect.27.wasm:0000018: error: function variable out of range: 0 (max 0)
124+
out/test/spec/tail-call/return_call_indirect.wast:582: assert_invalid passed:
125+
out/test/spec/tail-call/return_call_indirect/return_call_indirect.29.wasm:0000018: error: function variable out of range: 0 (max 0)
119126
0000018: error: OnRefFuncExpr callback failed
120-
75/75 tests passed.
127+
79/79 tests passed.
121128
;;; STDOUT ;;)

0 commit comments

Comments
 (0)