Skip to content

Commit f182330

Browse files
committed
Add the tail-call feature support for classic-interp
Signed-off-by: Xiaokang Qin <xiaokang.qxk@antgroup.com>
1 parent a7e7711 commit f182330

6 files changed

Lines changed: 134 additions & 33 deletions

File tree

build-scripts/config_common.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,8 @@ if (WAMR_BUILD_CUSTOM_NAME_SECTION EQUAL 1)
173173
add_definitions (-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
174174
message (" Custom name section enabled")
175175
endif ()
176+
if (WAMR_BUILD_TAIL_CALL EQUAL 1)
177+
add_definitions (-DWASM_ENABLE_TAIL_CALL=1)
178+
message (" Tail call enabled")
179+
endif ()
176180

core/iwasm/interpreter/wasm_interp_classic.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,11 +1285,33 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
12851285
cur_func = module->functions + fidx;
12861286
goto call_func_from_interp;
12871287

1288+
#if WASM_ENABLE_TAIL_CALL != 0
1289+
HANDLE_OP (WASM_OP_RETURN_CALL):
1290+
#if WASM_ENABLE_THREAD_MGR != 0
1291+
CHECK_SUSPEND_FLAGS();
1292+
#endif
1293+
read_leb_uint32(frame_ip, frame_ip_end, fidx);
1294+
#if WASM_ENABLE_MULTI_MODULE != 0
1295+
if (fidx >= module->function_count) {
1296+
wasm_set_exception(module, "unknown function");
1297+
goto got_exception;
1298+
}
1299+
#endif
1300+
cur_func = module->functions + fidx;
1301+
1302+
goto call_func_from_return_call;
1303+
#endif /* WASM_ENABLE_TAIL_CALL */
1304+
12881305
HANDLE_OP (WASM_OP_CALL_INDIRECT):
1306+
#if WASM_ENABLE_TAIL_CALL != 0
1307+
HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT):
1308+
#endif
12891309
{
12901310
WASMType *cur_type, *cur_func_type;
12911311
WASMTableInstance *cur_table_inst;
1292-
1312+
#if WASM_ENABLE_TAIL_CALL != 0
1313+
opcode = *(frame_ip - 1);
1314+
#endif
12931315
#if WASM_ENABLE_THREAD_MGR != 0
12941316
CHECK_SUSPEND_FLAGS();
12951317
#endif
@@ -1352,7 +1374,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
13521374
wasm_set_exception(module, "indirect call type mismatch");
13531375
goto got_exception;
13541376
}
1355-
1377+
#if WASM_ENABLE_TAIL_CALL != 0
1378+
if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
1379+
goto call_func_from_return_call;
1380+
#endif
13561381
goto call_func_from_interp;
13571382
}
13581383

@@ -3121,8 +3146,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
31213146
HANDLE_OP (WASM_OP_UNUSED_0x08):
31223147
HANDLE_OP (WASM_OP_UNUSED_0x09):
31233148
HANDLE_OP (WASM_OP_UNUSED_0x0a):
3124-
HANDLE_OP (WASM_OP_UNUSED_0x12):
3125-
HANDLE_OP (WASM_OP_UNUSED_0x13):
3149+
#if WASM_ENABLE_TAIL_CALL == 0
3150+
HANDLE_OP (WASM_OP_RETURN_CALL):
3151+
HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT):
3152+
#endif
31263153
HANDLE_OP (WASM_OP_UNUSED_0x14):
31273154
HANDLE_OP (WASM_OP_UNUSED_0x15):
31283155
HANDLE_OP (WASM_OP_UNUSED_0x16):
@@ -3151,6 +3178,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
31513178
FETCH_OPCODE_AND_DISPATCH ();
31523179
#endif
31533180

3181+
call_func_from_return_call:
3182+
POP(cur_func->param_cell_num);
3183+
FREE_FRAME(exec_env, frame);
3184+
word_copy(frame->lp, frame_sp, cur_func->param_cell_num);
3185+
wasm_exec_env_set_cur_frame(exec_env,
3186+
(WASMRuntimeFrame *)prev_frame);
3187+
goto call_func_from_entry;
31543188
call_func_from_interp:
31553189
/* Only do the copy when it's called from interpreter. */
31563190
{

core/iwasm/interpreter/wasm_interp_fast.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3125,8 +3125,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
31253125
HANDLE_OP (WASM_OP_UNUSED_0x08):
31263126
HANDLE_OP (WASM_OP_UNUSED_0x09):
31273127
HANDLE_OP (WASM_OP_UNUSED_0x0a):
3128-
HANDLE_OP (WASM_OP_UNUSED_0x12):
3129-
HANDLE_OP (WASM_OP_UNUSED_0x13):
3128+
HANDLE_OP (WASM_OP_RETURN_CALL):
3129+
HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT):
31303130
HANDLE_OP (WASM_OP_UNUSED_0x14):
31313131
HANDLE_OP (WASM_OP_UNUSED_0x15):
31323132
HANDLE_OP (WASM_OP_UNUSED_0x16):

