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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 1734 additions and 379 deletions

View File

@ -69,6 +69,7 @@ env:
GC_TEST_OPTIONS: "-s spec -G -b -P"
MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
MULTI_MEMORY_TEST_OPTIONS: "-s spec -E -b -P"
EXTENDED_CONST_EXPR_TEST_OPTIONS: "-s spec -N -b -P"
permissions:
contents: read
@ -164,6 +165,7 @@ jobs:
"-DWAMR_BUILD_MEMORY64=1",
"-DWAMR_BUILD_MULTI_MEMORY=1",
"-DWAMR_BUILD_SHARED=1",
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
]
os: [ubuntu-22.04]
platform: [android, linux]
@ -609,6 +611,7 @@ jobs:
$GC_TEST_OPTIONS,
$MEMORY64_TEST_OPTIONS,
$MULTI_MEMORY_TEST_OPTIONS,
$EXTENDED_CONST_EXPR_TEST_OPTIONS,
]
include:
- os: ubuntu-22.04

View File

@ -142,6 +142,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
]
os: [macos-13]
platform: [darwin]

View File

@ -100,6 +100,7 @@ jobs:
"-DWAMR_BUILD_MULTI_MODULE=1",
"-DWAMR_BUILD_PERF_PROFILING=1",
"-DWAMR_BUILD_REF_TYPES=1",
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
# doesn't support
"-DWAMR_BUILD_SIMD=0",
"-DWAMR_BUILD_TAIL_CALL=1",

View File

@ -37,6 +37,7 @@ env:
MULTI_TIER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
# For Spec Test
DEFAULT_TEST_OPTIONS: "-s spec -b -P"
EXTENDED_CONST_EXPR_TEST_OPTIONS: "-s spec -b -P -N"
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -P -M"
SIMD_TEST_OPTIONS: "-s spec -b -P -S"
THREADS_TEST_OPTIONS: "-s spec -b -P -p"
@ -128,6 +129,7 @@ jobs:
"-DWAMR_BUILD_MEMORY64=1",
"-DWAMR_BUILD_MULTI_MEMORY=1",
"-DWAMR_BUILD_SHARED=1",
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
]
os: [ubuntu-22.04]
platform: [android, linux]
@ -588,6 +590,7 @@ jobs:
$DEFAULT_TEST_OPTIONS,
$MULTI_MODULES_TEST_OPTIONS,
$SIMD_TEST_OPTIONS,
$EXTENDED_CONST_EXPR_TEST_OPTIONS,
$THREADS_TEST_OPTIONS,
$WASI_TEST_OPTIONS,
]

View File

@ -211,6 +211,10 @@ if (NOT DEFINED WAMR_BUILD_TAIL_CALL)
set (WAMR_BUILD_TAIL_CALL 0)
endif ()
if (NOT DEFINED WAMR_BUILD_EXTENDED_CONST_EXPR)
set (WAMR_BUILD_EXTENDED_CONST_EXPR 0)
endif ()
########################################
# Compilation options to marco
########################################
@ -673,7 +677,13 @@ if (WAMR_BUILD_INSTRUCTION_METERING EQUAL 1)
message (" Instruction metering enabled")
add_definitions (-DWASM_ENABLE_INSTRUCTION_METERING=1)
endif ()
if (WAMR_BUILD_EXTENDED_CONST_EXPR EQUAL 1)
message (" Extended constant expression enabled")
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=1)
else()
message (" Extended constant expression disabled")
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=0)
endif ()
########################################
# Show Phase4 Wasm proposals status.
########################################
@ -687,6 +697,7 @@ message (
" \"WebAssembly C and C++ API\"\n"
" Configurable. 0 is OFF. 1 is ON:\n"
" \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n"
" \"Extended Constant Expressions\" via WAMR_BUILD_EXTENDED_CONST_EXPR: ${WAMR_BUILD_EXTENDED_CONST_EXPR}\n"
" \"Fixed-width SIMD\" via WAMR_BUILD_SIMD: ${WAMR_BUILD_SIMD}\n"
" \"Garbage collection\" via WAMR_BUILD_GC: ${WAMR_BUILD_GC}\n"
" \"Legacy Exception handling\" via WAMR_BUILD_EXCE_HANDLING: ${WAMR_BUILD_EXCE_HANDLING}\n"
@ -701,7 +712,6 @@ message (
" \"Branch Hinting\"\n"
" \"Custom Annotation Syntax in the Text Format\"\n"
" \"Exception handling\"\n"
" \"Extended Constant Expressions\"\n"
" \"Import/Export of Mutable Globals\"\n"
" \"JS String Builtins\"\n"
" \"Relaxed SIMD\"\n"

View File

@ -720,4 +720,8 @@ unless used elsewhere */
#define WASM_ENABLE_INSTRUCTION_METERING 0
#endif
#ifndef WASM_ENABLE_EXTENDED_CONST_EXPR
#define WASM_ENABLE_EXTENDED_CONST_EXPR 0
#endif
#endif /* end of _CONFIG_H_ */

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]
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,
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 = 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
}
}

View File

@ -225,3 +225,18 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
return false;
}
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
void
destroy_init_expr_recursive(InitializerExpression *expr)
{
if (expr == NULL) {
return;
}
if (is_expr_binary_op(expr->init_expr_type)) {
destroy_init_expr_recursive(expr->u.binary.l_expr);
destroy_init_expr_recursive(expr->u.binary.r_expr);
}
wasm_runtime_free(expr);
}
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */

View File

@ -50,6 +50,11 @@ void
wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size,
const char *string, bool is_aot);
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
void
destroy_init_expr_recursive(InitializerExpression *expr);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -216,7 +216,7 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
#if WASM_ENABLE_GC != 0
WASMModule *module = comp_data->wasm_module;
#endif
bh_assert(expr != NULL);
/* + init value size */
switch (expr->init_expr_type) {
case INIT_EXPR_NONE:
@ -248,7 +248,7 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
{
uint32 i;
WASMStructNewInitValues *struct_new_init_values =
(WASMStructNewInitValues *)expr->u.data;
(WASMStructNewInitValues *)expr->u.unary.v.data;
/* type_index + field_count + fields */
size += sizeof(uint32) + sizeof(uint32);
@ -285,7 +285,7 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
{
WASMArrayNewInitValues *array_new_init_values =
(WASMArrayNewInitValues *)expr->u.data;
(WASMArrayNewInitValues *)expr->u.unary.v.data;
WASMArrayType *array_type = NULL;
uint32 value_count;
@ -308,6 +308,21 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
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:
{
size +=
get_init_expr_size(comp_ctx, comp_data, expr->u.binary.l_expr);
size +=
get_init_expr_size(comp_ctx, comp_data, expr->u.binary.r_expr);
break;
}
#endif
default:
bh_assert(0);
}
@ -324,15 +339,16 @@ get_table_init_data_size(AOTCompContext *comp_ctx,
/*
* mode (4 bytes), elem_type (4 bytes)
*
* table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
* bytes)
* table_index(4 bytes)
*/
size = (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32)
+ sizeof(uint64))
size = (uint32)(sizeof(uint32) * 2 + sizeof(uint32))
/* Size of WasmRefType - inner padding (ref type + nullable +
heap_type) */
+ 8;
size += get_init_expr_size(comp_ctx, comp_ctx->comp_data,
&table_init_data->offset);
/* + value count/func index count (4 bytes) + init_values */
size += sizeof(uint32);
for (i = 0; i < table_init_data->value_count; i++) {
@ -1811,6 +1827,10 @@ static bool
aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
AOTCompContext *comp_ctx, InitializerExpression *expr)
{
if (expr == NULL) {
aot_set_last_error("invalid init expr.");
return false;
}
uint32 offset = *p_offset;
#if WASM_ENABLE_GC != 0
WASMModule *module = comp_ctx->comp_data->wasm_module;
@ -1824,31 +1844,31 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
break;
case INIT_EXPR_TYPE_I32_CONST:
case INIT_EXPR_TYPE_F32_CONST:
EMIT_U32(expr->u.i32);
EMIT_U32(expr->u.unary.v.i32);
break;
case INIT_EXPR_TYPE_I64_CONST:
case INIT_EXPR_TYPE_F64_CONST:
EMIT_U64(expr->u.i64);
EMIT_U64(expr->u.unary.v.i64);
break;
case INIT_EXPR_TYPE_V128_CONST:
EMIT_V128(expr->u.v128);
EMIT_V128(expr->u.unary.v.v128);
break;
case INIT_EXPR_TYPE_GET_GLOBAL:
EMIT_U32(expr->u.global_index);
EMIT_U32(expr->u.unary.v.global_index);
break;
case INIT_EXPR_TYPE_FUNCREF_CONST:
case INIT_EXPR_TYPE_REFNULL_CONST:
EMIT_U32(expr->u.ref_index);
EMIT_U32(expr->u.unary.v.ref_index);
break;
#if WASM_ENABLE_GC != 0
case INIT_EXPR_TYPE_I31_NEW:
EMIT_U32(expr->u.i32);
EMIT_U32(expr->u.unary.v.i32);
break;
case INIT_EXPR_TYPE_STRUCT_NEW:
{
uint32 i;
WASMStructNewInitValues *init_values =
(WASMStructNewInitValues *)expr->u.data;
(WASMStructNewInitValues *)expr->u.unary.v.data;
WASMStructType *struct_type = NULL;
EMIT_U32(init_values->type_idx);
@ -1879,7 +1899,7 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
break;
}
case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
EMIT_U32(expr->u.type_index);
EMIT_U32(expr->u.unary.v.type_index);
break;
case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
{
@ -1889,11 +1909,11 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
< module->type_count);
array_type =
(WASMArrayType *)
module->types[expr->u.array_new_default.type_index];
module->types[expr->u.unary.v.array_new_default.type_index];
EMIT_U32(array_type->elem_type);
EMIT_U32(expr->u.array_new_default.type_index);
EMIT_U32(expr->u.array_new_default.length);
EMIT_U32(expr->u.unary.v.array_new_default.type_index);
EMIT_U32(expr->u.unary.v.array_new_default.length);
break;
}
case INIT_EXPR_TYPE_ARRAY_NEW:
@ -1901,7 +1921,7 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
{
uint32 value_count, i, field_size;
WASMArrayNewInitValues *init_values =
(WASMArrayNewInitValues *)expr->u.data;
(WASMArrayNewInitValues *)expr->u.unary.v.data;
WASMArrayType *array_type = NULL;
bh_assert(init_values->type_idx < module->type_count);
@ -1933,6 +1953,25 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
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:
if (comp_ctx->enable_extended_const) {
if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
expr->u.binary.l_expr)) {
return false;
}
if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
expr->u.binary.r_expr)) {
return false;
}
}
break;
#endif
default:
aot_set_last_error("invalid init expr type.");
return false;
@ -2034,8 +2073,10 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
EMIT_U32(init_datas[i]->mode);
EMIT_U32(init_datas[i]->elem_type);
EMIT_U32(init_datas[i]->table_index);
EMIT_U32(init_datas[i]->offset.init_expr_type);
EMIT_U64(init_datas[i]->offset.u.i64);
if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
&init_datas[i]->offset))
return false;
#if WASM_ENABLE_GC != 0
if (comp_ctx->enable_gc && init_datas[i]->elem_ref_type) {
EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.ref_type);

