diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 31d28b83bf..47b42e3b24 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -668,7 +668,7 @@ load_native_symbol_section(const uint8 *buf, const uint8 *buf_end, goto fail; } - for (i = cnt - 1; i >= 0; i--) { + for (i = (int32)cnt - 1; i >= 0; i--) { read_string(p, p_end, symbol); if (!strlen(symbol)) continue; @@ -3840,7 +3840,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, /* The layout is: literal size + literal + code (with plt table) */ uint8 *mmap_addr = module->literal - sizeof(uint32); uint32 total_size = - sizeof(uint32) + module->literal_size + module->code_size; + (uint32)sizeof(uint32) + module->literal_size + module->code_size; os_mprotect(mmap_addr, total_size, map_prot); } @@ -4529,7 +4529,7 @@ aot_unload(AOTModule *module) /* The layout is: literal size + literal + code (with plt table) */ uint8 *mmap_addr = module->literal - sizeof(uint32); uint32 total_size = - sizeof(uint32) + module->literal_size + module->code_size; + (uint32)sizeof(uint32) + module->literal_size + module->code_size; os_munmap(mmap_addr, total_size); } diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 4b2d4ac93c..e32fbbec9c 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -127,6 +127,28 @@ runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size) return mem; } +#if WASM_ENABLE_MULTI_MODULE != 0 +static AOTModuleInstance * +get_sub_module_inst(const AOTModuleInstance *parent_module_inst, + const AOTModule *sub_module) +{ + bh_list *sub_module_inst_list = parent_module_inst->e->sub_module_inst_list; + WASMSubModInstNode *node = bh_list_first_elem(sub_module_inst_list); + + AOTModuleInstance *inst = (AOTModuleInstance *)node->module_inst; + while (node && sub_module != (AOTModule *)inst->module) { + node = bh_list_elem_next(node); + inst = (AOTModuleInstance *)node->module_inst; + } + + if (!node) { + LOG_DEBUG("fail to find sub module instance"); + } + + return node ? inst : NULL; +} +#endif + #if WASM_ENABLE_AOT_STACK_FRAME != 0 static bool is_tiny_frame(WASMExecEnv *exec_env) @@ -760,6 +782,107 @@ globals_instantiate(AOTModuleInstance *module_inst, AOTModule *module, return NULL; } +static AOTFunctionInstance * +import_functions_instantiate(AOTModuleInstance *module_inst, AOTModule *module, + const WASMExternInstance *imports, + uint32 import_count, char *error_buf, + uint32 error_buf_size) +{ + uint64 total_size = sizeof(AOTFunctionInstance) * module->import_func_count; + + AOTFunctionInstance *functions = + runtime_malloc(total_size, error_buf, error_buf_size); + if (!functions) { + return NULL; + } + + AOTFunctionInstance *function = functions; + for (uint32 i = 0; i < module->import_func_count; i++, function++) { + function->is_import_func = true; + function->func_index = i; + + AOTImportFunc *import = module->import_funcs + i; + /*TODO: use name section content? */ + function->func_name = import->func_name; + function->u.func_import = import; + +#if WASM_ENABLE_MULTI_MODULE != 0 + if (import->import_module) { + /* from other .wasm */ + function->import_module_inst = + get_sub_module_inst(module_inst, import->import_module); + if (!function->import_module_inst) { + set_error_buf_v(error_buf, error_buf_size, + "unknown import module \"%s\"", + import->module_name); + goto fail; + } + + function->import_func_inst = aot_lookup_function( + function->import_module_inst, import->func_name); + if (!function->import_func_inst) { + set_error_buf_v(error_buf, error_buf_size, + "unknown import function \"%s\"", + import->func_name); + goto fail; + } + } + + /* from c_api (loading) */ + function->call_conv_wasm_c_api = import->call_conv_wasm_c_api; +#else + const WASMExternInstance *extern_inst = + wasm_runtime_get_extern_instance(imports, import_count, + WASM_IMPORT_EXPORT_KIND_FUNC, i); + if (!extern_inst) { + LOG_DEBUG("no import function(%s, %s) from imports list, might " + "provided by wasm_native", + import->module_name, import->func_name); + /* so it's from wasm_native */ + continue; + } + + /* if extern_inst is about a wasm function from other .wasm */ + AOTFunctionInstance *extern_inst_func = + (AOTFunctionInstance *)extern_inst->u.function; + if (!extern_inst_func) { + LOG_DEBUG("empty extern_inst_func for import function(%s, %s)", + "might provided by wasm_native", import->module_name, + import->func_name); + /* so it's from wasm_native */ + continue; + } + + bh_assert(extern_inst_func->is_import_func); + + /* don't allow wrong matchment */ + if (strcmp(import->func_name, extern_inst->field_name)) { + LOG_ERROR( + "mismatched import memory name: expect \"%s\", got \"%s\"", + import->func_name, extern_inst->field_name); + goto fail; + } + + /* from other .wasm */ + function->import_module_inst = extern_inst_func->import_module_inst; + function->import_func_inst = extern_inst_func->import_func_inst; + + /* from c_api (instantiation)*/ + function->call_conv_wasm_c_api = extern_inst_func->call_conv_wasm_c_api; + /* TODO: for now, let c_api finish this. Will move it to wasm_runtime + * later */ + /*module_inst->c_api_func_imports[i] = + * extern_inst_func->import_func_c_api;*/ + +#endif + } + + return functions; +fail: + wasm_runtime_free(functions); + return NULL; +} + /** * Destroy table instances. */ @@ -1602,6 +1725,7 @@ aot_destroy_memory(AOTMemoryInstance *memory) static bool init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module, + const WASMExternInstance *imports, uint32 import_count, char *error_buf, uint32 error_buf_size) { uint32 i; @@ -1621,12 +1745,32 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module, /* Set import function pointers */ func_ptrs = (void **)module_inst->func_ptrs; for (i = 0; i < module->import_func_count; i++, func_ptrs++) { - *func_ptrs = (void *)module->import_funcs[i].func_ptr_linked; - if (!*func_ptrs) { - const char *module_name = module->import_funcs[i].module_name; - const char *field_name = module->import_funcs[i].func_name; - LOG_WARNING("warning: failed to link import function (%s, %s)", - module_name, field_name); + AOTFunctionInstance *func = + aot_locate_import_function_instance(module_inst, i); + bh_assert(func->is_import_func); + + if (func->call_conv_wasm_c_api) { + /* when execution, goes to invoke_native() and use + * c_api_func_imports*/ + continue; + } + + if (func->import_module_inst) { + /* when execution, goes to invoke_native() and switch to another + * .wasm */ + continue; + } + + AOTImportFunc *import_func = func->u.func_import; + + LOG_DEBUG("use wasm_native linked functions for (%s,%s)", + import_func->module_name, import_func->func_name); + + *func_ptrs = import_func->func_ptr_linked; + + if (!func_ptrs) { + LOG_WARNING("warning: failed to link import function (%s,%s)", + import_func->module_name, import_func->func_name); } } @@ -1697,69 +1841,16 @@ aot_lookup_function_with_idx(AOTModuleInstance *module_inst, uint32 func_idx) return func_inst; } +/*TODO: */ AOTFunctionInstance * aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx) { - AOTModule *module = (AOTModule *)module_inst->module; AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e; - AOTFunctionInstance *func_inst; + AOTFunctionInstance *import_functions = extra->import_functions; - /* lookup from export functions first */ - if ((func_inst = aot_lookup_function_with_idx(module_inst, func_idx))) - return func_inst; + bh_assert(import_functions); - exception_lock(module_inst); - - /* allocate functions array if needed */ - if (!extra->functions) { - uint64 func_count = - ((uint64)module->import_func_count + module->func_count); - uint64 total_size = func_count * (uint64)sizeof(AOTFunctionInstance *); - - if ((func_count == 0) - || !(extra->functions = runtime_malloc(total_size, NULL, 0))) { - exception_unlock(module_inst); - return NULL; - } - - extra->function_count = (uint32)func_count; - } - - /* instantiate function if needed */ - bh_assert(func_idx < extra->function_count); - if (!extra->functions[func_idx]) { - AOTFunctionInstance *function = (AOTFunctionInstance *)runtime_malloc( - sizeof(AOTFunctionInstance), NULL, 0); - if (!function) { - exception_unlock(module_inst); - return NULL; - } - - if (func_idx < module->import_func_count) { - /* instantiate function from import section */ - function->is_import_func = true; - function->func_name = module->import_funcs[func_idx].func_name; - function->func_index = func_idx; - function->u.func_import = &module->import_funcs[func_idx]; - } - else { - /* instantiate non-import function */ - uint32 ftype_index = - module->func_type_indexes[func_idx - module->import_func_count]; - function->is_import_func = false; - function->func_index = func_idx; - function->u.func.func_type = - (AOTFuncType *)module->types[ftype_index]; - function->u.func.func_ptr = - module->func_ptrs[func_idx - module->import_func_count]; - } - - extra->functions[func_idx] = function; - } - - exception_unlock(module_inst); - - return extra->functions[func_idx]; + return import_functions + func_idx; } static bool @@ -1799,6 +1890,7 @@ cmp_func_inst(const void *a, const void *b) return strcmp(func_inst1->func_name, func_inst2->func_name); } +/* TODO: Can I reuse the AOTFunctionInstance ?*/ static bool create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module, char *error_buf, uint32 error_buf_size) @@ -1818,26 +1910,33 @@ create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module, module_inst->export_functions = (void *)export_func; for (i = 0; i < module->export_count; i++) { - if (exports[i].kind == EXPORT_KIND_FUNC) { - export_func->func_name = exports[i].name; - export_func->func_index = exports[i].index; - if (export_func->func_index < module->import_func_count) { - export_func->is_import_func = true; - export_func->u.func_import = - &module->import_funcs[export_func->func_index]; - } - else { - export_func->is_import_func = false; - func_index = - export_func->func_index - module->import_func_count; - ftype_index = module->func_type_indexes[func_index]; - export_func->u.func.func_type = - (AOTFuncType *)module->types[ftype_index]; - export_func->u.func.func_ptr = - module->func_ptrs[func_index]; - } - export_func++; + if (exports[i].kind != EXPORT_KIND_FUNC) { + continue; + } + + export_func->func_index = exports[i].index; + + if (export_func->func_index < module->import_func_count) { + AOTFunctionInstance *import_func = + aot_locate_import_function_instance( + module_inst, export_func->func_index); + *export_func = *import_func; } + else { + export_func->is_import_func = false; + + func_index = + export_func->func_index - module->import_func_count; + ftype_index = module->func_type_indexes[func_index]; + export_func->u.func.func_type = + (AOTFuncType *)module->types[ftype_index]; + + export_func->u.func.func_ptr = module->func_ptrs[func_index]; + } + + /* always use export names */ + export_func->func_name = exports[i].name; + export_func++; } qsort(module_inst->export_functions, module_inst->export_func_count, @@ -1938,7 +2037,7 @@ lookup_post_instantiate_func(AOTModuleInstance *module_inst, static bool execute_post_instantiate_functions(AOTModuleInstance *module_inst, - bool is_sub_inst, WASMExecEnv *exec_env_main) + bool is_spawned, WASMExecEnv *exec_env_main) { AOTModule *module = (AOTModule *)module_inst->module; AOTFunctionInstance *initialize_func = NULL; @@ -1957,7 +2056,7 @@ execute_post_instantiate_functions(AOTModuleInstance *module_inst, * the environment at most once, and that none of their other exports * are accessed before that call. */ - if (!is_sub_inst && module->import_wasi_api) { + if (!is_spawned && module->import_wasi_api) { initialize_func = lookup_post_instantiate_func(module_inst, "_initialize"); } @@ -1965,7 +2064,7 @@ execute_post_instantiate_functions(AOTModuleInstance *module_inst, /* Execute possible "__post_instantiate" function if wasm app is compiled by emsdk's early version */ - if (!is_sub_inst) { + if (!is_spawned) { post_inst_func = lookup_post_instantiate_func(module_inst, "__post_instantiate"); } @@ -1973,7 +2072,7 @@ execute_post_instantiate_functions(AOTModuleInstance *module_inst, #if WASM_ENABLE_BULK_MEMORY != 0 /* Only execute the memory init function for main instance since the data segments will be dropped once initialized */ - if (!is_sub_inst + if (!is_spawned #if WASM_ENABLE_LIBC_WASI != 0 && !module->import_wasi_api #endif @@ -1989,7 +2088,7 @@ execute_post_instantiate_functions(AOTModuleInstance *module_inst, return true; } - if (is_sub_inst) { + if (is_spawned) { bh_assert(exec_env_main); #ifdef OS_ENABLE_HW_BOUND_CHECK /* May come from pthread_create_wrapper, thread_spawn_wrapper and @@ -2082,7 +2181,7 @@ execute_post_instantiate_functions(AOTModuleInstance *module_inst, ret = true; fail: - if (is_sub_inst) { + if (is_spawned) { /* Restore the parent exec_env's module inst */ wasm_exec_env_restore_module_inst(exec_env_main, module_inst_main); } @@ -2116,7 +2215,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, uint64 total_size, table_size = 0; uint8 *p; uint32 i, extra_info_offset; - const bool is_sub_inst = parent != NULL; + const bool is_spawned = parent != NULL; #if WASM_ENABLE_MULTI_MODULE != 0 bool ret = false; #endif @@ -2183,7 +2282,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, #if WASM_ENABLE_GC != 0 /* Initialize gc heap first since it may be used when initializing globals and others */ - if (!is_sub_inst) { + if (!is_spawned) { uint32 gc_heap_size = wasm_runtime_get_gc_heap_size_default(); if (gc_heap_size < GC_HEAP_SIZE_MIN) @@ -2205,16 +2304,6 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, #if WASM_ENABLE_MULTI_MODULE != 0 extra->sub_module_inst_list = &extra->sub_module_inst_list_head; - - /* Allocate memory for import_func_module_insts*/ - if (module->import_func_count > 0 - && !(extra->import_func_module_insts = - runtime_malloc((uint64)module->import_func_count - * sizeof(WASMModuleInstanceCommon *), - error_buf, error_buf_size))) { - goto fail; - } - ret = wasm_runtime_sub_module_instantiate( (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); @@ -2300,15 +2389,25 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, imports, import_count, error_buf, error_buf_size)) goto fail; + extra->function_count = module->import_func_count + module->func_count; + if (extra->function_count > 0) { + extra->import_functions = import_functions_instantiate( + module_inst, module, imports, import_count, error_buf, + error_buf_size); + if (!extra->import_functions) + goto fail; + } + /* Initialize function pointers */ - if (!init_func_ptrs(module_inst, module, error_buf, error_buf_size)) + if (!init_func_ptrs(module_inst, module, imports, import_count, error_buf, + error_buf_size)) goto fail; if (!create_exports(module_inst, module, error_buf, error_buf_size)) goto fail; #if WASM_ENABLE_LIBC_WASI != 0 - if (!is_sub_inst) { + if (!is_spawned) { if (!wasm_runtime_init_wasi( (WASMModuleInstanceCommon *)module_inst, module->wasi_args.dir_list, module->wasi_args.dir_count, @@ -2504,7 +2603,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, } #endif - if (!execute_post_instantiate_functions(module_inst, is_sub_inst, + if (!execute_post_instantiate_functions(module_inst, is_spawned, exec_env_main)) { set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); goto fail; @@ -2518,7 +2617,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, return module_inst; fail: - aot_deinstantiate(module_inst, is_sub_inst); + aot_deinstantiate(module_inst, is_spawned); return NULL; } @@ -2546,7 +2645,7 @@ destroy_c_api_frames(Vector *frames) #endif void -aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) +aot_deinstantiate(AOTModuleInstance *module_inst, bool is_spawned) { AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e; WASMModuleInstanceExtraCommon *common = &extra->common; @@ -2572,13 +2671,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) } #endif -#if WASM_ENABLE_MULTI_MODULE != 0 - wasm_runtime_sub_module_deinstantiate( - (WASMModuleInstanceCommon *)module_inst); - if (extra->import_func_module_insts) - wasm_runtime_free(extra->import_func_module_insts); -#endif - tables_deinstantiate(module_inst); if (module_inst->memories) @@ -2599,14 +2691,8 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (module_inst->export_tables) wasm_runtime_free(module_inst->export_tables); - if (extra->functions) { - uint32 func_idx; - for (func_idx = 0; func_idx < extra->function_count; ++func_idx) { - if (extra->functions[func_idx]) { - wasm_runtime_free(extra->functions[func_idx]); - } - } - wasm_runtime_free(extra->functions); + if (extra->import_functions) { + wasm_runtime_free(extra->import_functions); } if (extra->globals) { @@ -2623,7 +2709,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(module_inst->c_api_func_imports); #if WASM_ENABLE_GC != 0 - if (!is_sub_inst) { + if (!is_spawned) { if (common->gc_heap_handle) mem_allocator_destroy(common->gc_heap_handle); if (common->gc_heap_pool) @@ -2631,7 +2717,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) } #endif - if (!is_sub_inst) { + if (!is_spawned) { wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); } @@ -2798,11 +2884,17 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; bool ret; - void *func_ptr = function->is_import_func - ? function->u.func_import->func_ptr_linked - : function->u.func.func_ptr; void *attachment = NULL; + + /* init_func_ptrs() has already copied func_ptr_linked value */ + void *func_ptr = + aot_get_function_pointer(module_inst, function->func_index); + #if WASM_ENABLE_MULTI_MODULE != 0 + /* + * TODO: this searching for sub_module_inst + * should have been done during loading) + */ bh_list *sub_module_list_node = NULL; const char *sub_inst_name = NULL; const char *func_name = function->u.func_import->module_name; @@ -2836,6 +2928,10 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, snprintf(buf, sizeof(buf), "invalid argument count %u, must be no smaller than %u", argc, func_type->param_cell_num); + /* + * TODO: might need to roll back to the original module_inst + * if has been changed to sub module instance + */ aot_set_exception(module_inst, buf); return false; } @@ -3446,15 +3542,11 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, AOTModuleInstance *module_inst = (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env); AOTModule *aot_module = (AOTModule *)module_inst->module; - CApiFuncImport *c_api_func_import = - module_inst->c_api_func_imports - ? module_inst->c_api_func_imports + func_idx - : NULL; + CApiFuncImport *c_api_func_import = NULL; uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 func_type_idx = func_type_indexes[func_idx]; AOTFuncType *func_type = (AOTFuncType *)aot_module->types[func_type_idx]; - void **func_ptrs = module_inst->func_ptrs; - void *func_ptr = func_ptrs[func_idx]; + void *func_ptr = NULL; AOTImportFunc *import_func; const char *signature; void *attachment; @@ -3463,10 +3555,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, bh_assert(func_idx < aot_module->import_func_count); import_func = aot_module->import_funcs + func_idx; - if (import_func->call_conv_wasm_c_api) - func_ptr = - c_api_func_import ? c_api_func_import->func_ptr_linked : NULL; + func_ptr = aot_get_function_pointer(module_inst, func_idx); if (!func_ptr) { snprintf(buf, sizeof(buf), "failed to call unlinked import function (%s, %s)", @@ -3475,25 +3565,42 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, goto fail; } - attachment = import_func->attachment; - if (import_func->call_conv_wasm_c_api) { + AOTFunctionInstance *func_inst = + aot_locate_import_function_instance(module_inst, func_idx); + if (func_inst->call_conv_wasm_c_api) { + /* from c_api */ + c_api_func_import = module_inst->c_api_func_imports + ? module_inst->c_api_func_imports + func_idx + : NULL; + if (!c_api_func_import) { + LOG_ERROR("c_api_func_imports should be set in c_api"); + goto fail; + } ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, argv, c_api_func_import->with_env_arg, c_api_func_import->env_arg); } - else if (!import_func->call_conv_raw) { + else if (func_inst->call_conv_raw) { + /* from wasm_native raw */ signature = import_func->signature; -#if WASM_ENABLE_MULTI_MODULE != 0 - WASMModuleInstanceCommon *sub_inst = NULL; - if ((sub_inst = ((AOTModuleInstanceExtra *)module_inst->e) - ->import_func_module_insts[func_idx])) { - exec_env = wasm_runtime_get_exec_env_singleton(sub_inst); - } - if (exec_env == NULL) { - wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst, - "create singleton exec_env failed"); - goto fail; + attachment = import_func->attachment; + ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, + signature, attachment, argv, argc, + argv); + } + else { + if (func_inst->import_module_inst) { + /* from other .wasm. switch */ + exec_env = wasm_runtime_get_exec_env_singleton( + (WASMModuleInstanceCommon *)func_inst->import_module_inst); + if (exec_env == NULL) { + wasm_runtime_set_exception( + (WASMModuleInstanceCommon *)module_inst, + "create singleton exec_env failed"); + goto fail; + } } + #if WASM_ENABLE_AOT_STACK_FRAME != 0 void *prev_frame = get_top_frame(exec_env); @@ -3501,11 +3608,15 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, goto fail; } #endif -#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ + + /* from wasm_native */ + signature = import_func->signature; + attachment = import_func->attachment; ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, attachment, argv, argc, argv); -#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_AOT_STACK_FRAME != 0 + +#if WASM_ENABLE_AOT_STACK_FRAME != 0 /* Free all frames allocated, note that some frames may be allocated in AOT code and haven't been freed if exception occurred */ @@ -3513,12 +3624,6 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, aot_free_frame(exec_env); #endif } - else { - signature = import_func->signature; - ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, - signature, attachment, argv, argc, - argv); - } fail: #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -4055,7 +4160,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, return; } - if (!length) { + if (!length || !tbl_seg_init_values) { return; } @@ -5699,43 +5804,62 @@ aot_resolve_function(const AOTModule *module, const char *function_name, bool aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func) { -#if WASM_ENABLE_MULTI_MODULE != 0 - char error_buf[128]; - AOTModule *sub_module = NULL; -#endif - + /* from wasm_native */ import_func->func_ptr_linked = wasm_native_resolve_symbol( import_func->module_name, import_func->func_name, import_func->func_type, &import_func->signature, &import_func->attachment, &import_func->call_conv_raw); + if (import_func->func_ptr_linked) { + return true; + } + #if WASM_ENABLE_MULTI_MODULE != 0 - if (!import_func->func_ptr_linked) { - if (!wasm_runtime_is_built_in_module(import_func->module_name)) { - sub_module = (AOTModule *)wasm_runtime_load_depended_module( - (WASMModuleCommon *)module, import_func->module_name, error_buf, - sizeof(error_buf)); - if (!sub_module) { - LOG_WARNING("Failed to load sub module: %s", error_buf); - } - if (!sub_module) - import_func->func_ptr_linked = aot_resolve_function_ex( - import_func->module_name, import_func->func_name, - import_func->func_type, error_buf, sizeof(error_buf)); - else - import_func->func_ptr_linked = aot_resolve_function( - sub_module, import_func->func_name, import_func->func_type, - error_buf, sizeof(error_buf)); - if (!import_func->func_ptr_linked) { - LOG_WARNING("Failed to link function: %s", error_buf); - } - } + if (!import_func->module_name) { + LOG_VERBOSE( + "does't have module name for function %s. host should provide link", + import_func->func_name); + return false; } + + /* from other .wasms' export functions */ + char error_buf[128]; + AOTModule *sub_module = (AOTModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)module, import_func->module_name, error_buf, + sizeof(error_buf)); + + if (!sub_module) { + LOG_DEBUG("failed to load sub module: %s", error_buf); + // /* + // * TOOD: seems aot_resolve_function_ex()'s only purpose is use + // * wasm_runtime_find_module_registered() again, after + // * wasm_runtime_load_depended_module() called. + // */ + // import_func->func_ptr_linked = aot_resolve_function_ex( + // import_func->module_name, import_func->func_name, + // import_func->func_type, error_buf, sizeof(error_buf)); + return false; + } + + import_func->func_ptr_linked = aot_resolve_function( + sub_module, import_func->func_name, import_func->func_type, error_buf, + sizeof(error_buf)); + if (import_func->func_ptr_linked) { + import_func->import_module = sub_module; + return true; + } + + LOG_WARNING("failed to link function (%s, %s): %s", + import_func->module_name, import_func->func_name, error_buf); #else (void)module; #endif - return import_func->func_ptr_linked != NULL; + LOG_DEBUG("can't resolve import function %s durning loading. wait for " + "instantiation linking", + import_func->func_name); + + return false; } #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 @@ -5894,4 +6018,27 @@ aot_destroy_global(AOTGlobalInstance *global) return; wasm_runtime_free(global); -} \ No newline at end of file +} + +AOTFunctionInstance * +aot_create_function_empty(const AOTModule *module) +{ + /*TODO: might remove tailed AOTImportFunc */ + AOTFunctionInstance *function = runtime_malloc( + sizeof(AOTFunctionInstance) + sizeof(AOTImportFunc), NULL, 0); + if (!function) { + return NULL; + } + + function->u.func_import = (AOTImportFunc *)(function + 1); + return function; +} + +void +aot_destroy_function(AOTFunctionInstance *function) +{ + if (!function) + return; + + wasm_runtime_free(function); +} diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 22e50fbe7e..0e1c3f0fa0 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -105,14 +105,25 @@ typedef struct AOTFunctionInstance { char *func_name; uint32 func_index; bool is_import_func; + union { struct { AOTFuncType *func_type; - /* function pointer linked */ void *func_ptr; } func; + /* setup by wasm_native */ AOTImportFunc *func_import; } u; + + /* from other .wasm */ + AOTModuleInstance *import_module_inst; + struct AOTFunctionInstance *import_func_inst; + /* copy it from AOTImportFunc */ + bool call_conv_raw; + /* write it from wasm_c_api */ + bool call_conv_wasm_c_api; + /* AOTModuleInstance collects it to form c_api_func_imports */ + CApiFuncImport import_func_c_api; } AOTFunctionInstance; /* Map of a function index to the element ith in @@ -143,13 +154,15 @@ typedef struct AOTModuleInstanceExtra { * created only when first time used. */ ExportFuncMap *export_func_maps; - AOTFunctionInstance **functions; + AOTFunctionInstance *import_functions; uint32 function_count; #if WASM_ENABLE_MULTI_MODULE != 0 bh_list sub_module_inst_list_head; bh_list *sub_module_inst_list; - WASMModuleInstanceCommon **import_func_module_insts; + + /*TODO: remove*/ + // WASMModuleInstanceCommon **import_func_module_insts; #endif #if WASM_ENABLE_SHARED_HEAP != 0 @@ -225,7 +238,7 @@ typedef struct AOTModule { /* function info */ uint32 func_count; - /* func pointers of AOTed (un-imported) functions */ + /* func pointers of AOTed (imported + local) functions */ void **func_ptrs; /* func type indexes of AOTed (un-imported) functions */ uint32 *func_type_indexes; @@ -505,6 +518,67 @@ aot_locate_table_elems(const AOTModule *module, AOTTableInstance *table, return table->elems; } +static inline AOTFunctionInstance * +aot_locate_import_function_instance(const AOTModuleInstance *inst, + uint32 func_idx) +{ + AOTModule *module = (AOTModule *)inst->module; + if (func_idx >= module->import_func_count) { + LOG_ERROR("You can only locate import function instance by func_idx " + "with this function."); + bh_assert(0); + return NULL; + } + + AOTModuleInstanceExtra *e = (AOTModuleInstanceExtra *)inst->e; + AOTFunctionInstance *func = e->import_functions + func_idx; + bh_assert(func && "func is NULL"); + return func; +} + +static inline void * +aot_get_function_pointer(const AOTModuleInstance *module_inst, uint32 func_idx) +{ + void **func_ptrs = module_inst->func_ptrs; + void *func_ptr = NULL; + + AOTModule *module = (AOTModule *)module_inst->module; + if (func_idx < module->import_func_count) { + const AOTFunctionInstance *func_inst = + aot_locate_import_function_instance(module_inst, func_idx); + + if (func_inst->call_conv_wasm_c_api) { + CApiFuncImport *c_api_func_import = + module_inst->c_api_func_imports + ? module_inst->c_api_func_imports + func_idx + : NULL; + func_ptr = + c_api_func_import ? c_api_func_import->func_ptr_linked : NULL; + } + else if (func_inst->call_conv_raw) { + func_ptr = func_ptrs[func_idx]; + } + else { + if (func_inst->import_module_inst) { + /* from other module */ + uint32 funx_idx_of_import_func = + func_inst->import_func_inst->func_index; + func_ptr = func_inst->import_module_inst + ->func_ptrs[funx_idx_of_import_func]; + } + else { + /* from host APIs, like wasm_export.h, in the future */ + func_ptr = func_ptrs[func_idx]; + } + } + } + else { + func_ptr = func_ptrs[func_idx]; + } + + return func_ptr; +} + /** * Load a AOT module from aot file buffer * @param buf the byte buffer which contains the AOT file data @@ -575,10 +649,10 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, * Deinstantiate a AOT module instance, destroy the resources. * * @param module_inst the AOT module instance to destroy - * @param is_sub_inst the flag of sub instance + * @param is_spawned the flag of sub instance */ void -aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst); +aot_deinstantiate(AOTModuleInstance *module_inst, bool is_spawned); AOTMemoryInstance * aot_create_memory(const AOTModule *module, const AOTMemoryType *type); @@ -932,6 +1006,35 @@ aot_set_global_value(AOTGlobalInstance *global, const WASMValue *value); void aot_destroy_global(AOTGlobalInstance *global); +AOTFunctionInstance * +aot_create_function_empty(const AOTModule *module); + +void +aot_destroy_function(AOTFunctionInstance *function); + +static inline void +aot_function_import_from_wasm(AOTFunctionInstance *func, + AOTModuleInstance *dep_inst, + AOTFunctionInstance *dep_func) +{ + func->import_module_inst = dep_inst; + func->import_func_inst = dep_func; +} + +static inline void +aot_function_import_from_c_api(AOTFunctionInstance *func, + CApiFuncImport *c_api_func_import) +{ + func->import_func_c_api = *c_api_func_import; +} + +/*might be unused*/ +static inline void +aot_function_import_from_native(AOTFunctionInstance *func, void *callback) +{ + func->u.func_import->func_ptr_linked = callback; +} + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index cbb99bb1b7..dbb167fbe3 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -744,27 +744,6 @@ wasm_store_delete(wasm_store_t *store) } /* Type Representations */ -static inline wasm_valkind_t -val_type_rt_2_valkind(uint8 val_type_rt) -{ - switch (val_type_rt) { -#define WAMR_VAL_TYPE_2_WASM_VAL_KIND(name) \ - case VALUE_TYPE_##name: \ - return WASM_##name; - - WAMR_VAL_TYPE_2_WASM_VAL_KIND(I32) - WAMR_VAL_TYPE_2_WASM_VAL_KIND(I64) - WAMR_VAL_TYPE_2_WASM_VAL_KIND(F32) - WAMR_VAL_TYPE_2_WASM_VAL_KIND(F64) - WAMR_VAL_TYPE_2_WASM_VAL_KIND(V128) - WAMR_VAL_TYPE_2_WASM_VAL_KIND(FUNCREF) -#undef WAMR_VAL_TYPE_2_WASM_VAL_KIND - - default: - return WASM_EXTERNREF; - } -} - static wasm_valtype_t * wasm_valtype_new_internal(uint8 val_type_rt) { @@ -970,6 +949,7 @@ wasm_functype_results(const wasm_functype_t *func_type) return func_type->results; } +#if WASM_ENABLE_MULTI_MODULE != 0 static bool cmp_val_kind_with_val_type(wasm_valkind_t v_k, uint8 v_t) { @@ -1012,6 +992,7 @@ wasm_functype_same_internal(const wasm_functype_t *type, return true; } +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ wasm_globaltype_t * wasm_globaltype_new(own wasm_valtype_t *val_type, wasm_mutability_t mut) @@ -3104,7 +3085,7 @@ wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *type, } wasm_func_t * -wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt, +wasm_func_new_internal(wasm_store_t *store, uint32 func_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_func_t *func = NULL; @@ -3605,47 +3586,42 @@ wasm_global_delete(wasm_global_t *global) #if WASM_ENABLE_INTERP != 0 static bool -interp_global_set(const WASMModuleInstance *inst_interp, uint16 global_idx_rt, +interp_global_set(const WASMModuleInstance *inst_interp, uint32 global_idx_rt, const wasm_val_t *v) { const WASMGlobalInstance *global_interp = inst_interp->e->globals + global_idx_rt; uint8 val_type_rt = global_interp->type; -#if WASM_ENABLE_MULTI_MODULE != 0 - uint8 *data = global_interp->import_global_inst + + uint8 *data = global_interp->import_module_inst ? global_interp->import_module_inst->global_data + global_interp->import_global_inst->data_offset : inst_interp->global_data + global_interp->data_offset; -#else - uint8 *data = inst_interp->global_data + global_interp->data_offset; -#endif return wasm_val_to_rt_val((WASMModuleInstanceCommon *)inst_interp, val_type_rt, v, data); } static bool -interp_global_get(const WASMModuleInstance *inst_interp, uint16 global_idx_rt, +interp_global_get(const WASMModuleInstance *inst_interp, uint32 global_idx_rt, wasm_val_t *out) { WASMGlobalInstance *global_interp = inst_interp->e->globals + global_idx_rt; uint8 val_type_rt = global_interp->type; -#if WASM_ENABLE_MULTI_MODULE != 0 - uint8 *data = global_interp->import_global_inst + + uint8 *data = global_interp->import_module_inst ? global_interp->import_module_inst->global_data + global_interp->import_global_inst->data_offset : inst_interp->global_data + global_interp->data_offset; -#else - uint8 *data = inst_interp->global_data + global_interp->data_offset; -#endif return rt_val_to_wasm_val(data, val_type_rt, out); } #endif #if WASM_ENABLE_AOT != 0 +/*TODO: get_global_addr() */ static bool -aot_global_set(const AOTModuleInstance *inst_aot, uint16 global_idx_rt, +aot_global_set(const AOTModuleInstance *inst_aot, uint32 global_idx_rt, const wasm_val_t *v) { AOTModule *module_aot = (AOTModule *)inst_aot->module; @@ -3672,7 +3648,7 @@ aot_global_set(const AOTModuleInstance *inst_aot, uint16 global_idx_rt, } static bool -aot_global_get(const AOTModuleInstance *inst_aot, uint16 global_idx_rt, +aot_global_get(const AOTModuleInstance *inst_aot, uint32 global_idx_rt, wasm_val_t *out) { AOTModule *module_aot = (AOTModule *)inst_aot->module; @@ -3765,7 +3741,7 @@ wasm_global_get(const wasm_global_t *global, wasm_val_t *out) } wasm_global_t * -wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt, +wasm_global_new_internal(wasm_store_t *store, uint32 global_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_global_t *global = NULL; @@ -3892,7 +3868,7 @@ wasm_table_new_basic(wasm_store_t *store, const wasm_tabletype_t *type) } wasm_table_t * -wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt, +wasm_table_new_internal(wasm_store_t *store, uint32 table_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_table_t *table = NULL; @@ -4272,7 +4248,7 @@ wasm_memory_copy(const wasm_memory_t *src) } wasm_memory_t * -wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt, +wasm_memory_new_internal(wasm_store_t *store, uint32 memory_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_memory_t *memory = NULL; @@ -4488,9 +4464,10 @@ wasm_memory_grow(wasm_memory_t *memory, wasm_memory_pages_t delta) } #if WASM_ENABLE_INTERP != 0 +#if WASM_ENABLE_MULTI_MODULE != 0 static bool interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, - uint16 func_idx_rt, wasm_func_t *import) + uint32 func_idx_rt, wasm_func_t *import) { WASMImport *imported_func_interp = NULL; @@ -4512,6 +4489,8 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, return false; imported_func_interp->u.function.call_conv_wasm_c_api = true; + + /*TODO: we can avoid this step */ /* only set func_ptr_linked to avoid unlink warning during instantiation, func_ptr_linked, with_env and env will be stored in module instance's c_api_func_imports later and used when calling import function */ @@ -4528,7 +4507,7 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, } static bool -interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt, +interp_link_global(const WASMModule *module_interp, uint32 global_idx_rt, wasm_global_t *import) { WASMImport *imported_global_interp = NULL; @@ -4578,6 +4557,7 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt, imported_global_interp->u.global.is_linked = true; return true; } +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ static bool interp_process_export(wasm_store_t *store, @@ -4667,6 +4647,7 @@ interp_process_export(wasm_store_t *store, #endif /* WASM_ENABLE_INTERP */ #if WASM_ENABLE_AOT != 0 +#if WASM_ENABLE_MULTI_MODULE != 0 static bool aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot, uint32 import_func_idx_rt, wasm_func_t *import) @@ -4702,7 +4683,7 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot, } static bool -aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, +aot_link_global(const AOTModule *module_aot, uint32 global_idx_rt, wasm_global_t *import) { AOTImportGlobal *import_aot_global = NULL; @@ -4749,6 +4730,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, LOG_DEBUG("%s failed", __FUNCTION__); return false; } +#endif /* WASM_ENABLE_MULTI_MODULE != 0*/ static bool aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot, @@ -4843,6 +4825,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot, } #endif /* WASM_ENABLE_AOT */ +#if WASM_ENABLE_MULTI_MODULE != 0 static bool do_link(const wasm_instance_t *inst, const wasm_module_t *module, const wasm_extern_vec_t *imports) @@ -4931,6 +4914,7 @@ do_link(const wasm_instance_t *inst, const wasm_module_t *module, LOG_DEBUG("%s failed", __FUNCTION__); return false; } +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ wasm_instance_t * wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, @@ -4953,6 +4937,70 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, &inst_args); } +bool +wasm_instance_create_import_list(const wasm_module_t *module, + const wasm_extern_vec_t *imports_src, + WASMExternInstance **imports_dst, + uint32 *imports_dst_count) +{ + *imports_dst = NULL; + *imports_dst_count = 0; + + if (!imports_src) { + LOG_VERBOSE("doesn't provide imports\n"); + *imports_dst_count = 0; + return true; + } + + wasm_importtype_vec_t import_types = { 0 }; + wasm_module_imports(module, &import_types); + + if (import_types.num_elems == 0) { + LOG_VERBOSE("module has no imports\n"); + return true; + } + + if (import_types.num_elems > imports_src->num_elems) { + LOG_ERROR("module has %d imports but only %d provided. Placeholders " + "are even allowed.\n", + import_types.num_elems, imports_src->num_elems); + return false; + } + + *imports_dst = malloc_internal((uint64)sizeof(WASMExternInstance) + * imports_src->num_elems); + if (!*imports_dst) { + return false; + } + + *imports_dst_count = (uint32)imports_src->num_elems; + + uint32 i = 0; + WASMExternInstance *import_out = *imports_dst; + for (; i < imports_src->num_elems; i++, import_out++) { + wasm_importtype_t *import_type = import_types.data[i]; + wasm_extern_t *import_in = imports_src->data[i]; + + if (!import_in) { + LOG_VERBOSE("imports[%d] is NULL and wasm_native may provide it\n", + i); + continue; + } + + if (!extern_t_to_WASMExternInstance(module, import_in, import_type, + import_out)) { + wasm_runtime_destroy_imports(*module, *imports_dst); + wasm_runtime_free(*imports_dst); + + *imports_dst = NULL; + *imports_dst_count = 0; + return false; + } + } + + return true; +} + wasm_instance_t * wasm_instance_new_with_args_ex(wasm_store_t *store, const wasm_module_t *module, const wasm_extern_vec_t *imports, @@ -4985,7 +5033,33 @@ wasm_instance_new_with_args_ex(wasm_store_t *store, const wasm_module_t *module, goto failed; } - /* executes the instantiate-time linking if provided */ +#if WASM_ENABLE_MULTI_MODULE == 0 + /* do instantiation-linking */ + struct WASMExternInstance *imports_out = NULL; + uint32 imports_out_count = 0; + if (!wasm_instance_create_import_list(module, imports, &imports_out, + &imports_out_count)) { + snprintf(sub_error_buf, sizeof(sub_error_buf), + "Failed to create import list"); + goto failed; + } + + InstantiationArgs inst_args_w_imports = *inst_args; + inst_args_w_imports.imports = imports_out; + inst_args_w_imports.import_count = imports_out_count; + + /* + * will do the linking result check at the end of + * wasm_runtime_instantiate + */ + instance->inst_comm_rt = wasm_runtime_instantiate_ex( + *module, &inst_args_w_imports, sub_error_buf, sizeof(sub_error_buf)); + if (!instance->inst_comm_rt) { + goto failed; + } + wasm_runtime_destroy_imports(*module, imports_out); +#else + /* do loading-linking */ if (imports) { if (!do_link(instance, module, imports)) { snprintf(sub_error_buf, sizeof(sub_error_buf), @@ -4993,15 +5067,17 @@ wasm_instance_new_with_args_ex(wasm_store_t *store, const wasm_module_t *module, goto failed; } } + /* - * will do the linking result check at the end of wasm_runtime_instantiate + * will do the linking result check at the end of + * wasm_runtime_instantiate */ - instance->inst_comm_rt = wasm_runtime_instantiate_ex( *module, inst_args, sub_error_buf, sizeof(sub_error_buf)); if (!instance->inst_comm_rt) { goto failed; } +#endif if (!wasm_runtime_create_exec_env_singleton(instance->inst_comm_rt)) { snprintf(sub_error_buf, sizeof(sub_error_buf), @@ -5066,28 +5142,44 @@ wasm_instance_new_with_args_ex(wasm_store_t *store, const wasm_module_t *module, func_import++; } - /* fill with inst */ + /* fill with inst and index in space(X) */ + uint32 function_idx_rt = 0; + uint32 global_idx_rt = 0; + uint32 memory_idx_rt = 0; + uint32 table_idx_rt = 0; for (i = 0; imports && imports->data && i < imports->num_elems; ++i) { wasm_extern_t *import = imports->data[i]; bh_assert(import); switch (import->kind) { case WASM_EXTERN_FUNC: + { wasm_extern_as_func(import)->inst_comm_rt = instance->inst_comm_rt; + wasm_extern_as_func(import)->func_idx_rt = function_idx_rt++; break; + } case WASM_EXTERN_GLOBAL: + { wasm_extern_as_global(import)->inst_comm_rt = instance->inst_comm_rt; + wasm_extern_as_global(import)->global_idx_rt = global_idx_rt++; break; + } case WASM_EXTERN_MEMORY: + { wasm_extern_as_memory(import)->inst_comm_rt = instance->inst_comm_rt; + wasm_extern_as_memory(import)->memory_idx_rt = memory_idx_rt++; break; + } case WASM_EXTERN_TABLE: + { wasm_extern_as_table(import)->inst_comm_rt = instance->inst_comm_rt; + wasm_extern_as_table(import)->table_idx_rt = table_idx_rt++; break; + } default: snprintf(sub_error_buf, sizeof(sub_error_buf), "Unknown import kind"); diff --git a/core/iwasm/common/wasm_c_api_internal.h b/core/iwasm/common/wasm_c_api_internal.h index 49a17a964b..b137b98270 100644 --- a/core/iwasm/common/wasm_c_api_internal.h +++ b/core/iwasm/common/wasm_c_api_internal.h @@ -70,7 +70,7 @@ struct wasm_memorytype_t { }; struct wasm_externtype_t { - uint32 extern_kind; + wasm_externkind_t extern_kind; /* reserved space */ uint8 data[1]; }; @@ -146,7 +146,7 @@ struct wasm_func_t { * an index in both functions runtime instance lists * of interpreter mode and aot mode */ - uint16 func_idx_rt; + uint32 func_idx_rt; WASMModuleInstanceCommon *inst_comm_rt; WASMFunctionInstanceCommon *func_comm_rt; }; @@ -164,7 +164,7 @@ struct wasm_global_t { * an index in both global runtime instance lists * of interpreter mode and aot mode */ - uint16 global_idx_rt; + uint32 global_idx_rt; WASMModuleInstanceCommon *inst_comm_rt; }; @@ -180,7 +180,7 @@ struct wasm_memory_t { * an index in both memory runtime instance lists * of interpreter mode and aot mode */ - uint16 memory_idx_rt; + uint32 memory_idx_rt; WASMModuleInstanceCommon *inst_comm_rt; }; @@ -196,7 +196,7 @@ struct wasm_table_t { * an index in both table runtime instance lists * of interpreter mode and aot mode */ - uint16 table_idx_rt; + uint32 table_idx_rt; WASMModuleInstanceCommon *inst_comm_rt; }; @@ -226,21 +226,43 @@ wasm_foreign_new_internal(wasm_store_t *store, uint32 foreign_idx_rt, WASMModuleInstanceCommon *inst_comm_rt); wasm_func_t * -wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt, +wasm_func_new_internal(wasm_store_t *store, uint32 func_idx_rt, WASMModuleInstanceCommon *inst_comm_rt); wasm_global_t * -wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt, +wasm_global_new_internal(wasm_store_t *store, uint32 global_idx_rt, WASMModuleInstanceCommon *inst_comm_rt); wasm_memory_t * -wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt, +wasm_memory_new_internal(wasm_store_t *store, uint32 memory_idx_rt, WASMModuleInstanceCommon *inst_comm_rt); wasm_table_t * -wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt, +wasm_table_new_internal(wasm_store_t *store, uint32 table_idx_rt, WASMModuleInstanceCommon *inst_comm_rt); void wasm_frame_vec_clone_internal(Vector *src, Vector *out); + +/* type conversions */ +wasm_valkind_t +val_type_rt_2_valkind(uint8 val_type_rt); + +bool +valkind_to_WASMValueType(wasm_valkind_t src, uint8 *dst); + +wasm_import_export_kind_t +externkind_to_import_export_kind(wasm_externkind_t src); + +bool +globaltype_to_WASMGlobalType(wasm_globaltype_t *src, WASMGlobalType *dst); + +bool +val_to_WASMValue(wasm_val_t *src, WASMValue *dst); + +bool +extern_t_to_WASMExternInstance(const wasm_module_t *module, wasm_extern_t *src, + wasm_importtype_t *type, + WASMExternInstance *dst); + #endif /* _WASM_C_API_INTERNAL_H */ diff --git a/core/iwasm/common/wasm_c_api_type_conv.c b/core/iwasm/common/wasm_c_api_type_conv.c new file mode 100644 index 0000000000..3d2dfdc3a9 --- /dev/null +++ b/core/iwasm/common/wasm_c_api_type_conv.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_log.h" +#include "wasm_c_api_internal.h" +#include "wasm_export.h" +#include "wasm_runtime_common.h" + +/* wasm_export.h types -> wasm_c_api.h types*/ + +wasm_valkind_t +val_type_rt_2_valkind(uint8 val_type_rt) +{ + switch (val_type_rt) { +#define WAMR_VAL_TYPE_2_WASM_VAL_KIND(name) \ + case VALUE_TYPE_##name: \ + return WASM_##name; + + WAMR_VAL_TYPE_2_WASM_VAL_KIND(I32) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(I64) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(F32) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(F64) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(V128) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(FUNCREF) +#undef WAMR_VAL_TYPE_2_WASM_VAL_KIND + + default: + return WASM_EXTERNREF; + } +} + +/* wasm_c_api.h types -> wasm_export.h types*/ +bool +valkind_to_WASMValueType(wasm_valkind_t src, uint8 *dst) +{ + switch (src) { +#define WASM_VAL_KIND_2_WAMR_VAL_TYPE(name) \ + case WASM_##name: \ + { \ + *dst = VALUE_TYPE_##name; \ + return true; \ + } + + WASM_VAL_KIND_2_WAMR_VAL_TYPE(I32) + WASM_VAL_KIND_2_WAMR_VAL_TYPE(I64) + WASM_VAL_KIND_2_WAMR_VAL_TYPE(F32) + WASM_VAL_KIND_2_WAMR_VAL_TYPE(F64) + WASM_VAL_KIND_2_WAMR_VAL_TYPE(V128) + WASM_VAL_KIND_2_WAMR_VAL_TYPE(FUNCREF) +#undef WASM_VAL_KIND_2_WAMR_VAL_TYPE + + default: + { + bh_assert(0); + return false; + } + } +} + +wasm_import_export_kind_t +externkind_to_import_export_kind(wasm_externkind_t src) +{ + if (src == WASM_EXTERN_FUNC) { + return WASM_IMPORT_EXPORT_KIND_FUNC; + } + else if (src == WASM_EXTERN_GLOBAL) { + return WASM_IMPORT_EXPORT_KIND_GLOBAL; + } + else if (src == WASM_EXTERN_TABLE) { + return WASM_IMPORT_EXPORT_KIND_TABLE; + } + else if (src == WASM_EXTERN_MEMORY) { + return WASM_IMPORT_EXPORT_KIND_MEMORY; + } + else { + bh_assert(0); + LOG_ERROR("Invalid wasm_externkind_t value. Can't convert to " + "wasm_import_export_kind_t"); + return 0; + } +} + +bool +globaltype_to_WASMGlobalType(wasm_globaltype_t *src, WASMGlobalType *dst) +{ + if (!valkind_to_WASMValueType(src->val_type->kind, &dst->val_type)) { + return false; + } + + dst->is_mutable = src->mutability == WASM_VAR ? WASM_VAR : WASM_CONST; + return true; +} + +bool +func_to_CApiFuncImport(wasm_func_t *src, CApiFuncImport *dst) +{ + dst->func_ptr_linked = + src->with_env ? (void *)src->u.cb_env.cb : (void *)src->u.cb; + dst->with_env_arg = src->with_env; + dst->env_arg = src->u.cb_env.env; + return true; +} + +bool +extern_t_to_WASMExternInstance(const wasm_module_t *module, wasm_extern_t *src, + wasm_importtype_t *type, WASMExternInstance *dst) +{ + dst->module_name = wasm_importtype_module(type)->data; + dst->field_name = wasm_importtype_name(type)->data; + + dst->kind = externkind_to_import_export_kind(wasm_extern_kind(src)); + + switch (wasm_extern_kind(src)) { + case WASM_EXTERN_FUNC: + { + wasm_func_t *function_in = wasm_extern_as_func(src); + + CApiFuncImport c_api_info = { 0 }; + func_to_CApiFuncImport(function_in, &c_api_info); + + dst->u.function = + wasm_runtime_create_function_c_api(*module, &c_api_info); + if (!dst->u.function) { + return false; + } + + break; + } + case WASM_EXTERN_GLOBAL: + { + wasm_global_t *global_in = wasm_extern_as_global(src); + + WASMGlobalType global_type = { 0 }; + if (!globaltype_to_WASMGlobalType(wasm_global_type(global_in), + &global_type)) { + return false; + } + + dst->u.global = wasm_runtime_create_global_internal(*module, NULL, + &global_type); + if (!dst->u.global) { + return false; + } + + /* set init value */ + switch (global_in->init->kind) { + case WASM_I32: + { + WASMValue val = { .i32 = global_in->init->of.i32 }; + wasm_runtime_set_global_value(*module, dst->u.global, &val); + break; + } + case WASM_I64: + { + WASMValue val = { .i64 = global_in->init->of.i64 }; + wasm_runtime_set_global_value(*module, dst->u.global, &val); + break; + } + case WASM_F32: + { + WASMValue val = { .f32 = global_in->init->of.f32 }; + wasm_runtime_set_global_value(*module, dst->u.global, &val); + break; + } + case WASM_F64: + { + WASMValue val = { .f64 = global_in->init->of.f64 }; + wasm_runtime_set_global_value(*module, dst->u.global, &val); + break; + } + default: + { + return false; + } + } + + break; + } + case WASM_EXTERN_MEMORY: + { + break; + } + case WASM_EXTERN_TABLE: + { + break; + } + default: + { + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/core/iwasm/common/wasm_loader_common.c b/core/iwasm/common/wasm_loader_common.c index 97ea5efd19..847c0a153a 100644 --- a/core/iwasm/common/wasm_loader_common.c +++ b/core/iwasm/common/wasm_loader_common.c @@ -51,9 +51,10 @@ check_memory64_flags_consistency(WASMModule *module, char *error_buf, #endif bool -wasm_memory_check_flags(const uint8 mem_flag, char *error_buf, +wasm_memory_check_flags(const uint32 mem_flag_w, char *error_buf, uint32 error_buf_size, bool is_aot) { + uint8 mem_flag = (uint8)(mem_flag_w & 0xFF); /* Check whether certain features indicated by mem_flag are enabled in * runtime */ if (mem_flag > MAX_PAGE_COUNT_FLAG) { diff --git a/core/iwasm/common/wasm_loader_common.h b/core/iwasm/common/wasm_loader_common.h index 81174fb264..2e143d322d 100644 --- a/core/iwasm/common/wasm_loader_common.h +++ b/core/iwasm/common/wasm_loader_common.h @@ -22,7 +22,7 @@ check_memory64_flags_consistency(WASMModule *module, char *error_buf, #endif bool -wasm_memory_check_flags(const uint8 mem_flag, char *error_buf, +wasm_memory_check_flags(const uint32 mem_flag, char *error_buf, uint32 error_buf_size, bool is_aot); bool diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 271e139494..2756db88d9 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1681,17 +1681,17 @@ wasm_runtime_instantiate_ex(WASMModuleCommon *module, void wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst, - bool is_sub_inst) + bool is_spawned) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - wasm_deinstantiate((WASMModuleInstance *)module_inst, is_sub_inst); + wasm_deinstantiate((WASMModuleInstance *)module_inst, is_spawned); return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - aot_deinstantiate((AOTModuleInstance *)module_inst, is_sub_inst); + aot_deinstantiate((AOTModuleInstance *)module_inst, is_spawned); return; } #endif @@ -7562,8 +7562,12 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, bh_list_first_elem(((WASMModule *)module)->import_module_list); } #endif + if (!sub_module_inst_list) { + LOG_ERROR("unknown module type %d", module->module_type); + return false; + } + while (sub_module_list_node) { - WASMSubModInstNode *sub_module_inst_list_node = NULL; WASMModuleCommon *sub_module = sub_module_list_node->module; WASMModuleInstanceCommon *sub_module_inst = NULL; sub_module_inst = wasm_runtime_instantiate_internal( @@ -7576,8 +7580,10 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, sub_module_list_node->module_name); return false; } - sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode), - error_buf, error_buf_size); + + WASMSubModInstNode *sub_module_inst_list_node = loader_malloc( + sizeof(WASMSubModInstNode), error_buf, error_buf_size); + if (!sub_module_inst_list_node) { LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ: %zu", sizeof(WASMSubModInstNode)); @@ -7585,36 +7591,10 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, wasm_runtime_deinstantiate_internal(sub_module_inst, false); return false; } - sub_module_inst_list_node->module_inst = - (WASMModuleInstance *)sub_module_inst; + sub_module_inst_list_node->module_inst = sub_module_inst; sub_module_inst_list_node->module_name = sub_module_list_node->module_name; -#if WASM_ENABLE_AOT != 0 - if (module_inst->module_type == Wasm_Module_AoT) { - AOTModuleInstance *aot_module_inst = - (AOTModuleInstance *)module_inst; - AOTModule *aot_module = (AOTModule *)module; - AOTModuleInstanceExtra *aot_extra = - (AOTModuleInstanceExtra *)aot_module_inst->e; - uint32 i; - AOTImportFunc *import_func; - for (i = 0; i < aot_module->import_func_count; i++) { - if (aot_extra->import_func_module_insts[i]) - continue; - - import_func = &aot_module->import_funcs[i]; - if (strcmp(sub_module_inst_list_node->module_name, - import_func->module_name) - == 0) { - aot_extra->import_func_module_insts[i] = - (WASMModuleInstanceCommon *) - sub_module_inst_list_node->module_inst; - } - } - } -#endif - bh_list_status ret = bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); bh_assert(BH_LIST_SUCCESS == ret); @@ -8089,7 +8069,11 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module, if (!extern_inst) return; - if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { + if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_FUNC) { + wasm_runtime_destroy_function(module, extern_inst->u.function); + extern_inst->u.function = NULL; + } + else if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { wasm_runtime_destroy_memory(module, extern_inst->u.memory); extern_inst->u.memory = NULL; } @@ -8111,24 +8095,145 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module, extern_inst->field_name = NULL; } -#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_WASI_TEST != 0 +WASMFunctionInstanceCommon * +wasm_runtime_create_function_wasm(struct WASMModuleCommon *const module, + WASMModuleInstanceCommon *dep_inst, + WASMFunctionInstanceCommon *dep_func) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + WASMFunctionInstance *func_empty = + wasm_create_function_empty((const WASMModule *)module); + func_empty->is_import_func = true; + + func_empty->import_module_inst = (WASMModuleInstance *)dep_inst; + func_empty->import_func_inst = (WASMFunctionInstance *)dep_func; + return (WASMFunctionInstanceCommon *)func_empty; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + bh_assert(false && "not supported yet"); + } +#endif + + LOG_ERROR("create function failed, invalid module type %d", + module->module_type); + return NULL; +} + +WASMFunctionInstanceCommon * +wasm_runtime_create_function_c_api(struct WASMModuleCommon *const module, + CApiFuncImport *c_api_info) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + WASMFunctionInstance *func_empty = + wasm_create_function_empty((const WASMModule *)module); + func_empty->is_import_func = true; + + func_empty->import_func_c_api = *c_api_info; + func_empty->call_conv_wasm_c_api = true; + return (WASMFunctionInstanceCommon *)func_empty; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + AOTFunctionInstance *func_empty = + aot_create_function_empty((const AOTModule *)module); + func_empty->is_import_func = true; + + func_empty->import_func_c_api = *c_api_info; + func_empty->call_conv_wasm_c_api = true; + return (AOTFunctionInstance *)func_empty; + } +#endif + + LOG_ERROR("create function failed, invalid module type %d", + module->module_type); + return NULL; +} + +/*might be unused*/ +WASMFunctionInstanceCommon * +wasm_runtime_create_function_native(struct WASMModuleCommon *const module, + void *callback) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + WASMFunctionInstance *func_empty = + wasm_create_function_empty((const WASMModule *)module); + func_empty->is_import_func = true; + + func_empty->u.func_import->func_ptr_linked = callback; + /*TBC: ?*/ + func_empty->call_conv_raw = false; + + return (WASMFunctionInstanceCommon *)func_empty; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + bh_assert(false && "not supported yet"); + } +#endif + + LOG_ERROR("create function failed, invalid module type %d", + module->module_type); + return NULL; +} + +WASMFunctionInstanceCommon * +wasm_runtime_create_function(struct WASMModuleCommon *const module, + struct WASMFuncType *const type, void *callback) +{ + bh_assert(false && "unimplemented"); + return NULL; +} + +void +wasm_runtime_destroy_function(struct WASMModuleCommon *const module, + WASMFunctionInstanceCommon *func) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + wasm_destroy_function(func); + return; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + bh_assert(false && "not supported yet"); + // aot_destroy_function(func); + return; + } +#endif + + LOG_ERROR("destroy function failed, invalid module type %d", + module->module_type); + return; +} + /* * 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. */ -static void +void wasm_runtime_destroy_imports(WASMModuleCommon *module, WASMExternInstance *extern_inst_list) { if (!module || !extern_inst_list) return; - for (int32 i = 0, import_count = wasm_runtime_get_import_count(module); - i < import_count; i++) { + int32 import_count = wasm_runtime_get_import_count(module); + for (int32 i = 0; i < import_count; i++) { 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_with_builtin(WASMModuleCommon *module, diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index e9643c2347..c06d137861 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -504,6 +504,25 @@ wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env); /* Get exec_env of thread local storage */ WASMExecEnv * wasm_runtime_get_exec_env_tls(void); +#endif /* OS_ENABLE_HW_BOUND_CHECK */ + +/* wasm-c-api import function info */ +typedef struct CApiFuncImport { + /* host func pointer after linked */ + void *func_ptr_linked; + /* whether the host func has env argument */ + bool with_env_arg; + /* the env argument of the host func */ + void *env_arg; +} CApiFuncImport; + +#if WASM_ENABLE_MULTI_MODULE != 0 +typedef struct WASMSubModInstNode { + bh_list_link l; + /* point to a string pool */ + const char *module_name; + WASMModuleInstanceCommon *module_inst; +} WASMSubModInstNode; #endif /* See wasm_export.h for description */ @@ -582,7 +601,7 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, /* Internal API */ void wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst, - bool is_sub_inst); + bool is_spawned); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon * @@ -1164,12 +1183,11 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst, uint32 argc, uint32 *argv, bool with_env, void *wasm_c_api_env); -struct CApiFuncImport; /* A quick version of wasm_runtime_invoke_c_api_native to directly invoke wasm-c-api import function from jitted code to improve performance */ bool wasm_runtime_quick_invoke_c_api_native(WASMModuleInstanceCommon *module_inst, - struct CApiFuncImport *c_api_import, + CApiFuncImport *c_api_import, wasm_val_t *params, uint32 param_count, wasm_val_t *results, uint32 result_count); @@ -1240,9 +1258,13 @@ 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, +wasm_runtime_create_table_internal(const wasm_module_t module, WASMTableType *const type); +wasm_function_inst_t +wasm_runtime_create_function_c_api(const wasm_module_t module, + CApiFuncImport *c_api_info); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 2eb4b32a3a..d44aa9313c 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -478,7 +478,9 @@ aot_create_import_funcs(const WASMModule *module) import_funcs[i].signature = import_func->signature; import_funcs[i].attachment = import_func->attachment; import_funcs[i].call_conv_raw = import_func->call_conv_raw; +#if WASM_ENABLE_MULTI_MODULE != 0 import_funcs[i].call_conv_wasm_c_api = false; +#endif /* Resolve function type index */ for (j = 0; j < module->type_count; j++) if (import_func->func_type == (WASMFuncType *)module->types[j]) { diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index c662f52f51..0d1a32d4dc 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -51,6 +51,9 @@ typedef WASMMemoryType AOTMemoryType; typedef WASMTableType AOTTableType; typedef WASMTable AOTTable; +struct AOTModule; +struct AOTFunc; + #if WASM_ENABLE_DEBUG_AOT != 0 typedef void *dwarf_extractor_handle_t; #endif @@ -191,14 +194,21 @@ typedef struct AOTImportFunc { AOTFuncType *func_type; uint32 func_type_index; /* function pointer after linked */ + void *func_ptr_linked; /* signature from registered native symbols */ const char *signature; /* attachment */ void *attachment; + + /* via wasm_native */ bool call_conv_raw; +#if WASM_ENABLE_MULTI_MODULE != 0 + /* by loading-link */ bool call_conv_wasm_c_api; - bool wasm_c_api_with_env; + struct AOTModule *import_module; + struct AOTFunc *import_func_linked; +#endif } AOTImportFunc; /** diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 51f33dffb1..7e454502a4 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1934,7 +1934,7 @@ aot_create_func_contexts(const AOTCompData *comp_data, AOTCompContext *comp_ctx) memset(func_ctxes, 0, size); - /* Create each function context */ + /* Create each function(non-import) context */ for (i = 0; i < comp_data->func_count; i++) { AOTFunc *func = comp_data->funcs[i]; if (!(func_ctxes[i] = diff --git a/core/iwasm/fast-jit/fe/jit_emit_function.c b/core/iwasm/fast-jit/fe/jit_emit_function.c index 1e41994407..62746986b0 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_function.c +++ b/core/iwasm/fast-jit/fe/jit_emit_function.c @@ -246,7 +246,14 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call) /* Call fast_jit_invoke_native in some cases */ if (!func_import->func_ptr_linked /* import func hasn't been linked */ +#if WASM_ENABLE_MULTI_MODULE != 0 || func_import->call_conv_wasm_c_api /* linked by wasm_c_api */ +#else + /* + * TODO: can't decide if it is conv_c_api now + * but we didn't setup func_ptr_linked, too + */ +#endif || func_import->call_conv_raw /* registered as raw mode */ || func_type->param_count >= 5 /* registered as normal mode, but jit_emit_callnative only supports diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 2d8e1f62bc..1946fe1fce 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -194,12 +194,13 @@ struct wasm_config_t { #ifndef INSTANTIATION_ARGS_OPTION_DEFINED #define INSTANTIATION_ARGS_OPTION_DEFINED +struct WASMExternInstance; /* WASM module instantiation arguments */ typedef struct InstantiationArgs { uint32_t default_stack_size; uint32_t host_managed_heap_size; uint32_t max_memory_pages; - const struct WasmExternInstance *imports; + const struct WASMExternInstance * imports; uint32_t import_count; } InstantiationArgs; #endif /* INSTANTIATION_ARGS_OPTION_DEFINED */ diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 92633781da..14e309111e 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -296,11 +296,12 @@ typedef struct WASMExternInstance { wasm_memory_inst_t memory; wasm_table_inst_t table; wasm_global_inst_t global; + wasm_function_inst_t function; } u; /* * to handle imports properly, - * especially for wasm_global_inst_t and wasm_func_inst_t + * especially for wasm_global_inst_t and wasm_function_inst_t */ wasm_module_inst_t dep_inst; } WASMExternInstance, *wasm_extern_inst_t; @@ -2378,6 +2379,14 @@ wasm_runtime_create_table(const wasm_module_t module, WASM_RUNTIME_API_EXTERN void wasm_runtime_destroy_table(const wasm_module_t module, wasm_table_inst_t table); +WASM_RUNTIME_API_EXTERN wasm_function_inst_t +wasm_runtime_create_function(const wasm_module_t module, + const wasm_func_type_t type, void *callback); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_destroy_function(const wasm_module_t module, + wasm_function_inst_t func); + /*TODO: take me out when have a linker */ WASM_RUNTIME_API_EXTERN wasm_module_inst_t wasm_runtime_instantiate_with_builtin_linker(wasm_module_t module, @@ -2394,6 +2403,10 @@ 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 extern_inst_list); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 4c9f9faafe..7a9d2ff317 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -563,7 +563,7 @@ typedef struct WASMFunctionImport { char *field_name; /* function type */ WASMFuncType *func_type; - /* native function pointer after linked */ + /* from wasm_native */ void *func_ptr_linked; /* signature from registered native symbols */ const char *signature; @@ -573,9 +573,12 @@ typedef struct WASMFunctionImport { /* the type index of this function's func_type */ uint32 type_idx; #endif + + /* via wasm_native */ bool call_conv_raw; - bool call_conv_wasm_c_api; #if WASM_ENABLE_MULTI_MODULE != 0 + /* by loading-link */ + bool call_conv_wasm_c_api; WASMModule *import_module; WASMFunction *import_func_linked; #endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index e0803f358d..cb074e2e95 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1268,7 +1268,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, cur_func_index = (uint32)(cur_func - module_inst->e->functions); bh_assert(cur_func_index < module_inst->module->import_function_count); - if (!func_import->call_conv_wasm_c_api) { + + if (!cur_func->call_conv_wasm_c_api) { + /*TODO: use func_ptrs instead */ native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } else if (module_inst->c_api_func_imports) { @@ -1284,7 +1286,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, return; } - if (func_import->call_conv_wasm_c_api) { + if (cur_func->call_conv_wasm_c_api) { ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, native_func_pointer, func_import->func_type, cur_func->param_cell_num, frame->lp, @@ -1294,14 +1296,14 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, argv_ret[1] = frame->lp[1]; } } - else if (!func_import->call_conv_raw) { - ret = wasm_runtime_invoke_native( + else if (cur_func->call_conv_raw) { + ret = wasm_runtime_invoke_native_raw( exec_env, native_func_pointer, func_import->func_type, func_import->signature, func_import->attachment, frame->lp, cur_func->param_cell_num, argv_ret); } else { - ret = wasm_runtime_invoke_native_raw( + ret = wasm_runtime_invoke_native( exec_env, native_func_pointer, func_import->func_type, func_import->signature, func_import->attachment, frame->lp, cur_func->param_cell_num, argv_ret); @@ -1354,7 +1356,6 @@ fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, } #endif -#if WASM_ENABLE_MULTI_MODULE != 0 static void wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMExecEnv *exec_env, @@ -1392,8 +1393,10 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, return; } - /* Switch exec_env but keep using the same one by replacing necessary - * variables */ + /* + * Switch the WASMExecEnv while retaining the same content + * by updating the necessary variables + */ sub_module_exec_env = wasm_runtime_get_exec_env_singleton( (WASMModuleInstanceCommon *)sub_module_inst); if (!sub_module_exec_env) { @@ -1426,7 +1429,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, wasm_exec_env_restore_module_inst(exec_env, (WASMModuleInstanceCommon *)module_inst); } -#endif #if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_DEBUG_INTERP != 0 @@ -6637,8 +6639,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, call_func_from_entry: { if (cur_func->is_import_func) { -#if WASM_ENABLE_MULTI_MODULE != 0 - if (cur_func->import_func_inst) { + if (cur_func->import_module_inst) { + /* from other .wasm */ wasm_interp_call_func_import(module, exec_env, cur_func, prev_frame); #if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 @@ -6698,9 +6700,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } #endif /* end of WASM_ENABLE_EXCE_HANDLING != 0 */ } - else -#endif /* end of WASM_ENABLE_MULTI_MODULE != 0 */ - { + else { + /* from wasm_native or c_api */ wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame); #if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 @@ -7485,14 +7486,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, #endif if (function->is_import_func) { -#if WASM_ENABLE_MULTI_MODULE != 0 if (function->import_module_inst) { wasm_interp_call_func_import(module_inst, exec_env, function, frame); } - else -#endif - { + else { /* it is a native function */ wasm_interp_call_func_native(module_inst, exec_env, function, frame); diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 55d8d6d576..9b0492449e 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1209,7 +1209,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, cur_func_index = (uint32)(cur_func - module_inst->e->functions); bh_assert(cur_func_index < module_inst->module->import_function_count); - if (!func_import->call_conv_wasm_c_api) { + + if (!cur_func->call_conv_wasm_c_api) { + /*TODO: use func_ptrs instead */ native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } else if (module_inst->c_api_func_imports) { @@ -1226,7 +1228,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, return; } - if (func_import->call_conv_wasm_c_api) { + if (cur_func->call_conv_wasm_c_api) { ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, native_func_pointer, func_import->func_type, cur_func->param_cell_num, frame->lp, @@ -1236,14 +1238,14 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, argv_ret[1] = frame->lp[1]; } } - else if (!func_import->call_conv_raw) { - ret = wasm_runtime_invoke_native( + else if (cur_func->call_conv_raw) { + ret = wasm_runtime_invoke_native_raw( exec_env, native_func_pointer, func_import->func_type, func_import->signature, func_import->attachment, frame->lp, cur_func->param_cell_num, argv_ret); } else { - ret = wasm_runtime_invoke_native_raw( + ret = wasm_runtime_invoke_native( exec_env, native_func_pointer, func_import->func_type, func_import->signature, func_import->attachment, frame->lp, cur_func->param_cell_num, argv_ret); @@ -1278,7 +1280,6 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, wasm_exec_env_set_cur_frame(exec_env, prev_frame); } -#if WASM_ENABLE_MULTI_MODULE != 0 static void wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMExecEnv *exec_env, @@ -1350,7 +1351,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, wasm_exec_env_restore_module_inst(exec_env, (WASMModuleInstanceCommon *)module_inst); } -#endif #if WASM_ENABLE_THREAD_MGR != 0 #define CHECK_SUSPEND_FLAGS() \ @@ -6253,15 +6253,12 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, #endif if (function->is_import_func) { -#if WASM_ENABLE_MULTI_MODULE != 0 if (function->import_module_inst) { LOG_DEBUG("it is a function of a sub module"); wasm_interp_call_func_import(module_inst, exec_env, function, frame); } - else -#endif - { + else { LOG_DEBUG("it is an native function"); wasm_interp_call_func_native(module_inst, exec_env, function, frame); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 4c5883b650..9856c4a6cd 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -90,12 +90,14 @@ wasm_resolve_symbols(WASMModule *module) uint32 idx; for (idx = 0; idx < module->import_function_count; ++idx) { WASMFunctionImport *import = &module->import_functions[idx].u.function; - bool linked = import->func_ptr_linked; + /* by wasm_native */ + bool linked = import->func_ptr_linked != NULL; + #if WASM_ENABLE_MULTI_MODULE != 0 - if (import->import_func_linked) { - linked = true; - } + /* by loading-linking */ + linked = import->import_func_linked != NULL; #endif + if (!linked && !wasm_resolve_import_func(module, import)) { ret = false; } @@ -162,10 +164,7 @@ wasm_resolve_function(const char *module_name, const char *function_name, bool wasm_resolve_import_func(const WASMModule *module, WASMFunctionImport *function) { -#if WASM_ENABLE_MULTI_MODULE != 0 - char error_buf[128]; - WASMModule *sub_module = NULL; -#endif + /* from wasm_native functions */ function->func_ptr_linked = wasm_native_resolve_symbol( function->module_name, function->field_name, function->func_type, &function->signature, &function->attachment, &function->call_conv_raw); @@ -175,29 +174,41 @@ wasm_resolve_import_func(const WASMModule *module, WASMFunctionImport *function) } #if WASM_ENABLE_MULTI_MODULE != 0 - if (!wasm_runtime_is_built_in_module(function->module_name)) { - sub_module = (WASMModule *)wasm_runtime_load_depended_module( - (WASMModuleCommon *)module, function->module_name, error_buf, - sizeof(error_buf)); - if (!sub_module) { - LOG_WARNING("failed to load sub module: %s", error_buf); - return false; - } + if (!function->module_name) { + LOG_VERBOSE( + "does't have module name for function %s. host should provide link", + function->field_name); + return false; } + + /* from other .wasms' export functions */ + char error_buf[128]; + WASMModule *sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)module, function->module_name, error_buf, + sizeof(error_buf)); + if (!sub_module) { + LOG_WARNING("failed to load sub module: %s", error_buf); + return false; + } + function->import_func_linked = wasm_resolve_function( function->module_name, function->field_name, function->func_type, error_buf, sizeof(error_buf)); - if (function->import_func_linked) { function->import_module = sub_module; return true; } - else { - LOG_WARNING("failed to link function (%s, %s): %s", - function->module_name, function->field_name, error_buf); - } + + LOG_WARNING("failed to link function (%s, %s): %s", function->module_name, + function->field_name, error_buf); +#else + (void)module; #endif + LOG_DEBUG("can't resolve import function %s durning loading. wait for " + "instantiation linking", + function->field_name); + return false; } @@ -223,10 +234,17 @@ get_sub_module_inst(const WASMModuleInstance *parent_module_inst, bh_list *sub_module_inst_list = parent_module_inst->e->sub_module_inst_list; WASMSubModInstNode *node = bh_list_first_elem(sub_module_inst_list); - while (node && sub_module != node->module_inst->module) { + WASMModuleInstance *inst = (WASMModuleInstance *)node->module_inst; + while (node && sub_module != inst->module) { node = bh_list_elem_next(node); + inst = (WASMModuleInstance *)node->module_inst; } - return node ? node->module_inst : NULL; + + if (!node) { + LOG_DEBUG("fail to find sub module instance"); + } + + return node ? inst : NULL; } #endif @@ -976,8 +994,11 @@ functions_deinstantiate(WASMFunctionInstance *functions) * Instantiate functions in a module. */ static WASMFunctionInstance * -functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, - char *error_buf, uint32 error_buf_size) +import_functions_instantiate(const WASMModule *module, + WASMModuleInstance *module_inst, + const WASMExternInstance *imports, + uint32 import_count, char *error_buf, + uint32 error_buf_size) { WASMImport *import; uint32 i, @@ -990,6 +1011,7 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, } total_size = sizeof(void *) * (uint64)module->import_function_count; + /*TODO: remove me if all goes to func_ptrs*/ if (total_size > 0 && !(module_inst->import_func_ptrs = runtime_malloc(total_size, error_buf, error_buf_size))) { @@ -1000,36 +1022,97 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* instantiate functions from import section */ function = functions; import = module->import_functions; - for (i = 0; i < module->import_function_count; i++, import++) { + for (i = 0; i < module->import_function_count; i++, import++, function++) { function->is_import_func = true; + WASMFunctionImport *import_func_type = &(import->u.function); + function->u.func_import = import_func_type; + function->param_cell_num = import_func_type->func_type->param_cell_num; + function->ret_cell_num = import_func_type->func_type->ret_cell_num; + function->param_count = + (uint16)import_func_type->func_type->param_count; + function->param_types = import_func_type->func_type->types; + function->local_cell_num = 0; + function->local_count = 0; + function->local_types = NULL; + /* copy value from module to inst */ + function->call_conv_raw = import_func_type->call_conv_raw; + #if WASM_ENABLE_MULTI_MODULE != 0 if (import->u.function.import_module) { + /* from other .wasm */ function->import_module_inst = get_sub_module_inst( module_inst, import->u.function.import_module); - - if (function->import_module_inst) { - function->import_func_inst = - wasm_lookup_function(function->import_module_inst, - import->u.function.field_name); + if (!function->import_module_inst) { + set_error_buf_v(error_buf, error_buf_size, + "unknown import module \"%s\"", + import->u.function.module_name); + return NULL; } + + function->import_func_inst = wasm_lookup_function( + function->import_module_inst, import->u.function.field_name); } -#endif /* WASM_ENABLE_MULTI_MODULE */ - function->u.func_import = &import->u.function; - function->param_cell_num = import->u.function.func_type->param_cell_num; - function->ret_cell_num = import->u.function.func_type->ret_cell_num; - function->param_count = - (uint16)function->u.func_import->func_type->param_count; - function->param_types = function->u.func_import->func_type->types; - function->local_cell_num = 0; - function->local_count = 0; - function->local_types = NULL; - /* Copy the function pointer to current instance */ - module_inst->import_func_ptrs[i] = - function->u.func_import->func_ptr_linked; + /* from c_api (loading)*/ + function->call_conv_wasm_c_api = import_func_type->call_conv_wasm_c_api; - function++; + /* from wasm_native and c_api */ + module_inst->import_func_ptrs[i] = import_func_type->func_ptr_linked; +#else + const WASMExternInstance *extern_inst = + wasm_runtime_get_extern_instance(imports, import_count, + WASM_IMPORT_EXPORT_KIND_FUNC, i); + if (!extern_inst) { + LOG_DEBUG("no import function(%s, %s) from imports list, might " + "provied by wasm_native", + import_func_type->module_name, + import_func_type->field_name); + /* so it's from wasm_native */ + module_inst->import_func_ptrs[i] = + import_func_type->func_ptr_linked; + continue; + } + + /* if extern_inst is about a wasm function from other .wasm */ + WASMFunctionInstance *extern_inst_func = + (WASMFunctionInstance *)extern_inst->u.function; + if (!extern_inst_func) { + LOG_DEBUG("empty extern_inst_func for import function(%s, %s)", + "might provided by wasm_native", + import_func_type->module_name, + import_func_type->field_name); + /* so it's from wasm_native */ + module_inst->import_func_ptrs[i] = + import_func_type->func_ptr_linked; + continue; + } + + bh_assert(extern_inst_func->is_import_func); + + /* don't allow wrong matchment */ + if (strcmp(import_func_type->field_name, extern_inst->field_name)) { + LOG_ERROR( + "mismatched import memory name: expect \"%s\", got \"%s\"", + import_func_type->field_name, extern_inst->field_name); + return NULL; + } + + /* from other .wasm */ + function->import_module_inst = extern_inst_func->import_module_inst; + function->import_func_inst = extern_inst_func->import_func_inst; + + /* from c_api (instantiation)*/ + function->call_conv_wasm_c_api = extern_inst_func->call_conv_wasm_c_api; + /* TODO: for now, let c_api finish this. Will move it to wasm_runtime + * later */ + /*module_inst->c_api_func_imports[i] = + * extern_inst_func->import_func_c_api;*/ + + /* from wasm_native */ + module_inst->import_func_ptrs[i] = + extern_inst_func->u.func_import->func_ptr_linked; +#endif } /* instantiate functions from function section */ @@ -1786,7 +1869,7 @@ lookup_post_instantiate_func(WASMModuleInstance *module_inst, static bool execute_post_instantiate_functions(WASMModuleInstance *module_inst, - bool is_sub_inst, WASMExecEnv *exec_env_main) + bool is_spawned, WASMExecEnv *exec_env_main) { WASMFunctionInstance *start_func = module_inst->e->start_function; WASMFunctionInstance *initialize_func = NULL; @@ -1808,7 +1891,7 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, * the environment at most once, and that none of their other exports * are accessed before that call. */ - if (!is_sub_inst && module->import_wasi_api) { + if (!is_spawned && module->import_wasi_api) { initialize_func = lookup_post_instantiate_func(module_inst, "_initialize"); } @@ -1816,7 +1899,7 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, /* Execute possible "__post_instantiate" function if wasm app is compiled by emsdk's early version */ - if (!is_sub_inst) { + if (!is_spawned) { post_inst_func = lookup_post_instantiate_func(module_inst, "__post_instantiate"); } @@ -1824,7 +1907,7 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, #if WASM_ENABLE_BULK_MEMORY != 0 /* Only execute the memory init function for main instance since the data segments will be dropped once initialized */ - if (!is_sub_inst + if (!is_spawned #if WASM_ENABLE_LIBC_WASI != 0 && !module->import_wasi_api #endif @@ -1840,7 +1923,7 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, return true; } - if (is_sub_inst) { + if (is_spawned) { bh_assert(exec_env_main); #ifdef OS_ENABLE_HW_BOUND_CHECK /* May come from pthread_create_wrapper, thread_spawn_wrapper and @@ -1915,7 +1998,7 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, ret = true; fail: - if (is_sub_inst) { + if (is_spawned) { /* Restore the parent exec_env's module inst */ wasm_exec_env_restore_module_inst(exec_env_main, module_inst_main); } @@ -2125,13 +2208,11 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, uint32 i; for (i = 0; i < module->import_function_count; i++) { - WASMFunctionImport *func = - &((module->import_functions + i)->u.function); - if (!func->func_ptr_linked -#if WASM_ENABLE_MULTI_MODULE != 0 - && !func->import_func_linked -#endif - ) { + void *func_ptr_linked = module_inst->import_func_ptrs[i]; + if (!func_ptr_linked) { + WASMFunctionImport *func = + &((module->import_functions + i)->u.function); + LOG_WARNING("warning: failed to link import function (%s, %s)", func->module_name, func->field_name); } @@ -2199,6 +2280,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, #if WASM_ENABLE_JIT != 0 static bool init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module, + const WASMExternInstance *imports, uint32 import_count, char *error_buf, uint32 error_buf_size) { uint32 i; @@ -2213,10 +2295,29 @@ init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module, /* Set import function pointers */ for (i = 0; i < module->import_function_count; i++, func_ptrs++) { - WASMFunctionImport *import_func = - &module->import_functions[i].u.function; - /* TODO: handle multi module */ + WASMFunctionInstance *func = + wasm_locate_function_instance(module_inst, i); + bh_assert(func->is_import_func); + + if (func->call_conv_wasm_c_api) { + /* when execution, goes to invoke_native() and use + * c_api_func_imports*/ + continue; + } + + if (func->import_module_inst) { + /* when execution, goes to invoke_native() and switch to another + * .wasm */ + continue; + } + + WASMFunctionImport *import_func = func->u.func_import; + + LOG_DEBUG("use wasm_native linked functions for (%s,%s)", + import_func->module_name, import_func->field_name); + *func_ptrs = import_func->func_ptr_linked; + bh_assert(*func_ptrs); } /* The defined function pointers will be set in @@ -2592,7 +2693,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #if WASM_ENABLE_MULTI_MODULE != 0 bool ret = false; #endif - const bool is_sub_inst = parent != NULL; + const bool is_spawned = parent != NULL; if (!module) return NULL; @@ -2714,7 +2815,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #endif #if WASM_ENABLE_GC != 0 - if (!is_sub_inst) { + if (!is_spawned) { uint32 gc_heap_size = wasm_runtime_get_gc_heap_size_default(); if (gc_heap_size < GC_HEAP_SIZE_MIN) @@ -2804,8 +2905,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, module, module_inst, first_table, imports, import_count, error_buf, error_buf_size))) || (module_inst->e->function_count > 0 - && !(module_inst->e->functions = functions_instantiate( - module, module_inst, error_buf, error_buf_size))) + && !(module_inst->e->functions = import_functions_instantiate( + module, module_inst, imports, import_count, error_buf, + error_buf_size))) || (module_inst->export_func_count > 0 && !(module_inst->export_functions = export_functions_instantiate( module, module_inst, module_inst->export_func_count, @@ -2833,7 +2935,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #endif #if WASM_ENABLE_JIT != 0 || (module_inst->e->function_count > 0 - && !init_func_ptrs(module_inst, module, error_buf, error_buf_size)) + && !init_func_ptrs(module_inst, module, imports, import_count, + error_buf, error_buf_size)) #endif #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || (module_inst->e->function_count > 0 @@ -2958,7 +3061,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, if (data_seg->is_passive) continue; #endif - if (is_sub_inst) + if (is_spawned) /* Ignore setting memory init data if the memory has been initialized */ continue; @@ -3471,7 +3574,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #if WASM_ENABLE_LIBC_WASI != 0 /* The sub-instance will get the wasi_ctx from main-instance */ - if (!is_sub_inst) { + if (!is_spawned) { if (!wasm_runtime_init_wasi( (WASMModuleInstanceCommon *)module_inst, module->wasi_args.dir_list, module->wasi_args.dir_count, @@ -3489,7 +3592,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #endif #if WASM_ENABLE_DEBUG_INTERP != 0 - if (!is_sub_inst) { + if (!is_spawned) { /* Add module instance into module's instance list */ os_mutex_lock(&module->instance_list_lock); if (module->instance_list) { @@ -3518,7 +3621,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, &module_inst->e->functions[module->start_function]; } - if (!execute_post_instantiate_functions(module_inst, is_sub_inst, + if (!execute_post_instantiate_functions(module_inst, is_spawned, exec_env_main)) { set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); goto fail; @@ -3561,7 +3664,7 @@ destroy_c_api_frames(Vector *frames) #endif void -wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) +wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_spawned) { if (!module_inst) return; @@ -3659,7 +3762,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) #endif #if WASM_ENABLE_GC != 0 - if (!is_sub_inst) { + if (!is_spawned) { if (module_inst->e->common.gc_heap_handle) mem_allocator_destroy(module_inst->e->common.gc_heap_handle); if (module_inst->e->common.gc_heap_pool) @@ -3678,7 +3781,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) if (module_inst->c_api_func_imports) wasm_runtime_free(module_inst->c_api_func_imports); - if (!is_sub_inst) { + if (!is_spawned) { wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); } @@ -4648,14 +4751,14 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf, /* function name not exported, print number instead */ if (frame.func_name_wp == NULL) { line_length = - snprintf(line_buf, sizeof(line_buf), - "#%02" PRIu32 ": 0x%04x - $f%" PRIu32 "\n", n, - frame.func_offset, frame.func_index); + (uint32)snprintf(line_buf, sizeof(line_buf), + "#%02" PRIu32 ": 0x%04x - $f%" PRIu32 "\n", + n, frame.func_offset, frame.func_index); } else { - line_length = snprintf(line_buf, sizeof(line_buf), - "#%02" PRIu32 ": 0x%04x - %s\n", n, - frame.func_offset, frame.func_name_wp); + line_length = (uint32)snprintf( + line_buf, sizeof(line_buf), "#%02" PRIu32 ": 0x%04x - %s\n", + n, frame.func_offset, frame.func_name_wp); } } @@ -4762,19 +4865,33 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, func_type_indexes = module_inst->func_type_indexes; func_type_idx = func_type_indexes[func_idx]; func_type = (WASMFuncType *)module->types[func_type_idx]; - func_ptr = module_inst->func_ptrs[func_idx]; bh_assert(func_idx < module->import_function_count); import_func = &module->import_functions[func_idx].u.function; - if (import_func->call_conv_wasm_c_api) { - if (module_inst->c_api_func_imports) { - c_api_func_import = module_inst->c_api_func_imports + func_idx; - func_ptr = c_api_func_import->func_ptr_linked; + + WASMFunctionInstance *func_inst = + wasm_locate_function_instance(module_inst, func_idx); + + if (func_inst->call_conv_wasm_c_api) { + c_api_func_import = module_inst->c_api_func_imports + ? module_inst->c_api_func_imports + func_idx + : NULL; + func_ptr = + c_api_func_import ? c_api_func_import->func_ptr_linked : NULL; + } + else if (func_inst->call_conv_raw) { + func_ptr = module_inst->func_ptrs[func_idx]; + } + else { + if (func_inst->import_module_inst) { + uint32 funx_idx_of_import_func = wasm_calc_function_index( + func_inst->import_module_inst, func_inst->import_func_inst); + func_ptr = func_inst->import_module_inst + ->func_ptrs[funx_idx_of_import_func]; } else { - c_api_func_import = NULL; - func_ptr = NULL; + func_ptr = module_inst->func_ptrs[func_idx]; } } @@ -4787,23 +4904,38 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, } attachment = import_func->attachment; - if (import_func->call_conv_wasm_c_api) { + if (func_inst->call_conv_wasm_c_api) { + /* from wasm_c_api */ ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, argv, c_api_func_import->with_env_arg, c_api_func_import->env_arg); } - else if (!import_func->call_conv_raw) { - signature = import_func->signature; - ret = - wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, - attachment, argv, argc, argv); - } - else { + else if (func_inst->call_conv_raw) { + /* from wasm_native raw */ signature = import_func->signature; ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, signature, attachment, argv, argc, argv); } + else { + if (func_inst->import_module_inst) { + /* from other .wasm. switch */ + exec_env = wasm_runtime_get_exec_env_singleton( + (WASMModuleInstanceCommon *)func_inst->import_module_inst); + if (!exec_env) { + wasm_runtime_set_exception( + (WASMModuleInstanceCommon *)module_inst, + "create singleton exec_env failed"); + goto fail; + } + } + + /* from wasm_native */ + signature = import_func->signature; + ret = + wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, + attachment, argv, argc, argv); + } fail: #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -5424,6 +5556,7 @@ wasm_destroy_table(WASMTableInstance *table) wasm_runtime_free(table); } +/*TODO: add init_value */ WASMGlobalInstance * wasm_create_global(const WASMModule *module, WASMModuleInstance *dep_inst, WASMGlobalType *type) @@ -5455,4 +5588,26 @@ wasm_destroy_global(WASMGlobalInstance *global) return; wasm_runtime_free(global); +} + +WASMFunctionInstance * +wasm_create_function_empty(const WASMModule *module) +{ + WASMFunctionInstance *function = runtime_malloc( + sizeof(WASMFunctionInstance) + sizeof(WASMFunctionImport), NULL, 0); + if (!function) { + return NULL; + } + + function->u.func_import = (WASMFunctionImport *)(function + 1); + return function; +} + +void +wasm_destroy_function(WASMFunctionInstance *function) +{ + if (!function) + return; + + wasm_runtime_free(function); } \ No newline at end of file diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index e76ee487bc..ff07ad0d7f 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -233,14 +233,24 @@ struct WASMFunctionInstance { uint8 *param_types; /* local types, NULL for import function */ uint8 *local_types; + union { + /* setup by wasm_native */ WASMFunctionImport *func_import; + /* local bytecode */ WASMFunction *func; } u; -#if WASM_ENABLE_MULTI_MODULE != 0 + + /* from other .wasm */ WASMModuleInstance *import_module_inst; WASMFunctionInstance *import_func_inst; -#endif + /* copy it from WASMFunctionImport */ + bool call_conv_raw; + /* write it from wasm_c_api */ + bool call_conv_wasm_c_api; + /* WASMModuleInstance collects it to form c_api_func_imports */ + CApiFuncImport import_func_c_api; + #if WASM_ENABLE_PERF_PROFILING != 0 /* total execution time */ uint64 total_exec_time; @@ -302,16 +312,6 @@ typedef struct WASMExportTagInstance { } WASMExportTagInstance; #endif -/* wasm-c-api import function info */ -typedef struct CApiFuncImport { - /* host func pointer after linked */ - void *func_ptr_linked; - /* whether the host func has env argument */ - bool with_env_arg; - /* the env argument of the host func */ - void *env_arg; -} CApiFuncImport; - /* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */ typedef struct WASMModuleInstanceExtraCommon { #if WASM_ENABLE_MODULE_INST_CONTEXT != 0 @@ -436,6 +436,10 @@ struct WASMModuleInstance { DefPointer(WASMModule *, module); DefPointer(WASMExecEnv *, exec_env_singleton); + /* + * TODO: is able to be removed. + * interp and fast-jit can use func_ptrs instead of this. + */ /* Array of function pointers to import functions, not available in AOTModuleInstance */ DefPointer(void **, import_func_ptrs); @@ -485,15 +489,6 @@ struct WASMModuleInstance { struct WASMInterpFrame; typedef struct WASMInterpFrame WASMRuntimeFrame; -#if WASM_ENABLE_MULTI_MODULE != 0 -typedef struct WASMSubModInstNode { - bh_list_link l; - /* point to a string pool */ - const char *module_name; - WASMModuleInstance *module_inst; -} WASMSubModInstNode; -#endif - /** * Return the code block of a function. * @@ -546,6 +541,23 @@ wasm_locate_table_elems(const WASMModule *module, WASMTableInstance *table, return table->elems; } +static inline WASMFunctionInstance * +wasm_locate_function_instance(const WASMModuleInstance *module_inst, + uint32 func_idx) +{ + WASMModuleInstanceExtra *e = (WASMModuleInstanceExtra *)module_inst->e; + WASMFunctionInstance *func = e->functions + func_idx; + return func; +} + +static inline uint32 +wasm_calc_function_index(const WASMModuleInstance *module_inst, + const WASMFunctionInstance *func) +{ + return (uint32)(func + - ((WASMModuleInstanceExtra *)module_inst->e)->functions); +} + static inline uint32 wasm_get_tbl_data_slots(const WASMTableType *table_type, const WASMTableImport *import_type) @@ -624,7 +636,7 @@ wasm_get_wasm_func_exec_time(const WASMModuleInstance *inst, const char *func_name); void -wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst); +wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_spawned); bool wasm_set_running_mode(WASMModuleInstance *module_inst, @@ -988,6 +1000,35 @@ wasm_set_global_value(WASMGlobalInstance *global, const WASMValue *value); void wasm_destroy_global(WASMGlobalInstance *global); +WASMFunctionInstance * +wasm_create_function_empty(const WASMModule *module); + +void +wasm_destroy_function(WASMFunctionInstance *function); + +static inline void +wasm_function_import_from_wasm(WASMFunctionInstance *func, + WASMModuleInstance *dep_inst, + WASMFunctionInstance *dep_func) +{ + func->import_module_inst = dep_inst; + func->import_func_inst = dep_func; +} + +static inline void +wasm_function_import_from_c_api(WASMFunctionInstance *func, + CApiFuncImport *c_api_func_import) +{ + func->import_func_c_api = *c_api_func_import; +} + +/*might be unused*/ +static inline void +wasm_function_import_from_native(WASMFunctionInstance *func, void *callback) +{ + func->u.func_import->func_ptr_linked = callback; +} + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/libc-builtin/builtin_wrapper.h b/core/iwasm/libraries/libc-builtin/builtin_wrapper.h index de5cf77e5d..51e376d127 100644 --- a/core/iwasm/libraries/libc-builtin/builtin_wrapper.h +++ b/core/iwasm/libraries/libc-builtin/builtin_wrapper.h @@ -12,6 +12,10 @@ /************************************* * Functions *************************************/ +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ + { #func_name, func_name##_wrapper, signature, NULL } +/* clang-format on */ /************************************* * Globals diff --git a/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c index 9305be628d..ade392959f 100644 --- a/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c @@ -138,6 +138,13 @@ wasm_runtime_create_extern_inst_for_spec_test(wasm_module_t module, if (!module || !import_type || !out) return false; + if (import_type->kind == WASM_IMPORT_EXPORT_KIND_FUNC) { + /* Let wasm_native inject wrappers into WASMFunctionImport */ + LOG_DEBUG("skip import(%s,%s) kind %d", import_type->module_name, + import_type->name, import_type->kind); + return true; + } + LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name, import_type->name, import_type->kind);