|
|
@@ -7086,7 +7086,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
|
|
}
|
|
|
else {
|
|
|
p--;
|
|
|
- skip_leb_uint32(p, p_end);
|
|
|
+ /* block type */
|
|
|
+ skip_leb_int32(p, p_end);
|
|
|
}
|
|
|
if (block_nested_depth
|
|
|
< sizeof(block_stack) / sizeof(BlockAddr)) {
|
|
|
@@ -7101,7 +7102,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
|
|
case EXT_OP_LOOP:
|
|
|
case EXT_OP_IF:
|
|
|
/* block type */
|
|
|
- skip_leb_uint32(p, p_end);
|
|
|
+ skip_leb_int32(p, p_end);
|
|
|
if (block_nested_depth
|
|
|
< sizeof(block_stack) / sizeof(BlockAddr)) {
|
|
|
block_stack[block_nested_depth].start_addr = p;
|
|
|
@@ -7850,7 +7851,11 @@ typedef struct BranchBlock {
|
|
|
BranchBlockPatch *patch_list;
|
|
|
/* This is used to save params frame_offset of of if block */
|
|
|
int16 *param_frame_offsets;
|
|
|
- /* This is used to recover dynamic offset for else branch */
|
|
|
+ /* This is used to recover the dynamic offset for else branch,
|
|
|
+ * and also to remember the start offset of dynamic space which
|
|
|
+ * stores the block arguments for loop block, so we can use it
|
|
|
+ * to copy the stack operands to the loop block's arguments in
|
|
|
+ * wasm_loader_emit_br_info for opcode br. */
|
|
|
uint16 start_dynamic_offset;
|
|
|
#endif
|
|
|
|
|
|
@@ -8001,13 +8006,26 @@ static void
|
|
|
free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
|
|
|
{
|
|
|
BranchBlock *tmp_csp = frame_csp;
|
|
|
+ uint32 i;
|
|
|
|
|
|
- for (uint32 i = 0; i < csp_num; i++) {
|
|
|
+ for (i = 0; i < csp_num; i++) {
|
|
|
free_label_patch_list(tmp_csp);
|
|
|
tmp_csp++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num)
|
|
|
+{
|
|
|
+ BranchBlock *tmp_csp = frame_csp;
|
|
|
+ uint32 i;
|
|
|
+
|
|
|
+ for (i = 0; i < csp_num; i++) {
|
|
|
+ if (tmp_csp->param_frame_offsets)
|
|
|
+ wasm_runtime_free(tmp_csp->param_frame_offsets);
|
|
|
+ tmp_csp++;
|
|
|
+ }
|
|
|
+}
|
|
|
#endif /* end of WASM_ENABLE_FAST_INTERP */
|
|
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
|
@@ -8126,6 +8144,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
|
|
|
if (ctx->frame_csp_bottom) {
|
|
|
#if WASM_ENABLE_FAST_INTERP != 0
|
|
|
free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
|
|
|
+ free_all_label_param_frame_offsets(ctx->frame_csp_bottom,
|
|
|
+ ctx->csp_num);
|
|
|
#endif
|
|
|
#if WASM_ENABLE_GC != 0
|
|
|
wasm_loader_clean_all_local_use_masks(ctx);
|
|
|
@@ -9238,8 +9258,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
|
|
|
emit_operand(ctx, *(int16 *)(frame_offset));
|
|
|
}
|
|
|
/* Part e */
|
|
|
- dynamic_offset =
|
|
|
- frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
|
|
|
+ if (frame_csp->label_type == LABEL_TYPE_LOOP)
|
|
|
+ /* Use start_dynamic_offset which was set in
|
|
|
+ copy_params_to_dynamic_space */
|
|
|
+ dynamic_offset = frame_csp->start_dynamic_offset
|
|
|
+ + wasm_get_cell_num(types, arity);
|
|
|
+ else
|
|
|
+ dynamic_offset =
|
|
|
+ frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
|
|
|
if (is_br)
|
|
|
ctx->dynamic_offset = dynamic_offset;
|
|
|
for (i = (int32)arity - 1; i >= 0; i--) {
|
|
|
@@ -10623,8 +10649,8 @@ fail:
|
|
|
* Part e: each param's dst offset
|
|
|
*/
|
|
|
static bool
|
|
|
-copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
|
|
|
- char *error_buf, uint32 error_buf_size)
|
|
|
+copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf,
|
|
|
+ uint32 error_buf_size)
|
|
|
{
|
|
|
bool ret = false;
|
|
|
int16 *frame_offset = NULL;
|
|
|
@@ -10638,6 +10664,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
|
|
|
uint32 param_count = block_type->u.type->param_count;
|
|
|
int16 condition_offset = 0;
|
|
|
bool disable_emit = false;
|
|
|
+ bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false);
|
|
|
int16 operand_offset = 0;
|
|
|
|
|
|
uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
|
|
|
@@ -10690,6 +10717,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
|
|
|
if (is_if_block)
|
|
|
emit_operand(loader_ctx, condition_offset);
|
|
|
|
|
|
+ /* Since the start offset to save the block's params and
|
|
|
+ * the start offset to save the block's results may be
|
|
|
+ * different, we remember the dynamic offset for loop block
|
|
|
+ * so that we can use it to copy the stack operands to the
|
|
|
+ * loop block's params in wasm_loader_emit_br_info. */
|
|
|
+ if (block->label_type == LABEL_TYPE_LOOP)
|
|
|
+ block->start_dynamic_offset = loader_ctx->dynamic_offset;
|
|
|
+
|
|
|
/* Part e) */
|
|
|
/* Push to dynamic space. The push will emit the dst offset. */
|
|
|
for (i = 0; i < param_count; i++)
|
|
|
@@ -11062,12 +11097,12 @@ re_scan:
|
|
|
#endif /* end of WASM_ENABLE_GC != 0 */
|
|
|
}
|
|
|
else {
|
|
|
- uint32 type_index;
|
|
|
+ int32 type_index;
|
|
|
/* Resolve the leb128 encoded type index as block type */
|
|
|
p--;
|
|
|
p_org = p - 1;
|
|
|
- read_leb_uint32(p, p_end, type_index);
|
|
|
- if (type_index >= module->type_count) {
|
|
|
+ read_leb_int32(p, p_end, type_index);
|
|
|
+ if ((uint32)type_index >= module->type_count) {
|
|
|
set_error_buf(error_buf, error_buf_size,
|
|
|
"unknown type");
|
|
|
goto fail;
|
|
|
@@ -11171,8 +11206,8 @@ re_scan:
|
|
|
|
|
|
if (BLOCK_HAS_PARAM(block_type)) {
|
|
|
/* Make sure params are in dynamic space */
|
|
|
- if (!copy_params_to_dynamic_space(
|
|
|
- loader_ctx, false, error_buf, error_buf_size))
|
|
|
+ if (!copy_params_to_dynamic_space(loader_ctx, error_buf,
|
|
|
+ error_buf_size))
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
@@ -11218,8 +11253,8 @@ re_scan:
|
|
|
/* skip the if label */
|
|
|
skip_label();
|
|
|
/* Emit a copy instruction */
|
|
|
- if (!copy_params_to_dynamic_space(
|
|
|
- loader_ctx, true, error_buf, error_buf_size))
|
|
|
+ if (!copy_params_to_dynamic_space(loader_ctx, error_buf,
|
|
|
+ error_buf_size))
|
|
|
goto fail;
|
|
|
|
|
|
/* Emit the if instruction */
|