From 4bfcbc2cab36267262c9c7d71c8e23f95f2334ba Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Sun, 27 Sep 2020 18:05:20 +0800 Subject: [PATCH] fix problem about local in fast-interp (#406) --- core/iwasm/interpreter/wasm_loader.c | 64 +++++++++++++++++++++-- core/iwasm/interpreter/wasm_mini_loader.c | 64 +++++++++++++++++++++-- wamr-compiler/CMakeLists.txt | 2 + 3 files changed, 122 insertions(+), 8 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 483b4607..20e20404 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -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; diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 5bfff577..c358dab4 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -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; diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 2d82452d..8de6f65d 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -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()