core/iwasm/interpreter/wasm_loader.c

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,10 +3307,12 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
33073307
break;
33083308

33093309
case WASM_OP_CALL:
3310+
case WASM_OP_RETURN_CALL:
33103311
skip_leb_uint32(p, p_end); /* funcidx */
33113312
break;
33123313

33133314
case WASM_OP_CALL_INDIRECT:
3315+
case WASM_OP_RETURN_CALL_INDIRECT:
33143316
skip_leb_uint32(p, p_end); /* typeidx */
33153317
CHECK_BUF(p, p_end, 1);
33163318
u8 = read_uint8(p); /* 0x00 */
@@ -5795,7 +5797,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
57955797
{
57965798
int32 idx;
57975799
uint8 ret_type;
5798-
for (idx = (int32)func->func_type->result_count - 1; idx >= 0; idx--) {
5800+
5801+
for (idx = (int32)func->func_type->result_count - 1; idx >= 0;
5802+
idx--) {
57995803
ret_type = *(func->func_type->types
58005804
+ func->func_type->param_count + idx);
58015805
POP_TYPE(ret_type);
@@ -5812,6 +5816,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
58125816
}
58135817

58145818
case WASM_OP_CALL:
5819+
case WASM_OP_RETURN_CALL:
58155820
{
58165821
WASMType *func_type;
58175822
uint32 func_idx;
@@ -5844,22 +5849,47 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
58445849
}
58455850
}
58465851

5847-
for (i = 0; i < func_type->result_count; i++) {
5848-
PUSH_TYPE(func_type->types[func_type->param_count + i]);
5852+
if (opcode == WASM_OP_CALL) {
5853+
for (i = 0; i < func_type->result_count; i++) {
5854+
PUSH_TYPE(func_type->types[func_type->param_count + i]);
58495855
#if WASM_ENABLE_FAST_INTERP != 0
5850-
/* Here we emit each return value's dynamic_offset. But in fact
5851-
* these offsets are continuous, so interpreter only need to get
5852-
* the first return value's offset.
5853-
*/
5854-
PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]);
5856+
/* Here we emit each return value's dynamic_offset. But in fact
5857+
* these offsets are continuous, so interpreter only need to get
5858+
* the first return value's offset.
5859+
*/
5860+
PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]);
58555861
#endif
5862+
}
5863+
}
5864+
else {
5865+
char *type_str[] = { "f64", "f32", "i64", "i32" };
5866+
uint8 type;
5867+
if (func_type->result_count != func->func_type->result_count) {
5868+
set_error_buf_v(error_buf, error_buf_size,
5869+
"%s%u%s", "type mismatch: expect ",
5870+
func->func_type->result_count,
5871+
" return values but got other");
5872+
goto fail;
5873+
}
5874+
for (i = 0; i < func_type->result_count; i++) {
5875+
type = func->func_type->types[func->func_type->param_count + i];
5876+
if (func_type->types[func_type->param_count + i] != type) {
5877+
set_error_buf_v(error_buf, error_buf_size,
5878+
"%s%s%s", "type mismatch: expect ",
5879+
type_str[type - VALUE_TYPE_F64],
5880+
" but got other");
5881+
goto fail;
5882+
}
5883+
}
5884+
RESET_STACK();
5885+
SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
58565886
}
5857-
58585887
func->has_op_func_call = true;
58595888
break;
58605889
}
58615890

58625891
case WASM_OP_CALL_INDIRECT:
5892+
case WASM_OP_RETURN_CALL_INDIRECT:
58635893
{
58645894
int32 idx;
58655895
WASMType *func_type;
@@ -5904,13 +5934,36 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
59045934
}
59055935
}
59065936

5907-
for (i = 0; i < func_type->result_count; i++) {
5908-
PUSH_TYPE(func_type->types[func_type->param_count + i]);
5937+
if (opcode == WASM_OP_CALL) {
5938+
for (i = 0; i < func_type->result_count; i++) {
5939+
PUSH_TYPE(func_type->types[func_type->param_count + i]);
59095940
#if WASM_ENABLE_FAST_INTERP != 0
5910-
PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]);
5941+
PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]);
59115942
#endif
5943+
}
5944+
}
5945+
else {
5946+
char *type_str[] = { "f64", "f32", "i64", "i32" };
5947+
uint8 type;
5948+
if (func_type->result_count != func->func_type->result_count) {
5949+
set_error_buf_v(error_buf, error_buf_size,
5950+
"%s%u%s", "type mismatch: expect ",
5951+
func->func_type->result_count,
5952+
" return values but got other");
5953+
goto fail;
5954+
}
5955+
for (i = 0; i < func_type->result_count; i++) {
5956+
type = func->func_type->types[func->func_type->param_count + i];
5957+
if (func_type->types[func_type->param_count + i] != type)
5958+
set_error_buf_v(error_buf, error_buf_size, "%s%s%s",
5959+
"type mismatch: expect ",
5960+
type_str[type - VALUE_TYPE_F64],
5961+
" but got other");
5962+
goto fail;
5963+
}
5964+
RESET_STACK();
5965+
SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
59125966
}
5913-
59145967
func->has_op_func_call = true;
59155968
break;
59165969
}

