Implement multi-value feature and import binarydump tool (#308)
This commit is contained in:
@ -66,10 +66,10 @@ extern "C" {
|
||||
#define EXPORT_KIND_MEMORY 2
|
||||
#define EXPORT_KIND_GLOBAL 3
|
||||
|
||||
#define BLOCK_TYPE_BLOCK 0
|
||||
#define BLOCK_TYPE_LOOP 1
|
||||
#define BLOCK_TYPE_IF 2
|
||||
#define BLOCK_TYPE_FUNCTION 3
|
||||
#define LABEL_TYPE_BLOCK 0
|
||||
#define LABEL_TYPE_LOOP 1
|
||||
#define LABEL_TYPE_IF 2
|
||||
#define LABEL_TYPE_FUNCTION 3
|
||||
|
||||
typedef struct WASMModule WASMModule;
|
||||
typedef struct WASMFunction WASMFunction;
|
||||
@ -98,9 +98,10 @@ typedef struct InitializerExpression {
|
||||
} InitializerExpression;
|
||||
|
||||
typedef struct WASMType {
|
||||
uint32 param_count;
|
||||
/* only one result is supported currently */
|
||||
uint32 result_count;
|
||||
uint16 param_count;
|
||||
uint16 result_count;
|
||||
uint16 param_cell_num;
|
||||
uint16 ret_cell_num;
|
||||
/* types of params and results */
|
||||
uint8 types[1];
|
||||
} WASMType;
|
||||
@ -206,7 +207,7 @@ typedef struct WASMFunction {
|
||||
uint16 ret_cell_num;
|
||||
/* cell num of local variables */
|
||||
uint16 local_cell_num;
|
||||
/* offset of each local, including function paramameters
|
||||
/* offset of each local, including function parameters
|
||||
and local variables */
|
||||
uint16 *local_offsets;
|
||||
|
||||
@ -351,9 +352,21 @@ typedef struct WASMModule {
|
||||
#endif
|
||||
} WASMModule;
|
||||
|
||||
typedef struct BlockType {
|
||||
/* Block type may be expressed in one of two forms:
|
||||
* either by the type of the single return value or
|
||||
* by a type index of module.
|
||||
*/
|
||||
union {
|
||||
uint8 value_type;
|
||||
WASMType *type;
|
||||
} u;
|
||||
bool is_value_type;
|
||||
} BlockType;
|
||||
|
||||
typedef struct WASMBranchBlock {
|
||||
uint8 block_type;
|
||||
uint8 return_type;
|
||||
uint8 label_type;
|
||||
uint32 cell_num;
|
||||
uint8 *target_addr;
|
||||
uint32 *frame_sp;
|
||||
} WASMBranchBlock;
|
||||
@ -421,40 +434,28 @@ wasm_value_type_size(uint8 value_type)
|
||||
inline static uint16
|
||||
wasm_value_type_cell_num(uint8 value_type)
|
||||
{
|
||||
switch (value_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
return 1;
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
return 2;
|
||||
default:
|
||||
bh_assert(0);
|
||||
if (value_type == VALUE_TYPE_VOID)
|
||||
return 0;
|
||||
else if (value_type == VALUE_TYPE_I32
|
||||
|| value_type == VALUE_TYPE_F32)
|
||||
return 1;
|
||||
else if (value_type == VALUE_TYPE_I64
|
||||
|| value_type == VALUE_TYPE_F64)
|
||||
return 2;
|
||||
else {
|
||||
bh_assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static uint16
|
||||
inline static uint32
|
||||
wasm_get_cell_num(const uint8 *types, uint32 type_count)
|
||||
{
|
||||
uint32 cell_num = 0;
|
||||
uint32 i;
|
||||
for (i = 0; i < type_count; i++)
|
||||
cell_num += wasm_value_type_cell_num(types[i]);
|
||||
return (uint16)cell_num;
|
||||
}
|
||||
|
||||
inline static uint16
|
||||
wasm_type_param_cell_num(const WASMType *type)
|
||||
{
|
||||
return wasm_get_cell_num(type->types, type->param_count);
|
||||
}
|
||||
|
||||
inline static uint16
|
||||
wasm_type_return_cell_num(const WASMType *type)
|
||||
{
|
||||
return wasm_get_cell_num(type->types + type->param_count,
|
||||
type->result_count);
|
||||
return cell_num;
|
||||
}
|
||||
|
||||
inline static bool
|
||||
@ -467,8 +468,45 @@ wasm_type_equal(const WASMType *type1, const WASMType *type2)
|
||||
? true : false;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
block_type_get_param_types(BlockType *block_type,
|
||||
uint8 **p_param_types)
|
||||
{
|
||||
uint32 param_count = 0;
|
||||
if (!block_type->is_value_type) {
|
||||
WASMType *wasm_type = block_type->u.type;
|
||||
*p_param_types = wasm_type->types;
|
||||
param_count = wasm_type->param_count;
|
||||
}
|
||||
else {
|
||||
*p_param_types = NULL;
|
||||
param_count = 0;
|
||||
}
|
||||
|
||||
return param_count;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
block_type_get_result_types(BlockType *block_type,
|
||||
uint8 **p_result_types)
|
||||
{
|
||||
uint32 result_count = 0;
|
||||
if (block_type->is_value_type) {
|
||||
if (block_type->u.value_type != VALUE_TYPE_VOID) {
|
||||
*p_result_types = &block_type->u.value_type;
|
||||
result_count = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
WASMType *wasm_type = block_type->u.type;
|
||||
*p_result_types = wasm_type->types + wasm_type->param_count;
|
||||
result_count = wasm_type->result_count;
|
||||
}
|
||||
return result_count;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_H_ */
|
||||
#endif /* end of _WASM_H_ */
|
||||
|
||||
@ -27,8 +27,8 @@ typedef struct WASMInterpFrame {
|
||||
uint8 *ip;
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
/* return offset of current frame.
|
||||
the callee will put return value here */
|
||||
/* return offset of the first return value of current frame.
|
||||
the callee will put return values here continuously */
|
||||
uint32 ret_offset;
|
||||
uint32 *lp;
|
||||
uint32 operand[1];
|
||||
|
||||
@ -414,13 +414,13 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
frame_sp += 2; \
|
||||
} while (0)
|
||||
|
||||
#define PUSH_CSP(type, ret_type, _target_addr) do { \
|
||||
bh_assert(frame_csp < frame->csp_boundary); \
|
||||
frame_csp->block_type = type; \
|
||||
frame_csp->return_type = ret_type; \
|
||||
frame_csp->target_addr = _target_addr; \
|
||||
frame_csp->frame_sp = frame_sp; \
|
||||
frame_csp++; \
|
||||
#define PUSH_CSP(_label_type, cell_num, _target_addr) do { \
|
||||
bh_assert(frame_csp < frame->csp_boundary); \
|
||||
frame_csp->label_type = _label_type; \
|
||||
frame_csp->cell_num = cell_num; \
|
||||
frame_csp->target_addr = _target_addr; \
|
||||
frame_csp->frame_sp = frame_sp; \
|
||||
frame_csp++; \
|
||||
} while (0)
|
||||
|
||||
#define POP_I32() (--frame_sp, *(int32*)frame_sp)
|
||||
@ -442,21 +442,15 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
|
||||
#define POP_CSP_N(n) do { \
|
||||
uint32 *frame_sp_old = frame_sp; \
|
||||
uint32 cell_num = 0; \
|
||||
POP_CSP_CHECK_OVERFLOW(n + 1); \
|
||||
frame_csp -= n; \
|
||||
frame_ip = (frame_csp - 1)->target_addr; \
|
||||
/* copy return value of block */ \
|
||||
/* copy arity values of block */ \
|
||||
frame_sp = (frame_csp - 1)->frame_sp; \
|
||||
switch ((frame_csp - 1)->return_type) { \
|
||||
case VALUE_TYPE_I32: \
|
||||
case VALUE_TYPE_F32: \
|
||||
PUSH_I32(*(frame_sp_old - 1)); \
|
||||
break; \
|
||||
case VALUE_TYPE_I64: \
|
||||
case VALUE_TYPE_F64: \
|
||||
PUSH_I64(GET_I64_FROM_ADDR(frame_sp_old - 2)); \
|
||||
break; \
|
||||
} \
|
||||
cell_num = (frame_csp - 1)->cell_num; \
|
||||
word_copy(frame_sp, frame_sp_old - cell_num, cell_num); \
|
||||
frame_sp += cell_num; \
|
||||
} while (0)
|
||||
|
||||
/* Pop the given number of elements from the given frame's stack. */
|
||||
@ -974,6 +968,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint8 *global_data = module->global_data;
|
||||
uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
WASMTableInstance *table = module->default_table;
|
||||
WASMType **wasm_types = module->module->types;
|
||||
WASMGlobalInstance *globals = module->globals, *global;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
WASMInterpFrame *frame = NULL;
|
||||
@ -984,7 +979,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
WASMBranchBlock *frame_csp = NULL;
|
||||
BlockAddr *cache_items;
|
||||
uint8 *frame_ip_end = frame_ip + 1;
|
||||
uint8 opcode, block_ret_type;
|
||||
uint8 opcode;
|
||||
uint32 *depths = NULL;
|
||||
uint32 depth_buf[BR_TABLE_TMP_BUF_LEN];
|
||||
uint32 i, depth, cond, count, fidx, tidx, frame_size = 0;
|
||||
@ -993,7 +988,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint8 *else_addr, *end_addr, *maddr = NULL;
|
||||
uint32 local_idx, local_offset, global_idx;
|
||||
uint8 local_type, *global_addr;
|
||||
uint32 cache_index;
|
||||
uint32 cache_index, type_index, cell_num;
|
||||
uint8 value_type;
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||
#define HANDLE_OPCODE(op) &&HANDLE_##op
|
||||
@ -1016,9 +1012,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
HANDLE_OP (WASM_OP_NOP):
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_BLOCK):
|
||||
block_ret_type = *frame_ip++;
|
||||
HANDLE_OP (EXT_OP_BLOCK):
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||
cell_num = wasm_types[type_index]->ret_cell_num;
|
||||
goto handle_op_block;
|
||||
|
||||
HANDLE_OP (WASM_OP_BLOCK):
|
||||
value_type = *frame_ip++;
|
||||
cell_num = wasm_value_type_cell_num(value_type);
|
||||
handle_op_block:
|
||||
cache_index = ((uintptr_t)frame_ip) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
|
||||
cache_items = exec_env->block_addr_cache[cache_index];
|
||||
if (cache_items[0].start_addr == frame_ip) {
|
||||
@ -1029,24 +1031,37 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
}
|
||||
else if (!wasm_loader_find_block_addr((BlockAddr*)exec_env->block_addr_cache,
|
||||
frame_ip, (uint8*)-1,
|
||||
BLOCK_TYPE_BLOCK,
|
||||
LABEL_TYPE_BLOCK,
|
||||
&else_addr, &end_addr,
|
||||
NULL, 0)) {
|
||||
wasm_set_exception(module, "find block address failed");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
PUSH_CSP(BLOCK_TYPE_BLOCK, block_ret_type, end_addr);
|
||||
PUSH_CSP(LABEL_TYPE_BLOCK, cell_num, end_addr);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (EXT_OP_LOOP):
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||
cell_num = wasm_types[type_index]->param_cell_num;
|
||||
goto handle_op_loop;
|
||||
|
||||
HANDLE_OP (WASM_OP_LOOP):
|
||||
block_ret_type = *frame_ip++;
|
||||
PUSH_CSP(BLOCK_TYPE_LOOP, block_ret_type, frame_ip);
|
||||
value_type = *frame_ip++;
|
||||
cell_num = wasm_value_type_cell_num(value_type);
|
||||
handle_op_loop:
|
||||
PUSH_CSP(LABEL_TYPE_LOOP, cell_num, frame_ip);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_IF):
|
||||
block_ret_type = *frame_ip++;
|
||||
HANDLE_OP (EXT_OP_IF):
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||
cell_num = wasm_types[type_index]->ret_cell_num;
|
||||
goto handle_op_if;
|
||||
|
||||
HANDLE_OP (WASM_OP_IF):
|
||||
value_type = *frame_ip++;
|
||||
cell_num = wasm_value_type_cell_num(value_type);
|
||||
handle_op_if:
|
||||
cache_index = ((uintptr_t)frame_ip) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
|
||||
cache_items = exec_env->block_addr_cache[cache_index];
|
||||
if (cache_items[0].start_addr == frame_ip) {
|
||||
@ -1059,7 +1074,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
}
|
||||
else if (!wasm_loader_find_block_addr((BlockAddr*)exec_env->block_addr_cache,
|
||||
frame_ip, (uint8*)-1,
|
||||
BLOCK_TYPE_IF,
|
||||
LABEL_TYPE_IF,
|
||||
&else_addr, &end_addr,
|
||||
NULL, 0)) {
|
||||
wasm_set_exception(module, "find block address failed");
|
||||
@ -1068,7 +1083,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
cond = (uint32)POP_I32();
|
||||
|
||||
PUSH_CSP(BLOCK_TYPE_IF, block_ret_type, end_addr);
|
||||
PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr);
|
||||
|
||||
/* condition of the if branch is false, else condition is met */
|
||||
if (cond == 0) {
|
||||
@ -1106,6 +1121,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
read_leb_uint32(frame_ip, frame_ip_end, depth);
|
||||
label_pop_csp_n:
|
||||
POP_CSP_N(depth);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
@ -1116,7 +1132,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
read_leb_uint32(frame_ip, frame_ip_end, depth);
|
||||
cond = (uint32)POP_I32();
|
||||
if (cond)
|
||||
POP_CSP_N(depth);
|
||||
goto label_pop_csp_n;
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_BR_TABLE):
|
||||
@ -1147,7 +1163,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
wasm_runtime_free(depths);
|
||||
depths = NULL;
|
||||
}
|
||||
POP_CSP_N(depth);
|
||||
goto label_pop_csp_n;
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_RETURN):
|
||||
@ -1192,7 +1208,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
wasm_set_exception(module, "type index is overflow");
|
||||
goto got_exception;
|
||||
}
|
||||
cur_type = module->module->types[tidx];
|
||||
cur_type = wasm_types[tidx];
|
||||
|
||||
/* to skip 0x00 here */
|
||||
frame_ip++;
|
||||
@ -2705,6 +2721,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
HANDLE_OP (EXT_OP_TEE_LOCAL_FAST_I64):
|
||||
HANDLE_OP (EXT_OP_COPY_STACK_TOP):
|
||||
HANDLE_OP (EXT_OP_COPY_STACK_TOP_I64):
|
||||
HANDLE_OP (EXT_OP_COPY_STACK_VALUES):
|
||||
{
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
@ -2753,7 +2770,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
else {
|
||||
WASMFunction *cur_wasm_func = cur_func->u.func;
|
||||
WASMType *func_type;
|
||||
uint8 ret_type;
|
||||
|
||||
func_type = cur_wasm_func->func_type;
|
||||
|
||||
@ -2790,10 +2806,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
(uint32)(cur_func->local_cell_num * 4));
|
||||
|
||||
/* Push function block as first block */
|
||||
ret_type = func_type->result_count
|
||||
? cur_func->param_types[func_type->param_count]
|
||||
: VALUE_TYPE_VOID;
|
||||
PUSH_CSP(BLOCK_TYPE_FUNCTION, ret_type, frame_ip_end - 1);
|
||||
cell_num = func_type->ret_cell_num;
|
||||
PUSH_CSP(LABEL_TYPE_FUNCTION, cell_num, frame_ip_end - 1);
|
||||
|
||||
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)frame);
|
||||
}
|
||||
@ -2837,7 +2851,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
WASMInterpFrame *frame, *outs_area;
|
||||
|
||||
/* Allocate sufficient cells for all kinds of return values. */
|
||||
unsigned all_cell_num = 2, i;
|
||||
unsigned all_cell_num = function->ret_cell_num > 2 ?
|
||||
function->ret_cell_num : 2, i;
|
||||
/* This frame won't be used by JITed code, so only allocate interp
|
||||
frame here. */
|
||||
unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
|
||||
|
||||
@ -679,21 +679,121 @@ trunc_f64_to_int(WASMModuleInstance *module,
|
||||
PUSH_##dst_op_type(value); \
|
||||
} while (0)
|
||||
|
||||
#define RECOVER_BR_INFO() do { \
|
||||
uint16 stack_index, ret_cell_num; \
|
||||
stack_index = *(uint16*)frame_ip; \
|
||||
frame_ip += sizeof(uint16); \
|
||||
ret_cell_num = *(uint8*)frame_ip; \
|
||||
frame_ip += sizeof(uint8); \
|
||||
if (ret_cell_num == 1) \
|
||||
frame_lp[stack_index] = \
|
||||
frame_lp[*(int16*)frame_ip]; \
|
||||
else if (ret_cell_num == 2) { \
|
||||
*(int64*)(frame_lp + stack_index) = \
|
||||
*(int64*)(frame_lp + *(int16*)frame_ip);\
|
||||
} \
|
||||
frame_ip += sizeof(int16); \
|
||||
frame_ip = *(uint8**)frame_ip; \
|
||||
static bool
|
||||
copy_stack_values(WASMModuleInstance *module,
|
||||
uint32 *frame_lp,
|
||||
uint32 arity,
|
||||
uint32 total_cell_num,
|
||||
const uint8 *cells,
|
||||
const int16 *src_offsets,
|
||||
const uint16 *dst_offsets)
|
||||
{
|
||||
/* To avoid the overlap issue between src offsets and dst offset,
|
||||
* we use 2 steps to do the copy. First step, copy the src values
|
||||
* to a tmp buf. Second step, copy the values from tmp buf to dst.
|
||||
*/
|
||||
uint32 buf[16] = {0}, i;
|
||||
uint32 *tmp_buf = buf;
|
||||
uint8 cell;
|
||||
int16 src, buf_index = 0;
|
||||
uint16 dst;
|
||||
|
||||
/* Allocate memory if the buf is not large enough */
|
||||
if (total_cell_num > sizeof(buf)/sizeof(uint32)) {
|
||||
uint64 total_size = sizeof(uint32) * (uint64)total_cell_num;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(tmp_buf = wasm_runtime_malloc((uint32)total_size))) {
|
||||
wasm_set_exception(module,
|
||||
"WASM interp failed: allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* 1) Copy values from src to tmp buf */
|
||||
for (i = 0; i < arity; i++) {
|
||||
cell = cells[i];
|
||||
src = src_offsets[i];
|
||||
if (cell == 1)
|
||||
tmp_buf[buf_index] = frame_lp[src];
|
||||
else
|
||||
*(uint64*)(tmp_buf + buf_index) = *(uint64*)(frame_lp + src);
|
||||
buf_index += cell;
|
||||
}
|
||||
|
||||
/* 2) Copy values from tmp buf to dest */
|
||||
buf_index = 0;
|
||||
for (i = 0; i < arity; i++) {
|
||||
cell = cells[i];
|
||||
dst = dst_offsets[i];
|
||||
if (cell == 1)
|
||||
frame_lp[dst] = tmp_buf[buf_index];
|
||||
else
|
||||
*(uint64*)(frame_lp + dst) = *(uint64*)(tmp_buf + buf_index);
|
||||
buf_index += cell;
|
||||
}
|
||||
|
||||
if (tmp_buf != buf) {
|
||||
wasm_runtime_free(tmp_buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define RECOVER_BR_INFO() do { \
|
||||
uint32 arity; \
|
||||
/* read arity */ \
|
||||
arity = *(uint32*)frame_ip; \
|
||||
frame_ip += sizeof(arity); \
|
||||
if (arity) { \
|
||||
uint32 total_cell; \
|
||||
uint16 *dst_offsets = NULL; \
|
||||
uint8 *cells; \
|
||||
int16 *src_offsets = NULL; \
|
||||
/* read total cell num */ \
|
||||
total_cell = *(uint32*)frame_ip; \
|
||||
frame_ip += sizeof(total_cell); \
|
||||
/* cells */ \
|
||||
cells = (uint8 *)frame_ip; \
|
||||
frame_ip += arity * sizeof(uint8); \
|
||||
/* src offsets */ \
|
||||
src_offsets = (int16 *)frame_ip; \
|
||||
frame_ip += arity * sizeof(int16); \
|
||||
/* dst offsets */ \
|
||||
dst_offsets = (uint16*)frame_ip; \
|
||||
frame_ip += arity * sizeof(uint16); \
|
||||
if (arity == 1) { \
|
||||
if (cells[0] == 1) \
|
||||
frame_lp[dst_offsets[0]] = \
|
||||
frame_lp[src_offsets[0]]; \
|
||||
else if (cells[0] == 2) { \
|
||||
*(int64*)(frame_lp + dst_offsets[0]) = \
|
||||
*(int64*)(frame_lp + src_offsets[0]); \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
if (!copy_stack_values(module, frame_lp, \
|
||||
arity, total_cell, \
|
||||
cells, src_offsets, \
|
||||
dst_offsets)) \
|
||||
goto got_exception; \
|
||||
} \
|
||||
} \
|
||||
frame_ip = *(uint8**)frame_ip; \
|
||||
} while (0)
|
||||
|
||||
#define SKIP_BR_INFO() do { \
|
||||
uint32 arity; \
|
||||
/* read and skip arity */ \
|
||||
arity = *(uint32*)frame_ip; \
|
||||
frame_ip += sizeof(arity); \
|
||||
if (arity) { \
|
||||
/* skip total cell num */ \
|
||||
frame_ip += sizeof(uint32); \
|
||||
/* skip cells, src offsets and dst offsets */ \
|
||||
frame_ip += (sizeof(uint8) + sizeof(int16) + sizeof(uint16)) * arity; \
|
||||
} \
|
||||
/* skip target address */ \
|
||||
frame_ip += sizeof(uint8*); \
|
||||
} while (0)
|
||||
|
||||
static inline int32
|
||||
@ -1034,6 +1134,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
recover_br_info:
|
||||
RECOVER_BR_INFO();
|
||||
HANDLE_OP_END ();
|
||||
|
||||
@ -1044,10 +1145,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
cond = frame_lp[GET_OFFSET()];
|
||||
|
||||
if (cond)
|
||||
RECOVER_BR_INFO();
|
||||
else {
|
||||
frame_ip += (2 + 1 + 2 + sizeof(uint8*));
|
||||
}
|
||||
goto recover_br_info;
|
||||
else
|
||||
SKIP_BR_INFO();
|
||||
|
||||
HANDLE_OP_END ();
|
||||
|
||||
@ -1062,16 +1162,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (!(didx >= 0 && (uint32)didx < count))
|
||||
didx = count;
|
||||
|
||||
frame_ip += (didx * ((2 + 1 + 2 + sizeof(uint8*))));
|
||||
RECOVER_BR_INFO();
|
||||
HANDLE_OP_END ();
|
||||
while (didx--)
|
||||
SKIP_BR_INFO();
|
||||
|
||||
goto recover_br_info;
|
||||
|
||||
HANDLE_OP (WASM_OP_RETURN):
|
||||
if (cur_func->ret_cell_num == 2) {
|
||||
*((uint64 *)(prev_frame->lp + prev_frame->ret_offset)) =
|
||||
GET_OPERAND(uint64, 0);
|
||||
} else if (cur_func->ret_cell_num == 1) {
|
||||
prev_frame->lp[prev_frame->ret_offset] = GET_OPERAND(int32, 0);;
|
||||
{
|
||||
uint32 ret_idx;
|
||||
WASMType *func_type;
|
||||
uint32 off, ret_offset;
|
||||
uint8 *ret_types;
|
||||
if (cur_func->is_import_func
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
&& !cur_func->import_func_inst
|
||||
#endif
|
||||
)
|
||||
func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
func_type = cur_func->u.func->func_type;
|
||||
|
||||
/* types of each return value */
|
||||
ret_types = func_type->types + func_type->param_count;
|
||||
ret_offset = prev_frame->ret_offset;
|
||||
|
||||
for (ret_idx = 0, off = sizeof(int16) * (func_type->result_count - 1);
|
||||
ret_idx < func_type->result_count;
|
||||
ret_idx++, off -= sizeof(int16)) {
|
||||
if (ret_types[ret_idx] == VALUE_TYPE_I64
|
||||
|| ret_types[ret_idx] == VALUE_TYPE_F64) {
|
||||
*((uint64 *)(prev_frame->lp + ret_offset)) =
|
||||
GET_OPERAND(uint64, off);
|
||||
ret_offset += 2;
|
||||
}
|
||||
else {
|
||||
prev_frame->lp[ret_offset] = GET_OPERAND(int32, off);
|
||||
ret_offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
goto return_func;
|
||||
|
||||
@ -1128,7 +1256,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
&& !cur_func->import_func_inst
|
||||
#endif
|
||||
)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
cur_func_type = cur_func->u.func->func_type;
|
||||
if (!wasm_type_equal(cur_type, cur_func_type)) {
|
||||
@ -2350,6 +2478,37 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
*(uint64*)(frame_lp + addr2) = *(uint64*)(frame_lp + addr1);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (EXT_OP_COPY_STACK_VALUES):
|
||||
{
|
||||
uint32 values_count, total_cell;
|
||||
uint8 *cells;
|
||||
int16 *src_offsets = NULL;
|
||||
uint16 *dst_offsets = NULL;
|
||||
|
||||
/* read values_count */
|
||||
values_count = *(uint32*)frame_ip;
|
||||
frame_ip += sizeof(values_count);
|
||||
/* read total cell num */
|
||||
total_cell = *(uint32*)frame_ip;
|
||||
frame_ip += sizeof(total_cell);
|
||||
/* cells */
|
||||
cells = (uint8 *)frame_ip;
|
||||
frame_ip += values_count * sizeof(uint8);
|
||||
/* src offsets */
|
||||
src_offsets = (int16 *)frame_ip;
|
||||
frame_ip += values_count * sizeof(int16);
|
||||
/* dst offsets */
|
||||
dst_offsets = (uint16*)frame_ip;
|
||||
frame_ip += values_count * sizeof(uint16);
|
||||
|
||||
if (!copy_stack_values(module, frame_lp,
|
||||
values_count, total_cell,
|
||||
cells, src_offsets,
|
||||
dst_offsets))
|
||||
goto got_exception;
|
||||
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
HANDLE_OP (WASM_OP_SET_LOCAL):
|
||||
HANDLE_OP (WASM_OP_TEE_LOCAL):
|
||||
{
|
||||
@ -2567,6 +2726,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
HANDLE_OP (WASM_OP_LOOP):
|
||||
HANDLE_OP (WASM_OP_END):
|
||||
HANDLE_OP (WASM_OP_NOP):
|
||||
HANDLE_OP (EXT_OP_BLOCK):
|
||||
HANDLE_OP (EXT_OP_LOOP):
|
||||
HANDLE_OP (EXT_OP_IF):
|
||||
{
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
@ -2596,8 +2758,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
}
|
||||
}
|
||||
frame_ip += cur_func->param_count * sizeof(int16);
|
||||
if (cur_func->ret_cell_num != 0)
|
||||
if (cur_func->ret_cell_num != 0) {
|
||||
/* Get the first return value's offset. Since loader emit all return
|
||||
* values' offset so we must skip remain return values' offsets.
|
||||
*/
|
||||
WASMType *func_type;
|
||||
if (cur_func->is_import_func
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
&& !cur_func->import_func_inst
|
||||
#endif
|
||||
)
|
||||
func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
func_type = cur_func->u.func->func_type;
|
||||
frame->ret_offset = GET_OFFSET();
|
||||
frame_ip += 2 * (func_type->result_count - 1);
|
||||
}
|
||||
SYNC_ALL_TO_FRAME();
|
||||
prev_frame = frame;
|
||||
}
|
||||
@ -2712,7 +2888,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
WASMInterpFrame *frame, *outs_area;
|
||||
|
||||
/* Allocate sufficient cells for all kinds of return values. */
|
||||
unsigned all_cell_num = 2, i;
|
||||
unsigned all_cell_num = function->ret_cell_num > 2 ?
|
||||
function->ret_cell_num : 2, i;
|
||||
/* This frame won't be used by JITed code, so only allocate interp
|
||||
frame here. */
|
||||
unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -255,8 +255,11 @@ typedef enum WASMOpcode {
|
||||
EXT_OP_TEE_LOCAL_FAST_I64 = 0xcb,
|
||||
EXT_OP_COPY_STACK_TOP = 0xcc,
|
||||
EXT_OP_COPY_STACK_TOP_I64 = 0xcd,
|
||||
|
||||
WASM_OP_IMPDEP = 0xce,
|
||||
EXT_OP_COPY_STACK_VALUES = 0xce,
|
||||
EXT_OP_BLOCK = 0xcf, /* block with blocktype */
|
||||
EXT_OP_LOOP = 0xd0, /* loop with blocktype */
|
||||
EXT_OP_IF = 0xd1, /* if with blocktype */
|
||||
WASM_OP_IMPDEP = 0xd2,
|
||||
|
||||
/* Post-MVP extend op prefix */
|
||||
WASM_OP_MISC_PREFIX = 0xfc,
|
||||
@ -499,7 +502,11 @@ static type _name[WASM_INSTRUCTION_NUM] = { \
|
||||
HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST_I64), /* 0xcb */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP), /* 0xcc */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xcd */ \
|
||||
HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xce */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_VALUES), /* 0xce */ \
|
||||
HANDLE_OPCODE (EXT_OP_BLOCK), /* 0xcf */ \
|
||||
HANDLE_OPCODE (EXT_OP_LOOP), /* 0xd0 */ \
|
||||
HANDLE_OPCODE (EXT_OP_IF), /* 0xd1 */ \
|
||||
HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xd2 */ \
|
||||
}; \
|
||||
do { \
|
||||
_name[WASM_OP_MISC_PREFIX] = \
|
||||
|
||||
@ -509,9 +509,9 @@ functions_instantiate(const WASMModule *module,
|
||||
import->u.function.field_name);
|
||||
function->u.func_import = &import->u.function;
|
||||
function->param_cell_num =
|
||||
wasm_type_param_cell_num(import->u.function.func_type);
|
||||
import->u.function.func_type->param_cell_num;
|
||||
function->ret_cell_num =
|
||||
wasm_type_return_cell_num(import->u.function.func_type);
|
||||
import->u.function.func_type->ret_cell_num;
|
||||
function->param_count =
|
||||
(uint16)function->u.func_import->func_type->param_count;
|
||||
function->param_types = function->u.func_import->func_type->types;
|
||||
@ -1804,4 +1804,4 @@ wasm_get_aux_stack(WASMExecEnv *exec_env,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user