Skip to content

Commit 36d4380

Browse files
Support table64 extension in classic-interp and AOT running modes (#3811)
Add table64 extension(in Memory64 proposal) support in classic-interp and AOT running modes, currently still use uint32 to represent table's initial and maximum size to keep AOT ABI unchanged.
1 parent 2b5e2d9 commit 36d4380

File tree

16 files changed

+922
-175
lines changed

16 files changed

+922
-175
lines changed

core/iwasm/aot/aot_loader.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,12 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
13821382
for (i = 0; i < module->table_count; i++, table++) {
13831383
read_uint8(buf, buf_end, table->table_type.elem_type);
13841384
read_uint8(buf, buf_end, table->table_type.flags);
1385+
1386+
if (!wasm_table_check_flags(table->table_type.flags, error_buf,
1387+
error_buf_size, true)) {
1388+
return false;
1389+
}
1390+
13851391
read_uint8(buf, buf_end, table->table_type.possible_grow);
13861392
#if WASM_ENABLE_GC != 0
13871393
if (wasm_is_type_multi_byte_type(table->table_type.elem_type)) {

core/iwasm/aot/aot_runtime.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -737,18 +737,24 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
737737

738738
#if WASM_ENABLE_REF_TYPES != 0
739739
bh_assert(
740-
table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
740+
table_seg->offset.init_expr_type
741+
== (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
742+
: INIT_EXPR_TYPE_I32_CONST)
741743
|| table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
742744
|| table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
743745
|| table_seg->offset.init_expr_type
744746
== INIT_EXPR_TYPE_REFNULL_CONST);
745747
#else
746-
bh_assert(table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
748+
bh_assert(table_seg->offset.init_expr_type
749+
== (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
750+
: INIT_EXPR_TYPE_I32_CONST)
747751
|| table_seg->offset.init_expr_type
748752
== INIT_EXPR_TYPE_GET_GLOBAL);
749753
#endif
750754

751755
/* Resolve table data base offset */
756+
/* TODO: The table64 current implementation assumes table max size
757+
* UINT32_MAX, so the offset conversion here is safe */
752758
if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
753759
global_index = table_seg->offset.u.global_index;
754760

core/iwasm/common/wasm_loader_common.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,37 @@ wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size,
1919
}
2020
}
2121

22+
#if WASM_ENABLE_MEMORY64 != 0
23+
bool
24+
check_memory64_flags_consistency(WASMModule *module, char *error_buf,
25+
uint32 error_buf_size, bool is_aot)
26+
{
27+
uint32 i;
28+
bool wasm64_flag, all_wasm64 = true, none_wasm64 = true;
29+
30+
for (i = 0; i < module->import_memory_count; ++i) {
31+
wasm64_flag =
32+
module->import_memories[i].u.memory.mem_type.flags & MEMORY64_FLAG;
33+
all_wasm64 &= wasm64_flag;
34+
none_wasm64 &= !wasm64_flag;
35+
}
36+
37+
for (i = 0; i < module->memory_count; ++i) {
38+
wasm64_flag = module->memories[i].flags & MEMORY64_FLAG;
39+
all_wasm64 &= wasm64_flag;
40+
none_wasm64 &= !wasm64_flag;
41+
}
42+
43+
if (!(all_wasm64 || none_wasm64)) {
44+
wasm_loader_set_error_buf(
45+
error_buf, error_buf_size,
46+
"inconsistent limits wasm64 flags for memory sections", is_aot);
47+
return false;
48+
}
49+
return true;
50+
}
51+
#endif
52+
2253
bool
2354
wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
2455
uint32 error_buf_size, bool is_aot)
@@ -60,6 +91,37 @@ wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
6091
return true;
6192
}
6293

