diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 19ca249496..5874931e05 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -12050,9 +12050,25 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMFuncType *wasm_type = block_type.u.type; BranchBlock *cur_block = loader_ctx->frame_csp - 1; +#if WASM_ENABLE_GC != 0 + WASMRefType *ref_type; + uint32 j = 0; +#endif #if WASM_ENABLE_FAST_INTERP != 0 uint32 cell_num; available_params = block_type.u.type->param_count; +#endif +#if WASM_ENABLE_GC != 0 + /* find the index of the last param + * in wasm_type->ref_type_maps as j */ + for (i = 0; i < block_type.u.type->param_count; i++) { + if (wasm_is_type_multi_byte_type(wasm_type->types[i])) { + j += 1; + } + } + if (j > 0) { + j -= 1; + } #endif for (i = 0; i < block_type.u.type->param_count; i++) { @@ -12066,6 +12082,19 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif break; } +#if WASM_ENABLE_GC != 0 + if (wasm_is_type_multi_byte_type( + wasm_type + ->types[wasm_type->param_count - i - 1])) { + bh_assert(wasm_type->ref_type_maps[j].index + == wasm_type->param_count - i - 1); + ref_type = wasm_type->ref_type_maps[j].ref_type; + bh_memcpy_s(&wasm_ref_type, sizeof(WASMRefType), + ref_type, + wasm_reftype_struct_size(ref_type)); + j--; + } +#endif POP_TYPE( wasm_type->types[wasm_type->param_count - i - 1]); diff --git a/tests/regression/ba-issues/issues/issue-4646/test.wasm b/tests/regression/ba-issues/issues/issue-4646/test.wasm new file mode 100644 index 0000000000..e163405eec Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-4646/test.wasm differ diff --git a/tests/regression/ba-issues/issues/issue-4646/test.wat b/tests/regression/ba-issues/issues/issue-4646/test.wat new file mode 100644 index 0000000000..3fd503c550 --- /dev/null +++ b/tests/regression/ba-issues/issues/issue-4646/test.wat @@ -0,0 +1,31 @@ +;; define different reference types +(type $struct_a (struct (field (mut i32)))) +(type $struct_b (struct (field (mut i64)))) +(type $struct_c (struct (field (mut i32)) (field (mut i32)))) + +(func $main + ;; prepare parameters: i32, ref_a, i32, ref_b + (i32.const 10) + (struct.new $struct_a (i32.const 100)) + (i32.const 20) + (struct.new $struct_b (i64.const 200)) + + ;; block with interleaved parameters: i32, ref_a, i32, ref_b -> ref_c + (block (param i32 (ref $struct_a) i32 (ref $struct_b)) (result (ref $struct_c)) + ;; clean up parameters from stack + drop ;; drop ref_b + drop ;; drop i32 + drop ;; drop ref_a + drop ;; drop i32 + + ;; return new type reference struct_c + (struct.new $struct_c (i32.const 300) (i32.const 400)) + ) + + ;; drop return value + drop +) + +(memory 1) +(export "memory" (memory 0)) +(export "_start" (func $main)) \ No newline at end of file diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json index decc6861aa..bc62c54915 100644 --- a/tests/regression/ba-issues/running_config.json +++ b/tests/regression/ba-issues/running_config.json @@ -1770,6 +1770,22 @@ "stdout content": "", "description": "no 'invalid local type'" } + }, + { + "deprecated": false, + "ids": [ + 4646 + ], + "runtime": "iwasm-default-gc-enabled", + "file": "test.wasm", + "mode": "classic-interp", + "options": "-f _start", + "argument": "", + "expected return": { + "ret code": 0, + "stdout content": "", + "description": "load successfully" + } } ] }