From 9d52960e4d097d2503d9cda7b36c1716dcec01da Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 7 Dec 2022 16:43:04 +0800 Subject: [PATCH 01/32] Fix wasm-c-api import func link issue in wasm_instance_new (#1787) When a wasm module is duplicated instantiated with wasm_instance_new, the function import info of the previous instantiation may be overwritten by the later instantiation, which may cause unexpected behavior. Store the function import info into the module instance to fix the issue. --- core/iwasm/aot/aot_runtime.c | 22 +++++- core/iwasm/aot/aot_runtime.h | 4 + core/iwasm/common/wasm_c_api.c | 80 ++++++++++++++++---- core/iwasm/interpreter/wasm.h | 1 - core/iwasm/interpreter/wasm_interp_classic.c | 11 ++- core/iwasm/interpreter/wasm_interp_fast.c | 11 ++- core/iwasm/interpreter/wasm_runtime.c | 11 ++- core/iwasm/interpreter/wasm_runtime.h | 12 +++ 8 files changed, 128 insertions(+), 24 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 1077c3af..133c5e38 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -987,7 +987,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, (uint64)module->memory_count * sizeof(AOTMemoryInstance); uint64 total_size, table_size = 0; uint8 *p; - uint32 i; + uint32 i, extra_info_offset; /* Check heap size */ heap_size = align_uint(heap_size, 8); @@ -1015,6 +1015,11 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, } total_size += table_size; + /* The offset of AOTModuleInstanceExtra, make it 8-byte aligned */ + total_size = (total_size + 7LL) & ~7LL; + extra_info_offset = (uint32)total_size; + total_size += sizeof(AOTModuleInstanceExtra); + /* Allocate module instance, global data, table data and heap data */ if (!(module_inst = runtime_malloc(total_size, error_buf, error_buf_size))) { @@ -1023,6 +1028,8 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, module_inst->module_type = Wasm_Module_AoT; module_inst->module = (void *)module; + module_inst->e = + (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); /* Initialize global info */ p = (uint8 *)module_inst + module_inst_struct_size @@ -1179,6 +1186,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (module_inst->exec_env_singleton) wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton); + if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports) + wasm_runtime_free( + ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports); + wasm_runtime_free(module_inst); } @@ -1750,6 +1761,10 @@ 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; + AOTModuleInstanceExtra *module_inst_extra = + (AOTModuleInstanceExtra *)module_inst->e; + CApiFuncImport *c_api_func_import = + module_inst_extra->c_api_func_imports + func_idx; uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 func_type_idx = func_type_indexes[func_idx]; AOTFuncType *func_type = aot_module->func_types[func_type_idx]; @@ -1764,6 +1779,9 @@ 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->func_ptr_linked; + if (!func_ptr) { snprintf(buf, sizeof(buf), "failed to call unlinked import function (%s, %s)", @@ -1776,7 +1794,7 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, if (import_func->call_conv_wasm_c_api) { ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, - argv, import_func->wasm_c_api_with_env, attachment); + 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; diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index d02af3cb..a6371729 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -73,6 +73,10 @@ typedef struct AOTFunctionInstance { } u; } AOTFunctionInstance; +typedef struct AOTModuleInstanceExtra { + CApiFuncImport *c_api_func_imports; +} AOTModuleInstanceExtra; + #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) /* clang-format off */ typedef struct AOTUnwindInfo { diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index f6212d5d..619e0229 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -4282,15 +4282,13 @@ 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; - imported_func_interp->u.function.wasm_c_api_with_env = import->with_env; - if (import->with_env) { + /* 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 */ + if (import->with_env) imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb; - imported_func_interp->u.function.attachment = import->u.cb_env.env; - } - else { + else imported_func_interp->u.function.func_ptr_linked = import->u.cb; - imported_func_interp->u.function.attachment = NULL; - } import->func_idx_rt = func_idx_rt; return true; @@ -4496,15 +4494,13 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot, return false; import_aot_func->call_conv_wasm_c_api = true; - import_aot_func->wasm_c_api_with_env = import->with_env; - if (import->with_env) { + /* 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 */ + if (import->with_env) import_aot_func->func_ptr_linked = import->u.cb_env.cb; - import_aot_func->attachment = import->u.cb_env.env; - } - else { + else import_aot_func->func_ptr_linked = import->u.cb; - import_aot_func->attachment = NULL; - } import->func_idx_rt = import_func_idx_rt; return true; @@ -4718,10 +4714,12 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, { char sub_error_buf[128] = { 0 }; char error_buf[256] = { 0 }; - uint32 import_count = 0; bool import_count_verified = false; wasm_instance_t *instance = NULL; - uint32 i = 0; + WASMModuleInstance *inst_rt; + CApiFuncImport *func_import = NULL, **p_func_imports = NULL; + uint32 i = 0, import_count = 0, import_func_count = 0; + uint64 total_size; bool processed = false; bh_assert(singleton_engine); @@ -4804,6 +4802,56 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } + inst_rt = (WASMModuleInstance *)instance->inst_comm_rt; +#if WASM_ENABLE_INTERP != 0 + if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { + p_func_imports = &inst_rt->e->c_api_func_imports; + import_func_count = inst_rt->module->import_function_count; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) { + p_func_imports = + &((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports; + import_func_count = ((AOTModule *)inst_rt->module)->import_func_count; + } +#endif + bh_assert(p_func_imports); + + /* create the c-api func import list */ + total_size = (uint64)sizeof(CApiFuncImport) * import_func_count; + if (total_size > 0 + && !(*p_func_imports = func_import = malloc_internal(total_size))) { + snprintf(sub_error_buf, sizeof(sub_error_buf), + "Failed to create wasm-c-api func imports"); + goto failed; + } + + /* fill in c-api func import list */ + for (i = 0; i < import_count; i++) { + wasm_func_t *func_host; + wasm_extern_t *in; + + in = imports->data[i]; + if (wasm_extern_kind(in) != WASM_EXTERN_FUNC) + continue; + + func_host = wasm_extern_as_func(in); + + func_import->with_env_arg = func_host->with_env; + if (func_host->with_env) { + func_import->func_ptr_linked = func_host->u.cb_env.cb; + func_import->env_arg = func_host->u.cb_env.env; + } + else { + func_import->func_ptr_linked = func_host->u.cb; + func_import->env_arg = NULL; + } + + func_import++; + } + bh_assert((uint32)(func_import - *p_func_imports) == import_func_count); + /* fill with inst */ for (i = 0; imports && imports->data && i < (uint32)import_count; ++i) { wasm_extern_t *import = imports->data[i]; diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 9c6a2ce3..58305a7f 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -189,7 +189,6 @@ typedef struct WASMFunctionImport { WASMFunction *import_func_linked; #endif bool call_conv_wasm_c_api; - bool wasm_c_api_with_env; } WASMFunctionImport; typedef struct WASMGlobalImport { diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 45ef4d56..39c23f9f 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -838,6 +838,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, WASMInterpFrame *prev_frame) { WASMFunctionImport *func_import = cur_func->u.func_import; + CApiFuncImport *c_api_func_import = NULL; unsigned local_cell_num = 2; WASMInterpFrame *frame; uint32 argv_ret[2], cur_func_index; @@ -858,7 +859,13 @@ 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); - native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; + if (!func_import->call_conv_wasm_c_api) { + native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; + } + else { + c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; + native_func_pointer = c_api_func_import->func_ptr_linked; + } if (!native_func_pointer) { snprintf(buf, sizeof(buf), @@ -872,7 +879,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, native_func_pointer, func_import->func_type, cur_func->param_cell_num, frame->lp, - func_import->wasm_c_api_with_env, func_import->attachment); + c_api_func_import->with_env_arg, c_api_func_import->env_arg); if (ret) { argv_ret[0] = frame->lp[0]; argv_ret[1] = frame->lp[1]; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index df356d56..3109b0c8 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -902,6 +902,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, WASMInterpFrame *prev_frame) { WASMFunctionImport *func_import = cur_func->u.func_import; + CApiFuncImport *c_api_func_import = NULL; unsigned local_cell_num = 2; WASMInterpFrame *frame; uint32 argv_ret[2], cur_func_index; @@ -921,7 +922,13 @@ 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); - native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; + if (!func_import->call_conv_wasm_c_api) { + native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; + } + else { + c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; + native_func_pointer = c_api_func_import->func_ptr_linked; + } if (!native_func_pointer) { char buf[128]; @@ -936,7 +943,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, native_func_pointer, func_import->func_type, cur_func->param_cell_num, frame->lp, - func_import->wasm_c_api_with_env, func_import->attachment); + c_api_func_import->with_env_arg, c_api_func_import->env_arg); if (ret) { argv_ret[0] = frame->lp[0]; argv_ret[1] = frame->lp[1]; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 8e8f96b5..080a0eea 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1948,6 +1948,9 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) os_mutex_destroy(&module_inst->e->mem_lock); #endif + if (module_inst->e->c_api_func_imports) + wasm_runtime_free(module_inst->e->c_api_func_imports); + wasm_runtime_free(module_inst); } @@ -2849,6 +2852,7 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, WASMType *func_type; void *func_ptr; WASMFunctionImport *import_func; + CApiFuncImport *c_api_func_import = NULL; const char *signature; void *attachment; char buf[96]; @@ -2870,6 +2874,11 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, 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) { + c_api_func_import = module_inst->e->c_api_func_imports + func_idx; + func_ptr = c_api_func_import->func_ptr_linked; + } + if (!func_ptr) { snprintf(buf, sizeof(buf), "failed to call unlinked import function (%s, %s)", @@ -2882,7 +2891,7 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, if (import_func->call_conv_wasm_c_api) { ret = wasm_runtime_invoke_c_api_native( (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, - argv, import_func->wasm_c_api_with_env, attachment); + 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; diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 3146b18f..1ebac5f3 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -192,6 +192,16 @@ typedef struct WASMExportMemInstance { WASMMemoryInstance *memory; } WASMExportMemInstance; +/* 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; + /* Extra info of WASM module instance for interpreter/jit mode */ typedef struct WASMModuleInstanceExtra { WASMGlobalInstance *globals; @@ -205,6 +215,8 @@ typedef struct WASMModuleInstanceExtra { WASMFunctionInstance *free_function; WASMFunctionInstance *retain_function; + CApiFuncImport *c_api_func_imports; + #if WASM_ENABLE_SHARED_MEMORY != 0 /* lock for shared memory atomic operations */ korp_mutex mem_lock; From c3d66f916ef8093e5c8cacf3329ed968f807cf58 Mon Sep 17 00:00:00 2001 From: Callum Macmillan Date: Wed, 7 Dec 2022 09:18:28 +0000 Subject: [PATCH 02/32] Add memory watchpoint support for source debugger (#1762) Allow to add watchpoints to variables for source debugging. For instance: `breakpoint set variable var` will pause WAMR execution when the address at var is written to. Can also set read/write watchpoints by passing r/w flags. This will pause execution when the address at var is read: `watchpoint set variable -w read var` Add two linked lists for read/write watchpoints. When the debug message handler receives a watchpoint request, it adds/removes to one/both of these lists. In the interpreter, when an address is read or stored to, check whether the address is in these lists. If so, throw a sigtrap and suspend the process. --- core/iwasm/interpreter/wasm_interp_classic.c | 49 ++++++- .../libraries/debug-engine/debug_engine.c | 82 +++++++++++ .../libraries/debug-engine/debug_engine.h | 24 ++++ core/iwasm/libraries/debug-engine/handler.c | 135 ++++++++++++++---- 4 files changed, 265 insertions(+), 25 deletions(-) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 39c23f9f..aa15b41a 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -70,6 +70,35 @@ typedef float64 CellType_F64; goto unaligned_atomic; \ } while (0) +#if WASM_ENABLE_DEBUG_INTERP != 0 +#define TRIGGER_WATCHPOINT_SIGTRAP() \ + do { \ + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); \ + CHECK_SUSPEND_FLAGS(); \ + } while (0) + +#define CHECK_WATCHPOINT(list, current_addr) \ + do { \ + WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list); \ + while (watchpoint) { \ + WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint); \ + if (watchpoint->addr <= current_addr \ + && watchpoint->addr + watchpoint->length > current_addr) { \ + TRIGGER_WATCHPOINT_SIGTRAP(); \ + } \ + watchpoint = next; \ + } \ + } while (0) + +#define CHECK_READ_WATCHPOINT(addr, offset) \ + CHECK_WATCHPOINT(watch_point_list_read, WASM_ADDR_OFFSET(addr + offset)) +#define CHECK_WRITE_WATCHPOINT(addr, offset) \ + CHECK_WATCHPOINT(watch_point_list_write, WASM_ADDR_OFFSET(addr + offset)) +#else +#define CHECK_READ_WATCHPOINT(addr, offset) +#define CHECK_WRITE_WATCHPOINT(addr, offset) +#endif + static inline uint32 rotl32(uint32 n, uint32 c) { @@ -1127,6 +1156,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; + WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env); + bh_list *watch_point_list_read = &debug_instance->watch_point_list_read; + bh_list *watch_point_list_write = &debug_instance->watch_point_list_write; #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 @@ -1792,6 +1824,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(4); PUSH_I32(LOAD_I32(maddr)); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1806,6 +1839,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(8); PUSH_I64(LOAD_I64(maddr)); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1819,6 +1853,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(1); PUSH_I32(sign_ext_8_32(*(int8 *)maddr)); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1832,6 +1867,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(1); PUSH_I32((uint32)(*(uint8 *)maddr)); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1845,6 +1881,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(2); PUSH_I32(sign_ext_16_32(LOAD_I16(maddr))); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1858,6 +1895,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(2); PUSH_I32((uint32)(LOAD_U16(maddr))); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1871,6 +1909,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(1); PUSH_I64(sign_ext_8_64(*(int8 *)maddr)); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1884,6 +1923,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(1); PUSH_I64((uint64)(*(uint8 *)maddr)); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1897,6 +1937,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(2); PUSH_I64(sign_ext_16_64(LOAD_I16(maddr))); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1910,6 +1951,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(2); PUSH_I64((uint64)(LOAD_U16(maddr))); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1924,6 +1966,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(4); PUSH_I64(sign_ext_32_64(LOAD_I32(maddr))); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1937,6 +1980,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(4); PUSH_I64((uint64)(LOAD_U32(maddr))); + CHECK_READ_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1953,6 +1997,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); CHECK_MEMORY_OVERFLOW(4); STORE_U32(maddr, frame_sp[1]); + CHECK_WRITE_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1969,6 +2014,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_MEMORY_OVERFLOW(8); PUT_I64_TO_ADDR((uint32 *)maddr, GET_I64_FROM_ADDR(frame_sp + 1)); + CHECK_WRITE_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -1993,7 +2039,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_MEMORY_OVERFLOW(2); STORE_U16(maddr, (uint16)sval); } - + CHECK_WRITE_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } @@ -2023,6 +2069,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_MEMORY_OVERFLOW(4); STORE_U32(maddr, (uint32)sval); } + CHECK_WRITE_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); } diff --git a/core/iwasm/libraries/debug-engine/debug_engine.c b/core/iwasm/libraries/debug-engine/debug_engine.c index 61b29da8..1b3db1d4 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.c +++ b/core/iwasm/libraries/debug-engine/debug_engine.c @@ -392,6 +392,8 @@ wasm_debug_instance_create(WASMCluster *cluster, int32 port) } bh_list_init(&instance->break_point_list); + bh_list_init(&instance->watch_point_list_read); + bh_list_init(&instance->watch_point_list_write); instance->cluster = cluster; exec_env = bh_list_first_elem(&cluster->exec_env_list); @@ -452,6 +454,23 @@ wasm_debug_instance_destroy_breakpoints(WASMDebugInstance *instance) } } +static void +wasm_debug_instance_destroy_watchpoints(WASMDebugInstance *instance, + bh_list *watchpoints) +{ + WASMDebugWatchPoint *watchpoint, *next; + + watchpoint = bh_list_first_elem(watchpoints); + while (watchpoint) { + next = bh_list_elem_next(watchpoint); + + bh_list_remove(watchpoints, watchpoint); + wasm_runtime_free(watchpoint); + + watchpoint = next; + } +} + void wasm_debug_instance_destroy(WASMCluster *cluster) { @@ -472,6 +491,10 @@ wasm_debug_instance_destroy(WASMCluster *cluster) /* destroy all breakpoints */ wasm_debug_instance_destroy_breakpoints(instance); + wasm_debug_instance_destroy_watchpoints( + instance, &instance->watch_point_list_read); + wasm_debug_instance_destroy_watchpoints( + instance, &instance->watch_point_list_write); os_mutex_destroy(&instance->wait_lock); os_cond_destroy(&instance->wait_cond); @@ -995,6 +1018,65 @@ wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr, return true; } +static bool +add_watchpoint(bh_list *list, uint64 addr, uint64 length) +{ + WASMDebugWatchPoint *watchpoint; + if (!(watchpoint = wasm_runtime_malloc(sizeof(WASMDebugWatchPoint)))) { + LOG_ERROR("WASM Debug Engine error: failed to allocate memory for " + "watchpoint"); + return false; + } + memset(watchpoint, 0, sizeof(WASMDebugWatchPoint)); + watchpoint->addr = addr; + watchpoint->length = length; + bh_list_insert(list, watchpoint); + return true; +} + +static bool +remove_watchpoint(bh_list *list, uint64 addr, uint64 length) +{ + WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list); + while (watchpoint) { + WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint); + if (watchpoint->addr == addr && watchpoint->length == length) { + bh_list_remove(list, watchpoint); + wasm_runtime_free(watchpoint); + } + watchpoint = next; + } + return true; +} + +bool +wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance, + uint64 addr, uint64 length) +{ + return add_watchpoint(&instance->watch_point_list_write, addr, length); +} + +bool +wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance, + uint64 addr, uint64 length) +{ + return remove_watchpoint(&instance->watch_point_list_write, addr, length); +} + +bool +wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance, + uint64 addr, uint64 length) +{ + return add_watchpoint(&instance->watch_point_list_read, addr, length); +} + +bool +wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance, + uint64 addr, uint64 length) +{ + return remove_watchpoint(&instance->watch_point_list_read, addr, length); +} + bool wasm_debug_instance_on_failure(WASMDebugInstance *instance) { diff --git a/core/iwasm/libraries/debug-engine/debug_engine.h b/core/iwasm/libraries/debug-engine/debug_engine.h index f7580a7b..e12f827b 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.h +++ b/core/iwasm/libraries/debug-engine/debug_engine.h @@ -36,6 +36,12 @@ typedef struct WASMDebugBreakPoint { uint64 orignal_data; } WASMDebugBreakPoint; +typedef struct WASMDebugWatchPoint { + bh_list_link next; + uint64 addr; + uint64 length; +} WASMDebugWatchPoint; + typedef enum debug_state_t { /* Debugger state conversion sequence: * DBG_LAUNCHING ---> APP_STOPPED <---> APP_RUNNING @@ -56,6 +62,8 @@ struct WASMDebugInstance { struct WASMDebugInstance *next; WASMDebugControlThread *control_thread; bh_list break_point_list; + bh_list watch_point_list_read; + bh_list watch_point_list_write; WASMCluster *cluster; uint32 id; korp_tid current_tid; @@ -184,6 +192,22 @@ bool wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr, uint64 length); +bool +wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance, + uint64 addr, uint64 length); + +bool +wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance, + uint64 addr, uint64 length); + +bool +wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance, + uint64 addr, uint64 length); + +bool +wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance, + uint64 addr, uint64 length); + bool wasm_debug_instance_on_failure(WASMDebugInstance *instance); diff --git a/core/iwasm/libraries/debug-engine/handler.c b/core/iwasm/libraries/debug-engine/handler.c index 701dd0c0..cf1a87c5 100644 --- a/core/iwasm/libraries/debug-engine/handler.c +++ b/core/iwasm/libraries/debug-engine/handler.c @@ -358,6 +358,14 @@ handle_general_query(WASMGDBServer *server, char *payload) send_thread_stop_status(server, status, tid); } + + if (!strcmp(name, "WatchpointSupportInfo")) { + os_mutex_lock(&tmpbuf_lock); + // Any uint32 is OK for the watchpoint support + snprintf(tmpbuf, MAX_PACKET_SIZE, "num:32;"); + write_packet(server, tmpbuf); + os_mutex_unlock(&tmpbuf_lock); + } } void @@ -643,46 +651,125 @@ handle_get_write_memory(WASMGDBServer *server, char *payload) os_mutex_unlock(&tmpbuf_lock); } +void +handle_breakpoint_software_add(WASMGDBServer *server, uint64 addr, + size_t length) +{ + bool ret = wasm_debug_instance_add_breakpoint( + (WASMDebugInstance *)server->thread->debug_instance, addr, length); + write_packet(server, ret ? "OK" : "EO1"); +} + +void +handle_breakpoint_software_remove(WASMGDBServer *server, uint64 addr, + size_t length) +{ + bool ret = wasm_debug_instance_remove_breakpoint( + (WASMDebugInstance *)server->thread->debug_instance, addr, length); + write_packet(server, ret ? "OK" : "EO1"); +} + +void +handle_watchpoint_write_add(WASMGDBServer *server, uint64 addr, size_t length) +{ + bool ret = wasm_debug_instance_watchpoint_write_add( + (WASMDebugInstance *)server->thread->debug_instance, addr, length); + write_packet(server, ret ? "OK" : "EO1"); +} + +void +handle_watchpoint_write_remove(WASMGDBServer *server, uint64 addr, + size_t length) +{ + bool ret = wasm_debug_instance_watchpoint_write_remove( + (WASMDebugInstance *)server->thread->debug_instance, addr, length); + write_packet(server, ret ? "OK" : "EO1"); +} + +void +handle_watchpoint_read_add(WASMGDBServer *server, uint64 addr, size_t length) +{ + bool ret = wasm_debug_instance_watchpoint_read_add( + (WASMDebugInstance *)server->thread->debug_instance, addr, length); + write_packet(server, ret ? "OK" : "EO1"); +} + +void +handle_watchpoint_read_remove(WASMGDBServer *server, uint64 addr, size_t length) +{ + bool ret = wasm_debug_instance_watchpoint_read_remove( + (WASMDebugInstance *)server->thread->debug_instance, addr, length); + write_packet(server, ret ? "OK" : "EO1"); +} + void handle_add_break(WASMGDBServer *server, char *payload) { + int arg_c; size_t type, length; uint64 addr; - if (sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length) == 3) { - if (type == eBreakpointSoftware) { - bool ret = wasm_debug_instance_add_breakpoint( - (WASMDebugInstance *)server->thread->debug_instance, addr, - length); - if (ret) - write_packet(server, "OK"); - else - write_packet(server, "E01"); - return; - } + if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length)) + != 3) { + LOG_ERROR("Unsupported number of add break arguments %d", arg_c); + write_packet(server, ""); + return; + } + + switch (type) { + case eBreakpointSoftware: + handle_breakpoint_software_add(server, addr, length); + break; + case eWatchpointWrite: + handle_watchpoint_write_add(server, addr, length); + break; + case eWatchpointRead: + handle_watchpoint_read_add(server, addr, length); + break; + case eWatchpointReadWrite: + handle_watchpoint_write_add(server, addr, length); + handle_watchpoint_read_add(server, addr, length); + break; + default: + LOG_ERROR("Unsupported breakpoint type %d", type); + write_packet(server, ""); + break; } - write_packet(server, ""); } void handle_remove_break(WASMGDBServer *server, char *payload) { + int arg_c; size_t type, length; uint64 addr; - if (sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length) == 3) { - if (type == eBreakpointSoftware) { - bool ret = wasm_debug_instance_remove_breakpoint( - (WASMDebugInstance *)server->thread->debug_instance, addr, - length); - if (ret) - write_packet(server, "OK"); - else - write_packet(server, "E01"); - return; - } + if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length)) + != 3) { + LOG_ERROR("Unsupported number of remove break arguments %d", arg_c); + write_packet(server, ""); + return; + } + + switch (type) { + case eBreakpointSoftware: + handle_breakpoint_software_remove(server, addr, length); + break; + case eWatchpointWrite: + handle_watchpoint_write_remove(server, addr, length); + break; + case eWatchpointRead: + handle_watchpoint_read_remove(server, addr, length); + break; + case eWatchpointReadWrite: + handle_watchpoint_write_remove(server, addr, length); + handle_watchpoint_read_remove(server, addr, length); + break; + default: + LOG_ERROR("Unsupported breakpoint type %d", type); + write_packet(server, ""); + break; } - write_packet(server, ""); } void From f6bef1e6047975253e040d426e73f6dc4290c856 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 8 Dec 2022 09:38:20 +0800 Subject: [PATCH 03/32] Implement i32.rem_s and i32.rem_u intrinsic (#1789) --- core/iwasm/aot/aot_intrinsic.c | 17 +++++++++ core/iwasm/aot/aot_intrinsic.h | 8 ++++ core/iwasm/aot/aot_reloc.h | 2 + core/iwasm/compilation/aot_emit_numberic.c | 43 +++++++++++++--------- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 7ac4b474..5d27fc9e 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -69,6 +69,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST }, { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S}, { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U}, + { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S}, + { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U}, { "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U}, { "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S}, { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U}, @@ -508,6 +510,18 @@ aot_intrinsic_i32_div_u(uint32 l, uint32 r) return l / r; } +int32 +aot_intrinsic_i32_rem_s(int32 l, int32 r) +{ + return l % r; +} + +uint32 +aot_intrinsic_i32_rem_u(uint32 l, uint32 r) +{ + return l % r; +} + uint64 aot_intrinsic_i64_div_u(uint64 l, uint64 r) { @@ -580,6 +594,8 @@ static void add_i32_common_intrinsics(AOTCompContext *comp_ctx) { add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_U); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_S); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_U); } static void @@ -675,6 +691,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) return; if (!strncmp(comp_ctx->target_arch, "thumb", 5)) { + add_i32_common_intrinsics(comp_ctx); if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) { } else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) { diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h index ae66037f..553d6724 100644 --- a/core/iwasm/aot/aot_intrinsic.h +++ b/core/iwasm/aot/aot_intrinsic.h @@ -60,6 +60,8 @@ extern "C" { #define AOT_INTRINSIC_FLAG_F32_CONST AOT_INTRINSIC_FLAG(0, 26) #define AOT_INTRINSIC_FLAG_I32_CONST AOT_INTRINSIC_FLAG(0, 27) #define AOT_INTRINSIC_FLAG_I32_DIV_U AOT_INTRINSIC_FLAG(0, 28) +#define AOT_INTRINSIC_FLAG_I32_REM_S AOT_INTRINSIC_FLAG(0, 29) +#define AOT_INTRINSIC_FLAG_I32_REM_U AOT_INTRINSIC_FLAG(0, 30) #define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0) #define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1) @@ -260,6 +262,12 @@ aot_intrinsic_i64_div_s(int64 l, int64 r); uint32 aot_intrinsic_i32_div_u(uint32 l, uint32 r); +int32 +aot_intrinsic_i32_rem_s(int32 l, int32 r); + +uint32 +aot_intrinsic_i32_rem_u(uint32 l, uint32 r); + uint64 aot_intrinsic_i64_div_u(uint64 l, uint64 r); diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 1ae52302..41f83bb6 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -115,6 +115,8 @@ typedef struct { REG_SYM(aot_intrinsic_i64_bit_or), \ REG_SYM(aot_intrinsic_i64_bit_and), \ REG_SYM(aot_intrinsic_i32_div_u), \ + REG_SYM(aot_intrinsic_i32_rem_s), \ + REG_SYM(aot_intrinsic_i32_rem_u), \ #define REG_COMMON_SYMBOLS \ REG_SYM(aot_set_exception_with_id), \ diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index d9bfca51..396fc0e9 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -31,7 +31,7 @@ #define LLVM_BUILD_OP_OR_INTRINSIC(Op, left, right, res, intrinsic, name, \ err_ret) \ do { \ - if (comp_ctx->disable_llvm_intrinsics && !is_i32 \ + if (comp_ctx->disable_llvm_intrinsics \ && aot_intrinsic_check_capability(comp_ctx, intrinsic)) { \ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, \ param_types[0], param_types, 2, \ @@ -234,8 +234,6 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, nan = LLVMConstRealOfString(ret_type, "NaN"); char *intrinsic = is_min ? (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64") : (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64"); - bool is_i32 = is_f32; - CHECK_LLVM_CONST(nan); param_types[0] = param_types[1] = ret_type; @@ -292,11 +290,13 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (is_min) - LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, "i64.or", - "tmp_int", false); + LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, + is_f32 ? "i32.or" : "i64.or", "tmp_int", + false); else - LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, "i64.and", - "tmp_int", false); + LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, + is_f32 ? "i32.and" : "i64.and", "tmp_int", + false); if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) { aot_set_last_error("llvm build bitcast fail."); @@ -402,7 +402,8 @@ compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMPositionBuilderAtEnd(comp_ctx->builder, no_overflow_block); LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, no_overflow_value, - "i64.rem_s", "rem_s", false); + is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", + false); /* Jump to rems_end block */ if (!LLVMBuildBr(comp_ctx->builder, rems_end_block)) { @@ -516,20 +517,24 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Build div */ switch (arith_op) { case INT_DIV_S: - LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, - "i64.div_s", "div_s", false); + LLVM_BUILD_OP_OR_INTRINSIC( + SDiv, left, right, res, + is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false); break; case INT_DIV_U: - LLVM_BUILD_OP_OR_INTRINSIC(UDiv, left, right, res, - "i64.div_u", "div_u", false); + LLVM_BUILD_OP_OR_INTRINSIC( + UDiv, left, right, res, + is_i32 ? "i32.div_u" : "i64.div_u", "div_u", false); break; case INT_REM_S: - LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, res, - "i64.rem_s", "rem_s", false); + LLVM_BUILD_OP_OR_INTRINSIC( + SRem, left, right, res, + is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", false); break; case INT_REM_U: - LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, - "i64.rem_u", "rem_u", false); + LLVM_BUILD_OP_OR_INTRINSIC( + URem, left, right, res, + is_i32 ? "i32.rem_u" : "i64.rem_u", "rem_u", false); break; default: bh_assert(0); @@ -568,7 +573,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, check_overflow_succ))) goto fail; - LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, "i64.div_s", + LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, + is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false); PUSH_INT(res); return true; @@ -594,7 +600,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return compile_rems(comp_ctx, func_ctx, left, right, overflow, is_i32); case INT_REM_U: - LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, "i64.rem_u", + LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, + is_i32 ? "i32.rem_u" : "i64.rem_u", "rem_u", false); PUSH_INT(res); return true; From 0d9e527fa06776d2da57a6822bf443cf9580a7c9 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 8 Dec 2022 12:21:34 +0800 Subject: [PATCH 04/32] Upgrade version number to 1.1.2 (#1788) Upgrade version number to 1.1.2, update RELEASE_NOTES.md and clear several compile warnings. --- RELEASE_NOTES.md | 109 +++++++++++++++++++ core/iwasm/interpreter/wasm_interp_classic.c | 4 +- core/shared/utils/bh_log.c | 4 +- core/version.h | 2 +- 4 files changed, 114 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 86cdbf6a..faba18c8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -12,6 +12,115 @@ --- +## WAMR-1.1.2 + +### Breaking Changes +Remove the LLVM MCJIT mode, replace it with LLVM ORC JIT eager mode +Add option to pass user data to the allocator functions of RuntimeInitArgs +Change how iwasm returns: + return 1 if an exception was thrown, else + return the wasi exit code if the wasm app is a wasi app, else + keep the same behavior as before +Enable bulk memory by default + +### New Features +Add control for the native stack check with hardware trap +Add memory watchpoint support to debugger +Add wasm_module_obtain() to clone wasm_module_t +Implement Fast JIT dump call stack and perf profiling +esp-idf: Add socket support for esp-idf platform + +### Bug Fixes +Fix XIP issue caused by rem_s on RISC-V +Fix XIP issues of fp to int cast and int rem/div +Fix missing float cmp for XIP +Correct the arch name for armv7a on NuttX +Fix issue of restoring wasm operand stack +Fix issue of thumb relocation R_ARM_THM_MOVT_ABS +Fix fast jit issue of translating opcode i32.rem_s/i64.rem_s +Fix interp/fast-jit float min/max issues +Fix missing intrinsics for risc-v which were reported by spec test +wasm-c-api: Fix init/destroy thread env multiple times issue +Fix wasm-c-api import func link issue in wasm_instance_new +Fix sample ref-types/wasm-c-api build error with wat2wasm low version +Fix zephyr sample build errors +Fix source debugger error handling: continue executing when detached +Fix scenario where the timeout for atomic wait is set to negative number + +### Enhancements +Refactor the layout of interpreter and AOT module instance +Refactor LLVM JIT: remove mcjit and legacy pass manager, upgrade to ORCv2 JIT +Refine Fast JIT call indirect and call native process +Refine Fast JIT accessing memory/table instance and global data +Refine AOT exception check when function return +Enable source debugger reconnection +Add wasm_runtime_get_wasi_exit_code +linux-sgx: Use non-destructive modes for opening files using SGX IPFS +Add wasm_runtime_unregister_natives +Implement invokeNative asm code for MinGW +Add wamr Blog link and Gitbook link to readme +Remove unnecessary app heap memory clean operations to reduce process RSS +Normalize how the global heap pool is configured across iwasm apps +Refine the stack frame size check in interpreter +Enlarge the default wasm operand stack size to 64KB +Use cmake POSITION_INDEPENDENT_CODE instead of hardcoding -pie -fPIE +Implement R_ARM_THM_MOVT_[ABS|REPL] for thumb +Suppress the warnings when building with GCC11 +samples/native-lib: Add a bit more complicated example +Add mutex initializer for wasm-c-api engine operations +XIP adaptation for xtensa platform +Update libuv version number +Remove an improper assumption when creating wasm_trap +Avoid initialize LLVM repeatedly +linux-sgx: Improve the remote attestation +linux-sgx: Improve the documentation of SGX-RA sample +linux-sgx: Allow to open files with arbitrary paths in the sandbox using IPFS +Avoid raising exception when debugging with VSCode +wamr-test-suites: Update runtest.py to support python3 +Enable Nuttx spec test option and register aot symbols +Use wabt binary instead of building from source in spec test +nuttx: Enable ref types by Kconfig +Update xtensa LLVM version to 15.x +Add bh_print_proc_mem() to dump memory info of current process +Create trap for error message when wasm_instance_new fails +wamr-test-suites: Add support for ARM/RISCV by QEMU +Enable to compile WAMR on platforms that don't support IPV6 +Fix warnings in the posix socket implementation +Update document for MacOS compilation +Install patched LLDB on vscode extension activation +Add ARM aeabi memcpy/memmove/memset symbols for AOT bulk memory ops + +### Others +Add CIs to release new version and publish binary files +Add more compilation groups of fast jit into CI +Enable spec test on nuttx and daily run it + +--- + +## WAMR-1.1.1 + +- Implement Linux SGX socket API getpeername, recvfrom and sendto +- Implement Linux SGX POSIX calls based on getsockname and set/getbool +- Integrate WASI-NN into WAMR: support TensorFlow/CPU/F32 in the first stage +- Add timeout send/recv and multicast client/server socket examples +- Support cross building and linking LLVM shared libs for wamrc +- Add darwin support for app_framework +- Add ios support for product-mini +- Update export_native_api.md: Relax the "ground rule" +- wasm_export.h: Add comments on wasm_runtime_register_natives +- Remove unused wasm_runtime_is_module_registered +- samples/multi-module: Examine module registration a bit +- samples/native-lib: Fix exec_env type +- Fix Linux SGX directional OCALL parameter for getsockname +- Fix threads issue to enable running threads spec proposal test cases +- Fix the "register native with iwasm" stuff for macOS +- Fix issues in assemblyscript lib +- Wrap wasi_socket_ext api with extern "C" to fix link failure with cxx project +- Fix invalid size of memory allocated in wasi init +- posix_thread.c: Avoid sem_getvalue deprecation warning on macOS + +--- + ## WAMR-1.1.0 - Extend support for Socket API: diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index aa15b41a..54fcf8d0 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -95,8 +95,8 @@ typedef float64 CellType_F64; #define CHECK_WRITE_WATCHPOINT(addr, offset) \ CHECK_WATCHPOINT(watch_point_list_write, WASM_ADDR_OFFSET(addr + offset)) #else -#define CHECK_READ_WATCHPOINT(addr, offset) -#define CHECK_WRITE_WATCHPOINT(addr, offset) +#define CHECK_READ_WATCHPOINT(addr, offset) (void)0 +#define CHECK_WRITE_WATCHPOINT(addr, offset) (void)0 #endif static inline uint32 diff --git a/core/shared/utils/bh_log.c b/core/shared/utils/bh_log.c index 03dde492..78c05806 100644 --- a/core/shared/utils/bh_log.c +++ b/core/shared/utils/bh_log.c @@ -103,5 +103,5 @@ bh_log_proc_mem(const char *function, uint32 line) { char prompt[128] = { 0 }; snprintf(prompt, sizeof(prompt), "[MEM] %s(...) L%" PRIu32, function, line); - return bh_print_proc_mem(prompt); -} \ No newline at end of file + bh_print_proc_mem(prompt); +} diff --git a/core/version.h b/core/version.h index 4a528c42..9834dae1 100644 --- a/core/version.h +++ b/core/version.h @@ -7,5 +7,5 @@ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 1 #define WAMR_VERSION_MINOR 1 -#define WAMR_VERSION_PATCH 1 +#define WAMR_VERSION_PATCH 2 #endif From 49be7cbbcb5706a842bd6768d40dc29704eb0254 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 8 Dec 2022 15:39:55 +0800 Subject: [PATCH 05/32] Fix link cpp object file error (#1791) Error was reported when building docker image: /usr/bin/ld: libaotclib.a(aot_llvm_extra.cpp.o): relocation R_X86_64_32S against symbol `_ZN4llvm30TargetTransformInfoWrapperPass2IDE' can not be used when making a PIE object; recompile with -fPIC Add `-fPIC` to `CMAKE_CXX_FLAGS` and `CMAKE_SHARED_LIBRARY_LINK_C_FLAGS` to fix it. --- build-scripts/config_common.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 6b7c0cd7..008d7f47 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -57,7 +57,9 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") + set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -fPIC") endif () else () include(CheckCCompilerFlag) From aa6a7a206928207ba04012eb19367c7c8cc2084b Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 8 Dec 2022 18:14:02 +0800 Subject: [PATCH 06/32] Fix link cxx object file error when building wamrc (#1794) --- wamr-compiler/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 53db4a6d..75c85a77 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -109,7 +109,9 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") + set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -fPIC") endif () else () add_definitions (-m32) From 14492757f87511eca405f386a4c71a624fb44f5d Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Thu, 8 Dec 2022 20:09:49 +0800 Subject: [PATCH 07/32] Move the release note template content to the end of file (#1795) Fix the issue that the release notes cannot be successfully created when releasing a new version. --- RELEASE_NOTES.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index faba18c8..9bc76ed4 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,17 +1,3 @@ -## WAMR-X.Y.Z - -### Breaking Changes - -### New Features - -### Bug Fixes - -### Enhancements - -### Others - ---- - ## WAMR-1.1.2 ### Breaking Changes @@ -225,3 +211,17 @@ Enable spec test on nuttx and daily run it - Fix build error on alios platform --- + +## WAMR-X.Y.Z + +### Breaking Changes + +### New Features + +### Bug Fixes + +### Enhancements + +### Others + +--- From ef4e795dba039ffb4c6d4b1c9aeb8373b3e57093 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 13 Dec 2022 10:48:51 +0800 Subject: [PATCH 08/32] Implement i32.div_s (#1792) --- core/iwasm/aot/aot_intrinsic.c | 10 ++++++++++ core/iwasm/aot/aot_intrinsic.h | 4 ++++ core/iwasm/aot/aot_reloc.h | 1 + 3 files changed, 15 insertions(+) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 5d27fc9e..ee1d4f92 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -68,6 +68,7 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST }, { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST }, { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S}, + { "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S}, { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U}, { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S}, { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U}, @@ -504,6 +505,12 @@ aot_intrinsic_i64_div_s(int64 l, int64 r) return l / r; } +int32 +aot_intrinsic_i32_div_s(int32 l, int32 r) +{ + return l / r; +} + uint32 aot_intrinsic_i32_div_u(uint32 l, uint32 r) { @@ -593,6 +600,7 @@ add_i64_common_intrinsics(AOTCompContext *comp_ctx) static void add_i32_common_intrinsics(AOTCompContext *comp_ctx) { + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_S); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_U); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_S); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_U); @@ -691,6 +699,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) return; if (!strncmp(comp_ctx->target_arch, "thumb", 5)) { + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST); add_i32_common_intrinsics(comp_ctx); if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) { } @@ -705,6 +714,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) } } else if (!strncmp(comp_ctx->target_arch, "riscv", 5)) { + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST); /* * Note: Use builtin intrinsics since hardware float operation * will cause rodata relocation diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h index 553d6724..2123058b 100644 --- a/core/iwasm/aot/aot_intrinsic.h +++ b/core/iwasm/aot/aot_intrinsic.h @@ -62,6 +62,7 @@ extern "C" { #define AOT_INTRINSIC_FLAG_I32_DIV_U AOT_INTRINSIC_FLAG(0, 28) #define AOT_INTRINSIC_FLAG_I32_REM_S AOT_INTRINSIC_FLAG(0, 29) #define AOT_INTRINSIC_FLAG_I32_REM_U AOT_INTRINSIC_FLAG(0, 30) +#define AOT_INTRINSIC_FLAG_I32_DIV_S AOT_INTRINSIC_FLAG(0, 31) #define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0) #define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1) @@ -259,6 +260,9 @@ aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs); int64 aot_intrinsic_i64_div_s(int64 l, int64 r); +int32 +aot_intrinsic_i32_div_s(int32 l, int32 r); + uint32 aot_intrinsic_i32_div_u(uint32 l, uint32 r); diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 41f83bb6..9b374051 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -114,6 +114,7 @@ typedef struct { REG_SYM(aot_intrinsic_i64_rem_u), \ REG_SYM(aot_intrinsic_i64_bit_or), \ REG_SYM(aot_intrinsic_i64_bit_and), \ + REG_SYM(aot_intrinsic_i32_div_s), \ REG_SYM(aot_intrinsic_i32_div_u), \ REG_SYM(aot_intrinsic_i32_rem_s), \ REG_SYM(aot_intrinsic_i32_rem_u), \ From d827315122d25281e207035e1858b783fa63d4cf Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 13 Dec 2022 11:32:35 +0800 Subject: [PATCH 09/32] Enable XIP in CI daily test (#1793) --- .github/workflows/spec_test_on_nuttx.yml | 2 +- tests/wamr-test-suites/spec-test-script/runtest.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 5f6be08a..35c588d8 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -25,7 +25,7 @@ jobs: wamr_test_option: [ # "-t fast-interp", "-t aot", - # "-t aot -X" + "-t aot -X" ] steps: - name: Install Utilities diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index ad181646..a61f03b1 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -948,15 +948,15 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = ' elif test_target == "armv7": cmd += ["--target=armv7", "--target-abi=gnueabihf"] elif test_target == "thumbv7": - cmd += ["--target=thumbv7", "--target-abi=gnueabihf", "--cpu=cortex-a9"] + cmd += ["--target=thumbv7", "--target-abi=gnueabihf", "--cpu=cortex-a9", "--cpu-features=-neon"] elif test_target == "riscv32_ilp32": - cmd += ["--target=riscv32", "--target-abi=ilp32"] + cmd += ["--target=riscv32", "--target-abi=ilp32", "--cpu=generic-rv32", "--cpu-features=+m,+a,+c"] elif test_target == "riscv32_ilp32d": - cmd += ["--target=riscv32", "--target-abi=ilp32d"] + cmd += ["--target=riscv32", "--target-abi=ilp32d", "--cpu=generic-rv32", "--cpu-features=+m,+a,+c"] elif test_target == "riscv64_lp64": - cmd += ["--target=riscv64", "--target-abi=lp64"] + cmd += ["--target=riscv64", "--target-abi=lp64", "--cpu=generic-rv64", "--cpu-features=+m,+a,+c"] elif test_target == "riscv64_lp64d": - cmd += ["--target=riscv64", "--target-abi=lp64d"] + cmd += ["--target=riscv64", "--target-abi=lp64d", "--cpu=generic-rv32", "--cpu-features=+m,+a,+c"] else: pass From 9083334f69459b8245cc58378d451660b8bdabf6 Mon Sep 17 00:00:00 2001 From: dongsheng28849455 <68947925+dongsheng28849455@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:45:26 +0800 Subject: [PATCH 10/32] Fix XIP issue of handling 64-bit const in 32-bit target (#1803) - Handle i64 const like f64 const - Ensure i64/f64 const is stored on 8-byte aligned address --- core/iwasm/compilation/aot_llvm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index b6e8b116..889ab259 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -2229,11 +2229,11 @@ aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol) if (idx < 0) { if (comp_ctx->pointer_size == sizeof(uint32) - && !strncmp(symbol, "f64#", 4)) { + && (!strncmp(symbol, "f64#", 4) || !strncmp(symbol, "i64#", 4))) { idx = bh_list_length(&comp_ctx->native_symbols); /* Add 4 bytes padding on 32-bit target to make sure that the f64 const is stored on 8-byte aligned address */ - if ((idx & 1) && !strncmp(comp_ctx->target_arch, "i386", 4)) { + if (idx & 1) { if (!insert_native_symbol(comp_ctx, "__ignore", idx)) { return -1; } @@ -2246,7 +2246,7 @@ aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol) } if (comp_ctx->pointer_size == sizeof(uint32) - && !strncmp(symbol, "f64#", 4)) { + && (!strncmp(symbol, "f64#", 4) || !strncmp(symbol, "i64#", 4))) { /* f64 const occupies 2 pointer slots on 32-bit target */ if (!insert_native_symbol(comp_ctx, "__ignore", idx + 1)) { return -1; From 294a625fe5f2752051032b5292fe72fd77caf0ac Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 13 Dec 2022 14:23:37 +0800 Subject: [PATCH 11/32] Use boringssl instead of openssl to implement wasm cache loading (#1804) --- CMakeLists.txt | 4 +-- build-scripts/involve_boringssl.cmake | 41 +++++++++++++++++++++++++++ build-scripts/runtime_lib.cmake | 12 +++----- core/iwasm/common/wasm_c_api.c | 2 +- samples/wasm-c-api/CMakeLists.txt | 6 ++-- samples/wasm-c-api/src/clone.c | 1 + 6 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 build-scripts/involve_boringssl.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f683868f..49b2969a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,7 +131,7 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) # STATIC LIBRARY add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE}) if (WAMR_BUILD_WASM_CACHE EQUAL 1) - target_link_libraries(iwasm_static OpenSSL::SSL) + target_link_libraries(iwasm_static PUBLIC boringssl_crypto) endif () set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib) @@ -142,7 +142,7 @@ add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) target_link_libraries (iwasm_shared ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) if (WAMR_BUILD_WASM_CACHE EQUAL 1) - target_link_libraries(iwasm_shared OpenSSL::SSL) + target_link_libraries(iwasm_shared boringssl_crypto) endif () if (MINGW) diff --git a/build-scripts/involve_boringssl.cmake b/build-scripts/involve_boringssl.cmake new file mode 100644 index 00000000..a0e069ba --- /dev/null +++ b/build-scripts/involve_boringssl.cmake @@ -0,0 +1,41 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +message(STATUS "involving boringssl...") + +include(ExternalProject) + +ExternalProject_Add(boringssl + PREFIX external/boringssl + # follow envoy, which tracks BoringSSL, which tracks Chromium + # https://github.com/envoyproxy/envoy/blob/main/bazel/repository_locations.bzl#L112 + # chromium-105.0.5195.37 (linux/beta) + URL https://github.com/google/boringssl/archive/098695591f3a2665fccef83a3732ecfc99acdcdd.tar.gz + URL_HASH SHA256=e141448cf6f686b6e9695f6b6459293fd602c8d51efe118a83106752cf7e1280 + DOWNLOAD_EXTRACT_TIMESTAMP NEW + # SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../external/boringssl + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/src/boringssl-build/libssl.a + ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/ + && ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/src/boringssl-build/libcrypto.a + ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/ + && ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/src/boringssl/src/include/openssl + ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/openssl +) + +add_library(boringssl_ssl STATIC IMPORTED GLOBAL) +set_target_properties( + boringssl_ssl + PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/libssl.a + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/ +) +add_dependencies(boringssl_ssl boringssl) + +add_library(boringssl_crypto STATIC IMPORTED GLOBAL) +set_target_properties( + boringssl_crypto + PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/libcrypto.a + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/ +) +add_dependencies(boringssl_crypto boringssl) \ No newline at end of file diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 439a7c63..ac3f4144 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -27,14 +27,6 @@ if (DEFINED EXTRA_SDK_INCLUDE_PATH) ) endif () -# Need exactly OpenSSL 1.1.1 -if (WAMR_BUILD_WASM_CACHE EQUAL 1) - # Set OPENSSL_ROOT_DIR to the root directory of an OpenSSL installation. - # Like: cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl - # Especially on MacOS - find_package(OpenSSL 1.1.1 EXACT REQUIRED) -endif () - # Set default options # Set WAMR_BUILD_TARGET, currently values supported: @@ -147,6 +139,10 @@ if (WAMR_BUILD_LIB_RATS EQUAL 1) include (${IWASM_DIR}/libraries/lib-rats/lib_rats.cmake) endif () +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + include (${WAMR_ROOT_DIR}/build-scripts/involve_boringssl.cmake) +endif () + ####################### Common sources ####################### if (NOT MSVC) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 619e0229..ae4ceaf9 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2183,7 +2183,7 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) #if WASM_ENABLE_WASM_CACHE != 0 /* if cached */ - SHA256((void *)binary->data, binary->num_elems, binary_hash); + SHA256((void *)binary->data, binary->num_elems, (uint8_t *)binary_hash); module_ex = try_reuse_loaded_module(store, binary_hash); if (module_ex) return module_ext_to_module(module_ex); diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 02b97d4c..87687405 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -94,7 +94,7 @@ endif() target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) if (WAMR_BUILD_WASM_CACHE EQUAL 1) - target_link_libraries(vmlib OpenSSL::SSL) + target_link_libraries(vmlib boringssl_crypto) endif () ################################################ @@ -165,7 +165,7 @@ foreach(EX ${EXAMPLES}) add_executable(${EX} ${SRC} ${UNCOMMON_SHARED_SOURCE} ${MM_UTIL}) set_target_properties (${EX} PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories(${EX} PRIVATE ${UNCOMMON_SHARED_DIR}) - target_link_libraries(${EX} vmlib -lpthread -lm) + target_link_libraries(${EX} vmlib) if (MSVC) target_compile_definitions(${EX} PRIVATE WASM_API_EXTERN=) endif() @@ -206,7 +206,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_custom_command( OUTPUT ${EX}_leak_check.report DEPENDS ${EX} ${EX}_WASM - COMMAND ${VALGRIND} --tool=memcheck --leak-check=summary -- ./${EX} > ${EX}_leak_check.report 2>&1 + COMMAND ${VALGRIND} --tool=memcheck --leak-check=full -- ./${EX} > ${EX}_leak_check.report 2>&1 WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) add_custom_target(${EX}_LEAK_TEST ALL diff --git a/samples/wasm-c-api/src/clone.c b/samples/wasm-c-api/src/clone.c index ce8ebd8b..da83b379 100644 --- a/samples/wasm-c-api/src/clone.c +++ b/samples/wasm-c-api/src/clone.c @@ -522,6 +522,7 @@ main() pthread_mutex_unlock(&ready_go_lock); pthread_cond_broadcast(&ready_go_cond); + sleep(3); for (size_t i = 0; i < sizeof(tids) / sizeof(tids[0]); i++) { if (tids[i] != 0) pthread_join(tids[i], NULL); From ca0b5cf816d2c6ec1f9e2d7c9bc9c0eed576e90e Mon Sep 17 00:00:00 2001 From: Callum Macmillan Date: Tue, 13 Dec 2022 07:16:43 +0000 Subject: [PATCH 12/32] Fix watchpoint segfault when using debug interp without server (#1806) --- core/iwasm/interpreter/wasm_interp_classic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 54fcf8d0..5fe81438 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1157,8 +1157,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env); - bh_list *watch_point_list_read = &debug_instance->watch_point_list_read; - bh_list *watch_point_list_write = &debug_instance->watch_point_list_write; + bh_list *watch_point_list_read = + debug_instance ? &debug_instance->watch_point_list_read : NULL; + bh_list *watch_point_list_write = + debug_instance ? &debug_instance->watch_point_list_write : NULL; #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 From 97d2b5a06082ad60f816c056d7aefb6f5ffcdc37 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 14 Dec 2022 09:42:03 +0800 Subject: [PATCH 13/32] Publish the docker image with tar/zip files (#1808) And fix issue found in fast jit call indirect. --- .github/workflows/build_docker_images.yml | 87 ++++++++++++++++------ .github/workflows/release_process.yml | 6 +- core/iwasm/fast-jit/fe/jit_emit_function.c | 6 +- test-tools/wamr-ide/README.md | 36 ++++++--- 4 files changed, 93 insertions(+), 42 deletions(-) diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index 7b101d2d..b9892279 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -6,6 +6,10 @@ name: Create and publish Docker images on: workflow_call: inputs: + upload_url: + description: upload binary assets to the URL of release + type: string + required: true ver_num: description: a semantic version number. type: string @@ -14,35 +18,72 @@ on: jobs: build-and-push-images: runs-on: ubuntu-22.04 - permissions: - contents: read - packages: write steps: - name: Checkout repository uses: actions/checkout@v3 - - name: Downcase github actor - id: downcase_github_actor - uses: ASzc/change-string-case-action@v2 - with: - string: ${{ github.actor }} - - - name: Login to the Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ steps.downcase_github_actor.outputs.lowercase }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push Docker image(wasm-toolchain:${{ inputs.ver_num }}) to Container registry + - name: Build and save Docker image(wasm-debug-server:${{ inputs.ver_num }}) to tar file run: | - docker build -t ghcr.io/${{ steps.downcase_github_actor.outputs.lowercase }}/wasm-toolchain:${{ inputs.ver_num }} . - docker push ghcr.io/${{ steps.downcase_github_actor.outputs.lowercase }}/wasm-toolchain:${{ inputs.ver_num }} + docker build -t wasm-debug-server:${{ inputs.ver_num }} . + docker save -o wasm-debug-server.tar wasm-debug-server:${{ inputs.ver_num }} + working-directory: test-tools/wamr-ide/WASM-Debug-Server/Docker + + - name: compress the tar file + run: | + tar czf wasm-debug-server-${{ inputs.ver_num }}.tar.gz wasm-debug-server.tar + zip wasm-debug-server-${{ inputs.ver_num }}.zip wasm-debug-server.tar + working-directory: test-tools/wamr-ide/WASM-Debug-Server/Docker + + - name: upload release tar.gz + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ inputs.upload_url }} + asset_path: test-tools/wamr-ide/WASM-Debug-Server/Docker/wasm-debug-server-${{ inputs.ver_num }}.tar.gz + asset_name: wasm-debug-server-${{ inputs.ver_num }}.tar.gz + asset_content_type: application/x-gzip + + - name: upload release zip + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ inputs.upload_url }} + asset_path: test-tools/wamr-ide/WASM-Debug-Server/Docker/wasm-debug-server-${{ inputs.ver_num }}.zip + asset_name: wasm-debug-server-${{ inputs.ver_num }}.zip + asset_content_type: application/zip + + - name: Build and save Docker image(wasm-toolchain:${{ inputs.ver_num }}) to tar file + run: | + docker build -t wasm-toolchain:${{ inputs.ver_num }} . + docker save -o wasm-toolchain.tar wasm-toolchain:${{ inputs.ver_num }} working-directory: test-tools/wamr-ide/WASM-Toolchain/Docker - - name: Build and push Docker image(wasm-debug-server:${{ inputs.ver_num }}) to Container registry + - name: compress the tar file run: | - docker build -t ghcr.io/${{ steps.downcase_github_actor.outputs.lowercase }}/wasm-debug-server:${{ inputs.ver_num }} . - docker push ghcr.io/${{ steps.downcase_github_actor.outputs.lowercase }}/wasm-debug-server:${{ inputs.ver_num }} - working-directory: test-tools/wamr-ide/WASM-Debug-Server/Docker + tar czf wasm-toolchain-${{ inputs.ver_num }}.tar.gz wasm-toolchain.tar + zip wasm-toolchain-${{ inputs.ver_num }}.zip wasm-toolchain.tar + working-directory: test-tools/wamr-ide/WASM-Toolchain/Docker + + - name: upload release tar.gz + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ inputs.upload_url }} + asset_path: test-tools/wamr-ide/WASM-Toolchain/Docker/wasm-toolchain-${{ inputs.ver_num }}.tar.gz + asset_name: wasm-toolchain-${{ inputs.ver_num }}.tar.gz + asset_content_type: application/x-gzip + + - name: upload release zip + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ inputs.upload_url }} + asset_path: test-tools/wamr-ide/WASM-Toolchain/Docker/wasm-toolchain-${{ inputs.ver_num }}.zip + asset_name: wasm-toolchain-${{ inputs.ver_num }}.zip + asset_content_type: application/zip + diff --git a/.github/workflows/release_process.yml b/.github/workflows/release_process.yml index e48c8ffe..aae2f890 100644 --- a/.github/workflows/release_process.yml +++ b/.github/workflows/release_process.yml @@ -37,9 +37,6 @@ jobs: echo "${extract_result}" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - - name: check output - run: echo 'the release note is "${{ env.RELEASE_NOTE }}"' - - name: create a release id: create_release uses: actions/create-release@v1 @@ -163,8 +160,9 @@ jobs: needs: [create_tag, create_release] uses: ./.github/workflows/build_docker_images.yml with: + upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver }} - + # # WAMR_LLDB release_wamr_lldb_on_ubuntu_2004: diff --git a/core/iwasm/fast-jit/fe/jit_emit_function.c b/core/iwasm/fast-jit/fe/jit_emit_function.c index 5b072874..ce22a950 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_function.c +++ b/core/iwasm/fast-jit/fe/jit_emit_function.c @@ -624,19 +624,19 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx, NEW_CONST(I32, offset_of_local(n))); break; case VALUE_TYPE_I64: - res = jit_cc_new_reg_I32(cc); + res = jit_cc_new_reg_I64(cc); GEN_INSN(LDI64, res, argv, NEW_CONST(I32, 0)); GEN_INSN(STI64, res, cc->fp_reg, NEW_CONST(I32, offset_of_local(n))); break; case VALUE_TYPE_F32: - res = jit_cc_new_reg_I32(cc); + res = jit_cc_new_reg_F32(cc); GEN_INSN(LDF32, res, argv, NEW_CONST(I32, 0)); GEN_INSN(STF32, res, cc->fp_reg, NEW_CONST(I32, offset_of_local(n))); break; case VALUE_TYPE_F64: - res = jit_cc_new_reg_I32(cc); + res = jit_cc_new_reg_F64(cc); GEN_INSN(LDF64, res, argv, NEW_CONST(I32, 0)); GEN_INSN(STF64, res, cc->fp_reg, NEW_CONST(I32, offset_of_local(n))); diff --git a/test-tools/wamr-ide/README.md b/test-tools/wamr-ide/README.md index 9b78ea7e..7e2c05ce 100644 --- a/test-tools/wamr-ide/README.md +++ b/test-tools/wamr-ide/README.md @@ -37,23 +37,35 @@ under `resource/debug/bin`. - Ubuntu Bionic 18.04(LTS) ``` -#### 3. Pull docker images from the registry(recommended) or build docker images on the host +#### 3. Load docker images from the release tar file or build docker images on the host -##### 3.1 Pull docker images from registry +##### 3.1 Load docker images from the release tar file -From now on, for each release, we have the same version tagged docker image pushed to GitHub package. +From now on, for each release, we have the same version tagged docker image saved as a tar file, which you can find and download in the release. -You could simply pull a certain version of docker images using the following commands: +You could download the tar archive files for docker images from the release, and then load them using the following commands: ```sh -# pull and retag wasm-toolchain -docker pull ghcr.io/bytecodealliance/wasm-toolchain:{version number} -docker tag ghcr.io/bytecodealliance/wasm-toolchain:{version number} wasm-toolchain:{version number} -docker rmi ghcr.io/bytecodealliance/wasm-toolchain:{version number} -# pull and retag wasm-debug-server -docker pull ghcr.io/bytecodealliance/wasm-debug-server:{version number} -docker tag ghcr.io/bytecodealliance/wasm-debug-server:{version number} wasm-debug-server:{version number} -docker rmi ghcr.io/bytecodealliance/wasm-debug-server:{version number} +# download the zip or tar.gz from release depending on your platform +# decompress and get the tar file + +# on Linux/MacOS, you could use tar +tar xf wasm-toolchain-{version number}.tar.gz +tar xf wasm-debug-server-{version number}.tar.gz +# or you could use unzip +unzip wasm-toolchain-{version number}.zip +unzip wasm-debug-server-{version number}.zip +# load wasm-toolchain +docker load --input wasm-toolchain.tar +# load wasm-debug-server +docker load --input wasm-debug-server.tar + +# on Windows, you could use any unzip software you like +# then loading docker images using powershell or git bash +# load wasm-toolchain +docker load --input ./wasm-toolchain.tar +# load wasm-debug-server +docker load --input ./wasm-debug-server.tar ``` ##### 3.2 Build docker images on host From d0c4c7036b2a6199c7822eac9a8b61d87c5ccd44 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Fri, 16 Dec 2022 14:15:32 +0800 Subject: [PATCH 14/32] vscode-extension: Run docker image with the same version as WAMR (#1815) --- .../resource/scripts/boot_debugger_server.bat | 2 +- .../resource/scripts/boot_debugger_server.sh | 2 +- .../resource/scripts/build.bat | 2 +- .../resource/scripts/build.sh | 2 +- .../VSCode-Extension/resource/scripts/run.bat | 2 +- .../VSCode-Extension/resource/scripts/run.sh | 2 +- .../VSCode-Extension/src/extension.ts | 13 ++- .../VSCode-Extension/src/taskProvider.ts | 15 ++-- .../src/utilities/directoryUtilities.ts | 86 ++++++++++++------- .../src/utilities/lldbUtilities.ts | 74 +++++++++++----- 10 files changed, 132 insertions(+), 68 deletions(-) diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat index 34304971..7fd1f024 100644 --- a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat +++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat @@ -6,5 +6,5 @@ docker run --rm -it --name=wasm-debug-server-ctr ^ -v "%cd%":/mnt ^ -p 1234:1234 ^ - wasm-debug-server:1.0 ^ + wasm-debug-server:%2 ^ /bin/bash -c "./debug.sh %1" diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh index 97e290fc..169fb7e5 100755 --- a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh +++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh @@ -8,5 +8,5 @@ set -e docker run --rm -it --name=wasm-debug-server-ctr \ -v "$(pwd)":/mnt \ -p 1234:1234 \ - wasm-debug-server:1.0 \ + wasm-debug-server:$2 \ /bin/bash -c "./debug.sh $1" diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat index 1fe6ca41..de415107 100644 --- a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat +++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat @@ -7,5 +7,5 @@ docker run --rm --name=wasm-toolchain-ctr ^ -it -v "%cd%":/mnt ^ --env=PROJ_PATH="%cd%" ^ - wasm-toolchain:1.0 ^ + wasm-toolchain:%2 ^ /bin/bash -c "./build_wasm.sh %1" diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh index 04892b4e..a8a42cc8 100755 --- a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh +++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh @@ -8,5 +8,5 @@ set -e docker run --rm --name=wasm-toolchain-ctr \ -it -v "$(pwd)":/mnt \ --env=PROJ_PATH="$(pwd)" \ - wasm-toolchain:1.0 \ + wasm-toolchain:$2 \ /bin/bash -c "./build_wasm.sh $1" diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat index 45d86bda..af47f35b 100644 --- a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat +++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat @@ -5,5 +5,5 @@ docker run --rm -it --name=wasm-debug-server-ctr ^ -v "%cd%":/mnt ^ - wasm-debug-server:1.0 ^ + wasm-debug-server:%2 ^ /bin/bash -c "./run.sh %1" diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh index 31961847..670e57c1 100755 --- a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh +++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh @@ -7,5 +7,5 @@ set -e docker run --rm -it --name=wasm-debug-server-ctr \ -v "$(pwd)":/mnt \ - wasm-debug-server:1.0 \ + wasm-debug-server:$2 \ /bin/bash -c "./run.sh $1" diff --git a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts index 7eb8b34a..e1d33b4e 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts @@ -18,7 +18,11 @@ import { } from './utilities/directoryUtilities'; import { decorationProvider } from './decorationProvider'; import { WasmDebugConfigurationProvider } from './debugConfigurationProvider'; -import { isLLDBInstalled, promptInstallLLDB } from './utilities/lldbUtilities'; +import { + isLLDBInstalled, + promptInstallLLDB, + getWAMRExtensionVersion, +} from './utilities/lldbUtilities'; let wasmTaskProvider: WasmTaskProvider; let wasmDebugConfigProvider: WasmDebugConfigurationProvider; @@ -43,6 +47,8 @@ export async function activate(context: vscode.ExtensionContext) { excludeFileArr = new Array(), scriptMap = new Map(); + const wamrVersion = getWAMRExtensionVersion(context); + /** * Get OS platform information for differ windows and linux execution script */ @@ -83,7 +89,7 @@ export async function activate(context: vscode.ExtensionContext) { typeMap.set('Debug', 'Debug'); typeMap.set('Destroy', 'Destroy'); - wasmTaskProvider = new WasmTaskProvider(typeMap, scriptMap); + wasmTaskProvider = new WasmTaskProvider(typeMap, scriptMap, wamrVersion); vscode.tasks.registerTaskProvider('wasm', wasmTaskProvider); @@ -670,7 +676,8 @@ export async function activate(context: vscode.ExtensionContext) { let _path = curWorkspace.concat( OS_PLATFORM === 'win32' ? '\\' - : OS_PLATFORM === 'linux' || OS_PLATFORM === 'darwin' + : OS_PLATFORM === 'linux' || + OS_PLATFORM === 'darwin' ? '/' : '', option diff --git a/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts index e5e1280e..7b2408bd 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts @@ -15,7 +15,8 @@ export interface OwnShellOption { export class WasmTaskProvider implements vscode.TaskProvider { constructor( public _type: Map, - public _script: Map + public _script: Map, + public _wamrVersion: string ) {} buildShellOption: OwnShellOption | undefined; @@ -31,7 +32,11 @@ export class WasmTaskProvider implements vscode.TaskProvider { let targetName = TargetConfigPanel.BUILD_ARGS.output_file_name.split('.')[0]; - if (os.platform() === 'linux' || os.platform() === 'darwin' || os.platform() === 'win32') { + if ( + os.platform() === 'linux' || + os.platform() === 'darwin' || + os.platform() === 'win32' + ) { /* build */ this.buildShellOption = { cmd: @@ -40,7 +45,7 @@ export class WasmTaskProvider implements vscode.TaskProvider { : (this._script.get('buildScript') as string), options: { executable: this._script.get('buildScript'), - shellArgs: [targetName, os.platform()], + shellArgs: [targetName, this._wamrVersion], }, }; @@ -52,7 +57,7 @@ export class WasmTaskProvider implements vscode.TaskProvider { : (this._script.get('debugScript') as string), options: { executable: this._script.get('debugScript'), - shellArgs: [targetName], + shellArgs: [targetName, this._wamrVersion], }, }; @@ -64,7 +69,7 @@ export class WasmTaskProvider implements vscode.TaskProvider { : (this._script.get('runScript') as string), options: { executable: this._script.get('runScript'), - shellArgs: [targetName], + shellArgs: [targetName, this._wamrVersion], }, }; diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts index 348e5730..c55be471 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts @@ -137,53 +137,73 @@ export function checkFolderName(folderName: string) { return valid; } -export function downloadFile(url: string, destinationPath: string): Promise { +export function downloadFile( + url: string, + destinationPath: string +): Promise { return new Promise((resolve, reject) => { const file = fileSystem.createWriteStream(destinationPath); const stream = request(url, undefined, (error, response, body) => { if (response.statusCode !== 200) { - reject(new Error(`Download from ${url} failed with ${response.statusMessage}`)); + reject( + new Error( + `Download from ${url} failed with ${response.statusMessage}` + ) + ); } }).pipe(file); - stream.on("close", resolve); - stream.on("error", reject); + stream.on('close', resolve); + stream.on('error', reject); }); } -export function unzipFile(sourcePath: string, getDestinationFileName: (entryName: string) => string): Promise { +export function unzipFile( + sourcePath: string, + getDestinationFileName: (entryName: string) => string +): Promise { return new Promise((resolve, reject) => { const unzippedFilePaths: string[] = []; - yauzl.open(sourcePath, { lazyEntries: true }, function(error, zipfile) { - if (error) { - reject(error); - return; - } - zipfile.readEntry(); - zipfile.on("entry", function(entry) { - // This entry is a directory so skip it - if (/\/$/.test(entry.fileName)) { - zipfile.readEntry(); + yauzl.open( + sourcePath, + { lazyEntries: true }, + function (error, zipfile) { + if (error) { + reject(error); return; - } - - zipfile.openReadStream(entry, function(error, readStream) { - if (error) { - reject(error); + } + zipfile.readEntry(); + zipfile.on('entry', function (entry) { + // This entry is a directory so skip it + if (/\/$/.test(entry.fileName)) { + zipfile.readEntry(); return; } - readStream.on("end", () => zipfile.readEntry()); - const destinationFileName = getDestinationFileName(entry.fileName); - fileSystem.mkdirSync(path.dirname(destinationFileName), { recursive: true }); - const file = fileSystem.createWriteStream(destinationFileName); - readStream.pipe(file).on("error", reject); - unzippedFilePaths.push(destinationFileName); + zipfile.openReadStream(entry, function (error, readStream) { + if (error) { + reject(error); + return; + } + readStream.on('end', () => zipfile.readEntry()); + const destinationFileName = getDestinationFileName( + entry.fileName + ); + fileSystem.mkdirSync( + path.dirname(destinationFileName), + { recursive: true } + ); + + const file = + fileSystem.createWriteStream(destinationFileName); + readStream.pipe(file).on('error', reject); + unzippedFilePaths.push(destinationFileName); + }); }); - }); - zipfile.on("end", function() { - zipfile.close(); - resolve(unzippedFilePaths); - }); - }); + zipfile.on('end', function () { + zipfile.close(); + resolve(unzippedFilePaths); + }); + } + ); }); -} \ No newline at end of file +} diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts index 50d468b9..e2eaec23 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts @@ -7,27 +7,41 @@ import * as vscode from 'vscode'; import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; -import { checkIfFileExists, downloadFile, unzipFile } from './directoryUtilities'; +import { + checkIfFileExists, + downloadFile, + unzipFile, +} from './directoryUtilities'; -const LLDB_RESOURCE_DIR = "resource/debug"; -const LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP: Partial> = { - "linux": "x86_64-ubuntu-22.04", - "darwin": "universal-macos-latest" +const LLDB_RESOURCE_DIR = 'resource/debug'; +const LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP: Partial< + Record +> = { + linux: 'x86_64-ubuntu-22.04', + darwin: 'universal-macos-latest', }; -const WAMR_LLDB_NOT_SUPPORTED_ERROR = new Error("WAMR LLDB is not supported on this platform"); +const WAMR_LLDB_NOT_SUPPORTED_ERROR = new Error( + 'WAMR LLDB is not supported on this platform' +); function getLLDBUnzipFilePath(destinationFolder: string, filename: string) { - const dirs = filename.split("/"); - if (dirs[0] === "inst") { + const dirs = filename.split('/'); + if (dirs[0] === 'inst') { dirs.shift(); } return path.join(destinationFolder, ...dirs); } +export function getWAMRExtensionVersion( + context: vscode.ExtensionContext +): string { + return require(path.join(context.extensionPath, 'package.json')).version; +} + function getLLDBDownloadUrl(context: vscode.ExtensionContext): string { - const wamrVersion = require(path.join(context.extensionPath, "package.json")).version; + const wamrVersion = getWAMRExtensionVersion(context); const lldbOsUrlSuffix = LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP[os.platform()]; if (!lldbOsUrlSuffix) { @@ -40,15 +54,25 @@ function getLLDBDownloadUrl(context: vscode.ExtensionContext): string { export function isLLDBInstalled(context: vscode.ExtensionContext): boolean { const extensionPath = context.extensionPath; const lldbOSDir = os.platform(); - const lldbBinaryPath = path.join(extensionPath, LLDB_RESOURCE_DIR, lldbOSDir, "bin", "lldb"); + const lldbBinaryPath = path.join( + extensionPath, + LLDB_RESOURCE_DIR, + lldbOSDir, + 'bin', + 'lldb' + ); return checkIfFileExists(lldbBinaryPath); } export async function promptInstallLLDB(context: vscode.ExtensionContext) { const extensionPath = context.extensionPath; - const setupPrompt = "setup"; - const skipPrompt = "skip"; - const response = await vscode.window.showWarningMessage('No LLDB instance found. Setup now?', setupPrompt, skipPrompt); + const setupPrompt = 'setup'; + const skipPrompt = 'skip'; + const response = await vscode.window.showWarningMessage( + 'No LLDB instance found. Setup now?', + setupPrompt, + skipPrompt + ); if (response === skipPrompt) { return; @@ -61,23 +85,31 @@ export async function promptInstallLLDB(context: vscode.ExtensionContext) { throw WAMR_LLDB_NOT_SUPPORTED_ERROR; } - const lldbDestinationFolder = path.join(extensionPath, LLDB_RESOURCE_DIR, destinationDir); - const lldbZipPath = path.join(lldbDestinationFolder, "bundle.zip"); + const lldbDestinationFolder = path.join( + extensionPath, + LLDB_RESOURCE_DIR, + destinationDir + ); + const lldbZipPath = path.join(lldbDestinationFolder, 'bundle.zip'); vscode.window.showInformationMessage(`Downloading LLDB...`); await downloadFile(downloadUrl, lldbZipPath); - vscode.window.showInformationMessage(`LLDB downloaded to ${lldbZipPath}. Installing...`); + vscode.window.showInformationMessage( + `LLDB downloaded to ${lldbZipPath}. Installing...` + ); - const lldbFiles = await unzipFile(lldbZipPath, filename => getLLDBUnzipFilePath(lldbDestinationFolder, filename)); + const lldbFiles = await unzipFile(lldbZipPath, filename => + getLLDBUnzipFilePath(lldbDestinationFolder, filename) + ); // Allow execution of lldb - lldbFiles.forEach(file => fs.chmodSync(file, "0775")); + lldbFiles.forEach(file => fs.chmodSync(file, '0775')); - vscode.window.showInformationMessage(`LLDB installed at ${lldbDestinationFolder}`); + vscode.window.showInformationMessage( + `LLDB installed at ${lldbDestinationFolder}` + ); // Remove the bundle.zip fs.unlink(lldbZipPath, () => {}); } - - From fb8727ba683b3969cc6075356bf109defefe6003 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 16 Dec 2022 14:16:58 +0800 Subject: [PATCH 15/32] Update release notes and fix issues reported by Coverity (#1813) --- .github/workflows/build_docker_images.yml | 4 ++-- RELEASE_NOTES.md | 3 +++ core/iwasm/libraries/debug-engine/handler.c | 4 ++-- test-tools/wamr-ide/README.md | 8 ++++---- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index b9892279..819bf94c 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -28,7 +28,7 @@ jobs: docker build -t wasm-debug-server:${{ inputs.ver_num }} . docker save -o wasm-debug-server.tar wasm-debug-server:${{ inputs.ver_num }} working-directory: test-tools/wamr-ide/WASM-Debug-Server/Docker - + - name: compress the tar file run: | tar czf wasm-debug-server-${{ inputs.ver_num }}.tar.gz wasm-debug-server.tar @@ -86,4 +86,4 @@ jobs: asset_path: test-tools/wamr-ide/WASM-Toolchain/Docker/wasm-toolchain-${{ inputs.ver_num }}.zip asset_name: wasm-toolchain-${{ inputs.ver_num }}.zip asset_content_type: application/zip - + diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 9bc76ed4..a0cfe7a8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -32,6 +32,8 @@ Fix sample ref-types/wasm-c-api build error with wat2wasm low version Fix zephyr sample build errors Fix source debugger error handling: continue executing when detached Fix scenario where the timeout for atomic wait is set to negative number +Fix link cxx object file error when building wamrc for docker image +Fix XIP issue of handling 64-bit const in 32-bit target ### Enhancements Refactor the layout of interpreter and AOT module instance @@ -75,6 +77,7 @@ Fix warnings in the posix socket implementation Update document for MacOS compilation Install patched LLDB on vscode extension activation Add ARM aeabi memcpy/memmove/memset symbols for AOT bulk memory ops +Enable wasm cache loading in wasm-c-api ### Others Add CIs to release new version and publish binary files diff --git a/core/iwasm/libraries/debug-engine/handler.c b/core/iwasm/libraries/debug-engine/handler.c index cf1a87c5..8d451b1a 100644 --- a/core/iwasm/libraries/debug-engine/handler.c +++ b/core/iwasm/libraries/debug-engine/handler.c @@ -731,7 +731,7 @@ handle_add_break(WASMGDBServer *server, char *payload) handle_watchpoint_read_add(server, addr, length); break; default: - LOG_ERROR("Unsupported breakpoint type %d", type); + LOG_ERROR("Unsupported breakpoint type %zu", type); write_packet(server, ""); break; } @@ -766,7 +766,7 @@ handle_remove_break(WASMGDBServer *server, char *payload) handle_watchpoint_read_remove(server, addr, length); break; default: - LOG_ERROR("Unsupported breakpoint type %d", type); + LOG_ERROR("Unsupported breakpoint type %zu", type); write_packet(server, ""); break; } diff --git a/test-tools/wamr-ide/README.md b/test-tools/wamr-ide/README.md index 7e2c05ce..d33f53f7 100644 --- a/test-tools/wamr-ide/README.md +++ b/test-tools/wamr-ide/README.md @@ -46,7 +46,7 @@ From now on, for each release, we have the same version tagged docker image save You could download the tar archive files for docker images from the release, and then load them using the following commands: ```sh -# download the zip or tar.gz from release depending on your platform +# download the zip or tar.gz from release depending on your platform # decompress and get the tar file # on Linux/MacOS, you could use tar @@ -55,14 +55,14 @@ tar xf wasm-debug-server-{version number}.tar.gz # or you could use unzip unzip wasm-toolchain-{version number}.zip unzip wasm-debug-server-{version number}.zip -# load wasm-toolchain +# load wasm-toolchain docker load --input wasm-toolchain.tar # load wasm-debug-server docker load --input wasm-debug-server.tar -# on Windows, you could use any unzip software you like +# on Windows, you could use any unzip software you like # then loading docker images using powershell or git bash -# load wasm-toolchain +# load wasm-toolchain docker load --input ./wasm-toolchain.tar # load wasm-debug-server docker load --input ./wasm-debug-server.tar From 14288f59b0857bbc74d10811f4024aea5f1db78c Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 19 Dec 2022 11:24:46 +0800 Subject: [PATCH 16/32] Implement Multi-tier JIT (#1774) Implement 2-level Multi-tier JIT engine: tier-up from Fast JIT to LLVM JIT to get quick cold startup by Fast JIT and better performance by gradually switching to LLVM JIT when the LLVM JIT functions are compiled by the backend threads. Refer to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/1302 --- build-scripts/config_common.cmake | 18 +- core/iwasm/common/wasm_runtime_common.c | 3 + core/iwasm/compilation/aot.h | 4 + core/iwasm/compilation/aot_emit_function.c | 48 +- .../fast-jit/cg/x86-64/jit_codegen_x86_64.cpp | 923 +++++++++++++++++- core/iwasm/fast-jit/fe/jit_emit_function.c | 4 +- core/iwasm/fast-jit/jit_codecache.c | 3 +- core/iwasm/fast-jit/jit_codegen.h | 11 +- core/iwasm/fast-jit/jit_compiler.c | 147 ++- core/iwasm/fast-jit/jit_compiler.h | 21 +- core/iwasm/fast-jit/jit_frontend.c | 6 + core/iwasm/fast-jit/jit_frontend.h | 11 + core/iwasm/fast-jit/jit_ir.def | 2 +- core/iwasm/interpreter/wasm.h | 71 +- core/iwasm/interpreter/wasm_interp_classic.c | 93 +- core/iwasm/interpreter/wasm_loader.c | 514 +++++++--- core/iwasm/interpreter/wasm_mini_loader.c | 511 +++++++--- core/iwasm/interpreter/wasm_runtime.c | 79 +- core/iwasm/interpreter/wasm_runtime.h | 9 + doc/build_wamr.md | 10 +- tests/wamr-test-suites/test_wamr.sh | 30 +- 21 files changed, 2180 insertions(+), 338 deletions(-) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 008d7f47..53b0207f 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -85,6 +85,13 @@ if (NOT WAMR_BUILD_AOT EQUAL 1) endif () endif () +if (WAMR_BUILD_FAST_JIT EQUAL 1) + if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0) + # Enable Lazy JIT by default + set (WAMR_BUILD_LAZY_JIT 1) + endif () +endif () + if (WAMR_BUILD_JIT EQUAL 1) if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0) # Enable Lazy JIT by default @@ -136,7 +143,12 @@ else () message (" WAMR AOT disabled") endif () if (WAMR_BUILD_FAST_JIT EQUAL 1) - message (" WAMR Fast JIT enabled") + if (WAMR_BUILD_LAZY_JIT EQUAL 1) + add_definitions("-DWASM_ENABLE_LAZY_JIT=1") + message (" WAMR Fast JIT enabled with Lazy Compilation") + else () + message (" WAMR Fast JIT enabled with Eager Compilation") + endif () else () message (" WAMR Fast JIT disabled") endif () @@ -151,6 +163,10 @@ if (WAMR_BUILD_JIT EQUAL 1) else () message (" WAMR LLVM ORC JIT disabled") endif () +if (WAMR_BUILD_FAST_JIT EQUAL 1 AND WAMR_BUILD_JIT EQUAL 1 + AND WAMR_BUILD_LAZY_JIT EQUAL 1) + message (" Multi-tier JIT enabled") +endif () if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) message (" Libc builtin enabled") else () diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8ddf4af4..fab9b59f 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2176,6 +2176,9 @@ static const char *exception_msgs[] = { "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */ "out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */ "wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */ +#if WASM_ENABLE_FAST_JIT != 0 + "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */ +#endif "", /* EXCE_ALREADY_THROWN */ }; /* clang-format on */ diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 8e8598c7..c7989851 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -309,6 +309,8 @@ aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode) #if WASM_ENABLE_MULTI_MODULE != 0 if (is_jit_mode) return tbl->table_max_size; +#else + (void)is_jit_mode; #endif return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size; } @@ -319,6 +321,8 @@ aot_get_tbl_data_slots(const AOTTable *tbl, bool is_jit_mode) #if WASM_ENABLE_MULTI_MODULE != 0 if (is_jit_mode) return tbl->table_max_size; +#else + (void)is_jit_mode; #endif return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size; } diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index fb2fca56..d6a5a4ab 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -798,7 +798,53 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, func = func_ctx->func; } else { - func = func_ctxes[func_idx - import_func_count]->func; + if (!comp_ctx->is_jit_mode) { + func = func_ctxes[func_idx - import_func_count]->func; + } + else { +#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0) + func = func_ctxes[func_idx - import_func_count]->func; +#else + /* JIT tier-up, load func ptr from func_ptrs[func_idx] */ + LLVMValueRef func_ptr, func_idx_const; + LLVMTypeRef func_ptr_type; + + if (!(func_idx_const = I32_CONST(func_idx))) { + aot_set_last_error("llvm build const failed."); + goto fail; + } + + if (!(func_ptr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, OPQ_PTR_TYPE, + func_ctx->func_ptrs, &func_idx_const, 1, + "func_ptr_tmp"))) { + aot_set_last_error("llvm build inbounds gep failed."); + goto fail; + } + + if (!(func_ptr = + LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, + func_ptr, "func_ptr"))) { + aot_set_last_error("llvm build load failed."); + goto fail; + } + + if (!(func_ptr_type = LLVMPointerType( + func_ctxes[func_idx - import_func_count] + ->func_type, + 0))) { + aot_set_last_error("construct func ptr type failed."); + goto fail; + } + + if (!(func = LLVMBuildBitCast(comp_ctx->builder, func_ptr, + func_ptr_type, + "indirect_func"))) { + aot_set_last_error("llvm build bit cast failed."); + goto fail; + } +#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0) */ + } } } diff --git a/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp b/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp index d10be6f3..48d1486d 100644 --- a/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp +++ b/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp @@ -6,6 +6,7 @@ #include "jit_codegen.h" #include "jit_codecache.h" #include "jit_compiler.h" +#include "jit_frontend.h" #include "jit_dump.h" #include @@ -21,6 +22,9 @@ using namespace asmjit; static char *code_block_switch_to_jitted_from_interp = NULL; static char *code_block_return_to_interp_from_jitted = NULL; +#if WASM_ENABLE_LAZY_JIT != 0 +static char *code_block_compile_fast_jit_and_then_call = NULL; +#endif typedef enum { REG_EBP_IDX = 0, @@ -107,16 +111,17 @@ x86::Xmm regs_float[] = { int jit_codegen_interp_jitted_glue(void *exec_env, JitInterpSwitchInfo *info, - void *target) + uint32 func_idx, void *target) { - typedef int32 (*F)(const void *exec_env, void *info, const void *target); + typedef int32 (*F)(const void *exec_env, void *info, uint32 func_idx, + const void *target); union { F f; void *v; } u; u.v = code_block_switch_to_jitted_from_interp; - return u.f(exec_env, info, target); + return u.f(exec_env, info, func_idx, target); } #define PRINT_LINE() LOG_VERBOSE("\n", __LINE__) @@ -5870,6 +5875,7 @@ lower_callbc(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list, JitReg xmm0_f64_hreg = jit_reg_new(JIT_REG_KIND_F64, 0); JitReg ret_reg = *(jit_insn_opnd(insn, 0)); JitReg func_reg = *(jit_insn_opnd(insn, 2)); + JitReg func_idx = *(jit_insn_opnd(insn, 3)); JitReg src_reg; int32 func_reg_no; @@ -5880,6 +5886,15 @@ lower_callbc(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list, func_reg_no = jit_reg_no(func_reg); CHECK_I64_REG_NO(func_reg_no); + CHECK_KIND(func_idx, JIT_REG_KIND_I32); + if (jit_reg_is_const(func_idx)) { + imm.setValue(jit_cc_get_const_I32(cc, func_idx)); + a.mov(regs_i64[REG_RDX_IDX], imm); + } + else { + a.movzx(regs_i64[REG_RDX_IDX], regs_i32[jit_reg_no(func_idx)]); + } + node = (JmpInfo *)jit_malloc(sizeof(JmpInfo)); if (!node) GOTO_FAIL; @@ -6762,6 +6777,761 @@ fail: return return_value; } +#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 + +#define MAX_REG_INTS 6 +#define MAX_REG_FLOATS 8 + +void * +jit_codegen_compile_call_to_llvm_jit(const WASMType *func_type) +{ + const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info(); + x86::Gp reg_lp = x86::r10, reg_res = x86::r12; + x86::Gp reg_tmp_i64 = x86::r11, reg_tmp_i32 = x86::r11d; + /* the index of integer argument registers */ + uint8 reg_idx_of_int_args[] = { REG_RDI_IDX, REG_RSI_IDX, REG_RDX_IDX, + REG_RCX_IDX, REG_R8_IDX, REG_R9_IDX }; + uint32 n_ints = 0, n_fps = 0, n_stacks = 0, n_pushed; + uint32 int_reg_idx = 0, fp_reg_idx = 0, stack_arg_idx = 0; + uint32 off_to_lp = 0, off_to_res = 0, code_size, i; + uint32 param_count = func_type->param_count; + uint32 result_count = func_type->result_count; + uint32 ext_result_count; + char *code_buf, *stream; + Imm imm; + + JitErrorHandler err_handler; + Environment env(Arch::kX64); + CodeHolder code; + code.init(env); + code.setErrorHandler(&err_handler); + x86::Assembler a(&code); + + /* Load the llvm jit function pointer */ + { + /* r11 = exec_env->module_inst */ + x86::Mem m1(regs_i64[hreg_info->exec_env_hreg_index], + (uint32)offsetof(WASMExecEnv, module_inst)); + a.mov(reg_tmp_i64, m1); + /* r11 = module_inst->func_ptrs */ + x86::Mem m2(reg_tmp_i64, + (uint32)offsetof(WASMModuleInstance, func_ptrs)); + a.mov(reg_tmp_i64, m2); + /* rax = func_ptrs[func_idx] */ + x86::Mem m3(reg_tmp_i64, x86::rdx, 3, 0); + a.mov(x86::rax, m3); + } + + n_ints++; /* exec_env */ + + for (i = 0; i < param_count; i++) { + switch (func_type->types[i]) { + case VALUE_TYPE_I32: + case VALUE_TYPE_I64: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + if (n_ints < MAX_REG_INTS) + n_ints++; + else + n_stacks++; + break; + case VALUE_TYPE_F32: + case VALUE_TYPE_F64: + if (n_fps < MAX_REG_FLOATS) + n_fps++; + else + n_stacks++; + break; + } + } + + ext_result_count = result_count > 1 ? result_count - 1 : 0; + + if (ext_result_count > 0) { + if (n_ints + ext_result_count <= MAX_REG_INTS) { + /* extra result pointers can be stored into int registers */ + n_ints += ext_result_count; + } + else { + /* part or all extra result pointers must be stored into stack */ + n_stacks += n_ints + ext_result_count - MAX_REG_INTS; + n_ints = MAX_REG_INTS; + } + } + + n_pushed = n_stacks; + if (n_stacks & 1) { + /* Align stack on 16 bytes */ + n_pushed++; + } + if (n_pushed > 0) { + imm.setValue(n_pushed * 8); + a.sub(x86::rsp, imm); + } + + /* r10 = outs_area->lp */ + { + x86::Mem m(regs_i64[hreg_info->exec_env_hreg_index], + (uint32)offsetof(WASMExecEnv, wasm_stack.s.top)); + a.mov(reg_lp, m); + a.add(reg_lp, (uint32)offsetof(WASMInterpFrame, lp)); + } + + /* rdi = exec_env */ + a.mov(regs_i64[reg_idx_of_int_args[int_reg_idx++]], + regs_i64[hreg_info->exec_env_hreg_index]); + + for (i = 0; i < param_count; i++) { + x86::Mem m_src(reg_lp, off_to_lp); + + switch (func_type->types[i]) { + case VALUE_TYPE_I32: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + { + if (int_reg_idx < MAX_REG_INTS) { + a.mov(regs_i32[reg_idx_of_int_args[int_reg_idx]], m_src); + int_reg_idx++; + } + else { + a.mov(reg_tmp_i32, m_src); + x86::Mem m_dst(x86::rsp, stack_arg_idx * 8); + a.mov(m_dst, reg_tmp_i32); + stack_arg_idx++; + } + off_to_lp += 4; + break; + } + case VALUE_TYPE_I64: + { + if (int_reg_idx < MAX_REG_INTS) { + a.mov(regs_i64[reg_idx_of_int_args[int_reg_idx]], m_src); + int_reg_idx++; + } + else { + a.mov(reg_tmp_i64, m_src); + x86::Mem m_dst(x86::rsp, stack_arg_idx * 8); + a.mov(m_dst, reg_tmp_i64); + stack_arg_idx++; + } + off_to_lp += 8; + break; + } + case VALUE_TYPE_F32: + { + if (fp_reg_idx < MAX_REG_FLOATS) { + a.movss(regs_float[fp_reg_idx], m_src); + fp_reg_idx++; + } + else { + a.mov(reg_tmp_i32, m_src); + x86::Mem m_dst(x86::rsp, stack_arg_idx * 8); + a.mov(m_dst, reg_tmp_i32); + stack_arg_idx++; + } + off_to_lp += 4; + break; + } + case VALUE_TYPE_F64: + { + if (fp_reg_idx < MAX_REG_FLOATS) { + a.movsd(regs_float[fp_reg_idx], m_src); + fp_reg_idx++; + } + else { + a.mov(reg_tmp_i64, m_src); + x86::Mem m_dst(x86::rsp, stack_arg_idx * 8); + a.mov(m_dst, reg_tmp_i64); + stack_arg_idx++; + } + off_to_lp += 8; + break; + } + } + } + + if (result_count > 0) { + switch (func_type->types[param_count]) { + case VALUE_TYPE_I32: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + case VALUE_TYPE_F32: + off_to_res = 4; + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + off_to_res = 8; + break; + } + + /* r12 = cur_frame->sp */ + x86::Mem m(x86::rbp, (uint32)offsetof(WASMInterpFrame, sp)); + a.mov(reg_res, m); + + for (i = 0; i < ext_result_count; i++) { + x86::Mem m(reg_res, off_to_res); + + if (int_reg_idx < MAX_REG_INTS) { + a.lea(regs_i64[reg_idx_of_int_args[int_reg_idx]], m); + int_reg_idx++; + } + else { + a.lea(reg_tmp_i64, m); + x86::Mem m_dst(x86::rsp, stack_arg_idx * 8); + a.mov(m_dst, reg_tmp_i64); + stack_arg_idx++; + } + + switch (func_type->types[param_count + 1 + i]) { + case VALUE_TYPE_I32: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + case VALUE_TYPE_F32: + off_to_res += 4; + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + off_to_res += 8; + break; + } + } + } + + bh_assert(int_reg_idx == n_ints); + bh_assert(fp_reg_idx == n_fps); + bh_assert(stack_arg_idx == n_stacks); + + /* Call the llvm jit function */ + a.call(x86::rax); + + /* Check if there was exception thrown */ + { + /* r11 = exec_env->module_inst */ + x86::Mem m1(regs_i64[hreg_info->exec_env_hreg_index], + (uint32)offsetof(WASMExecEnv, module_inst)); + a.mov(reg_tmp_i64, m1); + /* module_inst->cur_exception */ + x86::Mem m2(reg_tmp_i64, + (uint32)offsetof(WASMModuleInstance, cur_exception)); + /* bl = module_inst->cur_exception[0] */ + a.mov(x86::bl, m2); + + /* cur_exception[0] == 0 ? */ + Imm imm((uint8)0); + a.cmp(x86::bl, imm); + /* If yes, jump to `Get function result and return` */ + imm.setValue(INT32_MAX); + a.je(imm); + + char *stream = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); + + /* If no, set eax to JIT_INTERP_ACTION_THROWN, and + jump to code_block_return_to_interp_from_jitted to + return to interpreter */ + imm.setValue(JIT_INTERP_ACTION_THROWN); + a.mov(x86::eax, imm); + imm.setValue(code_block_return_to_interp_from_jitted); + a.mov(x86::rsi, imm); + a.jmp(x86::rsi); + + char *stream_new = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); + + *(int32 *)(stream - 4) = (uint32)(stream_new - stream); + } + + /* Get function result and return */ + + if (result_count > 0 && func_type->types[param_count] != VALUE_TYPE_F32 + && func_type->types[param_count] != VALUE_TYPE_F64) { + a.mov(x86::rdx, x86::rax); + } + + if (off_to_res > 0) { + imm.setValue(off_to_res); + a.add(reg_res, imm); + /* cur_frame->sp = r12 */ + x86::Mem m(x86::rbp, (uint32)offsetof(WASMInterpFrame, sp)); + a.mov(m, reg_res); + } + + if (n_pushed > 0) { + imm.setValue(n_pushed * 8); + a.add(x86::rsp, imm); + } + + /* Return to the caller */ + { + /* eax = action = JIT_INTERP_ACTION_NORMAL */ + Imm imm(0); + a.mov(x86::eax, imm); + + uint32 jitted_return_addr_offset = + jit_frontend_get_jitted_return_addr_offset(); + x86::Mem m(x86::rbp, jitted_return_addr_offset); + a.jmp(m); + } + + if (err_handler.err) + return NULL; + + code_buf = (char *)code.sectionById(0)->buffer().data(); + code_size = code.sectionById(0)->buffer().size(); + stream = (char *)jit_code_cache_alloc(code_size); + if (!stream) + return NULL; + + bh_memcpy_s(stream, code_size, code_buf, code_size); + +#if 0 + dump_native(stream, code_size); +#endif + + return stream; +} + +static WASMInterpFrame * +fast_jit_alloc_frame(WASMExecEnv *exec_env, uint32 param_cell_num, + uint32 ret_cell_num) +{ + WASMModuleInstance *module_inst = + (WASMModuleInstance *)exec_env->module_inst; + WASMInterpFrame *frame; + uint32 size_frame1 = wasm_interp_interp_frame_size(ret_cell_num); + uint32 size_frame2 = wasm_interp_interp_frame_size(param_cell_num); + + /** + * Check whether we can allocate two frames: the first is an implied + * frame to store the function results from jit function to call, + * the second is the frame for the jit function + */ + if ((uint8 *)exec_env->wasm_stack.s.top + size_frame1 + size_frame2 + > exec_env->wasm_stack.s.top_boundary) { + wasm_set_exception(module_inst, "wasm operand stack overflow"); + return NULL; + } + + /* Allocate the frame */ + frame = (WASMInterpFrame *)exec_env->wasm_stack.s.top; + exec_env->wasm_stack.s.top += size_frame1; + + frame->function = NULL; + frame->ip = NULL; + frame->sp = frame->lp; + frame->prev_frame = wasm_exec_env_get_cur_frame(exec_env); + frame->jitted_return_addr = + (uint8 *)code_block_return_to_interp_from_jitted; + + wasm_exec_env_set_cur_frame(exec_env, frame); + + return frame; +} + +void * +jit_codegen_compile_call_to_fast_jit(const WASMModule *module, uint32 func_idx) +{ + uint32 func_idx_non_import = func_idx - module->import_function_count; + WASMType *func_type = module->functions[func_idx_non_import]->func_type; + /* the index of integer argument registers */ + uint8 reg_idx_of_int_args[] = { REG_RDI_IDX, REG_RSI_IDX, REG_RDX_IDX, + REG_RCX_IDX, REG_R8_IDX, REG_R9_IDX }; + uint32 int_reg_idx, fp_reg_idx, stack_arg_idx; + uint32 switch_info_offset, exec_env_offset, stack_arg_offset; + uint32 int_reg_offset, frame_lp_offset; + uint32 switch_info_size, code_size, i; + uint32 param_count = func_type->param_count; + uint32 result_count = func_type->result_count; + uint32 ext_result_count = result_count > 1 ? result_count - 1 : 0; + uint32 param_cell_num = func_type->param_cell_num; + uint32 ret_cell_num = + func_type->ret_cell_num > 2 ? func_type->ret_cell_num : 2; + char *code_buf, *stream; + Imm imm; + + JitErrorHandler err_handler; + Environment env(Arch::kX64); + CodeHolder code; + code.init(env); + code.setErrorHandler(&err_handler); + x86::Assembler a(&code); + + /** + * Push JitInterpSwitchInfo and make stack 16-byte aligned: + * the size pushed must be odd multiples of 8, as the stack pointer + * %rsp must be aligned to a 16-byte boundary before making a call, + * and when a function (including this llvm jit function) gets + * control, the %rsp is not 16-byte aligned (call instruction will + * push the ret address to stack). + */ + switch_info_size = align_uint((uint32)sizeof(JitInterpSwitchInfo), 16) + 8; + imm.setValue((uint64)switch_info_size); + a.sub(x86::rsp, imm); + + /* Push all integer argument registers since we will use them as + temporarily registers to load/store data */ + for (i = 0; i < MAX_REG_INTS; i++) { + a.push(regs_i64[reg_idx_of_int_args[MAX_REG_INTS - 1 - i]]); + } + + /* We don't push float/double register since we don't use them here */ + + /** + * Layout of the stack now: + * stack arguments + * ret address of the caller + * switch info + * int registers: r9, r8, rcx, rdx, rsi + * exec_env: rdi + */ + + /* offset of the first stack argument to the stack pointer, + add 8 to skip the ret address of the caller */ + stack_arg_offset = switch_info_size + 8 * MAX_REG_INTS + 8; + /* offset of jit interp switch info to the stack pointer */ + switch_info_offset = 8 * MAX_REG_INTS; + /* offset of the first int register to the stack pointer */ + int_reg_offset = 8; + /* offset of exec_env to the stack pointer */ + exec_env_offset = 0; + + /* Call fast_jit_alloc_frame to allocate the stack frame to + receive the results of the fast jit function to call */ + + /* rdi = exec_env, has been already set as exec_env is + the first argument of LLVM JIT function */ + /* rsi = param_cell_num */ + imm.setValue(param_cell_num); + a.mov(x86::rsi, imm); + /* rdx = ret_cell_num */ + imm.setValue(ret_cell_num); + a.mov(x86::rdx, imm); + /* call fast_jit_alloc_frame */ + imm.setValue((uint64)(uintptr_t)fast_jit_alloc_frame); + a.mov(x86::rax, imm); + a.call(x86::rax); + + /* Check the return value, note now rax is the allocated frame */ + { + /* Did fast_jit_alloc_frame return NULL? */ + Imm imm((uint64)0); + a.cmp(x86::rax, imm); + /* If no, jump to `Copy arguments to frame lp area` */ + imm.setValue(INT32_MAX); + a.jne(imm); + + char *stream = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); + + /* If yes, set eax to 0, return to caller */ + + /* Pop all integer arument registers */ + for (i = 0; i < MAX_REG_INTS; i++) { + a.pop(regs_i64[reg_idx_of_int_args[i]]); + } + /* Pop jit interp switch info */ + imm.setValue((uint64)switch_info_size); + a.add(x86::rsp, imm); + + /* Return to the caller, don't use leave as we didn't + `push rbp` and `mov rbp, rsp` */ + a.ret(); + + /* Patch the offset of jne instruction */ + char *stream_new = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); + *(int32 *)(stream - 4) = (int32)(stream_new - stream); + } + + int_reg_idx = 1; /* skip exec_env */ + fp_reg_idx = 0; + stack_arg_idx = 0; + + /* Offset of the dest arguments to outs area */ + frame_lp_offset = wasm_interp_interp_frame_size(ret_cell_num) + + (uint32)offsetof(WASMInterpFrame, lp); + + /* Copy arguments to frame lp area */ + for (i = 0; i < func_type->param_count; i++) { + x86::Mem m_dst(x86::rax, frame_lp_offset); + switch (func_type->types[i]) { + case VALUE_TYPE_I32: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + if (int_reg_idx < MAX_REG_INTS) { + /* Copy i32 argument from int register */ + x86::Mem m_src(x86::rsp, int_reg_offset); + a.mov(x86::esi, m_src); + a.mov(m_dst, x86::esi); + int_reg_offset += 8; + int_reg_idx++; + } + else { + /* Copy i32 argument from stack */ + x86::Mem m_src(x86::rsp, stack_arg_offset); + a.mov(x86::esi, m_src); + a.mov(m_dst, x86::esi); + stack_arg_offset += 8; + stack_arg_idx++; + } + frame_lp_offset += 4; + break; + case VALUE_TYPE_I64: + if (int_reg_idx < MAX_REG_INTS) { + /* Copy i64 argument from int register */ + x86::Mem m_src(x86::rsp, int_reg_offset); + a.mov(x86::rsi, m_src); + a.mov(m_dst, x86::rsi); + int_reg_offset += 8; + int_reg_idx++; + } + else { + /* Copy i64 argument from stack */ + x86::Mem m_src(x86::rsp, stack_arg_offset); + a.mov(x86::rsi, m_src); + a.mov(m_dst, x86::rsi); + stack_arg_offset += 8; + stack_arg_idx++; + } + frame_lp_offset += 8; + break; + case VALUE_TYPE_F32: + if (fp_reg_idx < MAX_REG_FLOATS) { + /* Copy f32 argument from fp register */ + a.movss(m_dst, regs_float[fp_reg_idx++]); + } + else { + /* Copy f32 argument from stack */ + x86::Mem m_src(x86::rsp, stack_arg_offset); + a.mov(x86::esi, m_src); + a.mov(m_dst, x86::esi); + stack_arg_offset += 8; + stack_arg_idx++; + } + frame_lp_offset += 4; + break; + case VALUE_TYPE_F64: + if (fp_reg_idx < MAX_REG_FLOATS) { + /* Copy f64 argument from fp register */ + a.movsd(m_dst, regs_float[fp_reg_idx++]); + } + else { + /* Copy f64 argument from stack */ + x86::Mem m_src(x86::rsp, stack_arg_offset); + a.mov(x86::rsi, m_src); + a.mov(m_dst, x86::rsi); + stack_arg_offset += 8; + stack_arg_idx++; + } + frame_lp_offset += 8; + break; + default: + bh_assert(0); + } + } + + /* Call the fast jit function */ + { + /* info = rsp + switch_info_offset */ + a.lea(x86::rsi, x86::ptr(x86::rsp, switch_info_offset)); + /* info.frame = frame = rax, or return of fast_jit_alloc_frame */ + x86::Mem m1(x86::rsi, (uint32)offsetof(JitInterpSwitchInfo, frame)); + a.mov(m1, x86::rax); + + /* Call code_block_switch_to_jitted_from_interp + with argument (exec_env, info, func_idx, pc) */ + /* rdi = exec_env */ + a.mov(x86::rdi, x86::ptr(x86::rsp, exec_env_offset)); + /* rsi = info, has been set */ + /* rdx = func_idx */ + imm.setValue(func_idx); + a.mov(x86::rdx, imm); + /* module_inst = exec_env->module_inst */ + a.mov(x86::rcx, + x86::ptr(x86::rdi, (uint32)offsetof(WASMExecEnv, module_inst))); + /* fast_jit_func_ptrs = module_inst->fast_jit_func_ptrs */ + a.mov(x86::rcx, + x86::ptr(x86::rcx, (uint32)offsetof(WASMModuleInstance, + fast_jit_func_ptrs))); + imm.setValue(func_idx_non_import); + a.mov(x86::rax, imm); + x86::Mem m3(x86::rcx, x86::rax, 3, 0); + /* rcx = module_inst->fast_jit_func_ptrs[func_idx_non_import] */ + a.mov(x86::rcx, m3); + + imm.setValue( + (uint64)(uintptr_t)code_block_switch_to_jitted_from_interp); + a.mov(x86::rax, imm); + a.call(x86::rax); + } + + /* No need to check exception thrown here as it will be checked + in the caller */ + + /* Copy function results */ + if (result_count > 0) { + frame_lp_offset = offsetof(WASMInterpFrame, lp); + + switch (func_type->types[param_count]) { + case VALUE_TYPE_I32: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + a.mov(x86::eax, x86::edx); + frame_lp_offset += 4; + break; + case VALUE_TYPE_I64: + a.mov(x86::rax, x86::rdx); + frame_lp_offset += 8; + break; + case VALUE_TYPE_F32: + /* The first result has been put to xmm0 */ + frame_lp_offset += 4; + break; + case VALUE_TYPE_F64: + /* The first result has been put to xmm0 */ + frame_lp_offset += 8; + break; + default: + bh_assert(0); + } + + /* Copy extra results from exec_env->cur_frame */ + if (ext_result_count > 0) { + /* rdi = exec_env */ + a.mov(x86::rdi, x86::ptr(x86::rsp, exec_env_offset)); + /* rsi = exec_env->cur_frame */ + a.mov(x86::rsi, + x86::ptr(x86::rdi, (uint32)offsetof(WASMExecEnv, cur_frame))); + + for (i = 0; i < ext_result_count; i++) { + switch (func_type->types[param_count + 1 + i]) { + case VALUE_TYPE_I32: +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: +#endif + case VALUE_TYPE_F32: + { + /* Copy 32-bit result */ + a.mov(x86::ecx, x86::ptr(x86::rsi, frame_lp_offset)); + if (int_reg_idx < MAX_REG_INTS) { + x86::Mem m1(x86::rsp, + exec_env_offset + int_reg_idx * 8); + a.mov(x86::rdx, m1); + x86::Mem m2(x86::rdx, 0); + a.mov(m2, x86::ecx); + int_reg_idx++; + } + else { + x86::Mem m1(x86::rsp, stack_arg_offset); + a.mov(x86::rdx, m1); + x86::Mem m2(x86::rdx, 0); + a.mov(m2, x86::ecx); + stack_arg_offset += 8; + stack_arg_idx++; + } + frame_lp_offset += 4; + break; + } + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + { + /* Copy 64-bit result */ + a.mov(x86::rcx, x86::ptr(x86::rsi, frame_lp_offset)); + if (int_reg_idx < MAX_REG_INTS) { + x86::Mem m1(x86::rsp, + exec_env_offset + int_reg_idx * 8); + a.mov(x86::rdx, m1); + x86::Mem m2(x86::rdx, 0); + a.mov(m2, x86::rcx); + int_reg_idx++; + } + else { + x86::Mem m1(x86::rsp, stack_arg_offset); + a.mov(x86::rdx, m1); + x86::Mem m2(x86::rdx, 0); + a.mov(m2, x86::rcx); + stack_arg_offset += 8; + stack_arg_idx++; + } + frame_lp_offset += 8; + break; + } + default: + bh_assert(0); + } + } + } + } + + /* Free the frame allocated */ + + /* rdi = exec_env */ + a.mov(x86::rdi, x86::ptr(x86::rsp, exec_env_offset)); + /* rsi = exec_env->cur_frame */ + a.mov(x86::rsi, + x86::ptr(x86::rdi, (uint32)offsetof(WASMExecEnv, cur_frame))); + /* rdx = exec_env->cur_frame->prev_frame */ + a.mov(x86::rdx, + x86::ptr(x86::rsi, (uint32)offsetof(WASMInterpFrame, prev_frame))); + /* exec_env->wasm_stack.s.top = cur_frame */ + { + x86::Mem m(x86::rdi, offsetof(WASMExecEnv, wasm_stack.s.top)); + a.mov(m, x86::rsi); + } + /* exec_env->cur_frame = prev_frame */ + { + x86::Mem m(x86::rdi, offsetof(WASMExecEnv, cur_frame)); + a.mov(m, x86::rdx); + } + + /* Pop all integer arument registers */ + for (i = 0; i < MAX_REG_INTS; i++) { + a.pop(regs_i64[reg_idx_of_int_args[i]]); + } + /* Pop jit interp switch info */ + imm.setValue((uint64)switch_info_size); + a.add(x86::rsp, imm); + + /* Return to the caller, don't use leave as we didn't + `push rbp` and `mov rbp, rsp` */ + a.ret(); + + if (err_handler.err) { + return NULL; + } + + code_buf = (char *)code.sectionById(0)->buffer().data(); + code_size = code.sectionById(0)->buffer().size(); + stream = (char *)jit_code_cache_alloc(code_size); + if (!stream) + return NULL; + + bh_memcpy_s(stream, code_size, code_buf, code_size); + +#if 0 + printf("Code of call to fast jit of func %u:\n", func_idx); + dump_native(stream, code_size); + printf("\n"); +#endif + + return stream; +} + +#endif /* end of WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 */ + bool jit_codegen_lower(JitCompContext *cc) { @@ -6803,6 +7573,8 @@ jit_codegen_init() code.setErrorHandler(&err_handler); x86::Assembler a(&code); + /* Initialize code_block_switch_to_jitted_from_interp */ + /* push callee-save registers */ a.push(x86::rbp); a.push(x86::rbx); @@ -6822,9 +7594,11 @@ jit_codegen_init() /* exec_env_reg = exec_env */ a.mov(regs_i64[hreg_info->exec_env_hreg_index], x86::rdi); /* fp_reg = info->frame */ - a.mov(x86::rbp, x86::ptr(x86::rsi, 0)); - /* jmp target */ - a.jmp(x86::rdx); + a.mov(x86::rbp, x86::ptr(x86::rsi, offsetof(JitInterpSwitchInfo, frame))); + /* rdx = func_idx, is already set in the func_idx argument of + jit_codegen_interp_jitted_glue */ + /* jmp target, rcx = pc */ + a.jmp(x86::rcx); if (err_handler.err) return false; @@ -6842,26 +7616,25 @@ jit_codegen_init() dump_native(stream, code_size); #endif - a.setOffset(0); + /* Initialize code_block_return_to_interp_from_jitted */ - /* TODO: mask floating-point exception */ - /* TODO: floating-point parameters */ + a.setOffset(0); /* pop info */ a.pop(x86::rsi); /* info->frame = fp_reg */ { - x86::Mem m(x86::rsi, 0); + x86::Mem m(x86::rsi, offsetof(JitInterpSwitchInfo, frame)); a.mov(m, x86::rbp); } - /* info->out.ret.ival[0, 1] = rcx */ + /* info->out.ret.ival[0, 1] = rdx */ { - x86::Mem m(x86::rsi, 8); + x86::Mem m(x86::rsi, offsetof(JitInterpSwitchInfo, out.ret.ival)); a.mov(m, x86::rdx); } /* info->out.ret.fval[0, 1] = xmm0 */ { - x86::Mem m(x86::rsi, 16); + x86::Mem m(x86::rsi, offsetof(JitInterpSwitchInfo, out.ret.fval)); a.movsd(m, x86::xmm0); } @@ -6884,12 +7657,125 @@ jit_codegen_init() goto fail1; bh_memcpy_s(stream, code_size, code_buf, code_size); - code_block_return_to_interp_from_jitted = stream; + code_block_return_to_interp_from_jitted = + jit_globals->return_to_interp_from_jitted = stream; + +#if 0 + dump_native(stream, code_size); +#endif + +#if WASM_ENABLE_LAZY_JIT != 0 + /* Initialize code_block_compile_fast_jit_and_then_call */ + + a.setOffset(0); + + /* Use rbx, r12, r13 to save func_dix, module_inst and module, + as they are callee-save registers */ + + /* Backup func_idx: rbx = rdx = func_idx, note that rdx has + been prepared in the caller: + callbc or code_block_switch_to_jitted_from_interp */ + a.mov(x86::rbx, x86::rdx); + /* r12 = module_inst = exec_env->module_inst */ + { + x86::Mem m(regs_i64[hreg_info->exec_env_hreg_index], + (uint32)offsetof(WASMExecEnv, module_inst)); + a.mov(x86::r12, m); + } + /* rdi = r13 = module_inst->module */ + { + x86::Mem m(x86::r12, (uint32)offsetof(WASMModuleInstance, module)); + a.mov(x86::rdi, m); + a.mov(x86::r13, x86::rdi); + } + /* rsi = rdx = func_idx */ + a.mov(x86::rsi, x86::rdx); + /* Call jit_compiler_compile(module, func_idx) */ + { + Imm imm((uint64)(uintptr_t)jit_compiler_compile); + a.mov(x86::rax, imm); + a.call(x86::rax); + } + + /* Check if failed to compile the jit function */ + { + /* Did jit_compiler_compile return false? */ + Imm imm((uint8)0); + a.cmp(x86::al, imm); + /* If no, jump to `Load compiled func ptr and call it` */ + imm.setValue(INT32_MAX); + a.jne(imm); + + char *stream = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); + + /* If yes, call jit_set_exception_with_id to throw exception, + and then set eax to JIT_INTERP_ACTION_THROWN, and jump to + code_block_return_to_interp_from_jitted to return */ + + /* rdi = module_inst */ + a.mov(x86::rdi, x86::r12); + /* rsi = EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */ + imm.setValue(EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC); + a.mov(x86::rsi, imm); + /* Call jit_set_exception_with_id */ + imm.setValue((uint64)(uintptr_t)jit_set_exception_with_id); + a.mov(x86::rax, imm); + a.call(x86::rax); + /* Return to the caller */ + imm.setValue(JIT_INTERP_ACTION_THROWN); + a.mov(x86::eax, imm); + imm.setValue(code_block_return_to_interp_from_jitted); + a.mov(x86::rsi, imm); + a.jmp(x86::rsi); + + /* Patch the offset of jne instruction */ + char *stream_new = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); + *(int32 *)(stream - 4) = (int32)(stream_new - stream); + } + + /* Load compiled func ptr and call it */ + { + /* rsi = module->import_function_count */ + x86::Mem m1(x86::r13, + (uint32)offsetof(WASMModule, import_function_count)); + a.movzx(x86::rsi, m1); + /* rbx = rbx - module->import_function_count */ + a.sub(x86::rbx, x86::rsi); + /* rax = module->fast_jit_func_ptrs */ + x86::Mem m2(x86::r13, (uint32)offsetof(WASMModule, fast_jit_func_ptrs)); + a.mov(x86::rax, m2); + /* rax = fast_jit_func_ptrs[rbx] */ + x86::Mem m3(x86::rax, x86::rbx, 3, 0); + a.mov(x86::rax, m3); + a.jmp(x86::rax); + } + + if (err_handler.err) + goto fail2; + + code_buf = (char *)code.sectionById(0)->buffer().data(); + code_size = code.sectionById(0)->buffer().size(); + stream = (char *)jit_code_cache_alloc(code_size); + if (!stream) + goto fail2; + + bh_memcpy_s(stream, code_size, code_buf, code_size); + code_block_compile_fast_jit_and_then_call = + jit_globals->compile_fast_jit_and_then_call = stream; + +#if 0 + dump_native(stream, code_size); +#endif +#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */ - jit_globals->return_to_interp_from_jitted = - code_block_return_to_interp_from_jitted; return true; +#if WASM_ENABLE_LAZY_JIT != 0 +fail2: + jit_code_cache_free(code_block_return_to_interp_from_jitted); +#endif fail1: jit_code_cache_free(code_block_switch_to_jitted_from_interp); return false; @@ -6898,8 +7784,11 @@ fail1: void jit_codegen_destroy() { - jit_code_cache_free(code_block_switch_to_jitted_from_interp); +#if WASM_ENABLE_LAZY_JIT != 0 + jit_code_cache_free(code_block_compile_fast_jit_and_then_call); +#endif jit_code_cache_free(code_block_return_to_interp_from_jitted); + jit_code_cache_free(code_block_switch_to_jitted_from_interp); } /* clang-format off */ diff --git a/core/iwasm/fast-jit/fe/jit_emit_function.c b/core/iwasm/fast-jit/fe/jit_emit_function.c index ce22a950..a89f2ff5 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_function.c +++ b/core/iwasm/fast-jit/fe/jit_emit_function.c @@ -409,7 +409,7 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call) res = create_first_res_reg(cc, func_type); - GEN_INSN(CALLBC, res, 0, jitted_code); + GEN_INSN(CALLBC, res, 0, jitted_code, NEW_CONST(I32, func_idx)); if (!post_return(cc, func_type, res, true)) { goto fail; @@ -700,7 +700,7 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx, goto fail; } } - GEN_INSN(CALLBC, res, 0, jitted_code); + GEN_INSN(CALLBC, res, 0, jitted_code, func_idx); /* Store res into current frame, so that post_return in block func_return can get the value */ n = cc->jit_frame->sp - cc->jit_frame->lp; diff --git a/core/iwasm/fast-jit/jit_codecache.c b/core/iwasm/fast-jit/jit_codecache.c index 4c899ad9..66c2d033 100644 --- a/core/iwasm/fast-jit/jit_codecache.c +++ b/core/iwasm/fast-jit/jit_codecache.c @@ -58,8 +58,7 @@ jit_pass_register_jitted_code(JitCompContext *cc) { uint32 jit_func_idx = cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count; - cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin; cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] = - cc->jitted_addr_begin; + cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin; return true; } diff --git a/core/iwasm/fast-jit/jit_codegen.h b/core/iwasm/fast-jit/jit_codegen.h index 666a239a..735cddab 100644 --- a/core/iwasm/fast-jit/jit_codegen.h +++ b/core/iwasm/fast-jit/jit_codegen.h @@ -65,6 +65,14 @@ jit_codegen_gen_native(JitCompContext *cc); bool jit_codegen_lower(JitCompContext *cc); +#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 +void * +jit_codegen_compile_call_to_llvm_jit(const WASMType *func_type); + +void * +jit_codegen_compile_call_to_fast_jit(const WASMModule *module, uint32 func_idx); +#endif + /** * Dump native code in the given range to assembly. * @@ -75,7 +83,8 @@ void jit_codegen_dump_native(void *begin_addr, void *end_addr); int -jit_codegen_interp_jitted_glue(void *self, JitInterpSwitchInfo *info, void *pc); +jit_codegen_interp_jitted_glue(void *self, JitInterpSwitchInfo *info, + uint32 func_idx, void *pc); #ifdef __cplusplus } diff --git a/core/iwasm/fast-jit/jit_compiler.c b/core/iwasm/fast-jit/jit_compiler.c index c10a4099..67dcb7b5 100644 --- a/core/iwasm/fast-jit/jit_compiler.c +++ b/core/iwasm/fast-jit/jit_compiler.c @@ -10,9 +10,9 @@ #include "../interpreter/wasm.h" typedef struct JitCompilerPass { - /* Name of the pass. */ + /* Name of the pass */ const char *name; - /* The entry of the compiler pass. */ + /* The entry of the compiler pass */ bool (*run)(JitCompContext *cc); } JitCompilerPass; @@ -30,7 +30,7 @@ static JitCompilerPass compiler_passes[] = { #undef REG_PASS }; -/* Number of compiler passes. */ +/* Number of compiler passes */ #define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0])) #if WASM_ENABLE_FAST_JIT_DUMP == 0 @@ -43,14 +43,17 @@ static const uint8 compiler_passes_with_dump[] = { }; #endif -/* The exported global data of JIT compiler. */ +/* The exported global data of JIT compiler */ static JitGlobals jit_globals = { #if WASM_ENABLE_FAST_JIT_DUMP == 0 .passes = compiler_passes_without_dump, #else .passes = compiler_passes_with_dump, #endif - .return_to_interp_from_jitted = NULL + .return_to_interp_from_jitted = NULL, +#if WASM_ENABLE_LAZY_JIT != 0 + .compile_fast_jit_and_then_call = NULL, +#endif }; /* clang-format on */ @@ -60,7 +63,7 @@ apply_compiler_passes(JitCompContext *cc) const uint8 *p = jit_globals.passes; for (; *p; p++) { - /* Set the pass NO. */ + /* Set the pass NO */ cc->cur_pass_no = p - jit_globals.passes; bh_assert(*p < COMPILER_PASS_NUM); @@ -120,37 +123,53 @@ jit_compiler_get_pass_name(unsigned i) bool jit_compiler_compile(WASMModule *module, uint32 func_idx) { - JitCompContext *cc; + JitCompContext *cc = NULL; char *last_error; - bool ret = true; + bool ret = false; + uint32 i = func_idx - module->import_function_count; + uint32 j = i % WASM_ORC_JIT_BACKEND_THREAD_NUM; - /* Initialize compilation context. */ - if (!(cc = jit_calloc(sizeof(*cc)))) - return false; + /* Lock to avoid duplicated compilation by other threads */ + os_mutex_lock(&module->fast_jit_thread_locks[j]); + + if (jit_compiler_is_compiled(module, func_idx)) { + /* Function has been compiled */ + os_mutex_unlock(&module->fast_jit_thread_locks[j]); + return true; + } + + /* Initialize the compilation context */ + if (!(cc = jit_calloc(sizeof(*cc)))) { + goto fail; + } if (!jit_cc_init(cc, 64)) { - jit_free(cc); - return false; + goto fail; } cc->cur_wasm_module = module; - cc->cur_wasm_func = - module->functions[func_idx - module->import_function_count]; + cc->cur_wasm_func = module->functions[i]; cc->cur_wasm_func_idx = func_idx; cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow && !cc->cur_wasm_func->has_op_func_call) || (!module->possible_memory_grow); - /* Apply compiler passes. */ + /* Apply compiler passes */ if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) { last_error = jit_get_last_error(cc); os_printf("fast jit compilation failed: %s\n", last_error ? last_error : "unknown error"); - ret = false; + goto fail; } - /* Delete the compilation context. */ - jit_cc_delete(cc); + ret = true; + +fail: + /* Destroy the compilation context */ + if (cc) + jit_cc_delete(cc); + + os_mutex_unlock(&module->fast_jit_thread_locks[j]); return ret; } @@ -169,8 +188,92 @@ jit_compiler_compile_all(WASMModule *module) return true; } -int -jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info, void *pc) +bool +jit_compiler_is_compiled(const WASMModule *module, uint32 func_idx) { - return jit_codegen_interp_jitted_glue(exec_env, info, pc); + uint32 i = func_idx - module->import_function_count; + + bh_assert(func_idx >= module->import_function_count + && func_idx + < module->import_function_count + module->function_count); + +#if WASM_ENABLE_LAZY_JIT == 0 + return module->fast_jit_func_ptrs[i] ? true : false; +#else + return module->fast_jit_func_ptrs[i] + != jit_globals.compile_fast_jit_and_then_call + ? true + : false; +#endif +} + +#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 +bool +jit_compiler_set_call_to_llvm_jit(WASMModule *module, uint32 func_idx) +{ + uint32 i = func_idx - module->import_function_count; + uint32 j = i % WASM_ORC_JIT_BACKEND_THREAD_NUM; + WASMType *func_type = module->functions[i]->func_type; + uint32 k = + ((uint32)(uintptr_t)func_type >> 3) % WASM_ORC_JIT_BACKEND_THREAD_NUM; + void *func_ptr = NULL; + + /* Compile code block of call_to_llvm_jit_from_fast_jit of + this kind of function type if it hasn't been compiled */ + if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit)) { + os_mutex_lock(&module->fast_jit_thread_locks[k]); + if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit)) { + if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit = + jit_codegen_compile_call_to_llvm_jit(func_type))) { + os_mutex_unlock(&module->fast_jit_thread_locks[k]); + return false; + } + } + os_mutex_unlock(&module->fast_jit_thread_locks[k]); + } + + /* Switch current fast jit func ptr to the code block */ + os_mutex_lock(&module->fast_jit_thread_locks[j]); + module->fast_jit_func_ptrs[i] = func_ptr; + os_mutex_unlock(&module->fast_jit_thread_locks[j]); + return true; +} + +bool +jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx) +{ + void *func_ptr = NULL; + + func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx); + if (func_ptr) { + jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr); + } + + return func_ptr ? true : false; +} + +void +jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx, + void *func_ptr) +{ + WASMModuleInstance *instance; + uint32 i = func_idx - module->import_function_count; + + module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i] = func_ptr; + + os_mutex_lock(&module->instance_list_lock); + instance = module->instance_list; + while (instance) { + instance->func_ptrs[func_idx] = func_ptr; + instance = instance->e->next; + } + os_mutex_unlock(&module->instance_list_lock); +} +#endif /* end of WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 */ + +int +jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info, + uint32 func_idx, void *pc) +{ + return jit_codegen_interp_jitted_glue(exec_env, info, func_idx, pc); } diff --git a/core/iwasm/fast-jit/jit_compiler.h b/core/iwasm/fast-jit/jit_compiler.h index 602494db..9a49cffd 100644 --- a/core/iwasm/fast-jit/jit_compiler.h +++ b/core/iwasm/fast-jit/jit_compiler.h @@ -18,6 +18,9 @@ typedef struct JitGlobals { /* Compiler pass sequence, the last element must be 0 */ const uint8 *passes; char *return_to_interp_from_jitted; +#if WASM_ENABLE_LAZY_JIT != 0 + char *compile_fast_jit_and_then_call; +#endif } JitGlobals; /** @@ -87,8 +90,24 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx); bool jit_compiler_compile_all(WASMModule *module); +bool +jit_compiler_is_compiled(const WASMModule *module, uint32 func_idx); + +#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 +bool +jit_compiler_set_call_to_llvm_jit(WASMModule *module, uint32 func_idx); + +bool +jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx); + +void +jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx, + void *func_ptr); +#endif + int -jit_interp_switch_to_jitted(void *self, JitInterpSwitchInfo *info, void *pc); +jit_interp_switch_to_jitted(void *self, JitInterpSwitchInfo *info, + uint32 func_idx, void *pc); /* * Pass declarations: diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index 995bfb80..b20be960 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -2255,6 +2255,12 @@ jit_frontend_translate_func(JitCompContext *cc) return basic_block_entry; } +uint32 +jit_frontend_get_jitted_return_addr_offset() +{ + return (uint32)offsetof(WASMInterpFrame, jitted_return_addr); +} + #if 0 #if WASM_ENABLE_THREAD_MGR != 0 bool diff --git a/core/iwasm/fast-jit/jit_frontend.h b/core/iwasm/fast-jit/jit_frontend.h index d706c90b..fce8ecfd 100644 --- a/core/iwasm/fast-jit/jit_frontend.h +++ b/core/iwasm/fast-jit/jit_frontend.h @@ -13,6 +13,10 @@ #include "../aot/aot_runtime.h" #endif +#ifdef __cplusplus +extern "C" { +#endif + #if WASM_ENABLE_AOT == 0 typedef enum IntCond { INT_EQZ = 0, @@ -143,6 +147,9 @@ jit_frontend_translate_func(JitCompContext *cc); bool jit_frontend_lower(JitCompContext *cc); +uint32 +jit_frontend_get_jitted_return_addr_offset(); + uint32 jit_frontend_get_global_data_offset(const WASMModule *module, uint32 global_idx); @@ -483,4 +490,8 @@ set_local_f64(JitFrame *frame, int n, JitReg val) #define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF) #define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF) +#ifdef __cplusplus +} +#endif + #endif diff --git a/core/iwasm/fast-jit/jit_ir.def b/core/iwasm/fast-jit/jit_ir.def index d1684332..8a4396da 100644 --- a/core/iwasm/fast-jit/jit_ir.def +++ b/core/iwasm/fast-jit/jit_ir.def @@ -196,7 +196,7 @@ INSN(LOOKUPSWITCH, LookupSwitch, 1, 0) /* Call and return instructions */ INSN(CALLNATIVE, VReg, 2, 1) -INSN(CALLBC, Reg, 3, 2) +INSN(CALLBC, Reg, 4, 2) INSN(RETURNBC, Reg, 3, 0) INSN(RETURN, Reg, 1, 0) diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 58305a7f..7efa6d5f 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -124,6 +124,12 @@ typedef struct WASMType { uint16 param_cell_num; uint16 ret_cell_num; uint16 ref_count; +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + /* Code block to call llvm jit functions of this + kind of function type from fast jit jitted code */ + void *call_to_llvm_jit_from_fast_jit; +#endif /* types of params and results */ uint8 types[1]; } WASMType; @@ -255,13 +261,6 @@ struct WASMFunction { uint32 const_cell_num; #endif -#if WASM_ENABLE_FAST_JIT != 0 - void *fast_jit_jitted_code; -#endif -#if WASM_ENABLE_JIT != 0 - void *llvm_jit_func_ptr; -#endif - #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ || WASM_ENABLE_WAMR_COMPILER != 0 /* Whether function has opcode memory.grow */ @@ -277,6 +276,13 @@ struct WASMFunction { /* Whether function has opcode set_global_aux_stack */ bool has_op_set_global_aux_stack; #endif + +#if WASM_ENABLE_FAST_JIT != 0 + void *fast_jit_jitted_code; +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + void *llvm_jit_func_ptr; +#endif +#endif }; struct WASMGlobal { @@ -377,18 +383,22 @@ typedef struct WASMCustomSection { } WASMCustomSection; #endif -#if WASM_ENABLE_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 struct AOTCompData; struct AOTCompContext; /* Orc JIT thread arguments */ typedef struct OrcJitThreadArg { +#if WASM_ENABLE_JIT != 0 struct AOTCompContext *comp_ctx; +#endif struct WASMModule *module; uint32 group_idx; } OrcJitThreadArg; #endif +struct WASMModuleInstance; + struct WASMModule { /* Module type, for module loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode; @@ -495,18 +505,22 @@ struct WASMModule { uint64 load_size; #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ + && WASM_ENABLE_LAZY_JIT != 0) /** - * Count how many instances reference this module. When source - * debugging feature enabled, the debugger may modify the code - * section of the module, so we need to report a warning if user - * create several instances based on the same module + * List of instances referred to this module. When source debugging + * feature is enabled, the debugger may modify the code section of + * the module, so we need to report a warning if user create several + * instances based on the same module. Sub instances created by + * lib-pthread or spawn API won't be added into the list. * - * Sub_instances created by lib-pthread or spawn API will not - * influence or check the ref count + * Also add the instance to the list for Fast JIT to LLVM JIT + * tier-up, since we need to lazily update the LLVM func pointers + * in the instance. */ - uint32 ref_count; - korp_mutex ref_count_lock; + struct WASMModuleInstance *instance_list; + korp_mutex instance_list_lock; #endif #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 @@ -521,6 +535,9 @@ struct WASMModule { #if WASM_ENABLE_FAST_JIT != 0 /* func pointers of Fast JITed (un-imported) functions */ void **fast_jit_func_ptrs; + /* locks for Fast JIT lazy compilation */ + korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM]; + bool fast_jit_thread_locks_inited[WASM_ORC_JIT_BACKEND_THREAD_NUM]; #endif #if WASM_ENABLE_JIT != 0 @@ -530,9 +547,27 @@ struct WASMModule { void **func_ptrs; /* whether the func pointers are compiled */ bool *func_ptrs_compiled; - bool orcjit_stop_compiling; +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 + /* backend compilation threads */ korp_tid orcjit_threads[WASM_ORC_JIT_BACKEND_THREAD_NUM]; + /* backend thread arguments */ OrcJitThreadArg orcjit_thread_args[WASM_ORC_JIT_BACKEND_THREAD_NUM]; + /* whether to stop the compilation of backend threads */ + bool orcjit_stop_compiling; +#endif + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + /* wait lock/cond for the synchronization of + the llvm jit initialization */ + korp_mutex tierup_wait_lock; + korp_cond tierup_wait_cond; + bool tierup_wait_lock_inited; + korp_tid llvm_jit_init_thread; + /* whether the llvm jit is initialized */ + bool llvm_jit_inited; #endif }; diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 5fe81438..fa542b14 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -3947,28 +3947,48 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_FAST_JIT != 0 static void -fast_jit_call_func_bytecode(WASMExecEnv *exec_env, +fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, + WASMExecEnv *exec_env, WASMFunctionInstance *function, WASMInterpFrame *frame) { JitGlobals *jit_globals = jit_compiler_get_jit_globals(); JitInterpSwitchInfo info; + WASMModule *module = module_inst->module; WASMType *func_type = function->u.func->func_type; uint8 type = func_type->result_count ? func_type->types[func_type->param_count] : VALUE_TYPE_VOID; + uint32 func_idx = (uint32)(function - module_inst->e->functions); + uint32 func_idx_non_import = func_idx - module->import_function_count; + int32 action; #if WASM_ENABLE_REF_TYPES != 0 if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF) type = VALUE_TYPE_I32; #endif +#if WASM_ENABLE_LAZY_JIT != 0 + if (!jit_compiler_compile(module, func_idx)) { + wasm_set_exception(module_inst, "failed to compile fast jit function"); + return; + } +#endif + bh_assert(jit_compiler_is_compiled(module, func_idx)); + + /* Switch to jitted code to call the jit function */ info.out.ret.last_return_type = type; info.frame = frame; frame->jitted_return_addr = (uint8 *)jit_globals->return_to_interp_from_jitted; - jit_interp_switch_to_jitted(exec_env, &info, - function->u.func->fast_jit_jitted_code); + action = jit_interp_switch_to_jitted( + exec_env, &info, func_idx, + module_inst->fast_jit_func_ptrs[func_idx_non_import]); + bh_assert(action == JIT_INTERP_ACTION_NORMAL + || (action == JIT_INTERP_ACTION_THROWN + && wasm_runtime_get_exception(exec_env->module_inst))); + + /* Get the return values form info.out.ret */ if (func_type->result_count) { switch (type) { case VALUE_TYPE_I32: @@ -3992,8 +4012,10 @@ fast_jit_call_func_bytecode(WASMExecEnv *exec_env, break; } } + (void)action; + (void)func_idx; } -#endif +#endif /* end of WASM_ENABLE_FAST_JIT != 0 */ #if WASM_ENABLE_JIT != 0 static bool @@ -4023,11 +4045,13 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, WASMType *func_type = function->u.func->func_type; uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; + uint32 func_idx = (uint32)(function - module_inst->e->functions); bool ret; #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0) if (!llvm_jit_alloc_frame(exec_env, function - module_inst->e->functions)) { - wasm_set_exception(module_inst, "wasm operand stack overflow"); + /* wasm operand stack overflow has been thrown, + no need to throw again */ return false; } #endif @@ -4069,8 +4093,8 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, } ret = wasm_runtime_invoke_native( - exec_env, function->u.func->llvm_jit_func_ptr, func_type, NULL, - NULL, argv1, argc, argv); + exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, + argv1, argc, argv); if (!ret || wasm_get_exception(module_inst)) { if (clear_wasi_proc_exit_exception(module_inst)) @@ -4120,8 +4144,8 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, } else { ret = wasm_runtime_invoke_native( - exec_env, function->u.func->llvm_jit_func_ptr, func_type, NULL, - NULL, argv, argc, argv); + exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, + argv, argc, argv); if (clear_wasi_proc_exit_exception(module_inst)) ret = true; @@ -4129,7 +4153,7 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, return ret && !wasm_get_exception(module_inst) ? true : false; } } -#endif +#endif /* end of WASM_ENABLE_JIT != 0 */ void wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, @@ -4202,18 +4226,63 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } } else { -#if WASM_ENABLE_JIT != 0 +#if WASM_ENABLE_LAZY_JIT != 0 + + /* Fast JIT to LLVM JIT tier-up is enabled */ +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 + /* Fast JIT and LLVM JIT are both enabled, call llvm jit function + if it is compiled, else call fast jit function */ + uint32 func_idx = (uint32)(function - module_inst->e->functions); + if (module_inst->module->func_ptrs_compiled + [func_idx - module_inst->module->import_function_count]) { + llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, + argv); + /* For llvm jit, the results have been stored in argv, + no need to copy them from stack frame again */ + copy_argv_from_frame = false; + } + else { + fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); + } +#elif WASM_ENABLE_JIT != 0 + /* Only LLVM JIT is enabled */ llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, argv); /* For llvm jit, the results have been stored in argv, no need to copy them from stack frame again */ copy_argv_from_frame = false; #elif WASM_ENABLE_FAST_JIT != 0 - fast_jit_call_func_bytecode(exec_env, function, frame); + /* Only Fast JIT is enabled */ + fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); #else + /* Both Fast JIT and LLVM JIT are disabled */ wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); #endif + +#else /* else of WASM_ENABLE_LAZY_JIT != 0 */ + + /* Fast JIT to LLVM JIT tier-up is enabled */ +#if WASM_ENABLE_JIT != 0 + /* LLVM JIT is enabled */ + llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, + argv); + /* For llvm jit, the results have been stored in argv, + no need to copy them from stack frame again */ + copy_argv_from_frame = false; +#elif WASM_ENABLE_FAST_JIT != 0 + /* Fast JIT is enabled */ + fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); +#else + /* Both Fast JIT and LLVM JIT are disabled */ + wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); +#endif + +#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */ + (void)wasm_interp_call_func_bytecode; +#if WASM_ENABLE_FAST_JIT != 0 + (void)fast_jit_call_func_bytecode; +#endif } /* Output the return value to the caller */ diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index a74780d9..ef7df8e0 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -428,6 +428,12 @@ destroy_wasm_type(WASMType *type) return; } +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + if (type->call_to_llvm_jit_from_fast_jit) + jit_code_cache_free(type->call_to_llvm_jit_from_fast_jit); +#endif + wasm_runtime_free(type); } @@ -2925,93 +2931,78 @@ calculate_global_data_offset(WASMModule *module) module->global_data_size = data_offset; } -#if WASM_ENABLE_JIT != 0 -static void * -orcjit_thread_callback(void *arg) -{ - LLVMOrcJITTargetAddress func_addr = 0; - OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg; - AOTCompContext *comp_ctx = thread_arg->comp_ctx; - WASMModule *module = thread_arg->module; - uint32 group_idx = thread_arg->group_idx; - uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM; - uint32 func_count = module->function_count; - uint32 i, j; - typedef void (*F)(void); - LLVMErrorRef error; - char func_name[48]; - union { - F f; - void *v; - } u; - - /* Compile jit functions of this group */ - for (i = group_idx; i < func_count; - i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) { - snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i, - "_wrapper"); - LOG_DEBUG("compile func %s", func_name); - error = - LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name); - if (error != LLVMErrorSuccess) { - char *err_msg = LLVMGetErrorMessage(error); - os_printf("failed to compile orc jit function: %s\n", err_msg); - LLVMDisposeErrorMessage(err_msg); - continue; - } - - /* Call the jit wrapper function to trigger its compilation, so as - to compile the actual jit functions, since we add the latter to - function list in the PartitionFunction callback */ - u.v = (void *)func_addr; - u.f(); - - for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) { - if (i + j * group_stride < func_count) - module->func_ptrs_compiled[i + j * group_stride] = true; - } - - if (module->orcjit_stop_compiling) { - break; - } - } - - return NULL; -} - -static void -orcjit_stop_compile_threads(WASMModule *module) -{ - uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args) - / sizeof(OrcJitThreadArg)); - - module->orcjit_stop_compiling = true; - for (i = 0; i < thread_num; i++) { - if (module->orcjit_threads[i]) - os_thread_join(module->orcjit_threads[i], NULL); - } -} - +#if WASM_ENABLE_FAST_JIT != 0 static bool -compile_llvm_jit_functions(WASMModule *module, char *error_buf, - uint32 error_buf_size) +init_fast_jit_functions(WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ +#if WASM_ENABLE_LAZY_JIT != 0 + JitGlobals *jit_globals = jit_compiler_get_jit_globals(); +#endif + uint32 i; + + if (!module->function_count) + return true; + + if (!(module->fast_jit_func_ptrs = + loader_malloc(sizeof(void *) * module->function_count, error_buf, + error_buf_size))) { + return false; + } + +#if WASM_ENABLE_LAZY_JIT != 0 + for (i = 0; i < module->function_count; i++) { + module->fast_jit_func_ptrs[i] = + jit_globals->compile_fast_jit_and_then_call; + } +#endif + + for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) { + if (os_mutex_init(&module->fast_jit_thread_locks[i]) != 0) { + set_error_buf(error_buf, error_buf_size, + "init fast jit thread lock failed"); + return false; + } + module->fast_jit_thread_locks_inited[i] = true; + } + + return true; +} +#endif /* end of WASM_ENABLE_FAST_JIT != 0 */ + +#if WASM_ENABLE_JIT != 0 +static bool +init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, + uint32 error_buf_size) { AOTCompOption option = { 0 }; char *aot_last_error; uint64 size; - uint32 thread_num, i; - if (module->function_count > 0) { - size = sizeof(void *) * (uint64)module->function_count - + sizeof(bool) * (uint64)module->function_count; - if (!(module->func_ptrs = - loader_malloc(size, error_buf, error_buf_size))) { - return false; - } - module->func_ptrs_compiled = - (bool *)((uint8 *)module->func_ptrs - + sizeof(void *) * module->function_count); + if (module->function_count == 0) + return true; + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LLVM_JIT != 0 + if (os_mutex_init(&module->tierup_wait_lock) != 0) { + set_error_buf(error_buf, error_buf_size, "init jit tierup lock failed"); + return false; } + if (os_cond_init(&module->tierup_wait_cond) != 0) { + set_error_buf(error_buf, error_buf_size, "init jit tierup cond failed"); + os_mutex_destroy(&module->tierup_wait_lock); + return false; + } + module->tierup_wait_lock_inited = true; +#endif + + size = sizeof(void *) * (uint64)module->function_count + + sizeof(bool) * (uint64)module->function_count; + if (!(module->func_ptrs = loader_malloc(size, error_buf, error_buf_size))) { + return false; + } + module->func_ptrs_compiled = + (bool *)((uint8 *)module->func_ptrs + + sizeof(void *) * module->function_count); module->comp_data = aot_create_comp_data(module); if (!module->comp_data) { @@ -3052,6 +3043,19 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, return false; } + return true; +} + +static bool +init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ + char *aot_last_error; + uint32 i; + + if (module->function_count == 0) + return true; + if (!aot_compile_wasm(module->comp_ctx)) { aot_last_error = aot_get_last_error(); bh_assert(aot_last_error != NULL); @@ -3059,7 +3063,12 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, return false; } - bh_print_time("Begin to lookup jit functions"); +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + if (module->orcjit_stop_compiling) + return false; +#endif + + bh_print_time("Begin to lookup llvm jit functions"); for (i = 0; i < module->function_count; i++) { LLVMOrcJITTargetAddress func_addr = 0; @@ -3072,7 +3081,7 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, if (error != LLVMErrorSuccess) { char *err_msg = LLVMGetErrorMessage(error); set_error_buf_v(error_buf, error_buf_size, - "failed to compile orc jit function: %s", err_msg); + "failed to compile llvm jit function: %s", err_msg); LLVMDisposeErrorMessage(err_msg); return false; } @@ -3084,17 +3093,211 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, * loading/storing at the same time. */ module->func_ptrs[i] = (void *)func_addr; - module->functions[i]->llvm_jit_func_ptr = (void *)func_addr; + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + if (module->orcjit_stop_compiling) + return false; +#endif } + bh_print_time("End lookup llvm jit functions"); + + return true; +} +#endif /* end of WASM_ENABLE_JIT != 0 */ + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 +static void * +init_llvm_jit_functions_stage2_callback(void *arg) +{ + WASMModule *module = (WASMModule *)arg; + char error_buf[128]; + uint32 error_buf_size = (uint32)sizeof(error_buf); + + if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) { + module->orcjit_stop_compiling = true; + return NULL; + } + + os_mutex_lock(&module->tierup_wait_lock); + module->llvm_jit_inited = true; + os_cond_broadcast(&module->tierup_wait_cond); + os_mutex_unlock(&module->tierup_wait_lock); + + return NULL; +} +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 +/* The callback function to compile jit functions */ +static void * +orcjit_thread_callback(void *arg) +{ + OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg; +#if WASM_ENABLE_JIT != 0 + AOTCompContext *comp_ctx = thread_arg->comp_ctx; +#endif + WASMModule *module = thread_arg->module; + uint32 group_idx = thread_arg->group_idx; + uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM; + uint32 func_count = module->function_count; + uint32 i; + +#if WASM_ENABLE_FAST_JIT != 0 + /* Compile fast jit funcitons of this group */ + for (i = group_idx; i < func_count; i += group_stride) { + if (!jit_compiler_compile(module, i + module->import_function_count)) { + os_printf("failed to compile fast jit function %u\n", i); + break; + } + + if (module->orcjit_stop_compiling) { + return NULL; + } + } +#endif + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + /* For JIT tier-up, set each llvm jit func to call_to_fast_jit */ + for (i = group_idx; i < func_count; + i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) { + uint32 j; + + for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) { + if (i + j * group_stride < func_count) { + if (!jit_compiler_set_call_to_fast_jit( + module, + i + j * group_stride + module->import_function_count)) { + os_printf( + "failed to compile call_to_fast_jit for func %u\n", + i + j * group_stride + module->import_function_count); + module->orcjit_stop_compiling = true; + return NULL; + } + } + if (module->orcjit_stop_compiling) { + return NULL; + } + } + } + + /* Wait until init_llvm_jit_functions_stage2 finishes */ + os_mutex_lock(&module->tierup_wait_lock); + while (!module->llvm_jit_inited) { + os_cond_reltimedwait(&module->tierup_wait_cond, + &module->tierup_wait_lock, 10); + if (module->orcjit_stop_compiling) { + /* init_llvm_jit_functions_stage2 failed */ + os_mutex_unlock(&module->tierup_wait_lock); + return NULL; + } + } + os_mutex_unlock(&module->tierup_wait_lock); +#endif + +#if WASM_ENABLE_JIT != 0 + /* Compile llvm jit functions of this group */ + for (i = group_idx; i < func_count; + i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) { + LLVMOrcJITTargetAddress func_addr = 0; + LLVMErrorRef error; + char func_name[48]; + typedef void (*F)(void); + union { + F f; + void *v; + } u; + uint32 j; + + snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i, + "_wrapper"); + LOG_DEBUG("compile llvm jit func %s", func_name); + error = + LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name); + if (error != LLVMErrorSuccess) { + char *err_msg = LLVMGetErrorMessage(error); + os_printf("failed to compile llvm jit function %u: %s", i, err_msg); + LLVMDisposeErrorMessage(err_msg); + break; + } + + /* Call the jit wrapper function to trigger its compilation, so as + to compile the actual jit functions, since we add the latter to + function list in the PartitionFunction callback */ + u.v = (void *)func_addr; + u.f(); + + for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) { + if (i + j * group_stride < func_count) { + module->func_ptrs_compiled[i + j * group_stride] = true; +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, + i + j * group_stride); + error = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, + func_name); + if (error != LLVMErrorSuccess) { + char *err_msg = LLVMGetErrorMessage(error); + os_printf("failed to compile llvm jit function %u: %s", i, + err_msg); + LLVMDisposeErrorMessage(err_msg); + /* Ignore current llvm jit func, as its func ptr is + previous set to call_to_fast_jit, which also works */ + continue; + } + + jit_compiler_set_llvm_jit_func_ptr( + module, + i + j * group_stride + module->import_function_count, + (void *)func_addr); + + /* Try to switch to call this llvm jit funtion instead of + fast jit function from fast jit jitted code */ + jit_compiler_set_call_to_llvm_jit( + module, + i + j * group_stride + module->import_function_count); +#endif + } + } + + if (module->orcjit_stop_compiling) { + break; + } + } +#endif + + return NULL; +} + +static void +orcjit_stop_compile_threads(WASMModule *module) +{ + uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args) + / sizeof(OrcJitThreadArg)); + + module->orcjit_stop_compiling = true; + for (i = 0; i < thread_num; i++) { + if (module->orcjit_threads[i]) + os_thread_join(module->orcjit_threads[i], NULL); + } +} + +static bool +compile_jit_functions(WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ + uint32 thread_num = + (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg)); + uint32 i, j; + bh_print_time("Begin to compile jit functions"); - thread_num = - (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg)); - /* Create threads to compile the jit functions */ - for (i = 0; i < thread_num; i++) { + for (i = 0; i < thread_num && i < module->function_count; i++) { +#if WASM_ENABLE_JIT != 0 module->orcjit_thread_args[i].comp_ctx = module->comp_ctx; +#endif module->orcjit_thread_args[i].module = module; module->orcjit_thread_args[i].group_idx = i; @@ -3102,8 +3305,6 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, (void *)&module->orcjit_thread_args[i], APP_THREAD_STACK_SIZE_DEFAULT) != 0) { - uint32 j; - set_error_buf(error_buf, error_buf_size, "create orcjit compile thread failed"); /* Terminate the threads created */ @@ -3118,15 +3319,39 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, #if WASM_ENABLE_LAZY_JIT == 0 /* Wait until all jit functions are compiled for eager mode */ for (i = 0; i < thread_num; i++) { - os_thread_join(module->orcjit_threads[i], NULL); + if (module->orcjit_threads[i]) + os_thread_join(module->orcjit_threads[i], NULL); + } + +#if WASM_ENABLE_FAST_JIT != 0 + /* Ensure all the fast-jit functions are compiled */ + for (i = 0; i < module->function_count; i++) { + if (!jit_compiler_is_compiled(module, + i + module->import_function_count)) { + set_error_buf(error_buf, error_buf_size, + "failed to compile fast jit function"); + return false; + } } #endif +#if WASM_ENABLE_JIT != 0 + /* Ensure all the llvm-jit functions are compiled */ + for (i = 0; i < module->function_count; i++) { + if (!module->func_ptrs_compiled[i]) { + set_error_buf(error_buf, error_buf_size, + "failed to compile llvm jit function"); + return false; + } + } +#endif +#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */ + bh_print_time("End compile jit functions"); return true; } -#endif /* end of WASM_ENABLE_JIT != 0 */ +#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */ static bool wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, @@ -3538,23 +3763,41 @@ load_from_sections(WASMModule *module, WASMSection *sections, calculate_global_data_offset(module); #if WASM_ENABLE_FAST_JIT != 0 - if (module->function_count - && !(module->fast_jit_func_ptrs = - loader_malloc(sizeof(void *) * module->function_count, - error_buf, error_buf_size))) { - return false; - } - if (!jit_compiler_compile_all(module)) { - set_error_buf(error_buf, error_buf_size, "fast jit compilation failed"); + if (!init_fast_jit_functions(module, error_buf, error_buf_size)) { return false; } #endif #if WASM_ENABLE_JIT != 0 - if (!compile_llvm_jit_functions(module, error_buf, error_buf_size)) { + if (!init_llvm_jit_functions_stage1(module, error_buf, error_buf_size)) { return false; } -#endif /* end of WASM_ENABLE_JIT != 0 */ +#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0) + if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) { + return false; + } +#else + /* Run aot_compile_wasm in a backend thread, so as not to block the main + thread fast jit execution, since applying llvm optimizations in + aot_compile_wasm may cost a lot of time. + Create thread with enough native stack to apply llvm optimizations */ + if (os_thread_create(&module->llvm_jit_init_thread, + init_llvm_jit_functions_stage2_callback, + (void *)module, APP_THREAD_STACK_SIZE_DEFAULT * 8) + != 0) { + set_error_buf(error_buf, error_buf_size, + "create orcjit compile thread failed"); + return false; + } +#endif +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 + /* Create threads to compile the jit functions */ + if (!compile_jit_functions(module, error_buf, error_buf_size)) { + return false; + } +#endif #if WASM_ENABLE_MEMORY_TRACING != 0 wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module); @@ -3567,9 +3810,7 @@ create_module(char *error_buf, uint32 error_buf_size) { WASMModule *module = loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); -#if WASM_ENABLE_FAST_INTERP == 0 bh_list_status ret; -#endif if (!module) { return NULL; @@ -3584,19 +3825,31 @@ create_module(char *error_buf, uint32 error_buf_size) module->br_table_cache_list = &module->br_table_cache_list_head; ret = bh_list_init(module->br_table_cache_list); bh_assert(ret == BH_LIST_SUCCESS); - (void)ret; #endif #if WASM_ENABLE_MULTI_MODULE != 0 module->import_module_list = &module->import_module_list_head; + ret = bh_list_init(module->import_module_list); + bh_assert(ret == BH_LIST_SUCCESS); #endif + #if WASM_ENABLE_DEBUG_INTERP != 0 - bh_list_init(&module->fast_opcode_list); - if (os_mutex_init(&module->ref_count_lock) != 0) { + ret = bh_list_init(&module->fast_opcode_list); + bh_assert(ret == BH_LIST_SUCCESS); +#endif + +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ + && WASM_ENABLE_LAZY_JIT != 0) + if (os_mutex_init(&module->instance_list_lock) != 0) { + set_error_buf(error_buf, error_buf_size, + "init instance list lock failed"); wasm_runtime_free(module); return NULL; } #endif + + (void)ret; return module; } @@ -3964,10 +4217,19 @@ wasm_loader_unload(WASMModule *module) if (!module) return; -#if WASM_ENABLE_JIT != 0 - /* Stop LLVM JIT compilation firstly to avoid accessing +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 + module->orcjit_stop_compiling = true; + if (module->llvm_jit_init_thread) + os_thread_join(module->llvm_jit_init_thread, NULL); +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 + /* Stop Fast/LLVM JIT compilation firstly to avoid accessing module internal data after they were freed */ orcjit_stop_compile_threads(module); +#endif + +#if WASM_ENABLE_JIT != 0 if (module->func_ptrs) wasm_runtime_free(module->func_ptrs); if (module->comp_ctx) @@ -3976,6 +4238,13 @@ wasm_loader_unload(WASMModule *module) aot_destroy_comp_data(module->comp_data); #endif +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 + if (module->tierup_wait_lock_inited) { + os_mutex_destroy(&module->tierup_wait_lock); + os_cond_destroy(&module->tierup_wait_cond); + } +#endif + if (module->types) { for (i = 0; i < module->type_count; i++) { if (module->types[i]) @@ -3997,6 +4266,18 @@ wasm_loader_unload(WASMModule *module) wasm_runtime_free(module->functions[i]->code_compiled); if (module->functions[i]->consts) wasm_runtime_free(module->functions[i]->consts); +#endif +#if WASM_ENABLE_FAST_JIT != 0 + if (module->functions[i]->fast_jit_jitted_code) { + jit_code_cache_free( + module->functions[i]->fast_jit_jitted_code); + } +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + if (module->functions[i]->llvm_jit_func_ptr) { + jit_code_cache_free( + module->functions[i]->llvm_jit_func_ptr); + } +#endif #endif wasm_runtime_free(module->functions[i]); } @@ -4084,7 +4365,12 @@ wasm_loader_unload(WASMModule *module) wasm_runtime_free(fast_opcode); fast_opcode = next; } - os_mutex_destroy(&module->ref_count_lock); +#endif + +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ + && WASM_ENABLE_LAZY_JIT != 0) + os_mutex_destroy(&module->instance_list_lock); #endif #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 @@ -4093,12 +4379,14 @@ wasm_loader_unload(WASMModule *module) #if WASM_ENABLE_FAST_JIT != 0 if (module->fast_jit_func_ptrs) { - for (i = 0; i < module->function_count; i++) { - if (module->fast_jit_func_ptrs[i]) - jit_code_cache_free(module->fast_jit_func_ptrs[i]); - } wasm_runtime_free(module->fast_jit_func_ptrs); } + + for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) { + if (module->fast_jit_thread_locks_inited[i]) { + os_mutex_destroy(&module->fast_jit_thread_locks[i]); + } + } #endif wasm_runtime_free(module); diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index af116a82..cebd47ee 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -261,6 +261,12 @@ destroy_wasm_type(WASMType *type) return; } +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + if (type->call_to_llvm_jit_from_fast_jit) + jit_code_cache_free(type->call_to_llvm_jit_from_fast_jit); +#endif + wasm_runtime_free(type); } @@ -1783,93 +1789,78 @@ calculate_global_data_offset(WASMModule *module) module->global_data_size = data_offset; } -#if WASM_ENABLE_JIT != 0 -static void * -orcjit_thread_callback(void *arg) -{ - LLVMOrcJITTargetAddress func_addr = 0; - OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg; - AOTCompContext *comp_ctx = thread_arg->comp_ctx; - WASMModule *module = thread_arg->module; - uint32 group_idx = thread_arg->group_idx; - uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM; - uint32 func_count = module->function_count; - uint32 i, j; - typedef void (*F)(void); - LLVMErrorRef error; - char func_name[48]; - union { - F f; - void *v; - } u; - - /* Compile jit functions of this group */ - for (i = group_idx; i < func_count; - i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) { - snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i, - "_wrapper"); - LOG_DEBUG("compile func %s", func_name); - error = - LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name); - if (error != LLVMErrorSuccess) { - char *err_msg = LLVMGetErrorMessage(error); - os_printf("failed to compile orc jit function: %s", err_msg); - LLVMDisposeErrorMessage(err_msg); - continue; - } - - /* Call the jit wrapper function to trigger its compilation, so as - to compile the actual jit functions, since we add the latter to - function list in the PartitionFunction callback */ - u.v = (void *)func_addr; - u.f(); - - for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) { - if (i + j * group_stride < func_count) - module->func_ptrs_compiled[i + j * group_stride] = true; - } - - if (module->orcjit_stop_compiling) { - break; - } - } - - return NULL; -} - -static void -orcjit_stop_compile_threads(WASMModule *module) -{ - uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args) - / sizeof(OrcJitThreadArg)); - - module->orcjit_stop_compiling = true; - for (i = 0; i < thread_num; i++) { - if (module->orcjit_threads[i]) - os_thread_join(module->orcjit_threads[i], NULL); - } -} - +#if WASM_ENABLE_FAST_JIT != 0 static bool -compile_llvm_jit_functions(WASMModule *module, char *error_buf, - uint32 error_buf_size) +init_fast_jit_functions(WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ +#if WASM_ENABLE_LAZY_JIT != 0 + JitGlobals *jit_globals = jit_compiler_get_jit_globals(); +#endif + uint32 i; + + if (!module->function_count) + return true; + + if (!(module->fast_jit_func_ptrs = + loader_malloc(sizeof(void *) * module->function_count, error_buf, + error_buf_size))) { + return false; + } + +#if WASM_ENABLE_LAZY_JIT != 0 + for (i = 0; i < module->function_count; i++) { + module->fast_jit_func_ptrs[i] = + jit_globals->compile_fast_jit_and_then_call; + } +#endif + + for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) { + if (os_mutex_init(&module->fast_jit_thread_locks[i]) != 0) { + set_error_buf(error_buf, error_buf_size, + "init fast jit thread lock failed"); + return false; + } + module->fast_jit_thread_locks_inited[i] = true; + } + + return true; +} +#endif /* end of WASM_ENABLE_FAST_JIT != 0 */ + +#if WASM_ENABLE_JIT != 0 +static bool +init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, + uint32 error_buf_size) { AOTCompOption option = { 0 }; char *aot_last_error; uint64 size; - uint32 thread_num, i; - if (module->function_count > 0) { - size = sizeof(void *) * (uint64)module->function_count - + sizeof(bool) * (uint64)module->function_count; - if (!(module->func_ptrs = - loader_malloc(size, error_buf, error_buf_size))) { - return false; - } - module->func_ptrs_compiled = - (bool *)((uint8 *)module->func_ptrs - + sizeof(void *) * module->function_count); + if (module->function_count == 0) + return true; + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LLVM_JIT != 0 + if (os_mutex_init(&module->tierup_wait_lock) != 0) { + set_error_buf(error_buf, error_buf_size, "init jit tierup lock failed"); + return false; } + if (os_cond_init(&module->tierup_wait_cond) != 0) { + set_error_buf(error_buf, error_buf_size, "init jit tierup cond failed"); + os_mutex_destroy(&module->tierup_wait_lock); + return false; + } + module->tierup_wait_lock_inited = true; +#endif + + size = sizeof(void *) * (uint64)module->function_count + + sizeof(bool) * (uint64)module->function_count; + if (!(module->func_ptrs = loader_malloc(size, error_buf, error_buf_size))) { + return false; + } + module->func_ptrs_compiled = + (bool *)((uint8 *)module->func_ptrs + + sizeof(void *) * module->function_count); module->comp_data = aot_create_comp_data(module); if (!module->comp_data) { @@ -1910,6 +1901,19 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, return false; } + return true; +} + +static bool +init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ + char *aot_last_error; + uint32 i; + + if (module->function_count == 0) + return true; + if (!aot_compile_wasm(module->comp_ctx)) { aot_last_error = aot_get_last_error(); bh_assert(aot_last_error != NULL); @@ -1917,7 +1921,12 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, return false; } - bh_print_time("Begin to lookup jit functions"); +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + if (module->orcjit_stop_compiling) + return false; +#endif + + bh_print_time("Begin to lookup llvm jit functions"); for (i = 0; i < module->function_count; i++) { LLVMOrcJITTargetAddress func_addr = 0; @@ -1929,9 +1938,9 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, func_name); if (error != LLVMErrorSuccess) { char *err_msg = LLVMGetErrorMessage(error); - char buf[128]; + char buf[96]; snprintf(buf, sizeof(buf), - "failed to compile orc jit function: %s\n", err_msg); + "failed to compile llvm jit function: %s", err_msg); set_error_buf(error_buf, error_buf_size, buf); LLVMDisposeErrorMessage(err_msg); return false; @@ -1944,17 +1953,211 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, * loading/storing at the same time. */ module->func_ptrs[i] = (void *)func_addr; - module->functions[i]->llvm_jit_func_ptr = (void *)func_addr; + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + if (module->orcjit_stop_compiling) + return false; +#endif } + bh_print_time("End lookup llvm jit functions"); + + return true; +} +#endif /* end of WASM_ENABLE_JIT != 0 */ + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 +static void * +init_llvm_jit_functions_stage2_callback(void *arg) +{ + WASMModule *module = (WASMModule *)arg; + char error_buf[128]; + uint32 error_buf_size = (uint32)sizeof(error_buf); + + if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) { + module->orcjit_stop_compiling = true; + return NULL; + } + + os_mutex_lock(&module->tierup_wait_lock); + module->llvm_jit_inited = true; + os_cond_broadcast(&module->tierup_wait_cond); + os_mutex_unlock(&module->tierup_wait_lock); + + return NULL; +} +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 +/* The callback function to compile jit functions */ +static void * +orcjit_thread_callback(void *arg) +{ + OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg; +#if WASM_ENABLE_JIT != 0 + AOTCompContext *comp_ctx = thread_arg->comp_ctx; +#endif + WASMModule *module = thread_arg->module; + uint32 group_idx = thread_arg->group_idx; + uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM; + uint32 func_count = module->function_count; + uint32 i; + +#if WASM_ENABLE_FAST_JIT != 0 + /* Compile fast jit funcitons of this group */ + for (i = group_idx; i < func_count; i += group_stride) { + if (!jit_compiler_compile(module, i + module->import_function_count)) { + os_printf("failed to compile fast jit function %u\n", i); + break; + } + + if (module->orcjit_stop_compiling) { + return NULL; + } + } +#endif + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + /* For JIT tier-up, set each llvm jit func to call_to_fast_jit */ + for (i = group_idx; i < func_count; + i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) { + uint32 j; + + for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) { + if (i + j * group_stride < func_count) { + if (!jit_compiler_set_call_to_fast_jit( + module, + i + j * group_stride + module->import_function_count)) { + os_printf( + "failed to compile call_to_fast_jit for func %u\n", + i + j * group_stride + module->import_function_count); + module->orcjit_stop_compiling = true; + return NULL; + } + } + if (module->orcjit_stop_compiling) { + return NULL; + } + } + } + + /* Wait until init_llvm_jit_functions_stage2 finishes */ + os_mutex_lock(&module->tierup_wait_lock); + while (!module->llvm_jit_inited) { + os_cond_reltimedwait(&module->tierup_wait_cond, + &module->tierup_wait_lock, 10); + if (module->orcjit_stop_compiling) { + /* init_llvm_jit_functions_stage2 failed */ + os_mutex_unlock(&module->tierup_wait_lock); + return NULL; + } + } + os_mutex_unlock(&module->tierup_wait_lock); +#endif + +#if WASM_ENABLE_JIT != 0 + /* Compile llvm jit functions of this group */ + for (i = group_idx; i < func_count; + i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) { + LLVMOrcJITTargetAddress func_addr = 0; + LLVMErrorRef error; + char func_name[48]; + typedef void (*F)(void); + union { + F f; + void *v; + } u; + uint32 j; + + snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i, + "_wrapper"); + LOG_DEBUG("compile llvm jit func %s", func_name); + error = + LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name); + if (error != LLVMErrorSuccess) { + char *err_msg = LLVMGetErrorMessage(error); + os_printf("failed to compile llvm jit function %u: %s", i, err_msg); + LLVMDisposeErrorMessage(err_msg); + break; + } + + /* Call the jit wrapper function to trigger its compilation, so as + to compile the actual jit functions, since we add the latter to + function list in the PartitionFunction callback */ + u.v = (void *)func_addr; + u.f(); + + for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) { + if (i + j * group_stride < func_count) { + module->func_ptrs_compiled[i + j * group_stride] = true; +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, + i + j * group_stride); + error = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, + func_name); + if (error != LLVMErrorSuccess) { + char *err_msg = LLVMGetErrorMessage(error); + os_printf("failed to compile llvm jit function %u: %s", i, + err_msg); + LLVMDisposeErrorMessage(err_msg); + /* Ignore current llvm jit func, as its func ptr is + previous set to call_to_fast_jit, which also works */ + continue; + } + + jit_compiler_set_llvm_jit_func_ptr( + module, + i + j * group_stride + module->import_function_count, + (void *)func_addr); + + /* Try to switch to call this llvm jit funtion instead of + fast jit function from fast jit jitted code */ + jit_compiler_set_call_to_llvm_jit( + module, + i + j * group_stride + module->import_function_count); +#endif + } + } + + if (module->orcjit_stop_compiling) { + break; + } + } +#endif + + return NULL; +} + +static void +orcjit_stop_compile_threads(WASMModule *module) +{ + uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args) + / sizeof(OrcJitThreadArg)); + + module->orcjit_stop_compiling = true; + for (i = 0; i < thread_num; i++) { + if (module->orcjit_threads[i]) + os_thread_join(module->orcjit_threads[i], NULL); + } +} + +static bool +compile_jit_functions(WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ + uint32 thread_num = + (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg)); + uint32 i, j; + bh_print_time("Begin to compile jit functions"); - thread_num = - (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg)); - /* Create threads to compile the jit functions */ - for (i = 0; i < thread_num; i++) { + for (i = 0; i < thread_num && i < module->function_count; i++) { +#if WASM_ENABLE_JIT != 0 module->orcjit_thread_args[i].comp_ctx = module->comp_ctx; +#endif module->orcjit_thread_args[i].module = module; module->orcjit_thread_args[i].group_idx = i; @@ -1962,8 +2165,6 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, (void *)&module->orcjit_thread_args[i], APP_THREAD_STACK_SIZE_DEFAULT) != 0) { - uint32 j; - set_error_buf(error_buf, error_buf_size, "create orcjit compile thread failed"); /* Terminate the threads created */ @@ -1978,15 +2179,39 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf, #if WASM_ENABLE_LAZY_JIT == 0 /* Wait until all jit functions are compiled for eager mode */ for (i = 0; i < thread_num; i++) { - os_thread_join(module->orcjit_threads[i], NULL); + if (module->orcjit_threads[i]) + os_thread_join(module->orcjit_threads[i], NULL); + } + +#if WASM_ENABLE_FAST_JIT != 0 + /* Ensure all the fast-jit functions are compiled */ + for (i = 0; i < module->function_count; i++) { + if (!jit_compiler_is_compiled(module, + i + module->import_function_count)) { + set_error_buf(error_buf, error_buf_size, + "failed to compile fast jit function"); + return false; + } } #endif +#if WASM_ENABLE_JIT != 0 + /* Ensure all the llvm-jit functions are compiled */ + for (i = 0; i < module->function_count; i++) { + if (!module->func_ptrs_compiled[i]) { + set_error_buf(error_buf, error_buf_size, + "failed to compile llvm jit function"); + return false; + } + } +#endif +#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */ + bh_print_time("End compile jit functions"); return true; } -#endif /* end of WASM_ENABLE_JIT != 0 */ +#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */ #if WASM_ENABLE_REF_TYPES != 0 static bool @@ -2427,22 +2652,41 @@ load_from_sections(WASMModule *module, WASMSection *sections, calculate_global_data_offset(module); #if WASM_ENABLE_FAST_JIT != 0 - if (!(module->fast_jit_func_ptrs = - loader_malloc(sizeof(void *) * module->function_count, error_buf, - error_buf_size))) { - return false; - } - if (!jit_compiler_compile_all(module)) { - set_error_buf(error_buf, error_buf_size, "fast jit compilation failed"); + if (!init_fast_jit_functions(module, error_buf, error_buf_size)) { return false; } #endif #if WASM_ENABLE_JIT != 0 - if (!compile_llvm_jit_functions(module, error_buf, error_buf_size)) { + if (!init_llvm_jit_functions_stage1(module, error_buf, error_buf_size)) { return false; } -#endif /* end of WASM_ENABLE_JIT != 0 */ +#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0) + if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) { + return false; + } +#else + /* Run aot_compile_wasm in a backend thread, so as not to block the main + thread fast jit execution, since applying llvm optimizations in + aot_compile_wasm may cost a lot of time. + Create thread with enough native stack to apply llvm optimizations */ + if (os_thread_create(&module->llvm_jit_init_thread, + init_llvm_jit_functions_stage2_callback, + (void *)module, APP_THREAD_STACK_SIZE_DEFAULT * 8) + != 0) { + set_error_buf(error_buf, error_buf_size, + "create orcjit compile thread failed"); + return false; + } +#endif +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 + /* Create threads to compile the jit functions */ + if (!compile_jit_functions(module, error_buf, error_buf_size)) { + return false; + } +#endif #if WASM_ENABLE_MEMORY_TRACING != 0 wasm_runtime_dump_module_mem_consumption(module); @@ -2455,9 +2699,7 @@ create_module(char *error_buf, uint32 error_buf_size) { WASMModule *module = loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); -#if WASM_ENABLE_FAST_INTERP == 0 bh_list_status ret; -#endif if (!module) { return NULL; @@ -2472,9 +2714,18 @@ create_module(char *error_buf, uint32 error_buf_size) module->br_table_cache_list = &module->br_table_cache_list_head; ret = bh_list_init(module->br_table_cache_list); bh_assert(ret == BH_LIST_SUCCESS); - (void)ret; #endif +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 + if (os_mutex_init(&module->instance_list_lock) != 0) { + set_error_buf(error_buf, error_buf_size, + "init instance list lock failed"); + wasm_runtime_free(module); + return NULL; + } +#endif + + (void)ret; return module; } @@ -2686,10 +2937,19 @@ wasm_loader_unload(WASMModule *module) if (!module) return; -#if WASM_ENABLE_JIT != 0 - /* Stop LLVM JIT compilation firstly to avoid accessing +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 + module->orcjit_stop_compiling = true; + if (module->llvm_jit_init_thread) + os_thread_join(module->llvm_jit_init_thread, NULL); +#endif + +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 + /* Stop Fast/LLVM JIT compilation firstly to avoid accessing module internal data after they were freed */ orcjit_stop_compile_threads(module); +#endif + +#if WASM_ENABLE_JIT != 0 if (module->func_ptrs) wasm_runtime_free(module->func_ptrs); if (module->comp_ctx) @@ -2698,6 +2958,13 @@ wasm_loader_unload(WASMModule *module) aot_destroy_comp_data(module->comp_data); #endif +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 + if (module->tierup_wait_lock_inited) { + os_mutex_destroy(&module->tierup_wait_lock); + os_cond_destroy(&module->tierup_wait_cond); + } +#endif + if (module->types) { for (i = 0; i < module->type_count; i++) { if (module->types[i]) @@ -2719,6 +2986,18 @@ wasm_loader_unload(WASMModule *module) wasm_runtime_free(module->functions[i]->code_compiled); if (module->functions[i]->consts) wasm_runtime_free(module->functions[i]->consts); +#endif +#if WASM_ENABLE_FAST_JIT != 0 + if (module->functions[i]->fast_jit_jitted_code) { + jit_code_cache_free( + module->functions[i]->fast_jit_jitted_code); + } +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + if (module->functions[i]->llvm_jit_func_ptr) { + jit_code_cache_free( + module->functions[i]->llvm_jit_func_ptr); + } +#endif #endif wasm_runtime_free(module->functions[i]); } @@ -2775,14 +3054,20 @@ wasm_loader_unload(WASMModule *module) } #endif +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 + os_mutex_destroy(&module->instance_list_lock); +#endif + #if WASM_ENABLE_FAST_JIT != 0 if (module->fast_jit_func_ptrs) { - for (i = 0; i < module->function_count; i++) { - if (module->fast_jit_func_ptrs[i]) - jit_code_cache_free(module->fast_jit_func_ptrs[i]); - } wasm_runtime_free(module->fast_jit_func_ptrs); } + + for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) { + if (module->fast_jit_thread_locks_inited[i]) { + os_mutex_destroy(&module->fast_jit_thread_locks[i]); + } + } #endif wasm_runtime_free(module); @@ -5572,12 +5857,6 @@ re_scan: if (depth > 255) { /* The depth cannot be stored in one byte, create br_table cache to store each depth */ -#if WASM_ENABLE_DEBUG_INTERP != 0 - if (!record_fast_op(module, p_org, *p_org, - error_buf, error_buf_size)) { - goto fail; - } -#endif if (!(br_table_cache = loader_malloc( offsetof(BrTableCache, br_depths) + sizeof(uint32) diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 080a0eea..438dd59c 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -19,6 +19,9 @@ #if WASM_ENABLE_DEBUG_INTERP != 0 #include "../libraries/debug-engine/debug_engine.h" #endif +#if WASM_ENABLE_FAST_JIT != 0 +#include "../fast-jit/jit_compiler.h" +#endif #if WASM_ENABLE_JIT != 0 #include "../aot/aot_runtime.h" #endif @@ -1414,30 +1417,10 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, extra_info_offset = (uint32)total_size; total_size += sizeof(WASMModuleInstanceExtra); -#if WASM_ENABLE_DEBUG_INTERP != 0 - if (!is_sub_inst) { - os_mutex_lock(&module->ref_count_lock); - if (module->ref_count != 0) { - LOG_WARNING( - "warning: multiple instances referencing the same module may " - "cause unexpected behaviour during debugging"); - } - module->ref_count++; - os_mutex_unlock(&module->ref_count_lock); - } -#endif - /* Allocate the memory for module instance with memory instances, global data, table data appended at the end */ if (!(module_inst = runtime_malloc(total_size, error_buf, error_buf_size))) { -#if WASM_ENABLE_DEBUG_INTERP != 0 - if (!is_sub_inst) { - os_mutex_lock(&module->ref_count_lock); - module->ref_count--; - os_mutex_unlock(&module->ref_count_lock); - } -#endif return NULL; } @@ -1827,6 +1810,33 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, } #endif +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0) + if (!is_sub_inst) { + /* Add module instance into module's instance list */ + os_mutex_lock(&module->instance_list_lock); +#if WASM_ENABLE_DEBUG_INTERP != 0 + if (module->instance_list) { + LOG_WARNING( + "warning: multiple instances referencing to the same module " + "may cause unexpected behaviour during debugging"); + } +#endif +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + /* Copy llvm func ptrs again in case that they were updated + after the module instance was created */ + bh_memcpy_s(module_inst->func_ptrs + module->import_function_count, + sizeof(void *) * module->function_count, module->func_ptrs, + sizeof(void *) * module->function_count); +#endif + module_inst->e->next = module->instance_list; + module->instance_list = module_inst; + os_mutex_unlock(&module->instance_list_lock); + } +#endif + if (module->start_function != (uint32)-1) { /* TODO: fix start function can be import function issue */ if (module->start_function >= module->import_function_count) @@ -1864,8 +1874,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, wasm_runtime_dump_module_inst_mem_consumption( (WASMModuleInstanceCommon *)module_inst); #endif - (void)global_data_end; + (void)global_data_end; return module_inst; fail: @@ -1935,11 +1945,28 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0) if (!is_sub_inst) { - os_mutex_lock(&module_inst->module->ref_count_lock); - module_inst->module->ref_count--; - os_mutex_unlock(&module_inst->module->ref_count_lock); + WASMModule *module = module_inst->module; + WASMModuleInstance *instance_prev = NULL, *instance; + os_mutex_lock(&module->instance_list_lock); + + instance = module->instance_list; + while (instance) { + if (instance == module_inst) { + if (!instance_prev) + module->instance_list = instance->e->next; + else + instance_prev->e->next = instance->e->next; + break; + } + instance_prev = instance; + instance = instance->e->next; + } + + os_mutex_unlock(&module->instance_list_lock); } #endif @@ -2817,7 +2844,7 @@ fast_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, return call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, true, type_idx); } -#endif +#endif /* end of WASM_ENABLE_FAST_JIT != 0 */ #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 1ebac5f3..6d1a5340 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -59,6 +59,9 @@ typedef enum WASMExceptionID { EXCE_AUX_STACK_UNDERFLOW, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, EXCE_OPERAND_STACK_OVERFLOW, +#if WASM_ENABLE_FAST_JIT != 0 + EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC, +#endif EXCE_ALREADY_THROWN, EXCE_NUM, } WASMExceptionID; @@ -233,6 +236,12 @@ typedef struct WASMModuleInstanceExtra { #if WASM_ENABLE_MEMORY_PROFILING != 0 uint32 max_aux_stack_used; #endif + +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ + && WASM_ENABLE_LAZY_JIT != 0) + WASMModuleInstance *next; +#endif } WASMModuleInstanceExtra; struct AOTFuncPerfProfInfo; diff --git a/doc/build_wamr.md b/doc/build_wamr.md index d3c7a826..f32d69bc 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -240,7 +240,7 @@ make By default in Linux, the `fast interpreter`, `AOT` and `Libc WASI` are enabled, and JIT is disabled. And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth. -There are total 5 running modes supported: fast interpreter, classi interpreter, AOT, LLVM JIT and Fast JIT. +There are total 6 running modes supported: fast interpreter, classi interpreter, AOT, LLVM JIT, Fast JIT and Multi-tier JIT. (1) To run a wasm file with `fast interpreter` mode - build iwasm with default build and then: ```Bash @@ -301,6 +301,14 @@ make ``` The Fast JIT is a lightweight JIT engine with quick startup, small footprint and good portability, and gains ~50% performance of AOT. +(6) To enable the `Multi-tier JIT` mode: +``` Bash +mkdir build && cd build +cmake .. -DWAMR_BUILD_FAST_JTI=1 -DWAMR_BUILD_JIT=1 +make +``` +The Multi-tier JIT is a two level JIT tier-up engine, which launchs Fast JIT to run the wasm module as soon as possible and creates backend threads to compile the LLVM JIT functions at the same time, and when the LLVM JIT functions are compiled, the runtime will switch the extecution from the Fast JIT jitted code to LLVM JIT jitted code gradually, so as to gain the best performance. + Linux SGX (Intel Software Guard Extension) ------------------------- diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index b6ab2978..dca7f87c 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -16,7 +16,7 @@ function help() echo "-c clean previous test results, not start test" echo "-s {suite_name} test only one suite (spec)" echo "-m set compile target of iwasm(x86_64\x86_32\armv7_vfp\thumbv7_vfp\riscv64_lp64d\riscv64_lp64)" - echo "-t set compile type of iwasm(classic-interp\fast-interp\jit\aot\fast-jit)" + echo "-t set compile type of iwasm(classic-interp\fast-interp\jit\aot\fast-jit\multi-tier-jit)" echo "-M enable multi module feature" echo "-p enable multi thread feature" echo "-S enable SIMD feature" @@ -31,7 +31,7 @@ function help() OPT_PARSED="" WABT_BINARY_RELEASE="NO" #default type -TYPE=("classic-interp" "fast-interp" "jit" "aot" "fast-jit") +TYPE=("classic-interp" "fast-interp" "jit" "aot" "fast-jit" "multi-tier-jit") #default target TARGET="X86_64" ENABLE_MULTI_MODULE=0 @@ -84,7 +84,8 @@ do t) echo "set compile type of wamr " ${OPTARG} if [[ ${OPTARG} != "classic-interp" && ${OPTARG} != "fast-interp" \ - && ${OPTARG} != "jit" && ${OPTARG} != "aot" && ${OPTARG} != "fast-jit" ]]; then + && ${OPTARG} != "jit" && ${OPTARG} != "aot" + && ${OPTARG} != "fast-jit" && ${OPTARG} != "multi-tier-jit" ]]; then echo "*----- please varify a type of compile when using -t! -----*" help exit 1 @@ -213,6 +214,12 @@ readonly FAST_JIT_COMPILE_FLAGS="\ -DWAMR_BUILD_FAST_JIT=1 \ -DWAMR_BUILD_SPEC_TEST=1" +readonly MULTI_TIER_JIT_COMPILE_FLAGS="\ + -DWAMR_BUILD_TARGET=${TARGET} \ + -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \ + -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \ + -DWAMR_BUILD_SPEC_TEST=1" + readonly COMPILE_FLAGS=( "${CLASSIC_INTERP_COMPILE_FLAGS}" "${FAST_INTERP_COMPILE_FLAGS}" @@ -220,6 +227,7 @@ readonly COMPILE_FLAGS=( "${ORC_LAZY_JIT_COMPILE_FLAGS}" "${AOT_COMPILE_FLAGS}" "${FAST_JIT_COMPILE_FLAGS}" + "${MULTI_TIER_JIT_COMPILE_FLAGS}" ) # TODO: with libiwasm.so only @@ -409,6 +417,10 @@ function spec_test() echo "fast-jit doesn't support multi-thread feature yet, skip it" return fi + if [[ $1 == 'multi-tier-jit' ]]; then + echo "multi-tier-jit doesn't support multi-thread feature yet, skip it" + return + fi fi if [[ ${ENABLE_XIP} == 1 ]]; then @@ -667,7 +679,7 @@ function trigger() "fast-jit") echo "work in fast-jit mode" - # jit + # fast-jit BUILD_FLAGS="$FAST_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" build_iwasm_with_cfg $BUILD_FLAGS for suite in "${TEST_CASE_ARR[@]}"; do @@ -675,6 +687,16 @@ function trigger() done ;; + "multi-tier-jit") + echo "work in multi-tier-jit mode" + # multi-tier-jit + BUILD_FLAGS="$MULTI_TIER_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + build_iwasm_with_cfg $BUILD_FLAGS + for suite in "${TEST_CASE_ARR[@]}"; do + $suite"_test" multi-tier-jit + done + ;; + *) echo "unexpected mode, do nothing" ;; From d04f3988c3e456788c72f44cf807b4af35d94968 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 21 Dec 2022 18:29:29 +0900 Subject: [PATCH 17/32] libc-wasi: Fix spurious poll timeout (#1824) This reverts the "Fix libc-wasi poll_oneoff hang issue" change. https://github.com/bytecodealliance/wasm-micro-runtime/pull/1300 --- .../libraries/libc-wasi/sandboxed-system-primitives/src/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 0d44ae7d..d8c57459 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -2696,7 +2696,7 @@ wasmtime_ssp_poll_oneoff( timeout = ts > INT_MAX ? -1 : (int)ts; } else { - timeout = 1000; + timeout = -1; } int ret = poll(pfds, nsubscriptions, timeout); From 6fd8001eb6df203988b5c31393816c7cc23b0752 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Sat, 24 Dec 2022 09:17:39 +0800 Subject: [PATCH 18/32] Update CIs and documents to make naming of generated binaries consistent (#1823) --- .github/workflows/build_wamr_lldb.yml | 30 ++++---- .github/workflows/build_wamr_vscode_ext.yml | 13 ++-- test-tools/wamr-ide/README.md | 77 +++++++++++++------ .../wamr-ide/VSCode-Extension/README.md | 17 ++-- .../VSCode-Extension/resource/debug/README.md | 16 ++-- .../src/utilities/lldbUtilities.ts | 2 +- 6 files changed, 97 insertions(+), 58 deletions(-) diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index 6106fb42..fab40758 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -50,7 +50,7 @@ jobs: ./core/deps/llvm-project/build/libexec ./core/deps/llvm-project/build/share ./core/deps/llvm-project/lldb/tools/ - ./core/deps/llvm-project/inst/ + ./core/deps/llvm-project/wamr-lldb/ key: ${{inputs.arch}}-${{ inputs.runner }}-lldb_build - name: setup xcode macos @@ -92,10 +92,10 @@ jobs: if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'ubuntu') run: | echo "start to build lldb..." - mkdir -p inst + mkdir -p wamr-lldb cmake -S ./llvm -B build \ -G Ninja \ - -DCMAKE_INSTALL_PREFIX=../inst \ + -DCMAKE_INSTALL_PREFIX=../wamr-lldb \ -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;lldb" \ -DLLVM_TARGETS_TO_BUILD=X86 \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLLVM_BUILD_BENCHMARKS:BOOL=OFF \ @@ -111,10 +111,10 @@ jobs: if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos') run: | echo "start to build lldb..." - mkdir -p inst + mkdir -p wamr-lldb cmake -S ./llvm -B build \ -G Ninja \ - -DCMAKE_INSTALL_PREFIX=../inst \ + -DCMAKE_INSTALL_PREFIX=../wamr-lldb \ -DCMAKE_BUILD_TYPE:STRING="Release" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DLLVM_ENABLE_PROJECTS="clang;lldb" \ @@ -134,30 +134,30 @@ jobs: - name: pack a distribution if: steps.lldb_build_cache.outputs.cache-hit != 'true' run: | - mkdir -p inst/bin - mkdir -p inst/lib - cp build/bin/lldb* inst/bin - cp lldb/tools/lldb-vscode/package.json inst - cp -r lldb/tools/lldb-vscode/syntaxes/ inst + mkdir -p wamr-lldb/bin + mkdir -p wamr-lldb/lib + cp build/bin/lldb* wamr-lldb/bin + cp lldb/tools/lldb-vscode/package.json wamr-lldb + cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb working-directory: core/deps/llvm-project - name: pack ubuntu specific libraries if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'ubuntu') run: | - cp build/lib/liblldb*.so inst/lib - cp build/lib/liblldb*.so.* inst/lib + cp build/lib/liblldb*.so wamr-lldb/lib + cp build/lib/liblldb*.so.* wamr-lldb/lib working-directory: core/deps/llvm-project - name: pack macos specific libraries if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos') run: | - cp build/lib/liblldb*.dylib inst/lib + cp build/lib/liblldb*.dylib wamr-lldb/lib working-directory: core/deps/llvm-project - name: compress the binary run: | - tar czf wamr-lldb-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz inst - zip -r wamr-lldb-${{ inputs.ver_num }}-${{ inputs.runner }}.zip inst + tar czf wamr-lldb-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz wamr-lldb + zip -r wamr-lldb-${{ inputs.ver_num }}-${{ inputs.runner }}.zip wamr-lldb working-directory: core/deps/llvm-project - name: upload release tar.gz diff --git a/.github/workflows/build_wamr_vscode_ext.yml b/.github/workflows/build_wamr_vscode_ext.yml index cfbf3d40..81c938e6 100644 --- a/.github/workflows/build_wamr_vscode_ext.yml +++ b/.github/workflows/build_wamr_vscode_ext.yml @@ -41,8 +41,9 @@ jobs: - name: compress the vscode extension run: | - tar czf wamr_ide-${{ inputs.ver_num }}.tar.gz wamride-*.vsix - zip wamr_ide-${{ inputs.ver_num }}.zip wamride-*.vsix + mv wamride-*.vsix wamr-ide.vsix + tar czf wamr-ide-${{ inputs.ver_num }}.tar.gz wamr-ide.vsix + zip wamr-ide-${{ inputs.ver_num }}.zip wamr-ide.vsix working-directory: test-tools/wamr-ide/VSCode-Extension - name: upload release tar.gz @@ -51,8 +52,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ inputs.upload_url }} - asset_path: test-tools/wamr-ide/VSCode-Extension/wamr_ide-${{ inputs.ver_num }}.tar.gz - asset_name: wamr_ide-${{ inputs.ver_num }}.tar.gz + asset_path: test-tools/wamr-ide/VSCode-Extension/wamr-ide-${{ inputs.ver_num }}.tar.gz + asset_name: wamr-ide-${{ inputs.ver_num }}.tar.gz asset_content_type: application/x-gzip - name: upload release zip @@ -61,6 +62,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ inputs.upload_url }} - asset_path: test-tools/wamr-ide/VSCode-Extension/wamr_ide-${{ inputs.ver_num }}.zip - asset_name: wamr_ide-${{ inputs.ver_num }}.zip + asset_path: test-tools/wamr-ide/VSCode-Extension/wamr-ide-${{ inputs.ver_num }}.zip + asset_name: wamr-ide-${{ inputs.ver_num }}.zip asset_content_type: application/zip diff --git a/test-tools/wamr-ide/README.md b/test-tools/wamr-ide/README.md index d33f53f7..8a6e1509 100644 --- a/test-tools/wamr-ide/README.md +++ b/test-tools/wamr-ide/README.md @@ -14,17 +14,17 @@ The WAMR-IDE is an Integrated Development Environment to develop WebAssembly app ## How to setup WAMR IDE -Note: Please ensure that the scripts under `resource` directories have -execution permission. While on git they have x bits, you might have dropped -them eg. by copying them from Windows. -Similarly, do not drop execution permission when copying `lldb` binaries -under `resource/debug/bin`. +Now, we have same version tagged docker images, lldb binaries and VS Code installation file(.vsix file) packed for each GitHub release. So if you simply want to use WAMR debugging features in VS Code, the ideal(and effortless) way is following the tutorial in [this section](#21-download-wamr-vs-code-extension-from-the-github-releaserecommended-approach). -#### 1. Install `VSCode` on host. +Alternatively, if you want to build lldb, docker images, or .vsix file locally so that you can try the effect of your modification, you could refer to the tutorial in [this section](#22-build-wamr-vs-code-extension-locallyalternative-approach). + +### 1. Preparation + +#### 1.1. Install `VSCode` on host - make sure the version of [vscode](https://code.visualstudio.com/Download) you installed is at least _1.59.0_ -#### 2. Install `Docker` on host. +#### 1.2. Install `Docker` on host 1. [Windows: Docker Desktop](https://docs.docker.com/desktop/windows/install/) 2. [Ubuntu: Docker Engine](https://docs.docker.com/engine/install/ubuntu) @@ -37,11 +37,13 @@ under `resource/debug/bin`. - Ubuntu Bionic 18.04(LTS) ``` -#### 3. Load docker images from the release tar file or build docker images on the host +### 2. WAMR VS Code extension: download from the GitHub release or build locally -##### 3.1 Load docker images from the release tar file +#### 2.1 Download WAMR VS Code extension from the GitHub release(Recommended approach) -From now on, for each release, we have the same version tagged docker image saved as a tar file, which you can find and download in the release. +##### 2.1.1 Load docker images from the GitHub release tar file + +From now on, for each GitHub release, we have the same version tagged docker image saved as a tar file, which you can find and download in the GitHub release. You could download the tar archive files for docker images from the release, and then load them using the following commands: @@ -68,7 +70,23 @@ docker load --input ./wasm-toolchain.tar docker load --input ./wasm-debug-server.tar ``` -##### 3.2 Build docker images on host +##### 2.1.2 Download the VS Code extension installation file from the GitHub release + +From now on, for each GitHub release, we have the same version tagged zip/tar.gz file. For example, in release version 1.1.2, you can easily download and decompress `wamr-ide-1.1.2.tar.gz` `wamr-ide-1.1.2.zip`, which contains `wamr-ide.vsix` VS Code extension installation file. As you can imagine, in the future, when new releases are available, you can freely choose whichever version(for example, 1.2.0, 1.3.0, etc.) you prefer. It should work as long as you download the same version tagged docker image and .vsix file. + +##### 2.1.3 Install extension from vsix + +![install_from_vsix](./Media/install_from_vsix.png "install wamr-ide from vsix") + +select `wamr-ide.vsix` which you have decompressed from `.tar.gz` or `.zip` file. + +#### 2.2 Build WAMR VS Code extension locally(Alternative approach) + +You could also build the VS Code extension locally, the following instruction provides a thorough tutorial. It's worth noting that in the local build tutorial we use hard-coded tag version 1.0 other than the semantic version of WAMR. + +Note: Please ensure that the scripts under `resource` directories have execution permission. While on git they have x bits, you might have dropped them eg. by copying them from Windows. Similarly, do not drop execution permission when copying `lldb` binaries under `resource/debug/bin`. + +##### 2.2.1 Build docker images on host We have 2 docker images which should be built or loaded on your host, `wasm-toolchain` and `wasm-debug-server`. To build these 2 images, please enter the `WASM-Debug-Server/Docker` & `WASM-Toolchain/Docker`, then execute the `build_docker_image` script respectively. @@ -90,11 +108,11 @@ $ cd ./WASM-Debug-Server/Docker $ ./build_docker_image.sh ``` -#### After building, you can find `wasm-toolchain` and `wasm-debug-server` docker images on your local +##### 2.2.2 After building, you can find `wasm-toolchain` and `wasm-debug-server` docker images on your local ![docker-images](./Media/docker_images.png) -#### If building docker images fail during the process +##### 2.2.3 If building docker images fail during the process Sometimes building the Docker images may fail due to bad network conditions. If the `wasm-toolchain` and `wasm-debug-server` images do not exist after building, please build them manually. Fix the proxy setting if needed and execute the following command to build docker images. @@ -114,15 +132,15 @@ $ docker build --no-cache --build-arg http_proxy=http://proxy.example.com:1234 --build-arg https_proxy=http://proxy.example.com:1234 -t wasm-toolchain:1.0 . ``` -#### If you encounter the problem `failed to solve with frontend dockerfile.v0: failed to create LLB definition`, please config your docker desktop +##### 2.2.4 If you encounter the problem `failed to solve with frontend dockerfile.v0: failed to create LLB definition`, please config your docker desktop ![docker-engine-config](./Media/docker_engine_config.png) -#### Points To Remember +##### 2.2.5 Points To Remember - Make sure that the `wasm-toolchain:1.0` and `wasm-debug-server:1.0` docker images are both successfully built before using `WAMR IDE`, otherwise `Build`, `Run` and `Debug` will not work. -#### 4. Generate wamride extension package file +##### 2.2.6 Generate wamride extension package file `wamride-1.0.0.vsix` can be packaged by [`npm vsce`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension). @@ -134,14 +152,29 @@ $ npm install $ vsce package ``` -Note that patched `lldb` should be built and put into the `VSCode-Extension/resource/debug` folder before your package or extension debug process if you want to enable `source debugging` feature. -Please follow this [instruction](../../doc/source_debugging.md#debugging-with-interpreter) to build `lldb`. -Please follow this [instruction](./VSCode-Extension/resource/debug/README.md) -to copy the binaries. +##### 2.2.7 Enable VS Code debugging feature + +By default, when you build .vsix locally, the debugging feature is off. Suppose you want to enable the source debugging feature. In that case, you could download `lldb` binaries from our GitHub release (for example, `wamr-lldb-1.1.2-x86_64-ubuntu-20.04.tar.gz`), decompress and put every subdirectory and file to the installed directory of your VS Code extension. + +For example, let's say you are on an Ubuntu 20.04 machine. You first download and decompress `wamr-lldb-1.1.2-x86_64-ubuntu-20.04.tar.gz`, and you will get a `wamr-lldb` folder (or `inst` folder in our earlier release). Then, you can simply copy the files and directory inside that folder to the relative path `resource/debug/linux/` under your VS Code extension installation directory. + +Example commands on an Ubuntu 20.04 machine: + +```shell +# decompress .tar.gz file and get the folder +$ ls wamr-lldb +bin lib package.json syntaxes +# copy everything to the vscode extension installation path(in this case, it's /home/{usrname}/.vscode-server/extensions/wamr.wamride-1.0.0/) +$ cp inst/* /home/{usrname}/.vscode-server/extensions/wamr.wamride-1.0.0/resource/debug/linux/ +``` + +If you want to use your own patched `lldb`, you could follow this [instruction](../../doc/source_debugging.md#debugging-with-interpreter) to build `lldb`. And follow this [instruction](./VSCode-Extension/resource/debug/README.md) +to copy the binaries to replace the existing ones. + > **You can also debug the extension directly follow this [instruction](./VSCode-Extension/README.md) without packing the extension.** -#### 5. Install extension from vsix +##### 2.2.7 Install extension from vsix ![install_from_vsix](./Media/install_from_vsix.png "install wamr-ide from vsix") @@ -215,7 +248,7 @@ Click `Change workspace` button, a dialog will show as following. You can select ![right click menus](./Media/right_click_menus_2.png "right click menus") - #### After setting up `include path` and `exclude files`, the corresponding folder and files will be decorated with color and icon as following picture shows. +#### After setting up `include path` and `exclude files`, the corresponding folder and files will be decorated with color and icon as following picture shows ![decoration for files](./Media/decoration_for_files.png "decoration for files") diff --git a/test-tools/wamr-ide/VSCode-Extension/README.md b/test-tools/wamr-ide/VSCode-Extension/README.md index 381b7ec5..739e39a7 100644 --- a/test-tools/wamr-ide/VSCode-Extension/README.md +++ b/test-tools/wamr-ide/VSCode-Extension/README.md @@ -3,13 +3,16 @@ ### An integrated development environment for WASM. # How to debug this extension -> Note that when you download and -> decompress to get .vsix file from [our release](https://github.com/bytecodealliance/wasm-micro-runtime/releases). -> It's by default that the `source debugging` feature is not enabled. -> If you want to enable `source debugging` feature of this extension, -> you could either download `lldb` from [our release](https://github.com/bytecodealliance/wasm-micro-runtime/releases) and put them in correct path -mentioned in this [instruction](./resource/debug/README.md) (This is recommended way), -> or you could build `lldb` yourself follow this [instruction](./resource/debug/README.md) +> Note that when you download and +> decompress to get .vsix file from [our release](https://github.com/bytecodealliance/wasm-micro-runtime/releases). +> It's by default that the `source debugging` feature is not enabled. +> If you want to enable the `source debugging` feature of this extension, +> you could download `lldb` from [our release](https://github.com/bytecodealliance/wasm-micro-runtime/releases) +> (This is the recommended way, and you could do it with a single click in VS Code). +> Then if you want to use your customized lldb patch, +> you could build your own version of `lldb` +> and then follow this [instruction](./resource/debug/README.md) +> to put them in the correct path ### 1. open `VSCode_Extension` directory with the `vscode` diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md b/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md index 36fbc5d6..403e35ae 100644 --- a/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md +++ b/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md @@ -1,12 +1,14 @@ -### If you want to enable `source debugging` for this extension, please build `lldb` firstly following this [instruction](../../../../../doc/source_debugging.md#debugging-with-interpreter). +### If you want to enable `source debugging` for this extension and use your own patched `lldb`, please build `lldb` firstly following this [instruction](../../../../../doc/source_debugging.md#debugging-with-interpreter) -### After building(`linux` for example), create `bin` folder and `lib` folder respectively in `linux` directory, add following necessary target files into the folders. +### After building(`linux` for example), create `bin` folder and `lib` folder respectively in `linux` directory, add following necessary target files into the folders - ```shell - /llvm/build-lldb/bin/lldb # move this file to resource/debug/linux/bin/ - /llvm/build-lldb/bin/lldb-vscode # move this file to resource/debug/linux/bin/ - /llvm/build-lldb/lib/liblldb.so.13 # move this file to resource/debug/linux/lib/ - ``` +```shell +/llvm/build-lldb/bin/lldb # move this file to {VS Code directory}/resource/debug/linux/bin/ +/llvm/build-lldb/bin/lldb-vscode # move this file to {VS Code directory}/resource/debug/linux/bin/ +/llvm/build-lldb/lib/liblldb.so.13 # move this file to {VS Code directory}/resource/debug/linux/lib/ +``` + +> If you are debugging this extension following this [tutorial](../../README.md), {VS Code directory} will be `{WAMR root directory}/test-tools/wamr-ide/VSCode-Extension`. If you want to replace the current lldb with your own patched version so that you can use your patched lldb in VS Code, {VS Code directory} will be `~/.vscode/extensions/wamr.wamride-1.1.2` or `~/.vscode-server/extensions/wamr.wamride-1.1.2`. Note: For macOS, the library is named like `liblldb.13.0.1.dylib`. diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts index e2eaec23..d2ad4130 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts @@ -27,7 +27,7 @@ const WAMR_LLDB_NOT_SUPPORTED_ERROR = new Error( function getLLDBUnzipFilePath(destinationFolder: string, filename: string) { const dirs = filename.split('/'); - if (dirs[0] === 'inst') { + if (dirs[0] === 'wamr-lldb') { dirs.shift(); } From 2953614cb802ff3023dd36075f650282e0034547 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Sat, 24 Dec 2022 10:11:10 +0800 Subject: [PATCH 19/32] Port WAMR to the FreeBSD platform and update the document (#1825) --- core/shared/platform/freebsd/platform_init.c | 43 ++++++ .../platform/freebsd/platform_internal.h | 108 ++++++++++++++ .../platform/freebsd/shared_platform.cmake | 18 +++ doc/build_wamr.md | 15 ++ product-mini/platforms/freebsd/CMakeLists.txt | 132 ++++++++++++++++++ product-mini/platforms/freebsd/build_jit.sh | 11 ++ product-mini/platforms/freebsd/build_llvm.sh | 6 + product-mini/platforms/freebsd/main.c | 6 + 8 files changed, 339 insertions(+) create mode 100644 core/shared/platform/freebsd/platform_init.c create mode 100644 core/shared/platform/freebsd/platform_internal.h create mode 100644 core/shared/platform/freebsd/shared_platform.cmake create mode 100644 product-mini/platforms/freebsd/CMakeLists.txt create mode 100755 product-mini/platforms/freebsd/build_jit.sh create mode 100755 product-mini/platforms/freebsd/build_llvm.sh create mode 100644 product-mini/platforms/freebsd/main.c diff --git a/core/shared/platform/freebsd/platform_init.c b/core/shared/platform/freebsd/platform_init.c new file mode 100644 index 00000000..2aae13fa --- /dev/null +++ b/core/shared/platform/freebsd/platform_init.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{} + +int +os_printf(const char *format, ...) +{ + int ret = 0; + va_list ap; + + va_start(ap, format); +#ifndef BH_VPRINTF + ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif + va_end(ap); + + return ret; +} + +int +os_vprintf(const char *format, va_list ap) +{ +#ifndef BH_VPRINTF + return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif +} diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h new file mode 100644 index 00000000..7b4789c9 --- /dev/null +++ b/core/shared/platform/freebsd/platform_internal.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_FREEBSD +#define BH_PLATFORM_FREEBSD +#endif + +#define BH_HAS_DLFCN 1 + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; +typedef sem_t korp_sem; + +#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER + +#define os_thread_local_attribute __thread + +#define bh_socket_t int + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) + +#include + +#define OS_ENABLE_HW_BOUND_CHECK + +typedef jmp_buf korp_jmpbuf; + +#define os_setjmp setjmp +#define os_longjmp longjmp +#define os_alloca alloca + +#define os_getpagesize getpagesize + +typedef void (*os_signal_handler)(void *sig_addr); + +int +os_thread_signal_init(os_signal_handler handler); + +void +os_thread_signal_destroy(); + +bool +os_thread_signal_inited(); + +void +os_signal_unmask(); + +void +os_sigreturn(); +#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ +#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ diff --git a/core/shared/platform/freebsd/shared_platform.cmake b/core/shared/platform/freebsd/shared_platform.cmake new file mode 100644 index 00000000..12583fc6 --- /dev/null +++ b/core/shared/platform/freebsd/shared_platform.cmake @@ -0,0 +1,18 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_FREEBSD) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) + +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/doc/build_wamr.md b/doc/build_wamr.md index f32d69bc..27bea955 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -637,3 +637,18 @@ $ ls ../build_out/ libvmlib.a ) and an executable binary (*iwasm*) and copy *iwasm* to *build_out*. All original generated files are still under *product-mini/platforms/linux/build*. + +FreeBSD +------------------------- +First, install the dependent packages: +```shell +sudo pkg install gcc cmake wget +``` + +Then you can run the following commands to build iwasm with default configurations: +```shell +cd product-mini/platforms/freebsd +mkdir build && cd build +cmake .. +make +``` diff --git a/product-mini/platforms/freebsd/CMakeLists.txt b/product-mini/platforms/freebsd/CMakeLists.txt new file mode 100644 index 00000000..fee2934c --- /dev/null +++ b/product-mini/platforms/freebsd/CMakeLists.txt @@ -0,0 +1,132 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.9) + +project (iwasm) + +set (WAMR_BUILD_PLATFORM "freebsd") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +set(CMAKE_CXX_STANDARD 14) + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_FAST_JIT) + # Disable Fast JIT by default + set (WAMR_BUILD_FAST_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT DEFINED WAMR_BUILD_FAST_INTERP) + # Enable fast interpreter + set (WAMR_BUILD_FAST_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + # Disable multiple module by default + set (WAMR_BUILD_MULTI_MODULE 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD) + # Disable pthread library by default + set (WAMR_BUILD_LIB_PTHREAD 0) +endif () + +if (NOT DEFINED WAMR_BUILD_MINI_LOADER) + # Disable wasm mini loader by default + set (WAMR_BUILD_MINI_LOADER 0) +endif () + +if (NOT DEFINED WAMR_BUILD_SIMD) + # Enable SIMD by default + set (WAMR_BUILD_SIMD 1) +endif () + +if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) + # Disable Debug feature by default + set (WAMR_BUILD_DEBUG_INTERP 0) +endif () + +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + set (WAMR_BUILD_FAST_INTERP 0) + set (WAMR_BUILD_MINI_LOADER 0) + set (WAMR_BUILD_SIMD 0) +endif () + +set (WAMR_DISABLE_HW_BOUND_CHECK 1) + +set (CMAKE_SHARED_LINKER_FLAGS "-Wl") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + +set (CMAKE_MACOSX_RPATH True) + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) + +install (TARGETS iwasm DESTINATION bin) + +target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) + +add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) + +install (TARGETS libiwasm DESTINATION lib) + +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) + +target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) + diff --git a/product-mini/platforms/freebsd/build_jit.sh b/product-mini/platforms/freebsd/build_jit.sh new file mode 100755 index 00000000..e6bee753 --- /dev/null +++ b/product-mini/platforms/freebsd/build_jit.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +rm -fr build && mkdir build +cd build +cmake .. -DWAMR_BUILD_JIT=1 +nproc=$(sysctl -n hw.ncpu) +make -j ${nproc} +cd .. diff --git a/product-mini/platforms/freebsd/build_llvm.sh b/product-mini/platforms/freebsd/build_llvm.sh new file mode 100755 index 00000000..47387a3c --- /dev/null +++ b/product-mini/platforms/freebsd/build_llvm.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# Copyright (C) 2020 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/usr/bin/env python3 ../../../build-scripts/build_llvm.py "$@" diff --git a/product-mini/platforms/freebsd/main.c b/product-mini/platforms/freebsd/main.c new file mode 100644 index 00000000..8f0e84a9 --- /dev/null +++ b/product-mini/platforms/freebsd/main.c @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "../posix/main.c" From ba5cdbee3ab09d48d1f415a4c0d66e856d98c74e Mon Sep 17 00:00:00 2001 From: tonibofarull Date: Mon, 26 Dec 2022 05:24:23 +0100 Subject: [PATCH 20/32] Fix typo verify_module in aot_compiler.c (#1836) --- core/iwasm/compilation/aot_compiler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 61e21613..925371b1 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2597,7 +2597,7 @@ fail: } static bool -veriy_module(AOTCompContext *comp_ctx) +verify_module(AOTCompContext *comp_ctx) { char *msg = NULL; bool ret; @@ -2697,7 +2697,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx) the compilation process */ if (!comp_ctx->is_jit_mode) { bh_print_time("Begin to verify LLVM module"); - if (!veriy_module(comp_ctx)) { + if (!verify_module(comp_ctx)) { return false; } } From 5d006ad2632d97183a8c8e246093203e1257e98d Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 26 Dec 2022 14:22:15 +0800 Subject: [PATCH 21/32] Reuse build llvm libraries for spec test on nuttx (#1838) Fix daily CI break on NuttX. --- .github/workflows/spec_test_on_nuttx.yml | 34 +++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 35c588d8..03f99f73 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -9,11 +9,21 @@ on: workflow_dispatch: +env: + LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" + jobs: + build_llvm_libraries: + uses: ./.github/workflows/build_llvm_libraries.yml + with: + runs-on: "['ubuntu-22.04']" + spec_test_on_qemu: - runs-on: ubuntu-22.04 + runs-on: ${{ matrix.os }} + needs: [build_llvm_libraries] strategy: matrix: + os: [ubuntu-22.04] nuttx_board_config: [ # cortex-a9 "boards/arm/imx6/sabre-6quad/configs/nsh", @@ -61,6 +71,25 @@ jobs: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr + - name: Get LLVM libraries + id: cache_llvm + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: steps.cache_llvm.outputs.cache-hit != 'true' + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: Copy LLVM + run: cp -r core/deps/llvm apps/interpreters/wamr/wamr/core/deps/llvm + - name: Enable WAMR for NuttX run: | find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_INTERPRETERS_WAMR=y\nCONFIG_INTERPRETERS_WAMR_AOT=y\nCONFIG_INTERPRETERS_WAMR_FAST=y\nCONFIG_INTERPRETERS_WAMR_LOG=y\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\nCONFIG_INTERPRETERS_WAMR_REF_TYPES=y\nCONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST=y\nCONFIG_INTERPRETERS_WAMR_SHARED_MEMORY=y\nCONFIG_INTERPRETERS_WAMR_BULK_MEMORY=y\n' @@ -69,8 +98,7 @@ jobs: - name: Build wamrc working-directory: apps/interpreters/wamr/wamr/wamr-compiler run: | - sudo apt install llvm-13-dev - cmake -Bbuild -DWAMR_BUILD_WITH_CUSTOM_LLVM=1 . + cmake -Bbuild . cmake --build build - name: Build From 676c3c7b04aa96a8fc98c372455f2b52af0ceda2 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 27 Dec 2022 12:59:17 +0800 Subject: [PATCH 22/32] Fix failure about preopen of reactor modules (#1816) Support modes: - run a commander module only - run a reactor module only - run a commander module and a/multiple reactor modules together commander propagates WASIArguments to reactors --- core/iwasm/common/wasm_c_api.c | 7 +++ core/iwasm/common/wasm_runtime_common.c | 38 ++++++++----- core/iwasm/interpreter/wasm_loader.c | 60 +++++++++++++++----- core/iwasm/interpreter/wasm_runtime.c | 74 +++++++++++++++++-------- core/iwasm/interpreter/wasm_runtime.h | 5 ++ 5 files changed, 132 insertions(+), 52 deletions(-) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index ae4ceaf9..1f148ee5 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -1628,6 +1628,8 @@ wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt, ret = wasm_externref_obj2ref(inst_comm_rt, v->of.ref, (uint32 *)data); break; +#else + (void)inst_comm_rt; #endif default: LOG_WARNING("unexpected value type %d", val_type_rt); @@ -1907,6 +1909,9 @@ wasm_trap_new_internal(wasm_store_t *store, frame_instance; } } +#else + (void)store; + (void)inst_comm_rt; #endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */ return trap; @@ -2034,6 +2039,7 @@ wasm_foreign_new_internal(wasm_store_t *store, uint32 foreign_idx_rt, } foreign->ref_cnt++; + (void)inst_comm_rt; return foreign; } @@ -4291,6 +4297,7 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, imported_func_interp->u.function.func_ptr_linked = import->u.cb; import->func_idx_rt = func_idx_rt; + (void)inst; return true; } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index fab9b59f..88dd1c19 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2359,19 +2359,27 @@ wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, const char *dir_list[], { WASIArguments *wasi_args = get_wasi_args_from_module(module); - if (wasi_args) { - wasi_args->dir_list = dir_list; - wasi_args->dir_count = dir_count; - wasi_args->map_dir_list = map_dir_list; - wasi_args->map_dir_count = map_dir_count; - wasi_args->env = env_list; - wasi_args->env_count = env_count; - wasi_args->argv = argv; - wasi_args->argc = (uint32)argc; - wasi_args->stdio[0] = stdinfd; - wasi_args->stdio[1] = stdoutfd; - wasi_args->stdio[2] = stderrfd; + bh_assert(wasi_args); + + wasi_args->dir_list = dir_list; + wasi_args->dir_count = dir_count; + wasi_args->map_dir_list = map_dir_list; + wasi_args->map_dir_count = map_dir_count; + wasi_args->env = env_list; + wasi_args->env_count = env_count; + wasi_args->argv = argv; + wasi_args->argc = (uint32)argc; + wasi_args->stdio[0] = stdinfd; + wasi_args->stdio[1] = stdoutfd; + wasi_args->stdio[2] = stderrfd; + +#if WASM_ENABLE_MULTI_MODULE != 0 +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + wasm_propagate_wasi_args((WASMModule *)module); } +#endif +#endif } void @@ -2488,7 +2496,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, wasm_runtime_set_wasi_ctx(module_inst, wasi_ctx); - /* process argv[0], trip the path and suffix, only keep the program name */ + /* process argv[0], trip the path and suffix, only keep the program name + */ if (!copy_string_array((const char **)argv, argc, &argv_buf, &argv_list, &argv_buf_size)) { set_error_buf(error_buf, error_buf_size, @@ -3188,7 +3197,8 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); - /* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args */ + /* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args + */ uint32 argv_buf[32], *argv1 = argv_buf, *ints, *stacks, size; uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0; uint32 arg_i32, ptr_len; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index ef7df8e0..6a39d368 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -684,7 +684,7 @@ adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) } } -#if WASM_ENABLE_MULTI_MODULE != 0 +#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0 /** * Find export item of a module with export info: * module name, field name and export kind @@ -718,11 +718,15 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name, return NULL; } + (void)module_name; + /* since there is a validation in load_export_section(), it is for sure * export->index is valid*/ return export; } +#endif +#if WASM_ENABLE_MULTI_MODULE != 0 static WASMFunction * wasm_loader_resolve_function(const char *module_name, const char *function_name, const WASMType *expected_function_type, @@ -1240,6 +1244,8 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, table->init_size = declare_init_size; table->flags = declare_max_size_flag; table->max_size = declare_max_size; + + (void)parent_module; return true; fail: return false; @@ -1373,6 +1379,8 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; *p_buf = p; + + (void)parent_module; return true; fail: return false; @@ -1439,6 +1447,8 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, global->field_name = global_name; global->type = declare_type; global->is_mutable = (declare_mutable == 1); + + (void)parent_module; return true; fail: return false; @@ -2381,6 +2391,7 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, } #else read_leb_uint32(p, p_end, function_index); + (void)use_init_expr; #endif /* since we are using -1 to indicate ref.null */ @@ -2690,6 +2701,7 @@ load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func, } LOG_VERBOSE("Load code segment section success.\n"); + (void)module; return true; fail: return false; @@ -2900,6 +2912,8 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, LOG_VERBOSE("Ignore custom section [%s].", section_name); + (void)is_load_from_file_buf; + (void)module; return true; fail: return false; @@ -4054,24 +4068,19 @@ fail: return false; } -#if (WASM_ENABLE_MULTI_MODULE != 0) && (WASM_ENABLE_LIBC_WASI != 0) +#if WASM_ENABLE_LIBC_WASI != 0 /** * refer to * https://github.com/WebAssembly/WASI/blob/main/design/application-abi.md */ static bool -check_wasi_abi_compatibility(const WASMModule *module, bool main_module, +check_wasi_abi_compatibility(const WASMModule *module, +#if WASM_ENABLE_MULTI_MODULE != 0 + bool main_module, +#endif char *error_buf, uint32 error_buf_size) { /** - * need to handle: - * - non-wasi compatiable modules - * - a fake wasi compatiable module - * - a command acts as a main_module - * - a command acts as a sub_module - * - a reactor acts as a main_module - * - a reactor acts as a sub_module - * * be careful with: * wasi compatiable modules(command/reactor) which don't import any wasi * APIs. Usually, a command has to import a "prox_exit" at least, but a @@ -4087,8 +4096,20 @@ check_wasi_abi_compatibility(const WASMModule *module, bool main_module, * - no one will define either `_start` or `_initialize` on purpose * - `_start` should always be `void _start(void)` * - `_initialize` should always be `void _initialize(void)` + * */ + /* clang-format off */ + /** + * + * | | import_wasi_api True | | import_wasi_api False | | + * | ----------- | -------------------- | ---------------- | --------------------- | ---------------- | + * | | \_initialize() Y | \_initialize() N | \_initialize() Y | \_initialize() N | + * | \_start() Y | N | COMMANDER | N | COMMANDER | + * | \_start() N | REACTOR | N | REACTOR | OTHERS | + */ + /* clang-format on */ + WASMExport *initialize = NULL, *memory = NULL, *start = NULL; /* (func (export "_start") (...) */ @@ -4147,6 +4168,7 @@ check_wasi_abi_compatibility(const WASMModule *module, bool main_module, return false; } +#if WASM_ENABLE_MULTI_MODULE != 0 /* filter out commands (with `_start`) cases */ if (start && !main_module) { set_error_buf( @@ -4154,6 +4176,7 @@ check_wasi_abi_compatibility(const WASMModule *module, bool main_module, "a command (with _start function) can not be a sub-module"); return false; } +#endif /* * it is ok a reactor acts as a main module, @@ -4193,10 +4216,13 @@ wasm_loader_load(uint8 *buf, uint32 size, goto fail; } -#if (WASM_ENABLE_MULTI_MODULE != 0) && (WASM_ENABLE_LIBC_WASI != 0) +#if WASM_ENABLE_LIBC_WASI != 0 /* Check the WASI application ABI */ - if (!check_wasi_abi_compatibility(module, main_module, error_buf, - error_buf_size)) { + if (!check_wasi_abi_compatibility(module, +#if WASM_ENABLE_MULTI_MODULE != 0 + main_module, +#endif + error_buf, error_buf_size)) { goto fail; } #endif @@ -4971,6 +4997,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, } (void)u8; + (void)exec_env; return false; fail: return false; @@ -5834,6 +5861,8 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, i += 2; } + (void)error_buf; + (void)error_buf_size; return true; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 @@ -6098,6 +6127,9 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, ctx->dynamic_offset -= 2; } emit_operand(ctx, *(ctx->frame_offset)); + + (void)error_buf; + (void)error_buf_size; return true; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 438dd59c..fd85b71b 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -983,6 +983,18 @@ export_globals_instantiate(const WASMModule *module, } #endif +#if WASM_ENABLE_LIBC_WASI != 0 +static bool +execute_initialize_function(WASMModuleInstance *module_inst) +{ + WASMFunctionInstance *initialize = + wasm_lookup_function(module_inst, "_initialize", NULL); + return !initialize + || wasm_create_exec_env_and_call_function(module_inst, initialize, 0, + NULL); +} +#endif + static bool execute_post_inst_function(WASMModuleInstance *module_inst) { @@ -1175,28 +1187,6 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, sub_module_list_node = bh_list_elem_next(sub_module_list_node); -#if WASM_ENABLE_LIBC_WASI != 0 - { - /* - * reactor instances may assume that _initialize will be called by - * the environment at most once, and that none of their other - * exports are accessed before that call. - * - * let the loader decide how to act if there is no _initialize - * in a reactor - */ - WASMFunctionInstance *initialize = - wasm_lookup_function(sub_module_inst, "_initialize", NULL); - if (initialize - && !wasm_create_exec_env_and_call_function( - sub_module_inst, initialize, 0, NULL)) { - set_error_buf(error_buf, error_buf_size, - "Call _initialize failed "); - goto failed; - } - } -#endif - continue; failed: if (sub_module_inst_list_node) { @@ -1844,8 +1834,21 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, &module_inst->e->functions[module->start_function]; } - /* Execute __post_instantiate function */ - if (!execute_post_inst_function(module_inst) + if ( +#if WASM_ENABLE_LIBC_WASI != 0 + /* + * reactor instances may assume that _initialize will be called by + * the environment at most once, and that none of their other + * exports are accessed before that call. + * + * let the loader decide how to act if there is no _initialize + * in a reactor + */ + !execute_initialize_function(module_inst) || +#endif + /* Execute __post_instantiate function */ + !execute_post_inst_function(module_inst) + /* Execute the function in "start" section */ || !execute_start_function(module_inst)) { set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); goto fail; @@ -3231,3 +3234,26 @@ llvm_jit_free_frame(WASMExecEnv *exec_env) || WASM_ENABLE_PERF_PROFILING != 0 */ #endif /* end of WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 */ + +#if WASM_ENABLE_LIBC_WASI != 0 && WASM_ENABLE_MULTI_MODULE != 0 +void +wasm_propagate_wasi_args(WASMModule *module) +{ + if (!module->import_count) + return; + + bh_assert(&module->import_module_list_head); + + WASMRegisteredModule *node = + bh_list_first_elem(&module->import_module_list_head); + while (node) { + WASIArguments *wasi_args_impt_mod = + &((WASMModule *)(node->module))->wasi_args; + bh_assert(wasi_args_impt_mod); + + bh_memcpy_s(wasi_args_impt_mod, sizeof(WASIArguments), + &module->wasi_args, sizeof(WASIArguments)); + node = bh_list_elem_next(node); + } +} +#endif diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 6d1a5340..5bf09bb8 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -626,6 +626,11 @@ llvm_jit_free_frame(WASMExecEnv *exec_env); #endif #endif /* end of WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 */ +#if WASM_ENABLE_LIBC_WASI != 0 && WASM_ENABLE_MULTI_MODULE != 0 +void +wasm_propagate_wasi_args(WASMModule *module); +#endif + #ifdef __cplusplus } #endif From 679a8ab3cb0a629844b2049615d7214ce3a3e4a7 Mon Sep 17 00:00:00 2001 From: Wang Ning Date: Tue, 27 Dec 2022 15:04:36 +0800 Subject: [PATCH 23/32] Perfect the codebase for wamr-ide (#1817) Fix errors and warnings reported by eslint Add CONTRIBUTING document for vscode-extension --- .../wamr-ide/VSCode-Extension/.eslintrc.json | 13 +- .../wamr-ide/VSCode-Extension/CONTRIBUTING.md | 34 +++ .../wamr-ide/VSCode-Extension/package.json | 1 + .../resource/webview/js/configbuildtarget.js | 9 +- .../src/debugConfigurationProvider.ts | 6 +- .../src/decorationProvider.ts | 37 +-- .../VSCode-Extension/src/extension.ts | 260 +++++++++--------- .../VSCode-Extension/src/taskProvider.ts | 9 +- .../src/utilities/directoryUtilities.ts | 10 +- .../VSCode-Extension/src/utilities/getUri.ts | 2 +- .../src/utilities/lldbUtilities.ts | 9 +- .../src/view/NewProjectPanel.ts | 81 +++--- .../src/view/TargetConfigPanel.ts | 111 ++++---- .../wamr-ide/VSCode-Extension/tsconfig.json | 33 +-- 14 files changed, 316 insertions(+), 299 deletions(-) create mode 100644 test-tools/wamr-ide/VSCode-Extension/CONTRIBUTING.md diff --git a/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json b/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json index f9b22b79..5c1fd464 100644 --- a/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json +++ b/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json @@ -1,13 +1,12 @@ { "root": true, "parser": "@typescript-eslint/parser", + "extends": ["plugin:@typescript-eslint/recommended"], "parserOptions": { - "ecmaVersion": 6, + "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": [ - "@typescript-eslint" - ], + "plugins": ["@typescript-eslint"], "rules": { "@typescript-eslint/naming-convention": "warn", "@typescript-eslint/semi": "warn", @@ -16,9 +15,5 @@ "no-throw-literal": "warn", "semi": "off" }, - "ignorePatterns": [ - "out", - "dist", - "**/*.d.ts" - ] + "ignorePatterns": ["out", "dist", "**/*.d.ts"] } diff --git a/test-tools/wamr-ide/VSCode-Extension/CONTRIBUTING.md b/test-tools/wamr-ide/VSCode-Extension/CONTRIBUTING.md new file mode 100644 index 00000000..f70a959e --- /dev/null +++ b/test-tools/wamr-ide/VSCode-Extension/CONTRIBUTING.md @@ -0,0 +1,34 @@ +# CONTRIBUTING + +## Pull requests + +To submit your change: + +- Make sure your code is in line with our + [coding conventions](##Coding-conventions). +- Create an [issue] describing the bug the PR fixes or the feature you intend + to implement. +- Submit a [pull request] into the main branch. + +## Coding conventions + +#### Format + +The codebase is formatted by `Prettier` and the `.prettierrc.json` has been +configured. + +- VSCode along with `Format on Save` configuration could easily format your + code during development. +- You can run `prettier-format-check` and `prettier-format-apply` to check and + format your codebase with `prettier` in terminal. + +#### Lint + +`ESlint` is used as linter for the codebase and the `.eslintrc.json` has been +configured. + +- It's suggested to run `npm run lint` then fix errors and warnings before + committing. + +[issue]: https://github.com/bytecodealliance/wasm-micro-runtime/issues +[pull request]: https://github.com/bytecodealliance/wasm-micro-runtime/pulls diff --git a/test-tools/wamr-ide/VSCode-Extension/package.json b/test-tools/wamr-ide/VSCode-Extension/package.json index 61d1387c..fa3292c2 100644 --- a/test-tools/wamr-ide/VSCode-Extension/package.json +++ b/test-tools/wamr-ide/VSCode-Extension/package.json @@ -229,6 +229,7 @@ "watch": "tsc -watch -p ./", "pretest": "npm run compile && npm run lint", "lint": "eslint src --ext ts", + "lint-fix": "eslint --fix src --ext ts", "test": "node ./out/test/runTest.js", "prettier-format-check": "prettier --config .prettierrc.json 'src/**/*.ts' --check", "prettier-format-apply": "prettier --config .prettierrc.json 'src/**/*.ts' --write" diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js b/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js index 58b5afe2..837f384b 100644 --- a/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js +++ b/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ - const vscode = acquireVsCodeApi(); document.getElementById('btn_submit').onclick = () => { @@ -12,16 +11,16 @@ document.getElementById('btn_submit').onclick = () => { function submitFunc() { let outputFileName = document.getElementById('output_file_name').value; - let initmemSize = document.getElementById('initial_mem_size').value; - let maxmemSize = document.getElementById('max_mem_size').value; + let initMemSize = document.getElementById('initial_mem_size').value; + let maxMemSize = document.getElementById('max_mem_size').value; let stackSize = document.getElementById('stack_size').value; let exportedSymbols = document.getElementById('exported_symbols').value; vscode.postMessage({ command: 'config_build_target', outputFileName: outputFileName, - initmemSize: initmemSize, - maxmemSize: maxmemSize, + initMemSize: initMemSize, + maxMemSize: maxMemSize, stackSize: stackSize, exportedSymbols: exportedSymbols, }); diff --git a/test-tools/wamr-ide/VSCode-Extension/src/debugConfigurationProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/debugConfigurationProvider.ts index 8fd539c8..6294f7ef 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/debugConfigurationProvider.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/debugConfigurationProvider.ts @@ -9,8 +9,6 @@ import * as os from 'os'; export class WasmDebugConfigurationProvider implements vscode.DebugConfigurationProvider { - constructor() {} - /* default port set as 1234 */ private port = 1234; private hostPath!: string; @@ -29,7 +27,7 @@ export class WasmDebugConfigurationProvider return this.providerPromise; } - public setDebugConfig(hostPath: string, port: number) { + public setDebugConfig(hostPath: string, port: number): void { this.port = port; this.hostPath = hostPath; /* linux and windows has different debug configuration */ @@ -57,7 +55,7 @@ export class WasmDebugConfigurationProvider } } - public getDebugConfig() { + public getDebugConfig(): vscode.DebugConfiguration { return this.wasmDebugConfig; } } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts index e9687f69..46efcc90 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/decorationProvider.ts @@ -26,11 +26,11 @@ export class DecorationProvider implements vscode.FileDecorationProvider { public onDidChangeFileDecorations: vscode.Event< vscode.Uri | vscode.Uri[] | undefined >; - private _eventEmiter: vscode.EventEmitter; + private eventEmitter: vscode.EventEmitter; constructor() { - this._eventEmiter = new vscode.EventEmitter(); - this.onDidChangeFileDecorations = this._eventEmiter.event; + this.eventEmitter = new vscode.EventEmitter(); + this.onDidChangeFileDecorations = this.eventEmitter.event; this.disposables.push( vscode.window.registerFileDecorationProvider(this) ); @@ -39,34 +39,27 @@ export class DecorationProvider implements vscode.FileDecorationProvider { public provideFileDecoration( uri: vscode.Uri ): vscode.ProviderResult { - let currentPrjDir, - prjConfigDir, - configFilePath, - configData, - includePathArr = new Array(), - excludeFileArr = new Array(), - pathRelative; - - /* Read include_paths and exclude_fils from the config file */ - currentPrjDir = + const currentPrjDir = os.platform() === 'win32' ? (vscode.workspace.workspaceFolders?.[0].uri.fsPath as string) : os.platform() === 'linux' || os.platform() === 'darwin' - ? (currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri - .path as string) + ? (vscode.workspace.workspaceFolders?.[0].uri.path as string) : ''; - pathRelative = (uri.fsPath ? uri.fsPath : uri.toString()).replace( + const pathRelative = (uri.fsPath ? uri.fsPath : uri.toString()).replace( currentPrjDir, '..' ); - prjConfigDir = path.join(currentPrjDir, '.wamr'); - configFilePath = path.join(prjConfigDir, 'compilation_config.json'); + const prjConfigDir = path.join(currentPrjDir, '.wamr'); + const configFilePath = path.join( + prjConfigDir, + 'compilation_config.json' + ); if (readFromFile(configFilePath) !== '') { - configData = JSON.parse(readFromFile(configFilePath)); - includePathArr = configData['include_paths']; - excludeFileArr = configData['exclude_files']; + const configData = JSON.parse(readFromFile(configFilePath)); + const includePathArr = configData['includePaths']; + const excludeFileArr = configData['excludeFiles']; if (includePathArr.indexOf(pathRelative) > -1) { return DECORATION_INCLUDE_PATHS; @@ -81,7 +74,7 @@ export class DecorationProvider implements vscode.FileDecorationProvider { } public updateDecorationsForSource(uri: vscode.Uri): void { - this._eventEmiter.fire(uri); + this.eventEmitter.fire(uri); } } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts index e1d33b4e..17dda949 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts @@ -26,13 +26,20 @@ import { let wasmTaskProvider: WasmTaskProvider; let wasmDebugConfigProvider: WasmDebugConfigurationProvider; -var currentPrjDir = ''; -var extensionPath = ''; -var isWasmProject = false; +let currentPrjDir = ''; +let isWasmProject = false; +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function activate(context: vscode.ExtensionContext) { - var OS_PLATFORM = '', - buildScript = '', + const extensionPath = context.extensionPath; + const osPlatform = os.platform(); + const wamrVersion = getWAMRExtensionVersion(context); + const typeMap = new Map(); + const scriptMap = new Map(); + /* set relative path of build.bat|sh script */ + const scriptPrefix = 'resource/scripts/'; + + let buildScript = '', runScript = '', debugScript = '', destroyScript = '', @@ -40,40 +47,27 @@ export async function activate(context: vscode.ExtensionContext) { runScriptFullPath = '', debugScriptFullPath = '', destroyScriptFullPath = '', - typeMap = new Map(), /* include paths array used for written into config file */ - includePathArr = new Array(), + includePathArr = new Array(), /* exclude files array used for written into config file */ - excludeFileArr = new Array(), - scriptMap = new Map(); - - const wamrVersion = getWAMRExtensionVersion(context); - - /** - * Get OS platform information for differ windows and linux execution script - */ - OS_PLATFORM = os.platform(); + excludeFileArr = new Array(); /** * Provide Build & Run Task with Task Provider instead of "tasks.json" */ - /* set relative path of build.bat|sh script */ - let scriptPrefix = 'resource/scripts/'; - if (OS_PLATFORM === 'win32') { + if (osPlatform === 'win32') { buildScript = scriptPrefix.concat('build.bat'); runScript = scriptPrefix.concat('run.bat'); debugScript = scriptPrefix.concat('boot_debugger_server.bat'); destroyScript = scriptPrefix.concat('destroy.bat'); - } else if (OS_PLATFORM === 'linux' || OS_PLATFORM === 'darwin') { + } else if (osPlatform === 'linux' || osPlatform === 'darwin') { buildScript = scriptPrefix.concat('build.sh'); runScript = scriptPrefix.concat('run.sh'); debugScript = scriptPrefix.concat('boot_debugger_server.sh'); destroyScript = scriptPrefix.concat('destroy.sh'); } - extensionPath = context.extensionPath; - buildScriptFullPath = path.join(extensionPath, buildScript); runScriptFullPath = path.join(extensionPath, runScript); debugScriptFullPath = path.join(extensionPath, debugScript); @@ -94,10 +88,10 @@ export async function activate(context: vscode.ExtensionContext) { vscode.tasks.registerTaskProvider('wasm', wasmTaskProvider); if (vscode.workspace.workspaceFolders?.[0]) { - if (OS_PLATFORM === 'win32') { + if (osPlatform === 'win32') { currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri .fsPath as string; - } else if (OS_PLATFORM === 'linux' || OS_PLATFORM === 'darwin') { + } else if (osPlatform === 'linux' || osPlatform === 'darwin') { currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri .path as string; } @@ -107,7 +101,7 @@ export async function activate(context: vscode.ExtensionContext) { * it not, `build`, `run` and `debug` will be disabled */ if (currentPrjDir !== '') { - let wamrFolder = fileSystem + const wamrFolder = fileSystem .readdirSync(currentPrjDir, { withFileTypes: true, }) @@ -133,7 +127,7 @@ export async function activate(context: vscode.ExtensionContext) { .getConfiguration() .get('C_Cpp.default.systemIncludePath'); - let LibcBuiltinHeaderPath = path.join( + const libcBuiltinHeaderPath = path.join( extensionPath, 'resource/wamr-sdk/libc-builtin-sysroot/include' ); @@ -141,17 +135,17 @@ export async function activate(context: vscode.ExtensionContext) { if (newIncludeInCppArr !== undefined) { /* in case the configuration has not been set up, push directly */ if (newIncludeInCppArr === null) { - newIncludeInCppArr = new Array(); - newIncludeInCppArr.push(LibcBuiltinHeaderPath); + newIncludeInCppArr = []; + newIncludeInCppArr.push(libcBuiltinHeaderPath); } else { /* if the configuration has been set up, check the condition */ if ( /* include libc-builtin-sysroot */ newIncludeInCppArr.indexOf( - LibcBuiltinHeaderPath + libcBuiltinHeaderPath ) < 0 ) { - newIncludeInCppArr.push(LibcBuiltinHeaderPath); + newIncludeInCppArr.push(libcBuiltinHeaderPath); } } @@ -185,21 +179,21 @@ export async function activate(context: vscode.ExtensionContext) { ]); if (readFromConfigFile() !== '') { - let configData = JSON.parse(readFromConfigFile()); - includePathArr = configData['include_paths']; - excludeFileArr = configData['exclude_files']; + const configData = JSON.parse(readFromConfigFile()); + includePathArr = configData['includePaths']; + excludeFileArr = configData['excludeFiles']; - if (Object.keys(configData['build_args']).length !== 0) { - TargetConfigPanel.BUILD_ARGS = configData['build_args']; + if (Object.keys(configData['buildArgs']).length !== 0) { + TargetConfigPanel.buildArgs = configData['buildArgs']; } } - let disposableNewProj = vscode.commands.registerCommand( + const disposableNewProj = vscode.commands.registerCommand( 'wamride.newProject', () => { - let _ok = 'Set up now'; - let _cancle = 'Maybe later'; - let curWorkspace = vscode.workspace + const okStr = 'Set up now'; + const cancelStr = 'Maybe later'; + const curWorkspace = vscode.workspace .getConfiguration() .get('WAMR-IDE.configWorkspace'); @@ -208,11 +202,11 @@ export async function activate(context: vscode.ExtensionContext) { vscode.window .showWarningMessage( 'Please setup your workspace firstly.', - _ok, - _cancle + okStr, + cancelStr ) .then(item => { - if (item === _ok) { + if (item === okStr) { vscode.commands.executeCommand( 'wamride.changeWorkspace' ); @@ -233,10 +227,10 @@ export async function activate(context: vscode.ExtensionContext) { .get('WAMR-IDE.configWorkspace') + '', }, - _ok + okStr ) .then(item => { - if (item === _ok) { + if (item === okStr) { vscode.commands.executeCommand( 'wamride.changeWorkspace' ); @@ -250,7 +244,7 @@ export async function activate(context: vscode.ExtensionContext) { } ); - let disposableTargetConfig = vscode.commands.registerCommand( + const disposableTargetConfig = vscode.commands.registerCommand( 'wamride.targetConfig', () => { if (currentPrjDir !== '') { @@ -264,16 +258,16 @@ export async function activate(context: vscode.ExtensionContext) { } ); - let disposableChangeWorkspace = vscode.commands.registerCommand( + const disposableChangeWorkspace = vscode.commands.registerCommand( 'wamride.changeWorkspace', async () => { - let options: vscode.OpenDialogOptions = { + const options: vscode.OpenDialogOptions = { canSelectFiles: false, canSelectFolders: true, openLabel: 'Select Workspace', }; - let Workspace = await vscode.window + const workSpace = await vscode.window .showOpenDialog(options) .then(res => { if (res) { @@ -284,21 +278,21 @@ export async function activate(context: vscode.ExtensionContext) { }); /* update workspace value to vscode global settings */ - if (Workspace !== '' && Workspace !== undefined) { + if (workSpace !== '' && workSpace !== undefined) { await vscode.workspace .getConfiguration() .update( 'WAMR-IDE.configWorkspace', - Workspace.trim(), + workSpace.trim(), vscode.ConfigurationTarget.Global ) .then( - success => { + () => { vscode.window.showInformationMessage( 'Workspace has been set up successfully!' ); }, - error => { + () => { vscode.window.showErrorMessage( 'Set up Workspace failed!' ); @@ -308,7 +302,7 @@ export async function activate(context: vscode.ExtensionContext) { } ); - let disposableBuild = vscode.commands.registerCommand( + const disposableBuild = vscode.commands.registerCommand( 'wamride.build', () => { if (!isWasmProject) { @@ -327,7 +321,7 @@ export async function activate(context: vscode.ExtensionContext) { 'Destroy: Wasm-Container-Before-Build' ) .then(() => { - let disposable = vscode.tasks.onDidEndTaskProcess(t => { + const disposable = vscode.tasks.onDidEndTaskProcess(t => { if ( t.execution.task.name === 'Wasm-Container-Before-Build' @@ -345,7 +339,7 @@ export async function activate(context: vscode.ExtensionContext) { ) .then(() => { /* destroy the wasm-toolchain-ctr after building */ - let disposable_aft = + const disposableAft = vscode.tasks.onDidEndTask(a => { if ( a.execution.task.name === @@ -361,7 +355,7 @@ export async function activate(context: vscode.ExtensionContext) { .then(() => { /* dispose the event after this building process */ - disposable_aft.dispose(); + disposableAft.dispose(); }); } }); @@ -374,7 +368,7 @@ export async function activate(context: vscode.ExtensionContext) { } ); - let disposableDebug = vscode.commands.registerCommand( + const disposableDebug = vscode.commands.registerCommand( 'wamride.debug', async () => { if (!isWasmProject) { @@ -414,7 +408,7 @@ export async function activate(context: vscode.ExtensionContext) { ) .then(() => { /* execute the debug task when destroy task finish */ - let disposable_bfr = vscode.tasks.onDidEndTask(t => { + const disposableBfr = vscode.tasks.onDidEndTask(t => { if ( t.execution.task.name === 'Wasm-Container-Before-Debug' @@ -432,7 +426,7 @@ export async function activate(context: vscode.ExtensionContext) { ) .then(() => { /* register to listen debug session finish event */ - let dispose_aft = + const disposableAft = vscode.debug.onDidTerminateDebugSession( s => { if ( @@ -455,18 +449,19 @@ export async function activate(context: vscode.ExtensionContext) { 'Debug: Wasm' ); - dispose_aft.dispose(); + disposableAft.dispose(); } ); }); }); } - disposable_bfr.dispose(); + disposableBfr.dispose(); }); }); } ); - let disposableRun = vscode.commands.registerCommand('wamride.run', () => { + + const disposableRun = vscode.commands.registerCommand('wamride.run', () => { if (!isWasmProject) { vscode.window.showErrorMessage('run failed', { modal: true, @@ -489,7 +484,7 @@ export async function activate(context: vscode.ExtensionContext) { 'Destroy: Wasm-Container-Before-Run' ) .then(() => { - let dispose_bfr = vscode.tasks.onDidEndTaskProcess(e => { + const disposableAft = vscode.tasks.onDidEndTaskProcess(e => { if (e.execution.task.name === 'Wasm-Container-Before-Run') { /* make sure that run wasm task will be executed after destroy task finish */ vscode.commands @@ -499,25 +494,24 @@ export async function activate(context: vscode.ExtensionContext) { ) .then(() => { if (e.exitCode !== 0) { - dispose_bfr.dispose(); + disposableAft.dispose(); return; } }); - dispose_bfr.dispose(); + disposableAft.dispose(); } }); }); }); - let disposableToggleIncludePath = vscode.commands.registerCommand( + const disposableToggleIncludePath = vscode.commands.registerCommand( 'wamride.build.toggleStateIncludePath', fileUri => { - let pathRelative: string; - let path = + const path = fileUri._fsPath !== null && fileUri._fsPath !== undefined ? fileUri._fsPath : vscode.Uri.parse(fileUri.path as string).fsPath; - pathRelative = path.replace(currentPrjDir, '..'); + const pathRelative = path.replace(currentPrjDir, '..'); if (includePathArr.indexOf(pathRelative) > -1) { /* this folder has been added to include path, remove it */ @@ -531,25 +525,23 @@ export async function activate(context: vscode.ExtensionContext) { writeIntoConfigFile( includePathArr, excludeFileArr, - TargetConfigPanel.BUILD_ARGS + TargetConfigPanel.buildArgs ); decorationProvider.updateDecorationsForSource(fileUri); } ); - let disposableToggleExcludeFile = vscode.commands.registerCommand( + const disposableToggleExcludeFile = vscode.commands.registerCommand( 'wamride.build.toggleStateExclude', fileUri => { - let pathRelative: string; - - let path = + const path = fileUri._fsPath !== null && fileUri._fsPath !== undefined ? fileUri._fsPath : vscode.Uri.parse(fileUri.path as string).fsPath; /* replace the current project absolute path with .. to change to relative path */ - pathRelative = path.replace(currentPrjDir, '..'); + const pathRelative = path.replace(currentPrjDir, '..'); if (excludeFileArr.indexOf(pathRelative) > -1) { excludeFileArr = excludeFileArr.filter(val => { @@ -562,7 +554,7 @@ export async function activate(context: vscode.ExtensionContext) { writeIntoConfigFile( includePathArr, excludeFileArr, - TargetConfigPanel.BUILD_ARGS + TargetConfigPanel.buildArgs ); /* update decoration for this source file */ @@ -570,14 +562,14 @@ export async function activate(context: vscode.ExtensionContext) { } ); - let disposableOpenFolder = vscode.commands.registerCommand( + const disposableOpenFolder = vscode.commands.registerCommand( 'wamride.openFolder', () => { /* get projects list under current workspace */ - let _ok = 'Set up now'; - let _cancle = 'Maybe later'; - let _create = 'Create now'; - let curWorkspace = vscode.workspace + const okStr = 'Set up now'; + const cancelStr = 'Maybe later'; + const createStr = 'Create now'; + const curWorkspace = vscode.workspace .getConfiguration() .get('WAMR-IDE.configWorkspace') as string; @@ -586,11 +578,11 @@ export async function activate(context: vscode.ExtensionContext) { vscode.window .showWarningMessage( 'Please setup your workspace firstly.', - _ok, - _cancle + okStr, + cancelStr ) .then(item => { - if (item === _ok) { + if (item === okStr) { vscode.commands.executeCommand( 'wamride.changeWorkspace' ); @@ -611,10 +603,10 @@ export async function activate(context: vscode.ExtensionContext) { .get('WAMR-IDE.configWorkspace') + '', }, - _ok + okStr ) .then(item => { - if (item === _ok) { + if (item === okStr) { vscode.commands.executeCommand( 'wamride.changeWorkspace' ); @@ -640,7 +632,7 @@ export async function activate(context: vscode.ExtensionContext) { .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name); - let projFilesArr = directoryArr.filter(obj => { + const projFilesArr = directoryArr.filter(obj => { if (checkIfWasmProj(path.join(curWorkspace, obj))) { return true; } @@ -650,11 +642,11 @@ export async function activate(context: vscode.ExtensionContext) { vscode.window .showWarningMessage( 'Current workspace is empty, please create your project firstly.', - _create, - _cancle + createStr, + cancelStr ) .then(item => { - if (item === _create) { + if (item === createStr) { vscode.commands.executeCommand( 'wamride.newProject' ); @@ -673,18 +665,18 @@ export async function activate(context: vscode.ExtensionContext) { return; } - let _path = curWorkspace.concat( - OS_PLATFORM === 'win32' + const path = curWorkspace.concat( + osPlatform === 'win32' ? '\\' - : OS_PLATFORM === 'linux' || - OS_PLATFORM === 'darwin' + : osPlatform === 'linux' || + osPlatform === 'darwin' ? '/' : '', option ); /* open the selected wasm project */ - openWindoWithSituation(vscode.Uri.file(_path)); + openWindowWithSituation(vscode.Uri.file(path)); }); } } @@ -713,13 +705,14 @@ export async function activate(context: vscode.ExtensionContext) { } } -function openWindoWithSituation(uri: vscode.Uri) { +function openWindowWithSituation(uri: vscode.Uri) { /** * check if the workspace folder is empty, * if yes, open new window, else open in current window */ - let isWorkspaceEmpty: boolean; - isWorkspaceEmpty = !vscode.workspace.workspaceFolders?.[0] ? true : false; + const isWorkspaceEmpty = !vscode.workspace.workspaceFolders?.[0] + ? true + : false; isWorkspaceEmpty === false ? vscode.commands.executeCommand('vscode.openFolder', uri, { @@ -731,11 +724,11 @@ function openWindoWithSituation(uri: vscode.Uri) { } interface BuildArgs { - output_file_name: string; - init_memory_size: string; - max_memory_size: string; - stack_size: string; - exported_symbols: string; + outputFileName: string; + initMemorySize: string; + maxMemorySize: string; + stackSize: string; + exportedSymbols: string; } /** @@ -748,25 +741,25 @@ export function writeIntoConfigFile( includePathArr: string[], excludeFileArr: string[], buildArgs?: BuildArgs -) { - let jsonStr = JSON.stringify( +): void { + const jsonStr = JSON.stringify( { - include_paths: includePathArr, - exclude_files: excludeFileArr, - build_args: buildArgs ? buildArgs : '{}', + includePaths: includePathArr, + excludeFiles: excludeFileArr, + buildArgs: buildArgs ? buildArgs : '{}', }, null, '\t' ); - let prjConfigDir = path.join(currentPrjDir, '.wamr'); - let configFilePath = path.join(prjConfigDir, 'compilation_config.json'); + const prjConfigDir = path.join(currentPrjDir, '.wamr'); + const configFilePath = path.join(prjConfigDir, 'compilation_config.json'); writeIntoFile(configFilePath, jsonStr); } export function readFromConfigFile(): string { - let prjConfigDir = path.join(currentPrjDir, '.wamr'); - let configFilePath = path.join(prjConfigDir, 'compilation_config.json'); + const prjConfigDir = path.join(currentPrjDir, '.wamr'); + const configFilePath = path.join(prjConfigDir, 'compilation_config.json'); return readFromFile(configFilePath); } @@ -778,9 +771,9 @@ function generateCMakeFile( excludeFileArr: string[] ): void { // -Wl,--export=${EXPORT_SYMBOLS} - let srcFilePath = path.join(currentPrjDir, 'src'); - let prjConfigDir = path.join(currentPrjDir, '.wamr'); - let cmakeFilePath = path.join(prjConfigDir, 'project.cmake'); + const srcFilePath = path.join(currentPrjDir, 'src'); + const prjConfigDir = path.join(currentPrjDir, '.wamr'); + const cmakeFilePath = path.join(prjConfigDir, 'project.cmake'); let strIncludeList = 'set (PROJECT_INCLUDES'; let strSrcList = 'set (PROJECT_SRC_LIST'; @@ -795,17 +788,16 @@ function generateCMakeFile( let i, s, e: number; /* change the absolute path into relative path */ - let _re = currentPrjDir; - let _substr = '${CMAKE_CURRENT_SOURCE_DIR}/..'; + const _re = currentPrjDir; + const _substr = '${CMAKE_CURRENT_SOURCE_DIR}/..'; - let srcPathArr: Array<{ path: string }> | undefined; /** * set PROJECT_SRC_LIST * default ADD every c OR c++ OR cpp under the src/ path - * except the files saved in the exclude_files array + * except the files saved in the excludeFiles array */ - srcPathArr = getAllSrcFiles(srcFilePath); + const srcPathArr = getAllSrcFiles(srcFilePath); if (srcPathArr === undefined) { return; @@ -818,46 +810,46 @@ function generateCMakeFile( ) === -1 ) { /* replace currentPrjDir with ${CMAKE_CURRENT_SOURCE_DIR} */ - let _newStr = srcPathArr[s].path + const newStr = srcPathArr[s].path .replace(_re, _substr) .replace(/\\/g, '/'); - strSrcList = strSrcList.concat(' ', _newStr); + strSrcList = strSrcList.concat(' ', newStr); } } strSrcList = strSrcList.concat(' )'); for (i = 0; i < includePathArr.length; i++) { - let _newStr = includePathArr[i] + const newStr = includePathArr[i] .replace(/../, _substr) .replace(/\\/g, '/'); - strIncludeList = strIncludeList.concat(' ', _newStr); + strIncludeList = strIncludeList.concat(' ', newStr); } strIncludeList = strIncludeList.concat(' )'); /* set up user customized input in configBuildArgs webview */ strOutputFileName = strOutputFileName.concat( ' ', - TargetConfigPanel.BUILD_ARGS.output_file_name + ')' + TargetConfigPanel.buildArgs.outputFileName + ')' ); strInitMemSize = strInitMemSize.concat( ' ', - TargetConfigPanel.BUILD_ARGS.init_memory_size + ')' + TargetConfigPanel.buildArgs.initMemorySize + ')' ); strMaxMemSize = strMaxMemSize.concat( ' ', - TargetConfigPanel.BUILD_ARGS.max_memory_size + ')' + TargetConfigPanel.buildArgs.maxMemorySize + ')' ); strStackSize = strStackSize.concat( ' ', - TargetConfigPanel.BUILD_ARGS.stack_size + ')' + TargetConfigPanel.buildArgs.stackSize + ')' ); - let exportedSymbolArr = - TargetConfigPanel.BUILD_ARGS.exported_symbols.split(','); + const exportedSymbolArr = + TargetConfigPanel.buildArgs.exportedSymbols.split(','); strExportedSymbols = strExportedSymbols.concat(' "'); @@ -901,7 +893,7 @@ function getAllSrcFiles(_path: string) { const folders = entries.filter(folder => folder.isDirectory()); for (const folder of folders) { - let fileArr = getAllSrcFiles(path.join(_path, folder.name)); + const fileArr = getAllSrcFiles(path.join(_path, folder.name)); fileArr ? files.push(...fileArr) : ''; } @@ -911,7 +903,7 @@ function getAllSrcFiles(_path: string) { } } -function checkIfBuildSuccess(): Boolean { +function checkIfBuildSuccess(): boolean { try { let wasmExist = false; const entries = fileSystem.readdirSync( @@ -933,10 +925,10 @@ function checkIfBuildSuccess(): Boolean { } } -function checkIfWasmProj(_path: string): Boolean { +function checkIfWasmProj(path: string): boolean { try { let isWasmProj = false; - const entries = fileSystem.readdirSync(_path, { + const entries = fileSystem.readdirSync(path, { withFileTypes: true, }); diff --git a/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts index 7b2408bd..9b9b75f9 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts @@ -29,8 +29,8 @@ export class WasmTaskProvider implements vscode.TaskProvider { public provideTasks(): Thenable | undefined { if (!this.wasmPromise) { /* target name is used for generated aot target */ - let targetName = - TargetConfigPanel.BUILD_ARGS.output_file_name.split('.')[0]; + const targetName = + TargetConfigPanel.buildArgs.outputFileName.split('.')[0]; if ( os.platform() === 'linux' || @@ -219,7 +219,10 @@ export class WasmTaskProvider implements vscode.TaskProvider { * @param _task * @returns */ - public resolveTask(_task: vscode.Task): vscode.Task | undefined { + public resolveTask(task: vscode.Task): vscode.Task | undefined { + if (task) { + return task; + } return undefined; } } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts index c55be471..0efbea5d 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts @@ -31,7 +31,7 @@ export function createDirectory( return false; } - let parent = path.dirname(dest); + const parent = path.dirname(dest); if (!createDirectory(parent, mode)) { return false; } @@ -44,6 +44,7 @@ export function createDirectory( } } +// eslint-disable-next-line @typescript-eslint/no-unused-vars export function copyFiles(src: string, dest: string, flags?: number): boolean { try { fileSystem.copyFileSync(src, dest); @@ -64,7 +65,7 @@ export function writeIntoFile(path: string, data: string): void { export function readFromFile(path: string): string { try { - let data = fileSystem.readFileSync(path, { encoding: 'utf-8' }); + const data = fileSystem.readFileSync(path, { encoding: 'utf-8' }); return data as string; } catch (err) { vscode.window.showErrorMessage(err as string); @@ -114,9 +115,9 @@ export function checkIfFileExists(path: string): boolean { return false; } -export function checkFolderName(folderName: string) { +export function checkFolderName(folderName: string): boolean { let invalidCharacterArr: string[] = []; - var valid = true; + let valid = true; if (folderName.length > 255) { valid = false; @@ -143,6 +144,7 @@ export function downloadFile( ): Promise { return new Promise((resolve, reject) => { const file = fileSystem.createWriteStream(destinationPath); + // eslint-disable-next-line @typescript-eslint/no-unused-vars const stream = request(url, undefined, (error, response, body) => { if (response.statusCode !== 200) { reject( diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts index d897489d..93a7eef3 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts @@ -9,6 +9,6 @@ export function getUri( webview: Webview, extensionUri: Uri, pathList: string[] -) { +): Uri { return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList)); } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts index d2ad4130..a1729ab9 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts @@ -37,6 +37,7 @@ function getLLDBUnzipFilePath(destinationFolder: string, filename: string) { export function getWAMRExtensionVersion( context: vscode.ExtensionContext ): string { + // eslint-disable-next-line @typescript-eslint/no-var-requires return require(path.join(context.extensionPath, 'package.json')).version; } @@ -64,7 +65,9 @@ export function isLLDBInstalled(context: vscode.ExtensionContext): boolean { return checkIfFileExists(lldbBinaryPath); } -export async function promptInstallLLDB(context: vscode.ExtensionContext) { +export async function promptInstallLLDB( + context: vscode.ExtensionContext +): Promise { const extensionPath = context.extensionPath; const setupPrompt = 'setup'; const skipPrompt = 'skip'; @@ -111,5 +114,7 @@ export async function promptInstallLLDB(context: vscode.ExtensionContext) { ); // Remove the bundle.zip - fs.unlink(lldbZipPath, () => {}); + fs.unlink(lldbZipPath, () => { + return; + }); } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts b/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts index 29f1e054..79671f68 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts @@ -15,35 +15,37 @@ import { import { getUri } from '../utilities/getUri'; export class NewProjectPanel { - static USER_SET_WORKSPACE: string; + public static userSetWorkSpace: string; public static currentPanel: NewProjectPanel | undefined; - private readonly _panel: vscode.WebviewPanel; - private _disposables: vscode.Disposable[] = []; + private readonly viewPanel: vscode.WebviewPanel; + private disposableArr: vscode.Disposable[] = []; - static readonly EXCUTION_SUCCESS: number = 0; - static readonly DIR_EXSITED_ERR: number = -1; - static readonly USER_INTPUT_ERR: number = -2; - static readonly DIR_PATH_INVALID_ERR: number = -3; + private static readonly executionSuccess = 0; + private static readonly dirExistedError = -1; + private static readonly userInputError = -2; + private static readonly dirPathInvalidError = -3; constructor(extensionUri: vscode.Uri, panel: vscode.WebviewPanel) { - this._panel = panel; - this._panel.webview.html = this._getHtmlForWebview( - this._panel.webview, + this.viewPanel = panel; + this.viewPanel.webview.html = this.getHtmlForWebview( + this.viewPanel.webview, extensionUri, 'resource/webview/page/newProject.html' ); - this._setWebviewMessageListener(this._panel.webview, extensionUri); - this._panel.onDidDispose(this.dispose, null, this._disposables); + this._setWebviewMessageListener(this.viewPanel.webview, extensionUri); + this.viewPanel.onDidDispose(this.dispose, null, this.disposableArr); } - public static render(context: vscode.ExtensionContext) { - NewProjectPanel.USER_SET_WORKSPACE = vscode.workspace + public static render(context: vscode.ExtensionContext): void { + NewProjectPanel.userSetWorkSpace = vscode.workspace .getConfiguration() .get('WAMR-IDE.configWorkspace') as string; /* check if current panel is initialized */ if (NewProjectPanel.currentPanel) { - NewProjectPanel.currentPanel._panel.reveal(vscode.ViewColumn.One); + NewProjectPanel.currentPanel.viewPanel.reveal( + vscode.ViewColumn.One + ); } else { const panel = vscode.window.createWebviewPanel( 'newProject', @@ -62,25 +64,25 @@ export class NewProjectPanel { } } - private _creatNewProject( + private createNewProject( projName: string, template: string, extensionUri: vscode.Uri ): number { if (projName === '' || template === '') { - return NewProjectPanel.USER_INTPUT_ERR; + return NewProjectPanel.userInputError; } if (!checkFolderName(projName)) { - return NewProjectPanel.DIR_PATH_INVALID_ERR; + return NewProjectPanel.dirPathInvalidError; } - let ROOT_PATH = path.join(NewProjectPanel.USER_SET_WORKSPACE, projName); - let EXT_PATH = extensionUri.fsPath; + const ROOT_PATH = path.join(NewProjectPanel.userSetWorkSpace, projName); + const EXT_PATH = extensionUri.fsPath; if (fs.existsSync(ROOT_PATH)) { if (fs.lstatSync(ROOT_PATH).isDirectory()) { - return NewProjectPanel.DIR_EXSITED_ERR; + return NewProjectPanel.dirExistedError; } } @@ -98,14 +100,14 @@ export class NewProjectPanel { path.join(ROOT_PATH, '.wamr/project.cmake') ); - return NewProjectPanel.EXCUTION_SUCCESS; + return NewProjectPanel.executionSuccess; } - public _getHtmlForWebview( + public getHtmlForWebview( webview: vscode.Webview, extensionUri: vscode.Uri, templatePath: string - ) { + ): string { const toolkitUri = getUri(webview, extensionUri, [ 'node_modules', '@vscode', @@ -146,14 +148,14 @@ export class NewProjectPanel { message => { switch (message.command) { case 'create_new_project': - let createNewProjectStatus = this._creatNewProject( + const createNewProjectStatus = this.createNewProject( message.projectName, message.template, extensionUri ); if ( createNewProjectStatus === - NewProjectPanel.EXCUTION_SUCCESS + NewProjectPanel.executionSuccess ) { webview.postMessage({ command: 'proj_creation_finish', @@ -161,17 +163,17 @@ export class NewProjectPanel { }); } else if ( createNewProjectStatus === - NewProjectPanel.DIR_EXSITED_ERR + NewProjectPanel.dirExistedError ) { vscode.window.showErrorMessage( 'Project : ' + message.projectName + - ' exsits in your current root path, please change project name or root path!' + ' exists in your current root path, please change project name or root path!' ); return; } else if ( createNewProjectStatus === - NewProjectPanel.USER_INTPUT_ERR + NewProjectPanel.userInputError ) { vscode.window.showErrorMessage( 'Please fill chart before your submit!' @@ -179,7 +181,7 @@ export class NewProjectPanel { return; } else if ( createNewProjectStatus === - NewProjectPanel.DIR_PATH_INVALID_ERR + NewProjectPanel.dirPathInvalidError ) { if (os.platform() === 'win32') { vscode.window.showErrorMessage( @@ -203,19 +205,18 @@ export class NewProjectPanel { message.projectName + ' will be opened!' ); - let isWorkspaceEmpty: boolean; - let projPath = path.join( - NewProjectPanel.USER_SET_WORKSPACE, + const projPath = path.join( + NewProjectPanel.userSetWorkSpace, message.projectName ); - let uri = vscode.Uri.file(projPath); + const uri = vscode.Uri.file(projPath); /** * check if the vscode workspace folder is empty, * if yes, open new window, else open in current window */ - isWorkspaceEmpty = !vscode.workspace + const isWorkspaceEmpty = !vscode.workspace .workspaceFolders?.[0] ? true : false; @@ -233,7 +234,7 @@ export class NewProjectPanel { ); case 'close_webview': - this._panel.dispose(); + this.viewPanel.dispose(); return; default: @@ -241,16 +242,16 @@ export class NewProjectPanel { } }, undefined, - this._disposables + this.disposableArr ); } private dispose() { NewProjectPanel.currentPanel = undefined; - this._panel.dispose(); + this.viewPanel.dispose(); - while (this._disposables.length) { - const disposable = this._disposables.pop(); + while (this.disposableArr.length) { + const disposable = this.disposableArr.pop(); if (disposable) { disposable.dispose(); } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts b/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts index ccf0a0fe..f2e1343a 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts @@ -11,19 +11,19 @@ import { getUri } from '../utilities/getUri'; export class TargetConfigPanel { public static currentPanel: TargetConfigPanel | undefined; - private readonly _panel: vscode.WebviewPanel; + private readonly viewPanel: vscode.WebviewPanel; private _disposables: vscode.Disposable[] = []; - public static BUILD_ARGS = { - output_file_name: 'main.wasm', - init_memory_size: '131072', - max_memory_size: '131072', - stack_size: '4096', - exported_symbols: 'main', + public static buildArgs = { + outputFileName: 'main.wasm', + initMemorySize: '131072', + maxMemorySize: '131072', + stackSize: '4096', + exportedSymbols: 'main', }; - static readonly USER_INTPUT_ERR: number = -2; - static readonly EXCUTION_SUCCESS: number = 0; + private static readonly userInputError: number = -2; + private static readonly executionSuccess: number = 0; /** * @@ -31,24 +31,26 @@ export class TargetConfigPanel { * @param panelName */ constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { - this._panel = panel; - this._panel.webview.html = this._getHtmlForWebview( - this._panel.webview, + this.viewPanel = panel; + this.viewPanel.webview.html = this._getHtmlForWebview( + this.viewPanel.webview, extensionUri, 'resource/webview/page/configBuildTarget.html' ); - this._panel.onDidDispose(this.dispose, null, this._disposables); - this._setWebviewMessageListener(this._panel.webview); + this.viewPanel.onDidDispose(this.dispose, null, this._disposables); + this._setWebviewMessageListener(this.viewPanel.webview); } /** * * @param context */ - public static render(context: vscode.ExtensionContext) { + public static render(context: vscode.ExtensionContext): void { /* check if current panel is initialized */ if (TargetConfigPanel.currentPanel) { - TargetConfigPanel.currentPanel._panel.reveal(vscode.ViewColumn.One); + TargetConfigPanel.currentPanel.viewPanel.reveal( + vscode.ViewColumn.One + ); } else { const panel = vscode.window.createWebviewPanel( 'targetConfig', @@ -67,59 +69,56 @@ export class TargetConfigPanel { } } - private _configBuildArgs( + private configBuildArgs( outputFileName: string, - initmemSize: string, - maxmemSize: string, + initMemSize: string, + maxMemSize: string, stackSize: string, exportedSymbols: string ): number { if ( outputFileName === '' || - initmemSize === '' || - maxmemSize === '' || + initMemSize === '' || + maxMemSize === '' || stackSize === '' || exportedSymbols === '' ) { - return TargetConfigPanel.USER_INTPUT_ERR; + return TargetConfigPanel.userInputError; } - let _configStr: string; - let includePathArr = new Array(); - let excludeFileArr = new Array(); - let configJson: any; + let includePathArr = []; + let excludeFileArr = []; - let _configObj = { - output_file_name: outputFileName, - init_memory_size: initmemSize, - max_memory_size: maxmemSize, - stack_size: stackSize, - exported_symbols: exportedSymbols, + const configObj = { + outputFileName: outputFileName, + initMemorySize: initMemSize, + maxMemorySize: maxMemSize, + stackSize: stackSize, + exportedSymbols: exportedSymbols, }; + const configStr = readFromConfigFile(); - TargetConfigPanel.BUILD_ARGS = _configObj; + TargetConfigPanel.buildArgs = configObj; - _configStr = readFromConfigFile(); - - if (_configStr !== '' && _configStr !== undefined) { - configJson = JSON.parse(_configStr); + if (configStr !== '' && configStr !== undefined) { + const configJson = JSON.parse(configStr); includePathArr = - configJson['include_paths'] === undefined + configJson['includePaths'] === undefined ? [] - : configJson['include_paths']; + : configJson['includePaths']; excludeFileArr = - configJson['exclude_files'] === undefined + configJson['excludeFiles'] === undefined ? [] - : configJson['exclude_files']; + : configJson['excludeFiles']; } writeIntoConfigFile( includePathArr, excludeFileArr, - TargetConfigPanel.BUILD_ARGS + TargetConfigPanel.buildArgs ); - return TargetConfigPanel.EXCUTION_SUCCESS; + return TargetConfigPanel.executionSuccess; } private _getHtmlForWebview( @@ -158,23 +157,23 @@ export class TargetConfigPanel { .replace(/(\${styleUri})/, styleUri.toString()) .replace( /(\${output_file_val})/, - TargetConfigPanel.BUILD_ARGS.output_file_name + TargetConfigPanel.buildArgs.outputFileName ) .replace( /(\${initial_mem_size_val})/, - TargetConfigPanel.BUILD_ARGS.init_memory_size + TargetConfigPanel.buildArgs.initMemorySize ) .replace( /(\${max_mem_size_val})/, - TargetConfigPanel.BUILD_ARGS.max_memory_size + TargetConfigPanel.buildArgs.maxMemorySize ) .replace( /(\${stack_size_val})/, - TargetConfigPanel.BUILD_ARGS.stack_size + TargetConfigPanel.buildArgs.stackSize ) .replace( /(\${exported_symbols_val})/, - TargetConfigPanel.BUILD_ARGS.exported_symbols + TargetConfigPanel.buildArgs.exportedSymbols ); return html; @@ -187,8 +186,8 @@ export class TargetConfigPanel { case 'config_build_target': if ( message.outputFileName === '' || - message.initmemSize === '' || - message.maxmemSize === '' || + message.initMemSize === '' || + message.maxMemSize === '' || message.stackSize === '' || message.exportedSymbols === '' ) { @@ -197,13 +196,13 @@ export class TargetConfigPanel { ); return; } else if ( - this._configBuildArgs( + this.configBuildArgs( message.outputFileName, - message.initmemSize, - message.maxmemSize, + message.initMemSize, + message.maxMemSize, message.stackSize, message.exportedSymbols - ) === TargetConfigPanel.EXCUTION_SUCCESS + ) === TargetConfigPanel.executionSuccess ) { vscode.window .showInformationMessage( @@ -211,7 +210,7 @@ export class TargetConfigPanel { 'OK' ) .then(() => { - this._panel.dispose(); + this.viewPanel.dispose(); return; }); } @@ -227,7 +226,7 @@ export class TargetConfigPanel { private dispose() { TargetConfigPanel.currentPanel = undefined; - this._panel.dispose(); + this.viewPanel.dispose(); while (this._disposables.length) { const disposable = this._disposables.pop(); diff --git a/test-tools/wamr-ide/VSCode-Extension/tsconfig.json b/test-tools/wamr-ide/VSCode-Extension/tsconfig.json index b65c7451..c75039ee 100644 --- a/test-tools/wamr-ide/VSCode-Extension/tsconfig.json +++ b/test-tools/wamr-ide/VSCode-Extension/tsconfig.json @@ -1,21 +1,16 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6" - ], - "sourceMap": true, - "rootDir": "src", - "strict": true /* enable all strict type-checking options */ - /* Additional Checks */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": ["es6"], + "sourceMap": true, + "rootDir": "src", + "strict": true /* enable all strict type-checking options */ + /* Additional Checks */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + }, + "exclude": ["node_modules", ".vscode-test"] } From 26728cbef24ddf6c5d013904463192d4ec7009ec Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 27 Dec 2022 16:34:44 +0800 Subject: [PATCH 24/32] Remove unnecessary ret value control when spec test is enabled (#1839) wamr-test-suites scripts can handle the return value correctly when spec test is enabled. --- product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp | 5 ----- product-mini/platforms/posix/main.c | 5 ----- product-mini/platforms/windows/main.c | 5 ----- 3 files changed, 15 deletions(-) diff --git a/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp b/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp index 0a6f24a9..e760518a 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp @@ -796,12 +796,7 @@ fail1: /* Destroy runtime environment */ destroy_runtime(); -#if WASM_ENABLE_SPEC_TEST != 0 - (void)ret; - return 0; -#else return ret; -#endif } int diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 3dcf83e5..e04745c6 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -696,10 +696,5 @@ fail1: /* destroy runtime environment */ wasm_runtime_destroy(); -#if WASM_ENABLE_SPEC_TEST != 0 - (void)ret; - return 0; -#else return ret; -#endif } diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 399da4fb..14c25596 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -496,10 +496,5 @@ fail1: /* destroy runtime environment */ wasm_runtime_destroy(); -#if WASM_ENABLE_SPEC_TEST != 0 - (void)ret; - return 0; -#else return ret; -#endif } From b5f8a2bd087032af63aa5ede06a4dab14b7ea21d Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 29 Dec 2022 16:00:33 +0800 Subject: [PATCH 25/32] Add missing soft float intrinsics for risc-v AOT (#1845) --- core/iwasm/aot/arch/aot_reloc_riscv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/iwasm/aot/arch/aot_reloc_riscv.c b/core/iwasm/aot/arch/aot_reloc_riscv.c index 0d24876e..75fee56f 100644 --- a/core/iwasm/aot/arch/aot_reloc_riscv.c +++ b/core/iwasm/aot/arch/aot_reloc_riscv.c @@ -20,6 +20,7 @@ void __adddf3(); void __addsf3(); void __divdi3(); void __divsi3(); +void __divdf3(); void __divsf3(); void __eqsf2(); void __eqdf2(); @@ -42,9 +43,12 @@ void __floatunsisf(); void __floatunsidf(); void __gedf2(); void __gesf2(); +void __gtdf2(); void __gtsf2(); void __ledf2(); void __lesf2(); +void __ltdf2(); +void __ltsf2(); void __moddi3(); void __modsi3(); void __muldf3(); @@ -70,12 +74,16 @@ static SymbolMap target_sym_map[] = { #ifndef __riscv_flen REG_SYM(__adddf3), REG_SYM(__addsf3), + REG_SYM(__divdf3), REG_SYM(__divsf3), REG_SYM(__gedf2), REG_SYM(__gesf2), + REG_SYM(__gtdf2), REG_SYM(__gtsf2), REG_SYM(__ledf2), REG_SYM(__lesf2), + REG_SYM(__ltdf2), + REG_SYM(__ltsf2), REG_SYM(__muldf3), REG_SYM(__nedf2), REG_SYM(__nesf2), From 6c7ca90229e6393e474ea45cf988072c4a60c485 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 29 Dec 2022 16:49:27 +0800 Subject: [PATCH 26/32] Use float version library routine for XIP aot_intrinsic_xxx APIs (#1846) --- core/iwasm/aot/aot_intrinsic.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index ee1d4f92..ba3feaf9 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -134,7 +134,7 @@ aot_intrinsic_fdiv_f64(float64 a, float64 b) float32 aot_intrinsic_fabs_f32(float32 a) { - return (float32)fabs(a); + return fabsf(a); } float64 @@ -146,7 +146,7 @@ aot_intrinsic_fabs_f64(float64 a) float32 aot_intrinsic_ceil_f32(float32 a) { - return (float32)ceilf(a); + return ceilf(a); } float64 @@ -158,7 +158,7 @@ aot_intrinsic_ceil_f64(float64 a) float32 aot_intrinsic_floor_f32(float32 a) { - return (float32)floorf(a); + return floorf(a); } float64 @@ -170,7 +170,7 @@ aot_intrinsic_floor_f64(float64 a) float32 aot_intrinsic_trunc_f32(float32 a) { - return (float32)trunc(a); + return truncf(a); } float64 @@ -182,7 +182,7 @@ aot_intrinsic_trunc_f64(float64 a) float32 aot_intrinsic_rint_f32(float32 a) { - return (float32)rint(a); + return rintf(a); } float64 @@ -194,7 +194,7 @@ aot_intrinsic_rint_f64(float64 a) float32 aot_intrinsic_sqrt_f32(float32 a) { - return (float32)sqrt(a); + return sqrtf(a); } float64 @@ -206,7 +206,7 @@ aot_intrinsic_sqrt_f64(float64 a) float32 aot_intrinsic_copysign_f32(float32 a, float32 b) { - return signbit(b) ? (float32)-fabs(a) : (float32)fabs(a); + return signbit(b) ? -fabsf(a) : fabsf(a); } float64 @@ -223,7 +223,7 @@ aot_intrinsic_fmin_f32(float32 a, float32 b) else if (isnan(b)) return b; else - return (float32)fmin(a, b); + return fminf(a, b); } float64 @@ -243,7 +243,7 @@ aot_intrinsic_fmax_f32(float32 a, float32 b) else if (isnan(b)) return b; else - return (float32)fmax(a, b); + return fmaxf(a, b); } float64 From 41eb938a950708b249b91df74a74fcbefbf5ea7c Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 29 Dec 2022 18:11:05 +0800 Subject: [PATCH 27/32] Fix equal check in AOT XIP float cmp intrinsic (#1847) --- core/iwasm/aot/aot_intrinsic.c | 4 ++-- core/shared/utils/bh_platform.h | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index ba3feaf9..665be573 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -442,7 +442,7 @@ aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs) { switch (cond) { case FLOAT_EQ: - return (float32)fabs(lhs - rhs) <= WA_FLT_EPSILON ? 1 : 0; + return lhs == rhs ? 1 : 0; case FLOAT_LT: return lhs < rhs ? 1 : 0; @@ -473,7 +473,7 @@ aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs) { switch (cond) { case FLOAT_EQ: - return fabs(lhs - rhs) <= WA_DBL_EPSILON ? 1 : 0; + return lhs == rhs ? 1 : 0; case FLOAT_LT: return lhs < rhs ? 1 : 0; diff --git a/core/shared/utils/bh_platform.h b/core/shared/utils/bh_platform.h index 3bbd0c82..86aef839 100644 --- a/core/shared/utils/bh_platform.h +++ b/core/shared/utils/bh_platform.h @@ -35,9 +35,4 @@ #define WA_FREE wasm_runtime_free #endif -/* The epsilon value is from https://www.cplusplus.com/reference/cfloat/ */ - -#define WA_FLT_EPSILON 1e-5f -#define WA_DBL_EPSILON 1e-9 - #endif /* #ifndef _BH_PLATFORM_H */ From d1fe589d4324f760d733e8deea43b5e728c2fcc9 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 29 Dec 2022 18:48:55 +0800 Subject: [PATCH 28/32] Fix fmin/fmax in AOT XIP intrinsics (#1848) --- core/iwasm/aot/aot_intrinsic.c | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 665be573..a946334c 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -218,41 +218,45 @@ aot_intrinsic_copysign_f64(float64 a, float64 b) float32 aot_intrinsic_fmin_f32(float32 a, float32 b) { - if (isnan(a)) - return a; - else if (isnan(b)) - return b; + if (isnan(a) || isnan(b)) + return NAN; + else if (a == 0 && a == b) + return signbit(a) ? a : b; else - return fminf(a, b); + return a > b ? b : a; } float64 aot_intrinsic_fmin_f64(float64 a, float64 b) { - float64 c = fmin(a, b); - if (c == 0 && a == b) + if (isnan(a) || isnan(b)) + return NAN; + else if (a == 0 && a == b) return signbit(a) ? a : b; - return c; + else + return a > b ? b : a; } float32 aot_intrinsic_fmax_f32(float32 a, float32 b) { - if (isnan(a)) - return a; - else if (isnan(b)) - return b; + if (isnan(a) || isnan(b)) + return NAN; + else if (a == 0 && a == b) + return signbit(a) ? b : a; else - return fmaxf(a, b); + return a > b ? a : b; } float64 aot_intrinsic_fmax_f64(float64 a, float64 b) { - float64 c = fmax(a, b); - if (c == 0 && a == b) + if (isnan(a) || isnan(b)) + return NAN; + else if (a == 0 && a == b) return signbit(a) ? b : a; - return c; + else + return a > b ? a : b; } uint32 From 0090d3e3fc4de3864848f57a0a11809299102a2c Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 30 Dec 2022 14:37:04 +0800 Subject: [PATCH 29/32] Fix issue of resolving func name in custom name section (#1849) Should use import_function_count but not import_count to calculate the func_index in handle_name_section when custom name section feature is enabled. And clear the compile warnings of mini loader. --- core/iwasm/interpreter/wasm_loader.c | 4 ++-- core/iwasm/interpreter/wasm_mini_loader.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 6a39d368..d0a10b86 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -2806,8 +2806,8 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, func_name_len); CHECK_BUF(p, p_end, func_name_len); /* Skip the import functions */ - if (func_index >= module->import_count) { - func_index -= module->import_count; + if (func_index >= module->import_function_count) { + func_index -= module->import_function_count; if (func_index >= module->function_count) { set_error_buf(error_buf, error_buf_size, "out-of-range function index"); diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index cebd47ee..b1243a06 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -1708,8 +1708,8 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, func_name_len); CHECK_BUF(p, p_end, func_name_len); /* Skip the import functions */ - if (func_index >= module->import_count) { - func_index -= module->import_count; + if (func_index >= module->import_function_count) { + func_index -= module->import_function_count; bh_assert(func_index < module->function_count); if (!(module->functions[func_index]->field_name = const_str_list_insert( @@ -1733,6 +1733,8 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, i++; } + (void)previous_name_type; + (void)previous_func_index; return true; } #endif From d309091706f2fbfc3ccca2907226f57db4d612f3 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Fri, 30 Dec 2022 15:21:25 +0800 Subject: [PATCH 30/32] Register missing symbols for f32 to 64 bit integer conversion (#1850) --- core/iwasm/aot/aot_intrinsic.c | 8 ++++++++ core/iwasm/aot/aot_reloc.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index a946334c..319eeda5 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -58,6 +58,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 }, { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 }, { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 }, + { "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 }, + { "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 }, { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 }, { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 }, { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 }, @@ -635,6 +637,12 @@ add_f64_common_intrinsics(AOTCompContext *comp_ctx) add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FADD); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FSUB); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FMUL); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_MIN); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_MAX); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CEIL); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FLOOR); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TRUNC); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_RINT); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FDIV); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_SQRT); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP); diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 9b374051..9f5c2d57 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -101,6 +101,8 @@ typedef struct { REG_SYM(aot_intrinsic_f64_to_f32), \ REG_SYM(aot_intrinsic_f32_to_i32), \ REG_SYM(aot_intrinsic_f32_to_u32), \ + REG_SYM(aot_intrinsic_f32_to_i64), \ + REG_SYM(aot_intrinsic_f32_to_u64), \ REG_SYM(aot_intrinsic_f64_to_i32), \ REG_SYM(aot_intrinsic_f64_to_u32), \ REG_SYM(aot_intrinsic_f64_to_i64), \ From d5aa354d41531d39b5e108f1bdddb0d5f83c5d0a Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Fri, 30 Dec 2022 16:45:39 +0800 Subject: [PATCH 31/32] Return result directly if float cmp is called in AOT XIP (#1851) --- core/iwasm/compilation/aot_emit_numberic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index 396fc0e9..4c63e8a4 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -307,6 +307,14 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_types, 2, left, right))) return NULL; + /* The result of XIP intrinsic is 0 or 1, should return it directly */ + + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, + is_f32 ? "f32_cmp" : "f64_cmp")) { + return cmp; + } + if (!(cmp = LLVMBuildSelect(comp_ctx->builder, is_eq, tmp, cmp, "cmp"))) { aot_set_last_error("llvm build select fail."); return NULL; From bf2be805f9d9e228e6ef2a933f7d55dbc48f1a78 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 3 Jan 2023 17:16:49 +0800 Subject: [PATCH 32/32] Add more checks about the imports of wasm_instance_new (#1843) Check whether the `imports` argument is NULL in wasm_instance_new and check the import count of each kind. Fix issue reported by https://github.com/bytecodealliance/wasm-micro-runtime/issues/1833 --- core/iwasm/common/wasm_c_api.c | 136 ++++++++++++++++-------- samples/wasm-c-api/CMakeLists.txt | 27 ++--- samples/wasm-c-api/src/callback_chain.c | 2 +- 3 files changed, 102 insertions(+), 63 deletions(-) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 1f148ee5..d8b98413 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include "bh_log.h" #include "wasm_c_api_internal.h" #include "bh_assert.h" @@ -275,10 +276,14 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete) WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete) #ifndef NDEBUG +#if WAMR_BUILD_MEMORY_PROFILING != 0 #define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM() #else #define WASM_C_DUMP_PROC_MEM() (void)0 #endif +#else +#define WASM_C_DUMP_PROC_MEM() (void)0 +#endif /* Runtime Environment */ own wasm_config_t * @@ -4345,7 +4350,7 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt, return true; } -static uint32 +static bool interp_link(const wasm_instance_t *inst, const WASMModule *module_interp, wasm_extern_t *imports[]) { @@ -4390,11 +4395,11 @@ interp_link(const wasm_instance_t *inst, const WASMModule *module_interp, } } - return i; + return true; failed: LOG_DEBUG("%s failed", __FUNCTION__); - return (uint32)-1; + return false; } static bool @@ -4557,7 +4562,7 @@ failed: return false; } -static uint32 +static bool aot_link(const wasm_instance_t *inst, const AOTModule *module_aot, wasm_extern_t *imports[]) { @@ -4605,11 +4610,11 @@ aot_link(const wasm_instance_t *inst, const AOTModule *module_aot, } } - return i; + return true; failed: LOG_DEBUG("%s failed", __FUNCTION__); - return (uint32)-1; + return false; } static bool @@ -4713,6 +4718,57 @@ wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, KILOBYTE(32), KILOBYTE(32)); } +static bool +compare_imports(const wasm_module_t *module, const wasm_extern_vec_t *imports) +{ + unsigned import_func_count = 0; + unsigned import_global_count = 0; + unsigned import_memory_count = 0; + unsigned import_table_count = 0; + unsigned i = 0; + + for (i = 0; imports && i < imports->num_elems; i++) { + wasm_extern_t *import = imports->data[i]; + switch (wasm_extern_kind(import)) { + case WASM_EXTERN_FUNC: + import_func_count++; + break; + case WASM_EXTERN_GLOBAL: + import_global_count++; + break; + case WASM_EXTERN_MEMORY: + import_memory_count++; + break; + case WASM_EXTERN_TABLE: + import_table_count++; + break; + default: + UNREACHABLE(); + return false; + } + } + +#if WASM_ENABLE_INTERP != 0 + if ((*module)->module_type == Wasm_Module_Bytecode) + return import_func_count == MODULE_INTERP(module)->import_function_count + && import_global_count + == MODULE_INTERP(module)->import_global_count + && import_memory_count + == MODULE_INTERP(module)->import_memory_count + && import_table_count + == MODULE_INTERP(module)->import_table_count; +#endif +#if WASM_ENABLE_AOT != 0 + if ((*module)->module_type == Wasm_Module_AoT) + return import_func_count == MODULE_AOT(module)->import_func_count + && import_global_count == MODULE_AOT(module)->import_global_count + && import_memory_count == MODULE_AOT(module)->import_memory_count + && import_table_count == MODULE_AOT(module)->import_table_count; +#endif + + return false; +} + wasm_instance_t * wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, const wasm_extern_vec_t *imports, @@ -4721,18 +4777,22 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, { char sub_error_buf[128] = { 0 }; char error_buf[256] = { 0 }; - bool import_count_verified = false; wasm_instance_t *instance = NULL; WASMModuleInstance *inst_rt; CApiFuncImport *func_import = NULL, **p_func_imports = NULL; - uint32 i = 0, import_count = 0, import_func_count = 0; + uint32 i = 0, import_func_count = 0; uint64 total_size; - bool processed = false; + bool build_exported = false; bh_assert(singleton_engine); - if (!module) { + if (!module) return NULL; + + if (!compare_imports(module, imports)) { + snprintf(sub_error_buf, sizeof(sub_error_buf), + "Failed to match imports"); + goto failed; } WASM_C_DUMP_PROC_MEM(); @@ -4746,43 +4806,28 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, /* link module and imports */ if (imports && imports->num_elems) { + bool link = false; #if WASM_ENABLE_INTERP != 0 if ((*module)->module_type == Wasm_Module_Bytecode) { - import_count = MODULE_INTERP(module)->import_count; - - if (import_count) { - uint32 actual_link_import_count = - interp_link(instance, MODULE_INTERP(module), - (wasm_extern_t **)imports->data); - /* make sure a complete import list */ - if ((int32)import_count < 0 - || import_count != actual_link_import_count) { - snprintf(sub_error_buf, sizeof(sub_error_buf), - "Failed to validate imports"); - goto failed; - } + if (!interp_link(instance, MODULE_INTERP(module), + (wasm_extern_t **)imports->data)) { + snprintf(sub_error_buf, sizeof(sub_error_buf), + "Failed to validate imports"); + goto failed; } - import_count_verified = true; + link = true; } #endif #if WASM_ENABLE_AOT != 0 if ((*module)->module_type == Wasm_Module_AoT) { - import_count = MODULE_AOT(module)->import_func_count - + MODULE_AOT(module)->import_global_count - + MODULE_AOT(module)->import_memory_count - + MODULE_AOT(module)->import_table_count; - - if (import_count) { - import_count = aot_link(instance, MODULE_AOT(module), - (wasm_extern_t **)imports->data); - if ((int32)import_count < 0) { - snprintf(sub_error_buf, sizeof(sub_error_buf), - "Failed to validate imports"); - goto failed; - } + if (!aot_link(instance, MODULE_AOT(module), + (wasm_extern_t **)imports->data)) { + snprintf(sub_error_buf, sizeof(sub_error_buf), + "Failed to validate imports"); + goto failed; } - import_count_verified = true; + link = true; } #endif @@ -4790,7 +4835,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, * a wrong combination of module filetype and compilation flags * also leads to below branch */ - if (!import_count_verified) { + if (!link) { snprintf(sub_error_buf, sizeof(sub_error_buf), "Failed to verify import count"); goto failed; @@ -4809,6 +4854,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } + /* create the c-api func import list */ inst_rt = (WASMModuleInstance *)instance->inst_comm_rt; #if WASM_ENABLE_INTERP != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { @@ -4825,7 +4871,6 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, #endif bh_assert(p_func_imports); - /* create the c-api func import list */ total_size = (uint64)sizeof(CApiFuncImport) * import_func_count; if (total_size > 0 && !(*p_func_imports = func_import = malloc_internal(total_size))) { @@ -4835,7 +4880,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, } /* fill in c-api func import list */ - for (i = 0; i < import_count; i++) { + for (i = 0; imports && i < imports->num_elems; i++) { wasm_func_t *func_host; wasm_extern_t *in; @@ -4857,10 +4902,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, func_import++; } - bh_assert((uint32)(func_import - *p_func_imports) == import_func_count); /* fill with inst */ - for (i = 0; imports && imports->data && i < (uint32)import_count; ++i) { + for (i = 0; imports && imports->data && i < imports->num_elems; ++i) { wasm_extern_t *import = imports->data[i]; switch (import->kind) { case WASM_EXTERN_FUNC: @@ -4903,7 +4947,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } - processed = true; + build_exported = true; } #endif @@ -4927,7 +4971,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } - processed = true; + build_exported = true; } #endif @@ -4935,7 +4979,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, * a wrong combination of module filetype and compilation flags * leads to below branch */ - if (!processed) { + if (!build_exported) { snprintf(sub_error_buf, sizeof(sub_error_buf), "Incorrect filetype and compilation flags"); goto failed; diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 87687405..a6494624 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -159,6 +159,9 @@ endif() check_pie_supported() +include(CTest) +enable_testing() + foreach(EX ${EXAMPLES}) set(SRC ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.c) @@ -193,6 +196,12 @@ foreach(EX ${EXAMPLES}) ) add_dependencies(${EX} ${EX}_AOT) endif() + + # run `ctest --test-dir build` + add_test(NAME Test_${EX} + COMMAND ./${EX} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) endforeach() if (CMAKE_BUILD_TYPE STREQUAL "Debug") @@ -201,19 +210,5 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") REQUIRED ) - if(VALGRIND) - foreach(EX ${EXAMPLES}) - add_custom_command( - OUTPUT ${EX}_leak_check.report - DEPENDS ${EX} ${EX}_WASM - COMMAND ${VALGRIND} --tool=memcheck --leak-check=full -- ./${EX} > ${EX}_leak_check.report 2>&1 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - ) - add_custom_target(${EX}_LEAK_TEST ALL - DEPENDS ${EX}_leak_check.report - COMMAND grep "All heap blocks were freed -- no leaks are possible" ${EX}_leak_check.report - COMMENT "Please read ${EX}_leak_check.report when meeting Error" - ) - endforeach() - endif (VALGRIND) -endif (CMAKE_BUILD_TYPE STREQUAL "Debug") + # run `ctest -T memcheck -V --test-dir build` +endif() diff --git a/samples/wasm-c-api/src/callback_chain.c b/samples/wasm-c-api/src/callback_chain.c index 13b86ecc..e4f5801d 100644 --- a/samples/wasm-c-api/src/callback_chain.c +++ b/samples/wasm-c-api/src/callback_chain.c @@ -238,7 +238,7 @@ main(int argc, const char *argv[]) IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION) #undef CREATE_WASM_FUNCTION - wasm_extern_t *fs[10] = { 0 }; + wasm_extern_t *fs[2] = { 0 }; #define ADD_TO_FUNCTION_LIST(name, index, ...) \ fs[index] = wasm_func_as_extern(function_##name); IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)