94+
bool
95+
wasm_table_check_flags(const uint8 table_flag, char *error_buf,
96+
uint32 error_buf_size, bool is_aot)
97+
{
98+
/* Check whether certain features indicated by mem_flag are enabled in
99+
* runtime */
100+
if (table_flag > MAX_TABLE_SIZE_FLAG) {
101+
if (table_flag & SHARED_TABLE_FLAG) {
102+
wasm_loader_set_error_buf(error_buf, error_buf_size,
103+
"tables cannot be shared", is_aot);
104+
}
105+
#if WASM_ENABLE_MEMORY64 == 0
106+
if (table_flag & TABLE64_FLAG) {
107+
wasm_loader_set_error_buf(error_buf, error_buf_size,
108+
"invalid limits flags(table64 flag was "
109+
"found, please enable memory64)",
110+
is_aot);
111+
return false;
112+
}
113+
#endif
114+
}
115+
116+
if (table_flag > MAX_TABLE_SIZE_FLAG + TABLE64_FLAG) {
117+
wasm_loader_set_error_buf(error_buf, error_buf_size,
118+
"invalid limits flags", is_aot);
119+
return false;
120+
}
121+
122+
return true;
123+
}
124+
63125
/*
64126
* compare with a bigger type set in `wasm_value_type_size_internal()`,
65127
* this function will only cover global value type, function's param

core/iwasm/common/wasm_loader_common.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,22 @@
1313
extern "C" {
1414
#endif
1515

16+
#if WASM_ENABLE_MEMORY64 != 0
17+
/* check consistency of memory64 flags across all memories,
18+
* they must be either all wasm64 or all wasm32 */
19+
bool
20+
check_memory64_flags_consistency(WASMModule *module, char *error_buf,
21+
uint32 error_buf_size, bool is_aot);
22+
#endif
23+
1624
bool
1725
wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
1826
uint32 error_buf_size, bool is_aot);
1927

28+
bool
29+
wasm_table_check_flags(const uint8 table_flag, char *error_buf,
30+
uint32 error_buf_size, bool is_aot);
31+
2032
bool
2133
is_valid_value_type(uint8 value_tpye);
2234

core/iwasm/compilation/aot_compiler.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,20 @@ aot_validate_wasm(AOTCompContext *comp_ctx)
146146
}
147147

