fix problem about local in fast-interp (#406)

This commit is contained in:
Xu Jun 2020-09-27 18:05:20 +08:00 committed by GitHub
parent c59bfe24fb
commit 4bfcbc2cab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 8 deletions

View File

@ -4273,24 +4273,30 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
uint32 local_index, uint32 local_type, bool *preserved,
char *error_buf, uint32 error_buf_size)
{
uint32 i = 0;
int16 preserved_offset = (int16)local_index;
*preserved = false;
for (uint32 i = 0; i < loader_ctx->stack_cell_num; i++) {
while (i < loader_ctx->stack_cell_num) {
uint8 cur_type = loader_ctx->frame_ref_bottom[i];
/* move previous local into dynamic space before a set/tee_local opcode */
if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) {
if (preserved_offset == (int16)local_index) {
if (!(*preserved)) {
*preserved = true;
skip_label();
preserved_offset = loader_ctx->preserved_local_offset;
if (loader_ctx->p_code_compiled) {
bh_assert(preserved_offset != (int16)local_index);
}
if (local_type == VALUE_TYPE_I32
|| local_type == VALUE_TYPE_F32) {
preserved_offset = loader_ctx->preserved_local_offset;
/* Only increase preserve offset in the second traversal */
if (loader_ctx->p_code_compiled)
loader_ctx->preserved_local_offset++;
emit_label(EXT_OP_COPY_STACK_TOP);
}
else {
preserved_offset = loader_ctx->preserved_local_offset;
if (loader_ctx->p_code_compiled)
loader_ctx->preserved_local_offset += 2;
emit_label(EXT_OP_COPY_STACK_TOP_I64);
@ -4301,6 +4307,11 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
}
loader_ctx->frame_offset_bottom[i] = preserved_offset;
}
if (cur_type == VALUE_TYPE_I32 || cur_type == VALUE_TYPE_F32)
i++;
else
i += 2;
}
return true;
@ -4311,6 +4322,38 @@ fail:
#endif
}
static bool
preserve_local_for_block(WASMLoaderContext *loader_ctx, uint8 opcode,
char *error_buf, uint32 error_buf_size)
{
uint32 i = 0;
bool preserve_local;
/* preserve locals before blocks to ensure that "tee/set_local" inside
blocks will not influence the value of these locals */
while (i < loader_ctx->stack_cell_num) {
int16 cur_offset = loader_ctx->frame_offset_bottom[i];
uint8 cur_type = loader_ctx->frame_ref_bottom[i];
if ((cur_offset < loader_ctx->start_dynamic_offset)
&& (cur_offset >= 0)) {
if (!(preserve_referenced_local(loader_ctx, opcode, cur_offset,
cur_type, &preserve_local,
error_buf, error_buf_size)))
return false;
}
if (cur_type == VALUE_TYPE_I32 || cur_type == VALUE_TYPE_F32) {
i++;
}
else {
i += 2;
}
}
return true;
}
static bool
add_label_patch_to_list(BranchBlock *frame_csp,
uint8 patch_type, uint8 *p_code_compiled,
@ -5387,6 +5430,13 @@ fail:
#define BLOCK_HAS_PARAM(block_type) \
(!block_type.is_value_type && block_type.u.type->param_count > 0)
#define PRESERVE_LOCAL_FOR_BLOCK() do { \
if (!(preserve_local_for_block(loader_ctx, opcode, \
error_buf, error_buf_size))) { \
goto fail; \
} \
} while (0)
static bool
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
BlockAddr *block_addr_cache,
@ -5475,10 +5525,16 @@ re_scan:
break;
case WASM_OP_IF:
#if WASM_ENABLE_FAST_INTERP != 0
PRESERVE_LOCAL_FOR_BLOCK();
#endif
POP_I32();
goto handle_op_block_and_loop;
case WASM_OP_BLOCK:
case WASM_OP_LOOP:
#if WASM_ENABLE_FAST_INTERP != 0
PRESERVE_LOCAL_FOR_BLOCK();
#endif
handle_op_block_and_loop:
{
uint8 value_type;

View File

@ -3172,24 +3172,30 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
uint32 local_index, uint32 local_type, bool *preserved,
char *error_buf, uint32 error_buf_size)
{
uint32 i = 0;
int16 preserved_offset = (int16)local_index;
*preserved = false;
for (uint32 i = 0; i < loader_ctx->stack_cell_num; i++) {
while (i < loader_ctx->stack_cell_num) {
uint8 cur_type = loader_ctx->frame_ref_bottom[i];
/* move previous local into dynamic space before a set/tee_local opcode */
if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) {
if (preserved_offset == (int16)local_index) {
if (!(*preserved)) {
*preserved = true;
skip_label();
preserved_offset = loader_ctx->preserved_local_offset;
if (loader_ctx->p_code_compiled) {
bh_assert(preserved_offset != (int16)local_index);
}
if (local_type == VALUE_TYPE_I32
|| local_type == VALUE_TYPE_F32) {
preserved_offset = loader_ctx->preserved_local_offset;
/* Only increase preserve offset in the second traversal */
if (loader_ctx->p_code_compiled)
loader_ctx->preserved_local_offset++;
emit_label(EXT_OP_COPY_STACK_TOP);
}
else {
preserved_offset = loader_ctx->preserved_local_offset;
if (loader_ctx->p_code_compiled)
loader_ctx->preserved_local_offset += 2;
emit_label(EXT_OP_COPY_STACK_TOP_I64);
@ -3200,6 +3206,11 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
}
loader_ctx->frame_offset_bottom[i] = preserved_offset;
}
if (cur_type == VALUE_TYPE_I32 || cur_type == VALUE_TYPE_F32)
i++;
else
i += 2;
}
return true;
@ -3210,6 +3221,38 @@ fail:
#endif
}
static bool
preserve_local_for_block(WASMLoaderContext *loader_ctx, uint8 opcode,
char *error_buf, uint32 error_buf_size)
{
uint32 i = 0;
bool preserve_local;
/* preserve locals before blocks to ensure that "tee/set_local" inside
blocks will not influence the value of these locals */
while (i < loader_ctx->stack_cell_num) {
int16 cur_offset = loader_ctx->frame_offset_bottom[i];
uint8 cur_type = loader_ctx->frame_ref_bottom[i];
if ((cur_offset < loader_ctx->start_dynamic_offset)
&& (cur_offset >= 0)) {
if (!(preserve_referenced_local(loader_ctx, opcode, cur_offset,
cur_type, &preserve_local,
error_buf, error_buf_size)))
return false;
}
if (cur_type == VALUE_TYPE_I32 || cur_type == VALUE_TYPE_F32) {
i++;
}
else {
i += 2;
}
}
return true;
}
static bool
add_label_patch_to_list(BranchBlock *frame_csp,
uint8 patch_type, uint8 *p_code_compiled,
@ -4218,6 +4261,13 @@ fail:
#define BLOCK_HAS_PARAM(block_type) \
(!block_type.is_value_type && block_type.u.type->param_count > 0)
#define PRESERVE_LOCAL_FOR_BLOCK() do { \
if (!(preserve_local_for_block(loader_ctx, opcode, \
error_buf, error_buf_size))) { \
goto fail; \
} \
} while (0)
static bool
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
BlockAddr *block_addr_cache,
@ -4306,10 +4356,16 @@ re_scan:
break;
case WASM_OP_IF:
#if WASM_ENABLE_FAST_INTERP != 0
PRESERVE_LOCAL_FOR_BLOCK();
#endif
POP_I32();
goto handle_op_block_and_loop;
case WASM_OP_BLOCK:
case WASM_OP_LOOP:
#if WASM_ENABLE_FAST_INTERP != 0
PRESERVE_LOCAL_FOR_BLOCK();
#endif
handle_op_block_and_loop:
{
uint8 value_type;

View File

@ -10,6 +10,8 @@ else()
enable_language (ASM_MASM)
endif()
set (CMAKE_CXX_STANDARD 14)
if (NOT DEFINED WAMR_BUILD_PLATFORM)
set (WAMR_BUILD_PLATFORM "linux")
endif()