mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-06-01 14:37:14 +00:00
Implement post-MVP features and native stack overflow check (#243)
Implement native thread stack overflow check Implement post-MVP: Non-trapping float-to-int conversions Implement post-MVP: Sign-extension operators Enhance WASM loader checks
This commit is contained in:
parent
ab4f0c5419
commit
d381b0fdec
|
@ -124,3 +124,7 @@ else ()
|
|||
message (" Fast interpreter disabled")
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_SPEC_TEST EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_SPEC_TEST=1)
|
||||
message (" spec test compatible mode is on")
|
||||
endif()
|
||||
|
|
|
@ -179,6 +179,10 @@ enum {
|
|||
#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
|
||||
#endif
|
||||
|
||||
/* Reserved bytes to the native thread stack boundary, throw native
|
||||
stack overflow exception if the guard boudary is reached */
|
||||
#define RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY (512)
|
||||
|
||||
/* Default wasm block address cache size and conflict list size */
|
||||
#define BLOCK_ADDR_CACHE_SIZE 64
|
||||
#define BLOCK_ADDR_CONFLICT_SIZE 2
|
||||
|
|
|
@ -942,8 +942,7 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
/* check start function index */
|
||||
if (module->start_func_index != (uint32)-1
|
||||
&& (module->start_func_index < module->import_func_count
|
||||
|| module->start_func_index >= module->import_func_count
|
||||
&& (module->start_func_index >= module->import_func_count
|
||||
+ module->func_count)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
|
@ -1044,9 +1043,13 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
/* Set start function when function pointers are resolved */
|
||||
if (module->start_func_index != (uint32)-1) {
|
||||
module->start_function =
|
||||
module->func_ptrs[module->start_func_index
|
||||
- module->import_func_count];
|
||||
if (module->start_func_index >= module->import_func_count)
|
||||
module->start_function =
|
||||
module->func_ptrs[module->start_func_index
|
||||
- module->import_func_count];
|
||||
else
|
||||
/* TODO: fix start function can be import function issue */
|
||||
module->start_function = NULL;
|
||||
}
|
||||
else {
|
||||
module->start_function = NULL;
|
||||
|
|
|
@ -39,7 +39,11 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
init_expr = &global->init_expr;
|
||||
switch (init_expr->init_expr_type) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
bh_assert(init_expr->u.global_index < module->import_global_count);
|
||||
if (init_expr->u.global_index >= module->import_global_count + i) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Instantiate global failed: unknown global.");
|
||||
return false;
|
||||
}
|
||||
memcpy(p,
|
||||
&module->import_globals[init_expr->u.global_index].global_data_linked,
|
||||
global->size);
|
||||
|
@ -501,6 +505,9 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* set thread handle and stack boundary */
|
||||
wasm_exec_env_set_thread_info(exec_env);
|
||||
|
||||
ret = aot_call_function(exec_env, func, argc, argv);
|
||||
wasm_exec_env_destroy(exec_env);
|
||||
return ret;
|
||||
|
@ -556,6 +563,9 @@ aot_set_exception_with_id(AOTModuleInstance *module_inst,
|
|||
case EXCE_CALL_UNLINKED_IMPORT_FUNC:
|
||||
aot_set_exception(module_inst, "fail to call unlinked import function");
|
||||
break;
|
||||
case EXCE_NATIVE_STACK_OVERFLOW:
|
||||
aot_set_exception(module_inst, "native stack overflow");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -662,10 +672,12 @@ void *
|
|||
aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset)
|
||||
{
|
||||
int32 memory_data_size = (int32)module_inst->memory_data_size;
|
||||
uint8 *addr = (uint8 *)module_inst->memory_data.ptr + app_offset;
|
||||
|
||||
if (module_inst->heap_base_offset < app_offset
|
||||
&& app_offset < memory_data_size)
|
||||
return (uint8*)module_inst->memory_data.ptr + app_offset;
|
||||
if ((uint8*)module_inst->heap_data.ptr < addr
|
||||
&& addr < (uint8*)module_inst->memory_data.ptr
|
||||
+ memory_data_size)
|
||||
return addr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -929,6 +941,15 @@ aot_call_indirect(WASMExecEnv *exec_env,
|
|||
}
|
||||
}
|
||||
|
||||
/* this function is called from native code, so exec_env->handle and
|
||||
exec_env->native_stack_boundary must have been set, we don't set
|
||||
it again */
|
||||
|
||||
if ((uint8*)&module_inst < exec_env->native_stack_boundary) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
|
||||
return false;
|
||||
}
|
||||
|
||||
return wasm_runtime_invoke_native(exec_env, func_ptr,
|
||||
func_type, signature, attachment,
|
||||
argv, argc, argv);
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef enum AOTExceptionID {
|
|||
EXCE_UNDEFINED_ELEMENT,
|
||||
EXCE_UNINITIALIZED_ELEMENT,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
EXCE_NATIVE_STACK_OVERFLOW,
|
||||
EXCE_NUM,
|
||||
} AOTExceptionID;
|
||||
|
||||
|
|
|
@ -50,3 +50,12 @@ wasm_exec_env_get_module_inst(WASMExecEnv *exec_env)
|
|||
return exec_env->module_inst;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
|
||||
{
|
||||
exec_env->handle = os_self_thread();
|
||||
exec_env->native_stack_boundary = os_thread_get_stack_boundary()
|
||||
+ RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,15 @@ struct WASMInterpFrame;
|
|||
|
||||
/* Execution environment */
|
||||
typedef struct WASMExecEnv {
|
||||
/* Next thread's exec env of a WASM module instance. */
|
||||
/* Next thread's exec env of a WASM module instance. */
|
||||
struct WASMExecEnv *next;
|
||||
|
||||
/* Previous thread's exec env of a WASM module instance. */
|
||||
/* Previous thread's exec env of a WASM module instance. */
|
||||
struct WASMExecEnv *prev;
|
||||
|
||||
/* Note: field module_inst, argv_buf and native_stack_boundary
|
||||
are used by AOTed code, don't change the places of them */
|
||||
|
||||
/* The WASM module instance of current thread */
|
||||
struct WASMModuleInstanceCommon *module_inst;
|
||||
|
||||
|
@ -33,6 +36,11 @@ typedef struct WASMExecEnv {
|
|||
uint32 *argv_buf;
|
||||
#endif
|
||||
|
||||
/* The boundary of native stack. When runtime detects that native
|
||||
frame may overrun this boundary, it throws stack overflow
|
||||
exception. */
|
||||
uint8 *native_stack_boundary;
|
||||
|
||||
/* attachment for native function */
|
||||
void *attachment;
|
||||
|
||||
|
@ -48,11 +56,6 @@ typedef struct WASMExecEnv {
|
|||
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
|
||||
#endif
|
||||
|
||||
/* The boundary of native stack. When interpreter detects that native
|
||||
frame may overrun this boundary, it throws a stack overflow
|
||||
exception. */
|
||||
void *native_stack_boundary;
|
||||
|
||||
/* The WASM stack size */
|
||||
uint32 wasm_stack_size;
|
||||
|
||||
|
@ -61,13 +64,13 @@ typedef struct WASMExecEnv {
|
|||
uint64 __make_it_8_byte_aligned_;
|
||||
|
||||
struct {
|
||||
/* The top boundary of the stack. */
|
||||
/* The top boundary of the stack. */
|
||||
uint8 *top_boundary;
|
||||
|
||||
/* Top cell index which is free. */
|
||||
/* Top cell index which is free. */
|
||||
uint8 *top;
|
||||
|
||||
/* The Java stack. */
|
||||
/* The WASM stack. */
|
||||
uint8 bottom[1];
|
||||
} s;
|
||||
} wasm_stack;
|
||||
|
@ -159,6 +162,9 @@ wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env)
|
|||
struct WASMModuleInstanceCommon *
|
||||
wasm_exec_env_get_module_inst(WASMExecEnv *exec_env);
|
||||
|
||||
void
|
||||
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -14,8 +14,10 @@ static NativeSymbolsList g_native_symbols_list_end = NULL;
|
|||
uint32
|
||||
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST != 0
|
||||
uint32
|
||||
get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
|
||||
#endif
|
||||
|
||||
uint32
|
||||
get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
|
||||
|
@ -242,11 +244,13 @@ wasm_native_init()
|
|||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST
|
||||
n_native_symbols = get_spectest_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("spectest",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
#endif /* WASM_ENABLE_SPEC_TEST */
|
||||
#endif /* WASM_ENABLE_LIBC_BUILTIN */
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
|
||||
|
|
|
@ -292,7 +292,8 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
|||
return false;
|
||||
}
|
||||
|
||||
exec_env->handle = os_self_thread();
|
||||
/* set thread handle and stack boundary */
|
||||
wasm_exec_env_set_thread_info(exec_env);
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
|
||||
|
@ -1410,37 +1411,39 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
|||
}
|
||||
|
||||
/* print return value */
|
||||
switch (type->types[type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
os_printf("0x%x:i32", argv1[0]);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
{
|
||||
union { uint64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = argv1[0];
|
||||
u.parts[1] = argv1[1];
|
||||
if (type->result_count > 0) {
|
||||
switch (type->types[type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
os_printf("0x%x:i32", argv1[0]);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
{
|
||||
union { uint64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = argv1[0];
|
||||
u.parts[1] = argv1[1];
|
||||
#ifdef PRIx64
|
||||
os_printf("0x%"PRIx64":i64", u.val);
|
||||
os_printf("0x%"PRIx64":i64", u.val);
|
||||
#else
|
||||
char buf[16];
|
||||
if (sizeof(long) == 4)
|
||||
snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
|
||||
os_printf(buf, u.val);
|
||||
char buf[16];
|
||||
if (sizeof(long) == 4)
|
||||
snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
|
||||
os_printf(buf, u.val);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F32:
|
||||
os_printf("%.7g:f32", *(float32*)argv1);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
{
|
||||
union { float64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = argv1[0];
|
||||
u.parts[1] = argv1[1];
|
||||
os_printf("%.7g:f64", u.val);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F32:
|
||||
os_printf("%.7g:f32", *(float32*)argv1);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
{
|
||||
union { float64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = argv1[0];
|
||||
u.parts[1] = argv1[1];
|
||||
os_printf("%.7g:f64", u.val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
os_printf("\n");
|
||||
|
@ -2148,7 +2151,9 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env,
|
|||
return false;
|
||||
}
|
||||
|
||||
exec_env->handle = os_self_thread();
|
||||
/* this function is called from native code, so exec_env->handle and
|
||||
exec_env->native_stack_boundary must have been set, we don't set
|
||||
it again */
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
|
||||
|
|
|
@ -595,14 +595,14 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
case WASM_OP_I32_TRUNC_S_F32:
|
||||
case WASM_OP_I32_TRUNC_U_F32:
|
||||
sign = (opcode == WASM_OP_I32_TRUNC_S_F32) ? true : false;
|
||||
if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign))
|
||||
if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, false))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_TRUNC_S_F64:
|
||||
case WASM_OP_I32_TRUNC_U_F64:
|
||||
sign = (opcode == WASM_OP_I32_TRUNC_S_F64) ? true : false;
|
||||
if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign))
|
||||
if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, false))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
@ -616,14 +616,14 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
case WASM_OP_I64_TRUNC_S_F32:
|
||||
case WASM_OP_I64_TRUNC_U_F32:
|
||||
sign = (opcode == WASM_OP_I64_TRUNC_S_F32) ? true : false;
|
||||
if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign))
|
||||
if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, false))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_TRUNC_S_F64:
|
||||
case WASM_OP_I64_TRUNC_U_F64:
|
||||
sign = (opcode == WASM_OP_I64_TRUNC_S_F64) ? true : false;
|
||||
if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign))
|
||||
if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, false))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
@ -685,6 +685,67 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_EXTEND8_S:
|
||||
if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 8))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_EXTEND16_S:
|
||||
if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 16))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_EXTEND8_S:
|
||||
if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 8))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_EXTEND16_S:
|
||||
if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 16))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_EXTEND32_S:
|
||||
if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 32))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_MISC_PREFIX:
|
||||
{
|
||||
if (frame_ip < frame_ip_end) {
|
||||
opcode = *frame_ip++;
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F32:
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F32:
|
||||
sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F32) ? true : false;
|
||||
if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, true))
|
||||
return false;
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F64:
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F64:
|
||||
sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F64) ? true : false;
|
||||
if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, true))
|
||||
return false;
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F32:
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F32:
|
||||
sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F32) ? true : false;
|
||||
if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, true))
|
||||
return false;
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F64:
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F64:
|
||||
sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F64) ? true : false;
|
||||
if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, true))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,156 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#define ADD_BASIC_BLOCK(block, name) do { \
|
||||
if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
name))) { \
|
||||
aot_set_last_error("llvm add basic block failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
\
|
||||
LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef operand, LLVMTypeRef dest_type,
|
||||
LLVMValueRef min_value, LLVMValueRef max_value,
|
||||
char *name, bool sign)
|
||||
{
|
||||
LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ;
|
||||
LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block;
|
||||
LLVMValueRef is_less, is_greater, res, phi;
|
||||
LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
|
||||
LLVMValueRef vmin, vmax;
|
||||
|
||||
if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO,
|
||||
operand, operand, "fcmp_is_nan"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ADD_BASIC_BLOCK(check_nan_succ, "check_nan_succ");
|
||||
ADD_BASIC_BLOCK(is_nan_block, "is_nan_block");
|
||||
ADD_BASIC_BLOCK(check_less_succ, "check_less_succ");
|
||||
ADD_BASIC_BLOCK(is_less_block, "is_less_block");
|
||||
ADD_BASIC_BLOCK(check_greater_succ, "check_greater_succ");
|
||||
ADD_BASIC_BLOCK(is_greater_block, "is_greater_block");
|
||||
ADD_BASIC_BLOCK(res_block, "res_block");
|
||||
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, res,
|
||||
is_nan_block, check_nan_succ)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate is_nan block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, is_nan_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate check_nan_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
|
||||
if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
|
||||
min_value, "fcmp_min_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_less,
|
||||
is_less_block, check_less_succ)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate is_less block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, is_less_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate check_less_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
|
||||
if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
|
||||
max_value, "fcmp_max_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_greater,
|
||||
is_greater_block, check_greater_succ)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate is_greater block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, is_greater_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate check_greater_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ);
|
||||
if (sign)
|
||||
res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
|
||||
else
|
||||
res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate res_block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block);
|
||||
/* Create result phi */
|
||||
if (!(phi = LLVMBuildPhi(comp_ctx->builder,
|
||||
dest_type,
|
||||
"trunc_sat_result_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add phi incoming values */
|
||||
if (dest_type == I32_TYPE) {
|
||||
if (sign) {
|
||||
vmin = I32_CONST(INT32_MIN);
|
||||
vmax = I32_CONST(INT32_MAX);
|
||||
}
|
||||
else {
|
||||
vmin = I32_CONST(0);
|
||||
vmax = I32_CONST(UINT32_MAX);
|
||||
}
|
||||
}
|
||||
else if (dest_type == I64_TYPE) {
|
||||
if (sign) {
|
||||
vmin = I64_CONST(INT64_MIN);
|
||||
vmax = I64_CONST(INT64_MAX);
|
||||
}
|
||||
else {
|
||||
vmin = I64_CONST(0);
|
||||
vmax = I64_CONST(UINT64_MAX);
|
||||
}
|
||||
}
|
||||
LLVMAddIncoming(phi, &zero, &is_nan_block, 1);
|
||||
LLVMAddIncoming(phi, &vmin, &is_less_block, 1);
|
||||
LLVMAddIncoming(phi, &vmax, &is_greater_block, 1);
|
||||
LLVMAddIncoming(phi, &res, &check_greater_succ, 1);
|
||||
|
||||
if (dest_type == I32_TYPE)
|
||||
PUSH_I32(phi);
|
||||
else if (dest_type == I64_TYPE)
|
||||
PUSH_I64(phi);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
|
@ -109,7 +259,7 @@ fail:
|
|||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -125,16 +275,22 @@ aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F32_CONST(4294967296.0f);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_sat_f32_s" :
|
||||
"i32_trunc_sat_f32_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -150,9 +306,15 @@ aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F64_CONST(4294967296.0);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_sat_f64_s" :
|
||||
"i32_trunc_sat_f64_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
@ -180,9 +342,83 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth)
|
||||
{
|
||||
LLVMValueRef value, res, cast_value = NULL;
|
||||
|
||||
POP_I64(value);
|
||||
|
||||
if (bitwidth == 8) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT8_TYPE, true, "i8_intcast_i64");
|
||||
}
|
||||
else if (bitwidth == 16) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT16_TYPE, true, "i16_intcast_i64");
|
||||
}
|
||||
else if (bitwidth == 32) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
I32_TYPE, true, "i32_intcast_i64");
|
||||
}
|
||||
|
||||
if (!cast_value) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, "i64_extend_i64_s");
|
||||
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I64(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth)
|
||||
{
|
||||
LLVMValueRef value, res, cast_value = NULL;
|
||||
|
||||
POP_I32(value);
|
||||
|
||||
if (bitwidth == 8) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT8_TYPE, true, "i8_intcast_i32");
|
||||
}
|
||||
else if (bitwidth == 16) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT16_TYPE, true, "i16_intcast_i32");
|
||||
}
|
||||
|
||||
if (!cast_value) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, "i32_extend_i32_s");
|
||||
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I32(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -198,16 +434,22 @@ aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F32_CONST(18446744073709551616.0f);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_sat_f32_s" :
|
||||
"i64_trunc_sat_f32_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -223,9 +465,16 @@ aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F64_CONST(18446744073709551616.0);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_sat_f64_s" :
|
||||
"i64_trunc_sat_f64_u", sign);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -17,23 +17,31 @@ aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
|||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
|
|
@ -17,7 +17,8 @@ static char *exce_block_names[] = {
|
|||
"exce_invalid_func_idx", /* EXCE_INVALID_FUNCTION_INDEX */
|
||||
"exce_undefined_element", /* EXCE_UNDEFINED_ELEMENT */
|
||||
"exce_uninit_element", /* EXCE_UNINITIALIZED_ELEMENT */
|
||||
"exce_call_unlinked" /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
|
||||
"exce_call_unlinked", /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
|
||||
"exce_native_stack_overflow" /* EXCE_NATIVE_STACK_OVERFLOW */
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
|
@ -255,6 +255,39 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMBasicBlockRef check_stack;
|
||||
LLVMValueRef cmp;
|
||||
|
||||
if (!(check_stack = LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_stack"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_stack, block_curr);
|
||||
|
||||
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT,
|
||||
func_ctx->last_alloca, func_ctx->native_stack_bound,
|
||||
"cmp"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_NATIVE_STACK_OVERFLOW,
|
||||
true, cmp, check_stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_stack);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 func_idx, uint8 **p_frame_ip)
|
||||
|
@ -347,6 +380,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
else {
|
||||
func = func_ctxes[func_idx - import_func_count]->func;
|
||||
|
||||
if (!check_stack_boundary(comp_ctx, func_ctx))
|
||||
goto fail;
|
||||
|
||||
/* Call the function */
|
||||
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values, (uint32)param_count + 1,
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define ADD_BASIC_BLOCK(block, name) do { \
|
||||
if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
name))) { \
|
||||
name))) { \
|
||||
aot_set_last_error("llvm add basic block failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "aot_llvm.h"
|
||||
#include "aot_compiler.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
|
||||
|
@ -451,6 +452,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
LLVMTypeRef int8_ptr_type, int32_ptr_type;
|
||||
LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr;
|
||||
LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr;
|
||||
LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
|
||||
char local_name[32];
|
||||
uint64 size;
|
||||
uint32 i, j = 0;
|
||||
|
@ -526,6 +528,21 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* Get native stack boundary address */
|
||||
if (!(stack_bound_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
|
||||
&stack_bound_offset, 1, "stack_bound_addr"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_ctx->native_stack_bound =
|
||||
LLVMBuildLoad(comp_ctx->builder,
|
||||
stack_bound_addr, "native_stack_bound"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < aot_func_type->param_count; i++, j++) {
|
||||
snprintf(local_name, sizeof(local_name), "l%d", i);
|
||||
func_ctx->locals[i] =
|
||||
|
@ -580,6 +597,24 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
}
|
||||
}
|
||||
|
||||
if (aot_func_type->param_count + func->local_count > 0) {
|
||||
func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
|
||||
+ func->local_count - 1];
|
||||
if (!(func_ctx->last_alloca =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->last_alloca,
|
||||
INT8_PTR_TYPE, "stack_ptr"))) {
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(func_ctx->last_alloca = LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE,
|
||||
"stack_ptr"))) {
|
||||
aot_set_last_error("llvm build alloca failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed.");
|
||||
goto fail;
|
||||
|
|
|
@ -102,6 +102,8 @@ typedef struct AOTFuncContext {
|
|||
LLVMValueRef aot_inst;
|
||||
LLVMValueRef table_base;
|
||||
LLVMValueRef argv_buf;
|
||||
LLVMValueRef native_stack_bound;
|
||||
LLVMValueRef last_alloca;
|
||||
|
||||
LLVMValueRef heap_base_offset;
|
||||
LLVMValueRef mem_base_addr;
|
||||
|
|
|
@ -606,18 +606,128 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
|||
PUSH_##src_op_type(method(val)); \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type, \
|
||||
min_cond, max_cond) do { \
|
||||
src_type value = POP_##src_op_type(); \
|
||||
if (isnan(value)) { \
|
||||
wasm_set_exception(module, "invalid conversion to integer"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
else if (value min_cond || value max_cond) { \
|
||||
wasm_set_exception(module, "integer overflow"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
PUSH_##dst_op_type(((dst_type)value)); \
|
||||
#define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type) \
|
||||
static dst_type \
|
||||
func_name(src_type src_value, src_type src_min, src_type src_max, \
|
||||
dst_type dst_min, dst_type dst_max, bool is_sign) \
|
||||
{ \
|
||||
dst_type dst_value = 0; \
|
||||
if (!isnan(src_value)) { \
|
||||
if (src_value <= src_min) \
|
||||
dst_value = dst_min; \
|
||||
else if (src_value >= src_max) \
|
||||
dst_value = dst_max; \
|
||||
else { \
|
||||
if (is_sign) \
|
||||
dst_value = (dst_type)(signed_type)src_value; \
|
||||
else \
|
||||
dst_value = (dst_type)src_value; \
|
||||
} \
|
||||
} \
|
||||
return dst_value; \
|
||||
}
|
||||
|
||||
TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32)
|
||||
TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64)
|
||||
TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32)
|
||||
TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64)
|
||||
|
||||
static bool
|
||||
trunc_f32_to_int(WASMModuleInstance *module,
|
||||
uint32 *frame_sp,
|
||||
float32 src_min, float32 src_max,
|
||||
bool saturating, bool is_i32, bool is_sign)
|
||||
{
|
||||
float32 src_value = POP_F32();
|
||||
uint64 dst_value_i64;
|
||||
uint32 dst_value_i32;
|
||||
|
||||
if (!saturating) {
|
||||
if (isnan(src_value)) {
|
||||
wasm_set_exception(module, "invalid conversion to integer");
|
||||
return true;
|
||||
}
|
||||
else if (src_value <= src_min || src_value >= src_max) {
|
||||
wasm_set_exception(module, "integer overflow");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_i32) {
|
||||
uint32 dst_min = is_sign ? INT32_MIN : 0;
|
||||
uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
|
||||
dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
PUSH_I32(dst_value_i32);
|
||||
}
|
||||
else {
|
||||
uint64 dst_min = is_sign ? INT64_MIN : 0;
|
||||
uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
|
||||
dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
PUSH_I64(dst_value_i64);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
trunc_f64_to_int(WASMModuleInstance *module,
|
||||
uint32 *frame_sp,
|
||||
float64 src_min, float64 src_max,
|
||||
bool saturating, bool is_i32, bool is_sign)
|
||||
{
|
||||
float64 src_value = POP_F64();
|
||||
uint64 dst_value_i64;
|
||||
uint32 dst_value_i32;
|
||||
|
||||
if (!saturating) {
|
||||
if (isnan(src_value)) {
|
||||
wasm_set_exception(module, "invalid conversion to integer");
|
||||
return true;
|
||||
}
|
||||
else if (src_value <= src_min || src_value >= src_max) {
|
||||
wasm_set_exception(module, "integer overflow");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_i32) {
|
||||
uint32 dst_min = is_sign ? INT32_MIN : 0;
|
||||
uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
|
||||
dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
PUSH_I32(dst_value_i32);
|
||||
}
|
||||
else {
|
||||
uint64 dst_min = is_sign ? INT64_MIN : 0;
|
||||
uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
|
||||
dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
PUSH_I64(dst_value_i64);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) do { \
|
||||
if (trunc_f32_to_int(module, frame_sp, min, max, \
|
||||
false, is_i32, is_sign)) \
|
||||
goto got_exception; \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) do { \
|
||||
if (trunc_f64_to_int(module, frame_sp, min, max, \
|
||||
false, is_i32, is_sign)) \
|
||||
goto got_exception; \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) do { \
|
||||
(void)trunc_f32_to_int(module, frame_sp, min, max, \
|
||||
true, is_i32, is_sign); \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) do { \
|
||||
(void)trunc_f64_to_int(module, frame_sp, min, max, \
|
||||
true, is_i32, is_sign); \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_CONVERT(dst_type, dst_op_type, \
|
||||
|
@ -2088,23 +2198,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
all int32/uint32/int64/uint64 values, e.g.:
|
||||
UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f,
|
||||
but not 4294967295.0f. */
|
||||
DEF_OP_TRUNC(int32, I32, float32, F32, <= -2147483904.0f,
|
||||
>= 2147483648.0f);
|
||||
DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_TRUNC_U_F32):
|
||||
DEF_OP_TRUNC(uint32, I32, float32, F32, <= -1.0f,
|
||||
>= 4294967296.0f);
|
||||
DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_TRUNC_S_F64):
|
||||
DEF_OP_TRUNC(int32, I32, float64, F64, <= -2147483649.0,
|
||||
>= 2147483648.0);
|
||||
DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true);
|
||||
/* frame_sp can't be moved in trunc function, we need to manually adjust
|
||||
it if src and dst op's cell num is different */
|
||||
frame_sp--;
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_TRUNC_U_F64):
|
||||
DEF_OP_TRUNC(uint32, I32, float64, F64, <= -1.0 ,
|
||||
>= 4294967296.0);
|
||||
DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false);
|
||||
frame_sp--;
|
||||
HANDLE_OP_END ();
|
||||
|
||||
/* conversions of i64 */
|
||||
|
@ -2117,23 +2227,25 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_S_F32):
|
||||
DEF_OP_TRUNC(int64, I64, float32, F32, <= -9223373136366403584.0f,
|
||||
>= 9223372036854775808.0f);
|
||||
DEF_OP_TRUNC_F32(-9223373136366403584.0f, 9223372036854775808.0f,
|
||||
false, true);
|
||||
frame_sp++;
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_U_F32):
|
||||
DEF_OP_TRUNC(uint64, I64, float32, F32, <= -1.0f,
|
||||
>= 18446744073709551616.0f);
|
||||
DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f,
|
||||
false, false);
|
||||
frame_sp++;
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_S_F64):
|
||||
DEF_OP_TRUNC(int64, I64, float64, F64, <= -9223372036854777856.0,
|
||||
>= 9223372036854775808.0);
|
||||
DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0,
|
||||
false, true);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_U_F64):
|
||||
DEF_OP_TRUNC(uint64, I64, float64, F64, <= -1.0,
|
||||
>= 18446744073709551616.0);
|
||||
DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0,
|
||||
false, false);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
/* conversions of f32 */
|
||||
|
@ -2185,6 +2297,75 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP (WASM_OP_F64_REINTERPRET_I64):
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_EXTEND8_S):
|
||||
DEF_OP_CONVERT(int32, I32, int8, I32);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_EXTEND16_S):
|
||||
DEF_OP_CONVERT(int32, I32, int16, I32);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_EXTEND8_S):
|
||||
DEF_OP_CONVERT(int64, I64, int8, I64);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_EXTEND16_S):
|
||||
DEF_OP_CONVERT(int64, I64, int16, I64);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_EXTEND32_S):
|
||||
DEF_OP_CONVERT(int64, I64, int32, I64);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_MISC_PREFIX):
|
||||
{
|
||||
opcode = *frame_ip++;
|
||||
switch (opcode)
|
||||
{
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f,
|
||||
true, true);
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f,
|
||||
true, false);
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0,
|
||||
true, true);
|
||||
frame_sp--;
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0,
|
||||
true, false);
|
||||
frame_sp--;
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, 9223372036854775808.0f,
|
||||
false, true);
|
||||
frame_sp++;
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f,
|
||||
false, false);
|
||||
frame_sp++;
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, 9223372036854775808.0,
|
||||
false, true);
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-1.0f, 18446744073709551616.0,
|
||||
false, false);
|
||||
break;
|
||||
default:
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
break;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_IMPDEP):
|
||||
frame = prev_frame;
|
||||
frame_ip = frame->ip;
|
||||
|
@ -2359,7 +2540,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
|||
return;
|
||||
}
|
||||
|
||||
/* TODO: check stack overflow. */
|
||||
if ((uint8*)&prev_frame < exec_env->native_stack_boundary) {
|
||||
wasm_set_exception((WASMModuleInstance*)exec_env->module_inst,
|
||||
"WASM interp failed: native stack overflow.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame)))
|
||||
return;
|
||||
|
|
|
@ -536,18 +536,131 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
|||
frame_ip += 4; \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type, \
|
||||
min_cond, max_cond) do { \
|
||||
src_type value = GET_OPERAND(src_type, 0); \
|
||||
if (isnan(value)) { \
|
||||
wasm_set_exception(module, "invalid conversion to integer"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
else if (value min_cond || value max_cond) { \
|
||||
wasm_set_exception(module, "integer overflow"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
SET_OPERAND(dst_type, 2, value); \
|
||||
#define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type) \
|
||||
static dst_type \
|
||||
func_name(src_type src_value, src_type src_min, src_type src_max, \
|
||||
dst_type dst_min, dst_type dst_max, bool is_sign) \
|
||||
{ \
|
||||
dst_type dst_value = 0; \
|
||||
if (!isnan(src_value)) { \
|
||||
if (src_value <= src_min) \
|
||||
dst_value = dst_min; \
|
||||
else if (src_value >= src_max) \
|
||||
dst_value = dst_max; \
|
||||
else { \
|
||||
if (is_sign) \
|
||||
dst_value = (dst_type)(signed_type)src_value; \
|
||||
else \
|
||||
dst_value = (dst_type)src_value; \
|
||||
} \
|
||||
} \
|
||||
return dst_value; \
|
||||
}
|
||||
|
||||
TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32)
|
||||
TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64)
|
||||
TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32)
|
||||
TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64)
|
||||
|
||||
static bool
|
||||
trunc_f32_to_int(WASMModuleInstance *module,
|
||||
uint8 *frame_ip, uint32 *frame_lp,
|
||||
float32 src_min, float32 src_max,
|
||||
bool saturating, bool is_i32, bool is_sign)
|
||||
{
|
||||
float32 src_value = GET_OPERAND(float32, 0);
|
||||
uint64 dst_value_i64;
|
||||
uint32 dst_value_i32;
|
||||
|
||||
if (!saturating) {
|
||||
if (isnan(src_value)) {
|
||||
wasm_set_exception(module, "invalid conversion to integer");
|
||||
return true;
|
||||
}
|
||||
else if (src_value <= src_min || src_value >= src_max) {
|
||||
wasm_set_exception(module, "integer overflow");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_i32) {
|
||||
uint32 dst_min = is_sign ? INT32_MIN : 0;
|
||||
uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
|
||||
dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
SET_OPERAND(uint32, 2, dst_value_i32);
|
||||
}
|
||||
else {
|
||||
uint64 dst_min = is_sign ? INT64_MIN : 0;
|
||||
uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
|
||||
dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
SET_OPERAND(uint64, 2, dst_value_i64);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
trunc_f64_to_int(WASMModuleInstance *module,
|
||||
uint8 *frame_ip, uint32 *frame_lp,
|
||||
float64 src_min, float64 src_max,
|
||||
bool saturating, bool is_i32, bool is_sign)
|
||||
{
|
||||
float64 src_value = GET_OPERAND(float64, 0);
|
||||
uint64 dst_value_i64;
|
||||
uint32 dst_value_i32;
|
||||
|
||||
if (!saturating) {
|
||||
if (isnan(src_value)) {
|
||||
wasm_set_exception(module, "invalid conversion to integer");
|
||||
return true;
|
||||
}
|
||||
else if (src_value <= src_min || src_value >= src_max) {
|
||||
wasm_set_exception(module, "integer overflow");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_i32) {
|
||||
uint32 dst_min = is_sign ? INT32_MIN : 0;
|
||||
uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
|
||||
dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
SET_OPERAND(uint32, 2, dst_value_i32);
|
||||
}
|
||||
else {
|
||||
uint64 dst_min = is_sign ? INT64_MIN : 0;
|
||||
uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
|
||||
dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max,
|
||||
dst_min, dst_max, is_sign);
|
||||
SET_OPERAND(uint64, 2, dst_value_i64);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) do { \
|
||||
if (trunc_f32_to_int(module, frame_ip, frame_lp, min, max, \
|
||||
false, is_i32, is_sign)) \
|
||||
goto got_exception; \
|
||||
frame_ip += 4; \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) do { \
|
||||
if (trunc_f64_to_int(module, frame_ip, frame_lp, min, max, \
|
||||
false, is_i32, is_sign)) \
|
||||
goto got_exception; \
|
||||
frame_ip += 4; \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) do { \
|
||||
(void)trunc_f32_to_int(module, frame_ip, frame_lp, min, max, \
|
||||
true, is_i32, is_sign); \
|
||||
frame_ip += 4; \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) do { \
|
||||
(void)trunc_f64_to_int(module, frame_ip, frame_lp, min, max, \
|
||||
true, is_i32, is_sign); \
|
||||
frame_ip += 4; \
|
||||
} while (0)
|
||||
|
||||
|
@ -799,7 +912,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
int32 didx, val;
|
||||
uint8 *maddr = NULL;
|
||||
uint32 local_idx, local_offset, global_idx;
|
||||
uint8 local_type, *global_addr;
|
||||
uint8 opcode, local_type, *global_addr;
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||
#define HANDLE_OPCODE(op) &&HANDLE_##op
|
||||
|
@ -1981,23 +2094,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
all int32/uint32/int64/uint64 values, e.g.:
|
||||
UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f,
|
||||
but not 4294967295.0f. */
|
||||
DEF_OP_TRUNC(int32, I32, float32, F32, <= -2147483904.0f,
|
||||
>= 2147483648.0f);
|
||||
DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_TRUNC_U_F32):
|
||||
DEF_OP_TRUNC(uint32, I32, float32, F32, <= -1.0f,
|
||||
>= 4294967296.0f);
|
||||
DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_TRUNC_S_F64):
|
||||
DEF_OP_TRUNC(int32, I32, float64, F64, <= -2147483649.0,
|
||||
>= 2147483648.0);
|
||||
DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_TRUNC_U_F64):
|
||||
DEF_OP_TRUNC(uint32, I32, float64, F64, <= -1.0 ,
|
||||
>= 4294967296.0);
|
||||
DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
/* conversions of i64 */
|
||||
|
@ -2010,23 +2119,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_S_F32):
|
||||
DEF_OP_TRUNC(int64, I64, float32, F32, <= -9223373136366403584.0f,
|
||||
>= 9223372036854775808.0f);
|
||||
DEF_OP_TRUNC_F32(-9223373136366403584.0f,
|
||||
9223372036854775808.0f, false, true);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_U_F32):
|
||||
DEF_OP_TRUNC(uint64, I64, float32, F32, <= -1.0f,
|
||||
>= 18446744073709551616.0f);
|
||||
DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f,
|
||||
false, false);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_S_F64):
|
||||
DEF_OP_TRUNC(int64, I64, float64, F64, <= -9223372036854777856.0,
|
||||
>= 9223372036854775808.0);
|
||||
DEF_OP_TRUNC_F64(-9223372036854777856.0,
|
||||
9223372036854775808.0, false, true);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_TRUNC_U_F64):
|
||||
DEF_OP_TRUNC(uint64, I64, float64, F64, <= -1.0,
|
||||
>= 18446744073709551616.0);
|
||||
DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0,
|
||||
false, false);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
/* conversions of f32 */
|
||||
|
@ -2130,6 +2239,71 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_EXTEND8_S):
|
||||
DEF_OP_CONVERT(int32, I32, int8, I32);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_EXTEND16_S):
|
||||
DEF_OP_CONVERT(int32, I32, int16, I32);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_EXTEND8_S):
|
||||
DEF_OP_CONVERT(int64, I64, int8, I64);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_EXTEND16_S):
|
||||
DEF_OP_CONVERT(int64, I64, int16, I64);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_EXTEND32_S):
|
||||
DEF_OP_CONVERT(int64, I64, int32, I64);
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_MISC_PREFIX):
|
||||
{
|
||||
GET_OPCODE();
|
||||
switch (opcode)
|
||||
{
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f,
|
||||
true, true);
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f,
|
||||
true, false);
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0,
|
||||
true, true);
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0,
|
||||
true, false);
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, 9223372036854775808.0f,
|
||||
false, true);
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F32:
|
||||
DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f,
|
||||
false, false);
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, 9223372036854775808.0,
|
||||
false, true);
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F64:
|
||||
DEF_OP_TRUNC_SAT_F64(-1.0, 18446744073709551616.0,
|
||||
false, false);
|
||||
break;
|
||||
default:
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
break;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_IMPDEP):
|
||||
frame = prev_frame;
|
||||
frame_ip = frame->ip;
|
||||
|
@ -2334,7 +2508,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
|||
return;
|
||||
}
|
||||
|
||||
/* TODO: check stack overflow. */
|
||||
if ((uint8*)&prev_frame < exec_env->native_stack_boundary) {
|
||||
wasm_set_exception((WASMModuleInstance*)exec_env->module_inst,
|
||||
"WASM interp failed: native stack overflow.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame)))
|
||||
return;
|
||||
|
|
|
@ -321,7 +321,7 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
|
|||
|
||||
static bool
|
||||
load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
|
||||
InitializerExpression *init_expr,
|
||||
InitializerExpression *init_expr, uint8 type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||
|
@ -335,14 +335,20 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
|
|||
switch (flag) {
|
||||
/* i32.const */
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
if (type != VALUE_TYPE_I32)
|
||||
goto fail;
|
||||
read_leb_int32(p, p_end, init_expr->u.i32);
|
||||
break;
|
||||
/* i64.const */
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
if (type != VALUE_TYPE_I64)
|
||||
goto fail;
|
||||
read_leb_int64(p, p_end, init_expr->u.i64);
|
||||
break;
|
||||
/* f32.const */
|
||||
case INIT_EXPR_TYPE_F32_CONST:
|
||||
if (type != VALUE_TYPE_F32)
|
||||
goto fail;
|
||||
CHECK_BUF(p, p_end, 4);
|
||||
p_float = (uint8*)&init_expr->u.f32;
|
||||
for (i = 0; i < sizeof(float32); i++)
|
||||
|
@ -350,6 +356,8 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
|
|||
break;
|
||||
/* f64.const */
|
||||
case INIT_EXPR_TYPE_F64_CONST:
|
||||
if (type != VALUE_TYPE_F64)
|
||||
goto fail;
|
||||
CHECK_BUF(p, p_end, 8);
|
||||
p_float = (uint8*)&init_expr->u.f64;
|
||||
for (i = 0; i < sizeof(float64); i++)
|
||||
|
@ -360,21 +368,20 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
|
|||
read_leb_uint32(p, p_end, init_expr->u.global_index);
|
||||
break;
|
||||
default:
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"WASM module load failed: type mismatch");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
end_byte = read_uint8(p);
|
||||
if (end_byte != 0x0b) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"WASM module load failed: "
|
||||
"unexpected end of section or function");
|
||||
return false;
|
||||
}
|
||||
if (end_byte != 0x0b)
|
||||
goto fail;
|
||||
*p_buf = p;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"WASM module load failed: type mismatch or "
|
||||
"constant expression required.");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1104,7 +1111,6 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
WASMMemory *memory;
|
||||
|
||||
read_leb_uint32(p, p_end, memory_count);
|
||||
bh_assert(memory_count == 1);
|
||||
|
||||
if (memory_count) {
|
||||
if (memory_count > 1) {
|
||||
|
@ -1180,7 +1186,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
global->is_mutable = mutable ? true : false;
|
||||
|
||||
/* initialize expression */
|
||||
if (!load_init_expr(&p, p_end, &(global->init_expr), error_buf, error_buf_size))
|
||||
if (!load_init_expr(&p, p_end, &(global->init_expr),
|
||||
global->type, error_buf, error_buf_size))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1327,7 +1334,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
|
|||
|
||||
/* initialize expression */
|
||||
if (!load_init_expr(&p, p_end, &(table_segment->base_offset),
|
||||
error_buf, error_buf_size))
|
||||
VALUE_TYPE_I32, error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
read_leb_uint32(p, p_end, function_count);
|
||||
|
@ -1387,7 +1394,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
|||
for (i = 0; i < data_seg_count; i++) {
|
||||
read_leb_uint32(p, p_end, mem_index);
|
||||
|
||||
if (!load_init_expr(&p, p_end, &init_expr, error_buf, error_buf_size))
|
||||
if (!load_init_expr(&p, p_end, &init_expr, VALUE_TYPE_I32,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
read_leb_uint32(p, p_end, data_seg_len);
|
||||
|
@ -1455,20 +1463,33 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
WASMType *type;
|
||||
uint32 start_function;
|
||||
|
||||
read_leb_uint32(p, p_end, start_function);
|
||||
|
||||
if (start_function) {
|
||||
if (start_function >= module->function_count + module->import_function_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Load start section failed: "
|
||||
"unknown function.");
|
||||
return false;
|
||||
}
|
||||
module->start_function = start_function;
|
||||
if (start_function >= module->function_count
|
||||
+ module->import_function_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Load start section failed: "
|
||||
"unknown function.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (start_function < module->import_function_count)
|
||||
type = module->import_functions[start_function].u.function.func_type;
|
||||
else
|
||||
type = module->functions
|
||||
[start_function - module->import_function_count]->func_type;
|
||||
if (type->param_count != 0 || type->result_count != 0) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Load start section failed: "
|
||||
"invalid start function.");
|
||||
return false;
|
||||
}
|
||||
|
||||
module->start_function = start_function;
|
||||
|
||||
if (p != p_end) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Load start section failed: section size mismatch");
|
||||
|
@ -2345,6 +2366,16 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
|
|||
case WASM_OP_I64_REINTERPRET_F64:
|
||||
case WASM_OP_F32_REINTERPRET_I32:
|
||||
case WASM_OP_F64_REINTERPRET_I64:
|
||||
case WASM_OP_I32_EXTEND8_S:
|
||||
case WASM_OP_I32_EXTEND16_S:
|
||||
case WASM_OP_I64_EXTEND8_S:
|
||||
case WASM_OP_I64_EXTEND16_S:
|
||||
case WASM_OP_I64_EXTEND32_S:
|
||||
break;
|
||||
case WASM_OP_MISC_PREFIX:
|
||||
/* skip extend op */
|
||||
if (p < code_end_addr)
|
||||
p++;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -4714,6 +4745,58 @@ handle_next_reachable_block:
|
|||
PUSH_F64();
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_EXTEND8_S:
|
||||
case WASM_OP_I32_EXTEND16_S:
|
||||
POP_I32();
|
||||
PUSH_I32();
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_EXTEND8_S:
|
||||
case WASM_OP_I64_EXTEND16_S:
|
||||
case WASM_OP_I64_EXTEND32_S:
|
||||
POP_I64();
|
||||
PUSH_I64();
|
||||
break;
|
||||
|
||||
case WASM_OP_MISC_PREFIX:
|
||||
{
|
||||
opcode = read_uint8(p);
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
emit_byte(loader_ctx, opcode);
|
||||
#endif
|
||||
switch (opcode)
|
||||
{
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F32:
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F32:
|
||||
POP_F32();
|
||||
PUSH_I32();
|
||||
break;
|
||||
case WASM_OP_I32_TRUNC_SAT_S_F64:
|
||||
case WASM_OP_I32_TRUNC_SAT_U_F64:
|
||||
POP_F64();
|
||||
PUSH_I32();
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F32:
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F32:
|
||||
POP_F32();
|
||||
PUSH_I64();
|
||||
break;
|
||||
case WASM_OP_I64_TRUNC_SAT_S_F64:
|
||||
case WASM_OP_I64_TRUNC_SAT_U_F64:
|
||||
POP_F64();
|
||||
PUSH_I64();
|
||||
break;
|
||||
default:
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size,
|
||||
"WASM module load failed: "
|
||||
"invalid opcode 0xfc %02x.", opcode);
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size,
|
||||
|
|
|
@ -237,22 +237,42 @@ typedef enum WASMOpcode {
|
|||
WASM_OP_F32_REINTERPRET_I32 = 0xbe, /* f32.reinterpret/i32 */
|
||||
WASM_OP_F64_REINTERPRET_I64 = 0xbf, /* f64.reinterpret/i64 */
|
||||
|
||||
WASM_OP_I32_EXTEND8_S = 0xc0, /* i32.extend8_s */
|
||||
WASM_OP_I32_EXTEND16_S = 0xc1, /* i32.extend16_s */
|
||||
WASM_OP_I64_EXTEND8_S = 0xc2, /* i64.extend8_s */
|
||||
WASM_OP_I64_EXTEND16_S = 0xc3, /* i64.extend16_s */
|
||||
WASM_OP_I64_EXTEND32_S = 0xc4, /* i64.extend32_s */
|
||||
|
||||
/* drop/select specified types*/
|
||||
WASM_OP_DROP_64 = 0xc0,
|
||||
WASM_OP_SELECT_64 = 0xc1,
|
||||
WASM_OP_DROP_64 = 0xc5,
|
||||
WASM_OP_SELECT_64 = 0xc6,
|
||||
|
||||
/* extend op code */
|
||||
EXT_OP_GET_LOCAL_FAST = 0xc2,
|
||||
EXT_OP_SET_LOCAL_FAST_I64 = 0xc3,
|
||||
EXT_OP_SET_LOCAL_FAST = 0xc4,
|
||||
EXT_OP_TEE_LOCAL_FAST = 0xc5,
|
||||
EXT_OP_TEE_LOCAL_FAST_I64 = 0xc6,
|
||||
EXT_OP_COPY_STACK_TOP = 0xc7,
|
||||
EXT_OP_COPY_STACK_TOP_I64 = 0xc8,
|
||||
EXT_OP_GET_LOCAL_FAST = 0xc7,
|
||||
EXT_OP_SET_LOCAL_FAST_I64 = 0xc8,
|
||||
EXT_OP_SET_LOCAL_FAST = 0xc9,
|
||||
EXT_OP_TEE_LOCAL_FAST = 0xca,
|
||||
EXT_OP_TEE_LOCAL_FAST_I64 = 0xcb,
|
||||
EXT_OP_COPY_STACK_TOP = 0xcc,
|
||||
EXT_OP_COPY_STACK_TOP_I64 = 0xcd,
|
||||
|
||||
WASM_OP_IMPDEP = 0xc9
|
||||
WASM_OP_IMPDEP = 0xce,
|
||||
|
||||
/* Post-MVP extend op prefix */
|
||||
WASM_OP_MISC_PREFIX = 0xfc,
|
||||
} WASMOpcode;
|
||||
|
||||
typedef enum WASMEXTOpcode {
|
||||
WASM_OP_I32_TRUNC_SAT_S_F32 = 0x00,
|
||||
WASM_OP_I32_TRUNC_SAT_U_F32 = 0x01,
|
||||
WASM_OP_I32_TRUNC_SAT_S_F64 = 0x02,
|
||||
WASM_OP_I32_TRUNC_SAT_U_F64 = 0x03,
|
||||
WASM_OP_I64_TRUNC_SAT_S_F32 = 0x04,
|
||||
WASM_OP_I64_TRUNC_SAT_U_F32 = 0x05,
|
||||
WASM_OP_I64_TRUNC_SAT_S_F64 = 0x06,
|
||||
WASM_OP_I64_TRUNC_SAT_U_F64 = 0x07,
|
||||
} WASMEXTOpcode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -456,16 +476,24 @@ static type _name[WASM_INSTRUCTION_NUM] = { \
|
|||
HANDLE_OPCODE (WASM_OP_I64_REINTERPRET_F64), /* 0xbd */ \
|
||||
HANDLE_OPCODE (WASM_OP_F32_REINTERPRET_I32), /* 0xbe */ \
|
||||
HANDLE_OPCODE (WASM_OP_F64_REINTERPRET_I64), /* 0xbf */ \
|
||||
HANDLE_OPCODE (WASM_OP_DROP_64), /* 0xc0 */ \
|
||||
HANDLE_OPCODE (WASM_OP_SELECT_64), /* 0xc1 */ \
|
||||
HANDLE_OPCODE (EXT_OP_GET_LOCAL_FAST), /* 0xc2 */ \
|
||||
HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST_I64), /* 0xc3 */ \
|
||||
HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST), /* 0xc4 */ \
|
||||
HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST), /* 0xc5 */ \
|
||||
HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST_I64), /* 0xc6 */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP), /* 0xc7 */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xc8 */ \
|
||||
HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xc9 */ \
|
||||
}
|
||||
|
||||
HANDLE_OPCODE (WASM_OP_I32_EXTEND8_S), /* 0xc0 */ \
|
||||
HANDLE_OPCODE (WASM_OP_I32_EXTEND16_S), /* 0xc1 */ \
|
||||
HANDLE_OPCODE (WASM_OP_I64_EXTEND8_S), /* 0xc2 */ \
|
||||
HANDLE_OPCODE (WASM_OP_I64_EXTEND16_S), /* 0xc3 */ \
|
||||
HANDLE_OPCODE (WASM_OP_I64_EXTEND32_S), /* 0xc4 */ \
|
||||
HANDLE_OPCODE (WASM_OP_DROP_64), /* 0xc5 */ \
|
||||
HANDLE_OPCODE (WASM_OP_SELECT_64), /* 0xc6 */ \
|
||||
HANDLE_OPCODE (EXT_OP_GET_LOCAL_FAST), /* 0xc7 */ \
|
||||
HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST_I64), /* 0xc8 */ \
|
||||
HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST), /* 0xc9 */ \
|
||||
HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST), /* 0xca */ \
|
||||
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 */ \
|
||||
}; \
|
||||
do { \
|
||||
_name[WASM_OP_MISC_PREFIX] = \
|
||||
HANDLE_OPCODE (WASM_OP_MISC_PREFIX); /* 0xfc */ \
|
||||
} while (0)
|
||||
#endif /* end of _WASM_OPCODE_H */
|
||||
|
|
|
@ -419,47 +419,24 @@ globals_instantiate(const WASMModule *module,
|
|||
return globals;
|
||||
}
|
||||
|
||||
static void
|
||||
static bool
|
||||
globals_instantiate_fix(WASMGlobalInstance *globals,
|
||||
const WASMModule *module,
|
||||
WASMModuleInstance *module_inst)
|
||||
WASMModuleInstance *module_inst,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMGlobalInstance *global = globals;
|
||||
WASMImport *import = module->import_globals;
|
||||
uint32 i;
|
||||
|
||||
/* Fix globals from import section */
|
||||
for (i = 0; i < module->import_global_count; i++, import++, global++) {
|
||||
if (!strcmp(import->u.names.module_name, "env")) {
|
||||
if (!strcmp(import->u.names.field_name, "memoryBase")
|
||||
|| !strcmp(import->u.names.field_name, "__memory_base")) {
|
||||
global->initial_value.addr = 0;
|
||||
}
|
||||
else if (!strcmp(import->u.names.field_name, "tableBase")
|
||||
|| !strcmp(import->u.names.field_name, "__table_base")) {
|
||||
global->initial_value.addr = 0;
|
||||
}
|
||||
else if (!strcmp(import->u.names.field_name, "DYNAMICTOP_PTR")) {
|
||||
global->initial_value.i32 = (int32)
|
||||
(module_inst->default_memory->num_bytes_per_page
|
||||
* module_inst->default_memory->cur_page_count);
|
||||
module_inst->DYNAMICTOP_PTR_offset = global->data_offset;
|
||||
}
|
||||
else if (!strcmp(import->u.names.field_name, "STACKTOP")) {
|
||||
global->initial_value.i32 = 0;
|
||||
}
|
||||
else if (!strcmp(import->u.names.field_name, "STACK_MAX")) {
|
||||
/* Unused in emcc wasm bin actually. */
|
||||
global->initial_value.i32 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
InitializerExpression *init_expr = &module->globals[i].init_expr;
|
||||
|
||||
if (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
bh_assert(init_expr->u.global_index < module->import_global_count);
|
||||
if (init_expr->u.global_index >= module->import_global_count + i) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Instantiate global failed: unknown global.");
|
||||
return false;
|
||||
}
|
||||
global->initial_value = globals[init_expr->u.global_index].initial_value;
|
||||
}
|
||||
else {
|
||||
|
@ -468,6 +445,7 @@ globals_instantiate_fix(WASMGlobalInstance *globals,
|
|||
}
|
||||
global++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -658,7 +636,11 @@ wasm_instantiate(WASMModule *module,
|
|||
memory_data = module_inst->default_memory->memory_data;
|
||||
|
||||
/* fix import memoryBase */
|
||||
globals_instantiate_fix(globals, module, module_inst);
|
||||
if (!globals_instantiate_fix(globals, module, module_inst,
|
||||
error_buf, error_buf_size)) {
|
||||
wasm_deinstantiate(module_inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the global data */
|
||||
global_data = memory->global_data;
|
||||
|
@ -710,7 +692,7 @@ wasm_instantiate(WASMModule *module,
|
|||
&& (base_offset >= memory_size
|
||||
|| base_offset + length > memory_size)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Instantiate module failed: data segment out of range.");
|
||||
"Instantiate module failed: data segment does not fit.");
|
||||
wasm_deinstantiate(module_inst);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -784,9 +766,10 @@ wasm_instantiate(WASMModule *module,
|
|||
#endif
|
||||
|
||||
if (module->start_function != (uint32)-1) {
|
||||
bh_assert(module->start_function >= module->import_function_count);
|
||||
module_inst->start_function =
|
||||
&module_inst->functions[module->start_function];
|
||||
/* TODO: fix start function can be import function issue */
|
||||
if (module->start_function >= module->import_function_count)
|
||||
module_inst->start_function =
|
||||
&module_inst->functions[module->start_function];
|
||||
}
|
||||
|
||||
module_inst->module = module;
|
||||
|
@ -881,6 +864,9 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* set thread handle and stack boundary */
|
||||
wasm_exec_env_set_thread_info(exec_env);
|
||||
|
||||
ret = wasm_call_function(exec_env, func, argc, argv);
|
||||
wasm_exec_env_destroy(exec_env);
|
||||
return ret;
|
||||
|
@ -998,12 +984,13 @@ wasm_addr_app_to_native(WASMModuleInstance *module_inst,
|
|||
int32 app_offset)
|
||||
{
|
||||
WASMMemoryInstance *memory = module_inst->default_memory;
|
||||
uint8 *addr = memory->memory_data + app_offset;
|
||||
int32 memory_data_size =
|
||||
(int32)(memory->num_bytes_per_page * memory->cur_page_count);
|
||||
|
||||
if (memory->heap_base_offset < app_offset
|
||||
&& app_offset < memory_data_size)
|
||||
return memory->memory_data + app_offset;
|
||||
if (memory->heap_data < addr
|
||||
&& addr < memory->memory_data + memory_data_size)
|
||||
return addr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,6 @@ typedef struct WASMModuleInstance {
|
|||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
|
||||
uint32 DYNAMICTOP_PTR_offset;
|
||||
uint32 temp_ret;
|
||||
uint32 llvm_stack;
|
||||
|
||||
|
|
|
@ -993,12 +993,45 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env,
|
|||
wasm_runtime_set_exception(module_inst, buf);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST != 0
|
||||
static void
|
||||
print_wrapper(wasm_exec_env_t exec_env)
|
||||
{
|
||||
os_printf("in specttest.print()\n");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
|
||||
{
|
||||
os_printf("%d\n", i32);
|
||||
os_printf("in specttest.print_i32(%d)\n", i32);
|
||||
}
|
||||
|
||||
static void
|
||||
print_i32_f32_wrapper(wasm_exec_env_t exec_env, int32 i32, float f32)
|
||||
{
|
||||
os_printf("in specttest.print_i32_f32(%d, %f)\n", i32, f32);
|
||||
}
|
||||
|
||||
static void
|
||||
print_f64_f64_wrapper(wasm_exec_env_t exec_env, double f64_1, double f64_2)
|
||||
{
|
||||
os_printf("in specttest.print_f64_f64(%f, %f)\n", f64_1, f64_2);
|
||||
}
|
||||
|
||||
static void
|
||||
print_f32_wrapper(wasm_exec_env_t exec_env, float f32)
|
||||
{
|
||||
os_printf("in specttest.print_f32(%f)\n", f32);
|
||||
}
|
||||
|
||||
static void
|
||||
print_f64_wrapper(wasm_exec_env_t exec_env, double f64)
|
||||
{
|
||||
os_printf("in specttest.print_f64(%f)\n", f64);
|
||||
}
|
||||
#endif /* WASM_ENABLE_SPEC_TEST */
|
||||
|
||||
#define REG_NATIVE_FUNC(func_name, signature) \
|
||||
{ #func_name, func_name##_wrapper, signature, NULL }
|
||||
|
||||
|
@ -1060,9 +1093,16 @@ static NativeSymbol native_symbols_libc_builtin[] = {
|
|||
REG_NATIVE_FUNC(__cxa_throw, "(**i)")
|
||||
};
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST != 0
|
||||
static NativeSymbol native_symbols_spectest[] = {
|
||||
REG_NATIVE_FUNC(print_i32, "(i)")
|
||||
REG_NATIVE_FUNC(print, "()"),
|
||||
REG_NATIVE_FUNC(print_i32, "(i)"),
|
||||
REG_NATIVE_FUNC(print_i32_f32, "(if)"),
|
||||
REG_NATIVE_FUNC(print_f64_f64, "(fF)"),
|
||||
REG_NATIVE_FUNC(print_f32, "(f)"),
|
||||
REG_NATIVE_FUNC(print_f64, "(F)")
|
||||
};
|
||||
#endif
|
||||
|
||||
uint32
|
||||
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
|
||||
|
@ -1071,12 +1111,14 @@ get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
|
|||
return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST != 0
|
||||
uint32
|
||||
get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
|
||||
{
|
||||
*p_libc_builtin_apis = native_symbols_spectest;
|
||||
return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************
|
||||
* Global Variables *
|
||||
|
@ -1090,8 +1132,8 @@ typedef struct WASMNativeGlobalDef {
|
|||
|
||||
static WASMNativeGlobalDef native_global_defs[] = {
|
||||
{ "spectest", "global_i32", .global_data.i32 = 666 },
|
||||
{ "spectest", "global_f32", .global_data.f32 = 0 },
|
||||
{ "spectest", "global_f64", .global_data.f64 = 0 },
|
||||
{ "spectest", "global_f32", .global_data.f32 = 666.6 },
|
||||
{ "spectest", "global_f64", .global_data.f64 = 666.6 },
|
||||
{ "test", "global-i32", .global_data.i32 = 0 },
|
||||
{ "test", "global-f32", .global_data.f32 = 0 },
|
||||
{ "env", "STACKTOP", .global_data.u32 = 0 },
|
||||
|
|
|
@ -13,6 +13,22 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifndef _Static_assert
|
||||
#define _Static_assert static_assert
|
||||
#endif /* _Static_assert */
|
||||
|
||||
#ifndef _Alignof
|
||||
#define _Alignof alignof
|
||||
#endif /* _Alignof */
|
||||
|
||||
#ifndef _Noreturn
|
||||
#define _Noreturn [[ noreturn ]]
|
||||
#endif /* _Noreturn */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout");
|
||||
_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout");
|
||||
_Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout");
|
||||
|
@ -24,10 +40,6 @@ _Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout");
|
|||
_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout");
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint8_t __wasi_advice_t;
|
||||
#define __WASI_ADVICE_NORMAL (0)
|
||||
#define __WASI_ADVICE_SEQUENTIAL (1)
|
||||
|
@ -874,3 +886,4 @@ __wasi_errno_t wasmtime_ssp_sched_yield(void)
|
|||
#undef WASMTIME_SSP_SYSCALL_NAME
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -339,3 +339,9 @@ os_cond_signal(korp_cond *cond)
|
|||
return BHT_OK;
|
||||
}
|
||||
|
||||
uint8 *os_thread_get_stack_boundary()
|
||||
{
|
||||
/* TODO: get alios stack boundary */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ extern "C" {
|
|||
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
|
||||
|
||||
/* Stack size of applet threads's native part. */
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
|
||||
/* Default thread priority */
|
||||
#define BH_THREAD_DEFAULT_PRIORITY 0
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include "platform_api_vmcore.h"
|
||||
#include "platform_api_extension.h"
|
||||
|
||||
|
@ -218,3 +221,20 @@ int os_thread_join(korp_tid thread, void **value_ptr)
|
|||
return pthread_join(thread, value_ptr);
|
||||
}
|
||||
|
||||
uint8 *os_thread_get_stack_boundary()
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
void *addr = NULL;
|
||||
size_t size;
|
||||
|
||||
if (pthread_getattr_np(pthread_self(), &attr) == 0) {
|
||||
pthread_attr_getstack(&attr, &addr, &size);
|
||||
pthread_attr_destroy (&attr);
|
||||
}
|
||||
|
||||
if (addr)
|
||||
return (uint8*)addr + _STACK_SIZE_ADJUSTMENT;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ extern "C" {
|
|||
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
|
||||
|
||||
/* Stack size of applet threads's native part. */
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
|
||||
/* Default thread priority */
|
||||
#define BH_THREAD_DEFAULT_PRIORITY 0
|
||||
|
|
|
@ -65,6 +65,13 @@ uint64 os_time_get_boot_microsecond(void);
|
|||
*/
|
||||
korp_tid os_self_thread(void);
|
||||
|
||||
/**
|
||||
* Get current thread's stack boundary address, used for runtime
|
||||
* to check the native stack overflow. Return NULL if it is not
|
||||
* easy to implement, but may have potential issue.
|
||||
*/
|
||||
uint8 *os_thread_get_stack_boundary(void);
|
||||
|
||||
/**
|
||||
************** mutext APIs ***********
|
||||
* vmcore: Not required until pthread is supported by runtime
|
||||
|
|
|
@ -47,3 +47,9 @@ int os_cond_destroy(korp_cond *cond)
|
|||
return BHT_OK;
|
||||
}
|
||||
|
||||
uint8 *os_thread_get_stack_boundary()
|
||||
{
|
||||
/* TODO: get sgx stack boundary */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ extern "C" {
|
|||
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
|
||||
|
||||
/* Stack size of applet threads's native part. */
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
|
||||
/* Default thread priority */
|
||||
#define BH_THREAD_DEFAULT_PRIORITY 0
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
|
||||
|
||||
/* Stack size of applet threads's native part. */
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
|
||||
|
||||
/* Default thread priority */
|
||||
#define BH_THREAD_DEFAULT_PRIORITY 0
|
||||
|
|
|
@ -444,3 +444,13 @@ int os_cond_signal(korp_cond *cond)
|
|||
return BHT_OK;
|
||||
}
|
||||
|
||||
uint8 *os_thread_get_stack_boundary()
|
||||
{
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
korp_tid thread = k_current_get();
|
||||
return (uint8*)thread->stack_info.start;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ include_directories(
|
|||
${LVGL_DRIVER_DIR}/display
|
||||
${LVGL_DRIVER_DIR}/indev
|
||||
${LVGL_SOURCE_DIR}
|
||||
${LVGL_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../lv_config
|
||||
|
|
|
@ -59,7 +59,7 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|||
endif ()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE})
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user