148148
#if WASM_ENABLE_MEMORY64 != 0
149-
if (comp_ctx->pointer_size < sizeof(uint64) && IS_MEMORY64) {
150-
aot_set_last_error("Compiling wasm64 to 32bit platform is not allowed");
151-
return false;
149+
if (comp_ctx->pointer_size < sizeof(uint64)) {
150+
if (IS_MEMORY64) {
151+
aot_set_last_error("Compiling wasm64(contains i64 memory section) "
152+
"to 32bit platform is not allowed");
153+
return false;
154+
}
155+
156+
for (uint32 i = 0; i < comp_ctx->comp_data->table_count; ++i) {
157+
if (IS_TABLE64(i)) {
158+
aot_set_last_error("Compiling wasm64(contains i64 table "
159+
"section) to 32bit platform is not allowed");
160+
return false;
161+
}
162+
}
152163
}
153164
#endif
154165

core/iwasm/compilation/aot_compiler.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,13 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
532532
#define IS_MEMORY64 (comp_ctx->comp_data->memories[0].flags & MEMORY64_FLAG)
533533
#define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
534534
(IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
535+
#define IS_TABLE64(i) \
536+
(comp_ctx->comp_data->tables[i].table_type.flags & TABLE64_FLAG)
537+
#define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) \
538+
(IS_TABLE64(i) ? VAL_IF_ENABLED : VAL_IF_DISABLED)
535539
#else
536540
#define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
541+
#define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
537542
#endif
538543

539544
#define POP_I32(v) POP(v, VALUE_TYPE_I32)
@@ -548,6 +553,9 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
548553
POP(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
549554
#define POP_PAGE_COUNT(v) \
550555
POP(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
556+
#define POP_TBL_ELEM_IDX(v) \
557+
POP(v, TABLE64_COND_VALUE(tbl_idx, VALUE_TYPE_I64, VALUE_TYPE_I32))
558+
#define POP_TBL_ELEM_LEN(v) POP_TBL_ELEM_IDX(v)
551559

552560
#define POP_COND(llvm_value) \
553561
do { \
@@ -613,6 +621,9 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
613621
#define PUSH_GC_REF(v) PUSH(v, VALUE_TYPE_GC_REF)
614622
#define PUSH_PAGE_COUNT(v) \
615623
PUSH(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
624+
#define PUSH_TBL_ELEM_IDX(v) \
625+
PUSH(v, TABLE64_COND_VALUE(tbl_idx, VALUE_TYPE_I64, VALUE_TYPE_I32))
626+
#define PUSH_TBL_ELEM_LEN(v) PUSH_TBL_ELEM_IDX(v)
616627

617628
#define SET_CONST(v) \
618629
do { \

core/iwasm/compilation/aot_emit_function.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,6 +2089,9 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
20892089
LLVMValueRef ext_ret_offset, ext_ret_ptr, ext_ret, res;
20902090
LLVMValueRef *param_values = NULL, *value_rets = NULL;
20912091
LLVMValueRef *result_phis = NULL, value_ret, import_func_count;
2092+
#if WASM_ENABLE_MEMORY64 != 0
2093+
LLVMValueRef u32_max, u32_cmp_result;
2094+
#endif
20922095
LLVMTypeRef *param_types = NULL, ret_type;
20932096
LLVMTypeRef llvm_func_type, llvm_func_ptr_type;
20942097
LLVMTypeRef ext_ret_ptr_type;
@@ -2153,7 +2156,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
21532156
func_param_count = func_type->param_count;
21542157
func_result_count = func_type->result_count;
21552158

2156-
POP_I32(elem_idx);
2159+
POP_TBL_ELEM_IDX(elem_idx);
21572160

21582161
/* get the cur size of the table instance */
21592162
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
@@ -2182,14 +2185,47 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
21822185
goto fail;
21832186
}
21842187

2188+
#if WASM_ENABLE_MEMORY64 != 0
2189+
/* Check if elem index >= UINT32_MAX */
2190+
if (IS_TABLE64(tbl_idx)) {
2191+
if (!(u32_max = I64_CONST(UINT32_MAX))) {
2192+
aot_set_last_error("llvm build const failed");
2193+
goto fail;
2194+
}
2195+
if (!(u32_cmp_result =
2196+
LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
2197+
u32_max, "cmp_elem_idx_u32_max"))) {
2198+
aot_set_last_error("llvm build icmp failed.");
2199+
goto fail;
2200+
}
2201+
if (!(elem_idx = LLVMBuildTrunc(comp_ctx->builder, elem_idx, I32_TYPE,
2202+
"elem_idx_i32"))) {
2203+
aot_set_last_error("llvm build trunc failed.");
2204+
goto fail;
2205+
}
2206+
}
2207+
#endif
2208+
21852209
/* Check if (uint32)elem index >= table size */
21862210
if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
21872211
table_size_const, "cmp_elem_idx"))) {
21882212
aot_set_last_error("llvm build icmp failed.");
21892213
goto fail;
21902214
}
21912215

2192-
/* Throw exception if elem index >= table size */
2216+
#if WASM_ENABLE_MEMORY64 != 0
2217+
if (IS_TABLE64(tbl_idx)) {
2218+
if (!(cmp_elem_idx =
2219+
LLVMBuildOr(comp_ctx->builder, cmp_elem_idx, u32_cmp_result,
2220+
"larger_than_u32_max_or_cur_size"))) {
2221+
aot_set_last_error("llvm build or failed.");
2222+
goto fail;
2223+
}
2224+
}
2225+
#endif
2226+
2227+
/* Throw exception if elem index >= table size or elem index >= UINT32_MAX
2228+
*/
21932229
if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
21942230
comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
21952231
aot_set_last_error("llvm add basic block failed.");

0 commit comments

Comments
 (0)