diff --git a/CMakeLists.txt b/CMakeLists.txt index d77473e037..00c459f9c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required (VERSION 2.8...3.16) project (iwasm) # set (CMAKE_VERBOSE_MAKEFILE 1) -set (WAMR_BUILD_PLATFORM "linux") +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) # Reset default linker flags set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") @@ -18,7 +18,7 @@ set (CMAKE_C_STANDARD 99) # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/build-scripts/esp-idf/README.md b/build-scripts/esp-idf/README.md new file mode 100644 index 0000000000..6bec45d1e7 --- /dev/null +++ b/build-scripts/esp-idf/README.md @@ -0,0 +1,31 @@ +# wasm-micro-runtime as ESP-IDF component + +You can build an ESP-IDF project with wasm-micro-runtime as a component: + +- Make sure you have the ESP-IDF properly installed and setup +- In particular have the following paths set: + - `WAMR_PATH` to point to your wasm-micro-runtime repository + - `IDF_PATH` to point to your ESP-IDF + - `source $IDF_PATH/export.sh` +- Create a new project, e.g.: `idf.py create-project wamr-hello` +- In the newly created project folder edit the `CMakeList.txt`: + + ``` + cmake_minimum_required(VERSION 3.5) + + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + + set (COMPONENTS ${IDF_TARGET} main freertos esptool_py wamr) + + list(APPEND EXTRA_COMPONENT_DIRS "$ENV{WAMR_PATH}/build-scripts/esp-idf") + + project(wamr-hello) + ``` +- Develop your project in it's `main` component folder. + +You can find an example [here](../../product-mini/platforms/esp-idf). + +- Set target platform: `idf.py set-target esp32c3` +- Build: `idf.py build` +- Flash: `idf.py flash` +- Check the output: `idf.py monitor` \ No newline at end of file diff --git a/build-scripts/esp-idf/wamr/CMakeLists.txt b/build-scripts/esp-idf/wamr/CMakeLists.txt new file mode 100644 index 0000000000..c7b6100ec8 --- /dev/null +++ b/build-scripts/esp-idf/wamr/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (C) 2021 Intel Corporation and others. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# Set WAMR's build options +if("${IDF_TARGET}" STREQUAL "esp32c3") + set(WAMR_BUILD_TARGET "RISCV32") +else() + set(WAMR_BUILD_TARGET "XTENSA") +endif() + +set(WAMR_BUILD_PLATFORM "esp-idf") + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_FAST_INTERP) + set (WAMR_BUILD_FAST_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) + set (WAMR_BUILD_APP_FRAMEWORK 0) +endif () + +if (NOT CMAKE_BUILD_EARLY_EXPANSION) + if (WAMR_BUILD_TARGET STREQUAL "XTENSA") + idf_build_set_property(COMPILE_DEFINITIONS "-DBUILD_TARGET_XTENSA=1" APPEND) + endif () + if (WAMR_BUILD_INTERP) + idf_build_set_property(COMPILE_DEFINITIONS "-DWASM_ENABLE_INTERP=1" APPEND) + endif () + if (WAMR_BUILD_AOT) + idf_build_set_property(COMPILE_DEFINITIONS "-DWASM_ENABLE_AOT=1" APPEND) + endif () + + set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) + include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +endif() + +idf_component_register(SRCS ${WAMR_RUNTIME_LIB_SOURCE} ${PLATFORM_SHARED_SOURCE} + INCLUDE_DIRS ${IWASM_DIR}/include ${UTILS_SHARED_DIR} ${PLATFORM_SHARED_DIR} ${PLATFORM_SHARED_DIR}/../include + REQUIRES pthread +) + + diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 2ef197fc7d..513a0a6c2b 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -34,7 +34,7 @@ endif () # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/ci/Dockerfile b/ci/Dockerfile index f90e4cc7cc..b6e5af48bc 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -1,6 +1,8 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# tie the ${VARIANT} and a llvm binary release together +# please find a matched version on https://github.com/llvm/llvm-project/releases ARG VARIANT=focal FROM ubuntu:${VARIANT} @@ -34,6 +36,24 @@ RUN cd /opt/emsdk \ && ./emsdk activate 2.0.26 \ && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc +# +# install clang and llvm release +ARG CLANG_VER=13.0.0 +RUN wget https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VER}/clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-20.04.tar.xz -P /opt +RUN cd /opt \ + && tar xf clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-20.04.tar.xz \ + && ln -sf clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-20.04 clang-llvm +RUN rm /opt/clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-20.04.tar.xz + + +# +# install wasi-sdk +ARG WASI_SDK_VER=14 +RUN wget -c https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt +RUN tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ + && ln -fs /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk +RUN rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz + # #install wabt ARG WABT_VER=1.0.24 @@ -42,15 +62,6 @@ RUN tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ && ln -fs /opt/wabt-${WABT_VER} /opt/wabt RUN rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz -# -# install binaryen -ARG BINARYEN_VER=version_101 -RUN wget -c https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VER}/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz -P /opt -RUN tar xf /opt/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz -C /opt \ - && ln -fs /opt/binaryen-${BINARYEN_VER} /opt/binaryen -RUN rm /opt/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz - - # # install bazelisk ARG BAZELISK_VER=1.10.1 @@ -59,8 +70,13 @@ RUN wget -c https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK RUN chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel +# +# install +RUN apt update && apt install -y clang-format + # set path -RUN echo "PATH=/opt/clang_llvm/bin:/opt/wasi-sdk/bin:/opt/wabt/bin:/opt/binaryen/bin:/opt/bazelisk:${PATH}" >> /root/.bashrc +ENV PATH "$PATH:/opt/wasi-sdk/bin:/opt/wabt/bin:/opt/binaryen/bin:/opt/bazelisk:/opt/clang-llvm/bin" +RUN echo "export PATH=/opt/wasi-sdk/bin:/opt/wabt/bin:/opt/binaryen/bin:/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" >> /root/.bashrc # # PS @@ -72,5 +88,5 @@ RUN apt-get autoremove -y \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/* -VOLUME workspace -WORKDIR workspace +VOLUME /workspace +WORKDIR /workspace diff --git a/ci/build_wamr.sh b/ci/build_wamr.sh index 9b944662e6..b7e6c049d3 100755 --- a/ci/build_wamr.sh +++ b/ci/build_wamr.sh @@ -8,26 +8,27 @@ readonly ROOT=$(realpath "${CURRENT_PATH}/..") readonly VARIANT=$(lsb_release -c | awk '{print $2}') docker build \ - --build-arg VARIANT=${VARIANT} \ - --memory=4G --cpu-quota=50000 \ - -t wamr_dev_${VARIANT}:0.1 -f "${CURRENT_PATH}"/Dockerfile "${CURRENT_PATH}" && - docker run --rm -it \ - --cpus=".5" \ - --memory=4G \ - --name wamr_build_env \ - --mount type=bind,src="${ROOT}",dst=/workspace \ - wamr_dev_${VARIANT}:0.1 \ - /bin/bash -c "\ - pwd \ - && pushd product-mini/platforms/linux \ - && rm -rf build \ - && mkdir build \ - && pushd build \ - && cmake .. \ - && make \ - && popd \ - && popd \ - && echo 'Copying the binary ...' \ - && rm -rf build_out \ - && mkdir build_out \ - && cp product-mini/platforms/linux/build/iwasm build_out/iwasm" + --memory=4G --cpu-quota=50000 \ + -t wamr_dev_${VARIANT}:0.1 -f "${CURRENT_PATH}"/Dockerfile "${CURRENT_PATH}" \ + && docker run --rm -it \ + --cap-add=SYS_PTRACE \ + --cpus=".5" \ + --memory=4G \ + --mount type=bind,src="${ROOT}",dst=/workspace \ + --name wamr_build_env \ + --security-opt=seccomp=unconfined \ + wamr_dev_${VARIANT}:0.1 \ + /bin/bash -c "\ + pwd \ + && pushd product-mini/platforms/linux \ + && rm -rf build \ + && mkdir build \ + && pushd build \ + && cmake .. \ + && make \ + && popd \ + && popd \ + && echo 'Copying the binary ...' \ + && rm -rf build_out \ + && mkdir build_out \ + && cp product-mini/platforms/linux/build/iwasm build_out/iwasm" diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index f8766ddee7..f5dc822557 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -90,7 +90,8 @@ static bool check_buf(const uint8 *buf, const uint8 *buf_end, uint32 length, char *error_buf, uint32 error_buf_size) { - if (buf + length < buf || buf + length > buf_end) { + if ((uintptr_t)buf + length < (uintptr_t)buf + || (uintptr_t)buf + length > (uintptr_t)buf_end) { set_error_buf(error_buf, error_buf_size, "unexpect end"); return false; } @@ -1575,8 +1576,10 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) if (module->func_count > 0) { + uint32 plt_table_size = + module->is_indirect_mode ? 0 : get_plt_table_size(); rtl_func_table[module->func_count - 1].EndAddress = - (DWORD)(module->code_size - get_plt_table_size()); + (DWORD)(module->code_size - plt_table_size); if (!RtlAddFunctionTable(rtl_func_table, module->func_count, (DWORD64)(uintptr_t)module->code)) { @@ -2113,19 +2116,29 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, memcpy(group_name_buf, group_name, group_name_len); memcpy(symbol_name_buf, symbol_name, symbol_name_len); - if (group_name_len == strlen(".text") + if ((group_name_len == strlen(".text") + || (module->is_indirect_mode + && group_name_len == strlen(".text") + 1)) && !strncmp(group_name, ".text", strlen(".text"))) { - if (symbol_name_len == strlen(XMM_PLT_PREFIX) + 32 + if ((symbol_name_len == strlen(XMM_PLT_PREFIX) + 32 + || (module->is_indirect_mode + && symbol_name_len == strlen(XMM_PLT_PREFIX) + 32 + 1)) && !strncmp(symbol_name, XMM_PLT_PREFIX, strlen(XMM_PLT_PREFIX))) { module->xmm_plt_count++; } - else if (symbol_name_len == strlen(REAL_PLT_PREFIX) + 16 + else if ((symbol_name_len == strlen(REAL_PLT_PREFIX) + 16 + || (module->is_indirect_mode + && symbol_name_len + == strlen(REAL_PLT_PREFIX) + 16 + 1)) && !strncmp(symbol_name, REAL_PLT_PREFIX, strlen(REAL_PLT_PREFIX))) { module->real_plt_count++; } - else if (symbol_name_len == strlen(REAL_PLT_PREFIX) + 8 + else if ((symbol_name_len >= strlen(REAL_PLT_PREFIX) + 8 + || (module->is_indirect_mode + && symbol_name_len + == strlen(REAL_PLT_PREFIX) + 8 + 1)) && !strncmp(symbol_name, REAL_PLT_PREFIX, strlen(REAL_PLT_PREFIX))) { module->float_plt_count++; @@ -2230,7 +2243,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, #endif ) { #if !defined(BH_PLATFORM_LINUX) && !defined(BH_PLATFORM_LINUX_SGX) \ - && !defined(BH_PLATFORM_DARWIN) + && !defined(BH_PLATFORM_DARWIN) && !defined(BH_PLATFORM_WINDOWS) if (module->is_indirect_mode) { set_error_buf(error_buf, error_buf_size, "cannot apply relocation to text section " diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 7cad5d3be4..4ff63d465d 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1260,6 +1260,11 @@ aot_exception_handler(EXCEPTION_POINTERS *exce_info) return EXCEPTION_CONTINUE_EXECUTION; } } + + os_printf("Unhandled exception thrown: exception code: 0x%lx, " + "exception address: %p, exception information: %p\n", + ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress, + sig_addr); return EXCEPTION_CONTINUE_SEARCH; } #endif /* end of BH_PLATFORM_WINDOWS */ diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 26c60358ef..5e1a34c4e7 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -112,7 +112,7 @@ put_imm16_to_addr(int16 imm16, int16 *addr) if ((intptr_t)addr % 4 != 3) { *(int32 *)bytes = *addr_aligned1; *(int16 *)(bytes + ((intptr_t)addr % 4)) = imm16; - memcpy(addr_aligned1, bytes, 4); + *addr_aligned1 = *(int32 *)bytes; } else { addr_aligned2 = (int32 *)(((intptr_t)addr + 3) & ~3); diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index ea2fafd680..86ad1c3e1b 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -98,6 +98,8 @@ typedef struct WASMExecEnv { /* used to support debugger */ korp_mutex wait_lock; korp_cond wait_cond; + /* the count of threads which are joining current thread */ + uint32 wait_count; #endif #if WASM_ENABLE_DEBUG_INTERP != 0 diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index af2f59300f..be13d05c02 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -305,10 +305,11 @@ align_ptr(const uint8 *p, uint32 b) return (uint8 *)((v + m) & ~m); } -#define CHECK_BUF(buf, buf_end, length) \ - do { \ - if (buf + length < buf || buf + length > buf_end) \ - return false; \ +#define CHECK_BUF(buf, buf_end, length) \ + do { \ + if ((uintptr_t)buf + length < (uintptr_t)buf \ + || (uintptr_t)buf + length > (uintptr_t)buf_end) \ + return false; \ } while (0) #define read_uint16(p, p_end, res) \ @@ -347,9 +348,7 @@ wasm_runtime_is_xip_file(const uint8 *buf, uint32 size) if (section_type == AOT_SECTION_TYPE_TARGET_INFO) { p += 4; read_uint16(p, p_end, e_type); - if (e_type == E_TYPE_XIP) { - return true; - } + return (e_type == E_TYPE_XIP) ? true : false; } else if (section_type >= AOT_SECTION_TYPE_SIGANATURE) { return false; @@ -3227,8 +3226,19 @@ typedef uint32x4_t __m128i; #endif /* end of WASM_ENABLE_SIMD != 0 */ typedef void (*GenericFunctionPointer)(); +#if defined(__APPLE__) || defined(__MACH__) +/** + * Define the return type as 'void' in MacOS, since after converting + * 'int64 invokeNative' into 'float64 invokeNative_Float64', the + * return value passing might be invalid, the caller reads the return + * value from register rax but not xmm0. + */ +void +invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); +#else int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); +#endif typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint64 *, uint64); typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint64 *, uint64); diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index be7dea91c7..fe43d6bce3 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -560,6 +560,10 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } else { + bool recursive_call = + (func_ctx == func_ctxes[func_idx - import_func_count]) ? true + : false; + if (comp_ctx->is_indirect_mode) { LLVMTypeRef func_ptr_type; @@ -603,7 +607,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Check whether there was exception thrown when executing the function */ - if (!tail_call && !check_exception_thrown(comp_ctx, func_ctx)) + if (!tail_call && !recursive_call + && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; } diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 8fd6e82920..33c7179a29 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -500,7 +500,7 @@ create_cur_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) offset = I32_CONST(offsetof(AOTModuleInstance, cur_exception)); func_ctx->cur_exception = LLVMBuildInBoundsGEP( - comp_ctx->builder, func_ctx->aot_inst, &offset, 1, "cur_execption"); + comp_ctx->builder, func_ctx->aot_inst, &offset, 1, "cur_exception"); if (!func_ctx->cur_exception) { aot_set_last_error("llvm build in bounds gep failed."); return false; @@ -1610,7 +1610,76 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) abi = "ilp32d"; } - if (arch) { +#if defined(__APPLE__) || defined(__MACH__) + if (!abi) { + /* On MacOS platform, set abi to "gnu" to avoid generating + object file of Mach-O binary format which is unsupported */ + abi = "gnu"; + if (!arch && !cpu && !features) { + /* Get CPU name of the host machine to avoid checking + SIMD capability failed */ + if (!(cpu = cpu_new = LLVMGetHostCPUName())) { + aot_set_last_error("llvm get host cpu name failed."); + goto fail; + } + } + } +#endif + + if (abi) { + /* Construct target triple: --- */ + const char *vendor_sys; + char *arch1 = arch, default_arch[32] = { 0 }; + + if (!arch1) { + char *default_triple = LLVMGetDefaultTargetTriple(); + + if (!default_triple) { + aot_set_last_error( + "llvm get default target triple failed."); + goto fail; + } + + vendor_sys = strstr(default_triple, "-"); + bh_assert(vendor_sys); + bh_memcpy_s(default_arch, sizeof(default_arch), default_triple, + (uint32)(vendor_sys - default_triple)); + arch1 = default_arch; + + LLVMDisposeMessage(default_triple); + } + + /** + * Set - according to abi to generate the object file + * with the correct file format which might be different from the + * default object file format of the host, e.g., generating AOT file + * for Windows/MacOS under Linux host, or generating AOT file for + * Linux/MacOS under Windows host. + */ + if (!strcmp(abi, "msvc")) { + if (!strcmp(arch1, "i386")) + vendor_sys = "-pc-win32-"; + else + vendor_sys = "-pc-windows-"; + } + else { + vendor_sys = "-pc-linux-"; + } + + bh_assert(strlen(arch1) + strlen(vendor_sys) + strlen(abi) + < sizeof(triple_buf)); + bh_memcpy_s(triple_buf, (uint32)sizeof(triple_buf), arch1, + (uint32)strlen(arch1)); + bh_memcpy_s(triple_buf + strlen(arch1), + (uint32)(sizeof(triple_buf) - strlen(arch1)), + vendor_sys, (uint32)strlen(vendor_sys)); + bh_memcpy_s(triple_buf + strlen(arch1) + strlen(vendor_sys), + (uint32)(sizeof(triple_buf) - strlen(arch1) + - strlen(vendor_sys)), + abi, (uint32)strlen(abi)); + triple = triple_buf; + } + else if (arch) { /* Construct target triple: --- */ const char *vendor_sys; char *default_triple = LLVMGetDefaultTargetTriple(); @@ -1640,10 +1709,15 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) bh_assert(strlen(arch) + strlen(vendor_sys) + strlen(abi) < sizeof(triple_buf)); - memcpy(triple_buf, arch, strlen(arch)); - memcpy(triple_buf + strlen(arch), vendor_sys, strlen(vendor_sys)); - memcpy(triple_buf + strlen(arch) + strlen(vendor_sys), abi, - strlen(abi)); + bh_memcpy_s(triple_buf, (uint32)sizeof(triple_buf), arch, + (uint32)strlen(arch)); + bh_memcpy_s(triple_buf + strlen(arch), + (uint32)(sizeof(triple_buf) - strlen(arch)), vendor_sys, + (uint32)strlen(vendor_sys)); + bh_memcpy_s(triple_buf + strlen(arch) + strlen(vendor_sys), + (uint32)(sizeof(triple_buf) - strlen(arch) + - strlen(vendor_sys)), + abi, (uint32)strlen(abi)); triple = triple_buf; } @@ -1803,6 +1877,8 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) aot_set_last_error("create LLVM target machine failed."); goto fail; } + + LLVMSetTarget(comp_ctx->module, triple_norm); } if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0 @@ -1861,6 +1937,11 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) LLVMAddIndVarSimplifyPass(comp_ctx->pass_mgr); if (!option->is_jit_mode) { + /* Put Vectorize passes before GVN/LICM passes as the former + might gain more performance improvement and the latter might + break the optimizations for the former */ + LLVMAddLoopVectorizePass(comp_ctx->pass_mgr); + LLVMAddSLPVectorizePass(comp_ctx->pass_mgr); LLVMAddLoopRotatePass(comp_ctx->pass_mgr); LLVMAddLoopUnswitchPass(comp_ctx->pass_mgr); LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr); @@ -1870,11 +1951,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) disable them when building as multi-thread mode */ LLVMAddGVNPass(comp_ctx->pass_mgr); LLVMAddLICMPass(comp_ctx->pass_mgr); + LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr); + LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr); } - LLVMAddLoopVectorizePass(comp_ctx->pass_mgr); - LLVMAddSLPVectorizePass(comp_ctx->pass_mgr); - LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr); - LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr); } /* Create metadata for llvm float experimental constrained intrinsics */ diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 419d6d4936..0bfa02fcc7 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -3389,6 +3389,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); + expect = (uint8)expect; os_mutex_lock(&memory->mem_lock); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) @@ -3399,6 +3400,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); + expect = (uint16)expect; os_mutex_lock(&memory->mem_lock); readv = (uint32)LOAD_U16(maddr); if (readv == expect) @@ -3433,6 +3435,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); + expect = (uint8)expect; os_mutex_lock(&memory->mem_lock); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) @@ -3443,6 +3446,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); + expect = (uint16)expect; os_mutex_lock(&memory->mem_lock); readv = (uint64)LOAD_U16(maddr); if (readv == expect) @@ -3453,6 +3457,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); + expect = (uint32)expect; os_mutex_lock(&memory->mem_lock); readv = (uint64)LOAD_U32(maddr); if (readv == expect) diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 9bb5702194..0b567137fc 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -3308,6 +3308,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); + expect = (uint8)expect; os_mutex_lock(&memory->mem_lock); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) @@ -3318,6 +3319,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); + expect = (uint16)expect; os_mutex_lock(&memory->mem_lock); readv = (uint32)LOAD_U16(maddr); if (readv == expect) @@ -3352,6 +3354,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); + expect = (uint8)expect; os_mutex_lock(&memory->mem_lock); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) @@ -3362,6 +3365,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); + expect = (uint16)expect; os_mutex_lock(&memory->mem_lock); readv = (uint64)LOAD_U16(maddr); if (readv == expect) @@ -3372,6 +3376,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); + expect = (uint32)expect; os_mutex_lock(&memory->mem_lock); readv = (uint64)LOAD_U32(maddr); if (readv == expect) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 83f28a711c..51327d6cc1 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -47,7 +47,8 @@ static bool check_buf(const uint8 *buf, const uint8 *buf_end, uint32 length, char *error_buf, uint32 error_buf_size) { - if (buf + length < buf || buf + length > buf_end) { + if ((uintptr_t)buf + length < (uintptr_t)buf + || (uintptr_t)buf + length > (uintptr_t)buf_end) { set_error_buf(error_buf, error_buf_size, "unexpected end of section or function"); return false; @@ -59,7 +60,8 @@ static bool check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, char *error_buf, uint32 error_buf_size) { - if (buf + length < buf || buf + length > buf_end) { + if ((uintptr_t)buf + length < (uintptr_t)buf + || (uintptr_t)buf + length > (uintptr_t)buf_end) { set_error_buf(error_buf, error_buf_size, "unexpected end"); return false; } diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake index 262bc610c1..28caad10d4 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake @@ -3,7 +3,7 @@ set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR}) set (UVWASI_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../deps/uvwasi) -set (LIBUV_VERSION v1.39.0) +set (LIBUV_VERSION v1.42.0) add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1) @@ -21,6 +21,7 @@ if(NOT libuv_POPULATED) include_directories("${libuv_SOURCE_DIR}/include") add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL) set (UV_A_LIBS uv_a) + set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() include_directories(${UVWASI_DIR}/include) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index 297d0c50c0..560fdeb009 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -441,47 +441,100 @@ _Static_assert(sizeof(void *) != 4 || _Static_assert(sizeof(void *) != 8 || _Alignof(__wasi_iovec_t) == 8, "non-wasi data layout"); +/** + * The contents of a `subscription` when type is `eventtype::clock`. + */ +typedef struct __wasi_subscription_clock_t { + /** + * The clock against which to compare the timestamp. + */ + __wasi_clockid_t clock_id; + + uint8_t __paddings1[4]; + + /** + * The absolute or relative timestamp. + */ + __wasi_timestamp_t timeout; + + /** + * The amount of time that the implementation may wait additionally + * to coalesce with other events. + */ + __wasi_timestamp_t precision; + + /** + * Flags specifying whether the timeout is absolute or relative + */ + __wasi_subclockflags_t flags; + + uint8_t __paddings2[4]; + +} __wasi_subscription_clock_t __attribute__((aligned(8))); + +_Static_assert(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_clock_t, clock_id) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset"); + +/** + * The contents of a `subscription` when type is type is + * `eventtype::fd_read` or `eventtype::fd_write`. + */ +typedef struct __wasi_subscription_fd_readwrite_t { + /** + * The file descriptor on which to wait for it to become ready for reading or writing. + */ + __wasi_fd_t fd; + +} __wasi_subscription_fd_readwrite_t; + +_Static_assert(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, fd) == 0, "witx calculated offset"); + +/** + * The contents of a `subscription`. + */ +typedef union __wasi_subscription_u_u_t { + __wasi_subscription_clock_t clock; + __wasi_subscription_fd_readwrite_t fd_readwrite; +} __wasi_subscription_u_u_t ; + +typedef struct __wasi_subscription_u_t { + __wasi_eventtype_t type; + __wasi_subscription_u_u_t u; +} __wasi_subscription_u_t __attribute__((aligned(8))); + +_Static_assert(sizeof(__wasi_subscription_u_t) == 40, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_u_t, u) == 8, "witx calculated union offset"); +_Static_assert(sizeof(__wasi_subscription_u_u_t) == 32, "witx calculated union size"); +_Static_assert(_Alignof(__wasi_subscription_u_u_t) == 8, "witx calculated union align"); + +/** + * Subscription to an event. + */ typedef struct __wasi_subscription_t { + /** + * User-provided value that is attached to the subscription in the + * implementation and returned through `event::userdata`. + */ __wasi_userdata_t userdata; - __wasi_eventtype_t type; - uint8_t __paddings[7]; - union __wasi_subscription_u { - struct __wasi_subscription_u_clock_t { - __wasi_userdata_t identifier; - __wasi_clockid_t clock_id; - uint8_t __paddings1[4]; - __wasi_timestamp_t timeout; - __wasi_timestamp_t precision; - __wasi_subclockflags_t flags; - uint8_t __paddings2[6]; - } clock; - struct __wasi_subscription_u_fd_readwrite_t { - __wasi_fd_t fd; - } fd_readwrite; - } u; -} __wasi_subscription_t __attribute__((aligned(8))); -_Static_assert( - offsetof(__wasi_subscription_t, userdata) == 0, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, type) == 8, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, u.clock.identifier) == 16, - "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, u.clock.clock_id) == 24, - "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, u.clock.timeout) == 32, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, u.clock.precision) == 40, - "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, u.clock.flags) == 48, "non-wasi data layout"); -_Static_assert( - offsetof(__wasi_subscription_t, u.fd_readwrite.fd) == 16, - "non-wasi data layout"); -_Static_assert(sizeof(__wasi_subscription_t) == 56, "non-wasi data layout"); -_Static_assert(_Alignof(__wasi_subscription_t) == 8, "non-wasi data layout"); + + /** + * The type of the event to which to subscribe, and its contents + */ + __wasi_subscription_u_t u; + +} __wasi_subscription_t; + +_Static_assert(sizeof(__wasi_subscription_t) == 48, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset"); #if defined(WASMTIME_SSP_WASI_API) #define WASMTIME_SSP_SYSCALL_NAME(name) \ 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 94eb0024cb..7e01f85ca8 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 @@ -2418,19 +2418,19 @@ wasmtime_ssp_poll_oneoff( size_t *nevents) NO_LOCK_ANALYSIS { // Sleeping. - if (nsubscriptions == 1 && in[0].type == __WASI_EVENTTYPE_CLOCK) { + if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) { out[0] = (__wasi_event_t){ .userdata = in[0].userdata, - .type = in[0].type, + .type = in[0].u.type, }; #if CONFIG_HAS_CLOCK_NANOSLEEP clockid_t clock_id; - if (convert_clockid(in[0].u.clock.clock_id, &clock_id)) { + if (convert_clockid(in[0].u.u.clock.clock_id, &clock_id)) { struct timespec ts; - convert_timestamp(in[0].u.clock.timeout, &ts); + convert_timestamp(in[0].u.u.clock.timeout, &ts); int ret = clock_nanosleep( clock_id, - (in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 + (in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 ? TIMER_ABSTIME : 0, &ts, NULL); @@ -2441,9 +2441,9 @@ wasmtime_ssp_poll_oneoff( out[0].error = __WASI_ENOTSUP; } #else - switch (in[0].u.clock.clock_id) { + switch (in[0].u.u.clock.clock_id) { case __WASI_CLOCK_MONOTONIC: - if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0) { // TODO(ed): Implement. fputs("Unimplemented absolute sleep on monotonic clock\n", @@ -2454,12 +2454,12 @@ wasmtime_ssp_poll_oneoff( // Perform relative sleeps on the monotonic clock also using // nanosleep(). This is incorrect, but good enough for now. struct timespec ts; - convert_timestamp(in[0].u.clock.timeout, &ts); + convert_timestamp(in[0].u.u.clock.timeout, &ts); nanosleep(&ts, NULL); } break; case __WASI_CLOCK_REALTIME: - if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0) { // Sleeping to an absolute point in time can only be done // by waiting on a condition variable. @@ -2473,7 +2473,8 @@ wasmtime_ssp_poll_oneoff( return -1; } mutex_lock(&mutex); - cond_timedwait(&cond, &mutex, in[0].u.clock.timeout, true); + cond_timedwait(&cond, &mutex, in[0].u.u.clock.timeout, + true); mutex_unlock(&mutex); mutex_destroy(&mutex); cond_destroy(&cond); @@ -2481,7 +2482,7 @@ wasmtime_ssp_poll_oneoff( else { // Relative sleeps can be done using nanosleep(). struct timespec ts; - convert_timestamp(in[0].u.clock.timeout, &ts); + convert_timestamp(in[0].u.u.clock.timeout, &ts); nanosleep(&ts, NULL); } break; @@ -2519,18 +2520,18 @@ wasmtime_ssp_poll_oneoff( const __wasi_subscription_t *clock_subscription = NULL; for (size_t i = 0; i < nsubscriptions; ++i) { const __wasi_subscription_t *s = &in[i]; - switch (s->type) { + switch (s->u.type) { case __WASI_EVENTTYPE_FD_READ: case __WASI_EVENTTYPE_FD_WRITE: { __wasi_errno_t error = - fd_object_get_locked(&fos[i], ft, s->u.fd_readwrite.fd, + fd_object_get_locked(&fos[i], ft, s->u.u.fd_readwrite.fd, __WASI_RIGHT_POLL_FD_READWRITE, 0); if (error == 0) { // Proper file descriptor on which we can poll(). pfds[i] = (struct pollfd){ .fd = fd_number(fos[i]), - .events = s->type == __WASI_EVENTTYPE_FD_READ + .events = s->u.type == __WASI_EVENTTYPE_FD_READ ? POLLRDNORM : POLLWRNORM, }; @@ -2542,14 +2543,14 @@ wasmtime_ssp_poll_oneoff( out[(*nevents)++] = (__wasi_event_t){ .userdata = s->userdata, .error = error, - .type = s->type, + .type = s->u.type, }; } break; } case __WASI_EVENTTYPE_CLOCK: if (clock_subscription == NULL - && (s->u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) { // Relative timeout. fos[i] = NULL; @@ -2565,7 +2566,7 @@ wasmtime_ssp_poll_oneoff( out[(*nevents)++] = (__wasi_event_t){ .userdata = s->userdata, .error = __WASI_ENOSYS, - .type = s->type, + .type = s->u.type, }; break; } @@ -2579,7 +2580,7 @@ wasmtime_ssp_poll_oneoff( timeout = 0; } else if (clock_subscription != NULL) { - __wasi_timestamp_t ts = clock_subscription->u.clock.timeout / 1000000; + __wasi_timestamp_t ts = clock_subscription->u.u.clock.timeout / 1000000; timeout = ts > INT_MAX ? -1 : (int)ts; } else { @@ -2603,7 +2604,7 @@ wasmtime_ssp_poll_oneoff( for (size_t i = 0; i < nsubscriptions; ++i) { if (pfds[i].fd >= 0) { __wasi_filesize_t nbytes = 0; - if (in[i].type == __WASI_EVENTTYPE_FD_READ) { + if (in[i].u.type == __WASI_EVENTTYPE_FD_READ) { int l; if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0) nbytes = (__wasi_filesize_t)l; @@ -2622,7 +2623,7 @@ wasmtime_ssp_poll_oneoff( #else .error = __WASI_EBADF, #endif - .type = in[i].type, + .type = in[i].u.type, }; } else if ((pfds[i].revents & POLLERR) != 0) { @@ -2630,14 +2631,14 @@ wasmtime_ssp_poll_oneoff( out[(*nevents)++] = (__wasi_event_t){ .userdata = in[i].userdata, .error = __WASI_EIO, - .type = in[i].type, + .type = in[i].u.type, }; } else if ((pfds[i].revents & POLLHUP) != 0) { // End-of-file. out[(*nevents)++] = (__wasi_event_t){ .userdata = in[i].userdata, - .type = in[i].type, + .type = in[i].u.type, .u.fd_readwrite.nbytes = nbytes, .u.fd_readwrite.flags = __WASI_EVENT_FD_READWRITE_HANGUP, @@ -2647,7 +2648,7 @@ wasmtime_ssp_poll_oneoff( // Read or write possible. out[(*nevents)++] = (__wasi_event_t){ .userdata = in[i].userdata, - .type = in[i].type, + .type = in[i].u.type, .u.fd_readwrite.nbytes = nbytes, }; } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index b2524df4de..8db457c275 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -5,6 +5,13 @@ #include "thread_manager.h" +#if WASM_ENABLE_INTERP != 0 +#include "../interpreter/wasm_runtime.h" +#endif +#if WASM_ENABLE_AOT != 0 +#include "../aot/aot_runtime.h" +#endif + #if WASM_ENABLE_DEBUG_INTERP != 0 #include "debug_engine.h" #endif @@ -337,25 +344,38 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); wasm_module_inst_t module_inst = get_module_inst(exec_env); - wasm_module_t module = wasm_exec_env_get_module(exec_env); + wasm_module_t module; wasm_module_inst_t new_module_inst; WASMExecEnv *new_exec_env; uint32 aux_stack_start, aux_stack_size; + uint32 stack_size = 8192; - if (!module) { + if (!module_inst || !(module = wasm_exec_env_get_module(exec_env))) { return NULL; } +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + stack_size = + ((WASMModuleInstance *)module_inst)->default_wasm_stack_size; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + stack_size = + ((AOTModuleInstance *)module_inst)->default_wasm_stack_size; + } +#endif + if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, 8192, 0, NULL, 0))) { + module, true, stack_size, 0, NULL, 0))) { return NULL; } - if (module_inst) { - /* Set custom_data to new module instance */ - wasm_runtime_set_custom_data_internal( - new_module_inst, wasm_runtime_get_custom_data(module_inst)); - } + /* Set custom_data to new module instance */ + wasm_runtime_set_custom_data_internal( + new_module_inst, wasm_runtime_get_custom_data(module_inst)); new_exec_env = wasm_exec_env_create_internal(new_module_inst, exec_env->wasm_stack_size); @@ -605,16 +625,69 @@ wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst) #endif /* end of WASM_ENABLE_DEBUG_INTERP */ +/* Check whether the exec_env is in one of all clusters, the caller + should add lock to the cluster list before calling us */ +static bool +clusters_have_exec_env(WASMExecEnv *exec_env) +{ + WASMCluster *cluster = bh_list_first_elem(cluster_list); + WASMExecEnv *node; + + while (cluster) { + node = bh_list_first_elem(&cluster->exec_env_list); + + while (node) { + if (node == exec_env) { + bh_assert(exec_env->cluster == cluster); + return true; + } + node = bh_list_elem_next(node); + } + + cluster = bh_list_elem_next(cluster); + } + + return false; +} + int32 wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val) { - return os_thread_join(exec_env->handle, ret_val); + korp_tid handle; + + os_mutex_lock(&cluster_list_lock); + if (!clusters_have_exec_env(exec_env)) { + /* Invalid thread or the thread has exited */ + if (ret_val) + *ret_val = NULL; + os_mutex_unlock(&cluster_list_lock); + return 0; + } + exec_env->wait_count++; + handle = exec_env->handle; + os_mutex_unlock(&cluster_list_lock); + return os_thread_join(handle, ret_val); } int32 wasm_cluster_detach_thread(WASMExecEnv *exec_env) { - return os_thread_detach(exec_env->handle); + int32 ret = 0; + + os_mutex_lock(&cluster_list_lock); + if (!clusters_have_exec_env(exec_env)) { + /* Invalid thread or the thread has exited */ + os_mutex_unlock(&cluster_list_lock); + return 0; + } + if (exec_env->wait_count == 0) { + /* Only detach current thread when there is no other thread + joining it, otherwise let the system resources for the + thread be released after joining */ + ret = os_thread_detach(exec_env->handle); + } + os_mutex_unlock(&cluster_list_lock); + return ret; } void @@ -660,6 +733,14 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) int32 wasm_cluster_cancel_thread(WASMExecEnv *exec_env) { + os_mutex_lock(&cluster_list_lock); + if (!clusters_have_exec_env(exec_env)) { + /* Invalid thread or the thread has exited */ + os_mutex_unlock(&cluster_list_lock); + return 0; + } + os_mutex_unlock(&cluster_list_lock); + /* Set the termination flag */ #if WASM_ENABLE_DEBUG_INTERP != 0 wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index ca1cd8f804..2d4962a2c1 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -15,66 +15,11 @@ #ifdef __cplusplus extern "C" { #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 -#define WAMR_SIG_TRAP (5) -#define WAMR_SIG_STOP (19) -#define WAMR_SIG_TERM (15) -#define WAMR_SIG_SINGSTEP (0x1ff) - -#define STATUS_RUNNING (0) -#define STATUS_STOP (1) -#define STATUS_EXIT (2) -#define STATUS_STEP (3) - -#define IS_WAMR_TERM_SIG(signo) ((signo) == WAMR_SIG_TERM) - -#define IS_WAMR_STOP_SIG(signo) \ - ((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP) - -typedef struct WASMCurrentEnvStatus { - uint64 signal_flag : 32; - uint64 step_count : 16; - uint64 running_status : 16; - korp_mutex wait_lock; - korp_cond wait_cond; -} WASMCurrentEnvStatus; +#if WASM_ENABLE_DEBUG_INTERP != 0 typedef struct WASMDebugInstance WASMDebugInstance; - -WASMCurrentEnvStatus * -wasm_cluster_create_exenv_status(); - -void -wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status); - -void -wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo); - -void -wasm_cluster_thread_stopped(WASMExecEnv *exec_env); - -void -wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env); - -void -wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status); - -void -wasm_cluster_thread_exited(WASMExecEnv *exec_env); - -void -wasm_cluster_thread_continue(WASMExecEnv *exec_env); - -void -wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo); - -void -wasm_cluster_thread_step(WASMExecEnv *exec_env); - -void -wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst); - #endif + typedef struct WASMCluster { struct WASMCluster *next; @@ -183,6 +128,65 @@ void wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, void *custom_data); +#if WASM_ENABLE_DEBUG_INTERP != 0 +#define WAMR_SIG_TRAP (5) +#define WAMR_SIG_STOP (19) +#define WAMR_SIG_TERM (15) +#define WAMR_SIG_SINGSTEP (0x1ff) + +#define STATUS_RUNNING (0) +#define STATUS_STOP (1) +#define STATUS_EXIT (2) +#define STATUS_STEP (3) + +#define IS_WAMR_TERM_SIG(signo) ((signo) == WAMR_SIG_TERM) + +#define IS_WAMR_STOP_SIG(signo) \ + ((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP) + +typedef struct WASMCurrentEnvStatus { + uint64 signal_flag : 32; + uint64 step_count : 16; + uint64 running_status : 16; + korp_mutex wait_lock; + korp_cond wait_cond; +} WASMCurrentEnvStatus; + +WASMCurrentEnvStatus * +wasm_cluster_create_exenv_status(); + +void +wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status); + +void +wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo); + +void +wasm_cluster_thread_stopped(WASMExecEnv *exec_env); + +void +wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env); + +void +wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status); + +void +wasm_cluster_thread_exited(WASMExecEnv *exec_env); + +void +wasm_cluster_thread_continue(WASMExecEnv *exec_env); + +void +wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo); + +void +wasm_cluster_thread_step(WASMExecEnv *exec_env); + +void +wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst); + +#endif /* end of WASM_ENABLE_DEBUG_INTERP != 0 */ + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/android/platform_init.c b/core/shared/platform/android/platform_init.c index d7ffab33da..1e7cf4447b 100644 --- a/core/shared/platform/android/platform_init.c +++ b/core/shared/platform/android/platform_init.c @@ -89,6 +89,50 @@ readlinkat(int __dir_fd, const char *__path, char *__buf, size_t __buf_size) return -1; } +int +accept4(int __fd, struct sockaddr *__addr, socklen_t *__addr_length, + int __flags) +{ + API_NOT_SUPPORT_ERROR(accept4, 21); + return -1; +} + +int +dup3(int oldfd, int newfd, int cloexec) +{ + API_NOT_SUPPORT_ERROR(dup3, 21); + return -1; +} + +int +pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) +{ + API_NOT_SUPPORT_ERROR(pthread_condattr_setclock, 21); + return -1; +} + +int +epoll_create1(int flags) +{ + API_NOT_SUPPORT_ERROR(epoll_create1, 21); + return -1; +} + +int +epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, + const sigset_t *sigmask) +{ + API_NOT_SUPPORT_ERROR(epoll_pwait, 21); + return -1; +} + +int +inotify_init1(int flags) +{ + API_NOT_SUPPORT_ERROR(inotify_init1, 21); + return -1; +} + #endif #if __ANDROID_API__ < 23 diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index 3ba77baaa6..3a22a5064e 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -16,6 +16,7 @@ static size_t total_size_munmapped = 0; #define HUGE_PAGE_SIZE (2 * 1024 * 1024) +#if !defined(__APPLE__) && !defined(__NuttX__) static inline uintptr_t round_up(uintptr_t v, uintptr_t b) { @@ -29,6 +30,7 @@ round_down(uintptr_t v, uintptr_t b) uintptr_t m = b - 1; return v & ~m; } +#endif void * os_mmap(void *hint, size_t size, int prot, int flags) diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 1e7e4f3750..4a20c10a08 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -326,10 +326,18 @@ os_thread_get_stack_boundary() #elif defined(__APPLE__) || defined(__NuttX__) if ((addr = (uint8 *)pthread_get_stackaddr_np(self))) { stack_size = pthread_get_stacksize_np(self); + + /** + * Check whether stack_addr is the base or end of the stack, + * change it to the base if it is the end of stack. + */ + if (addr <= (uint8 *)&stack_size) + addr = addr + stack_size; + if (stack_size > max_stack_size) - addr -= max_stack_size; - else - addr -= stack_size; + stack_size = max_stack_size; + + addr -= stack_size; /* Reserved 1 guard page at least for safety */ addr += page_size; } diff --git a/core/shared/platform/esp-idf/espidf_malloc.c b/core/shared/platform/esp-idf/espidf_malloc.c index 138df39774..8fde7c8d34 100644 --- a/core/shared/platform/esp-idf/espidf_malloc.c +++ b/core/shared/platform/esp-idf/espidf_malloc.c @@ -14,6 +14,9 @@ os_malloc(unsigned size) uintptr_t *addr_field; buf_origin = malloc(size + 8 + sizeof(uintptr_t)); + if (!buf_origin) { + return NULL; + } buf_fixed = buf_origin + sizeof(void *); if ((uintptr_t)buf_fixed & (uintptr_t)0x7) { buf_fixed = (void *)((uintptr_t)(buf_fixed + 8) & (~(uintptr_t)7)); @@ -34,12 +37,15 @@ os_realloc(void *ptr, unsigned size) uintptr_t *addr_field; if (!ptr) { - return NULL; + return os_malloc(size); } addr_field = ptr - sizeof(uintptr_t); mem_origin = (void *)(*addr_field); mem_new = realloc(mem_origin, size + 8 + sizeof(uintptr_t)); + if (!mem_new) { + return NULL; + } if (mem_origin != mem_new) { mem_new_fixed = mem_new + sizeof(uintptr_t); @@ -61,7 +67,7 @@ void os_free(void *ptr) { void *mem_origin; - uintptr *addr_field; + uintptr_t *addr_field; if (ptr) { addr_field = ptr - sizeof(uintptr_t); diff --git a/core/shared/platform/esp-idf/espidf_memmap.c b/core/shared/platform/esp-idf/espidf_memmap.c index 587fd749b5..693094a634 100644 --- a/core/shared/platform/esp-idf/espidf_memmap.c +++ b/core/shared/platform/esp-idf/espidf_memmap.c @@ -9,12 +9,34 @@ void * os_mmap(void *hint, size_t size, int prot, int flags) { - return os_malloc((int)size); + if (prot & MMAP_PROT_EXEC) { + // Memory allocation with MALLOC_CAP_EXEC will return 4-byte aligned + // Reserve extra 4 byte to fixup alignment and size for the pointer to + // the originally allocated address + void *buf_origin = + heap_caps_malloc(size + 4 + sizeof(uintptr_t), MALLOC_CAP_EXEC); + if (!buf_origin) { + return NULL; + } + void *buf_fixed = buf_origin + sizeof(void *); + if ((uintptr_t)buf_fixed & (uintptr_t)0x7) { + buf_fixed = (void *)((uintptr_t)(buf_fixed + 4) & (~(uintptr_t)7)); + } + + uintptr_t *addr_field = buf_fixed - sizeof(uintptr_t); + *addr_field = (uintptr_t)buf_origin; + return buf_fixed; + } + else { + return os_malloc(size); + } } void os_munmap(void *addr, size_t size) { + // We don't need special handling of the executable allocations + // here, free() of esp-idf handles it properly return os_free(addr); } diff --git a/core/shared/platform/esp-idf/espidf_platform.c b/core/shared/platform/esp-idf/espidf_platform.c index e23eedeb76..af6be88cb0 100644 --- a/core/shared/platform/esp-idf/espidf_platform.c +++ b/core/shared/platform/esp-idf/espidf_platform.c @@ -44,7 +44,13 @@ os_time_get_boot_microsecond(void) uint8 * os_thread_get_stack_boundary(void) { +#if defined(CONFIG_FREERTOS_USE_TRACE_FACILITY) + TaskStatus_t pxTaskStatus; + vTaskGetInfo(xTaskGetCurrentTaskHandle(), &pxTaskStatus, pdTRUE, eInvalid); + return pxTaskStatus.pxStackBase; +#else // !defined(CONFIG_FREERTOS_USE_TRACE_FACILITY) return NULL; +#endif } int diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index 558a3733da..408784d544 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -47,6 +47,10 @@ static os_thread_data supervisor_thread_data; /* Thread data key */ static DWORD thread_data_key; +/* The GetCurrentThreadStackLimits API from "kernel32" */ +static void(WINAPI *GetCurrentThreadStackLimits_Kernel32)(PULONG_PTR, + PULONG_PTR) = NULL; + int os_sem_init(korp_sem *sem); int @@ -61,6 +65,8 @@ os_sem_signal(korp_sem *sem); int os_thread_sys_init() { + HMODULE module; + if (is_thread_sys_inited) return BHT_OK; @@ -84,6 +90,11 @@ os_thread_sys_init() if (!TlsSetValue(thread_data_key, &supervisor_thread_data)) goto fail4; + if ((module = GetModuleHandle((LPSTR) "kernel32"))) { + *(void **)&GetCurrentThreadStackLimits_Kernel32 = + GetProcAddress(module, "GetCurrentThreadStackLimits"); + } + is_thread_sys_inited = true; return BHT_OK; @@ -556,7 +567,6 @@ os_cond_signal(korp_cond *cond) static os_thread_local_attribute uint8 *thread_stack_boundary = NULL; -#if _WIN32_WINNT < 0x0602 static ULONG GetCurrentThreadStackLimits_Win7(PULONG_PTR p_low_limit, PULONG_PTR p_high_limit) @@ -579,7 +589,6 @@ GetCurrentThreadStackLimits_Win7(PULONG_PTR p_low_limit, os_printf("warning: VirtualQuery() failed\n"); return GetLastError(); } -#endif uint8 * os_thread_get_stack_boundary() @@ -591,13 +600,14 @@ os_thread_get_stack_boundary() return thread_stack_boundary; page_size = os_getpagesize(); -#if _WIN32_WINNT >= 0x0602 - GetCurrentThreadStackLimits(&low_limit, &high_limit); -#else - if (0 != GetCurrentThreadStackLimits_Win7(&low_limit, &high_limit)) { - return NULL; + if (GetCurrentThreadStackLimits_Kernel32) { + GetCurrentThreadStackLimits_Kernel32(&low_limit, &high_limit); } -#endif + else { + if (0 != GetCurrentThreadStackLimits_Win7(&low_limit, &high_limit)) + return NULL; + } + /* 4 pages are set unaccessible by system, we reserved one more page at least for safety */ thread_stack_boundary = (uint8 *)(uintptr_t)low_limit + page_size * 5; diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index eee1711f47..cff4afd2a2 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -2,18 +2,38 @@ # Prepare WASM building environments -For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to build WASM applications. Also we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md). +For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md). To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. -The offical *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WARM provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate -another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the offical release. +The official *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WARM provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate +another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release. And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk. For [AssemblyScript](https://github.com/AssemblyScript/assemblyscript), please refer to [AssemblyScript quick start](https://www.assemblyscript.org/quick-start.html) and [AssemblyScript compiler](https://www.assemblyscript.org/compiler.html#command-line-options) for how to install `asc` compiler and build WASM applications. -For Rust, please firstly ref to [Install Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install cargo, rustc and rustup, by default they are installed under ~/.cargo/bin, and then run `rustup target add wasm32-wasi` to install wasm32-wasi target for Rust toolchain. To build WASM applications, we can run `cargo build --target wasm32-wasi`, the output files are under `target/wasm32-wasi`. +For Rust, please refer to [Install Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install *cargo*, *rustc* and *rustup*. By default they are under ~/.cargo/bin. + +And then run such a command to install `wasm32-wasi` target. + +``` bash +$ rustup target add wasm32-wasi +``` + +To build WASM applications, run + +``` bash +$ cargo build --target wasm32-wasi +``` + +The output files are under `target/wasm32-wasi`. + +To build a release version + +``` bash +$ cargo build --release --target wasm32-wasi +``` Build WASM applications with wasi-sdk @@ -55,9 +75,9 @@ To build the source file to WASM bytecode, we can input the following command: ## 1. wasi-sdk options -There are some useful options which can be specified to build the source code (for more link options, please run `/opt/wasi-sdk/bin/wasm-ld --help`): +There are some useful options that are used to compile C/C++ to Wasm (for a full introduction, please refer to [clang command line argument reference](https://clang.llvm.org/docs/ClangCommandLineReference.html) and [wasm-ld command line argument manual](https://lld.llvm.org/WebAssembly.html)): -- **-nostdlib** Do not use the standard system startup files or libraries when linking. In this mode, the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for cmake to build WAMR with libc-builtin support or libc-wasi support. +- **-nostdlib** Do not use the standard system startup files or libraries when linking. In this mode, the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for CMake to build WAMR with libc-builtin support or libc-wasi support. - **-Wl,--no-entry** Do not output any entry point @@ -69,7 +89,7 @@ There are some useful options which can be specified to build the source code (f - **-Wl,--max-memory=\** Maximum size of the linear memory, which must be a multiple of 65536 -- **-z stack-size=\** The auxiliary stack size, which is an area of linear memory, and must be smaller than initial memory size. +- **-z stack-size=\** The auxiliary stack size, which is an area of linear memory, must be smaller than the initial memory size. - **-Wl,--strip-all** Strip all symbols @@ -81,7 +101,7 @@ There are some useful options which can be specified to build the source code (f - **-pthread** Support POSIX threads in generated code -For example, we can build the wasm app with command: +For example, we can build the wasm app with the command: ``` Bash /opt/wasi-sdk/bin/clang -O3 -nostdlib \ @@ -91,9 +111,9 @@ For example, we can build the wasm app with command: -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--no-entry -Wl,--strip-all -Wl,--allow-undefined ``` -to generate a wasm binary with nostdlib mode, auxiliary stack size is 8192 bytes, initial memory size is 64 KB, main function, heap base global and data end global are exported, no entry function is generated (no _start function is exported), and all symbols are stripped. Note that it is nostdlib mode, so libc-builtin should be enabled by runtime embedder or iwasm (with cmake -DWAMR_BUILD_LIBC_BUILT=1, enabled by iwasm in Linux by default). +to generate a wasm binary with nostdlib mode, the auxiliary stack size is 8192 bytes, initial memory size is 64 KB, main function, heap base global and data end global are exported, no entry function is generated (no _start function is exported), and all symbols are stripped. Note that it is nostdlib mode, so libc-builtin should be enabled by runtime embedder or iwasm (with `cmake -DWAMR_BUILD_LIBC_BUILT=1`, enabled by iwasm in Linux by default). -If we want to build the wasm app with wasi mode, we may build the wasm app with command: +If we want to build the wasm app with wasi mode, we may build the wasm app with the command: ```bash /opt/wasi-sdk/bin/clang -O3 \ @@ -103,7 +123,7 @@ If we want to build the wasm app with wasi mode, we may build the wasm app with -Wl,--strip-all ``` -to generate a wasm binary with wasi mode, auxiliary stack size is 8192 bytes, initial memory size is 64 KB, heap base global and data end global are exported, wasi entry function exported (_start function), and all symbols are stripped. Note that it is wasi mode, so libc-wasi should be enabled by runtime embedder or iwasm (with cmake -DWAMR_BUILD_LIBC_WASI=1, enabled by iwasm in Linux by default), and normally no need to export main function, by default _start function is executed by iwasm. +to generate a wasm binary with wasi mode, the auxiliary stack size is 8192 bytes, initial memory size is 64 KB, heap base global and data end global are exported, wasi entry function exported (_start function), and all symbols are stripped. Note that it is wasi mode, so libc-wasi should be enabled by runtime embedder or iwasm (with `cmake -DWAMR_BUILD_LIBC_WASI=1`, enabled by iwasm in Linux by default), and normally no need to export main function, by default _start function is executed by iwasm. ## 2. How to reduce the footprint? @@ -119,7 +139,7 @@ Firstly if libc-builtin (-nostdlib) mode meets the requirements, e.g. there are - reduce auxiliary stack size - The auxiliary stack is an area of linear memory, normally the size is 64 KB by default which might be a little large for embedded devices and actually partly used, we can use `-z stack-size=n` to set its size. + The auxiliary stack is an area of linear memory, normally the size is 64 KB by default which might be a little large for embedded devices and partly used, we can use `-z stack-size=n` to set its size. - use -O3 and -Wl,--strip-all @@ -133,7 +153,7 @@ Firstly if libc-builtin (-nostdlib) mode meets the requirements, e.g. there are - decrease block_addr_cache size for classic interpreter - The block_addr_cache is an hash cache to store the else/end addresses for WebAssembly blocks (BLOCK/IF/LOOP) to speed up address lookup. This is only available in classic interpreter. We can set it by define macro `-DBLOCK_ADDR_CACHE_SIZE=n`, e.g. add `add_defintion (-DBLOCK_ADDR_CACHE_SIZE=n)` in CMakeLists.txt, by default it is 64, and total block_addr_cache size is 3072 bytes in 64-bit platform and 1536 bytes in 32-bit platform. + The block_addr_cache is a hash cache to store the else/end addresses for WebAssembly blocks (BLOCK/IF/LOOP) to speed up address lookup. This is only available in the classic interpreter. We can set it by defineing macro `-DBLOCK_ADDR_CACHE_SIZE=n`, e.g. add `add_defintion (-DBLOCK_ADDR_CACHE_SIZE=n)` in CMakeLists.txt, by default it is 64, and the total block_addr_cache size is 3072 bytes in 64-bit platform and 1536 bytes in 32-bit platform. ### (2) Methods to reduce the libc-wasi (without -nostdlib) mode footprint @@ -178,7 +198,7 @@ EMCC_ONLY_FORCED_STDLIBS=1 emcc -O3 -s STANDALONE_WASM=1 \ There are some useful options: -- **EMCC_ONLY_FORCED_STDLIBS=1** whether to link libc library into the output binary or not, similar to `-nostdlib` option of wasi-sdk clang. If specified, then no libc library is linked and the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for cmake to build WAMR with libc-builtin support or libc-wasi support. +- **EMCC_ONLY_FORCED_STDLIBS=1** whether to link libc library into the output binary or not, similar to `-nostdlib` option of wasi-sdk clang. If specified, then no libc library is linked and the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for CMake to build WAMR with libc-builtin support or libc-wasi support. The emsdk's wasi implementation is incomplete, e.g. open a file might just return fail, so it is strongly not recommended to use this mode, especially when there are file io operations in wasm app, please use wasi-sdk instead. @@ -200,31 +220,48 @@ For more options, please ref to /upstream/emscripten/src/settings.js, # Build a project with cmake -If you have complex WASM application project which contains dozens of source files, you can consider using cmake for project building. +If you have a complex WASM application project which contains dozens of source files, you can consider using cmake for project building. You can cross compile your project by using the toolchain provided by WAMR. -We can generate a `CMakeLists.txt` file for `test.c`: +Assume the original `CMakeLists.txt` for `test.c` likes below: ``` cmake cmake_minimum_required (VERSION 3.5) project(hello_world) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--export=main") add_executable(hello_world test.c) ``` -It is simple to build this project by cmake: +It is easy to use *wasi-sdk* in CMake by setting *CMAKE_TOOLCHAIN_FILE* without any modification on the original *CMakeLists.txt*. -``` Bash -mkdir build && cd build -cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/wamr-sdk/app/wamr_toolchain.cmake -make +``` +$ cmake -DWASI_SDK_PREFIX=${WASI_SDK_INSTALLTION_DIR} + -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_INSTALLTION_DIR}/share/cmake/wasi-sdk.cmake + -DCMAKE_SYSROOT= + .. ``` -You will get ```hello_world``` which is the WASM app binary. +`WASI_SDK_INSTALLTION_DIR` is the directory in where you install the *wasi-sdk*. like */opt/wasi-sdk* + +If you prefer WASI, set *CMAKE_SYSROOT* to *wasi-sysroot* + +``` +$ cmake + -DCMAKE_SYSROOT=${WASI_SDK_INSTALLTION_DIR}/share/wasi-sysroot + .. +``` -> Note: If you have already built a SDK profile, then the **DCMAKE_TOOLCHAIN_FILE** should be changed into `$WAMR_ROOT/wamr-sdk/out/${PROFILE}/app-sdk/wamr_toolchain.cmake` +If you prefer *WAMR builtin libc*, set *CMAKE_SYSROOT* to *libc-builtin-sysroot* + +> Note: If you have already built a SDK profile + +``` +$ cmake + -DCMAKE_SYSROOT=${WAMR_SOURCE_ROOT}/wamr-sdk/app/libc-builtin-sysroot + .. +``` + +You will get ```hello_world``` which is the WASM app binary. # Compile WASM to AoT module diff --git a/doc/multi_module.md b/doc/multi_module.md index 030ad221fc..1c22863f95 100644 --- a/doc/multi_module.md +++ b/doc/multi_module.md @@ -1,17 +1,24 @@ -Multiple Modules as Dependencies -========================= +# Multiple Modules as Dependencies -It is allowed that one WASM module can *import* *functions*, *globals*, *memories* and *tables* from other modules as its dependencies, and also one module can *export* those entities for other modules to *access* and may *write*. +A WASM module can _import_ _functions_, _globals_, _memories_ and _tables_ from other modules as dependencies. A module can also _export_ those entities for other modules like a library. -WAMR loads all dependencies recursively according to the *import section* of a module. +WAMR loads all dependencies recursively according to the _import section_ of a module. -> Currently WAMR only implements the load-time dynamic linking. Please refer to [dynamic linking](https://webassembly.org/docs/dynamic-linking/) for more details. +> WAMR only implements the load-time dynamic linking. Please refer to [dynamic linking](https://webassembly.org/docs/dynamic-linking/) for more details. + +WAMR follows [WASI Command/Reactor Model](https://github.com/WebAssembly/WASI/blob/main/design/application-abi.md#current-unstable-abi). The WASI model separates modules into commands and reactors. A Command is the main module that requires exports of reactors(submodules). + +if `WASM_ENABLE_LIBC_WASI` is enabled, any module imports a WASI APIs, like `(import "wasi_snapshot_preview1" "XXX")`, should follow restrictions of the _WASI application ABI_: + +- a main module(a command) should include `_start()` +- a submodule(a reactor) should include `_initialize()` +- both a command and a reactor should include an exported `memory` ## Multi-Module Related APIs ### Register a module -``` c +```c bool wasm_runtime_register_module(const char *module_name, wasm_module_t module, @@ -19,23 +26,23 @@ wasm_runtime_register_module(const char *module_name, uint32_t error_buf_size); ``` -It is used to register a *module* with a *module_name* to WASM runtime, especially for the root module, which is loaded by `wasm_runtime_load()` and doesn't have a chance to tell runtime its *module name*. +It is used to register a _module_ with a _module_name_ to WASM runtime, especially for the main module, which is loaded by `wasm_runtime_load()` and doesn't have a chance to tell runtime its _module name_. -Fot all the sub modules, WAMR will get their names and load the .wasm files from the filesystem or stream, so no need to register the sub modules again. +WAMR will get submodules' names(according to the _import section_ of the main module) and load .wasm files from the filesystem or stream and then register them internally. ### Find a registered module -``` c +```c wasm_module_t wasm_runtime_find_module_registered( const char *module_name); ``` -It is used to check if a module with a given *module_name* has been registered, if yes return the module. +It is used to check whether a module with a given _module_name_ has been registered before or not. Return the module if yes. ### Module reader and destroyer -``` c +```c typedef bool (*module_reader)(const char *module_name, uint8_t **p_buffer, uint32_t *p_size); @@ -48,9 +55,9 @@ wasm_runtime_set_module_reader(const module_reader reader, const module_destroyer destroyer); ``` -WAMR hopes that the native host or embedding environment loads/unloads the module WASM files by themselves and only passes runtime the binary content without worrying filesystem or storage issues. `module_reader` and `module_destroyer` are two callbacks called when dynamic-loading/unloading the sub modules. Developers must implement the two callbacks by themselves. +WAMR hopes that the native host or embedding environment loads/unloads the module WASM files by themselves and only passes runtime the binary content without worrying about filesystem or storage issues. `module_reader` and `module_destroyer` are two callbacks called when dynamic-loading/unloading submodules. Developers must implement the two callbacks by themselves. -### Call function of sub module +### Call function of a submodule ```c wasm_function_inst_t @@ -59,87 +66,75 @@ wasm_runtime_lookup_function(wasm_module_inst_t const module_inst, const char *signature); ``` -Multi-module allows to lookup the function of sub module and call it. There are two ways to indicate the function *name*: +Multi-module allows one to look up an exported function of a submodule. There are two ways to indicate the function _name_: -- parent function name only by default, used to lookup the function of parent module -- sub module name, function name of sub module and two $ symbols, e.g. `$sub_module_name$function_name`, used to lookup function of sub module +- parent function name only by default, used to look up the function of the parent module +- submodule name, function name and two $ symbols, e.g. `$submodule_name$function_name`, used to lookup function of submodule +- `signature` can be NULL ## Example -### WASM modules -Suppose we have three C files, *mA.c*, *mB.c* and *mC.c*. Each of them has some exported functions and import some from others except mA. +### Attributes in C/C++ -Undefined symbols can be marked in the source code with the *import_name* clang attribute which means that they are expected to be undefined at static link time. Without the *import_module* clang attribute, undefined symbols will be marked from the *env* module. +Suppose there are three C files, _mA.c_, _mB.c_ and _mC.c_. Each of them exports functions and imports from others except mA. -``` C +import/export with two kinds of `__attribute__`: + +- `__attribute__((import_module("MODULE_NAME"))) __attribute__((import_name("FUNCTION_NAME")))`. to indicate dependencies of the current module. + +- `__attribute__((export_name("FUNCTION_NAME")))`. to expose functions. + +```C // mA.c -int A() { return 10; } +__attribute__((export_name("A1"))) int +A1() +{ + return 11; +} ``` -``` C +```C // mB.c -__attribute__((import_module("mA"))) __attribute__((import_name("A"))) extern int A(); -int B() { return 11; } -int call_A() { return A(); } -``` +__attribute__((import_module("mA"))) +__attribute__((import_name("A1"))) extern int +A1(); -``` C -// mC.c -__attribute__((import_module("mA"))) __attribute__((import_name("A"))) extern int A(); -__attribute__((import_module("mB"))) __attribute__((import_name("B"))) extern int B(); -int C() { return 12; } -int call_A() { return A(); } -int call_B() { return B(); } +__attribute__((export_name("B1"))) int +B1() +{ + return 21; +} ``` -By default no undefined symbols are allowed in the final binary. The flag *--allow-undefined* results in a WebAssembly import being defined for each undefined symbol. It is then up to the runtime to provide such symbols. - -When building an executable, only the entry point (_start) and symbols with the *export_name* attribute exported by default. in addition, symbols can be exported via the linker command line using *--export*. - -In the example, another linked command option *--export-all* is used. - -> with more detail, please refer to [WebAssembly lld port](https://lld.llvm.org/WebAssembly.html) +### Compile Options -Here is an example how to compile a *.c* to a *.wasm* with clang. Since there is no *start* function, we use *--no-entry* option. +to generate a wasm module as a command -``` shell -$ clang --target=wasm32 -nostdlib \ - -Wl,--no-entry,--allow-undefined,--export-all \ - -o mA.wasm mA.c -$ clang --target=wasm32 -nostdlib \ - -Wl,--no-entry,--allow-undefined,--export-all \ - -o mB.wasm mB.c -$ clang --target=wasm32 -nostdlib \ - -Wl,--no-entry,--allow-undefined,--export-all \ - -o mC.wasm mC.c +``` +$ /path/to/wasi-sdk/bin/clang -o command.wasm main_module.c ``` -put *mA.wasm*, *mB.wasm* and *mC.wasm* in the directory *wasm-apps* +to generate a wasm module as a reactor -``` shell -$ # copy mA.wasm, mB.wasm and mC.wasm into wasm-apps -$ tree wasm-apps/ -wasm-apps/ -├── mA.wasm -├── mB.wasm -└── mC.wasm +``` +$ /path/to/wasi-sdk/bin/clang -mexec-model=reactor -o reactor.wasm submodule.c ``` -eventually, their *import relationships* will be like: +In the above case, _mA_ and _mB_ are reactors(submodules), _mC_ is the command(main module). Their _import relationships_ will be like: ![import relationships](./pics/multi_module_pic1.png) ### libvmlib -We need to enable *WAMR_BUILD_MULTI_MODULE* option when building WAMR vmlib. Please ref to [Build WAMR core](./build_wamr.md) for a thoughtful guide. +We need to enable _WAMR_BUILD_MULTI_MODULE_ option when building WAMR vmlib. Please ref to [Build WAMR core](./build_wamr.md) for a thoughtful guide. ### code -After all above preparation, we can call some functions from native code with APIs +After all the preparation, we can call some functions from native code with APIs -first, create two callbacks to load WASM module files into memory and unload them later +First, create two callbacks to load WASM module files into memory and unload them later -``` c +```c static bool module_reader_cb(const char *module_name, uint8 **p_buffer, uint32 *p_size) { @@ -155,74 +150,12 @@ module_destroyer_cb(uint8 *buffer, uint32 size) } ``` -second, create a large buffer and tell WAMR malloc any resource only from this buffer later +Second, create a large buffer and tell WAMR malloc any resource only from this buffer later. -``` c -static char sandbox_memory_space[10 * 1024 * 1024] = { 0 }; -``` +More details -third, put all together - -``` c -int main() -{ - /* all malloc() only from the given buffer */ - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = sandbox_memory_space; - init_args.mem_alloc_option.pool.heap_size = sizeof(sandbox_memory_space); - - /* initialize runtime environment */ - wasm_runtime_full_init(&init_args); - - /* set module reader and destroyer */ - wasm_runtime_set_module_reader(module_reader_cb, module_destroyer_cb); - - /* load WASM byte buffer from WASM bin file */ - module_reader_cb("mC", &file_buf, &file_buf_size)); - - /* load mC and let WAMR load mA and mB */ - module = wasm_runtime_load(file_buf, file_buf_size, - error_buf, sizeof(error_buf)); - - /* instantiate the module */ - module_inst = - wasm_runtime_instantiate(module, stack_size, - heap_size, error_buf, sizeof(error_buf))); - - - printf("call \"C\", it will return 0xc:i32, ===> "); - wasm_application_execute_func(module_inst, "C", 0, &args[0]); - printf("call \"call_B\", it will return 0xb:i32, ===> "); - wasm_application_execute_func(module_inst, "call_B", 0, &args[0]); - printf("call \"call_A\", it will return 0xa:i32, ===>"); - wasm_application_execute_func(module_inst, "call_A", 0, &args[0]); - - /* call some functions of mB */ - printf("call \"mB.B\", it will return 0xb:i32, ===>"); - wasm_application_execute_func(module_inst, "$mB$B", 0, &args[0]); - printf("call \"mB.call_A\", it will return 0xa:i32, ===>"); - wasm_application_execute_func(module_inst, "$mB$call_A", 0, &args[0]); - - /* call some functions of mA */ - printf("call \"mA.A\", it will return 0xa:i32, ===>"); - wasm_application_execute_func(module_inst, "$mA$A", 0, &args[0]); - - // ... -} +```c +static char sandbox_memory_space[10 * 1024 * 1024] = { 0 }; ``` -> please refer to [main.c](../samples/multi_modules/src/main.c) - -The output of the main.c will like: - -``` shell -$ ./a.out - -call "C", it will return 0xc:i32, ===> 0xc:i32 -call "call_B", it will return 0xb:i32, ===> 0xb:i32 -call "call_A", it will return 0xa:i32, ===>0xa:i32 -call "mB.B", it will return 0xb:i32, ===>0xb:i32 -call "mB.call_A", it will return 0xa:i32, ===>0xa:i32 -call "mA.A", it will return 0xa:i32, ===>0xa:i32 - -``` +Third, put all together. Please refer to [main.c](../samples/multi-module/src/main.c) diff --git a/product-mini/platforms/darwin/CMakeLists.txt b/product-mini/platforms/darwin/CMakeLists.txt index 5ef30eb4cb..6485b59038 100644 --- a/product-mini/platforms/darwin/CMakeLists.txt +++ b/product-mini/platforms/darwin/CMakeLists.txt @@ -15,7 +15,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") @@ -55,8 +55,8 @@ if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) endif () if (NOT DEFINED WAMR_BUILD_LIBC_WASI) - # Disable libc wasi support by default - set (WAMR_BUILD_LIBC_WASI 0) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) endif () if (NOT DEFINED WAMR_BUILD_FAST_INTERP) @@ -65,7 +65,7 @@ if (NOT DEFINED WAMR_BUILD_FAST_INTERP) endif () if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) - # Enable multiple modules + # Disable multiple module by default set (WAMR_BUILD_MULTI_MODULE 0) endif () diff --git a/product-mini/platforms/esp-idf/.gitignore b/product-mini/platforms/esp-idf/.gitignore new file mode 100644 index 0000000000..c260f41fd2 --- /dev/null +++ b/product-mini/platforms/esp-idf/.gitignore @@ -0,0 +1,2 @@ +sdkconfig +sdkconfig.old \ No newline at end of file diff --git a/product-mini/platforms/esp-idf/CMakeLists.txt b/product-mini/platforms/esp-idf/CMakeLists.txt index 0c06469c39..d8a3d2f96c 100644 --- a/product-mini/platforms/esp-idf/CMakeLists.txt +++ b/product-mini/platforms/esp-idf/CMakeLists.txt @@ -1,77 +1,12 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2019-21 Intel Corporation and others. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # from ESP-IDF 4.0 examples/build_system/cmake/idf_as_lib cmake_minimum_required(VERSION 3.5) -project(wamr_on_esp32c3) -enable_language(ASM) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif () +set (COMPONENTS ${IDF_TARGET} main freertos esptool_py wamr) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{WAMR_PATH}/build-scripts/esp-idf") -if("${IDF_TARGET}" STREQUAL "") - message(FATAL_ERROR "You need to set IDF_TARGET to your target string") -endif() - -# Include for ESP-IDF build system functions -include($ENV{IDF_PATH}/tools/cmake/idf.cmake) -# Create idf::esp32c3 and idf::freertos static libraries -idf_build_process(${IDF_TARGET} - # try and trim the build; additional components - # will be included as needed based on dependency tree - # - # although esptool_py does not generate static library, - # processing the component is needed for flashing related - # targets and file generation - COMPONENTS ${IDF_TARGET} freertos esptool_py - SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig - BUILD_DIR ${CMAKE_BINARY_DIR}) - -# Set WAMR's build options -if("${IDF_TARGET}" STREQUAL "esp32c3") - set(WAMR_BUILD_TARGET "RISCV32") -else() - set(WAMR_BUILD_TARGET "XTENSA") - add_compile_options(-DWAMR_BUILD_TARGET_XTENSA=1) -endif() - -set(WAMR_BUILD_PLATFORM "esp-idf") - -if (NOT DEFINED WAMR_BUILD_INTERP) - set (WAMR_BUILD_INTERP 0) -endif () - -if (NOT DEFINED WAMR_BUILD_FAST_INTERP) - set (WAMR_BUILD_FAST_INTERP 0) -endif () - -if (NOT DEFINED WAMR_BUILD_AOT) - set (WAMR_BUILD_AOT 1) -endif () - -if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) - set (WAMR_BUILD_LIBC_BUILTIN 1) -endif () - -if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) - set (WAMR_BUILD_APP_FRAMEWORK 0) -endif () - - -# Set the compile time variable so that the right binary is selected -add_compile_options(-DWAMR_BUILD_INTERP=${WAMR_BUILD_INTERP}) - -set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) -include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) - -# define WAMR as library and provide it the esp-idf srcs -add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -target_link_libraries(vmlib PUBLIC idf::pthread idf::${IDF_TARGET} idf::freertos) - -# Define the final executable -set(elf_file ${CMAKE_PROJECT_NAME}.elf) -add_executable(${elf_file} main.c test_wasm.h) -target_link_libraries(${elf_file} idf::${IDF_TARGET} idf::freertos idf::spi_flash vmlib) -idf_build_executable(${elf_file}) +project(wamr-simple) \ No newline at end of file diff --git a/product-mini/platforms/esp-idf/build.sh b/product-mini/platforms/esp-idf/build.sh deleted file mode 100755 index d96fe404eb..0000000000 --- a/product-mini/platforms/esp-idf/build.sh +++ /dev/null @@ -1,4 +0,0 @@ -rm -rf build && mkdir build && cd build -cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32c3.cmake -DIDF_TARGET=esp32c3 -DCMAKE_BUILD_TYPE=Release -GNinja -cmake --build . -ninja flash diff --git a/product-mini/platforms/esp-idf/build_and_run.sh b/product-mini/platforms/esp-idf/build_and_run.sh new file mode 100755 index 0000000000..dd8dd5ca9b --- /dev/null +++ b/product-mini/platforms/esp-idf/build_and_run.sh @@ -0,0 +1,33 @@ +#!/bin/bash -e + +# Copyright (C) 2019-21 Intel Corporation and others. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +ESP32_TARGET="esp32" +ESP32C3_TARGET="esp32c3" + +usage () +{ + echo "USAGE:" + echo "$0 $ESP32_TARGET|$ESP32C3_TARGET" + echo "Example:" + echo " $0 $ESP32_TARGET" + echo " $0 $ESP32C3_TARGET" + exit 1 +} + +if [ $# != 1 ] ; then + usage +fi + +TARGET=$1 + +if [[ -z "${WAMR_PATH}" ]]; then + export WAMR_PATH=$PWD/../../.. +fi + +rm -rf build +idf.py set-target $TARGET +idf.py build +idf.py flash + diff --git a/product-mini/platforms/esp-idf/main.c b/product-mini/platforms/esp-idf/main.c deleted file mode 100644 index 4589ab80f5..0000000000 --- a/product-mini/platforms/esp-idf/main.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "wasm_export.h" -#include "bh_platform.h" -#include "test_wasm.h" - -static void * -app_instance_main(wasm_module_inst_t module_inst) -{ - const char *exception; - - wasm_application_execute_main(module_inst, 0, NULL); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); - return NULL; -} - -void * -iwasm_main(void *arg) -{ - (void)arg; /* unused */ - /* setup variables for instantiating and running the wasm module */ - uint8_t *wasm_file_buf = NULL; - unsigned wasm_file_buf_size = 0; - wasm_module_t wasm_module = NULL; - wasm_module_inst_t wasm_module_inst = NULL; - char error_buf[128]; - void *ret; - RuntimeInitArgs init_args; - - /* configure memory allocation */ - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - init_args.mem_alloc_type = Alloc_With_Allocator; - init_args.mem_alloc_option.allocator.malloc_func = (void *)os_malloc; - init_args.mem_alloc_option.allocator.realloc_func = (void *)os_realloc; - init_args.mem_alloc_option.allocator.free_func = (void *)os_free; - - printf("wasm_runtime_full_init\n"); - /* initialize runtime environment */ - if (!wasm_runtime_full_init(&init_args)) { - printf("Init runtime failed.\n"); - return NULL; - } - - /* load WASM byte buffer from byte buffer of include file */ - printf("use an internal test file, that's going to output Hello World\n"); - wasm_file_buf = (uint8_t *)wasm_test_file; - wasm_file_buf_size = sizeof(wasm_test_file); - - /* load WASM module */ - if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_buf_size, - error_buf, sizeof(error_buf)))) { - printf("Error in wasm_runtime_load: %s\n", error_buf); - goto fail1; - } - - printf("about to call wasm_runtime_instantiate\n"); - if (!(wasm_module_inst = - wasm_runtime_instantiate(wasm_module, 32 * 1024, // stack size - 32 * 1024, // heap size - error_buf, sizeof(error_buf)))) { - printf("Error while instantiating: %s\n", error_buf); - goto fail2; - } - - printf("run main() of the application\n"); - ret = app_instance_main(wasm_module_inst); - assert(!ret); - - /* destroy the module instance */ - printf("wasm_runtime_deinstantiate\n"); - wasm_runtime_deinstantiate(wasm_module_inst); - -fail2: - /* unload the module */ - printf("wasm_runtime_unload\n"); - wasm_runtime_unload(wasm_module); - -fail1: - /* destroy runtime environment */ - printf("wasm_runtime_destroy\n"); - wasm_runtime_destroy(); - - return NULL; -} - -void -app_main(void) -{ - pthread_t t; - int res; - - res = pthread_create(&t, NULL, iwasm_main, (void *)NULL); - assert(res == 0); - - res = pthread_join(t, NULL); - assert(res == 0); - - printf("Exiting... \n"); -} diff --git a/product-mini/platforms/esp-idf/main/CMakeLists.txt b/product-mini/platforms/esp-idf/main/CMakeLists.txt new file mode 100644 index 0000000000..55e7256704 --- /dev/null +++ b/product-mini/platforms/esp-idf/main/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (C) 2021 Intel Corporation and others. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +idf_component_register(SRCS "main.c" + INCLUDE_DIRS "." + REQUIRES wamr) diff --git a/product-mini/platforms/esp-idf/main/main.c b/product-mini/platforms/esp-idf/main/main.c new file mode 100644 index 0000000000..d13295d834 --- /dev/null +++ b/product-mini/platforms/esp-idf/main/main.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2019-21 Intel Corporation and others. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "wasm_export.h" +#include "bh_platform.h" +#include "test_wasm.h" + +#include "esp_log.h" + +#define LOG_TAG "wamr" + +static void * +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + + wasm_application_execute_main(module_inst, 0, NULL); + if ((exception = wasm_runtime_get_exception(module_inst))) + printf("%s\n", exception); + return NULL; +} + +void * +iwasm_main(void *arg) +{ + (void)arg; /* unused */ + /* setup variables for instantiating and running the wasm module */ + uint8_t *wasm_file_buf = NULL; + unsigned wasm_file_buf_size = 0; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + char error_buf[128]; + void *ret; + RuntimeInitArgs init_args; + + /* configure memory allocation */ + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)os_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)os_realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)os_free; + + ESP_LOGI(LOG_TAG, "Initialize WASM runtime"); + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + ESP_LOGE(LOG_TAG, "Init runtime failed."); + return NULL; + } + +#if WASM_ENABLE_INTERP != 0 + ESP_LOGI(LOG_TAG, "Run wamr with interpreter"); + + wasm_file_buf = (uint8_t *)wasm_test_file_interp; + wasm_file_buf_size = sizeof(wasm_test_file_interp); + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_buf_size, + error_buf, sizeof(error_buf)))) { + ESP_LOGE(LOG_TAG, "Error in wasm_runtime_load: %s", error_buf); + goto fail1interp; + } + + ESP_LOGI(LOG_TAG, "Instantiate WASM runtime"); + if (!(wasm_module_inst = + wasm_runtime_instantiate(wasm_module, 32 * 1024, // stack size + 32 * 1024, // heap size + error_buf, sizeof(error_buf)))) { + ESP_LOGE(LOG_TAG, "Error while instantiating: %s", error_buf); + goto fail2interp; + } + + ESP_LOGI(LOG_TAG, "run main() of the application"); + ret = app_instance_main(wasm_module_inst); + assert(!ret); + + /* destroy the module instance */ + ESP_LOGI(LOG_TAG, "Deinstantiate WASM runtime"); + wasm_runtime_deinstantiate(wasm_module_inst); + +fail2interp: + /* unload the module */ + ESP_LOGI(LOG_TAG, "Unload WASM module"); + wasm_runtime_unload(wasm_module); + +fail1interp: +#endif +#if WASM_ENABLE_AOT != 0 + ESP_LOGI(LOG_TAG, "Run wamr with AoT"); + + wasm_file_buf = (uint8_t *)wasm_test_file_aot; + wasm_file_buf_size = sizeof(wasm_test_file_aot); + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_buf_size, + error_buf, sizeof(error_buf)))) { + ESP_LOGE(LOG_TAG, "Error in wasm_runtime_load: %s", error_buf); + goto fail1aot; + } + + ESP_LOGI(LOG_TAG, "Instantiate WASM runtime"); + if (!(wasm_module_inst = + wasm_runtime_instantiate(wasm_module, 32 * 1024, // stack size + 32 * 1024, // heap size + error_buf, sizeof(error_buf)))) { + ESP_LOGE(LOG_TAG, "Error while instantiating: %s", error_buf); + goto fail2aot; + } + + ESP_LOGI(LOG_TAG, "run main() of the application"); + ret = app_instance_main(wasm_module_inst); + assert(!ret); + + /* destroy the module instance */ + ESP_LOGI(LOG_TAG, "Deinstantiate WASM runtime"); + wasm_runtime_deinstantiate(wasm_module_inst); + +fail2aot: + /* unload the module */ + ESP_LOGI(LOG_TAG, "Unload WASM module"); + wasm_runtime_unload(wasm_module); +fail1aot: +#endif + + /* destroy runtime environment */ + ESP_LOGI(LOG_TAG, "Destroy WASM runtime"); + wasm_runtime_destroy(); + + return NULL; +} + +void +app_main(void) +{ + pthread_t t; + int res; + + pthread_attr_t tattr; + pthread_attr_init(&tattr); + pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setstacksize(&tattr, 4096); + + res = pthread_create(&t, &tattr, iwasm_main, (void *)NULL); + assert(res == 0); + + res = pthread_join(t, NULL); + assert(res == 0); + + ESP_LOGI(LOG_TAG, "Exiting..."); +} diff --git a/product-mini/platforms/esp-idf/test_wasm.h b/product-mini/platforms/esp-idf/main/test_wasm.h similarity index 97% rename from product-mini/platforms/esp-idf/test_wasm.h rename to product-mini/platforms/esp-idf/main/test_wasm.h index e4e648ecb9..fc2d76fdb7 100644 --- a/product-mini/platforms/esp-idf/test_wasm.h +++ b/product-mini/platforms/esp-idf/main/test_wasm.h @@ -1,16 +1,10 @@ /* - * Copyright (C) 2019 Intel Corporation. All rights reserved. + * Copyright (C) 2019-21 Intel Corporation and others. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -/** - * The byte array buffer is the file content of a test wasm binary file, - * which is compiled by wasi-sdk toolchain from C source file of: - * product-mini/app-samples/hello-world/main.c. - */ -unsigned char __aligned(4) wasm_test_file[] = { -// binary for the interpreter -#if WAMR_BUILD_INTERP != 0 +#if WASM_ENABLE_INTERP != 0 +unsigned char __aligned(4) wasm_test_file_interp[] = { 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x00, 0x02, 0x31, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, @@ -45,8 +39,13 @@ unsigned char __aligned(4) wasm_test_file[] = { 0x3A, 0x20, 0x25, 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x00 -// binary for the xtensa aot compiler -#elif WAMR_BUILD_TARGET_XTENSA != 0 +}; +#endif + +#if WASM_ENABLE_AOT != 0 +#if BUILD_TARGET_XTENSA != 0 +// XTENSA +unsigned char __aligned(4) wasm_test_file_aot[] = { 0x00, 0x61, 0x6F, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -156,8 +155,10 @@ unsigned char __aligned(4) wasm_test_file[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 -// binary for the riscv aot compiler +}; #else +// RISC-V +unsigned char __aligned(4) wasm_test_file_aot[] = { 0x00, 0x61, 0x6F, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF3, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -282,5 +283,6 @@ unsigned char __aligned(4) wasm_test_file[] = { 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 -#endif }; +#endif +#endif \ No newline at end of file diff --git a/product-mini/platforms/esp-idf/sdkconfig.defaults b/product-mini/platforms/esp-idf/sdkconfig.defaults new file mode 100644 index 0000000000..bb158eea93 --- /dev/null +++ b/product-mini/platforms/esp-idf/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +# CONFIG_ESP_SYSTEM_MEMPROT_FEATURE is not set diff --git a/product-mini/platforms/esp-idf/sdkconfig.defaults.esp32 b/product-mini/platforms/esp-idf/sdkconfig.defaults.esp32 new file mode 100644 index 0000000000..538ea3da1f --- /dev/null +++ b/product-mini/platforms/esp-idf/sdkconfig.defaults.esp32 @@ -0,0 +1 @@ +# CONFIG_ESP32_MEMPROT_FEATURE is not set diff --git a/product-mini/platforms/esp-idf/sdkconfig.defaults.esp32c3 b/product-mini/platforms/esp-idf/sdkconfig.defaults.esp32c3 new file mode 100644 index 0000000000..29b82c4b8f --- /dev/null +++ b/product-mini/platforms/esp-idf/sdkconfig.defaults.esp32c3 @@ -0,0 +1 @@ +# CONFIG_ESP32C3_MEMPROT_FEATURE is not set diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 25bc75258b..c20abdc14f 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -131,10 +131,11 @@ align_ptr(const uint8 *p, uint32 b) #define AOT_SECTION_TYPE_SIGANATURE 6 #define E_TYPE_XIP 4 -#define CHECK_BUF(buf, buf_end, length) \ - do { \ - if (buf + length < buf || buf + length > buf_end) \ - return false; \ +#define CHECK_BUF(buf, buf_end, length) \ + do { \ + if ((uintptr_t)buf + length < (uintptr_t)buf \ + || (uintptr_t)buf + length > (uintptr_t)buf_end) \ + return false; \ } while (0) #define read_uint16(p, p_end, res) \ @@ -162,6 +163,7 @@ is_xip_file(const uint8 *buf, uint32 size) if (get_package_type(buf, size) != Wasm_Module_AoT) return false; + CHECK_BUF(p, p_end, 8); p += 8; while (p < p_end) { @@ -172,15 +174,14 @@ is_xip_file(const uint8 *buf, uint32 size) if (section_type == AOT_SECTION_TYPE_TARGET_INFO) { p += 4; read_uint16(p, p_end, e_type); - if (e_type == E_TYPE_XIP) { - return true; - } + return (e_type == E_TYPE_XIP) ? true : false; } else if (section_type >= AOT_SECTION_TYPE_SIGANATURE) { return false; } p += section_size; } + return false; } diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 6b739753b3..c0b6f6a8c9 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -18,7 +18,7 @@ set (CMAKE_C_STANDARD 99) # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index 0ac3fa302a..c85e2c548b 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -103,7 +103,7 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN -D_WINSOCK_DEPRECATED_NO_WARNINGS") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index dbe9acd590..6e25c4359b 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -234,6 +234,7 @@ main(int argc, char *argv[]) int log_verbose_level = 2; #endif bool is_repl_mode = false; + bool is_xip_file = false; #if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; @@ -382,6 +383,27 @@ main(int argc, char *argv[]) (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size))) goto fail1; +#if WASM_ENABLE_AOT != 0 + if (wasm_runtime_is_xip_file(wasm_file_buf, wasm_file_size)) { + uint8 *wasm_file_mapped; + int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC; + int map_flags = MMAP_MAP_32BIT; + + if (!(wasm_file_mapped = + os_mmap(NULL, (uint32)wasm_file_size, map_prot, map_flags))) { + printf("mmap memory failed\n"); + wasm_runtime_free(wasm_file_buf); + goto fail1; + } + + bh_memcpy_s(wasm_file_mapped, wasm_file_size, wasm_file_buf, + wasm_file_size); + wasm_runtime_free(wasm_file_buf); + wasm_file_buf = wasm_file_mapped; + is_xip_file = true; + } +#endif + #if WASM_ENABLE_MULTI_MODULE != 0 wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); #endif @@ -422,7 +444,10 @@ main(int argc, char *argv[]) fail2: /* free the file buffer */ - wasm_runtime_free(wasm_file_buf); + if (!is_xip_file) + wasm_runtime_free(wasm_file_buf); + else + os_munmap(wasm_file_buf, wasm_file_size); fail1: /* destroy runtime environment */ diff --git a/samples/basic/CMakeLists.txt b/samples/basic/CMakeLists.txt index d8a37652d9..7e10d46094 100644 --- a/samples/basic/CMakeLists.txt +++ b/samples/basic/CMakeLists.txt @@ -26,7 +26,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/samples/multi-module/CMakeLists.txt b/samples/multi-module/CMakeLists.txt index 48f67e1bbe..e3edd0476e 100644 --- a/samples/multi-module/CMakeLists.txt +++ b/samples/multi-module/CMakeLists.txt @@ -20,7 +20,7 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") @@ -113,8 +113,8 @@ else() message(CHECK_FAIL "not found") endif() -if(NOT EXISTS ${WASI_SDK_DIR} OR NOT EXISTS ${WASI_TOOLCHAIN_FILE} OR NOT EXISTS ${WASI_SYS_ROOT}) - message(FATAL_ERROR "Please set the absolute path of wasi-sdk with \'cmake -DWASI_SDK_HOME=XXX\'") +if((NOT EXISTS ${WASI_SDK_DIR}) OR (NOT EXISTS ${WASI_TOOLCHAIN_FILE}) OR (NOT EXISTS ${WASI_SYS_ROOT})) + message(FATAL_ERROR "Please set the absolute path of wasi-sdk with \'cmake -DWASI_SDK_DIR=XXX\'") else() message(STATUS "WASI_SDK_DIR is ${WASI_SDK_DIR}") message(STATUS "WASI_TOOLCHAIN_FILE is ${WASI_TOOLCHAIN_FILE}") diff --git a/samples/multi-thread/CMakeLists.txt b/samples/multi-thread/CMakeLists.txt index 0cf2bed13e..89b59833aa 100644 --- a/samples/multi-thread/CMakeLists.txt +++ b/samples/multi-thread/CMakeLists.txt @@ -20,7 +20,7 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/samples/ref-types/CMakeLists.txt b/samples/ref-types/CMakeLists.txt index 1da1517ef6..b3dd722b6f 100644 --- a/samples/ref-types/CMakeLists.txt +++ b/samples/ref-types/CMakeLists.txt @@ -26,7 +26,7 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/samples/spawn-thread/CMakeLists.txt b/samples/spawn-thread/CMakeLists.txt index 9fa129b219..794ec2aa21 100644 --- a/samples/spawn-thread/CMakeLists.txt +++ b/samples/spawn-thread/CMakeLists.txt @@ -20,7 +20,7 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index b855822a04..c395b627a1 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -32,7 +32,7 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # "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 STREQUAL "arm64") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") set (WAMR_BUILD_TARGET "AARCH64") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 65a102a315..e19ad6fde9 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -21,7 +21,8 @@ The script itself has to be put under the same directory with the "spec". """ -IWASM_CMD = "../../../product-mini/platforms/linux/build/iwasm" +PLATFORM_NAME = os.uname().sysname.lower() +IWASM_CMD = "../../../product-mini/platforms/" + PLATFORM_NAME + "/build/iwasm" IWASM_SGX_CMD = "../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm" SPEC_TEST_DIR = "spec/test/core" WAST2WASM_CMD = "./wabt/out/gcc/Release/wat2wasm" diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 7db0c042aa..920b0d0f36 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -141,6 +141,8 @@ def cleanup(self): os.killpg(self.p.pid, signal.SIGTERM) except OSError: pass + except IOError: + pass self.p = None self.stdin.close() if self.stdin != self.stdout: diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index f6fdf97422..8d943d97e6 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -222,6 +222,10 @@ if (NOT MSVC) endif() endif() +if (MSVC) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS") +endif() + # message ("-- CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") add_library (vmlib diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index c25d1ef1b7..1587d2ae14 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -79,7 +79,7 @@ main(int argc, char *argv[]) AOTCompOption option = { 0 }; char error_buf[128]; int log_verbose_level = 2; - bool sgx_mode = false; + bool sgx_mode = false, size_level_set = false; int exit_status = EXIT_FAILURE; option.opt_level = 3; @@ -133,6 +133,7 @@ main(int argc, char *argv[]) option.size_level = (uint32)atoi(argv[0] + 13); if (option.size_level > 3) option.size_level = 3; + size_level_set = true; } else if (!strcmp(argv[0], "-sgx")) { sgx_mode = true; @@ -207,6 +208,26 @@ main(int argc, char *argv[]) if (argc == 0 || !out_file_name) return print_help(); + if (!size_level_set) { + /** + * Set opt level to 1 by default for Windows and MacOS as + * they can not memory map out 0-2GB memory and might not + * be able to meet the requirements of some AOT relocation + * operations. + */ + if (option.target_abi && !strcmp(option.target_abi, "msvc")) { + LOG_VERBOSE("Set size level to 1 for Windows AOT file"); + option.size_level = 1; + } +#if defined(_WIN32) || defined(_WIN32_) || defined(__APPLE__) \ + || defined(__MACH__) + if (!option.target_abi) { + LOG_VERBOSE("Set size level to 1 for Windows or MacOS AOT file"); + option.size_level = 1; + } +#endif + } + if (sgx_mode) { option.size_level = 1; option.is_sgx_platform = true; @@ -214,6 +235,11 @@ main(int argc, char *argv[]) wasm_file_name = argv[0]; + if (!strcmp(wasm_file_name, out_file_name)) { + printf("Error: input file and output file are the same"); + return -1; + } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); init_args.mem_alloc_type = Alloc_With_Allocator; @@ -236,6 +262,11 @@ main(int argc, char *argv[]) (uint8 *)bh_read_file_to_buffer(wasm_file_name, &wasm_file_size))) goto fail1; + if (get_package_type(wasm_file, wasm_file_size) != Wasm_Module_Bytecode) { + printf("Invalid file type: expected wasm file but got other\n"); + goto fail2; + } + /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file, wasm_file_size, error_buf, sizeof(error_buf)))) { diff --git a/wamr-sdk/app/libc-builtin-sysroot/include/pthread.h b/wamr-sdk/app/libc-builtin-sysroot/include/pthread.h index 3084144578..71b7fce8c4 100644 --- a/wamr-sdk/app/libc-builtin-sysroot/include/pthread.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/pthread.h @@ -6,6 +6,10 @@ #ifndef _WAMR_LIB_PTHREAD_H #define _WAMR_LIB_PTHREAD_H +#ifdef __cplusplus +extern "C" { +#endif + #include /* Data type define of pthread, mutex, cond and key */ @@ -58,4 +62,8 @@ void *pthread_getspecific(pthread_key_t key); int pthread_key_delete(pthread_key_t key); +#ifdef __cplusplus +} +#endif + #endif /* end of _WAMR_LIB_PTHREAD_H */