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:
wenyongh
2020-04-30 17:52:11 +08:00
committed by GitHub
parent ab4f0c5419
commit d381b0fdec
36 changed files with 1246 additions and 232 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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 */

View File

@ -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;
}

View File

@ -136,7 +136,6 @@ typedef struct WASMModuleInstance {
WASIContext *wasi_ctx;
#endif
uint32 DYNAMICTOP_PTR_offset;
uint32 temp_ret;
uint32 llvm_stack;