From da31c079b2fd39cbaa4f7c8a7b937fb783876b82 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 12 Aug 2024 12:48:25 +0800 Subject: [PATCH 01/25] posix_thread.c: Restore old signal alternate stack before thread exit (#3693) Some host environment may also create an signal alternate stack and access it after the wasm runtime exits, the runtime should backup the stack info and restore it before thread exits. The issue was found in golang: ``` signal 23 received on thread with on signal stack fatal error: non-Go code disabled signaltstack ``` --- .../shared/platform/common/posix/posix_thread.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index d35a7773c..5ec957e52 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -504,6 +504,8 @@ static os_thread_local_attribute bool thread_signal_inited = false; #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 /* The signal alternate stack base addr */ static os_thread_local_attribute uint8 *sigalt_stack_base_addr; +/* The previous signal alternate stack */ +static os_thread_local_attribute stack_t prev_sigalt_stack; /* * ASAN is not designed to work with custom stack unwind or other low-level @@ -683,7 +685,9 @@ os_thread_signal_init(os_signal_handler handler) sigalt_stack_info.ss_sp = map_addr; sigalt_stack_info.ss_size = map_size; sigalt_stack_info.ss_flags = 0; - if (sigaltstack(&sigalt_stack_info, NULL) != 0) { + memset(&prev_sigalt_stack, 0, sizeof(stack_t)); + /* Set signal alternate stack and save the previous one */ + if (sigaltstack(&sigalt_stack_info, &prev_sigalt_stack) != 0) { os_printf("Failed to init signal alternate stack\n"); goto fail2; } @@ -729,19 +733,12 @@ fail1: void os_thread_signal_destroy() { -#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 - stack_t sigalt_stack_info; -#endif - if (!thread_signal_inited) return; #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 - /* Disable signal alternate stack */ - memset(&sigalt_stack_info, 0, sizeof(stack_t)); - sigalt_stack_info.ss_flags = SS_DISABLE; - sigalt_stack_info.ss_size = SIG_ALT_STACK_SIZE; - sigaltstack(&sigalt_stack_info, NULL); + /* Restore the previous signal alternate stack */ + sigaltstack(&prev_sigalt_stack, NULL); os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE); From 4e31bd63b7bcef5b69a9dc228fe333b308a7019d Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Tue, 13 Aug 2024 08:38:15 +0800 Subject: [PATCH 02/25] wamr-test-suites: Clean up generated tmp files after spec test (#3700) Add all possible generated tmp files to the list, those not actually generated will be simply ignored in the deletion process. --- tests/wamr-test-suites/spec-test-script/all.py | 3 ++- tests/wamr-test-suites/spec-test-script/runtest.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 1d4ed1b21..fcc5ff154 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -572,7 +572,8 @@ def main(): if options.parl_flag: # several cases might share the same workspace/tempfile at the same time # so, disable it while running parallelly - options.clean_up_flag = False + if options.multi_module_flag: + options.clean_up_flag = False options.verbose_flag = False start = time.time_ns() diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index d4bdaf273..268024323 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -1307,6 +1307,12 @@ if __name__ == "__main__": wasm_tempfile = create_tmp_file(".wasm") if test_aot: aot_tempfile = create_tmp_file(".aot") + # could be potientially compiled to aot + # with the future following call test_assert_xxx, + # add them to temp_file_repo now even if no actual following file, + # it will be simple ignore during final deletion if not exist + prefix = wasm_tempfile.split(".wasm")[0] + temp_file_repo.append(prefix + ".aot") ret_code = 0 try: @@ -1429,6 +1435,12 @@ if __name__ == "__main__": if test_aot: r = compile_wasm_to_aot(temp_files[1], temp_files[2], True, opts, r) + # could be potientially compiled to aot + # with the future following call test_assert_xxx, + # add them to temp_file_repo now even if no actual following file, + # it will be simple ignore during final deletion if not exist + prefix = temp_files[1].split(".wasm")[0] + temp_file_repo.append(prefix + ".aot") try: assert_prompt(r, ['Compile success'], opts.start_timeout, False) except: From 140ff25d46c79a6159ba7a16493857c99be7c3f7 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 13 Aug 2024 09:14:52 +0800 Subject: [PATCH 03/25] wasi-nn: Apply new architecture (#3692) ps. https://github.com/bytecodealliance/wasm-micro-runtime/issues/3677 --- build-scripts/config_common.cmake | 7 +- core/iwasm/common/wasm_native.c | 57 ++- .../wasi-nn/cmake/Findtensorflow_lite.cmake | 27 +- .../libraries/wasi-nn/cmake/wasi_nn.cmake | 45 +- .../libraries/wasi-nn/include/wasi_nn_host.h | 20 + .../libraries/wasi-nn/include/wasi_nn_types.h | 4 +- core/iwasm/libraries/wasi-nn/src/wasi_nn.c | 405 ++++++++++++------ .../libraries/wasi-nn/src/wasi_nn_openvino.c | 80 ++-- .../libraries/wasi-nn/src/wasi_nn_openvino.h | 35 +- .../libraries/wasi-nn/src/wasi_nn_private.h | 3 +- .../wasi-nn/src/wasi_nn_tensorflowlite.cpp | 61 +-- .../wasi-nn/src/wasi_nn_tensorflowlite.hpp | 40 +- .../wasi-nn/test/Dockerfile.wasi-nn-smoke | 9 +- .../libraries/wasi-nn/test/run_smoke_test.py | 4 - 14 files changed, 482 insertions(+), 315 deletions(-) create mode 100644 core/iwasm/libraries/wasi-nn/include/wasi_nn_host.h diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 8a1002235..10d1289eb 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -438,12 +438,13 @@ if (WAMR_BUILD_WASI_NN EQUAL 1) if (NOT WAMR_BUILD_WASI_NN_TFLITE EQUAL 1 AND NOT WAMR_BUILD_WASI_NN_OPENVINO EQUAL 1) message (FATAL_ERROR " Need to select a backend for WASI-NN") endif () + if (WAMR_BUILD_WASI_NN_TFLITE EQUAL 1) - message (" WASI-NN backend tflite enabled") + message (" WASI-NN: backend tflite enabled") add_definitions (-DWASM_ENABLE_WASI_NN_TFLITE) endif () if (WAMR_BUILD_WASI_NN_OPENVINO EQUAL 1) - message (" WASI-NN backend openvino enabled") + message (" WASI-NN: backend openvino enabled") add_definitions (-DWASM_ENABLE_WASI_NN_OPENVINO) endif () # Variant devices @@ -459,7 +460,7 @@ if (WAMR_BUILD_WASI_NN EQUAL 1) add_definitions (-DWASM_WASI_NN_EXTERNAL_DELEGATE_PATH="${WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH}") endif () if (WAMR_BUILD_WASI_EPHEMERAL_NN EQUAL 1) - message (" WASI-NN: WASI-Ephemeral-NN enabled") + message (" WASI-NN: use 'wasi_ephemeral_nn' instead of 'wasi-nn'") add_definitions (-DWASM_ENABLE_WASI_EPHEMERAL_NN=1) endif() endif () diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index cde40825e..9e8764a22 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -15,6 +15,9 @@ #if WASM_ENABLE_THREAD_MGR != 0 #include "../libraries/thread-mgr/thread_manager.h" #endif +#if WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +#include "wasi_nn_host.h" +#endif static NativeSymbolsList g_native_symbols_list = NULL; @@ -472,11 +475,12 @@ quick_aot_entry_init(); bool wasm_native_init() { -#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ - || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ - || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ - || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ - || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 +#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ + || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ + || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ + || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ + || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 \ + || WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 NativeSymbol *native_symbols; uint32 n_native_symbols; #endif @@ -562,13 +566,30 @@ wasm_native_init() goto fail; #endif /* WASM_ENABLE_LIB_RATS */ +#if WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + if (!wasi_nn_initialize()) + goto fail; + + n_native_symbols = get_wasi_nn_export_apis(&native_symbols); + if (n_native_symbols > 0 + && !wasm_native_register_natives( +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + "wasi_ephemeral_nn", +#else + "wasi_nn", +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ + native_symbols, n_native_symbols)) + goto fail; +#endif /* WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ + #if WASM_ENABLE_QUICK_AOT_ENTRY != 0 if (!quick_aot_entry_init()) { -#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ - || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ - || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ - || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ - || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 +#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ + || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ + || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ + || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ + || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 \ + || WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 goto fail; #else return false; @@ -577,11 +598,12 @@ wasm_native_init() #endif return true; -#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ - || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ - || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ - || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ - || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 +#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \ + || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ + || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ + || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ + || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 \ + || WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 fail: wasm_native_destroy(); return false; @@ -599,6 +621,7 @@ wasm_native_destroy() g_wasi_context_key = NULL; } #endif + #if WASM_ENABLE_LIB_PTHREAD != 0 lib_pthread_destroy(); #endif @@ -607,6 +630,10 @@ wasm_native_destroy() lib_wasi_threads_destroy(); #endif +#if WASM_ENABLE_WASI_NN != 0 || WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + wasi_nn_destroy(); +#endif + node = g_native_symbols_list; while (node) { node_next = node->next; diff --git a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake index 59fdaf758..052dd9804 100644 --- a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake +++ b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake @@ -1,12 +1,13 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -find_library(TENSORFLOW_LITE - NAMES tensorflow-lite +find_library(TENSORFLOW_LITE + NAMES tensorflow-lite + HINTS ${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite + NO_DEFAULT_PATHS ) -if(NOT EXISTS ${TENSORFLOW_LITE}) +if(NOT TENSORFLOW_LITE) if(NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") execute_process( COMMAND "${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh" @@ -32,11 +33,15 @@ if(NOT EXISTS ${TENSORFLOW_LITE}) "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite" "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL - ) - - set(TENSORFLOW_LITE_INCLUDE_DIR "${TENSORFLOW_SOURCE_DIR}") - set(FLATBUFFER_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include") - - include_directories(${TENSORFLOW_LITE_INCLUDE_DIR}) - include_directories(${FLATBUFFER_INCLUDE_DIR}) + ) +else () + message(STATUS "TensorFlow Lite library found: ${TENSORFLOW_LITE}") + set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") endif() + +set(TENSORFLOW_LITE_INCLUDE_DIR "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite") +set(FLATBUFFER_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include") + +include_directories(${TENSORFLOW_SOURCE_DIR}) +include_directories(${FLATBUFFER_INCLUDE_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite) diff --git a/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake b/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake index 49286f2f4..e2ad257e0 100644 --- a/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake +++ b/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake @@ -27,61 +27,48 @@ endif() # # wasi-nn general set(WASI_NN_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) -add_library( - wasi-nn-general - SHARED - ${WASI_NN_ROOT}/src/wasi_nn.c - ${WASI_NN_ROOT}/src/utils/wasi_nn_app_native.c +set(WASI_NN_SOURCES + ${WASI_NN_ROOT}/src/wasi_nn.c + ${WASI_NN_ROOT}/src/utils/wasi_nn_app_native.c ) -target_include_directories( - wasi-nn-general - PUBLIC - ${WASI_NN_ROOT}/include - ${WASI_NN_ROOT}/src - ${WASI_NN_ROOT}/src/utils -) -target_link_libraries( - wasi-nn-general - PUBLIC - libiwasm -) -target_compile_definitions( - wasi-nn-general - PUBLIC - $<$:NN_LOG_LEVEL=0> - $<$:NN_LOG_LEVEL=2> +include_directories(${WASI_NN_ROOT}/include) +add_compile_definitions( + $<$:NN_LOG_LEVEL=0> + $<$:NN_LOG_LEVEL=2> ) # # wasi-nn backends - +# # - tflite if(WAMR_BUILD_WASI_NN_TFLITE EQUAL 1) add_library( - wasi-nn-tflite + wasi_nn_tflite SHARED ${WASI_NN_ROOT}/src/wasi_nn_tensorflowlite.cpp ) + target_link_libraries( - wasi-nn-tflite + wasi_nn_tflite PUBLIC + libiwasm tensorflow-lite - wasi-nn-general ) endif() # - openvino if(WAMR_BUILD_WASI_NN_OPENVINO EQUAL 1) add_library( - wasi-nn-openvino + wasi_nn_openvino SHARED ${WASI_NN_ROOT}/src/wasi_nn_openvino.c ) + target_link_libraries( - wasi-nn-openvino + wasi_nn_openvino PUBLIC + libiwasm openvino::runtime openvino::runtime::c - wasi-nn-general ) endif() \ No newline at end of file diff --git a/core/iwasm/libraries/wasi-nn/include/wasi_nn_host.h b/core/iwasm/libraries/wasi-nn/include/wasi_nn_host.h new file mode 100644 index 000000000..cb056915f --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/include/wasi_nn_host.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_NN_HOST_H +#define WASI_NN_HOST_H + +#include "lib_export.h" + +uint32_t +get_wasi_nn_export_apis(NativeSymbol **p_native_symbols); + +bool +wasi_nn_initialize(); + +void +wasi_nn_destroy(); + +#endif /* WASI_NN_HOST_H */ \ No newline at end of file diff --git a/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h b/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h index 71c530ea5..d36f5977c 100644 --- a/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h +++ b/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h @@ -126,6 +126,7 @@ typedef enum { tensorflowlite, ggml, autodetect, + unknown_backend, } graph_encoding; // Define where the graph should be executed. @@ -161,9 +162,6 @@ typedef struct { BACKEND_DEINITIALIZE deinit; } api_function; -bool -wasi_nn_register_backend(api_function apis); - void wasi_nn_dump_tensor_dimension(tensor_dimensions *dim, int32_t output_len, char *output); diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c index 2d987d3b4..0d56981fc 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c @@ -10,40 +10,37 @@ #include #include #include +#include #include "wasi_nn_private.h" -#include "wasi_nn_app_native.h" -#include "logger.h" +#include "utils/wasi_nn_app_native.h" +#include "utils/logger.h" #include "bh_platform.h" #include "wasi_nn_types.h" #include "wasm_export.h" #define HASHMAP_INITIAL_SIZE 20 +#define TFLITE_BACKEND_LIB "libwasi_nn_tflite.so" +#define OPENVINO_BACKEND_LIB "libwasi_nn_openvino.so" +#define LLAMACPP_BACKEND_LIB "libwasi_nn_llamacpp.so" /* Global variables */ -// if using `load_by_name`, there is no known `encoding` at the time of loading -// so, just keep one `api_function` is enough -static api_function lookup = { 0 }; +struct backends_api_functions { + void *backend_handle; + api_function functions; +} lookup[autodetect] = { 0 }; -#define call_wasi_nn_func(wasi_error, func, ...) \ - do { \ - if (lookup.func) { \ - wasi_error = lookup.func(__VA_ARGS__); \ - if (wasi_error != success) \ - NN_ERR_PRINTF("Error %s: %d", #func, wasi_error); \ - } \ - else { \ - NN_ERR_PRINTF("Error %s is not registered", #func); \ - wasi_error = unsupported_operation; \ - } \ +#define call_wasi_nn_func(backend_encoding, func, wasi_error, ...) \ + do { \ + wasi_error = lookup[backend_encoding].functions.func(__VA_ARGS__); \ + if (wasi_error != success) \ + NN_ERR_PRINTF("Error %s() -> %d", #func, wasi_error); \ } while (0) +/* HashMap utils */ static HashMap *hashmap; -static void -wasi_nn_ctx_destroy(WASINNContext *wasi_nn_ctx); - static uint32 hash_func(const void *key) { @@ -74,12 +71,51 @@ key_destroy_func(void *key1) /* key type is wasm_module_inst_t*. do nothing */ } +static void +wasi_nn_ctx_destroy(WASINNContext *wasi_nn_ctx) +{ + NN_DBG_PRINTF("[WASI NN] DEINIT..."); + + if (wasi_nn_ctx == NULL) { + NN_ERR_PRINTF( + "Error when deallocating memory. WASI-NN context is NULL"); + return; + } + NN_DBG_PRINTF("Freeing wasi-nn"); + NN_DBG_PRINTF("-> is_model_loaded: %d", wasi_nn_ctx->is_model_loaded); + NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->backend); + + /* deinit() the backend */ + wasi_nn_error res; + call_wasi_nn_func(wasi_nn_ctx->backend, deinit, res, + wasi_nn_ctx->backend_ctx); + + wasm_runtime_free(wasi_nn_ctx); +} + static void value_destroy_func(void *value) { wasi_nn_ctx_destroy((WASINNContext *)value); } +bool +wasi_nn_initialize() +{ + NN_DBG_PRINTF("[WASI NN General] Initializing wasi-nn"); + + // hashmap { instance: wasi_nn_ctx } + hashmap = bh_hash_map_create(HASHMAP_INITIAL_SIZE, true, hash_func, + key_equal_func, key_destroy_func, + value_destroy_func); + if (hashmap == NULL) { + NN_ERR_PRINTF("Error while initializing hashmap"); + return false; + } + + return true; +} + static WASINNContext * wasi_nn_initialize_context() { @@ -91,34 +127,11 @@ wasi_nn_initialize_context() NN_ERR_PRINTF("Error when allocating memory for WASI-NN context"); return NULL; } - wasi_nn_ctx->is_model_loaded = false; - - /* only one backend can be registered */ - wasi_nn_error res; - call_wasi_nn_func(res, init, &wasi_nn_ctx->backend_ctx); - if (res != success) { - wasm_runtime_free(wasi_nn_ctx); - return NULL; - } + memset(wasi_nn_ctx, 0, sizeof(WASINNContext)); return wasi_nn_ctx; } -static bool -wasi_nn_initialize() -{ - NN_DBG_PRINTF("[WASI NN General] Initializing wasi-nn"); - // hashmap { instance: wasi_nn_ctx } - hashmap = bh_hash_map_create(HASHMAP_INITIAL_SIZE, true, hash_func, - key_equal_func, key_destroy_func, - value_destroy_func); - if (hashmap == NULL) { - NN_ERR_PRINTF("Error while initializing hashmap"); - return false; - } - return true; -} - /* Get wasi-nn context from module instance */ static WASINNContext * wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance) @@ -129,6 +142,7 @@ wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance) wasi_nn_ctx = wasi_nn_initialize_context(); if (wasi_nn_ctx == NULL) return NULL; + bool ok = bh_hash_map_insert(hashmap, (void *)instance, (void *)wasi_nn_ctx); if (!ok) { @@ -141,36 +155,31 @@ wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance) return wasi_nn_ctx; } -static void -wasi_nn_ctx_destroy(WASINNContext *wasi_nn_ctx) -{ - NN_DBG_PRINTF("[WASI NN] DEINIT..."); - - if (wasi_nn_ctx == NULL) { - NN_ERR_PRINTF( - "Error when deallocating memory. WASI-NN context is NULL"); - return; - } - NN_DBG_PRINTF("Freeing wasi-nn"); - NN_DBG_PRINTF("-> is_model_loaded: %d", wasi_nn_ctx->is_model_loaded); - NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->current_encoding); - - /* only one backend can be registered */ - wasi_nn_error res; - call_wasi_nn_func(res, deinit, wasi_nn_ctx->backend_ctx); - - wasm_runtime_free(wasi_nn_ctx); -} - void wasi_nn_destroy() { // destroy hashmap will destroy keys and values bh_hash_map_destroy(hashmap); + + // close backends' libraries and registered functions + for (unsigned i = 0; i < sizeof(lookup) / sizeof(lookup[0]); i++) { + if (lookup[i].backend_handle) { + dlclose(lookup[i].backend_handle); + lookup[i].backend_handle = NULL; + } + + lookup[i].functions.init = NULL; + lookup[i].functions.deinit = NULL; + lookup[i].functions.load = NULL; + lookup[i].functions.load_by_name = NULL; + lookup[i].functions.init_execution_context = NULL; + lookup[i].functions.set_input = NULL; + lookup[i].functions.compute = NULL; + lookup[i].functions.get_output = NULL; + } } /* Utils */ - static wasi_nn_error is_model_initialized(WASINNContext *wasi_nn_ctx) { @@ -181,8 +190,169 @@ is_model_initialized(WASINNContext *wasi_nn_ctx) return success; } -/* WASI-NN implementation */ +/* + *TODO: choose a proper backend based on + * - hardware + * - model file format + * - on device ML framework + */ +static graph_encoding +choose_a_backend() +{ + void *handle; + handle = dlopen(LLAMACPP_BACKEND_LIB, RTLD_LAZY); + if (handle) { + NN_INFO_PRINTF("Using llama.cpp backend"); + dlclose(handle); + return ggml; + } + + handle = dlopen(OPENVINO_BACKEND_LIB, RTLD_LAZY); + if (handle) { + NN_INFO_PRINTF("Using openvino backend"); + dlclose(handle); + return openvino; + } + + handle = dlopen(TFLITE_BACKEND_LIB, RTLD_LAZY); + if (handle) { + NN_INFO_PRINTF("Using tflite backend"); + dlclose(handle); + return tensorflowlite; + } + + return unknown_backend; +} + +static bool +register_backend(void *handle, api_function *functions) +{ + BACKEND_INITIALIZE init = (BACKEND_INITIALIZE)dlsym(handle, "init_backend"); + if (!init) { + NN_WARN_PRINTF("init_backend() not found"); + return false; + } + functions->init = init; + + BACKEND_DEINITIALIZE deinit = + (BACKEND_DEINITIALIZE)dlsym(handle, "deinit_backend"); + if (!deinit) { + NN_WARN_PRINTF("deinit_backend() not found"); + return false; + } + functions->deinit = deinit; + + LOAD load = (LOAD)dlsym(handle, "load"); + if (!load) { + NN_WARN_PRINTF("load() not found"); + return false; + } + functions->load = load; + + LOAD_BY_NAME load_by_name = (LOAD_BY_NAME)dlsym(handle, "load_by_name"); + if (!load_by_name) { + NN_WARN_PRINTF("load_by_name() not found"); + return false; + } + functions->load_by_name = load_by_name; + + INIT_EXECUTION_CONTEXT init_execution_context = + (INIT_EXECUTION_CONTEXT)dlsym(handle, "init_execution_context"); + if (!init_execution_context) { + NN_WARN_PRINTF("init_execution_context() not found"); + return false; + } + functions->init_execution_context = init_execution_context; + + SET_INPUT set_input = (SET_INPUT)dlsym(handle, "set_input"); + if (!set_input) { + NN_WARN_PRINTF("set_input() not found"); + return false; + } + functions->set_input = set_input; + + COMPUTE compute = (COMPUTE)dlsym(handle, "compute"); + if (!compute) { + NN_WARN_PRINTF("compute() not found"); + return false; + } + functions->compute = compute; + + GET_OUTPUT get_output = (GET_OUTPUT)dlsym(handle, "get_output"); + if (!get_output) { + NN_WARN_PRINTF("get_output() not found"); + return false; + } + functions->get_output = get_output; + + return true; +} + +static bool +prepare_backend(const char *lib_name, struct backends_api_functions *backend) +{ + NN_DBG_PRINTF("[Native Register] prepare_backend %s", lib_name); + + void *handle; + handle = dlopen(lib_name, RTLD_LAZY); + if (!handle) { + NN_ERR_PRINTF("Error loading %s. %s", lib_name, dlerror()); + return false; + } + + if (!register_backend(handle, &(backend->functions))) { + NN_ERR_PRINTF("Error when registering functions of %s", lib_name); + dlclose(handle); + return false; + } + + backend->backend_handle = handle; + return true; +} + +static const char * +graph_encoding_to_backend_lib_name(graph_encoding encoding) +{ + switch (encoding) { + case openvino: + return OPENVINO_BACKEND_LIB; + case tensorflowlite: + return TFLITE_BACKEND_LIB; + case ggml: + return LLAMACPP_BACKEND_LIB; + default: + return NULL; + } +} + +static bool +detect_and_load_backend(graph_encoding backend_hint, + struct backends_api_functions *backends, + graph_encoding *loaded_backed) +{ + if (backend_hint >= autodetect) + return false; + + if (backend_hint == autodetect) + backend_hint = choose_a_backend(); + + /* if already loaded */ + if (lookup[backend_hint].backend_handle) { + *loaded_backed = backend_hint; + return true; + } + + *loaded_backed = backend_hint; + const char *backend_lib_name = + graph_encoding_to_backend_lib_name(backend_hint); + if (!backend_lib_name) + return false; + + return prepare_backend(backend_lib_name, backends + backend_hint); +} + +/* WASI-NN implementation */ #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 wasi_nn_error wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_wasm *builder, @@ -222,13 +392,28 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, goto fail; } + graph_encoding loaded_backed = autodetect; + if (!detect_and_load_backend(encoding, lookup, &loaded_backed)) { + res = invalid_encoding; + NN_ERR_PRINTF("load backend failed"); + goto fail; + } + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); - call_wasi_nn_func(res, load, wasi_nn_ctx->backend_ctx, &builder_native, - encoding, target, g); + wasi_nn_ctx->backend = loaded_backed; + + /* init() the backend */ + call_wasi_nn_func(wasi_nn_ctx->backend, init, res, + &wasi_nn_ctx->backend_ctx); if (res != success) goto fail; - wasi_nn_ctx->current_encoding = encoding; + call_wasi_nn_func(wasi_nn_ctx->backend, load, res, wasi_nn_ctx->backend_ctx, + &builder_native, encoding, target, g); + if (res != success) + goto fail; + + wasi_nn_ctx->backend = loaded_backed; wasi_nn_ctx->is_model_loaded = true; fail: @@ -251,22 +436,37 @@ wasi_nn_load_by_name(wasm_exec_env_t exec_env, char *name, uint32_t name_len, } if (!wasm_runtime_validate_native_addr(instance, name, name_len)) { + NN_ERR_PRINTF("name is invalid"); return invalid_argument; } if (!wasm_runtime_validate_native_addr(instance, g, (uint64)sizeof(graph))) { + NN_ERR_PRINTF("graph is invalid"); return invalid_argument; } + graph_encoding loaded_backed = autodetect; + if (detect_and_load_backend(autodetect, lookup, &loaded_backed)) { + NN_ERR_PRINTF("load backend failed"); + return invalid_encoding; + } + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); wasi_nn_error res; - call_wasi_nn_func(res, load_by_name, wasi_nn_ctx->backend_ctx, name, - name_len, g); + + /* init() the backend */ + call_wasi_nn_func(wasi_nn_ctx->backend, init, res, + &wasi_nn_ctx->backend_ctx); if (res != success) return res; - wasi_nn_ctx->current_encoding = autodetect; + call_wasi_nn_func(wasi_nn_ctx->backend, load_by_name, res, + wasi_nn_ctx->backend_ctx, name, name_len, g); + if (res != success) + return res; + + wasi_nn_ctx->backend = loaded_backed; wasi_nn_ctx->is_model_loaded = true; return success; } @@ -294,8 +494,8 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g, return invalid_argument; } - call_wasi_nn_func(res, init_execution_context, wasi_nn_ctx->backend_ctx, g, - ctx); + call_wasi_nn_func(wasi_nn_ctx->backend, init_execution_context, res, + wasi_nn_ctx->backend_ctx, g, ctx); return res; } @@ -322,7 +522,8 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx, &input_tensor_native))) return res; - call_wasi_nn_func(res, set_input, wasi_nn_ctx->backend_ctx, ctx, index, + call_wasi_nn_func(wasi_nn_ctx->backend, set_input, res, + wasi_nn_ctx->backend_ctx, ctx, index, &input_tensor_native); // XXX: Free intermediate structure pointers if (input_tensor_native.dimensions) @@ -347,7 +548,8 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) if (success != (res = is_model_initialized(wasi_nn_ctx))) return res; - call_wasi_nn_func(res, compute, wasi_nn_ctx->backend_ctx, ctx); + call_wasi_nn_func(wasi_nn_ctx->backend, compute, res, + wasi_nn_ctx->backend_ctx, ctx); return res; } @@ -383,12 +585,14 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, } #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 - call_wasi_nn_func(res, get_output, wasi_nn_ctx->backend_ctx, ctx, index, - output_tensor, &output_tensor_len); + call_wasi_nn_func(wasi_nn_ctx->backend, get_output, res, + wasi_nn_ctx->backend_ctx, ctx, index, output_tensor, + &output_tensor_len); *output_tensor_size = output_tensor_len; #else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ - call_wasi_nn_func(res, get_output, wasi_nn_ctx->backend_ctx, ctx, index, - output_tensor, output_tensor_size); + call_wasi_nn_func(wasi_nn_ctx->backend, get_output, res, + wasi_nn_ctx->backend_ctx, ctx, index, output_tensor, + output_tensor_size); #endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ return res; } @@ -423,44 +627,3 @@ get_wasi_nn_export_apis(NativeSymbol **p_native_symbols) *p_native_symbols = native_symbols_wasi_nn; return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol); } - -__attribute__((used)) uint32_t -get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols) -{ - NN_DBG_PRINTF("[Native Register] get_native_lib"); - -#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 - *p_module_name = "wasi_ephemeral_nn"; -#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ - *p_module_name = "wasi_nn"; -#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ - - return get_wasi_nn_export_apis(p_native_symbols); -} - -__attribute__((used)) int -init_native_lib() -{ - NN_DBG_PRINTF("[Native Register] init_native_lib"); - - if (!wasi_nn_initialize()) - return 1; - - return 0; -} - -__attribute__((used)) void -deinit_native_lib() -{ - NN_DBG_PRINTF("[Native Register] deinit_native_lib"); - - wasi_nn_destroy(); -} - -__attribute__((used)) bool -wasi_nn_register_backend(api_function apis) -{ - NN_DBG_PRINTF("[Native Register] wasi_nn_register_backend"); - lookup = apis; - return true; -} diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.c index 678673e8b..db2f91db0 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.c +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.c @@ -5,7 +5,7 @@ #include "wasi_nn_types.h" #include "wasi_nn_openvino.h" -#include "logger.h" +#include "utils/logger.h" #include "bh_platform.h" #include "openvino/c/openvino.h" @@ -82,7 +82,7 @@ dump_ov_shape_t(const ov_shape_t *shape, int32_t output_len, char *output) static void print_model_input_output_info(ov_model_t *model) { - wasi_nn_error ov_error; + wasi_nn_error ov_error = success; char *friendly_name = NULL; size_t input_size = 0; ov_output_const_port_t *input_port = NULL; @@ -136,6 +136,7 @@ print_model_input_output_info(ov_model_t *model) output_port = NULL; } + ov_error = ov_error; fail: if (friendly_name) ov_free(friendly_name); @@ -157,16 +158,23 @@ wasi_nn_tensor_type_to_openvino_element_type(tensor_type wasi_nn_type) return F16; case fp32: return F32; +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 case fp64: return F64; case bf16: return BF16; + case i64: + return I64; case u8: return U8; case i32: return I32; - case i64: - return I64; +#else + case up8: + return U8; + case ip32: + return I32; +#endif default: break; } @@ -178,7 +186,7 @@ wasi_nn_tensor_type_to_openvino_element_type(tensor_type wasi_nn_type) static wasi_nn_error uint32_array_to_int64_array(uint32_t array_size, uint32_t *src, int64_t **dst) { - *dst = malloc(array_size * sizeof(int64_t)); + *dst = os_malloc(array_size * sizeof(int64_t)); if (!(*dst)) return runtime_error; @@ -189,9 +197,9 @@ uint32_array_to_int64_array(uint32_t array_size, uint32_t *src, int64_t **dst) return success; } -wasi_nn_error -openvino_load(void *ctx, graph_builder_array *builder, graph_encoding encoding, - execution_target target, graph *g) +__attribute__((visibility("default"))) wasi_nn_error +load(void *ctx, graph_builder_array *builder, graph_encoding encoding, + execution_target target, graph *g) { OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx; wasi_nn_error ret = unsupported_operation; @@ -227,7 +235,7 @@ openvino_load(void *ctx, graph_builder_array *builder, graph_encoding encoding, /* transfer weight to an ov tensor */ { - ov_ctx->weight_data = malloc(weight.size); + ov_ctx->weight_data = os_malloc(weight.size); if (!ov_ctx->weight_data) goto fail; memcpy(ov_ctx->weight_data, weight.buf, weight.size); @@ -255,9 +263,8 @@ fail: return ret; } -wasi_nn_error -openvino_load_by_name(void *ctx, const char *filename, uint32_t filename_len, - graph *g) +__attribute__((visibility("default"))) wasi_nn_error +load_by_name(void *ctx, const char *filename, uint32_t filename_len, graph *g) { OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx; wasi_nn_error ret = unsupported_operation; @@ -270,16 +277,15 @@ fail: return ret; } -wasi_nn_error -openvino_init_execution_context(void *ctx, graph g, - graph_execution_context *exec_ctx) +__attribute__((visibility("default"))) wasi_nn_error +init_execution_context(void *ctx, graph g, graph_execution_context *exec_ctx) { return success; } -wasi_nn_error -openvino_set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index, - tensor *wasi_nn_tensor) +__attribute__((visibility("default"))) wasi_nn_error +set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index, + tensor *wasi_nn_tensor) { OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx; wasi_nn_error ret = unsupported_operation; @@ -405,7 +411,7 @@ openvino_set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index, fail: if (ov_dims) - free(ov_dims); + os_free(ov_dims); ov_shape_free(&input_shape); if (ppp) ov_preprocess_prepostprocessor_free(ppp); @@ -429,8 +435,8 @@ fail: return ret; } -wasi_nn_error -openvino_compute(void *ctx, graph_execution_context exec_ctx) +__attribute__((visibility("default"))) wasi_nn_error +compute(void *ctx, graph_execution_context exec_ctx) { OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx; wasi_nn_error ret = unsupported_operation; @@ -441,9 +447,9 @@ fail: return ret; } -wasi_nn_error -openvino_get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index, - tensor_data output_tensor, uint32_t *output_tensor_size) +__attribute__((visibility("default"))) wasi_nn_error +get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index, + tensor_data output_tensor, uint32_t *output_tensor_size) { OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx; wasi_nn_error ret = unsupported_operation; @@ -471,8 +477,8 @@ fail: return ret; } -wasi_nn_error -openvino_initialize(void **ctx) +__attribute__((visibility("default"))) wasi_nn_error +init_backend(void **ctx) { ov_version_t version; OpenVINOContext *ov_ctx = NULL; @@ -509,8 +515,8 @@ fail: return ret; } -wasi_nn_error -openvino_destroy(void *ctx) +__attribute__((visibility("default"))) wasi_nn_error +deinit_backend(void *ctx) { OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx; @@ -518,7 +524,7 @@ openvino_destroy(void *ctx) return invalid_argument; if (ov_ctx->weight_data) - free(ov_ctx->weight_data); + os_free(ov_ctx->weight_data); if (ov_ctx->weights_tensor) ov_tensor_free(ov_ctx->weights_tensor); @@ -541,19 +547,3 @@ openvino_destroy(void *ctx) os_free(ov_ctx); return success; } - -__attribute__((constructor(200))) void -openvino_register_backend() -{ - api_function apis = { - .load = openvino_load, - .load_by_name = openvino_load_by_name, - .init_execution_context = openvino_init_execution_context, - .set_input = openvino_set_input, - .compute = openvino_compute, - .get_output = openvino_get_output, - .init = openvino_initialize, - .deinit = openvino_destroy, - }; - wasi_nn_register_backend(apis); -} \ No newline at end of file diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.h b/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.h index 798c69a0d..ea03a226f 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.h +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino.h @@ -8,29 +8,28 @@ #include "wasi_nn_types.h" -wasi_nn_error -openvino_load(void *ctx, graph_builder_array *builder, graph_encoding encoding, - execution_target target, graph *g); +__attribute__((visibility("default"))) wasi_nn_error +load(void *ctx, graph_builder_array *builder, graph_encoding encoding, + execution_target target, graph *g); -wasi_nn_error -openvino_init_execution_context(void *ctx, graph g, - graph_execution_context *exec_ctx); +__attribute__((visibility("default"))) wasi_nn_error +init_execution_context(void *ctx, graph g, graph_execution_context *exec_ctx); -wasi_nn_error -openvino_set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index, - tensor *input_tensor); +__attribute__((visibility("default"))) wasi_nn_error +set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index, + tensor *input_tensor); -wasi_nn_error -openvino_compute(void *ctx, graph_execution_context exec_ctx); +__attribute__((visibility("default"))) wasi_nn_error +compute(void *ctx, graph_execution_context exec_ctx); -wasi_nn_error -openvino_get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index, - tensor_data output_tensor, uint32_t *output_tensor_size); +__attribute__((visibility("default"))) wasi_nn_error +get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index, + tensor_data output_tensor, uint32_t *output_tensor_size); -wasi_nn_error -openvino_initialize(void **ctx); +__attribute__((visibility("default"))) wasi_nn_error +init_backend(void **ctx); -wasi_nn_error -openvino_destroy(void *ctx); +__attribute__((visibility("default"))) wasi_nn_error +deinit_backend(void *ctx); #endif /* WASI_NN_OPENVINO_HPP */ \ No newline at end of file diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h b/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h index df5080dea..bacae99ad 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h @@ -11,8 +11,7 @@ typedef struct { bool is_model_loaded; - // Optional - graph_encoding current_encoding; + graph_encoding backend; void *backend_ctx; } WASINNContext; 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 606aca243..6a3b5a47d 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -4,7 +4,7 @@ */ #include "wasi_nn_tensorflowlite.hpp" -#include "logger.h" +#include "utils/logger.h" #include "bh_platform.h" #include "wasi_nn_types.h" @@ -113,10 +113,9 @@ is_valid_graph_execution_context(TFLiteContext *tfl_ctx, } /* WASI-NN (tensorflow) implementation */ - -wasi_nn_error -tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, - graph_encoding encoding, execution_target target, graph *g) +__attribute__((visibility("default"))) wasi_nn_error +load(void *tflite_ctx, graph_builder_array *builder, graph_encoding encoding, + execution_target target, graph *g) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; @@ -168,9 +167,9 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, return success; } -wasi_nn_error -tensorflowlite_load_by_name(void *tflite_ctx, const char *filename, - uint32_t filename_len, graph *g) +__attribute__((visibility("default"))) wasi_nn_error +load_by_name(void *tflite_ctx, const char *filename, uint32_t filename_len, + graph *g) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; @@ -192,9 +191,8 @@ tensorflowlite_load_by_name(void *tflite_ctx, const char *filename, return success; } -wasi_nn_error -tensorflowlite_init_execution_context(void *tflite_ctx, graph g, - graph_execution_context *ctx) +__attribute__((visibility("default"))) wasi_nn_error +init_execution_context(void *tflite_ctx, graph g, graph_execution_context *ctx) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; @@ -281,9 +279,9 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, return success; } -wasi_nn_error -tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, - uint32_t index, tensor *input_tensor) +__attribute__((visibility("default"))) wasi_nn_error +set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index, + tensor *input_tensor) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; @@ -352,8 +350,8 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, return success; } -wasi_nn_error -tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx) +__attribute__((visibility("default"))) wasi_nn_error +compute(void *tflite_ctx, graph_execution_context ctx) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; @@ -365,10 +363,9 @@ tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx) return success; } -wasi_nn_error -tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, - uint32_t index, tensor_data output_tensor, - uint32_t *output_tensor_size) +__attribute__((visibility("default"))) wasi_nn_error +get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index, + tensor_data output_tensor, uint32_t *output_tensor_size) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; @@ -434,8 +431,8 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, return success; } -wasi_nn_error -tensorflowlite_initialize(void **tflite_ctx) +__attribute__((visibility("default"))) wasi_nn_error +init_backend(void **tflite_ctx) { TFLiteContext *tfl_ctx = new TFLiteContext(); if (tfl_ctx == NULL) { @@ -461,8 +458,8 @@ tensorflowlite_initialize(void **tflite_ctx) return success; } -wasi_nn_error -tensorflowlite_destroy(void *tflite_ctx) +__attribute__((visibility("default"))) wasi_nn_error +deinit_backend(void *tflite_ctx) { /* TensorFlow Lite memory is internally managed by tensorflow @@ -513,19 +510,3 @@ tensorflowlite_destroy(void *tflite_ctx) NN_DBG_PRINTF("Memory free'd."); return success; } - -__attribute__((constructor(200))) void -tflite_register_backend() -{ - api_function apis = { - .load = tensorflowlite_load, - .load_by_name = tensorflowlite_load_by_name, - .init_execution_context = tensorflowlite_init_execution_context, - .set_input = tensorflowlite_set_input, - .compute = tensorflowlite_compute, - .get_output = tensorflowlite_get_output, - .init = tensorflowlite_initialize, - .deinit = tensorflowlite_destroy, - }; - wasi_nn_register_backend(apis); -} \ No newline at end of file diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp index 630e741c0..d6e04ab0e 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp @@ -12,31 +12,33 @@ extern "C" { #endif -wasi_nn_error -tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, - graph_encoding encoding, execution_target target, graph *g); +__attribute__((visibility("default"))) wasi_nn_error +load(void *tflite_ctx, graph_builder_array *builder, graph_encoding encoding, + execution_target target, graph *g); -wasi_nn_error -tensorflowlite_init_execution_context(void *tflite_ctx, graph g, - graph_execution_context *ctx); +__attribute__((visibility("default"))) wasi_nn_error +load_by_name(void *tflite_ctx, const char *filename, uint32_t filename_len, + graph *g); -wasi_nn_error -tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, - uint32_t index, tensor *input_tensor); +__attribute__((visibility("default"))) wasi_nn_error +init_execution_context(void *tflite_ctx, graph g, graph_execution_context *ctx); -wasi_nn_error -tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx); +__attribute__((visibility("default"))) wasi_nn_error +set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index, + tensor *input_tensor); -wasi_nn_error -tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, - uint32_t index, tensor_data output_tensor, - uint32_t *output_tensor_size); +__attribute__((visibility("default"))) wasi_nn_error +compute(void *tflite_ctx, graph_execution_context ctx); -wasi_nn_error -tensorflowlite_initialize(void **tflite_ctx); +__attribute__((visibility("default"))) wasi_nn_error +get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index, + tensor_data output_tensor, uint32_t *output_tensor_size); -wasi_nn_error -tensorflowlite_destroy(void *tflite_ctx); +__attribute__((visibility("default"))) wasi_nn_error +init_backend(void **tflite_ctx); + +__attribute__((visibility("default"))) wasi_nn_error +deinit_backend(void *tflite_ctx); #ifdef __cplusplus } diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke b/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke index 4378ac395..261c77261 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke @@ -78,23 +78,22 @@ RUN cd openvino-mobilenet-raw \ && ./download_mobilenet.sh . \ && ls -l mobilenet.xml mobilenet.bin tensor-1x224x224x3-f32.bgr -# RUN apt update \ -# && apt install -y valgrind - # # iwasm. build from source WORKDIR /workspaces/wamr COPY . . WORKDIR /workspaces/wamr/product-mini/platforms/linux + RUN OpenVINO_DIR=/usr/lib/openvino-2023.2.0 \ cmake -S . -B build \ -DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_EPHEMERAL_NN=1 \ -DWAMR_BUILD_WASI_NN_OPENVINO=1 -DWAMR_BUILD_WASI_NN_TFLITE=1 \ && cmake --build build -RUN ln -sf "$(realpath ./build/iwasm)" /usr/local/bin/iwasm -# +ENV PATH=/workspaces/wamr/product-mini/platforms/linux/build:${PATH} +ENV LD_LIBRARY_PATH=/workspaces/wamr/product-mini/platforms/linux/build + # add smoke test script COPY core/iwasm/libraries/wasi-nn/test/run_smoke_test.py / diff --git a/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py b/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py index 08b19624a..a62d9cb7a 100644 --- a/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py +++ b/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py @@ -163,7 +163,6 @@ def execute_tflite_birds_v1_image(iwasm_bin: str, wasmedge_bin: str, cwd: Path): iwasm_output = execute_tflite_birds_v1_image_once( iwasm_bin, [ - "--native-lib=/workspaces/wamr/product-mini/platforms/linux/build/libwasi-nn-tflite.so", "--map-dir=.:.", ], cwd, @@ -182,7 +181,6 @@ def execute_openvino_mobilenet_image(iwasm_bin: str, wasmedge_bin: str, cwd: Pat iwasm_output = execute_openvino_mobilenet_image_once( iwasm_bin, [ - "--native-lib=/workspaces/wamr/product-mini/platforms/linux/build/libwasi-nn-openvino.so", "--map-dir=.:.", ], cwd, @@ -201,7 +199,6 @@ def execute_openvino_mobilenet_raw(iwasm_bin: str, wasmedge_bin: str, cwd: Path) iwasm_output = execute_openvino_mobilenet_raw_once( iwasm_bin, [ - "--native-lib=/workspaces/wamr/product-mini/platforms/linux/build/libwasi-nn-openvino.so", "--map-dir=.:.", ], cwd, @@ -239,7 +236,6 @@ def execute_openvino_road_segmentation_adas( iwasm_output = execute_openvino_road_segmentation_adas_once( iwasm_bin, [ - "--native-lib=/workspaces/wamr/product-mini/platforms/linux/build/libwasi-nn-openvino.so", "--map-dir=.:.", ], cwd, From 67fa155878861699336380980c3601f733f56194 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 13 Aug 2024 10:10:22 +0800 Subject: [PATCH 04/25] libc-wasi: Make rights of STDIN/STDOUT/STDERR fixed and overlook their access modes (#3694) When determining the file descriptor rights in the function fd_determine_type_rights(), we assign fixed and unchangeable rights to STDIN, STDOUT and STDERR. ps. https://github.com/bytecodealliance/wasm-micro-runtime/issues/3686 --- .../sandboxed-system-primitives/src/posix.c | 21 +++++++++- .../sandboxed-system-primitives/src/rights.h | 13 +++++++ .../shared/platform/common/posix/posix_file.c | 39 ++++++++++++++----- core/shared/platform/esp-idf/espidf_file.c | 39 ++++++++++++++----- .../platform/include/platform_api_extension.h | 27 +++++++++++++ core/shared/platform/windows/win_file.c | 18 +++++++++ 6 files changed, 138 insertions(+), 19 deletions(-) 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 627bbbb38..a313b9be5 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 @@ -459,8 +459,27 @@ fd_determine_type_rights(os_file_handle fd, __wasi_filetype_t *type, __wasi_rights_t *rights_inheriting) { struct __wasi_filestat_t buf; - __wasi_errno_t error = os_fstat(fd, &buf); + __wasi_errno_t error; + if (os_is_stdin_handle(fd)) { + *rights_base = RIGHTS_STDIN; + *rights_inheriting = RIGHTS_STDIN; + return __WASI_ESUCCESS; + } + + if (os_is_stdout_handle(fd)) { + *rights_base = RIGHTS_STDOUT; + *rights_inheriting = RIGHTS_STDOUT; + return __WASI_ESUCCESS; + } + + if (os_is_stderr_handle(fd)) { + *rights_base = RIGHTS_STDERR; + *rights_inheriting = RIGHTS_STDERR; + return __WASI_ESUCCESS; + } + + error = os_fstat(fd, &buf); if (error != __WASI_ESUCCESS) return error; diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h index 4f5838159..41ff56f27 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h @@ -47,6 +47,19 @@ #define RIGHTS_CHARACTER_DEVICE_BASE RIGHTS_ALL #define RIGHTS_CHARACTER_DEVICE_INHERITING RIGHTS_ALL +#define RIGHTS_STDIN \ + (__WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_FILESTAT_GET | \ + __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_WRITE | \ + __WASI_RIGHT_POLL_FD_READWRITE) + +#define RIGHTS_STDOUT \ + (__WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_DATASYNC | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_SYNC | \ + __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_WRITE | \ + __WASI_RIGHT_POLL_FD_READWRITE) + +#define RIGHTS_STDERR RIGHTS_STDOUT + // Only allow directory operations on directories. Directories can only // yield file descriptors to other directories and files. #define RIGHTS_DIRECTORY_BASE \ diff --git a/core/shared/platform/common/posix/posix_file.c b/core/shared/platform/common/posix/posix_file.c index e3aec9f4b..9ae0a03a2 100644 --- a/core/shared/platform/common/posix/posix_file.c +++ b/core/shared/platform/common/posix/posix_file.c @@ -54,6 +54,18 @@ #define CONFIG_HAS_O_SYNC #endif +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + // Converts a POSIX timespec to a WASI timestamp. static __wasi_timestamp_t convert_timespec(const struct timespec *ts) @@ -858,30 +870,39 @@ os_isatty(os_file_handle handle) #endif } +bool +os_is_stdin_handle(os_file_handle fd) +{ + return fd == STDIN_FILENO; +} + +bool +os_is_stdout_handle(os_file_handle fd) +{ + return fd == STDOUT_FILENO; +} + +bool +os_is_stderr_handle(os_file_handle fd) +{ + return fd == STDERR_FILENO; +} + os_file_handle os_convert_stdin_handle(os_raw_file_handle raw_stdin) { -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif return raw_stdin >= 0 ? raw_stdin : STDIN_FILENO; } os_file_handle os_convert_stdout_handle(os_raw_file_handle raw_stdout) { -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif return raw_stdout >= 0 ? raw_stdout : STDOUT_FILENO; } os_file_handle os_convert_stderr_handle(os_raw_file_handle raw_stderr) { -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif return raw_stderr >= 0 ? raw_stderr : STDERR_FILENO; } diff --git a/core/shared/platform/esp-idf/espidf_file.c b/core/shared/platform/esp-idf/espidf_file.c index ac7e58537..be50a2900 100644 --- a/core/shared/platform/esp-idf/espidf_file.c +++ b/core/shared/platform/esp-idf/espidf_file.c @@ -54,6 +54,18 @@ #define CONFIG_HAS_O_SYNC #endif +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + // Converts a POSIX timespec to a WASI timestamp. static __wasi_timestamp_t convert_timespec(const struct timespec *ts) @@ -858,30 +870,39 @@ os_isatty(os_file_handle handle) #endif } +bool +os_is_stdin_handle(os_file_handle fd) +{ + return fd == STDIN_FILENO; +} + +bool +os_is_stdout_handle(os_file_handle fd) +{ + return fd == STDOUT_FILENO; +} + +bool +os_is_stderr_handle(os_file_handle fd) +{ + return fd == STDERR_FILENO; +} + os_file_handle os_convert_stdin_handle(os_raw_file_handle raw_stdin) { -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif return raw_stdin >= 0 ? raw_stdin : STDIN_FILENO; } os_file_handle os_convert_stdout_handle(os_raw_file_handle raw_stdout) { -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif return raw_stdout >= 0 ? raw_stdout : STDOUT_FILENO; } os_file_handle os_convert_stderr_handle(os_raw_file_handle raw_stderr) { -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif return raw_stderr >= 0 ? raw_stderr : STDERR_FILENO; } diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 7c6120ba2..e165e5ef2 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -1502,6 +1502,33 @@ os_convert_stdout_handle(os_raw_file_handle raw_stdout); os_file_handle os_convert_stderr_handle(os_raw_file_handle raw_stderr); +/** + * + * @param fd a file handle + * + * @return true if it is stdin + */ +bool +os_is_stdin_handle(os_file_handle fd); + +/** + * + * @param fd a file handle + * + * @return true if it is stdout + */ +bool +os_is_stdout_handle(os_file_handle fd); + +/** + * + * @param fd a file handle + * + * @return true if it is stderr + */ +bool +os_is_stderr_handle(os_file_handle fd); + /** * Open a directory stream for the provided directory handle. The returned * directory stream will be positioned at the first entry in the directory. diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 63dfb5b5f..408d0d00c 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -1540,6 +1540,24 @@ create_stdio_handle(HANDLE raw_stdio_handle, DWORD stdio) return stdio_handle; } +bool +os_is_stdin_handle(os_file_handle fd) +{ + return fd->raw.handle == GetStdHandle(STD_INPUT_HANDLE); +} + +bool +os_is_stdout_handle(os_file_handle fd) +{ + return fd->raw.handle == GetStdHandle(STD_OUTPUT_HANDLE); +} + +bool +os_is_stderr_handle(os_file_handle fd) +{ + return fd->raw.handle == GetStdHandle(STD_ERROR_HANDLE); +} + os_file_handle os_convert_stdin_handle(os_raw_file_handle raw_stdin) { From a83adccd201bb363a5f9c5ef006ef723400572c1 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 13 Aug 2024 17:44:58 +0800 Subject: [PATCH 05/25] libc-builtin: Fix function prototype for wasm_runtime_module_realloc (#3702) Fix: ``` wamr/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c:20:1: warning: type of 'wasm_runtime_module_realloc' does not match original declaration [-Wlto-type-mismatch] wamr/core/iwasm/common/wasm_runtime_common.c:3033:1: note: return value type mismatch wamr/core/iwasm/common/wasm_runtime_common.c:3033:1: note: type 'uint64' should match type 'uint32' wamr/core/iwasm/common/wasm_runtime_common.c:3033:1: note: 'wasm_runtime_module_realloc' was previously declared here wamr/core/iwasm/common/wasm_runtime_common.c:3033:1: note: code may be misoptimized unless '-fno-strict-aliasing' is used ``` --- core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index 8db888fe3..a68c07494 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -16,7 +16,7 @@ void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); -uint32 +uint64 wasm_runtime_module_realloc(wasm_module_inst_t module, uint64 ptr, uint64 size, void **p_native_addr); @@ -683,9 +683,12 @@ calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size) static uint32 realloc_wrapper(wasm_exec_env_t exec_env, uint32 ptr, uint32 new_size) { + uint64 ret_offset = 0; wasm_module_inst_t module_inst = get_module_inst(exec_env); - return wasm_runtime_module_realloc(module_inst, ptr, new_size, NULL); + ret_offset = wasm_runtime_module_realloc(module_inst, ptr, new_size, NULL); + bh_assert(ret_offset < UINT32_MAX); + return (uint32)ret_offset; } static void From 37d7439ef9fb227a2afa778a79b3812d591c041a Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Wed, 14 Aug 2024 01:46:24 +0100 Subject: [PATCH 06/25] [refactoring] Extract read leb to a separate file, share the code between loader and mini loader (#3701) There's probably a number of other places where the bh_leb_read could be used (e.g. aot loader) but I'm making the change as small as possible. Further refactoring can be done later. --- core/iwasm/common/wasm_loader_common.c | 53 +++++++++++--- core/iwasm/common/wasm_loader_common.h | 8 +++ core/iwasm/interpreter/wasm_loader.c | 81 +--------------------- core/iwasm/interpreter/wasm_mini_loader.c | 69 +----------------- core/shared/utils/bh_leb128.c | 77 ++++++++++++++++++++ core/shared/utils/bh_leb128.h | 30 ++++++++ product-mini/platforms/alios-things/aos.mk | 1 + product-mini/platforms/nuttx/wamr.mk | 1 + tests/unit/shared-utils/bh_leb128_test.cc | 62 +++++++++++++++++ 9 files changed, 223 insertions(+), 159 deletions(-) create mode 100644 core/shared/utils/bh_leb128.c create mode 100644 core/shared/utils/bh_leb128.h create mode 100644 tests/unit/shared-utils/bh_leb128_test.cc diff --git a/core/iwasm/common/wasm_loader_common.c b/core/iwasm/common/wasm_loader_common.c index 179639fca..6dd31be2c 100644 --- a/core/iwasm/common/wasm_loader_common.c +++ b/core/iwasm/common/wasm_loader_common.c @@ -3,14 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #include "wasm_loader_common.h" +#include "bh_leb128.h" #include "bh_log.h" #if WASM_ENABLE_GC != 0 #include "../common/gc/gc_type.h" #endif -static void -set_error_buf(char *error_buf, uint32 error_buf_size, const char *string, - bool is_aot) +void +wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size, + const char *string, bool is_aot) { if (error_buf != NULL) { snprintf(error_buf, error_buf_size, "%s module load failed: %s", @@ -29,30 +30,30 @@ wasm_memory_check_flags(const uint8 mem_flag, char *error_buf, if (mem_flag & SHARED_MEMORY_FLAG) { LOG_VERBOSE("shared memory flag was found, please enable shared " "memory, lib-pthread or lib-wasi-threads"); - set_error_buf(error_buf, error_buf_size, "invalid limits flags", - is_aot); + wasm_loader_set_error_buf(error_buf, error_buf_size, + "invalid limits flags", is_aot); return false; } #endif #if WASM_ENABLE_MEMORY64 == 0 if (mem_flag & MEMORY64_FLAG) { LOG_VERBOSE("memory64 flag was found, please enable memory64"); - set_error_buf(error_buf, error_buf_size, "invalid limits flags", - is_aot); + wasm_loader_set_error_buf(error_buf, error_buf_size, + "invalid limits flags", is_aot); return false; } #endif } if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) { - set_error_buf(error_buf, error_buf_size, "invalid limits flags", - is_aot); + wasm_loader_set_error_buf(error_buf, error_buf_size, + "invalid limits flags", is_aot); return false; } else if ((mem_flag & SHARED_MEMORY_FLAG) && !(mem_flag & MAX_PAGE_COUNT_FLAG)) { - set_error_buf(error_buf, error_buf_size, - "shared memory must have maximum", is_aot); + wasm_loader_set_error_buf(error_buf, error_buf_size, + "shared memory must have maximum", is_aot); return false; } @@ -130,3 +131,33 @@ is_indices_overflow(uint32 import, uint32 other, char *error_buf, return false; } + +bool +read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, + uint64 *p_result, char *error_buf, uint32 error_buf_size) +{ + size_t offset = 0; + bh_leb_read_status_t status = + bh_leb_read(*p_buf, buf_end, maxbits, sign, p_result, &offset); + + switch (status) { + case BH_LEB_READ_SUCCESS: + *p_buf += offset; + return true; + case BH_LEB_READ_TOO_LONG: + wasm_loader_set_error_buf(error_buf, error_buf_size, + "integer representation too long", false); + return false; + case BH_LEB_READ_OVERFLOW: + wasm_loader_set_error_buf(error_buf, error_buf_size, + "integer too large", false); + return false; + case BH_LEB_READ_UNEXPECTED_END: + wasm_loader_set_error_buf(error_buf, error_buf_size, + "unexpected end", false); + return false; + default: + bh_assert(false); + return false; + } +} diff --git a/core/iwasm/common/wasm_loader_common.h b/core/iwasm/common/wasm_loader_common.h index 6bd0cf6c2..d574110ba 100644 --- a/core/iwasm/common/wasm_loader_common.h +++ b/core/iwasm/common/wasm_loader_common.h @@ -30,6 +30,14 @@ bool is_indices_overflow(uint32 import, uint32 other, char *error_buf, uint32 error_buf_size); +bool +read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, + uint64 *p_result, char *error_buf, uint32 error_buf_size); + +void +wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size, + const char *string, bool is_aot); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 785b28980..10324ac45 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -56,10 +56,7 @@ has_module_memory64(WASMModule *module) static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { - if (error_buf != NULL) { - snprintf(error_buf, error_buf_size, "WASM module load failed: %s", - string); - } + wasm_loader_set_error_buf(error_buf, error_buf_size, string, false); } #if WASM_ENABLE_MEMORY64 != 0 @@ -131,82 +128,6 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, #define skip_leb_int32(p, p_end) skip_leb(p) #define skip_leb_mem_offset(p, p_end) skip_leb(p) -static bool -read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, - uint64 *p_result, char *error_buf, uint32 error_buf_size) -{ - const uint8 *buf = *p_buf; - uint64 result = 0; - uint32 shift = 0; - uint32 offset = 0, bcnt = 0; - uint64 byte; - - while (true) { - /* uN or SN must not exceed ceil(N/7) bytes */ - if (bcnt + 1 > (maxbits + 6) / 7) { - set_error_buf(error_buf, error_buf_size, - "integer representation too long"); - return false; - } - - CHECK_BUF(buf, buf_end, offset + 1); - byte = buf[offset]; - offset += 1; - result |= ((byte & 0x7f) << shift); - shift += 7; - bcnt += 1; - if ((byte & 0x80) == 0) { - break; - } - } - - if (!sign && maxbits == 32 && shift >= maxbits) { - /* The top bits set represent values > 32 bits */ - if (((uint8)byte) & 0xf0) - goto fail_integer_too_large; - } - else if (sign && maxbits == 32) { - if (shift < maxbits) { - /* Sign extend, second-highest bit is the sign bit */ - if ((uint8)byte & 0x40) - result |= (~((uint64)0)) << shift; - } - else { - /* The top bits should be a sign-extension of the sign bit */ - bool sign_bit_set = ((uint8)byte) & 0x8; - int top_bits = ((uint8)byte) & 0xf0; - if ((sign_bit_set && top_bits != 0x70) - || (!sign_bit_set && top_bits != 0)) - goto fail_integer_too_large; - } - } - else if (sign && maxbits == 64) { - if (shift < maxbits) { - /* Sign extend, second-highest bit is the sign bit */ - if ((uint8)byte & 0x40) - result |= (~((uint64)0)) << shift; - } - else { - /* The top bits should be a sign-extension of the sign bit */ - bool sign_bit_set = ((uint8)byte) & 0x1; - int top_bits = ((uint8)byte) & 0xfe; - - if ((sign_bit_set && top_bits != 0x7e) - || (!sign_bit_set && top_bits != 0)) - goto fail_integer_too_large; - } - } - - *p_buf += offset; - *p_result = result; - return true; - -fail_integer_too_large: - set_error_buf(error_buf, error_buf_size, "integer too large"); -fail: - return false; -} - #define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) #define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p) diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 0012b84ae..6e70203fa 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -44,9 +44,7 @@ has_module_memory64(WASMModule *module) static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { - if (error_buf != NULL) - snprintf(error_buf, error_buf_size, "WASM module load failed: %s", - string); + wasm_loader_set_error_buf(error_buf, error_buf_size, string, false); } #define CHECK_BUF(buf, buf_end, length) \ @@ -95,71 +93,6 @@ is_byte_a_type(uint8 type) || (type == VALUE_TYPE_VOID); } -static void -read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, - uint64 *p_result, char *error_buf, uint32 error_buf_size) -{ - const uint8 *buf = *p_buf; - uint64 result = 0; - uint32 shift = 0; - uint32 offset = 0, bcnt = 0; - uint64 byte; - - while (true) { - bh_assert(bcnt + 1 <= (maxbits + 6) / 7); - CHECK_BUF(buf, buf_end, offset + 1); - byte = buf[offset]; - offset += 1; - result |= ((byte & 0x7f) << shift); - shift += 7; - bcnt += 1; - if ((byte & 0x80) == 0) { - break; - } - } - - if (!sign && maxbits == 32 && shift >= maxbits) { - /* The top bits set represent values > 32 bits */ - bh_assert(!(((uint8)byte) & 0xf0)); - } - else if (sign && maxbits == 32) { - if (shift < maxbits) { - /* Sign extend, second-highest bit is the sign bit */ - if ((uint8)byte & 0x40) - result |= (~((uint64)0)) << shift; - } - else { - /* The top bits should be a sign-extension of the sign bit */ - bool sign_bit_set = ((uint8)byte) & 0x8; - int top_bits = ((uint8)byte) & 0xf0; - bh_assert(!((sign_bit_set && top_bits != 0x70) - || (!sign_bit_set && top_bits != 0))); - (void)top_bits; - (void)sign_bit_set; - } - } - else if (sign && maxbits == 64) { - if (shift < maxbits) { - /* Sign extend, second-highest bit is the sign bit */ - if ((uint8)byte & 0x40) - result |= (~((uint64)0)) << shift; - } - else { - /* The top bits should be a sign-extension of the sign bit */ - bool sign_bit_set = ((uint8)byte) & 0x1; - int top_bits = ((uint8)byte) & 0xfe; - - bh_assert(!((sign_bit_set && top_bits != 0x7e) - || (!sign_bit_set && top_bits != 0))); - (void)top_bits; - (void)sign_bit_set; - } - } - - *p_buf += offset; - *p_result = result; -} - #define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) #define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p) #define read_bool(p) TEMPLATE_READ_VALUE(bool, p) diff --git a/core/shared/utils/bh_leb128.c b/core/shared/utils/bh_leb128.c new file mode 100644 index 000000000..8e4b13dce --- /dev/null +++ b/core/shared/utils/bh_leb128.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_leb128.h" + +bh_leb_read_status_t +bh_leb_read(const uint8 *buf, const uint8 *buf_end, uint32 maxbits, bool sign, + uint64 *p_result, size_t *p_offset) +{ + uint64 result = 0; + uint32 shift = 0; + uint32 offset = 0, bcnt = 0; + uint64 byte; + + while (true) { + /* uN or SN must not exceed ceil(N/7) bytes */ + if (bcnt + 1 > (maxbits + 6) / 7) { + return BH_LEB_READ_TOO_LONG; + } + + if ((uintptr_t)buf + offset + 1 < (uintptr_t)buf + || (uintptr_t)buf + offset + 1 > (uintptr_t)buf_end) { + return BH_LEB_READ_UNEXPECTED_END; + } + byte = buf[offset]; + offset += 1; + result |= ((byte & 0x7f) << shift); + shift += 7; + bcnt += 1; + if ((byte & 0x80) == 0) { + break; + } + } + + if (!sign && maxbits == 32 && shift >= maxbits) { + /* The top bits set represent values > 32 bits */ + if (((uint8)byte) & 0xf0) + return BH_LEB_READ_OVERFLOW; + } + else if (sign && maxbits == 32) { + if (shift < maxbits) { + /* Sign extend, second-highest bit is the sign bit */ + if ((uint8)byte & 0x40) + result |= (~((uint64)0)) << shift; + } + else { + /* The top bits should be a sign-extension of the sign bit */ + bool sign_bit_set = ((uint8)byte) & 0x8; + int top_bits = ((uint8)byte) & 0xf0; + if ((sign_bit_set && top_bits != 0x70) + || (!sign_bit_set && top_bits != 0)) + return BH_LEB_READ_OVERFLOW; + } + } + else if (sign && maxbits == 64) { + if (shift < maxbits) { + /* Sign extend, second-highest bit is the sign bit */ + if ((uint8)byte & 0x40) + result |= (~((uint64)0)) << shift; + } + else { + /* The top bits should be a sign-extension of the sign bit */ + bool sign_bit_set = ((uint8)byte) & 0x1; + int top_bits = ((uint8)byte) & 0xfe; + + if ((sign_bit_set && top_bits != 0x7e) + || (!sign_bit_set && top_bits != 0)) + return BH_LEB_READ_OVERFLOW; + } + } + + *p_offset = offset; + *p_result = result; + return BH_LEB_READ_SUCCESS; +} \ No newline at end of file diff --git a/core/shared/utils/bh_leb128.h b/core/shared/utils/bh_leb128.h new file mode 100644 index 000000000..ce73b4b88 --- /dev/null +++ b/core/shared/utils/bh_leb128.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BH_LEB128_H +#define _BH_LEB128_H + +#include "bh_platform.h" + +typedef enum { + BH_LEB_READ_SUCCESS, + BH_LEB_READ_TOO_LONG, + BH_LEB_READ_OVERFLOW, + BH_LEB_READ_UNEXPECTED_END, +} bh_leb_read_status_t; + +#ifdef __cplusplus +extern "C" { +#endif + +bh_leb_read_status_t +bh_leb_read(const uint8 *buf, const uint8 *buf_end, uint32 maxbits, bool sign, + uint64 *p_result, size_t *p_offset); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/product-mini/platforms/alios-things/aos.mk b/product-mini/platforms/alios-things/aos.mk index 947a4a91a..7d98ca0b8 100644 --- a/product-mini/platforms/alios-things/aos.mk +++ b/product-mini/platforms/alios-things/aos.mk @@ -102,6 +102,7 @@ $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/alios_platform.c \ ${SHARED_ROOT}/utils/bh_common.c \ ${SHARED_ROOT}/utils/bh_hashmap.c \ ${SHARED_ROOT}/utils/bh_list.c \ + ${SHARED_ROOT}/utils/bh_leb128.c \ ${SHARED_ROOT}/utils/bh_log.c \ ${SHARED_ROOT}/utils/bh_queue.c \ ${SHARED_ROOT}/utils/bh_vector.c \ diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 75bd69bef..96a3e2ab7 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -441,6 +441,7 @@ CSRCS += nuttx_platform.c \ bh_common.c \ bh_hashmap.c \ bh_list.c \ + bh_leb128.c \ bh_log.c \ bh_queue.c \ bh_vector.c \ diff --git a/tests/unit/shared-utils/bh_leb128_test.cc b/tests/unit/shared-utils/bh_leb128_test.cc new file mode 100644 index 000000000..f53864646 --- /dev/null +++ b/tests/unit/shared-utils/bh_leb128_test.cc @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_leb128.h" +#include "gtest/gtest.h" + +#include +#include + +template +void +run_read_leb_test(std::vector data, + bh_leb_read_status_t expected_status, T expected_value) +{ + size_t offset = 0; + uint64 value; + bh_leb_read_status_t status = + bh_leb_read(data.data(), data.data() + data.size(), sizeof(T) * 8, + std::is_signed::value, &value, &offset); + ASSERT_EQ(expected_status, status); + if (status == BH_LEB_READ_SUCCESS) { + ASSERT_EQ(data.size(), offset); + ASSERT_EQ(expected_value, (T)value); + } +} + +TEST(bh_leb128_test_suite, read_leb_u32) +{ + run_read_leb_test({ 0 }, BH_LEB_READ_SUCCESS, + 0); // min value + run_read_leb_test({ 2 }, BH_LEB_READ_SUCCESS, + 2); // single-byte value + run_read_leb_test({ 127 }, BH_LEB_READ_SUCCESS, + 127); // max single-byte value + run_read_leb_test({ 128, 1 }, BH_LEB_READ_SUCCESS, + 128); // min value with continuation bit + run_read_leb_test({ 160, 138, 32 }, BH_LEB_READ_SUCCESS, + 525600); // arbitrary value + run_read_leb_test({ 255, 255, 255, 255, 15 }, BH_LEB_READ_SUCCESS, + UINT32_MAX); // max value + run_read_leb_test({ 255, 255, 255, 255, 16 }, BH_LEB_READ_OVERFLOW, + UINT32_MAX); // overflow + run_read_leb_test({ 255, 255, 255, 255, 128 }, BH_LEB_READ_TOO_LONG, + 0); + run_read_leb_test({ 128 }, BH_LEB_READ_UNEXPECTED_END, 0); +} + +TEST(bh_leb128_test_suite, read_leb_i64) +{ + run_read_leb_test({ 184, 188, 195, 159, 237, 209, 128, 2 }, + BH_LEB_READ_SUCCESS, + 1128712371232312); // arbitrary value + run_read_leb_test( + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 127 }, + BH_LEB_READ_SUCCESS, + (uint64)INT64_MIN); // min value + run_read_leb_test({ 255, 255, 255, 255, 255, 255, 255, 255, 255, 0 }, + BH_LEB_READ_SUCCESS, + INT64_MAX); // max value +} \ No newline at end of file From da25906ed4faa5d559a570de807bcb2ea0df1c3b Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 14 Aug 2024 09:03:01 +0800 Subject: [PATCH 07/25] debug-interp: Only add lock when signal_flag is SIG_SINGSTEP (#3704) As reported in #3500, when debug interpreter is enabled, the classic interpreter performs a lock operation to read `exec_env->current_status->signal_flag` and do further handling before fetching next opcode, which makes the interpreter run slower. This PR atomic loads the `exec_env->current_status->signal_flag` without mutex lock when 32-bit atomic load is supported, and only adding lock for further handling when the signal_flag is WAMR_SIG_SINGSTEP, which improves the performance. --- core/iwasm/interpreter/wasm_interp_classic.c | 81 +++++++++++++------ .../libraries/thread-mgr/thread_manager.h | 6 +- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index bd8a4eeb1..f2d6b7e7b 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1399,26 +1399,48 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #endif /* WASM_ENABLE_DEBUG_INTERP */ #endif /* WASM_ENABLE_THREAD_MGR */ +#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 +#if BH_ATOMIC_32_IS_ATOMIC != 0 +#define GET_SIGNAL_FLAG() \ + do { \ + signal_flag = \ + BH_ATOMIC_32_LOAD(exec_env->current_status->signal_flag); \ + } while (0) +#else +#define GET_SIGNAL_FLAG() \ + do { \ + os_mutex_lock(&exec_env->wait_lock); \ + signal_flag = exec_env->current_status->signal_flag; \ + os_mutex_unlock(&exec_env->wait_lock); \ + } while (0) +#endif +#endif + #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OP(opcode) HANDLE_##opcode: #define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++] #if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 -#define HANDLE_OP_END() \ - do { \ - /* Record the current frame_ip, so when exception occurs, \ - debugger can know the exact opcode who caused the exception */ \ - frame_ip_orig = frame_ip; \ - os_mutex_lock(&exec_env->wait_lock); \ - while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ - && exec_env->current_status->step_count++ == 1) { \ - exec_env->current_status->step_count = 0; \ - SYNC_ALL_TO_FRAME(); \ - wasm_cluster_thread_waiting_run(exec_env); \ - } \ - os_mutex_unlock(&exec_env->wait_lock); \ - goto *handle_table[*frame_ip++]; \ +#define HANDLE_OP_END() \ + do { \ + /* Record the current frame_ip, so when exception occurs, \ + debugger can know the exact opcode who caused the exception */ \ + frame_ip_orig = frame_ip; \ + /* Atomic load the exec_env's signal_flag first, and then handle \ + more with lock if it is WAMR_SIG_SINGSTEP */ \ + GET_SIGNAL_FLAG(); \ + if (signal_flag == WAMR_SIG_SINGSTEP) { \ + os_mutex_lock(&exec_env->wait_lock); \ + while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ + && exec_env->current_status->step_count++ == 1) { \ + exec_env->current_status->step_count = 0; \ + SYNC_ALL_TO_FRAME(); \ + wasm_cluster_thread_waiting_run(exec_env); \ + } \ + os_mutex_unlock(&exec_env->wait_lock); \ + } \ + goto *handle_table[*frame_ip++]; \ } while (0) #else #define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() @@ -1427,16 +1449,24 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #define HANDLE_OP(opcode) case opcode: #if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 -#define HANDLE_OP_END() \ - os_mutex_lock(&exec_env->wait_lock); \ - if (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ - && exec_env->current_status->step_count++ == 1) { \ - exec_env->current_status->step_count = 0; \ - SYNC_ALL_TO_FRAME(); \ - wasm_cluster_thread_waiting_run(exec_env); \ - } \ - os_mutex_unlock(&exec_env->wait_lock); \ - continue +#define HANDLE_OP_END() \ + /* Record the current frame_ip, so when exception occurs, \ + debugger can know the exact opcode who caused the exception */ \ + frame_ip_orig = frame_ip; \ + /* Atomic load the exec_env's signal_flag first, and then handle \ + more with lock if it is WAMR_SIG_SINGSTEP */ \ + GET_SIGNAL_FLAG(); \ + if (signal_flag == WAMR_SIG_SINGSTEP) { \ + os_mutex_lock(&exec_env->wait_lock); \ + while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ + && exec_env->current_status->step_count++ == 1) { \ + exec_env->current_status->step_count = 0; \ + SYNC_ALL_TO_FRAME(); \ + wasm_cluster_thread_waiting_run(exec_env); \ + } \ + os_mutex_unlock(&exec_env->wait_lock); \ + } \ + continue; #else #define HANDLE_OP_END() continue #endif @@ -1545,6 +1575,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, debug_instance ? &debug_instance->watch_point_list_read : NULL; bh_list *watch_point_list_write = debug_instance ? &debug_instance->watch_point_list_write : NULL; +#if WASM_ENABLE_THREAD_MGR != 0 + uint32 signal_flag; +#endif #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 0cbba888f..f5ca1eaed 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -184,9 +184,9 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env); ((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP) struct WASMCurrentEnvStatus { - uint64 signal_flag : 32; - uint64 step_count : 16; - uint64 running_status : 16; + uint32 signal_flag; + uint16 step_count; + uint16 running_status; }; WASMCurrentEnvStatus * From 5b8dfbce7502ad4ab93e3e55ecfa2069c7d5eee8 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 14 Aug 2024 01:08:10 -0700 Subject: [PATCH 08/25] Fix compilation warnings (#3707) Compilation warnings were reported on mac: ``` core/shared/mem-alloc/ems/ems_gc.c:454:22: warning: passing arguments to 'wasm_runtime_gc_prepare' without a prototype is deprecated in all versions of C and is not supported in C2x [-Wdeprecated-non-prototype] gct_vm_gc_prepare(NULL); ^ core/shared/mem-alloc/ems/ems_gc.c:466:23: warning: passing arguments to 'wasm_runtime_gc_finalize' without a prototype is deprecated in all versions of C and is not supported in C2x [-Wdeprecated-non-prototype] gct_vm_gc_finished(NULL); ^ 2 warnings generated. ``` --- core/shared/mem-alloc/ems/ems_gc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/shared/mem-alloc/ems/ems_gc.h b/core/shared/mem-alloc/ems/ems_gc.h index 59cc00285..ff65b4e7c 100644 --- a/core/shared/mem-alloc/ems/ems_gc.h +++ b/core/shared/mem-alloc/ems/ems_gc.h @@ -309,10 +309,10 @@ void wasm_runtime_set_wasm_object_extra_info_flag(gc_object_t obj, bool set); void -wasm_runtime_gc_prepare(); +wasm_runtime_gc_prepare(void *exec_env); void -wasm_runtime_gc_finalize(); +wasm_runtime_gc_finalize(void *exec_env); #endif /* end of WASM_ENABLE_GC != 0 */ #define GC_HEAP_STAT_SIZE (128 / 4) From cce48a09436465191c760f1407df3ae9fb7d09cc Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 14 Aug 2024 16:20:32 +0800 Subject: [PATCH 09/25] test_wamr.sh: Fix build wabt tool (#3703) And fix a typo in ATTRIBUTIONS.md. --- ATTRIBUTIONS.md | 2 +- tests/wamr-test-suites/test_wamr.sh | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index b6e556d2b..cba0e5c4b 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -16,7 +16,7 @@ WAMR project reused some components from other open source project: - **asmjit**: for the Fast JIT x86-64 codegen implementation - **zydis**: for the Fast JIT x86-64 codegen implementation - **NuttX ELF headers**: used in core/iwasm/aot/debug/elf_parser.c -- **Dhrystone**: for the test benchmakr dhrystone +- **Dhrystone**: for the test benchmark dhrystone The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated operand stack location. diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index ee0dd7bbc..54e2ac1a7 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -409,12 +409,13 @@ function setup_wabt() git clone --recursive https://github.com/WebAssembly/wabt fi echo "upate wabt" - cd wabt - git fetch origin - git reset --hard origin/main - git checkout tags/${WABT_VERSION} -B ${WABT_VERSION} - cd .. - make -C wabt gcc-release -j 4 || exit 1 + cd wabt \ + && git fetch origin \ + && git reset --hard origin/main \ + && git checkout tags/${WABT_VERSION} -B ${WABT_VERSION} \ + && git submodule update --init \ + && cd .. \ + && make -C wabt gcc-release -j 4 || exit 1 fi } From 740f499e9c2930aa202b1b7e294da9256eeba46d Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 14 Aug 2024 18:11:18 +0800 Subject: [PATCH 10/25] Fix potential memory leak in insert_native_symbol (#3712) --- core/iwasm/compilation/aot_llvm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index fcf291919..d52a486a0 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -3288,6 +3288,7 @@ insert_native_symbol(AOTCompContext *comp_ctx, const char *symbol, int32 idx) bh_assert(strlen(symbol) <= sizeof(sym->symbol)); ret = snprintf(sym->symbol, sizeof(sym->symbol), "%s", symbol); if (ret < 0 || ret + 1 > (int)sizeof(sym->symbol)) { + wasm_runtime_free(sym); aot_set_last_error_v("symbol name too long: %s", symbol); return false; } From 000680f090c3ac2af0193244b8d587feb01b78cb Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 15 Aug 2024 14:49:50 +0800 Subject: [PATCH 11/25] NuttX: Retire CONFIG_ARCH_RV32IM and CONFIG_ARCH_RV64GC (#3717) These symbols had been removed from NuttX in 2022, so it's time to remove references to them. --- product-mini/platforms/nuttx/CMakeLists.txt | 4 ++-- product-mini/platforms/nuttx/wamr.mk | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/product-mini/platforms/nuttx/CMakeLists.txt b/product-mini/platforms/nuttx/CMakeLists.txt index e9fe5a9e3..ac6c47b91 100644 --- a/product-mini/platforms/nuttx/CMakeLists.txt +++ b/product-mini/platforms/nuttx/CMakeLists.txt @@ -18,9 +18,9 @@ elseif(CONFIG_ARCH_X86_64) set(WAMR_BUILD_TARGET X86_64) elseif(CONFIG_ARCH_XTENSA) set(WAMR_BUILD_TARGET XTENSA) -elseif(CONFIG_ARCH_RV64GC OR CONFIG_ARCH_RV64) +elseif(CONFIG_ARCH_RV64) set(WAMR_BUILD_TARGET RISCV64) -elseif(CONFIG_ARCH_RV32IM OR CONFIG_ARCH_RV32) +elseif(CONFIG_ARCH_RV32) set(WAMR_BUILD_TARGET RISCV32) elseif(CONFIG_ARCH_SIM) if(CONFIG_SIM_M32 OR CONFIG_HOST_X86) diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 96a3e2ab7..6e1f9ff7e 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -21,12 +21,6 @@ else ifeq ($(CONFIG_ARCH_X86_64),y) WAMR_BUILD_TARGET := X86_64 else ifeq ($(CONFIG_ARCH_XTENSA),y) WAMR_BUILD_TARGET := XTENSA -# RV64GC and RV32IM used in older -# version NuttX -else ifeq ($(CONFIG_ARCH_RV64GC),y) -WAMR_BUILD_TARGET := RISCV64 -else ifeq ($(CONFIG_ARCH_RV32IM),y) -WAMR_BUILD_TARGET := RISCV32 else ifeq ($(CONFIG_ARCH_RV64),y) WAMR_BUILD_TARGET := RISCV64 else ifeq ($(CONFIG_ARCH_RV32),y) From 58ca02bc5face02a55ce2797235a26d254f2aa34 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 15 Aug 2024 15:17:42 +0800 Subject: [PATCH 12/25] Add support for RISCV32 ILP32F (#3708) --- .github/workflows/spec_test_on_nuttx.yml | 9 ++++ build-scripts/config_common.cmake | 2 + core/config.h | 7 ++- core/iwasm/common/wasm_runtime_common.c | 60 +++++++++++++++++++----- doc/build_wamr.md | 2 +- product-mini/platforms/nuttx/wamr.mk | 6 +-- wamr-compiler/CMakeLists.txt | 2 + 7 files changed, 71 insertions(+), 17 deletions(-) diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 1ae3bdf04..059e5fbef 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -74,6 +74,11 @@ jobs: target: "riscv32", fpu_type: "none" }, + { + config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh", + target: "riscv32_ilp32f", + fpu_type: "fp" + }, # { # config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh", # target: "riscv32_ilp32d", @@ -120,6 +125,10 @@ jobs: - target_config: { config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64" } wamr_test_option: { mode: "-t aot -X" } + # XIP is not fully supported yet on RISCV32 ILP32F, some relocations can not be resolved + - target_config: { config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh", fpu_type: "fp" } + wamr_test_option: { mode: "-t aot -X" } + # Our xtensa environment doesn't have enough memory - target_config: { target: "xtensa" } wamr_feature_option: { mode: "-G" } diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 10d1289eb..d4dd2c0d6 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -39,6 +39,8 @@ elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64") add_definitions(-DBUILD_TARGET_RISCV64_LP64) elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D") add_definitions(-DBUILD_TARGET_RISCV32_ILP32D) +elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32F") + add_definitions(-DBUILD_TARGET_RISCV32_ILP32F) elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32") add_definitions(-DBUILD_TARGET_RISCV32_ILP32) elseif (WAMR_BUILD_TARGET STREQUAL "ARC") diff --git a/core/config.h b/core/config.h index 9fd540f32..7c783dd32 100644 --- a/core/config.h +++ b/core/config.h @@ -20,6 +20,7 @@ && !defined(BUILD_TARGET_RISCV64_LP64D) \ && !defined(BUILD_TARGET_RISCV64_LP64) \ && !defined(BUILD_TARGET_RISCV32_ILP32D) \ + && !defined(BUILD_TARGET_RISCV32_ILP32F) \ && !defined(BUILD_TARGET_RISCV32_ILP32) \ && !defined(BUILD_TARGET_ARC) /* clang-format on */ @@ -43,7 +44,11 @@ #define BUILD_TARGET_XTENSA #elif defined(__riscv) && (__riscv_xlen == 64) #define BUILD_TARGET_RISCV64_LP64D -#elif defined(__riscv) && (__riscv_xlen == 32) +#elif defined(__riscv) && (__riscv_xlen == 32) && !defined(__riscv_flen) +#define BUILD_TARGET_RISCV32_ILP32 +#elif defined(__riscv) && (__riscv_xlen == 32) && (__riscv_flen == 32) +#define BUILD_TARGET_RISCV32_ILP32F +#elif defined(__riscv) && (__riscv_xlen == 32) && (__riscv_flen == 64) #define BUILD_TARGET_RISCV32_ILP32D #elif defined(__arc__) #define BUILD_TARGET_ARC diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8ed14ec40..37a89f8fb 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -4718,9 +4718,13 @@ fail: * Implementation of wasm_runtime_invoke_native() */ -/* The invoke native implementation on ARM platform with VFP co-processor */ +/** + * The invoke native implementation on ARM platform with VFP co-processor, + * RISCV32 platform with/without FPU/DPFPU and ARC platform. + */ #if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) \ || defined(BUILD_TARGET_RISCV32_ILP32D) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) \ || defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) typedef void (*GenericFunctionPointer)(); void @@ -4821,7 +4825,8 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, #endif n_ints += 2; } -#if defined(BUILD_TARGET_RISCV32_ILP32) \ +#if defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) \ || defined(BUILD_TARGET_RISCV32_ILP32D) || defined(BUILD_TARGET_ARC) /* part in register, part in stack */ else if (n_ints == MAX_REG_INTS - 1) { @@ -4843,19 +4848,32 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_F32: if (n_fps < MAX_REG_FLOATS) n_fps++; +#if defined(BUILD_TARGET_RISCV32_ILP32F) + else if (n_ints < MAX_REG_INTS) { + n_ints++; + } +#endif else n_stacks++; break; case VALUE_TYPE_F64: +#if defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) || defined(BUILD_TARGET_ARC) + if (n_ints < MAX_REG_INTS - 1) { + n_ints += 2; + } + else if (n_ints == MAX_REG_INTS - 1) { + n_ints++; + n_stacks++; + } +#endif +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) if (n_fps < MAX_REG_FLOATS - 1) { -#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC) /* 64-bit data must be 8 bytes aligned in arm */ if (n_fps & 1) n_fps++; -#endif n_fps += 2; } -#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) else if (n_fps == MAX_REG_FLOATS - 1) { n_fps++; n_stacks++; @@ -4887,7 +4905,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* use int regs firstly if available */ if (n_ints & 1) n_ints++; - ints += 2; + n_ints += 2; } else { /* 64-bit data in stack must be 8 bytes aligned in riscv32 @@ -4911,7 +4929,8 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, n_stacks++; } -#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) argc1 = MAX_REG_INTS + MAX_REG_FLOATS + n_stacks; #elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) argc1 = MAX_REG_INTS + n_stacks; @@ -4928,7 +4947,8 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } ints = argv1; -#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) fps = ints + MAX_REG_INTS; stacks = fps + MAX_REG_FLOATS; #elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) @@ -5018,7 +5038,8 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, ints[n_ints++] = *argv_src++; ints[n_ints++] = *argv_src++; } -#if defined(BUILD_TARGET_RISCV32_ILP32) \ +#if defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) \ || defined(BUILD_TARGET_RISCV32_ILP32D) || defined(BUILD_TARGET_ARC) else if (n_ints == MAX_REG_INTS - 1) { ints[n_ints++] = *argv_src++; @@ -5042,22 +5063,36 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, { if (n_fps < MAX_REG_FLOATS) *(float32 *)&fps[n_fps++] = *(float32 *)argv_src++; +#if defined(BUILD_TARGET_RISCV32_ILP32F) + else if (n_ints < MAX_REG_INTS) { + ints[n_ints++] = *argv_src++; + } +#endif else *(float32 *)&stacks[n_stacks++] = *(float32 *)argv_src++; break; } case VALUE_TYPE_F64: { +#if defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) || defined(BUILD_TARGET_ARC) + if (n_ints < MAX_REG_INTS - 1) { + ints[n_ints++] = *argv_src++; + ints[n_ints++] = *argv_src++; + } + else if (n_ints == MAX_REG_INTS - 1) { + ints[n_ints++] = *argv_src++; + stacks[n_stacks++] = *argv_src++; + } +#endif +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) if (n_fps < MAX_REG_FLOATS - 1) { -#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC) /* 64-bit data must be 8 bytes aligned in arm */ if (n_fps & 1) n_fps++; -#endif fps[n_fps++] = *argv_src++; fps[n_fps++] = *argv_src++; } -#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) else if (n_fps == MAX_REG_FLOATS - 1) { fps[n_fps++] = *argv_src++; stacks[n_stacks++] = *argv_src++; @@ -5249,6 +5284,7 @@ fail: #endif /* end of defined(BUILD_TARGET_ARM_VFP) \ || defined(BUILD_TARGET_THUMB_VFP) \ || defined(BUILD_TARGET_RISCV32_ILP32D) \ + || defined(BUILD_TARGET_RISCV32_ILP32F) \ || defined(BUILD_TARGET_RISCV32_ILP32) \ || defined(BUILD_TARGET_ARC) */ diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 181f32ca0..2adb17f6a 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -28,7 +28,7 @@ The script `runtime_lib.cmake` defines a number of variables for configuring the - For ARM and THUMB, the format is \\[\]\[_VFP], where \ is the ARM sub-architecture and the "_VFP" suffix means using VFP coprocessor registers s0-s15 (d0-d7) for passing arguments or returning results in standard procedure-call. Both \ and "_VFP" are optional, e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. - For AARCH64, the format is\[\], VFP is enabled by default. \ is optional, e.g. AARCH64, AARCH64V8, AARCH64V8.1 and so on. - For RISCV64, the format is \[_abi], where "_abi" is optional, currently the supported formats are RISCV64, RISCV64_LP64D and RISCV64_LP64: RISCV64 and RISCV64_LP64D are identical, using [LP64D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (LP64 with hardware floating-point calling convention for FLEN=64). And RISCV64_LP64 uses [LP64](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). - - For RISCV32, the format is \[_abi], where "_abi" is optional, currently the supported formats are RISCV32, RISCV32_ILP32D and RISCV32_ILP32: RISCV32 and RISCV32_ILP32D are identical, using [ILP32D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (ILP32 with hardware floating-point calling convention for FLEN=64). And RISCV32_ILP32 uses [ILP32](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). + - For RISCV32, the format is \[_abi], where "_abi" is optional, currently the supported formats are RISCV32, RISCV32_ILP32D, RISCV32_ILP32F and RISCV32_ILP32: RISCV32 and RISCV32_ILP32D are identical, using [ILP32D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (ILP32 with hardware floating-point calling convention for FLEN=64). RISCV32_ILP32F uses [ILP32F](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (ILP32 with hardware floating-point calling convention for FLEN=32). And RISCV32_ILP32 uses [ILP32](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). ```bash cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 6e1f9ff7e..38553e863 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -101,10 +101,10 @@ else ifeq (${WAMR_BUILD_TARGET}, RISCV32) ifeq (${CONFIG_ARCH_DPFPU},y) CFLAGS += -DBUILD_TARGET_RISCV32_ILP32D -else ifneq (${CONFIG_ARCH_FPU},y) - CFLAGS += -DBUILD_TARGET_RISCV32_ILP32 +else ifeq (${CONFIG_ARCH_FPU},y) + CFLAGS += -DBUILD_TARGET_RISCV32_ILP32F else - $(error riscv32 ilp32f is unsupported) + CFLAGS += -DBUILD_TARGET_RISCV32_ILP32 endif INVOKE_NATIVE += invokeNative_riscv.S diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 245b4a031..2ab0462b2 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -121,6 +121,8 @@ elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64") add_definitions(-DBUILD_TARGET_RISCV64_LP64) elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D") add_definitions(-DBUILD_TARGET_RISCV32_ILP32D) +elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32F") + add_definitions(-DBUILD_TARGET_RISCV32_ILP32F) elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32") add_definitions(-DBUILD_TARGET_RISCV32_ILP32) else () From b845e2ede456fa7231f918f74debbedd61b68d36 Mon Sep 17 00:00:00 2001 From: James Ring Date: Thu, 15 Aug 2024 15:56:49 -0700 Subject: [PATCH 13/25] Add missing headers in bh_atomic.h and aot_llvm_extra.cpp (#3715) --- core/iwasm/compilation/aot_llvm_extra.cpp | 3 +++ core/shared/utils/bh_atomic.h | 1 + 2 files changed, 4 insertions(+) diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index fdd5517b9..fc0ece069 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -41,6 +41,9 @@ #include #include #include +#if LLVM_VERSION_MAJOR >= 17 +#include +#endif #include #include #include diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index 4f7d9bc83..5148497f8 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -6,6 +6,7 @@ #ifndef _BH_ATOMIC_H #define _BH_ATOMIC_H +#include "bh_platform.h" #include "gnuc.h" #ifdef __cplusplus From 63df2cf02d79183ba942f43963502675c3e9c172 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Fri, 16 Aug 2024 10:12:23 +0800 Subject: [PATCH 14/25] Update std atomic check and simd compatibility check for arc compiler (#3716) --- core/iwasm/compilation/aot_llvm.c | 3 ++- core/iwasm/compilation/aot_llvm_extra.cpp | 3 +++ core/shared/platform/include/platform_api_extension.h | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index d52a486a0..8c989ed6e 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -3121,7 +3121,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) #endif if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0 - && strncmp(comp_ctx->target_arch, "aarch64", 7) != 0) { + && strncmp(comp_ctx->target_arch, "aarch64", 7) != 0 + && strcmp(comp_ctx->target_arch, "arc") != 0) { /* Disable simd if it isn't supported by target arch */ option->enable_simd = false; } diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index fc0ece069..e6770eb45 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -176,6 +176,9 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str) else if (targetArch == llvm::Triple::aarch64) { return subTargetInfo->checkFeatures("+neon"); } + else if (targetArch == llvm::Triple::arc) { + return true; + } else { return false; } diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index e165e5ef2..b1c3b4f4a 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -104,8 +104,9 @@ os_thread_exit(void *retval); #endif /* Clang's __GNUC_PREREQ macro has a different meaning than GCC one, - so we have to handle this case specially */ -#if defined(__clang__) + so we have to handle this case specially(except the CCAC compiler + provided by MetaWare, which doesn't support atomic operations) */ +#if defined(__clang__) && !defined(__CCAC__) /* Clang provides stdatomic.h since 3.6.0 See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */ #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) From a44c487632fbbe290677d97688fd7c94060f1093 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Fri, 16 Aug 2024 11:33:51 +0800 Subject: [PATCH 15/25] runtest.py: Normallize option handling for XIP mode (#3722) --- .../spec-test-script/runtest.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 268024323..011578fce 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -62,6 +62,12 @@ aot_target_options_map = { "xtensa": ["--target=xtensa"], } +# AOT compilation options mapping for XIP mode +aot_target_options_map_xip = { + # avoid l32r relocations for xtensa + "xtensa": ["--mllvm=-mtext-section-literals"] +} + def debug(data): if debug_file: debug_file.write(data) @@ -1122,10 +1128,8 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = ' if opts.xip: cmd.append("--xip") - - # avoid l32r relocations for xtensa - if opts.target == "xtensa": - cmd.append("--mllvm=-mtext-section-literals") + if test_target in aot_target_options_map_xip: + cmd += aot_target_options_map_xip[test_target] if opts.multi_thread: cmd.append("--enable-multi-thread") @@ -1308,8 +1312,8 @@ if __name__ == "__main__": if test_aot: aot_tempfile = create_tmp_file(".aot") # could be potientially compiled to aot - # with the future following call test_assert_xxx, - # add them to temp_file_repo now even if no actual following file, + # with the future following call test_assert_xxx, + # add them to temp_file_repo now even if no actual following file, # it will be simple ignore during final deletion if not exist prefix = wasm_tempfile.split(".wasm")[0] temp_file_repo.append(prefix + ".aot") @@ -1436,8 +1440,8 @@ if __name__ == "__main__": if test_aot: r = compile_wasm_to_aot(temp_files[1], temp_files[2], True, opts, r) # could be potientially compiled to aot - # with the future following call test_assert_xxx, - # add them to temp_file_repo now even if no actual following file, + # with the future following call test_assert_xxx, + # add them to temp_file_repo now even if no actual following file, # it will be simple ignore during final deletion if not exist prefix = temp_files[1].split(".wasm")[0] temp_file_repo.append(prefix + ".aot") From 59f761b58d044dc8adc6bce236e9910e2ee67381 Mon Sep 17 00:00:00 2001 From: Jan Olaf Martin Date: Thu, 15 Aug 2024 21:37:10 -0700 Subject: [PATCH 16/25] aot compiler: Track non-0x00 tableindex as ref types use (#3695) Any use of a table index that isn't exactly a null byte (`0x00`) means that the module makes use of the reference types proposal. This is important to track because `aot_compiler.c` will blindly assume that all table indices are a single byte long otherwise. This fixes a crash in WAMR for modules that contain multi-byte encodings of table indices in `call_indirect` but make no other use of reference types features. --- core/iwasm/interpreter/wasm_loader.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 10324ac45..d2bcf7176 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -12004,6 +12004,14 @@ re_scan: read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 +#if WASM_ENABLE_WAMR_COMPILER != 0 + if (*p != 0x00) { + // Any non-0x00 byte requires the ref types proposal. + // This is different from checking the table_idx value + // since `0x80 0x00` etc. are all valid encodings of zero. + module->is_ref_types_used = true; + } +#endif read_leb_uint32(p, p_end, table_idx); #else CHECK_BUF(p, p_end, 1); From 4c127715df2abd65a16b685e2fe98681e85e403b Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Fri, 16 Aug 2024 14:04:41 +0800 Subject: [PATCH 17/25] aot compiler: Fix NaN handling for opcode f32/f64.const in XIP mode (#3721) If the value of a float constant is an NaN, the aot compiler creates an alloca, stores the converted i32 const into it and then loads f32 from it again, which may introduce a relocation in the AOT file and is not allowed for XIP mode. --- core/iwasm/compilation/aot_emit_const.c | 60 ++++++++++++------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_const.c b/core/iwasm/compilation/aot_emit_const.c index 5665b480b..64fa3ded1 100644 --- a/core/iwasm/compilation/aot_emit_const.c +++ b/core/iwasm/compilation/aot_emit_const.c @@ -68,23 +68,21 @@ aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { LLVMValueRef alloca, value; - if (!isnan(f32_const)) { - if (comp_ctx->is_indirect_mode - && aot_intrinsic_check_capability(comp_ctx, "f32.const")) { - WASMValue wasm_value; - memcpy(&wasm_value.f32, &f32_const, sizeof(float32)); - value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol, - &wasm_value, VALUE_TYPE_F32); - if (!value) { - return false; - } - PUSH_F32(value); - } - else { - value = F32_CONST(f32_const); - CHECK_LLVM_CONST(value); - PUSH_F32(value); + if (comp_ctx->is_indirect_mode + && aot_intrinsic_check_capability(comp_ctx, "f32.const")) { + WASMValue wasm_value; + memcpy(&wasm_value.f32, &f32_const, sizeof(float32)); + value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol, + &wasm_value, VALUE_TYPE_F32); + if (!value) { + return false; } + PUSH_F32(value); + } + else if (!isnan(f32_const)) { + value = F32_CONST(f32_const); + CHECK_LLVM_CONST(value); + PUSH_F32(value); } else { int32 i32_const; @@ -123,23 +121,21 @@ aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { LLVMValueRef alloca, value; - if (!isnan(f64_const)) { - if (comp_ctx->is_indirect_mode - && aot_intrinsic_check_capability(comp_ctx, "f64.const")) { - WASMValue wasm_value; - memcpy(&wasm_value.f64, &f64_const, sizeof(float64)); - value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol, - &wasm_value, VALUE_TYPE_F64); - if (!value) { - return false; - } - PUSH_F64(value); - } - else { - value = F64_CONST(f64_const); - CHECK_LLVM_CONST(value); - PUSH_F64(value); + if (comp_ctx->is_indirect_mode + && aot_intrinsic_check_capability(comp_ctx, "f64.const")) { + WASMValue wasm_value; + memcpy(&wasm_value.f64, &f64_const, sizeof(float64)); + value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol, + &wasm_value, VALUE_TYPE_F64); + if (!value) { + return false; } + PUSH_F64(value); + } + else if (!isnan(f64_const)) { + value = F64_CONST(f64_const); + CHECK_LLVM_CONST(value); + PUSH_F64(value); } else { int64 i64_const; From 67c33a29e38843f4045f57eb1120077275f4810d Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 19 Aug 2024 09:52:38 +0800 Subject: [PATCH 18/25] CI: Enable XIP spectest for RISCV32 ILP32F (#3727) --- .github/workflows/spec_test_on_nuttx.yml | 4 ---- tests/wamr-test-suites/spec-test-script/runtest.py | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 059e5fbef..f2e59ba68 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -125,10 +125,6 @@ jobs: - target_config: { config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64" } wamr_test_option: { mode: "-t aot -X" } - # XIP is not fully supported yet on RISCV32 ILP32F, some relocations can not be resolved - - target_config: { config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh", fpu_type: "fp" } - wamr_test_option: { mode: "-t aot -X" } - # Our xtensa environment doesn't have enough memory - target_config: { target: "xtensa" } wamr_feature_option: { mode: "-G" } diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 011578fce..291718b6e 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -65,7 +65,8 @@ aot_target_options_map = { # AOT compilation options mapping for XIP mode aot_target_options_map_xip = { # avoid l32r relocations for xtensa - "xtensa": ["--mllvm=-mtext-section-literals"] + "xtensa": ["--mllvm=-mtext-section-literals"], + "riscv32_ilp32f": ["--enable-builtin-intrinsics=i64.common,f64.common,f32.const,f64.const,f64xi32,f64xi64,f64_promote_f32,f32_demote_f64"], } def debug(data): From 88caa0c53adf4b43f1a8359d80ec01b431ce8bdc Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 19 Aug 2024 10:35:18 +0800 Subject: [PATCH 19/25] CI: Unify configuration stage for NuttX (#3725) --- .github/workflows/compilation_on_nuttx.yml | 43 ++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index 7a3c3067f..2f8014fac 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -68,18 +68,17 @@ jobs: # arm64 "boards/arm64/qemu/qemu-armv8a/configs/nsh", ] - wamr_config_option: [ - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n", - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n", - ] + + wamr_config_option: + - "CONFIG_INTERPRETERS_WAMR_AOT" + - "CONFIG_INTERPRETERS_WAMR_FAST" + - "CONFIG_INTERPRETERS_WAMR_CLASSIC" + - "CONFIG_INTERPRETERS_WAMR_AOT CONFIG_INTERPRETERS_WAMR_FAST" + - "CONFIG_INTERPRETERS_WAMR_AOT CONFIG_INTERPRETERS_WAMR_FAST CONFIG_INTERPRETERS_WAMR_LIBC_WASI" + - "CONFIG_INTERPRETERS_WAMR_AOT CONFIG_INTERPRETERS_WAMR_FAST CONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN" + - "CONFIG_INTERPRETERS_WAMR_AOT CONFIG_INTERPRETERS_WAMR_CLASSIC" + - "CONFIG_INTERPRETERS_WAMR_AOT CONFIG_INTERPRETERS_WAMR_CLASSIC CONFIG_INTERPRETERS_WAMR_LIBC_WASI" + - "CONFIG_INTERPRETERS_WAMR_AOT CONFIG_INTERPRETERS_WAMR_CLASSIC CONFIG_INTERPRETERS_WAMR_LIBC_WASI" steps: - name: Checkout NuttX @@ -102,16 +101,22 @@ jobs: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr - - name: Enable WAMR for NuttX + - name: Configure WAMR + working-directory: nuttx run: | - find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\n${{ matrix.wamr_config_option }}' - find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n' + tools/configure.sh ${{ matrix.nuttx_board_config }} + kconfig-tweak --enable CONFIG_PSEUDOFS_SOFTLINKS + kconfig-tweak --enable CONFIG_INTERPRETERS_WAMR + kconfig-tweak --enable CONFIG_INTERPRETERS_IWASM_TASK + kconfig-tweak --set-val CONFIG_INTERPRETERS_WAMR_PRIORITY 100 + kconfig-tweak --set-val CONFIG_INTERPRETERS_WAMR_STACKSIZE 8192 + for x in ${{ matrix.wamr_config_option }}; do + kconfig-tweak --enable $x + done - name: Build - run: | - cd nuttx - tools/configure.sh ${{ matrix.nuttx_board_config }} - make -j$(nproc) EXTRAFLAGS=-Werror + working-directory: nuttx + run: make -j$(nproc) EXTRAFLAGS=-Werror - name: Checkout Bloaty uses: actions/checkout@v3 From 97c95a2e2f12e39e21313e25263dad413811699a Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 19 Aug 2024 10:57:36 +0800 Subject: [PATCH 20/25] Fix table idx resolving in op call_indirect/return_call_indirect (#3726) The table index in the call_indirect/return_call_indirect opcode should be one byte 0x00 when ref-types/GC isn't enabled, and should be treated as leb u32 when ref-types/GC is enabled. And make aot compiler bail out if ref-types/GC is disabled by command line argument while ref-types instructions are used. --- core/iwasm/compilation/aot_llvm.c | 10 ++++++++++ core/iwasm/interpreter/wasm_interp_classic.c | 7 +++++++ core/iwasm/interpreter/wasm_loader.c | 16 +++++++++------- core/iwasm/interpreter/wasm_mini_loader.c | 5 ++++- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 8c989ed6e..2e1e82e56 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -3108,6 +3108,16 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) goto fail; } + /* Return error if ref-types and GC are disabled by command line but + ref-types instructions are used */ + if (!option->enable_ref_types && !option->enable_gc + && wasm_module->is_ref_types_used) { + aot_set_last_error("ref-types instruction was found, " + "try removing --disable-ref-types option " + "or adding --enable-gc option."); + goto fail; + } + /* Disable features when they are not actually used */ if (!wasm_module->is_simd_used) { option->enable_simd = comp_ctx->enable_simd = false; diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index f2d6b7e7b..766d2f52f 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -2281,8 +2281,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, bh_assert(tidx < module->module->type_count); cur_type = wasm_types[tidx]; + /* clang-format off */ +#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); +#else + frame_ip++; + tbl_idx = 0; +#endif bh_assert(tbl_idx < module->table_count); + /* clang-format on */ tbl_inst = wasm_get_table_inst(module, tbl_idx); diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index d2bcf7176..0891598d1 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -7149,10 +7149,10 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_RETURN_CALL_INDIRECT: #endif skip_leb_uint32(p, p_end); /* typeidx */ -#if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0 - u8 = read_uint8(p); /* 0x00 */ -#else +#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 skip_leb_uint32(p, p_end); /* tableidx */ +#else + u8 = read_uint8(p); /* 0x00 */ #endif break; @@ -12005,10 +12005,12 @@ re_scan: read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 #if WASM_ENABLE_WAMR_COMPILER != 0 - if (*p != 0x00) { - // Any non-0x00 byte requires the ref types proposal. - // This is different from checking the table_idx value - // since `0x80 0x00` etc. are all valid encodings of zero. + if (p + 1 < p_end && *p != 0x00) { + /* + * Any non-0x00 byte requires the ref types proposal. + * This is different from checking the table_idx value + * since `0x80 0x00` etc. are all valid encodings of zero. + */ module->is_ref_types_used = true; } #endif diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 6e70203fa..0bb2f34eb 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3501,8 +3501,11 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_RETURN_CALL_INDIRECT: #endif skip_leb_uint32(p, p_end); /* typeidx */ - CHECK_BUF(p, p_end, 1); +#if WASM_ENABLE_REF_TYPES != 0 + skip_leb_uint32(p, p_end); /* tableidx */ +#else u8 = read_uint8(p); /* 0x00 */ +#endif break; #if WASM_ENABLE_EXCE_HANDLING != 0 From 581e1d97670bff308c4878b77d9f4174a0e1b57e Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 20 Aug 2024 11:26:26 +0900 Subject: [PATCH 21/25] compilation: Use the dedicated stack-sizes section only for AOT (#3732) For JIT, we naturally use mach-o on macOS, where the section name we currently use is not valid and ends up with the errors like: ``` LLVM ERROR: Global variable '__orc_lcl.aot_stack_sizes.0' has an invalid section specifier '.aot_stack_sizes': mach-o section specifier requires a segment and section separated by a comma. ``` Because the dedicated section is not necessary for JIT, this commit simply stops using it. Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/3730 --- core/iwasm/compilation/aot_llvm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 2e1e82e56..d738cfc0e 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1690,7 +1690,15 @@ aot_create_stack_sizes(const AOTCompData *comp_data, AOTCompContext *comp_ctx) * avoid creating extra relocations in the precheck functions. */ LLVMSetLinkage(stack_sizes, LLVMInternalLinkage); - LLVMSetSection(stack_sizes, aot_stack_sizes_section_name); + /* + * for AOT, place it into a dedicated section for the convenience + * of the AOT file generation and symbol resolutions. + * + * for JIT, it doesn't matter. + */ + if (!comp_ctx->is_jit_mode) { + LLVMSetSection(stack_sizes, aot_stack_sizes_section_name); + } comp_ctx->stack_sizes_type = stack_sizes_type; comp_ctx->stack_sizes = stack_sizes; return true; From 6fdad9916ffffd8ea5f81cce1dc36ea585d074d1 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 20 Aug 2024 11:06:07 +0800 Subject: [PATCH 22/25] riscv: Add missing relocation intrinsics for __fixdfsi/__ltdf2 (#3733) --- core/iwasm/aot/arch/aot_reloc_riscv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/iwasm/aot/arch/aot_reloc_riscv.c b/core/iwasm/aot/arch/aot_reloc_riscv.c index 31830f780..b87bb2000 100644 --- a/core/iwasm/aot/arch/aot_reloc_riscv.c +++ b/core/iwasm/aot/arch/aot_reloc_riscv.c @@ -134,6 +134,7 @@ static SymbolMap target_sym_map[] = { REG_SYM(__eqdf2), REG_SYM(__extendsfdf2), REG_SYM(__fixdfdi), + REG_SYM(__fixdfsi), REG_SYM(__fixunsdfdi), REG_SYM(__fixunsdfsi), REG_SYM(__floatdidf), @@ -143,6 +144,7 @@ static SymbolMap target_sym_map[] = { REG_SYM(__gedf2), REG_SYM(__gtdf2), REG_SYM(__ledf2), + REG_SYM(__ltdf2), REG_SYM(__muldf3), REG_SYM(__nedf2), REG_SYM(__negdf2), From c04ef6b44f54d633d08b0634cc827869d32f5d58 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 20 Aug 2024 12:00:39 +0800 Subject: [PATCH 23/25] Update version to 2.1.2 and update release notes (#3718) --- RELEASE_NOTES.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ core/version.h | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 988315ef2..e296cdf9e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,77 @@ +## WAMR-2.1.2 + +### Breaking Changes + - wasi-nn: Apply new architecture (#3692) + +### New Features + - [wasi-nn] Add a new wasi-nn backend openvino (#3603) + - Add APIs into wasm_c_api.h to summary wasm function execution duration (#3639) + - Add support for RISCV32 ILP32F (#3708) + +### Bug Fixes + - libc-builtin: Fix function prototype for wasm_runtime_module_realloc (#3702) + - Fix potential memory leak in insert_native_symbol (#3712) + - aot compiler: Fix NaN handling for opcode f32/f64.const in XIP mode (#3721) + - Fix table idx resolving in op call_indirect/return_call_indirect (#3726) + +### Enhancements + - Remove a few hardcoded spec test knowledge from the core library (#3648) + - Change log of import function to be consistent (#3656) + - libc-builtin: Fix a printf format (#3652) + - Set compile symbol visibility to hidden in cmake (#3655) + - wamrc: Add --mllvm= option (#3658) + - wamr-compiler: Avoid size-level tweak if target is specified (#3659) + - aot runtime: Add missing arm/thumb relocations (#3660) + - aot compiler: Enlarge AOTNativeSymbol->symbol (#3662) + - aot compiler: Bail out on too long native symbol names (#3663) + - Support more features for rt-thread (#3661) + - Zephyr User Mode Support (#3650) + - Set posix thread name for debug build (#3657) + - Add emscripten_sleep() wrapper to libc-emcc (#3669) + - Fix a compilation warning (#3682) + - wamrc: Add some help text for --size-level (#3689) + - Restore linux iwasm default visibility (#3691) + - posix_thread.c: Restore old signal alternate stack before thread exit (#3693) + - libc-wasi: Make rights of STDIN/STDOUT/STDERR fixed and overlook their access modes (#3694) + - [refactoring] Extract read leb to a separate file, share the code between loader and mini loader (#3701) + - debug-interp: Only add lock when signal_flag is SIG_SINGSTEP (#3704) + - Fix compilation warnings (#3707) + - Add missing headers in bh_atomic.h and aot_llvm_extra.cpp (#3715) + - Update std atomic check and simd compatibility check for arc compiler (#3716) + - aot compiler: Track non-0x00 tableindex as ref types use (#3695) + - compilation: Use the dedicated stack-sizes section only for AOT (#3732) + - riscv: Add missing relocation intrinsics for __fixdfsi/__ltdf2 (#3733) + +### Others + - Fix night run CI (#3640) + - spec-test-script/runtest.py: Don't assume the tmp dir path (#3632) + - wamr-test-suites: Remove dead code (wasi_test) (#3634) + - wamr-test-suites/test_wamr.sh: Add an option to specify wamrc binary (#3635) + - CI: Build llvm for xtensa (#3637) + - spec-test-script/runtest.py: Avoid specifying -v=0 unnecessarily (#3642) + - spec-test-script: Add xtensa case (#3643) + - spec-test-script/runtest.py: Move "--size-level=1" to common place for RISCV64 (#3644) + - spec-test-script/runtest.py: Use a shorter timeout when expected to fail (#3647) + - spec-test-script: Make case_last_words larger (#3651) + - spec-test-script/runtest.py: Reduce stack size for aot w/o gc (#3653) + - spec-test-script: Skip a few tests for xtensa qemu (#3664) + - spec-test-script: Use -mtext-section-literals for xtensa xip (#3666) + - spec_test_on_nuttx.yml: Add xtensa (#3665) + - spec_test_on_nuttx.yml: Enable xip (#3671) + - spec_test_on_nuttx.yml: Record more logs (#3670) + - spec_test_on_nuttx.yml: Replace sed with kconfig-tweak (#3672) + - spec_test_on_nuttx.yml: Retire CONFIG_EOL_IS_LF (#3676) + - spec-test-script/runtest.py: Use wamrc --xip option for xip (#3683) + - CI: Bump NuttX version to 12.6 (#3684) + - wamr-test-suites: Clean up generated tmp files after spec test (#3700) + - test_wamr.sh: Fix build wabt tool (#3703) + - NuttX: Retire CONFIG_ARCH_RV32IM and CONFIG_ARCH_RV64GC (#3717) + - runtest.py: Normallize option handling for XIP mode (#3722) + - CI: Enable XIP spectest for RISCV32 ILP32F (#3727) + - CI: Unify configuration stage for NuttX (#3725) + +--- + ## WAMR-2.1.1 ### Breaking Changes diff --git a/core/version.h b/core/version.h index a1626f83c..4e2cbaefc 100644 --- a/core/version.h +++ b/core/version.h @@ -7,5 +7,5 @@ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 2 #define WAMR_VERSION_MINOR 1 -#define WAMR_VERSION_PATCH 1 +#define WAMR_VERSION_PATCH 2 #endif From d67cc26d56345d3494e5fd2ebab5fa5bcadaa5d7 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 20 Aug 2024 16:03:04 +0800 Subject: [PATCH 24/25] Fix load error not reported when magic header is invalid (#3734) When AOT isn't enabled and the input is a wasm file, wasm_runtime_load doesn't report error. Same when interpreter isn't enabled and the input is AOT file. This PR makes wasm_runtime_load report error "magic header not detected" for such situations. --- core/iwasm/common/wasm_runtime_common.c | 41 ++++++++++++++++++------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 37a89f8fb..f54ac4ab9 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1417,12 +1417,39 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf, uint32 error_buf_size) { WASMModuleCommon *module_common = NULL; + uint32 package_type; + bool magic_header_detected = false; if (!args) { + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: null load arguments"); return NULL; } - if (get_package_type(buf, size) == Wasm_Module_Bytecode) { + if (size < 4) { + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: unexpected end"); + return NULL; + } + + package_type = get_package_type(buf, size); + if (package_type == Wasm_Module_Bytecode) { +#if WASM_ENABLE_INTERP != 0 + magic_header_detected = true; +#endif + } + else if (package_type == Wasm_Module_AoT) { +#if WASM_ENABLE_AOT != 0 + magic_header_detected = true; +#endif + } + if (!magic_header_detected) { + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: magic header not detected"); + return NULL; + } + + if (package_type == Wasm_Module_Bytecode) { #if WASM_ENABLE_INTERP != 0 module_common = (WASMModuleCommon *)wasm_load(buf, size, @@ -1435,7 +1462,7 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args, args->wasm_binary_freeable; #endif } - else if (get_package_type(buf, size) == Wasm_Module_AoT) { + else if (package_type == Wasm_Module_AoT) { #if WASM_ENABLE_AOT != 0 module_common = (WASMModuleCommon *)aot_load_from_aot_file( buf, size, args, error_buf, error_buf_size); @@ -1444,15 +1471,7 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args, args->wasm_binary_freeable; #endif } - else { - if (size < 4) - set_error_buf(error_buf, error_buf_size, - "WASM module load failed: unexpected end"); - else - set_error_buf(error_buf, error_buf_size, - "WASM module load failed: magic header not detected"); - return NULL; - } + if (!module_common) { LOG_DEBUG("WASM module load failed"); return NULL; From f4383a9e62a0f4ac97c3ab66c6b88a2aee5c24a2 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Tue, 20 Aug 2024 17:03:28 +0800 Subject: [PATCH 25/25] Use node 18.x to build vscode extension (#3735) Fix the issue of releasing wamr-ide vscode extension: https://github.com/bytecodealliance/wasm-micro-runtime/actions/runs/10467675321/job/28987014745 --- .github/workflows/build_wamr_vscode_ext.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wamr_vscode_ext.yml b/.github/workflows/build_wamr_vscode_ext.yml index 322ba1c06..756215e60 100644 --- a/.github/workflows/build_wamr_vscode_ext.yml +++ b/.github/workflows/build_wamr_vscode_ext.yml @@ -20,10 +20,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Use Node.js 16.x + - name: Use Node.js 18.x uses: actions/setup-node@v4 with: - node-version: 16.x + node-version: 18.x - name: set vscode extension to correct version run: | @@ -33,7 +33,7 @@ jobs: - name: generate wamr ide vscode extension run: | - npm install -g vsce + npm install -g @vscode/vsce rm -rf node_modules npm install vsce package