Enhance aot feature flags emit and load (#3048)

- Emit SIMD/ref-types/bulk-memory flags into AOT file only when the features
  are really used in wasm file
- Remove unused tail-call flag and stringref flag
- Add memoy64 flag and dynamic-linking flag
- Change WASM_FEATURE_THREADS to WASM_FEATURE_MULTI_THREAD
This commit is contained in:
Wenyong Huang 2024-01-23 16:15:04 +08:00 committed by GitHub
parent 4f0551ac25
commit 7c812ece9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 166 additions and 30 deletions

View File

@ -481,7 +481,7 @@ check_feature_flags(char *error_buf, uint32 error_buf_size,
#endif #endif
#if WASM_ENABLE_THREAD_MGR == 0 #if WASM_ENABLE_THREAD_MGR == 0
if (feature_flags & WASM_FEATURE_THREADS) { if (feature_flags & WASM_FEATURE_MULTI_THREAD) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"thread is not enabled in this build"); "thread is not enabled in this build");
return false; return false;
@ -496,14 +496,6 @@ check_feature_flags(char *error_buf, uint32 error_buf_size,
} }
#endif #endif
#if WASM_ENABLE_TAIL_CALL == 0
if (feature_flags & WASM_FEATURE_TAIL_CALL) {
set_error_buf(error_buf, error_buf_size,
"tail call is not enabled in this build");
return false;
}
#endif
#if WASM_ENABLE_GC == 0 #if WASM_ENABLE_GC == 0
if (feature_flags & WASM_FEATURE_GARBAGE_COLLECTION) { if (feature_flags & WASM_FEATURE_GARBAGE_COLLECTION) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
@ -1186,8 +1178,12 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
case INIT_EXPR_TYPE_GET_GLOBAL: case INIT_EXPR_TYPE_GET_GLOBAL:
read_uint32(buf, buf_end, expr->u.global_index); read_uint32(buf, buf_end, expr->u.global_index);
break; break;
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0 /* INIT_EXPR_TYPE_FUNCREF_CONST can be used when
both reference types and GC are disabled */
case INIT_EXPR_TYPE_FUNCREF_CONST: case INIT_EXPR_TYPE_FUNCREF_CONST:
read_uint32(buf, buf_end, expr->u.ref_index);
break;
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0
case INIT_EXPR_TYPE_REFNULL_CONST: case INIT_EXPR_TYPE_REFNULL_CONST:
read_uint32(buf, buf_end, expr->u.ref_index); read_uint32(buf, buf_end, expr->u.ref_index);
break; break;

View File

@ -25,16 +25,16 @@ extern "C" {
/* Wasm feature supported, mainly used by AOTTargetInfo now */ /* Wasm feature supported, mainly used by AOTTargetInfo now */
#define WASM_FEATURE_SIMD_128BIT (1 << 0) #define WASM_FEATURE_SIMD_128BIT (1 << 0)
#define WASM_FEATURE_BULK_MEMORY (1 << 1) #define WASM_FEATURE_BULK_MEMORY (1 << 1)
#define WASM_FEATURE_THREADS (1 << 2) #define WASM_FEATURE_MULTI_THREAD (1 << 2)
#define WASM_FEATURE_REF_TYPES (1 << 3) #define WASM_FEATURE_REF_TYPES (1 << 3)
#define WASM_FEATURE_TAIL_CALL (1 << 4) #define WASM_FEATURE_GARBAGE_COLLECTION (1 << 4)
#define WASM_FEATURE_EXCEPTION_HANDLING (1 << 5) #define WASM_FEATURE_EXCEPTION_HANDLING (1 << 5)
#define WASM_FEATURE_GARBAGE_COLLECTION (1 << 6) #define WASM_FEATURE_MEMORY64 (1 << 6)
#define WASM_FEATURE_COMPONENT_MODEL (1 << 7) #define WASM_FEATURE_MULTI_MEMORY (1 << 7)
#define WASM_FEATURE_MULTIPLE_MEMORY (1 << 8) #define WASM_FEATURE_DYNAMIC_LINKING (1 << 8)
#define WASM_FEATURE_RELAXED_SIMD (1 << 9) #define WASM_FEATURE_COMPONENT_MODEL (1 << 9)
#define WASM_FEATURE_FLEXIBLE_VECTORS (1 << 10) #define WASM_FEATURE_RELAXED_SIMD (1 << 10)
#define WASM_FEATURE_STRING_REF (1 << 11) #define WASM_FEATURE_FLEXIBLE_VECTORS (1 << 11)
typedef enum AOTSectionType { typedef enum AOTSectionType {
AOT_SECTION_TYPE_TARGET_INFO = 0, AOT_SECTION_TYPE_TARGET_INFO = 0,

View File

@ -4389,14 +4389,11 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
obj_data->target_info.feature_flags |= WASM_FEATURE_BULK_MEMORY; obj_data->target_info.feature_flags |= WASM_FEATURE_BULK_MEMORY;
} }
if (comp_ctx->enable_thread_mgr) { if (comp_ctx->enable_thread_mgr) {
obj_data->target_info.feature_flags |= WASM_FEATURE_THREADS; obj_data->target_info.feature_flags |= WASM_FEATURE_MULTI_THREAD;
} }
if (comp_ctx->enable_ref_types) { if (comp_ctx->enable_ref_types) {
obj_data->target_info.feature_flags |= WASM_FEATURE_REF_TYPES; obj_data->target_info.feature_flags |= WASM_FEATURE_REF_TYPES;
} }
if (comp_ctx->enable_tail_call) {
obj_data->target_info.feature_flags |= WASM_FEATURE_TAIL_CALL;
}
if (comp_ctx->enable_gc) { if (comp_ctx->enable_gc) {
obj_data->target_info.feature_flags |= WASM_FEATURE_GARBAGE_COLLECTION; obj_data->target_info.feature_flags |= WASM_FEATURE_GARBAGE_COLLECTION;
} }

View File

@ -3075,17 +3075,25 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
LLVMDisposeMessage(triple); LLVMDisposeMessage(triple);
#if WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_WAMR_COMPILER != 0
WASMModule *wasm_module = (WASMModule *)comp_data->wasm_module;
/* Return error if SIMD is disabled by command line but SIMD instructions /* Return error if SIMD is disabled by command line but SIMD instructions
* are used */ * are used */
if (!option->enable_simd if (!option->enable_simd && wasm_module->is_simd_used) {
&& ((WASMModule *)comp_data->wasm_module)->is_simd_used) {
aot_set_last_error("SIMD is disabled by --disable-simd but SIMD " aot_set_last_error("SIMD is disabled by --disable-simd but SIMD "
"instructions are used in this module"); "instructions are used in this module");
goto fail; goto fail;
} }
if (!((WASMModule *)comp_data->wasm_module)->is_simd_used) { /* Disable features when they are not actually used */
option->enable_simd = false; if (!wasm_module->is_simd_used) {
option->enable_simd = comp_ctx->enable_simd = false;
}
if (!wasm_module->is_ref_types_used) {
option->enable_ref_types = comp_ctx->enable_ref_types = false;
}
if (!wasm_module->is_bulk_memory_used) {
option->enable_bulk_memory = comp_ctx->enable_bulk_memory = false;
} }
#endif #endif

View File

@ -980,6 +980,8 @@ struct WASMModule {
#if WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_WAMR_COMPILER != 0
bool is_simd_used; bool is_simd_used;
bool is_ref_types_used;
bool is_bulk_memory_used;
#endif #endif
}; };

View File

@ -854,6 +854,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
0, &cur_value, error_buf, 0, &cur_value, error_buf,
error_buf_size)) error_buf_size))
goto fail; goto fail;
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif #endif
break; break;
} }
@ -896,6 +899,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
error_buf_size)) error_buf_size))
goto fail; goto fail;
} }
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif #endif
break; break;
} }
@ -1619,6 +1625,13 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
type->quick_aot_entry = wasm_native_lookup_quick_aot_entry(type); type->quick_aot_entry = wasm_native_lookup_quick_aot_entry(type);
#endif #endif
#if WASM_ENABLE_WAMR_COMPILER != 0
for (i = 0; i < type->param_count + type->result_count; i++) {
if (type->types[i] == VALUE_TYPE_V128)
module->is_simd_used = true;
}
#endif
/* Calculate the minimal type index of the type equal to this type */ /* Calculate the minimal type index of the type equal to this type */
type->min_type_idx_normalized = type_idx; type->min_type_idx_normalized = type_idx;
for (i = 0; i < type_idx; i++) { for (i = 0; i < type_idx; i++) {
@ -1994,6 +2007,16 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
type->quick_aot_entry = wasm_native_lookup_quick_aot_entry(type); type->quick_aot_entry = wasm_native_lookup_quick_aot_entry(type);
#endif #endif
#if WASM_ENABLE_WAMR_COMPILER != 0
for (j = 0; j < type->param_count + type->result_count; j++) {
if (type->types[j] == VALUE_TYPE_V128)
module->is_simd_used = true;
else if (type->types[j] == VALUE_TYPE_FUNCREF
|| type->types[j] == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
}
#endif
/* If there is already a same type created, use it instead */ /* If there is already a same type created, use it instead */
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
if (wasm_type_equal(type, module->types[j], module->types, i)) { if (wasm_type_equal(type, module->types[j], module->types, i)) {
@ -2627,6 +2650,10 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
table->flags = declare_max_size_flag; table->flags = declare_max_size_flag;
table->max_size = declare_max_size; table->max_size = declare_max_size;
#if WASM_ENABLE_WAMR_COMPILER != 0
if (table->elem_type == VALUE_TYPE_EXTERNREF)
parent_module->is_ref_types_used = true;
#endif
(void)parent_module; (void)parent_module;
return true; return true;
fail: fail:
@ -2868,6 +2895,12 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
global->type = declare_type; global->type = declare_type;
global->is_mutable = (declare_mutable == 1); global->is_mutable = (declare_mutable == 1);
#if WASM_ENABLE_WAMR_COMPILER != 0
if (global->type == VALUE_TYPE_V128)
parent_module->is_simd_used = true;
else if (global->type == VALUE_TYPE_EXTERNREF)
parent_module->is_ref_types_used = true;
#endif
(void)parent_module; (void)parent_module;
(void)ret; (void)ret;
return true; return true;
@ -2955,6 +2988,11 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
adjust_table_max_size(table->init_size, table->flags, &table->max_size); adjust_table_max_size(table->init_size, table->flags, &table->max_size);
#if WASM_ENABLE_WAMR_COMPILER != 0
if (table->elem_type == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
#endif
*p_buf = p; *p_buf = p;
return true; return true;
fail: fail:
@ -3095,13 +3133,15 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
read_leb_uint32(p, p_end, u32); read_leb_uint32(p, p_end, u32);
module->import_table_count++; module->import_table_count++;
#if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0
if (module->import_table_count > 1) { if (module->import_table_count > 1) {
#if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"multiple tables"); "multiple tables");
return false; return false;
} #elif WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif #endif
}
break; break;
case IMPORT_KIND_MEMORY: /* import memory */ case IMPORT_KIND_MEMORY: /* import memory */
@ -3510,6 +3550,13 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
for (k = 0; k < sub_local_count; k++) { for (k = 0; k < sub_local_count; k++) {
func->local_types[local_type_index++] = type; func->local_types[local_type_index++] = type;
} }
#if WASM_ENABLE_WAMR_COMPILER != 0
if (type == VALUE_TYPE_V128)
module->is_simd_used = true;
else if (type == VALUE_TYPE_FUNCREF
|| type == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
#endif
} }
bh_assert(local_type_index == func->local_count); bh_assert(local_type_index == func->local_count);
@ -3573,13 +3620,15 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
WASMTable *table; WASMTable *table;
read_leb_uint32(p, p_end, table_count); read_leb_uint32(p, p_end, table_count);
#if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0
if (module->import_table_count + table_count > 1) { if (module->import_table_count + table_count > 1) {
#if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0
/* a total of one table is allowed */ /* a total of one table is allowed */
set_error_buf(error_buf, error_buf_size, "multiple tables"); set_error_buf(error_buf, error_buf_size, "multiple tables");
return false; return false;
} #elif WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif #endif
}
if (table_count) { if (table_count) {
module->table_count = table_count; module->table_count = table_count;
@ -3643,6 +3692,11 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
} }
} }
#endif /* end of WASM_ENABLE_GC != 0 */ #endif /* end of WASM_ENABLE_GC != 0 */
#if WASM_ENABLE_WAMR_COMPILER != 0
if (table->elem_type == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
#endif
} }
} }
@ -3741,6 +3795,14 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
mutable = read_uint8(p); mutable = read_uint8(p);
#endif /* end of WASM_ENABLE_GC */ #endif /* end of WASM_ENABLE_GC */
#if WASM_ENABLE_WAMR_COMPILER != 0
if (global->type == VALUE_TYPE_V128)
module->is_simd_used = true;
else if (global->type == VALUE_TYPE_FUNCREF
|| global->type == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
#endif
if (!check_mutability(mutable, error_buf, error_buf_size)) { if (!check_mutability(mutable, error_buf, error_buf_size)) {
return false; return false;
} }
@ -4302,6 +4364,11 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
error_buf, error_buf_size)) error_buf, error_buf_size))
return false; return false;
#endif /* WASM_ENABLE_REF_TYPES != 0 */ #endif /* WASM_ENABLE_REF_TYPES != 0 */
#if WASM_ENABLE_WAMR_COMPILER != 0
if (table_segment->elem_type == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
#endif
} }
} }
@ -4358,6 +4425,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
switch (mem_flag) { switch (mem_flag) {
case 0x01: case 0x01:
is_passive = true; is_passive = true;
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif
break; break;
case 0x00: case 0x00:
/* no memory index, treat index as 0 */ /* no memory index, treat index as 0 */
@ -4366,6 +4436,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
case 0x02: case 0x02:
/* read following memory index */ /* read following memory index */
read_leb_uint32(p, p_end, mem_index); read_leb_uint32(p, p_end, mem_index);
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif
check_mem_index: check_mem_index:
if (mem_index if (mem_index
>= module->import_memory_count + module->memory_count) { >= module->import_memory_count + module->memory_count) {
@ -4451,6 +4524,9 @@ load_datacount_section(const uint8 *buf, const uint8 *buf_end,
return false; return false;
} }
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif
LOG_VERBOSE("Load datacount section success.\n"); LOG_VERBOSE("Load datacount section success.\n");
return true; return true;
fail: fail:
@ -10184,6 +10260,13 @@ re_scan:
* the single return value. */ * the single return value. */
block_type.is_value_type = true; block_type.is_value_type = true;
block_type.u.value_type.type = value_type; block_type.u.value_type.type = value_type;
#if WASM_ENABLE_WAMR_COMPILER != 0
if (value_type == VALUE_TYPE_V128)
module->is_simd_used = true;
else if (value_type == VALUE_TYPE_FUNCREF
|| value_type == VALUE_TYPE_EXTERNREF)
module->is_ref_types_used = true;
#endif
#if WASM_ENABLE_GC != 0 #if WASM_ENABLE_GC != 0
if (value_type != VALUE_TYPE_VOID) { if (value_type != VALUE_TYPE_VOID) {
p_org = p; p_org = p;
@ -11274,6 +11357,9 @@ re_scan:
#endif #endif
PUSH_REF(type); PUSH_REF(type);
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
(void)vec_len; (void)vec_len;
break; break;
} }
@ -11325,6 +11411,9 @@ re_scan:
POP_I32(); POP_I32();
} }
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_REF_NULL: case WASM_OP_REF_NULL:
@ -11365,6 +11454,10 @@ re_scan:
PUSH_OFFSET_TYPE(ref_type); PUSH_OFFSET_TYPE(ref_type);
#endif #endif
PUSH_TYPE(ref_type); PUSH_TYPE(ref_type);
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_REF_IS_NULL: case WASM_OP_REF_IS_NULL:
@ -11416,6 +11509,10 @@ re_scan:
} }
#endif #endif
PUSH_I32(); PUSH_I32();
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_REF_FUNC: case WASM_OP_REF_FUNC:
@ -11483,6 +11580,10 @@ re_scan:
false, type_idx); false, type_idx);
PUSH_REF(wasm_ref_type.ref_type); PUSH_REF(wasm_ref_type.ref_type);
#endif #endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
#endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */ #endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */
@ -13426,6 +13527,9 @@ re_scan:
POP_I32(); POP_I32();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif #endif
break; break;
} }
@ -13446,6 +13550,9 @@ re_scan:
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif #endif
break; break;
} }
@ -13465,6 +13572,9 @@ re_scan:
POP_I32(); POP_I32();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif #endif
break; break;
} }
@ -13483,6 +13593,9 @@ re_scan:
POP_I32(); POP_I32();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_bulk_memory_used = true;
#endif #endif
break; break;
} }
@ -13553,6 +13666,10 @@ re_scan:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); POP_I32();
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_ELEM_DROP: case WASM_OP_ELEM_DROP:
@ -13565,6 +13682,10 @@ re_scan:
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, table_seg_idx); emit_uint32(loader_ctx, table_seg_idx);
#endif #endif
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_TABLE_COPY: case WASM_OP_TABLE_COPY:
@ -13618,6 +13739,10 @@ re_scan:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); POP_I32();
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_TABLE_SIZE: case WASM_OP_TABLE_SIZE:
@ -13634,6 +13759,10 @@ re_scan:
#endif #endif
PUSH_I32(); PUSH_I32();
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
case WASM_OP_TABLE_GROW: case WASM_OP_TABLE_GROW:
@ -13687,6 +13816,10 @@ re_scan:
PUSH_I32(); PUSH_I32();
else else
POP_I32(); POP_I32();
#if WASM_ENABLE_WAMR_COMPILER != 0
module->is_ref_types_used = true;
#endif
break; break;
} }
#endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */ #endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */