From 15139d2bb8a85d4a4d79d9eaf0c897b7b5f39c9e Mon Sep 17 00:00:00 2001 From: Zzzabiyaka <79576401+Zzzabiyaka@users.noreply.github.com> Date: Wed, 26 Apr 2023 02:16:29 +0100 Subject: [PATCH 01/14] CI: Add ubsan checks to samples/wasm-c-api (#2147) This PR adds ubsan checks with no alignment enabled to basic CI tests for samples/wasm-c-api. Co-authored-by: Maksim Litskevich --- .github/workflows/compilation_on_android_ubuntu.yml | 10 +++++++--- samples/wasm-c-api/CMakeLists.txt | 11 ++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index aa366833b..0266a73de 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -338,7 +338,9 @@ jobs: ] runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: + sanitizer: ["", "ubsan"] make_options: [ # Running mode $AOT_BUILD_OPTIONS, @@ -363,6 +365,7 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} - os: ubuntu-22.04 llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} + steps: - name: checkout uses: actions/checkout@v3 @@ -395,15 +398,16 @@ jobs: if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) run: | mkdir build && cd build - cmake .. + cmake -DSANITIZER="${{matrix.sanitizer}}" .. cmake --build . --config Release --parallel 4 working-directory: wamr-compiler - name: Build Sample [wasm-c-api] run: | - cmake -S . -B build ${{ matrix.make_options }} + VERBOSE=1 + cmake -S . -B build ${{ matrix.make_options }} -DSANITIZER="${{matrix.sanitizer}}" cmake --build build --config Release --parallel 4 - ctest --test-dir build + ctest --test-dir build --output-on-failure working-directory: samples/wasm-c-api build_samples_others: diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index e2be3b8f4..c528fe16d 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -24,7 +24,7 @@ if (APPLE) add_definitions(-DBH_PLATFORM_DARWIN) endif () -# Resetdefault linker flags +# Reset default linker flags set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") @@ -87,6 +87,15 @@ endif() set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +if (NOT DEFINED SANITIZER) + set(SANITIZER "") +elseif (SANITIZER STREQUAL "ubsan") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O2 -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=alignment" ) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") +elseif (NOT (SANITIZER STREQUAL "") ) + message(SEND_ERROR "Unsupported sanitizer: ${SANITIZER}") +endif() + add_library(vmlib STATIC ${WAMR_RUNTIME_LIB_SOURCE}) if (MSVC) target_compile_definitions(vmlib PRIVATE WASM_API_EXTERN=) From 5c497e5a1447995eaed54359489b1b25cac136e8 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 26 Apr 2023 18:13:11 +0800 Subject: [PATCH 02/14] Fix ems allocator unaligned memory access on riscv64 (#2140) Make `hmu_tree_node` struct packed and add 4 padding bytes before `kfc_tree_root_buf` field in `gc_heap_struct` struct to ensure the `left/right/parent` fields in `hmu_tree_node` are 8-byte aligned on the 64-bit target which doesn't support unaligned memory access. Fix the issue reported in #2136. --- core/shared/mem-alloc/ems/ems_alloc.c | 22 +++++---- core/shared/mem-alloc/ems/ems_gc_internal.h | 50 +++++++++++++++++++-- core/shared/mem-alloc/ems/ems_kfc.c | 38 ++++++++++++---- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/core/shared/mem-alloc/ems/ems_alloc.c b/core/shared/mem-alloc/ems/ems_alloc.c index 6f03fa58f..5c2a628a2 100644 --- a/core/shared/mem-alloc/ems/ems_alloc.c +++ b/core/shared/mem-alloc/ems/ems_alloc.c @@ -25,7 +25,7 @@ static bool remove_tree_node(gc_heap_t *heap, hmu_tree_node_t *p) { hmu_tree_node_t *q = NULL, **slot = NULL, *parent; - hmu_tree_node_t *root = &heap->kfc_tree_root; + hmu_tree_node_t *root = heap->kfc_tree_root; gc_uint8 *base_addr = heap->base_addr; gc_uint8 *end_addr = base_addr + heap->current_size; @@ -38,13 +38,17 @@ remove_tree_node(gc_heap_t *heap, hmu_tree_node_t *p) goto fail; } - /* get the slot which holds pointer to node p*/ + /* get the slot which holds pointer to node p */ if (p == p->parent->right) { - slot = &p->parent->right; + /* Don't use `slot = &p->parent->right` to avoid compiler warning */ + slot = (hmu_tree_node_t **)((uint8 *)p->parent + + offsetof(hmu_tree_node_t, right)); } else if (p == p->parent->left) { - /* p should be a child of its parent*/ - slot = &p->parent->left; + /* p should be a child of its parent */ + /* Don't use `slot = &p->parent->left` to avoid compiler warning */ + slot = (hmu_tree_node_t **)((uint8 *)p->parent + + offsetof(hmu_tree_node_t, left)); } else { goto fail; @@ -241,7 +245,7 @@ gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) node->left = node->right = node->parent = NULL; /* find proper node to link this new node to */ - root = &heap->kfc_tree_root; + root = heap->kfc_tree_root; tp = root; bh_assert(tp->size < size); while (1) { @@ -289,6 +293,7 @@ alloc_hmu(gc_heap_t *heap, gc_size_t size) uint32 node_idx = 0, init_node_idx = 0; hmu_tree_node_t *root = NULL, *tp = NULL, *last_tp = NULL; hmu_t *next, *rest; + uintptr_t tp_ret; bh_assert(gci_is_heap_valid(heap)); bh_assert(size > 0 && !(size & 7)); @@ -354,7 +359,7 @@ alloc_hmu(gc_heap_t *heap, gc_size_t size) } /* need to find a node in tree*/ - root = &heap->kfc_tree_root; + root = heap->kfc_tree_root; /* find the best node*/ bh_assert(root); @@ -402,7 +407,8 @@ alloc_hmu(gc_heap_t *heap, gc_size_t size) heap->highmark_size = heap->current_size - heap->total_free_size; hmu_set_size((hmu_t *)last_tp, size); - return (hmu_t *)last_tp; + tp_ret = (uintptr_t)last_tp; + return (hmu_t *)tp_ret; } return NULL; diff --git a/core/shared/mem-alloc/ems/ems_gc_internal.h b/core/shared/mem-alloc/ems/ems_gc_internal.h index 39b1ff8f1..e1ff9d61d 100644 --- a/core/shared/mem-alloc/ems/ems_gc_internal.h +++ b/core/shared/mem-alloc/ems/ems_gc_internal.h @@ -204,13 +204,47 @@ set_hmu_normal_node_next(hmu_normal_node_t *node, hmu_normal_node_t *next) } } +/** + * Define hmu_tree_node as a packed struct, since it is at the 4-byte + * aligned address and the size of hmu_head is 4, so in 64-bit target, + * the left/right/parent fields will be at 8-byte aligned address, + * we can access them directly. + */ +#if UINTPTR_MAX == UINT64_MAX +#if defined(_MSC_VER) +__pragma(pack(push, 1)); +#define __attr_packed +#elif defined(__GNUC__) || defined(__clang__) +#define __attr_packed __attribute__((packed)) +#else +#error "packed attribute isn't used to define struct hmu_tree_node" +#endif +#else /* else of UINTPTR_MAX == UINT64_MAX */ +#define __attr_packed +#endif + typedef struct hmu_tree_node { hmu_t hmu_header; - gc_size_t size; struct hmu_tree_node *left; struct hmu_tree_node *right; struct hmu_tree_node *parent; -} hmu_tree_node_t; + gc_size_t size; +} __attr_packed hmu_tree_node_t; + +#if UINTPTR_MAX == UINT64_MAX +#if defined(_MSC_VER) +__pragma(pack(pop)); +#endif +#endif + +bh_static_assert(sizeof(hmu_tree_node_t) == 8 + 3 * sizeof(void *)); +bh_static_assert(offsetof(hmu_tree_node_t, left) == 4); + +#define ASSERT_TREE_NODE_ALIGNED_ACCESS(tree_node) \ + do { \ + bh_assert((((uintptr_t)&tree_node->left) & (sizeof(uintptr_t) - 1)) \ + == 0); \ + } while (0) typedef struct gc_heap_struct { /* for double checking*/ @@ -223,8 +257,16 @@ typedef struct gc_heap_struct { hmu_normal_list_t kfc_normal_list[HMU_NORMAL_NODE_CNT]; - /* order in kfc_tree is: size[left] <= size[cur] < size[right]*/ - hmu_tree_node_t kfc_tree_root; +#if UINTPTR_MAX == UINT64_MAX + /* make kfc_tree_root_buf 4-byte aligned and not 8-byte aligned, + so kfc_tree_root's left/right/parent fields are 8-byte aligned + and we can access them directly */ + uint32 __padding; +#endif + uint8 kfc_tree_root_buf[sizeof(hmu_tree_node_t)]; + /* point to kfc_tree_root_buf, the order in kfc_tree is: + size[left] <= size[cur] < size[right] */ + hmu_tree_node_t *kfc_tree_root; /* whether heap is corrupted, e.g. the hmu nodes are modified by user */ diff --git a/core/shared/mem-alloc/ems/ems_kfc.c b/core/shared/mem-alloc/ems/ems_kfc.c index fe7732533..80d202679 100644 --- a/core/shared/mem-alloc/ems/ems_kfc.c +++ b/core/shared/mem-alloc/ems/ems_kfc.c @@ -27,7 +27,7 @@ gc_init_internal(gc_heap_t *heap, char *base_addr, gc_size_t heap_max_size) heap->total_free_size = heap->current_size; heap->highmark_size = 0; - root = &heap->kfc_tree_root; + root = heap->kfc_tree_root = (hmu_tree_node_t *)heap->kfc_tree_root_buf; memset(root, 0, sizeof *root); root->size = sizeof *root; hmu_set_ut(&root->hmu_header, HMU_FC); @@ -38,6 +38,9 @@ gc_init_internal(gc_heap_t *heap, char *base_addr, gc_size_t heap_max_size) hmu_set_ut(&q->hmu_header, HMU_FC); hmu_set_size(&q->hmu_header, heap->current_size); + ASSERT_TREE_NODE_ALIGNED_ACCESS(q); + ASSERT_TREE_NODE_ALIGNED_ACCESS(root); + hmu_mark_pinuse(&q->hmu_header); root->right = q; q->parent = root; @@ -165,6 +168,7 @@ gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size) intptr_t offset = (uint8 *)base_addr_new - (uint8 *)heap->base_addr; hmu_t *cur = NULL, *end = NULL; hmu_tree_node_t *tree_node; + uint8 **p_left, **p_right, **p_parent; gc_size_t heap_max_size, size; if ((((uintptr_t)pool_buf_new) & 7) != 0) { @@ -188,9 +192,18 @@ gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size) } heap->base_addr = (uint8 *)base_addr_new; - adjust_ptr((uint8 **)&heap->kfc_tree_root.left, offset); - adjust_ptr((uint8 **)&heap->kfc_tree_root.right, offset); - adjust_ptr((uint8 **)&heap->kfc_tree_root.parent, offset); + + ASSERT_TREE_NODE_ALIGNED_ACCESS(heap->kfc_tree_root); + + p_left = (uint8 **)((uint8 *)heap->kfc_tree_root + + offsetof(hmu_tree_node_t, left)); + p_right = (uint8 **)((uint8 *)heap->kfc_tree_root + + offsetof(hmu_tree_node_t, right)); + p_parent = (uint8 **)((uint8 *)heap->kfc_tree_root + + offsetof(hmu_tree_node_t, parent)); + adjust_ptr(p_left, offset); + adjust_ptr(p_right, offset); + adjust_ptr(p_parent, offset); cur = (hmu_t *)heap->base_addr; end = (hmu_t *)((char *)heap->base_addr + heap->current_size); @@ -206,12 +219,21 @@ gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size) if (hmu_get_ut(cur) == HMU_FC && !HMU_IS_FC_NORMAL(size)) { tree_node = (hmu_tree_node_t *)cur; - adjust_ptr((uint8 **)&tree_node->left, offset); - adjust_ptr((uint8 **)&tree_node->right, offset); - if (tree_node->parent != &heap->kfc_tree_root) + + ASSERT_TREE_NODE_ALIGNED_ACCESS(tree_node); + + p_left = (uint8 **)((uint8 *)tree_node + + offsetof(hmu_tree_node_t, left)); + p_right = (uint8 **)((uint8 *)tree_node + + offsetof(hmu_tree_node_t, right)); + p_parent = (uint8 **)((uint8 *)tree_node + + offsetof(hmu_tree_node_t, parent)); + adjust_ptr(p_left, offset); + adjust_ptr(p_right, offset); + if (tree_node->parent != heap->kfc_tree_root) /* The root node belongs to heap structure, it is fixed part and isn't changed. */ - adjust_ptr((uint8 **)&tree_node->parent, offset); + adjust_ptr(p_parent, offset); } cur = (hmu_t *)((char *)cur + size); } From c1723b8f3ebe79b357a36e82059468619f050993 Mon Sep 17 00:00:00 2001 From: Georgii Rylov Date: Wed, 26 Apr 2023 14:03:02 +0100 Subject: [PATCH 03/14] libc_wasi_wrapper.c: Fix min func issue for size_t < 8 bytes on some platforms (#2152) According to the 1999 ISO C standard (C99), size_t is an unsigned integer type of at least 16 bit (see sections 7.17 and 7.18.3), it may be uint32 in 32-bit platforms: https://en.cppreference.com/w/cpp/types/size_t Calling function `size_t min(size_t, size_t)` with two uint64 arguments may get invalid result. Co-authored-by: Georgii Rylov --- .../libraries/libc-wasi/libc_wasi_wrapper.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index ab2808c6e..afb11925a 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -56,8 +56,14 @@ typedef struct WASIContext *wasi_ctx_t; wasi_ctx_t wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); -static inline size_t -min(size_t a, size_t b) +static inline uint64_t +min_uint64(uint64_t a, uint64_t b) +{ + return a > b ? b : a; +} + +static inline uint32_t +min_uint32(uint32_t a, uint32_t b) { return a > b ? b : a; } @@ -962,7 +968,7 @@ get_timeout_for_poll_oneoff(const wasi_subscription_t *in, const __wasi_subscription_t *s = &in[i]; if (s->u.type == __WASI_EVENTTYPE_CLOCK && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) { - timeout = min(timeout, s->u.u.clock.timeout); + timeout = min_uint64(timeout, s->u.u.clock.timeout); } } return timeout; @@ -1016,8 +1022,8 @@ execute_interruptible_poll_oneoff( while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) { /* update timeout for clock subscription events */ - update_clock_subscription_data(in_copy, nsubscriptions, - min(time_quant, timeout - elapsed)); + update_clock_subscription_data( + in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed)); err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions, nevents); elapsed += time_quant; @@ -1999,7 +2005,7 @@ copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin, * only copy the amount in the app buffer. Otherwise, we fill the iovec * buffer and reduce size to copy on the next iteration */ - size_to_copy_into_iovec = min(data->buf_len, size_to_copy); + size_to_copy_into_iovec = min_uint32(data->buf_len, size_to_copy); native_addr = (void *)addr_app_to_native(data->buf_offset); bh_memcpy_s(native_addr, size_to_copy_into_iovec, buf, From ed6b8efade779e08183497d0a6575cb2a537342f Mon Sep 17 00:00:00 2001 From: ayakoakasaka <98828539+ayakoakasaka@users.noreply.github.com> Date: Thu, 27 Apr 2023 02:19:18 +0200 Subject: [PATCH 04/14] Avoid re-installing if Tensorflow is already installed for WASI-NN (#2148) Since the Tensorflow library is already installed in many cases(especially in the case of the embedded system), move the installation code to find_package. --- build-scripts/runtime_lib.cmake | 20 --------- .../wasi-nn/cmake/Findtensorflow_lite.cmake | 41 +++++++++++++++++++ core/iwasm/libraries/wasi-nn/wasi_nn.cmake | 5 +++ 3 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 80ca85c25..6931ece74 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -101,26 +101,6 @@ if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1) endif () if (WAMR_BUILD_WASI_NN EQUAL 1) - if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") - execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh - RESULT_VARIABLE TENSORFLOW_RESULT - ) - else () - message("Tensorflow is already downloaded.") - endif() - set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") - - if (WASI_NN_ENABLE_GPU EQUAL 1) - # Tensorflow specific: - # * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite - set (TFLITE_ENABLE_GPU ON) - endif () - - include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include) - include_directories (${TENSORFLOW_SOURCE_DIR}) - add_subdirectory( - "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite" - "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL) include (${IWASM_DIR}/libraries/wasi-nn/wasi_nn.cmake) endif () diff --git a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake new file mode 100644 index 000000000..bbeac3b14 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake @@ -0,0 +1,41 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + + +find_library(TENSORFLOW_LITE + NAMES tensorflow-lite +) + +if(NOT EXISTS ${TENSORFLOW_LITE}) + if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") + execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh + RESULT_VARIABLE TENSORFLOW_RESULT + ) + else () + message("Tensorflow is already downloaded.") + endif() + set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") + + if (WASI_NN_ENABLE_GPU EQUAL 1) + # Tensorflow specific: + # * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite + set (TFLITE_ENABLE_GPU ON) + endif () + + include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include) + include_directories (${TENSORFLOW_SOURCE_DIR}) + add_subdirectory( + "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite" + "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL) + +else() + find_path(TENSORFLOW_LITE_INCLUDE_DIR + NAMES tensorflow/lite/interpreter.h + ) + find_path(FLATBUFFER_INCLUDE_DIR + NAMES flatbuffers/flatbuffers.h + ) + include_directories (${TENSORFLOW_LITE_INCLUDE_DIR}) + include_directories (${FLATBUFFER_INCLUDE_DIR}) +endif() + diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn.cmake b/core/iwasm/libraries/wasi-nn/wasi_nn.cmake index 1bb53c086..019782c2e 100644 --- a/core/iwasm/libraries/wasi-nn/wasi_nn.cmake +++ b/core/iwasm/libraries/wasi-nn/wasi_nn.cmake @@ -1,6 +1,11 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +# Find tensorflow-lite +find_package(tensorflow_lite REQUIRED) + set (WASI_NN_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories (${WASI_NN_DIR}) From 247a49c4fde931805aed3fb21be889748e05e6e6 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Thu, 27 Apr 2023 18:31:39 +0800 Subject: [PATCH 05/14] CI: More precise trigger paths for github actions (#2157) Only trigger the necessary github actions when a CI file is changed. --- .github/workflows/compilation_on_android_ubuntu.yml | 6 ++++-- .github/workflows/compilation_on_macos.yml | 6 ++++-- .github/workflows/compilation_on_nuttx.yml | 4 ++-- .github/workflows/compilation_on_sgx.yml | 6 ++++-- .github/workflows/compilation_on_windows.yml | 4 ++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 0266a73de..2a57f6219 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -10,7 +10,8 @@ on: - opened - synchronize paths: - - ".github/**" + - ".github/workflows/build_llvm_libraries.yml" + - ".github/workflows/compilation_on_android_ubuntu.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" @@ -26,7 +27,8 @@ on: - main - "dev/**" paths: - - ".github/**" + - ".github/workflows/build_llvm_libraries.yml" + - ".github/workflows/compilation_on_android_ubuntu.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index ec81773f4..aaa97d038 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -10,7 +10,8 @@ on: - opened - synchronize paths: - - ".github/**" + - ".github/workflows/build_llvm_libraries.yml" + - ".github/workflows/compilation_on_macos.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" @@ -26,7 +27,8 @@ on: - main - "dev/**" paths: - - ".github/**" + - ".github/workflows/build_llvm_libraries.yml" + - ".github/workflows/compilation_on_macos.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index c8553a123..f338c8dea 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -10,7 +10,7 @@ on: - opened - synchronize paths: - - ".github/**" + - ".github/workflows/compilation_on_nuttx.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" @@ -26,7 +26,7 @@ on: - main - "dev/**" paths: - - ".github/**" + - ".github/workflows/compilation_on_nuttx.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" diff --git a/.github/workflows/compilation_on_sgx.yml b/.github/workflows/compilation_on_sgx.yml index 985674f6e..f17261118 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -10,7 +10,8 @@ on: - opened - synchronize paths: - - ".github/**" + - ".github/workflows/build_llvm_libraries.yml" + - ".github/workflows/compilation_on_sgx.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" @@ -26,7 +27,8 @@ on: - main - "dev/**" paths: - - ".github/**" + - ".github/workflows/build_llvm_libraries.yml" + - ".github/workflows/compilation_on_sgx.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 1cf06d626..0d38e8ae5 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -10,7 +10,7 @@ on: - opened - synchronize paths: - - ".github/**" + - ".github/workflows/compilation_on_windows.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" @@ -26,7 +26,7 @@ on: - main - "dev/**" paths: - - ".github/**" + - ".github/workflows/compilation_on_windows.yml" - "build-scripts/**" - "core/**" - "!core/deps/**" From 2b896c80ef22552f5062a57fcd4d798da9ec41f9 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 28 Apr 2023 14:56:44 +0900 Subject: [PATCH 06/14] wamrc: Add --stack-usage option (#2158) --- core/iwasm/compilation/aot_llvm.c | 6 +- core/iwasm/compilation/aot_llvm.h | 1 + core/iwasm/compilation/aot_llvm_extra2.cpp | 108 +++++++++++++++++++++ core/iwasm/compilation/aot_llvm_extra2.h | 17 ++++ core/iwasm/include/aot_export.h | 1 + wamr-compiler/main.c | 5 + 6 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 core/iwasm/compilation/aot_llvm_extra2.cpp create mode 100644 core/iwasm/compilation/aot_llvm_extra2.h diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 27550560f..dc3fe7f59 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -4,6 +4,7 @@ */ #include "aot_llvm.h" +#include "aot_llvm_extra2.h" #include "aot_compiler.h" #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" @@ -2055,9 +2056,10 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) code_model = LLVMCodeModelSmall; /* Create the target machine */ - if (!(comp_ctx->target_machine = LLVMCreateTargetMachine( + if (!(comp_ctx->target_machine = LLVMCreateTargetMachineWithOpts( target, triple_norm, cpu, features, opt_level, - LLVMRelocStatic, code_model))) { + LLVMRelocStatic, code_model, false, + option->stack_usage_file))) { aot_set_last_error("create LLVM target machine failed."); goto fail; } diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index b982e8083..2a1564019 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -415,6 +415,7 @@ typedef struct AOTCompOption { uint32 stack_bounds_checks; char **custom_sections; uint32 custom_sections_count; + const char *stack_usage_file; } AOTCompOption, *aot_comp_option_t; bool diff --git a/core/iwasm/compilation/aot_llvm_extra2.cpp b/core/iwasm/compilation/aot_llvm_extra2.cpp new file mode 100644 index 000000000..9bd44bbff --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_extra2.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c)2023 YAMAMOTO Takashi. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include + +#include "bh_assert.h" + +#include "aot_llvm_extra2.h" + +static llvm::Optional +convert(LLVMRelocMode reloc_mode) +{ + switch (reloc_mode) { + case LLVMRelocDefault: + return llvm::None; + case LLVMRelocStatic: + return llvm::Reloc::Static; + case LLVMRelocPIC: + return llvm::Reloc::PIC_; + case LLVMRelocDynamicNoPic: + return llvm::Reloc::DynamicNoPIC; + case LLVMRelocROPI: + return llvm::Reloc::ROPI; + case LLVMRelocRWPI: + return llvm::Reloc::RWPI; + case LLVMRelocROPI_RWPI: + return llvm::Reloc::ROPI_RWPI; + } + bh_assert(0); + return llvm::None; +} + +static llvm::CodeGenOpt::Level +convert(LLVMCodeGenOptLevel opt_level) +{ + switch (opt_level) { + case LLVMCodeGenLevelNone: + return llvm::CodeGenOpt::None; + case LLVMCodeGenLevelLess: + return llvm::CodeGenOpt::Less; + case LLVMCodeGenLevelDefault: + return llvm::CodeGenOpt::Default; + case LLVMCodeGenLevelAggressive: + return llvm::CodeGenOpt::Aggressive; + } + bh_assert(0); + return llvm::CodeGenOpt::None; +} + +static llvm::Optional +convert(LLVMCodeModel code_model, bool *jit) +{ + *jit = false; + switch (code_model) { + case LLVMCodeModelDefault: + return llvm::None; + case LLVMCodeModelJITDefault: + *jit = true; + return llvm::None; + case LLVMCodeModelTiny: + return llvm::CodeModel::Tiny; + case LLVMCodeModelSmall: + return llvm::CodeModel::Small; + case LLVMCodeModelKernel: + return llvm::CodeModel::Kernel; + case LLVMCodeModelMedium: + return llvm::CodeModel::Medium; + case LLVMCodeModelLarge: + return llvm::CodeModel::Large; + } + bh_assert(0); + return llvm::None; +} + +LLVMTargetMachineRef +LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple, + const char *cpu, const char *features, + LLVMCodeGenOptLevel opt_level, + LLVMRelocMode reloc_mode, + LLVMCodeModel code_model, + bool EmitStackSizeSection, + const char *StackUsageOutput) +{ + llvm::TargetOptions opts; + + // -fstack-size-section equiv + // emit it to ".stack_sizes" section in case of ELF + // you can read it with "llvm-readobj --stack-sizes" + opts.EmitStackSizeSection = EmitStackSizeSection; + + // -fstack-usage equiv + if (StackUsageOutput != NULL) { + opts.StackUsageOutput = StackUsageOutput; + } + + auto target = reinterpret_cast(ctarget); + auto rm = convert(reloc_mode); + auto ol = convert(opt_level); + bool jit; + auto cm = convert(code_model, &jit); + auto targetmachine = target->createTargetMachine(triple, cpu, features, + opts, rm, cm, ol, jit); + return reinterpret_cast(targetmachine); +} diff --git a/core/iwasm/compilation/aot_llvm_extra2.h b/core/iwasm/compilation/aot_llvm_extra2.h new file mode 100644 index 000000000..ef99622a4 --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_extra2.h @@ -0,0 +1,17 @@ +/* + * Copyright (c)2023 YAMAMOTO Takashi. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +LLVM_C_EXTERN_C_BEGIN +LLVMTargetMachineRef +LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple, + const char *cpu, const char *features, + LLVMCodeGenOptLevel opt_level, + LLVMRelocMode reloc_mode, + LLVMCodeModel code_model, + bool EmitStackSizeSection, + const char *StackUsageOutput); +LLVM_C_EXTERN_C_END diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index 792a4baa9..e58873bfd 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -63,6 +63,7 @@ typedef struct AOTCompOption { uint32_t stack_bounds_checks; char **custom_sections; uint32_t custom_sections_count; + const char *stack_usage_file; } AOTCompOption, *aot_comp_option_t; bool diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index f185a17b7..bd8691c4b 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -42,6 +42,8 @@ print_help() printf(" if the option is set:\n"); printf(" (1) it is always enabled when `--bounds-checks` is enabled,\n"); printf(" (2) else it is enabled/disabled according to the option value\n"); + printf(" --stack-usage= Generate a stack-usage file.\n"); + printf(" Similarly to `clang -fstack-usage`.\n"); printf(" --format= Specifies the format of the output file\n"); printf(" The format supported:\n"); printf(" aot (default) AoT file\n"); @@ -204,6 +206,9 @@ main(int argc, char *argv[]) else if (!strncmp(argv[0], "--stack-bounds-checks=", 22)) { option.stack_bounds_checks = (atoi(argv[0] + 22) == 1) ? 1 : 0; } + else if (!strncmp(argv[0], "--stack-usage=", 14)) { + option.stack_usage_file = argv[0] + 14; + } else if (!strncmp(argv[0], "--format=", 9)) { if (argv[0][9] == '\0') PRINT_HELP_AND_EXIT(); From 0166bfb5cd64fe0c5ebd8e0b3bfaaae7ff7dce1a Mon Sep 17 00:00:00 2001 From: Elis Byberi Date: Tue, 2 May 2023 03:12:49 +0200 Subject: [PATCH 07/14] Fix URL in language-bindings/python/README.md (#2166) Fix "WAMR API" and "WASM-C-API" URLs. --- language-bindings/python/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/language-bindings/python/README.md b/language-bindings/python/README.md index 9e504a9c0..ec82ee191 100644 --- a/language-bindings/python/README.md +++ b/language-bindings/python/README.md @@ -30,5 +30,5 @@ import wamr.wasmcapi.ffi as ffi For more information: -* [WAMR API](./wamr_api) -* [WASM-C-API](./wasm_c_api) +* [WAMR API](./wamr-api) +* [WASM-C-API](./wasm-c-api) From 65f64958f5568e48387456276fc2b0311d3b53cb Mon Sep 17 00:00:00 2001 From: Elis Byberi Date: Tue, 2 May 2023 03:13:49 +0200 Subject: [PATCH 08/14] Fix URL in embed_wamr.md (#2165) Fix "Embed WAMR into Python" URL. --- doc/embed_wamr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index ae3fe4181..050384027 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -1,7 +1,7 @@ Embedding WAMR guideline ===================================== -**Note**: This document is about how to embed WAMR into C/C++ host applications, for other languages, please refer to: [Embed WAMR into Python](../language-bindings/go), [Embed WAMR into Go](../language-bindings/go). +**Note**: This document is about how to embed WAMR into C/C++ host applications, for other languages, please refer to: [Embed WAMR into Python](../language-bindings/python), [Embed WAMR into Go](../language-bindings/go). All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files. From 47fcb8506f7f1ee66fadeef4de8a3481b44633a7 Mon Sep 17 00:00:00 2001 From: Elis Byberi Date: Wed, 3 May 2023 08:21:34 +0200 Subject: [PATCH 09/14] Fix URL in README.md (#2168) Fix "Samples" URL. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d7d4778b..8cbdcf495 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ **[Guide](https://wamr.gitbook.io/)**  **[Website](https://bytecodealliance.github.io/wamr.dev)**  **[Chat](https://bytecodealliance.zulipchat.com/#narrow/stream/290350-wamr)** -[Build WAMR](./doc/build_wamr.md) | [Build AOT Compiler](./wamr-compiler/README.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export Native API](./doc/export_native_api.md) | [Build Wasm Apps](./doc/build_wasm_app.md) | [Samples](./README.md#samples) +[Build WAMR](./doc/build_wamr.md) | [Build AOT Compiler](./wamr-compiler/README.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export Native API](./doc/export_native_api.md) | [Build Wasm Apps](./doc/build_wasm_app.md) | [Samples](./samples/README.md) WebAssembly Micro Runtime (WAMR) is a lightweight standalone WebAssembly (Wasm) runtime with small footprint, high performance and highly configurable features for applications cross from embedded, IoT, edge to Trusted Execution Environment (TEE), smart contract, cloud native and so on. It includes a few parts as below: - [**VMcore**](./core/iwasm/): A set of runtime libraries for loading and running Wasm modules. It supports several execution modes including interpreter, Ahead-of-Time compilation(AoT) and Just-in-Time compilation (JIT). The WAMR supports two JIT tiers - Fast JIT, LLVM JIT, and dynamic tier-up from Fast JIT to LLVM JIT. From 71d43f3ca18b96c983d0fa8ca45ea658d6f9ee4a Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Fri, 5 May 2023 03:20:05 +0200 Subject: [PATCH 10/14] Return error when exception was raised after main thread finishes (#2169) Currently, if a thread is spawned and raises an exception after the main thread has finished, iwasm returns with success instead of returning 1 (i.e. error). Since wasm_runtime_get_wasi_exit_code waits for all threads to finish and only returns the wasi exit code, this PR performs the exception check again and returns error if an exception was raised. --- .../test/trap_after_main_thread_finishes.c | 44 +++++++++++++++++++ .../test/trap_after_main_thread_finishes.json | 3 ++ product-mini/platforms/posix/main.c | 6 ++- product-mini/platforms/windows/main.c | 6 ++- 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c new file mode 100644 index 000000000..69e125d40 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef __wasi__ +#error This example only compiles to WASM/WASI target +#endif + +#include +#include +#include + +#include "wasi_thread_start.h" + +enum CONSTANTS { + SECOND = 1000 * 1000 * 1000, /* 1 second */ + TIMEOUT = 1LL * SECOND +}; + +typedef struct { + start_args_t base; +} shared_t; + +void +__wasi_thread_start_C(int thread_id, int *start_arg) +{ + /* Wait so that the exception is raised after the main thread has finished + * already */ + __builtin_wasm_memory_atomic_wait32(NULL, 0, TIMEOUT); + __builtin_trap(); +} + +int +main(int argc, char **argv) +{ + shared_t data = { 0 }; + + assert(start_args_init(&data.base)); + int thread_id = __wasi_thread_spawn(&data); + assert(thread_id > 0 && "Thread creation failed"); + + return EXIT_SUCCESS; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json new file mode 100644 index 000000000..9dc1e30d2 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json @@ -0,0 +1,3 @@ +{ + "exit_code": 1 +} diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 8727ed389..2e96ccddd 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -745,8 +745,12 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* propagate wasi exit code. */ + /* wait for threads to finish and propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); + if (wasm_runtime_get_exception(wasm_module_inst)) { + /* got an exception in spawned thread */ + ret = 1; + } } #endif diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 05647b5db..26fa7dcc9 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -549,8 +549,12 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* propagate wasi exit code. */ + /* wait for threads to finish and propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); + if (wasm_runtime_get_exception(wasm_module_inst)) { + /* got an exception in spawned thread */ + ret = 1; + } } #endif From 5a23ae465c58e3613e9dda1f676df52d93aa1356 Mon Sep 17 00:00:00 2001 From: Christof Petig <33882057+cpetig@users.noreply.github.com> Date: Fri, 5 May 2023 04:01:58 +0200 Subject: [PATCH 11/14] Fix three multi-threading and wasm-c-api-imports issues (#2173) Fix issue reported in #2172: wasm-c-api `wasm_func_call` may use a wrong exec_env when multi-threading is enabled, with error "invalid exec env" reported Fix issue reported in #2149: main instance's `c_api_func_imports` are not passed to the counterpart of new thread's instance in wasi-threads mode Fix issue of invalid size calculated to copy `c_api_func_imports` in pthread mode And refactor the code to use `wasm_cluster_dup_c_api_imports` to copy the `c_api_func_imports` to new thread for wasi-threads mode and pthread mode. --- core/iwasm/common/wasm_c_api.c | 15 +++++- .../lib-pthread/lib_pthread_wrapper.c | 41 +--------------- .../lib_wasi_threads_wrapper.c | 3 ++ .../libraries/thread-mgr/thread_manager.c | 49 +++++++++++++++++++ .../libraries/thread-mgr/thread_manager.h | 5 ++ 5 files changed, 73 insertions(+), 40 deletions(-) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 639980ca2..7b8cf4779 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -23,6 +23,9 @@ #if WASM_ENABLE_WASM_CACHE != 0 #include #endif +#if WASM_ENABLE_THREAD_MGR != 0 +#include "thread_manager.h" +#endif /* * Thread Model: @@ -3315,7 +3318,17 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params, goto failed; } - exec_env = wasm_runtime_get_exec_env_singleton(func->inst_comm_rt); +#ifdef OS_ENABLE_HW_BOUND_CHECK + exec_env = wasm_runtime_get_exec_env_tls(); +#endif +#if WASM_ENABLE_THREAD_MGR != 0 + if (!exec_env) { + exec_env = wasm_clusters_search_exec_env(func->inst_comm_rt); + } +#endif + if (!exec_env) { + exec_env = wasm_runtime_get_exec_env_singleton(func->inst_comm_rt); + } if (!exec_env) { goto failed; } diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index fc82e969e..ae1fd94f7 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -594,45 +594,8 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); #endif - /* workaround about passing instantiate-linking information */ - { - CApiFuncImport *c_api_func_imports; - uint32 import_func_count = 0; - uint32 size_in_bytes = 0; - -#if WASM_ENABLE_INTERP != 0 - if (module_inst->module_type == Wasm_Module_Bytecode) { - new_c_api_func_imports = &( - ((WASMModuleInstance *)new_module_inst)->e->c_api_func_imports); - c_api_func_imports = - ((WASMModuleInstance *)module_inst)->e->c_api_func_imports; - import_func_count = ((WASMModule *)module)->import_function_count; - } -#endif -#if WASM_ENABLE_AOT != 0 - if (module_inst->module_type == Wasm_Module_AoT) { - AOTModuleInstanceExtra *e = - (AOTModuleInstanceExtra *)((AOTModuleInstance *)new_module_inst) - ->e; - new_c_api_func_imports = &(e->c_api_func_imports); - - e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e; - c_api_func_imports = e->c_api_func_imports; - - import_func_count = ((AOTModule *)module)->import_func_count; - } -#endif - - if (import_func_count != 0 && c_api_func_imports) { - size_in_bytes = sizeof(CApiFuncImport *) * import_func_count; - *new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes); - if (!(*new_c_api_func_imports)) - goto fail; - - bh_memcpy_s(*new_c_api_func_imports, size_in_bytes, - c_api_func_imports, size_in_bytes); - } - } + if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst))) + goto fail; if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode)))) goto fail; diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index 30d66076d..6b36c9073 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -96,6 +96,9 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) wasm_runtime_set_custom_data_internal( new_module_inst, wasm_runtime_get_custom_data(module_inst)); + if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst))) + goto thread_preparation_fail; + #if WASM_ENABLE_LIBC_WASI != 0 wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst); if (wasi_ctx) diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index bfb89c089..9303eb3f5 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -733,6 +733,55 @@ fail1: return -1; } +bool +wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, + const WASMModuleInstanceCommon *module_inst_src) +{ + /* workaround about passing instantiate-linking information */ + CApiFuncImport **new_c_api_func_imports = NULL; + CApiFuncImport *c_api_func_imports; + uint32 import_func_count = 0; + uint32 size_in_bytes = 0; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst_src->module_type == Wasm_Module_Bytecode) { + new_c_api_func_imports = + &(((WASMModuleInstance *)module_inst_dst)->e->c_api_func_imports); + c_api_func_imports = ((const WASMModuleInstance *)module_inst_src) + ->e->c_api_func_imports; + import_func_count = + ((WASMModule *)(((const WASMModuleInstance *)module_inst_src) + ->module)) + ->import_function_count; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst_src->module_type == Wasm_Module_AoT) { + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e; + new_c_api_func_imports = &(e->c_api_func_imports); + + e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e; + c_api_func_imports = e->c_api_func_imports; + + import_func_count = + ((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module)) + ->import_func_count; + } +#endif + + if (import_func_count != 0 && c_api_func_imports) { + size_in_bytes = sizeof(CApiFuncImport) * import_func_count; + *new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes); + if (!(*new_c_api_func_imports)) + return false; + + bh_memcpy_s(*new_c_api_func_imports, size_in_bytes, c_api_func_imports, + size_in_bytes); + } + return true; +} + #if WASM_ENABLE_DEBUG_INTERP != 0 WASMCurrentEnvStatus * wasm_cluster_create_exenv_status() diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 899a4cc21..2060869c2 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -74,6 +74,11 @@ wasm_cluster_destroy(WASMCluster *cluster); WASMCluster * wasm_exec_env_get_cluster(WASMExecEnv *exec_env); +/* Forward registered functions to a new thread */ +bool +wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, + const WASMModuleInstanceCommon *module_inst_src); + int32 wasm_cluster_create_thread(WASMExecEnv *exec_env, wasm_module_inst_t module_inst, bool alloc_aux_stack, From 89be5622a5776e5240253c7acde39a1794ae31bb Mon Sep 17 00:00:00 2001 From: ayakoakasaka <98828539+ayakoakasaka@users.noreply.github.com> Date: Fri, 5 May 2023 10:29:36 +0200 Subject: [PATCH 12/14] wasi-nn: Add external delegation to support several NPU/GPU (#2162) Add VX delegation as an external delegation of TFLite, so that several NPU/GPU (from VeriSilicon, NXP, Amlogic) can be controlled via WASI-NN. Test Code can work with the X86 simulator. --- build-scripts/config_common.cmake | 7 ++ core/iwasm/libraries/wasi-nn/README.md | 13 +++ .../wasi-nn/src/wasi_nn_tensorflowlite.cpp | 43 +++++++- .../wasi-nn/test/Dockerfile.vx-delegate | 99 +++++++++++++++++++ 4 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 core/iwasm/libraries/wasi-nn/test/Dockerfile.vx-delegate diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 4b29ec869..ea8ad1f32 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -341,6 +341,13 @@ if (WAMR_BUILD_WASI_NN EQUAL 1) message (" WASI-NN: GPU enabled") add_definitions (-DWASI_NN_ENABLE_GPU=1) endif () + if (WAMR_BUILD_WASI_NN_ENABLE_EXT EQUAL 1) + message (" WASI-NN: External Delegation enabled") + add_definitions (-DWASI_NN_ENABLE_EXTERNAL_DELEGATE=1) + endif () + if (DEFINED WASI_NN_EXT_DELEGATE_PATH) + add_definitions (-DWASI_NN_EXT_DELEGATE_PATH="${WASI_NN_EXT_DELEGATE_PATH}") + endif () endif () if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1) diff --git a/core/iwasm/libraries/wasi-nn/README.md b/core/iwasm/libraries/wasi-nn/README.md index c5762618d..ac737c281 100644 --- a/core/iwasm/libraries/wasi-nn/README.md +++ b/core/iwasm/libraries/wasi-nn/README.md @@ -24,6 +24,7 @@ Build the runtime image for your execution target type. `EXECUTION_TYPE` can be: * `cpu` * `nvidia-gpu` +* `vx-delegate` ``` EXECUTION_TYPE=cpu @@ -71,6 +72,18 @@ docker run \ /assets/test_tensorflow.wasm ``` +* vx-delegate for NPU (x86 simulater) + +``` +docker run \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-vx-delegate \ + --dir=/assets \ + --env="TARGET=gpu" \ + /assets/test_tensorflow.wasm +``` + + + Requirements: * [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp index 0fe156381..dfd21787c 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -21,6 +21,10 @@ #include #endif +#if defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) +#include +#endif + /* Maximum number of graphs per WASM instance */ #define MAX_GRAPHS_PER_INST 10 /* Maximum number of graph execution context per WASM instance*/ @@ -42,6 +46,7 @@ typedef struct { uint32_t current_interpreters; Interpreter interpreters[MAX_GRAPH_EXEC_CONTEXTS_PER_INST]; korp_mutex g_lock; + TfLiteDelegate *delegate; } TFLiteContext; /* Utils */ @@ -194,18 +199,40 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, #if defined(WASI_NN_ENABLE_GPU) NN_WARN_PRINTF("GPU enabled."); // https://www.tensorflow.org/lite/performance/gpu - auto options = TfLiteGpuDelegateOptionsV2Default(); + TfLiteGpuDelegateOptionsV2 options = + TfLiteGpuDelegateOptionsV2Default(); options.inference_preference = TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED; options.inference_priority1 = TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY; - auto *delegate = TfLiteGpuDelegateV2Create(&options); + tfl_ctx->delegate = TfLiteGpuDelegateV2Create(&options); + if (tfl_ctx->delegate == NULL) { + NN_ERR_PRINTF("Error when generating GPU delegate."); + use_default = true; + return missing_memory; + } if (tfl_ctx->interpreters[*ctx] - .interpreter->ModifyGraphWithDelegate(delegate) + .interpreter->ModifyGraphWithDelegate(tfl_ctx->delegate) != kTfLiteOk) { NN_ERR_PRINTF("Error when enabling GPU delegate."); use_default = true; } +#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) + NN_WARN_PRINTF("external delegation enabled."); + TfLiteExternalDelegateOptions options = + TfLiteExternalDelegateOptionsDefault(WASI_NN_EXT_DELEGATE_PATH); + tfl_ctx->delegate = TfLiteExternalDelegateCreate(&options); + if (tfl_ctx->delegate == NULL) { + NN_ERR_PRINTF("Error when generating External delegate."); + use_default = true; + return missing_memory; + } + if (tfl_ctx->interpreters[*ctx] + .interpreter->ModifyGraphWithDelegate(tfl_ctx->delegate) + != kTfLiteOk) { + NN_ERR_PRINTF("Error when enabling External delegate."); + use_default = true; + } #else NN_WARN_PRINTF("GPU not enabled."); use_default = true; @@ -350,6 +377,8 @@ tensorflowlite_initialize(void **tflite_ctx) NN_ERR_PRINTF("Error while initializing the lock"); } + tfl_ctx->delegate = NULL; + *tflite_ctx = (void *)tfl_ctx; } @@ -364,6 +393,14 @@ tensorflowlite_destroy(void *tflite_ctx) */ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; + if (tfl_ctx->delegate != NULL) { +#if defined(WASI_NN_ENABLE_GPU) + TfLiteGpuDelegateV2Delete(tfl_ctx->delegate); +#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) + TfLiteExternalDelegateDelete(tfl_ctx->delegate); +#endif + } + NN_DBG_PRINTF("Freeing memory."); for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) { tfl_ctx->models[i].model.reset(); diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.vx-delegate b/core/iwasm/libraries/wasi-nn/test/Dockerfile.vx-delegate new file mode 100644 index 000000000..89cc1a9de --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.vx-delegate @@ -0,0 +1,99 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM ubuntu:20.04 AS base + +ENV DEBIAN_FRONTEND=noninteractive + + +RUN apt-get update && apt-get install -y \ + cmake build-essential git curl libssl-dev python3 + + +# Build TensorFlow Lite VX delegate default built for x86-64 simulator +WORKDIR /tmp +RUN git clone https://github.com/VeriSilicon/TIM-VX.git tim-vx +RUN git clone https://github.com/VeriSilicon/tflite-vx-delegate.git +RUN git clone https://github.com/tensorflow/tensorflow.git + + +# Build TIM-VX +WORKDIR /tmp/tim-vx/host_build +RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local ../ +RUN make -j$(grep -c ^processor /proc/cpuinfo) +RUN make install + +WORKDIR /tmp/tim-vx +#RUN mkdir -p prebuilt-sdk/x86_64_linux/lib/include +#RUN cp prebuilt-sdk/x86_64_linux/include/CL prebuilt-sdk/x86_64_linux/lib/include -fr + + +# Build TensorFlow Lite +WORKDIR /tmp/tensorflow/build +RUN cmake \ + -DBUILD_SHARED_LIBS=ON=on \ + -DTFLITE_ENABLE_RUY=on \ + -DTFLITE_ENABLE_NNAPI=off \ + -DTFLITE_ENABLE_XNNPACK=on \ + -DTFLITE_ENABLE_EXTERNAL_DELEGATE=on \ + ../tensorflow/lite/ +RUN make -j$(grep -c ^processor /proc/cpuinfo) +RUN make install +RUN cp --no-preserve=ownership -d lib*.so* /usr/local/lib +RUN cp -r --no-preserve=ownership -d flatbuffers/include/flatbuffers /usr/local/include +# install header files +RUN install -d /usr/local/include/tensorflow/lite && \ + cd /tmp/tensorflow/tensorflow/lite && \ + cp --parents \ + $(find . -name "*.h*") \ + /usr/local/include/tensorflow/lite +# install version.h from core +RUN install -d /usr/local/include/tensorflow/core/public && \ + cp /tmp/tensorflow/tensorflow/core/public/version.h /usr/local/include/tensorflow/core/public + + +# Build Vx Delegate default built for x86-64 simulator +WORKDIR /tmp/tflite-vx-delegate/build +RUN cmake \ + -DBUILD_SHARED_LIBS=ON \ + -DFETCHCONTENT_SOURCE_DIR_TENSORFLOW=/tmp/tensorflow \ + -DTFLITE_LIB_LOC=/usr/local/lib/libtensorflow-lite.so \ + -DTIM_VX_INSTALL=/usr/local \ + -DCMAKE_INSTALL_PREFIX=/usr/ \ + ../ +RUN make vx_delegate -j$(grep -c ^processor /proc/cpuinfo) +RUN make install +RUN cp --no-preserve=ownership -d lib*.so* /usr/lib +# install header files +RUN install -d /usr/local/include/tensorflow-lite-vx-delegate && \ + cd /tmp/tflite-vx-delegate/ && \ + cp --parents \ + $(find . -name "*.h*") \ + /usr/local/include/tensorflow-lite-vx-delegate + +ENV VIVANTE_SDK_DIR=/tmp/tim-vx/prebuilt-sdk/x86_64_linux/ +ENV VSIMULATOR_CONFIG=czl + +ENV LD_LIBRARY_PATH=/tmp/tim-vx/prebuilt-sdk/x86_64_linux/lib:/usr/local/lib:/lib/x86_64-linux-gnu/:/lib64/:/usr/lib:$LD_LIBRARY_PATH + + +# Build WASI-NN +WORKDIR /home/wamr + +COPY . . + +WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test/build + +RUN cmake \ + -DCMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH}:/usr/local/lib/ \ + -DCMAKE_INCLUDE_PATH=${CMAKE_INCLUDE_PATH}:/usr/local/include/ \ + -DWAMR_BUILD_WASI_NN=1 \ + -DWAMR_BUILD_WASI_NN_ENABLE_EXT=1 \ + -DWASI_NN_EXT_DELEGATE_PATH="/usr/lib/libvx_delegate.so" \ + .. + +RUN make -j $(grep -c ^processor /proc/cpuinfo) + +RUN cp /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm + +ENTRYPOINT [ "/run/iwasm" ] From 7f5d9d4f5e5eefe2ee32240f2e969d11097e54c8 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Mon, 8 May 2023 16:30:56 +0800 Subject: [PATCH 13/14] Update document for iwasm/wamrc dependent packages (#2183) --- product-mini/README.md | 13 ++++++++----- wamr-compiler/README.md | 13 +++++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/product-mini/README.md b/product-mini/README.md index 1499440e0..5847b2468 100644 --- a/product-mini/README.md +++ b/product-mini/README.md @@ -18,14 +18,17 @@ Note that all ESP-IDF toolchain files live under `$IDF_PATH/tools/cmake/`. ## Linux First of all please install the dependent packages. -Run command below in Ubuntu-18.04: - +Run command below in Ubuntu-22.04: ``` Bash -sudo apt install build-essential cmake g++-multilib libgcc-8-dev lib32gcc-8-dev +sudo apt install build-essential cmake g++-multilib libgcc-11-dev lib32gcc-11-dev ccache ``` -Or in Ubuntu-16.04: +Or in Ubuntu-20.04 ``` Bash -sudo apt install build-essential cmake g++-multilib libgcc-5-dev lib32gcc-5-dev +sudo apt install build-essential cmake g++-multilib libgcc-9-dev lib32gcc-9-dev ccache +``` +Or in Ubuntu-18.04: +``` Bash +sudo apt install build-essential cmake g++-multilib libgcc-8-dev lib32gcc-8-dev ccache ``` Or in Fedora: ``` Bash diff --git a/wamr-compiler/README.md b/wamr-compiler/README.md index a3a791f99..b9e566af2 100644 --- a/wamr-compiler/README.md +++ b/wamr-compiler/README.md @@ -1,7 +1,15 @@ ### Build wamrc AOT compiler -Both wasm binary file and AOT file are supported by iwasm. The wamrc AOT compiler is to compile wasm binary file to AOT file which can also be run by iwasm. Execute following commands to build **wamrc** compiler for Linux: +Both wasm binary file and AOT file are supported by iwasm. The wamrc AOT compiler is to compile wasm binary file to AOT file which can also be run by iwasm. You can execute following commands to build **wamrc** compiler: + +For **Linux**(Ubuntu 20.04 as an example): + +First, make sure necessary dependency are installed: + +```shell +sudo apt-get install git build-essential cmake g++-multilib libgcc-9-dev lib32gcc-9-dev ccache +``` ```shell cd wamr-compiler @@ -13,6 +21,7 @@ make ``` For **Windows**: + ```shell cd wamr-compiler python build_llvm.py @@ -20,4 +29,4 @@ mkdir build && cd build cmake .. cmake --build . --config Release # wamrc.exe is generated under .\Release directory -``` \ No newline at end of file +``` From 28274bed3434aa9e4a59269f33c6bc1875304602 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 8 May 2023 19:34:26 +0800 Subject: [PATCH 14/14] Fix build polybench benchmark error with wasi-sdk-19.0 (#2187) --- tests/benchmarks/polybench/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/benchmarks/polybench/build.sh b/tests/benchmarks/polybench/build.sh index 43cd3321a..bc7bf4c10 100755 --- a/tests/benchmarks/polybench/build.sh +++ b/tests/benchmarks/polybench/build.sh @@ -34,7 +34,8 @@ do utilities/polybench.c ${file} \ -Wl,--export=__heap_base -Wl,--export=__data_end \ -Wl,--export=malloc -Wl,--export=free \ - -DPOLYBENCH_TIME -o ${OUT_DIR}/${file_name%.*}.wasm + -DPOLYBENCH_TIME -o ${OUT_DIR}/${file_name%.*}.wasm \ + -D_WASI_EMULATED_PROCESS_CLOCKS echo "Compile ${file_name%.*}.wasm into ${file_name%.*}.aot" ${WAMRC_CMD} -o ${OUT_DIR}/${file_name%.*}.aot \