|
|
@@ -36,6 +36,21 @@
|
|
|
#define TEMPLATE_READ_VALUE(Type, p) \
|
|
|
(p += sizeof(Type), *(Type *)(p - sizeof(Type)))
|
|
|
|
|
|
+#if WASM_ENABLE_MEMORY64 != 0
|
|
|
+static bool
|
|
|
+has_module_memory64(WASMModule *module)
|
|
|
+{
|
|
|
+ /* TODO: multi-memories for now assuming the memory idx type is consistent
|
|
|
+ * across multi-memories */
|
|
|
+ if (module->import_memory_count > 0)
|
|
|
+ return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
|
|
|
+ else if (module->memory_count > 0)
|
|
|
+ return !!(module->memories[0].flags & MEMORY64_FLAG);
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
static void
|
|
|
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
|
|
{
|
|
|
@@ -278,7 +293,10 @@ type2str(uint8 type)
|
|
|
static bool
|
|
|
is_32bit_type(uint8 type)
|
|
|
{
|
|
|
- if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
|
|
|
+ if (type == VALUE_TYPE_I32
|
|
|
+ || type == VALUE_TYPE_F32
|
|
|
+ /* the operand stack is in polymorphic state */
|
|
|
+ || type == VALUE_TYPE_ANY
|
|
|
#if WASM_ENABLE_GC != 0
|
|
|
|| (sizeof(uintptr_t) == 4 && wasm_is_type_reftype(type))
|
|
|
#elif WASM_ENABLE_REF_TYPES != 0
|
|
|
@@ -394,10 +412,10 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
|
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
|
static bool
|
|
|
-check_type_index(const WASMModule *module, uint32 type_index, char *error_buf,
|
|
|
- uint32 error_buf_size)
|
|
|
+check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index,
|
|
|
+ char *error_buf, uint32 error_buf_size)
|
|
|
{
|
|
|
- if (type_index >= module->type_count) {
|
|
|
+ if (type_index >= type_count) {
|
|
|
set_error_buf_v(error_buf, error_buf_size, "unknown type %d",
|
|
|
type_index);
|
|
|
return false;
|
|
|
@@ -409,7 +427,8 @@ static bool
|
|
|
check_array_type(const WASMModule *module, uint32 type_index, char *error_buf,
|
|
|
uint32 error_buf_size)
|
|
|
{
|
|
|
- if (!check_type_index(module, type_index, error_buf, error_buf_size)) {
|
|
|
+ if (!check_type_index(module, module->type_count, type_index, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (module->types[type_index]->type_flag != WASM_TYPE_ARRAY) {
|
|
|
@@ -775,8 +794,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|
|
if (!is_byte_a_type(type1)) {
|
|
|
p--;
|
|
|
read_leb_uint32(p, p_end, type_idx);
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
- error_buf_size))
|
|
|
+ if (!check_type_index(module, module->type_count, type_idx,
|
|
|
+ error_buf, error_buf_size))
|
|
|
goto fail;
|
|
|
|
|
|
wasm_set_refheaptype_typeidx(&cur_ref_type.ref_ht_typeidx,
|
|
|
@@ -902,7 +921,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|
|
uint32 field_count;
|
|
|
read_leb_uint32(p, p_end, type_idx);
|
|
|
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
+ if (!check_type_index(module, module->type_count,
|
|
|
+ type_idx, error_buf,
|
|
|
error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
@@ -966,7 +986,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|
|
read_leb_uint32(p, p_end, cur_value.type_index);
|
|
|
type_idx = cur_value.type_index;
|
|
|
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
+ if (!check_type_index(module, module->type_count,
|
|
|
+ type_idx, error_buf,
|
|
|
error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
@@ -1001,7 +1022,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|
|
read_leb_uint32(p, p_end, cur_value.type_index);
|
|
|
type_idx = cur_value.type_index;
|
|
|
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
+ if (!check_type_index(module, module->type_count,
|
|
|
+ type_idx, error_buf,
|
|
|
error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
@@ -1275,6 +1297,13 @@ destroy_array_type(WASMArrayType *type)
|
|
|
static void
|
|
|
destroy_wasm_type(WASMType *type)
|
|
|
{
|
|
|
+ if (type->ref_count > 1) {
|
|
|
+ /* The type is referenced by other types
|
|
|
+ of current wasm module */
|
|
|
+ type->ref_count--;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
if (type->type_flag == WASM_TYPE_FUNC)
|
|
|
destroy_func_type((WASMFuncType *)type);
|
|
|
else if (type->type_flag == WASM_TYPE_STRUCT)
|
|
|
@@ -1289,8 +1318,9 @@ destroy_wasm_type(WASMType *type)
|
|
|
/* Resolve (ref null ht) or (ref ht) */
|
|
|
static bool
|
|
|
resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
- WASMModule *module, bool nullable, WASMRefType *ref_type,
|
|
|
- char *error_buf, uint32 error_buf_size)
|
|
|
+ WASMModule *module, uint32 type_count, bool nullable,
|
|
|
+ WASMRefType *ref_type, char *error_buf,
|
|
|
+ uint32 error_buf_size)
|
|
|
{
|
|
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
|
|
|
|
|
@@ -1301,8 +1331,9 @@ resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
|
|
|
if (wasm_is_refheaptype_typeidx(&ref_type->ref_ht_common)) {
|
|
|
/* heap type is (type i), i : typeidx, >= 0 */
|
|
|
- if (!check_type_index(module, ref_type->ref_ht_typeidx.type_idx,
|
|
|
- error_buf, error_buf_size)) {
|
|
|
+ if (!check_type_index(module, type_count,
|
|
|
+ ref_type->ref_ht_typeidx.type_idx, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
@@ -1320,9 +1351,10 @@ fail:
|
|
|
|
|
|
static bool
|
|
|
resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
- WASMModule *module, bool *p_need_ref_type_map,
|
|
|
- WASMRefType *ref_type, bool allow_packed_type,
|
|
|
- char *error_buf, uint32 error_buf_size)
|
|
|
+ WASMModule *module, uint32 type_count,
|
|
|
+ bool *p_need_ref_type_map, WASMRefType *ref_type,
|
|
|
+ bool allow_packed_type, char *error_buf,
|
|
|
+ uint32 error_buf_size)
|
|
|
{
|
|
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
|
|
uint8 type;
|
|
|
@@ -1334,8 +1366,8 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
|
|
|
if (wasm_is_reftype_htref_nullable(type)) {
|
|
|
/* (ref null ht) */
|
|
|
- if (!resolve_reftype_htref(&p, p_end, module, true, ref_type, error_buf,
|
|
|
- error_buf_size))
|
|
|
+ if (!resolve_reftype_htref(&p, p_end, module, type_count, true,
|
|
|
+ ref_type, error_buf, error_buf_size))
|
|
|
return false;
|
|
|
if (!wasm_is_refheaptype_common(&ref_type->ref_ht_common))
|
|
|
*p_need_ref_type_map = true;
|
|
|
@@ -1351,8 +1383,8 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
}
|
|
|
else if (wasm_is_reftype_htref_non_nullable(type)) {
|
|
|
/* (ref ht) */
|
|
|
- if (!resolve_reftype_htref(&p, p_end, module, false, ref_type,
|
|
|
- error_buf, error_buf_size))
|
|
|
+ if (!resolve_reftype_htref(&p, p_end, module, type_count, false,
|
|
|
+ ref_type, error_buf, error_buf_size))
|
|
|
return false;
|
|
|
*p_need_ref_type_map = true;
|
|
|
#if WASM_ENABLE_STRINGREF != 0
|
|
|
@@ -1401,7 +1433,8 @@ reftype_set_insert(HashMap *ref_type_set, const WASMRefType *ref_type,
|
|
|
|
|
|
static bool
|
|
|
resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
- uint32 type_idx, char *error_buf, uint32 error_buf_size)
|
|
|
+ uint32 type_count, uint32 type_idx, char *error_buf,
|
|
|
+ uint32 error_buf_size)
|
|
|
{
|
|
|
const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
|
|
|
uint32 param_count, result_count, i, j = 0;
|
|
|
@@ -1417,8 +1450,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
read_leb_uint32(p, p_end, param_count);
|
|
|
p_org = p;
|
|
|
for (i = 0; i < param_count; i++) {
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (need_ref_type_map)
|
|
|
@@ -1427,8 +1461,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
|
|
|
read_leb_uint32(p, p_end, result_count);
|
|
|
for (i = 0; i < result_count; i++) {
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (need_ref_type_map) {
|
|
|
@@ -1468,8 +1503,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < param_count; i++) {
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
type->types[i] = ref_type.ref_type;
|
|
|
@@ -1485,8 +1521,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
|
|
|
read_leb_uint32(p, p_end, result_count);
|
|
|
for (i = 0; i < result_count; i++) {
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
type->types[param_count + i] = ref_type.ref_type;
|
|
|
@@ -1527,18 +1564,6 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- /* Calculate the minimal type index of the type equal to this type */
|
|
|
- type->min_type_idx_normalized = type_idx;
|
|
|
- for (i = 0; i < type_idx; i++) {
|
|
|
- WASMFuncType *func_type = (WASMFuncType *)module->types[i];
|
|
|
- if (func_type->base_type.type_flag == WASM_TYPE_FUNC
|
|
|
- && wasm_func_type_equal(type, func_type, module->types,
|
|
|
- type_idx + 1)) {
|
|
|
- type->min_type_idx_normalized = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
*p_buf = p;
|
|
|
|
|
|
module->types[type_idx] = (WASMType *)type;
|
|
|
@@ -1552,8 +1577,8 @@ fail:
|
|
|
|
|
|
static bool
|
|
|
resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
- WASMModule *module, uint32 type_idx, char *error_buf,
|
|
|
- uint32 error_buf_size)
|
|
|
+ WASMModule *module, uint32 type_count, uint32 type_idx,
|
|
|
+ char *error_buf, uint32 error_buf_size)
|
|
|
{
|
|
|
const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
|
|
|
uint32 field_count, ref_type_map_count = 0, ref_field_count = 0;
|
|
|
@@ -1569,8 +1594,9 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
read_leb_uint32(p, p_end, field_count);
|
|
|
p_org = p;
|
|
|
for (i = 0; i < field_count; i++) {
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, true, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count,
|
|
|
+ &need_ref_type_map, &ref_type, true, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (need_ref_type_map)
|
|
|
@@ -1617,8 +1643,9 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
|
|
|
offset = (uint32)offsetof(WASMStructObject, field_data);
|
|
|
for (i = 0; i < field_count; i++) {
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, true, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count,
|
|
|
+ &need_ref_type_map, &ref_type, true, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
type->fields[i].field_type = ref_type.ref_type;
|
|
|
@@ -1671,8 +1698,8 @@ fail:
|
|
|
|
|
|
static bool
|
|
|
resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
- WASMModule *module, uint32 type_idx, char *error_buf,
|
|
|
- uint32 error_buf_size)
|
|
|
+ WASMModule *module, uint32 type_count, uint32 type_idx,
|
|
|
+ char *error_buf, uint32 error_buf_size)
|
|
|
{
|
|
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
|
|
uint8 mutable;
|
|
|
@@ -1680,8 +1707,8 @@ resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
WASMRefType ref_type;
|
|
|
WASMArrayType *type = NULL;
|
|
|
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, &ref_type,
|
|
|
- true, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, type_count, &need_ref_type_map,
|
|
|
+ &ref_type, true, error_buf, error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -1730,7 +1757,8 @@ init_ref_type(WASMModule *module, WASMRefType *ref_type, bool nullable,
|
|
|
int32 heap_type, char *error_buf, uint32 error_buf_size)
|
|
|
{
|
|
|
if (heap_type >= 0) {
|
|
|
- if (!check_type_index(module, heap_type, error_buf, error_buf_size)) {
|
|
|
+ if (!check_type_index(module, module->type_count, heap_type, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
wasm_set_refheaptype_typeidx(&ref_type->ref_ht_typeidx, nullable,
|
|
|
@@ -2010,6 +2038,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
|
|
|
if (flag == DEFINED_TYPE_FUNC) {
|
|
|
if (!resolve_func_type(&p, buf_end, module,
|
|
|
+ processed_type_count + rec_count,
|
|
|
processed_type_count + j, error_buf,
|
|
|
error_buf_size)) {
|
|
|
return false;
|
|
|
@@ -2017,6 +2046,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
}
|
|
|
else if (flag == DEFINED_TYPE_STRUCT) {
|
|
|
if (!resolve_struct_type(&p, buf_end, module,
|
|
|
+ processed_type_count + rec_count,
|
|
|
processed_type_count + j,
|
|
|
error_buf, error_buf_size)) {
|
|
|
return false;
|
|
|
@@ -2024,6 +2054,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
}
|
|
|
else if (flag == DEFINED_TYPE_ARRAY) {
|
|
|
if (!resolve_array_type(&p, buf_end, module,
|
|
|
+ processed_type_count + rec_count,
|
|
|
processed_type_count + j, error_buf,
|
|
|
error_buf_size)) {
|
|
|
return false;
|
|
|
@@ -2037,13 +2068,13 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
|
|
|
cur_type = module->types[processed_type_count + j];
|
|
|
|
|
|
+ cur_type->ref_count = 1;
|
|
|
cur_type->parent_type_idx = parent_type_idx;
|
|
|
cur_type->is_sub_final = is_sub_final;
|
|
|
|
|
|
- if (rec_count > 1) {
|
|
|
- cur_type->rec_count = rec_count;
|
|
|
- cur_type->rec_idx = j;
|
|
|
- }
|
|
|
+ cur_type->rec_count = rec_count;
|
|
|
+ cur_type->rec_idx = j;
|
|
|
+ cur_type->rec_begin_type_idx = processed_type_count;
|
|
|
}
|
|
|
|
|
|
/* resolve subtyping relationship in current rec group */
|
|
|
@@ -2055,6 +2086,11 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
module->types[cur_type->parent_type_idx];
|
|
|
cur_type->parent_type = parent_type;
|
|
|
cur_type->root_type = parent_type->root_type;
|
|
|
+ if (parent_type->inherit_depth == UINT16_MAX) {
|
|
|
+ set_error_buf(error_buf, error_buf_size,
|
|
|
+ "parent type's inherit depth too large");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
cur_type->inherit_depth = parent_type->inherit_depth + 1;
|
|
|
}
|
|
|
else {
|
|
|
@@ -2080,6 +2116,49 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* If there is already an equivalence type or a group of equivalence
|
|
|
+ recursive types created, use it or them instead */
|
|
|
+ for (j = 0; j < processed_type_count;) {
|
|
|
+ WASMType *src_type = module->types[j];
|
|
|
+ WASMType *cur_type = module->types[processed_type_count];
|
|
|
+ uint32 k, src_rec_count;
|
|
|
+
|
|
|
+ src_rec_count = src_type->rec_count;
|
|
|
+ if (src_rec_count != rec_count) {
|
|
|
+ /* no type equivalence */
|
|
|
+ j += src_rec_count;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (k = 0; k < rec_count; k++) {
|
|
|
+ src_type = module->types[j + k];
|
|
|
+ cur_type = module->types[processed_type_count + k];
|
|
|
+ if (!wasm_type_equal(src_type, cur_type, module->types,
|
|
|
+ module->type_count)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (k < rec_count) {
|
|
|
+ /* no type equivalence */
|
|
|
+ j += src_rec_count;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* type equivalence */
|
|
|
+ for (k = 0; k < rec_count; k++) {
|
|
|
+ if (module->types[j + k]->ref_count == UINT16_MAX) {
|
|
|
+ set_error_buf(error_buf, error_buf_size,
|
|
|
+ "wasm type's ref count too large");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ destroy_wasm_type(module->types[processed_type_count + k]);
|
|
|
+ module->types[processed_type_count + k] =
|
|
|
+ module->types[j + k];
|
|
|
+ module->types[j + k]->ref_count++;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
if (rec_count > 1) {
|
|
|
LOG_VERBOSE("Finished processing rec group [%d-%d]",
|
|
|
processed_type_count,
|
|
|
@@ -2511,8 +2590,9 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
return false;
|
|
|
}
|
|
|
#else /* else of WASM_ENABLE_GC == 0 */
|
|
|
- if (!resolve_value_type(&p, p_end, parent_module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) {
|
|
|
@@ -2947,8 +3027,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
|
|
|
declare_type = read_uint8(p);
|
|
|
declare_mutable = read_uint8(p);
|
|
|
#else
|
|
|
- if (!resolve_value_type(&p, p_end, parent_module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
declare_type = ref_type.ref_type;
|
|
|
@@ -3050,8 +3131,9 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|
|
return false;
|
|
|
}
|
|
|
#else /* else of WASM_ENABLE_GC == 0 */
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, &ref_type,
|
|
|
- false, error_buf, error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, module->type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
table->elem_type = ref_type.ref_type;
|
|
|
@@ -3536,7 +3618,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|
|
type_index_org = type_index;
|
|
|
#endif
|
|
|
|
|
|
-#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
|
|
|
+#if (WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0) \
|
|
|
+ && WASM_ENABLE_GC == 0
|
|
|
type_index = wasm_get_smallest_type_idx(
|
|
|
module->types, module->type_count, type_index);
|
|
|
#endif
|
|
|
@@ -3577,8 +3660,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|
|
#endif
|
|
|
#else
|
|
|
if (!resolve_value_type(&p_code, buf_code_end, module,
|
|
|
- &need_ref_type_map, &ref_type, false,
|
|
|
- error_buf, error_buf_size)) {
|
|
|
+ module->type_count, &need_ref_type_map,
|
|
|
+ &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
local_count += sub_local_count;
|
|
|
@@ -3664,8 +3748,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|
|
}
|
|
|
#else
|
|
|
if (!resolve_value_type(&p_code, buf_code_end, module,
|
|
|
- &need_ref_type_map, &ref_type, false,
|
|
|
- error_buf, error_buf_size)) {
|
|
|
+ module->type_count, &need_ref_type_map,
|
|
|
+ &ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (need_ref_type_map) {
|
|
|
@@ -3923,9 +4008,9 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|
|
global->type = read_uint8(p);
|
|
|
mutable = read_uint8(p);
|
|
|
#else
|
|
|
- if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
|
|
- &ref_type, false, error_buf,
|
|
|
- error_buf_size)) {
|
|
|
+ if (!resolve_value_type(&p, p_end, module, module->type_count,
|
|
|
+ &need_ref_type_map, &ref_type, false,
|
|
|
+ error_buf, error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
global->type = ref_type.ref_type;
|
|
|
@@ -4231,8 +4316,8 @@ load_elem_type(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|
|
#else
|
|
|
p--;
|
|
|
if (!resolve_value_type((const uint8 **)&p, p_end, module,
|
|
|
- &need_ref_type_map, &elem_ref_type, false,
|
|
|
- error_buf, error_buf_size)) {
|
|
|
+ module->type_count, &need_ref_type_map,
|
|
|
+ &elem_ref_type, false, error_buf, error_buf_size)) {
|
|
|
return false;
|
|
|
}
|
|
|
if (!wasm_is_type_reftype(elem_ref_type.ref_type)) {
|
|
|
@@ -4546,7 +4631,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
|
|
bool is_passive = false;
|
|
|
uint32 mem_flag;
|
|
|
#endif
|
|
|
- uint8 mem_offset_type;
|
|
|
+ uint8 mem_offset_type = VALUE_TYPE_I32;
|
|
|
|
|
|
read_leb_uint32(p, p_end, data_seg_count);
|
|
|
|
|
|
@@ -5592,6 +5677,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|
|
uint32 aux_data_end_global_index = (uint32)-1;
|
|
|
uint32 aux_heap_base_global_index = (uint32)-1;
|
|
|
WASMFuncType *func_type;
|
|
|
+ uint8 malloc_free_io_type = VALUE_TYPE_I32;
|
|
|
|
|
|
/* Find code and function sections if have */
|
|
|
while (section) {
|
|
|
@@ -5820,6 +5906,10 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|
|
module->retain_function = (uint32)-1;
|
|
|
|
|
|
/* Resolve malloc/free function exported by wasm module */
|
|
|
+#if WASM_ENABLE_MEMORY64 != 0
|
|
|
+ if (has_module_memory64(module))
|
|
|
+ malloc_free_io_type = VALUE_TYPE_I64;
|
|
|
+#endif
|
|
|
export = module->exports;
|
|
|
for (i = 0; i < module->export_count; i++, export ++) {
|
|
|
if (export->kind == EXPORT_KIND_FUNC) {
|
|
|
@@ -5828,8 +5918,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|
|
func_index = export->index - module->import_function_count;
|
|
|
func_type = module->functions[func_index]->func_type;
|
|
|
if (func_type->param_count == 1 && func_type->result_count == 1
|
|
|
- && func_type->types[0] == VALUE_TYPE_I32
|
|
|
- && func_type->types[1] == VALUE_TYPE_I32) {
|
|
|
+ && func_type->types[0] == malloc_free_io_type
|
|
|
+ && func_type->types[1] == malloc_free_io_type) {
|
|
|
bh_assert(module->malloc_function == (uint32)-1);
|
|
|
module->malloc_function = export->index;
|
|
|
LOG_VERBOSE("Found malloc function, name: %s, index: %u",
|
|
|
@@ -5842,9 +5932,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|
|
func_index = export->index - module->import_function_count;
|
|
|
func_type = module->functions[func_index]->func_type;
|
|
|
if (func_type->param_count == 2 && func_type->result_count == 1
|
|
|
- && func_type->types[0] == VALUE_TYPE_I32
|
|
|
+ && func_type->types[0] == malloc_free_io_type
|
|
|
&& func_type->types[1] == VALUE_TYPE_I32
|
|
|
- && func_type->types[2] == VALUE_TYPE_I32) {
|
|
|
+ && func_type->types[2] == malloc_free_io_type) {
|
|
|
uint32 j;
|
|
|
WASMExport *export_tmp;
|
|
|
|
|
|
@@ -5868,8 +5958,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|
|
module->functions[func_index]->func_type;
|
|
|
if (func_type->param_count == 1
|
|
|
&& func_type->result_count == 1
|
|
|
- && func_type->types[0] == VALUE_TYPE_I32
|
|
|
- && func_type->types[1] == VALUE_TYPE_I32) {
|
|
|
+ && func_type->types[0] == malloc_free_io_type
|
|
|
+ && func_type->types[1] == malloc_free_io_type) {
|
|
|
bh_assert(module->retain_function
|
|
|
== (uint32)-1);
|
|
|
module->retain_function = export_tmp->index;
|
|
|
@@ -5895,7 +5985,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|
|
func_index = export->index - module->import_function_count;
|
|
|
func_type = module->functions[func_index]->func_type;
|
|
|
if (func_type->param_count == 1 && func_type->result_count == 0
|
|
|
- && func_type->types[0] == VALUE_TYPE_I32) {
|
|
|
+ && func_type->types[0] == malloc_free_io_type) {
|
|
|
bh_assert(module->free_function == (uint32)-1);
|
|
|
module->free_function = export->index;
|
|
|
LOG_VERBOSE("Found free function, name: %s, index: %u",
|
|
|
@@ -10670,14 +10760,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
|
|
func->param_cell_num, func->local_cell_num, func->ret_cell_num);
|
|
|
#endif
|
|
|
#if WASM_ENABLE_MEMORY64 != 0
|
|
|
- bool is_memory64 = false;
|
|
|
- /* TODO: multi-memories for now assuming the memory idx type is consistent
|
|
|
- * across multi-memories */
|
|
|
- if (module->import_memory_count > 0)
|
|
|
- is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
|
|
|
- else if (module->memory_count > 0)
|
|
|
- is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
|
|
|
-
|
|
|
+ bool is_memory64 = has_module_memory64(module);
|
|
|
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
|
|
|
#else
|
|
|
mem_offset_type = VALUE_TYPE_I32;
|
|
|
@@ -10827,7 +10910,8 @@ re_scan:
|
|
|
p_org = p;
|
|
|
p--;
|
|
|
if (!resolve_value_type((const uint8 **)&p, p_end,
|
|
|
- module, &need_ref_type_map,
|
|
|
+ module, module->type_count,
|
|
|
+ &need_ref_type_map,
|
|
|
&wasm_ref_type, false,
|
|
|
error_buf, error_buf_size)) {
|
|
|
goto fail;
|
|
|
@@ -11254,8 +11338,10 @@ re_scan:
|
|
|
BlockType block_type;
|
|
|
|
|
|
if (loader_ctx->csp_num < 2
|
|
|
- || (loader_ctx->frame_csp - 1)->label_type
|
|
|
- != LABEL_TYPE_IF) {
|
|
|
+ /* the matched if isn't found */
|
|
|
+ || (loader_ctx->frame_csp - 1)->label_type != LABEL_TYPE_IF
|
|
|
+ /* duplicated else is found */
|
|
|
+ || (loader_ctx->frame_csp - 1)->else_addr) {
|
|
|
set_error_buf(
|
|
|
error_buf, error_buf_size,
|
|
|
"opcode else found without matched opcode if");
|
|
|
@@ -11303,8 +11389,8 @@ re_scan:
|
|
|
bh_memcpy_s(loader_ctx->frame_offset, size,
|
|
|
block->param_frame_offsets, size);
|
|
|
loader_ctx->frame_offset += (size / sizeof(int16));
|
|
|
- loader_ctx->dynamic_offset = block->start_dynamic_offset;
|
|
|
}
|
|
|
+ loader_ctx->dynamic_offset = block->start_dynamic_offset;
|
|
|
#endif
|
|
|
|
|
|
break;
|
|
|
@@ -11450,16 +11536,17 @@ re_scan:
|
|
|
#endif
|
|
|
POP_I32();
|
|
|
|
|
|
- /* Get the default depth and check it */
|
|
|
+ /* Get each depth and check it */
|
|
|
p_org = p;
|
|
|
for (i = 0; i <= count; i++) {
|
|
|
read_leb_uint32(p, p_end, depth);
|
|
|
- }
|
|
|
- if (loader_ctx->csp_num < depth + 1) {
|
|
|
- set_error_buf(error_buf, error_buf_size,
|
|
|
- "unknown label, "
|
|
|
- "unexpected end of section or function");
|
|
|
- goto fail;
|
|
|
+ bh_assert(loader_ctx->csp_num > 0);
|
|
|
+ if (loader_ctx->csp_num - 1 < depth) {
|
|
|
+ set_error_buf(error_buf, error_buf_size,
|
|
|
+ "unknown label, "
|
|
|
+ "unexpected end of section or function");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
}
|
|
|
p = p_org;
|
|
|
|
|
|
@@ -11475,12 +11562,6 @@ re_scan:
|
|
|
for (i = 0; i <= count; i++) {
|
|
|
p_org = p;
|
|
|
read_leb_uint32(p, p_end, depth);
|
|
|
- if (loader_ctx->csp_num < depth + 1) {
|
|
|
- set_error_buf(error_buf, error_buf_size,
|
|
|
- "unknown label, "
|
|
|
- "unexpected end of section or function");
|
|
|
- goto fail;
|
|
|
- }
|
|
|
p = p_org;
|
|
|
|
|
|
/* Get the target block's arity and check it */
|
|
|
@@ -11598,6 +11679,15 @@ re_scan:
|
|
|
if (opcode == WASM_OP_CALL_REF
|
|
|
|| opcode == WASM_OP_RETURN_CALL_REF) {
|
|
|
read_leb_uint32(p, p_end, type_idx1);
|
|
|
+ if (!check_type_index(module, module->type_count, type_idx1,
|
|
|
+ error_buf, error_buf_size)) {
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ if (module->types[type_idx1]->type_flag != WASM_TYPE_FUNC) {
|
|
|
+ set_error_buf(error_buf, error_buf_size,
|
|
|
+ "unkown function type");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
if (!wasm_loader_pop_nullable_typeidx(loader_ctx, &type,
|
|
|
&type_idx, error_buf,
|
|
|
error_buf_size)) {
|
|
|
@@ -11606,8 +11696,8 @@ re_scan:
|
|
|
if (type == VALUE_TYPE_ANY) {
|
|
|
type_idx = type_idx1;
|
|
|
}
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
- error_buf_size)) {
|
|
|
+ if (!check_type_index(module, module->type_count, type_idx,
|
|
|
+ error_buf, error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
if (module->types[type_idx]->type_flag != WASM_TYPE_FUNC) {
|
|
|
@@ -11615,7 +11705,9 @@ re_scan:
|
|
|
"unkown function type");
|
|
|
goto fail;
|
|
|
}
|
|
|
- if (type_idx != type_idx1) {
|
|
|
+ if (!wasm_func_type_is_super_of(
|
|
|
+ (WASMFuncType *)module->types[type_idx1],
|
|
|
+ (WASMFuncType *)module->types[type_idx])) {
|
|
|
set_error_buf(error_buf, error_buf_size,
|
|
|
"function type mismatch");
|
|
|
goto fail;
|
|
|
@@ -11871,8 +11963,7 @@ re_scan:
|
|
|
loader_ctx->reftype_map_num--;
|
|
|
}
|
|
|
#endif
|
|
|
- if (is_32bit_type(*(loader_ctx->frame_ref - 1))
|
|
|
- || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
|
|
|
+ if (is_32bit_type(*(loader_ctx->frame_ref - 1))) {
|
|
|
loader_ctx->frame_ref--;
|
|
|
loader_ctx->stack_cell_num--;
|
|
|
#if WASM_ENABLE_FAST_INTERP != 0
|
|
|
@@ -11950,6 +12041,7 @@ re_scan:
|
|
|
switch (*(loader_ctx->frame_ref - 1)) {
|
|
|
case VALUE_TYPE_I32:
|
|
|
case VALUE_TYPE_F32:
|
|
|
+ case VALUE_TYPE_ANY:
|
|
|
break;
|
|
|
case VALUE_TYPE_I64:
|
|
|
case VALUE_TYPE_F64:
|
|
|
@@ -12055,8 +12147,9 @@ re_scan:
|
|
|
#else
|
|
|
p_org = p + 1;
|
|
|
if (!resolve_value_type((const uint8 **)&p, p_end, module,
|
|
|
- &need_ref_type_map, &wasm_ref_type,
|
|
|
- false, error_buf, error_buf_size)) {
|
|
|
+ module->type_count, &need_ref_type_map,
|
|
|
+ &wasm_ref_type, false, error_buf,
|
|
|
+ error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
type = wasm_ref_type.ref_type;
|
|
|
@@ -12223,8 +12316,8 @@ re_scan:
|
|
|
#else
|
|
|
read_leb_int32(p, p_end, heap_type);
|
|
|
if (heap_type >= 0) {
|
|
|
- if (!check_type_index(module, heap_type, error_buf,
|
|
|
- error_buf_size)) {
|
|
|
+ if (!check_type_index(module, module->type_count, heap_type,
|
|
|
+ error_buf, error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
wasm_set_refheaptype_typeidx(&wasm_ref_type.ref_ht_typeidx,
|
|
|
@@ -12315,33 +12408,58 @@ re_scan:
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- /* Refer to a forward-declared function */
|
|
|
- if (func_idx >= cur_func_idx + module->import_function_count) {
|
|
|
+ /* Refer to a forward-declared function:
|
|
|
+ the function must be an import, exported, or present in
|
|
|
+ a table elem segment or global initializer to be used as
|
|
|
+ the operand to ref.func */
|
|
|
+ if (func_idx >= module->import_function_count) {
|
|
|
WASMTableSeg *table_seg = module->table_segments;
|
|
|
bool func_declared = false;
|
|
|
uint32 j;
|
|
|
|
|
|
- /* Check whether the function is declared in table segs,
|
|
|
- note that it doesn't matter whether the table seg's mode
|
|
|
- is passive, active or declarative. */
|
|
|
- for (i = 0; i < module->table_seg_count; i++, table_seg++) {
|
|
|
- if (table_seg->elem_type == VALUE_TYPE_FUNCREF
|
|
|
-#if WASM_ENABLE_GC != 0
|
|
|
- || (table_seg->elem_type == REF_TYPE_HT_NON_NULLABLE
|
|
|
- && table_seg->elem_ref_type->ref_ht_common
|
|
|
- .heap_type
|
|
|
- == HEAP_TYPE_FUNC)
|
|
|
-#endif
|
|
|
- ) {
|
|
|
- for (j = 0; j < table_seg->value_count; j++) {
|
|
|
- if (table_seg->init_values[j].u.ref_index
|
|
|
- == func_idx) {
|
|
|
- func_declared = true;
|
|
|
- break;
|
|
|
+ for (i = 0; i < module->global_count; i++) {
|
|
|
+ if (module->globals[i].type == VALUE_TYPE_FUNCREF
|
|
|
+ && module->globals[i].init_expr.init_expr_type
|
|
|
+ == INIT_EXPR_TYPE_FUNCREF_CONST
|
|
|
+ && module->globals[i].init_expr.u.u32 == func_idx) {
|
|
|
+ func_declared = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!func_declared) {
|
|
|
+ /* Check whether the function is declared in table segs,
|
|
|
+ note that it doesn't matter whether the table seg's
|
|
|
+ mode is passive, active or declarative. */
|
|
|
+ for (i = 0; i < module->table_seg_count;
|
|
|
+ i++, table_seg++) {
|
|
|
+ if (table_seg->elem_type == VALUE_TYPE_FUNCREF
|
|
|
+#if WASM_ENABLE_GC != 0
|
|
|
+ /* elem type is (ref null? func) or
|
|
|
+ (ref null? $t) */
|
|
|
+ || ((table_seg->elem_type
|
|
|
+ == REF_TYPE_HT_NON_NULLABLE
|
|
|
+ || table_seg->elem_type
|
|
|
+ == REF_TYPE_HT_NULLABLE)
|
|
|
+ && (table_seg->elem_ref_type->ref_ht_common
|
|
|
+ .heap_type
|
|
|
+ == HEAP_TYPE_FUNC
|
|
|
+ || table_seg->elem_ref_type
|
|
|
+ ->ref_ht_common.heap_type
|
|
|
+ > 0))
|
|
|
+#endif
|
|
|
+ ) {
|
|
|
+ for (j = 0; j < table_seg->value_count; j++) {
|
|
|
+ if (table_seg->init_values[j].u.ref_index
|
|
|
+ == func_idx) {
|
|
|
+ func_declared = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if (!func_declared) {
|
|
|
/* Check whether the function is exported */
|
|
|
for (i = 0; i < module->export_count; i++) {
|
|
|
@@ -13288,7 +13406,8 @@ re_scan:
|
|
|
#if WASM_ENABLE_FAST_INTERP != 0
|
|
|
emit_uint32(loader_ctx, type_idx);
|
|
|
#endif
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
+ if (!check_type_index(module, module->type_count,
|
|
|
+ type_idx, error_buf,
|
|
|
error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
@@ -13374,7 +13493,8 @@ re_scan:
|
|
|
#if WASM_ENABLE_FAST_INTERP != 0
|
|
|
emit_uint32(loader_ctx, type_idx);
|
|
|
#endif
|
|
|
- if (!check_type_index(module, type_idx, error_buf,
|
|
|
+ if (!check_type_index(module, module->type_count,
|
|
|
+ type_idx, error_buf,
|
|
|
error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|
|
|
@@ -13787,7 +13907,8 @@ re_scan:
|
|
|
emit_uint32(loader_ctx, (uint32)heap_type);
|
|
|
#endif
|
|
|
if (heap_type >= 0) {
|
|
|
- if (!check_type_index(module, heap_type, error_buf,
|
|
|
+ if (!check_type_index(module, module->type_count,
|
|
|
+ heap_type, error_buf,
|
|
|
error_buf_size)) {
|
|
|
goto fail;
|
|
|
}
|