From b18cb3b2cb24a81a0f7bc362e7bf98ae5c13f11a Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Thu, 19 Dec 2024 16:52:29 +0800 Subject: [PATCH] [instantiation linking] Create and import WASMGlobalInstance (#3914) --- core/iwasm/aot/aot_loader.c | 10 +- core/iwasm/aot/aot_runtime.c | 294 +++++++++++------ core/iwasm/aot/aot_runtime.h | 23 +- core/iwasm/common/wasm_native.h | 14 + core/iwasm/common/wasm_runtime_common.c | 300 ++++++++++++------ core/iwasm/common/wasm_runtime_common.h | 13 + core/iwasm/compilation/aot_emit_table.c | 1 + core/iwasm/compilation/aot_emit_variable.c | 269 ++++++++++++++-- core/iwasm/compilation/aot_llvm.c | 1 + core/iwasm/include/wasm_export.h | 38 +-- core/iwasm/interpreter/wasm.h | 5 + core/iwasm/interpreter/wasm_interp_classic.c | 13 - core/iwasm/interpreter/wasm_interp_fast.c | 13 - core/iwasm/interpreter/wasm_loader.c | 7 +- core/iwasm/interpreter/wasm_runtime.c | 208 +++++++----- core/iwasm/interpreter/wasm_runtime.h | 48 ++- core/iwasm/libraries/libc-builtin/SConscript | 2 + .../libraries/libc-builtin/builtin_wrapper.h | 47 +++ .../libraries/libc-builtin/libc_builtin.cmake | 13 +- .../libc-builtin/libc_builtin_wrapper.c | 38 ++- .../libc-builtin/spec_test_builtin_wrapper.c | 182 +++++++++++ .../libc-builtin/wasi_test_builtin_wrapper.c | 92 ++++++ tests/wamr-test-suites/test_wamr.sh | 2 +- 23 files changed, 1256 insertions(+), 377 deletions(-) create mode 100644 core/iwasm/libraries/libc-builtin/builtin_wrapper.h create mode 100644 core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c create mode 100644 core/iwasm/libraries/libc-builtin/wasi_test_builtin_wrapper.c diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index b2bf1a96d..31d28b83b 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -2144,9 +2144,11 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, AOTImportGlobal *import_globals; uint64 size; uint32 i, data_offset = 0; +#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_LIBC_BUILTIN != 0 WASMGlobalImport tmp_global; #endif +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ /* Allocate memory */ size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; @@ -2167,6 +2169,7 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, return false; } +#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_LIBC_BUILTIN != 0 if (wasm_native_lookup_libc_builtin_global( import_globals[i].module_name, import_globals[i].global_name, @@ -2182,9 +2185,12 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, tmp_global.global_data_linked; import_globals[i].is_linked = true; } -#else - import_globals[i].is_linked = false; + else #endif +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ + { + import_globals[i].is_linked = false; + } import_globals[i].size = wasm_value_type_size(import_globals[i].type.val_type); diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index ecc8380d6..4b2d4ac93 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -60,6 +60,7 @@ bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0); bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_base_addr_adj) == 8); bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_start_off) == 16); +bh_static_assert(offsetof(AOTModuleInstanceExtra, globals) == 24); bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3); @@ -80,6 +81,14 @@ bh_static_assert(offsetof(AOTTinyFrame, func_index) == sizeof(uint32) * 0); bh_static_assert(offsetof(AOTTinyFrame, ip_offset) == sizeof(uint32) * 1); bh_static_assert(sizeof(AOTTinyFrame) == sizeof(uint32) * 2); +bh_static_assert(offsetof(AOTGlobalInstance, initial_value) == 8); +bh_static_assert(offsetof(AOTGlobalInstance, import_module_inst) + == 8 + sizeof(WASMValue)); +bh_static_assert(offsetof(AOTGlobalInstance, import_global_inst) + == 8 + sizeof(WASMValue) + 8); +bh_static_assert(offsetof(AOTGlobalInstance, ref_type) + == 8 + sizeof(WASMValue) + 16); + static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { @@ -283,10 +292,20 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module, error_buf, error_buf_size)) { return false; } + + /*TODO: via WASMGlobalInstance->init_value ? */ if (init_expr->u.global_index < module->import_global_count) { +#if WASM_ENABLE_MULTI_MODULE != 0 PUT_REF_TO_ADDR( addr, module->import_globals[init_expr->u.global_index] .global_data_linked.gc_obj); +#else + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)module_inst->e; + AOTGlobalInstance *global = + e->globals + init_expr->u.global_index; + PUT_REF_TO_ADDR(addr, global->initial_value.gc_obj); +#endif } else { uint32 global_idx = @@ -444,69 +463,142 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module, } #endif /* end of WASM_ENABLE_GC != 0 */ -static bool -global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, - char *error_buf, uint32 error_buf_size) +static AOTGlobalInstance * +globals_instantiate(AOTModuleInstance *module_inst, AOTModule *module, + const WASMExternInstance *imports, uint32 import_count, + char *error_buf, uint32 error_buf_size) { uint32 i; - InitializerExpression *init_expr; uint8 *p = module_inst->global_data; - AOTImportGlobal *import_global = module->import_globals; - AOTGlobal *global = module->globals; + + uint64 total_size = + sizeof(AOTGlobalInstance) + * (uint64)(module->global_count + module->import_global_count); + AOTGlobalInstance *globals = + runtime_malloc(total_size, error_buf, error_buf_size); + if (!globals) { + return NULL; + } /* Initialize import global data */ - for (i = 0; i < module->import_global_count; i++, import_global++) { - bh_assert(import_global->data_offset + AOTGlobalInstance *global = globals; + AOTImportGlobal *import_global_type = module->import_globals; + for (i = 0; i < module->import_global_count; + i++, import_global_type++, global++) { + global->type = import_global_type->type.val_type; + global->is_mutable = import_global_type->type.is_mutable; + + bh_assert(import_global_type->data_offset == (uint32)(p - module_inst->global_data)); - init_global_data(p, import_global->type.val_type, - &import_global->global_data_linked); - p += import_global->size; + global->data_offset = import_global_type->data_offset; + +#if WASM_ENABLE_MULTI_MODULE != 0 + init_global_data(p, import_global_type->type.val_type, + &import_global_type->global_data_linked); +#else + const WASMExternInstance *extern_inst = + wasm_runtime_get_extern_instance(imports, import_count, + WASM_IMPORT_EXPORT_KIND_GLOBAL, i); + if (!extern_inst) { + LOG_ERROR("missing an import global(%s, %s)", + import_global_type->module_name, + import_global_type->global_name); + goto fail; + } + + /* just in case */ +#ifndef NDEBUG + if (strcmp(import_global_type->global_name, extern_inst->field_name)) { + LOG_ERROR( + "mismatched import global name: expect \"%s\", got \"%s\"", + import_global_type->global_name, extern_inst->field_name); + goto fail; + } +#endif + + bh_memcpy_s(&global->initial_value, sizeof(WASMValue), + &extern_inst->u.global->initial_value, sizeof(WASMValue)); + global->import_module_inst = + (WASMModuleInstance *)extern_inst->dep_inst; + /* write into global_data */ + init_global_data(p, global->type, &global->initial_value); +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ + + p += import_global_type->size; } /* Initialize defined global data */ - for (i = 0; i < module->global_count; i++, global++) { - uint8 flag; - bh_assert(global->data_offset + AOTGlobal *global_type = module->globals; + for (i = 0; i < module->global_count; i++, global_type++, global++) { + global->type = global_type->type.val_type; + global->is_mutable = global_type->type.is_mutable; + + bh_assert(global_type->data_offset == (uint32)(p - module_inst->global_data)); - init_expr = &global->init_expr; - flag = init_expr->init_expr_type; + global->data_offset = global_type->data_offset; + + InitializerExpression *init_expr = &global_type->init_expr; + uint8 flag = init_expr->init_expr_type; switch (flag) { case INIT_EXPR_TYPE_GET_GLOBAL: { if (!check_global_init_expr(module, init_expr->u.global_index, error_buf, error_buf_size)) { - return false; + goto fail; } -#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) { + + uint32 global_index_in_expr = init_expr->u.global_index; + if (global_index_in_expr < module->import_global_count) { +#if WASM_ENABLE_MULTI_MODULE != 0 + /* from WASMImportGlobal or WASMGlobal to global_data */ init_global_data( - p, global->type.val_type, - &module->import_globals[init_expr->u.global_index] + p, global_type->type.val_type, + &module->import_globals[global_index_in_expr] .global_data_linked); +#else + /* + * from WASMImportGlobal to WASMGlobalInstance + * to global_data + */ + global->initial_value = + globals[global_index_in_expr].initial_value; + init_global_data(p, global_type->type.val_type, + &global->initial_value); +#endif /* WASM_ENABLE_MULTI_MODULE != 0*/ } 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); - } +#if WASM_ENABLE_GC == 0 + bh_assert(false + && "only GC mode support using non-import global " + "in a constant expression"); #endif + uint32 adjusted_global_index_in_expr = + global_index_in_expr - module->import_global_count; + + /* + * from WASMGlobal to WASMGlobalInstance + * to global_data + */ + global->initial_value = + module->globals[adjusted_global_index_in_expr] + .init_expr.u; + init_global_data(p, global_type->type.val_type, + &global->initial_value); + } + break; } #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 case INIT_EXPR_TYPE_REFNULL_CONST: { + /* no need to assign global->initial_value */ *(uint32 *)p = NULL_REF; break; } #elif WASM_ENABLE_GC != 0 case INIT_EXPR_TYPE_REFNULL_CONST: { + /* no need to assign global->initial_value */ WASMObjectRef gc_obj = NULL_REF; PUT_REF_TO_ADDR(p, gc_obj); break; @@ -522,7 +614,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, if (!(func_obj = aot_create_func_obj(module_inst, func_idx, false, error_buf, error_buf_size))) { - return false; + goto fail; } } @@ -559,7 +651,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, module->type_count, &module->rtt_type_lock))) { set_error_buf(error_buf, error_buf_size, "create rtt object failed"); - return false; + goto fail; } if (!(struct_obj = wasm_struct_obj_new_internal( @@ -568,7 +660,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, rtt_type))) { set_error_buf(error_buf, error_buf_size, "create struct object failed"); - return false; + goto fail; } if (flag == INIT_EXPR_TYPE_STRUCT_NEW) { @@ -620,7 +712,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, module->type_count, &module->rtt_type_lock))) { set_error_buf(error_buf, error_buf_size, "create rtt object failed"); - return false; + goto fail; } if (!(array_obj = wasm_array_obj_new_internal( @@ -629,7 +721,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, rtt_type, len, arr_init_val))) { set_error_buf(error_buf, error_buf_size, "create array object failed"); - return false; + goto fail; } if (flag == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) { @@ -650,16 +742,22 @@ 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); + global->initial_value = init_expr->u; + init_global_data(p, global->type, &global->initial_value); break; } } - p += global->size; + + p += global_type->size; } bh_assert(module_inst->global_data_size == (uint32)(p - module_inst->global_data)); - return true; + + return globals; +fail: + wasm_runtime_free(globals); + return NULL; } /** @@ -839,7 +937,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Resolve table data base offset */ /* TODO: The table64 current implementation assumes table max size * UINT32_MAX, so the offset conversion here is safe */ - uint32 base_offset; + uint32 base_offset = 0; if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { uint32 global_index = table_seg->offset.u.global_index; uint32 global_data_offset; @@ -849,13 +947,10 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, return false; } - if (global_index < module->import_global_count) - global_data_offset = - module->import_globals[global_index].data_offset; - else - global_data_offset = - module->globals[global_index - module->import_global_count] - .data_offset; + /* since we have transfer data_offset into WASMGlobalInstance */ + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)module_inst->e; + global_data_offset = e->globals[global_index].data_offset; base_offset = *(uint32 *)(module_inst->global_data + global_data_offset); @@ -967,7 +1062,7 @@ memories_deinstantiate(AOTModuleInstance *module_inst) #else wasm_runtime_free(memory); #endif -#endif +#endif /* WASM_ENABLE_MULTI_MODULE == 0 */ } for (; mem_index < module->memory_count; mem_index++) { @@ -2002,26 +2097,6 @@ fail: return ret; } -static bool -check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size) -{ - uint32 i; - - /* init_func_ptrs() will go through import functions */ - - for (i = 0; i < module->import_global_count; i++) { - AOTImportGlobal *global = module->import_globals + i; - if (!global->is_linked) { - set_error_buf_v(error_buf, error_buf_size, - "failed to link import global (%s, %s)", - global->module_name, global->global_name); - return false; - } - } - - return true; -} - AOTModuleInstance * aot_instantiate(AOTModule *module, AOTModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, @@ -2193,8 +2268,14 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, + module_inst_mem_inst_size; module_inst->global_data = p; module_inst->global_data_size = module->global_data_size; - if (!global_instantiate(module_inst, module, error_buf, error_buf_size)) - goto fail; + extra->global_count = module->import_global_count + module->global_count; + if (extra->global_count > 0) { + extra->globals = + globals_instantiate(module_inst, module, imports, import_count, + error_buf, error_buf_size); + if (!extra->globals) + goto fail; + } /* __heap_base */ uint8 *aux_heap_base_global_data = NULL; @@ -2223,9 +2304,6 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, if (!init_func_ptrs(module_inst, module, error_buf, error_buf_size)) goto fail; - if (!check_linked_symbol(module, error_buf, error_buf_size)) - goto fail; - if (!create_exports(module_inst, module, error_buf, error_buf_size)) goto fail; @@ -2343,10 +2421,11 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, &tbl_init_size, &tbl_max_size); if (!wasm_elem_is_declarative(table_init_data->mode) - && !wasm_reftype_is_subtype_of( - table_init_data->elem_type, table_init_data->elem_ref_type, - table->elem_type, table->elem_ref_type.elem_ref_type, - module->types, module->type_count)) { + && !wasm_reftype_is_subtype_of((uint8)table_init_data->elem_type, + table_init_data->elem_ref_type, + table->elem_type, + table->elem_ref_type.elem_ref_type, + module->types, module->type_count)) { set_error_buf(error_buf, error_buf_size, "type mismatch: elements segment does not fit"); goto fail; @@ -2371,30 +2450,21 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, /* init vec(funcidx) or vec(expr) */ if (table_init_data->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { - uint32 data_offset; + uint32 data_offset = 0; if (!check_global_init_expr(module, table_init_data->offset.u.global_index, error_buf, error_buf_size)) { goto fail; } - if (table_init_data->offset.u.global_index - < module->import_global_count) { - data_offset = - module - ->import_globals[table_init_data->offset.u.global_index] - .data_offset; - } - else { - data_offset = - module - ->globals[table_init_data->offset.u.global_index - - module->import_global_count] - .data_offset; - } + /* since we have transfer data_offset into WASMGlobalInstance */ + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)module_inst->e; + data_offset = + e->globals[table_init_data->offset.u.global_index].data_offset; table_init_data->offset.u.i32 = - *(uint32 *)(module_inst->global_data + data_offset); + *(int32 *)(module_inst->global_data + data_offset); } /* check offset since length might negative */ @@ -2416,7 +2486,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, goto fail; } - for (j = 0; j < module->table_init_data_list[i]->value_count; j++) { + for (j = 0; j < table_init_data->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, @@ -2539,6 +2609,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(extra->functions); } + if (extra->globals) { + wasm_runtime_free(extra->globals); + } + if (module_inst->func_ptrs) wasm_runtime_free(module_inst->func_ptrs); @@ -5788,4 +5862,36 @@ aot_destroy_table(AOTTableInstance *table) return; wasm_runtime_free(table); +} + +AOTGlobalInstance * +aot_create_global(const AOTModule *module, AOTModuleInstance *dep_inst, + WASMGlobalType *type) +{ + AOTGlobalInstance *global = + runtime_malloc(sizeof(AOTGlobalInstance), NULL, 0); + if (!global) { + return NULL; + } + + global->type = type->val_type; + global->is_mutable = type->is_mutable; + global->import_module_inst = dep_inst; + /* empty global. set value later by wasm_set_global_value */ + return global; +} + +void +aot_set_global_value(AOTGlobalInstance *global, const WASMValue *value) +{ + global->initial_value = *value; +} + +void +aot_destroy_global(AOTGlobalInstance *global) +{ + if (!global) + return; + + wasm_runtime_free(global); } \ No newline at end of file diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 6cfa565fa..22e50fbe7 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -37,6 +37,11 @@ extern "C" { #define WASM_FEATURE_FRAME_NO_FUNC_IDX (1 << 13) #define WASM_FEATURE_MULTI_MODULE (1 << 14) +#define AOTGlobalInstance WASMGlobalInstance +#define AOTMemoryInstance WASMMemoryInstance +#define AOTTableInstance WASMTableInstance +#define AOTModuleInstance WASMModuleInstance + typedef enum AOTSectionType { AOT_SECTION_TYPE_TARGET_INFO = 0, AOT_SECTION_TYPE_INIT_DATA = 1, @@ -127,6 +132,9 @@ typedef struct AOTModuleInstanceExtra { DefPointer(uint8 *, shared_heap_base_addr_adj); MemBound shared_heap_start_off; + DefPointer(AOTGlobalInstance *, globals); + uint32 global_count; + WASMModuleInstanceExtraCommon common; /** @@ -137,6 +145,7 @@ typedef struct AOTModuleInstanceExtra { ExportFuncMap *export_func_maps; AOTFunctionInstance **functions; uint32 function_count; + #if WASM_ENABLE_MULTI_MODULE != 0 bh_list sub_module_inst_list_head; bh_list *sub_module_inst_list; @@ -363,10 +372,6 @@ typedef struct AOTModule { #endif } AOTModule; -#define AOTMemoryInstance WASMMemoryInstance -#define AOTTableInstance WASMTableInstance -#define AOTModuleInstance WASMModuleInstance - #if WASM_ENABLE_MULTI_MODULE != 0 #define AOTSubModInstNode WASMSubModInstNode #endif @@ -917,6 +922,16 @@ aot_set_table_elem(const AOTModule *module, AOTTableInstance *table, void aot_destroy_table(AOTTableInstance *table); +AOTGlobalInstance * +aot_create_global(const AOTModule *module, AOTModuleInstance *dep_inst, + WASMGlobalType *type); + +void +aot_set_global_value(AOTGlobalInstance *global, const WASMValue *value); + +void +aot_destroy_global(AOTGlobalInstance *global); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index 9a6afee19..f1188d832 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -110,6 +110,20 @@ void * wasm_native_lookup_quick_aot_entry(const WASMFuncType *func_type); #endif +#if WASM_ENABLE_SPEC_TEST != 0 +bool +wasm_runtime_create_extern_inst_for_spec_test(wasm_module_t module, + wasm_import_t *import_type, + WASMExternInstance *out); +#endif + +#if WASM_ENABLE_WASI_TEST != 0 +bool +wasm_runtime_create_extern_inst_for_wasi_test(wasm_module_t module, + wasm_import_t *import_type, + WASMExternInstance *out); +#endif + #ifdef __cplusplus } #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index b3bb54f55..271e13949 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2051,40 +2051,38 @@ wasm_runtime_set_module_inst(WASMExecEnv *exec_env, wasm_exec_env_set_module_inst(exec_env, module_inst); } -bool +WASMGlobalInstance * wasm_runtime_get_export_global_inst(WASMModuleInstanceCommon *const module_inst, - char const *name, - wasm_global_inst_t *global_inst) + char const *name) { + if (!module_inst || !name) { + return NULL; + } + #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { const WASMModuleInstance *wasm_module_inst = (const WASMModuleInstance *)module_inst; const WASMModule *wasm_module = wasm_module_inst->module; - uint32 i; - for (i = 0; i < wasm_module->export_count; i++) { + + for (uint32 i = 0; i < wasm_module->export_count; i++) { const WASMExport *wasm_export = &wasm_module->exports[i]; - if ((wasm_export->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) - && !strcmp(wasm_export->name, name)) { - const WASMModuleInstanceExtra *e = - (WASMModuleInstanceExtra *)wasm_module_inst->e; - const WASMGlobalInstance *global = - &e->globals[wasm_export->index]; - global_inst->kind = val_type_to_val_kind(global->type); - global_inst->is_mutable = global->is_mutable; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_inst->global_data = - wasm_module_inst->global_data + global->data_offset; -#else - global_inst->global_data = - global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : wasm_module_inst->global_data + global->data_offset; -#endif - return true; + + if (wasm_export->kind != WASM_IMPORT_EXPORT_KIND_GLOBAL) { + continue; } + + if (strcmp(wasm_export->name, name)) { + continue; + } + + WASMModuleInstanceExtra *e = + (WASMModuleInstanceExtra *)wasm_module_inst->e; + WASMGlobalInstance *global = &e->globals[wasm_export->index]; + return global; } + + return NULL; } #endif #if WASM_ENABLE_AOT != 0 @@ -2095,21 +2093,26 @@ wasm_runtime_get_export_global_inst(WASMModuleInstanceCommon *const module_inst, uint32 i; for (i = 0; i < aot_module->export_count; i++) { const AOTExport *aot_export = &aot_module->exports[i]; - if ((aot_export->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) - && !strcmp(aot_export->name, name)) { - const AOTGlobal *global = - &aot_module->globals[aot_export->index]; - global_inst->kind = val_type_to_val_kind(global->type.val_type); - global_inst->is_mutable = global->type.is_mutable; - global_inst->global_data = - aot_module_inst->global_data + global->data_offset; - return true; + + if (aot_export->kind != WASM_IMPORT_EXPORT_KIND_GLOBAL) { + continue; } + + if (strcmp(aot_export->name, name)) { + continue; + } + + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)aot_module_inst->e; + AOTGlobalInstance *global = &e->globals[aot_export->index]; + return global; } + + return NULL; } #endif - return false; + return NULL; } WASMTableInstance * @@ -7837,8 +7840,9 @@ wasm_table_inst_t wasm_runtime_create_table(WASMModuleCommon *const module, wasm_table_type_t const type) { - if (!module || !type) + if (!module || !type) { return NULL; + } #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) { @@ -7852,7 +7856,6 @@ wasm_runtime_create_table(WASMModuleCommon *const module, } #endif - LOG_ERROR("create table failed, invalid module type"); return NULL; } @@ -7896,6 +7899,125 @@ wasm_runtime_destroy_table(WASMModuleCommon *const module, LOG_ERROR("destroy table failed, invalid module type"); } +WASMGlobalInstance * +wasm_runtime_create_global_internal(WASMModuleCommon *const module, + WASMModuleInstanceCommon *dep_inst, + WASMGlobalType *const type) +{ + if (!module || !type) + return NULL; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + return wasm_create_global((WASMModule *)module, + (WASMModuleInstance *)dep_inst, type); + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + return aot_create_global((AOTModule *)module, + (AOTModuleInstance *)dep_inst, type); + } +#endif + + return NULL; +} + +void +wasm_runtime_set_global_value(WASMModuleCommon *module, + WASMGlobalInstance *global, WASMValue *value) +{ + if (!global || !value) + return; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + wasm_set_global_value(global, value); + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + aot_set_global_value(global, value); + } +#endif +} + +WASMGlobalInstance * +wasm_runtime_create_global(WASMModuleCommon *const module, + WASMGlobalType *const type, const wasm_val_t *value) +{ + WASMGlobalInstance *global = + wasm_runtime_create_global_internal(module, NULL, type); + if (!global) + return NULL; + + /* TODO: make a small function about conversion */ + WASMValue init_value = { 0 }; + /* wasm_val_t to WASMValue */ + switch (value->kind) { + case WASM_I32: + { + init_value.i32 = value->of.i32; + break; + } + case WASM_I64: + { + init_value.i64 = value->of.i64; + break; + } + case WASM_F32: + { + init_value.f32 = value->of.f32; + break; + } + case WASM_F64: + { + init_value.f64 = value->of.f64; + break; + } + // case WASM_V128: + // { + // bh_assert(false && "V128 not supported yet"); + // break; + // } + // case WASM_EXTERNREF: + // case WASM_FUNCREF: + default: + { + bh_assert(false && "unsupported value type"); + break; + } + } + + wasm_runtime_set_global_value(module, global, &init_value); + + return global; +} + +void +wasm_runtime_destroy_global(WASMModuleCommon *const module, + WASMGlobalInstance *global) +{ + if (!module) + return; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + wasm_destroy_global(global); + return; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + aot_destroy_global(global); + return; + } +#endif +} + /*TODO: take us(below) out when have a linker */ WASMModuleInstanceCommon * wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module, @@ -7942,59 +8064,24 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module, * WASMExternInstance->u.memory content * * WASModuleInstance->tables[i].elems takes - * the ownership of WASMExternInstance->u.table + * the ownership of WASMExternInstance->u.table as WASMTableInstance * * WASMModuleInstance->e->globals[i] copies the content of * WASMExternInstance->u.global */ if (imports) { + for (uint32 i = 0; i < import_count; i++) { + if (imports[i].kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) { + wasm_runtime_destroy_global(module, imports[i].u.global); + } + } + wasm_runtime_free(imports); } return inst; } -bool -wasm_runtime_create_extern_inst(WASMModuleCommon *module, - wasm_import_t *import_type, - WASMExternInstance *out) -{ - if (!out) - return false; - - LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name, - import_type->name, import_type->kind); - - out->module_name = import_type->module_name; - out->field_name = import_type->name; - out->kind = import_type->kind; - - if (import_type->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { - out->u.memory = - wasm_runtime_create_memory(module, import_type->u.memory_type); - if (!out->u.memory) { - LOG_ERROR("create memory failed\n"); - return false; - } - } - else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_TABLE) { - wasm_table_inst_t table = - wasm_runtime_create_table(module, import_type->u.table_type); - out->u.table = table; - if (!out->u.table) { - LOG_ERROR("create table failed\n"); - return false; - } - } - else { - LOG_DEBUG("unimplemented import(%s,%s) kind %d", - import_type->module_name, import_type->name, - import_type->kind); - } - - return true; -} - void wasm_runtime_destroy_extern_inst(WASMModuleCommon *module, WASMExternInstance *extern_inst) @@ -8006,6 +8093,14 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module, wasm_runtime_destroy_memory(module, extern_inst->u.memory); extern_inst->u.memory = NULL; } + else if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_TABLE) { + wasm_runtime_destroy_table(module, extern_inst->u.table); + extern_inst->u.table = NULL; + } + else if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) { + wasm_runtime_destroy_global(module, extern_inst->u.global); + extern_inst->u.global = NULL; + } else { LOG_DEBUG("unimplemented import(%s,%s) kind %d", extern_inst->module_name, extern_inst->field_name, @@ -8016,11 +8111,12 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module, extern_inst->field_name = NULL; } +#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_WASI_TEST != 0 /* * Be aware that it will remove all items in the list, regardless of whether * they were created by the runtime (for built-ins) or by users. */ -void +static void wasm_runtime_destroy_imports(WASMModuleCommon *module, WASMExternInstance *extern_inst_list) { @@ -8032,12 +8128,15 @@ wasm_runtime_destroy_imports(WASMModuleCommon *module, wasm_runtime_destroy_extern_inst(module, extern_inst_list + i); } } +#endif /* WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_WASI_TEST != 0 */ bool -wasm_runtime_create_imports(WASMModuleCommon *module, - bool (*module_name_filter)(const char *), - WASMExternInstance *out, uint32 out_len) +wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module, + WASMExternInstance *out, + uint32 out_len) { + LOG_DEBUG("create imports with builtin"); + int32 import_count_s = wasm_runtime_get_import_count(module); if (import_count_s < 0) @@ -8057,35 +8156,32 @@ wasm_runtime_create_imports(WASMModuleCommon *module, wasm_import_t import_type = { 0 }; wasm_runtime_get_import_type(module, i, &import_type); - if (module_name_filter - && !module_name_filter(import_type.module_name)) { - LOG_DEBUG("skip import(%s,%s)", import_type.module_name, - import_type.name); - continue; - } - +#if WASM_ENABLE_LIBC_BUILTIN != 0 WASMExternInstance *extern_instance = out + i; - if (!wasm_runtime_create_extern_inst(module, &import_type, - extern_instance)) { +#if WASM_ENABLE_SPEC_TEST != 0 + if (!wasm_runtime_create_extern_inst_for_spec_test(module, &import_type, + extern_instance)) { wasm_runtime_destroy_imports(module, out); - LOG_ERROR("create import failed"); + LOG_ERROR("create imports for spec test failed"); return false; } +#endif + +#if WASM_ENABLE_WASI_TEST != 0 + if (!wasm_runtime_create_extern_inst_for_wasi_test(module, &import_type, + extern_instance)) { + wasm_runtime_destroy_imports(module, out); + LOG_ERROR("create imports for wasi test failed"); + return false; + } +#endif + (void)extern_instance; +#endif } return true; } -bool -wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module, - WASMExternInstance *out, - uint32 out_len) -{ - LOG_DEBUG("create imports with builtin"); - return wasm_runtime_create_imports(module, wasm_runtime_is_built_in_module, - out, out_len); -} - #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 /* diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 0460c5ea8..e9643c234 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -1230,6 +1230,19 @@ wasm_runtime_get_extern_instance(const WASMExternInstance *imports, uint32 import_count, wasm_import_export_kind_t kind, uint32 index); +struct WASMGlobalInstance * +wasm_runtime_create_global_internal(wasm_module_t const module, + wasm_module_inst_t dep_inst, + wasm_global_type_t type); + +void +wasm_runtime_set_global_value(wasm_module_t const module, + wasm_global_inst_t global, WASMValue *value); + +struct WASMTableInstance * +wasm_runtime_create_table_internal(WASMModuleCommon *const module, + WASMTableType *const type); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/compilation/aot_emit_table.c b/core/iwasm/compilation/aot_emit_table.c index c5d0cf6c8..cd43ea015 100644 --- a/core/iwasm/compilation/aot_emit_table.c +++ b/core/iwasm/compilation/aot_emit_table.c @@ -132,6 +132,7 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx, return offset; } +/*TODO: move it to aot_llvm.c/h */ uint32 get_module_inst_extra_offset(AOTCompContext *comp_ctx) { diff --git a/core/iwasm/compilation/aot_emit_variable.c b/core/iwasm/compilation/aot_emit_variable.c index bb6d10b8e..7833eabdd 100644 --- a/core/iwasm/compilation/aot_emit_variable.c +++ b/core/iwasm/compilation/aot_emit_variable.c @@ -6,6 +6,7 @@ #include "aot_emit_variable.h" #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" +#include "aot_emit_table.h" #define CHECK_LOCAL(idx) \ do { \ @@ -149,43 +150,259 @@ aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return aot_compile_op_set_or_tee_local(comp_ctx, func_ctx, local_idx, true); } +/*TODO: should be optimized by moving globals to WASMModuleInstance */ +LLVMValueRef +get_global_from_wasm_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx) +{ + /* WASMModuleInstance->e->globals */ + uint32 e_offset_val = get_module_inst_extra_offset(comp_ctx); + uint32 globals_offset_val = e_offset_val; +#if WASM_ENABLE_JIT != 0 + if (comp_ctx->is_jit_mode) + globals_offset_val += offsetof(WASMModuleInstanceExtra, globals); + else +#endif + globals_offset_val += offsetof(AOTModuleInstanceExtra, globals); + + LLVMValueRef globals_offset = I32_CONST(globals_offset_val); + if (!globals_offset) { + aot_set_last_error("I32_CONST failed for globals_offset"); + return NULL; + } + + LLVMValueRef globals_ptr = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, + &globals_offset, 1, "globals_ptr"); + if (!globals_ptr) { + aot_set_last_error("LLVMBuildInBoundsGEP2 failed for globals_ptr"); + return NULL; + } + + LLVMValueRef globals = + LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, globals_ptr, "globals"); + if (!globals) { + aot_set_last_error("LLVMBuildLoad2 failed for globals"); + return NULL; + } + + /* WASMGlobalInstance[global_idx] */ + uint32 global_offset_val = global_idx * sizeof(WASMGlobalInstance); + LLVMValueRef global_offset = I32_CONST(global_offset_val); + if (!global_offset) { + aot_set_last_error("I32_CONST failed for global_offset"); + return NULL; + } + + LLVMValueRef global_ptr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, globals, &global_offset, 1, "global_ptr"); + if (!global_ptr) { + aot_set_last_error("LLVMBuildInBoundsGEP2 failed for global_ptr"); + return NULL; + } + + return global_ptr; +} + +static LLVMValueRef +get_global_value_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx) +{ + /* WASMGlobalInstance[global_idx] */ + LLVMValueRef global_ptr = + get_global_from_wasm_inst(comp_ctx, func_ctx, global_idx); + if (!global_ptr) { + aot_set_last_error("get_global_from_wasm_inst failed"); + return NULL; + } + + /* WASMGlobalInstance->import_module_inst */ + uint32 import_inst_offset_val = + offsetof(WASMGlobalInstance, import_module_inst); + LLVMValueRef import_inst_offset = I32_CONST(import_inst_offset_val); + if (!import_inst_offset) { + aot_set_last_error("I32_CONST failed for import_inst_offset"); + return NULL; + } + + LLVMValueRef import_inst_ptr_u8 = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, global_ptr, + &import_inst_offset, 1, "import_inst_u8_ptr"); + if (!import_inst_ptr_u8) { + aot_set_last_error( + "LLVMBuildInBoundsGEP2 failed for import_inst_ptr_u8"); + return NULL; + } + + LLVMValueRef import_inst_ptr = LLVMBuildBitCast( + comp_ctx->builder, import_inst_ptr_u8, OPQ_PTR_TYPE, "import_inst_ptr"); + if (!import_inst_ptr) { + aot_set_last_error("LLVMBuildBitCast failed for import_inst_ptr"); + return NULL; + } + + LLVMValueRef import_inst = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, + import_inst_ptr, "import_inst"); + if (!import_inst) { + aot_set_last_error("LLVMBuildLoad2 failed for import_inst"); + return NULL; + } + + /* WASMGlobalInstance->data_offset */ + uint32 data_offset_offset_val = offsetof(WASMGlobalInstance, data_offset); + LLVMValueRef data_offset_offset = I32_CONST(data_offset_offset_val); + if (!data_offset_offset) { + aot_set_last_error("I32_CONST failed for data_offset_offset"); + return NULL; + } + + LLVMValueRef data_offset_ptr = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, global_ptr, + &data_offset_offset, 1, "data_offset_ptr"); + if (!data_offset_ptr) { + aot_set_last_error("LLVMBuildInBoundsGEP2 failed for data_offset_ptr"); + return NULL; + } + + LLVMValueRef data_offset = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, + data_offset_ptr, "data_offset"); + if (!data_offset) { + aot_set_last_error("LLVMBuildLoad2 failed for data_offset"); + return NULL; + } + + /* WASMModuleInstance->global_data preparation */ + uint32 global_data_offset_val = + offsetof(WASMModuleInstance, global_table_data.bytes) + + sizeof(AOTMemoryInstance) + * (comp_ctx->comp_data->memory_count + + comp_ctx->comp_data->import_memory_count); + LLVMValueRef global_data_offset = I32_CONST(global_data_offset_val); + if (!global_data_offset) { + aot_set_last_error("I32_CONST failed for global_data_offset"); + return NULL; + } + + // Check if import_module_inst is NULL + LLVMBasicBlockRef then_block = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "then"); + if (!then_block) { + aot_set_last_error( + "LLVMAppendBasicBlockInContext failed for then_block"); + return NULL; + } + + LLVMBasicBlockRef else_block = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "else"); + if (!else_block) { + aot_set_last_error( + "LLVMAppendBasicBlockInContext failed for else_block"); + return NULL; + } + + LLVMBasicBlockRef merge_block = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "merge"); + if (!merge_block) { + aot_set_last_error( + "LLVMAppendBasicBlockInContext failed for merge_block"); + return NULL; + } + + LLVMValueRef terminator = LLVMBuildCondBr( + comp_ctx->builder, + LLVMBuildIsNull(comp_ctx->builder, import_inst, "is_null"), then_block, + else_block); + if (!terminator) { + aot_set_last_error("LLVMBuildCondBr failed"); + return NULL; + } + + // If import_module_inst is NULL + LLVMPositionBuilderAtEnd(comp_ctx->builder, then_block); + // load global_data from local module instance + LLVMValueRef local_global_data = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, + &global_data_offset, 1, "local_global_data"); + if (!local_global_data) { + aot_set_last_error( + "LLVMBuildInBoundsGEP2 failed for local_global_data"); + return NULL; + } + + // global value pointer + LLVMValueRef local_global_value_ptr = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, local_global_data, + &data_offset, 1, "local_global_value_ptr"); + if (!local_global_value_ptr) { + aot_set_last_error( + "LLVMBuildInBoundsGEP2 failed for local_global_value_ptr"); + return NULL; + } + + terminator = LLVMBuildBr(comp_ctx->builder, merge_block); + if (!terminator) { + aot_set_last_error("LLVMBuildBr failed"); + return NULL; + } + + // If import_module_inst is not NULL + LLVMPositionBuilderAtEnd(comp_ctx->builder, else_block); + // load global_data in import module instance + LLVMValueRef import_global_data = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, import_inst, + &global_data_offset, 1, "import_global_data"); + if (!import_global_data) { + aot_set_last_error( + "LLVMBuildInBoundsGEP2 failed for import_global_data"); + return NULL; + } + + LLVMValueRef import_global_value_ptr = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, import_global_data, + &data_offset, 1, "import_global_value_ptr"); + if (!import_global_value_ptr) { + aot_set_last_error( + "LLVMBuildInBoundsGEP2 failed for import_global_value_ptr"); + return NULL; + } + + terminator = LLVMBuildBr(comp_ctx->builder, merge_block); + if (!terminator) { + aot_set_last_error("LLVMBuildBr failed"); + return NULL; + } + + // Merge block + LLVMPositionBuilderAtEnd(comp_ctx->builder, merge_block); + LLVMValueRef phi = + LLVMBuildPhi(comp_ctx->builder, OPQ_PTR_TYPE, "global_value_addr"); + if (!phi) { + aot_set_last_error("LLVMBuildPhi failed for global_value_addr"); + return NULL; + } + + LLVMAddIncoming(phi, &local_global_value_ptr, &then_block, 1); + LLVMAddIncoming(phi, &import_global_value_ptr, &else_block, 1); + + return phi; +} + static bool compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 global_idx, bool is_set, bool is_aux_stack) { const AOTCompData *comp_data = comp_ctx->comp_data; uint32 import_global_count = comp_data->import_global_count; - uint32 global_base_offset; - uint32 global_offset; uint8 global_type; - LLVMValueRef offset, global_ptr, global, res; + LLVMValueRef global_ptr, global, res; LLVMTypeRef ptr_type = NULL; - global_base_offset = offsetof(AOTModuleInstance, global_table_data.bytes) - + sizeof(AOTMemoryInstance) - * (comp_ctx->comp_data->memory_count - + comp_ctx->comp_data->import_memory_count); - bh_assert(global_idx < import_global_count + comp_data->global_count); if (global_idx < import_global_count) { - global_offset = - global_base_offset - /* Get global data offset according to target info */ - + (comp_ctx->pointer_size == sizeof(uint64) - ? comp_data->import_globals[global_idx].data_offset_64bit - : comp_data->import_globals[global_idx].data_offset_32bit); global_type = comp_data->import_globals[global_idx].type.val_type; } else { - global_offset = - global_base_offset - /* Get global data offset according to target info */ - + (comp_ctx->pointer_size == sizeof(uint64) - ? comp_data->globals[global_idx - import_global_count] - .data_offset_64bit - : comp_data->globals[global_idx - import_global_count] - .data_offset_32bit); global_type = comp_data->globals[global_idx - import_global_count].type.val_type; } @@ -193,13 +410,7 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (comp_ctx->enable_gc && aot_is_type_gc_reftype(global_type)) global_type = VALUE_TYPE_GC_REF; - offset = I32_CONST(global_offset); - if (!(global_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, - func_ctx->aot_inst, &offset, 1, - "global_ptr_tmp"))) { - aot_set_last_error("llvm build in bounds gep failed."); - return false; - } + global_ptr = get_global_value_addr(comp_ctx, func_ctx, global_idx); switch (global_type) { case VALUE_TYPE_I32: diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index d9974eed4..51f33dffb 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -7,6 +7,7 @@ #include "aot_llvm_extra2.h" #include "aot_compiler.h" #include "aot_emit_exception.h" +// TODO: remove me if get_module_inst_extra_offset() has been moved out #include "aot_emit_table.h" #include "../aot/aot_runtime.h" #include "../aot/aot_intrinsic.h" diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2461555be..92633781d 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -142,6 +142,11 @@ typedef struct WASMMemoryInstance *wasm_memory_inst_t; struct WASMTableInstance; typedef struct WASMTableInstance *wasm_table_inst_t; +/*TODO: remove me when rebasing*/ +/* Global instance*/ +struct WASMGlobalInstance; +typedef struct WASMGlobalInstance *wasm_global_inst_t; + /* WASM section */ typedef struct wasm_section_t { struct wasm_section_t *next; @@ -282,6 +287,7 @@ typedef struct LoadArgs { } LoadArgs; #endif /* LOAD_ARGS_OPTION_DEFINED */ +/*TODO: move it to wasm_runtime_common.h? */ typedef struct WASMExternInstance { const char *module_name; const char *field_name; @@ -289,7 +295,14 @@ typedef struct WASMExternInstance { union { wasm_memory_inst_t memory; wasm_table_inst_t table; + wasm_global_inst_t global; } u; + + /* + * to handle imports properly, + * especially for wasm_global_inst_t and wasm_func_inst_t + */ + wasm_module_inst_t dep_inst; } WASMExternInstance, *wasm_extern_inst_t; #ifndef INSTANTIATION_ARGS_OPTION_DEFINED @@ -335,13 +348,6 @@ typedef struct wasm_val_t { } wasm_val_t; #endif -/* Global instance*/ -typedef struct wasm_global_inst_t { - wasm_valkind_t kind; - bool is_mutable; - void *global_data; -} wasm_global_inst_t; - typedef enum { WASM_LOG_LEVEL_FATAL = 0, WASM_LOG_LEVEL_ERROR = 1, @@ -1099,6 +1105,11 @@ wasm_memory_get_base_address(const wasm_memory_inst_t memory_inst); WASM_RUNTIME_API_EXTERN bool wasm_memory_enlarge(wasm_memory_inst_t memory_inst, uint64_t inc_page_count); +WASM_RUNTIME_API_EXTERN wasm_global_inst_t +wasm_runtime_create_immutable_global(const wasm_module_t module, + const wasm_global_type_t type, + const wasm_val_t *value); + /** * Call the given WASM function of a WASM module instance with * arguments (bytecode and AoT). @@ -1754,10 +1765,9 @@ wasm_runtime_unregister_natives(const char *module_name, * @return true if success, false otherwise * */ -WASM_RUNTIME_API_EXTERN bool +WASM_RUNTIME_API_EXTERN wasm_global_inst_t wasm_runtime_get_export_global_inst(const wasm_module_inst_t module_inst, - const char *name, - wasm_global_inst_t *global_inst); + const char *name); /** * @brief Retrieves the table instance exported from a WebAssembly module @@ -2384,14 +2394,6 @@ wasm_runtime_create_imports_with_builtin(wasm_module_t module, wasm_extern_inst_t out, uint32_t out_len); -WASM_RUNTIME_API_EXTERN void -wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports); - -WASM_RUNTIME_API_EXTERN bool -wasm_runtime_create_imports(wasm_module_t module, - bool (*module_name_filter)(const char *), - wasm_extern_inst_t out, uint32_t out_len); - #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 46129d517..4c9f9faaf 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -608,18 +608,23 @@ typedef struct WASMGlobalImport { char *module_name; char *field_name; WASMGlobalType type; + + /*TODO: not necessary if WASM_ENABLE_MULTI_MODULE == 0*/ bool is_linked; /* global data after linked */ WASMValue global_data_linked; + #if WASM_ENABLE_GC != 0 WASMRefType *ref_type; #endif + #if WASM_ENABLE_MULTI_MODULE != 0 /* imported function pointer after linked */ /* TODO: remove if not needed */ WASMModule *import_module; WASMGlobal *import_global_linked; #endif + #if WASM_ENABLE_FAST_JIT != 0 /* The data offset of current global in global data */ uint32 data_offset; diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 21b306cee..e0803f358 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1549,19 +1549,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ -static inline uint8 * -get_global_addr(uint8 *global_data, WASMGlobalInstance *global) -{ -#if WASM_ENABLE_MULTI_MODULE == 0 - return global_data + global->data_offset; -#else - return global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif -} - static void wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMExecEnv *exec_env, diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 84dbc14f3..55d8d6d57 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1450,19 +1450,6 @@ wasm_interp_dump_op_count() static void **global_handle_table; #endif -static inline uint8 * -get_global_addr(uint8 *global_data, WASMGlobalInstance *global) -{ -#if WASM_ENABLE_MULTI_MODULE == 0 - return global_data + global->data_offset; -#else - return global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif -} - static void wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMExecEnv *exec_env, diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f2ec0886b..be14d27b3 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -2991,7 +2991,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, return false; } +#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_LIBC_BUILTIN != 0 + /* link with libc-builtin provided */ ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name, global); if (ret) { @@ -3004,7 +3006,8 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, global->is_linked = true; } #endif -#if WASM_ENABLE_MULTI_MODULE != 0 + + /* link with other modules' */ if (!global->is_linked && !wasm_runtime_is_built_in_module(sub_module_name)) { sub_module = (WASMModule *)wasm_runtime_load_depended_module( @@ -3022,7 +3025,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, } } } -#endif +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ global->module_name = sub_module_name; global->field_name = global_name; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 198b5cc94..4c5883b65 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -296,8 +296,7 @@ memories_deinstantiate(WASMModuleInstance *module_inst) #else wasm_runtime_free(memory); #endif -#endif - (void)memory; +#endif /* WASM_ENABLE_MULTI_MODULE == 0 */ } for (; mem_index < module->memory_count; mem_index++) { @@ -772,8 +771,10 @@ tables_deinstantiate(WASMModuleInstance *module_inst) } #endif - wasm_runtime_free(module_inst->tables); - module_inst->tables = NULL; + if (module_inst->tables) { + wasm_runtime_free(module_inst->tables); + module_inst->tables = NULL; + } } /** @@ -1265,7 +1266,7 @@ instantiate_struct_global_recursive(WASMModule *module, (WASMStructNewInitValues *)wasm_value->data; WASMStructObjectRef field = instantiate_struct_global_recursive( - module, module_inst, heap_type, + module, module_inst, (uint32)heap_type, init_values1 ? INIT_EXPR_TYPE_STRUCT_NEW : INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT, init_values1, error_buf, error_buf_size); @@ -1370,6 +1371,7 @@ instantiate_array_global_recursive(WASMModule *module, */ static WASMGlobalInstance * globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, + const WASMExternInstance *imports, uint32 import_count, char *error_buf, uint32 error_buf_size) { WASMImport *import; @@ -1385,66 +1387,99 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, /* instantiate globals from import section */ global = globals; import = module->import_globals; - for (i = 0; i < module->import_global_count; i++, import++) { - WASMGlobalImport *global_import = &import->u.global; - global->type = global_import->type.val_type; - global->is_mutable = global_import->type.is_mutable; + for (i = 0; i < module->import_global_count; i++, import++, global++) { + WASMGlobalImport *import_global_type = &import->u.global; + + global->type = import_global_type->type.val_type; + global->is_mutable = import_global_type->type.is_mutable; #if WASM_ENABLE_GC != 0 - global->ref_type = global_import->ref_type; + global->ref_type = import_global_type->ref_type; #endif +#if WASM_ENABLE_FAST_JIT != 0 + bh_assert(global_data_offset == import_global_type->data_offset); +#endif + global->data_offset = global_data_offset; + global_data_offset += wasm_value_type_size(global->type); + #if WASM_ENABLE_MULTI_MODULE != 0 - if (global_import->import_module) { + if (import_global_type->import_module) { if (!(global->import_module_inst = get_sub_module_inst( - module_inst, global_import->import_module))) { + module_inst, import_global_type->import_module))) { set_error_buf(error_buf, error_buf_size, "unknown global"); goto fail; } - if (!(global->import_global_inst = wasm_lookup_global( - global->import_module_inst, global_import->field_name))) { + if (!(global->import_global_inst = + wasm_lookup_global(global->import_module_inst, + import_global_type->field_name))) { set_error_buf(error_buf, error_buf_size, "unknown global"); goto fail; } /* The linked global instance has been initialized, we just need to copy the value. */ - bh_memcpy_s(&(global->initial_value), sizeof(WASMValue), - &(global_import->import_global_linked->init_expr.u), - sizeof(WASMValue)); + bh_memcpy_s( + &(global->initial_value), sizeof(WASMValue), + &(import_global_type->import_global_linked->init_expr.u), + sizeof(WASMValue)); } - else -#endif - { +#if WASM_ENABLE_LIBC_BUILTIN != 0 + else { /* native globals share their initial_values in one module */ bh_memcpy_s(&(global->initial_value), sizeof(WASMValue), - &(global_import->global_data_linked), + &(import_global_type->global_data_linked), sizeof(WASMValue)); } -#if WASM_ENABLE_FAST_JIT != 0 - bh_assert(global_data_offset == global_import->data_offset); #endif - global->data_offset = global_data_offset; - global_data_offset += wasm_value_type_size(global->type); - global++; +#else + + /* refer to the imported global */ + const WASMExternInstance *extern_inst = + wasm_runtime_get_extern_instance(imports, import_count, + WASM_IMPORT_EXPORT_KIND_GLOBAL, i); + if (!extern_inst) { + LOG_ERROR("missing an import global(%s, %s)", + import_global_type->module_name, + import_global_type->field_name); + goto fail; + } + + /* just in case */ +#ifndef NDEBUG + if (strcmp(import_global_type->field_name, extern_inst->field_name)) { + LOG_ERROR( + "mismatched import global name: expect \"%s\", got \"%s\"", + import_global_type->field_name, extern_inst->field_name); + goto fail; + } +#endif + + bh_memcpy_s(&(global->initial_value), sizeof(WASMValue), + &(extern_inst->u.global->initial_value), sizeof(WASMValue)); + global->import_module_inst = + (WASMModuleInstance *)extern_inst->dep_inst; + global->import_global_inst = extern_inst->u.global; +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ } /* instantiate globals from global section */ - for (i = 0; i < module->global_count; i++) { - InitializerExpression *init_expr = &(module->globals[i].init_expr); - uint8 flag = init_expr->init_expr_type; - + for (i = 0; i < module->global_count; i++, global++) { global->type = module->globals[i].type.val_type; global->is_mutable = module->globals[i].type.is_mutable; + +#if WASM_ENABLE_GC != 0 + global->ref_type = module->globals[i].ref_type; +#endif + #if WASM_ENABLE_FAST_JIT != 0 bh_assert(global_data_offset == module->globals[i].data_offset); #endif global->data_offset = global_data_offset; global_data_offset += wasm_value_type_size(global->type); -#if WASM_ENABLE_GC != 0 - global->ref_type = module->globals[i].ref_type; -#endif + InitializerExpression *init_expr = &(module->globals[i].init_expr); + uint8 flag = init_expr->init_expr_type; switch (flag) { case INIT_EXPR_TYPE_GET_GLOBAL: { @@ -1453,10 +1488,9 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, 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)); + bh_memcpy_s(&(global->initial_value), sizeof(WASMValue), + &(globals[init_expr->u.global_index].initial_value), + sizeof(WASMValue)); break; } #if WASM_ENABLE_GC != 0 @@ -1525,11 +1559,9 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, #endif /* end of WASM_ENABLE_GC != 0 */ default: bh_memcpy_s(&(global->initial_value), sizeof(WASMValue), - &(init_expr->u), sizeof(init_expr->u)); + &(init_expr->u), sizeof(WASMValue)); break; } - - global++; } bh_assert((uint32)(global - globals) == global_count); @@ -2105,6 +2137,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, } } +#if WASM_ENABLE_MULTI_MODULE != 0 for (i = 0; i < module->import_global_count; i++) { WASMGlobalImport *global = &((module->import_globals + i)->u.global); @@ -2126,10 +2159,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, WASMTableImport *table = &((module->import_tables + i)->u.table); if (!wasm_runtime_is_built_in_module(table->module_name) -#if WASM_ENABLE_MULTI_MODULE != 0 - && !table->import_table_linked -#endif - ) { + && !table->import_table_linked) { set_error_buf_v(error_buf, error_buf_size, "failed to link import table (%s, %s)", table->module_name, table->field_name); @@ -2138,25 +2168,17 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, } for (i = 0; i < module->import_memory_count; i++) { - WASMMemoryImport *type = &((module->import_memories + i)->u.memory); - WASMMemoryInstance *memory = module_inst->memories[i]; - (void)memory; - if ( -#if WASM_ENABLE_MULTI_MODULE != 0 - !wasm_runtime_is_built_in_module(type->module_name) - && !type->import_memory_linked -#else - !memory -#endif - ) { + WASMMemoryImport *memory = &((module->import_memories + i)->u.memory); + + if (!wasm_runtime_is_built_in_module(memory->module_name) + && !memory->import_memory_linked) { set_error_buf_v(error_buf, error_buf_size, "failed to link import memory (%s, %s)", - type->module_name, type->field_name); + memory->module_name, memory->field_name); return false; } } -#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_TAGS != 0 for (i = 0; i < module->import_tag_count; i++) { WASMTagImport *tag = &((module->import_tags + i)->u.tag); @@ -2169,7 +2191,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, } } #endif /* WASM_ENABLE_TAGS != 0 */ -#endif +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ return true; } @@ -2726,8 +2748,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, */ global_count = module->import_global_count + module->global_count; if (global_count - && !(globals = globals_instantiate(module, module_inst, error_buf, - error_buf_size))) { + && !(globals = + globals_instantiate(module, module_inst, imports, import_count, + error_buf, error_buf_size))) { goto fail; } module_inst->e->global_count = global_count; @@ -2820,6 +2843,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, goto fail; } + /*TODO: init_global_data() ?*/ + /* WASMGlobalInstance->initial_value => WASMModuleInstance->global_data*/ if (global_count > 0) { /* Initialize the global data */ global_data = module_inst->global_data; @@ -2892,7 +2917,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, /* UINT32_MAX indicates that it is a null reference */ if ((uint32)global->initial_value.i32 != UINT32_MAX) { if (!(func_obj = wasm_create_func_obj( - module_inst, global->initial_value.i32, + module_inst, global->initial_value.u32, false, error_buf, error_buf_size))) goto fail; } @@ -3175,19 +3200,21 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #endif #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( + table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST + || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_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); #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( + table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST + || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_CONST + || table_seg->base_offset.init_expr_type + == INIT_EXPR_TYPE_GET_GLOBAL); #endif /* init vec(funcidx) or vec(expr) */ @@ -3410,7 +3437,7 @@ 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.u32); break; } #endif /* end of WASM_ENABLE_GC != 0 */ @@ -5395,4 +5422,37 @@ wasm_destroy_table(WASMTableInstance *table) return; wasm_runtime_free(table); +} + +WASMGlobalInstance * +wasm_create_global(const WASMModule *module, WASMModuleInstance *dep_inst, + WASMGlobalType *type) +{ + WASMGlobalInstance *global = + runtime_malloc(sizeof(WASMGlobalInstance), NULL, 0); + if (!global) { + return NULL; + } + + global->type = type->val_type; + global->is_mutable = type->is_mutable; + global->import_module_inst = dep_inst; + /* empty global. set value later by wasm_set_global_value */ + return global; +} + +void +wasm_set_global_value(WASMGlobalInstance *global, const WASMValue *value) +{ + bh_memcpy_s(&global->initial_value, sizeof(WASMValue), value, + sizeof(WASMValue)); +} + +void +wasm_destroy_global(WASMGlobalInstance *global) +{ + if (!global) + return; + + wasm_runtime_free(global); } \ No newline at end of file diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 6eebaa130..e76ee487b 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -192,19 +192,23 @@ struct WASMGlobalInstance { uint8 type; /* mutable or constant */ bool is_mutable; + /* data offset to the address of initial_value, started from the end of * WASMMemoryInstance(start of WASMGlobalInstance)*/ uint32 data_offset; - /* initial value */ + + /* + * initial value (before instantiation stage) + * - host creation. store initial value directly. no init expr + * - as a temp value before storing in global_data + */ WASMValue initial_value; -#if WASM_ENABLE_GC != 0 - WASMRefType *ref_type; -#endif -#if WASM_ENABLE_MULTI_MODULE != 0 + /* just for import, keep the reference here */ - WASMModuleInstance *import_module_inst; - WASMGlobalInstance *import_global_inst; -#endif + DefPointer(WASMModuleInstance *, import_module_inst); + DefPointer(WASMGlobalInstance *, import_global_inst); + /* WASMRefType *ref_type */ + DefPointer(void *, ref_type); }; struct WASMFunctionInstance { @@ -563,6 +567,24 @@ wasm_get_tbl_data_slots(const WASMTableType *table_type, #endif } +static inline uint8 * +get_global_addr(uint8 *global_data, WASMGlobalInstance *global) +{ + /* + * global->import_global_inst != NULL means the global is imported + * from another module. + * global->import_module_isnt != NULL means the data is stored in + * local module instance. + * + * A host created global doesn't have its own global_data need to + * be maintained. + */ + return global->import_module_inst + ? global->import_module_inst->global_data + + global->import_global_inst->data_offset + : global_data + global->data_offset; +} + WASMModule * wasm_load(uint8 *buf, uint32 size, #if WASM_ENABLE_MULTI_MODULE != 0 @@ -956,6 +978,16 @@ wasm_set_table_elem(const WASMModule *module, WASMTableInstance *table, void wasm_destroy_table(WASMTableInstance *table); +WASMGlobalInstance * +wasm_create_global(const WASMModule *module, WASMModuleInstance *dep_inst, + WASMGlobalType *type); + +void +wasm_set_global_value(WASMGlobalInstance *global, const WASMValue *value); + +void +wasm_destroy_global(WASMGlobalInstance *global); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/libc-builtin/SConscript b/core/iwasm/libraries/libc-builtin/SConscript index 8dd004382..34483c668 100644 --- a/core/iwasm/libraries/libc-builtin/SConscript +++ b/core/iwasm/libraries/libc-builtin/SConscript @@ -10,6 +10,8 @@ cwd = GetCurrentDir() #src = Split(''' #libc_builtin_wrapper.c +#spec_test_builtin_wrapper.c +#wasi_test_builtin_wrapper.c #''') src = Glob('*.c') diff --git a/core/iwasm/libraries/libc-builtin/builtin_wrapper.h b/core/iwasm/libraries/libc-builtin/builtin_wrapper.h new file mode 100644 index 000000000..de5cf77e5 --- /dev/null +++ b/core/iwasm/libraries/libc-builtin/builtin_wrapper.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +#ifndef _BUILTIN_WRAPPER_H_ +#define _BUILTIN_WRAPPER_H_ + +#include "wasm_export.h" +#include "../interpreter/wasm.h" +#include "../common/wasm_runtime_common.h" + +/************************************* + * Functions + *************************************/ + +/************************************* + * Globals + *************************************/ +typedef struct WASMNativeGlobalDef { + const char *module_name; + const char *name; + uint8 type; + bool is_mutable; + WASMValue value; +} WASMNativeGlobalDef; + +/************************************* + * Tables + *************************************/ + +typedef struct WASMNativeTableDef { + const char *module_name; + const char *name; + uint8 elem_type; + +} WASMNativeTableDef; + +/************************************* + * Memories + *************************************/ + +typedef struct WASMNativeMemoryDef { + const char *module_name; + const char *name; +} WASMNativeMemoryDef; + +#endif diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin.cmake b/core/iwasm/libraries/libc-builtin/libc_builtin.cmake index 0838712b8..859eb9cbb 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin.cmake +++ b/core/iwasm/libraries/libc-builtin/libc_builtin.cmake @@ -5,9 +5,16 @@ set (LIBC_BUILTIN_DIR ${CMAKE_CURRENT_LIST_DIR}) add_definitions (-DWASM_ENABLE_LIBC_BUILTIN=1) -include_directories(${LIBC_BUILTIN_DIR}) +include_directories (${LIBC_BUILTIN_DIR}) -file (GLOB source_all ${LIBC_BUILTIN_DIR}/*.c) +list (APPEND source_all ${LIBC_BUILTIN_DIR}/libc_builtin_wrapper.c) + +if (WAMR_BUILD_SPEC_TEST EQUAL 1) + list (APPEND source_all ${LIBC_BUILTIN_DIR}/spec_test_builtin_wrapper.c) +endif () + +if (WAMR_BUILD_WASI_TEST EQUAL 1) + list (APPEND source_all ${LIBC_BUILTIN_DIR}/wasi_test_builtin_wrapper.c) +endif () set (LIBC_BUILTIN_SOURCE ${source_all}) - diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index a68c07494..ace018332 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -5,8 +5,7 @@ #include "bh_common.h" #include "bh_log.h" -#include "wasm_export.h" -#include "../interpreter/wasm.h" +#include "builtin_wrapper.h" #if defined(_WIN32) || defined(_WIN32_) #define strncasecmp _strnicmp @@ -1129,15 +1128,8 @@ get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis) * Global Variables * *************************************/ -typedef struct WASMNativeGlobalDef { - const char *module_name; - const char *global_name; - uint8 type; - bool is_mutable; - WASMValue value; -} WASMNativeGlobalDef; - static WASMNativeGlobalDef native_global_defs[] = { +#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_SPEC_TEST != 0 { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 }, { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 }, @@ -1148,13 +1140,19 @@ static WASMNativeGlobalDef native_global_defs[] = { { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 }, { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 }, { "test", "g", VALUE_TYPE_I32, true, .value.i32 = 0 }, + #if WASM_ENABLE_GC != 0 { "G", "g", VALUE_TYPE_I32, false, .value.i32 = 4 }, { "M", "g", REF_TYPE_HT_NON_NULLABLE, false, .value.gc_obj = 0 }, #endif -#endif - { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL }, - { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL } + +#endif /* WASM_ENABLE_SPEC_TEST != 0 */ +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ + + { "global", "NaN", VALUE_TYPE_F64, false, + .value.u64 = 0x7FF8000000000000LL }, + { "global", "Infinity", VALUE_TYPE_F64, false, + .value.u64 = 0x7FF0000000000000LL } }; bool @@ -1172,7 +1170,7 @@ wasm_native_lookup_libc_builtin_global(const char *module_name, /* Lookup constant globals which can be defined by table */ while (global_def < global_def_end) { if (!strcmp(global_def->module_name, module_name) - && !strcmp(global_def->global_name, global_name)) { + && !strcmp(global_def->name, global_name)) { global->type.val_type = global_def->type; global->type.is_mutable = global_def->is_mutable; global->global_data_linked = global_def->value; @@ -1183,3 +1181,15 @@ wasm_native_lookup_libc_builtin_global(const char *module_name, return false; } + +/* + * it is a workaround to fix undefined reference to + * `wasm_runtime_create_extern_inst_for_spec_test' + */ +#if defined(__NuttX__) + +#if WASM_ENABLE_SPEC_TEST != 0 +#include "./spec_test_builtin_wrapper.c" +#endif + +#endif diff --git a/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c new file mode 100644 index 000000000..9305be628 --- /dev/null +++ b/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_log.h" +#include "builtin_wrapper.h" + +/************************************* + * Functions + *************************************/ + +/************************************* + * Globals + *************************************/ + +static WASMNativeGlobalDef spec_test_global_defs[] = { + /* for standard spec test */ + { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 }, + { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 }, + { "spectest", "global_f32", VALUE_TYPE_F32, false, .value.f32 = 666.6f }, + { "spectest", "global_f64", VALUE_TYPE_F64, false, .value.f64 = 666.6 }, + { "test", "global-i32", VALUE_TYPE_I32, false, .value.i32 = 0 }, + { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 }, + { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 }, + { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 }, + { "test", "g", VALUE_TYPE_I32, true, .value.i32 = 0 }, +/* for gc spec test */ +#if WASM_ENABLE_GC != 0 + { "G", "g", VALUE_TYPE_I32, false, .value.i32 = 4 }, + { "M", "g", REF_TYPE_HT_NON_NULLABLE, false, .value.gc_obj = 0 }, +#endif +}; + +static wasm_global_inst_t +create_spec_test_global(wasm_module_t module, const char *module_name, + const char *name, wasm_global_type_t type) +{ + if (!module || !module_name || !name || !type) { + return NULL; + } + + WASMNativeGlobalDef *global_def = spec_test_global_defs; + uint32 size = sizeof(spec_test_global_defs) / sizeof(WASMNativeGlobalDef); + WASMNativeGlobalDef *global_def_end = global_def + size; + for (; global_def < global_def_end; global_def++) { + if (strcmp(global_def->module_name, module_name) != 0) { + continue; + } + + if (strcmp(global_def->name, name) != 0) { + continue; + } + + wasm_global_inst_t global = + wasm_runtime_create_global_internal(module, NULL, type); + if (!global) { + return NULL; + } + + wasm_runtime_set_global_value(module, global, &global_def->value); + return global; + } + + return NULL; +} + +/************************************* + * Tables + *************************************/ +static WASMNativeTableDef builtin_table_defs[] = { + { "spectest", "table", VALUE_TYPE_FUNCREF }, + { "spectest", "table64", VALUE_TYPE_FUNCREF }, +}; + +static wasm_table_inst_t +create_spec_test_table(wasm_module_t module, const char *module_name, + const char *name, wasm_table_type_t type) +{ + if (!module || !module_name || !name || !type) { + return NULL; + } + + WASMNativeTableDef *table_def = builtin_table_defs; + size_t count = sizeof(builtin_table_defs) / sizeof(WASMNativeTableDef); + WASMNativeTableDef *table_def_end = builtin_table_defs + count; + + for (; table_def < table_def_end; table_def++) { + if (strcmp(table_def->module_name, module_name) != 0) { + continue; + } + + if (strcmp(table_def->name, name) != 0) { + continue; + } + + return wasm_runtime_create_table(module, type); + } + + return NULL; +} + +/************************************* + * Memories + *************************************/ + +/* + * no predefined memory for spec test + */ +static wasm_memory_inst_t +create_spec_test_memory(wasm_module_t module, const char *module_name, + const char *name, wasm_memory_type_t type) +{ + if (!module || !module_name || !name || !type) { + return NULL; + } + + if (strcmp(module_name, "spectest") != 0) { + return NULL; + } + + if (strcmp(name, "memory") != 0) { + return NULL; + } + + return wasm_runtime_create_memory(module, type); +} + +/************************************* + * Extern + *************************************/ + +bool +wasm_runtime_create_extern_inst_for_spec_test(wasm_module_t module, + wasm_import_t *import_type, + WASMExternInstance *out) +{ + if (!module || !import_type || !out) + return false; + + LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name, + import_type->name, import_type->kind); + + out->module_name = import_type->module_name; + out->field_name = import_type->name; + out->kind = import_type->kind; + + if (import_type->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { + out->u.memory = create_spec_test_memory( + module, import_type->module_name, import_type->name, + import_type->u.memory_type); + if (!out->u.memory) { + LOG_ERROR("create memory failed\n"); + return false; + } + } + else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_TABLE) { + out->u.table = create_spec_test_table(module, import_type->module_name, + import_type->name, + import_type->u.table_type); + if (!out->u.table) { + LOG_ERROR("create table failed\n"); + return false; + } + } + else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) { + out->u.global = create_spec_test_global( + module, import_type->module_name, import_type->name, + import_type->u.global_type); + if (!out->u.global) { + LOG_ERROR("create global failed\n"); + return false; + } + } + else { + LOG_DEBUG("unimplemented import(%s,%s) kind %d for spec test", + import_type->module_name, import_type->name, + import_type->kind); + } + + return true; +} diff --git a/core/iwasm/libraries/libc-builtin/wasi_test_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/wasi_test_builtin_wrapper.c new file mode 100644 index 000000000..7767c6a24 --- /dev/null +++ b/core/iwasm/libraries/libc-builtin/wasi_test_builtin_wrapper.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_log.h" +#include "builtin_wrapper.h" + +/************************************* + * Functions + *************************************/ + +/************************************* + * Globals + *************************************/ + +/************************************* + * Tables + *************************************/ + +/************************************* + * Memories + *************************************/ + +static WASMNativeMemoryDef builtin_memory_defs[] = { + { "foo", "bar" }, + { "env", "memory" }, +}; + +static wasm_memory_inst_t +create_wasi_test_memory(wasm_module_t module, const char *module_name, + const char *name, wasm_memory_type_t type) +{ + if (!module || !module_name || !name || !type) { + return NULL; + } + + WASMNativeMemoryDef *memory_def = builtin_memory_defs; + size_t count = sizeof(builtin_memory_defs) / sizeof(WASMNativeMemoryDef); + WASMNativeMemoryDef *memory_def_end = builtin_memory_defs + count; + + for (; memory_def < memory_def_end; memory_def++) { + if (strcmp(memory_def->module_name, module_name) != 0) { + continue; + } + + if (strcmp(memory_def->name, name) != 0) { + continue; + } + + return wasm_runtime_create_memory(module, type); + } + + return NULL; +} + +/************************************* + * Extern + *************************************/ + +bool +wasm_runtime_create_extern_inst_for_wasi_test(wasm_module_t module, + wasm_import_t *import_type, + WASMExternInstance *out) +{ + if (!module || !import_type || !out) + return false; + + LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name, + import_type->name, import_type->kind); + + out->module_name = import_type->module_name; + out->field_name = import_type->name; + out->kind = import_type->kind; + + if (import_type->kind != WASM_IMPORT_EXPORT_KIND_MEMORY) { + LOG_DEBUG("unimplemented import(%s,%s) kind %d for wasi test", + import_type->module_name, import_type->name, + import_type->kind); + return true; + } + + out->u.memory = + create_wasi_test_memory(module, import_type->module_name, + import_type->name, import_type->u.memory_type); + if (!out->u.memory) { + LOG_ERROR("create memory failed\n"); + return false; + } + + return true; +} \ No newline at end of file diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index fbcbfe202..b7a9248bc 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -1048,7 +1048,7 @@ function trigger() if [[ $TEST_CASE_ARR ]]; then for test in "${TEST_CASE_ARR[@]}"; do if [[ "$test" == "wasi_certification" ]]; then - EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_WASI_TEST=1" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_WASI_TEST=1 -DWAMR_BUILD_SPEC_TEST=0" fi if [[ "$test" == "wasi_certification" || "$test" == "standalone" ]]; then