From 4787b150b86ff1153559fbcc99c45df17a64a507 Mon Sep 17 00:00:00 2001 From: lum1n0us <62137521+lum1n0us@users.noreply.github.com> Date: Fri, 16 Oct 2020 17:43:57 +0800 Subject: [PATCH] Enable multi-module support for wasm-c-api (#426) it is allowed that all imported functions and globals can be linked by multi-module feature automatically or by wasm-c-api manually --- .github/workflows/linux.yml | 8 +- .github/workflows/mac.yml | 6 + core/iwasm/common/wasm_c_api.c | 70 +++++--- core/iwasm/common/wasm_runtime_common.c | 9 +- core/iwasm/common/wasm_runtime_common.h | 3 + core/iwasm/interpreter/wasm.h | 1 + core/iwasm/interpreter/wasm_interp_classic.c | 8 +- core/iwasm/interpreter/wasm_interp_fast.c | 18 +- core/iwasm/interpreter/wasm_loader.c | 69 ++------ core/iwasm/interpreter/wasm_mini_loader.c | 11 +- core/iwasm/interpreter/wasm_runtime.c | 115 +++++++----- core/shared/mem-alloc/tlsf | 1 + doc/release_ack.md | 61 +++++++ doc/roadmap.md | 23 +++ samples/wasm-c-api/CMakeLists.txt | 62 ++++--- samples/wasm-c-api/README.md | 15 +- samples/wasm-c-api/src/callback.c | 10 ++ samples/wasm-c-api/src/callback.wasm | Bin 102 -> 0 bytes samples/wasm-c-api/src/global.c | 10 ++ samples/wasm-c-api/src/global.wasm | Bin 576 -> 0 bytes .../wasm-c-api/src/globalexportimport-0.wat | 5 + .../wasm-c-api/src/globalexportimport-1.wat | 7 + samples/wasm-c-api/src/globalexportimport.c | 166 ++++++++++++++++++ samples/wasm-c-api/src/hello.c | 10 ++ samples/wasm-c-api/src/hello.wasm | Bin 71 -> 0 bytes .../wasm-c-api/src/utils/multi_module_utils.c | 47 +++++ 26 files changed, 550 insertions(+), 185 deletions(-) create mode 160000 core/shared/mem-alloc/tlsf create mode 100644 doc/release_ack.md create mode 100644 doc/roadmap.md delete mode 100644 samples/wasm-c-api/src/callback.wasm delete mode 100644 samples/wasm-c-api/src/global.wasm create mode 100644 samples/wasm-c-api/src/globalexportimport-0.wat create mode 100644 samples/wasm-c-api/src/globalexportimport-1.wat create mode 100644 samples/wasm-c-api/src/globalexportimport.c delete mode 100644 samples/wasm-c-api/src/hello.wasm create mode 100644 samples/wasm-c-api/src/utils/multi_module_utils.c diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 128af62e8..22d13e57e 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -84,12 +84,18 @@ jobs: cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 make cd .. && rm -rf build - - name: download wasi-sdk + - name: download and install wasi-sdk run: | cd /opt wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk-8.0-linux.tar.gz tar -xzf wasi-sdk-8.0-linux.tar.gz mv wasi-sdk-8.0 wasi-sdk + - name: download and install wabt + run: | + cd /opt + wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-ubuntu.tar.gz + tar -xzf wabt-1.0.19-ubuntu.tar.gz + mv wabt-1.0.19 wabt - name: Build Sample [wasm-c-api] run: | cd samples/wasm-c-api diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 361a9c2e4..6c8704b2b 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -84,6 +84,12 @@ jobs: cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 make cd .. && rm -rf build + - name: download and install wabt + run: | + cd /opt + sudo wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-macos.tar.gz + sudo tar -xzf wabt-1.0.19-macos.tar.gz + sudo mv wabt-1.0.19 wabt - name: Build Sample [wasm-c-api] run: | cd samples/wasm-c-api diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index f87edf6be..0ef9d4ceb 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -1696,7 +1696,14 @@ interp_global_set(const WASMModuleInstance *inst_interp, const WASMGlobalInstance *global_interp = inst_interp->globals + global_idx_rt; uint8 val_type_rt = global_interp->type; +#if WASM_ENABLE_MULTI_MODULE != 0 + uint8 *data = global_interp->import_global_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 bool ret = true; switch (val_type_rt) { @@ -1732,7 +1739,14 @@ interp_global_get(const WASMModuleInstance *inst_interp, { WASMGlobalInstance *global_interp = inst_interp->globals + global_idx_rt; uint8 val_type_rt = global_interp->type; +#if WASM_ENABLE_MULTI_MODULE != 0 + uint8 *data = global_interp->import_global_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 bool ret = true; switch (val_type_rt) { @@ -2080,6 +2094,7 @@ interp_link_global(const WASMModule *module_interp, } import->global_idx_rt = global_idx_rt; + imported_global_interp->u.global.is_linked = true; return true; } @@ -2432,35 +2447,44 @@ wasm_instance_new(wasm_store_t *store, } /* link module and imports */ - if (INTERP_MODE == current_runtime_mode()) { + if (imports) { + if (INTERP_MODE == current_runtime_mode()) { #if WASM_ENABLE_INTERP != 0 - import_count = ((WASMModule *)*module)->import_count; - INIT_VEC(instance->imports, wasm_extern_vec, import_count); - if (!instance->imports) { - goto failed; - } + import_count = ((WASMModule *)*module)->import_count; + INIT_VEC(instance->imports, wasm_extern_vec, import_count); + if (!instance->imports) { + goto failed; + } - import_count = interp_link(instance, (WASMModule *)*module, - (wasm_extern_t **)imports); + if (import_count) { + import_count = interp_link(instance, (WASMModule *)*module, + (wasm_extern_t **)imports); + if ((int32)import_count < 0) { + goto failed; + } + } #endif - } - else { + } + else { #if WASM_ENABLE_AOT != 0 - import_count = ((AOTModule *)*module)->import_func_count - + ((AOTModule *)*module)->import_global_count - + ((AOTModule *)*module)->import_memory_count - + ((AOTModule *)*module)->import_table_count; - INIT_VEC(instance->imports, wasm_extern_vec, import_count); - if (!instance->imports) { - goto failed; - } + import_count = ((AOTModule *)*module)->import_func_count + + ((AOTModule *)*module)->import_global_count + + ((AOTModule *)*module)->import_memory_count + + ((AOTModule *)*module)->import_table_count; + INIT_VEC(instance->imports, wasm_extern_vec, import_count); + if (!instance->imports) { + goto failed; + } - import_count = - aot_link(instance, (AOTModule *)*module, (wasm_extern_t **)imports); + if (import_count) { + import_count = aot_link(instance, (AOTModule *)*module, + (wasm_extern_t **)imports); + if ((int32)import_count < 0) { + goto failed; + } + } #endif - } - if ((int32)import_count < 0) { - goto failed; + } } instance->inst_comm_rt = wasm_runtime_instantiate( diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index abd2d752a..8d75eca45 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -539,6 +539,12 @@ wasm_runtime_destroy_loading_module_list() } #endif /* WASM_ENABLE_MULTI_MODULE */ +bool +wasm_runtime_is_host_module(const char *module_name) +{ + return strlen(module_name) == 0; +} + bool wasm_runtime_is_built_in_module(const char *module_name) { @@ -2342,7 +2348,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, wasm_runtime_set_exception(module_inst, buf); goto fail; } - type = wasm_func->u.func->func_type; + type = wasm_func->is_import_func ? wasm_func->u.func_import->func_type + : wasm_func->u.func->func_type; argc1 = wasm_func->param_cell_num; cell_num = argc1 > wasm_func->ret_cell_num ? argc1 : wasm_func->ret_cell_num; diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 8dd98dc41..111bfec2c 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -373,6 +373,9 @@ void wasm_runtime_destroy_loading_module_list(); #endif /* WASM_ENALBE_MULTI_MODULE */ +bool +wasm_runtime_is_host_module(const char *module_name); + bool wasm_runtime_is_built_in_module(const char *module_name); diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index f45464e0c..fea564260 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -177,6 +177,7 @@ typedef struct WASMGlobalImport { bool is_mutable; /* global data after linked */ WASMValue global_data_linked; + bool is_linked; #if WASM_ENABLE_MULTI_MODULE != 0 /* imported function pointer after linked */ /* TODO: remove if not needed */ diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index e18235d8b..d8ad05053 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1362,12 +1362,8 @@ label_pop_csp_n: /* always call module own functions */ cur_func = module->functions + fidx; - if (cur_func->is_import_func -#if WASM_ENABLE_MULTI_MODULE != 0 - && !cur_func->import_func_inst -#endif - ) - cur_func_type = cur_func->u.func_import->func_type; + if (cur_func->is_import_func) + cur_func_type = cur_func->u.func_import->func_type; else cur_func_type = cur_func->u.func->func_type; if (!wasm_type_equal(cur_type, cur_func_type)) { diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 37a10ad2a..643f680f7 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1270,11 +1270,7 @@ recover_br_info: WASMType *func_type; uint32 off, ret_offset; uint8 *ret_types; - if (cur_func->is_import_func -#if WASM_ENABLE_MULTI_MODULE != 0 - && !cur_func->import_func_inst -#endif - ) + if (cur_func->is_import_func) func_type = cur_func->u.func_import->func_type; else func_type = cur_func->u.func->func_type; @@ -1354,11 +1350,7 @@ recover_br_info: /* always call module own functions */ cur_func = module->functions + fidx; - if (cur_func->is_import_func -#if WASM_ENABLE_MULTI_MODULE != 0 - && !cur_func->import_func_inst -#endif - ) + if (cur_func->is_import_func) cur_func_type = cur_func->u.func_import->func_type; else cur_func_type = cur_func->u.func->func_type; @@ -3253,11 +3245,7 @@ recover_br_info: * values' offset so we must skip remain return values' offsets. */ WASMType *func_type; - if (cur_func->is_import_func -#if WASM_ENABLE_MULTI_MODULE != 0 - && !cur_func->import_func_inst -#endif - ) + if (cur_func->is_import_func) func_type = cur_func->u.func_import->func_type; else func_type = cur_func->u.func->func_type; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 804c497c3..f542f9deb 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -796,10 +796,11 @@ load_function_import(const WASMModule *parent_module, WASMModule *sub_module, declare_func_type = parent_module->types[declare_type_index]; - is_built_in_module = wasm_runtime_is_built_in_module(sub_module_name); - if (is_built_in_module) { - LOG_DEBUG("%s is a function of a built-in module %s", - function_name, sub_module_name); + if (wasm_runtime_is_host_module(sub_module_name)) { + /* do nothing, wait for injecting host created fuctions */ + } + else if ((is_built_in_module = + wasm_runtime_is_built_in_module(sub_module_name))) { /* check built-in modules */ linked_func = wasm_native_resolve_symbol(sub_module_name, function_name, @@ -810,8 +811,6 @@ load_function_import(const WASMModule *parent_module, WASMModule *sub_module, } #if WASM_ENABLE_MULTI_MODULE != 0 else { - LOG_DEBUG("%s is a function of a sub-module %s", - function_name, sub_module_name); linked_func = wasm_loader_resolve_function(sub_module_name, function_name, declare_func_type, @@ -820,19 +819,6 @@ load_function_import(const WASMModule *parent_module, WASMModule *sub_module, } #endif - if (!linked_func) { -#if WASM_ENABLE_SPEC_TEST != 0 - set_error_buf(error_buf, error_buf_size, - "unknown import or incompatible import type"); - return false; -#else -#if WASM_ENABLE_WAMR_COMPILER == 0 - LOG_WARNING("warning: fail to link import function (%s, %s)", - sub_module_name, function_name); -#endif -#endif - } - function->module_name = sub_module_name; function->field_name = function_name; function->func_type = declare_func_type; @@ -1096,8 +1082,6 @@ load_global_import(const WASMModule *parent_module, const uint8 *p = *p_buf, *p_end = buf_end; uint8 declare_type = 0; uint8 declare_mutable = 0; - bool is_mutable = false; - bool ret = false; CHECK_BUF(p, p_end, 2); declare_type = read_uint8(p); @@ -1109,50 +1093,33 @@ load_global_import(const WASMModule *parent_module, return false; } - is_mutable = declare_mutable & 1 ? true : false; - -#if WASM_ENABLE_LIBC_BUILTIN != 0 - ret = wasm_runtime_is_built_in_module(sub_module_name); - if (ret) { - /* check built-in modules */ - ret = wasm_native_lookup_libc_builtin_global(sub_module_name, - global_name, global); - if (ret) { - LOG_DEBUG("(%s, %s) is a global of a built-in module", - sub_module_name, global_name); - } + if (wasm_runtime_is_host_module(sub_module_name)) { + /* do nothing, let host injects the symbol */ + } + else if (wasm_runtime_is_built_in_module(sub_module_name)) { + /* check built-in modules */ + global->is_linked = wasm_native_lookup_libc_builtin_global( + sub_module_name, global_name, global); } -#endif /* WASM_ENABLE_LIBC_BUILTIN */ - #if WASM_ENABLE_MULTI_MODULE != 0 - if (!ret) { + else { /* check sub modules */ WASMGlobal *linked_global = wasm_loader_resolve_global(sub_module_name, global_name, declare_type, declare_mutable, error_buf, error_buf_size); if (linked_global) { - LOG_DEBUG("(%s, %s) is a global of external module", - sub_module_name, global_name); global->import_module = sub_module; global->import_global_linked = linked_global; - ret = true; + global->is_linked = true; } } #endif - if (!ret) { -#if WASM_ENABLE_SPEC_TEST != 0 - set_error_buf(error_buf, error_buf_size, - "unknown import or incompatible import type"); - return false; -#endif - } - global->module_name = sub_module_name; global->field_name = global_name; global->type = declare_type; - global->is_mutable = is_mutable; + global->is_mutable = (declare_mutable == 1); return true; fail: return false; @@ -1363,8 +1330,7 @@ load_depended_module(const WASMModule *parent_module, ret = reader(sub_module_name, &buffer, &buffer_size); if (!ret) { LOG_DEBUG("read the file of %s failed", sub_module_name); - set_error_buf_v(error_buf, error_buf_size, - "failed to read module file of %s", + set_error_buf_v(error_buf, error_buf_size, "unknown import", sub_module_name); goto DELETE_FROM_LOADING_LIST; } @@ -1568,7 +1534,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, LOG_DEBUG("import #%d: (%s, %s)", i, sub_module_name, field_name); #if WASM_ENABLE_MULTI_MODULE != 0 /* assume built-in modules have been loaded */ - if (!wasm_runtime_is_built_in_module(sub_module_name)) { + if (!wasm_runtime_is_host_module(sub_module_name) + && !wasm_runtime_is_built_in_module(sub_module_name)) { LOG_DEBUG("%s is an exported field of a %s", field_name, sub_module_name); /* diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index c358dab45..d25a310fe 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -527,19 +527,10 @@ load_global_import(const WASMModule *parent_module, /* check built-in modules */ ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name, global); - if (ret) { - LOG_DEBUG("(%s, %s) is a global of a built-in module", - sub_module_name, global_name); - } } #endif /* WASM_ENABLE_LIBC_BUILTIN */ - if (!ret) { - set_error_buf(error_buf, error_buf_size, - "unknown import or incompatible import type"); - return false; - } - + global->is_linked = ret; global->module_name = sub_module_name; global->field_name = global_name; global->type = declare_type; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 8a1e66fc3..bad93e1e5 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -550,56 +550,27 @@ functions_instantiate(const WASMModule *module, #if WASM_ENABLE_MULTI_MODULE != 0 if (import->u.function.import_module) { - LOG_DEBUG("(%s, %s) is a function of a sub-module", - import->u.function.module_name, - import->u.function.field_name); - function->import_module_inst = get_sub_module_inst(module_inst, import->u.function.import_module); - bh_assert(function->import_module_inst); - WASMFunction *function_linked = - import->u.function.import_func_linked; - - function->u.func = function_linked; - function->import_func_inst = - wasm_lookup_function(function->import_module_inst, - import->u.function.field_name, - NULL); - bh_assert(function->import_func_inst); - - function->param_cell_num = function->u.func->param_cell_num; - function->ret_cell_num = function->u.func->ret_cell_num; - function->local_cell_num = function->u.func->local_cell_num; - function->param_count = - (uint16)function->u.func->func_type->param_count; - function->local_count = (uint16)function->u.func->local_count; - function->param_types = function->u.func->func_type->types; - function->local_types = function->u.func->local_types; - function->local_offsets = function->u.func->local_offsets; -#if WASM_ENABLE_FAST_INTERP != 0 - function->const_cell_num = function->u.func->const_cell_num; -#endif + if (function->import_module_inst) { + function->import_func_inst = + wasm_lookup_function(function->import_module_inst, + import->u.function.field_name, NULL); + } } - else #endif /* WASM_ENABLE_MULTI_MODULE */ - { - LOG_DEBUG("(%s, %s) is a function of native", - import->u.function.module_name, - import->u.function.field_name); - 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; - } + 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; function++; } @@ -1069,6 +1040,57 @@ sub_module_deinstantiate(WASMModuleInstance *module_inst) } #endif +static bool +check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, + uint32 error_buf_size) +{ + WASMModule *module = module_inst->module; + 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 + ) { +#if WASM_ENABLE_SPEC_TEST != 0 + set_error_buf(error_buf, error_buf_size, + "unknown import or incompatible import type"); + return false; +#else +#if WASM_ENABLE_WAMR_COMPILER == 0 + LOG_WARNING("warning: fail to link import function (%s, %s)", + func->module_name, func->field_name); +#else + /* do nothing to avoid confused message */ +#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */ +#endif /* WASM_ENABLE_SPEC_TEST != 0 */ + } + } + + for (i = 0; i < module->import_global_count; i++) { + WASMGlobalImport *global = &((module->import_globals + i)->u.global); + if (!global->is_linked) { +#if WASM_ENABLE_SPEC_TEST != 0 + set_error_buf(error_buf, error_buf_size, + "unknown import or incompatible import type"); + return false; +#else +#if WASM_ENABLE_WAMR_COMPILER == 0 + LOG_DEBUG("warning: fail to link import global (%s, %s)", + global->module_name, global->field_name); +#else + /* do nothing to avoid confused message */ +#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */ +#endif /* WASM_ENABLE_SPEC_TEST != 0 */ + } + } + + return true; +} + /** * Instantiate module */ @@ -1215,6 +1237,11 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, bh_assert(global_data == global_data_end); } + if (!check_linked_symbol(module_inst, error_buf, error_buf_size)) { + wasm_deinstantiate(module_inst, false); + return NULL; + } + /* Initialize the memory data with data segment section */ module_inst->default_memory = module_inst->memory_count ? module_inst->memories[0] : NULL; diff --git a/core/shared/mem-alloc/tlsf b/core/shared/mem-alloc/tlsf new file mode 160000 index 000000000..a1f743ffa --- /dev/null +++ b/core/shared/mem-alloc/tlsf @@ -0,0 +1 @@ +Subproject commit a1f743ffac0305408b39e791e0ffb45f6d9bc777 diff --git a/doc/release_ack.md b/doc/release_ack.md new file mode 100644 index 000000000..a0adfff41 --- /dev/null +++ b/doc/release_ack.md @@ -0,0 +1,61 @@ +Major feature releases and contributors +========================================= + + +**May 07, 2019: WAMR first GitHub release** + +- Contributors: Wenyong Huang, Weining Lu, Lei Shi, Li Tian, Jizhao Zhang, Yi Zhang, Daoming Qiu, Xin Wang (Intel) + +**May 17, 2019: Application manager, WASM APP API, samples and test tools** + +- Contributors: Wenyong Huang, Weining Lu, Lei Shi, Li Tian, Jizhao Zhang, Yi Zhang, Daoming Qiu, Xin Wang (Intel) + + +**May 23, 2019: Support AliOS Things** + +- Contributor: JinZhou Zhu (Alibaba) + +**May 24, 2019: Support memory usage profiler** + +- Contributors Wenyong Huang (Intel) + +**Jun 11, 2019: Add WASM APP API connection** + + +- Contributor: Weining Lu (Intel) + +**Jun 10, 2019: Support VxWorks** + +- Contributor: Yiting Wang (WindRiver) + +**Aug 1, 2019: Add WGL graphic user interface API** + +- Contributor: Weining Lu + +**Aug 14, 2019: Add Docker support** + + +- Contributor: beriberikix + + +**Aug 14, 2019: WASM IoT app store demo** + + +- Contributor: Luhanzhi Li, Jun Xu (Intel) + + +**Aug 28, 2019: SGX support** + + +- Contributor: Mic Bowman (Intel) + + +**Sep 6, 2019: Mac platform support** + + +- Contributor: Jonathan Dong (Alibaba) + +**Nov 2019: WASI support** (Intel) + +**Jan 2020: Ahead of time and Just-in-Time compilation support** (Intel) + diff --git a/doc/roadmap.md b/doc/roadmap.md new file mode 100644 index 000000000..c5c7b84a9 --- /dev/null +++ b/doc/roadmap.md @@ -0,0 +1,23 @@ + +# WebAssembly Micro Runtime Roadmap + + + +## Data serialization +Evaluating using cbor as the default data serialization + +No plan yet. + + + +## Threading +Plan: 2020 Q1 + + + +## AssemblyScript Support and API + +Currently under evaluation + + + diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 682f2dc0b..46b30ce94 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -40,6 +40,7 @@ endif() set(WAMR_BUILD_LIBC_BUILTIN 1) set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_MULTI_MODULE 1) if(NOT DEFINED WAMR_BUILD_FAST_INTERP) set(WAMR_BUILD_FAST_INTERP 0) @@ -70,47 +71,44 @@ endif() ################################################ ################ application related ################ -file(GLOB SOURCES src/*.c) -add_library(c-api ${SOURCES}) -target_include_directories(c-api - PRIVATE ${C_API_PATH}/include +## locate wat2wasm +find_program(WAT2WASM + wat2wasm + PATHS /opt/wabt/bin /opt/wabt-1.0.18/bin + REQUIRED ) -target_link_libraries(c-api PRIVATE vmlib -lpthread -lm) -if (MSVC) - target_compile_definitions(c-api PRIVATE WASM_API_EXTERN=) + +if(NOT WAT2WASM) + message(SEND_ERROR "can not find wat2wasm") endif() +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +set(MM_UTIL src/utils/multi_module_utils.c) +# build executable for each .c +file(GLOB SOURCES src/*.c) foreach(SRC ${SOURCES}) get_filename_component(APPNAME ${SRC} NAME_WE) - # build executable for each .c - add_executable(${APPNAME} ${SRC}) - message("create executable about ${APPNAME}") - target_link_libraries(${APPNAME} c-api) + add_executable(${APPNAME} ${SRC} ${UNCOMMON_SHARED_SOURCE} ${MM_UTIL}) + target_include_directories(${APPNAME} PRIVATE ${UNCOMMON_SHARED_DIR}) + target_link_libraries(${APPNAME} vmlib -lpthread -lm) if (MSVC) target_compile_definitions(${APPNAME} PRIVATE WASM_API_EXTERN=) endif() +endforeach() - # copy .wasm - add_custom_command(TARGET ${APPNAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/src/${APPNAME}.wasm - ${PROJECT_BINARY_DIR}/ - BYPRODUCTS ${APPNAME}.wasm - COMMENT "Copy ${SRC} to the output directory" +# wat to wasm +file(GLOB WAT_FILES src/*.wat) +foreach(WAT_FILE ${WAT_FILES}) + get_filename_component(WATNAME ${WAT_FILE} NAME_WE) + + add_custom_target(${WATNAME}_WASM ALL + COMMAND ${WAT2WASM} ${WAT_FILE} -o ${PROJECT_BINARY_DIR}/${WATNAME}.wasm + DEPENDS ${WAT_FILE} + BYPRODUCTS ${PROJECT_BINARY_DIR}/${WATNAME}.wasm + VERBATIM + SOURCES ${WAT_FILE} ) - - # generate .aot file - if(${WAMR_BUILD_AOT} EQUAL 1) - if(EXISTS ${WAMRC}) - add_custom_command(TARGET ${APPNAME} POST_BUILD - COMMAND ${WAMRC} -o ${APPNAME}.aot - ${CMAKE_CURRENT_SOURCE_DIR}/src/${APPNAME}.wasm - BYPRODUCTS ${APPNAME}.aot - COMMENT "generate a aot file ${APPNAME}.aot" - ) - endif() - endif() - -endforeach(SRC ${SOURCES}) +endforeach() ################################################ diff --git a/samples/wasm-c-api/README.md b/samples/wasm-c-api/README.md index 31d2aea09..51b8642a2 100644 --- a/samples/wasm-c-api/README.md +++ b/samples/wasm-c-api/README.md @@ -1,5 +1,16 @@ -WAMR supports *wasm-c-api* in both *interpreter* mode and *aot* mode. By default, -all samples are compiled and run in "interpreter" mode. +WAMR supports *wasm-c-api* in both *interpreter* mode and *aot* mode. + +Before staring, we need to download and intall [WABT](https://github.com/WebAssembly/wabt/releases/latest). + +``` shell +$ cd /opt +$ wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-ubuntu.tar.gz +$ tar -xzf wabt-1.0.19-ubuntu.tar.gz +$ mv wabt-1.0.19 wabt +``` + +By default, all samples are compiled and run in "interpreter" mode. + ``` shell $ mkdir build diff --git a/samples/wasm-c-api/src/callback.c b/samples/wasm-c-api/src/callback.c index da3e7491e..52349c330 100644 --- a/samples/wasm-c-api/src/callback.c +++ b/samples/wasm-c-api/src/callback.c @@ -4,6 +4,14 @@ #include #include "wasm_c_api.h" +#include "wasm_export.h" +#include "bh_platform.h" + +extern bool +reader(const char *module_name, uint8 **p_buffer, uint32 *p_size); + +extern void +destroyer(uint8 *buffer, uint32 size); #define own @@ -61,6 +69,8 @@ own wasm_trap_t* closure_callback( int main(int argc, const char* argv[]) { + wasm_runtime_set_module_reader(reader, destroyer); + // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); diff --git a/samples/wasm-c-api/src/callback.wasm b/samples/wasm-c-api/src/callback.wasm deleted file mode 100644 index 7e00b580142c1e8171c18577fca06d1a39f2b48c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmW+sy9$6H6g~G!2(|bLewq;tNm*#lN=r*a1pRN?aNY-fSO@^!IcEq%iIPD9r{egn nEu-1|Lqn5QP-MFgPD&Y~ diff --git a/samples/wasm-c-api/src/global.c b/samples/wasm-c-api/src/global.c index ba73d95ed..a7b5c16af 100644 --- a/samples/wasm-c-api/src/global.c +++ b/samples/wasm-c-api/src/global.c @@ -4,6 +4,14 @@ #include #include "wasm_c_api.h" +#include "wasm_export.h" +#include "bh_platform.h" + +extern bool +reader(const char *module_name, uint8 **p_buffer, uint32 *p_size); + +extern void +destroyer(uint8 *buffer, uint32 size); #define own @@ -46,6 +54,8 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { int main(int argc, const char* argv[]) { + wasm_runtime_set_module_reader(reader, destroyer); + // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); diff --git a/samples/wasm-c-api/src/global.wasm b/samples/wasm-c-api/src/global.wasm deleted file mode 100644 index 0e76863278e62f064730544392e92c0194097134..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 576 zcmZXQO-{ow5JtbT6T7Whpo#-nYEMuq)~H-06)II1rKpK2HjbhSv17rS4Od{neYgaB zY$yJaP?YG+%lMl~u&(z6fZn^VLs5Z@z1xZmDr&*Ly~ga0h(esunAu4B6tx7PJ~E`E|BuF0*OHz%H|llY}Sd z7SvjF?mdh_gai%h%jL6lIOEopM_L z-(VDFw!t{cEOU}%nyx0l{#U=aCuUFsPyiNy2PguR0Ym_)UVV +#include +#include +#include + +#include "wasm_c_api.h" +#include "wasm_export.h" +#include "bh_platform.h" + +extern bool +reader(const char *module_name, uint8 **p_buffer, uint32 *p_size); + +extern void +destroyer(uint8 *buffer, uint32 size); + +#define own + +wasm_global_t* get_export_global(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_global(exports->data[i])) { + printf("> Error accessing global export %zu!\n", i); + exit(1); + } + return wasm_extern_as_global(exports->data[i]); +} + +wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) { + printf("> Error accessing function export %zu!\n", i); + exit(1); + } + return wasm_extern_as_func(exports->data[i]); +} + + +#define check(val, type, expected) \ + if (val.of.type != expected) { \ + printf("> Expected reading value %f or %d \n", expected, expected); \ + printf("> Error reading value %f or %d\n", val.of.type, val.of.type); \ + } + +#define check_global(global, type, expected) \ + { \ + wasm_val_t val; \ + wasm_global_get(global, &val); \ + check(val, type, expected); \ + } + +#define check_call(func, type, expected) \ + { \ + wasm_val_t results[1]; \ + wasm_func_call(func, NULL, results); \ + check(results[0], type, expected); \ + } + +wasm_module_t * create_module_from_file(wasm_store_t* store, const char * filename) +{ + FILE* file = fopen(filename, "rb"); + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + return 1; + } + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + wasm_byte_vec_delete(&binary); + fclose(file); + return module; +} + + +int main(int argc, const char* argv[]) { + wasm_runtime_set_module_reader(reader, destroyer); + + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0 + wasm_module_t* moduleimport = create_module_from_file(store, "globalimport.aot"); +#else + wasm_module_t* moduleimport = create_module_from_file(store, "globalexportimport-1.wasm"); +#endif + + // Instantiate. + printf("Instantiating Import module...\n"); + own wasm_instance_t* instance_import = + wasm_instance_new(store, moduleimport, NULL, NULL); //after this var_f32_export->inst_comm_rt is module_import + if (!instance_import) { + printf("> Error instantiating Import module!\n"); + return 1; + } + wasm_module_delete(moduleimport); + + // Extract export. + printf("Extracting exports from Import module...\n"); + own wasm_extern_vec_t exports_of_import; + wasm_instance_exports(instance_import, &exports_of_import); + int i = 0; + wasm_global_t *var_f32_export = get_export_global(&exports_of_import, i++); + wasm_func_t *get_var_f32_export = get_export_func(&exports_of_import, i++); + wasm_func_t* set_var_f32_export = get_export_func(&exports_of_import, i++); + wasm_func_t* get_var_f32_import = get_export_func(&exports_of_import, i++); + wasm_func_t* set_var_f32_import = get_export_func(&exports_of_import, i++); + + // Interact. + + // Check initial values. + printf("Check initial values...\n"); + check_global(var_f32_export, f32, 7.0); + check_call(get_var_f32_export, f32, 7.0); //Call to module export + check_call(get_var_f32_import, f32, 7.0); //Call to module import + + + // Modify variables through API and check again. + printf("Modify the variable to 37.0...\n"); + wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37.0}}; + wasm_global_set(var_f32_export, &val37); // var_f32_export->inst_comm_rt is module_import now + + check_global(var_f32_export, f32, 37.0); + check_call(get_var_f32_export, f32, 37.0); //Call to module export Failed here, still 7 + check_call(get_var_f32_import, f32, 37.0); //Call to module import + + // Modify variables through calls and check again. + printf("Modify the variable to 77.0...\n"); + wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77.}} }; + wasm_func_call(set_var_f32_export, args77, NULL); //Call to module export + check_call(get_var_f32_export, f32, 77.0); //Call to module export + check_global(var_f32_export, f32, 77.0); //Failed here, still 37 + check_call(get_var_f32_import, f32, 77.0); //Call to module import Failed here, still 37 + + + printf("Modify the variable to 78.0...\n"); + wasm_val_t args78[] = { {.kind = WASM_F32, .of = {.f32 = 78.0}} }; + wasm_func_call(set_var_f32_import, args78, NULL); + check_global(var_f32_export, f32, 78.0); + check_call(get_var_f32_export, f32, 78.0); //Call to module export Failed here, still 77 + check_call(get_var_f32_import, f32, 78.0); //Call to module import + + + // wasm_extern_vec_delete(&exports_of_export); + //wasm_instance_delete(instance_export); + wasm_extern_vec_delete(&exports_of_import); + //wasm_instance_delete(instance_import); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; + +} \ No newline at end of file diff --git a/samples/wasm-c-api/src/hello.c b/samples/wasm-c-api/src/hello.c index 491a24b3d..db8281c36 100644 --- a/samples/wasm-c-api/src/hello.c +++ b/samples/wasm-c-api/src/hello.c @@ -4,6 +4,14 @@ #include #include "wasm_c_api.h" +#include "wasm_export.h" +#include "bh_platform.h" + +extern bool +reader(const char *module_name, uint8 **p_buffer, uint32 *p_size); + +extern void +destroyer(uint8 *buffer, uint32 size); #define own @@ -18,6 +26,8 @@ own wasm_trap_t* hello_callback( int main(int argc, const char* argv[]) { + wasm_runtime_set_module_reader(reader, destroyer); + // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); diff --git a/samples/wasm-c-api/src/hello.wasm b/samples/wasm-c-api/src/hello.wasm deleted file mode 100644 index 2207c03eead3f45f13dfa58b73c6bce27716bffa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71 zcmZQbEY4+QU|?WuX=rF*U`$|OVCn+17+5n>b8_+-7?_(NeD-!Q&0JKP$H2%1Q3Te+ IAi%&40BKwiaR2}S diff --git a/samples/wasm-c-api/src/utils/multi_module_utils.c b/samples/wasm-c-api/src/utils/multi_module_utils.c new file mode 100644 index 000000000..67010914b --- /dev/null +++ b/samples/wasm-c-api/src/utils/multi_module_utils.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_read_file.h" +#include "wasm_export.h" + +static char * +build_module_path(const char *module_name) +{ + const char *module_search_path = "."; + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = BH_MALLOC(sz); + if (!wasm_file_name) { + return NULL; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + return wasm_file_name; +} + +bool +reader(const char *module_name, uint8 **p_buffer, uint32 *p_size) +{ + char *wasm_file_path = build_module_path(module_name); + if (!wasm_file_path) { + return false; + } + + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_path, p_size); + BH_FREE(wasm_file_path); + return *p_buffer != NULL; +} + +void +destroyer(uint8 *buffer, uint32 size) +{ + if (!buffer) { + return; + } + + BH_FREE(buffer); + buffer = NULL; +}