Support extended constant expressions (#4432)

* implement extended const expr (#4318)
* add a toggle to enable extended const on wamrc (#4412)
This commit is contained in:
TianlongLiang
2025-07-07 13:34:02 +08:00
committed by GitHub
parent be33a40ba7
commit 7d05dbc988
28 changed files with 1734 additions and 379 deletions

View File

@ -968,6 +968,35 @@ fail:
return false;
}
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
static void
destroy_init_expr(InitializerExpression *expr)
{
#if WASM_ENABLE_GC != 0
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
wasm_runtime_free(expr->u.unary.v.data);
}
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
// free left expr and right expr for binary oprand
if (!is_expr_binary_op(expr->init_expr_type)) {
return;
}
if (expr->u.binary.l_expr) {
destroy_init_expr_recursive(expr->u.binary.l_expr);
}
if (expr->u.binary.r_expr) {
destroy_init_expr_recursive(expr->u.binary.r_expr);
}
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
#endif
}
#endif /* end of WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0 \
*/
static void
destroy_import_memories(AOTImportMemory *import_memories)
{
@ -993,6 +1022,10 @@ destroy_mem_init_data_list(AOTModule *module, AOTMemInitData **data_list,
/* If the module owns the binary data, free the bytes buffer */
if (module->is_binary_freeable && data_list[i]->bytes)
wasm_runtime_free(data_list[i]->bytes);
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(&data_list[i]->offset);
#endif
/* Free the data segment structure itself */
wasm_runtime_free(data_list[i]);
}
@ -1043,11 +1076,11 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
uint32 byte_count;
uint32 is_passive;
uint32 memory_index;
InitializerExpression init_value;
InitializerExpression offset_expr;
read_uint32(buf, buf_end, is_passive);
read_uint32(buf, buf_end, memory_index);
if (!load_init_expr(&buf, buf_end, module, &init_value, error_buf,
if (!load_init_expr(&buf, buf_end, module, &offset_expr, error_buf,
error_buf_size)) {
return false;
}
@ -1062,8 +1095,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
data_list[i]->is_passive = (bool)is_passive;
data_list[i]->memory_index = memory_index;
#endif
data_list[i]->offset.init_expr_type = init_value.init_expr_type;
data_list[i]->offset.u = init_value.u;
data_list[i]->offset = offset_expr;
data_list[i]->byte_count = byte_count;
data_list[i]->bytes = NULL;
/* If the module owns the binary data, clone the bytes buffer */
@ -1148,18 +1180,6 @@ fail:
return false;
}
#if WASM_ENABLE_GC != 0
static void
destroy_init_expr(InitializerExpression *expr)
{
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
wasm_runtime_free(expr->u.data);
}
}
#endif /* end of WASM_ENABLE_GC != 0 */
static void
destroy_import_tables(AOTImportTable *import_tables)
{
@ -1183,6 +1203,9 @@ destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
for (j = 0; j < data_list[i]->value_count; j++) {
destroy_init_expr(&data_list[i]->init_values[j]);
}
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(&data_list[i]->offset);
#endif
wasm_runtime_free(data_list[i]);
}
@ -1208,34 +1231,34 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
break;
case INIT_EXPR_TYPE_I32_CONST:
case INIT_EXPR_TYPE_F32_CONST:
read_uint32(buf, buf_end, expr->u.i32);
read_uint32(buf, buf_end, expr->u.unary.v.i32);
break;
case INIT_EXPR_TYPE_I64_CONST:
case INIT_EXPR_TYPE_F64_CONST:
read_uint64(buf, buf_end, expr->u.i64);
read_uint64(buf, buf_end, expr->u.unary.v.i64);
break;
case INIT_EXPR_TYPE_V128_CONST:
i64x2 = (uint64 *)expr->u.v128.i64x2;
i64x2 = (uint64 *)expr->u.unary.v.v128.i64x2;
CHECK_BUF(buf, buf_end, sizeof(uint64) * 2);
wasm_runtime_read_v128(buf, &i64x2[0], &i64x2[1]);
buf += sizeof(uint64) * 2;
break;
case INIT_EXPR_TYPE_GET_GLOBAL:
read_uint32(buf, buf_end, expr->u.global_index);
read_uint32(buf, buf_end, expr->u.unary.v.global_index);
break;
/* INIT_EXPR_TYPE_FUNCREF_CONST can be used when
both reference types and GC are disabled */
case INIT_EXPR_TYPE_FUNCREF_CONST:
read_uint32(buf, buf_end, expr->u.ref_index);
read_uint32(buf, buf_end, expr->u.unary.v.ref_index);
break;
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0
case INIT_EXPR_TYPE_REFNULL_CONST:
read_uint32(buf, buf_end, expr->u.ref_index);
read_uint32(buf, buf_end, expr->u.unary.v.ref_index);
break;
#endif /* end of WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0 */
#if WASM_ENABLE_GC != 0
case INIT_EXPR_TYPE_I31_NEW:
read_uint32(buf, buf_end, expr->u.i32);
read_uint32(buf, buf_end, expr->u.unary.v.i32);
break;
case INIT_EXPR_TYPE_STRUCT_NEW:
{
@ -1256,7 +1279,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
free_if_fail = true;
init_values->count = field_count;
init_values->type_idx = type_idx;
expr->u.data = init_values;
expr->u.unary.v.data = init_values;
if (type_idx >= module->type_count) {
set_error_buf(error_buf, error_buf_size,
@ -1294,7 +1317,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
break;
}
case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
read_uint32(buf, buf_end, expr->u.type_index);
read_uint32(buf, buf_end, expr->u.unary.v.type_index);
break;
case INIT_EXPR_TYPE_ARRAY_NEW:
case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
@ -1317,8 +1340,8 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
}
if (init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
expr->u.array_new_default.type_index = type_idx;
expr->u.array_new_default.length = length;
expr->u.unary.v.array_new_default.type_index = type_idx;
expr->u.unary.v.array_new_default.length = length;
}
else {
uint32 i, elem_size, elem_data_count;
@ -1329,7 +1352,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
return false;
}
free_if_fail = true;
expr->u.data = init_values;
expr->u.unary.v.data = init_values;
init_values->type_idx = type_idx;
init_values->length = length;
@ -1357,6 +1380,34 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
break;
}
#endif /* end of WASM_ENABLE_GC != 0 */
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
case INIT_EXPR_TYPE_I32_ADD:
case INIT_EXPR_TYPE_I32_SUB:
case INIT_EXPR_TYPE_I32_MUL:
case INIT_EXPR_TYPE_I64_ADD:
case INIT_EXPR_TYPE_I64_SUB:
case INIT_EXPR_TYPE_I64_MUL:
{
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
if (!(expr->u.binary.l_expr =
loader_malloc(sizeof(InitializerExpression), error_buf,
error_buf_size))) {
goto fail;
}
if (!load_init_expr(&buf, buf_end, module, expr->u.binary.l_expr,
error_buf, error_buf_size))
goto fail;
if (!(expr->u.binary.r_expr =
loader_malloc(sizeof(InitializerExpression), error_buf,
error_buf_size))) {
goto fail;
}
if (!load_init_expr(&buf, buf_end, module, expr->u.binary.r_expr,
error_buf, error_buf_size))
goto fail;
break;
}
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
default:
set_error_buf(error_buf, error_buf_size, "invalid init expr type.");
return false;
@ -1369,10 +1420,13 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
fail:
#if WASM_ENABLE_GC != 0
if (free_if_fail) {
wasm_runtime_free(expr->u.data);
wasm_runtime_free(expr->u.unary.v.data);
}
#else
(void)free_if_fail;
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(expr);
#endif
return false;
}
@ -1535,14 +1589,16 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
/* Create each table data segment */
for (i = 0; i < module->table_init_data_count; i++) {
uint32 mode, elem_type;
uint32 table_index, init_expr_type, value_count;
uint64 init_expr_value, size1;
uint32 table_index, value_count;
uint64 size1;
InitializerExpression offset_expr;
read_uint32(buf, buf_end, mode);
read_uint32(buf, buf_end, elem_type);
read_uint32(buf, buf_end, table_index);
read_uint32(buf, buf_end, init_expr_type);
read_uint64(buf, buf_end, init_expr_value);
if (!load_init_expr(&buf, buf_end, module, &offset_expr, error_buf,
error_buf_size))
return false;
#if WASM_ENABLE_GC != 0
if (wasm_is_type_multi_byte_type(elem_type)) {
uint16 ref_type, nullable;
@ -1588,8 +1644,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
}
}
#endif
data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
data_list[i]->offset.u.i64 = (int64)init_expr_value;
data_list[i]->offset = offset_expr;
data_list[i]->value_count = value_count;
for (j = 0; j < data_list[i]->value_count; j++) {
if (!load_init_expr(&buf, buf_end, module,
@ -4500,7 +4555,7 @@ aot_unload(AOTModule *module)
destroy_import_globals(module->import_globals);
if (module->globals) {
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
uint32 i;
for (i = 0; i < module->global_count; i++) {
destroy_init_expr(&module->globals[i].init_expr);

View File

@ -289,18 +289,21 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
switch (flag) {
case INIT_EXPR_TYPE_GET_GLOBAL:
{
if (!check_global_init_expr(module, init_expr->u.global_index,
if (!check_global_init_expr(module,
init_expr->u.unary.v.global_index,
error_buf, error_buf_size)) {
return false;
}
if (init_expr->u.global_index < module->import_global_count) {
if (init_expr->u.unary.v.global_index
< module->import_global_count) {
PUT_REF_TO_ADDR(
addr, module->import_globals[init_expr->u.global_index]
.global_data_linked.gc_obj);
addr,
module->import_globals[init_expr->u.unary.v.global_index]
.global_data_linked.gc_obj);
}
else {
uint32 global_idx =
init_expr->u.global_index - module->import_global_count;
uint32 global_idx = init_expr->u.unary.v.global_index
- module->import_global_count;
return assign_table_init_value(
module_inst, module, &module->globals[global_idx].init_expr,
addr, error_buf, error_buf_size);
@ -316,7 +319,7 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
case INIT_EXPR_TYPE_FUNCREF_CONST:
{
WASMFuncObjectRef func_obj = NULL;
uint32 func_idx = init_expr->u.u32;
uint32 func_idx = init_expr->u.unary.v.u32;
if (func_idx != UINT32_MAX) {
if (!(func_obj =
@ -331,7 +334,8 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
}
case INIT_EXPR_TYPE_I31_NEW:
{
WASMI31ObjectRef i31_obj = wasm_i31_obj_new(init_expr->u.i32);
WASMI31ObjectRef i31_obj =
wasm_i31_obj_new(init_expr->u.unary.v.i32);
PUT_REF_TO_ADDR(addr, i31_obj);
break;
}
@ -345,11 +349,12 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
uint32 type_idx;
if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
init_values = (WASMStructNewInitValues *)init_expr->u.data;
init_values =
(WASMStructNewInitValues *)init_expr->u.unary.v.data;
type_idx = init_values->type_idx;
}
else {
type_idx = init_expr->u.type_index;
type_idx = init_expr->u.unary.v.type_index;
}
struct_type = (WASMStructType *)module->types[type_idx];
@ -398,12 +403,13 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
uint32 type_idx, len;
if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
type_idx = init_expr->u.array_new_default.type_index;
len = init_expr->u.array_new_default.length;
type_idx = init_expr->u.unary.v.array_new_default.type_index;
len = init_expr->u.unary.v.array_new_default.length;
arr_init_val = &empty_val;
}
else {
init_values = (WASMArrayNewInitValues *)init_expr->u.data;
init_values =
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
type_idx = init_values->type_idx;
len = init_values->length;
@ -454,6 +460,90 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
}
#endif /* end of WASM_ENABLE_GC != 0 */
static bool
get_init_value_recursive(AOTModuleInstance *module_inst, AOTModule *module,
InitializerExpression *expr, WASMValue *value,
char *error_buf, uint32 error_buf_size)
{
uint8 flag = expr->init_expr_type;
switch (flag) {
case INIT_EXPR_TYPE_GET_GLOBAL:
{
if (!check_global_init_expr(module, expr->u.unary.v.global_index,
error_buf, error_buf_size)) {
return false;
}
#if WASM_ENABLE_GC == 0
*value = module->import_globals[expr->u.unary.v.global_index]
.global_data_linked;
#else
if (expr->u.unary.v.global_index < module->import_global_count) {
*value = module->import_globals[expr->u.unary.v.global_index]
.global_data_linked;
}
else {
*value = module
->globals[expr->u.unary.v.global_index
- module->import_global_count]
.init_expr.u.unary.v;
}
#endif
break;
}
case INIT_EXPR_TYPE_I32_CONST:
case INIT_EXPR_TYPE_I64_CONST:
{
*value = expr->u.unary.v;
break;
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
case INIT_EXPR_TYPE_I32_ADD:
case INIT_EXPR_TYPE_I32_SUB:
case INIT_EXPR_TYPE_I32_MUL:
case INIT_EXPR_TYPE_I64_ADD:
case INIT_EXPR_TYPE_I64_SUB:
case INIT_EXPR_TYPE_I64_MUL:
{
WASMValue l_value, r_value;
if (!get_init_value_recursive(module_inst, module,
expr->u.binary.l_expr, &l_value,
error_buf, error_buf_size)) {
return false;
}
if (!get_init_value_recursive(module_inst, module,
expr->u.binary.r_expr, &r_value,
error_buf, error_buf_size)) {
return false;
}
if (flag == INIT_EXPR_TYPE_I32_ADD) {
value->i32 = l_value.i32 + r_value.i32;
}
else if (flag == INIT_EXPR_TYPE_I32_SUB) {
value->i32 = l_value.i32 - r_value.i32;
}
else if (flag == INIT_EXPR_TYPE_I32_MUL) {
value->i32 = l_value.i32 * r_value.i32;
}
else if (flag == INIT_EXPR_TYPE_I64_ADD) {
value->i64 = l_value.i64 + r_value.i64;
}
else if (flag == INIT_EXPR_TYPE_I64_SUB) {
value->i64 = l_value.i64 - r_value.i64;
}
else if (flag == INIT_EXPR_TYPE_I64_MUL) {
value->i64 = l_value.i64 * r_value.i64;
}
break;
}
#endif
default:
return false;
}
return true;
}
static bool
global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
char *error_buf, uint32 error_buf_size)
@ -482,30 +572,24 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
flag = init_expr->init_expr_type;
switch (flag) {
case INIT_EXPR_TYPE_GET_GLOBAL:
case INIT_EXPR_TYPE_I32_CONST:
case INIT_EXPR_TYPE_I64_CONST:
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
case INIT_EXPR_TYPE_I32_ADD:
case INIT_EXPR_TYPE_I32_SUB:
case INIT_EXPR_TYPE_I32_MUL:
case INIT_EXPR_TYPE_I64_ADD:
case INIT_EXPR_TYPE_I64_SUB:
case INIT_EXPR_TYPE_I64_MUL:
#endif
{
if (!check_global_init_expr(module, init_expr->u.global_index,
error_buf, error_buf_size)) {
WASMValue value;
if (!get_init_value_recursive(module_inst, module, init_expr,
&value, error_buf,
error_buf_size)) {
return false;
}
#if WASM_ENABLE_GC == 0
init_global_data(
p, global->type.val_type,
&module->import_globals[init_expr->u.global_index]
.global_data_linked);
#else
if (init_expr->u.global_index < module->import_global_count) {
init_global_data(
p, global->type.val_type,
&module->import_globals[init_expr->u.global_index]
.global_data_linked);
}
else {
uint32 global_idx =
init_expr->u.global_index - module->import_global_count;
init_global_data(p, global->type.val_type,
&module->globals[global_idx].init_expr.u);
}
#endif
init_global_data(p, global->type.val_type, &value);
break;
}
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
@ -526,7 +610,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
case INIT_EXPR_TYPE_FUNCREF_CONST:
{
WASMFuncObjectRef func_obj = NULL;
uint32 func_idx = init_expr->u.u32;
uint32 func_idx = init_expr->u.unary.v.ref_index;
if (func_idx != UINT32_MAX) {
if (!(func_obj =
@ -541,7 +625,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
}
case INIT_EXPR_TYPE_I31_NEW:
{
WASMI31ObjectRef i31_obj = wasm_i31_obj_new(init_expr->u.i32);
WASMI31ObjectRef i31_obj =
wasm_i31_obj_new(init_expr->u.unary.v.i32);
PUT_REF_TO_ADDR(p, i31_obj);
break;
}
@ -555,11 +640,12 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
uint32 type_idx;
if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
init_values = (WASMStructNewInitValues *)init_expr->u.data;
init_values =
(WASMStructNewInitValues *)init_expr->u.unary.v.data;
type_idx = init_values->type_idx;
}
else {
type_idx = init_expr->u.type_index;
type_idx = init_expr->u.unary.v.type_index;
}
struct_type = (WASMStructType *)module->types[type_idx];
@ -609,12 +695,14 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
uint32 type_idx, len;
if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
type_idx = init_expr->u.array_new_default.type_index;
len = init_expr->u.array_new_default.length;
type_idx =
init_expr->u.unary.v.array_new_default.type_index;
len = init_expr->u.unary.v.array_new_default.length;
arr_init_val = &empty_val;
}
else {
init_values = (WASMArrayNewInitValues *)init_expr->u.data;
init_values =
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
type_idx = init_values->type_idx;
len = init_values->length;
@ -660,7 +748,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
#endif /* end of WASM_ENABLE_GC != 0 */
default:
{
init_global_data(p, global->type.val_type, &init_expr->u);
init_global_data(p, global->type.val_type,
&init_expr->u.unary.v);
break;
}
}
@ -681,6 +770,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
uint64 total_size;
AOTTableInitData *table_seg;
AOTTableInstance *tbl_inst = first_tbl_inst;
uint8 offset_flag;
total_size = (uint64)sizeof(AOTTableInstance *) * module_inst->table_count;
if (total_size > 0
@ -753,28 +843,25 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
tbl_inst = module_inst->tables[table_seg->table_index];
bh_assert(tbl_inst);
offset_flag = table_seg->offset.init_expr_type;
#if WASM_ENABLE_REF_TYPES != 0
bh_assert(
table_seg->offset.init_expr_type
== (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
: INIT_EXPR_TYPE_I32_CONST)
|| table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
|| table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
|| table_seg->offset.init_expr_type
== INIT_EXPR_TYPE_REFNULL_CONST);
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|| offset_flag == INIT_EXPR_TYPE_FUNCREF_CONST
|| offset_flag == INIT_EXPR_TYPE_REFNULL_CONST
|| (tbl_inst->is_table64 ? is_valid_i64_offset(offset_flag)
: is_valid_i32_offset(offset_flag)));
#else
bh_assert(table_seg->offset.init_expr_type
== (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
: INIT_EXPR_TYPE_I32_CONST)
|| table_seg->offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL);
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|| (tbl_inst->is_table64 ? is_valid_i64_offset(offset_flag)
: is_valid_i32_offset(offset_flag)));
#endif
/* Resolve table data base offset */
/* TODO: The table64 current implementation assumes table max size
* UINT32_MAX, so the offset conversion here is safe */
if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
global_index = table_seg->offset.u.global_index;
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
global_index = table_seg->offset.u.unary.v.global_index;
if (!check_global_init_expr(module, global_index, error_buf,
error_buf_size)) {
@ -792,8 +879,15 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
base_offset =
*(uint32 *)(module_inst->global_data + global_data_offset);
}
else
base_offset = (uint32)table_seg->offset.u.i32;
else {
WASMValue offset_value;
if (!get_init_value_recursive(module_inst, module,
&table_seg->offset, &offset_value,
error_buf, error_buf_size)) {
return false;
}
base_offset = (uint32)offset_value.i32;
}
/* Copy table data */
/* base_offset only since length might negative */
@ -828,7 +922,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
#if WASM_ENABLE_GC == 0
for (j = 0; j < length; j++) {
tbl_inst->elems[base_offset + j] =
table_seg->init_values[j].u.ref_index;
table_seg->init_values[j].u.unary.v.ref_index;
}
#endif
}
@ -1128,6 +1222,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
AOTMemInitData *data_seg;
uint64 total_size;
mem_offset_t base_offset;
uint8 offset_flag;
module_inst->memory_count = memory_count;
total_size = sizeof(AOTMemoryInstance *) * (uint64)memory_count;
@ -1166,15 +1261,15 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
initialized */
continue;
bh_assert(data_seg->offset.init_expr_type
== (memory_inst->is_memory64 ? INIT_EXPR_TYPE_I64_CONST
: INIT_EXPR_TYPE_I32_CONST)
|| data_seg->offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL);
offset_flag = data_seg->offset.init_expr_type;
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|| (memory_inst->is_memory64
? is_valid_i64_offset(offset_flag)
: is_valid_i32_offset(offset_flag)));
/* Resolve memory data base offset */
if (data_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
global_index = data_seg->offset.u.global_index;
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
global_index = data_seg->offset.u.unary.v.global_index;
if (!check_global_init_expr(module, global_index, error_buf,
error_buf_size)) {
@ -1202,14 +1297,20 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
}
}
else {
WASMValue offset_value;
if (!get_init_value_recursive(module_inst, module,
&data_seg->offset, &offset_value,
error_buf, error_buf_size)) {
return false;
}
#if WASM_ENABLE_MEMORY64 != 0
if (memory_inst->is_memory64) {
base_offset = data_seg->offset.u.i64;
base_offset = offset_value.i64;
}
else
#endif
{
base_offset = data_seg->offset.u.u32;
base_offset = offset_value.u32;
}
}
@ -2055,6 +2156,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
uint8 tbl_elem_type;
uint32 tbl_init_size, tbl_max_size, j;
WASMRefType *tbl_elem_ref_type;
WASMValue offset_value;
bh_assert(table_init_data);
@ -2086,69 +2188,73 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
if (!wasm_elem_is_active(table_init_data->mode)) {
continue;
}
bh_assert(table_init_data->offset.init_expr_type
== INIT_EXPR_TYPE_I32_CONST
|| table_init_data->offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL
|| table_init_data->offset.init_expr_type
== INIT_EXPR_TYPE_FUNCREF_CONST
|| table_init_data->offset.init_expr_type
== INIT_EXPR_TYPE_REFNULL_CONST);
uint8 offset_flag = table_init_data->offset.init_expr_type;
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|| offset_flag == INIT_EXPR_TYPE_FUNCREF_CONST
|| offset_flag == INIT_EXPR_TYPE_REFNULL_CONST
|| offset_flag == INIT_EXPR_TYPE_I32_CONST
|| offset_flag == INIT_EXPR_TYPE_I32_ADD
|| offset_flag == INIT_EXPR_TYPE_I32_SUB
|| offset_flag == INIT_EXPR_TYPE_I32_MUL);
/* init vec(funcidx) or vec(expr) */
if (table_init_data->offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL) {
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
uint32 data_offset;
if (!check_global_init_expr(module,
table_init_data->offset.u.global_index,
error_buf, error_buf_size)) {
if (!check_global_init_expr(
module, table_init_data->offset.u.unary.v.global_index,
error_buf, error_buf_size)) {
goto fail;
}
if (table_init_data->offset.u.global_index
if (table_init_data->offset.u.unary.v.global_index
< module->import_global_count) {
data_offset =
module
->import_globals[table_init_data->offset.u.global_index]
.data_offset;
data_offset = module
->import_globals[table_init_data->offset.u
.unary.v.global_index]
.data_offset;
}
else {
data_offset =
module
->globals[table_init_data->offset.u.global_index
->globals[table_init_data->offset.u.unary.v.global_index
- module->import_global_count]
.data_offset;
}
table_init_data->offset.u.i32 =
offset_value.i32 =
*(uint32 *)(module_inst->global_data + data_offset);
}
else {
if (!get_init_value_recursive(
module_inst, module, &table_init_data->offset,
&offset_value, error_buf, error_buf_size)) {
goto fail;
}
}
/* check offset since length might negative */
if ((uint32)table_init_data->offset.u.i32 > table->cur_size) {
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)",
table_init_data->offset.u.i32, table->cur_size);
if ((uint32)offset_value.i32 > table->cur_size) {
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)", offset_value.i32,
table->cur_size);
set_error_buf(error_buf, error_buf_size,
"out of bounds table access");
goto fail;
}
if ((uint32)table_init_data->offset.u.i32 + table_init_data->value_count
if ((uint32)offset_value.i32 + table_init_data->value_count
> table->cur_size) {
LOG_DEBUG("base_offset(%d) + length(%d) > table->cur_size(%d)",
table_init_data->offset.u.i32,
table_init_data->value_count, table->cur_size);
offset_value.i32, table_init_data->value_count,
table->cur_size);
set_error_buf(error_buf, error_buf_size,
"out of bounds table access");
goto fail;
}
for (j = 0; j < module->table_init_data_list[i]->value_count; j++) {
if (!assign_table_init_value(
module_inst, module, &table_init_data->init_values[j],
table_data + table_init_data->offset.u.i32 + j, error_buf,
error_buf_size)) {
if (!assign_table_init_value(module_inst, module,
&table_init_data->init_values[j],
table_data + offset_value.i32 + j,
error_buf, error_buf_size)) {
goto fail;
}
}
@ -3741,10 +3847,10 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
for (i = 0; i < length; i++) {
#if WASM_ENABLE_GC != 0
/* UINT32_MAX indicates that it is a null ref */
if (init_values[i].u.ref_index != UINT32_MAX) {
if (!(func_obj = aot_create_func_obj(module_inst,
init_values[i].u.ref_index,
true, NULL, 0))) {
if (init_values[i].u.unary.v.ref_index != UINT32_MAX) {
if (!(func_obj = aot_create_func_obj(
module_inst, init_values[i].u.unary.v.ref_index, true,
NULL, 0))) {
aot_set_exception_with_id(module_inst, EXCE_NULL_FUNC_OBJ);
return;
}
@ -3754,7 +3860,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
table_elems[i] = NULL_REF;
}
#else
table_elems[i] = init_values[i].u.ref_index;
table_elems[i] = init_values[i].u.unary.v.ref_index;
#endif
}
}