View File

@ -2787,6 +2787,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
if (option->enable_shared_chain)
comp_ctx->enable_shared_chain = true;
if (option->enable_extended_const)
comp_ctx->enable_extended_const = true;
comp_ctx->opt_level = option->opt_level;
comp_ctx->size_level = option->size_level;

View File

@ -461,6 +461,9 @@ typedef struct AOTCompContext {
/* Enable LLVM PGO (Profile-Guided Optimization) */
bool enable_llvm_pgo;
/* Enable extended constant expression */
bool enable_extended_const;
/* Treat unknown import function as wasm-c-api import function
and allow to directly invoke it from AOT/JIT code */
bool quick_invoke_c_api_import;

View File

@ -121,7 +121,8 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 seg_idx,
+ dst_offset * sizeof(table_elem_type_t));
init_values = tbl_seg_init_values + src_offset;
for (i = 0; i < len; i++) {
addr[i] = (table_elem_type_t)(uintptr_t)init_values[+i].u.ref_index;
addr[i] =
(table_elem_type_t)(uintptr_t)init_values[+i].u.unary.v.ref_index;
}
return 0;

View File

@ -68,6 +68,7 @@ typedef struct AOTCompOption {
bool enable_ref_types;
bool enable_gc;
bool enable_aux_stack_check;
bool enable_extended_const;
AOTStackFrameType aux_stack_frame_type;
AOTCallStackFeatures call_stack_features;
bool enable_perf_profiling;

View File

@ -135,6 +135,12 @@ typedef void *table_elem_type_t;
#define INIT_EXPR_TYPE_F64_CONST 0x44
#define INIT_EXPR_TYPE_V128_CONST 0xFD
#define INIT_EXPR_TYPE_GET_GLOBAL 0x23
#define INIT_EXPR_TYPE_I32_ADD 0x6A
#define INIT_EXPR_TYPE_I32_SUB 0x6B
#define INIT_EXPR_TYPE_I32_MUL 0x6C
#define INIT_EXPR_TYPE_I64_ADD 0x7C
#define INIT_EXPR_TYPE_I64_SUB 0x7D
#define INIT_EXPR_TYPE_I64_MUL 0x7E
#define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
#define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
#define INIT_EXPR_TYPE_STRUCT_NEW 0xD3
@ -277,9 +283,41 @@ typedef struct InitializerExpression {
/* type of INIT_EXPR_TYPE_XXX, which is an instruction of
constant expression */
uint8 init_expr_type;
WASMValue u;
union {
struct {
WASMValue v;
} unary;
struct {
struct InitializerExpression *l_expr;
struct InitializerExpression *r_expr;
} binary;
} u;
} InitializerExpression;
static inline bool
is_expr_binary_op(uint8 flag)
{
return flag == INIT_EXPR_TYPE_I32_ADD || flag == INIT_EXPR_TYPE_I32_SUB
|| flag == INIT_EXPR_TYPE_I32_MUL || flag == INIT_EXPR_TYPE_I64_ADD
|| flag == INIT_EXPR_TYPE_I64_SUB || flag == INIT_EXPR_TYPE_I64_MUL;
}
/* check if table or data offset is valid for i32 offset */
static inline bool
is_valid_i32_offset(uint8 flag)
{
return flag == INIT_EXPR_TYPE_I32_CONST || flag == INIT_EXPR_TYPE_I32_ADD
|| flag == INIT_EXPR_TYPE_I32_SUB || flag == INIT_EXPR_TYPE_I32_MUL;
}
/* check if table or data offset is valid for i64 offset */
static inline bool
is_valid_i64_offset(uint8 flag)
{
return flag == INIT_EXPR_TYPE_I64_CONST || flag == INIT_EXPR_TYPE_I64_ADD
|| flag == INIT_EXPR_TYPE_I64_SUB || flag == INIT_EXPR_TYPE_I64_MUL;
}
#if WASM_ENABLE_GC != 0
/**
* Reference type of (ref null ht) or (ref ht),

View File

@ -5958,12 +5958,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|| init_values[i].init_expr_type
== INIT_EXPR_TYPE_FUNCREF_CONST);
#if WASM_ENABLE_GC == 0
table_elems[i] =
(table_elem_type_t)init_values[i].u.ref_index;
table_elems[i] = (table_elem_type_t)init_values[i]
.u.unary.v.ref_index;
#else
if (init_values[i].u.ref_index != UINT32_MAX) {
if (init_values[i].u.unary.v.ref_index
!= UINT32_MAX) {
if (!(func_obj = wasm_create_func_obj(
module, init_values[i].u.ref_index,
module,
init_values[i].u.unary.v.ref_index,
true, NULL, 0))) {
goto got_exception;
}

View File

@ -5350,12 +5350,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|| init_values[i].init_expr_type
== INIT_EXPR_TYPE_FUNCREF_CONST);
#if WASM_ENABLE_GC == 0
table_elems[i] =
(table_elem_type_t)init_values[i].u.ref_index;
table_elems[i] = (table_elem_type_t)init_values[i]
.u.unary.v.ref_index;
#else
if (init_values[i].u.ref_index != UINT32_MAX) {
if (init_values[i].u.unary.v.ref_index
!= UINT32_MAX) {
if (!(func_obj = wasm_create_func_obj(
module, init_values[i].u.ref_index,
module,
init_values[i].u.unary.v.ref_index,
true, NULL, 0))) {
goto got_exception;
}

View File

@ -453,6 +453,9 @@ typedef struct InitValue {
WASMRefType ref_type;
#endif
WASMValue value;
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression *expr;
#endif
} InitValue;
typedef struct ConstExprContext {
@ -477,7 +480,11 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
#if WASM_ENABLE_GC != 0
WASMRefType *ref_type, uint8 gc_opcode,
#endif
WASMValue *value, char *error_buf, uint32 error_buf_size)
WASMValue *value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression *expr,
#endif
char *error_buf, uint32 error_buf_size)
{
InitValue *cur_value;
@ -503,6 +510,10 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
cur_value->flag = flag;
cur_value->value = *value;
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
cur_value->expr = expr;
#endif
#if WASM_ENABLE_GC != 0
cur_value->gc_opcode = gc_opcode;
if (wasm_is_type_multi_byte_type(type)) {
@ -587,7 +598,11 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
#if WASM_ENABLE_GC != 0
WASMRefType *ref_type, uint8 *p_gc_opcode,
#endif
WASMValue *p_value, char *error_buf, uint32 error_buf_size)
WASMValue *p_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression **p_expr,
#endif
char *error_buf, uint32 error_buf_size)
{
InitValue *cur_value;
@ -623,7 +638,10 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
if (p_gc_opcode)
*p_gc_opcode = cur_value->gc_opcode;
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
if (p_expr)
*p_expr = cur_value->expr;
#endif
return true;
#if WASM_ENABLE_GC != 0
@ -639,7 +657,7 @@ fail:
}
static void
destroy_const_expr_stack(ConstExprContext *ctx)
destroy_const_expr_stack(ConstExprContext *ctx, bool free_exprs)
{
#if WASM_ENABLE_GC != 0
uint32 i;
@ -654,24 +672,62 @@ destroy_const_expr_stack(ConstExprContext *ctx)
}
}
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
if (free_exprs) {
for (uint32 j = 0; j < ctx->sp; j++) {
if (is_expr_binary_op(ctx->stack[j].expr->init_expr_type)) {
destroy_init_expr_recursive(ctx->stack[j].expr);
ctx->stack[j].expr = NULL;
}
}
}
#endif
if (ctx->stack != ctx->data) {
wasm_runtime_free(ctx->stack);
}
}
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
static void
destroy_init_expr(WASMModule *module, 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) {
destroy_init_expr_data_recursive(module, expr->u.data);
destroy_init_expr_data_recursive(module, expr->u.unary.v.data);
}
}
#endif /* end of WASM_ENABLE_GC != 0 */
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
// free left expr and right exprs 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
/* for init expr
* (data (i32.add (i32.const 0) (i32.sub (i32.const 1) (i32.const 2)))),
* the binary format is
* 0x11: 41 00 ; i32.const 0
* 0x13: 41 01 ; i32.const 1
* 0x15: 41 02 ; i32.const 2
* 0x17: 6b ; i32.sub
* 0x18: 6a ; i32.add
* for traversal: read opcodes and push them onto the stack. When encountering
* a binary opcode, pop two values from the stack which become the left and
* right child nodes of this binary operation node.
*/
static bool
load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
InitializerExpression *init_expr, uint8 type, void *ref_type,
@ -687,6 +743,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
uint8 opcode;
WASMRefType cur_ref_type = { 0 };
#endif
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression *cur_expr = NULL;
#endif
init_const_expr_stack(&const_expr_ctx, module);
@ -699,24 +758,32 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
case INIT_EXPR_TYPE_I32_CONST:
read_leb_int32(p, p_end, cur_value.i32);
if (!push_const_expr_stack(
&const_expr_ctx, flag, VALUE_TYPE_I32,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_I32,
#if WASM_ENABLE_GC != 0
NULL, 0,
#endif
&cur_value, error_buf, error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
break;
/* i64.const */
case INIT_EXPR_TYPE_I64_CONST:
read_leb_int64(p, p_end, cur_value.i64);
if (!push_const_expr_stack(
&const_expr_ctx, flag, VALUE_TYPE_I64,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_I64,
#if WASM_ENABLE_GC != 0
NULL, 0,
#endif
&cur_value, error_buf, error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
break;
/* f32.const */
@ -726,12 +793,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
for (i = 0; i < sizeof(float32); i++)
*p_float++ = *p++;
if (!push_const_expr_stack(
&const_expr_ctx, flag, VALUE_TYPE_F32,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_F32,
#if WASM_ENABLE_GC != 0
NULL, 0,
#endif
&cur_value, error_buf, error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
break;
/* f64.const */
@ -741,12 +812,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
for (i = 0; i < sizeof(float64); i++)
*p_float++ = *p++;
if (!push_const_expr_stack(
&const_expr_ctx, flag, VALUE_TYPE_F64,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_F64,
#if WASM_ENABLE_GC != 0
NULL, 0,
#endif
&cur_value, error_buf, error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
break;
#if WASM_ENABLE_SIMD != 0
@ -767,12 +842,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
cur_value.v128.i64x2[0] = high;
cur_value.v128.i64x2[1] = low;
if (!push_const_expr_stack(
&const_expr_ctx, flag, VALUE_TYPE_V128,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_V128,
#if WASM_ENABLE_GC != 0
NULL, 0,
#endif
&cur_value, error_buf, error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
#if WASM_ENABLE_WAMR_COMPILER != 0
/* If any init_expr is v128.const, mark SIMD used */
@ -783,7 +862,92 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
(WASM_ENABLE_FAST_INTERP != 0) */
#endif /* end of WASM_ENABLE_SIMD */
#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:
{
InitializerExpression *l_expr, *r_expr;
WASMValue l_value, r_value;
uint8 l_flag, r_flag;
uint8 value_type;
if (flag == INIT_EXPR_TYPE_I32_ADD
|| flag == INIT_EXPR_TYPE_I32_SUB
|| flag == INIT_EXPR_TYPE_I32_MUL) {
value_type = VALUE_TYPE_I32;
}
else {
value_type = VALUE_TYPE_I64;
}
/* If right flag indicates a binary operation, right expr will
* be popped from stack. Otherwise, allocate a new expr for
* right expr. Same for left expr.
*/
if (!(pop_const_expr_stack(&const_expr_ctx, &r_flag, value_type,
#if WASM_ENABLE_GC != 0
NULL, NULL,
#endif
&r_value, &r_expr, error_buf,
error_buf_size))) {
goto fail;
}
if (!is_expr_binary_op(r_flag)) {
if (!(r_expr = loader_malloc(sizeof(InitializerExpression),
error_buf, error_buf_size))) {
goto fail;
}
r_expr->init_expr_type = r_flag;
r_expr->u.unary.v = r_value;
}
if (!(pop_const_expr_stack(&const_expr_ctx, &l_flag, value_type,
#if WASM_ENABLE_GC != 0
NULL, NULL,
#endif
&l_value, &l_expr, error_buf,
error_buf_size))) {
destroy_init_expr_recursive(r_expr);
goto fail;
}
if (!is_expr_binary_op(l_flag)) {
if (!(l_expr = loader_malloc(sizeof(InitializerExpression),
error_buf, error_buf_size))) {
destroy_init_expr_recursive(r_expr);
goto fail;
}
l_expr->init_expr_type = l_flag;
l_expr->u.unary.v = l_value;
}
if (!(cur_expr = loader_malloc(sizeof(InitializerExpression),
error_buf, error_buf_size))) {
destroy_init_expr_recursive(l_expr);
destroy_init_expr_recursive(r_expr);
goto fail;
}
cur_expr->init_expr_type = flag;
cur_expr->u.binary.l_expr = l_expr;
cur_expr->u.binary.r_expr = r_expr;
if (!push_const_expr_stack(&const_expr_ctx, flag, value_type,
#if WASM_ENABLE_GC != 0
NULL, 0,
#endif
&cur_value, cur_expr, error_buf,
error_buf_size)) {
destroy_init_expr_recursive(cur_expr);
goto fail;
}
break;
}
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR */
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
/* ref.func */
case INIT_EXPR_TYPE_FUNCREF_CONST:
@ -799,6 +963,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
#if WASM_ENABLE_GC == 0
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_FUNCREF, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
#else
@ -816,8 +983,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
false, type_idx);
if (!push_const_expr_stack(&const_expr_ctx, flag,
cur_ref_type.ref_type, &cur_ref_type,
0, &cur_value, error_buf,
error_buf_size))
0, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
@ -837,8 +1007,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
cur_value.ref_index = NULL_REF;
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
&cur_value, error_buf,
error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
#else
int32 heap_type;
@ -861,13 +1034,19 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(&const_expr_ctx, flag,
cur_ref_type.ref_type,
&cur_ref_type, 0, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
}
else {
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
NULL, 0, &cur_value, error_buf,
error_buf_size))
NULL, 0, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
}
#endif
@ -956,8 +1135,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
#if WASM_ENABLE_GC != 0
&cur_ref_type, 0,
#endif
&cur_value, error_buf,
error_buf_size))
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
break;
@ -1020,6 +1202,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
&const_expr_ctx, NULL, field_type,
field_ref_type, NULL,
&struct_init_values->fields[field_idx],
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
destroy_init_expr_data_recursive(
module, struct_init_values);
@ -1033,6 +1218,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(
&const_expr_ctx, flag, cur_ref_type.ref_type,
&cur_ref_type, (uint8)opcode1, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
destroy_init_expr_data_recursive(
module, struct_init_values);
@ -1064,6 +1252,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(
&const_expr_ctx, flag, cur_ref_type.ref_type,
&cur_ref_type, (uint8)opcode1, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
goto fail;
}
@ -1112,8 +1303,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!pop_const_expr_stack(
&const_expr_ctx, NULL, VALUE_TYPE_I32,
NULL, NULL, &len_val, error_buf,
error_buf_size)) {
NULL, NULL, &len_val,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
goto fail;
}
@ -1132,6 +1326,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
&const_expr_ctx, NULL, elem_type,
elem_ref_type, NULL,
&array_init_values->elem_data[0],
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
destroy_init_expr_data_recursive(
module, array_init_values);
@ -1164,6 +1361,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
elem_ref_type, NULL,
&array_init_values
->elem_data[i - 1],
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
destroy_init_expr_data_recursive(
module, array_init_values);
@ -1180,10 +1380,13 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
uint32 len;
/* POP(i32) */
if (!pop_const_expr_stack(&const_expr_ctx, NULL,
VALUE_TYPE_I32, NULL,
NULL, &len_val, error_buf,
error_buf_size)) {
if (!pop_const_expr_stack(
&const_expr_ctx, NULL, VALUE_TYPE_I32, NULL,
NULL, &len_val,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
goto fail;
}
len = len_val.i32;
@ -1197,6 +1400,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(
&const_expr_ctx, flag, cur_ref_type.ref_type,
&cur_ref_type, (uint8)opcode1, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
if (array_init_values) {
destroy_init_expr_data_recursive(
@ -1223,9 +1429,13 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
case WASM_OP_REF_I31:
{
/* POP(i32) */
if (!pop_const_expr_stack(
&const_expr_ctx, NULL, VALUE_TYPE_I32, NULL,
NULL, &cur_value, error_buf, error_buf_size)) {
if (!pop_const_expr_stack(&const_expr_ctx, NULL,
VALUE_TYPE_I32, NULL, NULL,
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
goto fail;
}
@ -1234,6 +1444,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(
&const_expr_ctx, flag, cur_ref_type.ref_type,
&cur_ref_type, (uint8)opcode1, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
goto fail;
}
@ -1268,7 +1481,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
#if WASM_ENABLE_GC != 0
ref_type, &opcode,
#endif
&cur_value, error_buf, error_buf_size)) {
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
&cur_expr,
#endif
error_buf, error_buf_size)) {
goto fail;
}
@ -1278,8 +1495,21 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
goto fail;
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
if (cur_expr != NULL) {
bh_memcpy_s(init_expr, sizeof(InitializerExpression), cur_expr,
sizeof(InitializerExpression));
wasm_runtime_free(cur_expr);
}
else {
init_expr->init_expr_type = flag;
init_expr->u = cur_value;
init_expr->u.unary.v = cur_value;
}
#else
init_expr->init_expr_type = flag;
init_expr->u.unary.v = cur_value;
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
#if WASM_ENABLE_GC != 0
if (init_expr->init_expr_type == WASM_OP_GC_PREFIX) {
@ -1310,11 +1540,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
#endif /* end of WASM_ENABLE_GC != 0 */
*p_buf = p;
destroy_const_expr_stack(&const_expr_ctx);
destroy_const_expr_stack(&const_expr_ctx, false);
return true;
fail:
destroy_const_expr_stack(&const_expr_ctx);
destroy_const_expr_stack(&const_expr_ctx, true);
return false;
}
@ -4072,9 +4302,9 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
if (global->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
uint8 global_type;
WASMRefType *global_ref_type;
uint32 global_idx = global->init_expr.u.global_index;
uint32 global_idx = global->init_expr.u.unary.v.global_index;
if (global->init_expr.u.global_index
if (global->init_expr.u.unary.v.global_index
>= module->import_global_count + i) {
set_error_buf(error_buf, error_buf_size, "unknown global");
return false;
@ -4471,7 +4701,7 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
}
init_expr->init_expr_type = INIT_EXPR_TYPE_FUNCREF_CONST;
init_expr->u.ref_index = function_index;
init_expr->u.unary.v.ref_index = function_index;
}
*p_buf = p;
@ -4744,7 +4974,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
#if WASM_ENABLE_MEMORY64 != 0
if (table_elem_idx_type == VALUE_TYPE_I64
&& table_segment->base_offset.u.u64 > UINT32_MAX) {
&& table_segment->base_offset.u.unary.v.u64 > UINT32_MAX) {
set_error_buf(error_buf, error_buf_size,
"In table64, table base offset can't be "
"larger than UINT32_MAX");
@ -4904,6 +5134,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
if (!(dataseg = module->data_segments[i] = loader_malloc(
sizeof(WASMDataSeg), error_buf, error_buf_size))) {
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(module, &init_expr);
#endif
return false;
}
@ -6031,7 +6264,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
&& global->init_expr.init_expr_type
== INIT_EXPR_TYPE_I32_CONST) {
aux_heap_base_global = global;
aux_heap_base = (uint64)(uint32)global->init_expr.u.i32;
aux_heap_base =
(uint64)(uint32)global->init_expr.u.unary.v.i32;
aux_heap_base_global_index = export->index;
LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64,
aux_heap_base);
@ -6052,7 +6286,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
&& global->init_expr.init_expr_type
== INIT_EXPR_TYPE_I32_CONST) {
aux_data_end_global = global;
aux_data_end = (uint64)(uint32)global->init_expr.u.i32;
aux_data_end =
(uint64)(uint32)global->init_expr.u.unary.v.i32;
aux_data_end_global_index = export->index;
LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64,
aux_data_end);
@ -6093,10 +6328,11 @@ load_from_sections(WASMModule *module, WASMSection *sections,
&& global->type.val_type == VALUE_TYPE_I32
&& global->init_expr.init_expr_type
== INIT_EXPR_TYPE_I32_CONST
&& (uint64)(uint32)global->init_expr.u.i32
&& (uint64)(uint32)global->init_expr.u.unary.v.i32
<= aux_heap_base) {
aux_stack_top_global = global;
aux_stack_top = (uint64)(uint32)global->init_expr.u.i32;
aux_stack_top =
(uint64)(uint32)global->init_expr.u.unary.v.i32;
module->aux_stack_top_global_index =
module->import_global_count + global_index;
module->aux_stack_bottom = aux_stack_top;
@ -6947,7 +7183,7 @@ wasm_loader_unload(WASMModule *module)
wasm_runtime_free(module->memories);
if (module->globals) {
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
for (i = 0; i < module->global_count; i++) {
destroy_init_expr(module, &module->globals[i].init_expr);
}
@ -6980,6 +7216,9 @@ wasm_loader_unload(WASMModule *module)
#endif
wasm_runtime_free(module->table_segments[i].init_values);
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(module, &module->table_segments[i].base_offset);
#endif
}
wasm_runtime_free(module->table_segments);
}
@ -6989,6 +7228,10 @@ wasm_loader_unload(WASMModule *module)
if (module->data_segments[i]) {
if (module->data_segments[i]->is_data_cloned)
wasm_runtime_free(module->data_segments[i]->data);
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(module,
&(module->data_segments[i]->base_offset));
#endif
wasm_runtime_free(module->data_segments[i]);
}
}
@ -13260,7 +13503,8 @@ re_scan:
== 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) {
&& module->globals[i].init_expr.u.unary.v.u32
== func_idx) {
func_declared = true;
break;
}
@ -13289,7 +13533,8 @@ re_scan:
#endif
) {
for (j = 0; j < table_seg->value_count; j++) {
if (table_seg->init_values[j].u.ref_index
if (table_seg->init_values[j]
.u.unary.v.ref_index
== func_idx) {
func_declared = true;
break;

View File

@ -261,6 +261,9 @@ typedef struct InitValue {
uint8 type;
uint8 flag;
WASMValue value;
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression *expr;
#endif
} InitValue;
typedef struct ConstExprContext {
@ -282,7 +285,11 @@ init_const_expr_stack(ConstExprContext *ctx, WASMModule *module)
static bool
push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
WASMValue *value, char *error_buf, uint32 error_buf_size)
WASMValue *value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression *expr,
#endif
char *error_buf, uint32 error_buf_size)
{
InitValue *cur_value;
@ -305,6 +312,9 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
cur_value->type = type;
cur_value->flag = flag;
cur_value->value = *value;
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
cur_value->expr = expr;
#endif
return true;
fail:
@ -313,7 +323,11 @@ fail:
static bool
pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
WASMValue *p_value, char *error_buf, uint32 error_buf_size)
WASMValue *p_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression **p_expr,
#endif
char *error_buf, uint32 error_buf_size)
{
InitValue *cur_value;
@ -331,18 +345,50 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
*p_flag = cur_value->flag;
if (p_value)
*p_value = cur_value->value;
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
if (p_expr)
*p_expr = cur_value->expr;
#endif
return true;
}
static void
destroy_const_expr_stack(ConstExprContext *ctx)
destroy_const_expr_stack(ConstExprContext *ctx, bool free_exprs)
{
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
if (free_exprs) {
for (uint32 j = 0; j < ctx->sp; j++) {
if (is_expr_binary_op(ctx->stack[j].expr->init_expr_type)) {
destroy_init_expr_recursive(ctx->stack[j].expr);
ctx->stack[j].expr = NULL;
}
}
}
#endif
if (ctx->stack != ctx->data) {
wasm_runtime_free(ctx->stack);
}
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
static void
destroy_init_expr(InitializerExpression *expr)
{
// free left expr and right exprs 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 /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
static bool
load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
InitializerExpression *init_expr, uint8 type, char *error_buf,
@ -353,6 +399,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
uint32 i;
ConstExprContext const_expr_ctx = { 0 };
WASMValue cur_value = { 0 };
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
InitializerExpression *cur_expr = NULL;
#endif
init_const_expr_stack(&const_expr_ctx, module);
@ -367,8 +416,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_I32, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
bh_assert(0);
goto fail;
}
break;
/* i64.const */
@ -377,8 +429,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_I64, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
bh_assert(0);
goto fail;
}
break;
/* f32.const */
@ -390,8 +445,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_F32, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
bh_assert(0);
goto fail;
}
break;
/* f64.const */
@ -403,8 +461,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_F64, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
bh_assert(0);
goto fail;
}
break;
@ -417,13 +478,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
cur_value.ref_index = func_idx;
if (!check_function_index(module, func_idx, error_buf,
error_buf_size)) {
bh_assert(0);
goto fail;
}
if (!push_const_expr_stack(&const_expr_ctx, flag,
VALUE_TYPE_FUNCREF, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
bh_assert(0);
goto fail;
}
break;
}
@ -438,9 +502,12 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
cur_value.ref_index = UINT32_MAX;
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
&cur_value, error_buf,
error_buf_size)) {
bh_assert(0);
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size)) {
goto fail;
}
break;
}
@ -471,15 +538,93 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
}
if (!push_const_expr_stack(&const_expr_ctx, flag, global_type,
&cur_value, error_buf,
error_buf_size))
bh_assert(0);
&cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
NULL,
#endif
error_buf, error_buf_size))
goto fail;
break;
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
case INIT_EXPR_TYPE_I32_ADD:
case INIT_EXPR_TYPE_I64_ADD:
case INIT_EXPR_TYPE_I32_SUB:
case INIT_EXPR_TYPE_I64_SUB:
case INIT_EXPR_TYPE_I32_MUL:
case INIT_EXPR_TYPE_I64_MUL:
{
InitializerExpression *l_expr, *r_expr;
WASMValue l_value, r_value;
uint8 l_flag, r_flag;
uint8 value_type;
if (flag == INIT_EXPR_TYPE_I32_ADD
|| flag == INIT_EXPR_TYPE_I32_SUB
|| flag == INIT_EXPR_TYPE_I32_MUL) {
value_type = VALUE_TYPE_I32;
}
else {
value_type = VALUE_TYPE_I64;
}
/* If right flag indicates a binary operation, right expr will
* be popped from stack. Otherwise, allocate a new expr for
* right expr. Same for left expr.
*/
if (!(pop_const_expr_stack(&const_expr_ctx, &r_flag, value_type,
&r_value, &r_expr, error_buf,
error_buf_size))) {
goto fail;
}
if (!is_expr_binary_op(r_flag)) {
if (!(r_expr = loader_malloc(sizeof(InitializerExpression),
error_buf, error_buf_size))) {
goto fail;
}
r_expr->init_expr_type = r_flag;
r_expr->u.unary.v = r_value;
}
if (!(pop_const_expr_stack(&const_expr_ctx, &l_flag, value_type,
&l_value, &l_expr, error_buf,
error_buf_size))) {
destroy_init_expr_recursive(r_expr);
goto fail;
}
if (!is_expr_binary_op(l_flag)) {
if (!(l_expr = loader_malloc(sizeof(InitializerExpression),
error_buf, error_buf_size))) {
destroy_init_expr_recursive(r_expr);
goto fail;
}
l_expr->init_expr_type = l_flag;
l_expr->u.unary.v = l_value;
}
if (!(cur_expr = loader_malloc(sizeof(InitializerExpression),
error_buf, error_buf_size))) {
destroy_init_expr_recursive(l_expr);
destroy_init_expr_recursive(r_expr);
goto fail;
}
cur_expr->init_expr_type = flag;
cur_expr->u.binary.l_expr = l_expr;
cur_expr->u.binary.r_expr = r_expr;
if (!push_const_expr_stack(&const_expr_ctx, flag, value_type,
&cur_value, cur_expr, error_buf,
error_buf_size)) {
destroy_init_expr_recursive(cur_expr);
goto fail;
}
break;
}
#endif
default:
{
bh_assert(0);
goto fail;
}
}
@ -489,18 +634,42 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
/* There should be only one value left on the init value stack */
if (!pop_const_expr_stack(&const_expr_ctx, &flag, type, &cur_value,
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
&cur_expr,
#endif
error_buf, error_buf_size)) {
bh_assert(0);
goto fail;
}
bh_assert(const_expr_ctx.sp == 0);
if (const_expr_ctx.sp != 0) {
set_error_buf(error_buf, error_buf_size,
"type mismatch: illegal constant opcode sequence");
goto fail;
}
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
if (cur_expr != NULL) {
bh_memcpy_s(init_expr, sizeof(InitializerExpression), cur_expr,
sizeof(InitializerExpression));
wasm_runtime_free(cur_expr);
}
else {
init_expr->init_expr_type = flag;
init_expr->u = cur_value;
init_expr->u.unary.v = cur_value;
}
#else
init_expr->init_expr_type = flag;
init_expr->u.unary.v = cur_value;
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
*p_buf = p;
destroy_const_expr_stack(&const_expr_ctx);
destroy_const_expr_stack(&const_expr_ctx, false);
return true;
fail:
destroy_const_expr_stack(&const_expr_ctx, true);
return false;
}
static bool
@ -1385,13 +1554,14 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
* global.get instructions are
* only allowed to refer to imported globals.
*/
uint32 target_global_index = global->init_expr.u.global_index;
uint32 target_global_index =
global->init_expr.u.unary.v.global_index;
bh_assert(target_global_index < module->import_global_count);
(void)target_global_index;
}
else if (INIT_EXPR_TYPE_FUNCREF_CONST
== global->init_expr.init_expr_type) {
bh_assert(global->init_expr.u.ref_index
bh_assert(global->init_expr.u.unary.v.ref_index
< module->import_function_count
+ module->function_count);
}
@ -1575,7 +1745,7 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
}
init_expr->init_expr_type = INIT_EXPR_TYPE_FUNCREF_CONST;
init_expr->u.ref_index = function_index;
init_expr->u.unary.v.ref_index = function_index;
}
*p_buf = p;
@ -1890,6 +2060,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
if (!(dataseg = module->data_segments[i] = loader_malloc(
sizeof(WASMDataSeg), error_buf, error_buf_size))) {
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(&init_expr);
#endif
return false;
}
@ -2778,7 +2951,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
&& global->init_expr.init_expr_type
== INIT_EXPR_TYPE_I32_CONST) {
aux_heap_base_global = global;
aux_heap_base = (uint64)(uint32)global->init_expr.u.i32;
aux_heap_base =
(uint64)(uint32)global->init_expr.u.unary.v.i32;
aux_heap_base_global_index = export->index;
LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64,
aux_heap_base);
@ -2798,7 +2972,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
&& global->init_expr.init_expr_type
== INIT_EXPR_TYPE_I32_CONST) {
aux_data_end_global = global;
aux_data_end = (uint64)(uint32)global->init_expr.u.i32;
aux_data_end =
(uint64)(uint32)global->init_expr.u.unary.v.i32;
aux_data_end_global_index = export->index;
LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64,
aux_data_end);
@ -2838,10 +3013,11 @@ load_from_sections(WASMModule *module, WASMSection *sections,
&& global->type.val_type == VALUE_TYPE_I32
&& global->init_expr.init_expr_type
== INIT_EXPR_TYPE_I32_CONST
&& (uint64)(uint32)global->init_expr.u.i32
&& (uint64)(uint32)global->init_expr.u.unary.v.i32
<= aux_heap_base) {
aux_stack_top_global = global;
aux_stack_top = (uint64)(uint32)global->init_expr.u.i32;
aux_stack_top =
(uint64)(uint32)global->init_expr.u.unary.v.i32;
module->aux_stack_top_global_index =
module->import_global_count + global_index;
module->aux_stack_bottom = aux_stack_top;
@ -3448,8 +3624,14 @@ wasm_loader_unload(WASMModule *module)
if (module->memories)
wasm_runtime_free(module->memories);
if (module->globals)
if (module->globals) {
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
for (i = 0; i < module->global_count; i++) {
destroy_init_expr(&module->globals[i].init_expr);
}
#endif
wasm_runtime_free(module->globals);
}
if (module->exports)
wasm_runtime_free(module->exports);
@ -3458,6 +3640,9 @@ wasm_loader_unload(WASMModule *module)
for (i = 0; i < module->table_seg_count; i++) {
if (module->table_segments[i].init_values)
wasm_runtime_free(module->table_segments[i].init_values);
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(&module->table_segments[i].base_offset);
#endif
}
wasm_runtime_free(module->table_segments);
}
@ -3467,6 +3652,9 @@ wasm_loader_unload(WASMModule *module)
if (module->data_segments[i]) {
if (module->data_segments[i]->is_data_cloned)
wasm_runtime_free(module->data_segments[i]->data);
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
destroy_init_expr(&module->data_segments[i]->base_offset);
#endif
wasm_runtime_free(module->data_segments[i]);
}
}
@ -7320,7 +7508,8 @@ re_scan:
== 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) {
&& module->globals[i].init_expr.u.unary.v.ref_index
== func_idx) {
func_declared = true;
break;
}
@ -7334,7 +7523,8 @@ re_scan:
i++, table_seg++) {
if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
for (j = 0; j < table_seg->value_count; j++) {
if (table_seg->init_values[j].u.ref_index
if (table_seg->init_values[j]
.u.unary.v.ref_index
== func_idx) {
func_declared = true;
break;

View File

@ -1165,6 +1165,81 @@ instantiate_array_global_recursive(WASMModule *module,
}
#endif
static bool
get_init_value_recursive(WASMModule *module, InitializerExpression *expr,
WASMGlobalInstance *globals, 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)) {
goto fail;
}
*value = globals[expr->u.unary.v.global_index].initial_value;
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 (!expr->u.binary.l_expr || !expr->u.binary.r_expr) {
goto fail;
}
if (!get_init_value_recursive(module, expr->u.binary.l_expr,
globals, &l_value, error_buf,
error_buf_size)) {
goto fail;
}
if (!get_init_value_recursive(module, expr->u.binary.r_expr,
globals, &r_value, error_buf,
error_buf_size)) {
goto fail;
}
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 /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
default:
goto fail;
}
return true;
fail:
return false;
}
/**
* Instantiate globals in a module.
*/
@ -1209,7 +1284,7 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
/* The linked global instance has been initialized, we
just need to copy the value. */
global->initial_value =
global_import->import_global_linked->init_expr.u;
global_import->import_global_linked->init_expr.u.unary.v;
}
else
#endif
@ -1245,17 +1320,23 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
#endif
switch (flag) {
case INIT_EXPR_TYPE_I32_CONST:
case INIT_EXPR_TYPE_I64_CONST:
case INIT_EXPR_TYPE_GET_GLOBAL:
#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)) {
if (!get_init_value_recursive(module, init_expr, globals,
&global->initial_value, error_buf,
error_buf_size)) {
goto fail;
}
bh_memcpy_s(
&(global->initial_value), sizeof(WASMValue),
&(globals[init_expr->u.global_index].initial_value),
sizeof(globals[init_expr->u.global_index].initial_value));
break;
}
#if WASM_ENABLE_GC != 0
@ -1267,11 +1348,12 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
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_obj = instantiate_struct_global_recursive(
@ -1294,12 +1376,14 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
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;
array_init_value = &empty_value;
}
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;
@ -1318,13 +1402,12 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
case INIT_EXPR_TYPE_I31_NEW:
{
global->initial_value.gc_obj =
(wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
(wasm_obj_t)wasm_i31_obj_new(init_expr->u.unary.v.i32);
break;
}
#endif /* end of WASM_ENABLE_GC != 0 */
default:
bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
&(init_expr->u), sizeof(init_expr->u));
global->initial_value = init_expr->u.unary.v;
break;
}
@ -2698,6 +2781,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
uint8 *memory_data = NULL;
uint64 memory_size = 0;
WASMDataSeg *data_seg = module->data_segments[i];
WASMValue offset_value;
#if WASM_ENABLE_BULK_MEMORY != 0
if (data_seg->is_passive)
@ -2717,54 +2801,37 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
(uint64)memory->num_bytes_per_page * memory->cur_page_count;
bh_assert(memory_data || memory_size == 0);
bh_assert(data_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL
|| data_seg->base_offset.init_expr_type
== (memory->is_memory64 ? INIT_EXPR_TYPE_I64_CONST
: INIT_EXPR_TYPE_I32_CONST));
uint8 offset_flag = data_seg->base_offset.init_expr_type;
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|| (memory->is_memory64 ? is_valid_i64_offset(offset_flag)
: is_valid_i32_offset(offset_flag)));
if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
if (!check_global_init_expr(module,
data_seg->base_offset.u.global_index,
error_buf, error_buf_size)) {
if (!get_init_value_recursive(module, &data_seg->base_offset, globals,
&offset_value, error_buf,
error_buf_size)) {
goto fail;
}
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
if (!globals
|| globals[data_seg->base_offset.u.global_index].type
|| globals[data_seg->base_offset.u.unary.v.global_index].type
!= (memory->is_memory64 ? VALUE_TYPE_I64
: VALUE_TYPE_I32)) {
set_error_buf(error_buf, error_buf_size,
"data segment does not fit");
goto fail;
}
}
#if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
base_offset =
(uint64)globals[data_seg->base_offset.u.global_index]
.initial_value.i64;
base_offset = (uint64)offset_value.i64;
}
else
#endif
{
base_offset =
(uint32)globals[data_seg->base_offset.u.global_index]
.initial_value.i32;
base_offset = (uint32)offset_value.i32;
}
}
else {
#if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
base_offset = (uint64)data_seg->base_offset.u.i64;
}
else
#endif
{
base_offset = (uint32)data_seg->base_offset.u.i32;
}
}
/* check offset */
if (base_offset > memory_size) {
#if WASM_ENABLE_MEMORY64 != 0
@ -2842,36 +2909,39 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|| table->init_expr.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST);
if (table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
if (!check_global_init_expr(module, table->init_expr.u.global_index,
if (!check_global_init_expr(module,
table->init_expr.u.unary.v.global_index,
error_buf, error_buf_size)) {
goto fail;
}
table->init_expr.u.gc_obj =
globals[table->init_expr.u.global_index].initial_value.gc_obj;
table->init_expr.u.unary.v.gc_obj =
globals[table->init_expr.u.unary.v.global_index]
.initial_value.gc_obj;
}
else if (table->init_expr.init_expr_type
== INIT_EXPR_TYPE_FUNCREF_CONST) {
uint32 func_idx = table->init_expr.u.ref_index;
uint32 func_idx = table->init_expr.u.unary.v.ref_index;
if (func_idx != UINT32_MAX) {
if (!(table->init_expr.u.gc_obj =
if (!(table->init_expr.u.unary.v.gc_obj =
wasm_create_func_obj(module_inst, func_idx, false,
error_buf, error_buf_size)))
goto fail;
}
else {
table->init_expr.u.gc_obj = NULL_REF;
table->init_expr.u.unary.v.gc_obj = NULL_REF;
}
}
else if (table->init_expr.init_expr_type
== INIT_EXPR_TYPE_REFNULL_CONST) {
table->init_expr.u.gc_obj = NULL_REF;
table->init_expr.u.unary.v.gc_obj = NULL_REF;
}
LOG_DEBUG("Init table [%d] elements from [%d] to [%d] as: %p", i, 0,
table_inst->cur_size, (void *)table->init_expr.u.gc_obj);
table_inst->cur_size,
(void *)table->init_expr.u.unary.v.gc_obj);
for (j = 0; j < table_inst->cur_size; j++) {
*(table_data + j) = table->init_expr.u.gc_obj;
*(table_data + j) = table->init_expr.u.unary.v.gc_obj;
}
}
#endif /* end of WASM_ENABLE_GC != 0 */
@ -2883,6 +2953,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
/* has check it in loader */
WASMTableInstance *table = module_inst->tables[table_seg->table_index];
table_elem_type_t *table_data;
WASMValue offset_value;
uint32 j;
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
uint8 tbl_elem_type;
@ -2941,48 +3012,37 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
continue;
#endif
uint8 offset_flag = table_seg->base_offset.init_expr_type;
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
bh_assert(table_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_I32_CONST
|| table_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL
|| table_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_FUNCREF_CONST
|| table_seg->base_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
|| is_valid_i32_offset(offset_flag));
#else
bh_assert(table_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_I32_CONST
|| table_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL);
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|| is_valid_i32_offset(offset_flag));
#endif
/* init vec(funcidx) or vec(expr) */
if (table_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL) {
if (!check_global_init_expr(module,
table_seg->base_offset.u.global_index,
error_buf, error_buf_size)) {
if (!get_init_value_recursive(module, &table_seg->base_offset, globals,
&offset_value, error_buf,
error_buf_size)) {
goto fail;
}
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
if (!globals
|| globals[table_seg->base_offset.u.global_index].type
|| globals[table_seg->base_offset.u.unary.v.global_index].type
!= VALUE_TYPE_I32) {
set_error_buf(error_buf, error_buf_size,
"type mismatch: elements segment does not fit");
goto fail;
}
table_seg->base_offset.u.i32 =
globals[table_seg->base_offset.u.global_index]
.initial_value.i32;
}
/* check offset since length might negative */
if ((uint32)table_seg->base_offset.u.i32 > table->cur_size) {
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)",
table_seg->base_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);
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
set_error_buf(error_buf, error_buf_size,
"out of bounds table access");
@ -2995,9 +3055,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
/* check offset + length(could be zero) */
length = table_seg->value_count;
if ((uint32)table_seg->base_offset.u.i32 + length > table->cur_size) {
if ((uint32)offset_value.i32 + length > table->cur_size) {
LOG_DEBUG("base_offset(%d) + length(%d)> table->cur_size(%d)",
table_seg->base_offset.u.i32, length, table->cur_size);
offset_value.i32, length, table->cur_size);
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
set_error_buf(error_buf, error_buf_size,
"out of bounds table access");
@ -3027,10 +3087,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
case INIT_EXPR_TYPE_FUNCREF_CONST:
{
#if WASM_ENABLE_GC == 0
ref = (void *)(uintptr_t)init_expr->u.ref_index;
ref = (void *)(uintptr_t)init_expr->u.unary.v.ref_index;
#else
WASMFuncObjectRef func_obj;
uint32 func_idx = init_expr->u.ref_index;
uint32 func_idx = init_expr->u.unary.v.ref_index;
/* UINT32_MAX indicates that it is a null reference */
if (func_idx != UINT32_MAX) {
if (!(func_obj = wasm_create_func_obj(
@ -3049,14 +3109,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
#if WASM_ENABLE_GC != 0
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)) {
goto fail;
}
ref =
globals[init_expr->u.global_index].initial_value.gc_obj;
ref = globals[init_expr->u.unary.v.global_index]
.initial_value.gc_obj;
break;
}
case INIT_EXPR_TYPE_STRUCT_NEW:
@ -3069,12 +3129,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
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];
@ -3125,13 +3185,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
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;
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
type_idx = init_values->type_idx;
len = init_values->length;
@ -3177,14 +3238,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
}
case INIT_EXPR_TYPE_I31_NEW:
{
ref = (wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
ref =
(wasm_obj_t)wasm_i31_obj_new(init_expr->u.unary.v.i32);
break;
}
#endif /* end of WASM_ENABLE_GC != 0 */
}
*(table_data + table_seg->base_offset.u.i32 + j) =
(table_elem_type_t)ref;
*(table_data + offset_value.i32 + j) = (table_elem_type_t)ref;
}
}
@ -4706,10 +4767,10 @@ llvm_jit_table_init(WASMModuleInstance *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 = wasm_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 = wasm_create_func_obj(
module_inst, init_values[i].u.unary.v.ref_index, true,
NULL, 0))) {
wasm_set_exception(module_inst, "null function reference");
return;
}
@ -4719,7 +4780,7 @@ llvm_jit_table_init(WASMModuleInstance *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
}
}

