Skip to content

Commit 7d05dbc

Browse files
Support extended constant expressions (#4432)
* implement extended const expr (#4318) * add a toggle to enable extended const on wamrc (#4412)
1 parent be33a40 commit 7d05dbc

28 files changed

+1730
-375
lines changed

.github/workflows/compilation_on_android_ubuntu.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ env:
6969
GC_TEST_OPTIONS: "-s spec -G -b -P"
7070
MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
7171
MULTI_MEMORY_TEST_OPTIONS: "-s spec -E -b -P"
72+
EXTENDED_CONST_EXPR_TEST_OPTIONS: "-s spec -N -b -P"
7273

7374
permissions:
7475
contents: read
@@ -164,6 +165,7 @@ jobs:
164165
"-DWAMR_BUILD_MEMORY64=1",
165166
"-DWAMR_BUILD_MULTI_MEMORY=1",
166167
"-DWAMR_BUILD_SHARED=1",
168+
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
167169
]
168170
os: [ubuntu-22.04]
169171
platform: [android, linux]
@@ -609,6 +611,7 @@ jobs:
609611
$GC_TEST_OPTIONS,
610612
$MEMORY64_TEST_OPTIONS,
611613
$MULTI_MEMORY_TEST_OPTIONS,
614+
$EXTENDED_CONST_EXPR_TEST_OPTIONS,
612615
]
613616
include:
614617
- os: ubuntu-22.04

.github/workflows/compilation_on_macos.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ jobs:
142142
"-DWAMR_BUILD_SIMD=1",
143143
"-DWAMR_BUILD_TAIL_CALL=1",
144144
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
145+
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
145146
]
146147
os: [macos-13]
147148
platform: [darwin]

.github/workflows/compilation_on_sgx.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ jobs:
100100
"-DWAMR_BUILD_MULTI_MODULE=1",
101101
"-DWAMR_BUILD_PERF_PROFILING=1",
102102
"-DWAMR_BUILD_REF_TYPES=1",
103+
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
103104
# doesn't support
104105
"-DWAMR_BUILD_SIMD=0",
105106
"-DWAMR_BUILD_TAIL_CALL=1",

.github/workflows/nightly_run.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ env:
3737
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"
3838
# For Spec Test
3939
DEFAULT_TEST_OPTIONS: "-s spec -b -P"
40+
EXTENDED_CONST_EXPR_TEST_OPTIONS: "-s spec -b -P -N"
4041
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -P -M"
4142
SIMD_TEST_OPTIONS: "-s spec -b -P -S"
4243
THREADS_TEST_OPTIONS: "-s spec -b -P -p"
@@ -128,6 +129,7 @@ jobs:
128129
"-DWAMR_BUILD_MEMORY64=1",
129130
"-DWAMR_BUILD_MULTI_MEMORY=1",
130131
"-DWAMR_BUILD_SHARED=1",
132+
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
131133
]
132134
os: [ubuntu-22.04]
133135
platform: [android, linux]
@@ -588,6 +590,7 @@ jobs:
588590
$DEFAULT_TEST_OPTIONS,
589591
$MULTI_MODULES_TEST_OPTIONS,
590592
$SIMD_TEST_OPTIONS,
593+
$EXTENDED_CONST_EXPR_TEST_OPTIONS,
591594
$THREADS_TEST_OPTIONS,
592595
$WASI_TEST_OPTIONS,
593596
]

build-scripts/config_common.cmake

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ if (NOT DEFINED WAMR_BUILD_TAIL_CALL)
211211
set (WAMR_BUILD_TAIL_CALL 0)
212212
endif ()
213213