core/iwasm/interpreter/wasm_mini_loader.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,10 +2235,12 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
22352235
break;
22362236

22372237
case WASM_OP_CALL:
2238+
case WASM_OP_RETURN_CALL:
22382239
skip_leb_uint32(p, p_end); /* funcidx */
22392240
break;
22402241

22412242
case WASM_OP_CALL_INDIRECT:
2243+
case WASM_OP_RETURN_CALL_INDIRECT:
22422244
skip_leb_uint32(p, p_end); /* typeidx */
22432245
CHECK_BUF(p, p_end, 1);
22442246
u8 = read_uint8(p); /* 0x00 */
@@ -4593,25 +4595,30 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
45934595

45944596
case WASM_OP_RETURN:
45954597
{
4596-
int32 idx;
4597-
uint8 ret_type;
4598-
for (idx = (int32)func->func_type->result_count - 1; idx >= 0; idx--) {
4599-
ret_type = *(func->func_type->types
4600-
+ func->func_type->param_count + idx);
4601-
POP_TYPE(ret_type);
4598+
handle_op_return:
4599+
{
4600+
int32 idx;
4601+
uint8 ret_type;
4602+
for (idx = (int32)func->func_type->result_count - 1; idx >= 0;
4603+
idx--) {
4604+
ret_type = *(func->func_type->types
4605+
+ func->func_type->param_count + idx);
4606+
POP_TYPE(ret_type);
46024607
#if WASM_ENABLE_FAST_INTERP != 0
46034608
/* emit the offset after return opcode */
46044609
POP_OFFSET_TYPE(ret_type);
46054610
#endif
4606-
}
4611+
}
46074612

4608-
RESET_STACK();
4609-
SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
4613+
RESET_STACK();
4614+
SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
46104615

4611-
break;
4616+
break;
4617+
}
46124618
}
46134619

46144620
case WASM_OP_CALL:
4621+
case WASM_OP_RETURN_CALL:
46154622
{
46164623
WASMType *func_type;
46174624
uint32 func_idx;
@@ -4653,10 +4660,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
46534660
}
46544661

46554662
func->has_op_func_call = true;
4663+
if (opcode == WASM_OP_RETURN_CALL) { goto handle_op_return; }
46564664
break;
46574665
}
46584666

46594667
case WASM_OP_CALL_INDIRECT:
4668+
case WASM_OP_RETURN_CALL_INDIRECT:
46604669
{
46614670
int32 idx;
46624671
WASMType *func_type;
@@ -4698,6 +4707,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
46984707
}
46994708

47004709
func->has_op_func_call = true;
4710+
if (opcode == WASM_OP_RETURN_CALL_INDIRECT) { goto handle_op_return; }
47014711
break;
47024712
}
47034713

core/iwasm/interpreter/wasm_opcode.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ typedef enum WASMOpcode {
3434
WASM_OP_RETURN = 0x0f, /* return */
3535
WASM_OP_CALL = 0x10, /* call */
3636
WASM_OP_CALL_INDIRECT = 0x11, /* call_indirect */
37+
WASM_OP_RETURN_CALL = 0x12, /* return_call */
38+
WASM_OP_RETURN_CALL_INDIRECT = 0x13, /* return_call_indirect */
3739

38-
WASM_OP_UNUSED_0x12 = 0x12,
39-
WASM_OP_UNUSED_0x13 = 0x13,
4040
WASM_OP_UNUSED_0x14 = 0x14,
4141
WASM_OP_UNUSED_0x15 = 0x15,
4242
WASM_OP_UNUSED_0x16 = 0x16,
@@ -403,8 +403,8 @@ static type _name[WASM_INSTRUCTION_NUM] = { \
403403
HANDLE_OPCODE (WASM_OP_RETURN), /* 0x0f */ \
404404
HANDLE_OPCODE (WASM_OP_CALL), /* 0x10 */ \
405405
HANDLE_OPCODE (WASM_OP_CALL_INDIRECT), /* 0x11 */ \
406-
HANDLE_OPCODE (WASM_OP_UNUSED_0x12), /* 0x12 */ \
407-
HANDLE_OPCODE (WASM_OP_UNUSED_0x13), /* 0x13 */ \
406+
HANDLE_OPCODE (WASM_OP_RETURN_CALL), /* 0x12 */ \
407+
HANDLE_OPCODE (WASM_OP_RETURN_CALL_INDIRECT), /* 0x13 */ \
408408
HANDLE_OPCODE (WASM_OP_UNUSED_0x14), /* 0x14 */ \
409409
HANDLE_OPCODE (WASM_OP_UNUSED_0x15), /* 0x15 */ \
410410
HANDLE_OPCODE (WASM_OP_UNUSED_0x16), /* 0x16 */ \

0 commit comments

Comments
 (0)