View File

@ -293,6 +293,10 @@ Currently we only profile the memory consumption of module, module_instance and
- **WAMR_BUILD_AOT_INTRINSICS**=1/0, enable the AOT intrinsic functions, default to enable if not set. These functions can be called from the AOT code when `--disable-llvm-intrinsics` flag or `--enable-builtin-intrinsics=<intr1,intr2,...>` flag is used by wamrc to generate the AOT file.
> Note: See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions) for more details.
### **Enable extended constant expression**
- **WAMR_BUILD_EXTENDED_CONST_EXPR**=1/0, default to disable if not set.
> Note: See [Extended Constant Expressions](https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/Overview.md) for more details.
### **Configurable memory access boundary check**
- **WAMR_CONFIGURABLE_BOUNDS_CHECKS**=1/0, default to disable if not set
> Note: If it is enabled, allow to run `iwasm --disable-bounds-checks` to disable the memory access boundary checks for interpreter mode.

View File

@ -172,6 +172,7 @@ def test_case(
clean_up_flag=True,
verbose_flag=True,
gc_flag=False,
extended_const_flag=False,
memory64_flag=False,
multi_memory_flag=False,
qemu_flag=False,
@ -229,6 +230,9 @@ def test_case(
if gc_flag:
CMD.append("--gc")
if extended_const_flag:
CMD.append("--extended-const")
if memory64_flag:
CMD.append("--memory64")
@ -304,6 +308,7 @@ def test_suite(
clean_up_flag=True,
verbose_flag=True,
gc_flag=False,
extended_const_flag=False,
memory64_flag=False,
multi_memory_flag=False,
parl_flag=False,
@ -385,6 +390,7 @@ def test_suite(
clean_up_flag,
verbose_flag,
gc_flag,
extended_const_flag,
memory64_flag,
multi_memory_flag,
qemu_flag,
@ -428,6 +434,7 @@ def test_suite(
clean_up_flag,
verbose_flag,
gc_flag,
extended_const_flag,
memory64_flag,
multi_memory_flag,
qemu_flag,
@ -561,6 +568,13 @@ def main():
dest="gc_flag",
help="Running with GC feature",
)
parser.add_argument(
"--enable-extended-const",
action="store_true",
default=False,
dest="extended_const_flag",
help="Running with extended const expression feature",
)
parser.add_argument(
"--memory64",
action="store_true",
@ -619,6 +633,7 @@ def main():
options.clean_up_flag,
options.verbose_flag,
options.gc_flag,
options.extended_const_flag,
options.memory64_flag,
options.multi_memory_flag,
options.parl_flag,
@ -648,6 +663,7 @@ def main():
options.clean_up_flag,
options.verbose_flag,
options.gc_flag,
options.extended_const_flag,
options.memory64_flag,
options.multi_memory_flag,
options.qemu_flag,

View File

@ -0,0 +1,506 @@
diff --git a/test/core/elem.wast b/test/core/elem.wast
index 92dab52..3954bca 100644
--- a/test/core/elem.wast
+++ b/test/core/elem.wast
@@ -571,6 +571,7 @@
;; Element sections across multiple modules change the same table
+(;
(module $module1
(type $out-i32 (func (result i32)))
(table (export "shared-table") 10 funcref)
@@ -620,7 +621,7 @@
(assert_return (invoke $module1 "call-7") (i32.const 67))
(assert_return (invoke $module1 "call-8") (i32.const 69))
(assert_return (invoke $module1 "call-9") (i32.const 70))
-
+;)
;; Element segments must match element type of table
(assert_invalid
@@ -659,24 +660,30 @@
(func (export "set") (param $i i32) (param $x externref)
(table.set $t (local.get $i) (local.get $x))))
-(register "exporter" $m)
+;; (register "exporter" $m)
-(assert_return (invoke $m "get" (i32.const 0)) (ref.null extern))
-(assert_return (invoke $m "get" (i32.const 1)) (ref.null extern))
+;; (assert_return (invoke $m "get" (i32.const 0)) (ref.null extern))
+;; (assert_return (invoke $m "get" (i32.const 1)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 0)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 1)) (ref.null extern))
-(assert_return (invoke $m "set" (i32.const 0) (ref.extern 42)))
-(assert_return (invoke $m "set" (i32.const 1) (ref.extern 137)))
-
-(assert_return (invoke $m "get" (i32.const 0)) (ref.extern 42))
-(assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137))
+;; (assert_return (invoke $m "set" (i32.const 0) (ref.extern 42)))
+;; (assert_return (invoke $m "set" (i32.const 1) (ref.extern 137)))
+(assert_return (invoke "set" (i32.const 0) (ref.extern 42)))
+(assert_return (invoke "set" (i32.const 1) (ref.extern 137)))
+;; (assert_return (invoke $m "get" (i32.const 0)) (ref.extern 42))
+;; (assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137))
+(assert_return (invoke "get" (i32.const 0)) (ref.extern 42))
+(assert_return (invoke "get" (i32.const 1)) (ref.extern 137))
+(;
(module
(import "exporter" "table" (table $t 2 externref))
(elem (i32.const 0) externref (ref.null extern)))
(assert_return (invoke $m "get" (i32.const 0)) (ref.null extern))
(assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137))
-
+;)
;; Initializing a table with imported funcref global
(module $module4
@@ -686,6 +693,7 @@
(global (export "f") funcref (ref.func 0))
)
+(;
(register "module4" $module4)
(module
@@ -699,6 +707,7 @@
)
(assert_return (invoke "call_imported_elem") (i32.const 42))
+;)
;; Extended contant expressions
diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast
index adb5cb7..6396013 100644
--- a/test/core/ref_func.wast
+++ b/test/core/ref_func.wast
@@ -4,7 +4,7 @@
(register "M")
(module
- (func $f (import "M" "f") (param i32) (result i32))
+ (func $f (param $x i32) (result i32) (local.get $x))
(func $g (param $x i32) (result i32)
(i32.add (local.get $x) (i32.const 1))
)
diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast
index 380e84e..59230cf 100644
--- a/test/core/table_copy.wast
+++ b/test/core/table_copy.wast
@@ -14,11 +14,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -106,11 +106,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -198,11 +198,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -290,11 +290,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -382,11 +382,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -474,11 +474,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -566,11 +566,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -658,11 +658,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -750,11 +750,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -842,11 +842,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -934,11 +934,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1026,11 +1026,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1118,11 +1118,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1210,11 +1210,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1302,11 +1302,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1394,11 +1394,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1486,11 +1486,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -1578,11 +1578,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
diff --git a/test/core/table_init.wast b/test/core/table_init.wast
index 0b2d26f..3c595e5 100644
--- a/test/core/table_init.wast
+++ b/test/core/table_init.wast
@@ -14,11 +14,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -72,11 +72,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -130,11 +130,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t0) (i32.const 2) func 3 1 4 1)
@@ -196,11 +196,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -254,11 +254,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)
@@ -312,11 +312,11 @@
(module
(type (func (result i32))) ;; type #0
- (import "a" "ef0" (func (result i32))) ;; index 0
- (import "a" "ef1" (func (result i32)))
- (import "a" "ef2" (func (result i32)))
- (import "a" "ef3" (func (result i32)))
- (import "a" "ef4" (func (result i32))) ;; index 4
+ (func (result i32) (i32.const 0)) ;; index 0
+ (func (result i32) (i32.const 1))
+ (func (result i32) (i32.const 2))
+ (func (result i32) (i32.const 3))
+ (func (result i32) (i32.const 4)) ;; index 4
(table $t0 30 30 funcref)
(table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1)

View File

@ -336,6 +336,9 @@ parser.add_argument('--multi-thread', default=False, action='store_true',
parser.add_argument('--gc', default=False, action='store_true',
help='Test with GC')
parser.add_argument('--extended-const', action='store_true',
help='Enable extended const expression feature')
parser.add_argument('--memory64', default=False, action='store_true',
help='Test with Memory64')
@ -1112,6 +1115,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
cmd = [opts.wast2wasm, "--enable-memory64", "--no-check", wast_tempfile, "-o", wasm_tempfile ]
elif opts.multi_memory:
cmd = [opts.wast2wasm, "--enable-multi-memory", "--no-check", wast_tempfile, "-o", wasm_tempfile ]
elif opts.extended_const:
cmd = [opts.wast2wasm, "--enable-extended-const", "--no-check", wast_tempfile, "-o", wasm_tempfile ]
else:
# `--enable-multi-memory` for a case in memory.wast but doesn't require runtime support
cmd = [opts.wast2wasm, "--enable-multi-memory", "--enable-threads", "--no-check",
@ -1155,6 +1160,9 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
cmd.append("--enable-gc")
cmd.append("--enable-tail-call")
if opts.extended_const:
cmd.append("--enable-extended-const")
if output == 'object':
cmd.append("--format=object")
elif output == 'ir':

View File

@ -41,6 +41,7 @@ function help()
echo "-j set the platform to test"
echo "-T set sanitizer to use in tests(ubsan|tsan|asan|posan)"
echo "-A use the specified wamrc command instead of building it"
echo "-N enable extended const expression feature"
echo "-r [requirement name] [N [N ...]] specify a requirement name followed by one or more"
echo " subrequirement IDs, if no subrequirement is specificed,"
echo " it will run all subrequirements. When this optin is used,"
@ -59,6 +60,7 @@ ENABLE_MULTI_THREAD=0
COLLECT_CODE_COVERAGE=0
ENABLE_SIMD=0
ENABLE_GC=0
ENABLE_EXTENDED_CONST_EXPR=0
ENABLE_MEMORY64=0
ENABLE_MULTI_MEMORY=0
ENABLE_XIP=0
@ -87,7 +89,7 @@ REQUIREMENT_NAME=""
# Initialize an empty array for subrequirement IDs
SUBREQUIREMENT_IDS=()
while getopts ":s:cabgvt:m:MCpSXexwWEPGQF:j:T:r:A:" opt
while getopts ":s:cabgvt:m:MCpSXexwWEPGQF:j:T:r:A:N" opt
do
OPT_PARSED="TRUE"
case $opt in
@ -191,6 +193,10 @@ do
echo "enable GC feature"
ENABLE_GC=1
;;
N)
echo "enable extended const expression feature"
ENABLE_EXTENDED_CONST_EXPR=1
;;
P)
PARALLELISM=1
;;
@ -485,6 +491,17 @@ function spec_test()
# (func $f (param (ref null $t)) (result funcref) (local.get 0))
#
compile_reference_interpreter
elif [[ ${ENABLE_EXTENDED_CONST_EXPR} == 1 ]]; then
echo "checkout spec for extended const expression proposal"
git clone -b main --single-branch https://github.com/WebAssembly/extended-const.git spec
pushd spec
# Jan 14, 2025. README.md: Add note that this proposal is done (#20)
git reset --hard 8d4f6aa2b00a8e7c0174410028625c6a176db8a1
# ignore import table cases
git apply --ignore-whitespace ../../spec-test-script/extended_const.patch || exit 1
elif [[ ${ENABLE_MEMORY64} == 1 ]]; then
echo "checkout spec for memory64 proposal"
@ -587,6 +604,10 @@ function spec_test()
ARGS_FOR_SPEC_TEST+="--gc "
fi
if [[ ${ENABLE_EXTENDED_CONST_EXPR} == 1 ]]; then
ARGS_FOR_SPEC_TEST+="--enable-extended-const "
fi
if [[ 1 == ${ENABLE_MEMORY64} ]]; then
ARGS_FOR_SPEC_TEST+="--memory64 "
fi
@ -832,6 +853,7 @@ function build_wamrc()
&& cmake .. \
-DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE} \
-DWAMR_BUILD_SHRUNK_MEMORY=0 \
-DWAMR_BUILD_EXTENDED_CONST_EXPR=${ENABLE_EXTENDED_CONST_EXPR} \
&& make -j 4
}
@ -1023,6 +1045,10 @@ function trigger()
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_TAIL_CALL=1"
fi
if [[ ${ENABLE_EXTENDED_CONST_EXPR} == 1 ]]; then
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_EXTENDED_CONST_EXPR=1"
fi
if [[ ${ENABLE_DEBUG_VERSION} == 1 ]]; then
EXTRA_COMPILE_FLAGS+=" -DCMAKE_BUILD_TYPE=Debug"
fi

View File

@ -53,6 +53,7 @@ add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
add_definitions(-DWASM_ENABLE_MEMORY64=1)
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=1)
add_definitions(-DWASM_ENABLE_GC=1)

View File

@ -423,6 +423,7 @@ main(int argc, char *argv[])
option.enable_bulk_memory = true;
option.enable_ref_types = true;
option.enable_gc = false;
option.enable_extended_const = false;
aot_call_stack_features_init_default(&option.call_stack_features);
/* Process options */
@ -536,6 +537,9 @@ main(int argc, char *argv[])
else if (!strcmp(argv[0], "--disable-aux-stack-check")) {
option.enable_aux_stack_check = false;
}
else if (!strcmp(argv[0], "--enable-extended-const")) {
option.enable_extended_const = true;
}
else if (!strcmp(argv[0], "--enable-dump-call-stack")) {
option.aux_stack_frame_type = AOT_STACK_FRAME_TYPE_STANDARD;
}