214+
if (NOT DEFINED WAMR_BUILD_EXTENDED_CONST_EXPR)
215+
set (WAMR_BUILD_EXTENDED_CONST_EXPR 0)
216+
endif ()
217+
214218
########################################
215219
# Compilation options to marco
216220
########################################
@@ -673,7 +677,13 @@ if (WAMR_BUILD_INSTRUCTION_METERING EQUAL 1)
673677
message (" Instruction metering enabled")
674678
add_definitions (-DWASM_ENABLE_INSTRUCTION_METERING=1)
675679
endif ()
676-
680+
if (WAMR_BUILD_EXTENDED_CONST_EXPR EQUAL 1)
681+
message (" Extended constant expression enabled")
682+
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=1)
683+
else()
684+
message (" Extended constant expression disabled")
685+
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=0)
686+
endif ()
677687
########################################
678688
# Show Phase4 Wasm proposals status.
679689
########################################
@@ -687,6 +697,7 @@ message (
687697
" \"WebAssembly C and C++ API\"\n"
688698
" Configurable. 0 is OFF. 1 is ON:\n"
689699
" \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n"
700+
" \"Extended Constant Expressions\" via WAMR_BUILD_EXTENDED_CONST_EXPR: ${WAMR_BUILD_EXTENDED_CONST_EXPR}\n"
690701
" \"Fixed-width SIMD\" via WAMR_BUILD_SIMD: ${WAMR_BUILD_SIMD}\n"
691702
" \"Garbage collection\" via WAMR_BUILD_GC: ${WAMR_BUILD_GC}\n"
692703
" \"Legacy Exception handling\" via WAMR_BUILD_EXCE_HANDLING: ${WAMR_BUILD_EXCE_HANDLING}\n"
@@ -701,7 +712,6 @@ message (
701712
" \"Branch Hinting\"\n"
702713
" \"Custom Annotation Syntax in the Text Format\"\n"
703714
" \"Exception handling\"\n"
704-
" \"Extended Constant Expressions\"\n"
705715
" \"Import/Export of Mutable Globals\"\n"
706716
" \"JS String Builtins\"\n"
707717
" \"Relaxed SIMD\"\n"

core/config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,4 +720,8 @@ unless used elsewhere */
720720
#define WASM_ENABLE_INSTRUCTION_METERING 0
721721
#endif
722722

723+
#ifndef WASM_ENABLE_EXTENDED_CONST_EXPR
724+
#define WASM_ENABLE_EXTENDED_CONST_EXPR 0
725+
#endif
726+
723727
#endif /* end of _CONFIG_H_ */

core/iwasm/aot/aot_loader.c

Lines changed: 91 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,35 @@ load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
968968
return false;
969969
}
970970

971+
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
972+
static void
973+
destroy_init_expr(InitializerExpression *expr)
974+
{
975+
#if WASM_ENABLE_GC != 0
976+
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
977+
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
978+
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
979+
wasm_runtime_free(expr->u.unary.v.data);
980+
}
981+
#endif
982+
983+
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
984+
// free left expr and right expr for binary oprand
985+
if (!is_expr_binary_op(expr->init_expr_type)) {
986+
return;
987+
}
988+
if (expr->u.binary.l_expr) {
989+
destroy_init_expr_recursive(expr->u.binary.l_expr);
990+
}
991+
if (expr->u.binary.r_expr) {
992+
destroy_init_expr_recursive(expr->u.binary.r_expr);
993+
}
994+
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
995+
#endif
996+
}
997+
#endif /* end of WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0 \
998+
*/
999+
9711000
static void
9721001
destroy_import_memories(AOTImportMemory *import_memories)
9731002
{
@@ -993,6 +1022,10 @@ destroy_mem_init_data_list(AOTModule *module, AOTMemInitData **data_list,
9931022
/* If the module owns the binary data, free the bytes buffer */
9941023
if (module->is_binary_freeable && data_list[i]->bytes)
9951024
wasm_runtime_free(data_list[i]->bytes);
1025+
1026+
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
1027+
destroy_init_expr(&data_list[i]->offset);
1028+
#endif
9961029
/* Free the data segment structure itself */
9971030
wasm_runtime_free(data_list[i]);
9981031
}
@@ -1043,11 +1076,11 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
10431076
uint32 byte_count;
10441077
uint32 is_passive;
10451078
uint32 memory_index;
1046-
InitializerExpression init_value;
1079+
InitializerExpression offset_expr;
10471080

10481081
read_uint32(buf, buf_end, is_passive);
10491082
read_uint32(buf, buf_end, memory_index);
1050-
if (!load_init_expr(&buf, buf_end, module, &init_value, error_buf,
1083+
if (!load_init_expr(&buf, buf_end, module, &offset_expr, error_buf,
10511084
error_buf_size)) {
10521085
return false;
10531086
}
@@ -1062,8 +1095,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
10621095
data_list[i]->is_passive = (bool)is_passive;
10631096
data_list[i]->memory_index = memory_index;
10641097
#endif
1065-
data_list[i]->offset.init_expr_type = init_value.init_expr_type;
1066-
data_list[i]->offset.u = init_value.u;
1098+
data_list[i]->offset = offset_expr;
10671099
data_list[i]->byte_count = byte_count;
10681100
data_list[i]->bytes = NULL;
10691101
/* If the module owns the binary data, clone the bytes buffer */
@@ -1148,18 +1180,6 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
11481180
return false;
11491181
}
11501182

1151-
#if WASM_ENABLE_GC != 0
1152-
static void
1153-
destroy_init_expr(InitializerExpression *expr)
1154-
{
1155-
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
1156-
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
1157-
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
1158-
wasm_runtime_free(expr->u.data);
1159-
}
1160-
}
1161-
#endif /* end of WASM_ENABLE_GC != 0 */
1162-
11631183
static void
11641184
destroy_import_tables(AOTImportTable *import_tables)
11651185
{
@@ -1183,6 +1203,9 @@ destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
11831203
for (j = 0; j < data_list[i]->value_count; j++) {
11841204
destroy_init_expr(&data_list[i]->init_values[j]);
11851205
}
1206+
#endif
1207+
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
1208+
destroy_init_expr(&data_list[i]->offset);
11861209
#endif
11871210
wasm_runtime_free(data_list[i]);
11881211
}
@@ -1208,34 +1231,34 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
12081231
break;
12091232
case INIT_EXPR_TYPE_I32_CONST:
12101233
case INIT_EXPR_TYPE_F32_CONST:
1211-
read_uint32(buf, buf_end, expr->u.i32);
1234+
read_uint32(buf, buf_end, expr->u.unary.v.i32);
12121235
break;
12131236
case INIT_EXPR_TYPE_I64_CONST:
12141237
case INIT_EXPR_TYPE_F64_CONST:
1215-
read_uint64(buf, buf_end, expr->u.i64);
1238+
read_uint64(buf, buf_end, expr->u.unary.v.i64);
12161239
break;
12171240
case INIT_EXPR_TYPE_V128_CONST:
1218-
i64x2 = (uint64 *)expr->u.v128.i64x2;
1241+
i64x2 = (uint64 *)expr->u.unary.v.v128.i64x2;
12191242
CHECK_BUF(buf, buf_end, sizeof(uint64) * 2);
12201243
wasm_runtime_read_v128(buf, &i64x2[0], &i64x2[1]);
12211244
buf += sizeof(uint64) * 2;
12221245
break;
12231246
case INIT_EXPR_TYPE_GET_GLOBAL:
1224-
read_uint32(buf, buf_end, expr->u.global_index);
1247+
read_uint32(buf, buf_end, expr->u.unary.v.global_index);
12251248
break;
12261249
/* INIT_EXPR_TYPE_FUNCREF_CONST can be used when
12271250
both reference types and GC are disabled */
12281251
case INIT_EXPR_TYPE_FUNCREF_CONST:
1229-
read_uint32(buf, buf_end, expr->u.ref_index);
1252+
read_uint32(buf, buf_end, expr->u.unary.v.ref_index);
12301253
break;
12311254
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0
12321255
case INIT_EXPR_TYPE_REFNULL_CONST:
1233-
read_uint32(buf, buf_end, expr->u.ref_index);
1256+
read_uint32(buf, buf_end, expr->u.unary.v.ref_index);
12341257
break;
12351258
#endif /* end of WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0 */
12361259
#if WASM_ENABLE_GC != 0
12371260
case INIT_EXPR_TYPE_I31_NEW:
1238-
read_uint32(buf, buf_end, expr->u.i32);
1261+
read_uint32(buf, buf_end, expr->u.unary.v.i32);
12391262
break;
12401263
case INIT_EXPR_TYPE_STRUCT_NEW:
12411264
{
@@ -1256,7 +1279,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
12561279
free_if_fail = true;
12571280
init_values->count = field_count;
12581281
init_values->type_idx = type_idx;
1259-
expr->u.data = init_values;
1282+
expr->u.unary.v.data = init_values;
12601283

12611284
if (type_idx >= module->type_count) {
12621285
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,
12941317
break;
12951318
}
12961319
case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
1297-
read_uint32(buf, buf_end, expr->u.type_index);
1320+
read_uint32(buf, buf_end, expr->u.unary.v.type_index);
12981321
break;
12991322
case INIT_EXPR_TYPE_ARRAY_NEW:
13001323
case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
@@ -1317,8 +1340,8 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
13171340
}
13181341

13191342
if (init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
1320-
expr->u.array_new_default.type_index = type_idx;
1321-
expr->u.array_new_default.length = length;
1343+
expr->u.unary.v.array_new_default.type_index = type_idx;
1344+
expr->u.unary.v.array_new_default.length = length;
13221345
}
13231346
else {
13241347
uint32 i, elem_size, elem_data_count;
@@ -1329,7 +1352,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
13291352
return false;
13301353
}
13311354
free_if_fail = true;
1332-
expr->u.data = init_values;
1355+
expr->u.unary.v.data = init_values;
13331356

13341357
init_values->type_idx = type_idx;
13351358
init_values->length = length;
@@ -1357,6 +1380,34 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
13571380
break;
13581381
}
13591382
#endif /* end of WASM_ENABLE_GC != 0 */
1383+
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
1384+
case INIT_EXPR_TYPE_I32_ADD:
1385+
case INIT_EXPR_TYPE_I32_SUB:
1386+
case INIT_EXPR_TYPE_I32_MUL:
1387+
case INIT_EXPR_TYPE_I64_ADD:
1388+
case INIT_EXPR_TYPE_I64_SUB:
1389+
case INIT_EXPR_TYPE_I64_MUL:
1390+
{
1391+
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
1392+
if (!(expr->u.binary.l_expr =
1393+
loader_malloc(sizeof(InitializerExpression), error_buf,
1394+
error_buf_size))) {
1395+
goto fail;
1396+
}
1397+
if (!load_init_expr(&buf, buf_end, module, expr->u.binary.l_expr,
1398+
error_buf, error_buf_size))
1399+
goto fail;
1400+
if (!(expr->u.binary.r_expr =
1401+
loader_malloc(sizeof(InitializerExpression), error_buf,
1402+
error_buf_size))) {
1403+
goto fail;
1404+
}
1405+
if (!load_init_expr(&buf, buf_end, module, expr->u.binary.r_expr,
1406+
error_buf, error_buf_size))
1407+
goto fail;
1408+
break;
1409+
}
1410+
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
13601411
default:
13611412
set_error_buf(error_buf, error_buf_size, "invalid init expr type.");
13621413
return false;
@@ -1369,10 +1420,13 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
13691420
fail:
13701421
#if WASM_ENABLE_GC != 0
13711422
if (free_if_fail) {
1372-
wasm_runtime_free(expr->u.data);
1423+
wasm_runtime_free(expr->u.unary.v.data);
13731424
}
13741425
#else
13751426
(void)free_if_fail;
1427+
#endif
1428+
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
1429+
destroy_init_expr(expr);
13761430
#endif
13771431
return false;
13781432
}
@@ -1535,14 +1589,16 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
15351589
/* Create each table data segment */
15361590
for (i = 0; i < module->table_init_data_count; i++) {
15371591
uint32 mode, elem_type;
1538-
uint32 table_index, init_expr_type, value_count;
1539-
uint64 init_expr_value, size1;
1592+
uint32 table_index, value_count;
1593+
uint64 size1;
1594+
InitializerExpression offset_expr;
15401595

15411596
read_uint32(buf, buf_end, mode);
15421597
read_uint32(buf, buf_end, elem_type);
15431598
read_uint32(buf, buf_end, table_index);
1544-
read_uint32(buf, buf_end, init_expr_type);
1545-
read_uint64(buf, buf_end, init_expr_value);
1599+
if (!load_init_expr(&buf, buf_end, module, &offset_expr, error_buf,
1600+
error_buf_size))
1601+
return false;
15461602
#if WASM_ENABLE_GC != 0
15471603
if (wasm_is_type_multi_byte_type(elem_type)) {
15481604
uint16 ref_type, nullable;
@@ -1588,8 +1644,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
15881644
}
15891645
}
15901646
#endif
1591-
data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
1592-
data_list[i]->offset.u.i64 = (int64)init_expr_value;
1647+
data_list[i]->offset = offset_expr;
15931648
data_list[i]->value_count = value_count;
15941649
for (j = 0; j < data_list[i]->value_count; j++) {
15951650
if (!load_init_expr(&buf, buf_end, module,
@@ -4500,7 +4555,7 @@ aot_unload(AOTModule *module)
45004555
destroy_import_globals(module->import_globals);
45014556

45024557
if (module->globals) {
4503-
#if WASM_ENABLE_GC != 0
4558+
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
45044559
uint32 i;
45054560
for (i = 0; i < module->global_count; i++) {
45064561
destroy_init_expr(&module->globals[i].init_expr);

0 commit comments

Comments
 (0)