From acc4d93f6050b97d0cfbb0b54dae78ef1eff2ce3 Mon Sep 17 00:00:00 2001 From: turuslan Date: Wed, 31 Jan 2024 14:06:27 +0300 Subject: [PATCH 001/218] [qdrvm] hunter --- CMakeLists.txt | 14 + cmake/Hunter/config.cmake | 6 + cmake/HunterGate.cmake | 539 ++++++++++++++++++++ cmake/wasmedge-config.cmake | 13 + lib/api/CMakeLists.txt | 24 +- lib/loader/CMakeLists.txt | 2 +- lib/loader/ast/component/component_type.cpp | 3 + 7 files changed, 592 insertions(+), 9 deletions(-) create mode 100644 cmake/Hunter/config.cmake create mode 100644 cmake/HunterGate.cmake create mode 100644 cmake/wasmedge-config.cmake create mode 100644 lib/loader/ast/component/component_type.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7962eaf6f98e..1f275201b575 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,14 @@ cmake_policy(SET CMP0091 NEW) if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) endif() + +include(cmake/HunterGate.cmake) +HunterGate( + URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm1.zip + SHA1 8c0faf2b0d643a97e00dd0520d66fe2faaf5e573 + LOCAL +) + project(WasmEdge) # Overwrite it if you want to use static MSVC runtime library. @@ -138,6 +146,12 @@ if(WASMEDGE_BUILD_COVERAGE) append_coverage_compiler_flags() endif() +if(WASMEDGE_BUILD_AOT_RUNTIME) + hunter_add_package(ZLIB) + hunter_add_package(LLVM) + hunter_add_package(LLD) +endif() + include(Helper) include(GNUInstallDirs) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake new file mode 100644 index 000000000000..2654aaa0078e --- /dev/null +++ b/cmake/Hunter/config.cmake @@ -0,0 +1,6 @@ + +hunter_config( + LLVM + VERSION 16.0.1 + CMAKE_ARGS LLVM_ENABLE_PROJECTS=compiler-rt +) diff --git a/cmake/HunterGate.cmake b/cmake/HunterGate.cmake new file mode 100644 index 000000000000..1da4c2de259a --- /dev/null +++ b/cmake/HunterGate.cmake @@ -0,0 +1,539 @@ +# Copyright (c) 2013-2019, Ruslan Baratov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a gate file to Hunter package manager. +# Include this file using `include` command and add package you need, example: +# +# cmake_minimum_required(VERSION 3.5) +# +# include("cmake/HunterGate.cmake") +# HunterGate( +# URL "https://github.com/path/to/hunter/archive.tar.gz" +# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" +# ) +# +# project(MyProject) +# +# hunter_add_package(Foo) +# hunter_add_package(Boo COMPONENTS Bar Baz) +# +# Projects: +# * https://github.com/hunter-packages/gate/ +# * https://github.com/ruslo/hunter + +option(HUNTER_ENABLED "Enable Hunter package manager support" ON) + +if(HUNTER_ENABLED) + if(CMAKE_VERSION VERSION_LESS "3.2") + message( + FATAL_ERROR + "At least CMake version 3.2 required for Hunter dependency management." + " Update CMake or set HUNTER_ENABLED to OFF." + ) + endif() +endif() + +include(CMakeParseArguments) # cmake_parse_arguments + +option(HUNTER_STATUS_PRINT "Print working status" ON) +option(HUNTER_STATUS_DEBUG "Print a lot info" OFF) +option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON) + +set(HUNTER_ERROR_PAGE "https://docs.hunter.sh/en/latest/reference/errors") + +function(hunter_gate_status_print) + if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + message(STATUS "[hunter] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_status_debug) + if(HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + string(TIMESTAMP timestamp) + message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_error_page error_page) + message("------------------------------ ERROR ------------------------------") + message(" ${HUNTER_ERROR_PAGE}/${error_page}.html") + message("-------------------------------------------------------------------") + message("") + message(FATAL_ERROR "") +endfunction() + +function(hunter_gate_internal_error) + message("") + foreach(print_message ${ARGV}) + message("[hunter ** INTERNAL **] ${print_message}") + endforeach() + message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_error_page("error.internal") +endfunction() + +function(hunter_gate_fatal_error) + cmake_parse_arguments(hunter "" "ERROR_PAGE" "" "${ARGV}") + if("${hunter_ERROR_PAGE}" STREQUAL "") + hunter_gate_internal_error("Expected ERROR_PAGE") + endif() + message("") + foreach(x ${hunter_UNPARSED_ARGUMENTS}) + message("[hunter ** FATAL ERROR **] ${x}") + endforeach() + message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_error_page("${hunter_ERROR_PAGE}") +endfunction() + +function(hunter_gate_user_error) + hunter_gate_fatal_error(${ARGV} ERROR_PAGE "error.incorrect.input.data") +endfunction() + +function(hunter_gate_self root version sha1 result) + string(COMPARE EQUAL "${root}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("root is empty") + endif() + + string(COMPARE EQUAL "${version}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("version is empty") + endif() + + string(COMPARE EQUAL "${sha1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("sha1 is empty") + endif() + + string(SUBSTRING "${sha1}" 0 7 archive_id) + + if(EXISTS "${root}/cmake/Hunter") + set(hunter_self "${root}") + else() + set( + hunter_self + "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked" + ) + endif() + + set("${result}" "${hunter_self}" PARENT_SCOPE) +endfunction() + +# Set HUNTER_GATE_ROOT cmake variable to suitable value. +function(hunter_gate_detect_root) + # Check CMake variable + string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty) + if(not_empty) + set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable") + return() + endif() + + # Check environment variable + string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty) + if(not_empty) + set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by environment variable") + return() + endif() + + # Check HOME environment variable + string(COMPARE NOTEQUAL "$ENV{HOME}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable") + return() + endif() + + # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only) + if(WIN32) + string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using SYSTEMDRIVE environment variable" + ) + return() + endif() + + string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using USERPROFILE environment variable" + ) + return() + endif() + endif() + + hunter_gate_fatal_error( + "Can't detect HUNTER_ROOT" + ERROR_PAGE "error.detect.hunter.root" + ) +endfunction() + +function(hunter_gate_download dir) + string( + COMPARE + NOTEQUAL + "$ENV{HUNTER_DISABLE_AUTOINSTALL}" + "" + disable_autoinstall + ) + if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL) + hunter_gate_fatal_error( + "Hunter not found in '${dir}'" + "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'" + "Settings:" + " HUNTER_ROOT: ${HUNTER_GATE_ROOT}" + " HUNTER_SHA1: ${HUNTER_GATE_SHA1}" + ERROR_PAGE "error.run.install" + ) + endif() + string(COMPARE EQUAL "${dir}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("Empty 'dir' argument") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_SHA1 empty") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_URL empty") + endif() + + set(done_location "${dir}/DONE") + set(sha1_location "${dir}/SHA1") + + set(build_dir "${dir}/Build") + set(cmakelists "${dir}/CMakeLists.txt") + + hunter_gate_status_debug("Locking directory: ${dir}") + file(LOCK "${dir}" DIRECTORY GUARD FUNCTION) + hunter_gate_status_debug("Lock done") + + if(EXISTS "${done_location}") + # while waiting for lock other instance can do all the job + hunter_gate_status_debug("File '${done_location}' found, skip install") + return() + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(MAKE_DIRECTORY "${build_dir}") # check directory permissions + + # Disabling languages speeds up a little bit, reduces noise in the output + # and avoids path too long windows error + file( + WRITE + "${cmakelists}" + "cmake_minimum_required(VERSION 3.5)\n" + "project(HunterDownload LANGUAGES NONE)\n" + "include(ExternalProject)\n" + "ExternalProject_Add(\n" + " Hunter\n" + " URL\n" + " \"${HUNTER_GATE_URL}\"\n" + " URL_HASH\n" + " SHA1=${HUNTER_GATE_SHA1}\n" + " DOWNLOAD_DIR\n" + " \"${dir}\"\n" + " TLS_VERIFY\n" + " ${HUNTER_TLS_VERIFY}\n" + " SOURCE_DIR\n" + " \"${dir}/Unpacked\"\n" + " CONFIGURE_COMMAND\n" + " \"\"\n" + " BUILD_COMMAND\n" + " \"\"\n" + " INSTALL_COMMAND\n" + " \"\"\n" + ")\n" + ) + + if(HUNTER_STATUS_DEBUG) + set(logging_params "") + else() + set(logging_params OUTPUT_QUIET) + endif() + + hunter_gate_status_debug("Run generate") + + # Need to add toolchain file too. + # Otherwise on Visual Studio + MDD this will fail with error: + # "Could not find an appropriate version of the Windows 10 SDK installed on this machine" + if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") + get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE) + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}") + else() + # 'toolchain_arg' can't be empty + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=") + endif() + + string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make) + if(no_make) + set(make_arg "") + else() + # Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM + set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") + endif() + + execute_process( + COMMAND + "${CMAKE_COMMAND}" + "-H${dir}" + "-B${build_dir}" + "-G${CMAKE_GENERATOR}" + "${toolchain_arg}" + ${make_arg} + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error( + "Configure project failed." + "To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}" + "In directory ${dir}" + ) + endif() + + hunter_gate_status_print( + "Initializing Hunter workspace (${HUNTER_GATE_SHA1})" + " ${HUNTER_GATE_URL}" + " -> ${dir}" + ) + execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error("Build project failed") + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}") + file(WRITE "${done_location}" "DONE") + + hunter_gate_status_debug("Finished") +endfunction() + +# Must be a macro so master file 'cmake/Hunter' can +# apply all variables easily just by 'include' command +# (otherwise PARENT_SCOPE magic needed) +macro(HunterGate) + if(HUNTER_GATE_DONE) + # variable HUNTER_GATE_DONE set explicitly for external project + # (see `hunter_download`) + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() + + # First HunterGate command will init Hunter, others will be ignored + get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET) + + if(NOT HUNTER_ENABLED) + # Empty function to avoid error "unknown function" + function(hunter_add_package) + endfunction() + + set( + _hunter_gate_disabled_mode_dir + "${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode" + ) + if(EXISTS "${_hunter_gate_disabled_mode_dir}") + hunter_gate_status_debug( + "Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}" + ) + list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}") + endif() + elseif(_hunter_gate_done) + hunter_gate_status_debug("Secondary HunterGate (use old settings)") + hunter_gate_self( + "${HUNTER_CACHED_ROOT}" + "${HUNTER_VERSION}" + "${HUNTER_SHA1}" + _hunter_self + ) + include("${_hunter_self}/cmake/Hunter") + else() + set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}") + + string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name) + if(_have_project_name) + hunter_gate_fatal_error( + "Please set HunterGate *before* 'project' command. " + "Detected project: ${PROJECT_NAME}" + ERROR_PAGE "error.huntergate.before.project" + ) + endif() + + cmake_parse_arguments( + HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV} + ) + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1) + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url) + string( + COMPARE + NOTEQUAL + "${HUNTER_GATE_UNPARSED_ARGUMENTS}" + "" + _have_unparsed + ) + string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global) + string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath) + + if(_have_unparsed) + hunter_gate_user_error( + "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}" + ) + endif() + if(_empty_sha1) + hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory") + endif() + if(_empty_url) + hunter_gate_user_error("URL suboption of HunterGate is mandatory") + endif() + if(_have_global) + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)") + endif() + endif() + if(HUNTER_GATE_LOCAL) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)") + endif() + endif() + if(_have_filepath) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)") + endif() + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)") + endif() + endif() + + hunter_gate_detect_root() # set HUNTER_GATE_ROOT + + # Beautify path, fix probable problems with windows path slashes + get_filename_component( + HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE + ) + hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}") + if(NOT HUNTER_ALLOW_SPACES_IN_PATH) + string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces) + if(NOT _contain_spaces EQUAL -1) + hunter_gate_fatal_error( + "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces." + "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error" + "(Use at your own risk!)" + ERROR_PAGE "error.spaces.in.hunter.root" + ) + endif() + endif() + + string( + REGEX + MATCH + "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*" + HUNTER_GATE_VERSION + "${HUNTER_GATE_URL}" + ) + string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty) + if(_is_empty) + set(HUNTER_GATE_VERSION "unknown") + endif() + + hunter_gate_self( + "${HUNTER_GATE_ROOT}" + "${HUNTER_GATE_VERSION}" + "${HUNTER_GATE_SHA1}" + _hunter_self + ) + + set(_master_location "${_hunter_self}/cmake/Hunter") + if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter") + # Hunter downloaded manually (e.g. by 'git clone') + set(_unused "xxxxxxxxxx") + set(HUNTER_GATE_SHA1 "${_unused}") + set(HUNTER_GATE_VERSION "${_unused}") + else() + get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE) + set(_done_location "${_archive_id_location}/DONE") + set(_sha1_location "${_archive_id_location}/SHA1") + + # Check Hunter already downloaded by HunterGate + if(NOT EXISTS "${_done_location}") + hunter_gate_download("${_archive_id_location}") + endif() + + if(NOT EXISTS "${_done_location}") + hunter_gate_internal_error("hunter_gate_download failed") + endif() + + if(NOT EXISTS "${_sha1_location}") + hunter_gate_internal_error("${_sha1_location} not found") + endif() + file(READ "${_sha1_location}" _sha1_value) + string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal) + if(NOT _is_equal) + hunter_gate_internal_error( + "Short SHA1 collision:" + " ${_sha1_value} (from ${_sha1_location})" + " ${HUNTER_GATE_SHA1} (HunterGate)" + ) + endif() + if(NOT EXISTS "${_master_location}") + hunter_gate_user_error( + "Master file not found:" + " ${_master_location}" + "try to update Hunter/HunterGate" + ) + endif() + endif() + include("${_master_location}") + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() +endmacro() diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake new file mode 100644 index 000000000000..ae0427992a8b --- /dev/null +++ b/cmake/wasmedge-config.cmake @@ -0,0 +1,13 @@ + +add_library(WasmEdge::WasmEdge STATIC IMPORTED) +target_include_directories(WasmEdge::WasmEdge INTERFACE "${WASMEDGE_ROOT}/include") +target_link_libraries(WasmEdge::WasmEdge INTERFACE curses) +set(WASMEDGE_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.a") +set(WASMEDGE_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.a") +if(NOT EXISTS "${WASMEDGE_LIB}") + set(WASMEDGE_LIB "${WASMEDGE_LIB_DEBUG}") +endif() +set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_LIB}") +if(EXISTS "${WASMEDGE_LIB_DEBUG}") + set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION_DEBUG "${WASMEDGE_LIB_DEBUG}") +endif() diff --git a/lib/api/CMakeLists.txt b/lib/api/CMakeLists.txt index 5e8e46e11a2b..9ad7e285a9fc 100644 --- a/lib/api/CMakeLists.txt +++ b/lib/api/CMakeLists.txt @@ -163,38 +163,46 @@ if(WASMEDGE_BUILD_STATIC_LIB) wasmedge_add_static_lib_component_command(wasmedgeAOT) endif() + if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(WASMEDGE_LIBRARY_NAME "libwasmedged.a") + else() + set(WASMEDGE_LIBRARY_NAME "libwasmedge.a") + endif() + if(CMAKE_AR_NAME STREQUAL "libtool") - add_custom_command(OUTPUT "libwasmedge.a" - COMMAND ${CMAKE_AR} -static -o libwasmedge.a ${WASMEDGE_STATIC_LIB_LIBTOOL_FILES} $ + add_custom_command(OUTPUT "${WASMEDGE_LIBRARY_NAME}" + COMMAND ${CMAKE_AR} -static -o "${WASMEDGE_LIBRARY_NAME}" ${WASMEDGE_STATIC_LIB_LIBTOOL_FILES} $ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${WASMEDGE_STATIC_LIB_DEPS} wasmedgeCAPI ) else() - add_custom_command(OUTPUT "libwasmedge.a" + add_custom_command(OUTPUT "${WASMEDGE_LIBRARY_NAME}" ${WASMEDGE_STATIC_LIB_AR_CMDS} ${WASMEDGE_STATIC_LLVM_LIB_AR_CMDS} - COMMAND ${CMAKE_AR} -qcs libwasmedge.a $ objs/*/*.o + COMMAND ${CMAKE_AR} -qcs "${WASMEDGE_LIBRARY_NAME}" $ objs/*/*.o COMMAND ${CMAKE_COMMAND} -E remove_directory objs WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${WASMEDGE_STATIC_LIB_DEPS} wasmedgeCAPI ) endif() - add_custom_target(wasmedge_static_target ALL DEPENDS "libwasmedge.a") + add_custom_target(wasmedge_static_target ALL DEPENDS "${WASMEDGE_LIBRARY_NAME}") add_library(wasmedge_static STATIC IMPORTED GLOBAL) add_dependencies(wasmedge_static wasmedge_static_target) set_target_properties(wasmedge_static PROPERTIES - IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libwasmedge.a" - INTERFACE_INCLUDE_DIRECTORIES ${PROJECT_BINARY_DIR}/include/api + IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${WASMEDGE_LIBRARY_NAME}" + INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_BINARY_DIR}/include/api" ) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libwasmedge.a + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${WASMEDGE_LIBRARY_NAME}" DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(FILES ${WASMEDGE_CAPI_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wasmedge ) + install(FILES ${PROJECT_SOURCE_DIR}/cmake/wasmedge-config.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wasmedge) endif() diff --git a/lib/loader/CMakeLists.txt b/lib/loader/CMakeLists.txt index e6aef48569bb..c763ae34d3ae 100644 --- a/lib/loader/CMakeLists.txt +++ b/lib/loader/CMakeLists.txt @@ -26,7 +26,7 @@ wasmedge_add_library(wasmedgeLoader ast/component/sort.cpp ast/component/instance.cpp ast/component/alias.cpp - ast/component/type.cpp + ast/component/component_type.cpp ast/component/canonical.cpp ast/component/start.cpp ast/component/import_export.cpp diff --git a/lib/loader/ast/component/component_type.cpp b/lib/loader/ast/component/component_type.cpp new file mode 100644 index 000000000000..bcf73fffd515 --- /dev/null +++ b/lib/loader/ast/component/component_type.cpp @@ -0,0 +1,3 @@ +// "libwasmedge.a" is merged from objects extracted from libraries. +// "ar" can't extract duplicate "type.cpp.o" from "libwasmedgeLoader.a". +#include "./type.cpp" From f6ad5800f12be31823fdc8bfb1d07c60c3d23c9c Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 1 Feb 2024 10:12:43 +0300 Subject: [PATCH 002/218] [qdrvm] data segment --- include/api/wasmedge/wasmedge.h | 26 ++++++++++++++++++++++++++ include/executor/executor.h | 3 +++ lib/api/wasmedge.cpp | 31 +++++++++++++++++++++++++++++++ lib/executor/instantiate/data.cpp | 11 +++++++++++ 4 files changed, 71 insertions(+) diff --git a/include/api/wasmedge/wasmedge.h b/include/api/wasmedge/wasmedge.h index f32471640efe..caa01edbc761 100644 --- a/include/api/wasmedge/wasmedge.h +++ b/include/api/wasmedge/wasmedge.h @@ -4067,6 +4067,32 @@ WasmEdge_ExecutorExperimentalRegisterPostHostFunction( WasmEdge_ExecutorContext *Cxt, void *Data, void (*Func)(void *)); // <<<<<<<< WasmEdge Experimental Functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +// >>>>>>>> [qdrvm] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +typedef struct WasmEdge_DataSegment { + uint32_t Offset; + const uint8_t *Data; + uint32_t Length; +} WasmEdge_DataSegment; + +/// List the data section of the AST module. +/// +/// If the `Segments` buffer length is smaller than the result of the data +/// section size, the overflowed return values will be discarded. +/// +/// \param Cxt the WasmEdge_ASTModuleContext. +/// \param [out] Segments the data segment buffer. Can be NULL if data segments +/// are not needed. +/// \param Len the buffer length. +/// +/// \returns actual data segment list size. +WASMEDGE_CAPI_EXPORT extern uint32_t WasmEdge_ASTModuleListDataSegments( + const WasmEdge_ASTModuleContext *Cxt, WasmEdge_DataSegment *Segments, + const uint32_t Len); + +// <<<<<<<< [qdrvm] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + #ifdef __cplusplus } /// extern "C" #endif diff --git a/include/executor/executor.h b/include/executor/executor.h index 1107313a5282..cd6b3d3d5f7e 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -187,6 +187,9 @@ class Executor { atomicNotifyAll(); } + // [qdrvm] + Expect dataSegmentOffset(Runtime::StackManager &StackMgr, const AST::DataSegment &DataSeg); + private: /// Run Wasm bytecode expression for initialization. Expect runExpression(Runtime::StackManager &StackMgr, diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index a94d487118f2..abcde5bd376c 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -3282,6 +3282,37 @@ WASMEDGE_CAPI_EXPORT void WasmEdge_ExecutorExperimentalRegisterPostHostFunction( } // <<<<<<<< WasmEdge Experimental Functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +// >>>>>>>> [qdrvm] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +WASMEDGE_CAPI_EXPORT uint32_t WasmEdge_ASTModuleListDataSegments( + const WasmEdge_ASTModuleContext *Cxt, WasmEdge_DataSegment *Segments, + const uint32_t Len) { + if (!Cxt) { + return 0; + } + const auto &DataSegSpan = fromASTModCxt(Cxt)->getDataSection().getContent(); + WasmEdge::Configure Conf; + WasmEdge::Executor::Executor Executor{Conf}; + WasmEdge::Runtime::StackManager StackMgr; + uint32_t I = 0; + for (const auto &DataSeg : DataSegSpan) { + auto Offset = Executor.dataSegmentOffset(StackMgr, DataSeg); + if (!Offset) { + return 0; + } + if (I < Len) { + Segments[I].Offset = Offset.value(); + Segments[I].Data = DataSeg.getData().data(); + Segments[I].Length = DataSeg.getData().size(); + } + ++I; + } + return DataSegSpan.size(); +} + +// <<<<<<<< [qdrvm] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + #ifdef __cplusplus } // extern "C" #endif diff --git a/lib/executor/instantiate/data.cpp b/lib/executor/instantiate/data.cpp index 8903dc2babc8..3e1d6ec13b63 100644 --- a/lib/executor/instantiate/data.cpp +++ b/lib/executor/instantiate/data.cpp @@ -94,5 +94,16 @@ Expect Executor::initMemory(Runtime::StackManager &StackMgr, return {}; } +Expect Executor::dataSegmentOffset(Runtime::StackManager &StackMgr, const AST::DataSegment &DataSeg) { + if (DataSeg.getMode() == AST::DataSegment::DataMode::Active) { + if (auto Res = runExpression(StackMgr, DataSeg.getExpr().getInstrs()); + unlikely(!Res)) { + return Unexpect(Res); + } + return StackMgr.pop().get(); + } + return 0; +} + } // namespace Executor } // namespace WasmEdge From 54039306d52f2eb437bd6e1a5cba60cda8c0aad9 Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 1 Feb 2024 11:09:34 +0300 Subject: [PATCH 003/218] [qdrvm] thread local --- include/executor/executor.h | 18 ++++++++++++++++++ lib/executor/helper.cpp | 2 ++ 2 files changed, 20 insertions(+) diff --git a/include/executor/executor.h b/include/executor/executor.h index cd6b3d3d5f7e..ed7eed61e20a 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -754,6 +754,24 @@ class Executor { std::atomic_uint32_t *StopToken; }; + struct SavedThreadLocal { + SavedThreadLocal() : SavedThis(This), SavedCurrentStack(CurrentStack), SavedExecutionContext(ExecutionContext) { + } + + SavedThreadLocal(const SavedThreadLocal &) = delete; + SavedThreadLocal(SavedThreadLocal &&) = delete; + + ~SavedThreadLocal() { + This = SavedThis; + CurrentStack = SavedCurrentStack; + ExecutionContext = SavedExecutionContext; + } + + Executor *SavedThis; + Runtime::StackManager *SavedCurrentStack; + ExecutionContextStruct SavedExecutionContext; + }; + /// Pointer to current object. static thread_local Executor *This; /// Stack for passing into compiled functions diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index ec3ce4d6b2cd..3e5a02a47166 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -115,6 +115,8 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, Span Args = StackMgr.getTopSpan(ArgsN); std::vector Rets(RetsN); + SavedThreadLocal SavedThreadLocal; + { // Prepare the execution context. auto *ModInst = From f45887ebfc3f617ceae047d68ea79d2f72d0bf07 Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 1 Feb 2024 15:29:12 +0300 Subject: [PATCH 004/218] [qdrvm] fix hunter Signed-off-by: turuslan --- cmake/Helper.cmake | 34 ++++++++++++++++++---------------- cmake/wasmedge-config.cmake | 3 +++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 2b447ab23978..a738ce80617b 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -251,22 +251,24 @@ if((WASMEDGE_LINK_LLVM_STATIC OR WASMEDGE_BUILD_STATIC_LIB) AND WASMEDGE_BUILD_A list(APPEND WASMEDGE_LLVM_LINK_SHARED_COMPONENTS rt ) - if(WASMEDGE_BUILD_STATIC_LIB) - # Static library will forcefully turn off the LTO. - # Therefore, libz and libtinfo can be statically linked. - find_package(ZLIB REQUIRED) - get_filename_component(ZLIB_PATH "${ZLIB_LIBRARIES}" DIRECTORY) - list(APPEND WASMEDGE_LLVM_LINK_STATIC_COMPONENTS ${ZLIB_PATH}/libz.a) - if(NOT WASMEDGE_DISABLE_LIBTINFO) - list(APPEND WASMEDGE_LLVM_LINK_STATIC_COMPONENTS ${ZLIB_PATH}/libtinfo.a) - endif() - else() - # If not build static lib, dynamic link libz and libtinfo. - list(APPEND WASMEDGE_LLVM_LINK_SHARED_COMPONENTS - z - ) - if(NOT WASMEDGE_DISABLE_LIBTINFO) - list(APPEND WASMEDGE_LLVM_LINK_SHARED_COMPONENTS tinfo) + if(WASMEDGE_PLUGIN_ZLIB) + if(WASMEDGE_BUILD_STATIC_LIB) + # Static library will forcefully turn off the LTO. + # Therefore, libz and libtinfo can be statically linked. + find_package(ZLIB REQUIRED) + get_filename_component(ZLIB_PATH "${ZLIB_LIBRARIES}" DIRECTORY) + list(APPEND WASMEDGE_LLVM_LINK_STATIC_COMPONENTS ${ZLIB_PATH}/libz.a) + if(NOT WASMEDGE_DISABLE_LIBTINFO) + list(APPEND WASMEDGE_LLVM_LINK_STATIC_COMPONENTS ${ZLIB_PATH}/libtinfo.a) + endif() + else() + # If not build static lib, dynamic link libz and libtinfo. + list(APPEND WASMEDGE_LLVM_LINK_SHARED_COMPONENTS + z + ) + if(NOT WASMEDGE_DISABLE_LIBTINFO) + list(APPEND WASMEDGE_LLVM_LINK_SHARED_COMPONENTS tinfo) + endif() endif() endif() endif() diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index ae0427992a8b..b410c53b00bb 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -2,6 +2,9 @@ add_library(WasmEdge::WasmEdge STATIC IMPORTED) target_include_directories(WasmEdge::WasmEdge INTERFACE "${WASMEDGE_ROOT}/include") target_link_libraries(WasmEdge::WasmEdge INTERFACE curses) +if(APPLE) + target_link_libraries(WasmEdge::WasmEdge INTERFACE xar) +endif() set(WASMEDGE_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.a") set(WASMEDGE_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.a") if(NOT EXISTS "${WASMEDGE_LIB}") From 3a04e9fe228a5d807e4a9ead17c172f619c3645d Mon Sep 17 00:00:00 2001 From: kamilsa Date: Mon, 5 Feb 2024 12:15:42 +0600 Subject: [PATCH 005/218] Update llvm and lld to 17.0.6 --- CMakeLists.txt | 4 ++-- cmake/Hunter/config.cmake | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f275201b575..26d1daa77702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,8 @@ endif() include(cmake/HunterGate.cmake) HunterGate( - URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm1.zip - SHA1 8c0faf2b0d643a97e00dd0520d66fe2faaf5e573 + URL https://github.com/qdrvm/hunter/archive/e092ffe31bbc178249604845aaef8384c60547a8.zip + SHA1 e21a9e965611587af2452657e6bc6e0be99d3be0 LOCAL ) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake index 2654aaa0078e..74f03e5dd569 100644 --- a/cmake/Hunter/config.cmake +++ b/cmake/Hunter/config.cmake @@ -1,6 +1,20 @@ +set(ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}") + +if(ARCHITECTURE MATCHES "^(aarch64.*|AARCH64.*|arm.*|ARM.*)") + set(ARCHITECTURE AArch64) +elseif(ARCHITECTURE MATCHES "^(x86_64.*|AMD64.*|i386.*|i686.*)") + set(ARCHITECTURE X86) +elseif(ARCHITECTURE MATCHES "^(riscv.*)") + set(ARCHITECTURE RISCV) +else() + message(WARNING "Unknown architecture: ${ARCHITECTURE}, using all architectures to build LLVM") + set(ARCHITECTURE AArch64;X86;RISCV) +endif() hunter_config( LLVM - VERSION 16.0.1 - CMAKE_ARGS LLVM_ENABLE_PROJECTS=compiler-rt + VERSION 17.0.6 + CMAKE_ARGS + LLVM_ENABLE_PROJECTS=lld;clang + LLVM_TARGETS_TO_BUILD=${ARCHITECTURE};BPF ) From ebe8eba826994c7306ad4d72b95ee0c90c5635c7 Mon Sep 17 00:00:00 2001 From: kamilsa Date: Tue, 6 Feb 2024 12:19:42 +0600 Subject: [PATCH 006/218] Update llvm and lld to 17.0.6, reduce llvm targets --- CMakeLists.txt | 4 ++-- cmake/Hunter/config.cmake | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 26d1daa77702..96257ea564b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,8 @@ endif() include(cmake/HunterGate.cmake) HunterGate( - URL https://github.com/qdrvm/hunter/archive/e092ffe31bbc178249604845aaef8384c60547a8.zip - SHA1 e21a9e965611587af2452657e6bc6e0be99d3be0 + URL https://github.com/qdrvm/hunter/archive/b6c44ccfd5d9d0e87628737303084b4cfa9e200e.zip + SHA1 cecd3a154449c1b39fcf5dfaf1bed2c6bce0f67a LOCAL ) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake index 74f03e5dd569..684d9615017b 100644 --- a/cmake/Hunter/config.cmake +++ b/cmake/Hunter/config.cmake @@ -1,3 +1,4 @@ +## Identify native architecture to reduce amount of targets to build set(ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}") if(ARCHITECTURE MATCHES "^(aarch64.*|AARCH64.*|arm.*|ARM.*)") @@ -14,7 +15,7 @@ endif() hunter_config( LLVM VERSION 17.0.6 - CMAKE_ARGS + CMAKE_ARGS # inspired by https://github.com/WasmEdge/WasmEdge/blob/5e8556afa5a71f3d3ef9615334ecf1a9d4d0f1e8/utils/docker/Dockerfile.manylinux2014_x86_64#L57 LLVM_ENABLE_PROJECTS=lld;clang LLVM_TARGETS_TO_BUILD=${ARCHITECTURE};BPF ) From 38769c13dd82bac3b329ec10431d477344f7aedd Mon Sep 17 00:00:00 2001 From: turuslan Date: Wed, 7 Feb 2024 13:09:10 +0300 Subject: [PATCH 007/218] disable signal handling Signed-off-by: turuslan --- lib/system/fault.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/system/fault.cpp b/lib/system/fault.cpp index 673ce8aa1dd2..2d0a39764e06 100644 --- a/lib/system/fault.cpp +++ b/lib/system/fault.cpp @@ -47,18 +47,19 @@ thread_local Fault *localHandler = nullptr; } void enableHandler() noexcept { + [[maybe_unused]] struct sigaction Action {}; Action.sa_sigaction = &signalHandler; Action.sa_flags = SA_SIGINFO; - sigaction(SIGFPE, &Action, nullptr); - sigaction(SIGBUS, &Action, nullptr); - sigaction(SIGSEGV, &Action, nullptr); + // sigaction(SIGFPE, &Action, nullptr); + // sigaction(SIGBUS, &Action, nullptr); + // sigaction(SIGSEGV, &Action, nullptr); } void disableHandler() noexcept { - std::signal(SIGFPE, SIG_DFL); - std::signal(SIGBUS, SIG_DFL); - std::signal(SIGSEGV, SIG_DFL); + // std::signal(SIGFPE, SIG_DFL); + // std::signal(SIGBUS, SIG_DFL); + // std::signal(SIGSEGV, SIG_DFL); } #elif WASMEDGE_OS_WINDOWS From 44451ccaad914fe0b890ae0966dc878cd18fb798 Mon Sep 17 00:00:00 2001 From: turuslan Date: Mon, 19 Feb 2024 12:43:49 +0300 Subject: [PATCH 008/218] rename wasm file Signed-off-by: turuslan --- lib/aot/compiler.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/aot/compiler.cpp b/lib/aot/compiler.cpp index 57196583df3a..1e2e8a1665ac 100644 --- a/lib/aot/compiler.cpp +++ b/lib/aot/compiler.cpp @@ -5468,7 +5468,13 @@ Expect outputWasmLibrary(const std::filesystem::path &OutputPath, spdlog::info("output start"); - std::ofstream OS(OutputPath, std::ios_base::binary); + std::filesystem::path OutputPathTmp(OutputPath); + OutputPathTmp.replace_extension("%%%%%%%%%%.wasm"); + OutputPathTmp = createTemp(OutputPathTmp); + if (OutputPathTmp.empty()) { + return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); + } + std::ofstream OS(OutputPathTmp, std::ios_base::binary); if (!OS) { spdlog::error("output failed."); return Unexpect(ErrCode::Value::IllegalPath); @@ -5481,6 +5487,7 @@ Expect outputWasmLibrary(const std::filesystem::path &OutputPath, std::error_code Error; std::filesystem::remove(SharedObjectName, Error); + std::filesystem::rename(OutputPathTmp, OutputPath); return {}; } From bacf43f2a3d9fcf5dc3e49e2723e2947c5c5d796 Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 1 Feb 2024 10:54:54 +0800 Subject: [PATCH 009/218] [WASI-NN] ggml: bump llama.cpp b2037 Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 6fceddf0ce77..5066af48a730 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -47,7 +47,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2029 + GIT_TAG b2037 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) From 86e70832b752c161081abe063dc69b8663f5047f Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Wed, 7 Jun 2023 07:30:53 +0800 Subject: [PATCH 010/218] [AOT] Support exception handling, stack unwinding across AOT binary * Use hidden function `__register_frame` and `__deregister_frame` in libgcc and libunwind to apply FDE data in `.eh_frame` section Signed-off-by: Shen-Ta Hsieh --- include/loader/shared_library.h | 9 ++++-- include/system/fault.h | 1 - lib/aot/compiler.cpp | 21 ++++++++----- lib/aot/llvm.h | 22 +++++++++++++ lib/executor/engine/proxy.cpp | 6 +--- lib/executor/helper.cpp | 15 +++++---- lib/loader/shared_library.cpp | 56 +++++++++++++++++++++++++++++++-- lib/system/fault.cpp | 3 +- 8 files changed, 107 insertions(+), 26 deletions(-) diff --git a/include/loader/shared_library.h b/include/loader/shared_library.h index ea765d13b1fc..d9d756bd6568 100644 --- a/include/loader/shared_library.h +++ b/include/loader/shared_library.h @@ -97,8 +97,13 @@ class SharedLibrary : public std::enable_shared_from_this { uint64_t IntrinsicsAddress = 0; std::vector TypesAddress; std::vector CodesAddress; -#if WASMEDGE_OS_WINDOWS - void *PDataAddress = 0; +#if WASMEDGE_OS_LINUX + void *EHFrameAddress = nullptr; +#elif WASMEDGE_OS_MACOS + uint8_t *EHFrameAddress = nullptr; + uint32_t EHFrameSize = 0; +#elif WASMEDGE_OS_WINDOWS + void *PDataAddress = nullptr; uint32_t PDataSize = 0; #endif }; diff --git a/include/system/fault.h b/include/system/fault.h index 6b92bec08dac..562f32584ce4 100644 --- a/include/system/fault.h +++ b/include/system/fault.h @@ -15,7 +15,6 @@ #pragma once #include "common/errcode.h" - #include namespace WasmEdge { diff --git a/lib/aot/compiler.cpp b/lib/aot/compiler.cpp index 1e2e8a1665ac..02b04f473e2f 100644 --- a/lib/aot/compiler.cpp +++ b/lib/aot/compiler.cpp @@ -294,6 +294,7 @@ struct WasmEdge::AOT::Compiler::CompileContext { LLVM::Attribute NoReturn; LLVM::Attribute ReadOnly; LLVM::Attribute StrictFP; + LLVM::Attribute UWTable; LLVM::Attribute NoStackArgProbe; LLVM::Type VoidTy; LLVM::Type Int8Ty; @@ -371,7 +372,8 @@ struct WasmEdge::AOT::Compiler::CompileContext { NoInline(LLVM::Attribute::createEnum(C, LLVM::Core::NoInline, 0)), NoReturn(LLVM::Attribute::createEnum(C, LLVM::Core::NoReturn, 0)), ReadOnly(LLVM::Attribute::createEnum(C, LLVM::Core::ReadOnly, 0)), - StrictFP(LLVM::Attribute::createEnum(C, LLVM::Core::StrictFP, 0)), + StrictFP(LLVM::Attribute::createEnum(C, LLVM::Core::StrictFP, 1)), + UWTable(LLVM::Attribute::createEnum(C, LLVM::Core::UWTable, 0)), NoStackArgProbe( LLVM::Attribute::createString(C, "no-stack-arg-probe"sv, {})), VoidTy(LLContext.getVoidTy()), Int8Ty(LLContext.getInt8Ty()), @@ -422,6 +424,7 @@ struct WasmEdge::AOT::Compiler::CompileContext { Trap.Fn.setDSOLocal(true); Trap.Fn.addFnAttr(NoStackArgProbe); Trap.Fn.addFnAttr(StrictFP); + Trap.Fn.addFnAttr(UWTable); Trap.Fn.addFnAttr(NoReturn); Trap.Fn.addFnAttr(Cold); Trap.Fn.addFnAttr(NoInline); @@ -5219,13 +5222,12 @@ Expect outputNativeLibrary(const std::filesystem::path &OutputPath, "-dylib", "-demangle", "-macosx_version_min", OSVersion.c_str(), "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk", - ObjectName.u8string().c_str(), "-o", - OutputPath.u8string().c_str() //, - //"-lSystem" + ObjectName.u8string().c_str(), "-o", OutputPath.u8string().c_str() }, #elif WASMEDGE_OS_LINUX LinkResult = lld::elf::link( - std::initializer_list{"ld.lld", "--shared", "--gc-sections", + std::initializer_list{"ld.lld", "--eh-frame-hdr", + "--shared", "--gc-sections", "--discard-all", ObjectName.c_str(), "-o", OutputPath.u8string().c_str()}, #elif WASMEDGE_OS_WINDOWS @@ -5429,7 +5431,8 @@ Expect outputWasmLibrary(const std::filesystem::path &OutputPath, if (Section.getSize() == 0) { continue; } - if (!Section.isText() && !Section.isData() && !Section.isBSS()) { + if (!Section.isEHFrame() && !Section.isPData() && !Section.isText() && + !Section.isData() && !Section.isBSS()) { continue; } ++SectionCount; @@ -5447,7 +5450,7 @@ Expect outputWasmLibrary(const std::filesystem::path &OutputPath, } else { Content.assign(Res.begin(), Res.end()); } - if (Section.isPData()) { + if (Section.isEHFrame() || Section.isPData()) { WriteByte(OS, UINT8_C(4)); } else if (Section.isText()) { WriteByte(OS, UINT8_C(1)); @@ -5562,6 +5565,7 @@ Expect Compiler::compile(Span Data, const AST::Module &Module, F.setDSOLocal(true); F.addFnAttr(Context->NoStackArgProbe); F.addFnAttr(Context->StrictFP); + F.addFnAttr(Context->UWTable); F.addFnAttr(Context->NoReturn); LLVM::Builder Builder(Context->LLContext); Builder.positionAtEnd( @@ -5771,6 +5775,7 @@ void Compiler::compile(const AST::TypeSection &TypeSec) noexcept { F.setDLLStorageClass(LLVMDLLExportStorageClass); F.addFnAttr(Context->NoStackArgProbe); F.addFnAttr(Context->StrictFP); + F.addFnAttr(Context->UWTable); F.addParamAttr(0, Context->ReadOnly); F.addParamAttr(0, Context->NoAlias); F.addParamAttr(1, Context->NoAlias); @@ -5865,6 +5870,7 @@ void Compiler::compile(const AST::ImportSection &ImportSec) noexcept { } F.Fn.addFnAttr(Context->NoStackArgProbe); F.Fn.addFnAttr(Context->StrictFP); + F.Fn.addFnAttr(Context->UWTable); F.Fn.addParamAttr(0, Context->ReadOnly); F.Fn.addParamAttr(0, Context->NoAlias); @@ -6001,6 +6007,7 @@ void Compiler::compile(const AST::FunctionSection &FuncSec, F.Fn.setDLLStorageClass(LLVMDLLExportStorageClass); F.Fn.addFnAttr(Context->NoStackArgProbe); F.Fn.addFnAttr(Context->StrictFP); + F.Fn.addFnAttr(Context->UWTable); F.Fn.addParamAttr(0, Context->ReadOnly); F.Fn.addParamAttr(0, Context->NoAlias); diff --git a/lib/aot/llvm.h b/lib/aot/llvm.h index d7179f29019c..1b963e00345b 100644 --- a/lib/aot/llvm.h +++ b/lib/aot/llvm.h @@ -92,6 +92,7 @@ class Core { static inline unsigned int NoReturn = 0; static inline unsigned int ReadOnly = 0; static inline unsigned int StrictFP = 0; + static inline unsigned int UWTable = 0; static inline unsigned int InvariantGroup = 0; @@ -169,6 +170,7 @@ class Core { NoReturn = getEnumAttributeKind("noreturn"sv); ReadOnly = getEnumAttributeKind("readonly"sv); StrictFP = getEnumAttributeKind("strictfp"sv); + UWTable = getEnumAttributeKind("uwtable"sv); InvariantGroup = getMetadataKind("invariant.group"); } @@ -713,6 +715,11 @@ class Value { LLVM_FOR_EACH_VALUE_SUBCLASS(DECLARE_VALUE_CHECK) #undef DECLARE_VALUE_CHECK + std::string_view getValueName() noexcept { + size_t Size; + const auto Ptr = LLVMGetValueName2(Ref, &Size); + return {Ptr, Size}; + } inline void addFnAttr(const Attribute &A) noexcept; inline void addParamAttr(unsigned Index, const Attribute &A) noexcept; inline void addCallSiteAttribute(const Attribute &A) noexcept; @@ -723,8 +730,10 @@ class Value { Value getNextParam() noexcept { return LLVMGetNextParam(Ref); } Value getNextGlobal() noexcept { return LLVMGetNextGlobal(Ref); } Value getNextFunction() noexcept { return LLVMGetNextFunction(Ref); } + unsigned int countBasicBlocks() noexcept { return LLVMCountBasicBlocks(Ref); } Type getType() const noexcept { return LLVMTypeOf(Ref); } + Value getInitializer() noexcept { return LLVMGetInitializer(Ref); } void setInitializer(Value ConstantVal) noexcept { LLVMSetInitializer(Ref, ConstantVal.unwrap()); } @@ -1844,6 +1853,7 @@ class SectionIterator { inline bool isData() const noexcept; inline bool isBSS() const noexcept; inline bool isPData() const noexcept; + inline bool isEHFrame() const noexcept; private: LLVMSectionIteratorRef Ref = nullptr; @@ -1973,4 +1983,16 @@ bool SectionIterator::isPData() const noexcept { #endif } +bool SectionIterator::isEHFrame() const noexcept { +#if WASMEDGE_OS_LINUX + using namespace std::literals; + return ".eh_frame"sv == getName(); +#elif WASMEDGE_OS_MACOS + using namespace std::literals; + return "__eh_frame"sv == getName(); +#else + return false; +#endif +} + } // namespace WasmEdge::AOT::LLVM diff --git a/lib/executor/engine/proxy.cpp b/lib/executor/engine/proxy.cpp index c2ede34f09b8..d2e4d0d401f6 100644 --- a/lib/executor/engine/proxy.cpp +++ b/lib/executor/engine/proxy.cpp @@ -18,11 +18,7 @@ struct Executor::ProxyHelper (Executor::*)(Runtime::StackManager &, ArgsT...) noexcept> { template (Executor::*Func)(Runtime::StackManager &, ArgsT...) noexcept> - static auto proxy(ArgsT... Args) -#if !WASMEDGE_OS_WINDOWS - noexcept -#endif - { + static auto proxy(ArgsT... Args) { Expect Res = (This->*Func)(*CurrentStack, Args...); if (unlikely(!Res)) { Fault::emitFault(Res.error()); diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 3e5a02a47166..2e0e517f59dd 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -133,20 +133,23 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, prepare(StackMgr, ModInst->MemoryPtrs.data(), ModInst->GlobalPtrs.data()); } - { + try { // Get symbol and execute the function. Fault FaultHandler; uint32_t Code = PREPARE_FAULT(FaultHandler); - if (auto Err = ErrCode(static_cast(Code >> 24), Code); - unlikely(Err != ErrCode::Value::Success)) { + if (Code != 0) { + throw ErrCode(static_cast(Code >> 24), Code); + } + auto &Wrapper = FuncType.getSymbol(); + Wrapper(&ExecutionContext, Func.getSymbol().get(), Args.data(), + Rets.data()); + } catch (const ErrCode &Err) { + if (unlikely(Err != ErrCode::Value::Success)) { if (Err != ErrCode::Value::Terminated) { spdlog::error(Err); } return Unexpect(Err); } - auto &Wrapper = FuncType.getSymbol(); - Wrapper(&ExecutionContext, Func.getSymbol().get(), Args.data(), - Rets.data()); } // Push returns back to stack. diff --git a/lib/loader/shared_library.cpp b/lib/loader/shared_library.cpp index a868a897a40a..4de5e08643c5 100644 --- a/lib/loader/shared_library.cpp +++ b/lib/loader/shared_library.cpp @@ -21,6 +21,13 @@ #error Unsupported os! #endif +#if WASMEDGE_OS_LINUX || WASMEDGE_OS_MACOS +extern "C" { +extern void __register_frame(void *); +extern void __deregister_frame(void *); +} +#endif + namespace { inline constexpr uint64_t roundDownPageBoundary(const uint64_t Value) { // ARM64 Mac has a special page size @@ -112,7 +119,16 @@ Expect SharedLibrary::load(const AST::AOTSection &AOTSec) noexcept { break; case 3: // BSS break; -#if WASMEDGE_OS_WINDOWS +#if WASMEDGE_OS_LINUX + case 4: // EHFrame + EHFrameAddress = reinterpret_cast(Binary + Offset); + break; +#elif WASMEDGE_OS_MACOS + case 4: // EHFrame + EHFrameAddress = reinterpret_cast(Binary + Offset); + EHFrameSize = Size; + break; +#elif WASMEDGE_OS_WINDOWS case 4: // PData PDataAddress = reinterpret_cast(Binary + Offset); PDataSize = @@ -136,7 +152,24 @@ Expect SharedLibrary::load(const AST::AOTSection &AOTSec) noexcept { TypesAddress = AOTSec.getTypesAddress(); CodesAddress = AOTSec.getCodesAddress(); -#if WASMEDGE_OS_WINDOWS +#if WASMEDGE_OS_LINUX + if (EHFrameAddress) { + __register_frame(EHFrameAddress); + } +#elif WASMEDGE_OS_MACOS + if (EHFrameAddress) { + auto Iter = EHFrameAddress; + const auto End = EHFrameAddress + EHFrameSize - 4; + + while (Iter < End) { + if (Iter != EHFrameAddress) { + __register_frame(Iter); + } + const uint32_t Length = *reinterpret_cast(Iter); + Iter += Length + 4; + } + } +#elif WASMEDGE_OS_WINDOWS if (PDataSize != 0) { winapi::RtlAddFunctionTable( static_cast(PDataAddress), PDataSize, @@ -149,7 +182,24 @@ Expect SharedLibrary::load(const AST::AOTSection &AOTSec) noexcept { void SharedLibrary::unload() noexcept { if (Binary) { -#if WASMEDGE_OS_WINDOWS +#if WASMEDGE_OS_LINUX + if (EHFrameAddress) { + __deregister_frame(EHFrameAddress); + } +#elif WASMEDGE_OS_MACOS + if (EHFrameAddress) { + auto Iter = EHFrameAddress; + const auto End = EHFrameAddress + EHFrameSize - 4; + + while (Iter < End) { + if (Iter != EHFrameAddress) { + __deregister_frame(Iter); + } + const uint32_t Length = *reinterpret_cast(Iter); + Iter += Length + 4; + } + } +#elif WASMEDGE_OS_WINDOWS if (PDataSize != 0) { winapi::RtlDeleteFunctionTable( static_cast(PDataAddress)); diff --git a/lib/system/fault.cpp b/lib/system/fault.cpp index 2d0a39764e06..e3e954f7bbd7 100644 --- a/lib/system/fault.cpp +++ b/lib/system/fault.cpp @@ -25,8 +25,7 @@ std::atomic_uint handlerCount = 0; thread_local Fault *localHandler = nullptr; #if defined(SA_SIGINFO) -[[noreturn]] void signalHandler(int Signal, siginfo_t *Siginfo [[maybe_unused]], - void *) noexcept { +void signalHandler(int Signal, siginfo_t *Siginfo, void *) { { // Unblock current signal sigset_t Set; From 6c38365fec50339d7da8b8cddad2949ce45ac398 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:14:09 +0800 Subject: [PATCH 011/218] [CI] Bump actions/setup-python from 4 to 5 (#3088) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test-python-install-script.yml | 2 +- .github/workflows/wasi-testsuite.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-python-install-script.yml b/.github/workflows/test-python-install-script.yml index 38d84779fbde..7b59f79437eb 100644 --- a/.github/workflows/test-python-install-script.yml +++ b/.github/workflows/test-python-install-script.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Python env - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 - name: Install black run: pip install black diff --git a/.github/workflows/wasi-testsuite.yml b/.github/workflows/wasi-testsuite.yml index 7becc15cce3e..b92e3e8d4cd6 100644 --- a/.github/workflows/wasi-testsuite.yml +++ b/.github/workflows/wasi-testsuite.yml @@ -68,7 +68,7 @@ jobs: path: wasi-testsuite - name: Initialize Python environment - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' cache: pip From 7839b1f8f19d2cea56b548077f11f85f9ceee418 Mon Sep 17 00:00:00 2001 From: vincent Date: Sun, 4 Feb 2024 01:02:03 +0800 Subject: [PATCH 012/218] [Misc] Update the printed messages to match the actual installed version of OpenVINO. (#3193) Signed-off-by: vincent --- utils/wasi-nn/install-openvino.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/wasi-nn/install-openvino.sh b/utils/wasi-nn/install-openvino.sh index 761b6a21d2f8..57afdee82455 100755 --- a/utils/wasi-nn/install-openvino.sh +++ b/utils/wasi-nn/install-openvino.sh @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2019-2022 Second State INC set -e -echo "Installing OpenVINO with version 2023.0.2" +echo "Installing OpenVINO with version 2023.2.0" wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB echo "deb https://apt.repos.intel.com/openvino/2023 ubuntu20 main" | tee /etc/apt/sources.list.d/intel-openvino-2023.list From 01ead70615f59f5afb95f4dd4e55342d92f1ba59 Mon Sep 17 00:00:00 2001 From: "Shen-Ta Hsieh(BestSteve)" Date: Mon, 5 Feb 2024 20:45:21 +0800 Subject: [PATCH 013/218] [AOT] Fix windows build (#3195) * Change StrictFP value to 0 * Change UWTable value to 2 (UWTable::Default) * Move ErrCode handling code after try-catch block * Adjust compile options on windows Signed-off-by: Shen-Ta Hsieh --- cmake/Helper.cmake | 3 ++- lib/aot/CMakeLists.txt | 12 +++++++----- lib/aot/compiler.cpp | 5 +++-- lib/aot/llvm.h | 10 ++++++---- lib/executor/helper.cpp | 23 +++++++++++++---------- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index a738ce80617b..3b4aa6d8ec07 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -69,6 +69,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") -Wno-documentation-unknown-command -Wno-error=nested-anon-types -Wno-error=old-style-cast + -Wno-error=shadow -Wno-error=unused-command-line-argument -Wno-error=unknown-warning-option -Wno-ctad-maybe-unsupported @@ -80,6 +81,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") -Wno-signed-enum-bitfield -Wno-switch-enum -Wno-undefined-func-template + -Wno-deprecated-literal-operator ) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0.0) list(APPEND WASMEDGE_CFLAGS @@ -97,7 +99,6 @@ if(WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DNOMINMAX -D_ITERATOR_DEBUG_LEVEL=0) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") list(APPEND WASMEDGE_CFLAGS - "/EHa" -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-exit-time-destructors diff --git a/lib/aot/CMakeLists.txt b/lib/aot/CMakeLists.txt index 1ba8247b49bf..b937d4447bc5 100644 --- a/lib/aot/CMakeLists.txt +++ b/lib/aot/CMakeLists.txt @@ -43,7 +43,7 @@ else() # Command line warning D9025 : overriding '/EHs' with '/EHs-' # prevent LLVM from adding /EHs-c-. - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + if(WIN32) set(LLVM_REQUIRES_EH ON) endif() @@ -93,8 +93,10 @@ if(SUPPORT_EXCLUDE_LIBS) file(GLOB LLD_ALL_LIBS ${LLVM_LIBRARY_DIR}/liblld*.a) list(TRANSFORM LLD_ALL_LIBS REPLACE "^.*/" "") string(JOIN : LLD_ALL_LIBS_COLON ${LLD_ALL_LIBS}) - target_link_options(wasmedgeAOT - PUBLIC - "SHELL:-Wl,--exclude-libs=${LLD_ALL_LIBS_COLON}" - ) + if(NOT LLD_ALL_LIBS_COLON STREQUAL "") + target_link_options(wasmedgeAOT + PUBLIC + "SHELL:-Wl,--exclude-libs=${LLD_ALL_LIBS_COLON}" + ) + endif() endif() diff --git a/lib/aot/compiler.cpp b/lib/aot/compiler.cpp index 02b04f473e2f..a694254741ad 100644 --- a/lib/aot/compiler.cpp +++ b/lib/aot/compiler.cpp @@ -372,8 +372,9 @@ struct WasmEdge::AOT::Compiler::CompileContext { NoInline(LLVM::Attribute::createEnum(C, LLVM::Core::NoInline, 0)), NoReturn(LLVM::Attribute::createEnum(C, LLVM::Core::NoReturn, 0)), ReadOnly(LLVM::Attribute::createEnum(C, LLVM::Core::ReadOnly, 0)), - StrictFP(LLVM::Attribute::createEnum(C, LLVM::Core::StrictFP, 1)), - UWTable(LLVM::Attribute::createEnum(C, LLVM::Core::UWTable, 0)), + StrictFP(LLVM::Attribute::createEnum(C, LLVM::Core::StrictFP, 0)), + // UWTable::Default = 2 + UWTable(LLVM::Attribute::createEnum(C, LLVM::Core::UWTable, 2)), NoStackArgProbe( LLVM::Attribute::createString(C, "no-stack-arg-probe"sv, {})), VoidTy(LLContext.getVoidTy()), Int8Ty(LLContext.getInt8Ty()), diff --git a/lib/aot/llvm.h b/lib/aot/llvm.h index 1b963e00345b..30143e89982f 100644 --- a/lib/aot/llvm.h +++ b/lib/aot/llvm.h @@ -172,7 +172,7 @@ class Core { StrictFP = getEnumAttributeKind("strictfp"sv); UWTable = getEnumAttributeKind("uwtable"sv); - InvariantGroup = getMetadataKind("invariant.group"); + InvariantGroup = getMetadataKind("invariant.group"sv); } template @@ -839,10 +839,10 @@ class Attribute { uint64_t Val) noexcept { return LLVMCreateEnumAttribute(C.unwrap(), KindID, Val); } - static Attribute createString(Context &C, std::string_view KindID, + static Attribute createString(Context &C, std::string_view Kind, std::string_view Val) noexcept { return LLVMCreateStringAttribute( - C.unwrap(), KindID.data(), static_cast(KindID.size()), + C.unwrap(), Kind.data(), static_cast(Kind.size()), Val.data(), static_cast(Val.size())); } @@ -863,7 +863,9 @@ Value Module::addGlobal(Type Ty, bool IsConstant, LLVMLinkage Linkage, Value G = LLVMAddGlobal(Ref, Ty.unwrap(), Name); G.setLinkage(Linkage); G.setGlobalConstant(IsConstant); - G.setInitializer(Initializer); + if (Initializer) { + G.setInitializer(Initializer); + } return G; } diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 2e0e517f59dd..7bd8ccb887ea 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -133,23 +133,26 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, prepare(StackMgr, ModInst->MemoryPtrs.data(), ModInst->GlobalPtrs.data()); } + ErrCode Err; try { // Get symbol and execute the function. Fault FaultHandler; uint32_t Code = PREPARE_FAULT(FaultHandler); if (Code != 0) { - throw ErrCode(static_cast(Code >> 24), Code); + Err = ErrCode(static_cast(Code >> 24), Code); + } else { + auto &Wrapper = FuncType.getSymbol(); + Wrapper(&ExecutionContext, Func.getSymbol().get(), Args.data(), + Rets.data()); } - auto &Wrapper = FuncType.getSymbol(); - Wrapper(&ExecutionContext, Func.getSymbol().get(), Args.data(), - Rets.data()); - } catch (const ErrCode &Err) { - if (unlikely(Err != ErrCode::Value::Success)) { - if (Err != ErrCode::Value::Terminated) { - spdlog::error(Err); - } - return Unexpect(Err); + } catch (const ErrCode &E) { + Err = E; + } + if (unlikely(Err)) { + if (Err != ErrCode::Value::Terminated) { + spdlog::error(Err); } + return Unexpect(Err); } // Push returns back to stack. From 7778b2f86300b4b1ea32b2534f04b13d625bec96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 03:11:07 +0800 Subject: [PATCH 014/218] [CI] Bump GuillaumeFalourd/setup-windows10-sdk-action from 1 to 2 (#3196) Bumps [GuillaumeFalourd/setup-windows10-sdk-action](https://github.com/guillaumefalourd/setup-windows10-sdk-action) from 1 to 2. - [Release notes](https://github.com/guillaumefalourd/setup-windows10-sdk-action/releases) - [Commits](https://github.com/guillaumefalourd/setup-windows10-sdk-action/compare/v1...v2) --- updated-dependencies: - dependency-name: GuillaumeFalourd/setup-windows10-sdk-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/bindings-java.yml | 2 +- .github/workflows/reusable-build-on-windows-msvc.yml | 2 +- .github/workflows/reusable-build-on-windows.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bindings-java.yml b/.github/workflows/bindings-java.yml index b6ec7648351d..d69d992b3737 100644 --- a/.github/workflows/bindings-java.yml +++ b/.github/workflows/bindings-java.yml @@ -162,7 +162,7 @@ jobs: with: args: install cmake ninja vswhere - - uses: GuillaumeFalourd/setup-windows10-sdk-action@v1 + - uses: GuillaumeFalourd/setup-windows10-sdk-action@v2 with: sdk-version: 19041 diff --git a/.github/workflows/reusable-build-on-windows-msvc.yml b/.github/workflows/reusable-build-on-windows-msvc.yml index 2bed2e18429e..2ed200295c1b 100644 --- a/.github/workflows/reusable-build-on-windows-msvc.yml +++ b/.github/workflows/reusable-build-on-windows-msvc.yml @@ -28,7 +28,7 @@ jobs: uses: crazy-max/ghaction-chocolatey@v3 with: args: install cmake ninja vswhere - - uses: GuillaumeFalourd/setup-windows10-sdk-action@v1.11 + - uses: GuillaumeFalourd/setup-windows10-sdk-action@v2 with: sdk-version: 19041 - name: Set environment variables for release diff --git a/.github/workflows/reusable-build-on-windows.yml b/.github/workflows/reusable-build-on-windows.yml index 295b5e9a5875..35f47afb8114 100644 --- a/.github/workflows/reusable-build-on-windows.yml +++ b/.github/workflows/reusable-build-on-windows.yml @@ -28,7 +28,7 @@ jobs: uses: crazy-max/ghaction-chocolatey@v3 with: args: install cmake ninja vswhere - - uses: GuillaumeFalourd/setup-windows10-sdk-action@v1.11 + - uses: GuillaumeFalourd/setup-windows10-sdk-action@v2 with: sdk-version: 19041 - name: Set environment variables for release From 6865695bb45c83f93438980ed111ad4479510095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Wed, 7 Feb 2024 22:13:26 +0800 Subject: [PATCH 015/218] [component model] section order will affect index space (#3202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [component model] section order will affect index space which means these orders have semantic Signed-off-by: Lîm Tsú-thuàn --- include/ast/module.h | 55 +++++++----------------- include/ast/section.h | 17 +++----- include/loader/loader.h | 1 + lib/loader/ast/component.cpp | 81 ++++++++++++++++++++++-------------- lib/loader/ast/section.cpp | 10 ++++- lib/validator/validator.cpp | 18 +++++--- 6 files changed, 91 insertions(+), 91 deletions(-) diff --git a/include/ast/module.h b/include/ast/module.h index 7f74f77ed058..9661e25643b7 100644 --- a/include/ast/module.h +++ b/include/ast/module.h @@ -143,15 +143,22 @@ class Module { class CoreModuleSection : public Section { public: /// Getter of content. - Span getContent() const noexcept { return Content; } - std::vector &getContent() noexcept { return Content; } + const Module &getContent() const noexcept { return Content; } + Module &getContent() noexcept { return Content; } private: - std::vector Content; + Module Content; }; namespace Component { + class Component { + using Section = + std::variant; + public: /// Getter of magic vector. const std::vector &getMagic() const noexcept { return Magic; } @@ -165,32 +172,8 @@ class Component { const std::vector &getLayer() const noexcept { return Layer; } std::vector &getLayer() noexcept { return Layer; } - std::vector &getCustomSections() noexcept { - return CustomSecs; - } - CoreModuleSection &getCoreModuleSection() noexcept { return CoreModSec; } - const CoreModuleSection &getCoreModuleSection() const noexcept { - return CoreModSec; - } - std::vector &getCoreInstanceSection() noexcept { - return CoreInstSec; - } - std::vector &getCoreTypeSection() noexcept { - return CoreTypeSec; - } - ComponentSection &getComponentSection() noexcept { return CompSec; } - const ComponentSection &getComponentSection() const noexcept { - return CompSec; - } - std::vector &getInstanceSection() noexcept { - return InstSec; - } - std::vector &getAliasSection() noexcept { return AliasSec; } - std::vector &getTypeSection() noexcept { return TySec; } - std::vector &getCanonSection() noexcept { return CanonSec; } - StartSection &getStartSection() noexcept { return StartSec; } - std::vector &getImportSection() noexcept { return ImSec; } - std::vector &getExportSection() noexcept { return ExSec; } + std::vector
&getSections() noexcept { return Secs; } + Span getSections() const noexcept { return Secs; } private: /// \name Data of Module node. @@ -198,18 +181,8 @@ class Component { std::vector Magic; std::vector Version; std::vector Layer; - std::vector CustomSecs; - CoreModuleSection CoreModSec; - std::vector CoreInstSec; - std::vector CoreTypeSec; - ComponentSection CompSec; - std::vector InstSec; - std::vector AliasSec; - std::vector TySec; - std::vector CanonSec; - StartSection StartSec; - std::vector ImSec; - std::vector ExSec; + + std::vector
Secs; /// @} }; diff --git a/include/ast/section.h b/include/ast/section.h index a492dcdc9991..5de8389b9073 100644 --- a/include/ast/section.h +++ b/include/ast/section.h @@ -372,13 +372,13 @@ class CanonSection : public Section { class StartSection : public Section { public: /// Getter of content module. - Span getContent() const noexcept { return Content; } - std::vector &getContent() noexcept { return Content; } + const Start &getContent() const noexcept { return Content; } + Start &getContent() noexcept { return Content; } private: /// \name Data of StartSection. /// @{ - std::vector Content; + Start Content; /// @} }; @@ -411,18 +411,13 @@ class ExportSection : public Section { class Component; class ComponentSection : public Section { - public: /// Getter of content. - Span> getContent() const noexcept { - return Content; - } - std::vector> &getContent() noexcept { - return Content; - } + const Component &getContent() const noexcept { return *Content; } + std::shared_ptr getContent() noexcept { return Content; } private: - std::vector> Content; + std::shared_ptr Content; }; } // namespace Component diff --git a/include/loader/loader.h b/include/loader/loader.h index 0aa2b0d946c4..dff8641ece1e 100644 --- a/include/loader/loader.h +++ b/include/loader/loader.h @@ -307,6 +307,7 @@ class Loader { Expect loadSection(AST::Component::AliasSection &Sec); Expect loadSection(AST::Component::CoreTypeSection &Sec); Expect loadSection(AST::Component::TypeSection &Sec); + Expect loadSection(AST::Component::StartSection &Sec); Expect loadSection(AST::Component::CanonSection &Sec); Expect loadSection(AST::Component::ImportSection &Sec); Expect loadSection(AST::Component::ExportSection &Sec); diff --git a/lib/loader/ast/component.cpp b/lib/loader/ast/component.cpp index dee412aa64c8..328842d981d4 100644 --- a/lib/loader/ast/component.cpp +++ b/lib/loader/ast/component.cpp @@ -97,6 +97,8 @@ Loader::loadUnit() { } Expect Loader::loadComponent(AST::Component::Component &Comp) { + using namespace AST::Component; + while (auto ResSecId = FMgr.readByte()) { if (!ResSecId) { return logLoadError(ResSecId.error(), FMgr.getLastOffset(), @@ -107,103 +109,120 @@ Expect Loader::loadComponent(AST::Component::Component &Comp) { switch (NewSectionId) { case 0x00: - Comp.getCustomSections().emplace_back(); - if (auto Res = loadSection(Comp.getCustomSections().back()); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = loadSection( + Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } break; case 0x01: - if (auto Res = loadSection(Comp.getCoreModuleSection()); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = loadSection( + Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } break; case 0x02: { - AST::Component::CoreInstanceSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = loadSection( + Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getCoreInstanceSection().push_back(Sec); break; } case 0x03: { - AST::Component::CoreTypeSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getCoreTypeSection().push_back(Sec); break; } case 0x04: - if (auto Res = loadSection(Comp.getComponentSection()); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = loadSection( + Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } break; case 0x05: { - AST::Component::InstanceSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getInstanceSection().push_back(Sec); break; } case 0x06: { - AST::Component::AliasSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getAliasSection().push_back(Sec); break; } case 0x07: { - AST::Component::TypeSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getTypeSection().push_back(Sec); break; } case 0x08: { - AST::Component::CanonSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getCanonSection().push_back(Sec); break; } case 0x09: { - AST::Component::Start S; - if (auto Res = loadStart(S); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getStartSection().getContent().push_back(S); break; } case 0x0A: { - AST::Component::ImportSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getImportSection().push_back(Sec); break; } case 0x0B: { - AST::Component::ExportSection Sec; - if (auto Res = loadSection(Sec); !Res) { + Comp.getSections().emplace_back(); + if (auto Res = + loadSection(Comp.getSections().back().emplace()); + !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Comp.getExportSection().push_back(Sec); break; } default: diff --git a/lib/loader/ast/section.cpp b/lib/loader/ast/section.cpp index a6ba7b04f83b..a0093378aa26 100644 --- a/lib/loader/ast/section.cpp +++ b/lib/loader/ast/section.cpp @@ -194,7 +194,7 @@ Expect Loader::loadSection(AST::Component::ComponentSection &Sec) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); return Unexpect(Res); } - Sec.getContent().push_back(NestedComp); + Sec.getContent() = NestedComp; return {}; } @@ -224,7 +224,7 @@ Expect Loader::loadSection(AST::CoreModuleSection &Sec) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Module)); return Unexpect(Res); } - Sec.getContent().push_back(CoreMod); + Sec.getContent() = CoreMod; return {}; }); } @@ -267,6 +267,12 @@ Expect Loader::loadSection(AST::Component::TypeSection &Sec) { }); } +Expect Loader::loadSection(AST::Component::StartSection &Sec) { + return loadSectionContent(Sec, [this, &Sec]() -> Expect { + return loadStart(Sec.getContent()); + }); +} + Expect Loader::loadSection(AST::Component::CanonSection &Sec) { return loadSectionContent(Sec, [this, &Sec]() { return loadSectionContentVec( diff --git a/lib/validator/validator.cpp b/lib/validator/validator.cpp index 3d8c6fe5cdcd..188603b2c359 100644 --- a/lib/validator/validator.cpp +++ b/lib/validator/validator.cpp @@ -14,14 +14,20 @@ namespace WasmEdge { namespace Validator { Expect Validator::validate(const AST::Component::Component &Comp) { + using namespace AST::Component; + spdlog::warn("component validation is not done yet."); - for (auto &Mod : Comp.getCoreModuleSection().getContent()) { - validate(Mod); - } - for (const std::shared_ptr &C : - Comp.getComponentSection().getContent()) { - validate(*C); + for (auto &Sec : Comp.getSections()) { + if (std::holds_alternative(Sec)) { + auto &Mod = std::get(Sec).getContent(); + validate(Mod); + } else if (std::holds_alternative(Sec)) { + auto &C = std::get(Sec).getContent(); + validate(C); + } else { + // TODO: validate others section + } } return {}; From 5eea3ec70c1f53f338002c729820b30a54531577 Mon Sep 17 00:00:00 2001 From: "LO, CHIN-HAO" <49036880+hankluo6@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:43:50 -0600 Subject: [PATCH 016/218] [Misc] Fix the linking error with simdjson (#3206) Signed-off-by: hankluo6 --- plugins/wasi_nn/CMakeLists.txt | 2 +- test/spec/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 5066af48a730..f3963fb3b434 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -143,7 +143,7 @@ target_include_directories(wasmedgePluginWasiNN if(BACKEND STREQUAL "ggml") target_include_directories(wasmedgePluginWasiNN PUBLIC ${CMAKE_BINARY_DIR}/_deps/llama-src) - target_link_libraries(wasmedgePluginWasiNN PRIVATE common simdjson) + target_link_libraries(wasmedgePluginWasiNN PRIVATE common simdjson::simdjson) if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL) add_custom_command( TARGET wasmedgePluginWasiNN diff --git a/test/spec/CMakeLists.txt b/test/spec/CMakeLists.txt index 0e1eabe48bc5..aca888a0d6f7 100644 --- a/test/spec/CMakeLists.txt +++ b/test/spec/CMakeLists.txt @@ -86,7 +86,7 @@ wasmedge_add_library(wasmedgeTestSpec target_link_libraries(wasmedgeTestSpec PRIVATE - simdjson + simdjson::simdjson PUBLIC std::filesystem wasmedgeCommon From 20a2bfe8d1b38f9ac4d8d09d54241bc6fefa2609 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 13 Feb 2024 16:04:48 +0800 Subject: [PATCH 017/218] [Zlib] Use the zlib package from system Signed-off-by: hydai --- plugins/wasmedge_zlib/CMakeLists.txt | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/plugins/wasmedge_zlib/CMakeLists.txt b/plugins/wasmedge_zlib/CMakeLists.txt index 30fa7d733d40..f12889bfb276 100644 --- a/plugins/wasmedge_zlib/CMakeLists.txt +++ b/plugins/wasmedge_zlib/CMakeLists.txt @@ -1,19 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -# Don't reply on System zlib -# find_package(ZLIB REQUIRED) +find_package(ZLIB REQUIRED) set(ZLIB_COMPAT ON) -set(ZLIBNG_ENABLE_TESTS OFF) - -FetchContent_Declare( - zlib - GIT_REPOSITORY "https://github.com/zlib-ng/zlib-ng.git" - GIT_TAG 2.0.7 - GIT_PROGRESS TRUE -) -FetchContent_MakeAvailable(zlib) wasmedge_add_library(wasmedgePluginWasmEdgeZlib SHARED @@ -37,13 +27,13 @@ if(WASMEDGE_LINK_PLUGINS_STATIC) target_link_libraries(wasmedgePluginWasmEdgeZlib PRIVATE wasmedgeCAPI - zlib + z ) else() target_link_libraries(wasmedgePluginWasmEdgeZlib PRIVATE wasmedge_shared - zlib + z ) endif() From eb3526d3277a15b1cfd10c0aa187dda74925faa8 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 13 Feb 2024 16:55:39 +0800 Subject: [PATCH 018/218] [CI] No longer build zlib on manylinux2014, due to the API incompatible Signed-off-by: hydai --- .github/workflows/build-extensions.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 060c8b60db9e..6e3d7f2eaa59 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -319,16 +319,16 @@ jobs: env: output_prefix: build/plugins test_prefix: build/test/plugins - build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON + build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON build_options_manylinux2014_x86_64: -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF build_options_manylinux2014_aarch64: - tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_zlib + tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini tar_names_manylinux2014_x86_64: wasm_bpf tar_names_manylinux2014_aarch64: - test_bins_all_platforms: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests wasmedgeZlibTests + test_bins_all_platforms: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests test_bins_manylinux2014_x86_64: wasmBpfTests test_bins_manylinux2014_aarch64: - output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeZlib.so + output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so output_bins_manylinux2014_x86_64: libwasmedgePluginWasmBpf.so output_bins_manylinux2014_aarch64: needs: [get_version] From 208b491fc4d821127d61bcfcdb5e8814b435eed0 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 13 Feb 2024 16:09:13 +0800 Subject: [PATCH 019/218] [OpenWrt] Bump the WasmEdge version and API version Signed-off-by: hydai --- utils/openwrt/configuration/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/openwrt/configuration/Makefile b/utils/openwrt/configuration/Makefile index 08995b25b9b5..c1d244dcd134 100644 --- a/utils/openwrt/configuration/Makefile +++ b/utils/openwrt/configuration/Makefile @@ -1,9 +1,9 @@ include $(TOPDIR)/rules.mk - + PKG_NAME:=WasmEdge -PKG_VERSION:=0.12.1 +PKG_VERSION:=0.14.0 PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME) -WASMEDGE_SOVERSION:=0.0.2 +WASMEDGE_SOVERSION:=0.0.3 WASMEDGE_SONAME:=0 include $(INCLUDE_DIR)/package.mk From 2ae08dc4b894ca3f9dc24881efc0741311c9db08 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 5 Dec 2023 17:02:45 +0800 Subject: [PATCH 020/218] [AOT] Move LLVM-related code into separate directory * Rename cmake config WASMEDGE_BUILD_AOT_RUNTIME into WASMEDGE_USE_LLVM * Add a warning if old config was supplied * Separate out `CodeGen` function from `Compiler` class * Add `LLVM::Data` class for transfer `LLVM::Context` and `LLVM::Module` * Use `fpexcept.strict` for correct NAN-related behaviors Signed-off-by: Shen-Ta Hsieh --- .../workflows/reusable-build-on-android.yml | 2 +- CMakeLists.txt | 7 +- cmake/Helper.cmake | 2 +- examples/embed_cxx/CMakeLists.txt | 2 +- examples/embed_cxx/README.md | 2 +- examples/plugin/wasmedge-zlib/README.md | 2 +- flake.nix | 2 +- include/ast/section.h | 1 + include/llvm/codegen.h | 38 + include/{aot => llvm}/compiler.h | 14 +- include/llvm/data.h | 41 + lib/CMakeLists.txt | 3 +- lib/aot/CMakeLists.txt | 97 +-- lib/api/CMakeLists.txt | 10 +- lib/api/wasmedge.cpp | 62 +- lib/driver/CMakeLists.txt | 7 +- lib/driver/compilerTool.cpp | 15 +- lib/driver/fuzzTool.cpp | 16 +- lib/llvm/CMakeLists.txt | 99 +++ lib/llvm/codegen.cpp | 632 +++++++++++++++ lib/{aot => llvm}/compiler.cpp | 759 ++---------------- lib/llvm/data.cpp | 19 + lib/llvm/data.h | 13 + lib/{aot => llvm}/llvm.h | 21 +- test/CMakeLists.txt | 3 +- test/aot/CMakeLists.txt | 16 - test/api/APIUnitTest.cpp | 4 +- test/api/CMakeLists.txt | 6 +- test/llvm/CMakeLists.txt | 18 + .../AOTcoreTest.cpp => llvm/LLVMcoreTest.cpp} | 93 ++- test/mixcall/CMakeLists.txt | 2 +- test/mixcall/mixcallTest.cpp | 33 +- test/thread/CMakeLists.txt | 6 +- test/thread/ThreadTest.cpp | 21 +- thirdparty/CMakeLists.txt | 2 +- tools/wasmedge/CMakeLists.txt | 2 +- .../app/lib/src/main/cpp/CMakeLists.txt | 2 +- utils/android/standalone/build_for_android.sh | 2 +- utils/docker/Dockerfile.alpine-static | 2 +- utils/docker/Dockerfile.debian-static | 4 +- utils/ohos/build_for_ohos.sh | 2 +- utils/ohos/configuration/CMakeLists.txt | 2 +- utils/openwrt/configuration/Makefile | 2 +- 43 files changed, 1167 insertions(+), 921 deletions(-) create mode 100644 include/llvm/codegen.h rename include/{aot => llvm}/compiler.h (80%) create mode 100644 include/llvm/data.h create mode 100644 lib/llvm/CMakeLists.txt create mode 100644 lib/llvm/codegen.cpp rename lib/{aot => llvm}/compiler.cpp (90%) create mode 100644 lib/llvm/data.cpp create mode 100644 lib/llvm/data.h rename lib/{aot => llvm}/llvm.h (99%) create mode 100644 test/llvm/CMakeLists.txt rename test/{aot/AOTcoreTest.cpp => llvm/LLVMcoreTest.cpp} (86%) diff --git a/.github/workflows/reusable-build-on-android.yml b/.github/workflows/reusable-build-on-android.yml index dfb3b689d6f6..4e9912389b1b 100644 --- a/.github/workflows/reusable-build-on-android.yml +++ b/.github/workflows/reusable-build-on-android.yml @@ -39,7 +39,7 @@ jobs: - name: Build WasmEdge run: | export ANDROID_NDK_HOME=$(pwd)/android-ndk-r23b/ - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_PACKAGE="TGZ" -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=23 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_ANDROID_NDK=$ANDROID_NDK_HOME -DCMAKE_ANDROID_STL_TYPE=c++_static + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_PACKAGE="TGZ" -DWASMEDGE_USE_LLVM=OFF -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=23 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_ANDROID_NDK=$ANDROID_NDK_HOME -DCMAKE_ANDROID_STL_TYPE=c++_static cmake --build build cmake --build build --target package - name: Upload artifact diff --git a/CMakeLists.txt b/CMakeLists.txt index 96257ea564b8..eaaa64b9a73e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,6 @@ find_package(Threads REQUIRED) # List of WasmEdge options option(WASMEDGE_BUILD_TESTS "Generate build targets for the wasmedge unit tests." OFF) option(WASMEDGE_BUILD_COVERAGE "Generate coverage report. Require WASMEDGE_BUILD_TESTS." OFF) -option(WASMEDGE_BUILD_AOT_RUNTIME "Enable WasmEdge LLVM-based ahead of time compilation runtime." ON) option(WASMEDGE_BUILD_SHARED_LIB "Generate the WasmEdge shared library." ON) option(WASMEDGE_BUILD_STATIC_LIB "Generate the WasmEdge static library." OFF) option(WASMEDGE_BUILD_TOOLS "Generate wasmedge and wasmedgec tools. Depend on and will build the WasmEdge shared library." ON) @@ -67,6 +66,12 @@ option(WASMEDGE_BUILD_FUZZING "Generate fuzzing test tools. Couldn't build with option(WASMEDGE_BUILD_PLUGINS "Generate plugins." ON) option(WASMEDGE_BUILD_EXAMPLE "Generate examples." OFF) option(WASMEDGE_BUILD_WASI_NN_RPC "Generate Wasi-NN RPC." OFF) +option(WASMEDGE_USE_LLVM "Enable WasmEdge LLVM-based compilation runtime." ON) +if(WASMEDGE_BUILD_AOT_RUNTIME) + message(WARNING "WASMEDGE_BUILD_AOT_RUNTIME option was renamed to WASMEDGE_USE_LLVM") + set(WASMEDGE_USE_LLVM "${WASMEDGE_BUILD_AOT_RUNTIME}" CACHE STRING "Enable WasmEdge LLVM-based compilation runtime.") + unset(WASMEDGE_BUILD_AOT_RUNTIME CACHE) +endif() option(WASMEDGE_FORCE_DISABLE_LTO "Forcefully disable link time optimization when linking even in Release/RelWithDeb build." OFF) option(WASMEDGE_LINK_LLVM_STATIC "Statically link the LLVM library into the WasmEdge tools and libraries." OFF) option(WASMEDGE_LINK_TOOLS_STATIC "Statically link the wasmedge and wasmedgec tools. Will forcefully link the LLVM library statically." OFF) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 3b4aa6d8ec07..f4356ec43153 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -190,7 +190,7 @@ function(wasmedge_add_executable target) endfunction() # Generate the list of static libs to statically link LLVM. -if((WASMEDGE_LINK_LLVM_STATIC OR WASMEDGE_BUILD_STATIC_LIB) AND WASMEDGE_BUILD_AOT_RUNTIME) +if((WASMEDGE_LINK_LLVM_STATIC OR WASMEDGE_BUILD_STATIC_LIB) AND WASMEDGE_USE_LLVM) # Pack the LLVM and lld static libraries. find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_PATH}") execute_process( diff --git a/examples/embed_cxx/CMakeLists.txt b/examples/embed_cxx/CMakeLists.txt index 8bd184f8d0c0..e9851eddf6b2 100644 --- a/examples/embed_cxx/CMakeLists.txt +++ b/examples/embed_cxx/CMakeLists.txt @@ -5,7 +5,7 @@ project(embed_cxx CXX) set(CMAKE_CXX_STANDARD 17) set(WASMEDGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..) -set(WASMEDGE_BUILD_AOT_RUNTIME OFF) +set(WASMEDGE_USE_LLVM OFF) if (CMAKE_GENERATOR STREQUAL Ninja) set(CMAKE_JOB_POOLS "link=2") set(CMAKE_JOB_POOL_LINK link) diff --git a/examples/embed_cxx/README.md b/examples/embed_cxx/README.md index 1157c078fdda..3d10e7f20e60 100644 --- a/examples/embed_cxx/README.md +++ b/examples/embed_cxx/README.md @@ -7,7 +7,7 @@ First, download and extract [wasi-sdk](https://github.com/WebAssembly/wasi-sdk/r Build with cmake ```bash -cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF; cmake --build build +cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF; cmake --build build ``` Run `embed_cxx` diff --git a/examples/plugin/wasmedge-zlib/README.md b/examples/plugin/wasmedge-zlib/README.md index 687cfbda5376..60a0a62d7cff 100644 --- a/examples/plugin/wasmedge-zlib/README.md +++ b/examples/plugin/wasmedge-zlib/README.md @@ -31,7 +31,7 @@ export WASMEDGE_PLUGIN_PATH=$WASMEDGE_PATH/build/plugins/wasmedge_zlib mkdir build; cd build cmake .. -DWASMEDGE_PLUGIN_WASMEDGE_ZLIB=ON # In case you don't want `AOT` support, try the variant below -# cmake .. -DWASMEDGE_PLUGIN_ZLIB=ON -DWASMEDGE_BUILD_AOT_RUNTIME=OFF +# cmake .. -DWASMEDGE_PLUGIN_ZLIB=ON -DWASMEDGE_USE_LLVM=OFF cmake --build . -j # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge ``` diff --git a/flake.nix b/flake.nix index 071564ca2233..db8cd5dbcf12 100644 --- a/flake.nix +++ b/flake.nix @@ -53,7 +53,7 @@ -DCMAKE_BUILD_TYPE=Debug \ -DWASMEDGE_BUILD_PLUGINS=OFF \ -DWASMEDGE_BUILD_TESTS=OFF \ - -DWASMEDGE_BUILD_AOT_RUNTIME=ON \ + -DWASMEDGE_USE_LLVM=ON \ . ''; buildPhase = '' diff --git a/include/ast/section.h b/include/ast/section.h index 5de8389b9073..593f96e253d4 100644 --- a/include/ast/section.h +++ b/include/ast/section.h @@ -286,6 +286,7 @@ class AOTSection { std::vector CodesAddress; std::vector>> Sections; + std::vector Bytecodes; /// @} }; diff --git a/include/llvm/codegen.h b/include/llvm/codegen.h new file mode 100644 index 000000000000..48a9de813773 --- /dev/null +++ b/include/llvm/codegen.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/llvm/codegen.h - Code Generator class definition ---------===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file is the definition class of Compiler class. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/module.h" +#include "common/configure.h" +#include "common/errcode.h" +#include "common/filesystem.h" +#include "common/span.h" +#include "llvm/data.h" + +#include + +namespace WasmEdge::LLVM { + +/// Compiling LLVM Module into loadable executable binary. +class CodeGen { +public: + CodeGen(const Configure &Conf) noexcept : Conf(Conf) {} + Expect codegen(Span WasmData, Data D, + std::filesystem::path OutputPath) noexcept; + +private: + const Configure Conf; +}; + +} // namespace WasmEdge::LLVM diff --git a/include/aot/compiler.h b/include/llvm/compiler.h similarity index 80% rename from include/aot/compiler.h rename to include/llvm/compiler.h index 3ace24de2729..e603039eb5d6 100644 --- a/include/aot/compiler.h +++ b/include/llvm/compiler.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC -//===-- wasmedge/aot/compiler.h - Compiler class definition ---------------===// +//===-- wasmedge/llvm/compiler.h - Compiler class definition --------------===// // // Part of the WasmEdge Project. // @@ -18,19 +18,18 @@ #include "common/errcode.h" #include "common/filesystem.h" #include "common/span.h" +#include "llvm/data.h" #include -namespace WasmEdge { -namespace AOT { +namespace WasmEdge::LLVM { -/// Compiling Module into loadable executable binary. +/// Compiling Module into LLVM Module. class Compiler { public: Compiler(const Configure &Conf) noexcept : Context(nullptr), Conf(Conf) {} - Expect compile(Span Data, const AST::Module &Module, - std::filesystem::path OutputPath) noexcept; + Expect compile(const AST::Module &Module) noexcept; struct CompileContext; @@ -51,5 +50,4 @@ class Compiler { const Configure Conf; }; -} // namespace AOT -} // namespace WasmEdge +} // namespace WasmEdge::LLVM diff --git a/include/llvm/data.h b/include/llvm/data.h new file mode 100644 index 000000000000..22594d0ad04f --- /dev/null +++ b/include/llvm/data.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/llvm/data.h - Data class definition ----------------------===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file is the definition class of Data class. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/module.h" +#include "common/configure.h" +#include "common/errcode.h" +#include "common/filesystem.h" +#include "common/span.h" + +#include + +namespace WasmEdge::LLVM { + +/// Holds llvm-relative runtime data, like llvm::Context, llvm::Module, etc. +class Data { +public: + struct DataContext; + Data() noexcept; + ~Data() noexcept; + Data(Data &&) noexcept; + Data &operator=(Data &&) noexcept; + DataContext &extract() noexcept { return *Context; } + +private: + std::unique_ptr Context; + const Configure Conf; +}; + +} // namespace WasmEdge::LLVM diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a7f09e1c6ada..9d836a12ac9f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,8 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) add_subdirectory(aot) + add_subdirectory(llvm) endif() add_subdirectory(common) add_subdirectory(system) diff --git a/lib/aot/CMakeLists.txt b/lib/aot/CMakeLists.txt index b937d4447bc5..494055b10f97 100644 --- a/lib/aot/CMakeLists.txt +++ b/lib/aot/CMakeLists.txt @@ -1,77 +1,18 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_PATH}") -get_filename_component(LLVM_DIR "${LLVM_DIR}" ABSOLUTE) -list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR}) -include(LLVMConfig) -include(AddLLVM) - -get_filename_component(LLD_DIR "${LLVM_LIBRARY_DIR}/cmake/lld" ABSOLUTE) -find_package(LLD REQUIRED HINTS ${LLD_DIR}) - -if(WASMEDGE_LINK_LLVM_STATIC) - wasmedge_add_library(wasmedgeAOT - blake3.cpp - cache.cpp - compiler.cpp - ) - - target_link_libraries(wasmedgeAOT - PUBLIC - wasmedgeCommon - wasmedgeSystem - utilBlake3 - std::filesystem - ${WASMEDGE_LLVM_LINK_STATIC_COMPONENTS} - ${WASMEDGE_LLVM_LINK_SHARED_COMPONENTS} - ) -else() - if(APPLE) - list(APPEND LLD_LIBS lldMachO) - elseif(WIN32) - list(APPEND LLD_LIBS lldCOFF) - set(EXTRA_COMPONENTS DebugInfoPDB LibDriver WindowsManifest) - else() - list(APPEND LLD_LIBS lldELF) - endif() - - list(APPEND LLD_LIBS lldCommon) - if(LLVM_VERSION_MAJOR LESS_EQUAL 13) - list(APPEND LLD_LIBS lldDriver) - endif() - - # Command line warning D9025 : overriding '/EHs' with '/EHs-' - # prevent LLVM from adding /EHs-c-. - if(WIN32) - set(LLVM_REQUIRES_EH ON) - endif() - - llvm_add_library(wasmedgeAOT - blake3.cpp - cache.cpp - compiler.cpp - LINK_LIBS - wasmedgeCommon - wasmedgeSystem - utilBlake3 - ${LLD_LIBS} - std::filesystem - ${CMAKE_THREAD_LIBS_INIT} - LINK_COMPONENTS - core - lto - native - nativecodegen - option - passes - support - transformutils - ${EXTRA_COMPONENTS} - ) -endif() +wasmedge_add_library(wasmedgeAOT + blake3.cpp + cache.cpp +) -wasmedge_setup_target(wasmedgeAOT) +target_link_libraries(wasmedgeAOT + PUBLIC + wasmedgeCommon + wasmedgeSystem + utilBlake3 + std::filesystem +) target_include_directories(wasmedgeAOT SYSTEM @@ -84,19 +25,3 @@ target_include_directories(wasmedgeAOT ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/thirdparty/blake3 ) - -include(CheckCXXSourceCompiles) -set(CMAKE_REQUIRED_LINK_OPTIONS "-Wl,-lc,--exclude-libs=libc.a") -check_cxx_source_compiles("int main(){}" SUPPORT_EXCLUDE_LIBS) - -if(SUPPORT_EXCLUDE_LIBS) - file(GLOB LLD_ALL_LIBS ${LLVM_LIBRARY_DIR}/liblld*.a) - list(TRANSFORM LLD_ALL_LIBS REPLACE "^.*/" "") - string(JOIN : LLD_ALL_LIBS_COLON ${LLD_ALL_LIBS}) - if(NOT LLD_ALL_LIBS_COLON STREQUAL "") - target_link_options(wasmedgeAOT - PUBLIC - "SHELL:-Wl,--exclude-libs=${LLD_ALL_LIBS_COLON}" - ) - endif() -endif() diff --git a/lib/api/CMakeLists.txt b/lib/api/CMakeLists.txt index 9ad7e285a9fc..e79917183aa3 100644 --- a/lib/api/CMakeLists.txt +++ b/lib/api/CMakeLists.txt @@ -3,8 +3,8 @@ find_package(spdlog QUIET) add_definitions(-DWASMEDGE_COMPILE_LIBRARY) -if(WASMEDGE_BUILD_AOT_RUNTIME) - add_definitions(-DWASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) + add_definitions(-DWASMEDGE_USE_LLVM) endif() if(WASMEDGE_BUILD_WASI_NN_RPC) add_definitions(-DWASMEDGE_BUILD_WASI_NN_RPC) @@ -82,10 +82,11 @@ target_link_libraries(wasmedgeCAPI wasmedgeDriver ) -if (WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) target_link_libraries(wasmedgeCAPI PUBLIC wasmedgeAOT + wasmedgeLLVM ) endif() @@ -155,12 +156,13 @@ if(WASMEDGE_BUILD_STATIC_LIB) wasmedge_add_static_lib_component_command(wasmedgeVM) wasmedge_add_static_lib_component_command(wasmedgeDriver) - if(WASMEDGE_BUILD_AOT_RUNTIME) + if(WASMEDGE_USE_LLVM) foreach(LIB_NAME IN LISTS WASMEDGE_LLVM_LINK_STATIC_COMPONENTS) wasmedge_add_libs_component_command(${LIB_NAME}) endforeach() wasmedge_add_static_lib_component_command(utilBlake3) wasmedge_add_static_lib_component_command(wasmedgeAOT) + wasmedge_add_static_lib_component_command(wasmedgeLLVM) endif() if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index abcde5bd376c..5871405c9a69 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -3,7 +3,6 @@ #include "wasmedge/wasmedge.h" -#include "aot/compiler.h" #include "common/defines.h" #include "driver/compiler.h" #include "driver/tool.h" @@ -12,6 +11,8 @@ #include "plugin/plugin.h" #include "system/winapi.h" #include "vm/vm.h" +#include "llvm/codegen.h" +#include "llvm/compiler.h" #ifdef WASMEDGE_BUILD_FUZZING #include "driver/fuzzPO.h" @@ -66,10 +67,11 @@ struct WasmEdge_ExportTypeContext {}; // WasmEdge_CompilerContext implementation. struct WasmEdge_CompilerContext { -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM WasmEdge_CompilerContext(const WasmEdge::Configure &Conf) noexcept - : Compiler(Conf), Load(Conf), Valid(Conf) {} - WasmEdge::AOT::Compiler Compiler; + : Compiler(Conf), CodeGen(Conf), Load(Conf), Valid(Conf) {} + WasmEdge::LLVM::Compiler Compiler; + WasmEdge::LLVM::CodeGen CodeGen; WasmEdge::Loader::Loader Load; WasmEdge::Validator::Validator Valid; #endif @@ -1584,7 +1586,7 @@ WasmEdge_ExportTypeGetGlobalType(const WasmEdge_ASTModuleContext *ASTCxt, WASMEDGE_CAPI_EXPORT WasmEdge_CompilerContext * WasmEdge_CompilerCreate(const WasmEdge_ConfigureContext *ConfCxt [[maybe_unused]]) { -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM // Set force interpreter here to load instructions of function body forcibly. if (ConfCxt) { WasmEdge::Configure CopyConf(ConfCxt->Conf); @@ -1603,27 +1605,27 @@ WasmEdge_CompilerCreate(const WasmEdge_ConfigureContext *ConfCxt WASMEDGE_CAPI_EXPORT WasmEdge_Result WasmEdge_CompilerCompile( WasmEdge_CompilerContext *Cxt [[maybe_unused]], const char *InPath [[maybe_unused]], const char *OutPath [[maybe_unused]]) { -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM return wrap( [&]() -> WasmEdge::Expect { std::filesystem::path InputPath = std::filesystem::absolute(InPath); std::filesystem::path OutputPath = std::filesystem::absolute(OutPath); std::vector Data; std::unique_ptr Module; - if (auto Res = Cxt->Load.loadFile(InputPath)) { - Data = std::move(*Res); - } else { - return Unexpect(Res); - } - if (auto Res = Cxt->Load.parseModule(Data)) { - Module = std::move(*Res); - } else { - return Unexpect(Res); - } - if (auto Res = Cxt->Valid.validate(*Module.get()); !Res) { - return Unexpect(Res); - } - return Cxt->Compiler.compile(Data, *Module.get(), OutputPath); + return Cxt->Load.loadFile(InputPath) + .and_then([&](auto Result) noexcept { + Data = std::move(Result); + return Cxt->Load.parseModule(Data); + }) + .and_then([&](auto Result) noexcept { + Module = std::move(Result); + return Cxt->Valid.validate(*Module.get()); + }) + .and_then( + [&]() noexcept { return Cxt->Compiler.compile(*Module.get()); }) + .and_then([&](auto Result) noexcept { + return Cxt->CodeGen.codegen(Data, std::move(Result), OutputPath); + }); }, EmptyThen, Cxt); #else @@ -1643,21 +1645,21 @@ WASMEDGE_CAPI_EXPORT WasmEdge_Result WasmEdge_CompilerCompileFromBytes( WasmEdge_CompilerContext *Cxt [[maybe_unused]], const WasmEdge_Bytes Bytes [[maybe_unused]], const char *OutPath [[maybe_unused]]) { -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM return wrap( [&]() -> WasmEdge::Expect { std::filesystem::path OutputPath = std::filesystem::absolute(OutPath); auto Data = genSpan(Bytes.Buf, Bytes.Length); std::unique_ptr Module; - if (auto Res = Cxt->Load.parseModule(Data)) { - Module = std::move(*Res); - } else { - return Unexpect(Res); - } - if (auto Res = Cxt->Valid.validate(*Module.get()); !Res) { - return Unexpect(Res); - } - return Cxt->Compiler.compile(Data, *Module.get(), OutputPath); + return Cxt->Load.parseModule(Data) + .and_then([&](auto Result) noexcept { + Module = std::move(Result); + return Cxt->Valid.validate(*Module); + }) + .and_then([&]() noexcept { return Cxt->Compiler.compile(*Module); }) + .and_then([&](auto Result) noexcept { + return Cxt->CodeGen.codegen(Data, std::move(Result), OutputPath); + }); }, EmptyThen, Cxt); #else diff --git a/lib/driver/CMakeLists.txt b/lib/driver/CMakeLists.txt index 127366a67e34..1a6b947864f1 100644 --- a/lib/driver/CMakeLists.txt +++ b/lib/driver/CMakeLists.txt @@ -24,7 +24,7 @@ if(WASMEDGE_BUILD_WASI_NN_RPC) ) endif() -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) target_link_libraries(wasmedgeDriver PRIVATE wasmedgeLoader @@ -32,6 +32,7 @@ if(WASMEDGE_BUILD_AOT_RUNTIME) wasmedgePO wasmedgeVM wasmedgeAOT + wasmedgeLLVM ) else() target_link_libraries(wasmedgeDriver @@ -43,9 +44,9 @@ else() ) endif() -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) target_compile_definitions(wasmedgeDriver PRIVATE - -DWASMEDGE_BUILD_AOT_RUNTIME + -DWASMEDGE_USE_LLVM ) endif() diff --git a/lib/driver/compilerTool.cpp b/lib/driver/compilerTool.cpp index 9d8b4a5d94ab..7a4318aafa29 100644 --- a/lib/driver/compilerTool.cpp +++ b/lib/driver/compilerTool.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC -#include "aot/compiler.h" #include "common/configure.h" #include "common/defines.h" #include "common/filesystem.h" @@ -9,6 +8,8 @@ #include "driver/compiler.h" #include "loader/loader.h" #include "validator/validator.h" +#include "llvm/codegen.h" +#include "llvm/compiler.h" #include #include #include @@ -26,7 +27,7 @@ int Compiler([[maybe_unused]] struct DriverCompilerOptions &Opt) noexcept { std::ios::sync_with_stdio(false); Log::setInfoLoggingLevel(); -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM Configure Conf; if (Opt.PropMutGlobals.value()) { @@ -154,11 +155,17 @@ int Compiler([[maybe_unused]] struct DriverCompilerOptions &Opt) noexcept { Conf.getCompilerConfigure().setOutputFormat( CompilerConfigure::OutputFormat::Native); } - AOT::Compiler Compiler(Conf); - if (auto Res = Compiler.compile(Data, *Module, OutputPath); !Res) { + LLVM::Compiler Compiler(Conf); + LLVM::CodeGen CodeGen(Conf); + if (auto Res = Compiler.compile(*Module); !Res) { const auto Err = static_cast(Res.error()); spdlog::error("Compilation failed. Error code: {}", Err); return EXIT_FAILURE; + } else if (auto Res2 = CodeGen.codegen(Data, std::move(*Res), OutputPath); + !Res2) { + const auto Err = static_cast(Res2.error()); + spdlog::error("Code Generation failed. Error code: {}", Err); + return EXIT_FAILURE; } } diff --git a/lib/driver/fuzzTool.cpp b/lib/driver/fuzzTool.cpp index 83ffcc8bcc89..0b4974dff6fd 100644 --- a/lib/driver/fuzzTool.cpp +++ b/lib/driver/fuzzTool.cpp @@ -3,10 +3,11 @@ #ifdef WASMEDGE_BUILD_FUZZING #include "driver/fuzzTool.h" -#include "aot/compiler.h" #include "common/configure.h" #include "loader/loader.h" #include "validator/validator.h" +#include "llvm/codegen.h" +#include "llvm/compiler.h" namespace WasmEdge { namespace Driver { @@ -38,13 +39,18 @@ int FuzzTool(const uint8_t *Data, size_t Size) noexcept { } } - AOT::Compiler Compiler(Conf); - if (auto Res = Compiler.compile(Span(Data, Size), *Module, - "/dev/null"sv); - !Res) { + LLVM::Compiler Compiler(Conf); + LLVM::CodeGen CodeGen(Conf); + if (auto Res = Compiler.compile(*Module); !Res) { const auto Err = static_cast(Res.error()); spdlog::error("Compilation failed. Error code: {}"sv, Err); return EXIT_FAILURE; + } else if (auto Res2 = CodeGen.codegen(Span(Data, Size), + std::move(*Res), "/dev/null"sv); + !Res2) { + const auto Err = static_cast(Res2.error()); + spdlog::error("Code Generation failed. Error code: {}"sv, Err); + return EXIT_FAILURE; } return EXIT_SUCCESS; diff --git a/lib/llvm/CMakeLists.txt b/lib/llvm/CMakeLists.txt new file mode 100644 index 000000000000..c424b5798ef0 --- /dev/null +++ b/lib/llvm/CMakeLists.txt @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_PATH}") +get_filename_component(LLVM_DIR "${LLVM_DIR}" ABSOLUTE) +list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR}) +include(LLVMConfig) +include(AddLLVM) + +get_filename_component(LLD_DIR "${LLVM_LIBRARY_DIR}/cmake/lld" ABSOLUTE) +find_package(LLD REQUIRED HINTS ${LLD_DIR}) + +if(WASMEDGE_LINK_LLVM_STATIC) + wasmedge_add_library(wasmedgeLLVM + compiler.cpp + codegen.cpp + data.cpp + ) + + target_link_libraries(wasmedgeLLVM + PUBLIC + wasmedgeCommon + wasmedgeSystem + std::filesystem + ${WASMEDGE_LLVM_LINK_STATIC_COMPONENTS} + ${WASMEDGE_LLVM_LINK_SHARED_COMPONENTS} + ) +else() + if(APPLE) + list(APPEND LLD_LIBS lldMachO) + elseif(WIN32) + list(APPEND LLD_LIBS lldCOFF) + set(EXTRA_COMPONENTS DebugInfoPDB LibDriver WindowsManifest) + else() + list(APPEND LLD_LIBS lldELF) + endif() + + list(APPEND LLD_LIBS lldCommon) + if(LLVM_VERSION_MAJOR LESS_EQUAL 13) + list(APPEND LLD_LIBS lldDriver) + endif() + + # Command line warning D9025 : overriding '/EHs' with '/EHs-' + # prevent LLVM from adding /EHs-c-. + if(WIN32) + set(LLVM_REQUIRES_EH ON) + endif() + + llvm_add_library(wasmedgeLLVM + compiler.cpp + codegen.cpp + data.cpp + LINK_LIBS + wasmedgeCommon + wasmedgeSystem + ${LLD_LIBS} + std::filesystem + ${CMAKE_THREAD_LIBS_INIT} + LINK_COMPONENTS + core + lto + native + nativecodegen + option + passes + support + transformutils + ${EXTRA_COMPONENTS} + ) +endif() + +wasmedge_setup_target(wasmedgeLLVM) + +target_include_directories(wasmedgeLLVM + SYSTEM + PRIVATE + ${LLVM_INCLUDE_DIR} +) + +target_include_directories(wasmedgeLLVM + PUBLIC + ${PROJECT_BINARY_DIR}/include +) + +include(CheckCXXSourceCompiles) +set(CMAKE_REQUIRED_LINK_OPTIONS "-Wl,-lc,--exclude-libs=libc.a") +check_cxx_source_compiles("int main(){}" SUPPORT_EXCLUDE_LIBS) + +if(SUPPORT_EXCLUDE_LIBS) + file(GLOB LLD_ALL_LIBS ${LLVM_LIBRARY_DIR}/liblld*.a) + list(TRANSFORM LLD_ALL_LIBS REPLACE "^.*/" "") + string(JOIN : LLD_ALL_LIBS_COLON ${LLD_ALL_LIBS}) + if(NOT LLD_ALL_LIBS_COLON STREQUAL "") + target_link_options(wasmedgeLLVM + PUBLIC + "SHELL:-Wl,--exclude-libs=${LLD_ALL_LIBS_COLON}" + ) + endif() +endif() diff --git a/lib/llvm/codegen.cpp b/lib/llvm/codegen.cpp new file mode 100644 index 000000000000..f21f9d816721 --- /dev/null +++ b/lib/llvm/codegen.cpp @@ -0,0 +1,632 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +#include "llvm/codegen.h" + +#include "aot/version.h" +#include "common/defines.h" +#include "data.h" +#include "llvm.h" + +#include +#include +#include +#include +#include + +#if LLVM_VERSION_MAJOR >= 14 +#include +#endif +#if LLVM_VERSION_MAJOR >= 17 +#if WASMEDGE_OS_MACOS +LLD_HAS_DRIVER(macho) +#elif WASMEDGE_OS_LINUX +LLD_HAS_DRIVER(elf) +#elif WASMEDGE_OS_WINDOWS +LLD_HAS_DRIVER(coff) +#endif +#endif + +#if WASMEDGE_OS_MACOS +#include +#include +#endif +#if WASMEDGE_OS_WINDOWS +#include +#endif + +#if WASMEDGE_OS_LINUX +#define SYMBOL(X) X +#elif WASMEDGE_OS_MACOS +#define SYMBOL(X) "_" X +#elif WASMEDGE_OS_WINDOWS +#define SYMBOL(X) X +#endif + +namespace LLVM = WasmEdge::LLVM; +using namespace std::literals; + +namespace { + +using namespace WasmEdge; + +#if WASMEDGE_OS_MACOS +// Get current OS version +std::string getOSVersion() noexcept { + struct utsname Info; + if (::uname(&Info)) { + // default os version + return "13.0.0"s; + } + std::string_view Release = Info.release; + auto GetNum = [](std::string_view &String) noexcept { + uint64_t Result = 0; + while (!String.empty() && std::isdigit(String[0])) { + Result = Result * 10 + (String[0] - '0'); + String = String.substr(1); + } + return Result; + }; + auto SkipDot = [](std::string_view &String) noexcept { + if (!String.empty() && String[0] == '.') + String = String.substr(1); + }; + uint64_t Major = GetNum(Release); + SkipDot(Release); + uint64_t Minor = GetNum(Release); + SkipDot(Release); + uint64_t Micro = GetNum(Release); + + if (Major == 0) { + Major = 8; + } + if (Major <= 19) { + Micro = 0; + Minor = Major - 4; + Major = 10; + } else { + Micro = 0; + Minor = 0; + Major = 11 + Major - 20; + } + + return fmt::format("{}.{}.{}"sv, Major, Minor, Micro); +} +// Get current SDK version +std::string getSDKVersion() noexcept { + // TODO: parse SDKSettings.json to get real version + return "12.1"s; +} +// Get current SDK version in pair +std::pair getSDKVersionPair() noexcept { + // TODO: parse SDKSettings.json to get real version + return {UINT32_C(12), UINT32_C(1)}; +} +#endif + +Expect WriteByte(std::ostream &OS, uint8_t Data) noexcept { + OS.put(static_cast(Data)); + return {}; +} + +Expect WriteU32(std::ostream &OS, uint32_t Data) noexcept { + do { + uint8_t Byte = static_cast(Data & UINT32_C(0x7f)); + Data >>= 7; + if (Data > UINT32_C(0)) { + Byte |= UINT8_C(0x80); + } + WriteByte(OS, Byte); + } while (Data > UINT32_C(0)); + return {}; +} + +Expect WriteU64(std::ostream &OS, uint64_t Data) noexcept { + do { + uint8_t Byte = static_cast(Data & UINT64_C(0x7f)); + Data >>= 7; + if (Data > UINT64_C(0)) { + Byte |= UINT8_C(0x80); + } + WriteByte(OS, Byte); + } while (Data > UINT64_C(0)); + return {}; +} + +Expect WriteName(std::ostream &OS, std::string_view Data) noexcept { + WriteU32(OS, static_cast(Data.size())); + for (const auto C : Data) { + WriteByte(OS, static_cast(C)); + } + return {}; +} + +inline constexpr bool startsWith(std::string_view Value, + std::string_view Prefix) noexcept { + return Value.size() >= Prefix.size() && + Value.substr(0, Prefix.size()) == Prefix; +} + +std::filesystem::path uniquePath(const std::filesystem::path Model) noexcept { + using size_type = std::filesystem::path::string_type::size_type; + using value_type = std::filesystem::path::value_type; + static const auto Hex = "0123456789abcdef"sv; + std::random_device Device; + std::default_random_engine Engine(Device()); + std::uniform_int_distribution Distribution(0, Hex.size() - 1); + auto String = Model.native(); + for (size_type N = String.size(), I = 0; I < N; ++I) { + if (String[I] == static_cast('%')) { + String[I] = static_cast(Hex[Distribution(Engine)]); + } + } + return String; +} + +std::filesystem::path createTemp(const std::filesystem::path Model) noexcept { + while (true) { + auto Result = uniquePath(Model); + std::error_code Error; + if (!std::filesystem::exists(Result, Error)) { + if (Error) { + return {}; + } + return Result; + } + } +} + +// Write output object and link +Expect outputNativeLibrary(const std::filesystem::path &OutputPath, + const LLVM::MemoryBuffer &OSVec) noexcept { + spdlog::info("output start"); + std::filesystem::path ObjectName; + { + // tempfile + std::filesystem::path OPath(OutputPath); +#if WASMEDGE_OS_WINDOWS + OPath.replace_extension("%%%%%%%%%%.obj"sv); +#else + OPath.replace_extension("%%%%%%%%%%.o"sv); +#endif + ObjectName = createTemp(OPath); + if (ObjectName.empty()) { + // TODO:return error + spdlog::error("so file creation failed:{}", OPath.u8string()); + return Unexpect(ErrCode::Value::IllegalPath); + } + std::ofstream OS(ObjectName, std::ios_base::binary); + OS.write(OSVec.data(), static_cast(OSVec.size())); + OS.close(); + } + + // link + bool LinkResult = false; +#if WASMEDGE_OS_MACOS + const auto OSVersion = getOSVersion(); + const auto SDKVersion = getSDKVersion(); +#if LLVM_VERSION_MAJOR >= 14 + // LLVM 14 replaces the older mach_o lld implementation with the new one. + // So we need to change the namespace after LLVM 14.x released. + // Reference: https://reviews.llvm.org/D114842 + LinkResult = lld::macho::link( +#else + LinkResult = lld::mach_o::link( +#endif + std::initializer_list { + "lld", "-arch", +#if defined(__x86_64__) + "x86_64", +#elif defined(__aarch64__) + "arm64", +#else +#error Unsupported architecture on the MacOS! +#endif +#if LLVM_VERSION_MAJOR >= 14 + // LLVM 14 replaces the older mach_o lld implementation with the new + // one. And it require -arch and -platform_version to always be + // specified. Reference: https://reviews.llvm.org/D97799 + "-platform_version", "macos", OSVersion.c_str(), SDKVersion.c_str(), +#else + "-sdk_version", SDKVersion.c_str(), +#endif + "-dylib", "-demangle", "-macosx_version_min", OSVersion.c_str(), + "-syslibroot", + "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk", + ObjectName.u8string().c_str(), "-o", OutputPath.u8string().c_str() + }, +#elif WASMEDGE_OS_LINUX + LinkResult = lld::elf::link( + std::initializer_list{"ld.lld", "--eh-frame-hdr", + "--shared", "--gc-sections", + "--discard-all", ObjectName.c_str(), + "-o", OutputPath.u8string().c_str()}, +#elif WASMEDGE_OS_WINDOWS + LinkResult = lld::coff::link( + std::initializer_list{ + "lld-link", "-dll", "-base:0", "-nologo", + ObjectName.u8string().c_str(), + ("-out:" + OutputPath.u8string()).c_str()}, +#endif + +#if LLVM_VERSION_MAJOR >= 14 + llvm::outs(), llvm::errs(), false, false +#elif LLVM_VERSION_MAJOR >= 10 + false, llvm::outs(), llvm::errs() +#else + false, llvm::errs() +#endif + ); + +#if LLVM_VERSION_MAJOR >= 14 + lld::CommonLinkerContext::destroy(); +#endif + + if (LinkResult) { + std::error_code Error; + std::filesystem::remove(ObjectName, Error); +#if WASMEDGE_OS_WINDOWS + std::filesystem::path LibPath(OutputPath); + LibPath.replace_extension(".lib"sv); + std::filesystem::remove(LibPath, Error); +#endif + + spdlog::info("codegen done"); + } else { + spdlog::error("link error"); + } + +#if WASMEDGE_OS_MACOS + // codesign + if (LinkResult) { + pid_t PID = ::fork(); + if (PID == -1) { + spdlog::error("codesign error on fork:{}", std::strerror(errno)); + } else if (PID == 0) { + execlp("/usr/bin/codesign", "codesign", "-s", "-", + OutputPath.u8string().c_str(), nullptr); + std::exit(256); + } else { + int ChildStat; + waitpid(PID, &ChildStat, 0); + if (const int Status = WEXITSTATUS(ChildStat); Status != 0) { + spdlog::error("codesign exited with status {}", Status); + } + } + } +#endif + + return {}; +} + +Expect outputWasmLibrary(const std::filesystem::path &OutputPath, + Span Data, + const LLVM::MemoryBuffer &OSVec) noexcept { + std::filesystem::path SharedObjectName; + { + // tempfile + std::filesystem::path SOPath(OutputPath); + SOPath.replace_extension("%%%%%%%%%%" WASMEDGE_LIB_EXTENSION); + SharedObjectName = createTemp(SOPath); + if (SharedObjectName.empty()) { + // TODO:return error + spdlog::error("so file creation failed:{}", SOPath.u8string()); + return Unexpect(ErrCode::Value::IllegalPath); + } + std::ofstream OS(SharedObjectName, std::ios_base::binary); + OS.write(OSVec.data(), static_cast(OSVec.size())); + OS.close(); + } + + if (auto Res = outputNativeLibrary(SharedObjectName, OSVec); unlikely(!Res)) { + return Unexpect(Res); + } + + LLVM::MemoryBuffer SOFile; + if (auto [Res, ErrorMessage] = + LLVM::MemoryBuffer::getFile(SharedObjectName.u8string().c_str()); + unlikely(ErrorMessage)) { + spdlog::error("object file open error:{}", ErrorMessage.string_view()); + return Unexpect(ErrCode::Value::IllegalPath); + } else { + SOFile = std::move(Res); + } + + LLVM::Context Context; + LLVM::Binary ObjFile; + if (auto [Res, ErrorMessage] = LLVM::Binary::create(SOFile, Context); + unlikely(ErrorMessage)) { + spdlog::error("object file parse error:{}", ErrorMessage.string_view()); + return Unexpect(ErrCode::Value::IllegalPath); + } else { + ObjFile = std::move(Res); + } + + std::string OSCustomSecVec; + { + std::ostringstream OS; + WriteName(OS, "wasmedge"sv); + WriteU32(OS, AOT::kBinaryVersion); + +#if WASMEDGE_OS_LINUX + WriteByte(OS, UINT8_C(1)); +#elif WASMEDGE_OS_MACOS + WriteByte(OS, UINT8_C(2)); +#elif WASMEDGE_OS_WINDOWS + WriteByte(OS, UINT8_C(3)); +#else +#error Unsupported operating system! +#endif + +#if defined(__x86_64__) + WriteByte(OS, UINT8_C(1)); +#elif defined(__aarch64__) + WriteByte(OS, UINT8_C(2)); +#elif defined(__riscv) && __riscv_xlen == 64 + WriteByte(OS, UINT8_C(3)); +#elif defined(__arm__) && __ARM_ARCH == 7 + WriteByte(OS, UINT8_C(4)); +#else +#error Unsupported hardware architecture! +#endif + + std::vector> SymbolTable; +#if !WASMEDGE_OS_WINDOWS + for (auto Symbol = ObjFile.symbols(); + Symbol && !ObjFile.isSymbolEnd(Symbol); Symbol.next()) { + SymbolTable.emplace_back(Symbol.getName(), Symbol.getAddress()); + } +#else + for (auto &Symbol : + llvm::object::unwrap(ObjFile.unwrap()) + ->export_directories()) { + llvm::StringRef Name; + if (auto Error = Symbol.getSymbolName(Name); unlikely(!!Error)) { + continue; + } else if (Name.empty()) { + continue; + } + uint32_t Offset = 0; + if (auto Error = Symbol.getExportRVA(Offset); unlikely(!!Error)) { + continue; + } + SymbolTable.emplace_back(Name.str(), Offset); + } +#endif + uint64_t VersionAddress = 0, IntrinsicsAddress = 0; + std::vector Types; + std::vector Codes; + uint64_t CodesMin = std::numeric_limits::max(); + for (const auto &[Name, Address] : SymbolTable) { + if (Name == SYMBOL("version"sv)) { + VersionAddress = Address; + } else if (Name == SYMBOL("intrinsics"sv)) { + IntrinsicsAddress = Address; + } else if (startsWith(Name, SYMBOL("t"sv))) { + uint64_t Index = 0; + std::from_chars(Name.data() + SYMBOL("t"sv).size(), + Name.data() + Name.size(), Index); + if (Types.size() < Index + 1) { + Types.resize(Index + 1); + } + Types[Index] = Address; + } else if (startsWith(Name, SYMBOL("f"sv))) { + uint64_t Index = 0; + std::from_chars(Name.data() + SYMBOL("f"sv).size(), + Name.data() + Name.size(), Index); + if (Codes.size() < Index + 1) { + Codes.resize(Index + 1); + } + CodesMin = std::min(CodesMin, Index); + Codes[Index] = Address; + } + } + if (CodesMin != std::numeric_limits::max()) { + Codes.erase(Codes.begin(), + Codes.begin() + static_cast(CodesMin)); + } + WriteU64(OS, VersionAddress); + WriteU64(OS, IntrinsicsAddress); + WriteU64(OS, Types.size()); + for (const uint64_t TypeAddress : Types) { + WriteU64(OS, TypeAddress); + } + WriteU64(OS, Codes.size()); + for (const uint64_t CodeAddress : Codes) { + WriteU64(OS, CodeAddress); + } + + uint32_t SectionCount = 0; + for (auto Section = ObjFile.sections(); !ObjFile.isSectionEnd(Section); + Section.next()) { + if (Section.getSize() == 0) { + continue; + } + if (!Section.isEHFrame() && !Section.isPData() && !Section.isText() && + !Section.isData() && !Section.isBSS()) { + continue; + } + ++SectionCount; + } + WriteU32(OS, SectionCount); + + for (auto Section = ObjFile.sections(); !ObjFile.isSectionEnd(Section); + Section.next()) { + if (Section.getSize() == 0) { + continue; + } + std::vector Content; + if (auto Res = Section.getContents(); unlikely(Res.empty())) { + assumingUnreachable(); + } else { + Content.assign(Res.begin(), Res.end()); + } + if (Section.isEHFrame() || Section.isPData()) { + WriteByte(OS, UINT8_C(4)); + } else if (Section.isText()) { + WriteByte(OS, UINT8_C(1)); + } else if (Section.isData()) { + WriteByte(OS, UINT8_C(2)); + } else if (Section.isBSS()) { + WriteByte(OS, UINT8_C(3)); + } else { + continue; + } + + WriteU64(OS, Section.getAddress()); + WriteU64(OS, Content.size()); + WriteName(OS, std::string_view(Content.data(), Content.size())); + } + OSCustomSecVec = OS.str(); + } + + spdlog::info("output start"); + + std::ofstream OS(OutputPath, std::ios_base::binary); + if (!OS) { + spdlog::error("output failed."); + return Unexpect(ErrCode::Value::IllegalPath); + } + OS.write(reinterpret_cast(Data.data()), + static_cast(Data.size())); + // Custom section id + WriteByte(OS, UINT8_C(0x00)); + WriteName(OS, std::string_view(OSCustomSecVec.data(), OSCustomSecVec.size())); + + std::error_code Error; + std::filesystem::remove(SharedObjectName, Error); + + spdlog::info("output done"); + return {}; +} + +} // namespace + +namespace WasmEdge::LLVM { + +Expect CodeGen::codegen(Span WasmData, Data D, + std::filesystem::path OutputPath) noexcept { + auto &LLContext = D.extract().LLContext; + auto &LLModule = D.extract().LLModule; + auto &TM = D.extract().TM; + std::filesystem::path LLPath(OutputPath); + LLPath.replace_extension("ll"sv); + +#if WASMEDGE_OS_WINDOWS + { + // create dummy dllmain function + auto FTy = LLVM::Type::getFunctionType(LLContext.getInt32Ty(), {}); + auto F = + LLModule.addFunction(FTy, LLVMExternalLinkage, "_DllMainCRTStartup"); + F.setVisibility(LLVMProtectedVisibility); + F.setDSOLocal(true); + F.addFnAttr( + LLVM::Attribute::createString(LLContext, "no-stack-arg-probe"sv, {})); + F.addFnAttr( + LLVM::Attribute::createEnum(LLContext, LLVM::Core::StrictFP, 0)); + F.addFnAttr(LLVM::Attribute::createEnum(LLContext, LLVM::Core::UWTable, 2)); + F.addFnAttr( + LLVM::Attribute::createEnum(LLContext, LLVM::Core::NoReturn, 0)); + LLVM::Builder Builder(LLContext); + Builder.positionAtEnd(LLVM::BasicBlock::create(LLContext, F, "entry")); + Builder.createRet(LLContext.getInt32(1u)); + + auto A = LLModule.addAlias(F.getType(), F, "_fltused"); + A.setLinkage(LLVMExternalLinkage); + A.setVisibility(LLVMProtectedVisibility); + A.setDSOLocal(true); + } +#endif +#if WASMEDGE_OS_MACOS + { + const auto [Major, Minor] = getSDKVersionPair(); + LLModule.addFlag(LLVMModuleFlagBehaviorError, "SDK Version"sv, + LLVM::Value::getConstVector32(LLContext, {Major, Minor})); + } +#endif + + if (Conf.getCompilerConfigure().getOutputFormat() != + CompilerConfigure::OutputFormat::Wasm) { + // create wasm.code and wasm.size + auto Int32Ty = LLContext.getInt32Ty(); + auto Content = LLVM::Value::getConstString( + LLContext, + {reinterpret_cast(WasmData.data()), WasmData.size()}, + true); + LLModule.addGlobal(Content.getType(), true, LLVMExternalLinkage, Content, + "wasm.code"); + LLModule.addGlobal(Int32Ty, true, LLVMExternalLinkage, + LLVM::Value::getConstInt(Int32Ty, WasmData.size()), + "wasm.size"); + for (auto Fn = LLModule.getFirstFunction(); Fn; Fn = Fn.getNextFunction()) { + if (Fn.getLinkage() == LLVMInternalLinkage) { + Fn.setLinkage(LLVMExternalLinkage); + Fn.setVisibility(LLVMProtectedVisibility); + Fn.setDSOLocal(true); + Fn.setDLLStorageClass(LLVMDLLExportStorageClass); + } + } + } else { + for (auto Fn = LLModule.getFirstFunction(); Fn; Fn = Fn.getNextFunction()) { + if (Fn.getLinkage() == LLVMInternalLinkage) { + Fn.setLinkage(LLVMPrivateLinkage); + Fn.setVisibility(LLVMProtectedVisibility); + Fn.setDSOLocal(true); + Fn.setDLLStorageClass(LLVMDefaultStorageClass); + } + } + } + + // set dllexport + for (auto GV = LLModule.getFirstGlobal(); GV; GV = GV.getNextGlobal()) { + if (GV.getLinkage() == LLVMExternalLinkage) { + GV.setVisibility(LLVMProtectedVisibility); + GV.setDSOLocal(true); + GV.setDLLStorageClass(LLVMDLLExportStorageClass); + } + } + + if (Conf.getCompilerConfigure().isDumpIR()) { + if (auto ErrorMessage = LLModule.printModuleToFile("wasm.ll"); + unlikely(ErrorMessage)) { + spdlog::error("wasm.ll open error:{}", ErrorMessage.string_view()); + return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); + } + } + + spdlog::info("codegen start"); + // codegen + { + if (Conf.getCompilerConfigure().isDumpIR()) { + if (auto ErrorMessage = LLModule.printModuleToFile("wasm-opt.ll")) { + // TODO:return error + spdlog::error("printModuleToFile failed"); + return Unexpect(ErrCode::Value::IllegalPath); + } + } + + auto [OSVec, ErrorMessage] = + TM.emitToMemoryBuffer(LLModule, LLVMObjectFile); + if (ErrorMessage) { + // TODO:return error + spdlog::error("addPassesToEmitFile failed"); + return Unexpect(ErrCode::Value::IllegalPath); + } + + if (Conf.getCompilerConfigure().getOutputFormat() == + CompilerConfigure::OutputFormat::Wasm) { + if (auto Res = outputWasmLibrary(OutputPath, WasmData, OSVec); + unlikely(!Res)) { + return Unexpect(Res); + } + } else { + if (auto Res = outputNativeLibrary(OutputPath, OSVec); unlikely(!Res)) { + return Unexpect(Res); + } + } + } + + return {}; +} + +} // namespace WasmEdge::LLVM diff --git a/lib/aot/compiler.cpp b/lib/llvm/compiler.cpp similarity index 90% rename from lib/aot/compiler.cpp rename to lib/llvm/compiler.cpp index a694254741ad..bae3e1926d9e 100644 --- a/lib/aot/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -1,119 +1,32 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC -#include "aot/compiler.h" +#include "llvm/compiler.h" #include "aot/version.h" #include "common/defines.h" #include "common/filesystem.h" #include "common/log.h" +#include "data.h" #include "llvm.h" #include #include -#include #include #include #include -#include #include -#include #include #include -#include -#include #include #include #include -#if LLVM_VERSION_MAJOR >= 14 -#include -#endif -#if LLVM_VERSION_MAJOR >= 17 -#if WASMEDGE_OS_MACOS -LLD_HAS_DRIVER(macho) -#elif WASMEDGE_OS_LINUX -LLD_HAS_DRIVER(elf) -#elif WASMEDGE_OS_WINDOWS -LLD_HAS_DRIVER(coff) -#endif -#endif - -#if WASMEDGE_OS_MACOS -#include -#include -#endif -#if WASMEDGE_OS_WINDOWS -#include -#endif - -#if WASMEDGE_OS_LINUX -#define SYMBOL(X) X -#elif WASMEDGE_OS_MACOS -#define SYMBOL(X) "_" X -#elif WASMEDGE_OS_WINDOWS -#define SYMBOL(X) X -#endif - +namespace LLVM = WasmEdge::LLVM; using namespace std::literals; -namespace LLVM = WasmEdge::AOT::LLVM; namespace { -#if WASMEDGE_OS_MACOS -// Get current OS version -std::string getOSVersion() noexcept { - struct utsname Info; - if (::uname(&Info)) { - // default os version - return "13.0.0"; - } - std::string_view Release = Info.release; - auto GetNum = [](std::string_view &String) noexcept { - uint64_t Result = 0; - while (!String.empty() && std::isdigit(String[0])) { - Result = Result * 10 + (String[0] - '0'); - String = String.substr(1); - } - return Result; - }; - auto SkipDot = [](std::string_view &String) noexcept { - if (!String.empty() && String[0] == '.') - String = String.substr(1); - }; - uint64_t Major = GetNum(Release); - SkipDot(Release); - uint64_t Minor = GetNum(Release); - SkipDot(Release); - uint64_t Micro = GetNum(Release); - - if (Major == 0) { - Major = 8; - } - if (Major <= 19) { - Micro = 0; - Minor = Major - 4; - Major = 10; - } else { - Micro = 0; - Minor = 0; - Major = 11 + Major - 20; - } - - return fmt::format("{}.{}.{}"sv, Major, Minor, Micro); -} -// Get current SDK version -std::string getSDKVersion() noexcept { - // TODO: parse SDKSettings.json to get real version - return "12.1"s; -} -// Get current SDK version in pair -std::pair getSDKVersionPair() noexcept { - // TODO: parse SDKSettings.json to get real version - return {UINT32_C(12), UINT32_C(1)}; -} -#endif - static bool isVoidReturn(WasmEdge::Span ValTypes) noexcept; static LLVM::Type toLLVMType(LLVM::Context &LLContext, @@ -153,7 +66,7 @@ toLLVMLevel(WasmEdge::CompilerConfigure::OptimizationLevel Level) noexcept { case OL::O0: return "default,function(tailcallelim)"; case OL::O1: - return "default"; + return "default,function(tailcallelim)"; case OL::O2: return "default"; case OL::O3: @@ -209,83 +122,9 @@ static inline LLVMCodeGenOptLevel toLLVMCodeGenLevel( assumingUnreachable(); } } - -WasmEdge::Expect WriteByte(std::ostream &OS, uint8_t Data) noexcept { - OS.put(static_cast(Data)); - return {}; -} - -WasmEdge::Expect WriteU32(std::ostream &OS, uint32_t Data) noexcept { - do { - uint8_t Byte = static_cast(Data & UINT32_C(0x7f)); - Data >>= 7; - if (Data > UINT32_C(0)) { - Byte |= UINT8_C(0x80); - } - WriteByte(OS, Byte); - } while (Data > UINT32_C(0)); - return {}; -} - -WasmEdge::Expect WriteU64(std::ostream &OS, uint64_t Data) noexcept { - do { - uint8_t Byte = static_cast(Data & UINT64_C(0x7f)); - Data >>= 7; - if (Data > UINT64_C(0)) { - Byte |= UINT8_C(0x80); - } - WriteByte(OS, Byte); - } while (Data > UINT64_C(0)); - return {}; -} - -WasmEdge::Expect WriteName(std::ostream &OS, - std::string_view Data) noexcept { - WriteU32(OS, static_cast(Data.size())); - for (const auto C : Data) { - WriteByte(OS, static_cast(C)); - } - return {}; -} - -inline constexpr bool startsWith(std::string_view Value, - std::string_view Prefix) noexcept { - return Value.size() >= Prefix.size() && - Value.substr(0, Prefix.size()) == Prefix; -} - -std::filesystem::path uniquePath(const std::filesystem::path Model) noexcept { - using size_type = std::filesystem::path::string_type::size_type; - using value_type = std::filesystem::path::value_type; - static const auto Hex = "0123456789abcdef"sv; - std::random_device Device; - std::default_random_engine Engine(Device()); - std::uniform_int_distribution Distribution(0, Hex.size() - 1); - auto String = Model.native(); - for (size_type N = String.size(), I = 0; I < N; ++I) { - if (String[I] == static_cast('%')) { - String[I] = static_cast(Hex[Distribution(Engine)]); - } - } - return String; -} - -std::filesystem::path createTemp(const std::filesystem::path Model) noexcept { - while (true) { - auto Result = uniquePath(Model); - std::error_code Error; - if (!std::filesystem::exists(Result, Error)) { - if (Error) { - return {}; - } - return Result; - } - } -} - } // namespace -struct WasmEdge::AOT::Compiler::CompileContext { +struct LLVM::Compiler::CompileContext { LLVM::Context &LLContext; LLVM::Module &LLModule; LLVM::Attribute Cold; @@ -320,7 +159,6 @@ struct WasmEdge::AOT::Compiler::CompileContext { LLVM::Type IntrinsicsTableTy; LLVM::Type IntrinsicsTablePtrTy; LLVM::Message SubtargetFeatures; - bool IsCustomSection; #if defined(__x86_64__) #if defined(__XOP__) @@ -364,8 +202,8 @@ struct WasmEdge::AOT::Compiler::CompileContext { std::vector Globals; LLVM::Value IntrinsicsTable; LLVM::FunctionCallee Trap; - CompileContext(LLVM::Context &C, LLVM::Module &M, bool IsGenericBinary, - bool IsCustomSection) noexcept + CompileContext(LLVM::Context &C, LLVM::Module &M, + bool IsGenericBinary) noexcept : LLContext(C), LLModule(M), Cold(LLVM::Attribute::createEnum(C, LLVM::Core::Cold, 0)), NoAlias(LLVM::Attribute::createEnum(C, LLVM::Core::NoAlias, 0)), @@ -415,7 +253,6 @@ struct WasmEdge::AOT::Compiler::CompileContext { Int8PtrTy, static_cast(AST::Module::Intrinsics::kIntrinsicMax))), IntrinsicsTablePtrTy(IntrinsicsTableTy.getPointerTo()), - IsCustomSection(IsCustomSection), IntrinsicsTable(LLModule.addGlobal(IntrinsicsTablePtrTy, true, LLVMExternalLinkage, LLVM::Value(), "intrinsics")) { @@ -431,7 +268,7 @@ struct WasmEdge::AOT::Compiler::CompileContext { Trap.Fn.addFnAttr(NoInline); LLModule.addGlobal(Int32Ty, true, LLVMExternalLinkage, - LLVM::Value::getConstInt(Int32Ty, kBinaryVersion), + LLVM::Value::getConstInt(Int32Ty, AOT::kBinaryVersion), "version"); if (!IsGenericBinary) { @@ -565,7 +402,7 @@ namespace { using namespace WasmEdge; -static bool isVoidReturn(Span ValTypes) noexcept { +static bool isVoidReturn(Span ValTypes) noexcept { return ValTypes.empty(); } @@ -657,13 +494,12 @@ class FunctionCompiler { struct Control; public: - FunctionCompiler(AOT::Compiler::CompileContext &Context, + FunctionCompiler(LLVM::Compiler::CompileContext &Context, LLVM::FunctionCallee F, Span Locals, bool Interruptible, bool InstructionCounting, - bool GasMeasuring, bool OptNone) noexcept + bool GasMeasuring) noexcept : Context(Context), LLContext(Context.LLContext), - Interruptible(Interruptible), OptNone(OptNone), F(F), - Builder(LLContext) { + Interruptible(Interruptible), F(F), Builder(LLContext) { if (F.Fn) { Builder.positionAtEnd(LLVM::BasicBlock::create(LLContext, F.Fn, "entry")); ExecCtx = Builder.createLoad(Context.ExecCtxTy, F.Fn.getFirstParam()); @@ -3489,7 +3325,7 @@ class FunctionCompiler { Offset); auto Ptr = Builder.createBitCast(VPtr, TargetType.getPointerTo()); - auto Load = Builder.createLoad(TargetType, Ptr, OptNone); + auto Load = Builder.createLoad(TargetType, Ptr, true); Load.setAlignment(1 << Alignment); Load.setOrdering(LLVMAtomicOrderingSequentiallyConsistent); @@ -3518,7 +3354,7 @@ class FunctionCompiler { Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Offset); auto Ptr = Builder.createBitCast(VPtr, TargetType.getPointerTo()); - auto Store = Builder.createStore(V, Ptr, OptNone); + auto Store = Builder.createStore(V, Ptr, true); Store.setAlignment(1 << Alignment); Store.setOrdering(LLVMAtomicOrderingSequentiallyConsistent); } @@ -4188,7 +4024,7 @@ class FunctionCompiler { auto VPtr = Builder.createInBoundsGEP1( Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Off); auto Ptr = Builder.createBitCast(VPtr, LoadTy.getPointerTo()); - auto LoadInst = Builder.createLoad(LoadTy, Ptr, OptNone); + auto LoadInst = Builder.createLoad(LoadTy, Ptr, true); LoadInst.setAlignment(1 << Alignment); stackPush(LoadInst); } @@ -4259,7 +4095,7 @@ class FunctionCompiler { auto VPtr = Builder.createInBoundsGEP1( Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Off); auto Ptr = Builder.createBitCast(VPtr, LoadTy.getPointerTo()); - auto StoreInst = Builder.createStore(V, Ptr, OptNone); + auto StoreInst = Builder.createStore(V, Ptr, true); StoreInst.setAlignment(1 << Alignment); } void compileSplatOp(LLVM::Type VectorTy) noexcept { @@ -5116,7 +4952,7 @@ class FunctionCompiler { return Value; } - AOT::Compiler::CompileContext &Context; + LLVM::Compiler::CompileContext &Context; LLVM::Context &LLContext; std::vector> Local; std::vector Stack; @@ -5125,7 +4961,6 @@ class FunctionCompiler { std::unordered_map TrapBB; bool IsUnreachable = false; bool Interruptible = false; - bool OptNone = false; struct Control { size_t StackSize; bool Unreachable; @@ -5166,342 +5001,12 @@ std::vector unpackStruct(LLVM::Builder &Builder, return Ret; } -// Write output object and link -Expect outputNativeLibrary(const std::filesystem::path &OutputPath, - const LLVM::MemoryBuffer &OSVec) noexcept { - spdlog::info("output start"); - std::filesystem::path ObjectName; - { - // tempfile - std::filesystem::path OPath(OutputPath); -#if WASMEDGE_OS_WINDOWS - OPath.replace_extension("%%%%%%%%%%.obj"sv); -#else - OPath.replace_extension("%%%%%%%%%%.o"sv); -#endif - ObjectName = createTemp(OPath); - if (ObjectName.empty()) { - // TODO:return error - spdlog::error("so file creation failed:{}", OPath.u8string()); - return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); - } - std::ofstream OS(ObjectName, std::ios_base::binary); - OS.write(OSVec.data(), static_cast(OSVec.size())); - OS.close(); - } - - // link - bool LinkResult = false; -#if WASMEDGE_OS_MACOS - const auto OSVersion = getOSVersion(); - const auto SDKVersion = getSDKVersion(); -#if LLVM_VERSION_MAJOR >= 14 - // LLVM 14 replaces the older mach_o lld implementation with the new one. - // So we need to change the namespace after LLVM 14.x released. - // Reference: https://reviews.llvm.org/D114842 - LinkResult = lld::macho::link( -#else - LinkResult = lld::mach_o::link( -#endif - std::initializer_list { - "lld", "-arch", -#if defined(__x86_64__) - "x86_64", -#elif defined(__aarch64__) - "arm64", -#else -#error Unsupported architecture on the MacOS! -#endif -#if LLVM_VERSION_MAJOR >= 14 - // LLVM 14 replaces the older mach_o lld implementation with the new - // one. And it require -arch and -platform_version to always be - // specified. Reference: https://reviews.llvm.org/D97799 - "-platform_version", "macos", OSVersion.c_str(), SDKVersion.c_str(), -#else - "-sdk_version", SDKVersion.c_str(), -#endif - "-dylib", "-demangle", "-macosx_version_min", OSVersion.c_str(), - "-syslibroot", - "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk", - ObjectName.u8string().c_str(), "-o", OutputPath.u8string().c_str() - }, -#elif WASMEDGE_OS_LINUX - LinkResult = lld::elf::link( - std::initializer_list{"ld.lld", "--eh-frame-hdr", - "--shared", "--gc-sections", - "--discard-all", ObjectName.c_str(), - "-o", OutputPath.u8string().c_str()}, -#elif WASMEDGE_OS_WINDOWS - LinkResult = lld::coff::link( - std::initializer_list{ - "lld-link", "-dll", "-base:0", "-nologo", - ObjectName.u8string().c_str(), - ("-out:" + OutputPath.u8string()).c_str()}, -#endif - -#if LLVM_VERSION_MAJOR >= 14 - llvm::outs(), llvm::errs(), false, false -#elif LLVM_VERSION_MAJOR >= 10 - false, llvm::outs(), llvm::errs() -#else - false, llvm::errs() -#endif - ); - -#if LLVM_VERSION_MAJOR >= 14 - lld::CommonLinkerContext::destroy(); -#endif - - if (LinkResult) { - std::error_code Error; - std::filesystem::remove(ObjectName, Error); -#if WASMEDGE_OS_WINDOWS - std::filesystem::path LibPath(OutputPath); - LibPath.replace_extension(".lib"sv); - std::filesystem::remove(LibPath, Error); -#endif - - spdlog::info("compile done"); - } else { - spdlog::error("link error"); - } - -#if WASMEDGE_OS_MACOS - // codesign - if (LinkResult) { - pid_t PID = ::fork(); - if (PID == -1) { - spdlog::error("codesign error on fork:{}", std::strerror(errno)); - } else if (PID == 0) { - execlp("/usr/bin/codesign", "codesign", "-s", "-", - OutputPath.u8string().c_str(), nullptr); - std::exit(256); - } else { - int ChildStat; - waitpid(PID, &ChildStat, 0); - if (const int Status = WEXITSTATUS(ChildStat); Status != 0) { - spdlog::error("codesign exited with status {}", Status); - } - } - } -#endif - - return {}; -} - -Expect outputWasmLibrary(const std::filesystem::path &OutputPath, - Span Data, - const LLVM::MemoryBuffer &OSVec) noexcept { - std::filesystem::path SharedObjectName; - { - // tempfile - std::filesystem::path SOPath(OutputPath); - SOPath.replace_extension("%%%%%%%%%%" WASMEDGE_LIB_EXTENSION); - SharedObjectName = createTemp(SOPath); - if (SharedObjectName.empty()) { - // TODO:return error - spdlog::error("so file creation failed:{}", SOPath.u8string()); - return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); - } - std::ofstream OS(SharedObjectName, std::ios_base::binary); - OS.write(OSVec.data(), static_cast(OSVec.size())); - OS.close(); - } - - if (auto Res = outputNativeLibrary(SharedObjectName, OSVec); unlikely(!Res)) { - return Unexpect(Res); - } - - LLVM::MemoryBuffer SOFile; - if (auto [Res, ErrorMessage] = - LLVM::MemoryBuffer::getFile(SharedObjectName.u8string().c_str()); - unlikely(ErrorMessage)) { - spdlog::error("object file open error:{}", ErrorMessage.string_view()); - return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); - } else { - SOFile = std::move(Res); - } - - LLVM::Context Context; - LLVM::Binary ObjFile; - if (auto [Res, ErrorMessage] = LLVM::Binary::create(SOFile, Context); - unlikely(ErrorMessage)) { - spdlog::error("object file parse error:{}", ErrorMessage.string_view()); - return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); - } else { - ObjFile = std::move(Res); - } - - std::string OSCustomSecVec; - { - std::ostringstream OS; - WriteName(OS, "wasmedge"sv); - WriteU32(OS, WasmEdge::AOT::kBinaryVersion); - -#if WASMEDGE_OS_LINUX - WriteByte(OS, UINT8_C(1)); -#elif WASMEDGE_OS_MACOS - WriteByte(OS, UINT8_C(2)); -#elif WASMEDGE_OS_WINDOWS - WriteByte(OS, UINT8_C(3)); -#else -#error Unsupported operating system! -#endif - -#if defined(__x86_64__) - WriteByte(OS, UINT8_C(1)); -#elif defined(__aarch64__) - WriteByte(OS, UINT8_C(2)); -#elif defined(__riscv) && __riscv_xlen == 64 - WriteByte(OS, UINT8_C(3)); -#elif defined(__arm__) && __ARM_ARCH == 7 - WriteByte(OS, UINT8_C(4)); -#else -#error Unsupported hardware architecture! -#endif - - std::vector> SymbolTable; -#if !WASMEDGE_OS_WINDOWS - for (auto Symbol = ObjFile.symbols(); - Symbol && !ObjFile.isSymbolEnd(Symbol); Symbol.next()) { - SymbolTable.emplace_back(Symbol.getName(), Symbol.getAddress()); - } -#else - for (auto &Symbol : - llvm::object::unwrap(ObjFile.unwrap()) - ->export_directories()) { - llvm::StringRef Name; - if (auto Error = Symbol.getSymbolName(Name); unlikely(!!Error)) { - continue; - } else if (Name.empty()) { - continue; - } - uint32_t Offset = 0; - if (auto Error = Symbol.getExportRVA(Offset); unlikely(!!Error)) { - continue; - } - SymbolTable.emplace_back(Name.str(), Offset); - } -#endif - uint64_t VersionAddress = 0, IntrinsicsAddress = 0; - std::vector Types; - std::vector Codes; - uint64_t CodesMin = std::numeric_limits::max(); - for (const auto &[Name, Address] : SymbolTable) { - if (Name == SYMBOL("version"sv)) { - VersionAddress = Address; - } else if (Name == SYMBOL("intrinsics"sv)) { - IntrinsicsAddress = Address; - } else if (startsWith(Name, SYMBOL("t"sv))) { - uint64_t Index = 0; - std::from_chars(Name.data() + SYMBOL("t"sv).size(), - Name.data() + Name.size(), Index); - if (Types.size() < Index + 1) { - Types.resize(Index + 1); - } - Types[Index] = Address; - } else if (startsWith(Name, SYMBOL("f"sv))) { - uint64_t Index = 0; - std::from_chars(Name.data() + SYMBOL("f"sv).size(), - Name.data() + Name.size(), Index); - if (Codes.size() < Index + 1) { - Codes.resize(Index + 1); - } - CodesMin = std::min(CodesMin, Index); - Codes[Index] = Address; - } - } - if (CodesMin != std::numeric_limits::max()) { - Codes.erase(Codes.begin(), - Codes.begin() + static_cast(CodesMin)); - } - WriteU64(OS, VersionAddress); - WriteU64(OS, IntrinsicsAddress); - WriteU64(OS, Types.size()); - for (const uint64_t TypeAddress : Types) { - WriteU64(OS, TypeAddress); - } - WriteU64(OS, Codes.size()); - for (const uint64_t CodeAddress : Codes) { - WriteU64(OS, CodeAddress); - } - - uint32_t SectionCount = 0; - for (auto Section = ObjFile.sections(); !ObjFile.isSectionEnd(Section); - Section.next()) { - if (Section.getSize() == 0) { - continue; - } - if (!Section.isEHFrame() && !Section.isPData() && !Section.isText() && - !Section.isData() && !Section.isBSS()) { - continue; - } - ++SectionCount; - } - WriteU32(OS, SectionCount); - - for (auto Section = ObjFile.sections(); !ObjFile.isSectionEnd(Section); - Section.next()) { - if (Section.getSize() == 0) { - continue; - } - std::vector Content; - if (auto Res = Section.getContents(); unlikely(Res.empty())) { - assumingUnreachable(); - } else { - Content.assign(Res.begin(), Res.end()); - } - if (Section.isEHFrame() || Section.isPData()) { - WriteByte(OS, UINT8_C(4)); - } else if (Section.isText()) { - WriteByte(OS, UINT8_C(1)); - } else if (Section.isData()) { - WriteByte(OS, UINT8_C(2)); - } else if (Section.isBSS()) { - WriteByte(OS, UINT8_C(3)); - } else { - continue; - } - - WriteU64(OS, Section.getAddress()); - WriteU64(OS, Content.size()); - WriteName(OS, std::string_view(Content.data(), Content.size())); - } - OSCustomSecVec = OS.str(); - } - - spdlog::info("output start"); - - std::filesystem::path OutputPathTmp(OutputPath); - OutputPathTmp.replace_extension("%%%%%%%%%%.wasm"); - OutputPathTmp = createTemp(OutputPathTmp); - if (OutputPathTmp.empty()) { - return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); - } - std::ofstream OS(OutputPathTmp, std::ios_base::binary); - if (!OS) { - spdlog::error("output failed."); - return Unexpect(ErrCode::Value::IllegalPath); - } - OS.write(reinterpret_cast(Data.data()), - static_cast(Data.size())); - // Custom section id - WriteByte(OS, UINT8_C(0x00)); - WriteName(OS, std::string_view(OSCustomSecVec.data(), OSCustomSecVec.size())); - - std::error_code Error; - std::filesystem::remove(SharedObjectName, Error); - std::filesystem::rename(OutputPathTmp, OutputPath); - return {}; -} - } // namespace namespace WasmEdge { -namespace AOT { +namespace LLVM { -Expect Compiler::compile(Span Data, const AST::Module &Module, - std::filesystem::path OutputPath) noexcept { +Expect Compiler::compile(const AST::Module &Module) noexcept { // Check the module is validated. if (unlikely(!Module.getIsValidated())) { spdlog::error(ErrCode::Value::NotValidated); @@ -5510,26 +5015,17 @@ Expect Compiler::compile(Span Data, const AST::Module &Module, std::unique_lock Lock(Mutex); spdlog::info("compile start"); - std::filesystem::path LLPath(OutputPath); - LLPath.replace_extension("ll"sv); LLVM::Core::init(); - LLVM::Context LLContext; - LLVM::Module LLModule(LLContext, LLPath.u8string().c_str()); + LLVM::Data D; + auto &LLContext = D.extract().LLContext; + auto &LLModule = D.extract().LLModule; LLModule.setTarget(LLVM::getDefaultTargetTriple().unwrap()); LLModule.addFlag(LLVMModuleFlagBehaviorError, "PIC Level"sv, 2); -#if WASMEDGE_OS_MACOS - { - const auto [Major, Minor] = getSDKVersionPair(); - LLModule.addFlag(LLVMModuleFlagBehaviorError, "SDK Version"sv, - LLVM::Value::getConstVector32(LLContext, {Major, Minor})); - } -#endif + CompileContext NewContext(LLContext, LLModule, - Conf.getCompilerConfigure().isGenericBinary(), - Conf.getCompilerConfigure().getOutputFormat() == - CompilerConfigure::OutputFormat::Wasm); + Conf.getCompilerConfigure().isGenericBinary()); struct RAIICleanup { RAIICleanup(CompileContext *&Context, CompileContext &NewContext) : Context(Context) { @@ -5556,76 +5052,18 @@ Expect Compiler::compile(Span Data, const AST::Module &Module, compile(Module.getExportSection()); // StartSection is not required to compile -#if WASMEDGE_OS_WINDOWS - { - // create dummy dllmain function - auto FTy = LLVM::Type::getFunctionType(Context->LLContext.getInt32Ty(), {}); - auto F = Context->LLModule.addFunction(FTy, LLVMExternalLinkage, - "_DllMainCRTStartup"); - F.setVisibility(LLVMProtectedVisibility); - F.setDSOLocal(true); - F.addFnAttr(Context->NoStackArgProbe); - F.addFnAttr(Context->StrictFP); - F.addFnAttr(Context->UWTable); - F.addFnAttr(Context->NoReturn); - LLVM::Builder Builder(Context->LLContext); - Builder.positionAtEnd( - LLVM::BasicBlock::create(Context->LLContext, F, "entry")); - Builder.createRet(Context->LLContext.getInt32(1u)); - - auto A = LLModule.addAlias(F.getType(), F, "_fltused"); - A.setLinkage(LLVMExternalLinkage); - A.setVisibility(LLVMProtectedVisibility); - A.setDSOLocal(true); - } -#endif - - if (!Context->IsCustomSection) { - // create wasm.code and wasm.size - auto Int32Ty = Context->Int32Ty; - auto Content = LLVM::Value::getConstString( - LLContext, {reinterpret_cast(Data.data()), Data.size()}, - true); - LLModule.addGlobal(Content.getType(), true, LLVMExternalLinkage, Content, - "wasm.code"); - LLModule.addGlobal(Int32Ty, true, LLVMExternalLinkage, - LLVM::Value::getConstInt(Int32Ty, Data.size()), - "wasm.size"); - } - - // set dllexport - for (auto GV = LLModule.getFirstGlobal(); GV; GV = GV.getNextGlobal()) { - if (GV.getLinkage() == LLVMExternalLinkage) { - GV.setVisibility(LLVMProtectedVisibility); - GV.setDSOLocal(true); - GV.setDLLStorageClass(LLVMDLLExportStorageClass); - } - } - - if (Conf.getCompilerConfigure().isDumpIR()) { - if (auto ErrorMessage = LLModule.printModuleToFile("wasm.ll"); - unlikely(ErrorMessage)) { - spdlog::error("wasm.ll open error:{}", ErrorMessage.string_view()); - return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); - } - } - spdlog::info("verify start"); LLModule.verify(LLVMPrintMessageAction); - spdlog::info("optimize start"); - // optimize + codegen - auto Triple = LLModule.getTarget(); + spdlog::info("optimize start"); + auto &TM = D.extract().TM; { - LLVM::TargetMachine TM; - { - auto [TheTarget, ErrorMessage] = LLVM::Target::getFromTriple(Triple); - if (ErrorMessage) { - // TODO:return error - spdlog::error("lookupTarget failed:{}", ErrorMessage.string_view()); - return Unexpect(ErrCode::Value::IllegalPath); - } - + auto Triple = LLModule.getTarget(); + auto [TheTarget, ErrorMessage] = LLVM::Target::getFromTriple(Triple); + if (ErrorMessage) { + spdlog::error("getFromTriple failed:{}", ErrorMessage.string_view()); + return Unexpect(ErrCode::Value::IllegalPath); + } else { std::string CPUName; #if defined(__riscv) && __riscv_xlen == 64 CPUName = "generic-rv64"s; @@ -5639,90 +5077,69 @@ Expect Compiler::compile(Span Data, const AST::Module &Module, TM = LLVM::TargetMachine::create( TheTarget, Triple, CPUName.c_str(), - Context->SubtargetFeatures.unwrap(), + LLVM::getHostCPUFeatures().unwrap(), toLLVMCodeGenLevel( Conf.getCompilerConfigure().getOptimizationLevel()), LLVMRelocPIC, LLVMCodeModelDefault); } #if LLVM_VERSION_MAJOR >= 13 - { - auto PBO = LLVM::PassBuilderOptions::create(); - LLVM::Error Error = PBO.runPasses( - LLModule, - toLLVMLevel(Conf.getCompilerConfigure().getOptimizationLevel()), TM); - if (Error) { - spdlog::error("{}"sv, Error.message().string_view()); - } + auto PBO = LLVM::PassBuilderOptions::create(); + if (auto Error = PBO.runPasses( + LLModule, + toLLVMLevel(Conf.getCompilerConfigure().getOptimizationLevel()), + TM)) { + spdlog::error("{}"sv, Error.message().string_view()); } #else - { - auto FP = LLVM::PassManager::createForModule(LLModule); - auto MP = LLVM::PassManager::create(); - - TM.addAnalysisPasses(MP); - TM.addAnalysisPasses(FP); - { - auto PMB = LLVM::PassManagerBuilder::create(); - auto [OptLevel, SizeLevel] = - toLLVMLevel(Conf.getCompilerConfigure().getOptimizationLevel()); - PMB.setOptLevel(OptLevel); - PMB.setSizeLevel(SizeLevel); - PMB.populateFunctionPassManager(FP); - PMB.populateModulePassManager(MP); - } - if (Conf.getCompilerConfigure().getOptimizationLevel() == - CompilerConfigure::OptimizationLevel::O0) { - FP.addTailCallEliminationPass(); - } - - FP.initializeFunctionPassManager(); - for (auto Fn = LLModule.getFirstFunction(); Fn; - Fn = Fn.getNextFunction()) { - FP.runFunctionPassManager(Fn); - } - FP.finalizeFunctionPassManager(); - MP.runPassManager(LLModule); - } -#endif + auto FP = LLVM::PassManager::createForModule(LLModule); + auto MP = LLVM::PassManager::create(); - // Set initializer for constant value - if (auto IntrinsicsTable = LLModule.getNamedGlobal("intrinsics")) { - IntrinsicsTable.setInitializer( - LLVM::Value::getConstNull(IntrinsicsTable.getType())); - IntrinsicsTable.setGlobalConstant(false); + TM.addAnalysisPasses(MP); + TM.addAnalysisPasses(FP); + { + auto PMB = LLVM::PassManagerBuilder::create(); + auto [OptLevel, SizeLevel] = + toLLVMLevel(Conf.getCompilerConfigure().getOptimizationLevel()); + PMB.setOptLevel(OptLevel); + PMB.setSizeLevel(SizeLevel); + PMB.populateFunctionPassManager(FP); + PMB.populateModulePassManager(MP); } - - if (Conf.getCompilerConfigure().isDumpIR()) { - if (auto ErrorMessage = LLModule.printModuleToFile("wasm-opt.ll")) { - // TODO:return error - spdlog::error("printModuleToFile failed"); - return Unexpect(ErrCode::Value::IllegalPath); - } + switch (Conf.getCompilerConfigure().getOptimizationLevel()) { + case CompilerConfigure::OptimizationLevel::O0: + case CompilerConfigure::OptimizationLevel::O1: + FP.addTailCallEliminationPass(); + break; + default: + break; } - spdlog::info("codegen start"); - auto [OSVec, ErrorMessage] = - TM.emitToMemoryBuffer(LLModule, LLVMObjectFile); - if (ErrorMessage) { - // TODO:return error - spdlog::error("addPassesToEmitFile failed"); - return Unexpect(ErrCode::Value::IllegalPath); + FP.initializeFunctionPassManager(); + for (auto Fn = LLModule.getFirstFunction(); Fn; Fn = Fn.getNextFunction()) { + FP.runFunctionPassManager(Fn); } + FP.finalizeFunctionPassManager(); + MP.runPassManager(LLModule); +#endif + } - if (Context->IsCustomSection) { - if (auto Res = outputWasmLibrary(OutputPath, Data, OSVec); - unlikely(!Res)) { - return Unexpect(Res); - } - } else { - if (auto Res = outputNativeLibrary(OutputPath, OSVec); unlikely(!Res)) { - return Unexpect(Res); - } - } + // Set initializer for constant value + if (auto IntrinsicsTable = LLModule.getNamedGlobal("intrinsics")) { + IntrinsicsTable.setInitializer( + LLVM::Value::getConstNull(IntrinsicsTable.getType())); + IntrinsicsTable.setGlobalConstant(false); + } else { + auto IntrinsicsTableTy = LLVM::Type::getArrayType( + LLContext.getInt8Ty().getPointerTo(), + static_cast(Executable::Intrinsics::kIntrinsicMax)); + LLModule.addGlobal( + IntrinsicsTableTy.getPointerTo(), false, LLVMExternalLinkage, + LLVM::Value::getConstNull(IntrinsicsTableTy), "intrinsics"); } - return {}; + spdlog::info("optimize done"); + return Expect{std::move(D)}; } void Compiler::compile(const AST::TypeSection &TypeSec) noexcept { @@ -5754,7 +5171,7 @@ void Compiler::compile(const AST::TypeSection &TypeSec) noexcept { Context->FunctionTypes.push_back(&OldFuncType); auto F = Context->FunctionWrappers[J]; Context->FunctionWrappers.push_back(F); - auto A = Context->LLModule.addAlias(F.getType(), F, Name.c_str()); + auto A = Context->LLModule.addAlias(WrapperTy, F, Name.c_str()); A.setLinkage(LLVMExternalLinkage); A.setVisibility(LLVMProtectedVisibility); A.setDSOLocal(true); @@ -5859,16 +5276,12 @@ void Compiler::compile(const AST::ImportSection &ImportSec) noexcept { auto FTy = toLLVMType(Context->LLContext, Context->ExecCtxPtrTy, FuncType); auto RTy = FTy.getReturnType(); - const auto Linkage = - Context->IsCustomSection ? LLVMPrivateLinkage : LLVMExternalLinkage; auto F = LLVM::FunctionCallee{ - FTy, Context->LLModule.addFunction( - FTy, Linkage, fmt::format("f{}"sv, FuncID).c_str())}; + FTy, + Context->LLModule.addFunction(FTy, LLVMInternalLinkage, + fmt::format("f{}"sv, FuncID).c_str())}; F.Fn.setVisibility(LLVMProtectedVisibility); F.Fn.setDSOLocal(true); - if (!Context->IsCustomSection) { - F.Fn.setDLLStorageClass(LLVMDLLExportStorageClass); - } F.Fn.addFnAttr(Context->NoStackArgProbe); F.Fn.addFnAttr(Context->StrictFP); F.Fn.addFnAttr(Context->UWTable); @@ -6029,14 +5442,12 @@ void Compiler::compile(const AST::FunctionSection &FuncSec, FunctionCompiler FC(*Context, F, Locals, Conf.getCompilerConfigure().isInterruptible(), Conf.getStatisticsConfigure().isInstructionCounting(), - Conf.getStatisticsConfigure().isCostMeasuring(), - Conf.getCompilerConfigure().getOptimizationLevel() == - CompilerConfigure::OptimizationLevel::O0); + Conf.getStatisticsConfigure().isCostMeasuring()); auto Type = Context->resolveBlockType(T); FC.compile(*Code, std::move(Type)); F.Fn.eliminateUnreachableBlocks(); } } -} // namespace AOT +} // namespace LLVM } // namespace WasmEdge diff --git a/lib/llvm/data.cpp b/lib/llvm/data.cpp new file mode 100644 index 000000000000..9590f89b9670 --- /dev/null +++ b/lib/llvm/data.cpp @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +#include "llvm/data.h" +#include "data.h" +#include "llvm.h" + +namespace LLVM = WasmEdge::LLVM; + +LLVM::Data::Data() noexcept : Context(std::make_unique()) {} + +LLVM::Data::~Data() noexcept {} + +LLVM::Data::Data(LLVM::Data &&RHS) noexcept : Context(std::move(RHS.Context)) {} +LLVM::Data &LLVM::Data::operator=(LLVM::Data &&RHS) noexcept { + using std::swap; + swap(Context, RHS.Context); + return *this; +} diff --git a/lib/llvm/data.h b/lib/llvm/data.h new file mode 100644 index 000000000000..555a37c57708 --- /dev/null +++ b/lib/llvm/data.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC +#pragma once + +#include "llvm.h" +#include "llvm/data.h" + +struct WasmEdge::LLVM::Data::DataContext { + LLVM::Context LLContext; + LLVM::Module LLModule; + LLVM::TargetMachine TM; + DataContext() noexcept : LLContext(), LLModule(LLContext, "wasm") {} +}; diff --git a/lib/aot/llvm.h b/lib/llvm/llvm.h similarity index 99% rename from lib/aot/llvm.h rename to lib/llvm/llvm.h index 30143e89982f..dd907e72bcc9 100644 --- a/lib/aot/llvm.h +++ b/lib/llvm/llvm.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC +#pragma once #include "common/errcode.h" #include "common/span.h" @@ -28,7 +29,7 @@ #define __x86_64__ 1 #endif -namespace WasmEdge::AOT::LLVM { +namespace WasmEdge::LLVM { class Core { public: @@ -283,6 +284,7 @@ class Module { uint32_t Val) noexcept; inline Value getFirstGlobal() noexcept; inline Value getFirstFunction() noexcept; + inline Value getNamedFunction(const char *Name) noexcept; inline Message printModuleToFile(const char *File) noexcept; inline Message verify(LLVMVerifierFailureAction Action) noexcept; @@ -765,6 +767,11 @@ class Value { void setOrdering(LLVMAtomicOrdering Ordering) noexcept { LLVMSetOrdering(Ref, Ordering); } + std::string_view getName() noexcept { + size_t Length; + auto Data = LLVMGetValueName2(Ref, &Length); + return {Data, Length}; + } inline void addCase(Value OnVal, BasicBlock Dest) noexcept; inline void addDestination(BasicBlock Dest) noexcept; @@ -903,6 +910,10 @@ void Module::addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key, Value Module::getFirstGlobal() noexcept { return LLVMGetFirstGlobal(Ref); } Value Module::getFirstFunction() noexcept { return LLVMGetFirstFunction(Ref); } +Value Module::getNamedFunction(const char *Name) noexcept { + return LLVMGetNamedFunction(Ref, Name); +} + Message Module::printModuleToFile(const char *Filename) noexcept { Message M; LLVMPrintModuleToFile(Ref, Filename, &M.unwrap()); @@ -1546,7 +1557,7 @@ class Builder { Value getConstrainedFPExcept() noexcept { using namespace std::literals; auto Ctx = getCtx(); - auto ExceptStr = "fpexcept.ignore"sv; + auto ExceptStr = "fpexcept.strict"sv; auto ExceptMDS = LLVMMDStringInContext2(Ctx, ExceptStr.data(), ExceptStr.size()); return LLVMMetadataAsValue(Ctx, ExceptMDS); @@ -1943,13 +1954,13 @@ class Binary { LLVMBinaryRef Ref = nullptr; }; -} // namespace WasmEdge::AOT::LLVM +} // namespace WasmEdge::LLVM #include #include #include -namespace WasmEdge::AOT::LLVM { +namespace WasmEdge::LLVM { void Value::setDSOLocal(bool Local) noexcept { llvm::cast(reinterpret_cast(Ref)) @@ -1997,4 +2008,4 @@ bool SectionIterator::isEHFrame() const noexcept { #endif } -} // namespace WasmEdge::AOT::LLVM +} // namespace WasmEdge::LLVM diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 73405ee189fb..5400f42296ac 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -60,8 +60,9 @@ else() set(GTEST_BOTH_LIBRARIES "gtest;gtest_main") endif() -if (WASMEDGE_BUILD_AOT_RUNTIME) +if (WASMEDGE_USE_LLVM) add_subdirectory(aot) + add_subdirectory(llvm) add_subdirectory(mixcall) endif() add_subdirectory(common) diff --git a/test/aot/CMakeLists.txt b/test/aot/CMakeLists.txt index b49c48042a7d..a272b5e1c3e8 100644 --- a/test/aot/CMakeLists.txt +++ b/test/aot/CMakeLists.txt @@ -1,22 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -wasmedge_add_executable(wasmedgeAOTCoreTests - AOTcoreTest.cpp -) - -add_test(wasmedgeAOTCoreTests wasmedgeAOTCoreTests) - -target_link_libraries(wasmedgeAOTCoreTests - PRIVATE - std::filesystem - ${GTEST_BOTH_LIBRARIES} - wasmedgeTestSpec - wasmedgeLoader - wasmedgeAOT - wasmedgeVM -) - wasmedge_add_executable(wasmedgeAOTCacheTests AOTCacheTest.cpp ) diff --git a/test/api/APIUnitTest.cpp b/test/api/APIUnitTest.cpp index 289671cc7475..fd933d8da0d0 100644 --- a/test/api/APIUnitTest.cpp +++ b/test/api/APIUnitTest.cpp @@ -1143,7 +1143,7 @@ TEST(APICoreTest, ExportType) { WasmEdge_ASTModuleDelete(Mod); } -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM TEST(APICoreTest, Compiler) { WasmEdge_ConfigureContext *Conf = WasmEdge_ConfigureCreate(); std::ifstream OutFile; @@ -1328,7 +1328,7 @@ TEST(APICoreTest, Loader) { WasmEdge_ErrCode_WrongVMWorkflow, WasmEdge_LoaderParseFromBuffer(nullptr, nullptr, Buf.data(), static_cast(Buf.size())))); -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM // Failed case to parse from buffer with AOT compiled WASM EXPECT_TRUE(readToVector("test_aot" WASMEDGE_LIB_EXTENSION, Buf)); Mod = nullptr; diff --git a/test/api/CMakeLists.txt b/test/api/CMakeLists.txt index 6e92b3c1641a..e694eb0e3753 100644 --- a/test/api/CMakeLists.txt +++ b/test/api/CMakeLists.txt @@ -1,8 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -if(WASMEDGE_BUILD_AOT_RUNTIME) - add_definitions(-DWASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) + add_definitions(-DWASMEDGE_USE_LLVM) endif() if(WASMEDGE_BUILD_PLUGINS) add_definitions(-DWASMEDGE_BUILD_PLUGINS) @@ -74,7 +74,7 @@ target_link_libraries(wasmedgeAPIStepsCoreTests wasmedge_shared ) -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) wasmedge_add_executable(wasmedgeAPIAOTCoreTests APIAOTCoreTest.cpp ) diff --git a/test/llvm/CMakeLists.txt b/test/llvm/CMakeLists.txt new file mode 100644 index 000000000000..d1033cd9af4e --- /dev/null +++ b/test/llvm/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +wasmedge_add_executable(wasmedgeLLVMCoreTests + LLVMcoreTest.cpp +) + +add_test(wasmedgeLLVMCoreTests wasmedgeLLVMCoreTests) + +target_link_libraries(wasmedgeLLVMCoreTests + PRIVATE + std::filesystem + ${GTEST_BOTH_LIBRARIES} + wasmedgeTestSpec + wasmedgeLoader + wasmedgeLLVM + wasmedgeVM +) diff --git a/test/aot/AOTcoreTest.cpp b/test/llvm/LLVMcoreTest.cpp similarity index 86% rename from test/aot/AOTcoreTest.cpp rename to test/llvm/LLVMcoreTest.cpp index bf06003f4ede..7eb7da3ba133 100644 --- a/test/aot/AOTcoreTest.cpp +++ b/test/llvm/LLVMcoreTest.cpp @@ -14,10 +14,11 @@ /// //===----------------------------------------------------------------------===// -#include "aot/compiler.h" #include "common/defines.h" #include "common/log.h" #include "vm/vm.h" +#include "llvm/codegen.h" +#include "llvm/compiler.h" #include "../spec/hostfunc.h" #include "../spec/spectest.h" @@ -60,24 +61,27 @@ TEST_P(NativeCoreTest, TestSuites) { CopyConf.getCompilerConfigure().setOptimizationLevel( WasmEdge::CompilerConfigure::OptimizationLevel::O0); CopyConf.getCompilerConfigure().setDumpIR(true); - WasmEdge::AOT::Compiler Compiler(CopyConf); + WasmEdge::LLVM::Compiler Compiler(CopyConf); + WasmEdge::LLVM::CodeGen CodeGen(CopyConf); auto Path = std::filesystem::u8path(Filename); Path.replace_extension(std::filesystem::u8path(WASMEDGE_LIB_EXTENSION)); const auto SOPath = Path.u8string(); - auto Data = *Loader.loadFile(Filename); + std::vector Data; std::unique_ptr Module; - if (auto Res = Loader.parseModule(Data)) { - Module = std::move(*Res); - } else { - return Unexpect(Res); - } - if (auto Res = ValidatorEngine.validate(*Module); !Res) { - return Unexpect(Res); - } - if (auto Res = Compiler.compile(Data, *Module, SOPath); !Res) { - return Unexpect(Res); - } - return SOPath; + return Loader.loadFile(Filename) + .and_then([&](auto Result) noexcept { + Data = std::move(Result); + return Loader.parseModule(Data); + }) + .and_then([&](auto Result) noexcept { + Module = std::move(Result); + return ValidatorEngine.validate(*Module); + }) + .and_then([&]() noexcept { return Compiler.compile(*Module); }) + .and_then([&](auto Result) noexcept { + return CodeGen.codegen(Data, std::move(Result), SOPath); + }) + .and_then([&]() noexcept { return Expect{SOPath}; }); }; T.onModule = [&VM, &Compile](const std::string &ModName, const std::string &Filename) -> Expect { @@ -166,24 +170,27 @@ TEST_P(CustomWasmCoreTest, TestSuites) { CopyConf.getCompilerConfigure().setOptimizationLevel( WasmEdge::CompilerConfigure::OptimizationLevel::O0); CopyConf.getCompilerConfigure().setDumpIR(true); - WasmEdge::AOT::Compiler Compiler(CopyConf); + WasmEdge::LLVM::Compiler Compiler(CopyConf); + WasmEdge::LLVM::CodeGen CodeGen(CopyConf); auto Path = std::filesystem::u8path(Filename); Path.replace_extension(std::filesystem::u8path(".aot.wasm")); const auto SOPath = Path.u8string(); - auto Data = *Loader.loadFile(Filename); + std::vector Data; std::unique_ptr Module; - if (auto Res = Loader.parseModule(Data)) { - Module = std::move(*Res); - } else { - return Unexpect(Res); - } - if (auto Res = ValidatorEngine.validate(*Module); !Res) { - return Unexpect(Res); - } - if (auto Res = Compiler.compile(Data, *Module, SOPath); !Res) { - return Unexpect(Res); - } - return SOPath; + return Loader.loadFile(Filename) + .and_then([&](auto Result) noexcept { + Data = std::move(Result); + return Loader.parseModule(Data); + }) + .and_then([&](auto Result) noexcept { + Module = std::move(Result); + return ValidatorEngine.validate(*Module); + }) + .and_then([&]() noexcept { return Compiler.compile(*Module); }) + .and_then([&](auto Result) noexcept { + return CodeGen.codegen(Data, std::move(Result), SOPath); + }) + .and_then([&]() noexcept { return Expect{SOPath}; }); }; T.onModule = [&VM, &Compile](const std::string &ModName, const std::string &Filename) -> Expect { @@ -282,12 +289,15 @@ TEST(AsyncRunWsmFile, NativeInterruptTest) { WasmEdge::VM::VM VM(Conf); WasmEdge::Loader::Loader Loader(Conf); WasmEdge::Validator::Validator ValidatorEngine(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); auto Path = std::filesystem::temp_directory_path() / std::filesystem::u8path("AOTcoreTest" WASMEDGE_LIB_EXTENSION); auto Module = *Loader.parseModule(AsyncWasm); ASSERT_TRUE(ValidatorEngine.validate(*Module)); - ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path)); + auto Data = Compiler.compile(*Module); + ASSERT_TRUE(Data); + ASSERT_TRUE(CodeGen.codegen(AsyncWasm, std::move(*Data), Path)); { auto Timeout = std::chrono::system_clock::now() + std::chrono::milliseconds(1); @@ -320,12 +330,15 @@ TEST(AsyncExecute, NativeInterruptTest) { WasmEdge::VM::VM VM(Conf); WasmEdge::Loader::Loader Loader(Conf); WasmEdge::Validator::Validator ValidatorEngine(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); auto Path = std::filesystem::temp_directory_path() / std::filesystem::u8path("AOTcoreTest" WASMEDGE_LIB_EXTENSION); auto Module = *Loader.parseModule(AsyncWasm); ASSERT_TRUE(ValidatorEngine.validate(*Module)); - ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path)); + auto Data = Compiler.compile(*Module); + ASSERT_TRUE(Data); + ASSERT_TRUE(CodeGen.codegen(AsyncWasm, std::move(*Data), Path)); ASSERT_TRUE(VM.loadWasm(Path)); ASSERT_TRUE(VM.validate()); ASSERT_TRUE(VM.instantiate()); @@ -361,12 +374,15 @@ TEST(AsyncRunWsmFile, CustomWasmInterruptTest) { WasmEdge::VM::VM VM(Conf); WasmEdge::Loader::Loader Loader(Conf); WasmEdge::Validator::Validator ValidatorEngine(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); auto Path = std::filesystem::temp_directory_path() / std::filesystem::u8path("AOTcoreTest.aot.wasm"); auto Module = *Loader.parseModule(AsyncWasm); ASSERT_TRUE(ValidatorEngine.validate(*Module)); - ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path)); + auto Data = Compiler.compile(*Module); + ASSERT_TRUE(Data); + ASSERT_TRUE(CodeGen.codegen(AsyncWasm, std::move(*Data), Path)); { auto Timeout = std::chrono::system_clock::now() + std::chrono::milliseconds(1); @@ -399,12 +415,15 @@ TEST(AsyncExecute, CustomWasmInterruptTest) { WasmEdge::VM::VM VM(Conf); WasmEdge::Loader::Loader Loader(Conf); WasmEdge::Validator::Validator ValidatorEngine(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); auto Path = std::filesystem::temp_directory_path() / std::filesystem::u8path("AOTcoreTest.aot.wasm"); auto Module = *Loader.parseModule(AsyncWasm); ASSERT_TRUE(ValidatorEngine.validate(*Module)); - ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path)); + auto Data = Compiler.compile(*Module); + ASSERT_TRUE(Data); + ASSERT_TRUE(CodeGen.codegen(AsyncWasm, std::move(*Data), Path)); ASSERT_TRUE(VM.loadWasm(Path)); ASSERT_TRUE(VM.validate()); ASSERT_TRUE(VM.instantiate()); diff --git a/test/mixcall/CMakeLists.txt b/test/mixcall/CMakeLists.txt index 9b2c37314498..25ecc95ebcb4 100644 --- a/test/mixcall/CMakeLists.txt +++ b/test/mixcall/CMakeLists.txt @@ -17,6 +17,6 @@ target_link_libraries(wasmedgeMixcallTests PRIVATE std::filesystem ${GTEST_BOTH_LIBRARIES} - wasmedgeAOT + wasmedgeLLVM wasmedgeVM ) diff --git a/test/mixcall/mixcallTest.cpp b/test/mixcall/mixcallTest.cpp index 892a61471ff1..a79adf1fa5c1 100644 --- a/test/mixcall/mixcallTest.cpp +++ b/test/mixcall/mixcallTest.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC -#include "aot/compiler.h" #include "common/configure.h" #include "common/errinfo.h" #include "common/filesystem.h" @@ -9,6 +8,8 @@ #include "runtime/instance/module.h" #include "validator/validator.h" #include "vm/vm.h" +#include "llvm/codegen.h" +#include "llvm/compiler.h" #include #include @@ -111,20 +112,24 @@ bool compileModule(const WasmEdge::Configure &Conf, std::string_view InPath, std::string_view OutPath) { WasmEdge::Loader::Loader Load(Conf); WasmEdge::Validator::Validator Valid(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); - auto Mod = Load.parseModule(InPath); - auto Data = Load.loadFile(InPath); - if (!Mod || !Data) { - return false; - } - if (auto Res = Valid.validate(*(*Mod).get()); !Res) { - return false; - } - if (auto Res = Compiler.compile(*Data, *(*Mod).get(), OutPath); !Res) { - return false; - } - return true; + std::vector Data; + std::unique_ptr Module; + return Load.loadFile(InPath) + .and_then([&](auto Result) noexcept { + Data = std::move(Result); + return Load.parseModule(InPath); + }) + .and_then([&](auto Result) noexcept { + Module = std::move(Result); + return Valid.validate(*Module); + }) + .and_then([&]() noexcept { return Compiler.compile(*Module); }) + .and_then([&](auto Result) noexcept { + return CodeGen.codegen(Data, std::move(Result), OutPath); + }).has_value(); } TEST(MixCallTest, Call__InterpCallAOT) { diff --git a/test/thread/CMakeLists.txt b/test/thread/CMakeLists.txt index 8d458d509b12..cdbad7f85169 100644 --- a/test/thread/CMakeLists.txt +++ b/test/thread/CMakeLists.txt @@ -14,13 +14,13 @@ target_link_libraries(wasmedgeThreadTests wasmedgeVM ) -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) target_compile_definitions(wasmedgeThreadTests PRIVATE - -DWASMEDGE_BUILD_AOT_RUNTIME + -DWASMEDGE_USE_LLVM ) target_link_libraries(wasmedgeThreadTests PRIVATE - wasmedgeAOT + wasmedgeLLVM ) endif() diff --git a/test/thread/ThreadTest.cpp b/test/thread/ThreadTest.cpp index 61b9d7969a86..9fc902dd5afb 100644 --- a/test/thread/ThreadTest.cpp +++ b/test/thread/ThreadTest.cpp @@ -15,8 +15,9 @@ #include "common/log.h" #include "vm/vm.h" -#ifdef WASMEDGE_BUILD_AOT_RUNTIME -#include "aot/compiler.h" +#ifdef WASMEDGE_USE_LLVM +#include "llvm/codegen.h" +#include "llvm/compiler.h" #endif #include "gtest/gtest.h" @@ -225,7 +226,7 @@ TEST(AsyncExecute, GasThreadTest) { } } -#ifdef WASMEDGE_BUILD_AOT_RUNTIME +#ifdef WASMEDGE_USE_LLVM TEST(AOTAsyncExecute, ThreadTest) { WasmEdge::Configure Conf; @@ -238,10 +239,13 @@ TEST(AOTAsyncExecute, ThreadTest) { { WasmEdge::Loader::Loader Loader(Conf); WasmEdge::Validator::Validator ValidatorEngine(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); auto Module = *Loader.parseModule(MersenneTwister19937); ASSERT_TRUE(ValidatorEngine.validate(*Module)); - ASSERT_TRUE(Compiler.compile(MersenneTwister19937, *Module, Path)); + auto Data = Compiler.compile(*Module); + ASSERT_TRUE(Data); + ASSERT_TRUE(CodeGen.codegen(MersenneTwister19937, std::move(*Data), Path)); } WasmEdge::VM::VM VM(Conf); @@ -287,10 +291,13 @@ TEST(AOTAsyncExecute, GasThreadTest) { { WasmEdge::Loader::Loader Loader(Conf); WasmEdge::Validator::Validator ValidatorEngine(Conf); - WasmEdge::AOT::Compiler Compiler(Conf); + WasmEdge::LLVM::Compiler Compiler(Conf); + WasmEdge::LLVM::CodeGen CodeGen(Conf); auto Module = *Loader.parseModule(MersenneTwister19937); ASSERT_TRUE(ValidatorEngine.validate(*Module)); - ASSERT_TRUE(Compiler.compile(MersenneTwister19937, *Module, Path)); + auto Data = Compiler.compile(*Module); + ASSERT_TRUE(Data); + ASSERT_TRUE(CodeGen.codegen(MersenneTwister19937, std::move(*Data), Path)); } WasmEdge::VM::VM VM(Conf); diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 0d862b2f429b..ee81128c5b29 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) add_subdirectory(blake3) endif() diff --git a/tools/wasmedge/CMakeLists.txt b/tools/wasmedge/CMakeLists.txt index a886510d4cbf..a99141340873 100644 --- a/tools/wasmedge/CMakeLists.txt +++ b/tools/wasmedge/CMakeLists.txt @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -if(WASMEDGE_BUILD_AOT_RUNTIME) +if(WASMEDGE_USE_LLVM) wasmedge_add_executable(wasmedgec wasmedgec.cpp ) diff --git a/utils/android/app/lib/src/main/cpp/CMakeLists.txt b/utils/android/app/lib/src/main/cpp/CMakeLists.txt index 5855009e86b0..12635680fc3c 100644 --- a/utils/android/app/lib/src/main/cpp/CMakeLists.txt +++ b/utils/android/app/lib/src/main/cpp/CMakeLists.txt @@ -3,10 +3,10 @@ cmake_minimum_required(VERSION 3.22.1) project("wasmedge_lib") set(WASMEDGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../..) -set(WASMEDGE_BUILD_AOT_RUNTIME OFF CACHE BOOL "" FORCE) set(WASMEDGE_BUILD_PLUGINS OFF CACHE BOOL "" FORCE) set(WASMEDGE_BUILD_TOOLS OFF CACHE BOOL "" FORCE) set(WASMEDGE_BUILD_SHARED_LIB ON CACHE BOOL "" FORCE) +set(WASMEDGE_USE_LLVM OFF CACHE BOOL "" FORCE) set(WASMEDGE_FORCE_DISABLE_LTO ON CACHE BOOL "" FORCE) # fast fixed problem for `-fuse-ld=gold`, we use lld. if (CMAKE_GENERATOR STREQUAL Ninja) set(CMAKE_JOB_POOLS "link=2") diff --git a/utils/android/standalone/build_for_android.sh b/utils/android/standalone/build_for_android.sh index 6f50107d64f5..920605cf9ebb 100755 --- a/utils/android/standalone/build_for_android.sh +++ b/utils/android/standalone/build_for_android.sh @@ -11,7 +11,7 @@ WASMEDGE_ROOT_PATH=$(dirname $(dirname $(dirname $(dirname $0)))) cd ${WASMEDGE_ROOT_PATH} -if ! cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=23 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_ANDROID_NDK=$ANDROID_NDK_HOME -DCMAKE_ANDROID_STL_TYPE=c++_static; then +if ! cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=23 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_ANDROID_NDK=$ANDROID_NDK_HOME -DCMAKE_ANDROID_STL_TYPE=c++_static; then echo === CMakeOutput.log === cat build/CMakeFiles/CMakeOutput.log echo === CMakeError.log === diff --git a/utils/docker/Dockerfile.alpine-static b/utils/docker/Dockerfile.alpine-static index d92dd8da5f77..36e936af9016 100644 --- a/utils/docker/Dockerfile.alpine-static +++ b/utils/docker/Dockerfile.alpine-static @@ -62,7 +62,7 @@ RUN --mount=type=bind,target=/src,source=. \ # For cross compiling -DCMAKE_TOOLCHAIN_FILE="$(xx-toolchain)" \ -DWASMEDGE_BUILD_PACKAGE="TGZ" \ - -DWASMEDGE_BUILD_AOT_RUNTIME=ON \ + -DWASMEDGE_USE_LLVM=ON \ # Build just what we need -DWASMEDGE_BUILD_STATIC_LIB=ON \ -DWASMEDGE_BUILD_TESTS=OFF \ diff --git a/utils/docker/Dockerfile.debian-static b/utils/docker/Dockerfile.debian-static index 7c43fc788193..cea1563b9fed 100644 --- a/utils/docker/Dockerfile.debian-static +++ b/utils/docker/Dockerfile.debian-static @@ -75,14 +75,14 @@ RUN cmake -S /src -B /build -G Ninja \ -DCMAKE_INSTALL_PREFIX=/install \ -DWASMEDGE_BUILD_PACKAGE="TGZ" \ -DWASMEDGE_BUILD_TESTS=OFF \ - -DWASMEDGE_BUILD_AOT_RUNTIME=ON \ -DWASMEDGE_BUILD_SHARED_LIB=OFF \ -DWASMEDGE_BUILD_STATIC_LIB=ON \ -DWASMEDGE_BUILD_TOOLS=OFF \ -DWASMEDGE_BUILD_PLUGINS=OFF \ -DWASMEDGE_BUILD_EXAMPLE=OFF \ -DWASMEDGE_LINK_LLVM_STATIC=ON \ - -DWASMEDGE_LINK_TOOLS_STATIC=ON + -DWASMEDGE_LINK_TOOLS_STATIC=ON \ + -DWASMEDGE_USE_LLVM=ON RUN cmake --build /build -- install RUN cmake --build /build -- package diff --git a/utils/ohos/build_for_ohos.sh b/utils/ohos/build_for_ohos.sh index 23aa6dec4ebd..2fba76ab763b 100755 --- a/utils/ohos/build_for_ohos.sh +++ b/utils/ohos/build_for_ohos.sh @@ -13,7 +13,7 @@ cd ${WASMEDGE_ROOT_PATH} mkdir build cd build -if ! cmake .. -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_ON_OHOS=ON -DOHOS_DIR_PATH=${OHOS_DIR_PATH} -DOHOS_SYSROOT_PATH="${OHOS_DIR_PATH}/out/ohos-arm-release/obj/third_party/musl/"; then +if ! cmake .. -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_ON_OHOS=ON -DOHOS_DIR_PATH=${OHOS_DIR_PATH} -DOHOS_SYSROOT_PATH="${OHOS_DIR_PATH}/out/ohos-arm-release/obj/third_party/musl/"; then echo === CMakeOutput.log === cat build/CMakeFiles/CMakeOutput.log echo === CMakeError.log === diff --git a/utils/ohos/configuration/CMakeLists.txt b/utils/ohos/configuration/CMakeLists.txt index 980a23a2119a..f6b88b78ac9c 100644 --- a/utils/ohos/configuration/CMakeLists.txt +++ b/utils/ohos/configuration/CMakeLists.txt @@ -71,10 +71,10 @@ include(Helper) # List of WasmEdge options option(WASMEDGE_BUILD_TESTS "Generate build targets for the wasmedge unit tests." OFF) option(WASMEDGE_BUILD_COVERAGE "Generate coverage report. Require WASMEDGE_BUILD_TESTS." OFF) -option(WASMEDGE_BUILD_AOT_RUNTIME "Enable WasmEdge LLVM-based ahead of time compilation runtime." ON) option(WASMEDGE_BUILD_SHARED_LIB "Generate the WasmEdge shared library." ON) option(WASMEDGE_BUILD_STATIC_LIB "Generate the WasmEdge static library." OFF) option(WASMEDGE_BUILD_TOOLS "Generate wasmedge and wasmedgec tools." ON) +option(WASMEDGE_USE_LLVM "Enable WasmEdge LLVM-based ahead of time compilation runtime." ON) option(WASMEDGE_FORCE_DISABLE_LTO "Forcibly disable link time optimization when linking even in Release/RelWithDeb build." OFF) set(WASMEDGE_BUILD_PACKAGE "DEB;RPM" CACHE STRING "Package generate types") set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpack_config.cmake) diff --git a/utils/openwrt/configuration/Makefile b/utils/openwrt/configuration/Makefile index c1d244dcd134..42d4e0e77627 100644 --- a/utils/openwrt/configuration/Makefile +++ b/utils/openwrt/configuration/Makefile @@ -37,7 +37,7 @@ define Package/$(PKG_NAME)/install endef CMAKE_OPTIONS += \ - -DWASMEDGE_BUILD_AOT_RUNTIME=OFF \ + -DWASMEDGE_USE_LLVM=OFF \ $(eval $(call BuildPackage,$(PKG_NAME))) From 947c2144e8cb1c4f39e99fca27e52b4a1c7a343d Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 1 Feb 2024 13:34:24 +0800 Subject: [PATCH 021/218] [JIT] Add llvm orcjit as dependency Signed-off-by: Shen-Ta Hsieh --- cmake/Helper.cmake | 2 +- lib/llvm/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index f4356ec43153..395f8b03f095 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -195,7 +195,7 @@ if((WASMEDGE_LINK_LLVM_STATIC OR WASMEDGE_BUILD_STATIC_LIB) AND WASMEDGE_USE_LLV find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_PATH}") execute_process( COMMAND ${LLVM_BINARY_DIR}/bin/llvm-config --libs --link-static - core lto native nativecodegen option passes support transformutils all-targets + core lto native nativecodegen option passes support orcjit transformutils all-targets OUTPUT_VARIABLE WASMEDGE_LLVM_LINK_LIBS_NAME ) string(REPLACE "-l" "" WASMEDGE_LLVM_LINK_LIBS_NAME "${WASMEDGE_LLVM_LINK_LIBS_NAME}") diff --git a/lib/llvm/CMakeLists.txt b/lib/llvm/CMakeLists.txt index c424b5798ef0..306dfeb3d141 100644 --- a/lib/llvm/CMakeLists.txt +++ b/lib/llvm/CMakeLists.txt @@ -64,6 +64,7 @@ else() option passes support + orcjit transformutils ${EXTRA_COMPONENTS} ) From 7f3867a16c59f9daa913a0e7b856c9ff602f6738 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 1 Feb 2024 13:47:12 +0800 Subject: [PATCH 022/218] [JIT] Use OrcThreadSafeContext and OrcThreadSafeModule Signed-off-by: Shen-Ta Hsieh --- lib/llvm/codegen.cpp | 11 +++-- lib/llvm/compiler.cpp | 32 +++++++------- lib/llvm/data.h | 5 ++- lib/llvm/llvm.h | 98 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 109 insertions(+), 37 deletions(-) diff --git a/lib/llvm/codegen.cpp b/lib/llvm/codegen.cpp index f21f9d816721..0b42f7440d83 100644 --- a/lib/llvm/codegen.cpp +++ b/lib/llvm/codegen.cpp @@ -299,7 +299,8 @@ Expect outputNativeLibrary(const std::filesystem::path &OutputPath, return {}; } -Expect outputWasmLibrary(const std::filesystem::path &OutputPath, +Expect outputWasmLibrary(LLVM::Context LLContext, + const std::filesystem::path &OutputPath, Span Data, const LLVM::MemoryBuffer &OSVec) noexcept { std::filesystem::path SharedObjectName; @@ -332,9 +333,8 @@ Expect outputWasmLibrary(const std::filesystem::path &OutputPath, SOFile = std::move(Res); } - LLVM::Context Context; LLVM::Binary ObjFile; - if (auto [Res, ErrorMessage] = LLVM::Binary::create(SOFile, Context); + if (auto [Res, ErrorMessage] = LLVM::Binary::create(SOFile, LLContext); unlikely(ErrorMessage)) { spdlog::error("object file parse error:{}", ErrorMessage.string_view()); return Unexpect(ErrCode::Value::IllegalPath); @@ -506,7 +506,7 @@ namespace WasmEdge::LLVM { Expect CodeGen::codegen(Span WasmData, Data D, std::filesystem::path OutputPath) noexcept { - auto &LLContext = D.extract().LLContext; + auto LLContext = D.extract().LLContext(); auto &LLModule = D.extract().LLModule; auto &TM = D.extract().TM; std::filesystem::path LLPath(OutputPath); @@ -570,7 +570,6 @@ Expect CodeGen::codegen(Span WasmData, Data D, for (auto Fn = LLModule.getFirstFunction(); Fn; Fn = Fn.getNextFunction()) { if (Fn.getLinkage() == LLVMInternalLinkage) { Fn.setLinkage(LLVMPrivateLinkage); - Fn.setVisibility(LLVMProtectedVisibility); Fn.setDSOLocal(true); Fn.setDLLStorageClass(LLVMDefaultStorageClass); } @@ -615,7 +614,7 @@ Expect CodeGen::codegen(Span WasmData, Data D, if (Conf.getCompilerConfigure().getOutputFormat() == CompilerConfigure::OutputFormat::Wasm) { - if (auto Res = outputWasmLibrary(OutputPath, WasmData, OSVec); + if (auto Res = outputWasmLibrary(LLContext, OutputPath, WasmData, OSVec); unlikely(!Res)) { return Unexpect(Res); } diff --git a/lib/llvm/compiler.cpp b/lib/llvm/compiler.cpp index bae3e1926d9e..60397ffdd499 100644 --- a/lib/llvm/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -29,19 +29,19 @@ namespace { static bool isVoidReturn(WasmEdge::Span ValTypes) noexcept; -static LLVM::Type toLLVMType(LLVM::Context &LLContext, +static LLVM::Type toLLVMType(LLVM::Context LLContext, const WasmEdge::ValType &ValType) noexcept; static std::vector -toLLVMArgsType(LLVM::Context &LLContext, LLVM::Type ExecCtxPtrTy, +toLLVMArgsType(LLVM::Context LLContext, LLVM::Type ExecCtxPtrTy, WasmEdge::Span ValTypes) noexcept; static LLVM::Type -toLLVMRetsType(LLVM::Context &LLContext, +toLLVMRetsType(LLVM::Context LLContext, WasmEdge::Span ValTypes) noexcept; static LLVM::Type -toLLVMType(LLVM::Context &LLContext, LLVM::Type ExecCtxPtrTy, +toLLVMType(LLVM::Context LLContext, LLVM::Type ExecCtxPtrTy, const WasmEdge::AST::FunctionType &FuncType) noexcept; static LLVM::Value -toLLVMConstantZero(LLVM::Context &LLContext, +toLLVMConstantZero(LLVM::Context LLContext, const WasmEdge::ValType &ValType) noexcept; static std::vector unpackStruct(LLVM::Builder &Builder, LLVM::Value Struct) noexcept; @@ -125,7 +125,7 @@ static inline LLVMCodeGenOptLevel toLLVMCodeGenLevel( } // namespace struct LLVM::Compiler::CompileContext { - LLVM::Context &LLContext; + LLVM::Context LLContext; LLVM::Module &LLModule; LLVM::Attribute Cold; LLVM::Attribute NoAlias; @@ -202,7 +202,7 @@ struct LLVM::Compiler::CompileContext { std::vector Globals; LLVM::Value IntrinsicsTable; LLVM::FunctionCallee Trap; - CompileContext(LLVM::Context &C, LLVM::Module &M, + CompileContext(LLVM::Context C, LLVM::Module &M, bool IsGenericBinary) noexcept : LLContext(C), LLModule(M), Cold(LLVM::Attribute::createEnum(C, LLVM::Core::Cold, 0)), @@ -258,7 +258,6 @@ struct LLVM::Compiler::CompileContext { "intrinsics")) { Trap.Ty = LLVM::Type::getFunctionType(VoidTy, {Int32Ty}); Trap.Fn = LLModule.addFunction(Trap.Ty, LLVMPrivateLinkage, "trap"); - Trap.Fn.setVisibility(LLVMProtectedVisibility); Trap.Fn.setDSOLocal(true); Trap.Fn.addFnAttr(NoStackArgProbe); Trap.Fn.addFnAttr(StrictFP); @@ -406,7 +405,7 @@ static bool isVoidReturn(Span ValTypes) noexcept { return ValTypes.empty(); } -static LLVM::Type toLLVMType(LLVM::Context &LLContext, +static LLVM::Type toLLVMType(LLVM::Context LLContext, const ValType &ValType) noexcept { switch (ValType.getCode()) { case TypeCode::I32: @@ -427,7 +426,7 @@ static LLVM::Type toLLVMType(LLVM::Context &LLContext, } static std::vector -toLLVMTypeVector(LLVM::Context &LLContext, +toLLVMTypeVector(LLVM::Context LLContext, Span ValTypes) noexcept { std::vector Result; Result.reserve(ValTypes.size()); @@ -438,14 +437,14 @@ toLLVMTypeVector(LLVM::Context &LLContext, } static std::vector -toLLVMArgsType(LLVM::Context &LLContext, LLVM::Type ExecCtxPtrTy, +toLLVMArgsType(LLVM::Context LLContext, LLVM::Type ExecCtxPtrTy, Span ValTypes) noexcept { auto Result = toLLVMTypeVector(LLContext, ValTypes); Result.insert(Result.begin(), ExecCtxPtrTy); return Result; } -static LLVM::Type toLLVMRetsType(LLVM::Context &LLContext, +static LLVM::Type toLLVMRetsType(LLVM::Context LLContext, Span ValTypes) noexcept { if (isVoidReturn(ValTypes)) { return LLContext.getVoidTy(); @@ -461,7 +460,7 @@ static LLVM::Type toLLVMRetsType(LLVM::Context &LLContext, return LLVM::Type::getStructType(Result); } -static LLVM::Type toLLVMType(LLVM::Context &LLContext, LLVM::Type ExecCtxPtrTy, +static LLVM::Type toLLVMType(LLVM::Context LLContext, LLVM::Type ExecCtxPtrTy, const AST::FunctionType &FuncType) noexcept { auto ArgsTy = toLLVMArgsType(LLContext, ExecCtxPtrTy, FuncType.getParamTypes()); @@ -469,7 +468,7 @@ static LLVM::Type toLLVMType(LLVM::Context &LLContext, LLVM::Type ExecCtxPtrTy, return LLVM::Type::getFunctionType(RetTy, ArgsTy); } -static LLVM::Value toLLVMConstantZero(LLVM::Context &LLContext, +static LLVM::Value toLLVMConstantZero(LLVM::Context LLContext, const ValType &ValType) noexcept { switch (ValType.getCode()) { case TypeCode::I32: @@ -4953,7 +4952,7 @@ class FunctionCompiler { } LLVM::Compiler::CompileContext &Context; - LLVM::Context &LLContext; + LLVM::Context LLContext; std::vector> Local; std::vector Stack; LLVM::Value LocalInstrCount = nullptr; @@ -5019,7 +5018,7 @@ Expect Compiler::compile(const AST::Module &Module) noexcept { LLVM::Core::init(); LLVM::Data D; - auto &LLContext = D.extract().LLContext; + auto LLContext = D.extract().LLContext(); auto &LLModule = D.extract().LLModule; LLModule.setTarget(LLVM::getDefaultTargetTriple().unwrap()); LLModule.addFlag(LLVMModuleFlagBehaviorError, "PIC Level"sv, 2); @@ -5280,7 +5279,6 @@ void Compiler::compile(const AST::ImportSection &ImportSec) noexcept { FTy, Context->LLModule.addFunction(FTy, LLVMInternalLinkage, fmt::format("f{}"sv, FuncID).c_str())}; - F.Fn.setVisibility(LLVMProtectedVisibility); F.Fn.setDSOLocal(true); F.Fn.addFnAttr(Context->NoStackArgProbe); F.Fn.addFnAttr(Context->StrictFP); diff --git a/lib/llvm/data.h b/lib/llvm/data.h index 555a37c57708..da602876d050 100644 --- a/lib/llvm/data.h +++ b/lib/llvm/data.h @@ -6,8 +6,9 @@ #include "llvm/data.h" struct WasmEdge::LLVM::Data::DataContext { - LLVM::Context LLContext; + LLVM::OrcThreadSafeContext TSContext; LLVM::Module LLModule; LLVM::TargetMachine TM; - DataContext() noexcept : LLContext(), LLModule(LLContext, "wasm") {} + DataContext() noexcept : TSContext(), LLModule(LLContext(), "wasm") {} + LLVM::Context LLContext() noexcept { return TSContext.getContext(); } }; diff --git a/lib/llvm/llvm.h b/lib/llvm/llvm.h index dd907e72bcc9..af5729a8660c 100644 --- a/lib/llvm/llvm.h +++ b/lib/llvm/llvm.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -208,16 +209,8 @@ class BasicBlock; class Context { public: constexpr Context(LLVMContextRef R) noexcept : Ref(R) {} - Context(const Context &) = delete; - Context &operator=(const Context &) = delete; - Context(Context &&C) noexcept : Context() { swap(*this, C); } - Context &operator=(Context &&C) noexcept { - swap(*this, C); - return *this; - } - - Context() noexcept : Ref(LLVMContextCreate()) {} - ~Context() noexcept { LLVMContextDispose(Ref); } + Context(const Context &) = default; + Context &operator=(const Context &) = default; constexpr operator bool() const noexcept { return Ref != nullptr; } constexpr auto &unwrap() const noexcept { return Ref; } @@ -263,7 +256,7 @@ class Module { return *this; } - Module(Context &C, const char *Name) noexcept + Module(const Context &C, const char *Name) noexcept : Ref(LLVMModuleCreateWithNameInContext(Name, C.unwrap())) {} ~Module() noexcept { LLVMDisposeModule(Ref); } @@ -291,6 +284,7 @@ class Module { constexpr operator bool() const noexcept { return Ref != nullptr; } constexpr auto &unwrap() const noexcept { return Ref; } constexpr auto &unwrap() noexcept { return Ref; } + LLVMModuleRef release() noexcept { return std::exchange(Ref, nullptr); } friend void swap(Module &LHS, Module &RHS) noexcept { using std::swap; swap(LHS.Ref, RHS.Ref); @@ -345,6 +339,7 @@ class Error { constexpr operator bool() const noexcept { return Ref != nullptr; } constexpr auto &unwrap() const noexcept { return Ref; } constexpr auto &unwrap() noexcept { return Ref; } + LLVMErrorRef release() noexcept { return std::exchange(Ref, nullptr); } friend void swap(Error &LHS, Error &RHS) noexcept { using std::swap; swap(LHS.Ref, RHS.Ref); @@ -1819,7 +1814,8 @@ class PassBuilderOptions { LLVMPassBuilderOptionsSetMergeFunctions(Ref, MergeFunctions); } - Error runPasses(Module &M, const char *Passes, TargetMachine &TM) noexcept { + Error runPasses(Module &M, const char *Passes, + const TargetMachine &TM = nullptr) noexcept { return LLVMRunPasses(M.unwrap(), Passes, TM.unwrap(), Ref); } @@ -1954,6 +1950,84 @@ class Binary { LLVMBinaryRef Ref = nullptr; }; +class OrcThreadSafeContext { +public: + constexpr OrcThreadSafeContext(LLVMOrcThreadSafeContextRef R) noexcept + : Ref(R) {} + OrcThreadSafeContext(const OrcThreadSafeContext &) = delete; + OrcThreadSafeContext &operator=(const OrcThreadSafeContext &) = delete; + OrcThreadSafeContext(OrcThreadSafeContext &&B) noexcept + : OrcThreadSafeContext() { + swap(*this, B); + } + OrcThreadSafeContext &operator=(OrcThreadSafeContext &&B) noexcept { + swap(*this, B); + return *this; + } + + OrcThreadSafeContext() noexcept : Ref(LLVMOrcCreateNewThreadSafeContext()) {} + ~OrcThreadSafeContext() noexcept { LLVMOrcDisposeThreadSafeContext(Ref); } + + constexpr operator bool() const noexcept { return Ref != nullptr; } + constexpr auto &unwrap() const noexcept { return Ref; } + constexpr auto &unwrap() noexcept { return Ref; } + LLVMOrcThreadSafeContextRef release() noexcept { + return std::exchange(Ref, nullptr); + } + friend void swap(OrcThreadSafeContext &LHS, + OrcThreadSafeContext &RHS) noexcept { + using std::swap; + swap(LHS.Ref, RHS.Ref); + } + + Context getContext() noexcept { + return LLVMOrcThreadSafeContextGetContext(Ref); + } + +private: + LLVMOrcThreadSafeContextRef Ref = nullptr; +}; + +class OrcThreadSafeModule { +public: + constexpr OrcThreadSafeModule() noexcept = default; + constexpr OrcThreadSafeModule(LLVMOrcThreadSafeModuleRef R) noexcept + : Ref(R) {} + OrcThreadSafeModule(const OrcThreadSafeModule &) = delete; + OrcThreadSafeModule &operator=(const OrcThreadSafeModule &) = delete; + OrcThreadSafeModule(OrcThreadSafeModule &&B) noexcept + : OrcThreadSafeModule() { + swap(*this, B); + } + OrcThreadSafeModule &operator=(OrcThreadSafeModule &&B) noexcept { + swap(*this, B); + return *this; + } + + OrcThreadSafeModule(Module &&M, OrcThreadSafeContext &C) noexcept + : Ref(LLVMOrcCreateNewThreadSafeModule(M.release(), C.unwrap())) {} + ~OrcThreadSafeModule() noexcept { LLVMOrcDisposeThreadSafeModule(Ref); } + + constexpr operator bool() const noexcept { return Ref != nullptr; } + constexpr auto &unwrap() const noexcept { return Ref; } + constexpr auto &unwrap() noexcept { return Ref; } + LLVMOrcThreadSafeModuleRef release() noexcept { + return std::exchange(Ref, nullptr); + } + friend void swap(OrcThreadSafeModule &LHS, + OrcThreadSafeModule &RHS) noexcept { + using std::swap; + swap(LHS.Ref, RHS.Ref); + } + Error withModuleDo(LLVMOrcGenericIRModuleOperationFunction F, + void *Ctx) noexcept { + return LLVMOrcThreadSafeModuleWithModuleDo(Ref, F, Ctx); + } + +private: + LLVMOrcThreadSafeModuleRef Ref = nullptr; +}; + } // namespace WasmEdge::LLVM #include From 977dd26018b73bdaf1d58d2fca7fcd2437c08c95 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 1 Feb 2024 14:57:13 +0800 Subject: [PATCH 023/218] [JIT] Create interface class `Executable` to hold shared library, AOT section and JIT library in `Symbol` * Move `Wrapper` and `IntrinsticsTable` into `Executable * Split `SharedLibrary` into two class * Remove LDMgr * Add `loadExecutable` in `Loader` Signed-off-by: Shen-Ta Hsieh --- include/ast/module.h | 32 +------ include/ast/type.h | 14 +-- include/common/executable.h | 83 ++++++++++++++++ include/common/symbol.h | 17 ++-- include/executor/executor.h | 2 +- include/loader/aot_section.h | 93 ++++++++++++++++++ include/loader/ldmgr.h | 56 ----------- include/loader/loader.h | 19 ++-- include/loader/shared_library.h | 106 +++++++++++---------- lib/executor/engine/proxy.cpp | 4 +- lib/llvm/compiler.cpp | 58 +++++------ lib/loader/CMakeLists.txt | 2 +- lib/loader/aot_section.cpp | 164 ++++++++++++++++++++++++++++++++ lib/loader/ast/module.cpp | 105 ++++++++++---------- lib/loader/ldmgr.cpp | 53 ----------- lib/loader/loader.cpp | 9 +- lib/loader/shared_library.cpp | 163 +------------------------------ 17 files changed, 510 insertions(+), 470 deletions(-) create mode 100644 include/common/executable.h create mode 100644 include/loader/aot_section.h delete mode 100644 include/loader/ldmgr.h create mode 100644 lib/loader/aot_section.cpp delete mode 100644 lib/loader/ldmgr.cpp diff --git a/include/ast/module.h b/include/ast/module.h index 9661e25643b7..887e5f21fcac 100644 --- a/include/ast/module.h +++ b/include/ast/module.h @@ -66,37 +66,9 @@ class Module { const AOTSection &getAOTSection() const { return AOTSec; } AOTSection &getAOTSection() { return AOTSec; } - enum class Intrinsics : uint32_t { - kTrap, - kCall, - kCallIndirect, - kMemCopy, - kMemFill, - kMemGrow, - kMemSize, - kMemInit, - kDataDrop, - kTableGet, - kTableSet, - kTableCopy, - kTableFill, - kTableGrow, - kTableSize, - kTableInit, - kElemDrop, - kRefFunc, - kTableGetFuncSymbol, - kMemoryAtomicNotify, - kMemoryAtomicWait, - kCallRef, - kRefGetFuncSymbol, - kIntrinsicMax, - }; - using IntrinsicsTable = void * [uint32_t(Intrinsics::kIntrinsicMax)]; - /// Getter and setter of compiled symbol. const auto &getSymbol() const noexcept { return IntrSymbol; } - void setSymbol(Symbol S) noexcept { + void setSymbol(Symbol S) noexcept { IntrSymbol = std::move(S); } @@ -131,7 +103,7 @@ class Module { /// \name Data of AOT. /// @{ AOTSection AOTSec; - Symbol IntrSymbol; + Symbol IntrSymbol; /// @} /// \name Validated flag. diff --git a/include/ast/type.h b/include/ast/type.h index b9490e6776cb..663ff04a2cd1 100644 --- a/include/ast/type.h +++ b/include/ast/type.h @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #pragma once +#include "common/executable.h" #include "common/span.h" #include "common/symbol.h" #include "common/types.h" @@ -74,15 +75,12 @@ class Limit { /// AST FunctionType node. class FunctionType { public: - /// Function type wrapper for symbols. - using Wrapper = void(void *ExecCtx, void *Function, const ValVariant *Args, - ValVariant *Rets); - /// Constructors. FunctionType() = default; FunctionType(Span P, Span R) : ParamTypes(P.begin(), P.end()), ReturnTypes(R.begin(), R.end()) {} - FunctionType(Span P, Span R, Symbol S) + FunctionType(Span P, Span R, + Symbol S) : ParamTypes(P.begin(), P.end()), ReturnTypes(R.begin(), R.end()), WrapSymbol(std::move(S)) {} @@ -112,14 +110,16 @@ class FunctionType { /// Getter and setter of symbol. const auto &getSymbol() const noexcept { return WrapSymbol; } - void setSymbol(Symbol S) noexcept { WrapSymbol = std::move(S); } + void setSymbol(Symbol S) noexcept { + WrapSymbol = std::move(S); + } private: /// \name Data of FunctionType. /// @{ std::vector ParamTypes; std::vector ReturnTypes; - Symbol WrapSymbol; + Symbol WrapSymbol; /// @} }; diff --git a/include/common/executable.h b/include/common/executable.h new file mode 100644 index 000000000000..c03493c30d61 --- /dev/null +++ b/include/common/executable.h @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/common/executable.h - Executable Code definition ---------===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the Executable, which holds interface +/// to executable binary objects. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "common/defines.h" +#include "common/symbol.h" +#include "common/types.h" + +#include +#include +#include + +namespace WasmEdge { + +/// Holder class for library handle +class Executable : public std::enable_shared_from_this { + Executable(const Executable &) = delete; + Executable &operator=(const Executable &) = delete; + Executable(Executable &&) = delete; + Executable &operator=(Executable &&) = delete; + +public: + Executable() noexcept = default; + virtual ~Executable() noexcept = default; + + /// Function type wrapper for symbols. + using Wrapper = void(void *ExecCtx, void *Function, const ValVariant *Args, + ValVariant *Rets); + + enum class Intrinsics : uint32_t { + kTrap, + kCall, + kCallIndirect, + kMemCopy, + kMemFill, + kMemGrow, + kMemSize, + kMemInit, + kDataDrop, + kTableGet, + kTableSet, + kTableCopy, + kTableFill, + kTableGrow, + kTableSize, + kTableInit, + kElemDrop, + kRefFunc, + kTableGetFuncSymbol, + kMemoryAtomicNotify, + kMemoryAtomicWait, + kCallRef, + kRefGetFuncSymbol, + kIntrinsicMax, + }; + using IntrinsicsTable = void * [uint32_t(Intrinsics::kIntrinsicMax)]; + + virtual Symbol getIntrinsics() noexcept = 0; + + virtual std::vector> getTypes(size_t Size) noexcept = 0; + + virtual std::vector> getCodes(size_t Offset, + size_t Size) noexcept = 0; + +protected: + template Symbol createSymbol(T *Pointer) const noexcept { + return Symbol(shared_from_this(), Pointer); + } +}; + +} // namespace WasmEdge diff --git a/include/common/symbol.h b/include/common/symbol.h index 282333b56df9..9258cb1826d5 100644 --- a/include/common/symbol.h +++ b/include/common/symbol.h @@ -16,19 +16,16 @@ #include -namespace WasmEdge::Loader { -class SharedLibrary; -} - namespace WasmEdge { +class Executable; /// Holder class for library symbol template class Symbol { private: - friend class Loader::SharedLibrary; + friend class Executable; template friend class Symbol; - Symbol(std::shared_ptr H, T *S) noexcept + Symbol(std::shared_ptr H, T *S) noexcept : Library(std::move(H)), Pointer(S) {} public: @@ -57,16 +54,16 @@ template class Symbol { } private: - std::shared_ptr Library; + std::shared_ptr Library; T *Pointer = nullptr; }; template class Symbol { private: - friend class Loader::SharedLibrary; + friend class Executable; template friend class Symbol; - Symbol(std::shared_ptr H, T (*S)[]) noexcept + Symbol(std::shared_ptr H, T (*S)[]) noexcept : Library(std::move(H)), Pointer(*S) {} public: @@ -88,7 +85,7 @@ template class Symbol { } private: - std::shared_ptr Library; + std::shared_ptr Library; T *Pointer = nullptr; }; diff --git a/include/executor/executor.h b/include/executor/executor.h index ed7eed61e20a..dcceb2fa5db8 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -706,7 +706,7 @@ class Executor { template struct ProxyHelper; /// Callbacks for compiled modules - static const AST::Module::IntrinsicsTable Intrinsics; + static const Executable::IntrinsicsTable Intrinsics; private: template diff --git a/include/loader/aot_section.h b/include/loader/aot_section.h new file mode 100644 index 000000000000..b6666bf965f6 --- /dev/null +++ b/include/loader/aot_section.h @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/loader/aot_section.h - AOT Section definition ------------===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the AOTSection, which holds logics to +/// load from an AOTSection +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/section.h" +#include "common/executable.h" +#include "common/filesystem.h" +#include "system/winapi.h" + +#include +#include +#include + +namespace WasmEdge { +namespace Loader { + +/// Holder class for library handle +class AOTSection : public Executable { +public: + AOTSection() noexcept = default; + ~AOTSection() noexcept override { unload(); } + Expect load(const AST::AOTSection &AOTSec) noexcept; + void unload() noexcept; + + Symbol getIntrinsics() noexcept override { + if (Binary) { + return createSymbol( + getPointer(IntrinsicsAddress)); + } + return {}; + } + + std::vector> getTypes(size_t) noexcept override { + std::vector> Result; + if (Binary) { + Result.reserve(TypesAddress.size()); + for (const auto Address : TypesAddress) { + Result.push_back(createSymbol(getPointer(Address))); + } + } + return Result; + } + + std::vector> getCodes(size_t, size_t) noexcept override { + std::vector> Result; + if (Binary) { + Result.reserve(CodesAddress.size()); + for (const auto Address : CodesAddress) { + Result.push_back(createSymbol(getPointer(Address))); + } + } + return Result; + } + +private: + uintptr_t getOffset() const noexcept { + return reinterpret_cast(Binary); + } + + template T *getPointer(uint64_t Address) const noexcept { + return reinterpret_cast(getOffset() + Address); + } + + uint8_t *Binary = nullptr; + uint64_t BinarySize = 0; + uint64_t IntrinsicsAddress = 0; + std::vector TypesAddress; + std::vector CodesAddress; +#if WASMEDGE_OS_LINUX + void *EHFrameAddress = nullptr; +#elif WASMEDGE_OS_MACOS + uint8_t *EHFrameAddress = nullptr; + uint32_t EHFrameSize = 0; +#elif WASMEDGE_OS_WINDOWS + void *PDataAddress = nullptr; + uint32_t PDataSize = 0; +#endif +}; + +} // namespace Loader +} // namespace WasmEdge diff --git a/include/loader/ldmgr.h b/include/loader/ldmgr.h deleted file mode 100644 index 8787ab9978df..000000000000 --- a/include/loader/ldmgr.h +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2019-2022 Second State INC - -//===-- wasmedge/loader/ldmgr.h - Loadable Manager definition -------------===// -// -// Part of the WasmEdge Project. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the declaration of the LDMgr class, which controls flow -/// of Compiled Binary loading. -/// -//===----------------------------------------------------------------------===// -#pragma once - -#include "common/types.h" -#include "loader/shared_library.h" - -#include -#include -#include - -namespace WasmEdge { - -/// Loadable manager interface. -class LDMgr { -public: - LDMgr(const void *IT = nullptr) : Intrinsics(IT) {} - - /// Set the file path. - Expect setPath(const std::filesystem::path &FilePath); - - /// Read embedded Wasm binary. - Expect> getWasm(); - - /// Read wasmedge version. - Expect getVersion(); - - /// Get symbol. - template auto getSymbol(const char *Name) noexcept { - return Library->get(Name); - } - - /// Reset status. - void reset() noexcept { - Intrinsics = nullptr; - Library.reset(); - } - -private: - std::shared_ptr Library; - const void *Intrinsics; -}; - -} // namespace WasmEdge diff --git a/include/loader/loader.h b/include/loader/loader.h index dff8641ece1e..e5c68477c86f 100644 --- a/include/loader/loader.h +++ b/include/loader/loader.h @@ -18,8 +18,8 @@ #include "common/configure.h" #include "common/errinfo.h" #include "loader/filemgr.h" -#include "loader/ldmgr.h" #include "loader/serialize.h" +#include "loader/shared_library.h" #include #include @@ -126,8 +126,8 @@ NodeAttrFromAST() noexcept { class Loader { public: Loader(const Configure &Conf, - const AST::Module::IntrinsicsTable *IT = nullptr) noexcept - : Conf(Conf), Ser(Conf), LMgr(IT), IntrinsicsTable(IT) {} + const Executable::IntrinsicsTable *IT = nullptr) noexcept + : Conf(Conf), Ser(Conf), IntrinsicsTable(IT) {} ~Loader() noexcept = default; /// Load data from file path. @@ -160,10 +160,11 @@ class Loader { Expect> serializeModule(const AST::Module &Mod); /// Reset status. - void reset() noexcept { - FMgr.reset(); - LMgr.reset(); - } + void reset() noexcept { FMgr.reset(); } + + /// Setup Symbol from an Exetuable. + Expect loadExecutable(AST::Module &Mod, + std::shared_ptr Library); private: /// \name Helper functions to print error log when loading AST nodes @@ -201,7 +202,6 @@ class Loader { Expect loadModule(AST::Module &Mod); Expect loadModuleInBound(AST::Module &Mod, std::optional Bound); - Expect loadCompiled(AST::Module &Mod); /// @} /// \name Load AST section node helper functions @@ -416,8 +416,7 @@ class Loader { const Configure Conf; const Serializer Ser; FileMgr FMgr; - LDMgr LMgr; - const AST::Module::IntrinsicsTable *IntrinsicsTable; + const Executable::IntrinsicsTable *IntrinsicsTable; std::recursive_mutex Mutex; bool HasDataSection; diff --git a/include/loader/shared_library.h b/include/loader/shared_library.h index d9d756bd6568..d376a69c4da8 100644 --- a/include/loader/shared_library.h +++ b/include/loader/shared_library.h @@ -15,10 +15,8 @@ #pragma once #include "ast/section.h" -#include "common/defines.h" -#include "common/errcode.h" +#include "common/executable.h" #include "common/filesystem.h" -#include "common/symbol.h" #include "system/winapi.h" #include @@ -29,12 +27,7 @@ namespace WasmEdge { namespace Loader { /// Holder class for library handle -class SharedLibrary : public std::enable_shared_from_this { - SharedLibrary(const SharedLibrary &) = delete; - SharedLibrary &operator=(const SharedLibrary &) = delete; - SharedLibrary(SharedLibrary &&) = delete; - SharedLibrary &operator=(SharedLibrary &&) = delete; - +class SharedLibrary : public Executable { public: #if WASMEDGE_OS_WINDOWS using NativeHandle = winapi::HMODULE_; @@ -43,69 +36,78 @@ class SharedLibrary : public std::enable_shared_from_this { #endif SharedLibrary() noexcept = default; - ~SharedLibrary() noexcept { unload(); } + ~SharedLibrary() noexcept override { unload(); } Expect load(const std::filesystem::path &Path) noexcept; - Expect load(const AST::AOTSection &AOTSec) noexcept; void unload() noexcept; - template Symbol get(const char *Name) { - return Symbol(shared_from_this(), - reinterpret_cast(getSymbolAddr(Name))); + Symbol getIntrinsics() noexcept override { + return get("intrinsics"); } - uintptr_t getOffset() const noexcept; + std::vector> getTypes(size_t Size) noexcept override { + using namespace std::literals; + std::vector> Result; + Result.reserve(Size); + for (size_t I = 0; I < Size; ++I) { + // "t" prefix is for type helper function + const std::string Name = fmt::format("t{}"sv, I); + if (auto Symbol = get(Name.c_str())) { + Result.push_back(std::move(Symbol)); + } + } - template T *getPointer(uint64_t Address) const noexcept { - return reinterpret_cast(getOffset() + Address); + return Result; } - template Symbol getIntrinsics() noexcept { - if (Binary) { - return Symbol(shared_from_this(), getPointer(IntrinsicsAddress)); + std::vector> getCodes(size_t Offset, + size_t Size) noexcept override { + using namespace std::literals; + std::vector> Result; + Result.reserve(Size); + for (size_t I = 0; I < Size; ++I) { + // "f" prefix is for code function + const std::string Name = fmt::format("f{}"sv, I + Offset); + if (auto Symbol = get(Name.c_str())) { + Result.push_back(std::move(Symbol)); + } } - return {}; + + return Result; } - template std::vector> getTypes() noexcept { - std::vector> Result; - if (Binary) { - Result.reserve(TypesAddress.size()); - for (const auto Address : TypesAddress) { - Result.push_back(Symbol(shared_from_this(), getPointer(Address))); - } + /// Read embedded Wasm binary. + Expect> getWasm() noexcept { + const auto Size = get("wasm.size"); + if (unlikely(!Size)) { + spdlog::error(ErrCode::Value::IllegalGrammar); + return Unexpect(ErrCode::Value::IllegalGrammar); } - return Result; + const auto Code = get("wasm.code"); + if (unlikely(!Code)) { + spdlog::error(ErrCode::Value::IllegalGrammar); + return Unexpect(ErrCode::Value::IllegalGrammar); + } + + return std::vector(Code.get(), Code.get() + *Size); } - template std::vector> getCodes() noexcept { - std::vector> Result; - if (Binary) { - Result.reserve(CodesAddress.size()); - for (const auto Address : CodesAddress) { - Result.push_back(Symbol(shared_from_this(), getPointer(Address))); - } + /// Read wasmedge version. + Expect getVersion() noexcept { + const auto Version = get("version"); + if (unlikely(!Version)) { + spdlog::error(ErrCode::Value::IllegalGrammar); + return Unexpect(ErrCode::Value::IllegalGrammar); } - return Result; + return *Version; + } + + template Symbol get(const char *Name) { + return createSymbol(reinterpret_cast(getSymbolAddr(Name))); } private: void *getSymbolAddr(const char *Name) const noexcept; NativeHandle Handle{}; - - uint8_t *Binary = nullptr; - uint64_t BinarySize = 0; - uint64_t IntrinsicsAddress = 0; - std::vector TypesAddress; - std::vector CodesAddress; -#if WASMEDGE_OS_LINUX - void *EHFrameAddress = nullptr; -#elif WASMEDGE_OS_MACOS - uint8_t *EHFrameAddress = nullptr; - uint32_t EHFrameSize = 0; -#elif WASMEDGE_OS_WINDOWS - void *PDataAddress = nullptr; - uint32_t PDataSize = 0; -#endif }; } // namespace Loader diff --git a/lib/executor/engine/proxy.cpp b/lib/executor/engine/proxy.cpp index d2e4d0d401f6..35a3f750f031 100644 --- a/lib/executor/engine/proxy.cpp +++ b/lib/executor/engine/proxy.cpp @@ -41,14 +41,14 @@ struct Executor::ProxyHelper (Executor::*)(Runtime::StackManager &, #endif // Intrinsics table -const AST::Module::IntrinsicsTable Executor::Intrinsics = { +const Executable::IntrinsicsTable Executor::Intrinsics = { #if defined(_MSC_VER) && !defined(__clang__) #define ENTRY(NAME, FUNC) \ reinterpret_cast(&Executor::ProxyHelper< \ decltype(&Executor::FUNC)>::proxy<&Executor::FUNC>) #else #define ENTRY(NAME, FUNC) \ - [uint8_t(AST::Module::Intrinsics::NAME)] = reinterpret_cast( \ + [uint8_t(Executable::Intrinsics::NAME)] = reinterpret_cast( \ &Executor::ProxyHelper::proxy< \ &Executor::FUNC>) #endif diff --git a/lib/llvm/compiler.cpp b/lib/llvm/compiler.cpp index 60397ffdd499..e74e0b8c266c 100644 --- a/lib/llvm/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -251,7 +251,7 @@ struct LLVM::Compiler::CompileContext { ExecCtxPtrTy(ExecCtxTy.getPointerTo()), IntrinsicsTableTy(LLVM::Type::getArrayType( Int8PtrTy, - static_cast(AST::Module::Intrinsics::kIntrinsicMax))), + static_cast(Executable::Intrinsics::kIntrinsicMax))), IntrinsicsTablePtrTy(IntrinsicsTableTy.getPointerTo()), IntrinsicsTable(LLModule.addGlobal(IntrinsicsTablePtrTy, true, LLVMExternalLinkage, LLVM::Value(), @@ -314,7 +314,7 @@ struct LLVM::Compiler::CompileContext { LLVM::BasicBlock::create(LLContext, Trap.Fn, "entry")); auto FnTy = LLVM::Type::getFunctionType(VoidTy, {Int32Ty}); auto CallTrap = Builder.createCall( - getIntrinsic(Builder, AST::Module::Intrinsics::kTrap, FnTy), + getIntrinsic(Builder, Executable::Intrinsics::kTrap, FnTy), {Trap.Fn.getFirstParam()}); CallTrap.addCallSiteAttribute(NoReturn); Builder.createUnreachable(); @@ -363,7 +363,7 @@ struct LLVM::Compiler::CompileContext { return Builder.createExtractValue(ExecCtx, 6); } LLVM::FunctionCallee getIntrinsic(LLVM::Builder &Builder, - AST::Module::Intrinsics Index, + Executable::Intrinsics Index, LLVM::Type Ty) noexcept { const auto Value = static_cast(Index); auto PtrTy = Ty.getPointerTo(); @@ -816,7 +816,7 @@ class FunctionCompiler { break; case OpCode::Ref__func: stackPush(Builder.createCall( - Context.getIntrinsic(Builder, AST::Module::Intrinsics::kRefFunc, + Context.getIntrinsic(Builder, Executable::Intrinsics::kRefFunc, LLVM::Type::getFunctionType(Context.Int64x2Ty, {Context.Int32Ty}, false)), @@ -871,7 +871,7 @@ class FunctionCompiler { auto Idx = stackPop(); stackPush(Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableGet, + Builder, Executable::Intrinsics::kTableGet, LLVM::Type::getFunctionType(Context.Int64x2Ty, {Context.Int32Ty, Context.Int32Ty}, false)), @@ -883,7 +883,7 @@ class FunctionCompiler { auto Idx = stackPop(); Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableSet, + Builder, Executable::Intrinsics::kTableSet, LLVM::Type::getFunctionType( Context.Int64Ty, {Context.Int32Ty, Context.Int32Ty, Context.Int64x2Ty}, @@ -897,7 +897,7 @@ class FunctionCompiler { auto Dst = stackPop(); Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableInit, + Builder, Executable::Intrinsics::kTableInit, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, @@ -909,7 +909,7 @@ class FunctionCompiler { } case OpCode::Elem__drop: { Builder.createCall( - Context.getIntrinsic(Builder, AST::Module::Intrinsics::kElemDrop, + Context.getIntrinsic(Builder, Executable::Intrinsics::kElemDrop, LLVM::Type::getFunctionType( Context.VoidTy, {Context.Int32Ty}, false)), {LLContext.getInt32(Instr.getTargetIndex())}); @@ -921,7 +921,7 @@ class FunctionCompiler { auto Dst = stackPop(); Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableCopy, + Builder, Executable::Intrinsics::kTableCopy, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, @@ -936,7 +936,7 @@ class FunctionCompiler { auto Val = stackPop(); stackPush(Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableGrow, + Builder, Executable::Intrinsics::kTableGrow, LLVM::Type::getFunctionType( Context.Int32Ty, {Context.Int32Ty, Context.Int64x2Ty, Context.Int32Ty}, @@ -946,7 +946,7 @@ class FunctionCompiler { } case OpCode::Table__size: { stackPush(Builder.createCall( - Context.getIntrinsic(Builder, AST::Module::Intrinsics::kTableSize, + Context.getIntrinsic(Builder, Executable::Intrinsics::kTableSize, LLVM::Type::getFunctionType(Context.Int32Ty, {Context.Int32Ty}, false)), @@ -958,7 +958,7 @@ class FunctionCompiler { auto Val = stackPop(); auto Off = stackPop(); Builder.createCall( - Context.getIntrinsic(Builder, AST::Module::Intrinsics::kTableFill, + Context.getIntrinsic(Builder, Executable::Intrinsics::kTableFill, LLVM::Type::getFunctionType( Context.Int32Ty, {Context.Int32Ty, Context.Int32Ty, @@ -1066,7 +1066,7 @@ class FunctionCompiler { break; case OpCode::Memory__size: stackPush(Builder.createCall( - Context.getIntrinsic(Builder, AST::Module::Intrinsics::kMemSize, + Context.getIntrinsic(Builder, Executable::Intrinsics::kMemSize, LLVM::Type::getFunctionType(Context.Int32Ty, {Context.Int32Ty}, false)), @@ -1076,7 +1076,7 @@ class FunctionCompiler { auto Diff = stackPop(); stackPush(Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kMemGrow, + Builder, Executable::Intrinsics::kMemGrow, LLVM::Type::getFunctionType(Context.Int32Ty, {Context.Int32Ty, Context.Int32Ty}, false)), @@ -1089,7 +1089,7 @@ class FunctionCompiler { auto Dst = stackPop(); Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kMemInit, + Builder, Executable::Intrinsics::kMemInit, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, @@ -1101,7 +1101,7 @@ class FunctionCompiler { } case OpCode::Data__drop: { Builder.createCall( - Context.getIntrinsic(Builder, AST::Module::Intrinsics::kDataDrop, + Context.getIntrinsic(Builder, Executable::Intrinsics::kDataDrop, LLVM::Type::getFunctionType( Context.VoidTy, {Context.Int32Ty}, false)), {LLContext.getInt32(Instr.getTargetIndex())}); @@ -1113,7 +1113,7 @@ class FunctionCompiler { auto Dst = stackPop(); Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kMemCopy, + Builder, Executable::Intrinsics::kMemCopy, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, @@ -1129,7 +1129,7 @@ class FunctionCompiler { auto Off = stackPop(); Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kMemFill, + Builder, Executable::Intrinsics::kMemFill, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int8Ty, Context.Int32Ty}, @@ -3282,7 +3282,7 @@ class FunctionCompiler { stackPush(Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kMemoryAtomicNotify, + Builder, Executable::Intrinsics::kMemoryAtomicNotify, LLVM::Type::getFunctionType( Context.Int32Ty, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty}, false)), @@ -3301,7 +3301,7 @@ class FunctionCompiler { stackPush(Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kMemoryAtomicWait, + Builder, Executable::Intrinsics::kMemoryAtomicWait, LLVM::Type::getFunctionType(Context.Int32Ty, {Context.Int32Ty, Context.Int32Ty, Context.Int64Ty, Context.Int64Ty, @@ -3556,7 +3556,7 @@ class FunctionCompiler { { auto FPtr = Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableGetFuncSymbol, + Builder, Executable::Intrinsics::kTableGetFuncSymbol, LLVM::Type::getFunctionType( FTy.getPointerTo(), {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty}, false)), @@ -3615,7 +3615,7 @@ class FunctionCompiler { Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kCallIndirect, + Builder, Executable::Intrinsics::kCallIndirect, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, Context.Int8PtrTy, @@ -3696,7 +3696,7 @@ class FunctionCompiler { { auto FPtr = Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kTableGetFuncSymbol, + Builder, Executable::Intrinsics::kTableGetFuncSymbol, LLVM::Type::getFunctionType( FTy.getPointerTo(), {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty}, false)), @@ -3749,7 +3749,7 @@ class FunctionCompiler { Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kCallIndirect, + Builder, Executable::Intrinsics::kCallIndirect, LLVM::Type::getFunctionType(Context.VoidTy, {Context.Int32Ty, Context.Int32Ty, Context.Int32Ty, Context.Int8PtrTy, @@ -3811,7 +3811,7 @@ class FunctionCompiler { { auto FPtr = Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kRefGetFuncSymbol, + Builder, Executable::Intrinsics::kRefGetFuncSymbol, LLVM::Type::getFunctionType(FTy.getPointerTo(), {Context.Int64x2Ty}, false)), {Ref}); @@ -3868,7 +3868,7 @@ class FunctionCompiler { Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kCallRef, + Builder, Executable::Intrinsics::kCallRef, LLVM::Type::getFunctionType( Context.VoidTy, {Context.Int64x2Ty, Context.Int8PtrTy, Context.Int8PtrTy}, @@ -3932,7 +3932,7 @@ class FunctionCompiler { { auto FPtr = Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kRefGetFuncSymbol, + Builder, Executable::Intrinsics::kRefGetFuncSymbol, LLVM::Type::getFunctionType(FTy.getPointerTo(), {Context.Int64x2Ty}, false)), {Ref}); @@ -3983,7 +3983,7 @@ class FunctionCompiler { Builder.createCall( Context.getIntrinsic( - Builder, AST::Module::Intrinsics::kCallRef, + Builder, Executable::Intrinsics::kCallRef, LLVM::Type::getFunctionType( Context.VoidTy, {Context.Int64x2Ty, Context.Int8PtrTy, Context.Int8PtrTy}, @@ -5325,7 +5325,7 @@ void Compiler::compile(const AST::ImportSection &ImportSec) noexcept { Builder.createCall( Context->getIntrinsic( - Builder, AST::Module::Intrinsics::kCall, + Builder, Executable::Intrinsics::kCall, LLVM::Type::getFunctionType( Context->VoidTy, {Context->Int32Ty, Context->Int8PtrTy, Context->Int8PtrTy}, diff --git a/lib/loader/CMakeLists.txt b/lib/loader/CMakeLists.txt index c763ae34d3ae..d396a962f8ba 100644 --- a/lib/loader/CMakeLists.txt +++ b/lib/loader/CMakeLists.txt @@ -3,8 +3,8 @@ wasmedge_add_library(wasmedgeLoaderFileMgr filemgr.cpp - ldmgr.cpp shared_library.cpp + aot_section.cpp ) target_link_libraries(wasmedgeLoaderFileMgr diff --git a/lib/loader/aot_section.cpp b/lib/loader/aot_section.cpp new file mode 100644 index 000000000000..39f7f32571d7 --- /dev/null +++ b/lib/loader/aot_section.cpp @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +#include "loader/aot_section.h" +#include "common/log.h" +#include "system/allocator.h" + +#if WASMEDGE_OS_LINUX || WASMEDGE_OS_MACOS +extern "C" { +extern void __register_frame(void *); +extern void __deregister_frame(void *); +} +#endif + +namespace { +inline constexpr uint64_t roundDownPageBoundary(const uint64_t Value) { +// ARM64 Mac has a special page size +#if WASMEDGE_OS_MACOS && defined(__aarch64__) + return Value & ~UINT64_C(16383); +#else + return Value & ~UINT64_C(4095); +#endif +} +inline constexpr uint64_t roundUpPageBoundary(const uint64_t Value) { +// ARM64 Mac has a special page size +#if WASMEDGE_OS_MACOS && defined(__aarch64__) + return roundDownPageBoundary(Value + UINT64_C(16383)); +#else + return roundDownPageBoundary(Value + UINT64_C(4095)); +#endif +} +} // namespace + +namespace WasmEdge::Loader { + +Expect AOTSection::load(const AST::AOTSection &AOTSec) noexcept { + BinarySize = 0; + for (const auto &Section : AOTSec.getSections()) { + const auto Offset = std::get<1>(Section); + const auto Size = std::get<2>(Section); + BinarySize = std::max(BinarySize, Offset + Size); + } + BinarySize = roundUpPageBoundary(BinarySize); + + Binary = Allocator::allocate_chunk(BinarySize); + if (unlikely(!Binary)) { + spdlog::error(ErrCode::Value::MemoryOutOfBounds); + return Unexpect(ErrCode::Value::MemoryOutOfBounds); + } + + std::vector> ExecutableRanges; + for (const auto &Section : AOTSec.getSections()) { + const auto Offset = std::get<1>(Section); + const auto Size = std::get<2>(Section); + const auto &Content = std::get<3>(Section); + if (Size > BinarySize || Offset > BinarySize || + Offset + Size > BinarySize || Content.size() > Size) { + return Unexpect(ErrCode::Value::IntegerTooLarge); + } + std::copy(Content.begin(), Content.end(), Binary + Offset); + switch (std::get<0>(Section)) { + case 1: { // Text + const auto O = roundDownPageBoundary(Offset); + const auto S = roundUpPageBoundary(Size + (Offset - O)); + ExecutableRanges.emplace_back(Binary + O, S); + break; + } + case 2: // Data + break; + case 3: // BSS + break; +#if WASMEDGE_OS_LINUX + case 4: // EHFrame + EHFrameAddress = reinterpret_cast(Binary + Offset); + break; +#elif WASMEDGE_OS_MACOS + case 4: // EHFrame + EHFrameAddress = reinterpret_cast(Binary + Offset); + EHFrameSize = Size; + break; +#elif WASMEDGE_OS_WINDOWS + case 4: // PData + PDataAddress = reinterpret_cast(Binary + Offset); + PDataSize = + static_cast(Size / sizeof(winapi::RUNTIME_FUNCTION_)); + break; +#endif + default: + return Unexpect(ErrCode::Value::IntegerTooLarge); + } + } + + for (const auto &[Pointer, Size] : ExecutableRanges) { + if (!Allocator::set_chunk_executable(Pointer, Size)) { + spdlog::error(ErrCode::Value::MemoryOutOfBounds); + spdlog::error(" set_chunk_executable failed:{}", std::strerror(errno)); + return Unexpect(ErrCode::Value::MemoryOutOfBounds); + } + } + + IntrinsicsAddress = AOTSec.getIntrinsicsAddress(); + TypesAddress = AOTSec.getTypesAddress(); + CodesAddress = AOTSec.getCodesAddress(); + +#if WASMEDGE_OS_LINUX + if (EHFrameAddress) { + __register_frame(EHFrameAddress); + } +#elif WASMEDGE_OS_MACOS + if (EHFrameAddress) { + auto Iter = EHFrameAddress; + const auto End = EHFrameAddress + EHFrameSize - 4; + + while (Iter < End) { + if (Iter != EHFrameAddress) { + __register_frame(Iter); + } + const uint32_t Length = *reinterpret_cast(Iter); + Iter += Length + 4; + } + } +#elif WASMEDGE_OS_WINDOWS + if (PDataSize != 0) { + winapi::RtlAddFunctionTable( + static_cast(PDataAddress), PDataSize, + reinterpret_cast(Binary)); + } +#endif + + return {}; +} + +void AOTSection::unload() noexcept { + if (Binary) { +#if WASMEDGE_OS_LINUX + if (EHFrameAddress) { + __deregister_frame(EHFrameAddress); + } +#elif WASMEDGE_OS_MACOS + if (EHFrameAddress) { + auto Iter = EHFrameAddress; + const auto End = EHFrameAddress + EHFrameSize - 4; + + while (Iter < End) { + if (Iter != EHFrameAddress) { + __deregister_frame(Iter); + } + const uint32_t Length = *reinterpret_cast(Iter); + Iter += Length + 4; + } + } +#elif WASMEDGE_OS_WINDOWS + if (PDataSize != 0) { + winapi::RtlDeleteFunctionTable( + static_cast(PDataAddress)); + } +#endif + Allocator::set_chunk_readable_writable(Binary, BinarySize); + Allocator::release_chunk(Binary, BinarySize); + Binary = nullptr; + } +} + +} // namespace WasmEdge::Loader diff --git a/lib/loader/ast/module.cpp b/lib/loader/ast/module.cpp index 2597b105dbb1..871743e59669 100644 --- a/lib/loader/ast/module.cpp +++ b/lib/loader/ast/module.cpp @@ -1,7 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC +#include "loader/aot_section.h" #include "loader/loader.h" +#include "loader/shared_library.h" #include #include @@ -181,16 +183,10 @@ Expect Loader::loadModule(AST::Module &Mod) { return loadModuleInBound(Mod, std::nullopt); } -// Load compiled function from loadable manager. See "include/loader/loader.h". -Expect Loader::loadCompiled(AST::Module &Mod) { +// Setup symbols from loaded binary. See "include/loader/loader.h". +Expect Loader::loadExecutable(AST::Module &Mod, + std::shared_ptr Exec) { auto &FuncTypes = Mod.getTypeSection().getContent(); - for (size_t I = 0; I < FuncTypes.size(); ++I) { - const std::string Name = "t" + std::to_string(I); - if (auto Symbol = - LMgr.getSymbol(Name.c_str())) { - FuncTypes[I].setSymbol(std::move(Symbol)); - } - } size_t Offset = 0; for (const auto &ImpDesc : Mod.getImportSection().getContent()) { if (ImpDesc.getExternalType() == ExternalType::Function) { @@ -198,69 +194,70 @@ Expect Loader::loadCompiled(AST::Module &Mod) { } } auto &CodeSegs = Mod.getCodeSection().getContent(); - for (size_t I = 0; I < CodeSegs.size(); ++I) { - const std::string Name = "f" + std::to_string(I + Offset); - if (auto Symbol = LMgr.getSymbol(Name.c_str())) { - CodeSegs[I].setSymbol(std::move(Symbol)); - } - } - return {}; -} - -Expect Loader::loadUniversalWASM(AST::Module &Mod) { - bool FallBackInterpreter = false; - auto Library = std::make_shared(); - if (auto Res = Library->load(Mod.getAOTSection()); unlikely(!Res)) { - spdlog::error(" AOT section -- library load failed:{} , use " - "interpreter mode instead.", - Res.error()); - FallBackInterpreter = true; - } // Check the symbols. - auto FuncTypeSymbols = Library->getTypes(); - auto CodeSymbols = Library->getCodes(); - auto IntrinsicsSymbol = - Library->getIntrinsics(); - auto &FuncTypes = Mod.getTypeSection().getContent(); - auto &CodeSegs = Mod.getCodeSection().getContent(); - if (!FallBackInterpreter && - unlikely(FuncTypeSymbols.size() != FuncTypes.size())) { + auto FuncTypeSymbols = Exec->getTypes(FuncTypes.size()); + auto CodeSymbols = Exec->getCodes(Offset, CodeSegs.size()); + auto IntrinsicsSymbol = Exec->getIntrinsics(); + if (unlikely(FuncTypeSymbols.size() != FuncTypes.size())) { spdlog::error(" AOT section -- number of types not matching:{} {}, " "use interpreter mode instead.", FuncTypeSymbols.size(), FuncTypes.size()); - FallBackInterpreter = true; + return Unexpect(ErrCode::Value::IllegalGrammar); } - if (!FallBackInterpreter && unlikely(CodeSymbols.size() != CodeSegs.size())) { + if (unlikely(CodeSymbols.size() != CodeSegs.size())) { spdlog::error(" AOT section -- number of codes not matching:{} {}, " "use interpreter mode instead.", CodeSymbols.size(), CodeSegs.size()); - FallBackInterpreter = true; + return Unexpect(ErrCode::Value::IllegalGrammar); } - if (!FallBackInterpreter && unlikely(!IntrinsicsSymbol)) { + if (unlikely(!IntrinsicsSymbol)) { spdlog::error(" AOT section -- intrinsics table symbol not found, use " "interpreter mode instead."); - FallBackInterpreter = true; + return Unexpect(ErrCode::Value::IllegalGrammar); } // Set the symbols into the module. - if (!FallBackInterpreter) { - for (size_t I = 0; I < FuncTypes.size(); ++I) { - FuncTypes[I].setSymbol(std::move(FuncTypeSymbols[I])); - } - for (size_t I = 0; I < CodeSegs.size(); ++I) { - CodeSegs[I].setSymbol(std::move(CodeSymbols[I])); + for (size_t I = 0; I < FuncTypes.size(); ++I) { + FuncTypes[I].setSymbol(std::move(FuncTypeSymbols[I])); + } + for (size_t I = 0; I < CodeSegs.size(); ++I) { + CodeSegs[I].setSymbol(std::move(CodeSymbols[I])); + } + Mod.setSymbol(std::move(IntrinsicsSymbol)); + if (!Conf.getRuntimeConfigure().isForceInterpreter()) { + // If the configure is set to force interpreter mode, not to set the + // symbol. + if (auto &Symbol = Mod.getSymbol()) { + *Symbol = IntrinsicsTable; } - Mod.setSymbol(std::move(IntrinsicsSymbol)); - } else { - // Fallback to the interpreter mode case: Re-read the code section. - WASMType = InputType::WASM; - FMgr.seek(Mod.getCodeSection().getStartOffset()); - if (auto Res = loadSection(Mod.getCodeSection()); !Res) { - spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Module)); - return Unexpect(Res); + } + + return {}; +} + +Expect Loader::loadUniversalWASM(AST::Module &Mod) { + if (!Conf.getRuntimeConfigure().isForceInterpreter()) { + auto Exec = std::make_shared(); + if (auto Res = Exec->load(Mod.getAOTSection()); unlikely(!Res)) { + spdlog::error(" AOT section -- library load failed:{} , use " + "interpreter mode instead.", + Res.error()); + } else { + if (loadExecutable(Mod, Exec)) { + return {}; + } } } + + // Fallback to the interpreter mode case: Re-read the code section. + WASMType = InputType::WASM; + FMgr.seek(Mod.getCodeSection().getStartOffset()); + if (auto Res = loadSection(Mod.getCodeSection()); !Res) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Module)); + return Unexpect(Res); + } + return {}; } diff --git a/lib/loader/ldmgr.cpp b/lib/loader/ldmgr.cpp deleted file mode 100644 index 85f817f33748..000000000000 --- a/lib/loader/ldmgr.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2019-2022 Second State INC - -#include "loader/ldmgr.h" - -#include "common/log.h" -#include - -namespace WasmEdge { - -// Set path to loadable manager. See "include/loader/ldmgr.h". -Expect LDMgr::setPath(const std::filesystem::path &FilePath) { - Library = std::make_shared(); - if (auto Res = Library->load(FilePath); unlikely(!Res)) { - return Unexpect(Res); - } - - const auto IntrinsicsTable = getSymbol("intrinsics"); - if (IntrinsicsTable) { - if (unlikely(!Intrinsics)) { - spdlog::error(ErrCode::Value::IntrinsicsTableNotFound); - return Unexpect(ErrCode::Value::IntrinsicsTableNotFound); - } - *IntrinsicsTable = Intrinsics; - } - return {}; -} - -Expect> LDMgr::getWasm() { - const auto Size = getSymbol("wasm.size"); - if (unlikely(!Size)) { - spdlog::error(ErrCode::Value::IllegalGrammar); - return Unexpect(ErrCode::Value::IllegalGrammar); - } - const auto Code = getSymbol("wasm.code"); - if (unlikely(!Code)) { - spdlog::error(ErrCode::Value::IllegalGrammar); - return Unexpect(ErrCode::Value::IllegalGrammar); - } - - return std::vector(Code.get(), Code.get() + *Size); -} - -Expect LDMgr::getVersion() { - const auto Version = getSymbol("version"); - if (unlikely(!Version)) { - spdlog::error(ErrCode::Value::IllegalGrammar); - return Unexpect(ErrCode::Value::IllegalGrammar); - } - return *Version; -} - -} // namespace WasmEdge diff --git a/lib/loader/loader.cpp b/lib/loader/loader.cpp index 15963dd10583..4e3a5022092a 100644 --- a/lib/loader/loader.cpp +++ b/lib/loader/loader.cpp @@ -82,11 +82,12 @@ Loader::parseWasmUnit(const std::filesystem::path &FilePath) { // AOT compiled shared-library-WASM cases. Use ldmgr to load the module. WASMType = InputType::SharedLibrary; FMgr.reset(); - if (auto Res = LMgr.setPath(FilePath); !Res) { + std::shared_ptr Library = std::make_shared(); + if (auto Res = Library->load(FilePath); !Res) { spdlog::error(ErrInfo::InfoFile(FilePath)); return Unexpect(Res); } - if (auto Res = LMgr.getVersion()) { + if (auto Res = Library->getVersion()) { if (*Res != AOT::kBinaryVersion) { spdlog::error(ErrInfo::InfoMismatch(AOT::kBinaryVersion, *Res)); spdlog::error(ErrInfo::InfoFile(FilePath)); @@ -98,7 +99,7 @@ Loader::parseWasmUnit(const std::filesystem::path &FilePath) { } std::unique_ptr Mod; - if (auto Code = LMgr.getWasm()) { + if (auto Code = Library->getWasm()) { // Set the binary and load module. // Not to use parseModule() here to keep the `WASMType` value. if (auto Res = FMgr.setCode(*Code); !Res) { @@ -120,7 +121,7 @@ Loader::parseWasmUnit(const std::filesystem::path &FilePath) { if (!Conf.getRuntimeConfigure().isForceInterpreter()) { // If the configure is set to force interpreter mode, not to load the AOT // related data. - if (auto Res = loadCompiled(*Mod); unlikely(!Res)) { + if (auto Res = loadExecutable(*Mod, Library); unlikely(!Res)) { spdlog::error(ErrInfo::InfoFile(FilePath)); return Unexpect(Res); } diff --git a/lib/loader/shared_library.cpp b/lib/loader/shared_library.cpp index 4de5e08643c5..8383d9a205f4 100644 --- a/lib/loader/shared_library.cpp +++ b/lib/loader/shared_library.cpp @@ -2,9 +2,7 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #include "loader/shared_library.h" - #include "common/log.h" -#include "system/allocator.h" #include #include @@ -21,34 +19,7 @@ #error Unsupported os! #endif -#if WASMEDGE_OS_LINUX || WASMEDGE_OS_MACOS -extern "C" { -extern void __register_frame(void *); -extern void __deregister_frame(void *); -} -#endif - -namespace { -inline constexpr uint64_t roundDownPageBoundary(const uint64_t Value) { -// ARM64 Mac has a special page size -#if WASMEDGE_OS_MACOS && defined(__aarch64__) - return Value & ~UINT64_C(16383); -#else - return Value & ~UINT64_C(4095); -#endif -} -inline constexpr uint64_t roundUpPageBoundary(const uint64_t Value) { -// ARM64 Mac has a special page size -#if WASMEDGE_OS_MACOS && defined(__aarch64__) - return roundDownPageBoundary(Value + UINT64_C(16383)); -#else - return roundDownPageBoundary(Value + UINT64_C(4095)); -#endif -} -} // namespace - -namespace WasmEdge { -namespace Loader { +namespace WasmEdge::Loader { // Open so file. See "include/loader/shared_library.h". Expect SharedLibrary::load(const std::filesystem::path &Path) noexcept { @@ -83,132 +54,7 @@ Expect SharedLibrary::load(const std::filesystem::path &Path) noexcept { return {}; } -Expect SharedLibrary::load(const AST::AOTSection &AOTSec) noexcept { - BinarySize = 0; - for (const auto &Section : AOTSec.getSections()) { - const auto Offset = std::get<1>(Section); - const auto Size = std::get<2>(Section); - BinarySize = std::max(BinarySize, Offset + Size); - } - BinarySize = roundUpPageBoundary(BinarySize); - - Binary = Allocator::allocate_chunk(BinarySize); - if (unlikely(!Binary)) { - spdlog::error(ErrCode::Value::MemoryOutOfBounds); - return Unexpect(ErrCode::Value::MemoryOutOfBounds); - } - - std::vector> ExecutableRanges; - for (const auto &Section : AOTSec.getSections()) { - const auto Offset = std::get<1>(Section); - const auto Size = std::get<2>(Section); - const auto &Content = std::get<3>(Section); - if (Size > BinarySize || Offset > BinarySize || - Offset + Size > BinarySize || Content.size() > Size) { - return Unexpect(ErrCode::Value::IntegerTooLarge); - } - std::copy(Content.begin(), Content.end(), Binary + Offset); - switch (std::get<0>(Section)) { - case 1: { // Text - const auto O = roundDownPageBoundary(Offset); - const auto S = roundUpPageBoundary(Size + (Offset - O)); - ExecutableRanges.emplace_back(Binary + O, S); - break; - } - case 2: // Data - break; - case 3: // BSS - break; -#if WASMEDGE_OS_LINUX - case 4: // EHFrame - EHFrameAddress = reinterpret_cast(Binary + Offset); - break; -#elif WASMEDGE_OS_MACOS - case 4: // EHFrame - EHFrameAddress = reinterpret_cast(Binary + Offset); - EHFrameSize = Size; - break; -#elif WASMEDGE_OS_WINDOWS - case 4: // PData - PDataAddress = reinterpret_cast(Binary + Offset); - PDataSize = - static_cast(Size / sizeof(winapi::RUNTIME_FUNCTION_)); - break; -#endif - default: - return Unexpect(ErrCode::Value::IntegerTooLarge); - } - } - - for (const auto &[Pointer, Size] : ExecutableRanges) { - if (!Allocator::set_chunk_executable(Pointer, Size)) { - spdlog::error(ErrCode::Value::MemoryOutOfBounds); - spdlog::error(" set_chunk_executable failed:{}", std::strerror(errno)); - return Unexpect(ErrCode::Value::MemoryOutOfBounds); - } - } - - IntrinsicsAddress = AOTSec.getIntrinsicsAddress(); - TypesAddress = AOTSec.getTypesAddress(); - CodesAddress = AOTSec.getCodesAddress(); - -#if WASMEDGE_OS_LINUX - if (EHFrameAddress) { - __register_frame(EHFrameAddress); - } -#elif WASMEDGE_OS_MACOS - if (EHFrameAddress) { - auto Iter = EHFrameAddress; - const auto End = EHFrameAddress + EHFrameSize - 4; - - while (Iter < End) { - if (Iter != EHFrameAddress) { - __register_frame(Iter); - } - const uint32_t Length = *reinterpret_cast(Iter); - Iter += Length + 4; - } - } -#elif WASMEDGE_OS_WINDOWS - if (PDataSize != 0) { - winapi::RtlAddFunctionTable( - static_cast(PDataAddress), PDataSize, - reinterpret_cast(Binary)); - } -#endif - - return {}; -} - void SharedLibrary::unload() noexcept { - if (Binary) { -#if WASMEDGE_OS_LINUX - if (EHFrameAddress) { - __deregister_frame(EHFrameAddress); - } -#elif WASMEDGE_OS_MACOS - if (EHFrameAddress) { - auto Iter = EHFrameAddress; - const auto End = EHFrameAddress + EHFrameSize - 4; - - while (Iter < End) { - if (Iter != EHFrameAddress) { - __deregister_frame(Iter); - } - const uint32_t Length = *reinterpret_cast(Iter); - Iter += Length + 4; - } - } -#elif WASMEDGE_OS_WINDOWS - if (PDataSize != 0) { - winapi::RtlDeleteFunctionTable( - static_cast(PDataAddress)); - } -#endif - Allocator::set_chunk_readable_writable(Binary, BinarySize); - Allocator::release_chunk(Binary, BinarySize); - Binary = nullptr; - } if (Handle) { #if WASMEDGE_OS_WINDOWS winapi::FreeLibrary(Handle); @@ -230,9 +76,4 @@ void *SharedLibrary::getSymbolAddr(const char *Name) const noexcept { #endif } -uintptr_t SharedLibrary::getOffset() const noexcept { - return reinterpret_cast(Binary); -} - -} // namespace Loader -} // namespace WasmEdge +} // namespace WasmEdge::Loader From eb13b4fa0636bb4bfa591bf8e44e8953988f1d17 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 1 Feb 2024 15:03:14 +0800 Subject: [PATCH 024/218] [JIT] Add LLVM JIT Support * Add `LLVM::JITLibrary` * Add new command line option for enabling JIT Signed-off-by: Shen-Ta Hsieh --- include/common/configure.h | 10 ++ include/driver/tool.h | 4 + include/llvm/jit.h | 50 ++++++++++ lib/driver/runtimeTool.cpp | 5 + lib/llvm/CMakeLists.txt | 2 + lib/llvm/jit.cpp | 93 ++++++++++++++++++ lib/llvm/llvm.h | 191 +++++++++++++++++++++++++++++++++++++ lib/vm/CMakeLists.txt | 7 ++ lib/vm/vm.cpp | 22 +++++ 9 files changed, 384 insertions(+) create mode 100644 include/llvm/jit.h create mode 100644 lib/llvm/jit.cpp diff --git a/include/common/configure.h b/include/common/configure.h index add57945b5c2..2ba9a5e6c683 100644 --- a/include/common/configure.h +++ b/include/common/configure.h @@ -114,6 +114,7 @@ class RuntimeConfigure { RuntimeConfigure() noexcept = default; RuntimeConfigure(const RuntimeConfigure &RHS) noexcept : MaxMemPage(RHS.MaxMemPage.load(std::memory_order_relaxed)), + EnableJIT(RHS.EnableJIT.load(std::memory_order_relaxed)), ForceInterpreter(RHS.ForceInterpreter.load(std::memory_order_relaxed)), AllowAFUNIX(RHS.AllowAFUNIX.load(std::memory_order_relaxed)) {} @@ -125,6 +126,14 @@ class RuntimeConfigure { return MaxMemPage.load(std::memory_order_relaxed); } + void setEnableJIT(bool IsEnableJIT) noexcept { + EnableJIT.store(IsEnableJIT, std::memory_order_relaxed); + } + + bool isEnableJIT() const noexcept { + return EnableJIT.load(std::memory_order_relaxed); + } + void setForceInterpreter(bool IsForceInterpreter) noexcept { ForceInterpreter.store(IsForceInterpreter, std::memory_order_relaxed); } @@ -143,6 +152,7 @@ class RuntimeConfigure { private: std::atomic MaxMemPage = 65536; + std::atomic EnableJIT = false; std::atomic ForceInterpreter = false; std::atomic AllowAFUNIX = false; }; diff --git a/include/driver/tool.h b/include/driver/tool.h index 63cafb655908..38cf04e6f877 100644 --- a/include/driver/tool.h +++ b/include/driver/tool.h @@ -73,6 +73,8 @@ struct DriverToolOptions { "Enable generating code for counting time during execution."sv)), ConfEnableAllStatistics(PO::Description( "Enable generating code for all statistics options include instruction counting, gas measuring, and execution time"sv)), + ConfEnableJIT( + PO::Description("Enable Just-In-Time compiler for running WASM"sv)), ConfForceInterpreter( PO::Description("Forcibly run WASM in interpreter mode."sv)), TimeLim( @@ -114,6 +116,7 @@ struct DriverToolOptions { PO::Option ConfEnableGasMeasuring; PO::Option ConfEnableTimeMeasuring; PO::Option ConfEnableAllStatistics; + PO::Option ConfEnableJIT; PO::Option ConfForceInterpreter; PO::Option TimeLim; PO::List GasLim; @@ -131,6 +134,7 @@ struct DriverToolOptions { .add_option("enable-gas-measuring"sv, ConfEnableGasMeasuring) .add_option("enable-time-measuring"sv, ConfEnableTimeMeasuring) .add_option("enable-all-statistics"sv, ConfEnableAllStatistics) + .add_option("enable-jit"sv, ConfEnableJIT) .add_option("force-interpreter"sv, ConfForceInterpreter) .add_option("disable-import-export-mut-globals"sv, PropMutGlobals) .add_option("disable-non-trap-float-to-int"sv, PropNonTrapF2IConvs) diff --git a/include/llvm/jit.h b/include/llvm/jit.h new file mode 100644 index 000000000000..78e3c5ec9bc6 --- /dev/null +++ b/include/llvm/jit.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/llvm/jit.h - JIT Engine class definition -----------------===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file is the definition class of JIT engine class. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/module.h" +#include "common/configure.h" +#include "common/errcode.h" +#include "llvm/data.h" +#include + +namespace WasmEdge::LLVM { +class OrcLLJIT; + +class JITLibrary : public Executable { +public: + JITLibrary(OrcLLJIT JIT) noexcept; + ~JITLibrary() noexcept override; + + Symbol getIntrinsics() noexcept override; + + std::vector> getTypes(size_t Size) noexcept override; + + std::vector> getCodes(size_t Offset, + size_t Size) noexcept override; + +private: + OrcLLJIT *J; +}; + +class JIT { +public: + JIT(const Configure &Conf) noexcept : Conf(Conf) {} + Expect> load(Data D) noexcept; + +private: + const Configure Conf; +}; + +} // namespace WasmEdge::LLVM diff --git a/lib/driver/runtimeTool.cpp b/lib/driver/runtimeTool.cpp index ccbf4db20339..35cbd363e233 100644 --- a/lib/driver/runtimeTool.cpp +++ b/lib/driver/runtimeTool.cpp @@ -108,6 +108,11 @@ int Tool(struct DriverToolOptions &Opt) noexcept { Conf.getStatisticsConfigure().setTimeMeasuring(true); } } + if (Opt.ConfEnableJIT.value()) { + Conf.getRuntimeConfigure().setEnableJIT(true); + Conf.getCompilerConfigure().setOptimizationLevel( + WasmEdge::CompilerConfigure::OptimizationLevel::O1); + } if (Opt.ConfForceInterpreter.value()) { Conf.getRuntimeConfigure().setForceInterpreter(true); } diff --git a/lib/llvm/CMakeLists.txt b/lib/llvm/CMakeLists.txt index 306dfeb3d141..8ac9141a08e0 100644 --- a/lib/llvm/CMakeLists.txt +++ b/lib/llvm/CMakeLists.txt @@ -15,6 +15,7 @@ if(WASMEDGE_LINK_LLVM_STATIC) compiler.cpp codegen.cpp data.cpp + jit.cpp ) target_link_libraries(wasmedgeLLVM @@ -50,6 +51,7 @@ else() compiler.cpp codegen.cpp data.cpp + jit.cpp LINK_LIBS wasmedgeCommon wasmedgeSystem diff --git a/lib/llvm/jit.cpp b/lib/llvm/jit.cpp new file mode 100644 index 000000000000..8aa3835e82b4 --- /dev/null +++ b/lib/llvm/jit.cpp @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +#include "llvm/jit.h" +#include "common/log.h" + +#include "data.h" +#include "llvm.h" + +namespace LLVM = WasmEdge::LLVM; +using namespace std::literals; + +namespace WasmEdge::LLVM { + +JITLibrary::JITLibrary(OrcLLJIT JIT) noexcept + : J(std::make_unique(std::move(JIT)).release()) {} + +JITLibrary::~JITLibrary() noexcept { + std::unique_ptr JIT(std::exchange(J, nullptr)); +} + +Symbol +JITLibrary::getIntrinsics() noexcept { + if (auto Symbol = J->lookup("intrinsics")) { + return createSymbol(*Symbol); + } else { + spdlog::error("{}"sv, Symbol.error().message().string_view()); + return {}; + } +} + +std::vector> +JITLibrary::getTypes(size_t Size) noexcept { + std::vector> Result; + Result.reserve(Size); + for (size_t I = 0; I < Size; ++I) { + const std::string Name = fmt::format("t{}"sv, I); + if (auto Symbol = J->lookup(Name.c_str())) { + Result.push_back(createSymbol(*Symbol)); + } else { + spdlog::error("{}"sv, Symbol.error().message().string_view()); + Result.emplace_back(); + } + } + + return Result; +} + +std::vector> JITLibrary::getCodes(size_t Offset, + size_t Size) noexcept { + std::vector> Result; + Result.reserve(Size); + for (size_t I = 0; I < Size; ++I) { + const std::string Name = fmt::format("f{}"sv, I + Offset); + if (auto Symbol = J->lookup(Name.c_str())) { + Result.push_back(createSymbol(*Symbol)); + } else { + spdlog::error("{}"sv, Symbol.error().message().string_view()); + Result.emplace_back(); + } + } + + return Result; +} + +Expect> JIT::load(Data D) noexcept { + OrcLLJIT J; + if (auto Res = OrcLLJIT::create(); !Res) { + spdlog::error("{}"sv, Res.error().message().string_view()); + return Unexpect(ErrCode::Value::HostFuncError); + } else { + J = std::move(*Res); + } + + auto &LLModule = D.extract().LLModule; + + if (Conf.getCompilerConfigure().isDumpIR()) { + if (auto ErrorMessage = LLModule.printModuleToFile("wasm-jit.ll")) { + spdlog::error("printModuleToFile failed"); + } + } + + auto MainJD = J.getMainJITDylib(); + if (auto Err = J.addLLVMIRModule( + MainJD, + OrcThreadSafeModule(LLModule.release(), D.extract().TSContext))) { + spdlog::error("{}"sv, Err.message().string_view()); + return Unexpect(ErrCode::Value::HostFuncError); + } + + return std::make_shared(std::move(J)); +} +} // namespace WasmEdge::LLVM diff --git a/lib/llvm/llvm.h b/lib/llvm/llvm.h index af5729a8660c..b7ce98cedc9c 100644 --- a/lib/llvm/llvm.h +++ b/lib/llvm/llvm.h @@ -17,6 +17,31 @@ #include #include +#if LLVM_VERSION_MAJOR >= 12 +#include +#endif + +#if LLVM_VERSION_MAJOR < 13 +using LLVMOrcMaterializationResponsibilityRef = + struct LLVMOrcOpaqueMaterializationResponsibility *; +using LLVMOrcIRTransformLayerRef = struct LLVMOrcOpaqueIRTransformLayer *; +using LLVMOrcIRTransformLayerTransformFunction = + LLVMErrorRef (*)(void *Ctx, LLVMOrcThreadSafeModuleRef *ModInOut, + LLVMOrcMaterializationResponsibilityRef MR) noexcept; +using LLVMOrcGenericIRModuleOperationFunction = + LLVMErrorRef (*)(void *Ctx, LLVMModuleRef M) noexcept; +static LLVMOrcIRTransformLayerRef +LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) noexcept; +static void LLVMOrcIRTransformLayerSetTransform( + LLVMOrcIRTransformLayerRef IRTransformLayer, + LLVMOrcIRTransformLayerTransformFunction TransformFunction, + void *Ctx) noexcept; +static LLVMErrorRef +LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcThreadSafeModuleRef TSM, + LLVMOrcGenericIRModuleOperationFunction F, + void *Ctx) noexcept; +#endif + #if LLVM_VERSION_MAJOR >= 13 #include #else @@ -2028,11 +2053,130 @@ class OrcThreadSafeModule { LLVMOrcThreadSafeModuleRef Ref = nullptr; }; +class OrcJITDylib { +public: + constexpr OrcJITDylib() noexcept = default; + constexpr OrcJITDylib(LLVMOrcJITDylibRef R) noexcept : Ref(R) {} + OrcJITDylib(const OrcJITDylib &) = delete; + OrcJITDylib &operator=(const OrcJITDylib &) = delete; + OrcJITDylib(OrcJITDylib &&B) noexcept : OrcJITDylib() { swap(*this, B); } + OrcJITDylib &operator=(OrcJITDylib &&B) noexcept { + swap(*this, B); + return *this; + } + + constexpr operator bool() const noexcept { return Ref != nullptr; } + constexpr auto &unwrap() const noexcept { return Ref; } + constexpr auto &unwrap() noexcept { return Ref; } + friend void swap(OrcJITDylib &LHS, OrcJITDylib &RHS) noexcept { + using std::swap; + swap(LHS.Ref, RHS.Ref); + } + +private: + LLVMOrcJITDylibRef Ref = nullptr; +}; + +class OrcIRTransformLayer { +public: + constexpr OrcIRTransformLayer() noexcept = default; + constexpr OrcIRTransformLayer(LLVMOrcIRTransformLayerRef R) noexcept + : Ref(R) {} + OrcIRTransformLayer(const OrcIRTransformLayer &) = delete; + OrcIRTransformLayer &operator=(const OrcIRTransformLayer &) = delete; + OrcIRTransformLayer(OrcIRTransformLayer &&B) noexcept + : OrcIRTransformLayer() { + swap(*this, B); + } + OrcIRTransformLayer &operator=(OrcIRTransformLayer &&B) noexcept { + swap(*this, B); + return *this; + } + + constexpr operator bool() const noexcept { return Ref != nullptr; } + constexpr auto &unwrap() const noexcept { return Ref; } + constexpr auto &unwrap() noexcept { return Ref; } + friend void swap(OrcIRTransformLayer &LHS, + OrcIRTransformLayer &RHS) noexcept { + using std::swap; + swap(LHS.Ref, RHS.Ref); + } + + void setTransform(LLVMOrcIRTransformLayerTransformFunction TransformFunction, + void *Ctx) noexcept { + LLVMOrcIRTransformLayerSetTransform(Ref, TransformFunction, Ctx); + } + +private: + LLVMOrcIRTransformLayerRef Ref = nullptr; +}; + +class OrcLLJIT { +public: + constexpr OrcLLJIT() noexcept = default; + constexpr OrcLLJIT(LLVMOrcLLJITRef R) noexcept : Ref(R) {} + OrcLLJIT(const OrcLLJIT &) = delete; + OrcLLJIT &operator=(const OrcLLJIT &) = delete; + OrcLLJIT(OrcLLJIT &&B) noexcept : OrcLLJIT() { swap(*this, B); } + OrcLLJIT &operator=(OrcLLJIT &&B) noexcept { + swap(*this, B); + return *this; + } + + ~OrcLLJIT() noexcept { LLVMOrcDisposeLLJIT(Ref); } + + constexpr operator bool() const noexcept { return Ref != nullptr; } + constexpr auto &unwrap() const noexcept { return Ref; } + constexpr auto &unwrap() noexcept { return Ref; } + friend void swap(OrcLLJIT &LHS, OrcLLJIT &RHS) noexcept { + using std::swap; + swap(LHS.Ref, RHS.Ref); + } + + static cxx20::expected create() noexcept { + OrcLLJIT Result; + if (auto Err = LLVMOrcCreateLLJIT(&Result.Ref, nullptr)) { + return cxx20::unexpected(Err); + } else { + return Result; + } + } + + OrcJITDylib getMainJITDylib() noexcept { + return LLVMOrcLLJITGetMainJITDylib(Ref); + } + + Error addLLVMIRModule(const OrcJITDylib &L, OrcThreadSafeModule M) noexcept { + return LLVMOrcLLJITAddLLVMIRModule(Ref, L.unwrap(), M.release()); + } + + template + cxx20::expected lookup(const char *Name) noexcept { + LLVMOrcJITTargetAddress Addr; + if (auto Err = LLVMOrcLLJITLookup(Ref, &Addr, Name)) { + return cxx20::unexpected(Err); + } + return reinterpret_cast(Addr); + } + + OrcIRTransformLayer getIRTransformLayer() noexcept { + return LLVMOrcLLJITGetIRTransformLayer(Ref); + } + +private: + LLVMOrcLLJITRef Ref = nullptr; +}; + } // namespace WasmEdge::LLVM #include #include #include +#if LLVM_VERSION_MAJOR < 13 +#include +#include +#include +#endif namespace WasmEdge::LLVM { @@ -2083,3 +2227,50 @@ bool SectionIterator::isEHFrame() const noexcept { } } // namespace WasmEdge::LLVM + +#if LLVM_VERSION_MAJOR < 13 +namespace llvm { +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ThreadSafeModule, + LLVMOrcThreadSafeModuleRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::IRTransformLayer, + LLVMOrcIRTransformLayerRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::MaterializationResponsibility, + LLVMOrcMaterializationResponsibilityRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJIT, LLVMOrcLLJITRef) +} // namespace llvm + +LLVMOrcIRTransformLayerRef +LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) noexcept { + using llvm::unwrap; + using llvm::wrap; + return wrap(&(unwrap(J)->getIRTransformLayer())); +} +void LLVMOrcIRTransformLayerSetTransform( + LLVMOrcIRTransformLayerRef IRTransformLayer, + LLVMOrcIRTransformLayerTransformFunction TransformFunction, + void *Ctx) noexcept { + using llvm::unwrap; + using llvm::wrap; + unwrap(IRTransformLayer) + ->setTransform([=](llvm::orc::ThreadSafeModule TSM, + llvm::orc::MaterializationResponsibility &R) + -> llvm::Expected { + LLVMOrcThreadSafeModuleRef TSMRef = + wrap(new llvm::orc::ThreadSafeModule(std::move(TSM))); + if (LLVMErrorRef Err = TransformFunction(Ctx, &TSMRef, wrap(&R))) { + return unwrap(Err); + } + return std::move(*unwrap(TSMRef)); + }); +} + +LLVMErrorRef +LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcThreadSafeModuleRef TSM, + LLVMOrcGenericIRModuleOperationFunction F, + void *Ctx) noexcept { + using llvm::unwrap; + using llvm::wrap; + return wrap(unwrap(TSM)->withModuleDo( + [&](llvm::Module &M) { return unwrap(F(Ctx, wrap(&M))); })); +} +#endif diff --git a/lib/vm/CMakeLists.txt b/lib/vm/CMakeLists.txt index 0158e0bdfaf6..91f8316c3fe8 100644 --- a/lib/vm/CMakeLists.txt +++ b/lib/vm/CMakeLists.txt @@ -15,3 +15,10 @@ target_link_libraries(wasmedgeVM wasmedgeExecutor wasmedgeHostModuleWasi ) + +if(WASMEDGE_USE_LLVM) + target_link_libraries(wasmedgeVM + PUBLIC + wasmedgeLLVM + ) +endif() diff --git a/lib/vm/vm.cpp b/lib/vm/vm.cpp index 398e4be97d27..59433efaa4f3 100644 --- a/lib/vm/vm.cpp +++ b/lib/vm/vm.cpp @@ -5,6 +5,8 @@ #include "host/wasi/wasimodule.h" #include "plugin/plugin.h" +#include "llvm/compiler.h" +#include "llvm/jit.h" #include "host/mock/wasi_crypto_module.h" #include "host/mock/wasi_logging_module.h" @@ -398,6 +400,26 @@ Expect VM::unsafeInstantiate() { spdlog::error(ErrCode::Value::WrongVMWorkflow); return Unexpect(ErrCode::Value::WrongVMWorkflow); } + + if (Mod) { + if (Conf.getRuntimeConfigure().isEnableJIT() && !Mod->getSymbol()) { + LLVM::Compiler Compiler(Conf); + LLVM::JIT JIT(Conf); + if (auto Res = Compiler.compile(*Mod); !Res) { + const auto Err = static_cast(Res.error()); + spdlog::error( + "Compilation failed. Error code: {}, use interpreter mode instead."sv, + Err); + } else if (auto Res2 = JIT.load(std::move(*Res)); !Res2) { + const auto Err = static_cast(Res2.error()); + spdlog::warn( + "JIT failed. Error code: {}, use interpreter mode instead."sv, Err); + } else { + LoaderEngine.loadExecutable(*Mod, std::move(*Res2)); + } + } + } + if (auto Res = ExecutorEngine.instantiateModule(StoreRef, *Mod.get())) { Stage = VMStage::Instantiated; ActiveModInst = std::move(*Res); From 6fbc62ff349b88372ee87f5e005c3c85afcd4de5 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Fri, 9 Feb 2024 02:26:04 +0800 Subject: [PATCH 025/218] [JIT] Add test for JIT Signed-off-by: Shen-Ta Hsieh --- test/llvm/LLVMcoreTest.cpp | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/llvm/LLVMcoreTest.cpp b/test/llvm/LLVMcoreTest.cpp index 7eb7da3ba133..49f195d5cd28 100644 --- a/test/llvm/LLVMcoreTest.cpp +++ b/test/llvm/LLVMcoreTest.cpp @@ -45,6 +45,7 @@ static SpecTest T(std::filesystem::u8path("../spec/testSuites"sv)); // Parameterized testing class. class NativeCoreTest : public testing::TestWithParam {}; class CustomWasmCoreTest : public testing::TestWithParam {}; +class JITCoreTest : public testing::TestWithParam {}; TEST_P(NativeCoreTest, TestSuites) { const auto [Proposal, Conf, UnitName] = T.resolve(GetParam()); @@ -266,6 +267,79 @@ TEST_P(CustomWasmCoreTest, TestSuites) { T.run(Proposal, UnitName); } +TEST_P(JITCoreTest, TestSuites) { + const auto [Proposal, Conf, UnitName] = T.resolve(GetParam()); + WasmEdge::Configure CopyConf = Conf; + CopyConf.getRuntimeConfigure().setEnableJIT(true); + CopyConf.getCompilerConfigure().setOptimizationLevel( + WasmEdge::CompilerConfigure::OptimizationLevel::O0); + CopyConf.getCompilerConfigure().setDumpIR(true); + WasmEdge::VM::VM VM(CopyConf); + WasmEdge::SpecTestModule SpecTestMod; + VM.registerModule(SpecTestMod); + T.onModule = [&VM](const std::string &ModName, + const std::string &Filename) -> Expect { + if (!ModName.empty()) { + return VM.registerModule(ModName, Filename); + } else { + return VM.loadWasm(Filename) + .and_then([&VM]() { return VM.validate(); }) + .and_then([&VM]() { return VM.instantiate(); }); + } + }; + T.onLoad = [&VM](const std::string &Filename) -> Expect { + return VM.loadWasm(Filename); + }; + T.onValidate = [&VM](const std::string &Filename) -> Expect { + return VM.loadWasm(Filename).and_then([&VM]() { return VM.validate(); }); + }; + T.onInstantiate = [&VM](const std::string &Filename) -> Expect { + return VM.loadWasm(Filename) + .and_then([&VM]() { return VM.validate(); }) + .and_then([&VM]() { return VM.instantiate(); }); + }; + // Helper function to call functions. + T.onInvoke = [&VM](const std::string &ModName, const std::string &Field, + const std::vector &Params, + const std::vector &ParamTypes) + -> Expect>> { + if (!ModName.empty()) { + // Invoke function of named module. Named modules are registered in Store + // Manager. + return VM.execute(ModName, Field, Params, ParamTypes); + } else { + // Invoke function of anonymous module. Anonymous modules are instantiated + // in VM. + return VM.execute(Field, Params, ParamTypes); + } + }; + // Helper function to get values. + T.onGet = [&VM](const std::string &ModName, const std::string &Field) + -> Expect> { + // Get module instance. + const WasmEdge::Runtime::Instance::ModuleInstance *ModInst = nullptr; + if (ModName.empty()) { + ModInst = VM.getActiveModule(); + } else { + ModInst = VM.getStoreManager().findModule(ModName); + } + if (ModInst == nullptr) { + return Unexpect(ErrCode::Value::WrongInstanceAddress); + } + + // Get global instance. + WasmEdge::Runtime::Instance::GlobalInstance *GlobInst = + ModInst->findGlobalExports(Field); + if (unlikely(GlobInst == nullptr)) { + return Unexpect(ErrCode::Value::WrongInstanceAddress); + } + return std::make_pair(GlobInst->getValue(), + GlobInst->getGlobalType().getValType()); + }; + + T.run(Proposal, UnitName); +} + // Initiate test suite. INSTANTIATE_TEST_SUITE_P( TestUnit, NativeCoreTest, @@ -273,6 +347,9 @@ INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P( TestUnit, CustomWasmCoreTest, testing::ValuesIn(T.enumerate(SpecTest::TestMode::AOT))); +INSTANTIATE_TEST_SUITE_P( + TestUnit, JITCoreTest, + testing::ValuesIn(T.enumerate(SpecTest::TestMode::JIT))); std::array AsyncWasm{ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, From 838a8f1aebfa0e5762f790845575e96bf8b469b2 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Mon, 5 Feb 2024 17:23:38 +0800 Subject: [PATCH 026/218] [JIT] Prevent JIT when LLVM is disabled Signed-off-by: Shen-Ta Hsieh --- lib/vm/CMakeLists.txt | 4 ++++ lib/vm/vm.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/vm/CMakeLists.txt b/lib/vm/CMakeLists.txt index 91f8316c3fe8..072db4af7799 100644 --- a/lib/vm/CMakeLists.txt +++ b/lib/vm/CMakeLists.txt @@ -17,6 +17,10 @@ target_link_libraries(wasmedgeVM ) if(WASMEDGE_USE_LLVM) + target_compile_definitions(wasmedgeVM + PUBLIC + -DWASMEDGE_USE_LLVM + ) target_link_libraries(wasmedgeVM PUBLIC wasmedgeLLVM diff --git a/lib/vm/vm.cpp b/lib/vm/vm.cpp index 59433efaa4f3..5643649d5c94 100644 --- a/lib/vm/vm.cpp +++ b/lib/vm/vm.cpp @@ -403,6 +403,7 @@ Expect VM::unsafeInstantiate() { if (Mod) { if (Conf.getRuntimeConfigure().isEnableJIT() && !Mod->getSymbol()) { +#ifdef WASMEDGE_USE_LLVM LLVM::Compiler Compiler(Conf); LLVM::JIT JIT(Conf); if (auto Res = Compiler.compile(*Mod); !Res) { @@ -417,6 +418,9 @@ Expect VM::unsafeInstantiate() { } else { LoaderEngine.loadExecutable(*Mod, std::move(*Res2)); } +#else + spdlog::error("LLVM disabled, JIT is unsupported!"); +#endif } } From b0802bbda2548fdf92994e04082db0fac96dea25 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Fri, 9 Feb 2024 09:03:54 +0800 Subject: [PATCH 027/218] [JIT] Add support for stack unwinding in windows Signed-off-by: Shen-Ta Hsieh --- lib/llvm/llvm.h | 133 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 11 deletions(-) diff --git a/lib/llvm/llvm.h b/lib/llvm/llvm.h index b7ce98cedc9c..935541cfdd14 100644 --- a/lib/llvm/llvm.h +++ b/lib/llvm/llvm.h @@ -21,6 +21,15 @@ #include #endif +#if LLVM_VERSION_MAJOR < 12 && WASMEDGE_OS_WINDOWS +using LLVMOrcObjectLayerRef = struct LLVMOrcOpaqueObjectLayer *; +using LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction = + LLVMOrcObjectLayerRef (*)(void *Ctx, LLVMOrcExecutionSessionRef ES, + const char *Triple) noexcept; +static void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( + LLVMOrcLLJITBuilderRef Builder, + LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, void *Ctx) noexcept; +#endif #if LLVM_VERSION_MAJOR < 13 using LLVMOrcMaterializationResponsibilityRef = struct LLVMOrcOpaqueMaterializationResponsibility *; @@ -2135,7 +2144,7 @@ class OrcLLJIT { static cxx20::expected create() noexcept { OrcLLJIT Result; - if (auto Err = LLVMOrcCreateLLJIT(&Result.Ref, nullptr)) { + if (auto Err = LLVMOrcCreateLLJIT(&Result.Ref, getBuilder())) { return cxx20::unexpected(Err); } else { return Result; @@ -2165,6 +2174,8 @@ class OrcLLJIT { private: LLVMOrcLLJITRef Ref = nullptr; + + static inline LLVMOrcLLJITBuilderRef getBuilder() noexcept; }; } // namespace WasmEdge::LLVM @@ -2172,12 +2183,41 @@ class OrcLLJIT { #include #include #include +#if LLVM_VERSION_MAJOR < 12 || WASMEDGE_OS_WINDOWS +#include +#endif #if LLVM_VERSION_MAJOR < 13 #include #include #include #endif +#if WASMEDGE_OS_WINDOWS +#include +#include +#include +#endif + +namespace llvm { +#if WASMEDGE_OS_WINDOWS +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ExecutionSession, + LLVMOrcExecutionSessionRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ObjectLayer, LLVMOrcObjectLayerRef) +#endif +#if LLVM_VERSION_MAJOR < 12 +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJITBuilder, LLVMOrcLLJITBuilderRef) +#endif +#if LLVM_VERSION_MAJOR < 13 +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ThreadSafeModule, + LLVMOrcThreadSafeModuleRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::IRTransformLayer, + LLVMOrcIRTransformLayerRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::MaterializationResponsibility, + LLVMOrcMaterializationResponsibilityRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJIT, LLVMOrcLLJITRef) +#endif +} // namespace llvm + namespace WasmEdge::LLVM { void Value::setDSOLocal(bool Local) noexcept { @@ -2226,19 +2266,90 @@ bool SectionIterator::isEHFrame() const noexcept { #endif } +#if WASMEDGE_OS_WINDOWS +// Register stack unwind info for JIT functions +class Win64EHManager : public llvm::SectionMemoryManager { + using Base = llvm::SectionMemoryManager; + uint64_t CodeAddress = 0; + +public: + ~Win64EHManager() noexcept override {} + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + llvm::StringRef SectionName) override { + using namespace std::literals; + const auto Allocated = + Base::allocateCodeSection(Size, Alignment, SectionID, SectionName); + if (SectionName == llvm::StringRef(".text"sv)) { + CodeAddress = reinterpret_cast(Allocated); + } + return Allocated; + } + + void registerEHFrames(uint8_t *Addr, uint64_t /*LoadAddr*/, + size_t Size) noexcept override { + using namespace std::literals; + winapi::RUNTIME_FUNCTION_ *const FunctionTable = + reinterpret_cast(Addr); + const uint32_t EntryCount = + static_cast(Size / sizeof(winapi::RUNTIME_FUNCTION_)); + if (EntryCount == 0) + return; + // Calculate object image base address by assuming that address of the first + // function is equal to the address of the code section + const auto ImageBase = CodeAddress - FunctionTable[0].BeginAddress; + winapi::RtlAddFunctionTable(FunctionTable, EntryCount, ImageBase); + EHFrames.push_back({Addr, Size}); + } + void deregisterEHFrames() noexcept override { + using namespace std::literals; + for (auto &Frame : EHFrames) { + winapi::RtlDeleteFunctionTable( + reinterpret_cast(Frame.Addr)); + } + EHFrames.clear(); + } +}; + +LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept { + using llvm::unwrap; + using llvm::wrap; + const LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder(); + LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( + Builder, + [](void *, LLVMOrcExecutionSessionRef ES, const char *) noexcept { + auto Layer = std::make_unique( + *unwrap(ES), []() { return std::make_unique(); }); + Layer->setOverrideObjectFlagsWithResponsibilityFlags(true); + Layer->setAutoClaimResponsibilityForObjectSymbols(true); + return wrap(static_cast(Layer.release())); + }, + nullptr); + return Builder; +} +#else +LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept { return nullptr; } +#endif + } // namespace WasmEdge::LLVM +#if LLVM_VERSION_MAJOR < 12 && WASMEDGE_OS_WINDOWS +void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( + LLVMOrcLLJITBuilderRef Builder, + LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, + void *Ctx) noexcept { + using llvm::unwrap; + using llvm::wrap; + unwrap(Builder)->setObjectLinkingLayerCreator( + [=](llvm::orc::ExecutionSession &ES, const llvm::Triple &TT) { + auto TTStr = TT.str(); + return std::unique_ptr( + unwrap(F(Ctx, wrap(&ES), TTStr.c_str()))); + }); +} +#endif #if LLVM_VERSION_MAJOR < 13 -namespace llvm { -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ThreadSafeModule, - LLVMOrcThreadSafeModuleRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::IRTransformLayer, - LLVMOrcIRTransformLayerRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::MaterializationResponsibility, - LLVMOrcMaterializationResponsibilityRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJIT, LLVMOrcLLJITRef) -} // namespace llvm - LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) noexcept { using llvm::unwrap; From 2895c4cdc5a5b9720b47cef80e5e5d1570bc035b Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Wed, 7 Feb 2024 18:48:38 +0800 Subject: [PATCH 028/218] [AOT] Support uwtable in older llvm versions Signed-off-by: Shen-Ta Hsieh --- lib/llvm/codegen.cpp | 3 ++- lib/llvm/compiler.cpp | 4 ++-- lib/llvm/llvm.h | 5 +++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/llvm/codegen.cpp b/lib/llvm/codegen.cpp index 0b42f7440d83..35a414df72b6 100644 --- a/lib/llvm/codegen.cpp +++ b/lib/llvm/codegen.cpp @@ -524,7 +524,8 @@ Expect CodeGen::codegen(Span WasmData, Data D, LLVM::Attribute::createString(LLContext, "no-stack-arg-probe"sv, {})); F.addFnAttr( LLVM::Attribute::createEnum(LLContext, LLVM::Core::StrictFP, 0)); - F.addFnAttr(LLVM::Attribute::createEnum(LLContext, LLVM::Core::UWTable, 2)); + F.addFnAttr(LLVM::Attribute::createEnum(LLContext, LLVM::Core::UWTable, + LLVM::Core::UWTableDefault)); F.addFnAttr( LLVM::Attribute::createEnum(LLContext, LLVM::Core::NoReturn, 0)); LLVM::Builder Builder(LLContext); diff --git a/lib/llvm/compiler.cpp b/lib/llvm/compiler.cpp index e74e0b8c266c..155f10d4ca1c 100644 --- a/lib/llvm/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -211,8 +211,8 @@ struct LLVM::Compiler::CompileContext { NoReturn(LLVM::Attribute::createEnum(C, LLVM::Core::NoReturn, 0)), ReadOnly(LLVM::Attribute::createEnum(C, LLVM::Core::ReadOnly, 0)), StrictFP(LLVM::Attribute::createEnum(C, LLVM::Core::StrictFP, 0)), - // UWTable::Default = 2 - UWTable(LLVM::Attribute::createEnum(C, LLVM::Core::UWTable, 2)), + UWTable(LLVM::Attribute::createEnum(C, LLVM::Core::UWTable, + LLVM::Core::UWTableDefault)), NoStackArgProbe( LLVM::Attribute::createString(C, "no-stack-arg-probe"sv, {})), VoidTy(LLContext.getVoidTy()), Int8Ty(LLContext.getInt8Ty()), diff --git a/lib/llvm/llvm.h b/lib/llvm/llvm.h index 935541cfdd14..c45fcf99c595 100644 --- a/lib/llvm/llvm.h +++ b/lib/llvm/llvm.h @@ -129,6 +129,11 @@ class Core { static inline unsigned int ReadOnly = 0; static inline unsigned int StrictFP = 0; static inline unsigned int UWTable = 0; +#if LLVM_VERSION_MAJOR >= 15 + static constexpr inline const unsigned int UWTableDefault = 2; +#else + static constexpr inline const unsigned int UWTableDefault = 0; +#endif static inline unsigned int InvariantGroup = 0; From eb80f8e69535e971ab0918dc92a663489094251f Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 13 Feb 2024 15:53:20 +0800 Subject: [PATCH 029/218] [Plugin] Don't install llvm, use preinstalled llvm. * Add clang and llvm-strip symbolic links in ubuntu for wasm-bpf test Signed-off-by: Shen-Ta Hsieh --- .github/workflows/build-extensions.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 6e3d7f2eaa59..d8f15561b183 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -211,13 +211,15 @@ jobs: apt update apt install -y libssl-dev apt install -y libelf-dev zlib1g-dev pkg-config - apt install -y clang llvm + apt install -y clang-15 apt install -y cargo # Running tests of wasm_bpf requires proper ebpf running environment mount -t debugfs none /sys/kernel/debug - name: Build plugins using ${{ matrix.compiler }} with ${{ matrix.build_type }} mode shell: bash run: | + update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 100 + update-alternatives --install /usr/bin/llvm-strip llvm-strip /usr/bin/llvm-strip-15 100 testbin_array=(${test_bins}) cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} for (( i=0; i<${#testbin_array[@]}; i++ )); From 25a575f8b31f7f577e90db2fe63f340a752650ed Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 15 Feb 2024 00:19:03 +0800 Subject: [PATCH 030/218] [WASI] Ignore NONBLOCK flags on windows, fix #3084 Signed-off-by: Shen-Ta Hsieh --- lib/host/wasi/inode-win.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/host/wasi/inode-win.cpp b/lib/host/wasi/inode-win.cpp index a13c63a86a60..a4d07ea1f718 100644 --- a/lib/host/wasi/inode-win.cpp +++ b/lib/host/wasi/inode-win.cpp @@ -86,6 +86,10 @@ WasiExpect> inline constexpr getOpenFlags( AttributeFlags |= FILE_FLAG_WRITE_THROUGH_; FdFlags &= ~__WASI_FDFLAGS_DSYNC; } + if (FdFlags & __WASI_FDFLAGS_NONBLOCK) { + // Ignore NONBLOCK flag + FdFlags &= ~__WASI_FDFLAGS_NONBLOCK; + } if (OpenFlags & __WASI_OFLAGS_DIRECTORY) { AttributeFlags |= FILE_ATTRIBUTE_DIRECTORY_; OpenFlags &= ~__WASI_OFLAGS_DIRECTORY; From ea7ab1aecd2bb8877ed66ef6f8d3fa55a0f12c5d Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 8 Feb 2024 01:26:34 +0800 Subject: [PATCH 031/218] [CI] Use the latest llvm from homebrew, remove the pinned llvm@16 Signed-off-by: hydai --- .github/workflows/reusable-build-on-macos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-build-on-macos.yml b/.github/workflows/reusable-build-on-macos.yml index 5f9d523de0d0..4131e50df42d 100644 --- a/.github/workflows/reusable-build-on-macos.yml +++ b/.github/workflows/reusable-build-on-macos.yml @@ -35,7 +35,7 @@ jobs: - name: Setup build environment run: | eval $(/opt/homebrew/bin/brew shellenv) - brew install llvm@16 ninja cmake wabt grpc + brew install llvm ninja cmake wabt grpc - name: Set environment variables for release if: ${{ inputs.release }} run: | @@ -44,7 +44,7 @@ jobs: - name: Build WasmEdge run: | eval $(/opt/homebrew/bin/brew shellenv) - export LLVM_DIR="$(brew --prefix)/opt/llvm@16/lib/cmake" + export LLVM_DIR="$(brew --prefix)/opt/llvm/lib/cmake" export CC=clang export CXX=clang++ rm -rf build output From 62884c90cc0cad9afd442818615765f4868e0b03 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 16 Feb 2024 14:53:21 +0800 Subject: [PATCH 032/218] [Misc] enable -Wno-deprecated-literal-operator only if clang >= 17.0.0 (#3219) Fixes #3201 Signed-off-by: hydai --- cmake/Helper.cmake | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 395f8b03f095..9dcd7d2065fc 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -81,8 +81,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") -Wno-signed-enum-bitfield -Wno-switch-enum -Wno-undefined-func-template - -Wno-deprecated-literal-operator ) + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 17.0.0) + list(APPEND WASMEDGE_CFLAGS + -Wno-deprecated-literal-operator + ) + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0.0) list(APPEND WASMEDGE_CFLAGS -Wno-error=return-std-move-in-c++11 From 8e29c40b3330a25a65b30f88d70739ba59159484 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 01:44:26 +0800 Subject: [PATCH 033/218] [CI] Bump undici from 5.27.2 to 5.28.3 in /.github/actions/expand-variables (#3226) Bumps [undici](https://github.com/nodejs/undici) from 5.27.2 to 5.28.3. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v5.27.2...v5.28.3) --- updated-dependencies: - dependency-name: undici dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/expand-variables/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/expand-variables/package-lock.json b/.github/actions/expand-variables/package-lock.json index 0ce55136525c..ff8f198e6275 100644 --- a/.github/actions/expand-variables/package-lock.json +++ b/.github/actions/expand-variables/package-lock.json @@ -47,9 +47,9 @@ } }, "node_modules/undici": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", - "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", "dependencies": { "@fastify/busboy": "^2.0.0" }, From ece05798ce3faae503cdd6cbf7ab99299c4665e2 Mon Sep 17 00:00:00 2001 From: Sarrah Bastawala <84874044+sarrah-basta@users.noreply.github.com> Date: Mon, 19 Feb 2024 00:55:13 +0530 Subject: [PATCH 034/218] [WASI-OCR] WASI-OCR New Plugin for using Tesseract OCR within WasmEdge (#2962) * Final commit for Wasi-OCR plugin integrating OCR capabilities within WasmEdge Introducing **Wasi-OCR**: A WasmEdge Plugin for Optical Character Recognition (OCR) powered by the Tesseract API. This plugin offers seamless integration with Tesseract, a leading open-source OCR engine, enabling the extraction of text from images. Harness the power of OCR in your Document AI applications within WasmEdge effortlessly. --------- Signed-off-by: Sarrah Bastawala <84874044+sarrah-basta@users.noreply.github.com> --- CMakeLists.txt | 2 +- plugins/CMakeLists.txt | 7 ++- plugins/wasi_ocr/CMakeLists.txt | 51 ++++++++++++++++++++++ plugins/wasi_ocr/wasiocrbase.h | 23 ++++++++++ plugins/wasi_ocr/wasiocrenv.cpp | 42 ++++++++++++++++++ plugins/wasi_ocr/wasiocrenv.h | 46 ++++++++++++++++++++ plugins/wasi_ocr/wasiocrfunc.cpp | 69 ++++++++++++++++++++++++++++++ plugins/wasi_ocr/wasiocrfunc.h | 30 +++++++++++++ plugins/wasi_ocr/wasiocrmodule.cpp | 17 ++++++++ plugins/wasi_ocr/wasiocrmodule.h | 23 ++++++++++ 10 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 plugins/wasi_ocr/CMakeLists.txt create mode 100644 plugins/wasi_ocr/wasiocrbase.h create mode 100644 plugins/wasi_ocr/wasiocrenv.cpp create mode 100644 plugins/wasi_ocr/wasiocrenv.h create mode 100644 plugins/wasi_ocr/wasiocrfunc.cpp create mode 100644 plugins/wasi_ocr/wasiocrfunc.h create mode 100644 plugins/wasi_ocr/wasiocrmodule.cpp create mode 100644 plugins/wasi_ocr/wasiocrmodule.h diff --git a/CMakeLists.txt b/CMakeLists.txt index eaaa64b9a73e..040f01fe3753 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL "Enable LLAMA_METAL in the WASI- option(WASMEDGE_PLUGIN_WASI_CRYPTO "Enable WasmEdge Wasi-crypto plugin." OFF) option(WASMEDGE_PLUGIN_WASI_LOGGING "Enable WasmEdge wasi-logging plugin." OFF) option(WASMEDGE_PLUGIN_WASM_BPF "Enable WasmEdge wasm-bpf plugin." OFF) +option(WASMEDGE_PLUGIN_WASI_OCR "Enable WasmEdge wasm-ocr plugin." OFF) option(WASMEDGE_PLUGIN_OPENCVMINI "Enable WasmEdge opencvmini plugin." OFF) option(WASMEDGE_PLUGIN_PROCESS "Enable WasmEdge process plugin." OFF) option(WASMEDGE_PLUGIN_IMAGE "Enable WasmEdge image plugin." OFF) @@ -201,4 +202,3 @@ endif() include(CPack) include(CPackComponent) - diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index abe3e8e6c78e..91b64909b3f5 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -54,6 +54,10 @@ if(WASMEDGE_PLUGIN_WASM_BPF) endif() endif() +if(WASMEDGE_PLUGIN_WASI_OCR) + add_subdirectory(wasi_ocr) +endif() + if(WASMEDGE_PLUGIN_OPENCVMINI) # Only Linux and MacOS support wasmedge_opencvmini now. if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") @@ -73,4 +77,5 @@ endif() if(WASMEDGE_PLUGIN_ZLIB) add_subdirectory(wasmedge_zlib) -endif() + +endif() \ No newline at end of file diff --git a/plugins/wasi_ocr/CMakeLists.txt b/plugins/wasi_ocr/CMakeLists.txt new file mode 100644 index 000000000000..b2eef6d35b3d --- /dev/null +++ b/plugins/wasi_ocr/CMakeLists.txt @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +add_library(wasmedgePluginWasiOCR + SHARED + wasiocrenv.cpp + wasiocrfunc.cpp + wasiocrmodule.cpp +) + +target_compile_options(wasmedgePluginWasiOCR + PUBLIC + -DWASMEDGE_PLUGIN +) + +target_include_directories(wasmedgePluginWasiOCR + PUBLIC + $ + ${CMAKE_CURRENT_SOURCE_DIR} +) + +if(WASMEDGE_LINK_PLUGINS_STATIC) + target_link_libraries(wasmedgePluginWasiOCR + PRIVATE + wasmedgeCAPI + ) +else() + target_link_libraries(wasmedgePluginWasiOCR + PRIVATE + wasmedge_shared + ) +endif() + +install(TARGETS wasmedgePluginWasiOCR DESTINATION ${CMAKE_INSTALL_LIBDIR}/wasmedge) + +message(STATUS "WASI-OCR: Build Tesseract backend for WASI-OCR") +find_package(PkgConfig REQUIRED) +pkg_search_module(TESSERACT REQUIRED tesseract) +pkg_search_module(LEPTONICA REQUIRED lept) + +target_include_directories(wasmedgePluginWasiOCR + PUBLIC + ${TESSERACT_INCLUDE_DIRS} + ${LEPTONICA_INCLUDE_DIRS} +) + +target_link_libraries(wasmedgePluginWasiOCR + PUBLIC + ${TESSERACT_LIBRARIES} + ${LEPTONICA_LIBRARIES} +) diff --git a/plugins/wasi_ocr/wasiocrbase.h b/plugins/wasi_ocr/wasiocrbase.h new file mode 100644 index 000000000000..38fd9d7225be --- /dev/null +++ b/plugins/wasi_ocr/wasiocrbase.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#pragma once + +#include "common/errcode.h" +#include "runtime/hostfunc.h" +#include "wasiocrenv.h" + +namespace WasmEdge { +namespace Host { + +template class WasiOCR : public Runtime::HostFunction { +public: + WasiOCR(WASIOCR::WasiOCREnvironment &HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + WASIOCR::WasiOCREnvironment &Env; +}; + +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_ocr/wasiocrenv.cpp b/plugins/wasi_ocr/wasiocrenv.cpp new file mode 100644 index 000000000000..3df9d69c19d8 --- /dev/null +++ b/plugins/wasi_ocr/wasiocrenv.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#include "wasiocrenv.h" +#include "wasiocrmodule.h" + +namespace WasmEdge { +namespace Host { + +namespace { + +Runtime::Instance::ModuleInstance * +create(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasiOCRModule; +} + +Plugin::Plugin::PluginDescriptor Descriptor{ + .Name = "wasi_ocr", + .Description = "A WasmEdge Plugin for Optical Character Recognition (OCR) " + "powered by the Tesseract API.", + .APIVersion = Plugin::Plugin::CurrentAPIVersion, + .Version = {0, 10, 1, 0}, + .ModuleCount = 1, + .ModuleDescriptions = + (Plugin::PluginModule::ModuleDescriptor[]){ + { + .Name = "wasi_ocr", + .Description = + "A WasmEdge Plugin for Optical Character Recognition (OCR) " + "powered by the Tesseract API.", + .Create = create, + }, + }, + .AddOptions = nullptr, +}; + +} // namespace + +Plugin::PluginRegister WASIOCR::WasiOCREnvironment::Register(&Descriptor); + +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_ocr/wasiocrenv.h b/plugins/wasi_ocr/wasiocrenv.h new file mode 100644 index 000000000000..9e90a5efe6d9 --- /dev/null +++ b/plugins/wasi_ocr/wasiocrenv.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#pragma once + +#include "common/log.h" +#include "plugin/plugin.h" +#include + +#include +#include + +namespace WasmEdge { +namespace Host { +namespace WASIOCR { + +enum class ErrNo : uint32_t { + Success = 0, // No error occurred. + InvalidArgument = 1, // Caller module passed an invalid argument. + MissingMemory = 2, // Caller module is missing a memory export. + Busy = 3 // Device or resource busy. +}; + +class WasiOCREnvironment { +public: + WasiOCREnvironment() noexcept { + // check Tesseract API by initializing tesseract-ocr with English, without + // specifying tessdata path + if (TesseractApi->Init(NULL, "eng")) { + spdlog::error("[WASI-OCR] Error occurred when initializing tesseract."); + } + } + ~WasiOCREnvironment() noexcept { + if (TesseractApi) { + TesseractApi->End(); + ; + } + } + tesseract::TessBaseAPI *TesseractApi = new tesseract::TessBaseAPI(); + + static Plugin::PluginRegister Register; +}; + +} // namespace WASIOCR +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_ocr/wasiocrfunc.cpp b/plugins/wasi_ocr/wasiocrfunc.cpp new file mode 100644 index 000000000000..a1d17d816723 --- /dev/null +++ b/plugins/wasi_ocr/wasiocrfunc.cpp @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#include "wasiocrfunc.h" +#include "common/log.h" + +#include +#include + +namespace WasmEdge { +namespace Host { + +Expect +WasiOCRNumOfExtractions::body(const Runtime::CallingFrame &Frame, + uint32_t ImagePathPtr, uint32_t ImagePathLen) { + // Check memory instance from module. + auto *MemInst = Frame.getMemoryByIndex(0); + if (MemInst == nullptr) { + return Unexpect(ErrCode::Value::HostFuncError); + } + auto ImagePtr = MemInst->getSpan(ImagePathPtr, ImagePathLen); + if (unlikely(ImagePtr.size() != ImagePathLen)) { + return Unexpect(ErrCode::Value::HostFuncError); + } + Pix *image = pixRead(ImagePtr.data()); + + Env.TesseractApi->SetImage(image); + Env.TesseractApi->Recognize(0); + + tesseract::PageIteratorLevel level = tesseract::RIL_WORD; + const char *outText = Env.TesseractApi->GetTSVText(level); + + uint32_t length = strlen(outText); + pixDestroy(&image); + return static_cast(length); +} + +Expect WasiOCRGetOutput::body(const Runtime::CallingFrame &Frame, + uint32_t OutBufferPtr [[maybe_unused]], + uint32_t OutBufferMaxSize + [[maybe_unused]]) { + // Check memory instance from module. + auto *MemInst = Frame.getMemoryByIndex(0); + if (MemInst == nullptr) { + return Unexpect(ErrCode::Value::HostFuncError); + } + + // Check the return value: OutBufferPtr should be valid. + auto Buf = MemInst->getSpan(OutBufferPtr, OutBufferMaxSize); + if (unlikely(Buf.empty())) { + spdlog::error( + "[WASI-OCR] Failed when accessing the return OutBufferPtr memory."); + return static_cast(WASIOCR::ErrNo::InvalidArgument); + } + + tesseract::PageIteratorLevel level = tesseract::RIL_WORD; + const char *outText = Env.TesseractApi->GetTSVText(level); + std::strcpy(Buf.data(), outText); + + // remaining free and deltee memory stuff + Env.TesseractApi->End(); + delete[] outText; // USE WHEN USING TESS API + + return static_cast(WASIOCR::ErrNo::Success); + // return outText; +} + +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_ocr/wasiocrfunc.h b/plugins/wasi_ocr/wasiocrfunc.h new file mode 100644 index 000000000000..ad98639b7a47 --- /dev/null +++ b/plugins/wasi_ocr/wasiocrfunc.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#pragma once + +#include "runtime/callingframe.h" +#include "wasiocrbase.h" + +#include + +namespace WasmEdge { +namespace Host { + +class WasiOCRNumOfExtractions : public WasiOCR { +public: + WasiOCRNumOfExtractions(WASIOCR::WasiOCREnvironment &HostEnv) + : WasiOCR(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t ImagePathPtr, + uint32_t ImagePathLen); +}; + +class WasiOCRGetOutput : public WasiOCR { +public: + WasiOCRGetOutput(WASIOCR::WasiOCREnvironment &HostEnv) : WasiOCR(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t OutBufferPtr, + uint32_t OutBufferMaxSize); +}; + +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_ocr/wasiocrmodule.cpp b/plugins/wasi_ocr/wasiocrmodule.cpp new file mode 100644 index 000000000000..ea16f2156891 --- /dev/null +++ b/plugins/wasi_ocr/wasiocrmodule.cpp @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#include "wasiocrmodule.h" +#include "wasiocrfunc.h" + +namespace WasmEdge { +namespace Host { + +WasiOCRModule::WasiOCRModule() : ModuleInstance("wasi_ephemeral_ocr") { + addHostFunc("num_of_extractions", + std::make_unique(Env)); + addHostFunc("get_output", std::make_unique(Env)); +} + +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_ocr/wasiocrmodule.h b/plugins/wasi_ocr/wasiocrmodule.h new file mode 100644 index 000000000000..cbab6d5c9161 --- /dev/null +++ b/plugins/wasi_ocr/wasiocrmodule.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Second State INC + +#pragma once + +#include "runtime/instance/module.h" +#include "wasiocrenv.h" + +namespace WasmEdge { +namespace Host { + +class WasiOCRModule : public Runtime::Instance::ModuleInstance { +public: + WasiOCRModule(); + + WASIOCR::WasiOCREnvironment &getEnv() { return Env; } + +private: + WASIOCR::WasiOCREnvironment Env; +}; + +} // namespace Host +} // namespace WasmEdge From bec1b71b94e048ea2f42b9afc4d3f107147051f7 Mon Sep 17 00:00:00 2001 From: "Shen-Ta Hsieh(BestSteve)" Date: Mon, 19 Feb 2024 03:55:00 +0800 Subject: [PATCH 035/218] [Misc] Ignore false positive warnings in MSVC (#3215) Signed-off-by: Shen-Ta Hsieh --- include/experimental/expected.hpp | 14 ++++++++++++++ test/expected/noexcept.cpp | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/include/experimental/expected.hpp b/include/experimental/expected.hpp index 1242e52332cc..61fdb5a670e2 100644 --- a/include/experimental/expected.hpp +++ b/include/experimental/expected.hpp @@ -1615,7 +1615,14 @@ class expected : public detail::expected_move_assign_base, } constexpr const_rvalue_reference_type value() const && { if (!has_value()) { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:5272) +#endif throw(bad_expected_access(std::move(error()))); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif } return std::move(impl_base::val()); } @@ -1627,7 +1634,14 @@ class expected : public detail::expected_move_assign_base, } constexpr rvalue_reference_type value() && { if (!has_value()) { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:5272) +#endif throw(bad_expected_access(std::move(error()))); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif } return std::move(impl_base::val()); } diff --git a/test/expected/noexcept.cpp b/test/expected/noexcept.cpp index aacf20f7f420..6a26c182b927 100644 --- a/test/expected/noexcept.cpp +++ b/test/expected/noexcept.cpp @@ -31,7 +31,14 @@ TEST(NoExceptTest, ThrowAll) { [[noreturn]] [[maybe_unused]] throw_all(throw_all &&) noexcept(false) { throw 0; } +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4722) +#endif [[noreturn]] ~throw_all() noexcept(false) { throw 0; } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif [[noreturn]] throw_all &operator=(const throw_all &) noexcept(false) { throw 0; } From 6082a5ac137cc7296456ca228e5c99681e1b665a Mon Sep 17 00:00:00 2001 From: hydai Date: Mon, 19 Feb 2024 15:15:41 +0800 Subject: [PATCH 036/218] [OpenWrt] Bump the WasmEdge C API version to 0.1.0 (#3220) Signed-off-by: hydai --- utils/openwrt/configuration/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/openwrt/configuration/Makefile b/utils/openwrt/configuration/Makefile index 42d4e0e77627..7fdfa0fa9b03 100644 --- a/utils/openwrt/configuration/Makefile +++ b/utils/openwrt/configuration/Makefile @@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=WasmEdge PKG_VERSION:=0.14.0 PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME) -WASMEDGE_SOVERSION:=0.0.3 +WASMEDGE_SOVERSION:=0.1.0 WASMEDGE_SONAME:=0 include $(INCLUDE_DIR)/package.mk From cce66fae9034911882536130dae78b08b11e2f31 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 21 Feb 2024 15:39:35 +0800 Subject: [PATCH 037/218] [WASI-NN] ggml: fix incorrect inputs tokens number after calling embedding (#3228) Signed-off-by: hydai --- plugins/wasi_nn/ggml.cpp | 3 ++- plugins/wasi_nn/ggml.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 2d83eafb4de6..fd50b702018d 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -178,7 +178,7 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, Expect buildOutputMetadata(Context &CxtRef, std::string &Metadata) noexcept { std::ostringstream OS; - OS << R"({"input_tokens": )" << CxtRef.LlamaInputs.size() + OS << R"({"input_tokens": )" << CxtRef.LlamaNInputs << R"(, "output_tokens": )" << CxtRef.LlamaOutputTokens.size() << R"(, "llama_build_number": )" << LLAMA_BUILD_NUMBER << R"(, "llama_commit": ")" << LLAMA_COMMIT << R"("})"; @@ -523,6 +523,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, const std::string Prompt(reinterpret_cast(Tensor.Tensor.data()), Tensor.Tensor.size()); CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); + CxtRef.LlamaNInputs = CxtRef.LlamaInputs.size(); if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: set the input...Done"sv); } diff --git a/plugins/wasi_nn/ggml.h b/plugins/wasi_nn/ggml.h index ad3f28d9b073..4df0b76dbae4 100644 --- a/plugins/wasi_nn/ggml.h +++ b/plugins/wasi_nn/ggml.h @@ -53,6 +53,7 @@ struct Context { llama_context *LlamaContext = nullptr; struct llama_sampling_context *LlamaSampling = nullptr; std::vector LlamaEmbd; + uint64_t LlamaNInputs; uint64_t LlamaNPast; uint64_t LlamaNConsumed; }; From b67ef9aa817b54fc43e66549ae0a43428f894950 Mon Sep 17 00:00:00 2001 From: dm4 Date: Fri, 19 Jan 2024 14:38:44 +0800 Subject: [PATCH 038/218] [WASI-NN] ggml: add llava support Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 29 +- plugins/wasi_nn/ggml.cpp | 590 ++++++++++++++++++++------------- plugins/wasi_nn/ggml.h | 12 +- thirdparty/ggml/ggml.patch | 77 ++++- 4 files changed, 461 insertions(+), 247 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index f3963fb3b434..3275f86c8185 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -12,6 +12,8 @@ if(BACKEND STREQUAL "ggml") if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_CUBLAS) message(STATUS "WASI-NN GGML LLAMA backend: Enable LLAMA_CUBLAS") set(LLAMA_CUBLAS ON) + # We need to set GGML_USE_CUBLAS for clip from llava. + add_compile_definitions(GGML_USE_CUBLAS) # If CUBLAS is ON, then OpenBLAS should be OFF. set(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_BLAS OFF) else() @@ -142,8 +144,31 @@ target_include_directories(wasmedgePluginWasiNN ) if(BACKEND STREQUAL "ggml") - target_include_directories(wasmedgePluginWasiNN PUBLIC ${CMAKE_BINARY_DIR}/_deps/llama-src) - target_link_libraries(wasmedgePluginWasiNN PRIVATE common simdjson::simdjson) + # Setup llava from llama.cpp + wasmedge_add_library(llava OBJECT + ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava/clip.cpp + ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava/llava.cpp + ) + target_link_libraries(llava PRIVATE ggml llama) + target_include_directories(llava PUBLIC + ${CMAKE_BINARY_DIR}/_deps/llama-src + ${CMAKE_BINARY_DIR}/_deps/llama-src/common + ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava + ) + target_compile_options(llava PRIVATE + -Wno-error=unused-function + -Wno-error=unused-variable + -Wno-unused-function + -Wno-unused-variable + ) + wasmedge_setup_target(llava) + + # Setup include and link from llama.cpp + target_include_directories(wasmedgePluginWasiNN PUBLIC + ${CMAKE_BINARY_DIR}/_deps/llama-src + ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava + ) + target_link_libraries(wasmedgePluginWasiNN PRIVATE common simdjson::simdjson llava) if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL) add_custom_command( TARGET wasmedgePluginWasiNN diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index fd50b702018d..f7b6a68fc9df 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -6,9 +6,11 @@ #ifdef WASMEDGE_PLUGIN_WASI_NN_BACKEND_GGML #include "simdjson.h" +#include #include #include #include +#include #include #endif @@ -27,8 +29,29 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, } // Get metadata from the json. - // Need to update Model: - // * n_gpu_layers + + // Currently supported metadata: + // Plugin parameters (used by this plugin): + // enable-log: bool + // enable-debug-log: bool + // stream-stdout: bool + // embedding: bool + // n-predict: uint64_t + // reverse-prompt: string + // mmproj: string + // image: string + // Model parameters (need to reload the model if updated): + // n-gpu-layers: int64_t + // Context parameters (used by the llama context): + // ctx-size: uint64_t + // batch-size: uint64_t + // threads: uint64_t + // Sampling parameters (used by the llama sampling context). + // temp: double + // top-p: double + // repeat-penalty: double + // presence-penalty: double + // frequency-penalty: double // Get the current llama parameters. llama_model_params ModelParams = llama_model_default_params(); @@ -86,6 +109,26 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, } GraphRef.ReversePrompt = ReversePrompt; } + if (Doc.at_key("mmproj").error() == simdjson::SUCCESS) { + std::string_view MMProjModelPath; + auto Err = Doc["mmproj"].get().get(MMProjModelPath); + if (Err) { + spdlog::error( + "[WASI-NN] GGML backend: Unable to retrieve the mmproj option."sv); + return ErrNo::InvalidArgument; + } + GraphRef.MMProjModelPath = MMProjModelPath; + } + if (Doc.at_key("image").error() == simdjson::SUCCESS) { + std::string_view ImagePath; + auto Err = Doc["image"].get().get(ImagePath); + if (Err) { + spdlog::error( + "[WASI-NN] GGML backend: Unable to retrieve the image option."sv); + return ErrNo::InvalidArgument; + } + GraphRef.ImagePath = ImagePath; + } // The model parameters. if (Doc.at_key("n-gpu-layers").error() == simdjson::SUCCESS) { @@ -122,6 +165,7 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, return ErrNo::InvalidArgument; } } + // The sampling parameters. if (Doc.at_key("temp").error() == simdjson::SUCCESS) { auto Err = Doc["temp"].get().get(GraphRef.Temp); @@ -175,6 +219,23 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, return ErrNo::Success; } +Expect setupGPTParam(Graph &GraphRef, gpt_params &GPTParams) { + GPTParams.sparams.temp = GraphRef.Temp; + GPTParams.sparams.top_p = GraphRef.TopP; + GPTParams.sparams.penalty_repeat = GraphRef.RepeatPenalty; + GPTParams.sparams.penalty_present = GraphRef.PresencePenalty; + return ErrNo::Success; +} + +Expect setupContextParam(Graph &GraphRef, + llama_context_params &ContextParams) { + ContextParams.n_ctx = GraphRef.CtxSize; + ContextParams.n_batch = GraphRef.BatchSize; + ContextParams.n_threads = GraphRef.Threads; + ContextParams.n_threads_batch = GraphRef.Threads; + return ErrNo::Success; +} + Expect buildOutputMetadata(Context &CxtRef, std::string &Metadata) noexcept { std::ostringstream OS; @@ -312,6 +373,48 @@ Expect getEmbedding(WasiNNEnvironment &Env, return ErrNo::Success; } +ErrNo EvaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, + std::vector Tokens, int &NPast) noexcept { + uint32_t NCtx = llama_n_ctx(LlamaContext); + + // End the inference if the context is full. + if (NPast + static_cast(Tokens.size()) > NCtx) { + if (GraphRef.EnableLog) { + spdlog::info( + "[WASI-NN] GGML backend: the context if full ({} / {} tokens). Please increase your context size."sv, + NPast + static_cast(Tokens.size()), NCtx); + } + return ErrNo::ContextFull; + } + + for (int I = 0; I < static_cast(Tokens.size()); + I += GraphRef.BatchSize) { + int NEval = static_cast(Tokens.size()) - I; + if (NEval > static_cast(GraphRef.BatchSize)) { + NEval = GraphRef.BatchSize; + } + // llama_batch_get_one(*token, n_tokens, position, sequence_id) + // This will return batch for single sequence of tokens starting at + // position. + const llama_seq_id SequenceId = 0; + auto Status = + llama_decode(LlamaContext, + llama_batch_get_one(&Tokens[I], NEval, NPast, SequenceId)); + if (Status == 1) { + spdlog::error( + "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); + return ErrNo::RuntimeError; + } else if (Status < 0) { + spdlog::error( + "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); + return ErrNo::RuntimeError; + } + NPast += NEval; + } + + return ErrNo::Success; +} + } // namespace details Expect load(WasiNNEnvironment &Env, Span> Builders, @@ -323,9 +426,12 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, // Initialize the plugin parameters. auto ContextDefault = llama_context_default_params(); GraphRef.EnableLog = false; + GraphRef.EnableDebugLog = false; GraphRef.StreamStdout = false; - GraphRef.ReversePrompt = ""sv; GraphRef.NPredict = ContextDefault.n_ctx; + GraphRef.ReversePrompt = ""sv; + GraphRef.MMProjModelPath = ""sv; + GraphRef.ImagePath = ""sv; // Initialize the model parameters. GraphRef.NGPULayers = 0; #ifdef __APPLE__ @@ -503,13 +609,8 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, spdlog::info("[WASI-NN][Debug] GGML backend: init llama context"sv); } llama_context_params ContextParams = llama_context_default_params(); - ContextParams.n_ctx = GraphRef.CtxSize; - ContextParams.n_batch = GraphRef.BatchSize; - ContextParams.n_threads = GraphRef.Threads; - ContextParams.n_threads_batch = GraphRef.Threads; - ContextParams.embedding = GraphRef.Embedding; - - auto *LlamaContext = + details::setupContextParam(GraphRef, ContextParams); + auto LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: init llama context...Done"sv); @@ -522,8 +623,64 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, const bool AddBos = llama_should_add_bos_token(GraphRef.LlamaModel); const std::string Prompt(reinterpret_cast(Tensor.Tensor.data()), Tensor.Tensor.size()); - CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); - CxtRef.LlamaNInputs = CxtRef.LlamaInputs.size(); + if (GraphRef.MMProjModelPath == ""sv) { + // Text only prompt. + CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); + CxtRef.LlamaNInputs = CxtRef.LlamaInputs.size(); + } else { + // Handle llava format prompt. + + // Show some warnings. + if (GraphRef.EnableLog) { + if (GraphRef.ImagePath == ""sv) { + spdlog::info( + "[WASI-NN] GGML backend: Image path is not set, will process as text-only prompt"sv); + } + if (GraphRef.CtxSize < 4096) { + spdlog::info( + "[WASI-NN] GGML backend: Context size is {}, " + "we recommand context size >= 2048 when using llava-v1.5 " + "and context size >= 4096 when using llava-v1.6 for better results."sv, + GraphRef.CtxSize); + } + } + + // We split prompt by as placeholder and save the position. + const std::string_view PromptPlaceholder = ""; + auto PlaceholderPosition = Prompt.find(PromptPlaceholder); + if (PlaceholderPosition == std::string::npos) { + spdlog::error( + "[WASI-NN] GGML backend: Error: unable to find the placeholder in the llava prompt."sv); + return ErrNo::InvalidArgument; + } + std::string PromptBeforeImage = Prompt.substr(0, PlaceholderPosition); + std::string PromptAfterImage = + Prompt.substr(PlaceholderPosition + PromptPlaceholder.length()); + std::vector EmbdInputBeforeImage = + llama_tokenize(LlamaContext, PromptBeforeImage, AddBos, true); + std::vector EmbdInputAfterImage = + llama_tokenize(LlamaContext, PromptAfterImage, false, true); + CxtRef.LlavaImagePosition = EmbdInputBeforeImage.size(); + CxtRef.LlamaInputs.reserve(EmbdInputBeforeImage.size() + + EmbdInputAfterImage.size()); + CxtRef.LlamaInputs.insert(CxtRef.LlamaInputs.end(), + EmbdInputBeforeImage.begin(), + EmbdInputBeforeImage.end()); + CxtRef.LlamaInputs.insert(CxtRef.LlamaInputs.end(), + EmbdInputAfterImage.begin(), + EmbdInputAfterImage.end()); + + // Load image for llava. + int LlavaVerbosity = 0; + if (GraphRef.EnableLog) { + LlavaVerbosity = 1; + } + auto ClipContext = + clip_model_load(GraphRef.MMProjModelPath.c_str(), LlavaVerbosity); + CxtRef.LlavaImageEmbd = llava_image_embed_make_with_filename( + ClipContext, GraphRef.Threads, GraphRef.ImagePath.c_str()); + clip_free(ClipContext); + } if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: set the input...Done"sv); } @@ -597,35 +754,22 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { "[WASI-NN][Debug] GGML backend: clear the previous output and tokens...Done"sv); } - // Main predict loop. - if (GraphRef.EnableDebugLog) { - spdlog::info("[WASI-NN][Debug] GGML backend: enter main predict loop"sv); - } + // Initialize the llama context. gpt_params GPTParams; - GPTParams.sparams.temp = GraphRef.Temp; - GPTParams.sparams.top_p = GraphRef.TopP; - GPTParams.sparams.penalty_repeat = GraphRef.RepeatPenalty; - GPTParams.sparams.penalty_present = GraphRef.PresencePenalty; - GPTParams.sparams.penalty_freq = GraphRef.FrequencyPenalty; + llama_context_params ContextParams = llama_context_default_params(); + details::setupGPTParam(GraphRef, GPTParams); + details::setupContextParam(GraphRef, ContextParams); + auto LlamaContext = + llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); struct llama_sampling_context *CtxSampling = llama_sampling_init(GPTParams.sparams); - std::vector Embd; - uint64_t NPast = 0; - uint64_t NConsumed = 0; + // Prepare variables; + int32_t NPast = 0; int32_t NRemain = GraphRef.NPredict; - // Initialize the llama context. - llama_context_params ContextParams = llama_context_default_params(); - ContextParams.n_ctx = GraphRef.CtxSize; - ContextParams.n_batch = GraphRef.BatchSize; - auto *LlamaContext = - llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); - // Get the context size. const uint64_t NCtx = llama_n_ctx(LlamaContext); // Minus 4 for the special tokens. (Such as , , ... tokens.) const uint64_t MaxTokensListSize = NCtx - 4; - // Use the const sequence id here. - const llama_seq_id SequenceId = 0; // Return value. auto ReturnCode = ErrNo::Success; @@ -639,109 +783,91 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { return ErrNo::PromptTooLong; } + // Evaluate input tokens. + if (CxtRef.LlavaImageEmbd == nullptr) { + // Text only prompt. + ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, + CxtRef.LlamaInputs, NPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate input tokens."sv); + return ReturnCode; + } + } else { + // Llava format prompt with image data. + std::vector EmbdInputBeforeImage( + CxtRef.LlamaInputs.begin(), + CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition); + std::vector EmbdInputAfterImage(CxtRef.LlamaInputs.begin() + + CxtRef.LlavaImagePosition, + CxtRef.LlamaInputs.end()); + ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, + EmbdInputBeforeImage, NPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate input tokens before image."sv); + return ReturnCode; + } + bool EvalImageStatus = llava_eval_image_embed( + LlamaContext, CxtRef.LlavaImageEmbd, GraphRef.BatchSize, &NPast); + if (!EvalImageStatus) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate embed image tokens."sv); + return ErrNo::RuntimeError; + } + ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, + EmbdInputAfterImage, NPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate input tokens after image."sv); + return ReturnCode; + } + } + // Main predict loop. + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: enter main predict loop"sv); + } while (NRemain > 0) { - // Preidct - if (!Embd.empty()) { - // Input too long. - if (static_cast(Embd.size()) > MaxTokensListSize) { - if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the prompt is too long. Your input has {} tokens. Please reduce it to {} tokens."sv, - Embd.size(), MaxTokensListSize); - } - ReturnCode = ErrNo::PromptTooLong; - break; - } - - // We do not swap context here. End the inference if the context is full. - if (NPast + static_cast(Embd.size()) > NCtx) { - if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the context if full ({} / {} tokens). Please increase your ctx-size."sv, - NPast + static_cast(Embd.size()), NCtx); - } - ReturnCode = ErrNo::ContextFull; - break; - } - - // Evaluate tokens in batches. - for (int I = 0; I < static_cast(Embd.size()); - I += GraphRef.BatchSize) { - uint64_t NEval = static_cast(Embd.size()) - I; - if (NEval > static_cast(GraphRef.BatchSize)) { - NEval = GraphRef.BatchSize; - } - // llama_batch_get_one(*token, n_tokens, position, sequence_id) - // This will return batch for single sequence of tokens starting at - // position. - auto Status = - llama_decode(LlamaContext, llama_batch_get_one(&Embd[I], NEval, - NPast, SequenceId)); - if (Status == 1) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); - return ErrNo::RuntimeError; - } - if (Status < 0) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); - return ErrNo::RuntimeError; - } - - NPast += NEval; - } + const llama_token Id = + llama_sampling_sample(CtxSampling, LlamaContext, nullptr); + llama_sampling_accept(CtxSampling, LlamaContext, Id, true); + --NRemain; + + // Save the output token. + CxtRef.LlamaOutputTokens.emplace_back(Id); + CxtRef.LlamaOutputs += llama_token_to_piece(LlamaContext, Id); + // When setting StreamStdout, we print the output to stdout. + if (GraphRef.StreamStdout) { + std::cout << llama_token_to_piece(LlamaContext, Id) << std::flush; } - - Embd.clear(); - - if (static_cast(CxtRef.LlamaInputs.size()) <= NConsumed) { - const llama_token Id = - llama_sampling_sample(CtxSampling, LlamaContext, nullptr); - llama_sampling_accept(CtxSampling, LlamaContext, Id, true); - Embd.emplace_back(Id); - --NRemain; - // Save the output token. - CxtRef.LlamaOutputTokens.emplace_back(Id); - CxtRef.LlamaOutputs += llama_token_to_piece(LlamaContext, Id); - // When setting StreamStdout, we print the output to stdout. - if (GraphRef.StreamStdout) { - std::cout << llama_token_to_piece(LlamaContext, Id) << std::flush; + // Break if reverse prompt is found. + if (!GraphRef.ReversePrompt.empty() && + CxtRef.LlamaOutputs.find(GraphRef.ReversePrompt) != std::string::npos) { + if (GraphRef.EnableLog) { + spdlog::info("[WASI-NN] GGML backend: reverse prompt found"sv); } - // Break if reverse prompt is found. - if (!GraphRef.ReversePrompt.empty() && - CxtRef.LlamaOutputs.find(GraphRef.ReversePrompt) != - std::string::npos) { - if (GraphRef.EnableLog) { - spdlog::info("[WASI-NN] GGML backend: reverse prompt found"sv); - } - break; - } - // Deal with end of text token. - if (llama_sampling_last(CtxSampling) == - llama_token_eos(GraphRef.LlamaModel)) { - if (GraphRef.EnableLog) { - spdlog::info("[WASI-NN] GGML backend: EOS token found"sv); - } - break; - } - } else { - while (static_cast(CxtRef.LlamaInputs.size()) > NConsumed) { - Embd.push_back(CxtRef.LlamaInputs[NConsumed]); - // Push the prompt in the sampling context. - llama_sampling_accept(CtxSampling, LlamaContext, - CxtRef.LlamaInputs[NConsumed], false); - ++NConsumed; - if (Embd.size() >= GraphRef.BatchSize) { - break; - } + break; + } + // Deal with end of text token. + if (llama_sampling_last(CtxSampling) == + llama_token_eos(GraphRef.LlamaModel)) { + if (GraphRef.EnableLog) { + spdlog::info("[WASI-NN] GGML backend: EOS token found"sv); } + break; + } + // Evaluate the output token. + ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, {Id}, NPast); + if (ReturnCode != ErrNo::Success) { + break; } } if (GraphRef.EnableDebugLog) { spdlog::info( "[WASI-NN][Debug] GGML backend: enter main predict loop...Done"sv); } + // End of main predict loop. if (GraphRef.EnableLog) { llama_print_timings(LlamaContext); @@ -751,6 +877,10 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // Users could fully control the contexts by themselves via their prompt. llama_sampling_free(CtxSampling); llama_free(LlamaContext); + if (CxtRef.LlavaImageEmbd != nullptr) { + llava_image_embed_free(CxtRef.LlavaImageEmbd); + CxtRef.LlavaImageEmbd = nullptr; + } if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: compute...Done"sv); @@ -813,133 +943,113 @@ Expect computeSingle(WasiNNEnvironment &Env, // Initialize the llama context. gpt_params GPTParams; - GPTParams.sparams.temp = GraphRef.Temp; - GPTParams.sparams.top_p = GraphRef.TopP; - GPTParams.sparams.penalty_repeat = GraphRef.RepeatPenalty; - GPTParams.sparams.penalty_present = GraphRef.PresencePenalty; - GPTParams.sparams.penalty_freq = GraphRef.FrequencyPenalty; - CxtRef.LlamaSampling = llama_sampling_init(GPTParams.sparams); llama_context_params ContextParams = llama_context_default_params(); - ContextParams.n_ctx = GraphRef.CtxSize; - ContextParams.n_batch = GraphRef.BatchSize; - ContextParams.n_threads = GraphRef.Threads; - ContextParams.n_threads_batch = GraphRef.Threads; + details::setupGPTParam(GraphRef, GPTParams); + details::setupContextParam(GraphRef, ContextParams); CxtRef.LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); - CxtRef.LlamaEmbd.clear(); + CxtRef.LlamaSampling = llama_sampling_init(GPTParams.sparams); CxtRef.LlamaNPast = 0; - CxtRef.LlamaNConsumed = 0; - } - - // Get the context size. - const uint64_t NCtx = llama_n_ctx(CxtRef.LlamaContext); - // Minus 4 for the special tokens. (Such as , , ... tokens.) - const uint64_t MaxTokensListSize = NCtx - 4; - // Use the const sequence id here. - const llama_seq_id SequenceId = 0; - // Check if the input is too long. - if (static_cast(CxtRef.LlamaInputs.size()) > MaxTokensListSize) { - if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the prompt is too long. Your input has {} tokens. Please reduce it to {} tokens."sv, - CxtRef.LlamaInputs.size(), MaxTokensListSize); + // Get the context size. + const uint64_t NCtx = llama_n_ctx(CxtRef.LlamaContext); + // Minus 4 for the special tokens. (Such as , , ... tokens.) + const uint64_t MaxTokensListSize = NCtx - 4; + // Return value. + auto ReturnCode = ErrNo::Success; + + // Check if the input is too long. + if (static_cast(CxtRef.LlamaInputs.size()) > MaxTokensListSize) { + if (GraphRef.EnableLog) { + spdlog::info( + "[WASI-NN] GGML backend: the prompt is too long. Your input has {} tokens. Please reduce it to {} tokens."sv, + CxtRef.LlamaInputs.size(), MaxTokensListSize); + } + return ErrNo::PromptTooLong; } - return ErrNo::PromptTooLong; - } - // Main predict loop. - while (true) { - if (!CxtRef.LlamaEmbd.empty()) { - // Input too long. - if (static_cast(CxtRef.LlamaEmbd.size()) > MaxTokensListSize) { - if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the prompt is too long. Your input has {} tokens. Please reduce it to {} tokens."sv, - CxtRef.LlamaEmbd.size(), MaxTokensListSize); - } - return ErrNo::PromptTooLong; + // Evaluate input tokens. + if (CxtRef.LlavaImageEmbd == nullptr) { + // Text only prompt. + ReturnCode = details::EvaluateTokens( + GraphRef, CxtRef.LlamaContext, CxtRef.LlamaInputs, CxtRef.LlamaNPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate input tokens."sv); + return ReturnCode; } - - // We do not swap context here. End the inference if the context is full. - if (CxtRef.LlamaNPast + static_cast(CxtRef.LlamaEmbd.size()) > - NCtx) { - if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the context if full ({} / {} tokens). Please increase your ctx-size."sv, - CxtRef.LlamaNPast + - static_cast(CxtRef.LlamaEmbd.size()), - NCtx); - } - return ErrNo::ContextFull; + } else { + // Llava format prompt with image data. + std::vector EmbdInputBeforeImage( + CxtRef.LlamaInputs.begin(), + CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition); + std::vector EmbdInputAfterImage( + CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition, + CxtRef.LlamaInputs.end()); + ReturnCode = + details::EvaluateTokens(GraphRef, CxtRef.LlamaContext, + EmbdInputBeforeImage, CxtRef.LlamaNPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate input tokens before image."sv); + return ReturnCode; } - - // Evaluate tokens in batches. - for (uint64_t I = 0; I < static_cast(CxtRef.LlamaEmbd.size()); - I += GraphRef.BatchSize) { - uint64_t NEval = static_cast(CxtRef.LlamaEmbd.size()) - I; - if (NEval > static_cast(GraphRef.BatchSize)) { - NEval = GraphRef.BatchSize; - } - // llama_batch_get_one(*token, n_tokens, position, sequence_id) - // This will return batch for single sequence of tokens starting at - // position. - auto Status = - llama_decode(CxtRef.LlamaContext, - llama_batch_get_one(&CxtRef.LlamaEmbd[I], NEval, - CxtRef.LlamaNPast, SequenceId)); - if (Status == 1) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); - return ErrNo::RuntimeError; - } - if (Status < 0) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); - return ErrNo::RuntimeError; - } - - CxtRef.LlamaNPast += NEval; + bool EvalImageStatus = + llava_eval_image_embed(CxtRef.LlamaContext, CxtRef.LlavaImageEmbd, + GraphRef.BatchSize, &CxtRef.LlamaNPast); + if (!EvalImageStatus) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate embed image tokens ."sv); + return ErrNo::RuntimeError; + } + ReturnCode = + details::EvaluateTokens(GraphRef, CxtRef.LlamaContext, + EmbdInputAfterImage, CxtRef.LlamaNPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: failed to evaluate input tokens after image."sv); + return ReturnCode; } } + } - CxtRef.LlamaEmbd.clear(); - - if (static_cast(CxtRef.LlamaInputs.size()) <= - CxtRef.LlamaNConsumed) { - const llama_token Id = llama_sampling_sample( - CxtRef.LlamaSampling, CxtRef.LlamaContext, nullptr); - llama_sampling_accept(CxtRef.LlamaSampling, CxtRef.LlamaContext, Id, - true); - CxtRef.LlamaEmbd.emplace_back(Id); - // Save the output token. - CxtRef.LlamaOutputTokens.emplace_back(Id); - CxtRef.LlamaOutputs += llama_token_to_piece(CxtRef.LlamaContext, Id); - // Deal with end of text token. - if (llama_sampling_last(CxtRef.LlamaSampling) == - llama_token_eos(GraphRef.LlamaModel)) { - if (GraphRef.EnableLog) { - spdlog::info("[WASI-NN] GGML backend: EOS token found"sv); - } - return ErrNo::EndOfSequence; - } - return ErrNo::Success; - } else { - while (static_cast(CxtRef.LlamaInputs.size()) > - CxtRef.LlamaNConsumed) { - CxtRef.LlamaEmbd.push_back(CxtRef.LlamaInputs[CxtRef.LlamaNConsumed]); - // Push the prompt in the sampling context. - llama_sampling_accept(CxtRef.LlamaSampling, CxtRef.LlamaContext, - CxtRef.LlamaInputs[CxtRef.LlamaNConsumed], false); - ++CxtRef.LlamaNConsumed; - if (CxtRef.LlamaEmbd.size() >= GraphRef.BatchSize) { - break; - } - } + // Main predict process. + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: enter main predict process"sv); + } + auto ReturnCode = ErrNo::Success; + const llama_token Id = + llama_sampling_sample(CxtRef.LlamaSampling, CxtRef.LlamaContext, nullptr); + llama_sampling_accept(CxtRef.LlamaSampling, CxtRef.LlamaContext, Id, true); + + // Save the output token. + // In single token mode, we do not handle StreamStdout and ReversePrompt. + CxtRef.LlamaOutputTokens.emplace_back(Id); + CxtRef.LlamaOutputs += llama_token_to_piece(CxtRef.LlamaContext, Id); + // Deal with end of text token. + if (llama_sampling_last(CxtRef.LlamaSampling) == + llama_token_eos(GraphRef.LlamaModel)) { + ReturnCode = ErrNo::EndOfSequence; + if (GraphRef.EnableLog) { + spdlog::info("[WASI-NN] GGML backend: EOS token found"sv); } } + // Evaluate the output token if not EOS. + if (ReturnCode != ErrNo::EndOfSequence) { + ReturnCode = details::EvaluateTokens(GraphRef, CxtRef.LlamaContext, {Id}, + CxtRef.LlamaNPast); + } + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: enter main predict process...Done"sv); + } + // End of main predict process. - return ErrNo::Success; + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: computeSingleToken...Done"sv); + } + + return ReturnCode; } Expect finiSingle(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { @@ -972,15 +1082,17 @@ Expect finiSingle(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { llama_free(CxtRef.LlamaContext); CxtRef.LlamaSampling = nullptr; CxtRef.LlamaContext = nullptr; + if (CxtRef.LlavaImageEmbd != nullptr) { + llava_image_embed_free(CxtRef.LlavaImageEmbd); + CxtRef.LlavaImageEmbd = nullptr; + } if (GraphRef.EnableDebugLog) { spdlog::info( "[WASI-NN][Debug] GGML backend: finiSingle: free the llama context...Done"sv); } // Reset the context variables. - CxtRef.LlamaEmbd.clear(); CxtRef.LlamaNPast = 0; - CxtRef.LlamaNConsumed = 0; return ErrNo::Success; } diff --git a/plugins/wasi_nn/ggml.h b/plugins/wasi_nn/ggml.h index 4df0b76dbae4..7f26f2a7fd4d 100644 --- a/plugins/wasi_nn/ggml.h +++ b/plugins/wasi_nn/ggml.h @@ -9,6 +9,7 @@ #ifdef WASMEDGE_PLUGIN_WASI_NN_BACKEND_GGML #include #include +#include #endif namespace WasmEdge::Host::WASINN { @@ -28,6 +29,8 @@ struct Graph { bool Embedding = false; uint64_t NPredict; std::string ReversePrompt; + std::string MMProjModelPath; + std::string ImagePath; // Model parameters: int64_t NGPULayers = 0; // Context parameters: @@ -47,15 +50,16 @@ struct Context { Context(size_t GId, Graph &) noexcept : GraphId(GId) {} size_t GraphId; std::vector LlamaInputs; + uint64_t LlamaNInputs = 0; std::string LlamaOutputs; std::vector LlamaOutputTokens; // Preserve for computing single token llama_context *LlamaContext = nullptr; struct llama_sampling_context *LlamaSampling = nullptr; - std::vector LlamaEmbd; - uint64_t LlamaNInputs; - uint64_t LlamaNPast; - uint64_t LlamaNConsumed; + int32_t LlamaNPast = 0; + // Preserve for llava + struct llava_image_embed *LlavaImageEmbd = nullptr; + size_t LlavaImagePosition = 0; }; #else struct Graph {}; diff --git a/thirdparty/ggml/ggml.patch b/thirdparty/ggml/ggml.patch index dafaff70dbdc..a8af344e3309 100644 --- a/thirdparty/ggml/ggml.patch +++ b/thirdparty/ggml/ggml.patch @@ -1,8 +1,81 @@ +diff --git a/examples/llava/clip.cpp b/examples/llava/clip.cpp +index 9129052a..482a84e5 100644 +--- a/examples/llava/clip.cpp ++++ b/examples/llava/clip.cpp +@@ -768,6 +768,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + + // kv + const int n_kv = gguf_get_n_kv(ctx); ++ if (verbosity >= 1) { + printf("%s: loaded meta data with %d key-value pairs and %d tensors from %s\n", + __func__, n_kv, n_tensors, fname); + { +@@ -807,6 +808,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + printf("%s: - type %4s: %4d tensors\n", __func__, ggml_type_name(kv.first), kv.second); + } + } ++ } + + // data + size_t buffer_size = 0; +@@ -848,18 +850,18 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + + #ifdef GGML_USE_CUBLAS + new_clip->backend = ggml_backend_cuda_init(0); +- printf("%s: CLIP using CUDA backend\n", __func__); ++ if (verbosity >= 1) printf("%s: CLIP using CUDA backend\n", __func__); + #endif + + #ifdef GGML_USE_METAL + new_clip->backend = ggml_backend_metal_init(); +- printf("%s: CLIP using Metal backend\n", __func__); ++ if (verbosity >= 1) printf("%s: CLIP using Metal backend\n", __func__); + #endif + + + if (!new_clip->backend) { + new_clip->backend = ggml_backend_cpu_init(); +- printf("%s: CLIP using CPU backend\n", __func__); ++ if (verbosity >= 1) printf("%s: CLIP using CPU backend\n", __func__); + } + + // model size and capabilities +@@ -891,7 +893,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + } + } + +- printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, buffer_size / (1024.0 * 1024.0), n_tensors); ++ if (verbosity >= 1) printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, buffer_size / (1024.0 * 1024.0), n_tensors); + + // load tensors + { +@@ -1086,7 +1088,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + new_clip->compute_buffer = ggml_backend_alloc_buffer(new_clip->backend, compute_memory_buffer_size); + new_clip->compute_alloc = ggml_allocr_new_from_buffer(new_clip->compute_buffer); + +- printf("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); ++ if (verbosity >= 1) printf("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); + } + + return new_clip; +diff --git a/examples/llava/llava.cpp b/examples/llava/llava.cpp +index d42e7582..30833df0 100644 +--- a/examples/llava/llava.cpp ++++ b/examples/llava/llava.cpp +@@ -31,7 +31,7 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli + const int64_t t_img_enc_end_us = ggml_time_us(); + float t_img_enc_ms = (t_img_enc_end_us - t_img_enc_start_us) / 1000.0; + +- printf("\n%s: image encoded in %8.2f ms by CLIP (%8.2f ms per image patch)\n", __func__, t_img_enc_ms, t_img_enc_ms / *n_img_pos); ++ // printf("\n%s: image encoded in %8.2f ms by CLIP (%8.2f ms per image patch)\n", __func__, t_img_enc_ms, t_img_enc_ms / *n_img_pos); + + return true; + } diff --git a/llama.cpp b/llama.cpp -index 5329bd8..fa2b3d2 100644 +index 02b0a485..2088b5a9 100644 --- a/llama.cpp +++ b/llama.cpp -@@ -9625,7 +9625,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { +@@ -11516,7 +11516,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { static void llama_log_callback_default(ggml_log_level level, const char * text, void * user_data) { (void) level; From 111b646393c296bc172d4910927705fdae5376c5 Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 21 Feb 2024 16:41:05 +0800 Subject: [PATCH 039/218] [WASI-NN] ggml: bump llama.cpp b2220 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- thirdparty/ggml/ggml.patch | 50 +++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 3275f86c8185..c027741074f4 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2037 + GIT_TAG b2220 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) diff --git a/thirdparty/ggml/ggml.patch b/thirdparty/ggml/ggml.patch index a8af344e3309..4368f3ed92c8 100644 --- a/thirdparty/ggml/ggml.patch +++ b/thirdparty/ggml/ggml.patch @@ -1,8 +1,8 @@ diff --git a/examples/llava/clip.cpp b/examples/llava/clip.cpp -index 9129052a..482a84e5 100644 +index ef9e4ba7..a1b49793 100644 --- a/examples/llava/clip.cpp +++ b/examples/llava/clip.cpp -@@ -768,6 +768,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { +@@ -859,6 +859,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { // kv const int n_kv = gguf_get_n_kv(ctx); @@ -10,15 +10,15 @@ index 9129052a..482a84e5 100644 printf("%s: loaded meta data with %d key-value pairs and %d tensors from %s\n", __func__, n_kv, n_tensors, fname); { -@@ -807,6 +808,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { +@@ -898,6 +899,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { printf("%s: - type %4s: %4d tensors\n", __func__, ggml_type_name(kv.first), kv.second); } } + } // data - size_t buffer_size = 0; -@@ -848,18 +850,18 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + size_t model_size = 0; +@@ -937,18 +939,18 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { #ifdef GGML_USE_CUBLAS new_clip->backend = ggml_backend_cuda_init(0); @@ -40,29 +40,35 @@ index 9129052a..482a84e5 100644 } // model size and capabilities -@@ -891,7 +893,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { +@@ -980,7 +982,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { } } -- printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, buffer_size / (1024.0 * 1024.0), n_tensors); -+ if (verbosity >= 1) printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, buffer_size / (1024.0 * 1024.0), n_tensors); +- printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, model_size / (1024.0 * 1024.0), n_tensors); ++ if (verbosity >= 1) printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, model_size / (1024.0 * 1024.0), n_tensors); // load tensors { -@@ -1086,7 +1088,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - new_clip->compute_buffer = ggml_backend_alloc_buffer(new_clip->backend, compute_memory_buffer_size); - new_clip->compute_alloc = ggml_allocr_new_from_buffer(new_clip->compute_buffer); - +@@ -1216,7 +1218,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + ggml_cgraph * gf = clip_image_build_graph(new_clip, &batch); + ggml_gallocr_reserve(new_clip->compute_alloc, gf); + size_t compute_memory_buffer_size = ggml_gallocr_get_buffer_size(new_clip->compute_alloc, 0); - printf("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); + if (verbosity >= 1) printf("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); } return new_clip; diff --git a/examples/llava/llava.cpp b/examples/llava/llava.cpp -index d42e7582..30833df0 100644 +index 1a1cf7c7..b84a9404 100644 --- a/examples/llava/llava.cpp +++ b/examples/llava/llava.cpp -@@ -31,7 +31,7 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli +@@ -290,12 +290,12 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli + // clip_image_save_to_bmp(*tmp, "image_feature.bmp"); + } + +- printf("%s: image embedding created: %d tokens\n", __func__, *n_img_pos); ++ // printf("%s: image embedding created: %d tokens\n", __func__, *n_img_pos); + const int64_t t_img_enc_end_us = ggml_time_us(); float t_img_enc_ms = (t_img_enc_end_us - t_img_enc_start_us) / 1000.0; @@ -71,11 +77,23 @@ index d42e7582..30833df0 100644 return true; } +diff --git a/examples/llava/llava.h b/examples/llava/llava.h +index 2d40f3f1..8897b3d8 100644 +--- a/examples/llava/llava.h ++++ b/examples/llava/llava.h +@@ -18,6 +18,7 @@ + #endif + + struct clip_ctx; ++struct clip_image_u8; + + #ifdef __cplusplus + extern "C" { diff --git a/llama.cpp b/llama.cpp -index 02b0a485..2088b5a9 100644 +index 4296eca3..5ac03032 100644 --- a/llama.cpp +++ b/llama.cpp -@@ -11516,7 +11516,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { +@@ -12757,7 +12757,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { static void llama_log_callback_default(ggml_log_level level, const char * text, void * user_data) { (void) level; From 22b9565de6ad298fa8c46ab229a61b3e5bd30fd6 Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 21 Feb 2024 17:04:53 +0800 Subject: [PATCH 040/218] [WASI-NN] ggml: fix typo Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index f7b6a68fc9df..c034344a60ff 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -639,7 +639,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, if (GraphRef.CtxSize < 4096) { spdlog::info( "[WASI-NN] GGML backend: Context size is {}, " - "we recommand context size >= 2048 when using llava-v1.5 " + "we recommend context size >= 2048 when using llava-v1.5 " "and context size >= 4096 when using llava-v1.6 for better results."sv, GraphRef.CtxSize); } @@ -999,7 +999,7 @@ Expect computeSingle(WasiNNEnvironment &Env, GraphRef.BatchSize, &CxtRef.LlamaNPast); if (!EvalImageStatus) { spdlog::error( - "[WASI-NN] GGML backend: failed to evaluate embed image tokens ."sv); + "[WASI-NN] GGML backend: failed to evaluate embed image tokens."sv); return ErrNo::RuntimeError; } ReturnCode = From a30b6e4ac10d98975977f2ae43c6b188db1e6abf Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 22 Feb 2024 00:26:37 +0800 Subject: [PATCH 041/218] [WASI-NN] ggml: support main-gpu and tensor-split (#3229) Signed-off-by: hydai --- plugins/wasi_nn/ggml.cpp | 67 ++++++++++++++++++++++++++++++++++------ plugins/wasi_nn/ggml.h | 2 ++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index c034344a60ff..54209eec181e 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -6,6 +6,7 @@ #ifdef WASMEDGE_PLUGIN_WASI_NN_BACKEND_GGML #include "simdjson.h" +#include #include #include #include @@ -42,6 +43,8 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, // image: string // Model parameters (need to reload the model if updated): // n-gpu-layers: int64_t + // main-gpu: int64_t + // tensor-split: string, comma-separated floating number list // Context parameters (used by the llama context): // ctx-size: uint64_t // batch-size: uint64_t @@ -56,6 +59,8 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, // Get the current llama parameters. llama_model_params ModelParams = llama_model_default_params(); ModelParams.n_gpu_layers = GraphRef.NGPULayers; + ModelParams.main_gpu = GraphRef.MainGPU; + ModelParams.tensor_split = GraphRef.TensorSplit.data(); // The plugin parameters. if (Doc.at_key("enable-log").error() == simdjson::SUCCESS) { @@ -139,6 +144,44 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, return ErrNo::InvalidArgument; } } + if (Doc.at_key("main-gpu").error() == simdjson::SUCCESS) { + auto Err = Doc["main-gpu"].get().get(GraphRef.MainGPU); + if (Err) { + spdlog::error( + "[WASI-NN] GGML backend: Unable to retrieve the main-gpu option."sv); + return ErrNo::InvalidArgument; + } + } + if (Doc.at_key("tensor-split").error() == simdjson::SUCCESS) { + // The TensorSplit is a comma-separated list of non-negative values. + // E.g., "3,2" presents 60% of the data to GPU 0 and 40% to GPU 1. + std::string_view TSV; + auto Err = Doc["tensor-split"].get().get(TSV); + if (Err) { + spdlog::error( + "[WASI-NN] GGML backend: Unable to retrieve the tensor-split option."sv); + return ErrNo::InvalidArgument; + } + std::string TS(TSV); + std::replace(TS.begin(), TS.end(), ',', ' '); + std::stringstream SS(TS); + GraphRef.TensorSplit.clear(); + while (SS.good()) { + float TmpTensor; + SS >> TmpTensor; + GraphRef.TensorSplit.push_back(TmpTensor); + } + uint32_t NDevices = llama_max_devices(); + if (GraphRef.TensorSplit.size() > NDevices) { + spdlog::error( + "[WASI-NN] GGML backend: Number of Tensor-Split is larger " + "than MaxDevices, please reduce the size of tensor-split."sv); + return ErrNo::InvalidArgument; + } + for (uint32_t Idx = GraphRef.TensorSplit.size(); Idx < NDevices; Idx++) { + GraphRef.TensorSplit.push_back(0.0f); + } + } // The context parameters. if (Doc.at_key("ctx-size").error() == simdjson::SUCCESS) { @@ -318,9 +361,9 @@ Expect getEmbedding(WasiNNEnvironment &Env, // Check if the input is too long. if (static_cast(CxtRef.LlamaInputs.size()) > MaxTokensListSize) { if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the prompt is too long. Your input has {} tokens. Please reduce it to {} tokens."sv, - CxtRef.LlamaInputs.size(), MaxTokensListSize); + spdlog::info("[WASI-NN] GGML backend: the prompt is too long. Your input " + "has {} tokens. Please reduce it to {} tokens."sv, + CxtRef.LlamaInputs.size(), MaxTokensListSize); } return ErrNo::PromptTooLong; } @@ -335,12 +378,13 @@ Expect getEmbedding(WasiNNEnvironment &Env, NTokens, NPast, SequenceId)); if (Status == 1) { spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); + "[WASI-NN] GGML backend: failed to llama_decode: try " + "reducing the size of the batch or increasing the size of context"sv); return ErrNo::RuntimeError; } if (Status < 0) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); + spdlog::error("[WASI-NN] GGML backend: failed to llama_decode: internal " + "fatal error. Please open an issue on GitHub"sv); return ErrNo::RuntimeError; } @@ -481,7 +525,8 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, } else { if (GraphRef.EnableDebugLog) { spdlog::info( - "[WASI-NN][Debug] GGML backend: Model path not found in nn-preload, write model into a tmpfile."sv); + "[WASI-NN][Debug] GGML backend: Model path not found in nn-preload, " + "write model into a tmpfile."sv); } // TODO: pass the model directly to ggml // Write ggml model to file. @@ -516,6 +561,8 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, GraphRef.ModelFilePath = ModelFilePath; llama_model_params ModelParams = llama_model_default_params(); ModelParams.n_gpu_layers = GraphRef.NGPULayers; + ModelParams.main_gpu = GraphRef.MainGPU; + ModelParams.tensor_split = GraphRef.TensorSplit.data(); GraphRef.LlamaModel = llama_load_model_from_file(GraphRef.ModelFilePath.c_str(), ModelParams); if (GraphRef.LlamaModel == nullptr) { @@ -776,9 +823,9 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // Check if the input is too long. if (static_cast(CxtRef.LlamaInputs.size()) > MaxTokensListSize) { if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the prompt is too long. Your input has {} tokens. Please reduce it to {} tokens."sv, - CxtRef.LlamaInputs.size(), MaxTokensListSize); + spdlog::info("[WASI-NN] GGML backend: the prompt is too long. Your input " + "has {} tokens. Please reduce it to {} tokens."sv, + CxtRef.LlamaInputs.size(), MaxTokensListSize); } return ErrNo::PromptTooLong; } diff --git a/plugins/wasi_nn/ggml.h b/plugins/wasi_nn/ggml.h index 7f26f2a7fd4d..67c70fcc30fd 100644 --- a/plugins/wasi_nn/ggml.h +++ b/plugins/wasi_nn/ggml.h @@ -32,7 +32,9 @@ struct Graph { std::string MMProjModelPath; std::string ImagePath; // Model parameters: + int64_t MainGPU = 0; // Use GPU 0 by default int64_t NGPULayers = 0; + std::vector TensorSplit; // Context parameters: uint64_t CtxSize; uint64_t BatchSize; From be7fa0b4b8f1a02f798d57143fe2c3fd2f26040e Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 22 Feb 2024 03:41:26 +0800 Subject: [PATCH 042/218] [WASI-NN] ggml: bump to b2230 for supporting the gemma model Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index c027741074f4..d65d2e06c447 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2220 + GIT_TAG b2230 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) From 9265eb960bf2cbfb8bafad3d0a8ea213109a833d Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 5 Feb 2024 15:58:55 +0800 Subject: [PATCH 043/218] [Tools] Support GC in configure and tools. Signed-off-by: YiYing He --- include/common/configure.h | 26 ++++++++++++++++++++++++++ include/driver/compiler.h | 4 ++++ include/driver/tool.h | 3 +++ lib/driver/runtimeTool.cpp | 8 ++++++++ 4 files changed, 41 insertions(+) diff --git a/include/common/configure.h b/include/common/configure.h index 2ba9a5e6c683..a0d9e88056c9 100644 --- a/include/common/configure.h +++ b/include/common/configure.h @@ -231,6 +231,18 @@ class Configure { void removeProposal(const Proposal Type) noexcept { std::unique_lock Lock(Mutex); + if (Type == Proposal::FunctionReferences && + Proposals.test(static_cast(Proposal::GC))) { + // Proposal dependency: GC depends FunctionReferences. + return; + } + if (Type == Proposal::ReferenceTypes && + (Proposals.test(static_cast(Proposal::GC)) || + Proposals.test(static_cast(Proposal::FunctionReferences)))) { + // Proposal dependency: GC and FunctionReferences depend on + // ReferenceTypes. + return; + } Proposals.reset(static_cast(Type)); } @@ -339,6 +351,11 @@ class Configure { if (Code == OpCode::Return_call_ref && !hasProposal(Proposal::TailCall)) { return Proposal::TailCall; } + } else if (Code == OpCode::Ref__eq || + (Code >= OpCode::Struct__new && Code <= OpCode::I31__get_u)) { + if (!hasProposal(Proposal::GC)) { + return Proposal::GC; + } } return {}; } @@ -351,6 +368,15 @@ class Configure { void unsafeAddProposal(const Proposal Type) noexcept { Proposals.set(static_cast(Type)); + // Proposal dependency: FunctionReferences depends on ReferenceTypes. + if (Type == Proposal::FunctionReferences) { + Proposals.set(static_cast(Proposal::ReferenceTypes)); + } + // Proposal dependency: GC depends on FunctionReferences and ReferenceTypes. + if (Type == Proposal::GC) { + Proposals.set(static_cast(Proposal::FunctionReferences)); + Proposals.set(static_cast(Proposal::ReferenceTypes)); + } } void unsafeAddHostRegistration(const HostRegistration Host) noexcept { diff --git a/include/driver/compiler.h b/include/driver/compiler.h index ca86b813a056..07bc64ff1083 100644 --- a/include/driver/compiler.h +++ b/include/driver/compiler.h @@ -53,6 +53,8 @@ struct DriverCompilerOptions { PropTailCall(PO::Description("Enable Tail-call proposal"sv)), PropExtendConst(PO::Description("Enable Extended-const proposal"sv)), PropThreads(PO::Description("Enable Threads proposal"sv)), + PropFunctionReference( + PO::Description("Enable Function Reference proposal"sv)), PropAll(PO::Description("Enable all features"sv)), PropOptimizationLevel( PO::Description("Optimization level, one of 0, 1, 2, 3, s, z."sv), @@ -78,6 +80,7 @@ struct DriverCompilerOptions { PO::Option PropTailCall; PO::Option PropExtendConst; PO::Option PropThreads; + PO::Option PropFunctionReference; PO::Option PropAll; PO::Option PropOptimizationLevel; @@ -102,6 +105,7 @@ struct DriverCompilerOptions { .add_option("enable-tail-call"sv, PropTailCall) .add_option("enable-extended-const"sv, PropExtendConst) .add_option("enable-threads"sv, PropThreads) + .add_option("enable-function-reference"sv, PropFunctionReference) .add_option("enable-all"sv, PropAll) .add_option("optimize"sv, PropOptimizationLevel); } diff --git a/include/driver/tool.h b/include/driver/tool.h index 38cf04e6f877..35d123490864 100644 --- a/include/driver/tool.h +++ b/include/driver/tool.h @@ -62,6 +62,7 @@ struct DriverToolOptions { PropThreads(PO::Description("Enable Threads proposal"sv)), PropFunctionReference( PO::Description("Enable Function Reference proposal"sv)), + PropGC(PO::Description("Enable GC proposal, this is experimental"sv)), PropComponent(PO::Description( "Enable Component Model proposal, this is experimental"sv)), PropAll(PO::Description("Enable all features"sv)), @@ -110,6 +111,7 @@ struct DriverToolOptions { PO::Option PropExtendConst; PO::Option PropThreads; PO::Option PropFunctionReference; + PO::Option PropGC; PO::Option PropComponent; PO::Option PropAll; PO::Option ConfEnableInstructionCounting; @@ -149,6 +151,7 @@ struct DriverToolOptions { .add_option("enable-extended-const"sv, PropExtendConst) .add_option("enable-threads"sv, PropThreads) .add_option("enable-function-reference"sv, PropFunctionReference) + .add_option("enable-gc"sv, PropGC) .add_option("enable-component"sv, PropComponent) .add_option("enable-all"sv, PropAll) .add_option("time-limit"sv, TimeLim) diff --git a/lib/driver/runtimeTool.cpp b/lib/driver/runtimeTool.cpp index 35cbd363e233..8a4214551898 100644 --- a/lib/driver/runtimeTool.cpp +++ b/lib/driver/runtimeTool.cpp @@ -68,6 +68,10 @@ int Tool(struct DriverToolOptions &Opt) noexcept { if (Opt.PropFunctionReference.value()) { Conf.addProposal(Proposal::FunctionReferences); } + if (Opt.PropGC.value()) { + Conf.addProposal(Proposal::GC); + spdlog::warn("GC proposal is enabled, this is experimental."); + } if (Opt.PropComponent.value()) { Conf.addProposal(Proposal::Component); spdlog::warn("component model is enabled, this is experimental."); @@ -77,6 +81,10 @@ int Tool(struct DriverToolOptions &Opt) noexcept { Conf.addProposal(Proposal::TailCall); Conf.addProposal(Proposal::ExtendedConst); Conf.addProposal(Proposal::Threads); + Conf.addProposal(Proposal::GC); + Conf.addProposal(Proposal::Component); + spdlog::warn("GC proposal is enabled, this is experimental."); + spdlog::warn("component model is enabled, this is experimental."); } std::optional Timeout; From 834afd53db885e8fe800bcb257b5d1bbcf2e72be Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 5 Feb 2024 16:00:45 +0800 Subject: [PATCH 044/218] [Loader] GC proposal loader. Info: [Misc] Support GC proposal (#2726) Signed-off-by: Little Willy <641902082@qq.com> Signed-off-by: YiYing He --- include/ast/instruction.h | 30 +- include/ast/section.h | 6 +- include/ast/type.h | 530 +++++++++++++++++++++++++++++- include/common/enum.inc | 39 +++ include/common/types.h | 126 +++++-- include/loader/filemgr.h | 3 + include/loader/loader.h | 117 +++---- lib/loader/ast/component.cpp | 1 - lib/loader/ast/component/type.cpp | 5 +- lib/loader/ast/instruction.cpp | 100 +++++- lib/loader/ast/module.cpp | 23 +- lib/loader/ast/section.cpp | 68 +++- lib/loader/ast/segment.cpp | 52 +-- lib/loader/ast/type.cpp | 248 ++++++++++---- lib/loader/filemgr.cpp | 10 + 15 files changed, 1118 insertions(+), 240 deletions(-) diff --git a/include/ast/instruction.h b/include/ast/instruction.h index 04e1d354680a..a9bda963ffb8 100644 --- a/include/ast/instruction.h +++ b/include/ast/instruction.h @@ -32,6 +32,10 @@ class Instruction { uint32_t StackEraseEnd; int32_t PCOffset; }; + struct BrCastDescriptor { + struct JumpDescriptor Jump; + ValType RType1, RType2; + }; public: /// Constructor assigns the OpCode and the Offset. @@ -46,10 +50,11 @@ class Instruction { #endif Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; + Flags.IsAllocBrCast = false; } /// Copy constructor. - Instruction(const Instruction &Instr) + Instruction(const Instruction &Instr) noexcept : Data(Instr.Data), Offset(Instr.Offset), Code(Instr.Code), Flags(Instr.Flags) { if (Flags.IsAllocLabelList) { @@ -60,15 +65,18 @@ class Instruction { Data.SelectT.ValTypeList = new ValType[Data.SelectT.ValTypeListSize]; std::copy_n(Instr.Data.SelectT.ValTypeList, Data.SelectT.ValTypeListSize, Data.SelectT.ValTypeList); + } else if (Flags.IsAllocBrCast) { + Data.BrCast = new BrCastDescriptor(*Instr.Data.BrCast); } } /// Move constructor. - Instruction(Instruction &&Instr) + Instruction(Instruction &&Instr) noexcept : Data(Instr.Data), Offset(Instr.Offset), Code(Instr.Code), Flags(Instr.Flags) { Instr.Flags.IsAllocLabelList = false; Instr.Flags.IsAllocValTypeList = false; + Instr.Flags.IsAllocBrCast = false; } /// Destructor. @@ -198,18 +206,31 @@ class Instruction { #endif } + /// Getter and setter of BrCast info for Br_cast instructions. + void setBrCast(uint32_t LabelIdx) { + reset(); + Data.BrCast = new BrCastDescriptor(); + Data.BrCast->Jump.TargetIndex = LabelIdx; + Flags.IsAllocBrCast = true; + } + const BrCastDescriptor &getBrCast() const noexcept { return *Data.BrCast; } + BrCastDescriptor &getBrCast() noexcept { return *Data.BrCast; } + private: /// Release allocated resources. - void reset() { + void reset() noexcept { if (Flags.IsAllocLabelList) { Data.BrTable.LabelListSize = 0; delete[] Data.BrTable.LabelList; } else if (Flags.IsAllocValTypeList) { Data.SelectT.ValTypeListSize = 0; delete[] Data.SelectT.ValTypeList; + } else if (Flags.IsAllocBrCast) { + delete Data.BrCast; } Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; + Flags.IsAllocBrCast = false; } /// Swap function. @@ -268,12 +289,15 @@ class Instruction { #endif // Type 9: IsLast. bool IsLast; + // Type 10: TypeCastBranch. + BrCastDescriptor *BrCast; } Data; uint32_t Offset = 0; OpCode Code = OpCode::End; struct { bool IsAllocLabelList : 1; bool IsAllocValTypeList : 1; + bool IsAllocBrCast : 1; } Flags; /// @} }; diff --git a/include/ast/section.h b/include/ast/section.h index 593f96e253d4..5605999c3df9 100644 --- a/include/ast/section.h +++ b/include/ast/section.h @@ -70,13 +70,13 @@ class CustomSection : public Section { class TypeSection : public Section { public: /// Getter of content vector. - Span getContent() const noexcept { return Content; } - std::vector &getContent() noexcept { return Content; } + Span getContent() const noexcept { return Content; } + std::vector &getContent() noexcept { return Content; } private: /// \name Data of TypeSection. /// @{ - std::vector Content; + std::vector Content; /// @} }; diff --git a/include/ast/type.h b/include/ast/type.h index 663ff04a2cd1..252ef02f9e8e 100644 --- a/include/ast/type.h +++ b/include/ast/type.h @@ -19,6 +19,7 @@ #include "common/symbol.h" #include "common/types.h" +#include #include namespace WasmEdge { @@ -76,11 +77,11 @@ class Limit { class FunctionType { public: /// Constructors. - FunctionType() = default; - FunctionType(Span P, Span R) + FunctionType() noexcept = default; + FunctionType(Span P, Span R) noexcept : ParamTypes(P.begin(), P.end()), ReturnTypes(R.begin(), R.end()) {} FunctionType(Span P, Span R, - Symbol S) + Symbol S) noexcept : ParamTypes(P.begin(), P.end()), ReturnTypes(R.begin(), R.end()), WrapSymbol(std::move(S)) {} @@ -123,6 +124,529 @@ class FunctionType { /// @} }; +/// AST FieldType node for GC proposal. +class FieldType { +public: + /// Constructors. + FieldType() noexcept = default; + FieldType(const ValType &Type, ValMut Mut) noexcept : Type(Type), Mut(Mut) {} + + /// Getter and setter of storage type. + const ValType &getStorageType() const noexcept { return Type; } + void setStorageType(const ValType &VType) noexcept { Type = VType; } + + /// Getter and setter of value mutation. + ValMut getValMut() const noexcept { return Mut; } + void setValMut(ValMut VMut) noexcept { Mut = VMut; } + +private: + /// \name Data of FieldType. + /// @{ + ValType Type; + ValMut Mut; + /// @} +}; + +/// AST CompositeType node for GC proposal. +class CompositeType { +public: + /// Constructors. + CompositeType() noexcept = default; + CompositeType(const FunctionType &FT) noexcept + : Type(TypeCode::Func), FType(FT) {} + + /// Getter of content. + const FunctionType &getFuncType() const noexcept { + return *std::get_if(&FType); + } + FunctionType &getFuncType() noexcept { + return *std::get_if(&FType); + } + const std::vector &getFieldTypes() const noexcept { + return *std::get_if>(&FType); + } + + /// Setter of content. + void setArrayType(FieldType &&FT) noexcept { + Type = TypeCode::Array; + FType = std::vector{std::move(FT)}; + } + void setStructType(std::vector &&VFT) noexcept { + Type = TypeCode::Struct; + FType = std::move(VFT); + } + void setFunctionType(FunctionType &&FT) noexcept { + Type = TypeCode::Func; + FType = std::move(FT); + } + + /// Getter of content type. + TypeCode getContentTypeCode() const noexcept { return Type; } + + /// Checker if is a function type. + bool isFunc() const noexcept { return (Type == TypeCode::Func); } + + /// Expand the composite type to its reference. + TypeCode expand() const noexcept { + switch (Type) { + case TypeCode::Func: + return TypeCode::FuncRef; + case TypeCode::Struct: + return TypeCode::StructRef; + case TypeCode::Array: + return TypeCode::ArrayRef; + default: + assumingUnreachable(); + } + } + +private: + /// \name Data of CompositeType. + /// @{ + TypeCode Type; + std::variant, FunctionType> FType; + /// @} +}; + +/// AST SubType node for GC proposal. +class SubType { +public: + /// Constructors. + SubType() noexcept = default; + SubType(const FunctionType &FT) noexcept + : IsFinal(true), CompType(FT), RecTypeInfo(std::nullopt), + TypeIndex(std::nullopt) {} + + /// Getter and setter of final flag. + bool isFinal() const noexcept { return IsFinal; } + void setFinal(bool F) noexcept { IsFinal = F; } + + /// Getter of type index vector. + Span getSuperTypeIndices() const noexcept { + return SuperTypeIndices; + } + std::vector &getSuperTypeIndices() noexcept { + return SuperTypeIndices; + } + + /// Getter of composite type. + const CompositeType &getCompositeType() const noexcept { return CompType; } + CompositeType &getCompositeType() noexcept { return CompType; } + + /// Recursive type information. + struct RecInfo { + uint32_t Index; + uint32_t RecTypeSize; + }; + + /// Getter of recursive type information. + std::optional getRecursiveInfo() const noexcept { + return RecTypeInfo; + } + void setRecursiveInfo(uint32_t Index, uint32_t Size) noexcept { + RecTypeInfo = RecInfo{Index, Size}; + } + + /// Getter of type index information in a module. + std::optional getTypeIndex() const noexcept { return TypeIndex; } + void setTypeIndex(uint32_t Index) noexcept { TypeIndex = Index; } + +private: + /// \name Data of CompositeType. + /// @{ + /// Is final. + bool IsFinal; + /// List of super type indices. + std::vector SuperTypeIndices; + /// Content of composite type. + CompositeType CompType; + /// @} + + /// \name Information for defined types. + /// @{ + /// Recursive type information. Record the index in the recursive type. + std::optional RecTypeInfo; + /// Type index in the module. Record for backward iteration. + std::optional TypeIndex; + /// @} +}; + +/// AST Type match helper class. +class TypeMatcher { +public: + /// Validator: Match 2 defined types in the same module. + static bool matchType(Span TypeList, uint32_t ExpIdx, + uint32_t GotIdx) noexcept { + return matchType(TypeList, ExpIdx, TypeList, GotIdx); + } + + /// Validator: Match 2 composite types in the same module. + static bool matchType(Span TypeList, + const CompositeType &Exp, + const CompositeType &Got) noexcept { + auto isFieldTypeMatched = [&](const FieldType &ExpFieldType, + const FieldType &GotFieldType) -> bool { + bool IsMatch = false; + if (ExpFieldType.getValMut() == GotFieldType.getValMut()) { + // For both const or both var: Got storage type should match the + // expected storage type. + IsMatch = matchType(TypeList, ExpFieldType.getStorageType(), + GotFieldType.getStorageType()); + if (ExpFieldType.getValMut() == ValMut::Var) { + // If both var: and vice versa. + IsMatch &= matchType(TypeList, GotFieldType.getStorageType(), + ExpFieldType.getStorageType()); + } + } + return IsMatch; + }; + + if (Exp.getContentTypeCode() != Got.getContentTypeCode()) { + return false; + } + switch (Exp.getContentTypeCode()) { + case TypeCode::Func: { + const auto &ExpFType = Exp.getFuncType(); + const auto &GotFType = Got.getFuncType(); + return matchTypes(TypeList, GotFType.getParamTypes(), + ExpFType.getParamTypes()) && + matchTypes(TypeList, ExpFType.getReturnTypes(), + GotFType.getReturnTypes()); + } + case TypeCode::Struct: { + const auto &ExpFType = Exp.getFieldTypes(); + const auto &GotFType = Got.getFieldTypes(); + if (GotFType.size() < ExpFType.size()) { + return false; + } + for (uint32_t I = 0; I < ExpFType.size(); I++) { + if (!isFieldTypeMatched(ExpFType[I], GotFType[I])) { + return false; + } + } + return true; + } + case TypeCode::Array: { + const auto &ExpFType = Exp.getFieldTypes(); + const auto &GotFType = Got.getFieldTypes(); + return isFieldTypeMatched(ExpFType[0], GotFType[0]); + } + default: + return false; + } + } + + /// Validator: Match 2 value types in the same module. + static bool matchType(Span TypeList, const ValType &Exp, + const ValType &Got) noexcept { + return matchType(TypeList, Exp, TypeList, Got); + } + + /// Validator: Match 2 type lists in the same module. + static bool matchTypes(Span TypeList, + Span Exp, + Span Got) noexcept { + if (Exp.size() != Got.size()) { + return false; + } + for (uint32_t I = 0; I < Exp.size(); I++) { + if (!matchType(TypeList, Exp[I], Got[I])) { + return false; + } + } + return true; + } + + /// Matcher: Match 2 defined types. + static bool matchType(Span ExpTypeList, uint32_t ExpIdx, + Span GotTypeList, + uint32_t GotIdx) noexcept { + if (ExpIdx >= ExpTypeList.size() || GotIdx >= GotTypeList.size()) { + return false; + } + if (isDefTypeEqual(ExpTypeList, ExpIdx, GotTypeList, GotIdx)) { + return true; + } + const auto *GotType = GotTypeList[GotIdx]; + for (auto TIdx : GotType->getSuperTypeIndices()) { + if (matchType(ExpTypeList, ExpIdx, GotTypeList, TIdx)) { + return true; + } + } + return false; + } + + /// Matcher: Match 2 value types. + static bool matchType(Span ExpTypeList, + const ValType &Exp, + Span GotTypeList, + const ValType &Got) noexcept { + if (!Exp.isRefType() && !Got.isRefType() && + Exp.getCode() == Got.getCode()) { + // Match for the non-reference type case. + return true; + } + if (Exp.isRefType() && Got.isRefType()) { + // Nullable matching. + if (!Exp.isNullableRefType() && Got.isNullableRefType()) { + return false; + } + + // Match heap type. + if (Exp.isAbsHeapType() && Got.isAbsHeapType()) { + // Case 1: Both abstract heap type. + return matchTypeCode(Exp.getHeapTypeCode(), Got.getHeapTypeCode()); + } else if (Exp.isAbsHeapType()) { + // Case 2: Match a type index to abstract heap type. + if (Got.getTypeIndex() >= GotTypeList.size()) { + return false; + } + return matchTypeCode( + Exp.getHeapTypeCode(), + GotTypeList[Got.getTypeIndex()]->getCompositeType().expand()); + } else if (Got.isAbsHeapType()) { + // Case 3: Match abstract heap type to a type index. + if (Exp.getTypeIndex() >= ExpTypeList.size()) { + return false; + } + TypeCode ExpandGotType = + ExpTypeList[Exp.getTypeIndex()]->getCompositeType().expand(); + switch (Got.getHeapTypeCode()) { + case TypeCode::NullRef: + return matchTypeCode(TypeCode::AnyRef, ExpandGotType); + case TypeCode::NullFuncRef: + return matchTypeCode(TypeCode::FuncRef, ExpandGotType); + case TypeCode::NullExternRef: + return matchTypeCode(TypeCode::ExternRef, ExpandGotType); + default: + return false; + } + } else { + // Case 4: Match defined types. + return matchType(ExpTypeList, Exp.getTypeIndex(), GotTypeList, + Got.getTypeIndex()); + } + } + return false; + } + +private: + /// Matcher: Helper for checking the equivalent of 2 defined types. + static bool isDefTypeEqual(Span LHSList, + uint32_t LHSIdx, + Span RHSList, + uint32_t RHSIdx) { + if (LHSList.data() == RHSList.data() && LHSIdx == RHSIdx) { + // Two type indices in the same module are the same. + return true; + } + const auto *LHSType = LHSList[LHSIdx]; + const auto *RHSType = RHSList[RHSIdx]; + // For GC proposal, a single subtype can be seemed as a self-recursive type. + // That is, `(rec (type $t1 (func (param (ref $t1)))))` and + // `(type $t1 (func (param (ref $t1))))` are the same. + // Therefore, use the subtype length for the recursive type size. + const uint32_t LRecSize = LHSType->getRecursiveInfo().has_value() + ? LHSType->getRecursiveInfo()->RecTypeSize + : 1U; + const uint32_t RRecSize = RHSType->getRecursiveInfo().has_value() + ? RHSType->getRecursiveInfo()->RecTypeSize + : 1U; + if (LRecSize != RRecSize) { + // 2 recursive type sizes are different. Must not be the same. + return false; + } + if (LRecSize > 1) { + // Both are in a recursive type with > 1 subtypes. + if (LHSType->getRecursiveInfo()->Index != + RHSType->getRecursiveInfo()->Index) { + // The recursive indices should be the same. + return false; + } + // The recursive types should be the same. + uint32_t LStartIdx = LHSIdx - LHSType->getRecursiveInfo()->Index; + uint32_t RStartIdx = RHSIdx - RHSType->getRecursiveInfo()->Index; + return isRecTypeEqual(LHSList, LStartIdx, RHSList, RStartIdx, LRecSize); + } else { + // Both are composite types or self-recursive types. + return isRecTypeEqual(LHSList, LHSIdx, RHSList, RHSIdx, 1); + } + } + + /// Matcher: Helper for checking the equivalent of 2 recursive types. + static bool isRecTypeEqual(Span LHSList, + uint32_t LStartIdx, + Span RHSList, + uint32_t RStartIdx, uint32_t RecSize) { + + auto isValTypeEqual = [&](const ValType <ype, + const ValType &RType) -> bool { + if (LType.getHeapTypeCode() == TypeCode::TypeIndex && + RType.getHeapTypeCode() == TypeCode::TypeIndex) { + if (LType.getCode() != RType.getCode()) { + return false; + } + // Check the index is the recursive type internal index or not. + auto LIdx = LType.getTypeIndex(); + auto RIdx = RType.getTypeIndex(); + assuming(LIdx < LHSList.size() && RIdx < RHSList.size()); + bool IsLInSelfRecType = + (LIdx >= LStartIdx && LIdx < LStartIdx + RecSize); + bool IsRInSelfRecType = + (RIdx >= RStartIdx && RIdx < RStartIdx + RecSize); + if (IsLInSelfRecType != IsRInSelfRecType) { + // If the one index is the recursive type internal index but the other + // isn't, the value types must be different. + return false; + } + if (IsLInSelfRecType) { + // For both are internal indices of the recursive types, the internal + // indices must be the same. + if (LIdx - LStartIdx == RIdx - RStartIdx) { + return true; + } else { + return false; + } + } + // For neither are internal indices, keep checking the equivalent of the + // defined types. + return isDefTypeEqual(LHSList, LIdx, RHSList, RIdx); + } else { + return (LType.getCode() == RType.getCode() && + LType.getHeapTypeCode() == RType.getHeapTypeCode()); + } + }; + + auto isFieldTypeEqual = + [isValTypeEqual](const std::vector &LFieldTypes, + const std::vector &RFieldTypes) -> bool { + if (LFieldTypes.size() != RFieldTypes.size()) { + return false; + } + for (uint32_t I = 0; I < LFieldTypes.size(); I++) { + if (LFieldTypes[I].getValMut() != RFieldTypes[I].getValMut()) { + return false; + } + if (!isValTypeEqual(LFieldTypes[I].getStorageType(), + RFieldTypes[I].getStorageType())) { + return false; + } + } + return true; + }; + + auto isFuncTypeEqual = + [isValTypeEqual](const FunctionType &LFuncType, + const FunctionType &RFuncType) -> bool { + auto &LPTypes = LFuncType.getParamTypes(); + auto &LRTypes = LFuncType.getReturnTypes(); + auto &RPTypes = RFuncType.getParamTypes(); + auto &RRTypes = RFuncType.getReturnTypes(); + if (LPTypes.size() != RPTypes.size() || + LRTypes.size() != RRTypes.size()) { + return false; + } + for (uint32_t I = 0; I < LPTypes.size(); I++) { + if (!isValTypeEqual(LPTypes[I], RPTypes[I])) { + return false; + } + } + for (uint32_t I = 0; I < LRTypes.size(); I++) { + if (!isValTypeEqual(LRTypes[I], RRTypes[I])) { + return false; + } + } + return true; + }; + + auto isCompTypeEqual = [isFuncTypeEqual, isFieldTypeEqual]( + const CompositeType &LCompType, + const CompositeType &RCompType) -> bool { + if (LCompType.expand() != RCompType.expand()) { + return false; + } + switch (LCompType.expand()) { + case TypeCode::FuncRef: + return isFuncTypeEqual(LCompType.getFuncType(), + RCompType.getFuncType()); + case TypeCode::StructRef: + case TypeCode::ArrayRef: + return isFieldTypeEqual(LCompType.getFieldTypes(), + RCompType.getFieldTypes()); + default: + assumingUnreachable(); + } + }; + + for (uint32_t I = 0; I < RecSize; I++) { + // Every subtype in the recursive types should be equivalent. + const auto *LHSType = LHSList[LStartIdx + I]; + const auto *RHSType = RHSList[RStartIdx + I]; + if (LHSType->isFinal() != RHSType->isFinal()) { + return false; + } + auto LSuperTypes = LHSType->getSuperTypeIndices(); + auto RSuperTypes = RHSType->getSuperTypeIndices(); + if (LSuperTypes.size() != RSuperTypes.size()) { + return false; + } + // TODO: GC - Fix the subtype matching. + uint32_t SuperTypesSize = static_cast(LSuperTypes.size()); + for (uint32_t J = 0; J < SuperTypesSize; J++) { + if (!isValTypeEqual(ValType(TypeCode::Ref, LSuperTypes[J]), + ValType(TypeCode::Ref, RSuperTypes[J]))) { + return false; + } + } + if (!isCompTypeEqual(LHSType->getCompositeType(), + RHSType->getCompositeType())) { + return false; + } + } + return true; + } + + /// Matcher: Helper for matching 2 type codes. + static bool matchTypeCode(TypeCode Exp, TypeCode Got) noexcept { + // Handle the equal cases first. + if (Exp == Got) { + return true; + } + + // Match the func types: nofunc <= func + if (Exp == TypeCode::FuncRef || Exp == TypeCode::NullFuncRef) { + return Got == TypeCode::NullFuncRef; + } + if (Got == TypeCode::FuncRef || Got == TypeCode::NullFuncRef) { + return false; + } + + // Match the extern types: noextern <= extern + if (Exp == TypeCode::ExternRef || Exp == TypeCode::NullExternRef) { + return Got == TypeCode::NullExternRef; + } + if (Got == TypeCode::ExternRef || Got == TypeCode::NullExternRef) { + return false; + } + + // Match the other types: none <= i31 | struct | array <= eq <= any + switch (Exp) { + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + // This will filter out the i31/struct/array unmatch cases. + return Got == TypeCode::NullRef; + case TypeCode::EqRef: + return Got != TypeCode::AnyRef; + case TypeCode::AnyRef: + return true; + default: + break; + } + return false; + } +}; + /// AST MemoryType node. class MemoryType { public: diff --git a/include/common/enum.inc b/include/common/enum.inc index 33c376b4d55b..4bb4c50c716b 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -67,6 +67,8 @@ A(Seg_Element, "element segment") A(Seg_Code, "code segment") A(Seg_Data, "data segment") A(Type_Module, "module type") +A(Type_Rec, "recursive type") +A(Type_Sub, "sub type") A(Type_Limit, "limit") A(Type_Function, "function type") A(Type_Memory, "memory type") @@ -286,12 +288,46 @@ O(I64__extend32_s, 0xC4, "i64.extend32_s") O(Ref__null, 0xD0, "ref.null") O(Ref__is_null, 0xD1, "ref.is_null") O(Ref__func, 0xD2, "ref.func") +O(Ref__eq, 0xD3, "ref.eq") O(Ref__as_non_null, 0xD4, "ref.as_non_null") // Control Instructions (part 2) O(Br_on_null, 0xD5, "br_on_null") O(Br_on_non_null, 0xD6, "br_on_non_null") +// GC Instructions +O(Struct__new, 0xFB00, "struct.new") +O(Struct__new_default, 0xFB01, "struct.new_default") +O(Struct__get, 0xFB02, "struct.get") +O(Struct__get_s, 0xFB03, "struct.get_s") +O(Struct__get_u, 0xFB04, "struct.get_u") +O(Struct__set, 0xFB05, "struct.set") +O(Array__new, 0xFB06, "array.new") +O(Array__new_default, 0xFB07, "array.new_default") +O(Array__new_fixed, 0xFB08, "array.new_fixed") +O(Array__new_data, 0xFB09, "array.new_data") +O(Array__new_elem, 0xFB0A, "array.new_elem") +O(Array__get, 0xFB0B, "array.get") +O(Array__get_s, 0xFB0C, "array.get_s") +O(Array__get_u, 0xFB0D, "array.get_u") +O(Array__set, 0xFB0E, "array.set") +O(Array__len, 0xFB0F, "array.len") +O(Array__fill, 0xFB10, "array.fill") +O(Array__copy, 0xFB11, "array.copy") +O(Array__init_data, 0xFB12, "array.init_data") +O(Array__init_elem, 0xFB13, "array.init_elem") +O(Ref__test, 0xFB14, "ref.test (ref)") +O(Ref__test_null, 0xFB15, "ref.test (ref.null)") +O(Ref__cast, 0xFB16, "ref.cast (ref)") +O(Ref__cast_null, 0xFB17, "ref.cast (ref.null)") +O(Br_on_cast, 0xFB18, "br_on_cast") +O(Br_on_cast_fail, 0xFB19, "br_on_cast_fail") +O(Any__convert_extern, 0xFB1A, "any.convert_extern") +O(Extern__convert_any, 0xFB1B, "extern.convert_any") +O(Ref__i31, 0xFB1C, "ref.i31") +O(I31__get_s, 0xFB1D, "i31.get_s") +O(I31__get_u, 0xFB1E, "i31.get_u") + // Saturating Truncation Instructions O(I32__trunc_sat_f32_s, 0xFC00, "i32.trunc_sat_f32_s") O(I32__trunc_sat_f32_u, 0xFC01, "i32.trunc_sat_f32_u") @@ -670,6 +706,7 @@ P(ExtendedConst, "Extended const") P(Threads, "Threads") P(FunctionReferences, "Typed Function References") P(Component, "Component model") +P(GC, "GC proposal") #undef P #endif // UseProposal @@ -1002,6 +1039,7 @@ M(Version, "version") // Versions I(Label, "label") I(Local, "local") +I(DefinedType, "defined type") I(FunctionType, "function type") I(Function, "function") I(Table, "table") @@ -1010,6 +1048,7 @@ I(Global, "global") I(Element, "element") I(Data, "data") I(Lane, "lane") +I(Field, "field") #undef I #endif // UseIndexCategory diff --git a/include/common/types.h b/include/common/types.h index a13cd555c94e..8376a4bd0ec2 100644 --- a/include/common/types.h +++ b/include/common/types.h @@ -61,20 +61,20 @@ using doublex2_t = SIMDArray; using floatx4_t = SIMDArray; // The bit pattern of the value types: -// ---------------------------------------------------------------------------- -// byte | 0th | 1st | 2nd | 3rd | 4th ~ 7th -// ------|-----------|--------------|---------------------|-------------------- -// | | ValTypeCode | For the HeapType use -// | | 0x7F, 0x7E, | (Function references and GC proposal) -// | | 0x7D, 0x7C, | HeapTypeCode | -// | | (numtype) | 0x00, 0x40, | Type index -// code | Reserved | 0x7B, | 0x70, 0x6F, | (uint32_t) -// | (Padding) | (vectype) | (func-ref proposal) | -// | | 0x78, 0x77, | 0x73, 0x72, 0x71, | -// | | (packedtype) | 0x6E, 0x6D, 0x6C, | -// | | 0x64, 0x63 | 0x6B, 0x6A | -// | | (reftype) | (GC proposal) | -// ---------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// byte | 0th | 1st | 2nd | 3rd | 4th ~ 7th +// ------|-------------|--------------|---------------------|------------------- +// | | ValTypeCode | For the HeapType use +// | 0th: | 0x7F, 0x7E, | (Function references and GC proposal) +// | Reserved | 0x7D, 0x7C, | HeapTypeCode | +// | (Padding) | (numtype) | 0x00, 0x40, | Type index +// code | | 0x7B, | 0x70, 0x6F, | (uint32_t) +// | | (vectype) | (func-ref proposal) | +// | 1st: | 0x78, 0x77, | 0x73, 0x72, 0x71, | +// | Externalize | (packedtype) | 0x6E, 0x6D, 0x6C, | +// | | 0x64, 0x63 | 0x6B, 0x6A | +// | | (reftype) | (GC proposal) | +// ----------------------------------------------------------------------------- // In order to compress the various value type definitions into uint64_t length, // WasmEdge implements the ValType class for extending the value types. // As the definitions in the typed function references and GC proposal, the @@ -89,6 +89,7 @@ class ValType { ValType() noexcept = default; // General constructors for initializing data. ValType(TypeCode C, TypeCode HT, uint32_t I) noexcept { + Inner.Data.Externalize = 0; Inner.Data.Code = C; Inner.Data.HTCode = HT; Inner.Data.Idx = I; @@ -98,6 +99,7 @@ class ValType { } // Constructor for the value type codes without heap type immediates. ValType(TypeCode C) noexcept { + Inner.Data.Externalize = 0; Inner.Data.Idx = 0; switch (C) { case TypeCode::I32: @@ -136,14 +138,15 @@ class ValType { } // Constructor for the value type with abs heap type in reference type. ValType(TypeCode C, TypeCode HT) noexcept { + Inner.Data.Externalize = 0; Inner.Data.Code = C; Inner.Data.HTCode = HT; Inner.Data.Idx = 0; assuming(isAbsHeapType()); - assuming(isRefType()); } // Constructor for the value type with type index in reference type. ValType(TypeCode C, uint32_t I) noexcept { + Inner.Data.Externalize = 0; Inner.Data.Code = C; Inner.Data.HTCode = TypeCode::TypeIndex; Inner.Data.Idx = I; @@ -207,11 +210,14 @@ class ValType { bool isFuncRefType() const noexcept { return (Inner.Data.HTCode == TypeCode::FuncRef) || + (Inner.Data.HTCode == TypeCode::NullFuncRef) || (Inner.Data.HTCode == TypeCode::TypeIndex); } bool isExternRefType() const noexcept { - return (Inner.Data.HTCode == TypeCode::ExternRef); + return (Inner.Data.HTCode == TypeCode::ExternRef) || + (Inner.Data.HTCode == TypeCode::NullExternRef) || + Inner.Data.Externalize; } bool isNullableRefType() const noexcept { @@ -219,28 +225,75 @@ class ValType { } bool isAbsHeapType() const noexcept { - switch (Inner.Data.HTCode) { - case TypeCode::NullFuncRef: - case TypeCode::NullExternRef: - case TypeCode::NullRef: - case TypeCode::FuncRef: - case TypeCode::ExternRef: - case TypeCode::AnyRef: - case TypeCode::EqRef: - case TypeCode::I31Ref: - case TypeCode::StructRef: - case TypeCode::ArrayRef: - return true; + if (isRefType()) { + switch (Inner.Data.HTCode) { + case TypeCode::NullFuncRef: + case TypeCode::NullExternRef: + case TypeCode::NullRef: + case TypeCode::FuncRef: + case TypeCode::ExternRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + return true; + default: + return false; + } + } + return false; + } + + uint32_t getBitWidth() const noexcept { + switch (Inner.Data.Code) { + case TypeCode::I8: + return 8U; + case TypeCode::I16: + return 16U; + case TypeCode::I32: + case TypeCode::F32: + return 32U; + case TypeCode::I64: + case TypeCode::F64: + return 64U; + case TypeCode::V128: + return 128U; default: - return false; + // Bit width not available for reftypes. + assumingUnreachable(); } } -protected: + ValType getNullableRef() const noexcept { + assuming(isRefType()); + return ValType(TypeCode::RefNull, Inner.Data.HTCode, Inner.Data.Idx); + } + ValType &toNullableRef() noexcept { + assuming(isRefType()); + Inner.Data.Code = TypeCode::RefNull; + return *this; + } + ValType getNonNullableRef() const noexcept { + assuming(isRefType()); + return ValType(TypeCode::Ref, Inner.Data.HTCode, Inner.Data.Idx); + } + ValType &toNonNullableRef() noexcept { + assuming(isRefType()); + Inner.Data.Code = TypeCode::Ref; + return *this; + } + + void setExternalized() noexcept { Inner.Data.Externalize = 1U; } + void setInternalized() noexcept { Inner.Data.Externalize = 0U; } + bool isExternalized() noexcept { return Inner.Data.Externalize != 0U; } + +private: union { uint8_t Raw[8]; struct { - uint8_t Paddings[2]; + uint8_t Padding; + uint8_t Externalize; TypeCode Code; TypeCode HTCode; uint32_t Idx; @@ -303,6 +356,8 @@ class BlockType { /// FuncRef definition. namespace Runtime::Instance { class FunctionInstance; +class StructInstance; +class ArrayInstance; } // namespace Runtime::Instance /// NumType and RefType variant definitions. @@ -317,9 +372,18 @@ struct RefVariant { template RefVariant(const T *P) noexcept { setData(TypeCode::ExternRef, reinterpret_cast(P)); } + template RefVariant(const ValType &VT, const T *P) noexcept { + setData(VT, reinterpret_cast(P)); + } RefVariant(const Runtime::Instance::FunctionInstance *P) noexcept { setData(TypeCode::FuncRef, reinterpret_cast(P)); } + RefVariant(const Runtime::Instance::StructInstance *P) noexcept { + setData(TypeCode::StructRef, reinterpret_cast(P)); + } + RefVariant(const Runtime::Instance::ArrayInstance *P) noexcept { + setData(TypeCode::ArrayRef, reinterpret_cast(P)); + } // Getter of type. const ValType &getType() const noexcept { diff --git a/include/loader/filemgr.h b/include/loader/filemgr.h index ab223053fcd4..596d62ac56c8 100644 --- a/include/loader/filemgr.h +++ b/include/loader/filemgr.h @@ -86,6 +86,9 @@ class FileMgr { /// Read a string, which is size(unsigned int) + bytes. Expect readName(); + /// Peek one byte. + Expect peekByte(); + /// Get the file header type. FileHeader getHeaderType(); diff --git a/include/loader/loader.h b/include/loader/loader.h index e5c68477c86f..6db703b6bf40 100644 --- a/include/loader/loader.h +++ b/include/loader/loader.h @@ -73,6 +73,15 @@ template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { return ASTNodeAttr::Sec_DataCount; } +template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { + return ASTNodeAttr::Type_Rec; +} +template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { + return ASTNodeAttr::Type_Function; +} +template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { + return ASTNodeAttr::Seg_Element; +} template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { return ASTNodeAttr::Sec_Alias; @@ -187,104 +196,92 @@ class Loader { } /// @} + /// \name Load AST Module functions + /// @{ Expect, std::unique_ptr>> loadUnit(); Expect, std::vector>> loadPreamble(); - - /// \name Load AST Component functions - /// @{ - Expect loadComponent(AST::Component::Component &Comp); - /// @} - - /// \name Load AST Module functions - /// @{ Expect loadModule(AST::Module &Mod); Expect loadModuleInBound(AST::Module &Mod, std::optional Bound); + Expect loadUniversalWASM(AST::Module &Mod); + Expect loadModuleAOT(AST::AOTSection &AOTSection); + Expect loadComponent(AST::Component::Component &Comp); /// @} /// \name Load AST section node helper functions /// @{ - Expect loadUniversalWASM(AST::Module &Mod); - Expect loadModuleAOT(AST::AOTSection &AOTSection); - - Expect loadSectionSize(ASTNodeAttr Node); - template - Expect loadSectionContent(T &Sec, L &&Func) { - Sec.setStartOffset(FMgr.getOffset()); - if (auto Res = loadSectionSize(NodeAttrFromAST())) { - // Set the section size. - Sec.setContentSize(*Res); - auto StartOffset = FMgr.getOffset(); - auto ResContent = Func(); - if (!ResContent) { - return Unexpect(ResContent); - } - // Check the read size match the section size. - auto EndOffset = FMgr.getOffset(); - if (EndOffset - StartOffset != Sec.getContentSize()) { - return logLoadError(ErrCode::Value::SectionSizeMismatch, EndOffset, - NodeAttrFromAST()); + Expect loadVecCnt() { + // Read the vector size. + if (auto Res = FMgr.readU32()) { + if ((*Res) / 2 > FMgr.getRemainSize()) { + return Unexpect(ErrCode::Value::IntegerTooLong); } + return *Res; } else { return Unexpect(Res); } - return {}; } - template - Expect loadSectionContentVec(T &Sec, L &&Func) { + + template + Expect loadVec(std::vector &Vec, ElemLoader &&Func) { uint32_t VecCnt = 0; // Read the vector size. - if (auto Res = FMgr.readU32()) { + if (auto Res = loadVecCnt()) { VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, - FMgr.getLastOffset(), NodeAttrFromAST()); - } - Sec.getContent().resize(VecCnt); + Vec.resize(*Res); } else { return logLoadError(Res.error(), FMgr.getLastOffset(), - NodeAttrFromAST()); + NodeAttrFromAST()); } // Sequently create the AST node T and read data. for (uint32_t I = 0; I < VecCnt; ++I) { - if (auto Res = Func(Sec.getContent()[I]); !Res) { - spdlog::error(ErrInfo::InfoAST(NodeAttrFromAST())); + if (auto Res = Func(Vec[I]); !Res) { + spdlog::error(ErrInfo::InfoAST(NodeAttrFromAST())); return Unexpect(Res); } } return {}; } - template - Expect loadVec(std::vector &Vec, L &&Func) { - uint32_t VecCnt = 0; - // Read the vector size. + template + Expect loadSectionContent(T &Sec, ElemLoader &&Func) { + Sec.setStartOffset(FMgr.getOffset()); if (auto Res = FMgr.readU32()) { - VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, + // Load the section size first. + if (unlikely(FMgr.getRemainSize() < (*Res))) { + return logLoadError(ErrCode::Value::LengthOutOfBounds, FMgr.getLastOffset(), NodeAttrFromAST()); } - Vec.resize(VecCnt); + // Set the section size. + Sec.setContentSize(*Res); + auto StartOffset = FMgr.getOffset(); + // Invoke the callback function. + auto ResContent = Func(); + if (!ResContent) { + return Unexpect(ResContent); + } + // Check the read size matches the section size. + auto EndOffset = FMgr.getOffset(); + if (EndOffset - StartOffset != Sec.getContentSize()) { + return logLoadError(ErrCode::Value::SectionSizeMismatch, EndOffset, + NodeAttrFromAST()); + } } else { return logLoadError(Res.error(), FMgr.getLastOffset(), NodeAttrFromAST()); } - - // Sequently create the AST node T and read data. - for (uint32_t I = 0; I < VecCnt; ++I) { - if (auto Res = Func(Vec[I]); !Res) { - spdlog::error(ErrInfo::InfoAST(NodeAttrFromAST())); - return Unexpect(Res); - } - } - return {}; } + template + Expect loadSectionContentVec(T &Sec, ElemLoader &&Func) { + return loadVec(Sec.getContent(), std::move(Func)); + } + /// @} + /// \name Load AST nodes functions /// @{ Expect loadSection(AST::CustomSection &Sec); @@ -327,8 +324,12 @@ class Loader { Expect loadDesc(AST::ExportDesc &ExpDesc); Expect loadHeapType(TypeCode TC, ASTNodeAttr From); Expect loadRefType(ASTNodeAttr From); - Expect loadValType(ASTNodeAttr From); + Expect loadValType(ASTNodeAttr From, bool IsStorageType = false); + Expect loadMutability(ASTNodeAttr From); + Expect loadFieldType(AST::FieldType &FType); + Expect loadCompositeType(AST::CompositeType &CType); Expect loadLimit(AST::Limit &Lim); + Expect loadType(AST::SubType &SType); Expect loadType(AST::FunctionType &FuncType); Expect loadType(AST::MemoryType &MemType); Expect loadType(AST::TableType &TabType); diff --git a/lib/loader/ast/component.cpp b/lib/loader/ast/component.cpp index 328842d981d4..37ffb7283921 100644 --- a/lib/loader/ast/component.cpp +++ b/lib/loader/ast/component.cpp @@ -56,7 +56,6 @@ Loader::loadUnit() { Mod->getMagic() = WasmMagic; Mod->getVersion() = Ver; if (!Conf.getRuntimeConfigure().isForceInterpreter()) { - if (auto Res = loadModuleAOT(Mod->getAOTSection()); !Res) { return Unexpect(Res); } diff --git a/lib/loader/ast/component/type.cpp b/lib/loader/ast/component/type.cpp index 7afd5270b165..55667be7819a 100644 --- a/lib/loader/ast/component/type.cpp +++ b/lib/loader/ast/component/type.cpp @@ -312,14 +312,13 @@ Expect Loader::loadType(ComponentType &Ty) { } Expect Loader::loadComponentDecl(ComponentDecl &Decl) { - auto Pos = FMgr.getLastOffset(); - auto Res = FMgr.readByte(); + auto Res = FMgr.peekByte(); if (!Res) { return Unexpect(Res); } else if (*Res != 0x03U) { - FMgr.seek(Pos); return loadInstanceDecl(Decl.emplace()); } else { + FMgr.readByte(); return loadImportDecl(Decl.emplace()); } } diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index f5b1679be61b..2f35e643a47d 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -19,7 +19,8 @@ Expect Loader::loadOpCode() { return Unexpect(B1); } - if (Payload == 0xFCU || Payload == 0xFDU || Payload == 0xFEU) { + if (Payload == 0xFBU || Payload == 0xFCU || Payload == 0xFDU || + Payload == 0xFEU) { // 2-bytes OpCode case. if (auto B2 = FMgr.readU32()) { Payload <<= 8; @@ -241,12 +242,10 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { case OpCode::Br_table: { uint32_t VecCnt = 0; // Read the vector of labels. - if (auto Res = readU32(VecCnt); unlikely(!Res)) { - return Unexpect(Res); - } - if (VecCnt / 2 > FMgr.getRemainSize()) { - // Too many label for Br_table. - return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), + if (auto Res = loadVecCnt()) { + VecCnt = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), ASTNodeAttr::Instruction); } Instr.setLabelListSize(VecCnt + 1); @@ -288,6 +287,8 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { // Reference Instructions. case OpCode::Ref__null: + case OpCode::Ref__test_null: + case OpCode::Ref__cast_null: if (auto Res = loadHeapType(TypeCode::RefNull, ASTNodeAttr::Instruction)) { Instr.setValType(*Res); } else { @@ -295,11 +296,85 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return Unexpect(Res); } return {}; + case OpCode::Ref__test: + case OpCode::Ref__cast: + if (auto Res = loadHeapType(TypeCode::Ref, ASTNodeAttr::Instruction)) { + Instr.setValType(*Res); + } else { + // The AST node information is handled. + return Unexpect(Res); + } + return {}; case OpCode::Ref__is_null: + case OpCode::Ref__eq: case OpCode::Ref__as_non_null: return {}; case OpCode::Ref__func: + case OpCode::Struct__new: + case OpCode::Struct__new_default: + case OpCode::Array__new: + case OpCode::Array__new_default: + case OpCode::Array__get: + case OpCode::Array__get_s: + case OpCode::Array__get_u: + case OpCode::Array__set: + case OpCode::Array__fill: return readU32(Instr.getTargetIndex()); + case OpCode::Struct__get: + case OpCode::Struct__get_s: + case OpCode::Struct__get_u: + case OpCode::Struct__set: + case OpCode::Array__new_fixed: + case OpCode::Array__new_data: + case OpCode::Array__new_elem: + case OpCode::Array__copy: + case OpCode::Array__init_data: + case OpCode::Array__init_elem: + if (auto Res = readU32(Instr.getTargetIndex()); unlikely(!Res)) { + return Unexpect(Res); + } + return readU32(Instr.getSourceIndex()); + case OpCode::Br_on_cast: + case OpCode::Br_on_cast_fail: { + // Read the flag. + uint8_t Flag = 0U; + if (auto Res = readU8(Flag); !Res) { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Instruction); + } + // Read the label index. + uint32_t LabelIdx = 0U; + if (auto Res = readU32(LabelIdx); !Res) { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Instruction); + } + // Read the heap types. + Instr.setBrCast(LabelIdx); + if (auto Res = + loadHeapType(((Flag & 0x01U) ? TypeCode::RefNull : TypeCode::Ref), + ASTNodeAttr::Instruction)) { + Instr.getBrCast().RType1 = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Instruction); + } + if (auto Res = + loadHeapType(((Flag & 0x02U) ? TypeCode::RefNull : TypeCode::Ref), + ASTNodeAttr::Instruction)) { + Instr.getBrCast().RType2 = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Instruction); + } + return {}; + } + case OpCode::Array__len: + case OpCode::Any__convert_extern: + case OpCode::Extern__convert_any: + case OpCode::Ref__i31: + case OpCode::I31__get_s: + case OpCode::I31__get_u: + return {}; // Parametric Instructions. case OpCode::Drop: @@ -307,12 +382,11 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return {}; case OpCode::Select_t: { // Read the vector of value types. - uint32_t VecCnt; - if (auto Res = readU32(VecCnt); unlikely(!Res)) { - return Unexpect(Res); - } - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), + uint32_t VecCnt = 0; + if (auto Res = loadVecCnt()) { + VecCnt = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), ASTNodeAttr::Instruction); } Instr.setValTypeListSize(VecCnt); diff --git a/lib/loader/ast/module.cpp b/lib/loader/ast/module.cpp index 871743e59669..dd26dc1d017a 100644 --- a/lib/loader/ast/module.cpp +++ b/lib/loader/ast/module.cpp @@ -186,7 +186,17 @@ Expect Loader::loadModule(AST::Module &Mod) { // Setup symbols from loaded binary. See "include/loader/loader.h". Expect Loader::loadExecutable(AST::Module &Mod, std::shared_ptr Exec) { - auto &FuncTypes = Mod.getTypeSection().getContent(); + auto &SubTypes = Mod.getTypeSection().getContent(); + for (auto &SubType : SubTypes) { + if (unlikely(!SubType.getCompositeType().isFunc())) { + // TODO: GC - AOT: implement other composite types. + spdlog::error(ErrCode::Value::MalformedSection); + spdlog::error(" Currently AOT not support GC proposal yet."); + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Module)); + return Unexpect(ErrCode::Value::MalformedSection); + } + } + size_t Offset = 0; for (const auto &ImpDesc : Mod.getImportSection().getContent()) { if (ImpDesc.getExternalType() == ExternalType::Function) { @@ -196,13 +206,13 @@ Expect Loader::loadExecutable(AST::Module &Mod, auto &CodeSegs = Mod.getCodeSection().getContent(); // Check the symbols. - auto FuncTypeSymbols = Exec->getTypes(FuncTypes.size()); + auto FuncTypeSymbols = Exec->getTypes(SubTypes.size()); auto CodeSymbols = Exec->getCodes(Offset, CodeSegs.size()); auto IntrinsicsSymbol = Exec->getIntrinsics(); - if (unlikely(FuncTypeSymbols.size() != FuncTypes.size())) { + if (unlikely(FuncTypeSymbols.size() != SubTypes.size())) { spdlog::error(" AOT section -- number of types not matching:{} {}, " "use interpreter mode instead.", - FuncTypeSymbols.size(), FuncTypes.size()); + FuncTypeSymbols.size(), SubTypes.size()); return Unexpect(ErrCode::Value::IllegalGrammar); } if (unlikely(CodeSymbols.size() != CodeSegs.size())) { @@ -218,8 +228,9 @@ Expect Loader::loadExecutable(AST::Module &Mod, } // Set the symbols into the module. - for (size_t I = 0; I < FuncTypes.size(); ++I) { - FuncTypes[I].setSymbol(std::move(FuncTypeSymbols[I])); + for (size_t I = 0; I < SubTypes.size(); ++I) { + SubTypes[I].getCompositeType().getFuncType().setSymbol( + std::move(FuncTypeSymbols[I])); } for (size_t I = 0; I < CodeSegs.size(); ++I) { CodeSegs[I].setSymbol(std::move(CodeSymbols[I])); diff --git a/lib/loader/ast/section.cpp b/lib/loader/ast/section.cpp index a0093378aa26..0e42a26d1f52 100644 --- a/lib/loader/ast/section.cpp +++ b/lib/loader/ast/section.cpp @@ -12,19 +12,6 @@ namespace WasmEdge { namespace Loader { -// Load content size. See "include/loader/loader.h". -Expect Loader::loadSectionSize(ASTNodeAttr Node) { - if (auto Res = FMgr.readU32()) { - if (unlikely(FMgr.getRemainSize() < (*Res))) { - return logLoadError(ErrCode::Value::LengthOutOfBounds, - FMgr.getLastOffset(), Node); - } - return *Res; - } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), Node); - } -} - // Load content of custom section. See "include/loader/loader.h". Expect Loader::loadSection(AST::CustomSection &Sec) { return loadSectionContent(Sec, [this, &Sec]() -> Expect { @@ -55,10 +42,57 @@ Expect Loader::loadSection(AST::CustomSection &Sec) { // Load vector of type section. See "include/loader/loader.h". Expect Loader::loadSection(AST::TypeSection &Sec) { - return loadSectionContent(Sec, [this, &Sec]() { - return loadSectionContentVec(Sec, [this](AST::FunctionType &FuncType) { - return loadType(FuncType); - }); + return loadSectionContent(Sec, [this, &Sec]() -> Expect { + // Read the recursive type vector size. + uint32_t VecCnt = 0; + if (auto Res = loadVecCnt()) { + VecCnt = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Sec_Type); + } + // Read the recursive types. + Sec.getContent().clear(); + uint32_t SubTypeCnt = 0; + for (uint32_t I = 0; I < VecCnt; I++) { + if (auto CodeByte = FMgr.peekByte()) { + TypeCode Code = static_cast(*CodeByte); + if (Code == TypeCode::Rec) { + // Case: 0x4E vec(subtype). + FMgr.readByte(); + uint32_t RecVecCnt = 0; + if (auto Res = loadVecCnt()) { + RecVecCnt = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Sec_Type); + } + for (uint32_t J = 0; J < RecVecCnt; ++J) { + Sec.getContent().emplace_back(); + if (auto Res = loadType(Sec.getContent().back()); unlikely(!Res)) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Sec_Type)); + return Unexpect(Res); + } + Sec.getContent().back().setRecursiveInfo(J, RecVecCnt); + Sec.getContent().back().setTypeIndex(SubTypeCnt); + SubTypeCnt++; + } + } else { + // Case: subtype. + Sec.getContent().emplace_back(); + Sec.getContent().back().setTypeIndex(SubTypeCnt); + SubTypeCnt++; + if (auto Res = loadType(Sec.getContent().back()); unlikely(!Res)) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Sec_Type)); + return Unexpect(Res); + } + } + } else { + return logLoadError(CodeByte.error(), FMgr.getLastOffset(), + ASTNodeAttr::Sec_Type); + } + } + return {}; }); } diff --git a/lib/loader/ast/segment.cpp b/lib/loader/ast/segment.cpp index 47bb5d8a6606..6b7cea07d4bc 100644 --- a/lib/loader/ast/segment.cpp +++ b/lib/loader/ast/segment.cpp @@ -12,8 +12,7 @@ namespace Loader { // Load binary of TableSegment node. See "include/loader/loader.h". Expect Loader::loadSegment(AST::TableSegment &TabSeg) { // Check the first byte is the reftype in table type or not. - auto StartOffset = FMgr.getOffset(); - if (auto CheckByte = FMgr.readByte()) { + if (auto CheckByte = FMgr.peekByte()) { if (*CheckByte == 0x40U) { // Table segment case is for FunctionReferences proposal. if (!Conf.hasProposal(Proposal::FunctionReferences)) { @@ -21,6 +20,7 @@ Expect Loader::loadSegment(AST::TableSegment &TabSeg) { Proposal::FunctionReferences, FMgr.getLastOffset(), ASTNodeAttr::Seg_Table); } + FMgr.readByte(); // Check the second byte. if (auto Res = FMgr.readByte()) { @@ -45,8 +45,7 @@ Expect Loader::loadSegment(AST::TableSegment &TabSeg) { return Unexpect(Res); } } else { - // The table type case. Seek back 1 byte and read the table type. - FMgr.seek(StartOffset); + // The table type case. if (auto Res = loadType(TabSeg.getTableType()); unlikely(!Res)) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Table)); return Unexpect(Res); @@ -231,28 +230,10 @@ Expect Loader::loadSegment(AST::ElementSegment &ElemSeg) { } [[fallthrough]]; case 0x04: { - uint32_t VecCnt = 0; - if (auto Res = FMgr.readU32(); unlikely(!Res)) { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Seg_Element); - } else { - VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, - FMgr.getLastOffset(), ASTNodeAttr::Seg_Element); - } - } - ElemSeg.getInitExprs().clear(); - ElemSeg.getInitExprs().reserve(VecCnt); - for (uint32_t I = 0; I < VecCnt; ++I) { - ElemSeg.getInitExprs().emplace_back(); - if (auto Res = loadExpression(ElemSeg.getInitExprs().back()); - unlikely(!Res)) { - spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element)); - return Unexpect(Res); - } - } - break; + return loadVec( + ElemSeg.getInitExprs(), [this](AST::Expression &Expr) -> Expect { + return loadExpression(Expr); + }); } default: @@ -275,19 +256,14 @@ Expect Loader::loadSegment(AST::CodeSegment &CodeSeg) { // Read the vector of local variable counts and types. uint32_t VecCnt = 0; - if (auto Res = FMgr.readU32()) { + if (auto Res = loadVecCnt()) { VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), - ASTNodeAttr::Seg_Code); - } - - CodeSeg.getLocals().clear(); - CodeSeg.getLocals().reserve(VecCnt); } else { return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Seg_Code); + ASTNodeAttr::Seg_Element); } + CodeSeg.getLocals().clear(); + CodeSeg.getLocals().reserve(VecCnt); uint32_t TotalLocalCnt = 0; for (uint32_t I = 0; I < VecCnt; ++I) { uint32_t LocalCnt = 0; @@ -389,12 +365,8 @@ Expect Loader::loadSegment(AST::DataSegment &DataSeg) { { // Read initialization data. uint32_t VecCnt = 0; - if (auto Res = FMgr.readU32()) { + if (auto Res = loadVecCnt()) { VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, - FMgr.getLastOffset(), ASTNodeAttr::Seg_Data); - } } else { return logLoadError(Res.error(), FMgr.getLastOffset(), ASTNodeAttr::Seg_Data); diff --git a/lib/loader/ast/type.cpp b/lib/loader/ast/type.cpp index e4ff1aef6453..bea3657a724a 100644 --- a/lib/loader/ast/type.cpp +++ b/lib/loader/ast/type.cpp @@ -29,6 +29,19 @@ Expect Loader::loadHeapType(TypeCode TC, ASTNodeAttr From) { [[fallthrough]]; case TypeCode::FuncRef: return ValType(TC, HTCode); + case TypeCode::NullFuncRef: + case TypeCode::NullExternRef: + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(ErrCode::Value::MalformedRefType, Proposal::GC, + FMgr.getLastOffset(), From); + } + return ValType(TC, HTCode); default: return logLoadError(ErrCode::Value::MalformedRefType, FMgr.getLastOffset(), From); @@ -66,6 +79,19 @@ Expect Loader::loadRefType(ASTNodeAttr From) { // The FuncRef (0x70) is always allowed in the RefType even if the // reference-types proposal not enabled. return ValType(Code); + case TypeCode::NullFuncRef: + case TypeCode::NullExternRef: + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(FailCode, Proposal::GC, FMgr.getLastOffset(), + From); + } + return ValType(Code); case TypeCode::Ref: case TypeCode::RefNull: { if (!Conf.hasProposal(Proposal::FunctionReferences)) { @@ -83,7 +109,7 @@ Expect Loader::loadRefType(ASTNodeAttr From) { } // Load binary and decode ValType. See "include/loader/loader.h". -Expect Loader::loadValType(ASTNodeAttr From) { +Expect Loader::loadValType(ASTNodeAttr From, bool IsStorageType) { if (auto Res = FMgr.readByte()) { TypeCode Code = static_cast(*Res); switch (Code) { @@ -98,6 +124,16 @@ Expect Loader::loadValType(ASTNodeAttr From) { case TypeCode::F32: case TypeCode::F64: return ValType(Code); + case TypeCode::I8: + case TypeCode::I16: + if (!IsStorageType) { + break; + } + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::GC, + FMgr.getLastOffset(), From); + } + return ValType(Code); case TypeCode::FuncRef: if (!Conf.hasProposal(Proposal::ReferenceTypes) && !Conf.hasProposal(Proposal::BulkMemoryOperations)) { @@ -113,6 +149,19 @@ Expect Loader::loadValType(ASTNodeAttr From) { From); } return ValType(Code); + case TypeCode::NullFuncRef: + case TypeCode::NullExternRef: + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::GC, + FMgr.getLastOffset(), From); + } + return ValType(Code); case TypeCode::Ref: case TypeCode::RefNull: if (!Conf.hasProposal(Proposal::FunctionReferences)) { @@ -122,14 +171,89 @@ Expect Loader::loadValType(ASTNodeAttr From) { } return loadHeapType(Code, From); default: - return logLoadError(ErrCode::Value::MalformedValType, - FMgr.getLastOffset(), From); + break; + } + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), From); + } + return logLoadError(ErrCode::Value::MalformedValType, FMgr.getLastOffset(), + From); +} + +Expect Loader::loadMutability(ASTNodeAttr From) { + if (auto Res = FMgr.readByte()) { + switch (static_cast(*Res)) { + case ValMut::Const: + case ValMut::Var: + return static_cast(*Res); + default: + return logLoadError(ErrCode::Value::InvalidMut, FMgr.getLastOffset(), + From); } } else { return logLoadError(Res.error(), FMgr.getLastOffset(), From); } } +Expect Loader::loadFieldType(AST::FieldType &FType) { + if (auto Res = loadValType(ASTNodeAttr::Type_Rec, true)) { + FType.setStorageType(*Res); + } else { + // The error code logging is handled. + return Unexpect(Res); + } + if (auto Res = loadMutability(ASTNodeAttr::Type_Rec)) { + FType.setValMut(*Res); + } else { + // The error code logging is handled. + return Unexpect(Res); + } + return {}; +} + +Expect Loader::loadCompositeType(AST::CompositeType &CType) { + if (auto CodeByte = FMgr.readByte()) { + switch (static_cast(*CodeByte)) { + case TypeCode::Array: { + AST::FieldType FType; + if (auto Res = loadFieldType(FType); unlikely(!Res)) { + return Unexpect(Res); + } + CType.setArrayType(std::move(FType)); + return {}; + } + case TypeCode::Struct: { + std::vector FList; + if (auto Res = loadVec( + FList, + [this](AST::FieldType &FType) -> Expect { + // The error code logging is handled. + return loadFieldType(FType); + }); + !Res) { + return Unexpect(Res); + } + CType.setStructType(std::move(FList)); + return {}; + } + case TypeCode::Func: { + AST::FunctionType FuncType; + if (auto Res = loadType(FuncType); unlikely(!Res)) { + return Unexpect(Res); + } + CType.setFunctionType(std::move(FuncType)); + return {}; + } + default: + return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), + ASTNodeAttr::Type_Rec); + } + } else { + return logLoadError(CodeByte.error(), FMgr.getLastOffset(), + ASTNodeAttr::Type_Rec); + } +} + // Load binary to construct Limit node. See "include/loader/loader.h". Expect Loader::loadLimit(AST::Limit &Lim) { // Read limit. @@ -186,69 +310,77 @@ Expect Loader::loadLimit(AST::Limit &Lim) { return {}; } -// Load binary to construct FunctionType node. See "include/loader/loader.h". -Expect Loader::loadType(AST::FunctionType &FuncType) { - uint32_t VecCnt = 0; - - // Read type of Func (0x60). - if (auto Res = FMgr.readByte()) { - if (static_cast(*Res) != TypeCode::Func) { - return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), - ASTNodeAttr::Type_Function); +// Load binary to construct SubType node. See "include/loader/loader.h". +Expect Loader::loadType(AST::SubType &SType) { + if (auto CodeByte = FMgr.peekByte()) { + switch (static_cast(*CodeByte)) { + default: + // Case: comptype. + SType.setFinal(true); + return loadCompositeType(SType.getCompositeType()); + case TypeCode::Sub: + // Case: 0x50 vec(typeidx) comptype. + SType.setFinal(false); + break; + case TypeCode::SubFinal: + // Case: 0x4F vec(typeidx) comptype. + SType.setFinal(true); + break; } - } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Type_Function); - } - - // Read vector of parameter types. - if (auto Res = FMgr.readU32()) { - VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), - ASTNodeAttr::Type_Function); + FMgr.readByte(); + if (auto Res = loadVec( + SType.getSuperTypeIndices(), + [this](uint32_t &Idx) -> Expect { + if (auto Num = FMgr.readU32()) { + Idx = *Num; + } else { + return logLoadError(Num.error(), FMgr.getLastOffset(), + ASTNodeAttr::Type_Sub); + } + return {}; + }); + !Res) { + return Unexpect(Res); } - FuncType.getParamTypes().clear(); - FuncType.getParamTypes().reserve(VecCnt); + return loadCompositeType(SType.getCompositeType()); } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Type_Function); + return logLoadError(CodeByte.error(), FMgr.getLastOffset(), + ASTNodeAttr::Type_Rec); } - for (uint32_t I = 0; I < VecCnt; ++I) { +} + +// Load binary to construct FunctionType node. See "include/loader/loader.h". +Expect Loader::loadType(AST::FunctionType &FuncType) { + // Read type of Func (0x60). Moved into the composite type. + auto LoadValType = [this](ValType &VT) -> Expect { if (auto Res = loadValType(ASTNodeAttr::Type_Function)) { - FuncType.getParamTypes().push_back(*Res); + VT = *Res; } else { - // The AST node information is handled. + // The error code logging is handled. return Unexpect(Res); } + return {}; + }; + // Read vector of parameter types. + if (auto Res = + loadVec(FuncType.getParamTypes(), LoadValType); + !Res) { + return Unexpect(Res); } // Read vector of result types. - if (auto Res = FMgr.readU32()) { - VecCnt = *Res; - if (VecCnt / 2 > FMgr.getRemainSize()) { - return logLoadError(ErrCode::Value::IntegerTooLong, FMgr.getLastOffset(), - ASTNodeAttr::Type_Function); - } - FuncType.getReturnTypes().clear(); - FuncType.getReturnTypes().reserve(VecCnt); - } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Type_Function); + if (auto Res = + loadVec(FuncType.getReturnTypes(), LoadValType); + !Res) { + return Unexpect(Res); } - if (unlikely(!Conf.hasProposal(Proposal::MultiValue)) && VecCnt > 1) { + + if (unlikely(!Conf.hasProposal(Proposal::MultiValue)) && + FuncType.getReturnTypes().size() > 1) { return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::MultiValue, FMgr.getLastOffset(), ASTNodeAttr::Type_Function); } - for (uint32_t I = 0; I < VecCnt; ++I) { - if (auto Res = loadValType(ASTNodeAttr::Type_Function)) { - FuncType.getReturnTypes().push_back(*Res); - } else { - // The AST node information is handled. - return Unexpect(Res); - } - } return {}; } @@ -291,19 +423,11 @@ Expect Loader::loadType(AST::GlobalType &GlobType) { } // Read mutability. - if (auto Res = FMgr.readByte()) { - GlobType.setValMut(static_cast(*Res)); - switch (GlobType.getValMut()) { - case ValMut::Const: - case ValMut::Var: - break; - default: - return logLoadError(ErrCode::Value::InvalidMut, FMgr.getLastOffset(), - ASTNodeAttr::Type_Global); - } + if (auto Res = loadMutability(ASTNodeAttr::Type_Global)) { + GlobType.setValMut(*Res); } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Type_Global); + // The AST node information is handled. + return Unexpect(Res); } return {}; } diff --git a/lib/loader/filemgr.cpp b/lib/loader/filemgr.cpp index 775d962f71e6..a9d62384d8a6 100644 --- a/lib/loader/filemgr.cpp +++ b/lib/loader/filemgr.cpp @@ -370,6 +370,16 @@ Expect FileMgr::readName() { return Str; } +// Peek one byte. See "include/loader/filemgr.h". +Expect FileMgr::peekByte() { + if (auto Res = readByte()) { + Pos--; + return Res; + } else { + return Unexpect(Res); + } +} + // Get the file header type. See "include/loader/filemgr.h". FileMgr::FileHeader FileMgr::getHeaderType() { if (Size >= 4) { From 22fed600640a395e7e43ff2036ffbb86b9ed9531 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 5 Feb 2024 16:05:08 +0800 Subject: [PATCH 045/218] [Validator] GC proposal validator. Signed-off-by: YiYing He --- include/validator/formchecker.h | 18 +- include/validator/validator.h | 1 + lib/validator/formchecker.cpp | 761 ++++++++++++++++++++++---------- lib/validator/validator.cpp | 165 +++++-- 4 files changed, 671 insertions(+), 274 deletions(-) diff --git a/include/validator/formchecker.h b/include/validator/formchecker.h index cfacaf4fd6a5..4e189ba37b13 100644 --- a/include/validator/formchecker.h +++ b/include/validator/formchecker.h @@ -32,14 +32,6 @@ typedef std::optional VType; static inline constexpr VType unreachableVType() { return VType(); } -static inline constexpr bool isNumType(const VType V) { - return !V || V->isNumType(); -} - -static inline constexpr bool isRefType(const VType V) { - return !V || V->isRefType(); -} - class FormChecker { public: FormChecker() = default; @@ -50,7 +42,7 @@ class FormChecker { Expect validate(const ValType &VT) const noexcept; /// Adder of contexts - void addType(const AST::FunctionType &Func); + void addType(const AST::SubType &Type); void addFunc(const uint32_t TypeIdx, const bool IsImport = false); void addTable(const AST::TableType &Tab); void addMemory(const AST::MemoryType &Mem); @@ -72,11 +64,7 @@ class FormChecker { /// Helper function ValType VTypeToAST(const VType &V); - /// ValType matcher - bool matchType(const ValType &Exp, const ValType &Got) const noexcept; - bool matchTypes(Span Exp, - Span Got) const noexcept; - + /// Control frame struct CtrlFrame { CtrlFrame() = default; CtrlFrame(struct CtrlFrame &&F) @@ -136,7 +124,7 @@ class FormChecker { Expect StackPopAny(); /// Contexts. - std::vector, std::vector>> Types; + std::vector Types; std::vector Funcs; std::vector Tables; uint32_t Mems = 0; diff --git a/include/validator/validator.h b/include/validator/validator.h index a508ad9af7c4..3b5991d668b5 100644 --- a/include/validator/validator.h +++ b/include/validator/validator.h @@ -37,6 +37,7 @@ class Validator { private: /// Validate AST::Types + Expect validate(const AST::SubType &Type); Expect validate(const AST::Limit &Lim); Expect validate(const AST::TableType &Tab); Expect validate(const AST::MemoryType &Mem); diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index 1d09abc06e63..b66e8e40050a 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -68,18 +68,7 @@ Expect FormChecker::validate(const ValType &VT) const noexcept { return {}; } -void FormChecker::addType(const AST::FunctionType &Func) { - std::vector Param, Ret; - Param.reserve(Func.getParamTypes().size()); - Ret.reserve(Func.getReturnTypes().size()); - for (auto Val : Func.getParamTypes()) { - Param.push_back(Val); - } - for (auto Val : Func.getReturnTypes()) { - Ret.push_back(Val); - } - Types.emplace_back(std::move(Param), std::move(Ret)); -} +void FormChecker::addType(const AST::SubType &Type) { Types.push_back(&Type); } void FormChecker::addFunc(const uint32_t TypeIdx, const bool IsImport) { if (Types.size() > TypeIdx) { @@ -129,60 +118,6 @@ ValType FormChecker::VTypeToAST(const VType &V) { return *V; } -bool FormChecker::matchType(const ValType &Exp, - const ValType &Got) const noexcept { - if (!Exp.isRefType() && !Got.isRefType() && Exp.getCode() == Got.getCode()) { - // Match for the non-reference type case. - return true; - } - if (Exp.isRefType() && Got.isRefType()) { - // Nullable matching. - if (!Exp.isNullableRefType() && Got.isNullableRefType()) { - return false; - } - - // Match the heap type. - if (Exp.getHeapTypeCode() == Got.getHeapTypeCode() && - Exp.getHeapTypeCode() != TypeCode::TypeIndex) { - // Abs heap types are the same. - return true; - } - if (Exp.getHeapTypeCode() == TypeCode::FuncRef && - Got.getHeapTypeCode() == TypeCode::TypeIndex) { - // Match type index to any funcref. - return true; - } - if (Exp.getHeapTypeCode() == TypeCode::TypeIndex && - Got.getHeapTypeCode() == TypeCode::TypeIndex) { - // Match got type index to expected type index. - if (matchTypes(Types[Exp.getTypeIndex()].first, - Types[Got.getTypeIndex()].first) && - matchTypes(Types[Exp.getTypeIndex()].second, - Types[Got.getTypeIndex()].second)) { - // Note: In future versions of WebAssembly, subtyping on function types - // may be relaxed to support co- and contra-variance. - // Due to passing the validation of type section, this will not cause - // infinite recursion. - return true; - } - } - } - return false; -} - -bool FormChecker::matchTypes(Span Exp, - Span Got) const noexcept { - if (Exp.size() != Got.size()) { - return false; - } - for (uint32_t I = 0; I < Exp.size(); I++) { - if (!matchType(Exp[I], Got[I])) { - return false; - } - } - return true; -} - Expect FormChecker::checkExpr(AST::InstrView Instrs) { if (Instrs.size() > 0) { // Push ctrl frame ([] -> [Returns]) @@ -203,13 +138,31 @@ Expect FormChecker::checkInstrs(AST::InstrView Instrs) { } return {}; } + Expect FormChecker::checkInstr(const AST::Instruction &Instr) { // Note: The instructions and their immediates have passed proposal // configuration checking in loader phase. + // Helper lambda for checking the defined type. + auto checkDefinedType = + [this](uint32_t TIdx, TypeCode TC) -> Expect { + if (TIdx >= Types.size()) { + return logOutOfRange(ErrCode::Value::InvalidFuncTypeIdx, + ErrInfo::IndexCategory::FunctionType, TIdx, + static_cast(Types.size())); + } + const auto &CType = Types[TIdx]->getCompositeType(); + if (CType.getContentTypeCode() == TC) { + return &CType; + } else { + spdlog::error(ErrCode::Value::TypeCheckFailed); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + }; + // Helper lambda for checking and resolve the block type. - auto checkBlockType = [this](std::vector &Buffer, - const BlockType &BType) + auto checkBlockType = [this, checkDefinedType](std::vector &Buffer, + const BlockType &BType) -> Expect, Span>> { using ReturnType = std::pair, Span>; if (BType.isEmpty()) { @@ -223,14 +176,13 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { Buffer[0] = BType.getValType(); return ReturnType{{}, Buffer}; } else { - // Type index case. t2* = type[index].returns - const uint32_t TypeIdx = BType.getTypeIndex(); - if (TypeIdx >= Types.size()) { - return logOutOfRange(ErrCode::Value::InvalidFuncTypeIdx, - ErrInfo::IndexCategory::FunctionType, TypeIdx, - static_cast(Types.size())); + // Type index case. t2* = functype.returns. + if (auto Res = checkDefinedType(BType.getTypeIndex(), TypeCode::Func)) { + const auto &FType = (*Res)->getFuncType(); + return ReturnType{FType.getParamTypes(), FType.getReturnTypes()}; + } else { + return Unexpect(Res); } - return ReturnType{Types[TypeIdx].first, Types[TypeIdx].second}; } }; @@ -298,16 +250,9 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { // Helper lambda for checking value types matching. auto checkTypesMatching = [this](Span Exp, Span Got) -> Expect { - if (!matchTypes(Exp, Got)) { - std::vector ExpV, GotV; - ExpV.reserve(Exp.size()); - for (auto &I : Exp) { - ExpV.push_back(I); - } - GotV.reserve(Got.size()); - for (auto &I : Got) { - GotV.push_back(I); - } + if (!AST::TypeMatcher::matchTypes(Types, Exp, Got)) { + std::vector ExpV(Exp.begin(), Exp.end()), + GotV(Got.begin(), Got.end()); spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error(ErrInfo::InfoMismatch(ExpV, GotV)); return Unexpect(ErrCode::Value::TypeCheckFailed); @@ -315,13 +260,61 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return {}; }; + // Helper lambda for recording jump data. + auto recordJump = [this, &Instr](AST::Instruction::JumpDescriptor &Jump, + uint32_t Arity, CtrlFrame &Frame) -> void { + const uint32_t Remain = + static_cast(ValStack.size() - Frame.Height); + Jump.StackEraseBegin = Remain + Arity; + Jump.StackEraseEnd = Arity; + Jump.PCOffset = static_cast(Frame.Jump - &Instr); + }; + + // Helper lambda for unpacking a value type. + auto unpackType = [](const ValType &T) -> ValType { + if (T.isPackType()) { + return ValType(TypeCode::I32); + } + return T; + }; + + // Helper lambda for downcasting into the top heap type. + auto toTopHeapType = [this](const ValType &T) -> ValType { + assuming(T.isRefType()); + if (T.isAbsHeapType()) { + switch (T.getHeapTypeCode()) { + case TypeCode::NullFuncRef: + case TypeCode::FuncRef: + return TypeCode::FuncRef; + case TypeCode::NullExternRef: + case TypeCode::ExternRef: + return TypeCode::ExternRef; + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + return TypeCode::AnyRef; + default: + assumingUnreachable(); + } + } else { + const auto &CompType = Types[T.getTypeIndex()]->getCompositeType(); + if (CompType.isFunc()) { + return TypeCode::FuncRef; + } else { + return TypeCode::AnyRef; + } + } + }; + switch (Instr.getOpCode()) { // Control instructions. case OpCode::Unreachable: return unreachable(); case OpCode::Nop: return {}; - case OpCode::If: case OpCode::Block: case OpCode::Loop: { @@ -383,13 +376,8 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { if (auto Res = popTypes(NTypes); !Res) { return Unexpect(Res); } - const uint32_t Remain = - static_cast(ValStack.size() - CtrlStack[*D].Height); - const uint32_t Arity = static_cast(NTypes.size()); - auto &Jump = const_cast(Instr).getJump(); - Jump.StackEraseBegin = Remain + Arity; - Jump.StackEraseEnd = Arity; - Jump.PCOffset = static_cast(CtrlStack[*D].Jump - &Instr); + recordJump(const_cast(Instr).getJump(), + static_cast(NTypes.size()), CtrlStack[*D]); return unreachable(); } case OpCode::Br_if: @@ -404,13 +392,8 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { if (auto Res = popTypes(NTypes); !Res) { return Unexpect(Res); } - const uint32_t Remain = - static_cast(ValStack.size() - CtrlStack[*D].Height); - const uint32_t Arity = static_cast(NTypes.size()); - auto &Jump = const_cast(Instr).getJump(); - Jump.StackEraseBegin = Remain + Arity; - Jump.StackEraseEnd = Arity; - Jump.PCOffset = static_cast(CtrlStack[*D].Jump - &Instr); + recordJump(const_cast(Instr).getJump(), + static_cast(NTypes.size()), CtrlStack[*D]); pushTypes(NTypes); return {}; } @@ -450,13 +433,8 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } } - const uint32_t Remain = - static_cast(ValStack.size() - CtrlStack[*N].Height); - const uint32_t Arity = static_cast(NTypes.size()); - LabelTable[LabelIdx].StackEraseBegin = Remain + Arity; - LabelTable[LabelIdx].StackEraseEnd = Arity; - LabelTable[LabelIdx].PCOffset = - static_cast(CtrlStack[*N].Jump - &Instr); + recordJump(LabelTable[LabelIdx], static_cast(NTypes.size()), + CtrlStack[*N]); pushTypes(TypeBuf); } else { return Unexpect(N); @@ -466,13 +444,8 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { if (auto Res = popTypes(NTypes); !Res) { return Unexpect(Res); } - const uint32_t Remain = - static_cast(ValStack.size() - CtrlStack[*M].Height); - const uint32_t Arity = static_cast(NTypes.size()); - LabelTable[LabelTableSize].StackEraseBegin = Remain + Arity; - LabelTable[LabelTableSize].StackEraseEnd = Arity; - LabelTable[LabelTableSize].PCOffset = - static_cast(CtrlStack[*M].Jump - &Instr); + recordJump(LabelTable[LabelTableSize], + static_cast(NTypes.size()), CtrlStack[*M]); return unreachable(); } else { return Unexpect(M); @@ -484,27 +457,21 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { if (auto D = checkCtrlStackDepth(Instr.getTargetIndex())) { const auto NTypes = getLabelTypes(CtrlStack[*D]); if (auto ResT = popType()) { - if (*ResT == unreachableVType()) { - // will not reach here. Validation succeeds. - return {}; - } - if (!(*ResT)->isRefType()) { + if ((*ResT).has_value() && !(*ResT)->isRefType()) { spdlog::error(ErrCode::Value::InvalidBrRefType); return Unexpect(ErrCode::ErrCode::Value::InvalidBrRefType); } if (auto Res = popTypes(NTypes); !Res) { return Unexpect(Res); } - const uint32_t Remain = - static_cast(ValStack.size() - CtrlStack[*D].Height); - const uint32_t Arity = static_cast(NTypes.size()); - auto &Jump = const_cast(Instr).getJump(); - Jump.StackEraseBegin = Remain + Arity; - Jump.StackEraseEnd = Arity; - Jump.PCOffset = static_cast(CtrlStack[*D].Jump - &Instr); + recordJump(const_cast(Instr).getJump(), + static_cast(NTypes.size()), CtrlStack[*D]); pushTypes(NTypes); - pushType(ValType(TypeCode::Ref, (*ResT)->getHeapTypeCode(), - (*ResT)->getTypeIndex())); + if ((*ResT).has_value()) { + pushType((*ResT)->toNonNullableRef()); + } else { + pushType(unreachableVType()); + } return {}; } else { return Unexpect(ResT); @@ -514,36 +481,27 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } case OpCode::Br_on_non_null: if (auto D = checkCtrlStackDepth(Instr.getTargetIndex())) { + // Get the result type of the label. (Should be [t* rt].) auto LabelTypes = getLabelTypes(CtrlStack[*D]); std::vector NTypes(LabelTypes.begin(), LabelTypes.end()); - if (NTypes.empty()) { + if (unlikely(NTypes.empty())) { spdlog::error(ErrCode::Value::InvalidBrRefType); return Unexpect(ErrCode::Value::InvalidBrRefType); } - ValType RType = NTypes.back(); - NTypes.pop_back(); - if (!RType.isRefType() || RType.isNullableRefType()) { - spdlog::error(ErrCode::Value::InvalidBrRefType); - return Unexpect(ErrCode::Value::InvalidBrRefType); - } - if (auto Res = popType(ValType(TypeCode::RefNull, RType.getHeapTypeCode(), - RType.getTypeIndex())); - !Res) { + // Pop types [t* (ref.null rt)]. + ValType &RT = NTypes.back(); + if (!RT.isRefType()) { spdlog::error(ErrCode::Value::InvalidBrRefType); return Unexpect(ErrCode::Value::InvalidBrRefType); } + RT.toNullableRef(); if (auto Res = popTypes(NTypes); !Res) { - spdlog::error(ErrCode::Value::InvalidBrRefType); - return Unexpect(ErrCode::Value::InvalidBrRefType); + return Unexpect(Res); } - const uint32_t Remain = - static_cast(ValStack.size() - CtrlStack[*D].Height); - const uint32_t Arity = static_cast(NTypes.size() + 1); - // We plus 1 here because we did `pop_back` on `NTypes` - auto &Jump = const_cast(Instr).getJump(); - Jump.StackEraseBegin = Remain + Arity; - Jump.StackEraseEnd = Arity; - Jump.PCOffset = static_cast(CtrlStack[*D].Jump - &Instr); + recordJump(const_cast(Instr).getJump(), + static_cast(NTypes.size()), CtrlStack[*D]); + // Push types [t*]. + NTypes.pop_back(); pushTypes(NTypes); return {}; } else { @@ -558,40 +516,43 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { case OpCode::Call: { auto N = Instr.getTargetIndex(); - if (N >= Funcs.size()) { + if (unlikely(N >= Funcs.size())) { return logOutOfRange(ErrCode::Value::InvalidFuncIdx, ErrInfo::IndexCategory::Function, N, static_cast(Funcs.size())); } - return StackTrans(Types[Funcs[N]].first, Types[Funcs[N]].second); + // Due to validation when adding functions, Type[Funcs[N]] must be a + // function type. + auto &FuncType = Types[Funcs[N]]->getCompositeType().getFuncType(); + return StackTrans(FuncType.getParamTypes(), FuncType.getReturnTypes()); } case OpCode::Call_indirect: { auto N = Instr.getTargetIndex(); auto T = Instr.getSourceIndex(); // Check source table index. - if (T >= Tables.size()) { + if (unlikely(T >= Tables.size())) { return logOutOfRange(ErrCode::Value::InvalidTableIdx, ErrInfo::IndexCategory::Table, T, static_cast(Tables.size())); } - if (!Tables[T].isFuncRefType()) { + if (unlikely(!Tables[T].isFuncRefType())) { spdlog::error(ErrCode::Value::InvalidTableIdx); return Unexpect(ErrCode::Value::InvalidTableIdx); } // Check target function type index. - if (N >= Types.size()) { - return logOutOfRange(ErrCode::Value::InvalidFuncTypeIdx, - ErrInfo::IndexCategory::FunctionType, N, - static_cast(Types.size())); - } - if (auto Res = popType(TypeCode::I32); !Res) { - return Unexpect(Res); + if (auto CompType = checkDefinedType(N, TypeCode::Func)) { + if (auto Res = popType(TypeCode::I32); !Res) { + return Unexpect(Res); + } + const auto &FType = (*CompType)->getFuncType(); + return StackTrans(FType.getParamTypes(), FType.getReturnTypes()); + } else { + return Unexpect(CompType); } - return StackTrans(Types[N].first, Types[N].second); } case OpCode::Return_call: { auto N = Instr.getTargetIndex(); - if (Funcs.size() <= N) { + if (unlikely(N >= Funcs.size())) { // Call function index out of range spdlog::error(ErrCode::Value::InvalidFuncIdx); spdlog::error( @@ -599,12 +560,13 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { static_cast(Funcs.size()))); return Unexpect(ErrCode::Value::InvalidFuncIdx); } - if (!matchTypes(Returns, Types[Funcs[N]].second)) { - spdlog::error(ErrCode::Value::TypeCheckFailed); - spdlog::error(ErrInfo::InfoMismatch(Returns, Types[Funcs[N]].second)); - return Unexpect(ErrCode::Value::TypeCheckFailed); + // Due to validation when adding functions, Type[Funcs[N]] must be a + // function type. + auto &FType = Types[Funcs[N]]->getCompositeType().getFuncType(); + if (auto Res = checkTypesMatching(Returns, FType.getReturnTypes()); !Res) { + return Unexpect(Res); } - if (auto Res = popTypes(Types[Funcs[N]].first); !Res) { + if (auto Res = popTypes(FType.getParamTypes()); !Res) { return Unexpect(Res); } return unreachable(); @@ -613,70 +575,62 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { auto N = Instr.getTargetIndex(); auto T = Instr.getSourceIndex(); // Check source table index. - if (Tables.size() <= T) { - spdlog::error(ErrCode::Value::InvalidTableIdx); - spdlog::error( - ErrInfo::InfoForbidIndex(ErrInfo::IndexCategory::Table, T, - static_cast(Tables.size()))); - return Unexpect(ErrCode::Value::InvalidTableIdx); + if (unlikely(T >= Tables.size())) { + return logOutOfRange(ErrCode::Value::InvalidTableIdx, + ErrInfo::IndexCategory::Table, T, + static_cast(Tables.size())); } - if (!Tables[T].isFuncRefType()) { + if (unlikely(!Tables[T].isFuncRefType())) { spdlog::error(ErrCode::Value::InvalidTableIdx); return Unexpect(ErrCode::Value::InvalidTableIdx); } // Check target function type index. - if (Types.size() <= N) { - spdlog::error(ErrCode::Value::InvalidFuncTypeIdx); - spdlog::error( - ErrInfo::InfoForbidIndex(ErrInfo::IndexCategory::FunctionType, N, - static_cast(Types.size()))); - return Unexpect(ErrCode::Value::InvalidFuncTypeIdx); - } - if (!matchTypes(Returns, Types[N].second)) { - spdlog::error(ErrCode::Value::TypeCheckFailed); - spdlog::error(ErrInfo::InfoMismatch(Returns, Types[N].second)); - return Unexpect(ErrCode::Value::TypeCheckFailed); - } - if (auto Res = popType(TypeCode::I32); !Res) { - return Unexpect(Res); - } - if (auto Res = popTypes(Types[N].first); !Res) { - return Unexpect(Res); + if (auto CompType = checkDefinedType(N, TypeCode::Func)) { + const auto &FType = (*CompType)->getFuncType(); + if (auto Res = checkTypesMatching(Returns, FType.getReturnTypes()); + !Res) { + return Unexpect(Res); + } + if (auto Res = popType(TypeCode::I32); !Res) { + return Unexpect(Res); + } + if (auto Res = popTypes(FType.getParamTypes()); !Res) { + return Unexpect(Res); + } + return unreachable(); + } else { + return Unexpect(CompType); } - return unreachable(); } - case OpCode::Call_ref: { - auto TypeIdx = Instr.getTargetIndex(); - if (TypeIdx >= static_cast(Types.size())) { - return logOutOfRange(ErrCode::Value::InvalidFuncTypeIdx, - ErrInfo::IndexCategory::FunctionType, TypeIdx, - static_cast(Types.size())); + case OpCode::Call_ref: + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Func)) { + const auto &FType = (*Res)->getFuncType(); + std::vector Input = FType.getParamTypes(); + Input.push_back(ValType(TypeCode::RefNull, Instr.getTargetIndex())); + return StackTrans(Input, FType.getReturnTypes()); + } else { + return Unexpect(Res); } - std::vector Input = Types[TypeIdx].first; - Input.push_back(ValType(TypeCode::RefNull, TypeIdx)); - return StackTrans(Input, Types[TypeIdx].second); - } case OpCode::Return_call_ref: { - auto TypeIdx = Instr.getTargetIndex(); - if (TypeIdx >= Types.size()) { - // Call function index out of range - spdlog::error(ErrCode::Value::InvalidFuncIdx); - spdlog::error(ErrInfo::InfoForbidIndex( - ErrInfo::IndexCategory::FunctionType, TypeIdx, - static_cast(Types.size()))); - return Unexpect(ErrCode::Value::InvalidFuncIdx); - } - if (!matchTypes(Returns, Types[TypeIdx].second)) { - spdlog::error(ErrCode::Value::TypeCheckFailed); - spdlog::error(ErrInfo::InfoMismatch(Returns, Types[TypeIdx].second)); - return Unexpect(ErrCode::Value::TypeCheckFailed); - } - std::vector Input = Types[TypeIdx].first; - Input.push_back(ValType(TypeCode::RefNull, TypeIdx)); - if (auto Res = popTypes(Input); !Res) { - return Unexpect(Res); + if (auto CompType = + checkDefinedType(Instr.getTargetIndex(), TypeCode::Func)) { + const auto &FType = (*CompType)->getFuncType(); + if (auto Res = checkTypesMatching(Returns, FType.getReturnTypes()); + !Res) { + return Unexpect(Res); + } + if (auto Res = + popType(ValType(TypeCode::RefNull, Instr.getTargetIndex())); + !Res) { + return Unexpect(Res); + } + if (auto Res = popTypes(FType.getParamTypes()); !Res) { + return Unexpect(Res); + } + return unreachable(); + } else { + return Unexpect(CompType); } - return unreachable(); } // Reference Instructions. @@ -688,7 +642,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } case OpCode::Ref__is_null: if (auto Res = popType()) { - if (!isRefType(*Res)) { + if ((*Res).has_value() && !(*Res)->isRefType()) { spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error( ErrInfo::InfoMismatch(TypeCode::FuncRef, VTypeToAST(*Res))); @@ -710,6 +664,11 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { assuming(TypeIdx < Types.size()); return StackTrans({}, {ValType(TypeCode::Ref, TypeIdx)}); } + case OpCode::Ref__eq: { + return StackTrans({ValType(TypeCode::RefNull, TypeCode::EqRef), + ValType(TypeCode::RefNull, TypeCode::EqRef)}, + {ValType(TypeCode::I32)}); + } case OpCode::Ref__as_non_null: { if (auto Res = popType()) { if (*Res == unreachableVType()) { @@ -722,12 +681,354 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { ValType(TypeCode::RefNull, TypeCode::FuncRef), VTypeToAST(*Res))); return Unexpect(ErrCode::Value::TypeCheckFailed); } - return StackTrans({}, {ValType(TypeCode::Ref, (*Res)->getHeapTypeCode(), - (*Res)->getTypeIndex())}); + return StackTrans({}, {(*Res)->toNonNullableRef()}); + } else { + return Unexpect(Res); + } + } + + case OpCode::Struct__new: + case OpCode::Struct__new_default: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Struct)) { + std::vector Fields; + if (Instr.getOpCode() == OpCode::Struct__new) { + Fields.reserve((*Res)->getFieldTypes().size()); + } + for (auto &FType : (*Res)->getFieldTypes()) { + if (Instr.getOpCode() == OpCode::Struct__new) { + Fields.emplace_back(unpackType(FType.getStorageType())); + } else if (!FType.getStorageType().isDefaultable()) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(" Value type should be defaultable."); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + } + return StackTrans(Fields, + {ValType(TypeCode::Ref, Instr.getTargetIndex())}); + } else { + return Unexpect(Res); + } + } + case OpCode::Struct__get: + case OpCode::Struct__get_s: + case OpCode::Struct__get_u: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Struct)) { + if (Instr.getSourceIndex() >= (*Res)->getFieldTypes().size()) { + return logOutOfRange( + ErrCode::Value::InvalidFieldIdx, ErrInfo::IndexCategory::Field, + Instr.getSourceIndex(), + static_cast((*Res)->getFieldTypes().size())); + } + const auto &FType = (*Res)->getFieldTypes()[Instr.getSourceIndex()]; + if (unlikely(Instr.getOpCode() == OpCode::Struct__get && + FType.getStorageType().isPackType())) { + // For a packed type, the `_s` or `_u` in instruction is required. + spdlog::error(ErrCode::Value::InvalidPackedField); + return Unexpect(ErrCode::Value::InvalidPackedField); + } else if (unlikely(Instr.getOpCode() != OpCode::Struct__get && + !FType.getStorageType().isPackType())) { + // The `_s` or `_u` in instruction only accepts packed field. + spdlog::error(ErrCode::Value::InvalidUnpackedField); + return Unexpect(ErrCode::Value::InvalidUnpackedField); + } + return StackTrans({ValType(TypeCode::RefNull, Instr.getTargetIndex())}, + {unpackType(FType.getStorageType())}); + } else { + return Unexpect(Res); + } + } + case OpCode::Struct__set: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Struct)) { + if (Instr.getSourceIndex() >= (*Res)->getFieldTypes().size()) { + return logOutOfRange( + ErrCode::Value::InvalidFieldIdx, ErrInfo::IndexCategory::Field, + Instr.getSourceIndex(), + static_cast((*Res)->getFieldTypes().size())); + } + const auto &FType = (*Res)->getFieldTypes()[Instr.getSourceIndex()]; + if (FType.getValMut() != ValMut::Var) { + spdlog::error(ErrCode::Value::ImmutableField); + return Unexpect(ErrCode::Value::ImmutableField); + } + return StackTrans({ValType(TypeCode::RefNull, Instr.getTargetIndex()), + unpackType(FType.getStorageType())}, + {}); + } else { + return Unexpect(Res); + } + } + case OpCode::Array__new: + case OpCode::Array__new_default: + case OpCode::Array__new_fixed: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Array)) { + const auto &SType = (*Res)->getFieldTypes()[0].getStorageType(); + if (Instr.getOpCode() == OpCode::Array__new) { + return StackTrans({unpackType(SType), ValType(TypeCode::I32)}, + {ValType(TypeCode::Ref, Instr.getTargetIndex())}); + } else if (Instr.getOpCode() == OpCode::Array__new_default) { + if (!SType.isDefaultable()) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(" Value type should be defaultable."); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + return StackTrans({ValType(TypeCode::I32)}, + {ValType(TypeCode::Ref, Instr.getTargetIndex())}); + } else { + std::vector Fields(Instr.getSourceIndex(), unpackType(SType)); + return StackTrans(Fields, + {ValType(TypeCode::Ref, Instr.getTargetIndex())}); + } + } else { + return Unexpect(Res); + } + } + case OpCode::Array__new_data: + case OpCode::Array__init_data: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Array)) { + const auto &FType = (*Res)->getFieldTypes()[0]; + if (Instr.getOpCode() == OpCode::Array__init_data && + FType.getValMut() != ValMut::Var) { + spdlog::error(ErrCode::Value::ImmutableArray); + return Unexpect(ErrCode::Value::ImmutableArray); + } + if (!unpackType(FType.getStorageType()).isNumType()) { + spdlog::error(ErrCode::Value::ArrayTypesNumtypeRequired); + return Unexpect(ErrCode::Value::ArrayTypesNumtypeRequired); + } + if (Instr.getSourceIndex() >= Datas.size()) { + return logOutOfRange( + ErrCode::Value::InvalidDataIdx, ErrInfo::IndexCategory::Data, + Instr.getSourceIndex(), static_cast(Datas.size())); + } + if (Instr.getOpCode() == OpCode::Array__new_data) { + return StackTrans({ValType(TypeCode::I32), ValType(TypeCode::I32)}, + {ValType(TypeCode::Ref, Instr.getTargetIndex())}); + } else { + return StackTrans({ValType(TypeCode::RefNull, Instr.getTargetIndex()), + ValType(TypeCode::I32), ValType(TypeCode::I32), + ValType(TypeCode::I32)}, + {}); + } + } else { + return Unexpect(Res); + } + } + case OpCode::Array__new_elem: + case OpCode::Array__init_elem: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Array)) { + const auto &FType = (*Res)->getFieldTypes()[0]; + if (Instr.getOpCode() == OpCode::Array__init_elem && + FType.getValMut() != ValMut::Var) { + spdlog::error(ErrCode::Value::ImmutableArray); + return Unexpect(ErrCode::Value::ImmutableArray); + } + if (!FType.getStorageType().isRefType()) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + if (Instr.getSourceIndex() >= Elems.size()) { + return logOutOfRange( + ErrCode::Value::InvalidElemIdx, ErrInfo::IndexCategory::Element, + Instr.getSourceIndex(), static_cast(Elems.size())); + } + if (!AST::TypeMatcher::matchType(Types, FType.getStorageType(), + Elems[Instr.getSourceIndex()])) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(ErrInfo::InfoMismatch(FType.getStorageType(), + Elems[Instr.getSourceIndex()])); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + if (Instr.getOpCode() == OpCode::Array__new_elem) { + return StackTrans({ValType(TypeCode::I32), ValType(TypeCode::I32)}, + {ValType(TypeCode::Ref, Instr.getTargetIndex())}); + } else { + return StackTrans({ValType(TypeCode::RefNull, Instr.getTargetIndex()), + ValType(TypeCode::I32), ValType(TypeCode::I32), + ValType(TypeCode::I32)}, + {}); + } + } else { + return Unexpect(Res); + } + } + case OpCode::Array__get: + case OpCode::Array__get_s: + case OpCode::Array__get_u: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Array)) { + const auto &FType = (*Res)->getFieldTypes()[0]; + if (unlikely(Instr.getOpCode() == OpCode::Array__get && + FType.getStorageType().isPackType())) { + // For a packed type, the `_s` or `_u` in instruction is required. + spdlog::error(ErrCode::Value::InvalidPackedArray); + return Unexpect(ErrCode::Value::InvalidPackedArray); + } else if (unlikely(Instr.getOpCode() != OpCode::Array__get && + !FType.getStorageType().isPackType())) { + // The `_s` or `_u` in instruction only accepts packed array. + spdlog::error(ErrCode::Value::InvalidUnpackedArray); + return Unexpect(ErrCode::Value::InvalidUnpackedArray); + } + return StackTrans({ValType(TypeCode::RefNull, Instr.getTargetIndex()), + ValType(TypeCode::I32)}, + {unpackType(FType.getStorageType())}); + } else { + return Unexpect(Res); + } + } + case OpCode::Array__set: + case OpCode::Array__fill: { + if (auto Res = checkDefinedType(Instr.getTargetIndex(), TypeCode::Array)) { + const auto &FType = (*Res)->getFieldTypes()[0]; + if (FType.getValMut() != ValMut::Var) { + spdlog::error(ErrCode::Value::ImmutableArray); + return Unexpect(ErrCode::Value::ImmutableArray); + } + std::vector Fields = { + ValType(TypeCode::RefNull, Instr.getTargetIndex()), + ValType(TypeCode::I32), unpackType(FType.getStorageType())}; + if (Instr.getOpCode() == OpCode::Array__fill) { + Fields.emplace_back(ValType(TypeCode::I32)); + } + return StackTrans(Fields, {}); + } else { + return Unexpect(Res); + } + } + case OpCode::Array__len: + return StackTrans({ValType(TypeCode::ArrayRef)}, {ValType(TypeCode::I32)}); + case OpCode::Array__copy: { + if (auto Dst = checkDefinedType(Instr.getTargetIndex(), TypeCode::Array)) { + const auto &DstFType = (*Dst)->getFieldTypes()[0]; + if (DstFType.getValMut() != ValMut::Var) { + spdlog::error(ErrCode::Value::ImmutableArray); + return Unexpect(ErrCode::Value::ImmutableArray); + } + if (auto Src = + checkDefinedType(Instr.getSourceIndex(), TypeCode::Array)) { + const auto &SrcFType = (*Src)->getFieldTypes()[0]; + if (!AST::TypeMatcher::matchType(Types, DstFType.getStorageType(), + SrcFType.getStorageType())) { + spdlog::error(ErrCode::Value::ArrayTypesMismatch); + spdlog::error(ErrInfo::InfoMismatch(DstFType.getStorageType(), + SrcFType.getStorageType())); + return Unexpect(ErrCode::Value::ArrayTypesMismatch); + } + return StackTrans({ValType(TypeCode::RefNull, Instr.getTargetIndex()), + ValType(TypeCode::I32), + ValType(TypeCode::RefNull, Instr.getSourceIndex()), + ValType(TypeCode::I32), ValType(TypeCode::I32)}, + {}); + } else { + return Unexpect(Src); + } + } else { + return Unexpect(Dst); + } + } + + case OpCode::Ref__test: + case OpCode::Ref__test_null: + case OpCode::Ref__cast: + case OpCode::Ref__cast_null: { + if (auto Res = validate(Instr.getValType()); !Res) { + return Unexpect(Res); + } + if (auto Res = popType()) { + if (!(*Res).has_value() || !(*Res)->isRefType()) { + // For getting bottom valtype here, matching must fail. + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error( + ErrInfo::InfoMismatch(Instr.getValType(), VTypeToAST(*Res))); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + if (!AST::TypeMatcher::matchType(Types, toTopHeapType(**Res), + Instr.getValType())) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(ErrInfo::InfoMismatch(**Res, Instr.getValType())); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + if (Instr.getOpCode() == OpCode::Ref__test || + Instr.getOpCode() == OpCode::Ref__test_null) { + return StackTrans({}, {ValType(TypeCode::I32)}); + } else { + return StackTrans({}, {Instr.getValType()}); + } } else { return Unexpect(Res); } } + case OpCode::Br_on_cast: + case OpCode::Br_on_cast_fail: { + // The reference types should be valid. + auto &RT1 = Instr.getBrCast().RType1; + auto &RT2 = Instr.getBrCast().RType2; + if (auto Res = validate(RT1); !Res) { + return Unexpect(Res); + } + if (auto Res = validate(RT2); !Res) { + return Unexpect(Res); + } + // The reference type RT2 should match RT1. + if (unlikely(!AST::TypeMatcher::matchType(Types, RT1, RT2))) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(ErrInfo::InfoMismatch(RT1, RT2)); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + if (auto D = checkCtrlStackDepth(Instr.getBrCast().Jump.TargetIndex)) { + // Get the result type of the label. (Should be [t* rt'].) + auto LabelTypes = getLabelTypes(CtrlStack[*D]); + std::vector NTypes(LabelTypes.begin(), LabelTypes.end()); + if (unlikely(NTypes.empty())) { + spdlog::error(ErrCode::Value::InvalidBrRefType); + return Unexpect(ErrCode::Value::InvalidBrRefType); + } + // Get the type difference between rt1 \ rt2. (rt1' = rt1 \ rt2) + ValType RT1P = RT2.isNullableRefType() ? RT1.getNonNullableRef() : RT1; + // For br_on_cast, rt2 must match rt'. + // For Br_on_cast_fail, rt1' must match rt'. + ValType &RTP = NTypes.back(); + const ValType &RTRHS = + Instr.getOpCode() == OpCode::Br_on_cast ? RT2 : RT1P; + if (unlikely(!AST::TypeMatcher::matchType(Types, RTP, RTRHS))) { + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(ErrInfo::InfoMismatch(RTP, RTRHS)); + return Unexpect(ErrCode::Value::TypeCheckFailed); + } + // Pop types [t* rt1]. + RTP = RT1; + if (auto Res = popTypes(NTypes); !Res) { + return Unexpect(Res); + } + recordJump(const_cast(Instr).getBrCast().Jump, + static_cast(NTypes.size()), CtrlStack[*D]); + // For br_on_cast, push types [t* rt1']. + // For Br_on_cast_fail, push types [t* rt2]. + RTP = Instr.getOpCode() == OpCode::Br_on_cast ? RT1P : RT2; + pushTypes(NTypes); + return {}; + } else { + return Unexpect(D); + } + } + case OpCode::Any__convert_extern: + if (auto Res = popType(TypeCode::ExternRef)) { + return StackTrans({}, {ValType((*Res)->getCode(), TypeCode::AnyRef)}); + } else { + return Unexpect(Res); + } + case OpCode::Extern__convert_any: + if (auto Res = popType(TypeCode::AnyRef)) { + return StackTrans({}, {ValType((*Res)->getCode(), TypeCode::ExternRef)}); + } else { + return Unexpect(Res); + } + case OpCode::Ref__i31: + return StackTrans({ValType(TypeCode::I32)}, + {ValType(TypeCode::Ref, TypeCode::I31Ref)}); + case OpCode::I31__get_s: + case OpCode::I31__get_u: + return StackTrans({ValType(TypeCode::RefNull, TypeCode::I31Ref)}, + {ValType(TypeCode::I32)}); + // Parametric Instructions. case OpCode::Drop: return StackPopAny(); @@ -749,12 +1050,12 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } // T1 and T2 should be number type. - if (!isNumType(T1)) { + if (T1.has_value() && !T1->isNumType()) { spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error(ErrInfo::InfoMismatch(TypeCode::I32, VTypeToAST(T1))); return Unexpect(ErrCode::Value::TypeCheckFailed); } - if (!isNumType(T2)) { + if (T2.has_value() && !T2->isNumType()) { spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error(ErrInfo::InfoMismatch(VTypeToAST(T1), VTypeToAST(T2))); return Unexpect(ErrCode::Value::TypeCheckFailed); @@ -883,8 +1184,8 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { Instr.getSourceIndex(), static_cast(Elems.size())); } // Check is the reference types matched. - if (!matchType(Tables[Instr.getTargetIndex()], - Elems[Instr.getSourceIndex()])) { + if (!AST::TypeMatcher::matchType(Types, Tables[Instr.getTargetIndex()], + Elems[Instr.getSourceIndex()])) { spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error(ErrInfo::InfoMismatch(Tables[Instr.getTargetIndex()], Elems[Instr.getSourceIndex()])); @@ -901,8 +1202,8 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { Instr.getSourceIndex(), static_cast(Tables.size())); } // Check is the reference types matched. - if (!matchType(Tables[Instr.getTargetIndex()], - Tables[Instr.getSourceIndex()])) { + if (!AST::TypeMatcher::matchType(Types, Tables[Instr.getTargetIndex()], + Tables[Instr.getSourceIndex()])) { spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error(ErrInfo::InfoMismatch(Tables[Instr.getTargetIndex()], Tables[Instr.getSourceIndex()])); @@ -1868,7 +2169,7 @@ Expect FormChecker::popType(ValType E) { return E; } - if (!matchType(E, **Res)) { + if (!AST::TypeMatcher::matchType(Types, E, **Res)) { // Expect value on value stack is not matched spdlog::error(ErrCode::Value::TypeCheckFailed); spdlog::error(ErrInfo::InfoMismatch(VTypeToAST(E), VTypeToAST(*Res))); diff --git a/lib/validator/validator.cpp b/lib/validator/validator.cpp index 188603b2c359..7985910fc712 100644 --- a/lib/validator/validator.cpp +++ b/lib/validator/validator.cpp @@ -6,6 +6,7 @@ #include "common/errinfo.h" #include +#include #include #include #include @@ -137,6 +138,64 @@ Expect Validator::validate(const AST::Module &Mod) { return {}; } +// Validate Sub type. See "include/validator/validator.h". +Expect Validator::validate(const AST::SubType &Type) { + const auto &TypeVec = Checker.getTypes(); + const auto &CompType = Type.getCompositeType(); + + // Check the validation of the composite type. + if (CompType.isFunc()) { + const auto &FType = CompType.getFuncType(); + for (auto &PType : FType.getParamTypes()) { + if (auto Res = Checker.validate(PType); !Res) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Type_Function)); + return Unexpect(Res); + } + } + for (auto &RType : FType.getReturnTypes()) { + if (auto Res = Checker.validate(RType); !Res) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Type_Function)); + return Unexpect(Res); + } + } + } else { + const auto &FTypes = CompType.getFieldTypes(); + for (auto &FieldType : FTypes) { + if (auto Res = Checker.validate(FieldType.getStorageType()); !Res) { + return Unexpect(Res); + } + } + } + + // In current version, the length of type index vector will be <= 1. + if (Type.getSuperTypeIndices().size() > 1) { + spdlog::error(ErrCode::Value::InvalidSubType); + spdlog::error(" Accepts 1 super type currently."); + return Unexpect(ErrCode::Value::InvalidSubType); + } + for (auto Index : Type.getSuperTypeIndices()) { + if (Index >= TypeVec.size()) { + spdlog::error(ErrCode::Value::InvalidSubType); + spdlog::error( + ErrInfo::InfoForbidIndex(ErrInfo::IndexCategory::DefinedType, Index, + static_cast(TypeVec.size()))); + return Unexpect(ErrCode::Value::InvalidSubType); + } + if (TypeVec[Index]->isFinal()) { + spdlog::error(ErrCode::Value::InvalidSubType); + spdlog::error(" Super type should not be final."); + return Unexpect(ErrCode::Value::InvalidSubType); + } + auto &SuperType = TypeVec[Index]->getCompositeType(); + if (!AST::TypeMatcher::matchType(Checker.getTypes(), SuperType, CompType)) { + spdlog::error(ErrCode::Value::InvalidSubType); + spdlog::error(" Super type not matched."); + return Unexpect(ErrCode::Value::InvalidSubType); + } + } + return {}; +} + // Validate Limit type. See "include/validator/validator.h". Expect Validator::validate(const AST::Limit &Lim) { if (Lim.hasMax() && Lim.getMin() > Lim.getMax()) { @@ -263,7 +322,7 @@ Expect Validator::validate(const AST::ElementSegment &ElemSeg) { static_cast(TableVec.size()))); return Unexpect(ErrCode::Value::InvalidTableIdx); } - // TODO: Use Checker.matchType() to match types instead. + // TODO: Use AST::TypeMatcher::matchType() to match types instead. // For the element segments, the RefType may not record the strict type // index, and should check the init exprs for the real type index to do type // matching. But for the table type, the type index is recorded into the @@ -291,12 +350,16 @@ Expect Validator::validate(const AST::ElementSegment &ElemSeg) { // Validate Code segment. See "include/validator/validator.h". Expect Validator::validate(const AST::CodeSegment &CodeSeg, const uint32_t TypeIdx) { + // Due to the validation of the function section, the type of index bust be a + // function type. + const auto &FuncType = + Checker.getTypes()[TypeIdx]->getCompositeType().getFuncType(); // Reset stack in FormChecker. Checker.reset(); // Add parameters into this frame. - for (auto Val : Checker.getTypes()[TypeIdx].first) { - // Local passed as function parameters should be initialized - Checker.addLocal(Val, true); + for (auto &Type : FuncType.getParamTypes()) { + // Local passed as function parameters should be initialized. + Checker.addLocal(Type, true); } // Add locals into this frame. for (auto Val : CodeSeg.getLocals()) { @@ -310,7 +373,7 @@ Expect Validator::validate(const AST::CodeSegment &CodeSeg, } // Validate function body expression. if (auto Res = Checker.validate(CodeSeg.getExpr().getInstrs(), - Checker.getTypes()[TypeIdx].second); + FuncType.getReturnTypes()); !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Expression)); return Unexpect(Res); @@ -348,7 +411,7 @@ Expect Validator::validate(const AST::ImportDesc &ImpDesc) { // loader phase. case ExternalType::Function: { const auto TId = ImpDesc.getExternalFuncTypeIdx(); - // Function type index must exist in context. + // Function type index must exist in context and be valid. if (TId >= Checker.getTypes().size()) { spdlog::error(ErrCode::Value::InvalidFuncTypeIdx); spdlog::error(ErrInfo::InfoForbidIndex( @@ -356,6 +419,11 @@ Expect Validator::validate(const AST::ImportDesc &ImpDesc) { static_cast(Checker.getTypes().size()))); return Unexpect(ErrCode::Value::InvalidFuncTypeIdx); } + if (!Checker.getTypes()[TId]->getCompositeType().isFunc()) { + spdlog::error(ErrCode::Value::InvalidFuncTypeIdx); + spdlog::error(" Defined type index {} is not a function type.", TId); + return Unexpect(ErrCode::Value::InvalidFuncTypeIdx); + } Checker.addRef(static_cast(Checker.getFunctions().size())); Checker.addFunc(TId, true); return {}; @@ -443,18 +511,41 @@ Expect Validator::validate(const AST::ExportDesc &ExpDesc) { } Expect Validator::validate(const AST::TypeSection &TypeSec) { - for (const auto &Type : TypeSec.getContent()) { - for (auto &PType : Type.getParamTypes()) { - if (auto Res = Checker.validate(PType); !Res) { - return Unexpect(Res); + const auto STypeList = TypeSec.getContent(); + uint32_t Idx = 0; + while (Idx < STypeList.size()) { + const auto &SType = STypeList[Idx]; + if (SType.getRecursiveInfo().has_value()) { + // Recursive type case. Add types first for referring recursively. + uint32_t RecSize = SType.getRecursiveInfo()->RecTypeSize; + for (uint32_t I = Idx; I < Idx + RecSize; I++) { + Checker.addType(STypeList[I]); } - } - for (auto &RType : Type.getReturnTypes()) { - if (auto Res = Checker.validate(RType); !Res) { - return Unexpect(Res); + for (uint32_t I = Idx; I < Idx + RecSize; I++) { + if (auto Res = validate(STypeList[I]); !Res) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Type_Rec)); + return Unexpect(Res); + } } + Idx += RecSize; + } else { + // SubType case. + if (Conf.hasProposal(Proposal::GC)) { + // For the GC proposal, the subtype is seemed as a self-recursive type. + // Add types first for referring recursively. + Checker.addType(SType); + if (auto Res = validate(*Checker.getTypes().back()); !Res) { + return Unexpect(Res); + } + } else { + // Validating first. + if (auto Res = validate(SType); !Res) { + return Unexpect(Res); + } + Checker.addType(SType); + } + Idx++; } - Checker.addType(Type); } return {}; } @@ -484,6 +575,11 @@ Expect Validator::validate(const AST::FunctionSection &FuncSec) { static_cast(TypeVec.size()))); return Unexpect(ErrCode::Value::InvalidFuncTypeIdx); } + if (!TypeVec[TId]->getCompositeType().isFunc()) { + spdlog::error(ErrCode::Value::InvalidFuncTypeIdx); + spdlog::error(" Defined type index {} is not a function type.", TId); + return Unexpect(ErrCode::Value::InvalidFuncTypeIdx); + } Checker.addFunc(TId); } return {}; @@ -590,18 +686,18 @@ Expect Validator::validate(const AST::StartSection &StartSec) { return Unexpect(ErrCode::Value::InvalidFuncIdx); } auto TId = Checker.getFunctions()[FId]; - auto &Type = Checker.getTypes()[TId]; - if (Type.first.size() != 0 || Type.second.size() != 0) { + assuming(TId < Checker.getTypes().size()); + if (!Checker.getTypes()[TId]->getCompositeType().isFunc()) { + spdlog::error(ErrCode::Value::InvalidStartFunc); + spdlog::error(" Defined type index {} is not a function type.", TId); + return Unexpect(ErrCode::Value::InvalidStartFunc); + } + auto &Type = Checker.getTypes()[TId]->getCompositeType().getFuncType(); + if (Type.getParamTypes().size() != 0 || Type.getReturnTypes().size() != 0) { // Start function signature should be {}->{} - std::vector Params, Returns; - for (auto &V : Type.first) { - Params.push_back(Checker.VTypeToAST(V)); - } - for (auto &V : Type.second) { - Returns.push_back(Checker.VTypeToAST(V)); - } spdlog::error(ErrCode::Value::InvalidStartFunc); - spdlog::error(ErrInfo::InfoMismatch({}, {}, Params, Returns)); + spdlog::error(ErrInfo::InfoMismatch({}, {}, Type.getParamTypes(), + Type.getReturnTypes())); return Unexpect(ErrCode::Value::InvalidStartFunc); } } @@ -636,11 +732,14 @@ Expect Validator::validateConstExpr(AST::InstrView Instrs, case OpCode::Global__get: { // For initialization case, global indices must be imported globals. auto GlobIdx = Instr.getTargetIndex(); - if (GlobIdx >= Checker.getNumImportGlobals()) { + uint32_t ValidGlobalSize = Checker.getNumImportGlobals(); + if (Conf.hasProposal(Proposal::GC)) { + ValidGlobalSize = static_cast(Checker.getGlobals().size()); + } + if (GlobIdx >= ValidGlobalSize) { spdlog::error(ErrCode::Value::InvalidGlobalIdx); - spdlog::error(ErrInfo::InfoForbidIndex( - ErrInfo::IndexCategory::Global, GlobIdx, - static_cast(Checker.getNumImportGlobals()))); + spdlog::error(ErrInfo::InfoForbidIndex(ErrInfo::IndexCategory::Global, + GlobIdx, ValidGlobalSize)); spdlog::error( ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); return Unexpect(ErrCode::Value::InvalidGlobalIdx); @@ -676,6 +775,14 @@ Expect Validator::validateConstExpr(AST::InstrView Instrs, case OpCode::Ref__null: case OpCode::V128__const: case OpCode::End: + case OpCode::Struct__new: + case OpCode::Struct__new_default: + case OpCode::Array__new: + case OpCode::Array__new_default: + case OpCode::Array__new_fixed: + case OpCode::Any__convert_extern: + case OpCode::Extern__convert_any: + case OpCode::Ref__i31: break; // For the Extended-const proposal, these instructions are accepted. From 0502d5b15f4cb7eb35d625f1f8ec265ea8bdacaf Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 5 Feb 2024 16:06:32 +0800 Subject: [PATCH 046/218] [Runtime] Runtime structure of GC proposal. Signed-off-by: YiYing He --- include/runtime/hostfunc.h | 15 ++++- include/runtime/instance/array.h | 79 ++++++++++++++++++++++++++ include/runtime/instance/composite.h | 72 +++++++++++++++++++++++ include/runtime/instance/data.h | 14 +++++ include/runtime/instance/function.h | 47 ++++++++------- include/runtime/instance/global.h | 5 +- include/runtime/instance/module.h | 85 +++++++++++++++++++--------- include/runtime/instance/struct.h | 59 +++++++++++++++++++ include/runtime/stackmgr.h | 17 ++++-- 9 files changed, 339 insertions(+), 54 deletions(-) create mode 100644 include/runtime/instance/array.h create mode 100644 include/runtime/instance/composite.h create mode 100644 include/runtime/instance/struct.h diff --git a/include/runtime/hostfunc.h b/include/runtime/hostfunc.h index 783aa8e3013a..cb100b25a864 100644 --- a/include/runtime/hostfunc.h +++ b/include/runtime/hostfunc.h @@ -30,7 +30,8 @@ class CallingFrame; class HostFunctionBase { public: HostFunctionBase() = delete; - HostFunctionBase(const uint64_t FuncCost) : Cost(FuncCost) {} + HostFunctionBase(const uint64_t FuncCost) + : DefType(AST::FunctionType()), Cost(FuncCost) {} virtual ~HostFunctionBase() = default; /// Run host function body. @@ -39,13 +40,18 @@ class HostFunctionBase { Span Rets) = 0; /// Getter of function type. - const AST::FunctionType &getFuncType() const { return FuncType; } + const AST::FunctionType &getFuncType() const noexcept { + return DefType.getCompositeType().getFuncType(); + } /// Getter of host function cost. uint64_t getCost() const { return Cost; } + /// Getter of defined type. + const AST::SubType &getDefinedType() const noexcept { return DefType; } + protected: - AST::FunctionType FuncType; + AST::SubType DefType; const uint64_t Cost; }; @@ -93,6 +99,7 @@ template class HostFunction : public HostFunctionBase { } void initializeFuncType() { + auto &FuncType = DefType.getCompositeType().getFuncType(); using F = FuncTraits; using ArgsT = typename F::ArgsT; FuncType.getParamTypes().reserve(F::ArgsN); @@ -145,6 +152,7 @@ template class HostFunction : public HostFunctionBase { template void pushValType(std::index_sequence) { + auto &FuncType = DefType.getCompositeType().getFuncType(); (FuncType.getParamTypes().push_back( ValTypeFromType>()), ...); @@ -152,6 +160,7 @@ template class HostFunction : public HostFunctionBase { template void pushRetType(std::index_sequence) { + auto &FuncType = DefType.getCompositeType().getFuncType(); (FuncType.getReturnTypes().push_back( ValTypeFromType>()), ...); diff --git a/include/runtime/instance/array.h b/include/runtime/instance/array.h new file mode 100644 index 000000000000..6518b630b1c8 --- /dev/null +++ b/include/runtime/instance/array.h @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/runtime/instance/array.h - Array Instance definition -----===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the array instance definition in store manager. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/type.h" +#include "common/span.h" +#include "common/types.h" +#include "runtime/instance/composite.h" + +#include + +namespace WasmEdge { +namespace Runtime { +namespace Instance { + +class ArrayInstance : public CompositeBase { +public: + ArrayInstance() = delete; + ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, + const uint32_t Size) noexcept + : CompositeBase(Mod, Idx), RefCount(1), + Data(Size, static_cast(0)) { + assuming(ModInst); + } + ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, + const uint32_t Size, const ValVariant &Init) noexcept + : CompositeBase(Mod, Idx), RefCount(1), Data(Size, Init) { + assuming(ModInst); + } + ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, + std::vector &&Init) noexcept + : CompositeBase(Mod, Idx), RefCount(1), Data(std::move(Init)) { + assuming(ModInst); + } + + /// Get field data in array instance. + ValVariant &getData(uint32_t Idx) noexcept { return Data[Idx]; } + const ValVariant &getData(uint32_t Idx) const noexcept { return Data[Idx]; } + + /// Get full array. + Span getArray() noexcept { return Data; } + Span getArray() const noexcept { return Data; } + + /// Get array length. + uint32_t getLength() const noexcept { + return static_cast(Data.size()); + } + + /// Get reference count. + uint32_t getRefCount() const noexcept { return RefCount; } + + /// Get boundary index. + uint32_t getBoundIdx() const noexcept { + return std::max(static_cast(Data.size()), UINT32_C(1)) - + UINT32_C(1); + } + +private: + /// \name Data of array instance. + /// @{ + uint32_t RefCount; + std::vector Data; + /// @} +}; + +} // namespace Instance +} // namespace Runtime +} // namespace WasmEdge diff --git a/include/runtime/instance/composite.h b/include/runtime/instance/composite.h new file mode 100644 index 000000000000..e8b9024e6a3e --- /dev/null +++ b/include/runtime/instance/composite.h @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/runtime/instance/composite.h - Composite base definition -===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the base class definition of composite instances +/// (function, struct, and array). +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/type.h" +#include "common/types.h" + +#include + +namespace WasmEdge { +namespace Runtime { +namespace Instance { + +class ModuleInstance; + +class CompositeBase { +public: + /// Constructor for only host function instance case. + CompositeBase() noexcept : ModInst(nullptr), TypeIdx(0) {} + /// Constructor for function, array, and struct instances. + CompositeBase(const ModuleInstance *Mod, const uint32_t Idx) noexcept + : ModInst(Mod), TypeIdx(Idx) { + assuming(ModInst); + } + + /// Getter of module instance of this instance. + const ModuleInstance *getModule() const noexcept { return ModInst; } + + /// Getter of closed type index of this instance in the module. + uint32_t getTypeIndex() const noexcept { return TypeIdx; } + + /// Getter of value type in defined type form. + ValType getDefType() const noexcept { + if (ModInst) { + return ValType(TypeCode::Ref, TypeIdx); + } else { + // nullptr `ModInst` case is only for host function instance case. + return ValType(TypeCode::Ref, TypeCode::FuncRef); + } + } + +protected: + friend class ModuleInstance; + void linkDefinedType(const ModuleInstance *Mod, + const uint32_t Index) noexcept { + assuming(Mod); + ModInst = Mod; + TypeIdx = Index; + } + + /// \name Data of composite instances. + /// @{ + const ModuleInstance *ModInst; + uint32_t TypeIdx; + /// @} +}; + +} // namespace Instance +} // namespace Runtime +} // namespace WasmEdge diff --git a/include/runtime/instance/data.h b/include/runtime/instance/data.h index 119d94b97052..ae227a1d5351 100644 --- a/include/runtime/instance/data.h +++ b/include/runtime/instance/data.h @@ -34,6 +34,20 @@ class DataInstance { /// Get data in data instance. Span getData() const noexcept { return Data; } + /// Load bytes to value. + ValVariant loadValue(uint32_t Offset, uint32_t N) const noexcept { + assuming(N <= 16); + // Check the data boundary. + if (unlikely(static_cast(Offset) + static_cast(N) > + Data.size())) { + return 0; + } + // Load the data to the value. + uint128_t Value; + std::memcpy(&Value, &Data[Offset], N); + return Value; + } + /// Clear data in data instance. void clear() { Data.clear(); } diff --git a/include/runtime/instance/function.h b/include/runtime/instance/function.h index 5730e91afe5f..0ec9845e8b75 100644 --- a/include/runtime/instance/function.h +++ b/include/runtime/instance/function.h @@ -16,6 +16,7 @@ #include "ast/instruction.h" #include "common/symbol.h" #include "runtime/hostfunc.h" +#include "runtime/instance/composite.h" #include #include @@ -28,30 +29,44 @@ namespace Instance { class ModuleInstance; -class FunctionInstance { +class FunctionInstance : public CompositeBase { public: using CompiledFunction = void; FunctionInstance() = delete; /// Move constructor. FunctionInstance(FunctionInstance &&Inst) noexcept - : ModInst(Inst.ModInst), FuncType(Inst.FuncType), - Data(std::move(Inst.Data)) {} + : CompositeBase(Inst.ModInst, Inst.TypeIdx), FuncType(Inst.FuncType), + Data(std::move(Inst.Data)) { + assuming(ModInst); + } /// Constructor for native function. - FunctionInstance(const ModuleInstance *Mod, const AST::FunctionType &Type, + FunctionInstance(const ModuleInstance *Mod, const uint32_t TIdx, + const AST::FunctionType &Type, Span> Locs, AST::InstrView Expr) noexcept - : ModInst(Mod), FuncType(Type), - Data(std::in_place_type_t(), Locs, Expr) {} + : CompositeBase(Mod, TIdx), FuncType(Type), + Data(std::in_place_type_t(), Locs, Expr) { + assuming(ModInst); + } /// Constructor for compiled function. - FunctionInstance(const ModuleInstance *Mod, const AST::FunctionType &Type, + FunctionInstance(const ModuleInstance *Mod, const uint32_t TIdx, + const AST::FunctionType &Type, Symbol S) noexcept - : ModInst(Mod), FuncType(Type), - Data(std::in_place_type_t>(), std::move(S)) {} - /// Constructor for host function. - FunctionInstance(const ModuleInstance *Mod, + : CompositeBase(Mod, TIdx), FuncType(Type), + Data(std::in_place_type_t>(), std::move(S)) { + assuming(ModInst); + } + /// Constructors for host function. + FunctionInstance(const ModuleInstance *Mod, const uint32_t TIdx, std::unique_ptr &&Func) noexcept - : ModInst(Mod), FuncType(Func->getFuncType()), + : CompositeBase(Mod, TIdx), FuncType(Func->getFuncType()), + Data(std::in_place_type_t>(), + std::move(Func)) { + assuming(ModInst); + } + FunctionInstance(std::unique_ptr &&Func) noexcept + : CompositeBase(), FuncType(Func->getFuncType()), Data(std::in_place_type_t>(), std::move(Func)) {} @@ -70,9 +85,6 @@ class FunctionInstance { return std::holds_alternative>(Data); } - /// Getter of module instance of this function instance. - const ModuleInstance *getModule() const noexcept { return ModInst; } - /// Getter of function type. const AST::FunctionType &getFuncType() const noexcept { return FuncType; } @@ -124,12 +136,9 @@ class FunctionInstance { } }; - friend class ModuleInstance; - void setModule(const ModuleInstance *Mod) noexcept { ModInst = Mod; } - /// \name Data of function instance. /// @{ - const ModuleInstance *ModInst; + const AST::FunctionType &FuncType; std::variant, std::unique_ptr> diff --git a/include/runtime/instance/global.h b/include/runtime/instance/global.h index fcbf590ba97f..9915b82de5af 100644 --- a/include/runtime/instance/global.h +++ b/include/runtime/instance/global.h @@ -35,10 +35,11 @@ class GlobalInstance { /// Getter of value. const ValVariant &getValue() const noexcept { return Value; } - - /// Getter of value. ValVariant &getValue() noexcept { return Value; } + /// Setter of value. + void setValue(const ValVariant &Val) noexcept { Value = Val; } + private: /// \name Data of global instance. /// @{ diff --git a/include/runtime/instance/module.h b/include/runtime/instance/module.h index d9b3a1a440a8..4f0252c02a7a 100644 --- a/include/runtime/instance/module.h +++ b/include/runtime/instance/module.h @@ -16,11 +16,13 @@ #include "ast/type.h" #include "common/errcode.h" #include "runtime/hostfunc.h" +#include "runtime/instance/array.h" #include "runtime/instance/data.h" #include "runtime/instance/elem.h" #include "runtime/instance/function.h" #include "runtime/instance/global.h" #include "runtime/instance/memory.h" +#include "runtime/instance/struct.h" #include "runtime/instance/table.h" #include @@ -91,31 +93,35 @@ class ModuleInstance { void addHostFunc(std::string_view Name, std::unique_ptr &&Func) { std::unique_lock Lock(Mutex); - unsafeAddHostInstance(Name, OwnedFuncInsts, FuncInsts, ExpFuncs, - std::make_unique( - this, std::move(Func))); + unsafeImportDefinedType(Func->getDefinedType()); + unsafeAddHostInstance( + Name, OwnedFuncInsts, FuncInsts, ExpFuncs, + std::make_unique( + this, static_cast(Types.size()) - 1, std::move(Func))); } void addHostFunc(std::string_view Name, - std::unique_ptr &&Func) { + std::unique_ptr &&Func) { std::unique_lock Lock(Mutex); - Func->setModule(this); + assuming(Func->isHostFunction()); + unsafeImportDefinedType(Func->getHostFunc().getDefinedType()); + Func->linkDefinedType(this, static_cast(Types.size()) - 1); unsafeAddHostInstance(Name, OwnedFuncInsts, FuncInsts, ExpFuncs, std::move(Func)); } void addHostTable(std::string_view Name, - std::unique_ptr &&Tab) { + std::unique_ptr &&Tab) { std::unique_lock Lock(Mutex); unsafeAddHostInstance(Name, OwnedTabInsts, TabInsts, ExpTables, std::move(Tab)); } void addHostMemory(std::string_view Name, - std::unique_ptr &&Mem) { + std::unique_ptr &&Mem) { std::unique_lock Lock(Mutex); unsafeAddHostInstance(Name, OwnedMemInsts, MemInsts, ExpMems, std::move(Mem)); } void addHostGlobal(std::string_view Name, - std::unique_ptr &&Glob) { + std::unique_ptr &&Glob) { std::unique_lock Lock(Mutex); unsafeAddHostInstance(Name, OwnedGlobInsts, GlobInsts, ExpGlobals, std::move(Glob)); @@ -183,10 +189,11 @@ class ModuleInstance { friend class Executor::Executor; friend class Runtime::CallingFrame; - /// Copy the function types in type section to this module instance. - void addFuncType(const AST::FunctionType &FuncType) { + /// Create and copy the defined type to this module instance. + void addDefinedType(const AST::SubType &SType) { std::unique_lock Lock(Mutex); - FuncTypes.emplace_back(FuncType); + OwnedTypes.push_back(std::make_unique(SType)); + Types.push_back(OwnedTypes.back().get()); } /// Create and add instances into this module instance. @@ -215,6 +222,18 @@ class ModuleInstance { std::unique_lock Lock(Mutex); unsafeAddInstance(OwnedDataInsts, DataInsts, std::forward(Values)...); } + template ArrayInstance *newArray(Args &&...Values) { + std::unique_lock Lock(Mutex); + OwnedArrayInsts.push_back( + std::make_unique(this, std::forward(Values)...)); + return OwnedArrayInsts.back().get(); + } + template StructInstance *newStruct(Args &&...Values) { + std::unique_lock Lock(Mutex); + OwnedStructInsts.push_back( + std::make_unique(this, std::forward(Values)...)); + return OwnedStructInsts.back().get(); + } /// Import instances into this module instance. void importFunction(FunctionInstance *Func) { @@ -253,17 +272,21 @@ class ModuleInstance { ExpGlobals.insert_or_assign(std::string(Name), GlobInsts[Idx]); } - /// Get function type by index. - Expect getFuncType(uint32_t Idx) const noexcept { + /// Get defined type list. + Span getTypeList() const noexcept { return Types; } + + /// Get instance pointer by index. + Expect getType(uint32_t Idx) const noexcept { std::shared_lock Lock(Mutex); - if (unlikely(Idx >= FuncTypes.size())) { + if (unlikely(Idx >= Types.size())) { // Error logging need to be handled in caller. return Unexpect(ErrCode::Value::WrongInstanceIndex); } - return &FuncTypes[Idx]; + return unsafeGetType(Idx); + } + const AST::SubType *unsafeGetType(uint32_t Idx) const noexcept { + return Types[Idx]; } - - /// Get instance pointer by index. Expect getFunc(uint32_t Idx) const noexcept { std::shared_lock Lock(Mutex); if (Idx >= FuncInsts.size()) { @@ -360,13 +383,20 @@ class ModuleInstance { return StartFunc; } - /// Add the instances under the module by pointers. + /// Unsafe import instance into this module. template std::enable_if_t, void> unsafeImportInstance(std::vector &Vec, T *Ptr) { Vec.push_back(Ptr); } + /// Unsafe import defined type from host function into this module. + void unsafeImportDefinedType(const AST::SubType &SType) { + Types.push_back(&SType); + const_cast(Types.back()) + ->setTypeIndex(static_cast(Types.size()) - 1); + } + /// Unsafe create and add the instance into this module. template std::enable_if_t, void> @@ -429,16 +459,19 @@ class ModuleInstance { /// Module name. const std::string ModName; - /// Function types. - std::vector FuncTypes; + /// Defined types. + std::vector Types; + std::vector> OwnedTypes; /// Owned instances in this module. - std::vector> OwnedFuncInsts; - std::vector> OwnedTabInsts; - std::vector> OwnedMemInsts; - std::vector> OwnedGlobInsts; - std::vector> OwnedElemInsts; - std::vector> OwnedDataInsts; + std::vector> OwnedFuncInsts; + std::vector> OwnedTabInsts; + std::vector> OwnedMemInsts; + std::vector> OwnedGlobInsts; + std::vector> OwnedElemInsts; + std::vector> OwnedDataInsts; + std::vector> OwnedArrayInsts; + std::vector> OwnedStructInsts; /// Imported and added instances in this module. std::vector FuncInsts; diff --git a/include/runtime/instance/struct.h b/include/runtime/instance/struct.h new file mode 100644 index 000000000000..be72143ec7d9 --- /dev/null +++ b/include/runtime/instance/struct.h @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/runtime/instance/struct.h - Struct Instance definition ---===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the struct instance definition in store manager. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/type.h" +#include "common/span.h" +#include "common/types.h" +#include "runtime/instance/composite.h" + +#include + +namespace WasmEdge { +namespace Runtime { +namespace Instance { + +class StructInstance : public CompositeBase { +public: + StructInstance() = delete; + StructInstance(const ModuleInstance *Mod, const uint32_t Idx, + const uint32_t MemberCnt) noexcept + : CompositeBase(Mod, Idx), RefCount(1), + Data(MemberCnt, static_cast(0)) { + assuming(ModInst); + } + StructInstance(const ModuleInstance *Mod, const uint32_t Idx, + std::vector &&Init) noexcept + : CompositeBase(Mod, Idx), RefCount(1), Data(std::move(Init)) { + assuming(ModInst); + } + + /// Get field data in struct instance. + ValVariant &getField(uint32_t Idx) noexcept { return Data[Idx]; } + const ValVariant &getField(uint32_t Idx) const noexcept { return Data[Idx]; } + + /// Get reference count. + uint32_t getRefCount() const noexcept { return RefCount; } + +private: + /// \name Data of struct instance. + /// @{ + uint32_t RefCount; + std::vector Data; + /// @} +}; + +} // namespace Instance +} // namespace Runtime +} // namespace WasmEdge diff --git a/include/runtime/stackmgr.h b/include/runtime/stackmgr.h index 1d28b1e91233..ef9b521fd755 100644 --- a/include/runtime/stackmgr.h +++ b/include/runtime/stackmgr.h @@ -49,16 +49,16 @@ class StackManager { /// Getter of stack size. size_t size() const noexcept { return ValueStack.size(); } - /// Unsafe Getter of top entry of stack. + /// Unsafe getter of top entry of stack. Value &getTop() { return ValueStack.back(); } - /// Unsafe Getter of top N-th value entry of stack. + /// Unsafe getter of top N-th value entry of stack. Value &getTopN(uint32_t Offset) noexcept { assuming(0 < Offset && Offset <= ValueStack.size()); return ValueStack[ValueStack.size() - Offset]; } - /// Unsafe Getter of top N value entries of stack. + /// Unsafe getter of top N value entries of stack. Span getTopSpan(uint32_t N) { return Span(ValueStack.end() - N, N); } @@ -68,13 +68,22 @@ class StackManager { ValueStack.push_back(std::forward(Val)); } - /// Unsafe Pop and return the top entry. + /// Unsafe pop and return the top entry. Value pop() { Value V = std::move(ValueStack.back()); ValueStack.pop_back(); return V; } + /// Unsafe pop and return the top N entries. + std::vector pop(uint32_t N) { + std::vector Vec; + Vec.reserve(N); + std::move(ValueStack.end() - N, ValueStack.end(), std::back_inserter(Vec)); + ValueStack.erase(ValueStack.end() - N, ValueStack.end()); + return Vec; + } + /// Push a new frame entry to stack. void pushFrame(const Instance::ModuleInstance *Module, AST::InstrView::iterator From, uint32_t LocalNum = 0, From e751adbec85f4bfba65cf2f8cec08eeb68d78405 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 7 Feb 2024 18:11:12 +0800 Subject: [PATCH 047/218] [Executor] GC proposal execution and fix for AOT. Signed-off-by: YiYing He --- include/executor/executor.h | 103 ++++- lib/api/wasmedge.cpp | 34 +- lib/executor/CMakeLists.txt | 1 + lib/executor/engine/controlInstr.cpp | 69 ++- lib/executor/engine/engine.cpp | 168 ++++++-- lib/executor/engine/proxy.cpp | 40 +- lib/executor/engine/refInstr.cpp | 599 ++++++++++++++++++++++++++ lib/executor/engine/variableInstr.cpp | 2 +- lib/executor/executor.cpp | 39 +- lib/executor/helper.cpp | 70 +-- lib/executor/instantiate/function.cpp | 13 +- lib/executor/instantiate/import.cpp | 100 ++--- lib/executor/instantiate/module.cpp | 26 +- lib/llvm/compiler.cpp | 46 +- 14 files changed, 1073 insertions(+), 237 deletions(-) create mode 100644 lib/executor/engine/refInstr.cpp diff --git a/include/executor/executor.h b/include/executor/executor.h index dcceb2fa5db8..d0de566c141e 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -274,21 +274,12 @@ class Executor { AST::InstrView::iterator &PC) noexcept; /// @} - /// \name Helper Functions for matching value types. - /// @{ - bool matchType(const Runtime::Instance::ModuleInstance &ModExp, - const ValType &Exp, - const Runtime::Instance::ModuleInstance &ModGot, - const ValType &Got) const noexcept; - - bool matchTypes(const Runtime::Instance::ModuleInstance &ModExp, - Span Exp, - const Runtime::Instance::ModuleInstance &ModGot, - Span Got) const noexcept; - /// @} - /// \name Helper Functions for getting instances. /// @{ + /// Helper function for get defined type by index. + const AST::SubType *getDefTypeByIdx(Runtime::StackManager &StackMgr, + const uint32_t Idx) const; + /// Helper function for get function instance by index. Runtime::Instance::FunctionInstance * getFuncInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; @@ -326,15 +317,19 @@ class Executor { Expect runBrIfOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; - Expect runBrOnNull(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept; - Expect runBrOnNonNull(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept; + Expect runBrOnNullOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; + Expect runBrOnNonNullOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; Expect runBrTableOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; + Expect runBrOnCastOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC, + bool IsReverse = false) noexcept; Expect runReturnOp(Runtime::StackManager &StackMgr, AST::InstrView::iterator &PC) noexcept; Expect runCallOp(Runtime::StackManager &StackMgr, @@ -360,6 +355,76 @@ class Executor { uint32_t Idx) const noexcept; Expect runGlobalSetOp(Runtime::StackManager &StackMgr, uint32_t Idx) const noexcept; + /// ======= Reference instructions ======= + Expect runRefNullOp(Runtime::StackManager &StackMgr, + const ValType &Type) const noexcept; + Expect runRefIsNullOp(ValVariant &Val) const noexcept; + Expect runRefFuncOp(Runtime::StackManager &StackMgr, + uint32_t Idx) const noexcept; + Expect runRefEqOp(ValVariant &Val1, + const ValVariant &Val2) const noexcept; + Expect runRefAsNonNullOp(RefVariant &Val, + const AST::Instruction &Instr) const noexcept; + Expect runStructNewOp(Runtime::StackManager &StackMgr, + const uint32_t DefIndex, + bool IsDefault = false) const noexcept; + Expect runStructGetOp(ValVariant &Val, const uint32_t Idx, + const AST::CompositeType &CompType, + const AST::Instruction &Instr, + bool IsSigned = false) const noexcept; + Expect runStructSetOp(const ValVariant &Val, const RefVariant &InstRef, + const AST::CompositeType &CompType, uint32_t Idx, + const AST::Instruction &Instr) const noexcept; + Expect runArrayNewOp(Runtime::StackManager &StackMgr, + const uint32_t DefIndex, uint32_t InitCnt, + uint32_t ValCnt) const noexcept; + Expect + runArrayNewDataOp(Runtime::StackManager &StackMgr, + const Runtime::Instance::DataInstance &DataInst, + const AST::Instruction &Instr) const noexcept; + Expect + runArrayNewElemOp(Runtime::StackManager &StackMgr, + const Runtime::Instance::ElementInstance &ElemInst, + const AST::Instruction &Instr) const noexcept; + Expect runArraySetOp(const ValVariant &Val, const uint32_t Idx, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const AST::Instruction &Instr) const noexcept; + Expect runArrayGetOp(ValVariant &Val, const uint32_t Idx, + const AST::CompositeType &CompType, + const AST::Instruction &Instr, + bool IsSigned = false) const noexcept; + Expect runArrayLenOp(ValVariant &Val, + const AST::Instruction &Instr) const noexcept; + Expect runArrayFillOp(uint32_t N, const ValVariant &Val, uint32_t D, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const AST::Instruction &Instr) const noexcept; + Expect runArrayCopyOp(uint32_t N, uint32_t S, + const RefVariant &SrcInstRef, uint32_t D, + const RefVariant &DstInstRef, + const AST::CompositeType &SrcCompType, + const AST::CompositeType &DstCompType, + const AST::Instruction &Instr) const noexcept; + Expect + runArrayInitDataOp(uint32_t N, uint32_t S, uint32_t D, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const Runtime::Instance::DataInstance &DataInst, + const AST::Instruction &Instr) const noexcept; + Expect + runArrayInitElemOp(uint32_t N, uint32_t S, uint32_t D, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const Runtime::Instance::ElementInstance &ElemInst, + const AST::Instruction &Instr) const noexcept; + Expect runRefTestOp(const Runtime::Instance::ModuleInstance *ModInst, + ValVariant &Val, const AST::Instruction &Instr, + bool IsCast = false) const noexcept; + Expect runRefConvOp(RefVariant &Val, TypeCode TCode) const noexcept; + Expect runRefI31Op(ValVariant &Val) const noexcept; + Expect runI31GetOp(ValVariant &Val, const AST::Instruction &Instr, + bool IsSigned = false) const noexcept; /// ======= Table instructions ======= Expect runTableGetOp(Runtime::StackManager &StackMgr, Runtime::Instance::TableInstance &TabInst, diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index 5871405c9a69..618c2b0924dc 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -396,20 +396,21 @@ class CAPIHostFunc : public Runtime::HostFunctionBase { void *ExtData, const uint64_t FuncCost = 0) noexcept : Runtime::HostFunctionBase(FuncCost), Func(FuncPtr), Wrap(nullptr), Binding(nullptr), Data(ExtData) { - FuncType = *Type; + DefType.getCompositeType().getFuncType() = *Type; } CAPIHostFunc(const AST::FunctionType *Type, WasmEdge_WrapFunc_t WrapPtr, void *BindingPtr, void *ExtData, const uint64_t FuncCost = 0) noexcept : Runtime::HostFunctionBase(FuncCost), Func(nullptr), Wrap(WrapPtr), Binding(BindingPtr), Data(ExtData) { - FuncType = *Type; + DefType.getCompositeType().getFuncType() = *Type; } ~CAPIHostFunc() noexcept override = default; Expect run(const Runtime::CallingFrame &CallFrame, Span Args, Span Rets) override { + auto &FuncType = DefType.getCompositeType().getFuncType(); std::vector Params(FuncType.getParamTypes().size()), Returns(FuncType.getReturnTypes().size()); for (uint32_t I = 0; I < Args.size(); I++) { @@ -1375,12 +1376,10 @@ WasmEdge_ImportTypeGetFunctionType(const WasmEdge_ASTModuleContext *ASTCxt, fromImpTypeCxt(Cxt)->getExternalType() == WasmEdge::ExternalType::Function) { uint32_t Idx = fromImpTypeCxt(Cxt)->getExternalFuncTypeIdx(); - const auto &FuncTypes = - fromASTModCxt(ASTCxt)->getTypeSection().getContent(); - if (Idx >= FuncTypes.size()) { - return nullptr; + auto SubTypes = fromASTModCxt(ASTCxt)->getTypeSection().getContent(); + if (Idx < SubTypes.size() && SubTypes[Idx].getCompositeType().isFunc()) { + return toFuncTypeCxt(&(SubTypes[Idx].getCompositeType().getFuncType())); } - return toFuncTypeCxt(&FuncTypes[Idx]); } return nullptr; } @@ -1448,7 +1447,6 @@ WasmEdge_ExportTypeGetFunctionType(const WasmEdge_ASTModuleContext *ASTCxt, WasmEdge::ExternalType::Function) { auto ImpDescs = fromASTModCxt(ASTCxt)->getImportSection().getContent(); auto FuncIdxs = fromASTModCxt(ASTCxt)->getFunctionSection().getContent(); - auto FuncTypes = fromASTModCxt(ASTCxt)->getTypeSection().getContent(); uint32_t ExtIdx = fromExpTypeCxt(Cxt)->getExternalIndex(); // Indexing the import descriptions. @@ -1471,11 +1469,13 @@ WasmEdge_ExportTypeGetFunctionType(const WasmEdge_ASTModuleContext *ASTCxt, // Invalid function index. return nullptr; } - // Get the function type by index. - if (TypeIdx >= FuncTypes.size()) { - return nullptr; + // Get the function type. + auto SubTypes = fromASTModCxt(ASTCxt)->getTypeSection().getContent(); + if (TypeIdx < SubTypes.size() && + SubTypes[TypeIdx].getCompositeType().isFunc()) { + return toFuncTypeCxt( + &(SubTypes[TypeIdx].getCompositeType().getFuncType())); } - return toFuncTypeCxt(&FuncTypes[TypeIdx]); } return nullptr; } @@ -2208,8 +2208,8 @@ WasmEdge_FunctionInstanceCreate(const WasmEdge_FunctionTypeContext *Type, const uint64_t Cost) { if (Type && HostFunc) { return toFuncCxt(new WasmEdge::Runtime::Instance::FunctionInstance( - nullptr, std::make_unique(fromFuncTypeCxt(Type), HostFunc, - Data, Cost))); + std::make_unique(fromFuncTypeCxt(Type), HostFunc, Data, + Cost))); } return nullptr; } @@ -2221,8 +2221,8 @@ WasmEdge_FunctionInstanceCreateBinding(const WasmEdge_FunctionTypeContext *Type, const uint64_t Cost) { if (Type && WrapFunc) { return toFuncCxt(new WasmEdge::Runtime::Instance::FunctionInstance( - nullptr, std::make_unique(fromFuncTypeCxt(Type), WrapFunc, - Binding, Data, Cost))); + std::make_unique(fromFuncTypeCxt(Type), WrapFunc, Binding, + Data, Cost))); } return nullptr; } @@ -2572,7 +2572,7 @@ WASMEDGE_CAPI_EXPORT WasmEdge_Result WasmEdge_GlobalInstanceSetValue( return Unexpect(WasmEdge::ErrCode::Value::SetValueErrorType); } } - fromGlobCxt(Cxt)->getValue() = Val; + fromGlobCxt(Cxt)->setValue(Val); return {}; }, EmptyThen, Cxt); diff --git a/lib/executor/CMakeLists.txt b/lib/executor/CMakeLists.txt index 79c3b978fddf..d9eb7232fda0 100644 --- a/lib/executor/CMakeLists.txt +++ b/lib/executor/CMakeLists.txt @@ -17,6 +17,7 @@ wasmedge_add_library(wasmedgeExecutor engine/threadInstr.cpp engine/memoryInstr.cpp engine/variableInstr.cpp + engine/refInstr.cpp engine/engine.cpp helper.cpp executor.cpp diff --git a/lib/executor/engine/controlInstr.cpp b/lib/executor/engine/controlInstr.cpp index 1b18974f8b6d..b383f81f71f8 100644 --- a/lib/executor/engine/controlInstr.cpp +++ b/lib/executor/engine/controlInstr.cpp @@ -50,9 +50,9 @@ Expect Executor::runBrIfOp(Runtime::StackManager &StackMgr, return {}; } -Expect Executor::runBrOnNull(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept { +Expect Executor::runBrOnNullOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { if (StackMgr.getTop().get().isNull()) { StackMgr.pop(); return runBrOp(StackMgr, Instr, PC); @@ -60,9 +60,9 @@ Expect Executor::runBrOnNull(Runtime::StackManager &StackMgr, return {}; } -Expect Executor::runBrOnNonNull(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept { +Expect Executor::runBrOnNonNullOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { if (!StackMgr.getTop().get().isNull()) { return runBrOp(StackMgr, Instr, PC); } @@ -89,6 +89,34 @@ Expect Executor::runBrTableOp(Runtime::StackManager &StackMgr, LabelTable[LabelTableSize].PCOffset, PC); } +Expect Executor::runBrOnCastOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC, + bool IsReverse) noexcept { + // Get value on top of stack. + const auto *ModInst = StackMgr.getModule(); + const auto &Val = StackMgr.getTop().get(); + const auto &VT = Val.getType(); + Span GotTypeList = ModInst->getTypeList(); + if (!VT.isAbsHeapType()) { + auto *Inst = Val.getPtr(); + // Reference must not be nullptr here because the null references are typed + // with the least abstract heap type. + if (Inst->getModule()) { + GotTypeList = Inst->getModule()->getTypeList(); + } + } + + if (AST::TypeMatcher::matchType(ModInst->getTypeList(), + Instr.getBrCast().RType2, GotTypeList, + VT) != IsReverse) { + return branchToLabel(StackMgr, Instr.getBrCast().Jump.StackEraseBegin, + Instr.getBrCast().Jump.StackEraseEnd, + Instr.getBrCast().Jump.PCOffset, PC); + } + return {}; +} + Expect Executor::runReturnOp(Runtime::StackManager &StackMgr, AST::InstrView::iterator &PC) noexcept { // Check stop token @@ -105,8 +133,7 @@ Expect Executor::runCallOp(Runtime::StackManager &StackMgr, AST::InstrView::iterator &PC, bool IsTailCall) noexcept { // Get Function address. - const auto *ModInst = StackMgr.getModule(); - const auto *FuncInst = *ModInst->getFunc(Instr.getTargetIndex()); + const auto *FuncInst = getFuncInstByIdx(StackMgr, Instr.getTargetIndex()); if (auto Res = enterFunction(StackMgr, *FuncInst, PC + 1, IsTailCall); !Res) { return Unexpect(Res); } else { @@ -147,7 +174,7 @@ Expect Executor::runCallIndirectOp(Runtime::StackManager &StackMgr, // Get function type at index x. const auto *ModInst = StackMgr.getModule(); - const auto *TargetFuncType = *ModInst->getFuncType(Instr.getTargetIndex()); + const auto &ExpDefType = **ModInst->getType(Instr.getTargetIndex()); // Pop the value i32.const i from the Stack. uint32_t Idx = StackMgr.pop().get(); @@ -173,18 +200,28 @@ Expect Executor::runCallIndirectOp(Runtime::StackManager &StackMgr, // Check function type. const auto *FuncInst = retrieveFuncRef(Ref); - const auto &FuncType = FuncInst->getFuncType(); - if (!matchTypes(*ModInst, TargetFuncType->getParamTypes(), - *FuncInst->getModule(), FuncType.getParamTypes()) || - !matchTypes(*ModInst, TargetFuncType->getReturnTypes(), - *FuncInst->getModule(), FuncType.getReturnTypes())) { + bool IsMatch = false; + if (FuncInst->getModule()) { + IsMatch = AST::TypeMatcher::matchType( + ModInst->getTypeList(), *ExpDefType.getTypeIndex(), + FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex()); + } else { + // Independent host module instance case. Matching the composite type + // directly. + IsMatch = AST::TypeMatcher::matchType( + ModInst->getTypeList(), ExpDefType.getCompositeType(), + FuncInst->getHostFunc().getDefinedType().getCompositeType()); + } + if (!IsMatch) { + auto &ExpFuncType = ExpDefType.getCompositeType().getFuncType(); + auto &GotFuncType = FuncInst->getFuncType(); spdlog::error(ErrCode::Value::IndirectCallTypeMismatch); spdlog::error(ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset(), {Idx}, {ValTypeFromType()})); spdlog::error(ErrInfo::InfoMismatch( - TargetFuncType->getParamTypes(), TargetFuncType->getReturnTypes(), - FuncType.getParamTypes(), FuncType.getReturnTypes())); + ExpFuncType.getParamTypes(), ExpFuncType.getReturnTypes(), + GotFuncType.getParamTypes(), GotFuncType.getReturnTypes())); return Unexpect(ErrCode::Value::IndirectCallTypeMismatch); } diff --git a/lib/executor/engine/engine.cpp b/lib/executor/engine/engine.cpp index 358624cea668..1b3bac1c9681 100644 --- a/lib/executor/engine/engine.cpp +++ b/lib/executor/engine/engine.cpp @@ -28,8 +28,18 @@ Executor::runFunction(Runtime::StackManager &StackMgr, StackMgr.pushFrame(nullptr, AST::InstrView::iterator(), 0, 0); // Push arguments. - for (auto &Val : Params) { - StackMgr.push(Val); + const auto &PTypes = Func.getFuncType().getParamTypes(); + for (uint32_t I = 0; I < Params.size(); I++) { + // For the references, transform to non-null reference type if the value not + // null. + if (PTypes[I].isRefType() && Params[I].get().getPtr() && + Params[I].get().getType().isNullableRefType()) { + auto Val = Params[I]; + Val.get().getType().toNonNullableRef(); + StackMgr.push(Val); + } else { + StackMgr.push(Params[I]); + } } // Enter and execute function. @@ -85,6 +95,16 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, auto Dispatch = [this, &PC, &StackMgr]() -> Expect { const AST::Instruction &Instr = *PC; + + auto GetDstCompType = [&StackMgr, &Instr, this]() { + return getDefTypeByIdx(StackMgr, Instr.getTargetIndex()) + ->getCompositeType(); + }; + auto GetSrcCompType = [&StackMgr, &Instr, this]() { + return getDefTypeByIdx(StackMgr, Instr.getSourceIndex()) + ->getCompositeType(); + }; + switch (Instr.getOpCode()) { // Control instructions. case OpCode::Unreachable: @@ -128,9 +148,13 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, case OpCode::Br_table: return runBrTableOp(StackMgr, Instr, PC); case OpCode::Br_on_null: - return runBrOnNull(StackMgr, Instr, PC); + return runBrOnNullOp(StackMgr, Instr, PC); case OpCode::Br_on_non_null: - return runBrOnNonNull(StackMgr, Instr, PC); + return runBrOnNonNullOp(StackMgr, Instr, PC); + case OpCode::Br_on_cast: + return runBrOnCastOp(StackMgr, Instr, PC); + case OpCode::Br_on_cast_fail: + return runBrOnCastOp(StackMgr, Instr, PC, true); case OpCode::Return: return runReturnOp(StackMgr, PC); case OpCode::Call: @@ -148,31 +172,121 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, // Reference Instructions case OpCode::Ref__null: - StackMgr.push(RefVariant(Instr.getValType())); - return {}; - case OpCode::Ref__is_null: { - ValVariant &Val = StackMgr.getTop(); - if (Val.get().isNull()) { - Val.emplace(UINT32_C(1)); - } else { - Val.emplace(UINT32_C(0)); - } - return {}; - } - case OpCode::Ref__func: { - const auto *ModInst = StackMgr.getModule(); - const auto *FuncInst = *ModInst->getFunc(Instr.getTargetIndex()); - StackMgr.push(RefVariant(FuncInst)); - return {}; + return runRefNullOp(StackMgr, Instr.getValType()); + case OpCode::Ref__is_null: + return runRefIsNullOp(StackMgr.getTop()); + case OpCode::Ref__func: + return runRefFuncOp(StackMgr, Instr.getTargetIndex()); + case OpCode::Ref__eq: { + ValVariant Rhs = StackMgr.pop(); + return runRefEqOp(StackMgr.getTop(), Rhs); } case OpCode::Ref__as_non_null: - if (StackMgr.getTop().get().isNull()) { - spdlog::error(ErrCode::Value::CastNullToNonNull); - spdlog::error( - ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); - return Unexpect(ErrCode::Value::CastNullToNonNull); - } - return {}; + return runRefAsNonNullOp(StackMgr.getTop().get(), Instr); + + // GC Instructions + case OpCode::Struct__new: + return runStructNewOp(StackMgr, Instr.getTargetIndex()); + case OpCode::Struct__new_default: + return runStructNewOp(StackMgr, Instr.getTargetIndex(), true); + case OpCode::Struct__get: + case OpCode::Struct__get_u: + return runStructGetOp(StackMgr.getTop(), Instr.getSourceIndex(), + GetDstCompType(), Instr); + case OpCode::Struct__get_s: + return runStructGetOp(StackMgr.getTop(), Instr.getSourceIndex(), + GetDstCompType(), Instr, true); + case OpCode::Struct__set: { + const ValVariant Val = StackMgr.pop(); + RefVariant StructRef = StackMgr.pop().get(); + return runStructSetOp(Val, StructRef, GetDstCompType(), + Instr.getSourceIndex(), Instr); + } + case OpCode::Array__new: + return runArrayNewOp(StackMgr, Instr.getTargetIndex(), 1, + StackMgr.pop().get()); + case OpCode::Array__new_default: + return runArrayNewOp(StackMgr, Instr.getTargetIndex(), 0, + StackMgr.pop().get()); + case OpCode::Array__new_fixed: + return runArrayNewOp(StackMgr, Instr.getTargetIndex(), + Instr.getSourceIndex(), Instr.getSourceIndex()); + case OpCode::Array__new_data: + return runArrayNewDataOp( + StackMgr, *getDataInstByIdx(StackMgr, Instr.getSourceIndex()), Instr); + case OpCode::Array__new_elem: + return runArrayNewElemOp( + StackMgr, *getElemInstByIdx(StackMgr, Instr.getSourceIndex()), Instr); + case OpCode::Array__get: + case OpCode::Array__get_u: { + const uint32_t Idx = StackMgr.pop().get(); + return runArrayGetOp(StackMgr.getTop(), Idx, GetDstCompType(), Instr); + } + case OpCode::Array__get_s: { + const uint32_t Idx = StackMgr.pop().get(); + return runArrayGetOp(StackMgr.getTop(), Idx, GetDstCompType(), Instr, + true); + } + case OpCode::Array__set: { + ValVariant Val = StackMgr.pop(); + const uint32_t Idx = StackMgr.pop().get(); + RefVariant ArrayRef = StackMgr.pop().get(); + return runArraySetOp(Val, Idx, ArrayRef, GetDstCompType(), Instr); + } + case OpCode::Array__len: + return runArrayLenOp(StackMgr.getTop(), Instr); + case OpCode::Array__fill: { + const uint32_t N = StackMgr.pop().get(); + const ValVariant Val = StackMgr.pop(); + const uint32_t D = StackMgr.pop().get(); + RefVariant ArrayRef = StackMgr.pop().get(); + return runArrayFillOp(N, Val, D, ArrayRef, GetDstCompType(), Instr); + } + case OpCode::Array__copy: { + const uint32_t N = StackMgr.pop().get(); + const uint32_t S = StackMgr.pop().get(); + RefVariant SrcArrayRef = StackMgr.pop().get(); + const uint32_t D = StackMgr.pop().get(); + RefVariant DstArrayRef = StackMgr.pop().get(); + return runArrayCopyOp(N, S, SrcArrayRef, D, DstArrayRef, GetSrcCompType(), + GetDstCompType(), Instr); + } + case OpCode::Array__init_data: { + const uint32_t N = StackMgr.pop().get(); + const uint32_t S = StackMgr.pop().get(); + const uint32_t D = StackMgr.pop().get(); + RefVariant ArrayRef = StackMgr.pop().get(); + return runArrayInitDataOp( + N, S, D, ArrayRef, GetDstCompType(), + *getDataInstByIdx(StackMgr, Instr.getSourceIndex()), Instr); + } + case OpCode::Array__init_elem: { + const uint32_t N = StackMgr.pop().get(); + const uint32_t S = StackMgr.pop().get(); + const uint32_t D = StackMgr.pop().get(); + RefVariant ArrayRef = StackMgr.pop().get(); + return runArrayInitElemOp( + N, S, D, ArrayRef, GetDstCompType(), + *getElemInstByIdx(StackMgr, Instr.getSourceIndex()), Instr); + } + case OpCode::Ref__test: + case OpCode::Ref__test_null: + return runRefTestOp(StackMgr.getModule(), StackMgr.getTop(), Instr); + case OpCode::Ref__cast: + case OpCode::Ref__cast_null: + return runRefTestOp(StackMgr.getModule(), StackMgr.getTop(), Instr, true); + case OpCode::Any__convert_extern: + return runRefConvOp(StackMgr.getTop().get(), + TypeCode::AnyRef); + case OpCode::Extern__convert_any: + return runRefConvOp(StackMgr.getTop().get(), + TypeCode::ExternRef); + case OpCode::Ref__i31: + return runRefI31Op(StackMgr.getTop()); + case OpCode::I31__get_s: + return runI31GetOp(StackMgr.getTop(), Instr, true); + case OpCode::I31__get_u: + return runI31GetOp(StackMgr.getTop(), Instr); // Parametric Instructions case OpCode::Drop: diff --git a/lib/executor/engine/proxy.cpp b/lib/executor/engine/proxy.cpp index 35a3f750f031..bbd9188e43b0 100644 --- a/lib/executor/engine/proxy.cpp +++ b/lib/executor/engine/proxy.cpp @@ -138,15 +138,22 @@ Expect Executor::tableGetFuncSymbol(Runtime::StackManager &StackMgr, const auto *ModInst = StackMgr.getModule(); assuming(ModInst); - const auto TargetFuncType = ModInst->getFuncType(FuncTypeIdx); - assuming(TargetFuncType && *TargetFuncType); + const auto &ExpDefType = **ModInst->getType(FuncTypeIdx); const auto *FuncInst = retrieveFuncRef(*Ref); assuming(FuncInst); - const auto &FuncType = FuncInst->getFuncType(); - if (!matchTypes(*ModInst, (*TargetFuncType)->getParamTypes(), - *FuncInst->getModule(), FuncType.getParamTypes()) || - !matchTypes(*ModInst, (*TargetFuncType)->getReturnTypes(), - *FuncInst->getModule(), FuncType.getReturnTypes())) { + bool IsMatch = false; + if (FuncInst->getModule()) { + IsMatch = AST::TypeMatcher::matchType( + ModInst->getTypeList(), *ExpDefType.getTypeIndex(), + FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex()); + } else { + // Independent host module instance case. Matching the composite type + // directly. + IsMatch = AST::TypeMatcher::matchType( + ModInst->getTypeList(), ExpDefType.getCompositeType(), + FuncInst->getHostFunc().getDefinedType().getCompositeType()); + } + if (!IsMatch) { return Unexpect(ErrCode::Value::IndirectCallTypeMismatch); } @@ -176,15 +183,26 @@ Executor::callIndirect(Runtime::StackManager &StackMgr, const uint32_t TableIdx, const auto *ModInst = StackMgr.getModule(); assuming(ModInst); - const auto TargetFuncType = ModInst->getFuncType(FuncTypeIdx); - assuming(TargetFuncType && *TargetFuncType); + const auto &ExpDefType = **ModInst->getType(FuncTypeIdx); const auto *FuncInst = retrieveFuncRef(*Ref); assuming(FuncInst); - const auto &FuncType = FuncInst->getFuncType(); - if (unlikely(**TargetFuncType != FuncType)) { + bool IsMatch = false; + if (FuncInst->getModule()) { + IsMatch = AST::TypeMatcher::matchType( + ModInst->getTypeList(), *ExpDefType.getTypeIndex(), + FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex()); + } else { + // Independent host module instance case. Matching the composite type + // directly. + IsMatch = AST::TypeMatcher::matchType( + ModInst->getTypeList(), ExpDefType.getCompositeType(), + FuncInst->getHostFunc().getDefinedType().getCompositeType()); + } + if (!IsMatch) { return Unexpect(ErrCode::Value::IndirectCallTypeMismatch); } + const auto &FuncType = FuncInst->getFuncType(); const uint32_t ParamsSize = static_cast(FuncType.getParamTypes().size()); const uint32_t ReturnsSize = diff --git a/lib/executor/engine/refInstr.cpp b/lib/executor/engine/refInstr.cpp new file mode 100644 index 000000000000..ecfbdf616e2e --- /dev/null +++ b/lib/executor/engine/refInstr.cpp @@ -0,0 +1,599 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +#include "executor/executor.h" + +namespace WasmEdge { +namespace Executor { + +namespace { +ValVariant packVal(const ValType &Type, const ValVariant &Val) { + if (Type.isPackType()) { + switch (Type.getCode()) { + case TypeCode::I8: + return ValVariant(Val.get() & 0xFFU); + case TypeCode::I16: + return ValVariant(Val.get() & 0xFFFFU); + default: + assumingUnreachable(); + } + } + return Val; +} + +ValVariant unpackVal(const ValType &Type, const ValVariant &Val, + bool IsSigned = false) { + if (Type.isPackType()) { + uint32_t Num = Val.get(); + switch (Type.getCode()) { + case TypeCode::I8: + if (IsSigned) { + return static_cast(static_cast(Num)); + } else { + return static_cast(static_cast(Num)); + } + case TypeCode::I16: + if (IsSigned) { + return static_cast(static_cast(Num)); + } else { + return static_cast(static_cast(Num)); + } + default: + assumingUnreachable(); + } + } + return Val; +} + +std::vector packVals(const ValType &Type, + std::vector &&Vals) { + for (uint32_t I = 0; I < Vals.size(); I++) { + Vals[I] = packVal(Type, Vals[I]); + } + return std::move(Vals); +} +} // namespace + +Expect Executor::runRefNullOp(Runtime::StackManager &StackMgr, + const ValType &Type) const noexcept { + TypeCode Bot; + // A null reference is typed with the least type in its respective hierarchy. + if (Type.isAbsHeapType()) { + switch (Type.getHeapTypeCode()) { + case TypeCode::NullFuncRef: + case TypeCode::FuncRef: + Bot = TypeCode::NullFuncRef; + break; + case TypeCode::NullExternRef: + case TypeCode::ExternRef: + Bot = TypeCode::NullExternRef; + break; + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + Bot = TypeCode::NullRef; + break; + default: + assumingUnreachable(); + } + } else { + const auto &CompType = (*StackMgr.getModule()->getType(Type.getTypeIndex())) + ->getCompositeType(); + if (CompType.isFunc()) { + Bot = TypeCode::NullFuncRef; + } else { + Bot = TypeCode::NullRef; + } + } + StackMgr.push(RefVariant(Bot)); + return {}; +} + +Expect Executor::runRefIsNullOp(ValVariant &Val) const noexcept { + Val.emplace(Val.get().isNull() ? 1U : 0U); + return {}; +} + +Expect Executor::runRefFuncOp(Runtime::StackManager &StackMgr, + uint32_t Idx) const noexcept { + const auto *FuncInst = getFuncInstByIdx(StackMgr, Idx); + StackMgr.push(RefVariant(FuncInst->getDefType(), FuncInst)); + return {}; +} + +Expect Executor::runRefEqOp(ValVariant &Val1, + const ValVariant &Val2) const noexcept { + Val1.emplace(Val1.get().getPtr() == + Val2.get().getPtr() + ? 1U + : 0U); + return {}; +} + +Expect +Executor::runRefAsNonNullOp(RefVariant &Ref, + const AST::Instruction &Instr) const noexcept { + if (Ref.isNull()) { + spdlog::error(ErrCode::Value::CastNullToNonNull); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::CastNullToNonNull); + } + Ref.getType().toNonNullableRef(); + return {}; +} + +Expect Executor::runStructNewOp(Runtime::StackManager &StackMgr, + const uint32_t DefIndex, + bool IsDefault) const noexcept { + /// TODO: The array and struct instances are owned by the module instance + /// currently because of referring the defined types of the module instances. + /// This may be changed after applying the garbage collection mechanism. + const auto &CompType = + getDefTypeByIdx(StackMgr, DefIndex)->getCompositeType(); + uint32_t N = static_cast(CompType.getFieldTypes().size()); + if (IsDefault) { + auto *Inst = + const_cast(StackMgr.getModule()) + ->newStruct(DefIndex, N); + StackMgr.push(RefVariant(Inst->getDefType(), Inst)); + } else { + auto Vals = StackMgr.pop(N); + for (uint32_t I = 0; I < N; I++) { + Vals[I] = packVal(CompType.getFieldTypes()[I].getStorageType(), Vals[I]); + } + auto *Inst = + const_cast(StackMgr.getModule()) + ->newStruct(DefIndex, std::move(Vals)); + StackMgr.push(RefVariant(Inst->getDefType(), Inst)); + } + return {}; +} + +Expect Executor::runStructGetOp(ValVariant &Val, const uint32_t Idx, + const AST::CompositeType &CompType, + const AST::Instruction &Instr, + bool IsSigned) const noexcept { + const auto *Inst = + Val.get().getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullStruct); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullStruct); + } + const auto &SType = CompType.getFieldTypes()[Idx].getStorageType(); + Val = unpackVal(SType, Inst->getField(Idx), IsSigned); + return {}; +} + +Expect +Executor::runStructSetOp(const ValVariant &Val, const RefVariant &InstRef, + const AST::CompositeType &CompType, uint32_t Idx, + const AST::Instruction &Instr) const noexcept { + auto *Inst = InstRef.getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullStruct); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullStruct); + } + const auto &SType = CompType.getFieldTypes()[Idx].getStorageType(); + Inst->getField(Idx) = packVal(SType, Val); + return {}; +} + +Expect Executor::runArrayNewOp(Runtime::StackManager &StackMgr, + const uint32_t DefIndex, uint32_t InitCnt, + uint32_t ValCnt) const noexcept { + /// TODO: The array and struct instances are owned by the module instance + /// currently because of referring the defined types of the module instances. + /// This may be changed after applying the garbage collection mechanism. + assuming(InitCnt == 0 || InitCnt == 1 || InitCnt == ValCnt); + const auto &CompType = + getDefTypeByIdx(StackMgr, DefIndex)->getCompositeType(); + const auto &VType = CompType.getFieldTypes()[0].getStorageType(); + if (InitCnt == 0) { + auto *Inst = + const_cast(StackMgr.getModule()) + ->newArray(DefIndex, ValCnt); + StackMgr.push(RefVariant(Inst->getDefType(), Inst)); + } else if (InitCnt == 1) { + auto *Inst = + const_cast(StackMgr.getModule()) + ->newArray(DefIndex, ValCnt, packVal(VType, StackMgr.getTop())); + StackMgr.getTop().emplace(Inst->getDefType(), Inst); + } else { + auto *Inst = + const_cast(StackMgr.getModule()) + ->newArray(DefIndex, packVals(VType, StackMgr.pop(ValCnt))); + StackMgr.push(RefVariant(Inst->getDefType(), Inst)); + } + return {}; +} + +Expect +Executor::runArrayNewDataOp(Runtime::StackManager &StackMgr, + const Runtime::Instance::DataInstance &DataInst, + const AST::Instruction &Instr) const noexcept { + const uint32_t N = StackMgr.pop().get(); + const uint32_t S = StackMgr.getTop().get(); + const auto &CompType = + getDefTypeByIdx(StackMgr, Instr.getTargetIndex())->getCompositeType(); + const uint32_t BSize = + CompType.getFieldTypes()[0].getStorageType().getBitWidth() / 8; + if (static_cast(S) + static_cast(N) * BSize > + DataInst.getData().size()) { + spdlog::error(ErrCode::Value::MemoryOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary( + static_cast(S), N * BSize, + DataInst.getData().size() > 0 + ? static_cast(DataInst.getData().size() - 1) + : 0U)); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::MemoryOutOfBounds); + } + /// TODO: The array and struct instances are owned by the module instance + /// currently because of referring the defined types of the module instances. + /// This may be changed after applying the garbage collection mechanism. + auto *Inst = + const_cast(StackMgr.getModule()) + ->newArray(Instr.getTargetIndex(), N); + for (uint32_t Idx = 0; Idx < N; Idx++) { + // The value has been packed. + Inst->getData(Idx) = DataInst.loadValue(S + Idx * BSize, BSize); + } + StackMgr.getTop().emplace(Inst->getDefType(), Inst); + return {}; +} + +Expect +Executor::runArrayNewElemOp(Runtime::StackManager &StackMgr, + const Runtime::Instance::ElementInstance &ElemInst, + const AST::Instruction &Instr) const noexcept { + const uint32_t N = StackMgr.pop().get(); + const uint32_t S = StackMgr.getTop().get(); + const auto &CompType = + getDefTypeByIdx(StackMgr, Instr.getTargetIndex())->getCompositeType(); + const auto &SType = CompType.getFieldTypes()[0].getStorageType(); + auto ElemSrc = ElemInst.getRefs(); + if (static_cast(S) + static_cast(N) > ElemSrc.size()) { + spdlog::error(ErrCode::Value::TableOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary( + static_cast(S), N, + ElemSrc.size() > 0 ? static_cast(ElemSrc.size() - 1) : 0U)); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::TableOutOfBounds); + } + std::vector Refs(ElemSrc.begin() + S, ElemSrc.begin() + S + N); + /// TODO: The array and struct instances are owned by the module instance + /// currently because of referring the defined types of the module instances. + /// This may be changed after applying the garbage collection mechanism. + auto *Inst = + const_cast(StackMgr.getModule()) + ->newArray(Instr.getTargetIndex(), packVals(SType, std::move(Refs))); + StackMgr.getTop().emplace(Inst->getDefType(), Inst); + return {}; +} + +Expect +Executor::runArraySetOp(const ValVariant &Val, const uint32_t Idx, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const AST::Instruction &Instr) const noexcept { + auto *Inst = InstRef.getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + if (Idx >= Inst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(Idx, 1, Inst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + const auto &SType = CompType.getFieldTypes()[0].getStorageType(); + Inst->getData(Idx) = packVal(SType, Val); + return {}; +} + +Expect Executor::runArrayGetOp(ValVariant &Val, const uint32_t Idx, + const AST::CompositeType &CompType, + const AST::Instruction &Instr, + bool IsSigned) const noexcept { + const auto *Inst = + Val.get().getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + if (Idx >= Inst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(Idx, 1, Inst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + const auto &SType = CompType.getFieldTypes()[0].getStorageType(); + Val = unpackVal(SType, Inst->getData(Idx), IsSigned); + return {}; +} + +Expect +Executor::runArrayLenOp(ValVariant &Val, + const AST::Instruction &Instr) const noexcept { + const auto *Inst = + Val.get().getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + Val.emplace(Inst->getLength()); + return {}; +} + +Expect +Executor::runArrayFillOp(uint32_t N, const ValVariant &Val, uint32_t D, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const AST::Instruction &Instr) const noexcept { + auto *Inst = InstRef.getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + if (static_cast(D) + static_cast(N) > Inst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(static_cast(D), N, + Inst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + const auto &SType = CompType.getFieldTypes()[0].getStorageType(); + auto Arr = Inst->getArray(); + std::fill(Arr.begin() + D, Arr.begin() + D + N, packVal(SType, Val)); + return {}; +} + +Expect +Executor::runArrayCopyOp(uint32_t N, uint32_t S, const RefVariant &SrcInstRef, + uint32_t D, const RefVariant &DstInstRef, + const AST::CompositeType &SrcCompType, + const AST::CompositeType &DstCompType, + const AST::Instruction &Instr) const noexcept { + auto *SrcInst = SrcInstRef.getPtr(); + auto *DstInst = DstInstRef.getPtr(); + if (SrcInst == nullptr || DstInst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + if (static_cast(S) + static_cast(N) > + SrcInst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(static_cast(S), N, + SrcInst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + if (static_cast(D) + static_cast(N) > + DstInst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(static_cast(D), N, + DstInst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + const auto &SrcSType = SrcCompType.getFieldTypes()[0].getStorageType(); + const auto &DstSType = DstCompType.getFieldTypes()[0].getStorageType(); + auto SrcArr = SrcInst->getArray(); + auto DstArr = DstInst->getArray(); + if (D <= S) { + std::transform(SrcArr.begin() + S, SrcArr.begin() + S + N, + DstArr.begin() + D, [&](const ValVariant &V) { + return packVal(DstSType, unpackVal(SrcSType, V)); + }); + } else { + std::transform(std::make_reverse_iterator(SrcArr.begin() + S + N), + std::make_reverse_iterator(SrcArr.begin() + S), + std::make_reverse_iterator(DstArr.begin() + D + N), + [&](const ValVariant &V) { + return packVal(DstSType, unpackVal(SrcSType, V)); + }); + } + return {}; +} + +Expect +Executor::runArrayInitDataOp(uint32_t N, uint32_t S, uint32_t D, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const Runtime::Instance::DataInstance &DataInst, + const AST::Instruction &Instr) const noexcept { + const uint32_t BSize = + CompType.getFieldTypes()[0].getStorageType().getBitWidth() / 8; + auto *Inst = InstRef.getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + if (static_cast(D) + static_cast(N) > Inst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(static_cast(D), N, + Inst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + if (static_cast(S) + static_cast(N) * BSize > + DataInst.getData().size()) { + spdlog::error(ErrCode::Value::MemoryOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary( + static_cast(S), N * BSize, + DataInst.getData().size() > 0 + ? static_cast(DataInst.getData().size() - 1) + : 0U)); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::MemoryOutOfBounds); + } + for (uint32_t Off = 0; Off < N; Off++) { + // The value has been packed. + Inst->getData(D + Off) = DataInst.loadValue(S + Off * BSize, BSize); + } + return {}; +} + +Expect +Executor::runArrayInitElemOp(uint32_t N, uint32_t S, uint32_t D, + const RefVariant &InstRef, + const AST::CompositeType &CompType, + const Runtime::Instance::ElementInstance &ElemInst, + const AST::Instruction &Instr) const noexcept { + auto ElemSrc = ElemInst.getRefs(); + auto *Inst = InstRef.getPtr(); + if (Inst == nullptr) { + spdlog::error(ErrCode::Value::AccessNullArray); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullArray); + } + if (static_cast(D) + static_cast(N) > Inst->getLength()) { + spdlog::error(ErrCode::Value::ArrayOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary(static_cast(D), N, + Inst->getBoundIdx())); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::ArrayOutOfBounds); + } + if (static_cast(S) + static_cast(N) > ElemSrc.size()) { + spdlog::error(ErrCode::Value::TableOutOfBounds); + spdlog::error(ErrInfo::InfoBoundary( + static_cast(S), N, + ElemSrc.size() > 0 ? static_cast(ElemSrc.size() - 1) : 0U)); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::TableOutOfBounds); + } + const auto &SType = CompType.getFieldTypes()[0].getStorageType(); + + auto Arr = Inst->getArray(); + // The value has been packed. + std::transform(ElemSrc.begin() + S, ElemSrc.begin() + S + N, Arr.begin() + D, + [&](const RefVariant &V) { return packVal(SType, V); }); + return {}; +} + +Expect +Executor::runRefTestOp(const Runtime::Instance::ModuleInstance *ModInst, + ValVariant &Val, const AST::Instruction &Instr, + bool IsCast) const noexcept { + // Copy the value type here due to handling the externalized case. + auto VT = Val.get().getType(); + if (VT.isExternalized()) { + VT = ValType(TypeCode::Ref, TypeCode::ExternRef); + } + Span GotTypeList = ModInst->getTypeList(); + if (!VT.isAbsHeapType()) { + auto *Inst = + Val.get().getPtr(); + // Reference must not be nullptr here because the null references are typed + // with the least abstract heap type. + if (Inst->getModule()) { + GotTypeList = Inst->getModule()->getTypeList(); + } + } + + if (AST::TypeMatcher::matchType(ModInst->getTypeList(), Instr.getValType(), + GotTypeList, VT)) { + if (!IsCast) { + Val.emplace(1U); + } + } else { + if (IsCast) { + spdlog::error(ErrCode::Value::CastFailed); + spdlog::error(ErrInfo::InfoMismatch(Instr.getValType(), VT)); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::CastFailed); + } else { + Val.emplace(0U); + } + } + return {}; +} + +Expect Executor::runRefConvOp(RefVariant &Ref, + TypeCode TCode) const noexcept { + + if (TCode == TypeCode::AnyRef) { + // Internalize. + if (Ref.isNull()) { + Ref = RefVariant(ValType(TypeCode::RefNull, TypeCode::NullRef)); + } else { + Ref.getType().setInternalized(); + if (Ref.getType().isExternRefType()) { + Ref.getType() = ValType(TypeCode::Ref, TypeCode::AnyRef); + } + } + } else { + // Externalize. + if (Ref.isNull()) { + Ref = RefVariant(ValType(TypeCode::RefNull, TypeCode::NullExternRef)); + } else { + // Use the externalize flag because the value type information should be + // reserved when a reference being externalized and internalized. + Ref.getType().setExternalized(); + } + } + return {}; +} + +Expect Executor::runRefI31Op(ValVariant &Val) const noexcept { + uint32_t RefNum = (Val.get() & 0x7FFFFFFFU) | 0x80000000U; + Val = RefVariant(ValType(TypeCode::Ref, TypeCode::I31Ref), + reinterpret_cast(static_cast(RefNum))); + return {}; +} + +Expect Executor::runI31GetOp(ValVariant &Val, + const AST::Instruction &Instr, + bool IsSigned) const noexcept { + uint32_t RefNum = static_cast( + reinterpret_cast(Val.get().getPtr())); + if ((RefNum & 0x80000000U) == 0) { + spdlog::error(ErrCode::Value::AccessNullI31); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullI31); + } + RefNum &= 0x7FFFFFFFU; + if (IsSigned) { + RefNum |= ((RefNum & 0x40000000U) << 1); + } + Val.emplace(RefNum); + return {}; +} + +} // namespace Executor +} // namespace WasmEdge diff --git a/lib/executor/engine/variableInstr.cpp b/lib/executor/engine/variableInstr.cpp index f57ee4fec1f0..0ea8ae4fd78a 100644 --- a/lib/executor/engine/variableInstr.cpp +++ b/lib/executor/engine/variableInstr.cpp @@ -39,7 +39,7 @@ Expect Executor::runGlobalSetOp(Runtime::StackManager &StackMgr, uint32_t Idx) const noexcept { auto *GlobInst = getGlobInstByIdx(StackMgr, Idx); assuming(GlobInst); - GlobInst->getValue() = StackMgr.pop(); + GlobInst->setValue(StackMgr.pop()); return {}; } diff --git a/lib/executor/executor.cpp b/lib/executor/executor.cpp index a330009e070f..b212eeb20823 100644 --- a/lib/executor/executor.cpp +++ b/lib/executor/executor.cpp @@ -81,12 +81,12 @@ Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst, return Unexpect(ErrCode::Value::FuncNotFound); } - // Check parameter and function type. + // Matching arguments and function type. const auto &FuncType = FuncInst->getFuncType(); const auto &PTypes = FuncType.getParamTypes(); const auto &RTypes = FuncType.getReturnTypes(); - if (!matchTypes(*FuncInst->getModule(), ParamTypes, *FuncInst->getModule(), - PTypes)) { + if (!AST::TypeMatcher::matchTypes(FuncInst->getModule()->getTypeList(), + ParamTypes, PTypes)) { spdlog::error(ErrCode::Value::FuncSigMismatch); spdlog::error(ErrInfo::InfoMismatch( PTypes, RTypes, std::vector(ParamTypes.begin(), ParamTypes.end()), @@ -115,8 +115,37 @@ Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst, // Get return values. std::vector> Returns(RTypes.size()); for (uint32_t I = 0; I < RTypes.size(); ++I) { - Returns[RTypes.size() - I - 1] = - std::make_pair(StackMgr.pop(), RTypes[RTypes.size() - I - 1]); + auto Val = StackMgr.pop(); + const auto &RType = RTypes[RTypes.size() - I - 1]; + if (RType.isRefType()) { + // For the types of the return values, they should be transformed into + // abstract heap types due to the opaque of type indices. + auto &RefType = Val.get().getType(); + if (RefType.isExternalized()) { + // First handle the forced externalized value type case. + RefType = ValType(TypeCode::Ref, TypeCode::ExternRef); + } + if (!RefType.isAbsHeapType()) { + // The instance must not be nullptr because the null references are + // already dynamic typed into the top abstract heap type. + auto *Inst = + Val.get().getPtr(); + assuming(Inst); + // The ModInst may be nullptr only in the independent host function + // instance. Therefore the module instance here must not be nullptr + // because the independent host function instance cannot be imported and + // be referred by instructions. + const auto *ModInst = Inst->getModule(); + auto *DefType = *ModInst->getType(RefType.getTypeIndex()); + RefType = + ValType(RefType.getCode(), DefType->getCompositeType().expand()); + } + // Should use the value type from the reference here due to the dynamic + // typing rule of the null references. + Returns[RTypes.size() - I - 1] = std::make_pair(Val, RefType); + } else { + Returns[RTypes.size() - I - 1] = std::make_pair(Val, RType); + } } // After execution, the value stack size should be 0. diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 7bd8ccb887ea..7ac06956c047 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -205,6 +205,16 @@ Expect Executor::branchToLabel(Runtime::StackManager &StackMgr, return {}; } +const AST::SubType *Executor::getDefTypeByIdx(Runtime::StackManager &StackMgr, + const uint32_t Idx) const { + const auto *ModInst = StackMgr.getModule(); + // When top frame is dummy frame, cannot find instance. + if (unlikely(ModInst == nullptr)) { + return nullptr; + } + return ModInst->unsafeGetType(Idx); +} + Runtime::Instance::FunctionInstance * Executor::getFuncInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const { @@ -271,65 +281,5 @@ Executor::getDataInstByIdx(Runtime::StackManager &StackMgr, return ModInst->unsafeGetData(Idx); } -bool Executor::matchType(const Runtime::Instance::ModuleInstance &ModExp, - const ValType &Exp, - const Runtime::Instance::ModuleInstance &ModGot, - const ValType &Got) const noexcept { - if (!Exp.isRefType() && !Got.isRefType() && Exp.getCode() == Got.getCode()) { - // Match for the non-reference type case. - return true; - } - if (Exp.isRefType() && Got.isRefType()) { - // Nullable matching. - if (!Exp.isNullableRefType() && Got.isNullableRefType()) { - return false; - } - - // Match the heap type. - if (Exp.getHeapTypeCode() == Got.getHeapTypeCode() && - Exp.getHeapTypeCode() != TypeCode::TypeIndex) { - // Abs heap type are the same. - return true; - } - if (Exp.getHeapTypeCode() == TypeCode::FuncRef && - Got.getHeapTypeCode() == TypeCode::TypeIndex) { - // Match type index to any funcref. - return true; - } - if (Exp.getHeapTypeCode() == TypeCode::TypeIndex && - Got.getHeapTypeCode() == TypeCode::TypeIndex) { - // Match got type index to expected type index. - if (matchTypes( - ModExp, ModExp.FuncTypes[Exp.getTypeIndex()].getParamTypes(), - ModGot, ModGot.FuncTypes[Got.getTypeIndex()].getParamTypes()) && - matchTypes( - ModExp, ModExp.FuncTypes[Exp.getTypeIndex()].getReturnTypes(), - ModGot, ModGot.FuncTypes[Got.getTypeIndex()].getReturnTypes())) { - // Note: In future versions of WebAssembly, subtyping on function types - // may be relaxed to support co- and contra-variance. - // Due to passing the validation of type section, this will not cause - // infinite recursion. - return true; - } - } - } - return false; -} - -bool Executor::matchTypes(const Runtime::Instance::ModuleInstance &ModExp, - Span Exp, - const Runtime::Instance::ModuleInstance &ModGot, - Span Got) const noexcept { - if (Exp.size() != Got.size()) { - return false; - } - for (uint32_t I = 0; I < Exp.size(); I++) { - if (!matchType(ModExp, Exp[I], ModGot, Got[I])) { - return false; - } - } - return true; -} - } // namespace Executor } // namespace WasmEdge diff --git a/lib/executor/instantiate/function.cpp b/lib/executor/instantiate/function.cpp index d0239bac0506..ceb50d49a452 100644 --- a/lib/executor/instantiate/function.cpp +++ b/lib/executor/instantiate/function.cpp @@ -27,17 +27,20 @@ Expect Executor::instantiate(Runtime::Instance::ModuleInstance &ModInst, // and dispatch it into different cases to reduce branch misses. if (CodeSegs[0].getSymbol() != false) { for (uint32_t I = 0; I < CodeSegs.size(); ++I) { - auto *FuncType = *ModInst.getFuncType(TypeIdxs[I]); auto Symbol = CodeSegs[I].getSymbol(); - ModInst.addFunc(*FuncType, std::move(Symbol)); + ModInst.addFunc( + TypeIdxs[I], + (*ModInst.getType(TypeIdxs[I]))->getCompositeType().getFuncType(), + std::move(Symbol)); } } else { // Iterate through the code segments to instantiate function instances. for (uint32_t I = 0; I < CodeSegs.size(); ++I) { // Create and add the function instance into the module instance. - auto *FuncType = *ModInst.getFuncType(TypeIdxs[I]); - ModInst.addFunc(*FuncType, CodeSegs[I].getLocals(), - CodeSegs[I].getExpr().getInstrs()); + ModInst.addFunc( + TypeIdxs[I], + (*ModInst.getType(TypeIdxs[I]))->getCompositeType().getFuncType(), + CodeSegs[I].getLocals(), CodeSegs[I].getExpr().getInstrs()); } } return {}; diff --git a/lib/executor/instantiate/import.cpp b/lib/executor/instantiate/import.cpp index 612a6b8f7913..ade278b99b3d 100644 --- a/lib/executor/instantiate/import.cpp +++ b/lib/executor/instantiate/import.cpp @@ -106,8 +106,8 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, auto ExtType = ImpDesc.getExternalType(); auto ModName = ImpDesc.getModuleName(); auto ExtName = ImpDesc.getExternalName(); - const auto *TargetModInst = StoreMgr.findModule(ModName); - if (unlikely(TargetModInst == nullptr)) { + const auto *ImpModInst = StoreMgr.findModule(ModName); + if (unlikely(ImpModInst == nullptr)) { auto Res = logUnknownError(ModName, ExtName, ExtType); if (ModName == "wasi_snapshot_preview1") { spdlog::error(" This is a WASI related import. Please ensure that " @@ -132,8 +132,7 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, } return Res; } - if (auto Res = - checkImportMatched(ModName, ExtName, ExtType, *TargetModInst); + if (auto Res = checkImportMatched(ModName, ExtName, ExtType, *ImpModInst); unlikely(!Res)) { return Unexpect(Res); } @@ -144,16 +143,17 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, // Get function type index. External type checked in validation. uint32_t TypeIdx = ImpDesc.getExternalFuncTypeIdx(); // Import matching. - auto *TargetInst = TargetModInst->findFuncExports(ExtName); - const auto &TargetType = TargetInst->getFuncType(); - const auto *FuncType = *ModInst.getFuncType(TypeIdx); + auto *ImpInst = ImpModInst->findFuncExports(ExtName); + const auto &ExpDefType = **ModInst.getType(TypeIdx); // External function type should match the import function type in // description. - if (!matchTypes(ModInst, FuncType->getParamTypes(), *TargetModInst, - TargetType.getParamTypes()) || - !matchTypes(ModInst, FuncType->getReturnTypes(), *TargetModInst, - TargetType.getReturnTypes())) { + + if (!AST::TypeMatcher::matchType( + ModInst.getTypeList(), *ExpDefType.getTypeIndex(), + ImpModInst->getTypeList(), ImpInst->getTypeIndex())) { bool IsMatchV2 = false; + const auto &ExpFuncType = ExpDefType.getCompositeType().getFuncType(); + const auto &ImpFuncType = ImpInst->getFuncType(); if (ModName == "wasi_snapshot_preview1") { /* * The following functions should provide V1 and V2. @@ -177,11 +177,12 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, for (auto Iter = CompatibleWASISocketAPI.begin(); Iter != CompatibleWASISocketAPI.end(); Iter++) { if (ExtName == *Iter) { - auto *TargetInstV2 = - TargetModInst->findFuncExports(*Iter + "_v2"); - if (TargetInstV2->getFuncType() == *FuncType) { + auto *ImpInstV2 = ImpModInst->findFuncExports(*Iter + "_v2"); + if (!AST::TypeMatcher::matchType( + ModInst.getTypeList(), *ExpDefType.getTypeIndex(), + ImpModInst->getTypeList(), ImpInst->getTypeIndex())) { // Try to match the new version - TargetInst = TargetInstV2; + ImpInst = ImpInstV2; IsMatchV2 = true; break; } @@ -190,13 +191,13 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, } if (!IsMatchV2) { return logMatchError( - ModName, ExtName, ExtType, FuncType->getParamTypes(), - FuncType->getReturnTypes(), TargetType.getParamTypes(), - TargetType.getReturnTypes()); + ModName, ExtName, ExtType, ExpFuncType.getParamTypes(), + ExpFuncType.getReturnTypes(), ImpFuncType.getParamTypes(), + ImpFuncType.getReturnTypes()); } } // Set the matched function address to module instance. - ModInst.importFunction(TargetInst); + ModInst.importFunction(ImpInst); break; } case ExternalType::Table: { @@ -205,23 +206,25 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, const auto &TabLim = TabType.getLimit(); // Import matching. External table type should match the one in import // description. - auto *TargetInst = TargetModInst->findTableExports(ExtName); - const auto &TargetType = TargetInst->getTableType(); - const auto &TargetLim = TargetType.getLimit(); + auto *ImpInst = ImpModInst->findTableExports(ExtName); + const auto &ImpType = ImpInst->getTableType(); + const auto &ImpLim = ImpType.getLimit(); // External table reference type should match the import table reference // type in description, and vice versa. - if (!matchType(ModInst, TabType.getRefType(), *TargetModInst, - TargetType.getRefType()) || - !matchType(*TargetModInst, TargetType.getRefType(), ModInst, - TabType.getRefType()) || - !matchLimit(TabLim, TargetLim)) { + if (!AST::TypeMatcher::matchType( + ModInst.getTypeList(), TabType.getRefType(), + ImpModInst->getTypeList(), ImpType.getRefType()) || + !AST::TypeMatcher::matchType( + ImpModInst->getTypeList(), ImpType.getRefType(), + ModInst.getTypeList(), TabType.getRefType()) || + !matchLimit(TabLim, ImpLim)) { return logMatchError(ModName, ExtName, ExtType, TabType.getRefType(), TabLim.hasMax(), TabLim.getMin(), TabLim.getMax(), - TargetType.getRefType(), TargetLim.hasMax(), - TargetLim.getMin(), TargetLim.getMax()); + ImpType.getRefType(), ImpLim.hasMax(), + ImpLim.getMin(), ImpLim.getMax()); } // Set the matched table address to module instance. - ModInst.importTable(TargetInst); + ModInst.importTable(ImpInst); break; } case ExternalType::Memory: { @@ -230,16 +233,15 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, const auto &MemLim = MemType.getLimit(); // Import matching. External memory type should match the one in import // description. - auto *TargetInst = TargetModInst->findMemoryExports(ExtName); - const auto &TargetLim = TargetInst->getMemoryType().getLimit(); - if (!matchLimit(MemLim, TargetLim)) { + auto *ImpInst = ImpModInst->findMemoryExports(ExtName); + const auto &ImpLim = ImpInst->getMemoryType().getLimit(); + if (!matchLimit(MemLim, ImpLim)) { return logMatchError(ModName, ExtName, ExtType, MemLim.hasMax(), - MemLim.getMin(), MemLim.getMax(), - TargetLim.hasMax(), TargetLim.getMin(), - TargetLim.getMax()); + MemLim.getMin(), MemLim.getMax(), ImpLim.hasMax(), + ImpLim.getMin(), ImpLim.getMax()); } // Set the matched memory address to module instance. - ModInst.importMemory(TargetInst); + ModInst.importMemory(ImpInst); break; } case ExternalType::Global: { @@ -247,28 +249,30 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, const auto &GlobType = ImpDesc.getExternalGlobalType(); // Import matching. External global type should match the one in // import description. - auto *TargetInst = TargetModInst->findGlobalExports(ExtName); - const auto &TargetType = TargetInst->getGlobalType(); + auto *ImpInst = ImpModInst->findGlobalExports(ExtName); + const auto &ImpType = ImpInst->getGlobalType(); bool IsMatch = false; - if (TargetType.getValMut() == GlobType.getValMut()) { + if (ImpType.getValMut() == GlobType.getValMut()) { // For both const or both var: external global value type should match // the import global value type in description. - IsMatch = matchType(ModInst, GlobType.getValType(), *TargetModInst, - TargetType.getValType()); - if (TargetType.getValMut() == ValMut::Var) { + IsMatch = AST::TypeMatcher::matchType( + ModInst.getTypeList(), GlobType.getValType(), + ImpModInst->getTypeList(), ImpType.getValType()); + if (ImpType.getValMut() == ValMut::Var) { // If both var: import global value type in description should also // match the external global value type. - IsMatch &= matchType(*TargetModInst, TargetType.getValType(), ModInst, - GlobType.getValType()); + IsMatch &= AST::TypeMatcher::matchType( + ImpModInst->getTypeList(), ImpType.getValType(), + ModInst.getTypeList(), GlobType.getValType()); } } if (!IsMatch) { return logMatchError(ModName, ExtName, ExtType, GlobType.getValType(), - GlobType.getValMut(), TargetType.getValType(), - TargetType.getValMut()); + GlobType.getValMut(), ImpType.getValType(), + ImpType.getValMut()); } // Set the matched global address to module instance. - ModInst.importGlobal(TargetInst); + ModInst.importGlobal(ImpInst); break; } default: diff --git a/lib/executor/instantiate/module.cpp b/lib/executor/instantiate/module.cpp index f6f73d58e8cb..79647fd9f8b7 100644 --- a/lib/executor/instantiate/module.cpp +++ b/lib/executor/instantiate/module.cpp @@ -45,9 +45,9 @@ Executor::instantiate(Runtime::StoreManager &StoreMgr, const AST::Module &Mod, } // Instantiate Function Types in Module Instance. (TypeSec) - for (auto &FuncType : Mod.getTypeSection().getContent()) { - // Copy param and return lists to module instance. - ModInst->addFuncType(FuncType); + for (auto &SubType : Mod.getTypeSection().getContent()) { + // Copy defined types to module instance. + ModInst->addDefinedType(SubType); } // Instantiate ImportSection and do import matching. (ImportSec) @@ -70,18 +70,8 @@ Executor::instantiate(Runtime::StoreManager &StoreMgr, const AST::Module &Mod, // This function will always success. instantiate(*ModInst, MemSec); - // Add a temp module to Store with only imported globals for initialization. - std::unique_ptr TmpModInst = - std::make_unique(""); - for (uint32_t I = 0; I < ModInst->getGlobalImportNum(); ++I) { - TmpModInst->importGlobal(*(ModInst->getGlobal(I))); - } - for (uint32_t I = 0; I < ModInst->getFuncNum(); ++I) { - TmpModInst->importFunction(*(ModInst->getFunc(I))); - } - - // Push a new frame {TmpModInst:{globaddrs}, locals:none} - StackMgr.pushFrame(TmpModInst.get(), AST::InstrView::iterator(), 0, 0); + // Push a new frame {ModInst, locals:none} + StackMgr.pushFrame(ModInst.get(), AST::InstrView::iterator(), 0, 0); // Instantiate GlobalSection (GlobalSec) const AST::GlobalSection &GlobSec = Mod.getGlobalSection(); @@ -101,17 +91,11 @@ Executor::instantiate(Runtime::StoreManager &StoreMgr, const AST::Module &Mod, return Unexpect(Res); } - // Pop frame with the temp. module. - StackMgr.popFrame(); - // Instantiate ExportSection (ExportSec) const AST::ExportSection &ExportSec = Mod.getExportSection(); // This function will always success. instantiate(*ModInst, ExportSec); - // Push a new frame {ModInst, locals:none} - StackMgr.pushFrame(ModInst.get(), AST::InstrView::iterator(), 0, 0); - // Instantiate ElementSection (ElemSec) const AST::ElementSection &ElemSec = Mod.getElementSection(); if (auto Res = instantiate(StackMgr, *ModInst, ElemSec); !Res) { diff --git a/lib/llvm/compiler.cpp b/lib/llvm/compiler.cpp index 155f10d4ca1c..3c0ea1c590a2 100644 --- a/lib/llvm/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -800,7 +800,34 @@ class FunctionCompiler { break; case OpCode::Ref__null: { std::array Val = {0}; - std::copy_n(Instr.getValType().getRawData().cbegin(), 8, Val.begin()); + // For null references, the dynamic type down scaling is needed. + ValType VType; + if (Instr.getValType().isAbsHeapType()) { + switch (Instr.getValType().getHeapTypeCode()) { + case TypeCode::NullFuncRef: + case TypeCode::FuncRef: + VType = TypeCode::NullFuncRef; + break; + case TypeCode::NullExternRef: + case TypeCode::ExternRef: + VType = TypeCode::NullExternRef; + break; + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + VType = TypeCode::NullRef; + break; + default: + assumingUnreachable(); + } + } else { + // TODO: GC - AOT: support other composite here. + VType = TypeCode::NullFuncRef; + } + std::copy_n(VType.getRawData().cbegin(), 8, Val.begin()); auto Vector = LLVM::Value::getConstVector8(LLContext, Val); stackPush(Builder.createBitCast(Vector, Context.Int64x2Ty)); break; @@ -5147,17 +5174,22 @@ void Compiler::compile(const AST::TypeSection &TypeSec) noexcept { {Context->ExecCtxPtrTy, Context->Int8PtrTy, Context->Int8PtrTy, Context->Int8PtrTy}, false); - const auto &FuncTypes = TypeSec.getContent(); - const auto Size = FuncTypes.size(); + auto SubTypes = TypeSec.getContent(); + const auto Size = SubTypes.size(); if (Size == 0) { return; } - Context->FunctionTypes.reserve(Size); - Context->FunctionWrappers.reserve(Size); + Context->FunctionTypes.reserve(SubTypes.size()); + Context->FunctionWrappers.reserve(SubTypes.size()); // Iterate and compile types. - for (size_t I = 0; I < Size; ++I) { - const auto &FuncType = FuncTypes[I]; + for (size_t I = 0; I < SubTypes.size(); ++I) { + // TODO: GC - AOT: implement other composite types. + if (!SubTypes[I].getCompositeType().isFunc()) { + spdlog::error("GC proposal not supported for AOT currently."); + return; + } + const auto &FuncType = SubTypes[I].getCompositeType().getFuncType(); const auto Name = fmt::format("t{}"sv, Context->FunctionTypes.size()); // Check function type is unique From 41f0707fc0cff6a429c8c3b200efbbafef760b02 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 5 Feb 2024 16:08:25 +0800 Subject: [PATCH 048/218] [Serializer] Extend serializer for supporting GC in the future. Signed-off-by: YiYing He --- include/loader/serialize.h | 2 + lib/loader/serialize/serial_section.cpp | 45 ++++++++++++++++++---- lib/loader/serialize/serial_type.cpp | 51 +++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 10 deletions(-) diff --git a/include/loader/serialize.h b/include/loader/serialize.h index 95e41c3ad0b2..fa71dfaea935 100644 --- a/include/loader/serialize.h +++ b/include/loader/serialize.h @@ -88,6 +88,8 @@ class Serializer { std::vector &OutVec) const noexcept; Expect serializeLimit(const AST::Limit &Lim, std::vector &OutVec) const noexcept; + Expect serializeType(const AST::SubType &SType, + std::vector &OutVec) const noexcept; Expect serializeType(const AST::FunctionType &Type, std::vector &OutVec) const noexcept; Expect serializeType(const AST::TableType &Type, diff --git a/lib/loader/serialize/serial_section.cpp b/lib/loader/serialize/serial_section.cpp index d018b76e1f83..57cad5d43e7b 100644 --- a/lib/loader/serialize/serial_section.cpp +++ b/lib/loader/serialize/serial_section.cpp @@ -29,12 +29,43 @@ Serializer::serializeSection(const AST::CustomSection &Sec, Expect Serializer::serializeSection(const AST::TypeSection &Sec, std::vector &OutVec) const noexcept { - // Type section: 0x01 + size:u32 + content:vec(functype). - return serializeSectionContent( - Sec, 0x01U, OutVec, - [=](const AST::FunctionType &R, std::vector &V) { - return serializeType(R, V); - }); + // Type section: 0x01 + size:u32 + content:vec(rectype). + auto STypes = Sec.getContent(); + + // record the recursive type vector size. + if (STypes.size() > 0) { + // Section ID. + OutVec.push_back(0x01U); + auto OrgSize = OutVec.size(); + uint32_t RecCnt = 0; + // Content: vec(rectype). + for (uint32_t I = 0; I < STypes.size(); I++) { + auto RecInfo = STypes[I].getRecursiveInfo(); + if (!RecInfo.has_value()) { + RecCnt++; + } else if (RecInfo->Index == 0) { + // First element of recursive type. + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::GC, + ASTNodeAttr::Sec_Type); + } + OutVec.push_back(static_cast(TypeCode::Rec)); + serializeU32(RecInfo->RecTypeSize, OutVec); + RecCnt++; + } + if (auto Res = serializeType(STypes[I], OutVec); unlikely(!Res)) { + spdlog::error(ASTNodeAttr::Sec_Type); + return Unexpect(Res); + } + } + // Backward insert the recursive type vector size. + serializeU32(RecCnt, OutVec, + std::next(OutVec.begin(), static_cast(OrgSize))); + // Backward insert the section size. + serializeU32(static_cast(OutVec.size() - OrgSize), OutVec, + std::next(OutVec.begin(), static_cast(OrgSize))); + } + return {}; } // Serialize import section. See "include/loader/serialize.h". @@ -175,7 +206,7 @@ Serializer::serializeSection(const AST::DataCountSection &Sec, !Conf.hasProposal(Proposal::ReferenceTypes)) { return logNeedProposal(ErrCode::Value::MalformedSection, Proposal::BulkMemoryOperations, - ASTNodeAttr::Module); + ASTNodeAttr::Sec_DataCount); } // Section ID. OutVec.push_back(0x0CU); diff --git a/lib/loader/serialize/serial_type.cpp b/lib/loader/serialize/serial_type.cpp index f4a75ab98189..f9c6ea3802dd 100644 --- a/lib/loader/serialize/serial_type.cpp +++ b/lib/loader/serialize/serial_type.cpp @@ -123,13 +123,58 @@ Serializer::serializeLimit(const AST::Limit &Lim, return {}; } +// Serialize sub type. See "include/loader/serialize.h". +Expect +Serializer::serializeType(const AST::SubType &SType, + std::vector &OutVec) const noexcept { + // Sub type: vec(typeidx) + if (SType.getSuperTypeIndices().size() > 0) { + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::GC, + ASTNodeAttr::Type_Rec); + } + if (SType.isFinal()) { + OutVec.push_back(static_cast(TypeCode::SubFinal)); + } else { + OutVec.push_back(static_cast(TypeCode::Sub)); + } + serializeU32(static_cast(SType.getSuperTypeIndices().size()), + OutVec); + for (const auto &Idx : SType.getSuperTypeIndices()) { + serializeU32(Idx, OutVec); + } + } + // Composite type: array | struct | func + TypeCode CTypeCode = SType.getCompositeType().getContentTypeCode(); + OutVec.push_back(static_cast(CTypeCode)); + switch (CTypeCode) { + case TypeCode::Func: + if (auto Res = + serializeType(SType.getCompositeType().getFuncType(), OutVec); + unlikely(!Res)) { + return Unexpect(Res); + } + break; + case TypeCode::Array: + case TypeCode::Struct: + if (!Conf.hasProposal(Proposal::GC)) { + return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::GC, + ASTNodeAttr::Type_Rec); + } + // TODO: GC - Serializer: implementation. + [[fallthrough]]; + default: + return logSerializeError(ErrCode::Value::MalformedValType, + ASTNodeAttr::Type_Rec); + } + return {}; +} + // Serialize function type. See "include/loader/serialize.h". Expect Serializer::serializeType(const AST::FunctionType &Type, std::vector &OutVec) const noexcept { - // Function type: 0x60 + paramtypes:vec(valtype) + returntypes:vec(valtype). - // Prefix 0x60. - OutVec.push_back(0x60U); + // Function type: paramtypes:vec(valtype) + returntypes:vec(valtype). // Param types: vec(valtype). serializeU32(static_cast(Type.getParamTypes().size()), OutVec); for (auto &VType : Type.getParamTypes()) { From a22fae88f7ad3c7894c8ee8853af5335c2c87d0c Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 5 Feb 2024 16:09:15 +0800 Subject: [PATCH 049/218] [Test] Support GC spec test suite. Not to turn on the GC proposal testing for interpreter now. Will turn on it once passing. Signed-off-by: YiYing He --- test/api/helper.cpp | 6 +- test/loader/filemgrTest.cpp | 308 +++++++++++------- test/plugins/wasm_bpf/simple_ringbuf_test.cpp | 11 +- test/plugins/wasm_bpf/wasm_bpf.cpp | 11 +- test/spec/CMakeLists.txt | 2 +- test/spec/spectest.cpp | 154 ++++++--- 6 files changed, 327 insertions(+), 165 deletions(-) diff --git a/test/api/helper.cpp b/test/api/helper.cpp index b172a9adf600..81377e80ad20 100644 --- a/test/api/helper.cpp +++ b/test/api/helper.cpp @@ -23,9 +23,9 @@ namespace WasmEdge { static Proposal ProposalList[] = { - Proposal::TailCall, Proposal::MultiMemories, Proposal::Annotations, - Proposal::Memory64, Proposal::ExceptionHandling, Proposal::ExtendedConst, - Proposal::Threads, Proposal::FunctionReferences}; + Proposal::TailCall, Proposal::MultiMemories, Proposal::Annotations, + Proposal::Memory64, Proposal::ExceptionHandling, Proposal::ExtendedConst, + Proposal::Threads, Proposal::FunctionReferences, Proposal::GC}; WasmEdge_ConfigureContext *createConf(const Configure &Conf) { auto *Cxt = WasmEdge_ConfigureCreate(); diff --git a/test/loader/filemgrTest.cpp b/test/loader/filemgrTest.cpp index 35923a917550..31555427208f 100644 --- a/test/loader/filemgrTest.cpp +++ b/test/loader/filemgrTest.cpp @@ -369,8 +369,148 @@ TEST(FileManagerTest, File__ReadSigned64TooLarge) { EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLarge, ReadNum.error()); } +TEST(FileManagerTest, File__PeekByte) { + // 19. Test unsigned char peeking. + WasmEdge::Expect PeekByte; + ASSERT_TRUE(Mgr.setPath("filemgrTestData/readByteTest.bin")); + EXPECT_EQ(0U, Mgr.getOffset()); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x00, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0xFF, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x1F, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x2E, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x3D, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x4C, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x5B, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x6A, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x79, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x88, PeekByte.value()); + Mgr.readByte(); + ASSERT_FALSE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(10U, Mgr.getOffset()); +} + +TEST(FileManagerTest, File__ReadSigned33) { + // 20. Test signed 33bit integer decoding. + WasmEdge::Expect ReadNum; + // Reuse the test data of reading S32 + ASSERT_TRUE(Mgr.setPath("filemgrTestData/readS32Test.bin")); + EXPECT_EQ(0U, Mgr.getOffset()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(0, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(INT32_MAX, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(INT32_MIN, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(-1, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(1, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(134, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(-348415746, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(13018, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(-98765432, ReadNum.value()); + ASSERT_TRUE(ReadNum = Mgr.readS33()); + EXPECT_EQ(891055, ReadNum.value()); + ASSERT_FALSE(ReadNum = Mgr.readS33()); + EXPECT_EQ(30U, Mgr.getOffset()); + + std::vector TestData = { + // First number. + // The first 4 bytes are 0b11111111, which indicates 4*7=28 lowest bits + // be 1. + // The last byte is 0b00001111. The highest bit is 0, indicating that this + // is the last byte. The fifth lowest bit is 0, indicating this number is + // a positive number. Therefore, the sixth and seventh bit must also be 0. + // The lowest 4 bits are all 1. + // In total, the represented number is 2^32 - 1. + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x0F, + // Second number. + // The first 4 bytes are 0b10000000, which indicates 4*7=28 lowest bits + // be 0. + // The last byte is 0b01110000. The highest bit is 0, indicating that this + // is the last byte. The fifth lowest bit is 1, indicating this number is + // a negative number. Therefore, the sixth and seventh bit must also be 1. + // The lowest 4 bits are all 0. + // In total, the represented number is 0b1 with 32 tailing zeros, which is + // -2^32. + 0x80, + 0x80, + 0x80, + 0x80, + 0x70, + }; + + ASSERT_TRUE(Mgr.setCode(std::move(TestData))); + ASSERT_EQ((1LL << 32) - 1, Mgr.readS33().value()); + ASSERT_EQ(5, Mgr.getOffset()); + ASSERT_EQ(-(1LL << 32), Mgr.readS33().value()); + ASSERT_EQ(10, Mgr.getOffset()); +} + +TEST(FileManagerTest, File__ReadSigned33TooLong) { + // 21. Test signed 33bit integer decoding in too long case. + WasmEdge::Expect ReadNum; + // Reuse the test data of reading S32. Loading too long for S32 is the same as + // S33, since both of them occupy at most 5 bytes. + ASSERT_TRUE(Mgr.setPath("filemgrTestData/readS32TestTooLong.bin")); + ASSERT_FALSE(ReadNum = Mgr.readS33()); + EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLong, ReadNum.error()); +} + +TEST(FileManagerTest, File__ReadSigned33TooLarge) { + // 22. Test signed 33bit integer decoding in too large case. + WasmEdge::Expect ReadNum; + // The first 4 bytes starts with bit 1, which indicates there is a coming + // fifth byte. The last byte is 0b00101111. The highest bit is 0, indicating + // that this is the last byte. The fifth lowest bit is 0, indicating this + // number is a positive number. Therefore, the sixth and seventh bit must also + // be 0. However, the sixth lowest bit is 1, which will cause loading a too + // large positive number. + ASSERT_TRUE( + Mgr.setCode(std::vector({0xFF, 0xFF, 0xFF, 0xFF, 0x1F}))); + ASSERT_FALSE(ReadNum = Mgr.readS33()); + EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLarge, ReadNum.error()); + // The first 4 bytes starts with bit 1, which indicates there is a coming + // fifth byte. The last byte is 0b01011111. The highest bit is 0, indicating + // that this is the last byte. The fifth lowest bit is 1, indicating this + // number is a negative number. Therefore, the sixth and seventh bit must also + // be 1. However, the sixth lowest bit is 0, which will cause loading a too + // large negative number. + ASSERT_TRUE( + Mgr.setCode(std::vector({0xFF, 0xFF, 0xFF, 0xFF, 0x5F}))); + ASSERT_FALSE(ReadNum = Mgr.readS33()); + EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLarge, ReadNum.error()); +} + TEST(FileManagerTest, Vector__ReadByte) { - // 19. Test unsigned char reading. + // 1. Test unsigned char reading. WasmEdge::Expect ReadByte; ASSERT_TRUE(Mgr.setCode(std::vector{0x00, 0xFF, 0x1F, 0x2E, 0x3D, 0x4C, 0x5B, 0x6A, 0x79, 0x88})); @@ -402,7 +542,7 @@ TEST(FileManagerTest, Vector__ReadByte) { } TEST(FileManagerTest, Vector__ReadBytes) { - // 20. Test unsigned char list reading. + // 2. Test unsigned char list reading. WasmEdge::Expect> ReadBytes; ASSERT_TRUE(Mgr.setCode(std::vector{0x00, 0xFF, 0x1F, 0x2E, 0x3D, 0x4C, 0x5B, 0x6A, 0x79, 0x88})); @@ -428,7 +568,7 @@ TEST(FileManagerTest, Vector__ReadBytes) { } TEST(FileManagerTest, Vector__ReadUnsigned32) { - // 21. Test unsigned 32bit integer decoding. + // 3. Test unsigned 32bit integer decoding. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x80, 0x80, 0x80, 0x08, 0xFF, @@ -462,7 +602,7 @@ TEST(FileManagerTest, Vector__ReadUnsigned32) { } TEST(FileManagerTest, Vector__ReadUnsigned64) { - // 22. Test unsigned 64bit integer decoding. + // 4. Test unsigned 64bit integer decoding. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0x80, @@ -499,7 +639,7 @@ TEST(FileManagerTest, Vector__ReadUnsigned64) { } TEST(FileManagerTest, Vector__ReadSigned32) { - // 23. Test signed 32bit integer decoding. + // 5. Test signed 32bit integer decoding. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x80, 0x80, 0x80, @@ -533,7 +673,7 @@ TEST(FileManagerTest, Vector__ReadSigned32) { } TEST(FileManagerTest, Vector__ReadSigned64) { - // 24. Test signed 64bit integer decoding. + // 6. Test signed 64bit integer decoding. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, @@ -570,7 +710,7 @@ TEST(FileManagerTest, Vector__ReadSigned64) { } TEST(FileManagerTest, Vector__ReadFloat32) { - // 25. Test Special Cases float. + // 7. Test Special Cases float. // // 1. +0.0 // 2. -0.0 @@ -612,7 +752,7 @@ TEST(FileManagerTest, Vector__ReadFloat32) { } TEST(FileManagerTest, Vector__ReadFloat64) { - // 26. Test Special Cases double. + // 8. Test Special Cases double. // // 1. +0.0 // 2. -0.0 @@ -657,7 +797,7 @@ TEST(FileManagerTest, Vector__ReadFloat64) { } TEST(FileManagerTest, Vector__ReadName) { - // 27. Test utf-8 string reading. + // 9. Test utf-8 string reading. WasmEdge::Expect ReadStr; ASSERT_TRUE(Mgr.setCode(std::vector{0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x01, 0x20, 0x06, 0x4C, @@ -678,7 +818,7 @@ TEST(FileManagerTest, Vector__ReadName) { } TEST(FileManagerTest, Vector__ReadUnsigned32TooLong) { - // 28. Test unsigned 32bit integer decoding in too long case. + // 10. Test unsigned 32bit integer decoding in too long case. WasmEdge::Expect ReadNum; ASSERT_TRUE( Mgr.setCode(std::vector{0x80, 0x80, 0x80, 0x80, 0x80, 0x00})); @@ -687,7 +827,7 @@ TEST(FileManagerTest, Vector__ReadUnsigned32TooLong) { } TEST(FileManagerTest, Vector__ReadUnsigned32TooLarge) { - // 29. Test unsigned 32bit integer decoding in too large case. + // 11. Test unsigned 32bit integer decoding in too large case. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{0x80, 0x80, 0x80, 0x80, 0x1F})); ASSERT_FALSE(ReadNum = Mgr.readU32()); @@ -695,7 +835,7 @@ TEST(FileManagerTest, Vector__ReadUnsigned32TooLarge) { } TEST(FileManagerTest, Vector__ReadSigned32TooLong) { - // 30. Test signed 32bit integer decoding in too long case. + // 12. Test signed 32bit integer decoding in too long case. WasmEdge::Expect ReadNum; ASSERT_TRUE( Mgr.setCode(std::vector{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F})); @@ -704,7 +844,7 @@ TEST(FileManagerTest, Vector__ReadSigned32TooLong) { } TEST(FileManagerTest, Vector__ReadSigned32TooLarge) { - // 31. Test signed 32bit integer decoding in too large case. + // 13. Test signed 32bit integer decoding in too large case. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{0xFF, 0xFF, 0xFF, 0xFF, 0x4F})); ASSERT_FALSE(ReadNum = Mgr.readS32()); @@ -712,7 +852,7 @@ TEST(FileManagerTest, Vector__ReadSigned32TooLarge) { } TEST(FileManagerTest, Vector__ReadUnsigned64TooLong) { - // 32. Test unsigned 64bit integer decoding in too long case. + // 14. Test unsigned 64bit integer decoding in too long case. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00})); @@ -721,7 +861,7 @@ TEST(FileManagerTest, Vector__ReadUnsigned64TooLong) { } TEST(FileManagerTest, Vector__ReadUnsigned64TooLarge) { - // 33. Test unsigned 64bit integer decoding in too large case. + // 15. Test unsigned 64bit integer decoding in too large case. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E})); @@ -730,7 +870,7 @@ TEST(FileManagerTest, Vector__ReadUnsigned64TooLarge) { } TEST(FileManagerTest, Vector__ReadSigned64TooLong) { - // 34. Test signed 64bit integer decoding in too long case. + // 16. Test signed 64bit integer decoding in too long case. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F})); @@ -739,7 +879,7 @@ TEST(FileManagerTest, Vector__ReadSigned64TooLong) { } TEST(FileManagerTest, Vector__ReadSigned64TooLarge) { - // 35. Test signed 64bit integer decoding in too large case. + // 17. Test signed 64bit integer decoding in too large case. WasmEdge::Expect ReadNum; ASSERT_TRUE(Mgr.setCode(std::vector{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41})); @@ -747,106 +887,46 @@ TEST(FileManagerTest, Vector__ReadSigned64TooLarge) { EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLarge, ReadNum.error()); } -TEST(FileManagerTest, File__ReadSigned33) { - // 36. Test signed 33bit integer decoding. - WasmEdge::Expect ReadNum; - // Reuse the test data of reading S32 - ASSERT_TRUE(Mgr.setPath("filemgrTestData/readS32Test.bin")); +TEST(FileManagerTest, Vector__PeekByte) { + // 18. Test unsigned char peeking. + WasmEdge::Expect PeekByte; + ASSERT_TRUE(Mgr.setCode(std::vector{0x00, 0xFF, 0x1F, 0x2E, 0x3D, + 0x4C, 0x5B, 0x6A, 0x79, 0x88})); EXPECT_EQ(0U, Mgr.getOffset()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(0, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(INT32_MAX, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(INT32_MIN, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(-1, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(1, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(134, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(-348415746, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(13018, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(-98765432, ReadNum.value()); - ASSERT_TRUE(ReadNum = Mgr.readS33()); - EXPECT_EQ(891055, ReadNum.value()); - ASSERT_FALSE(ReadNum = Mgr.readS33()); - EXPECT_EQ(30U, Mgr.getOffset()); - - std::vector TestData = { - // First number. - // The first 4 bytes are 0b11111111, which indicates 4*7=28 lowest bits - // be 1. - // The last byte is 0b00001111. The highest bit is 0, indicating that this - // is the last byte. The fifth lowest bit is 0, indicating this number is - // a positive number. Therefore, the sixth and seventh bit must also be 0. - // The lowest 4 bits are all 1. - // In total, the represented number is 2^32 - 1. - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0x0F, - // Second number. - // The first 4 bytes are 0b10000000, which indicates 4*7=28 lowest bits - // be 0. - // The last byte is 0b01110000. The highest bit is 0, indicating that this - // is the last byte. The fifth lowest bit is 1, indicating this number is - // a negative number. Therefore, the sixth and seventh bit must also be 1. - // The lowest 4 bits are all 0. - // In total, the represented number is 0b1 with 32 tailing zeros, which is - // -2^32. - 0x80, - 0x80, - 0x80, - 0x80, - 0x70, - }; - - ASSERT_TRUE(Mgr.setCode(std::move(TestData))); - ASSERT_EQ((1LL << 32) - 1, Mgr.readS33().value()); - ASSERT_EQ(5, Mgr.getOffset()); - ASSERT_EQ(-(1LL << 32), Mgr.readS33().value()); - ASSERT_EQ(10, Mgr.getOffset()); -} - -TEST(FileManagerTest, File__ReadSigned33TooLong) { - // 37. Test signed 33bit integer decoding in too long case. - WasmEdge::Expect ReadNum; - // Reuse the test data of reading S32. Loading too long for S32 is the same as - // S33, since both of them occupy at most 5 bytes. - ASSERT_TRUE(Mgr.setPath("filemgrTestData/readS32TestTooLong.bin")); - ASSERT_FALSE(ReadNum = Mgr.readS33()); - EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLong, ReadNum.error()); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x00, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0xFF, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x1F, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x2E, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x3D, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x4C, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x5B, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x6A, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x79, PeekByte.value()); + Mgr.readByte(); + ASSERT_TRUE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(0x88, PeekByte.value()); + Mgr.readByte(); + ASSERT_FALSE(PeekByte = Mgr.peekByte()); + EXPECT_EQ(10U, Mgr.getOffset()); } -TEST(FileManagerTest, File__ReadSigned33TooLarge) { - // 38. Test signed 33bit integer decoding in too large case. - WasmEdge::Expect ReadNum; - // The first 4 bytes starts with bit 1, which indicates there is a coming - // fifth byte. The last byte is 0b00101111. The highest bit is 0, indicating - // that this is the last byte. The fifth lowest bit is 0, indicating this - // number is a positive number. Therefore, the sixth and seventh bit must also - // be 0. However, the sixth lowest bit is 1, which will cause loading a too - // large positive number. - ASSERT_TRUE( - Mgr.setCode(std::vector({0xFF, 0xFF, 0xFF, 0xFF, 0x1F}))); - ASSERT_FALSE(ReadNum = Mgr.readS33()); - EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLarge, ReadNum.error()); - // The first 4 bytes starts with bit 1, which indicates there is a coming - // fifth byte. The last byte is 0b01011111. The highest bit is 0, indicating - // that this is the last byte. The fifth lowest bit is 1, indicating this - // number is a negative number. Therefore, the sixth and seventh bit must also - // be 1. However, the sixth lowest bit is 0, which will cause loading a too - // large negative number. - ASSERT_TRUE( - Mgr.setCode(std::vector({0xFF, 0xFF, 0xFF, 0xFF, 0x5F}))); - ASSERT_FALSE(ReadNum = Mgr.readS33()); - EXPECT_EQ(WasmEdge::ErrCode::Value::IntegerTooLarge, ReadNum.error()); -} } // namespace GTEST_API_ int main(int argc, char **argv) { diff --git a/test/plugins/wasm_bpf/simple_ringbuf_test.cpp b/test/plugins/wasm_bpf/simple_ringbuf_test.cpp index b615524e360a..f7052105263e 100644 --- a/test/plugins/wasm_bpf/simple_ringbuf_test.cpp +++ b/test/plugins/wasm_bpf/simple_ringbuf_test.cpp @@ -186,16 +186,17 @@ TEST(WasmBpfTest, SimpleRingbuf) { // In the following several steps we will prepare for polling // Create an instance of the polling callback function - auto callbackFuncInst = - std::make_unique( - &moduleInst, std::make_unique()); + moduleInst.addHostFunc("__polling_callback_hostfunc"sv, + std::make_unique()); + auto *callbackFuncInst = + moduleInst.findFuncExports("__polling_callback_hostfunc"); // Create a function table, and fill the callback function into it auto funcTableInst = std::make_unique( WasmEdge::AST::TableType(WasmEdge::TypeCode::FuncRef, 1)); ASSERT_TRUE(funcTableInst->setRefs( - std::initializer_list{callbackFuncInst.get()}, - 0, 0, 1)); + std::initializer_list{callbackFuncInst}, 0, 0, + 1)); // Add the table to the main module moduleInst.addHostTable("__indirect_function_table"sv, std::move(funcTableInst)); diff --git a/test/plugins/wasm_bpf/wasm_bpf.cpp b/test/plugins/wasm_bpf/wasm_bpf.cpp index 5f80042d7ef8..9bf84f87bedf 100644 --- a/test/plugins/wasm_bpf/wasm_bpf.cpp +++ b/test/plugins/wasm_bpf/wasm_bpf.cpp @@ -279,16 +279,17 @@ TEST(WasmBpfTest, RunBpfProgramWithPolling) { // In the following several steps we will prepare for polling // Create an instance of the polling callback function - auto callbackFuncInst = - std::make_unique( - &moduleInst, std::make_unique()); + moduleInst.addHostFunc("__polling_callback_hostfunc"sv, + std::make_unique()); + auto *callbackFuncInst = + moduleInst.findFuncExports("__polling_callback_hostfunc"); // Create a function table, and fill the callback function into it auto funcTableInst = std::make_unique( WasmEdge::AST::TableType(WasmEdge::TypeCode::FuncRef, 1)); EXPECT_TRUE(funcTableInst->setRefs( - std::initializer_list{callbackFuncInst.get()}, - 0, 0, 1)); + std::initializer_list{callbackFuncInst}, 0, 0, + 1)); // Add the table to the main module moduleInst.addHostTable("__indirect_function_table"sv, std::move(funcTableInst)); diff --git a/test/spec/CMakeLists.txt b/test/spec/CMakeLists.txt index aca888a0d6f7..24ed7d86f068 100644 --- a/test/spec/CMakeLists.txt +++ b/test/spec/CMakeLists.txt @@ -76,7 +76,7 @@ function(wasmedge_copy_spec_testsuite proposal) message(STATUS "Copying test suite to ${CMAKE_CURRENT_BINARY_DIR}/testSuites/${proposal} -- done") endfunction() -foreach(PROPOSAL core multi-memory tail-call extended-const threads function-references) +foreach(PROPOSAL core multi-memory tail-call extended-const threads function-references gc) wasmedge_copy_spec_testsuite(${PROPOSAL}) endforeach() diff --git a/test/spec/spectest.cpp b/test/spec/spectest.cpp index 07ddf2216718..f3a83bc1e55f 100644 --- a/test/spec/spectest.cpp +++ b/test/spec/spectest.cpp @@ -159,23 +159,27 @@ parseValueList(const simdjson::dom::array &Args) { ResultTypes.emplace_back(WasmEdge::TypeCode::V128); } else if (Value.type() == simdjson::dom::element_type::STRING) { std::string_view ValueStr = Value; - if (Type == "externref"sv) { + if (Type == "externref"sv || Type == "anyref"sv) { + WasmEdge::TypeCode Code = Type == "externref"sv + ? WasmEdge::TypeCode::ExternRef + : WasmEdge::TypeCode::AnyRef; if (Value == "null"sv) { - Result.emplace_back(WasmEdge::RefVariant()); + Result.emplace_back(WasmEdge::RefVariant(Code)); } else { - // Add 0x1 uint32_t prefix in this externref index case. - Result.emplace_back(WasmEdge::RefVariant(reinterpret_cast( - std::stoul(std::string(ValueStr)) + 0x100000000ULL))); + // ExternRef and AnyRef are non-opaque references. Add 0x1 uint32_t + // prefix in this case to present non-null. + Result.emplace_back(WasmEdge::RefVariant( + Code, reinterpret_cast(std::stoul(std::string(ValueStr)) + + 0x100000000ULL))); } - ResultTypes.emplace_back(WasmEdge::TypeCode::ExternRef); + ResultTypes.emplace_back(Code); } else if (Type == "funcref"sv) { if (Value == "null"sv) { - Result.emplace_back(WasmEdge::RefVariant()); + Result.emplace_back( + WasmEdge::RefVariant(WasmEdge::TypeCode::FuncRef)); } else { - // Add 0x1 uint32_t prefix in this funcref index case. - Result.emplace_back(WasmEdge::RefVariant( - reinterpret_cast( - std::stoul(std::string(ValueStr)) + 0x100000000ULL))); + // Not support input value of opaque references for testing. + assumingUnreachable(); } ResultTypes.emplace_back(WasmEdge::TypeCode::FuncRef); } else if (Type == "i32"sv) { @@ -254,6 +258,7 @@ static const TestsuiteProposal TestsuiteProposals[] = { {"threads"sv, {Proposal::Threads}}, {"function-references"sv, {Proposal::FunctionReferences, Proposal::TailCall}}, + {"gc"sv, {Proposal::GC}, WasmEdge::SpecTest::TestMode::Interpreter}, }; } // namespace @@ -299,6 +304,21 @@ bool SpecTest::compare(const std::pair &Expected, const std::pair &Got) const { const auto &TypeStr = Expected.first; const auto &ValStr = Expected.second; + + auto IsRefMatch = [&ValStr](const WasmEdge::RefVariant &R) { + if (ValStr == "null"sv) { + // If explicitly expected a `null`, the reference must be null. + return R.isNull(); + } + if (ValStr == ""sv) { + // Opaque expected reference. Always true. + return true; + } + // Explicitly expected the reference value. + return static_cast(reinterpret_cast( + R.getPtr())) == static_cast(std::stoul(ValStr)); + }; + bool IsV128 = (std::string_view(TypeStr).substr(0, 4) == "v128"sv); if (!IsV128 && ValStr.substr(0, 4) == "nan:"sv) { // Handle NaN case @@ -314,43 +334,103 @@ bool SpecTest::compare(const std::pair &Expected, } return std::isnan(Got.first.get()); } + } else if (TypeStr == "ref"sv) { + // "ref" fits all reference types. + if (!Got.second.isRefType()) { + return false; + } + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "anyref"sv) { + // "anyref" fits all internal reference types. + if (!Got.second.isRefType() || Got.second.isExternRefType()) { + return false; + } + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "eqref"sv) { + // "eqref" fits eqref, structref, arrayref, i31ref, and nullref. + if (!Got.second.isRefType()) { + return false; + } + switch (Got.second.getHeapTypeCode()) { + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + case TypeCode::NullRef: + break; + default: + return false; + } + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "structref"sv) { + // "structref" structref and nullref. + if (!Got.second.isRefType()) { + return false; + } + switch (Got.second.getHeapTypeCode()) { + case TypeCode::StructRef: + case TypeCode::NullRef: + break; + default: + return false; + } + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "arrayref"sv) { + // "arrayref" arrayref and nullref. + if (!Got.second.isRefType()) { + return false; + } + switch (Got.second.getHeapTypeCode()) { + case TypeCode::ArrayRef: + case TypeCode::NullRef: + break; + default: + return false; + } + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "i31ref"sv) { + // "i31ref" i31ref and nullref. + if (!Got.second.isRefType()) { + return false; + } + switch (Got.second.getHeapTypeCode()) { + case TypeCode::I31Ref: + case TypeCode::NullRef: + break; + default: + return false; + } + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "nullref"sv) { + if (!Got.second.isRefType() || + Got.second.getHeapTypeCode() != TypeCode::NullRef) { + return false; + } + return IsRefMatch(Got.first.get()); } else if (TypeStr == "funcref"sv) { + // "funcref" fits funcref and nullfuncref. if (!Got.second.isFuncRefType()) { return false; } - if (ValStr == "null"sv) { - return Got.first.get().isNull(); - } else { - // Due to the implementations of the embedders, the value of FuncRef is - // opaque. Therefore not to compare the value here. - return !Got.first.get().isNull(); + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "nullfuncref"sv) { + if (!Got.second.isRefType() || + Got.second.getHeapTypeCode() != TypeCode::NullFuncRef) { + return false; } + return IsRefMatch(Got.first.get()); } else if (TypeStr == "externref"sv) { + // "externref" fits externref and nullexternref. if (!Got.second.isExternRefType()) { return false; } - if (ValStr == "null"sv) { - return Got.first.get().isNull(); - } else { - if (Got.first.get().isNull()) { - return false; - } - return static_cast(reinterpret_cast( - &WasmEdge::retrieveExternRef( - Got.first.get()))) == - static_cast(std::stoul(ValStr)); - } - } else if (TypeStr == "ref"sv) { - if (!Got.second.isNullableRefType()) { + return IsRefMatch(Got.first.get()); + } else if (TypeStr == "nullexternref"sv) { + if (!Got.second.isRefType() || + Got.second.getHeapTypeCode() != TypeCode::NullExternRef) { return false; } - if (ValStr == "null"sv) { - return Got.first.get().isNull(); - } else { - // Due to the implementations of the embedders, the value of Ref is - // opaque. Therefore not to compare the value here. - return !Got.first.get().isNull(); - } + return IsRefMatch(Got.first.get()); } else if (TypeStr == "i32"sv) { if (Got.second.getCode() != TypeCode::I32) { return false; From eec265d05e8d97e0b797335d8b5f0e691e845b9e Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 19 Feb 2024 15:49:22 +0800 Subject: [PATCH 050/218] [Changelog] Update the changelog for the 0.14.0-alpha.2 pre-release. Signed-off-by: YiYing He --- .CurrentChangelog.md | 11 +++++++++-- Changelog.md | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index a23a94d89dd2..8ac8645231f4 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.1 (2024-01-05) +### 0.14.0-alpha.2 (2024-02-19) Breaking changes: @@ -36,9 +36,13 @@ Features: * Supported WASM Typed Function References proposal. * Added the `WasmEdge_Proposal_FunctionReferences` for the configuration in WasmEdge C API. * Users can use the `--enable-function-reference` to enable the proposal in `wasmedge` and `wasmedgec` tools. + * Supported WASM GC proposal (interpreter only). + * Added the `WasmEdge_Proposal_GC` for the configuration in WasmEdge C API. + * Users can use the `--enable-gc` to enable the proposal in `wasmedge` and `wasmedgec` tools. * Component Model proposal (experimental, loader phase only). * Added the `WasmEdge_Proposal_Component` for the configuration in WasmEdge C API. * Users can use the `--enable-function-reference` to enable the proposal in `wasmedge` tool. +* [JIT]: Support LLVM JIT. * [C API]: New C API for supporting the new proposals. * `WasmEdge_ValType` related APIs can help developers to generate or compare value types. * `WasmEdge_ValTypeGenI32()` (replacing `WasmEdge_ValType_I32`) @@ -85,6 +89,9 @@ Features: Fixed issues: * Fixed some API document in the API header. +* [Executor]: Minor fixes. + * Fixed integer overflow on `memGrow` boundary check. + * Refined the slice copy in table instances. * [WASI]: Minor fixes. * Fixed the function signature matching for WASI imports when backwarding supporting older version. (#3073) * Fixed large timestamp causing overflow (#3106). @@ -114,4 +121,4 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.1-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-alpha.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index eba6f9c97737..41dbdf56072b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.1 (2024-01-05) +### 0.14.0-alpha.2 (2024-02-19) Breaking changes: @@ -36,9 +36,13 @@ Features: * Supported WASM Typed Function References proposal. * Added the `WasmEdge_Proposal_FunctionReferences` for the configuration in WasmEdge C API. * Users can use the `--enable-function-reference` to enable the proposal in `wasmedge` and `wasmedgec` tools. + * Supported WASM GC proposal (interpreter only). + * Added the `WasmEdge_Proposal_GC` for the configuration in WasmEdge C API. + * Users can use the `--enable-gc` to enable the proposal in `wasmedge` and `wasmedgec` tools. * Component Model proposal (experimental, loader phase only). * Added the `WasmEdge_Proposal_Component` for the configuration in WasmEdge C API. * Users can use the `--enable-function-reference` to enable the proposal in `wasmedge` tool. +* [JIT]: Support LLVM JIT. * [C API]: New C API for supporting the new proposals. * `WasmEdge_ValType` related APIs can help developers to generate or compare value types. * `WasmEdge_ValTypeGenI32()` (replacing `WasmEdge_ValType_I32`) @@ -85,6 +89,9 @@ Features: Fixed issues: * Fixed some API document in the API header. +* [Executor]: Minor fixes. + * Fixed integer overflow on `memGrow` boundary check. + * Refined the slice copy in table instances. * [WASI]: Minor fixes. * Fixed the function signature matching for WASI imports when backwarding supporting older version. (#3073) * Fixed large timestamp causing overflow (#3106). @@ -114,7 +121,7 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.1-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-alpha.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 13910701039dfc3a72cd80659a647c5c72c5370c Mon Sep 17 00:00:00 2001 From: dm4 Date: Mon, 19 Feb 2024 16:07:08 +0800 Subject: [PATCH 051/218] [Changelog] Update the changelog for WASI-NN GGML backend Signed-off-by: dm4 --- .CurrentChangelog.md | 12 ++++++++---- Changelog.md | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index 8ac8645231f4..53ccc9ec510d 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.2 (2024-02-19) +### 0.14.0-alpha.2 (2024-02-23) Breaking changes: @@ -72,7 +72,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b1743 + * Bump llama.cpp to b2230. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -81,10 +81,14 @@ Features: * Default enable Metal on macOS. * Introduce `load_by_name_with_config()` to load model with metadata. * Introduce single token inference by `compute_single`, `get_output_single`, and `fini_single` - * Add some llama errors to WASI-NN + * Add some llama errors to WASI-NN. * `EndOfSequence`: returned when encounter `` token on single token inferece. * `ContextFull`: returned when the context is full. * `PromptTooLong`: returned when the input size is too large. + * Support Llava and Gemma inference. + * Add `mmproj` option to set the projection model. + * Add `image` option to set the image. + * Support embedding generation. Fixed issues: @@ -119,6 +123,6 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, zhumeme +Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, vincent, zhumeme If you want to build from source, please use WasmEdge-0.14.0-alpha.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 41dbdf56072b..04389b1e84f4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.2 (2024-02-19) +### 0.14.0-alpha.2 (2024-02-23) Breaking changes: @@ -72,7 +72,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b1743 + * Bump llama.cpp to b2230. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -81,10 +81,14 @@ Features: * Default enable Metal on macOS. * Introduce `load_by_name_with_config()` to load model with metadata. * Introduce single token inference by `compute_single`, `get_output_single`, and `fini_single` - * Add some llama errors to WASI-NN + * Add some llama errors to WASI-NN. * `EndOfSequence`: returned when encounter `` token on single token inferece. * `ContextFull`: returned when the context is full. * `PromptTooLong`: returned when the input size is too large. + * Support Llava and Gemma inference. + * Add `mmproj` option to set the projection model. + * Add `image` option to set the image. + * Support embedding generation. Fixed issues: @@ -119,7 +123,7 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, zhumeme +Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, vincent, zhumeme If you want to build from source, please use WasmEdge-0.14.0-alpha.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. From f1f2cf51caae301bd7952d1a1177e9ebc7e75b55 Mon Sep 17 00:00:00 2001 From: vincent Date: Sat, 23 Sep 2023 14:15:19 +0800 Subject: [PATCH 052/218] [Plugin] Call constructor in vector-allocated space The original approach triggers constructor twice, including one move constructor. However, it seems there is a bug in the default move constructor's handling of aligning memory, it's always allocating inaccessible memory locations, then resulting in a __memmove_avx_unaligned_erms segmentation fault. Signed-off-by: vincent --- include/plugin/plugin.h | 3 +-- lib/plugin/plugin.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/plugin/plugin.h b/include/plugin/plugin.h index c91478b7d499..7fd9f83f991f 100644 --- a/include/plugin/plugin.h +++ b/include/plugin/plugin.h @@ -105,6 +105,7 @@ class Plugin { Plugin &operator=(Plugin &&) noexcept = default; Plugin() noexcept = default; + explicit Plugin(const PluginDescriptor *D) noexcept; constexpr const char *name() const noexcept { assuming(Desc); @@ -150,8 +151,6 @@ class Plugin { static bool loadFile(const std::filesystem::path &Path) noexcept; - explicit Plugin(const PluginDescriptor *D) noexcept; - public: WASMEDGE_EXPORT static void registerPlugin(const PluginDescriptor *Desc) noexcept; diff --git a/lib/plugin/plugin.cpp b/lib/plugin/plugin.cpp index 0dd837280324..fbf354a970c6 100644 --- a/lib/plugin/plugin.cpp +++ b/lib/plugin/plugin.cpp @@ -399,7 +399,7 @@ Plugin::registerPlugin(const PluginDescriptor *Desc) noexcept { } const auto Index = PluginRegistry.size(); - PluginRegistry.push_back(Plugin(Desc)); + PluginRegistry.emplace_back(Desc); PluginNameLookup.emplace(Desc->Name, Index); return; From 2d230ab4090b5cdb3c47c9dd7ebf8bb156915057 Mon Sep 17 00:00:00 2001 From: vincent Date: Sat, 23 Sep 2023 18:02:36 +0800 Subject: [PATCH 053/218] [Plugin] Decouple plugin registration from lib loading Handling special case where the main program statically links Wasmedge but still requires dynamic loading of plugins. Signed-off-by: vincent --- include/plugin/plugin.h | 11 +++++------ lib/plugin/plugin.cpp | 17 ++++++----------- plugins/wasi_crypto/ctx.cpp | 3 ++- plugins/wasi_crypto/ctx.h | 1 - plugins/wasi_logging/env.cpp | 5 ++--- plugins/wasi_logging/wasi_logging/env.h | 1 - plugins/wasi_nn/wasinnenv.cpp | 4 ++-- plugins/wasi_nn/wasinnenv.h | 1 - plugins/wasm_bpf/wasm-bpf-module.cpp | 2 +- plugins/wasmedge_image/image_env.cpp | 5 ++--- plugins/wasmedge_image/image_env.h | 4 +--- plugins/wasmedge_opencvmini/opencvmini_env.cpp | 5 ++--- plugins/wasmedge_opencvmini/opencvmini_env.h | 2 -- plugins/wasmedge_process/processenv.cpp | 5 ++--- plugins/wasmedge_process/processenv.h | 1 - plugins/wasmedge_tensorflow/tensorflow_env.cpp | 5 ++--- plugins/wasmedge_tensorflow/tensorflow_env.h | 2 -- .../tensorflowlite_env.cpp | 5 ++--- .../tensorflowlite_env.h | 2 -- plugins/wasmedge_zlib/zlibenv.cpp | 5 ++--- plugins/wasmedge_zlib/zlibenv.h | 3 --- test/plugins/unittest/testplugin.cpp | 5 ++--- test/plugins/unittest/testplugin.h | 1 - 23 files changed, 33 insertions(+), 62 deletions(-) diff --git a/include/plugin/plugin.h b/include/plugin/plugin.h index 7fd9f83f991f..92f08bc0d138 100644 --- a/include/plugin/plugin.h +++ b/include/plugin/plugin.h @@ -29,6 +29,11 @@ #define WASMEDGE_EXPORT [[gnu::visibility("default")]] #endif +#define EXPORT_GET_DESCRIPTOR(Descriptor) \ + extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor() { \ + return &Descriptor; \ + } + namespace WasmEdge { namespace Plugin { @@ -156,11 +161,5 @@ class Plugin { registerPlugin(const PluginDescriptor *Desc) noexcept; }; -struct PluginRegister { - WASMEDGE_EXPORT PluginRegister(const Plugin::PluginDescriptor *Desc) noexcept; - - WASMEDGE_EXPORT ~PluginRegister() noexcept; -}; - } // namespace Plugin } // namespace WasmEdge diff --git a/lib/plugin/plugin.cpp b/lib/plugin/plugin.cpp index fbf354a970c6..0c403bc59f80 100644 --- a/lib/plugin/plugin.cpp +++ b/lib/plugin/plugin.cpp @@ -350,6 +350,11 @@ bool Plugin::loadFile(const std::filesystem::path &Path) noexcept { return false; } + if (auto GetDescriptor = + Lib->get("GetDescriptor")) { + Plugin::registerPlugin(GetDescriptor()); + } + if (PluginRegistry.size() != Index + 1) { // Check C interface if (auto GetDescriptor = Lib->get( @@ -393,6 +398,7 @@ Span Plugin::plugins() noexcept { return PluginRegistry; } WASMEDGE_EXPORT void Plugin::registerPlugin(const PluginDescriptor *Desc) noexcept { + IncreaseNiftyCounter(); assuming(NiftyCounter != 0); if (Desc->APIVersion != CurrentAPIVersion) { return; @@ -421,16 +427,5 @@ Plugin::findModule(std::string_view Name) const noexcept { } return nullptr; } - -WASMEDGE_EXPORT -PluginRegister::PluginRegister(const Plugin::PluginDescriptor *Desc) noexcept { - IncreaseNiftyCounter(); - Plugin::registerPlugin(Desc); -} - -WASMEDGE_EXPORT PluginRegister::~PluginRegister() noexcept { - DecreaseNiftyCounter(); -} - } // namespace Plugin } // namespace WasmEdge diff --git a/plugins/wasi_crypto/ctx.cpp b/plugins/wasi_crypto/ctx.cpp index 7ff586f68d9d..db2eefe1a26d 100644 --- a/plugins/wasi_crypto/ctx.cpp +++ b/plugins/wasi_crypto/ctx.cpp @@ -72,9 +72,10 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; +EXPORT_GET_DESCRIPTOR(Descriptor) + } // namespace -Plugin::PluginRegister WasiCrypto::Context::Register(&Descriptor); std::shared_mutex WasiCrypto::Context::Mutex; std::weak_ptr WasiCrypto::Context::Instance; diff --git a/plugins/wasi_crypto/ctx.h b/plugins/wasi_crypto/ctx.h index f5eda8a74c64..46a93d841dc0 100644 --- a/plugins/wasi_crypto/ctx.h +++ b/plugins/wasi_crypto/ctx.h @@ -358,7 +358,6 @@ class Context { static std::shared_mutex Mutex; static std::weak_ptr Instance; - static Plugin::PluginRegister Register; }; } // namespace WasiCrypto diff --git a/plugins/wasi_logging/env.cpp b/plugins/wasi_logging/env.cpp index 0f55170fff8b..0e5160a19c2a 100644 --- a/plugins/wasi_logging/env.cpp +++ b/plugins/wasi_logging/env.cpp @@ -28,9 +28,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; -} // namespace - -Plugin::PluginRegister WasiLoggingEnvironment::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasi_logging/wasi_logging/env.h b/plugins/wasi_logging/wasi_logging/env.h index 8a2864d27413..2c199f96a7c0 100644 --- a/plugins/wasi_logging/wasi_logging/env.h +++ b/plugins/wasi_logging/wasi_logging/env.h @@ -16,7 +16,6 @@ class WasiLoggingEnvironment { spdlog::stdout_color_mt("wasi_logging_stdout"); inline const static std::shared_ptr StderrLogger = spdlog::stderr_color_mt("wasi_logging_stderr"); - static Plugin::PluginRegister Register; }; } // namespace Host diff --git a/plugins/wasi_nn/wasinnenv.cpp b/plugins/wasi_nn/wasinnenv.cpp index 438c7f024554..6a4038a10f0a 100644 --- a/plugins/wasi_nn/wasinnenv.cpp +++ b/plugins/wasi_nn/wasinnenv.cpp @@ -157,9 +157,9 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = addOptions, }; -} // namespace WASINN +EXPORT_GET_DESCRIPTOR(Descriptor) -Plugin::PluginRegister WASINN::WasiNNEnvironment::Register(&Descriptor); +} // namespace WASINN } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasi_nn/wasinnenv.h b/plugins/wasi_nn/wasinnenv.h index 00c8df0fb0dd..bc83b73900a7 100644 --- a/plugins/wasi_nn/wasinnenv.h +++ b/plugins/wasi_nn/wasinnenv.h @@ -206,7 +206,6 @@ struct WasiNNEnvironment : static PO::Option NNRPCURI; // For RPC client mode std::shared_ptr NNRPCChannel; #endif - static Plugin::PluginRegister Register; }; } // namespace WASINN diff --git a/plugins/wasm_bpf/wasm-bpf-module.cpp b/plugins/wasm_bpf/wasm-bpf-module.cpp index 9ae739d41a2b..6118f6ffca6b 100644 --- a/plugins/wasm_bpf/wasm-bpf-module.cpp +++ b/plugins/wasm_bpf/wasm-bpf-module.cpp @@ -53,7 +53,7 @@ Plugin::Plugin::PluginDescriptor Descriptor{ }, .AddOptions = nullptr}; -Plugin::PluginRegister Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_image/image_env.cpp b/plugins/wasmedge_image/image_env.cpp index 022787ca2b17..a1f104aea5c8 100644 --- a/plugins/wasmedge_image/image_env.cpp +++ b/plugins/wasmedge_image/image_env.cpp @@ -32,9 +32,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; -} // namespace - -Plugin::PluginRegister WasmEdgeImage::ImgEnv::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_image/image_env.h b/plugins/wasmedge_image/image_env.h index 0eea7ba5eb44..b2b59c2c61da 100644 --- a/plugins/wasmedge_image/image_env.h +++ b/plugins/wasmedge_image/image_env.h @@ -23,9 +23,7 @@ enum class DataType : uint32_t { BGR32F = 3, }; -struct ImgEnv { - static Plugin::PluginRegister Register; -}; +struct ImgEnv {}; } // namespace WasmEdgeImage } // namespace Host diff --git a/plugins/wasmedge_opencvmini/opencvmini_env.cpp b/plugins/wasmedge_opencvmini/opencvmini_env.cpp index c205d7f4c8f5..d5211492ae16 100644 --- a/plugins/wasmedge_opencvmini/opencvmini_env.cpp +++ b/plugins/wasmedge_opencvmini/opencvmini_env.cpp @@ -33,9 +33,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; -} // namespace - -Plugin::PluginRegister WasmEdgeOpenCVMiniEnvironment::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_opencvmini/opencvmini_env.h b/plugins/wasmedge_opencvmini/opencvmini_env.h index 9ab004ea2ab1..f2e606cb99d5 100644 --- a/plugins/wasmedge_opencvmini/opencvmini_env.h +++ b/plugins/wasmedge_opencvmini/opencvmini_env.h @@ -16,8 +16,6 @@ class WasmEdgeOpenCVMiniEnvironment { public: WasmEdgeOpenCVMiniEnvironment() noexcept; - static Plugin::PluginRegister Register; - std::map MatPool; Expect getMat(uint32_t MatKey) { diff --git a/plugins/wasmedge_process/processenv.cpp b/plugins/wasmedge_process/processenv.cpp index 8c769a336426..32a318f79496 100644 --- a/plugins/wasmedge_process/processenv.cpp +++ b/plugins/wasmedge_process/processenv.cpp @@ -56,9 +56,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = addOptions, }; -} // namespace - -Plugin::PluginRegister WasmEdgeProcessEnvironment::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_process/processenv.h b/plugins/wasmedge_process/processenv.h index f1b4ddbc4ecb..a7dc11616174 100644 --- a/plugins/wasmedge_process/processenv.h +++ b/plugins/wasmedge_process/processenv.h @@ -46,7 +46,6 @@ class WasmEdgeProcessEnvironment { static PO::List AllowCmd; static PO::Option AllowCmdAll; - static Plugin::PluginRegister Register; }; } // namespace Host diff --git a/plugins/wasmedge_tensorflow/tensorflow_env.cpp b/plugins/wasmedge_tensorflow/tensorflow_env.cpp index 9a672863758f..04fb55072746 100644 --- a/plugins/wasmedge_tensorflow/tensorflow_env.cpp +++ b/plugins/wasmedge_tensorflow/tensorflow_env.cpp @@ -32,9 +32,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; -} // namespace - -Plugin::PluginRegister WasmEdgeTensorflow::TFEnv::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_tensorflow/tensorflow_env.h b/plugins/wasmedge_tensorflow/tensorflow_env.h index 8cfcd645f760..46160dcb6918 100644 --- a/plugins/wasmedge_tensorflow/tensorflow_env.h +++ b/plugins/wasmedge_tensorflow/tensorflow_env.h @@ -117,8 +117,6 @@ struct TFEnv { } } - static Plugin::PluginRegister Register; - private: std::unordered_set RecycledIdx; std::vector TFContext; diff --git a/plugins/wasmedge_tensorflowlite/tensorflowlite_env.cpp b/plugins/wasmedge_tensorflowlite/tensorflowlite_env.cpp index 47a3e037e760..a6d194eaf078 100644 --- a/plugins/wasmedge_tensorflowlite/tensorflowlite_env.cpp +++ b/plugins/wasmedge_tensorflowlite/tensorflowlite_env.cpp @@ -32,9 +32,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; -} // namespace - -Plugin::PluginRegister WasmEdgeTensorflowLite::TFLiteEnv::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_tensorflowlite/tensorflowlite_env.h b/plugins/wasmedge_tensorflowlite/tensorflowlite_env.h index f4f606f4872e..188ab9c2d837 100644 --- a/plugins/wasmedge_tensorflowlite/tensorflowlite_env.h +++ b/plugins/wasmedge_tensorflowlite/tensorflowlite_env.h @@ -63,8 +63,6 @@ struct TFLiteEnv { } } - static Plugin::PluginRegister Register; - private: std::unordered_set RecycledIdx; std::vector TFLiteContext; diff --git a/plugins/wasmedge_zlib/zlibenv.cpp b/plugins/wasmedge_zlib/zlibenv.cpp index 45654a288e4b..f00a9ef75afa 100644 --- a/plugins/wasmedge_zlib/zlibenv.cpp +++ b/plugins/wasmedge_zlib/zlibenv.cpp @@ -31,9 +31,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = nullptr, }; -} // namespace - -Plugin::PluginRegister WasmEdgeZlibEnvironment::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasmedge_zlib/zlibenv.h b/plugins/wasmedge_zlib/zlibenv.h index 97781a573b63..190025cdbe0e 100644 --- a/plugins/wasmedge_zlib/zlibenv.h +++ b/plugins/wasmedge_zlib/zlibenv.h @@ -91,9 +91,6 @@ class WasmEdgeZlibEnvironment { std::unordered_map> ZStreamMap; std::map, std::greater> GZFileMap; std::unordered_map GZHeaderMap; - - /// Initial Configurations - static Plugin::PluginRegister Register; }; } // namespace Host diff --git a/test/plugins/unittest/testplugin.cpp b/test/plugins/unittest/testplugin.cpp index 21431b14f063..565b77c87b3b 100644 --- a/test/plugins/unittest/testplugin.cpp +++ b/test/plugins/unittest/testplugin.cpp @@ -49,9 +49,8 @@ Plugin::Plugin::PluginDescriptor Descriptor{ .AddOptions = addOptions, }; -} // namespace - -Plugin::PluginRegister WasmEdgePluginTestEnv::Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) +} // namespace } // namespace Host } // namespace WasmEdge diff --git a/test/plugins/unittest/testplugin.h b/test/plugins/unittest/testplugin.h index 214ab0495fcc..d7373c9c6e12 100644 --- a/test/plugins/unittest/testplugin.h +++ b/test/plugins/unittest/testplugin.h @@ -20,7 +20,6 @@ class WasmEdgePluginTestEnv { static PO::List CmdArgs; static PO::Option CmdName; - static Plugin::PluginRegister Register; }; template From 1c66a2f01da873793040535c67d16a7e8cc49bbd Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 23 Feb 2024 20:54:00 +0800 Subject: [PATCH 054/218] [CI] Remove zlib plugin on manylinux2014 Signed-off-by: hydai --- .github/workflows/release.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a4a24313159..bab5fc642bd2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -336,13 +336,13 @@ jobs: runs-on: ${{ matrix.host_runner }} env: output_prefix: build/plugins - build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON + build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON build_options_manylinux2014_x86_64: -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF build_options_manylinux2014_aarch64: - tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_zlib + tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini tar_names_manylinux2014_x86_64: wasm_bpf tar_names_manylinux2014_aarch64: - output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeZlib.so + output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so output_bins_manylinux2014_x86_64: libwasmedgePluginWasmBpf.so output_bins_manylinux2014_aarch64: needs: create_release @@ -442,12 +442,6 @@ jobs: run: | mv plugin_wasmedge_opencvmini.tar.gz WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber - - name: Upload wasmedge_zlib plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_zlib.tar.gz WasmEdge-plugin-wasmedge_zlib-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_zlib-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber build_and_upload_plugin_macos: strategy: From f32b086eec2c1df41680ef2b3448e8f921622322 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 23 Feb 2024 20:55:19 +0800 Subject: [PATCH 055/218] [CI] Don't install grpc related deps in the release workflow Signed-off-by: hydai --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bab5fc642bd2..0212e94ed3f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -145,7 +145,7 @@ jobs: shell: bash run: | apt update - apt install -y unzip libopenblas-dev pkg-config protobuf-compiler-grpc libgrpc-dev libgrpc++-dev + apt install -y unzip libopenblas-dev pkg-config bash utils/wasi-nn/install-openvino.sh bash utils/wasi-nn/install-pytorch.sh - name: Build WASI-NN plugin From ff053783f802008e70fafb4be09fdfe76a138baf Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 23 Feb 2024 21:43:41 +0800 Subject: [PATCH 056/218] [CI] Seperate the release and build deps Signed-off-by: hydai --- .github/workflows/reusable-build-on-ubuntu.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/reusable-build-on-ubuntu.yml b/.github/workflows/reusable-build-on-ubuntu.yml index 4df645267a82..2b5bec432bf6 100644 --- a/.github/workflows/reusable-build-on-ubuntu.yml +++ b/.github/workflows/reusable-build-on-ubuntu.yml @@ -27,9 +27,15 @@ jobs: container: wasmedge/wasmedge:${{ matrix.docker_tag }} steps: - name: Install dependencies + if: ${{ !matrix.release }} run: | apt-get update apt-get install -y pkg-config protobuf-compiler-grpc libgrpc-dev libgrpc++-dev + - name: Install dependencies + if: ${{ matrix.release }} + run: | + apt-get update + apt-get install -y pkg-config - uses: actions/checkout@v3 with: fetch-depth: 0 From 3abe6b7bc25a1588e21f3e9aba1fcb497d542608 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 23 Feb 2024 22:27:13 +0800 Subject: [PATCH 057/218] [CI] not matrix.release, it's release only Signed-off-by: hydai --- .github/workflows/reusable-build-on-ubuntu.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable-build-on-ubuntu.yml b/.github/workflows/reusable-build-on-ubuntu.yml index 2b5bec432bf6..fbbb1c32a6b0 100644 --- a/.github/workflows/reusable-build-on-ubuntu.yml +++ b/.github/workflows/reusable-build-on-ubuntu.yml @@ -26,13 +26,13 @@ jobs: BUILD_TESTS: OFF container: wasmedge/wasmedge:${{ matrix.docker_tag }} steps: - - name: Install dependencies - if: ${{ !matrix.release }} + - name: Install dependencies - non-release + if: ${{ !release }} run: | apt-get update apt-get install -y pkg-config protobuf-compiler-grpc libgrpc-dev libgrpc++-dev - - name: Install dependencies - if: ${{ matrix.release }} + - name: Install dependencies - release + if: ${{ release }} run: | apt-get update apt-get install -y pkg-config From bedba57b2183897ff6f6aed3f9cd3592288b1e98 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 23 Feb 2024 22:48:38 +0800 Subject: [PATCH 058/218] [CI] inherit from the input fields Signed-off-by: hydai --- .github/workflows/reusable-build-on-ubuntu.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-build-on-ubuntu.yml b/.github/workflows/reusable-build-on-ubuntu.yml index fbbb1c32a6b0..cd6f37a417a0 100644 --- a/.github/workflows/reusable-build-on-ubuntu.yml +++ b/.github/workflows/reusable-build-on-ubuntu.yml @@ -27,12 +27,12 @@ jobs: container: wasmedge/wasmedge:${{ matrix.docker_tag }} steps: - name: Install dependencies - non-release - if: ${{ !release }} + if: ${{ !inputs.release }} run: | apt-get update apt-get install -y pkg-config protobuf-compiler-grpc libgrpc-dev libgrpc++-dev - name: Install dependencies - release - if: ${{ release }} + if: ${{ inputs.release }} run: | apt-get update apt-get install -y pkg-config From 2e07973b16149bd938c2082f21d2588879c1efdf Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Wed, 21 Feb 2024 18:04:58 +0800 Subject: [PATCH 059/218] [Docker] Rename SHA256SUM file for manylinux2014 Signed-off-by: Yi Huang --- utils/docker/Dockerfile.manylinux2014_aarch64 | 4 ++-- utils/docker/Dockerfile.manylinux2014_x86_64 | 4 ++-- utils/docker/{SHA256SUM => SHA256SUM.manylinux2014} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename utils/docker/{SHA256SUM => SHA256SUM.manylinux2014} (100%) diff --git a/utils/docker/Dockerfile.manylinux2014_aarch64 b/utils/docker/Dockerfile.manylinux2014_aarch64 index 59ca239e828a..72c5a1a49f9f 100644 --- a/utils/docker/Dockerfile.manylinux2014_aarch64 +++ b/utils/docker/Dockerfile.manylinux2014_aarch64 @@ -5,7 +5,7 @@ FROM quay.io/pypa/manylinux2014_aarch64 MAINTAINER hydai hydai@secondstate.io -ADD SHA256SUM /root/ +ADD SHA256SUM.manylinux2014 /root/ ENV PATH /opt/rh/devtoolset-10/root/usr/bin${PATH:+:${PATH}} ENV MANPATH /opt/rh/devtoolset-10/root/usr/share/man${MANPATH:+:${MANPATH}} @@ -27,7 +27,7 @@ RUN cd && (yum check-update || true) && yum install -y xz openssl-devel rpm-buil https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.5/cmake-16.0.5.src.tar.xz \ https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.5/third-party-16.0.5.src.tar.xz \ https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.5/clang-16.0.5.src.tar.xz && \ - sha256sum -c SHA256SUM && \ + sha256sum -c SHA256SUM.manylinux2014 && \ gzip -dc zstd-1.5.5.tar.gz | tar -xf - && \ gzip -dc cmake-3.26.4.tar.gz | tar -xf - && \ gzip -dc v1.11.1.tar.gz | tar -xf - && \ diff --git a/utils/docker/Dockerfile.manylinux2014_x86_64 b/utils/docker/Dockerfile.manylinux2014_x86_64 index cc6a942a3a0f..9555dbbf4b7f 100644 --- a/utils/docker/Dockerfile.manylinux2014_x86_64 +++ b/utils/docker/Dockerfile.manylinux2014_x86_64 @@ -5,7 +5,7 @@ FROM quay.io/pypa/manylinux2014_x86_64 MAINTAINER hydai hydai@secondstate.io -ADD SHA256SUM /root/ +ADD SHA256SUM.manylinux2014 /root/ ENV PATH /opt/rh/devtoolset-11/root/usr/bin${PATH:+:${PATH}} ENV MANPATH /opt/rh/devtoolset-11/root/usr/share/man${MANPATH:+:${MANPATH}} @@ -27,7 +27,7 @@ RUN cd && (yum check-update || true) && yum install -y xz openssl-devel rpm-buil https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.5/cmake-16.0.5.src.tar.xz \ https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.5/third-party-16.0.5.src.tar.xz \ https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.5/clang-16.0.5.src.tar.xz && \ - sha256sum -c SHA256SUM && \ + sha256sum -c SHA256SUM.manylinux2014 && \ gzip -dc zstd-1.5.5.tar.gz | tar -xf - && \ gzip -dc cmake-3.26.4.tar.gz | tar -xf - && \ gzip -dc v1.11.1.tar.gz | tar -xf - && \ diff --git a/utils/docker/SHA256SUM b/utils/docker/SHA256SUM.manylinux2014 similarity index 100% rename from utils/docker/SHA256SUM rename to utils/docker/SHA256SUM.manylinux2014 From b29286d68ab2772057857b7fb574dbb6f0c33140 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 16 Feb 2024 18:48:54 +0800 Subject: [PATCH 060/218] [Docker] manylinux_2_28 (#3188) Signed-off-by: Yi Huang --- .github/workflows/docker.yml | 57 +++++++++++++++++++ ...ckerfile.manylinux_2_28-build-plugins-deps | 15 +++++ .../docker/Dockerfile.manylinux_2_28_aarch64 | 56 ++++++++++++++++++ utils/docker/Dockerfile.manylinux_2_28_x86_64 | 56 ++++++++++++++++++ utils/docker/SHA256SUM.manylinux_2_28 | 7 +++ 5 files changed, 191 insertions(+) create mode 100644 utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps create mode 100644 utils/docker/Dockerfile.manylinux_2_28_aarch64 create mode 100644 utils/docker/Dockerfile.manylinux_2_28_x86_64 create mode 100644 utils/docker/SHA256SUM.manylinux_2_28 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 53b76eee23c7..4e1ac1cc9ffe 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -251,3 +251,60 @@ jobs: org.opencontainers.image.version=${{ needs.prep.outputs.version }} org.opencontainers.image.created=${{ needs.prep.outputs.created }} org.opencontainers.image.revision=${{ github.sha }} + + build-manylinux_2_28_x86_64: + name: build-manylinux_2_28_x86_64 + runs-on: ubuntu-latest + needs: [prep] + container: + image: wasmedge/wasmedge:ci-image-base + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: "Rebuild wasmedge/wasmedge:manylinux_2_28_x86_64" + uses: docker/build-push-action@v5 + with: + build-args: BASE=quay.io/pypa/manylinux_2_28_x86_64 + context: ./utils/docker + file: utils/docker/Dockerfile.manylinux_2_28_x86_64 + platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ needs.prep.outputs.docker_image }}:manylinux_2_28_x86_64 + labels: | + org.opencontainers.image.title=${{ github.event.repository.name }} + org.opencontainers.image.description=${{ github.event.repository.description }} + org.opencontainers.image.url=${{ github.event.repository.html_url }} + org.opencontainers.image.source=${{ github.event.repository.clone_url }} + org.opencontainers.image.version=${{ needs.prep.outputs.version }} + org.opencontainers.image.created=${{ needs.prep.outputs.created }} + org.opencontainers.image.revision=${{ github.sha }} + + - name: "Rebuild wasmedge/wasmedge:manylinux_2_28_x86_64-plugins-deps" + uses: docker/build-push-action@v5 + with: + build-args: BASE=wasmedge/wasmedge:manylinux_2_28_x86_64 + context: ./utils/docker + file: utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps + platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ needs.prep.outputs.docker_image }}:manylinux_2_28_x86_64-plugins-deps + labels: | + org.opencontainers.image.title=${{ github.event.repository.name }} + org.opencontainers.image.description=${{ github.event.repository.description }} + org.opencontainers.image.url=${{ github.event.repository.html_url }} + org.opencontainers.image.source=${{ github.event.repository.clone_url }} + org.opencontainers.image.version=${{ needs.prep.outputs.version }} + org.opencontainers.image.created=${{ needs.prep.outputs.created }} + org.opencontainers.image.revision=${{ github.sha }} diff --git a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps new file mode 100644 index 000000000000..60b8a044bbcd --- /dev/null +++ b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps @@ -0,0 +1,15 @@ +ARG BASE=wasmedge/wasmedge:manylinux_2_28_x86_64 +FROM ${BASE} + +ENV PATH /opt/rh/gcc-toolset-13/root/usr/bin${PATH:+:${PATH}} +ENV MANPATH /opt/rh/gcc-toolset-13/root/usr/share/man${MANPATH:+:${MANPATH}} +ENV INFOPATH /opt/rh/gcc-toolset-13/root/usr/share/info${INFOPATH:+:${INFOPATH}} +ENV PKG_CONFIG_PATH /opt/rh/gcc-toolset-13/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} + +RUN cd && (yum check-update || true) && yum install -y wget unzip + +COPY install-opencvmini.sh . +ENV OPENCV_VERSION=4.8.0 +RUN [ "/bin/bash", "install-opencvmini.sh" ] + +RUN yum clean all diff --git a/utils/docker/Dockerfile.manylinux_2_28_aarch64 b/utils/docker/Dockerfile.manylinux_2_28_aarch64 new file mode 100644 index 000000000000..98dc2e368db8 --- /dev/null +++ b/utils/docker/Dockerfile.manylinux_2_28_aarch64 @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +FROM quay.io/pypa/manylinux_2_28_aarch64 + +MAINTAINER hydai hydai@secondstate.io + +ADD SHA256SUM.manylinux_2_28 /root/ + +ENV PATH /opt/rh/gcc-toolset-13/root/usr/bin${PATH:+:${PATH}} +ENV MANPATH /opt/rh/gcc-toolset-13/root/usr/share/man${MANPATH:+:${MANPATH}} +ENV INFOPATH /opt/rh/gcc-toolset-13/root/usr/share/info${INFOPATH:+:${INFOPATH}} +ENV PKG_CONFIG_PATH /opt/rh/gcc-toolset-13/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} + +RUN cd && (yum check-update || true) && yum install -y openssl-devel rpm-build cmake && \ + yum install -y gcc-toolset-13 && \ + export CPU=$(/opt/python/cp311-cp311/bin/python3 -c \ + 'import multiprocessing; print(multiprocessing.cpu_count())') && \ + export CFGFLAGS="--prefix=/opt/rh/gcc-toolset-13/root/usr --disable-shared --libdir=/opt/rh/gcc-toolset-13/root/usr/lib64" && \ + curl -s -L -O --remote-name-all \ + https://github.com/ninja-build/ninja/archive/refs/tags/v1.11.1.tar.gz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/llvm-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/lld-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/libunwind-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/cmake-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/third-party-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang-17.0.6.src.tar.xz && \ + sha256sum -c SHA256SUM.manylinux_2_28 && \ + gzip -dc v1.11.1.tar.gz | tar -xf - && \ + xz -dc llvm-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc lld-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc libunwind-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc cmake-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc third-party-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc clang-17.0.6.src.tar.xz | tar -xf - && \ + export ZSTDFLAGS=(PREFIX=/opt/rh/gcc-toolset-13/root/usr LIBDIR=/opt/rh/gcc-toolset-13/root/usr/lib64 SED_ERE_OPT=--regexp-extended MOREFLAGS="-std=c17 -O3 -fPIC -fPIE -fvisibility=hidden") && \ + mkdir build && cd build && /opt/python/cp311-cp311/bin/python \ + ../ninja-1.11.1/configure.py --bootstrap \ + --with-python=/opt/python/cp311-cp311/bin/python && \ + cp -v ninja /opt/rh/gcc-toolset-13/root/usr/bin/ninja && cd - && rm -rf build && \ + mv -v llvm-17.0.6.src llvm && \ + mv -v lld-17.0.6.src lld && \ + mv -v libunwind-17.0.6.src libunwind && \ + mv -v cmake-17.0.6.src cmake && \ + mv -v third-party-17.0.6.src third-party && \ + mv -v clang-17.0.6.src clang && \ + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/opt/rh/gcc-toolset-13/root/usr \ + -DPython3_ROOT_DIR=/opt/python/cp311-cp311 -DLLVM_LIBDIR_SUFFIX=64 \ + -DLLVM_TARGETS_TO_BUILD="AArch64;BPF" -DLLVM_ENABLE_PROJECTS="lld;clang" \ + -DLLVM_DEFAULT_TARGET_TRIPLE="aarch64-redhat-linux-gnu" \ + -DBUILD_SHARED_LIBS=OFF llvm && \ + cmake --build build --target install && \ + rm -rf build && rm -rf * + +RUN yum clean all diff --git a/utils/docker/Dockerfile.manylinux_2_28_x86_64 b/utils/docker/Dockerfile.manylinux_2_28_x86_64 new file mode 100644 index 000000000000..ba1fe2e9078d --- /dev/null +++ b/utils/docker/Dockerfile.manylinux_2_28_x86_64 @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +FROM quay.io/pypa/manylinux_2_28_x86_64 + +MAINTAINER hydai hydai@secondstate.io + +ADD SHA256SUM.manylinux_2_28 /root/ + +ENV PATH /opt/rh/gcc-toolset-13/root/usr/bin${PATH:+:${PATH}} +ENV MANPATH /opt/rh/gcc-toolset-13/root/usr/share/man${MANPATH:+:${MANPATH}} +ENV INFOPATH /opt/rh/gcc-toolset-13/root/usr/share/info${INFOPATH:+:${INFOPATH}} +ENV PKG_CONFIG_PATH /opt/rh/gcc-toolset-13/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} + +RUN cd && (yum check-update || true) && yum install -y openssl-devel rpm-build cmake && \ + yum install -y gcc-toolset-13 && \ + export CPU=$(/opt/python/cp311-cp311/bin/python3 -c \ + 'import multiprocessing; print(multiprocessing.cpu_count())') && \ + export CFGFLAGS="--prefix=/opt/rh/gcc-toolset-13/root/usr --disable-shared --libdir=/opt/rh/gcc-toolset-13/root/usr/lib64" && \ + curl -s -L -O --remote-name-all \ + https://github.com/ninja-build/ninja/archive/refs/tags/v1.11.1.tar.gz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/llvm-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/lld-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/libunwind-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/cmake-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/third-party-17.0.6.src.tar.xz \ + https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang-17.0.6.src.tar.xz && \ + sha256sum -c SHA256SUM.manylinux_2_28 && \ + gzip -dc v1.11.1.tar.gz | tar -xf - && \ + xz -dc llvm-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc lld-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc libunwind-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc cmake-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc third-party-17.0.6.src.tar.xz | tar -xf - && \ + xz -dc clang-17.0.6.src.tar.xz | tar -xf - && \ + export ZSTDFLAGS=(PREFIX=/opt/rh/gcc-toolset-13/root/usr LIBDIR=/opt/rh/gcc-toolset-13/root/usr/lib64 SED_ERE_OPT=--regexp-extended MOREFLAGS="-std=c17 -O3 -fPIC -fPIE -fvisibility=hidden") && \ + mkdir build && cd build && /opt/python/cp311-cp311/bin/python \ + ../ninja-1.11.1/configure.py --bootstrap \ + --with-python=/opt/python/cp311-cp311/bin/python && \ + cp -v ninja /opt/rh/gcc-toolset-13/root/usr/bin/ninja && cd - && rm -rf build && \ + mv -v llvm-17.0.6.src llvm && \ + mv -v lld-17.0.6.src lld && \ + mv -v libunwind-17.0.6.src libunwind && \ + mv -v cmake-17.0.6.src cmake && \ + mv -v third-party-17.0.6.src third-party && \ + mv -v clang-17.0.6.src clang && \ + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/opt/rh/gcc-toolset-13/root/usr \ + -DPython3_ROOT_DIR=/opt/python/cp311-cp311 -DLLVM_LIBDIR_SUFFIX=64 \ + -DLLVM_TARGETS_TO_BUILD="X86;BPF" -DLLVM_ENABLE_PROJECTS="lld;clang" \ + -DLLVM_DEFAULT_TARGET_TRIPLE="x86_64-pc-linux-gnu" \ + -DBUILD_SHARED_LIBS=OFF llvm && \ + cmake --build build --target install && \ + rm -rf build && rm -rf * + +RUN yum clean all diff --git a/utils/docker/SHA256SUM.manylinux_2_28 b/utils/docker/SHA256SUM.manylinux_2_28 new file mode 100644 index 000000000000..0b732009baad --- /dev/null +++ b/utils/docker/SHA256SUM.manylinux_2_28 @@ -0,0 +1,7 @@ +31747ae633213f1eda3842686f83c2aa1412e0f5691d1c14dbbcc67fe7400cea v1.11.1.tar.gz +a78f668a726ae1d3d9a7179996d97b12b90fb76ab9442a43110b972ff7ad9029 clang-17.0.6.src.tar.xz +807f069c54dc20cb47b21c1f6acafdd9c649f3ae015609040d6182cab01140f4 cmake-17.0.6.src.tar.xz +9e7535a353aa862730b4ba38df42e06f6856b40c4cc51b57f27b5046dc21d70d libunwind-17.0.6.src.tar.xz +4ac13125616dc44905b85820aa403d27ec1226329b7f674daeb5f5584c6f0b22 lld-17.0.6.src.tar.xz +b638167da139126ca11917b6880207cc6e8f9d1cbb1a48d87d017f697ef78188 llvm-17.0.6.src.tar.xz +3054d0a9c9375dab1a4539cc2cc45ab340341c5d71475f9599ba7752e222947b third-party-17.0.6.src.tar.xz From f169437a92cb28a7279083a5c188638d2cabf82c Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 27 Feb 2024 00:55:42 +0800 Subject: [PATCH 061/218] [Misc] Only build wasi_nn_rpc when WASMEDGE_BUILD_WASI_NN_RPC is ON (#3242) Signed-off-by: hydai --- .github/workflows/reusable-build-on-macos.yml | 8 ++++- CMakeLists.txt | 33 ++++++++++--------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/.github/workflows/reusable-build-on-macos.yml b/.github/workflows/reusable-build-on-macos.yml index 4131e50df42d..2009dd5dce16 100644 --- a/.github/workflows/reusable-build-on-macos.yml +++ b/.github/workflows/reusable-build-on-macos.yml @@ -32,10 +32,16 @@ jobs: - name: Ensure git safe directory run: | git config --global --add safe.directory $(pwd) - - name: Setup build environment + - name: Setup build environment - non-release + if: ${{ !inputs.release }} run: | eval $(/opt/homebrew/bin/brew shellenv) brew install llvm ninja cmake wabt grpc + - name: Setup build environment - release + if: ${{ inputs.release }} + run: | + eval $(/opt/homebrew/bin/brew shellenv) + brew install llvm ninja cmake wabt - name: Set environment variables for release if: ${{ inputs.release }} run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 040f01fe3753..b086de24959f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,22 +125,23 @@ if(WASMEDGE_BUILD_PLUGINS) endif() endif() -# * Homebrew: grpc -# * Debian, Ubuntu: libgrpc-dev, libgrpc++-dev -find_package(PkgConfig) -if(PkgConfig_FOUND) - pkg_check_modules(gRPCPP grpc++) -endif() -# Do not check find_package(gRPC), because libgrpc-dev for Ubuntu 22.04 does not contain cmake files. -# https://packages.ubuntu.com/search?keywords=libgrpc-dev -# Do not check find_package(protobuf), because libprotobuf-dev for Ubuntu does not contain cmake files. -# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1027876 -if(gRPCPP_FOUND AND WASMEDGE_BUILD_SHARED_LIB) - message(STATUS "Setting WASMEDGE_BUILD_WASI_NN_RPC to ON. If you see an error related to gRPC or protobuf, try setting this to OFF.") - set(WASMEDGE_BUILD_WASI_NN_RPC ON) -endif() -if(WASMEDGE_BUILD_WASI_NN_RPC AND NOT WASMEDGE_BUILD_SHARED_LIB) - message(FATAL_ERROR "WASMEDGE_BUILD_WASI_NN_RPC depends on WASMEDGE_BUILD_SHARED_LIB") +if(WASMEDGE_BUILD_WASI_NN_RPC) + # * Homebrew: grpc + # * Debian, Ubuntu: libgrpc-dev, libgrpc++-dev + find_package(PkgConfig) + if(PkgConfig_FOUND) + pkg_check_modules(gRPCPP grpc++) + endif() + # Do not check find_package(gRPC), because libgrpc-dev for Ubuntu 22.04 does not contain cmake files. + # https://packages.ubuntu.com/search?keywords=libgrpc-dev + # Do not check find_package(protobuf), because libprotobuf-dev for Ubuntu does not contain cmake files. + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1027876 + if(gRPCPP_FOUND AND WASMEDGE_BUILD_SHARED_LIB) + message(STATUS "If you see an error related to gRPC or protobuf, try setting WASMEDGE_BUILD_WASI_NN_RPC to OFF.") + endif() + if(WASMEDGE_BUILD_WASI_NN_RPC AND NOT WASMEDGE_BUILD_SHARED_LIB) + message(FATAL_ERROR "WASMEDGE_BUILD_WASI_NN_RPC depends on WASMEDGE_BUILD_SHARED_LIB") + endif() endif() set(WASMEDGE_BUILD_PACKAGE "DEB;RPM" CACHE STRING "Package generate types") From 3a76c82f5781e85721c84a4719b55794d816653d Mon Sep 17 00:00:00 2001 From: "Shen-Ta Hsieh(BestSteve)" Date: Tue, 27 Feb 2024 03:03:13 +0800 Subject: [PATCH 062/218] [AOT] Skip gc-types in function generator (#3244) Signed-off-by: Shen-Ta Hsieh --- lib/llvm/compiler.cpp | 198 +++++++++++++++++++++--------------------- 1 file changed, 100 insertions(+), 98 deletions(-) diff --git a/lib/llvm/compiler.cpp b/lib/llvm/compiler.cpp index 3c0ea1c590a2..8f5e5a341bba 100644 --- a/lib/llvm/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -5179,113 +5179,115 @@ void Compiler::compile(const AST::TypeSection &TypeSec) noexcept { if (Size == 0) { return; } - Context->FunctionTypes.reserve(SubTypes.size()); - Context->FunctionWrappers.reserve(SubTypes.size()); + Context->FunctionTypes.reserve(Size); + Context->FunctionWrappers.reserve(Size); // Iterate and compile types. - for (size_t I = 0; I < SubTypes.size(); ++I) { - // TODO: GC - AOT: implement other composite types. - if (!SubTypes[I].getCompositeType().isFunc()) { - spdlog::error("GC proposal not supported for AOT currently."); - return; - } - const auto &FuncType = SubTypes[I].getCompositeType().getFuncType(); - const auto Name = fmt::format("t{}"sv, Context->FunctionTypes.size()); - - // Check function type is unique - { - bool Unique = true; - for (size_t J = 0; J < I; ++J) { - const auto &OldFuncType = *Context->FunctionTypes[J]; - if (OldFuncType == FuncType) { - Unique = false; - Context->FunctionTypes.push_back(&OldFuncType); - auto F = Context->FunctionWrappers[J]; - Context->FunctionWrappers.push_back(F); - auto A = Context->LLModule.addAlias(WrapperTy, F, Name.c_str()); - A.setLinkage(LLVMExternalLinkage); - A.setVisibility(LLVMProtectedVisibility); - A.setDSOLocal(true); - A.setDLLStorageClass(LLVMDLLExportStorageClass); - break; + for (size_t I = 0; I < Size; ++I) { + if (SubTypes[I].getCompositeType().isFunc()) { + const auto &FuncType = SubTypes[I].getCompositeType().getFuncType(); + const auto Name = fmt::format("t{}"sv, Context->FunctionTypes.size()); + + // Check function type is unique + { + bool Unique = true; + for (size_t J = 0; J < I; ++J) { + if (const auto OldFuncType = Context->FunctionTypes[J]) { + if (*OldFuncType == FuncType) { + Unique = false; + Context->FunctionTypes.push_back(OldFuncType); + auto F = Context->FunctionWrappers[J]; + Context->FunctionWrappers.push_back(F); + auto A = Context->LLModule.addAlias(WrapperTy, F, Name.c_str()); + A.setLinkage(LLVMExternalLinkage); + A.setVisibility(LLVMProtectedVisibility); + A.setDSOLocal(true); + A.setDLLStorageClass(LLVMDLLExportStorageClass); + break; + } + } + } + if (!Unique) { + continue; } } - if (!Unique) { - continue; - } - } - - // Create Wrapper - auto F = Context->LLModule.addFunction(WrapperTy, LLVMExternalLinkage, - Name.c_str()); - { - F.setVisibility(LLVMProtectedVisibility); - F.setDSOLocal(true); - F.setDLLStorageClass(LLVMDLLExportStorageClass); - F.addFnAttr(Context->NoStackArgProbe); - F.addFnAttr(Context->StrictFP); - F.addFnAttr(Context->UWTable); - F.addParamAttr(0, Context->ReadOnly); - F.addParamAttr(0, Context->NoAlias); - F.addParamAttr(1, Context->NoAlias); - F.addParamAttr(2, Context->NoAlias); - F.addParamAttr(3, Context->NoAlias); - - LLVM::Builder Builder(Context->LLContext); - Builder.positionAtEnd( - LLVM::BasicBlock::create(Context->LLContext, F, "entry")); - auto FTy = - toLLVMType(Context->LLContext, Context->ExecCtxPtrTy, FuncType); - auto RTy = FTy.getReturnType(); - std::vector FPTy(FTy.getNumParams()); - FTy.getParamTypes(FPTy); - - const size_t ArgCount = FPTy.size() - 1; - const size_t RetCount = - RTy.isVoidTy() ? 0 - : (RTy.isStructTy() ? RTy.getStructNumElements() : 1); - auto ExecCtxPtr = F.getFirstParam(); - auto RawFunc = LLVM::FunctionCallee{ - FTy, - Builder.createBitCast(ExecCtxPtr.getNextParam(), FTy.getPointerTo())}; - auto RawArgs = ExecCtxPtr.getNextParam().getNextParam(); - auto RawRets = RawArgs.getNextParam(); - - std::vector Args; - Args.reserve(FTy.getNumParams()); - Args.push_back(ExecCtxPtr); - for (size_t J = 0; J < ArgCount; ++J) { - auto ArgTy = FPTy[J + 1]; - auto VPtr = Builder.createConstInBoundsGEP1_64(Context->Int8Ty, RawArgs, - J * kValSize); - auto Ptr = Builder.createBitCast(VPtr, ArgTy.getPointerTo()); - Args.push_back(Builder.createLoad(ArgTy, Ptr)); - } - - auto Ret = Builder.createCall(RawFunc, Args); - if (RTy.isVoidTy()) { - // nothing to do - } else if (RTy.isStructTy()) { - auto Rets = unpackStruct(Builder, Ret); - for (size_t J = 0; J < RetCount; ++J) { + // Create Wrapper + auto F = Context->LLModule.addFunction(WrapperTy, LLVMExternalLinkage, + Name.c_str()); + { + F.setVisibility(LLVMProtectedVisibility); + F.setDSOLocal(true); + F.setDLLStorageClass(LLVMDLLExportStorageClass); + F.addFnAttr(Context->NoStackArgProbe); + F.addFnAttr(Context->StrictFP); + F.addFnAttr(Context->UWTable); + F.addParamAttr(0, Context->ReadOnly); + F.addParamAttr(0, Context->NoAlias); + F.addParamAttr(1, Context->NoAlias); + F.addParamAttr(2, Context->NoAlias); + F.addParamAttr(3, Context->NoAlias); + + LLVM::Builder Builder(Context->LLContext); + Builder.positionAtEnd( + LLVM::BasicBlock::create(Context->LLContext, F, "entry")); + + auto FTy = + toLLVMType(Context->LLContext, Context->ExecCtxPtrTy, FuncType); + auto RTy = FTy.getReturnType(); + std::vector FPTy(FTy.getNumParams()); + FTy.getParamTypes(FPTy); + + const size_t ArgCount = FPTy.size() - 1; + const size_t RetCount = + RTy.isVoidTy() + ? 0 + : (RTy.isStructTy() ? RTy.getStructNumElements() : 1); + auto ExecCtxPtr = F.getFirstParam(); + auto RawFunc = LLVM::FunctionCallee{ + FTy, Builder.createBitCast(ExecCtxPtr.getNextParam(), + FTy.getPointerTo())}; + auto RawArgs = ExecCtxPtr.getNextParam().getNextParam(); + auto RawRets = RawArgs.getNextParam(); + + std::vector Args; + Args.reserve(FTy.getNumParams()); + Args.push_back(ExecCtxPtr); + for (size_t J = 0; J < ArgCount; ++J) { + auto ArgTy = FPTy[J + 1]; auto VPtr = Builder.createConstInBoundsGEP1_64(Context->Int8Ty, - RawRets, J * kValSize); - auto Ptr = - Builder.createBitCast(VPtr, Rets[J].getType().getPointerTo()); - Builder.createStore(Rets[J], Ptr); + RawArgs, J * kValSize); + auto Ptr = Builder.createBitCast(VPtr, ArgTy.getPointerTo()); + Args.push_back(Builder.createLoad(ArgTy, Ptr)); } - } else { - auto VPtr = - Builder.createConstInBoundsGEP1_64(Context->Int8Ty, RawRets, 0); - auto Ptr = Builder.createBitCast(VPtr, Ret.getType().getPointerTo()); - Builder.createStore(Ret, Ptr); + + auto Ret = Builder.createCall(RawFunc, Args); + if (RTy.isVoidTy()) { + // nothing to do + } else if (RTy.isStructTy()) { + auto Rets = unpackStruct(Builder, Ret); + for (size_t J = 0; J < RetCount; ++J) { + auto VPtr = Builder.createConstInBoundsGEP1_64( + Context->Int8Ty, RawRets, J * kValSize); + auto Ptr = + Builder.createBitCast(VPtr, Rets[J].getType().getPointerTo()); + Builder.createStore(Rets[J], Ptr); + } + } else { + auto VPtr = + Builder.createConstInBoundsGEP1_64(Context->Int8Ty, RawRets, 0); + auto Ptr = Builder.createBitCast(VPtr, Ret.getType().getPointerTo()); + Builder.createStore(Ret, Ptr); + } + Builder.createRetVoid(); } - Builder.createRetVoid(); + // Copy wrapper, param and return lists to module instance. + Context->FunctionTypes.push_back(&FuncType); + Context->FunctionWrappers.push_back(F); + } else { + Context->FunctionTypes.push_back(nullptr); + Context->FunctionWrappers.push_back(LLVM::Value()); } - // Copy wrapper, param and return lists to module instance. - Context->FunctionTypes.push_back(&FuncType); - Context->FunctionWrappers.push_back(F); } } From 76a3dacb44110f6dc2bb6d406a5ff445b3958a33 Mon Sep 17 00:00:00 2001 From: "LO, CHIN-HAO" <49036880+hankluo6@users.noreply.github.com> Date: Tue, 27 Feb 2024 00:59:06 -0600 Subject: [PATCH 063/218] [Installer] Remove macOS metadata during installation (#3243) Signed-off-by: hankluo6 --- utils/install.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/install.py b/utils/install.py index 921f51676bbe..7ea8581d8a9b 100644 --- a/utils/install.py +++ b/utils/install.py @@ -164,6 +164,9 @@ def extract_archive( for filename in files_extracted: fname = filename.replace(CONST_ipkg, ipath) + if "._" in filename: + remove(join(to_path, filename)) + continue # Skip if it ends with "wasmedge" as it is going to be removed at a later stage if fname.endswith("wasmedge") and not fname.endswith("bin/wasmedge"): continue @@ -1614,8 +1617,6 @@ def main(args): logging.info("Installing WasmEdge") # Copy the tree for sub_dir in listdir(join(TEMP_PATH, CONST_ipkg)): - if "._" in sub_dir: - continue if sub_dir == "lib64": copytree(join(TEMP_PATH, CONST_ipkg, sub_dir), join(args.path, "lib")) else: From 1c0254adcbda2beaf46f88cad88ab412f99229c9 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 27 Feb 2024 02:09:25 +0800 Subject: [PATCH 064/218] [CI] No longer trigger the file not found error in the installer workflows Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 3597adabb62b..cbbc02ad75e3 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -193,13 +193,13 @@ jobs: - name: Check for bashrc generation if: ${{ matrix.name != 'MacOS-arm64' }} run: | - rm ~/.bashrc + rm -f ~/.bashrc bash utils/install.sh -D if ls -a ~ | grep .bashrc; then echo "Fail: Bashrc found" && exit 1; else echo "Pass: Bashrc not found"; fi; - name: Check for bashrc generation if: ${{ matrix.name == 'MacOS-arm64' }} run: | - rm ~/.zshenv + rm -f ~/.zshenv bash utils/install.sh -D if ls -a ~ | grep .zshenv; then echo echo "Pass: zshenv found"; else "Fail: zshenv not found" && exit 1; fi; - name: Uninstall WasmEdge From daa28f66213b169b2d9d174da281c860b5993f4a Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 27 Feb 2024 02:25:24 +0800 Subject: [PATCH 065/218] [CI] Use zsh in the installer macos workflow Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 16 ++++++++++++++++ .../workflows/test-python-install-script.yml | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index cbbc02ad75e3..d48c85c0fa8e 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -185,49 +185,61 @@ jobs: fetch-depth: 0 - name: Install WasmEdge latest release + shell: zsh {0} run: | bash utils/install.sh -D - name: Uninstall WasmEdge + shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Check for bashrc generation + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | rm -f ~/.bashrc bash utils/install.sh -D if ls -a ~ | grep .bashrc; then echo "Fail: Bashrc found" && exit 1; else echo "Pass: Bashrc not found"; fi; - name: Check for bashrc generation + shell: zsh {0} if: ${{ matrix.name == 'MacOS-arm64' }} run: | rm -f ~/.zshenv bash utils/install.sh -D if ls -a ~ | grep .zshenv; then echo echo "Pass: zshenv found"; else "Fail: zshenv not found" && exit 1; fi; - name: Uninstall WasmEdge + shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge latest release with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -e all -D - name: Uninstall WasmEdge with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/uninstall.sh -q -V - name: Install deprecated WasmEdge specific release (0.10.0) + shell: zsh {0} run: | bash utils/install.sh -v 0.10.0 -D - name: Uninstall WasmEdge + shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge specific release (0.10.0) with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -e all -v 0.10.0 -D - name: Uninstall WasmEdge with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/uninstall.sh -q -V - name: Plugins Install check MacOS-x86 + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -v 0.10.0-alpha.1 @@ -243,6 +255,7 @@ jobs: # ls /usr/lib/wasmedge/ | grep libwasmedgePluginWasmEdgeProcess.dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) - name: Plugins Install check MacOS-arm64 + shell: zsh {0} if: ${{ matrix.name == 'MacOS-arm64' }} run: | bash utils/install.sh -v 0.13.1 --plugins wasmedge_tensorflow @@ -251,14 +264,17 @@ jobs: ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasmEdgeTensorflowLite.dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) - name: Tensorflow changes - libtensorflow_cc 2.6.0 will replace the old libtensorflow 2.6.0 + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -v 0.12.0-alpha.2 -e tensorflow --tf-version 0.12.0-alpha.2 --tf-deps-version 0.12.0-alpha.2 --tf-tools-version 0.12.0-alpha.2 ls ~/.wasmedge/lib/ | grep libtensorflow_cc* && echo "Pass: libtensorflow_cc found" || (echo "Fail: libtensorflow_cc found not found" && exit 1) - name: Uninstall WasmEdge + shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Latest Release Check + shell: zsh {0} run: | _res_git_=$(git ls-remote --refs --tags "https://github.com/WasmEdge/WasmEdge.git" | cut -d '/' -f 3 | awk '{ if ($1 ~ /-/) print; else print $0"_" ; }' | sort --version-sort | sed 's/_$//' | grep -e '^[0-9]\+.[0-9]\+.[0-9]\+$' | tail -1) _res_curl_=$(curl -w "%{url_effective}\n" -I -L -s -S https://github.com/WasmEdge/WasmEdge/releases/latest -o /dev/null | grep -Eo '[0-9]+.[0-9]+.[0-9]+') diff --git a/.github/workflows/test-python-install-script.yml b/.github/workflows/test-python-install-script.yml index 7b59f79437eb..60cd7c72be14 100644 --- a/.github/workflows/test-python-install-script.yml +++ b/.github/workflows/test-python-install-script.yml @@ -343,43 +343,54 @@ jobs: fetch-depth: 0 - name: Install python + shell: zsh {0} run: | eval $(/opt/homebrew/bin/brew shellenv) ${{ matrix.package_manager }} install python - name: Install WasmEdge latest release + shell: zsh {0} run: | python3 utils/install.py -D - name: Uninstall WasmEdge + shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge latest release with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | python3 utils/install.py -e all -D - name: Uninstall WasmEdge with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge specific release (0.10.0) + shell: zsh {0} run: | python3 utils/install.py -v 0.10.0 -D - name: Uninstall WasmEdge + shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge deprecated release (0.9.0) - Fails purposefully + shell: zsh {0} run: | python3 utils/install.py -v 0.9.0 -D 2>&1 | grep -q "Version not supported. Min Version: 0.10.0" && echo "Pass: Version not supported. Min Version: 0.10.0 found" \ || (echo "Failed: Version not supported. Min Version: 0.10.0 message not found" && exit 1) - name: Install WasmEdge specific release (0.10.0) with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | python3 utils/install.py -e all -v 0.10.0 -D - name: Uninstall WasmEdge with all extensions + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/uninstall.sh -q -V - name: Plugins Install check MacOS-x86 + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | python3 utils/install.py -v 0.10.0-alpha.1 @@ -397,6 +408,7 @@ jobs: # ls /usr/lib/wasmedge/ | grep libwasmedgePluginWasmEdgeProcess.dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) - name: Plugins Install check MacOS-arm64 + shell: zsh {0} if: ${{ matrix.name == 'MacOS-arm64' }} run: | python3 utils/install.py -v 0.13.1 --plugins wasmedge_tensorflow @@ -407,6 +419,7 @@ jobs: ls ~/.wasmedge/plugin/ | grep libwasmedge_rustls.dylib && echo "Pass: Plugins found" || (echo "Fail: Wasmedge Rustls Plugin not found" && exit 1) - name: Install multiple versions and Tensorflow extension/plugins for pre and post 0.13.x + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | python3 utils/install.py -e tensorflow -D 2>&1 -v 0.12.0 @@ -414,12 +427,14 @@ jobs: python3 utils/install.py --plugins wasmedge_tensorflow -D 2>&1 - name: Install multiple versions and Tensorflow extension/plugins for pre and post 0.13.x + shell: zsh {0} if: ${{ matrix.name == 'MacOS-arm64' }} run: | python3 utils/install.py --plugins wasmedge_tensorflow -D 2>&1 -v 0.13.1 python3 utils/install.py --plugins wasmedge_tensorflow -D 2>&1 - name: Install multiple versions and Image extension/plugins for pre and post 0.13.x + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | python3 utils/install.py -e image -D 2>&1 -v 0.12.0 @@ -427,18 +442,21 @@ jobs: python3 utils/install.py --plugins wasmedge_image -D 2>&1 - name: Install multiple versions and Image extension/plugins for pre and post 0.13.x + shell: zsh {0} if: ${{ matrix.name == 'MacOS-arm64' }} run: | python3 utils/install.py --plugins wasmedge_image -D 2>&1 -v 0.13.1 python3 utils/install.py --plugins wasmedge_image -D 2>&1 - name: Check for differences in the installation + shell: zsh {0} if: ${{ matrix.name == 'MacOS-arm64' }} run: | bash utils/installer_changes.sh $HOME/.wasmedge bash utils/installer_changes.sh $HOME/new_folder - name: Check for differences in the installation + shell: zsh {0} if: ${{ matrix.name != 'MacOS-arm64' }} run: | PYTHON_EXECUTABLE=python3 bash utils/installer_changes.sh "$HOME"/.wasmedge @@ -452,6 +470,7 @@ jobs: PYTHON_EXECUTABLE=python3 bash utils/installer_changes.sh /usr "-e all" "-v 0.12.1" - name: Latest Release Check + shell: zsh {0} run: | _res_git_=$(git ls-remote --refs --tags "https://github.com/WasmEdge/WasmEdge.git" | cut -d '/' -f 3 | awk '{ if ($1 ~ /-/) print; else print $0"_" ; }' | sort --version-sort | sed 's/_$//' | grep -e '^[0-9]\+.[0-9]\+.[0-9]\+$' | tail -1) _res_curl_=$(curl -w "%{url_effective}\n" -I -L -s -S https://github.com/WasmEdge/WasmEdge/releases/latest -o /dev/null | grep -Eo '[0-9]+.[0-9]+.[0-9]+') From 76a531ea4ed65ddcef07c541e55a71f2f600f241 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 27 Feb 2024 03:02:36 +0800 Subject: [PATCH 066/218] [CI] Fix linter issue in the install.py Signed-off-by: hydai --- utils/install.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/utils/install.py b/utils/install.py index 7ea8581d8a9b..99abf4421887 100644 --- a/utils/install.py +++ b/utils/install.py @@ -243,9 +243,13 @@ def _preprocess(self, v, separator, ignorecase): if ignorecase: v = v.lower() return [ - int(x) - if x.isdigit() - else [int(y) if y.isdigit() else y for y in re.findall("\d+|[a-zA-Z]+", x)] + ( + int(x) + if x.isdigit() + else [ + int(y) if y.isdigit() else y for y in re.findall("\d+|[a-zA-Z]+", x) + ] + ) for x in re.split(separator, v) ] From c7fd9882f10fcac38eb0ce2c5d0c71ee8e64f5a2 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 27 Feb 2024 03:10:02 +0800 Subject: [PATCH 067/218] [CI] Fix the wrong echo location Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index d48c85c0fa8e..35eb4ce00c27 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -205,7 +205,7 @@ jobs: run: | rm -f ~/.zshenv bash utils/install.sh -D - if ls -a ~ | grep .zshenv; then echo echo "Pass: zshenv found"; else "Fail: zshenv not found" && exit 1; fi; + if ls -a ~ | grep .zshenv; then echo "Pass: zshenv found"; else echo "Fail: zshenv not found" && exit 1; fi; - name: Uninstall WasmEdge shell: zsh {0} run: | From b0a64df59156a50cf063c17ffd8dc752b0bb4b41 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 27 Feb 2024 03:30:08 +0800 Subject: [PATCH 068/218] [CI] Separate the installer workflow between macOS amd64 and arm64 Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 97 +++++++++++++---------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 35eb4ce00c27..33109659f4b5 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -166,18 +166,9 @@ jobs: (echo "Fail: Fetched version does not equal GitHub Ref\nFetched:$_res_git_\nCI:$_res_curl_" && exit 1) - macos: - strategy: - matrix: - include: - - name: MacOS-latest - host_runner: macos-latest - package_manager: brew - - name: MacOS-arm64 - host_runner: macos-14 - package_manager: brew - name: ${{ matrix.name }} - runs-on: ${{ matrix.host_runner }} + macos_amd64: + name: macos-amd64 + runs-on: macos-latest steps: - uses: actions/checkout@v3 @@ -185,62 +176,38 @@ jobs: fetch-depth: 0 - name: Install WasmEdge latest release - shell: zsh {0} run: | bash utils/install.sh -D - name: Uninstall WasmEdge - shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Check for bashrc generation - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} run: | rm -f ~/.bashrc bash utils/install.sh -D if ls -a ~ | grep .bashrc; then echo "Fail: Bashrc found" && exit 1; else echo "Pass: Bashrc not found"; fi; - - name: Check for bashrc generation - shell: zsh {0} - if: ${{ matrix.name == 'MacOS-arm64' }} - run: | - rm -f ~/.zshenv - bash utils/install.sh -D - if ls -a ~ | grep .zshenv; then echo "Pass: zshenv found"; else echo "Fail: zshenv not found" && exit 1; fi; - name: Uninstall WasmEdge - shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge latest release with all extensions - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -e all -D - name: Uninstall WasmEdge with all extensions - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/uninstall.sh -q -V - name: Install deprecated WasmEdge specific release (0.10.0) - shell: zsh {0} run: | bash utils/install.sh -v 0.10.0 -D - name: Uninstall WasmEdge - shell: zsh {0} run: | bash utils/uninstall.sh -q -V - name: Install WasmEdge specific release (0.10.0) with all extensions - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -e all -v 0.10.0 -D - name: Uninstall WasmEdge with all extensions - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/uninstall.sh -q -V - name: Plugins Install check MacOS-x86 - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} run: | bash utils/install.sh -v 0.10.0-alpha.1 ls ~/.wasmedge/plugin/ | grep .dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) @@ -254,21 +221,65 @@ jobs: # bash utils/install.sh -v 0.10.0-alpha.1 -p /usr # ls /usr/lib/wasmedge/ | grep libwasmedgePluginWasmEdgeProcess.dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) + - name: Tensorflow changes - libtensorflow_cc 2.6.0 will replace the old libtensorflow 2.6.0 + run: | + bash utils/install.sh -v 0.12.0-alpha.2 -e tensorflow --tf-version 0.12.0-alpha.2 --tf-deps-version 0.12.0-alpha.2 --tf-tools-version 0.12.0-alpha.2 + ls ~/.wasmedge/lib/ | grep libtensorflow_cc* && echo "Pass: libtensorflow_cc found" || (echo "Fail: libtensorflow_cc found not found" && exit 1) + - name: Uninstall WasmEdge + run: | + bash utils/uninstall.sh -q -V + - name: Latest Release Check + run: | + _res_git_=$(git ls-remote --refs --tags "https://github.com/WasmEdge/WasmEdge.git" | cut -d '/' -f 3 | awk '{ if ($1 ~ /-/) print; else print $0"_" ; }' | sort --version-sort | sed 's/_$//' | grep -e '^[0-9]\+.[0-9]\+.[0-9]\+$' | tail -1) + _res_curl_=$(curl -w "%{url_effective}\n" -I -L -s -S https://github.com/WasmEdge/WasmEdge/releases/latest -o /dev/null | grep -Eo '[0-9]+.[0-9]+.[0-9]+') + [ "$_res_git_" = "$_res_curl_" ] && echo "Pass: Fetched version equals release" || + (echo "Fail: Fetched version does not equal GitHub Ref\nFetched:$_res_git_\nCI:$_res_curl_" && exit 1) + + macos-arm64: + name: macos-arm64 + runs-on: macos-14 + env: + SHELL: zsh + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install WasmEdge latest release + shell: zsh {0} + run: | + bash utils/install.sh -D + - name: Uninstall WasmEdge + shell: zsh {0} + run: | + bash utils/uninstall.sh -q -V + - name: Check for bashrc generation + shell: zsh {0} + run: | + rm -f ~/.zshenv + bash utils/install.sh -D + if ls -a ~ | grep .zshenv; then echo "Pass: zshenv found"; else echo "Fail: zshenv not found" && exit 1; fi; + - name: Uninstall WasmEdge + shell: zsh {0} + run: | + bash utils/uninstall.sh -q -V + - name: Install deprecated WasmEdge specific release (0.10.0) + shell: zsh {0} + run: | + bash utils/install.sh -v 0.10.0 -D + - name: Uninstall WasmEdge + shell: zsh {0} + run: | + bash utils/uninstall.sh -q -V - name: Plugins Install check MacOS-arm64 shell: zsh {0} - if: ${{ matrix.name == 'MacOS-arm64' }} run: | bash utils/install.sh -v 0.13.1 --plugins wasmedge_tensorflow ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasmEdgeTensorflow.dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) bash utils/install.sh -v 0.13.1 --plugins wasmedge_tensorflowlite ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasmEdgeTensorflowLite.dylib && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) - - name: Tensorflow changes - libtensorflow_cc 2.6.0 will replace the old libtensorflow 2.6.0 - shell: zsh {0} - if: ${{ matrix.name != 'MacOS-arm64' }} - run: | - bash utils/install.sh -v 0.12.0-alpha.2 -e tensorflow --tf-version 0.12.0-alpha.2 --tf-deps-version 0.12.0-alpha.2 --tf-tools-version 0.12.0-alpha.2 - ls ~/.wasmedge/lib/ | grep libtensorflow_cc* && echo "Pass: libtensorflow_cc found" || (echo "Fail: libtensorflow_cc found not found" && exit 1) - name: Uninstall WasmEdge shell: zsh {0} run: | From 7a78d84fb51841bc959594627d35244a7c84fc56 Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 29 Feb 2024 16:12:21 +0800 Subject: [PATCH 069/218] [WASI-NN] ggml: add inline base64 prompt support for llava Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 174 ++++++++++++++++++++++++++++++++------- 1 file changed, 144 insertions(+), 30 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 54209eec181e..89e8b7afcbe0 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -7,6 +7,7 @@ #ifdef WASMEDGE_PLUGIN_WASI_NN_BACKEND_GGML #include "simdjson.h" #include +#include #include #include #include @@ -417,7 +418,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, return ErrNo::Success; } -ErrNo EvaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, +ErrNo evaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, std::vector Tokens, int &NPast) noexcept { uint32_t NCtx = llama_n_ctx(LlamaContext); @@ -459,6 +460,93 @@ ErrNo EvaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, return ErrNo::Success; } +const std::string_view Base64ImageTagPrefix = ""; +const std::string_view PromptImagePlaceholder = ""; + +bool checkBase64Image(const std::string Prompt) noexcept { + // Check if the prompt contains a base64 image. + // Follow this link for the supported image formats: + // https://github.com/ggerganov/llama.cpp/blob/master/common/stb_image.h + + auto Base64ImageTagBeginPos = Prompt.find(Base64ImageTagPrefix); + if (Base64ImageTagBeginPos == std::string::npos) { + return false; + } + auto Base64ImageTagEndPos = + Prompt.find(Base64ImageTagSuffix, Base64ImageTagBeginPos); + if (Base64ImageTagEndPos == std::string::npos) { + return false; + } + return true; +} + +struct llava_image_embed * +loadBase64ImageFromPrompt(Graph &GraphRef, clip_ctx *ClipContext, + std::string Prompt) noexcept { + // Load the base64 image from the prompt. + // Follow this link for the supported image formats: + // https://github.com/ggerganov/llama.cpp/blob/master/common/stb_image.h + + // Find `` + auto Base64ImageTagEndPos = + Prompt.find(Base64ImageTagSuffix, Base64ImageBytesBeginPos); + if (Base64ImageTagEndPos == std::string::npos) { + return nullptr; + } + + auto Base64Str = + Prompt.substr(Base64ImageBytesBeginPos + Base64ImageBytesPrefix.size(), + Base64ImageTagEndPos - Base64ImageBytesBeginPos - + Base64ImageBytesPrefix.size()); + + // Decode the base64 image. + auto RequiredBytes = base64::required_encode_size(Base64Str.size()); + auto ImageBytes = std::vector(RequiredBytes); + base64::decode(Base64Str.begin(), Base64Str.end(), ImageBytes.begin()); + + return llava_image_embed_make_with_bytes( + ClipContext, GraphRef.Threads, ImageBytes.data(), ImageBytes.size()); +} + +ErrNo replaceBase64ImagePlaceholderInPrompt(std::string &Prompt) noexcept { + // Replace the base64 image in the prompt with a placeholder. + + // Find `` + auto Base64ImageTagEndPos = + Prompt.find(Base64ImageTagSuffix, Base64ImageTagBeginPos); + if (Base64ImageTagEndPos == std::string::npos) { + return ErrNo::InvalidArgument; + } + + auto Base64ImageTagLength = Base64ImageTagEndPos - Base64ImageTagBeginPos + + Base64ImageTagSuffix.size(); + Prompt.replace(Base64ImageTagBeginPos, Base64ImageTagLength, + PromptImagePlaceholder); + + return ErrNo::Success; +} + } // namespace details Expect load(WasiNNEnvironment &Env, Span> Builders, @@ -668,8 +756,8 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, spdlog::info("[WASI-NN][Debug] GGML backend: set the input"sv); } const bool AddBos = llama_should_add_bos_token(GraphRef.LlamaModel); - const std::string Prompt(reinterpret_cast(Tensor.Tensor.data()), - Tensor.Tensor.size()); + std::string Prompt(reinterpret_cast(Tensor.Tensor.data()), + Tensor.Tensor.size()); if (GraphRef.MMProjModelPath == ""sv) { // Text only prompt. CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); @@ -677,12 +765,18 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, } else { // Handle llava format prompt. + // Check if the prompt contains a base64 image. + bool ContainBase64Image = details::checkBase64Image(Prompt); + if (GraphRef.ImagePath == ""sv && ContainBase64Image == false) { + spdlog::error( + "[WASI-NN] GGML backend: Error: when using llava model, " + "you need to specify the image path or have the base64 encoded " + "image in the prompt."sv); + return ErrNo::InvalidArgument; + } + // Show some warnings. if (GraphRef.EnableLog) { - if (GraphRef.ImagePath == ""sv) { - spdlog::info( - "[WASI-NN] GGML backend: Image path is not set, will process as text-only prompt"sv); - } if (GraphRef.CtxSize < 4096) { spdlog::info( "[WASI-NN] GGML backend: Context size is {}, " @@ -692,17 +786,48 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, } } + // Load image for llava. + int LlavaVerbosity = 0; + if (GraphRef.EnableLog) { + LlavaVerbosity = 1; + } + auto ClipContext = + clip_model_load(GraphRef.MMProjModelPath.c_str(), LlavaVerbosity); + if (ContainBase64Image) { + // Load the base64 image from the prompt. + CxtRef.LlavaImageEmbd = + details::loadBase64ImageFromPrompt(GraphRef, ClipContext, Prompt); + // Replace the base64 image in the prompt with a placeholder. + auto Res = details::replaceBase64ImagePlaceholderInPrompt(Prompt); + if (Res != ErrNo::Success) { + spdlog::error( + "[WASI-NN] GGML backend: Error: unable to replace the base64 image in the prompt."sv); + clip_free(ClipContext); + return Res; + } + } else { + // Load the image from the file. + CxtRef.LlavaImageEmbd = llava_image_embed_make_with_filename( + ClipContext, GraphRef.Threads, GraphRef.ImagePath.c_str()); + } + clip_free(ClipContext); + if (CxtRef.LlavaImageEmbd == nullptr) { + spdlog::error( + "[WASI-NN] GGML backend: Error: unable to load the image {}."sv, + GraphRef.ImagePath); + return ErrNo::InvalidArgument; + } + // We split prompt by as placeholder and save the position. - const std::string_view PromptPlaceholder = ""; - auto PlaceholderPosition = Prompt.find(PromptPlaceholder); + auto PlaceholderPosition = Prompt.find(details::PromptImagePlaceholder); if (PlaceholderPosition == std::string::npos) { spdlog::error( "[WASI-NN] GGML backend: Error: unable to find the placeholder in the llava prompt."sv); return ErrNo::InvalidArgument; } std::string PromptBeforeImage = Prompt.substr(0, PlaceholderPosition); - std::string PromptAfterImage = - Prompt.substr(PlaceholderPosition + PromptPlaceholder.length()); + std::string PromptAfterImage = Prompt.substr( + PlaceholderPosition + details::PromptImagePlaceholder.length()); std::vector EmbdInputBeforeImage = llama_tokenize(LlamaContext, PromptBeforeImage, AddBos, true); std::vector EmbdInputAfterImage = @@ -716,17 +841,6 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, CxtRef.LlamaInputs.insert(CxtRef.LlamaInputs.end(), EmbdInputAfterImage.begin(), EmbdInputAfterImage.end()); - - // Load image for llava. - int LlavaVerbosity = 0; - if (GraphRef.EnableLog) { - LlavaVerbosity = 1; - } - auto ClipContext = - clip_model_load(GraphRef.MMProjModelPath.c_str(), LlavaVerbosity); - CxtRef.LlavaImageEmbd = llava_image_embed_make_with_filename( - ClipContext, GraphRef.Threads, GraphRef.ImagePath.c_str()); - clip_free(ClipContext); } if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: set the input...Done"sv); @@ -833,7 +947,7 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // Evaluate input tokens. if (CxtRef.LlavaImageEmbd == nullptr) { // Text only prompt. - ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, + ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, CxtRef.LlamaInputs, NPast); if (ReturnCode != ErrNo::Success) { spdlog::error( @@ -848,7 +962,7 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { std::vector EmbdInputAfterImage(CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition, CxtRef.LlamaInputs.end()); - ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, + ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, EmbdInputBeforeImage, NPast); if (ReturnCode != ErrNo::Success) { spdlog::error( @@ -862,7 +976,7 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { "[WASI-NN] GGML backend: failed to evaluate embed image tokens."sv); return ErrNo::RuntimeError; } - ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, + ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, EmbdInputAfterImage, NPast); if (ReturnCode != ErrNo::Success) { spdlog::error( @@ -905,7 +1019,7 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { break; } // Evaluate the output token. - ReturnCode = details::EvaluateTokens(GraphRef, LlamaContext, {Id}, NPast); + ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, {Id}, NPast); if (ReturnCode != ErrNo::Success) { break; } @@ -1018,7 +1132,7 @@ Expect computeSingle(WasiNNEnvironment &Env, // Evaluate input tokens. if (CxtRef.LlavaImageEmbd == nullptr) { // Text only prompt. - ReturnCode = details::EvaluateTokens( + ReturnCode = details::evaluateTokens( GraphRef, CxtRef.LlamaContext, CxtRef.LlamaInputs, CxtRef.LlamaNPast); if (ReturnCode != ErrNo::Success) { spdlog::error( @@ -1034,7 +1148,7 @@ Expect computeSingle(WasiNNEnvironment &Env, CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition, CxtRef.LlamaInputs.end()); ReturnCode = - details::EvaluateTokens(GraphRef, CxtRef.LlamaContext, + details::evaluateTokens(GraphRef, CxtRef.LlamaContext, EmbdInputBeforeImage, CxtRef.LlamaNPast); if (ReturnCode != ErrNo::Success) { spdlog::error( @@ -1050,7 +1164,7 @@ Expect computeSingle(WasiNNEnvironment &Env, return ErrNo::RuntimeError; } ReturnCode = - details::EvaluateTokens(GraphRef, CxtRef.LlamaContext, + details::evaluateTokens(GraphRef, CxtRef.LlamaContext, EmbdInputAfterImage, CxtRef.LlamaNPast); if (ReturnCode != ErrNo::Success) { spdlog::error( @@ -1083,7 +1197,7 @@ Expect computeSingle(WasiNNEnvironment &Env, } // Evaluate the output token if not EOS. if (ReturnCode != ErrNo::EndOfSequence) { - ReturnCode = details::EvaluateTokens(GraphRef, CxtRef.LlamaContext, {Id}, + ReturnCode = details::evaluateTokens(GraphRef, CxtRef.LlamaContext, {Id}, CxtRef.LlamaNPast); } if (GraphRef.EnableDebugLog) { From fc50e5d4433674bb3dd335861c60b3dafc19e63d Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 29 Feb 2024 16:30:35 +0800 Subject: [PATCH 070/218] [WASI-NN] ggml: bump llama.cpp b2294 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- thirdparty/ggml/ggml.patch | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index d65d2e06c447..4441271fc8bf 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2230 + GIT_TAG b2294 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) diff --git a/thirdparty/ggml/ggml.patch b/thirdparty/ggml/ggml.patch index 4368f3ed92c8..d1b369e24a13 100644 --- a/thirdparty/ggml/ggml.patch +++ b/thirdparty/ggml/ggml.patch @@ -59,9 +59,18 @@ index ef9e4ba7..a1b49793 100644 return new_clip; diff --git a/examples/llava/llava.cpp b/examples/llava/llava.cpp -index 1a1cf7c7..b84a9404 100644 +index 98012816..e8567d8f 100644 --- a/examples/llava/llava.cpp +++ b/examples/llava/llava.cpp +@@ -257,7 +257,7 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli + } + } + const int64_t t_img_enc_batch_us = ggml_time_us(); +- printf("%s: %d segments encoded in %8.2f ms\n", __func__, (int)img_res_v.size, (t_img_enc_batch_us - t_img_enc_start_us) / 1000.0); ++ // printf("%s: %d segments encoded in %8.2f ms\n", __func__, (int)img_res_v.size, (t_img_enc_batch_us - t_img_enc_start_us) / 1000.0); + + const int32_t * image_grid = clip_image_grid(ctx_clip); + @@ -290,12 +290,12 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli // clip_image_save_to_bmp(*tmp, "image_feature.bmp"); } @@ -90,10 +99,10 @@ index 2d40f3f1..8897b3d8 100644 #ifdef __cplusplus extern "C" { diff --git a/llama.cpp b/llama.cpp -index 4296eca3..5ac03032 100644 +index 30d5eb32..9c940162 100644 --- a/llama.cpp +++ b/llama.cpp -@@ -12757,7 +12757,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { +@@ -13266,7 +13266,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { static void llama_log_callback_default(ggml_log_level level, const char * text, void * user_data) { (void) level; From 0af2108a9067a6dd5d1aa5365ce5ff3d526aaa16 Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 29 Feb 2024 16:31:46 +0800 Subject: [PATCH 071/218] [WASI-NN] ggml: remove special ngl default value for macOS Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 89e8b7afcbe0..adc5d5cddbd7 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -566,10 +566,6 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, GraphRef.ImagePath = ""sv; // Initialize the model parameters. GraphRef.NGPULayers = 0; -#ifdef __APPLE__ - // We will always set the ngl to 1 on macOS to enable Metal. - GraphRef.NGPULayers = 1; -#endif // Initialize the context parameters. GraphRef.CtxSize = ContextDefault.n_ctx; GraphRef.BatchSize = ContextDefault.n_batch; From 40df809b9c1c324a0f051cfb4a1eff4a1521f56e Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 29 Feb 2024 21:14:57 +0800 Subject: [PATCH 072/218] [WASI-NN] ggml: minor fix, add more debug log Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index adc5d5cddbd7..f1a6787cb223 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -460,23 +460,31 @@ ErrNo evaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, return ErrNo::Success; } -const std::string_view Base64ImageTagPrefix = ""; -const std::string_view PromptImagePlaceholder = ""; +const std::string_view Base64ImageTagPrefix = ""sv; +const std::string_view PromptImagePlaceholder = ""sv; -bool checkBase64Image(const std::string Prompt) noexcept { +bool containsBase64Image(Graph &GraphRef, std::string Prompt) noexcept { // Check if the prompt contains a base64 image. // Follow this link for the supported image formats: // https://github.com/ggerganov/llama.cpp/blob/master/common/stb_image.h auto Base64ImageTagBeginPos = Prompt.find(Base64ImageTagPrefix); if (Base64ImageTagBeginPos == std::string::npos) { + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: No base64 image tag found in the prompt."sv); + } return false; } auto Base64ImageTagEndPos = Prompt.find(Base64ImageTagSuffix, Base64ImageTagBeginPos); if (Base64ImageTagEndPos == std::string::npos) { + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: Found an unclosed base64 image tag."sv); + } return false; } return true; @@ -762,8 +770,8 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, // Handle llava format prompt. // Check if the prompt contains a base64 image. - bool ContainBase64Image = details::checkBase64Image(Prompt); - if (GraphRef.ImagePath == ""sv && ContainBase64Image == false) { + bool ContainsBase64Image = details::containsBase64Image(GraphRef, Prompt); + if (GraphRef.ImagePath == ""sv && ContainsBase64Image == false) { spdlog::error( "[WASI-NN] GGML backend: Error: when using llava model, " "you need to specify the image path or have the base64 encoded " @@ -789,7 +797,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, } auto ClipContext = clip_model_load(GraphRef.MMProjModelPath.c_str(), LlavaVerbosity); - if (ContainBase64Image) { + if (ContainsBase64Image) { // Load the base64 image from the prompt. CxtRef.LlavaImageEmbd = details::loadBase64ImageFromPrompt(GraphRef, ClipContext, Prompt); From 863b99437da274f67529ec6006b367e239769f03 Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 29 Feb 2024 21:23:02 +0800 Subject: [PATCH 073/218] [WASI-NN] ggml: handle base64 decode error Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index f1a6787cb223..eee077970be0 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -525,7 +525,13 @@ loadBase64ImageFromPrompt(Graph &GraphRef, clip_ctx *ClipContext, // Decode the base64 image. auto RequiredBytes = base64::required_encode_size(Base64Str.size()); auto ImageBytes = std::vector(RequiredBytes); - base64::decode(Base64Str.begin(), Base64Str.end(), ImageBytes.begin()); + try { + base64::decode(Base64Str.begin(), Base64Str.end(), ImageBytes.begin()); + } catch (const base64_error &E) { + spdlog::error("[WASI-NN] GGML backend: Error when base64::decode: {}"sv, + E.what()); + return nullptr; + } return llava_image_embed_make_with_bytes( ClipContext, GraphRef.Threads, ImageBytes.data(), ImageBytes.size()); @@ -817,8 +823,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, clip_free(ClipContext); if (CxtRef.LlavaImageEmbd == nullptr) { spdlog::error( - "[WASI-NN] GGML backend: Error: unable to load the image {}."sv, - GraphRef.ImagePath); + "[WASI-NN] GGML backend: Error: unable to load the image."sv); return ErrNo::InvalidArgument; } From 6ed6617b649ed5e71661e396b8b97087ef39cc89 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 1 Mar 2024 13:52:53 +0800 Subject: [PATCH 074/218] [Installer] Support WasmEdge rustls plugin installation on aarch64 (#3249) Signed-off-by: hydai --- utils/install.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/install.py b/utils/install.py index 99abf4421887..716c9e213293 100644 --- a/utils/install.py +++ b/utils/install.py @@ -405,6 +405,7 @@ def compare(self, version2, separator=". |-", ignorecase=True): "darwin" + "arm64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), "manylinux2014" + "x86_64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), "ubuntu20.04" + "x86_64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), + "ubuntu20.04" + "aarch64" + WASMEDGE_RUSTLS: VersionString("0.13.5"), "ubuntu20.04" + "x86_64" + WASM_BPF: VersionString("0.13.2"), "manylinux2014" + "x86_64" + WASM_BPF: VersionString("0.13.2"), } From bcb9ec7834972ecd41e3e2a2959deba5a970065a Mon Sep 17 00:00:00 2001 From: hydai Date: Sun, 3 Mar 2024 22:09:58 +0800 Subject: [PATCH 075/218] [CI] Replace 'WASMEDGE_BUILD_AOT_RUNTIME' with 'WASMEDGE_USE_LLVM' (#3250) Signed-off-by: hydai --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/workflows/build-extensions.yml | 8 ++++---- .github/workflows/release.yml | 10 +++++----- .../reusable-build-extensions-on-manylinux.yml | 2 +- .github/workflows/wasi-testsuite.yml | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 0b45d8453b09..afbeaedaab5e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -100,6 +100,6 @@ body: placeholder: | - C++ Compiler version: - CMake version: - - CMake flags: (e.g. `-DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=ON`) + - CMake flags: (e.g. `-DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=ON`) validations: required: false diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index d8f15561b183..1677eba059d9 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -123,7 +123,7 @@ jobs: ldconfig plugin_array=(${tar_names}) option_array=(${build_options}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF for (( i=0; i<${#plugin_array[@]}; i++ )); do echo "Building ${plugin_array[$i]} backend:" @@ -221,7 +221,7 @@ jobs: update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 100 update-alternatives --install /usr/bin/llvm-strip llvm-strip /usr/bin/llvm-strip-15 100 testbin_array=(${test_bins}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} for (( i=0; i<${#testbin_array[@]}; i++ )); do echo "Building ${testbin_array[$i]} :" @@ -356,7 +356,7 @@ jobs: run: | source "$HOME/.cargo/env" testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.docker_tag }}}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.docker_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.docker_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl for (( i=0; i<${#testbin_array[@]}; i++ )); do echo "Building ${testbin_array[$i]} :" @@ -474,7 +474,7 @@ jobs: export LLVM_DIR="$(brew --prefix)/opt/llvm@16/lib/cmake" export CC=clang export CXX=clang++ - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl for (( i=0; i<${#testbin_array[@]}; i++ )); do echo "Building ${testbin_array[$i]} :" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0212e94ed3f1..a04c95ab3a97 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -157,7 +157,7 @@ jobs: option_array=(${build_options}) outtarget=${output_bin%.*} outtarget=${outtarget#lib} - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF for (( i=0; i<${#plugin_array[@]}; i++ )); do echo "Building ${plugin_array[$i]} backend:" @@ -230,7 +230,7 @@ jobs: shell: bash run: | outbin_array=(${output_bins}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} for (( i=0; i<${#outbin_array[@]}; i++ )); do echo "Building ${outbin_array[$i]} :" @@ -368,7 +368,7 @@ jobs: run: | source "$HOME/.cargo/env" outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.docker_tag }}}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.docker_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.docker_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl for (( i=0; i<${#outbin_array[@]}; i++ )); do echo "Building ${outbin_array[$i]} :" @@ -485,7 +485,7 @@ jobs: export LLVM_DIR="$(brew --prefix)/opt/llvm@16/lib/cmake" export CC=clang export CXX=clang++ - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl ${build_options} + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl ${build_options} for (( i=0; i<${#outbin_array[@]}; i++ )); do echo "Building ${outbin_array[$i]} :" @@ -569,7 +569,7 @@ jobs: git config --global --add safe.directory $(pwd) - name: Build runtime only manylinux2014 package run: | - bash utils/docker/build-manylinux.sh -DWASMEDGE_BUILD_AOT_RUNTIME=OFF + bash utils/docker/build-manylinux.sh -DWASMEDGE_USE_LLVM=OFF - name: Upload ${{ matrix.name }} tar.gz package to artifact uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index 12cb57ed80f7..423f683fa8a2 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -75,7 +75,7 @@ jobs: target=${target#lib} fi - cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_BUILD_AOT_RUNTIME=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl + cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl - uses: actions/cache/save@v3 with: key: ${{ steps.prep.outputs.cache_key1 }} diff --git a/.github/workflows/wasi-testsuite.yml b/.github/workflows/wasi-testsuite.yml index b92e3e8d4cd6..a718e4085222 100644 --- a/.github/workflows/wasi-testsuite.yml +++ b/.github/workflows/wasi-testsuite.yml @@ -44,7 +44,7 @@ jobs: working-directory: WasmEdge run: | sudo apt install -y software-properties-common cmake clang ninja-build - cmake -Bbuild -GNinja -DWASMEDGE_BUILD_AOT_RUNTIME=OFF . + cmake -Bbuild -GNinja -DWASMEDGE_USE_LLVM=OFF . cmake --build build echo "$GITHUB_WORKSPACE/WasmEdge/build/tools/wasmedge" >> $GITHUB_PATH @@ -56,7 +56,7 @@ jobs: export LLVM_DIR="/usr/local/opt/llvm/lib/cmake" export CC=clang export CXX=clang++ - cmake -Bbuild -GNinja -DWASMEDGE_BUILD_AOT_RUNTIME=OFF . + cmake -Bbuild -GNinja -DWASMEDGE_USE_LLVM=OFF . cmake --build build echo "$GITHUB_WORKSPACE/WasmEdge/build/tools/wasmedge" >> $GITHUB_PATH From b4646114b6bb941cd3131097d85506589a0c3fad Mon Sep 17 00:00:00 2001 From: hydai Date: Mon, 4 Mar 2024 18:21:37 +0800 Subject: [PATCH 076/218] [CI] Enable new arm64 runner (#3240) Signed-off-by: hydai --- .github/workflows/README.md | 2 +- .github/workflows/build-extensions.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/test-install-script.yml | 2 +- .github/workflows/test-python-install-script.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index e3be092b39da..d1ad924fcb16 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -38,7 +38,7 @@ flowchart LR "docker_tag": "manylinux2014_x86_64" }, { - "runner": "linux-arm64", + "runner": "linux-arm64-v2", "docker_tag": "manylinux2014_aarch64" } ] diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 1677eba059d9..536cab479eef 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -313,7 +313,7 @@ jobs: docker_tag: manylinux2014_x86_64-plugins-deps build_type: Release - name: Plugins_aarch64 - host_runner: linux-arm64 + host_runner: linux-arm64-v2 docker_tag: manylinux2014_aarch64-plugins-deps build_type: Release name: Plugins (${{ matrix.docker_tag }}, g++, ${{ matrix.build_type }}) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index abb87318214f..4bbb6e24d950 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -96,7 +96,7 @@ jobs: with: version: ${{ needs.get_version.outputs.version }} matrix: "[{'name':'manylinux 2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64'}, - {'name':'manylinux 2014 aarch64','runner':'linux-arm64','docker_tag':'manylinux2014_aarch64'}]" + {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" build_on_debian_static: needs: [get_version, lint] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a04c95ab3a97..1d3978457927 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,7 +74,7 @@ jobs: version: ${{ needs.create_release.outputs.version }} matrix: "[{'name':'manylinux 2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64'}, - {'name':'manylinux 2014 aarch64','runner':'linux-arm64','docker_tag':'manylinux2014_aarch64'}]" + {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" release: true secrets: inherit @@ -330,7 +330,7 @@ jobs: host_runner: ubuntu-latest docker_tag: manylinux2014_x86_64-plugins-deps - name: Plugins_aarch64 - host_runner: linux-arm64 + host_runner: linux-arm64-v2 docker_tag: manylinux2014_aarch64-plugins-deps name: Build and upload plugins on ${{ matrix.docker_tag }} runs-on: ${{ matrix.host_runner }} diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 33109659f4b5..8641f3d6329a 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -72,7 +72,7 @@ jobs: python3_ex: python3.7 extra_setup_command: apt update -y && apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget && wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz && tar xzf Python-3.7.4.tgz && cd Python-3.7.4 && ./configure && make -j && make install && cd .. - name: manylinux2014 aarch64 - host_runner: linux-arm64 + host_runner: linux-arm64-v2 package_manager: yum docker_image: wasmedge/wasmedge:manylinux2014_aarch64 python_package: python2 python3 diff --git a/.github/workflows/test-python-install-script.yml b/.github/workflows/test-python-install-script.yml index 60cd7c72be14..55f6b82b925d 100644 --- a/.github/workflows/test-python-install-script.yml +++ b/.github/workflows/test-python-install-script.yml @@ -86,7 +86,7 @@ jobs: python3_ex: python3.7 extra_setup_command: apt update -y && apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget && wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz && tar xzf Python-3.7.4.tgz && cd Python-3.7.4 && ./configure && make -j && make install && cd .. - name: manylinux2014 aarch64 - host_runner: linux-arm64 + host_runner: linux-arm64-v2 package_manager: yum docker_image: wasmedge/wasmedge:manylinux2014_aarch64 python_package: python2 python3 From 3ab97ac564819d65e9c7bb8ff61db5407f036ff2 Mon Sep 17 00:00:00 2001 From: hetvishastri <70652355+hetvishastri@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:27:04 -0500 Subject: [PATCH 077/218] [WASI] fixing inode_linux.cpp fromFileType error (#3247) Signed-off-by: hetvishastri --- lib/host/wasi/inode-linux.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/host/wasi/inode-linux.cpp b/lib/host/wasi/inode-linux.cpp index 8307465e62b1..27932936baa0 100644 --- a/lib/host/wasi/inode-linux.cpp +++ b/lib/host/wasi/inode-linux.cpp @@ -610,7 +610,7 @@ INode::pathFilestatGet(std::string Path, Filestat.dev = SysFStat.st_dev; Filestat.ino = SysFStat.st_ino; - Filestat.filetype = fromFileType(SysFStat.st_mode); + Filestat.filetype = fromFileType(static_cast(SysFStat.st_mode)); Filestat.nlink = SysFStat.st_nlink; Filestat.size = SysFStat.st_size; Filestat.atim = fromTimespec(SysFStat.st_atim); @@ -1371,7 +1371,7 @@ INode::sockGetPeerAddr(__wasi_address_family_t *AddressFamilyPtr, } __wasi_filetype_t INode::unsafeFiletype() const noexcept { - return fromFileType(Stat->st_mode); + return fromFileType(static_cast(Stat->st_mode)); } WasiExpect<__wasi_filetype_t> INode::filetype() const noexcept { From cd312d18cc8b8a2808effa3dedcd3e23db7c3495 Mon Sep 17 00:00:00 2001 From: tannal <149947508+tannal@users.noreply.github.com> Date: Tue, 5 Mar 2024 02:11:37 +0800 Subject: [PATCH 078/218] [WASI] fix lastpart special case in resolve path (#3246) Signed-off-by: tannal --- lib/host/wasi/vinode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/host/wasi/vinode.cpp b/lib/host/wasi/vinode.cpp index fe3fe70ed477..f112d525ee20 100644 --- a/lib/host/wasi/vinode.cpp +++ b/lib/host/wasi/vinode.cpp @@ -106,7 +106,7 @@ WasiExpect> VINode::bind(__wasi_rights_t FRB, WasiExpect VINode::pathCreateDirectory(std::shared_ptr Fd, std::string_view Path) { std::vector Buffer; - if (auto Res = resolvePath(Fd, Path); unlikely(!Res)) { + if (auto Res = resolvePath(Fd, Path, false); unlikely(!Res)) { return WasiUnexpect(Res); } else if (!Fd->can(__WASI_RIGHTS_PATH_CREATE_DIRECTORY)) { return WasiUnexpect(__WASI_ERRNO_NOTCAPABLE); From cc292ffdae936ae8fa62f32f818a7e0c8b86fafc Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 5 Mar 2024 12:12:31 +0800 Subject: [PATCH 079/218] [WASI-NN] ggml: bump to b2334 for supporting the starcoder2 model (#3254) Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 4441271fc8bf..86a48cefc764 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2294 + GIT_TAG b2334 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) From ef0d2a7d68f2866784ced720add3dfdaeefdc3cf Mon Sep 17 00:00:00 2001 From: Dhruv Jain <92215138+jaydee029@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:53:35 +0530 Subject: [PATCH 080/218] [CI] changing the workflow permissions hierarchy as per ossf docs (#3203) * changing permissions hierarchy as per ossf docs Signed-off-by: Dhruv Jain <92215138+jaydee029@users.noreply.github.com> * Update reusable-build-on-windows.yml Signed-off-by: Dhruv Jain <92215138+jaydee029@users.noreply.github.com> * added line spaces Signed-off-by: Dhruv Jain <92215138+jaydee029@users.noreply.github.com> * formatting added Signed-off-by: Dhruv Jain <92215138+jaydee029@users.noreply.github.com> --------- Signed-off-by: Dhruv Jain <92215138+jaydee029@users.noreply.github.com> --- .github/workflows/bindings-java.yml | 8 +++++- .github/workflows/build-extensions.yml | 16 ++++++++---- .github/workflows/build.yml | 26 +++++++++++++++---- .github/workflows/labeler.yml | 2 ++ .github/workflows/misc-linters.yml | 3 +++ .../reusable-build-on-alpine-static.yml | 5 +++- .../workflows/reusable-build-on-android.yml | 5 +++- .../workflows/reusable-build-on-fedora.yml | 5 +++- .github/workflows/reusable-build-on-macos.yml | 5 +++- .../workflows/reusable-build-on-manylinux.yml | 5 +++- .../workflows/reusable-build-on-ubuntu.yml | 5 +++- .../reusable-build-on-windows-msvc.yml | 5 +++- .github/workflows/reusable-call-linter.yml | 7 ++--- .../reusable-create-source-tarball.yml | 3 +++ .github/workflows/static-code-analysis.yml | 3 +++ .github/workflows/wasi-testsuite.yml | 3 +++ .github/workflows/winget-submit.yml | 4 ++- 17 files changed, 88 insertions(+), 22 deletions(-) diff --git a/.github/workflows/bindings-java.yml b/.github/workflows/bindings-java.yml index d69d992b3737..c4907d2714b7 100644 --- a/.github/workflows/bindings-java.yml +++ b/.github/workflows/bindings-java.yml @@ -23,10 +23,12 @@ on: - "lib/api/**" permissions: - contents: write + contents: read jobs: build_ubuntu: + permissions: + contents: write name: Ubuntu 22.04 runs-on: ${{ matrix.os }} strategy: @@ -83,6 +85,8 @@ jobs: bindings/java/wasmedge-java/build/libs/wasmedge-java-*.jar build_macos: + permissions: + contents: write name: MacOS runs-on: ${{ matrix.os }} strategy: @@ -145,6 +149,8 @@ jobs: bindings/java/wasmedge-java/build/libs/wasmedge-java-*.jar build_windows: + permissions: + contents: write name: Windows runs-on: windows-2022 env: diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 536cab479eef..20108a8f0a16 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -40,19 +40,15 @@ on: - "utils/wasi-crypto/**" permissions: - contents: write + contents: read jobs: # TODO: Refactor `lint` with `on.workflow_run` # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow lint: - permissions: - contents: read uses: ./.github/workflows/reusable-call-linter.yml get_version: - permissions: - contents: read name: Retrieve version information needs: lint runs-on: ubuntu-latest @@ -75,6 +71,8 @@ jobs: # Due to the dependencies and exclusions of WASI-NN, build them saperately. build_ubuntu_wasi_nn: + permissions: + contents: write strategy: matrix: include: @@ -176,6 +174,8 @@ jobs: path: plugin_wasi_nn-ggml.tar.gz build_ubuntu: + permissions: + contents: write strategy: matrix: include: @@ -298,6 +298,8 @@ jobs: # Due to the dependencies and exclusions of WASI-NN, build them saperately. build_wasinn_manylinux: + permissions: + contents: write name: WASI-NN (manylinux, g++, Release) needs: get_version uses: ./.github/workflows/reusable-build-extensions.yml @@ -305,6 +307,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_manylinux: + permissions: + contents: write strategy: matrix: include: @@ -433,6 +437,8 @@ jobs: path: plugin_wasmedge_zlib.tar.gz build_macos: + permissions: + contents: write strategy: matrix: include: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4bbb6e24d950..4b05b412021e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,19 +40,15 @@ on: - "cmake/**" permissions: - contents: write + contents: read jobs: # TODO: Refactor `lint` with `on.workflow_run` # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow lint: - permissions: - contents: read uses: ./.github/workflows/reusable-call-linter.yml get_version: - permissions: - contents: read needs: lint name: Retrieve version information runs-on: ubuntu-latest @@ -74,6 +70,8 @@ jobs: echo "version=$(git describe --match '[0-9].[0-9]*' --tag)" >> $GITHUB_OUTPUT create_source_tarball: + permissions: + contents: write needs: [get_version, lint] name: Source Tarball uses: ./.github/workflows/reusable-create-source-tarball.yml @@ -81,6 +79,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_on_macos: + permissions: + contents: write needs: [get_version, lint] name: macOS uses: ./.github/workflows/reusable-build-on-macos.yml @@ -90,6 +90,8 @@ jobs: {'name':'MacOS 13 (arm64)','runner':'macos-14','darwin_version':22,'arch':'arm64'}]" build_on_manylinux_2014: + permissions: + contents: write needs: [get_version, lint] name: Manylinux2014 uses: ./.github/workflows/reusable-build-on-manylinux.yml @@ -99,6 +101,8 @@ jobs: {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" build_on_debian_static: + permissions: + contents: write needs: [get_version, lint] name: Debian (static) uses: ./.github/workflows/reusable-build-on-debian-static.yml @@ -106,6 +110,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_on_alpine_static: + permissions: + contents: write needs: [get_version, lint] name: Alpine (static) uses: ./.github/workflows/reusable-build-on-alpine-static.yml @@ -113,6 +119,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_on_ubuntu_22_04: + permissions: + contents: write needs: [get_version, lint] name: Ubuntu uses: ./.github/workflows/reusable-build-on-ubuntu.yml @@ -126,6 +134,8 @@ jobs: {'name':'ubuntu-22.04-coverage','compiler':'g++','build_type':'Debug','docker_tag':'ubuntu-build-gcc','coverage':true,'tests':true}]" build_on_windows: + permissions: + contents: write needs: [get_version, lint] name: Windows uses: ./.github/workflows/reusable-build-on-windows.yml @@ -133,6 +143,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_on_windows_msvc: + permissions: + contents: write needs: [get_version, lint] name: Windows-MSVC uses: ./.github/workflows/reusable-build-on-windows-msvc.yml @@ -140,6 +152,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_on_android: + permissions: + contents: write needs: [get_version, lint] name: Android uses: ./.github/workflows/reusable-build-on-android.yml @@ -147,6 +161,8 @@ jobs: version: ${{ needs.get_version.outputs.version }} build_on_fedora: + permissions: + contents: write needs: [get_version, lint] name: Fedora uses: ./.github/workflows/reusable-build-on-fedora.yml diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index ba464c418003..e7a01df7f2cb 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -7,6 +7,8 @@ on: - reopened - closed +permissions: + contents: read jobs: labeler: permissions: diff --git a/.github/workflows/misc-linters.yml b/.github/workflows/misc-linters.yml index ff8dcf6e4623..a45ce285eb12 100644 --- a/.github/workflows/misc-linters.yml +++ b/.github/workflows/misc-linters.yml @@ -6,6 +6,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: misc: permissions: diff --git a/.github/workflows/reusable-build-on-alpine-static.yml b/.github/workflows/reusable-build-on-alpine-static.yml index a2d82e2224a9..17b0214cd963 100644 --- a/.github/workflows/reusable-build-on-alpine-static.yml +++ b/.github/workflows/reusable-build-on-alpine-static.yml @@ -8,7 +8,10 @@ on: required: true release: type: boolean - + +permissions: + contents: read + jobs: build_on_debian_static: permissions: diff --git a/.github/workflows/reusable-build-on-android.yml b/.github/workflows/reusable-build-on-android.yml index 4e9912389b1b..2c5544385cbb 100644 --- a/.github/workflows/reusable-build-on-android.yml +++ b/.github/workflows/reusable-build-on-android.yml @@ -10,7 +10,10 @@ on: type: boolean upload_asset_url: type: string - + +permissions: + contents: read + jobs: build_on_android: permissions: diff --git a/.github/workflows/reusable-build-on-fedora.yml b/.github/workflows/reusable-build-on-fedora.yml index 13e87fc1e7eb..b1b66bc1f219 100644 --- a/.github/workflows/reusable-build-on-fedora.yml +++ b/.github/workflows/reusable-build-on-fedora.yml @@ -10,7 +10,10 @@ on: type: boolean upload_asset_url: type: string - + +permissions: + contents: read + jobs: build_fedora: permissions: diff --git a/.github/workflows/reusable-build-on-macos.yml b/.github/workflows/reusable-build-on-macos.yml index 2009dd5dce16..4ddba4d9e119 100644 --- a/.github/workflows/reusable-build-on-macos.yml +++ b/.github/workflows/reusable-build-on-macos.yml @@ -11,7 +11,10 @@ on: required: true release: type: boolean - + +permissions: + contents: read + jobs: build_on_macos: permissions: diff --git a/.github/workflows/reusable-build-on-manylinux.yml b/.github/workflows/reusable-build-on-manylinux.yml index f74a5086a0d3..dada9ac53af9 100644 --- a/.github/workflows/reusable-build-on-manylinux.yml +++ b/.github/workflows/reusable-build-on-manylinux.yml @@ -11,7 +11,10 @@ on: required: true release: type: boolean - + +permissions: + contents: read + jobs: build_on_manylinux: permissions: diff --git a/.github/workflows/reusable-build-on-ubuntu.yml b/.github/workflows/reusable-build-on-ubuntu.yml index cd6f37a417a0..aeee6beeb88a 100644 --- a/.github/workflows/reusable-build-on-ubuntu.yml +++ b/.github/workflows/reusable-build-on-ubuntu.yml @@ -11,7 +11,10 @@ on: required: true release: type: boolean - + +permissions: + contents: read + jobs: build_on_ubuntu: permissions: diff --git a/.github/workflows/reusable-build-on-windows-msvc.yml b/.github/workflows/reusable-build-on-windows-msvc.yml index 2ed200295c1b..41d09b8b7c92 100644 --- a/.github/workflows/reusable-build-on-windows-msvc.yml +++ b/.github/workflows/reusable-build-on-windows-msvc.yml @@ -8,7 +8,10 @@ on: required: true release: type: boolean - + +permissions: + contents: read + jobs: build_on_windows: permissions: diff --git a/.github/workflows/reusable-call-linter.yml b/.github/workflows/reusable-call-linter.yml index de94d8a288b2..2eb54de5b0ea 100644 --- a/.github/workflows/reusable-call-linter.yml +++ b/.github/workflows/reusable-call-linter.yml @@ -2,11 +2,12 @@ name: Clang-Format on: workflow_call: - + +permissions: + contents: read + jobs: lint: - permissions: - contents: read runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/reusable-create-source-tarball.yml b/.github/workflows/reusable-create-source-tarball.yml index d415ad412156..ed8c26d44fdb 100644 --- a/.github/workflows/reusable-create-source-tarball.yml +++ b/.github/workflows/reusable-create-source-tarball.yml @@ -9,6 +9,9 @@ on: release: type: boolean +permissions: + contents: read + jobs: create_source_tarball: permissions: diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml index 2ebfeecd9870..d4fd3039a811 100644 --- a/.github/workflows/static-code-analysis.yml +++ b/.github/workflows/static-code-analysis.yml @@ -39,6 +39,9 @@ on: - "CMakeLists.txt" - "cmake/**" +permissions: + contents: read + jobs: static_analysis: permissions: diff --git a/.github/workflows/wasi-testsuite.yml b/.github/workflows/wasi-testsuite.yml index a718e4085222..b846d35ed55a 100644 --- a/.github/workflows/wasi-testsuite.yml +++ b/.github/workflows/wasi-testsuite.yml @@ -22,6 +22,9 @@ on: - "include/host/wasi/**" - "thirdparty/wasi/**" +permissions: + contents: read + jobs: test: permissions: diff --git a/.github/workflows/winget-submit.yml b/.github/workflows/winget-submit.yml index 842ae4dbcaa7..92a16c4b54b1 100644 --- a/.github/workflows/winget-submit.yml +++ b/.github/workflows/winget-submit.yml @@ -5,10 +5,12 @@ on: release: types: [published] +permissions: + contents: read + jobs: winget: permissions: - contents: read packages: write name: Publish WinGet Package runs-on: windows-latest From a4cdee64fc82f0af0017982547ac496249cf0532 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Tue, 5 Mar 2024 16:29:51 +0800 Subject: [PATCH 081/218] [Executor] Fix independent host function invocation. (#3255) Signed-off-by: YiYing He --- lib/executor/executor.cpp | 10 ++++++++-- test/api/APIUnitTest.cpp | 13 +++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/executor/executor.cpp b/lib/executor/executor.cpp index b212eeb20823..8f15d5bb3c59 100644 --- a/lib/executor/executor.cpp +++ b/lib/executor/executor.cpp @@ -85,8 +85,14 @@ Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst, const auto &FuncType = FuncInst->getFuncType(); const auto &PTypes = FuncType.getParamTypes(); const auto &RTypes = FuncType.getReturnTypes(); - if (!AST::TypeMatcher::matchTypes(FuncInst->getModule()->getTypeList(), - ParamTypes, PTypes)) { + // The defined type list may be empty if the function is an independent + // function instance, that is, the module instance will be nullptr. For this + // case, all of value types are number types or abstract heap types. + WasmEdge::Span TypeList = {}; + if (FuncInst->getModule()) { + TypeList = FuncInst->getModule()->getTypeList(); + } + if (!AST::TypeMatcher::matchTypes(TypeList, ParamTypes, PTypes)) { spdlog::error(ErrCode::Value::FuncSigMismatch); spdlog::error(ErrInfo::InfoMismatch( PTypes, RTypes, std::vector(ParamTypes.begin(), ParamTypes.end()), diff --git a/test/api/APIUnitTest.cpp b/test/api/APIUnitTest.cpp index fd933d8da0d0..35ebebeaf4f6 100644 --- a/test/api/APIUnitTest.cpp +++ b/test/api/APIUnitTest.cpp @@ -1691,6 +1691,19 @@ TEST(APICoreTest, ExecutorWithStatistics) { isErrMatch(WasmEdge_ErrCategory_UserLevelError, 0x5678U, WasmEdge_ExecutorInvoke(ExecCxt, FuncCxt, nullptr, 0, R, 1))); + // Invoke independent host functions + // host function "func-add": {externref, i32} -> {i32} + WasmEdge_ValType Result[1] = {WasmEdge_ValTypeGenI32()}; + WasmEdge_FunctionTypeContext *FuncType = + WasmEdge_FunctionTypeCreate(nullptr, 0, Result, 1); + FuncCxt = WasmEdge_FunctionInstanceCreate(FuncType, ExternTerm, nullptr, 0); + WasmEdge_FunctionTypeDelete(FuncType); + EXPECT_NE(FuncCxt, nullptr); + EXPECT_TRUE(WasmEdge_ResultOK( + WasmEdge_ExecutorInvoke(ExecCxt, FuncCxt, nullptr, 0, R, 1))); + WasmEdge_FunctionInstanceDelete(FuncCxt); + EXPECT_TRUE(true); + // Statistics get instruction count EXPECT_GT(WasmEdge_StatisticsGetInstrCount(Stat), 0ULL); EXPECT_EQ(WasmEdge_StatisticsGetInstrCount(nullptr), 0ULL); From dd3265f33a109f05b4b57a620b917afae8a4bba2 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 5 Mar 2024 15:25:48 +0800 Subject: [PATCH 082/218] [CI] Fix the wrong asset names Signed-off-by: hydai --- .github/workflows/build-extensions.yml | 32 +++++++++++--------- .github/workflows/release.yml | 42 ++++++++++++++------------ 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 20108a8f0a16..a498924804b1 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -315,10 +315,12 @@ jobs: - name: Plugins_x86_64 host_runner: ubuntu-latest docker_tag: manylinux2014_x86_64-plugins-deps + asset_tag: manylinux2014_x86_64 build_type: Release - name: Plugins_aarch64 host_runner: linux-arm64-v2 docker_tag: manylinux2014_aarch64-plugins-deps + asset_tag: manylinux2014_aarch64 build_type: Release name: Plugins (${{ matrix.docker_tag }}, g++, ${{ matrix.build_type }}) runs-on: ${{ matrix.host_runner }} @@ -359,8 +361,8 @@ jobs: shell: bash run: | source "$HOME/.cargo/env" - testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.docker_tag }}}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.docker_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl + testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.asset_tag }}}) + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.asset_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl for (( i=0; i<${#testbin_array[@]}; i++ )); do echo "Building ${testbin_array[$i]} :" @@ -369,8 +371,8 @@ jobs: - name: Test plugins shell: bash run: | - plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.docker_tag }}}) - testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.docker_tag }}}) + plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) + testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.asset_tag }}}) for (( i=0; i<${#plugin_array[@]}; i++ )); do echo "Testing ${plugin_array[$i]} :" @@ -381,8 +383,8 @@ jobs: - name: Prepare the WasmEdge plugins tar.gz package shell: bash run: | - plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.docker_tag }}}) - outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.docker_tag }}}) + plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) + outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) for (( i=0; i<${#plugin_array[@]}; i++ )); do echo "Copying ${plugin_array[$i]} :" @@ -392,48 +394,48 @@ jobs: - name: Upload artifact - wasi_crypto uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasi_crypto-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasi_crypto-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasi_crypto.tar.gz - name: Upload artifact - wasi_logging uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasi_logging-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasi_logging-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasi_logging.tar.gz - name: Upload artifact - wasmedge_process uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasmedge_process-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasmedge_process-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_process.tar.gz - name: Upload artifact - wasmedge_tensorflow uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasmedge_tensorflow-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasmedge_tensorflow-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_tensorflow.tar.gz - name: Upload artifact - wasmedge_tensorflowlite uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_tensorflowlite.tar.gz - name: Upload artifact - wasmedge_image uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasmedge_image-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasmedge_image-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_image.tar.gz - name: Upload artifact - wasm_bpf if: contains(matrix.docker_tag, 'manylinux2014_x86_64') uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasm_bpf-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasm_bpf-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasm_bpf.tar.gz - name: Upload artifact - wasmedge_opencvmini uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasmedge_opencvmini-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasmedge_opencvmini-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_opencvmini.tar.gz - name: Upload artifact - wasmedge_zlib uses: actions/upload-artifact@v3 with: - name: WasmEdge-plugin-wasmedge_zlib-${{ needs.get_version.outputs.version }}-${{ matrix.docker_tag }}.tar.gz + name: WasmEdge-plugin-wasmedge_zlib-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_zlib.tar.gz build_macos: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d3978457927..1105a8e174b0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -329,9 +329,11 @@ jobs: - name: Plugins_x86_64 host_runner: ubuntu-latest docker_tag: manylinux2014_x86_64-plugins-deps + asset_tag: manylinux2014_x86_64 - name: Plugins_aarch64 host_runner: linux-arm64-v2 docker_tag: manylinux2014_aarch64-plugins-deps + asset_tag: manylinux2014_aarch64 name: Build and upload plugins on ${{ matrix.docker_tag }} runs-on: ${{ matrix.host_runner }} env: @@ -367,8 +369,8 @@ jobs: shell: bash run: | source "$HOME/.cargo/env" - outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.docker_tag }}}) - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.docker_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl + outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) + cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.asset_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl for (( i=0; i<${#outbin_array[@]}; i++ )); do echo "Building ${outbin_array[$i]} :" @@ -380,8 +382,8 @@ jobs: - name: Prepare the plugins tar.gz package shell: bash run: | - plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.docker_tag }}}) - outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.docker_tag }}}) + plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) + outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) for (( i=0; i<${#plugin_array[@]}; i++ )); do echo "Copying ${plugin_array[$i]} :" @@ -397,51 +399,51 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasi_crypto.tar.gz WasmEdge-plugin-wasi_crypto-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasi_crypto-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasi_crypto.tar.gz WasmEdge-plugin-wasi_crypto-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasi_crypto-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasi_logging plugin tar.gz package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasi_logging.tar.gz WasmEdge-plugin-wasi_logging-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasi_logging-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasi_logging.tar.gz WasmEdge-plugin-wasi_logging-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasi_logging-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasmedge_process plugin tar.gz package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasmedge_process.tar.gz WasmEdge-plugin-wasmedge_process-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_process-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasmedge_process.tar.gz WasmEdge-plugin-wasmedge_process-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_process-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasmedge_tensorflow plugin tar.gz package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasmedge_tensorflow.tar.gz WasmEdge-plugin-wasmedge_tensorflow-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_tensorflow-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasmedge_tensorflow.tar.gz WasmEdge-plugin-wasmedge_tensorflow-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_tensorflow-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasmedge_tensorflowlite plugin tar.gz package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasmedge_tensorflowlite.tar.gz WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasmedge_tensorflowlite.tar.gz WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasmedge_image plugin tar.gz package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasmedge_image.tar.gz WasmEdge-plugin-wasmedge_image-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_image-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasmedge_image.tar.gz WasmEdge-plugin-wasmedge_image-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_image-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasm_bpf plugin tar.gz package if: contains(matrix.docker_tag, 'manylinux2014_x86_64') env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasm_bpf.tar.gz WasmEdge-plugin-wasm_bpf-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasm_bpf-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasm_bpf.tar.gz WasmEdge-plugin-wasm_bpf-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasm_bpf-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - name: Upload wasmedge_opencvmini plugin tar.gz package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mv plugin_wasmedge_opencvmini.tar.gz WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.docker_tag }}.tar.gz --clobber + mv plugin_wasmedge_opencvmini.tar.gz WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber build_and_upload_plugin_macos: strategy: From 2af604c1e07b0a7706ea79ad44233d19f6dfe968 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 5 Mar 2024 16:42:40 +0800 Subject: [PATCH 083/218] [CI] Support asset_tag in expend-variables Signed-off-by: hydai --- .../actions/expand-variables/dist/index.js | 1815 +++++++++++------ .github/actions/expand-variables/main.js | 2 + .github/workflows/release.yml | 4 +- ...reusable-build-extensions-on-manylinux.yml | 5 +- .../workflows/reusable-build-extensions.yml | 1 + 5 files changed, 1146 insertions(+), 681 deletions(-) diff --git a/.github/actions/expand-variables/dist/index.js b/.github/actions/expand-variables/dist/index.js index f39cb0b80874..f2260c8e3ad0 100644 --- a/.github/actions/expand-variables/dist/index.js +++ b/.github/actions/expand-variables/dist/index.js @@ -1,7 +1,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 5183: +/***/ 3651: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -28,7 +28,7 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; const os = __importStar(__nccwpck_require__(2037)); -const utils_1 = __nccwpck_require__(8091); +const utils_1 = __nccwpck_require__(1324); /** * Commands * @@ -100,7 +100,7 @@ function escapeProperty(s) { /***/ }), -/***/ 2619: +/***/ 4136: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -135,12 +135,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(5183); -const file_command_1 = __nccwpck_require__(5939); -const utils_1 = __nccwpck_require__(8091); +const command_1 = __nccwpck_require__(3651); +const file_command_1 = __nccwpck_require__(2533); +const utils_1 = __nccwpck_require__(1324); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); -const oidc_utils_1 = __nccwpck_require__(3669); +const oidc_utils_1 = __nccwpck_require__(6354); /** * The code to exit an action */ @@ -425,17 +425,17 @@ exports.getIDToken = getIDToken; /** * Summary exports */ -var summary_1 = __nccwpck_require__(4992); +var summary_1 = __nccwpck_require__(6817); Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); /** * @deprecated use core.summary */ -var summary_2 = __nccwpck_require__(4992); +var summary_2 = __nccwpck_require__(6817); Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); /** * Path exports */ -var path_utils_1 = __nccwpck_require__(6067); +var path_utils_1 = __nccwpck_require__(8040); Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); @@ -443,7 +443,7 @@ Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: funct /***/ }), -/***/ 5939: +/***/ 2533: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -474,8 +474,8 @@ exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); -const uuid_1 = __nccwpck_require__(8860); -const utils_1 = __nccwpck_require__(8091); +const uuid_1 = __nccwpck_require__(2228); +const utils_1 = __nccwpck_require__(1324); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { @@ -508,7 +508,7 @@ exports.prepareKeyValueMessage = prepareKeyValueMessage; /***/ }), -/***/ 3669: +/***/ 6354: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -524,9 +524,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(429); -const auth_1 = __nccwpck_require__(1535); -const core_1 = __nccwpck_require__(2619); +const http_client_1 = __nccwpck_require__(5957); +const auth_1 = __nccwpck_require__(1410); +const core_1 = __nccwpck_require__(4136); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -592,7 +592,7 @@ exports.OidcClient = OidcClient; /***/ }), -/***/ 6067: +/***/ 8040: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -657,7 +657,7 @@ exports.toPlatformPath = toPlatformPath; /***/ }), -/***/ 4992: +/***/ 6817: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -947,7 +947,7 @@ exports.summary = _summary; /***/ }), -/***/ 8091: +/***/ 1324: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -994,7 +994,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 1535: +/***/ 1410: /***/ (function(__unused_webpack_module, exports) { "use strict"; @@ -1082,7 +1082,7 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 429: +/***/ 5957: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1124,9 +1124,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; const http = __importStar(__nccwpck_require__(3685)); const https = __importStar(__nccwpck_require__(5687)); -const pm = __importStar(__nccwpck_require__(5957)); -const tunnel = __importStar(__nccwpck_require__(6237)); -const undici_1 = __nccwpck_require__(5116); +const pm = __importStar(__nccwpck_require__(1456)); +const tunnel = __importStar(__nccwpck_require__(796)); +const undici_1 = __nccwpck_require__(2606); var HttpCodes; (function (HttpCodes) { HttpCodes[HttpCodes["OK"] = 200] = "OK"; @@ -1745,7 +1745,7 @@ const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCa /***/ }), -/***/ 5957: +/***/ 1456: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -1834,15 +1834,15 @@ function isLoopbackAddress(host) { /***/ }), -/***/ 6237: +/***/ 796: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(2576); +module.exports = __nccwpck_require__(6891); /***/ }), -/***/ 2576: +/***/ 6891: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2114,31 +2114,32 @@ exports.debug = debug; // for test /***/ }), -/***/ 5116: +/***/ 2606: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Client = __nccwpck_require__(8224) -const Dispatcher = __nccwpck_require__(1312) -const errors = __nccwpck_require__(5767) -const Pool = __nccwpck_require__(9729) -const BalancedPool = __nccwpck_require__(8580) -const Agent = __nccwpck_require__(8162) -const util = __nccwpck_require__(6223) +const Client = __nccwpck_require__(4256) +const Dispatcher = __nccwpck_require__(7978) +const errors = __nccwpck_require__(51) +const Pool = __nccwpck_require__(135) +const BalancedPool = __nccwpck_require__(1438) +const Agent = __nccwpck_require__(2438) +const util = __nccwpck_require__(2014) const { InvalidArgumentError } = errors -const api = __nccwpck_require__(4596) -const buildConnector = __nccwpck_require__(3311) -const MockClient = __nccwpck_require__(624) -const MockAgent = __nccwpck_require__(8180) -const MockPool = __nccwpck_require__(3429) -const mockErrors = __nccwpck_require__(463) -const ProxyAgent = __nccwpck_require__(2498) -const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(398) -const DecoratorHandler = __nccwpck_require__(3978) -const RedirectHandler = __nccwpck_require__(1962) -const createRedirectInterceptor = __nccwpck_require__(9095) +const api = __nccwpck_require__(4908) +const buildConnector = __nccwpck_require__(5599) +const MockClient = __nccwpck_require__(4927) +const MockAgent = __nccwpck_require__(3667) +const MockPool = __nccwpck_require__(9726) +const mockErrors = __nccwpck_require__(2106) +const ProxyAgent = __nccwpck_require__(6524) +const RetryHandler = __nccwpck_require__(5112) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(6223) +const DecoratorHandler = __nccwpck_require__(1509) +const RedirectHandler = __nccwpck_require__(7144) +const createRedirectInterceptor = __nccwpck_require__(6789) let hasCrypto try { @@ -2156,6 +2157,7 @@ module.exports.Pool = Pool module.exports.BalancedPool = BalancedPool module.exports.Agent = Agent module.exports.ProxyAgent = ProxyAgent +module.exports.RetryHandler = RetryHandler module.exports.DecoratorHandler = DecoratorHandler module.exports.RedirectHandler = RedirectHandler @@ -2220,7 +2222,7 @@ if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { let fetchImpl = null module.exports.fetch = async function fetch (resource) { if (!fetchImpl) { - fetchImpl = (__nccwpck_require__(3360).fetch) + fetchImpl = (__nccwpck_require__(3246).fetch) } try { @@ -2233,20 +2235,20 @@ if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { throw err } } - module.exports.Headers = __nccwpck_require__(7967).Headers - module.exports.Response = __nccwpck_require__(1570).Response - module.exports.Request = __nccwpck_require__(8619).Request - module.exports.FormData = __nccwpck_require__(4595).FormData - module.exports.File = __nccwpck_require__(9072).File - module.exports.FileReader = __nccwpck_require__(7784).FileReader + module.exports.Headers = __nccwpck_require__(3767).Headers + module.exports.Response = __nccwpck_require__(6476).Response + module.exports.Request = __nccwpck_require__(6814).Request + module.exports.FormData = __nccwpck_require__(4089).FormData + module.exports.File = __nccwpck_require__(8731).File + module.exports.FileReader = __nccwpck_require__(7689).FileReader - const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(4428) + const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(4612) module.exports.setGlobalOrigin = setGlobalOrigin module.exports.getGlobalOrigin = getGlobalOrigin - const { CacheStorage } = __nccwpck_require__(6723) - const { kConstruct } = __nccwpck_require__(4063) + const { CacheStorage } = __nccwpck_require__(5420) + const { kConstruct } = __nccwpck_require__(1837) // Cache & CacheStorage are tightly coupled with fetch. Even if it may run // in an older version of Node, it doesn't have any use without fetch. @@ -2254,21 +2256,21 @@ if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { } if (util.nodeMajor >= 16) { - const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(30) + const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(2739) module.exports.deleteCookie = deleteCookie module.exports.getCookies = getCookies module.exports.getSetCookies = getSetCookies module.exports.setCookie = setCookie - const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6822) + const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(834) module.exports.parseMIMEType = parseMIMEType module.exports.serializeAMimeType = serializeAMimeType } if (util.nodeMajor >= 18 && hasCrypto) { - const { WebSocket } = __nccwpck_require__(6624) + const { WebSocket } = __nccwpck_require__(1917) module.exports.WebSocket = WebSocket } @@ -2287,20 +2289,20 @@ module.exports.mockErrors = mockErrors /***/ }), -/***/ 8162: +/***/ 2438: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { InvalidArgumentError } = __nccwpck_require__(5767) -const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(1439) -const DispatcherBase = __nccwpck_require__(8188) -const Pool = __nccwpck_require__(9729) -const Client = __nccwpck_require__(8224) -const util = __nccwpck_require__(6223) -const createRedirectInterceptor = __nccwpck_require__(9095) -const { WeakRef, FinalizationRegistry } = __nccwpck_require__(7905)() +const { InvalidArgumentError } = __nccwpck_require__(51) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(7460) +const DispatcherBase = __nccwpck_require__(854) +const Pool = __nccwpck_require__(135) +const Client = __nccwpck_require__(4256) +const util = __nccwpck_require__(2014) +const createRedirectInterceptor = __nccwpck_require__(6789) +const { WeakRef, FinalizationRegistry } = __nccwpck_require__(4142)() const kOnConnect = Symbol('onConnect') const kOnDisconnect = Symbol('onDisconnect') @@ -2443,11 +2445,11 @@ module.exports = Agent /***/ }), -/***/ 1306: +/***/ 9670: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const { addAbortListener } = __nccwpck_require__(6223) -const { RequestAbortedError } = __nccwpck_require__(5767) +const { addAbortListener } = __nccwpck_require__(2014) +const { RequestAbortedError } = __nccwpck_require__(51) const kListener = Symbol('kListener') const kSignal = Symbol('kSignal') @@ -2504,16 +2506,16 @@ module.exports = { /***/ }), -/***/ 2414: +/***/ 9725: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { AsyncResource } = __nccwpck_require__(852) -const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(5767) -const util = __nccwpck_require__(6223) -const { addSignal, removeSignal } = __nccwpck_require__(1306) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(51) +const util = __nccwpck_require__(2014) +const { addSignal, removeSignal } = __nccwpck_require__(9670) class ConnectHandler extends AsyncResource { constructor (opts, callback) { @@ -2616,7 +2618,7 @@ module.exports = connect /***/ }), -/***/ 7576: +/***/ 6346: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -2631,10 +2633,10 @@ const { InvalidArgumentError, InvalidReturnValueError, RequestAbortedError -} = __nccwpck_require__(5767) -const util = __nccwpck_require__(6223) +} = __nccwpck_require__(51) +const util = __nccwpck_require__(2014) const { AsyncResource } = __nccwpck_require__(852) -const { addSignal, removeSignal } = __nccwpck_require__(1306) +const { addSignal, removeSignal } = __nccwpck_require__(9670) const assert = __nccwpck_require__(9491) const kResume = Symbol('resume') @@ -2873,21 +2875,21 @@ module.exports = pipeline /***/ }), -/***/ 233: +/***/ 3055: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Readable = __nccwpck_require__(425) +const Readable = __nccwpck_require__(7767) const { InvalidArgumentError, RequestAbortedError -} = __nccwpck_require__(5767) -const util = __nccwpck_require__(6223) -const { getResolveErrorBodyCallback } = __nccwpck_require__(4726) +} = __nccwpck_require__(51) +const util = __nccwpck_require__(2014) +const { getResolveErrorBodyCallback } = __nccwpck_require__(2588) const { AsyncResource } = __nccwpck_require__(852) -const { addSignal, removeSignal } = __nccwpck_require__(1306) +const { addSignal, removeSignal } = __nccwpck_require__(9670) class RequestHandler extends AsyncResource { constructor (opts, callback) { @@ -3056,11 +3058,12 @@ function request (opts, callback) { } module.exports = request +module.exports.RequestHandler = RequestHandler /***/ }), -/***/ 5401: +/***/ 2275: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -3071,11 +3074,11 @@ const { InvalidArgumentError, InvalidReturnValueError, RequestAbortedError -} = __nccwpck_require__(5767) -const util = __nccwpck_require__(6223) -const { getResolveErrorBodyCallback } = __nccwpck_require__(4726) +} = __nccwpck_require__(51) +const util = __nccwpck_require__(2014) +const { getResolveErrorBodyCallback } = __nccwpck_require__(2588) const { AsyncResource } = __nccwpck_require__(852) -const { addSignal, removeSignal } = __nccwpck_require__(1306) +const { addSignal, removeSignal } = __nccwpck_require__(9670) class StreamHandler extends AsyncResource { constructor (opts, factory, callback) { @@ -3288,16 +3291,16 @@ module.exports = stream /***/ }), -/***/ 1771: +/***/ 4348: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(5767) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(51) const { AsyncResource } = __nccwpck_require__(852) -const util = __nccwpck_require__(6223) -const { addSignal, removeSignal } = __nccwpck_require__(1306) +const util = __nccwpck_require__(2014) +const { addSignal, removeSignal } = __nccwpck_require__(9670) const assert = __nccwpck_require__(9491) class UpgradeHandler extends AsyncResource { @@ -3401,22 +3404,22 @@ module.exports = upgrade /***/ }), -/***/ 4596: +/***/ 4908: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -module.exports.request = __nccwpck_require__(233) -module.exports.stream = __nccwpck_require__(5401) -module.exports.pipeline = __nccwpck_require__(7576) -module.exports.upgrade = __nccwpck_require__(1771) -module.exports.connect = __nccwpck_require__(2414) +module.exports.request = __nccwpck_require__(3055) +module.exports.stream = __nccwpck_require__(2275) +module.exports.pipeline = __nccwpck_require__(6346) +module.exports.upgrade = __nccwpck_require__(4348) +module.exports.connect = __nccwpck_require__(9725) /***/ }), -/***/ 425: +/***/ 7767: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -3426,9 +3429,9 @@ module.exports.connect = __nccwpck_require__(2414) const assert = __nccwpck_require__(9491) const { Readable } = __nccwpck_require__(2781) -const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(5767) -const util = __nccwpck_require__(6223) -const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(6223) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(51) +const util = __nccwpck_require__(2014) +const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(2014) let Blob @@ -3438,6 +3441,8 @@ const kBody = Symbol('kBody') const kAbort = Symbol('abort') const kContentType = Symbol('kContentType') +const noop = () => {} + module.exports = class BodyReadable extends Readable { constructor ({ resume, @@ -3571,37 +3576,50 @@ module.exports = class BodyReadable extends Readable { return this[kBody] } - async dump (opts) { + dump (opts) { let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144 const signal = opts && opts.signal - const abortFn = () => { - this.destroy() - } - let signalListenerCleanup + if (signal) { - if (typeof signal !== 'object' || !('aborted' in signal)) { - throw new InvalidArgumentError('signal must be an AbortSignal') - } - util.throwIfAborted(signal) - signalListenerCleanup = util.addAbortListener(signal, abortFn) - } - try { - for await (const chunk of this) { - util.throwIfAborted(signal) - limit -= Buffer.byteLength(chunk) - if (limit < 0) { - return + try { + if (typeof signal !== 'object' || !('aborted' in signal)) { + throw new InvalidArgumentError('signal must be an AbortSignal') } + util.throwIfAborted(signal) + } catch (err) { + return Promise.reject(err) } - } catch { - util.throwIfAborted(signal) - } finally { - if (typeof signalListenerCleanup === 'function') { - signalListenerCleanup() - } else if (signalListenerCleanup) { - signalListenerCleanup[Symbol.dispose]() - } } + + if (this.closed) { + return Promise.resolve(null) + } + + return new Promise((resolve, reject) => { + const signalListenerCleanup = signal + ? util.addAbortListener(signal, () => { + this.destroy() + }) + : noop + + this + .on('close', function () { + signalListenerCleanup() + if (signal && signal.aborted) { + reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) + } else { + resolve(null) + } + }) + .on('error', noop) + .on('data', function (chunk) { + limit -= chunk.length + if (limit <= 0) { + this.destroy() + } + }) + .resume() + }) } } @@ -3731,14 +3749,14 @@ function consumeFinish (consume, err) { /***/ }), -/***/ 4726: +/***/ 2588: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const assert = __nccwpck_require__(9491) const { ResponseStatusCodeError -} = __nccwpck_require__(5767) -const { toUSVString } = __nccwpck_require__(6223) +} = __nccwpck_require__(51) +const { toUSVString } = __nccwpck_require__(2014) async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { assert(body) @@ -3784,7 +3802,7 @@ module.exports = { getResolveErrorBodyCallback } /***/ }), -/***/ 8580: +/***/ 1438: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -3793,7 +3811,7 @@ module.exports = { getResolveErrorBodyCallback } const { BalancedPoolMissingUpstreamError, InvalidArgumentError -} = __nccwpck_require__(5767) +} = __nccwpck_require__(51) const { PoolBase, kClients, @@ -3801,10 +3819,10 @@ const { kAddClient, kRemoveClient, kGetDispatcher -} = __nccwpck_require__(1273) -const Pool = __nccwpck_require__(9729) -const { kUrl, kInterceptors } = __nccwpck_require__(1439) -const { parseOrigin } = __nccwpck_require__(6223) +} = __nccwpck_require__(334) +const Pool = __nccwpck_require__(135) +const { kUrl, kInterceptors } = __nccwpck_require__(7460) +const { parseOrigin } = __nccwpck_require__(2014) const kFactory = Symbol('factory') const kOptions = Symbol('options') @@ -3982,24 +4000,24 @@ module.exports = BalancedPool /***/ }), -/***/ 7011: +/***/ 4482: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kConstruct } = __nccwpck_require__(4063) -const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(8265) -const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(6223) -const { kHeadersList } = __nccwpck_require__(1439) -const { webidl } = __nccwpck_require__(5337) -const { Response, cloneResponse } = __nccwpck_require__(1570) -const { Request } = __nccwpck_require__(8619) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(1048) -const { fetching } = __nccwpck_require__(3360) -const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(6913) +const { kConstruct } = __nccwpck_require__(1837) +const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(9212) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(2014) +const { kHeadersList } = __nccwpck_require__(7460) +const { webidl } = __nccwpck_require__(8184) +const { Response, cloneResponse } = __nccwpck_require__(6476) +const { Request } = __nccwpck_require__(6814) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(4030) +const { fetching } = __nccwpck_require__(3246) +const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(9567) const assert = __nccwpck_require__(9491) -const { getGlobalDispatcher } = __nccwpck_require__(398) +const { getGlobalDispatcher } = __nccwpck_require__(6223) /** * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation @@ -4828,16 +4846,16 @@ module.exports = { /***/ }), -/***/ 6723: +/***/ 5420: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kConstruct } = __nccwpck_require__(4063) -const { Cache } = __nccwpck_require__(7011) -const { webidl } = __nccwpck_require__(5337) -const { kEnumerableProperty } = __nccwpck_require__(6223) +const { kConstruct } = __nccwpck_require__(1837) +const { Cache } = __nccwpck_require__(4482) +const { webidl } = __nccwpck_require__(8184) +const { kEnumerableProperty } = __nccwpck_require__(2014) class CacheStorage { /** @@ -4980,28 +4998,28 @@ module.exports = { /***/ }), -/***/ 4063: -/***/ ((module) => { +/***/ 1837: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; module.exports = { - kConstruct: Symbol('constructable') + kConstruct: (__nccwpck_require__(7460).kConstruct) } /***/ }), -/***/ 8265: +/***/ 9212: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const assert = __nccwpck_require__(9491) -const { URLSerializer } = __nccwpck_require__(6822) -const { isValidHeaderName } = __nccwpck_require__(6913) +const { URLSerializer } = __nccwpck_require__(834) +const { isValidHeaderName } = __nccwpck_require__(9567) /** * @see https://url.spec.whatwg.org/#concept-url-equals @@ -5050,7 +5068,7 @@ module.exports = { /***/ }), -/***/ 8224: +/***/ 4256: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -5064,10 +5082,10 @@ const assert = __nccwpck_require__(9491) const net = __nccwpck_require__(1808) const http = __nccwpck_require__(3685) const { pipeline } = __nccwpck_require__(2781) -const util = __nccwpck_require__(6223) -const timers = __nccwpck_require__(8581) -const Request = __nccwpck_require__(1562) -const DispatcherBase = __nccwpck_require__(8188) +const util = __nccwpck_require__(2014) +const timers = __nccwpck_require__(1518) +const Request = __nccwpck_require__(8751) +const DispatcherBase = __nccwpck_require__(854) const { RequestContentLengthMismatchError, ResponseContentLengthMismatchError, @@ -5081,8 +5099,8 @@ const { HTTPParserError, ResponseExceededMaxSizeError, ClientDestroyedError -} = __nccwpck_require__(5767) -const buildConnector = __nccwpck_require__(3311) +} = __nccwpck_require__(51) +const buildConnector = __nccwpck_require__(5599) const { kUrl, kReset, @@ -5134,7 +5152,7 @@ const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest -} = __nccwpck_require__(1439) +} = __nccwpck_require__(7460) /** @type {import('http2')} */ let http2 @@ -5540,16 +5558,16 @@ function onHTTP2GoAway (code) { resume(client) } -const constants = __nccwpck_require__(6744) -const createRedirectInterceptor = __nccwpck_require__(9095) +const constants = __nccwpck_require__(3626) +const createRedirectInterceptor = __nccwpck_require__(6789) const EMPTY_BUF = Buffer.alloc(0) async function lazyllhttp () { - const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(7445) : undefined + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(1931) : undefined let mod try { - mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(6442), 'base64')) + mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(271), 'base64')) } catch (e) { /* istanbul ignore next */ @@ -5557,7 +5575,7 @@ async function lazyllhttp () { // being enabled, but the occurring of this other error // * https://github.com/emscripten-core/emscripten/issues/11495 // got me to remove that check to avoid breaking Node 12. - mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(7445), 'base64')) + mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(1931), 'base64')) } return await WebAssembly.instantiate(mod, { @@ -5973,11 +5991,9 @@ class Parser { socket[kReset] = true } - let pause - try { - pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false - } catch (err) { - util.destroy(socket, err) + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false + + if (request.aborted) { return -1 } @@ -6024,13 +6040,8 @@ class Parser { this.bytesRead += buf.length - try { - if (request.onData(buf) === false) { - return constants.ERROR.PAUSED - } - } catch (err) { - util.destroy(socket, err) - return -1 + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED } } @@ -6071,11 +6082,7 @@ class Parser { return -1 } - try { - request.onComplete(headers) - } catch (err) { - errorRequest(client, request, err) - } + request.onComplete(headers) client[kQueue][client[kRunningIdx]++] = null @@ -6239,7 +6246,7 @@ async function connect (client) { const idx = hostname.indexOf(']') assert(idx !== -1) - const ip = hostname.substr(1, idx - 1) + const ip = hostname.substring(1, idx) assert(net.isIP(ip)) hostname = ip @@ -6738,6 +6745,7 @@ function writeH2 (client, session, request) { return false } + /** @type {import('node:http2').ClientHttp2Stream} */ let stream const h2State = client[kHTTP2SessionState] @@ -6833,14 +6841,10 @@ function writeH2 (client, session, request) { const shouldEndStream = method === 'GET' || method === 'HEAD' if (expectContinue) { headers[HTTP2_HEADER_EXPECT] = '100-continue' - /** - * @type {import('node:http2').ClientHttp2Stream} - */ stream = session.request(headers, { endStream: shouldEndStream, signal }) stream.once('continue', writeBodyH2) } else { - /** @type {import('node:http2').ClientHttp2Stream} */ stream = session.request(headers, { endStream: shouldEndStream, signal @@ -6852,7 +6856,9 @@ function writeH2 (client, session, request) { ++h2State.openStreams stream.once('response', headers => { - if (request.onHeaders(Number(headers[HTTP2_HEADER_STATUS]), headers, stream.resume.bind(stream), '') === false) { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + + if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) { stream.pause() } }) @@ -6862,13 +6868,17 @@ function writeH2 (client, session, request) { }) stream.on('data', (chunk) => { - if (request.onData(chunk) === false) stream.pause() + if (request.onData(chunk) === false) { + stream.pause() + } }) stream.once('close', () => { h2State.openStreams -= 1 // TODO(HTTP/2): unref only if current streams count is 0 - if (h2State.openStreams === 0) session.unref() + if (h2State.openStreams === 0) { + session.unref() + } }) stream.once('error', function (err) { @@ -7028,7 +7038,11 @@ function writeStream ({ h2stream, body, client, request, socket, contentLength, } } const onAbort = function () { - onFinished(new RequestAbortedError()) + if (finished) { + return + } + const err = new RequestAbortedError() + queueMicrotask(() => onFinished(err)) } const onFinished = function (err) { if (finished) { @@ -7345,7 +7359,7 @@ module.exports = Client /***/ }), -/***/ 7905: +/***/ 4142: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -7353,7 +7367,7 @@ module.exports = Client /* istanbul ignore file: only for Node 12 */ -const { kConnected, kSize } = __nccwpck_require__(1439) +const { kConnected, kSize } = __nccwpck_require__(7460) class CompatWeakRef { constructor (value) { @@ -7401,7 +7415,7 @@ module.exports = function () { /***/ }), -/***/ 8709: +/***/ 2040: /***/ ((module) => { "use strict"; @@ -7421,16 +7435,16 @@ module.exports = { /***/ }), -/***/ 30: +/***/ 2739: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { parseSetCookie } = __nccwpck_require__(1915) -const { stringify, getHeadersList } = __nccwpck_require__(7318) -const { webidl } = __nccwpck_require__(5337) -const { Headers } = __nccwpck_require__(7967) +const { parseSetCookie } = __nccwpck_require__(7151) +const { stringify, getHeadersList } = __nccwpck_require__(2285) +const { webidl } = __nccwpck_require__(8184) +const { Headers } = __nccwpck_require__(3767) /** * @typedef {Object} Cookie @@ -7613,15 +7627,15 @@ module.exports = { /***/ }), -/***/ 1915: +/***/ 7151: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(8709) -const { isCTLExcludingHtab } = __nccwpck_require__(7318) -const { collectASequenceOfCodePointsFast } = __nccwpck_require__(6822) +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(2040) +const { isCTLExcludingHtab } = __nccwpck_require__(2285) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(834) const assert = __nccwpck_require__(9491) /** @@ -7938,14 +7952,14 @@ module.exports = { /***/ }), -/***/ 7318: +/***/ 2285: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const assert = __nccwpck_require__(9491) -const { kHeadersList } = __nccwpck_require__(1439) +const { kHeadersList } = __nccwpck_require__(7460) function isCTLExcludingHtab (value) { if (value.length === 0) { @@ -8237,7 +8251,7 @@ module.exports = { /***/ }), -/***/ 3311: +/***/ 5599: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -8245,8 +8259,8 @@ module.exports = { const net = __nccwpck_require__(1808) const assert = __nccwpck_require__(9491) -const util = __nccwpck_require__(6223) -const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(5767) +const util = __nccwpck_require__(2014) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(51) let tls // include tls conditionally since it is not always available @@ -8434,7 +8448,7 @@ module.exports = buildConnector /***/ }), -/***/ 5767: +/***/ 51: /***/ ((module) => { "use strict"; @@ -8633,6 +8647,19 @@ class ResponseExceededMaxSizeError extends UndiciError { } } +class RequestRetryError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + Error.captureStackTrace(this, RequestRetryError) + this.name = 'RequestRetryError' + this.message = message || 'Request retry error' + this.code = 'UND_ERR_REQ_RETRY' + this.statusCode = code + this.data = data + this.headers = headers + } +} + module.exports = { HTTPParserError, UndiciError, @@ -8652,13 +8679,14 @@ module.exports = { NotSupportedError, ResponseContentLengthMismatchError, BalancedPoolMissingUpstreamError, - ResponseExceededMaxSizeError + ResponseExceededMaxSizeError, + RequestRetryError } /***/ }), -/***/ 1562: +/***/ 8751: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -8667,10 +8695,10 @@ module.exports = { const { InvalidArgumentError, NotSupportedError -} = __nccwpck_require__(5767) +} = __nccwpck_require__(51) const assert = __nccwpck_require__(9491) -const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(1439) -const util = __nccwpck_require__(6223) +const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(7460) +const util = __nccwpck_require__(2014) // tokenRegExp and headerCharRegex have been lifted from // https://github.com/nodejs/node/blob/main/lib/_http_common.js @@ -8865,7 +8893,7 @@ class Request { } if (!extractBody) { - extractBody = (__nccwpck_require__(6770).extractBody) + extractBody = (__nccwpck_require__(7030).extractBody) } const [bodyStream, contentType] = extractBody(body) @@ -8894,9 +8922,9 @@ class Request { onBodySent (chunk) { if (this[kHandler].onBodySent) { try { - this[kHandler].onBodySent(chunk) + return this[kHandler].onBodySent(chunk) } catch (err) { - this.onError(err) + this.abort(err) } } } @@ -8908,9 +8936,9 @@ class Request { if (this[kHandler].onRequestSent) { try { - this[kHandler].onRequestSent() + return this[kHandler].onRequestSent() } catch (err) { - this.onError(err) + this.abort(err) } } } @@ -8935,14 +8963,23 @@ class Request { channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) } - return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + } catch (err) { + this.abort(err) + } } onData (chunk) { assert(!this.aborted) assert(!this.completed) - return this[kHandler].onData(chunk) + try { + return this[kHandler].onData(chunk) + } catch (err) { + this.abort(err) + return false + } } onUpgrade (statusCode, headers, socket) { @@ -8961,7 +8998,13 @@ class Request { if (channels.trailers.hasSubscribers) { channels.trailers.publish({ request: this, trailers }) } - return this[kHandler].onComplete(trailers) + + try { + return this[kHandler].onComplete(trailers) + } catch (err) { + // TODO (fix): This might be a bad idea? + this.onError(err) + } } onError (error) { @@ -8975,6 +9018,7 @@ class Request { return } this.aborted = true + return this[kHandler].onError(error) } @@ -9149,7 +9193,7 @@ module.exports = Request /***/ }), -/***/ 1439: +/***/ 7460: /***/ ((module) => { module.exports = { @@ -9211,24 +9255,26 @@ module.exports = { kHTTP2BuildRequest: Symbol('http2 build request'), kHTTP1BuildRequest: Symbol('http1 build request'), kHTTP2CopyHeaders: Symbol('http2 copy headers'), - kHTTPConnVersion: Symbol('http connection version') + kHTTPConnVersion: Symbol('http connection version'), + kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), + kConstruct: Symbol('constructable') } /***/ }), -/***/ 6223: +/***/ 2014: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const assert = __nccwpck_require__(9491) -const { kDestroyed, kBodyUsed } = __nccwpck_require__(1439) +const { kDestroyed, kBodyUsed } = __nccwpck_require__(7460) const { IncomingMessage } = __nccwpck_require__(3685) const stream = __nccwpck_require__(2781) const net = __nccwpck_require__(1808) -const { InvalidArgumentError } = __nccwpck_require__(5767) +const { InvalidArgumentError } = __nccwpck_require__(51) const { Blob } = __nccwpck_require__(4300) const nodeUtil = __nccwpck_require__(3837) const { stringify } = __nccwpck_require__(3477) @@ -9348,13 +9394,13 @@ function getHostname (host) { const idx = host.indexOf(']') assert(idx !== -1) - return host.substr(1, idx - 1) + return host.substring(1, idx) } const idx = host.indexOf(':') if (idx === -1) return host - return host.substr(0, idx) + return host.substring(0, idx) } // IP addresses are not valid server names per RFC6066 @@ -9451,7 +9497,7 @@ function parseHeaders (headers, obj = {}) { if (!val) { if (Array.isArray(headers[i + 1])) { - obj[key] = headers[i + 1] + obj[key] = headers[i + 1].map(x => x.toString('utf8')) } else { obj[key] = headers[i + 1].toString('utf8') } @@ -9654,16 +9700,7 @@ function throwIfAborted (signal) { } } -let events function addAbortListener (signal, listener) { - if (typeof Symbol.dispose === 'symbol') { - if (!events) { - events = __nccwpck_require__(2361) - } - if (typeof events.addAbortListener === 'function' && 'aborted' in signal) { - return events.addAbortListener(signal, listener) - } - } if ('addEventListener' in signal) { signal.addEventListener('abort', listener, { once: true }) return () => signal.removeEventListener('abort', listener) @@ -9687,6 +9724,21 @@ function toUSVString (val) { return `${val}` } +// Parsed accordingly to RFC 9110 +// https://www.rfc-editor.org/rfc/rfc9110#field.content-range +function parseRangeHeader (range) { + if (range == null || range === '') return { start: 0, end: null, size: null } + + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null + return m + ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } + : null +} + const kEnumerableProperty = Object.create(null) kEnumerableProperty.enumerable = true @@ -9720,27 +9772,29 @@ module.exports = { buildURL, throwIfAborted, addAbortListener, + parseRangeHeader, nodeMajor, nodeMinor, - nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13) + nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13), + safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'] } /***/ }), -/***/ 8188: +/***/ 854: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Dispatcher = __nccwpck_require__(1312) +const Dispatcher = __nccwpck_require__(7978) const { ClientDestroyedError, ClientClosedError, InvalidArgumentError -} = __nccwpck_require__(5767) -const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(1439) +} = __nccwpck_require__(51) +const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(7460) const kDestroyed = Symbol('destroyed') const kClosed = Symbol('closed') @@ -9928,7 +9982,7 @@ module.exports = DispatcherBase /***/ }), -/***/ 1312: +/***/ 7978: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -9955,14 +10009,14 @@ module.exports = Dispatcher /***/ }), -/***/ 6770: +/***/ 7030: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Busboy = __nccwpck_require__(1702) -const util = __nccwpck_require__(6223) +const Busboy = __nccwpck_require__(9638) +const util = __nccwpck_require__(2014) const { ReadableStreamFrom, isBlobLike, @@ -9970,18 +10024,18 @@ const { readableStreamClose, createDeferredPromise, fullyReadBody -} = __nccwpck_require__(6913) -const { FormData } = __nccwpck_require__(4595) -const { kState } = __nccwpck_require__(1048) -const { webidl } = __nccwpck_require__(5337) -const { DOMException, structuredClone } = __nccwpck_require__(7213) +} = __nccwpck_require__(9567) +const { FormData } = __nccwpck_require__(4089) +const { kState } = __nccwpck_require__(4030) +const { webidl } = __nccwpck_require__(8184) +const { DOMException, structuredClone } = __nccwpck_require__(3074) const { Blob, File: NativeFile } = __nccwpck_require__(4300) -const { kBodyUsed } = __nccwpck_require__(1439) +const { kBodyUsed } = __nccwpck_require__(7460) const assert = __nccwpck_require__(9491) -const { isErrored } = __nccwpck_require__(6223) +const { isErrored } = __nccwpck_require__(2014) const { isUint8Array, isArrayBuffer } = __nccwpck_require__(9830) -const { File: UndiciFile } = __nccwpck_require__(9072) -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6822) +const { File: UndiciFile } = __nccwpck_require__(8731) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(834) let ReadableStream = globalThis.ReadableStream @@ -10568,7 +10622,7 @@ module.exports = { /***/ }), -/***/ 7213: +/***/ 3074: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -10727,12 +10781,12 @@ module.exports = { /***/ }), -/***/ 6822: +/***/ 834: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const assert = __nccwpck_require__(9491) const { atob } = __nccwpck_require__(4300) -const { isomorphicDecode } = __nccwpck_require__(6913) +const { isomorphicDecode } = __nccwpck_require__(9567) const encoder = new TextEncoder() @@ -10851,17 +10905,14 @@ function dataURLProcessor (dataURL) { * @param {boolean} excludeFragment */ function URLSerializer (url, excludeFragment = false) { - const href = url.href - if (!excludeFragment) { - return href + return url.href } - const hash = href.lastIndexOf('#') - if (hash === -1) { - return href - } - return href.slice(0, hash) + const href = url.href + const hashLength = url.hash.length + + return hashLength === 0 ? href : href.substring(0, href.length - hashLength) } // https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points @@ -11364,7 +11415,7 @@ module.exports = { /***/ }), -/***/ 9072: +/***/ 8731: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -11372,11 +11423,11 @@ module.exports = { const { Blob, File: NativeFile } = __nccwpck_require__(4300) const { types } = __nccwpck_require__(3837) -const { kState } = __nccwpck_require__(1048) -const { isBlobLike } = __nccwpck_require__(6913) -const { webidl } = __nccwpck_require__(5337) -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6822) -const { kEnumerableProperty } = __nccwpck_require__(6223) +const { kState } = __nccwpck_require__(4030) +const { isBlobLike } = __nccwpck_require__(9567) +const { webidl } = __nccwpck_require__(8184) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(834) +const { kEnumerableProperty } = __nccwpck_require__(2014) const encoder = new TextEncoder() class File extends Blob { @@ -11716,16 +11767,16 @@ module.exports = { File, FileLike, isFileLike } /***/ }), -/***/ 4595: +/***/ 4089: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(6913) -const { kState } = __nccwpck_require__(1048) -const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(9072) -const { webidl } = __nccwpck_require__(5337) +const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(9567) +const { kState } = __nccwpck_require__(4030) +const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(8731) +const { webidl } = __nccwpck_require__(8184) const { Blob, File: NativeFile } = __nccwpck_require__(4300) /** @type {globalThis['File']} */ @@ -11989,7 +12040,7 @@ module.exports = { FormData } /***/ }), -/***/ 4428: +/***/ 4612: /***/ ((module) => { "use strict"; @@ -12037,7 +12088,7 @@ module.exports = { /***/ }), -/***/ 7967: +/***/ 3767: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -12045,20 +12096,27 @@ module.exports = { -const { kHeadersList } = __nccwpck_require__(1439) -const { kGuard } = __nccwpck_require__(1048) -const { kEnumerableProperty } = __nccwpck_require__(6223) +const { kHeadersList, kConstruct } = __nccwpck_require__(7460) +const { kGuard } = __nccwpck_require__(4030) +const { kEnumerableProperty } = __nccwpck_require__(2014) const { makeIterator, isValidHeaderName, isValidHeaderValue -} = __nccwpck_require__(6913) -const { webidl } = __nccwpck_require__(5337) +} = __nccwpck_require__(9567) +const { webidl } = __nccwpck_require__(8184) const assert = __nccwpck_require__(9491) const kHeadersMap = Symbol('headers map') const kHeadersSortedMap = Symbol('headers map sorted') +/** + * @param {number} code + */ +function isHTTPWhiteSpaceCharCode (code) { + return code === 0x00a || code === 0x00d || code === 0x009 || code === 0x020 +} + /** * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize * @param {string} potentialValue @@ -12067,12 +12125,12 @@ function headerValueNormalize (potentialValue) { // To normalize a byte sequence potentialValue, remove // any leading and trailing HTTP whitespace bytes from // potentialValue. + let i = 0; let j = potentialValue.length + + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i - // Trimming the end with `.replace()` and a RegExp is typically subject to - // ReDoS. This is safer and faster. - let i = potentialValue.length - while (/[\r\n\t ]/.test(potentialValue.charAt(--i))); - return potentialValue.slice(0, i + 1).replace(/^[\r\n\t ]+/, '') + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) } function fill (headers, object) { @@ -12081,7 +12139,8 @@ function fill (headers, object) { // 1. If object is a sequence, then for each header in object: // Note: webidl conversion to array has already been done. if (Array.isArray(object)) { - for (const header of object) { + for (let i = 0; i < object.length; ++i) { + const header = object[i] // 1. If header does not contain exactly two items, then throw a TypeError. if (header.length !== 2) { throw webidl.errors.exception({ @@ -12091,15 +12150,16 @@ function fill (headers, object) { } // 2. Append (header’s first item, header’s second item) to headers. - headers.append(header[0], header[1]) + appendHeader(headers, header[0], header[1]) } } else if (typeof object === 'object' && object !== null) { // Note: null should throw // 2. Otherwise, object is a record, then for each key → value in object, // append (key, value) to headers - for (const [key, value] of Object.entries(object)) { - headers.append(key, value) + const keys = Object.keys(object) + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers, keys[i], object[keys[i]]) } } else { throw webidl.errors.conversionFailed({ @@ -12110,6 +12170,50 @@ function fill (headers, object) { } } +/** + * @see https://fetch.spec.whatwg.org/#concept-headers-append + */ +function appendHeader (headers, name, value) { + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value, + type: 'header value' + }) + } + + // 3. If headers’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if headers’s guard is "request" and name is a + // forbidden header name, return. + // Note: undici does not implement forbidden header names + if (headers[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (headers[kGuard] === 'request-no-cors') { + // 5. Otherwise, if headers’s guard is "request-no-cors": + // TODO + } + + // 6. Otherwise, if headers’s guard is "response" and name is a + // forbidden response-header name, return. + + // 7. Append (name, value) to headers’s header list. + return headers[kHeadersList].append(name, value) + + // 8. If headers’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from headers +} + class HeadersList { /** @type {[string, string][]|null} */ cookies = null @@ -12118,7 +12222,7 @@ class HeadersList { if (init instanceof HeadersList) { this[kHeadersMap] = new Map(init[kHeadersMap]) this[kHeadersSortedMap] = init[kHeadersSortedMap] - this.cookies = init.cookies + this.cookies = init.cookies === null ? null : [...init.cookies] } else { this[kHeadersMap] = new Map(init) this[kHeadersSortedMap] = null @@ -12180,7 +12284,7 @@ class HeadersList { // the first such header to value and remove the // others. // 2. Otherwise, append header (name, value) to list. - return this[kHeadersMap].set(lowercaseName, { name, value }) + this[kHeadersMap].set(lowercaseName, { name, value }) } // https://fetch.spec.whatwg.org/#concept-header-list-delete @@ -12193,20 +12297,18 @@ class HeadersList { this.cookies = null } - return this[kHeadersMap].delete(name) + this[kHeadersMap].delete(name) } // https://fetch.spec.whatwg.org/#concept-header-list-get get (name) { - // 1. If list does not contain name, then return null. - if (!this.contains(name)) { - return null - } + const value = this[kHeadersMap].get(name.toLowerCase()) + // 1. If list does not contain name, then return null. // 2. Return the values of all headers in list whose name // is a byte-case-insensitive match for name, // separated from each other by 0x2C 0x20, in order. - return this[kHeadersMap].get(name.toLowerCase())?.value ?? null + return value === undefined ? null : value.value } * [Symbol.iterator] () { @@ -12232,6 +12334,9 @@ class HeadersList { // https://fetch.spec.whatwg.org/#headers-class class Headers { constructor (init = undefined) { + if (init === kConstruct) { + return + } this[kHeadersList] = new HeadersList() // The new Headers(init) constructor steps are: @@ -12255,43 +12360,7 @@ class Headers { name = webidl.converters.ByteString(name) value = webidl.converters.ByteString(value) - // 1. Normalize value. - value = headerValueNormalize(value) - - // 2. If name is not a header name or value is not a - // header value, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.append', - value: name, - type: 'header name' - }) - } else if (!isValidHeaderValue(value)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.append', - value, - type: 'header value' - }) - } - - // 3. If headers’s guard is "immutable", then throw a TypeError. - // 4. Otherwise, if headers’s guard is "request" and name is a - // forbidden header name, return. - // Note: undici does not implement forbidden header names - if (this[kGuard] === 'immutable') { - throw new TypeError('immutable') - } else if (this[kGuard] === 'request-no-cors') { - // 5. Otherwise, if headers’s guard is "request-no-cors": - // TODO - } - - // 6. Otherwise, if headers’s guard is "response" and name is a - // forbidden response-header name, return. - - // 7. Append (name, value) to headers’s header list. - // 8. If headers’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from headers - return this[kHeadersList].append(name, value) + return appendHeader(this, name, value) } // https://fetch.spec.whatwg.org/#dom-headers-delete @@ -12336,7 +12405,7 @@ class Headers { // 7. Delete name from this’s header list. // 8. If this’s guard is "request-no-cors", then remove // privileged no-CORS request headers from this. - return this[kHeadersList].delete(name) + this[kHeadersList].delete(name) } // https://fetch.spec.whatwg.org/#dom-headers-get @@ -12429,7 +12498,7 @@ class Headers { // 7. Set (name, value) in this’s header list. // 8. If this’s guard is "request-no-cors", then remove // privileged no-CORS request headers from this - return this[kHeadersList].set(name, value) + this[kHeadersList].set(name, value) } // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie @@ -12465,7 +12534,8 @@ class Headers { const cookies = this[kHeadersList].cookies // 3. For each name of names: - for (const [name, value] of names) { + for (let i = 0; i < names.length; ++i) { + const [name, value] = names[i] // 1. If name is `set-cookie`, then: if (name === 'set-cookie') { // 1. Let values be a list of all values of headers in list whose name @@ -12473,8 +12543,8 @@ class Headers { // 2. For each value of values: // 1. Append (name, value) to headers. - for (const value of cookies) { - headers.push([name, value]) + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]) } } else { // 2. Otherwise: @@ -12498,6 +12568,12 @@ class Headers { keys () { webidl.brandCheck(this, Headers) + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key') + } + return makeIterator( () => [...this[kHeadersSortedMap].values()], 'Headers', @@ -12508,6 +12584,12 @@ class Headers { values () { webidl.brandCheck(this, Headers) + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'value') + } + return makeIterator( () => [...this[kHeadersSortedMap].values()], 'Headers', @@ -12518,6 +12600,12 @@ class Headers { entries () { webidl.brandCheck(this, Headers) + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key+value') + } + return makeIterator( () => [...this[kHeadersSortedMap].values()], 'Headers', @@ -12597,7 +12685,7 @@ module.exports = { /***/ }), -/***/ 3360: +/***/ 3246: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -12611,9 +12699,9 @@ const { makeAppropriateNetworkError, filterResponse, makeResponse -} = __nccwpck_require__(1570) -const { Headers } = __nccwpck_require__(7967) -const { Request, makeRequest } = __nccwpck_require__(8619) +} = __nccwpck_require__(6476) +const { Headers } = __nccwpck_require__(3767) +const { Request, makeRequest } = __nccwpck_require__(6814) const zlib = __nccwpck_require__(9796) const { bytesMatch, @@ -12644,10 +12732,10 @@ const { urlIsLocal, urlIsHttpHttpsScheme, urlHasHttpsScheme -} = __nccwpck_require__(6913) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(1048) +} = __nccwpck_require__(9567) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(4030) const assert = __nccwpck_require__(9491) -const { safelyExtractBody } = __nccwpck_require__(6770) +const { safelyExtractBody } = __nccwpck_require__(7030) const { redirectStatusSet, nullBodyStatus, @@ -12655,15 +12743,15 @@ const { requestBodyHeader, subresourceSet, DOMException -} = __nccwpck_require__(7213) -const { kHeadersList } = __nccwpck_require__(1439) +} = __nccwpck_require__(3074) +const { kHeadersList } = __nccwpck_require__(7460) const EE = __nccwpck_require__(2361) const { Readable, pipeline } = __nccwpck_require__(2781) -const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(6223) -const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(6822) +const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(2014) +const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(834) const { TransformStream } = __nccwpck_require__(5356) -const { getGlobalDispatcher } = __nccwpck_require__(398) -const { webidl } = __nccwpck_require__(5337) +const { getGlobalDispatcher } = __nccwpck_require__(6223) +const { webidl } = __nccwpck_require__(8184) const { STATUS_CODES } = __nccwpck_require__(3685) const GET_OR_HEAD = ['GET', 'HEAD'] @@ -12889,7 +12977,7 @@ function finalizeAndReportTiming (response, initiatorType = 'other') { } // 8. If response’s timing allow passed flag is not set, then: - if (!timingInfo.timingAllowPassed) { + if (!response.timingAllowPassed) { // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. timingInfo = createOpaqueTimingInfo({ startTime: timingInfo.startTime @@ -13806,6 +13894,9 @@ function httpRedirectFetch (fetchParams, response) { // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name request.headersList.delete('authorization') + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. request.headersList.delete('cookie') request.headersList.delete('host') @@ -14560,7 +14651,7 @@ async function httpNetworkFetch ( path: url.pathname + url.search, origin: url.origin, method: request.method, - body: fetchParams.controller.dispatcher.isMockActive ? request.body && request.body.source : body, + body: fetchParams.controller.dispatcher.isMockActive ? request.body && (request.body.source || request.body.stream) : body, headers: request.headersList.entries, maxRedirections: 0, upgrade: request.mode === 'websocket' ? 'websocket' : undefined @@ -14605,7 +14696,7 @@ async function httpNetworkFetch ( location = val } - headers.append(key, val) + headers[kHeadersList].append(key, val) } } else { const keys = Object.keys(headersList) @@ -14619,7 +14710,7 @@ async function httpNetworkFetch ( location = val } - headers.append(key, val) + headers[kHeadersList].append(key, val) } } @@ -14723,7 +14814,7 @@ async function httpNetworkFetch ( const key = headersList[n + 0].toString('latin1') const val = headersList[n + 1].toString('latin1') - headers.append(key, val) + headers[kHeadersList].append(key, val) } resolve({ @@ -14750,7 +14841,7 @@ module.exports = { /***/ }), -/***/ 8619: +/***/ 6814: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -14758,16 +14849,17 @@ module.exports = { -const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(6770) -const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(7967) -const { FinalizationRegistry } = __nccwpck_require__(7905)() -const util = __nccwpck_require__(6223) +const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(7030) +const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(3767) +const { FinalizationRegistry } = __nccwpck_require__(4142)() +const util = __nccwpck_require__(2014) const { isValidHTTPToken, sameOrigin, normalizeMethod, - makePolicyContainer -} = __nccwpck_require__(6913) + makePolicyContainer, + normalizeMethodRecord +} = __nccwpck_require__(9567) const { forbiddenMethodsSet, corsSafeListedMethodsSet, @@ -14777,19 +14869,18 @@ const { requestCredentials, requestCache, requestDuplex -} = __nccwpck_require__(7213) +} = __nccwpck_require__(3074) const { kEnumerableProperty } = util -const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(1048) -const { webidl } = __nccwpck_require__(5337) -const { getGlobalOrigin } = __nccwpck_require__(4428) -const { URLSerializer } = __nccwpck_require__(6822) -const { kHeadersList } = __nccwpck_require__(1439) +const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(4030) +const { webidl } = __nccwpck_require__(8184) +const { getGlobalOrigin } = __nccwpck_require__(4612) +const { URLSerializer } = __nccwpck_require__(834) +const { kHeadersList, kConstruct } = __nccwpck_require__(7460) const assert = __nccwpck_require__(9491) const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(2361) let TransformStream = globalThis.TransformStream -const kInit = Symbol('init') const kAbortController = Symbol('abortController') const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { @@ -14800,7 +14891,7 @@ const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { class Request { // https://fetch.spec.whatwg.org/#dom-request constructor (input, init = {}) { - if (input === kInit) { + if (input === kConstruct) { return } @@ -14939,8 +15030,10 @@ class Request { urlList: [...request.urlList] }) + const initHasKey = Object.keys(init).length !== 0 + // 13. If init is not empty, then: - if (Object.keys(init).length > 0) { + if (initHasKey) { // 1. If request’s mode is "navigate", then set it to "same-origin". if (request.mode === 'navigate') { request.mode = 'same-origin' @@ -15055,7 +15148,7 @@ class Request { } // 23. If init["integrity"] exists, then set request’s integrity metadata to it. - if (init.integrity !== undefined && init.integrity != null) { + if (init.integrity != null) { request.integrity = String(init.integrity) } @@ -15071,16 +15164,16 @@ class Request { // 2. If method is not a method or method is a forbidden method, then // throw a TypeError. - if (!isValidHTTPToken(init.method)) { - throw TypeError(`'${init.method}' is not a valid HTTP method.`) + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`) } if (forbiddenMethodsSet.has(method.toUpperCase())) { - throw TypeError(`'${init.method}' HTTP method is unsupported.`) + throw new TypeError(`'${method}' HTTP method is unsupported.`) } // 3. Normalize method. - method = normalizeMethod(init.method) + method = normalizeMethodRecord[method] ?? normalizeMethod(method) // 4. Set request’s method to method. request.method = method @@ -15151,7 +15244,7 @@ class Request { // 30. Set this’s headers to a new Headers object with this’s relevant // Realm, whose header list is request’s header list and guard is // "request". - this[kHeaders] = new Headers() + this[kHeaders] = new Headers(kConstruct) this[kHeaders][kHeadersList] = request.headersList this[kHeaders][kGuard] = 'request' this[kHeaders][kRealm] = this[kRealm] @@ -15171,25 +15264,25 @@ class Request { } // 32. If init is not empty, then: - if (Object.keys(init).length !== 0) { + if (initHasKey) { + /** @type {HeadersList} */ + const headersList = this[kHeaders][kHeadersList] // 1. Let headers be a copy of this’s headers and its associated header // list. - let headers = new Headers(this[kHeaders]) - // 2. If init["headers"] exists, then set headers to init["headers"]. - if (init.headers !== undefined) { - headers = init.headers - } + const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) // 3. Empty this’s headers’s header list. - this[kHeaders][kHeadersList].clear() + headersList.clear() // 4. If headers is a Headers object, then for each header in its header // list, append header’s name/header’s value to this’s headers. - if (headers.constructor.name === 'Headers') { + if (headers instanceof HeadersList) { for (const [key, val] of headers) { - this[kHeaders].append(key, val) + headersList.append(key, val) } + // Note: Copy the `set-cookie` meta-data. + headersList.cookies = headers.cookies } else { // 5. Otherwise, fill this’s headers with headers. fillHeaders(this[kHeaders], headers) @@ -15478,10 +15571,10 @@ class Request { // 3. Let clonedRequestObject be the result of creating a Request object, // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. - const clonedRequestObject = new Request(kInit) + const clonedRequestObject = new Request(kConstruct) clonedRequestObject[kState] = clonedRequest clonedRequestObject[kRealm] = this[kRealm] - clonedRequestObject[kHeaders] = new Headers() + clonedRequestObject[kHeaders] = new Headers(kConstruct) clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard] clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm] @@ -15702,15 +15795,15 @@ module.exports = { Request, makeRequest } /***/ }), -/***/ 1570: +/***/ 6476: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { Headers, HeadersList, fill } = __nccwpck_require__(7967) -const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(6770) -const util = __nccwpck_require__(6223) +const { Headers, HeadersList, fill } = __nccwpck_require__(3767) +const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(7030) +const util = __nccwpck_require__(2014) const { kEnumerableProperty } = util const { isValidReasonPhrase, @@ -15720,18 +15813,18 @@ const { serializeJavascriptValueToJSONString, isErrorLike, isomorphicEncode -} = __nccwpck_require__(6913) +} = __nccwpck_require__(9567) const { redirectStatusSet, nullBodyStatus, DOMException -} = __nccwpck_require__(7213) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(1048) -const { webidl } = __nccwpck_require__(5337) -const { FormData } = __nccwpck_require__(4595) -const { getGlobalOrigin } = __nccwpck_require__(4428) -const { URLSerializer } = __nccwpck_require__(6822) -const { kHeadersList } = __nccwpck_require__(1439) +} = __nccwpck_require__(3074) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(4030) +const { webidl } = __nccwpck_require__(8184) +const { FormData } = __nccwpck_require__(4089) +const { getGlobalOrigin } = __nccwpck_require__(4612) +const { URLSerializer } = __nccwpck_require__(834) +const { kHeadersList, kConstruct } = __nccwpck_require__(7460) const assert = __nccwpck_require__(9491) const { types } = __nccwpck_require__(3837) @@ -15852,7 +15945,7 @@ class Response { // 2. Set this’s headers to a new Headers object with this’s relevant // Realm, whose header list is this’s response’s header list and guard // is "response". - this[kHeaders] = new Headers() + this[kHeaders] = new Headers(kConstruct) this[kHeaders][kGuard] = 'response' this[kHeaders][kHeadersList] = this[kState].headersList this[kHeaders][kRealm] = this[kRealm] @@ -16222,11 +16315,7 @@ webidl.converters.XMLHttpRequestBodyInit = function (V) { return webidl.converters.Blob(V, { strict: false }) } - if ( - types.isAnyArrayBuffer(V) || - types.isTypedArray(V) || - types.isDataView(V) - ) { + if (types.isArrayBuffer(V) || types.isTypedArray(V) || types.isDataView(V)) { return webidl.converters.BufferSource(V) } @@ -16285,7 +16374,7 @@ module.exports = { /***/ }), -/***/ 1048: +/***/ 4030: /***/ ((module) => { "use strict"; @@ -16303,16 +16392,16 @@ module.exports = { /***/ }), -/***/ 6913: +/***/ 9567: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(7213) -const { getGlobalOrigin } = __nccwpck_require__(4428) +const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(3074) +const { getGlobalOrigin } = __nccwpck_require__(4612) const { performance } = __nccwpck_require__(4074) -const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(6223) +const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(2014) const assert = __nccwpck_require__(9491) const { isUint8Array } = __nccwpck_require__(9830) @@ -16412,52 +16501,57 @@ function isValidReasonPhrase (statusText) { return true } -function isTokenChar (c) { - return !( - c >= 0x7f || - c <= 0x20 || - c === '(' || - c === ')' || - c === '<' || - c === '>' || - c === '@' || - c === ',' || - c === ';' || - c === ':' || - c === '\\' || - c === '"' || - c === '/' || - c === '[' || - c === ']' || - c === '?' || - c === '=' || - c === '{' || - c === '}' - ) +/** + * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 + * @param {number} c + */ +function isTokenCharCode (c) { + switch (c) { + case 0x22: + case 0x28: + case 0x29: + case 0x2c: + case 0x2f: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x40: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x7b: + case 0x7d: + // DQUOTE and "(),/:;<=>?@[\]{}" + return false + default: + // VCHAR %x21-7E + return c >= 0x21 && c <= 0x7e + } } -// See RFC 7230, Section 3.2.6. -// https://github.com/chromium/chromium/blob/d7da0240cae77824d1eda25745c4022757499131/third_party/blink/renderer/platform/network/http_parsers.cc#L321 +/** + * @param {string} characters + */ function isValidHTTPToken (characters) { - if (!characters || typeof characters !== 'string') { + if (characters.length === 0) { return false } for (let i = 0; i < characters.length; ++i) { - const c = characters.charCodeAt(i) - if (c > 0x7f || !isTokenChar(c)) { + if (!isTokenCharCode(characters.charCodeAt(i))) { return false } } return true } -// https://fetch.spec.whatwg.org/#header-name -// https://github.com/chromium/chromium/blob/b3d37e6f94f87d59e44662d6078f6a12de845d17/net/http/http_util.cc#L342 +/** + * @see https://fetch.spec.whatwg.org/#header-name + * @param {string} potentialValue + */ function isValidHeaderName (potentialValue) { - if (potentialValue.length === 0) { - return false - } - return isValidHTTPToken(potentialValue) } @@ -17002,11 +17096,30 @@ function isCancelled (fetchParams) { fetchParams.controller.state === 'terminated' } -// https://fetch.spec.whatwg.org/#concept-method-normalize +const normalizeMethodRecord = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizeMethodRecord, null) + +/** + * @see https://fetch.spec.whatwg.org/#concept-method-normalize + * @param {string} method + */ function normalizeMethod (method) { - return /^(DELETE|GET|HEAD|OPTIONS|POST|PUT)$/i.test(method) - ? method.toUpperCase() - : method + return normalizeMethodRecord[method.toLowerCase()] ?? method } // https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string @@ -17351,20 +17464,21 @@ module.exports = { urlIsLocal, urlHasHttpsScheme, urlIsHttpHttpsScheme, - readAllBytes + readAllBytes, + normalizeMethodRecord } /***/ }), -/***/ 5337: +/***/ 8184: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { types } = __nccwpck_require__(3837) -const { hasOwn, toUSVString } = __nccwpck_require__(6913) +const { hasOwn, toUSVString } = __nccwpck_require__(9567) /** @type {import('../../types/webidl').Webidl} */ const webidl = {} @@ -17790,12 +17904,10 @@ webidl.converters.ByteString = function (V) { // 2. If the value of any element of x is greater than // 255, then throw a TypeError. for (let index = 0; index < x.length; index++) { - const charCode = x.charCodeAt(index) - - if (charCode > 255) { + if (x.charCodeAt(index) > 255) { throw new TypeError( 'Cannot convert argument to a ByteString because the character at ' + - `index ${index} has a value of ${charCode} which is greater than 255.` + `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` ) } } @@ -18013,7 +18125,7 @@ module.exports = { /***/ }), -/***/ 7645: +/***/ 8603: /***/ ((module) => { "use strict"; @@ -18311,7 +18423,7 @@ module.exports = { /***/ }), -/***/ 7784: +/***/ 7689: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -18321,16 +18433,16 @@ const { staticPropertyDescriptors, readOperation, fireAProgressEvent -} = __nccwpck_require__(3934) +} = __nccwpck_require__(698) const { kState, kError, kResult, kEvents, kAborted -} = __nccwpck_require__(8587) -const { webidl } = __nccwpck_require__(5337) -const { kEnumerableProperty } = __nccwpck_require__(6223) +} = __nccwpck_require__(4514) +const { webidl } = __nccwpck_require__(8184) +const { kEnumerableProperty } = __nccwpck_require__(2014) class FileReader extends EventTarget { constructor () { @@ -18663,13 +18775,13 @@ module.exports = { /***/ }), -/***/ 1764: +/***/ 9354: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { webidl } = __nccwpck_require__(5337) +const { webidl } = __nccwpck_require__(8184) const kState = Symbol('ProgressEvent state') @@ -18749,7 +18861,7 @@ module.exports = { /***/ }), -/***/ 8587: +/***/ 4514: /***/ ((module) => { "use strict"; @@ -18767,7 +18879,7 @@ module.exports = { /***/ }), -/***/ 3934: +/***/ 698: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -18779,11 +18891,11 @@ const { kResult, kAborted, kLastProgressEventFired -} = __nccwpck_require__(8587) -const { ProgressEvent } = __nccwpck_require__(1764) -const { getEncoding } = __nccwpck_require__(7645) -const { DOMException } = __nccwpck_require__(7213) -const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(6822) +} = __nccwpck_require__(4514) +const { ProgressEvent } = __nccwpck_require__(9354) +const { getEncoding } = __nccwpck_require__(8603) +const { DOMException } = __nccwpck_require__(3074) +const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(834) const { types } = __nccwpck_require__(3837) const { StringDecoder } = __nccwpck_require__(1576) const { btoa } = __nccwpck_require__(4300) @@ -19167,7 +19279,7 @@ module.exports = { /***/ }), -/***/ 398: +/***/ 6223: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -19176,8 +19288,8 @@ module.exports = { // We include a version number for the Dispatcher API. In case of breaking changes, // this version number must be increased to avoid conflicts. const globalDispatcher = Symbol.for('undici.globalDispatcher.1') -const { InvalidArgumentError } = __nccwpck_require__(5767) -const Agent = __nccwpck_require__(8162) +const { InvalidArgumentError } = __nccwpck_require__(51) +const Agent = __nccwpck_require__(2438) if (getGlobalDispatcher() === undefined) { setGlobalDispatcher(new Agent()) @@ -19207,7 +19319,7 @@ module.exports = { /***/ }), -/***/ 3978: +/***/ 1509: /***/ ((module) => { "use strict"; @@ -19250,16 +19362,16 @@ module.exports = class DecoratorHandler { /***/ }), -/***/ 1962: +/***/ 7144: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const util = __nccwpck_require__(6223) -const { kBodyUsed } = __nccwpck_require__(1439) +const util = __nccwpck_require__(2014) +const { kBodyUsed } = __nccwpck_require__(7460) const assert = __nccwpck_require__(9491) -const { InvalidArgumentError } = __nccwpck_require__(5767) +const { InvalidArgumentError } = __nccwpck_require__(51) const EE = __nccwpck_require__(2361) const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] @@ -19474,13 +19586,356 @@ module.exports = RedirectHandler /***/ }), -/***/ 9095: +/***/ 5112: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(9491) + +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(7460) +const { RequestRetryError } = __nccwpck_require__(51) +const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(2014) + +function calculateRetryAfterHeader (retryAfter) { + const current = Date.now() + const diff = new Date(retryAfter).getTime() - current + + return diff +} + +class RetryHandler { + constructor (opts, handlers) { + const { retryOptions, ...dispatchOpts } = opts + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes + } = retryOptions ?? {} + + this.dispatch = handlers.dispatch + this.handler = handlers.handler + this.opts = dispatchOpts + this.abort = null + this.aborted = false + this.retryOpts = { + retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1000, // 30s, + timeout: minTimeout ?? 500, // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + 'ECONNRESET', + 'ECONNREFUSED', + 'ENOTFOUND', + 'ENETDOWN', + 'ENETUNREACH', + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'EPIPE' + ] + } + + this.retryCount = 0 + this.start = 0 + this.end = null + this.etag = null + this.resume = null + + // Handle possible onConnect duplication + this.handler.onConnect(reason => { + this.aborted = true + if (this.abort) { + this.abort(reason) + } else { + this.reason = reason + } + }) + } + + onRequestSent () { + if (this.handler.onRequestSent) { + this.handler.onRequestSent() + } + } + + onUpgrade (statusCode, headers, socket) { + if (this.handler.onUpgrade) { + this.handler.onUpgrade(statusCode, headers, socket) + } + } + + onConnect (abort) { + if (this.aborted) { + abort(this.reason) + } else { + this.abort = abort + } + } + + onBodySent (chunk) { + if (this.handler.onBodySent) return this.handler.onBodySent(chunk) + } + + static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { + const { statusCode, code, headers } = err + const { method, retryOptions } = opts + const { + maxRetries, + timeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions + let { counter, currentTimeout } = state + + currentTimeout = + currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout + + // Any code that is not a Undici's originated and allowed to retry + if ( + code && + code !== 'UND_ERR_REQ_RETRY' && + code !== 'UND_ERR_SOCKET' && + !errorCodes.includes(code) + ) { + cb(err) + return + } + + // If a set of method are provided and the current method is not in the list + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err) + return + } + + // If a set of status code are provided and the current status code is not in the list + if ( + statusCode != null && + Array.isArray(statusCodes) && + !statusCodes.includes(statusCode) + ) { + cb(err) + return + } + + // If we reached the max number of retries + if (counter > maxRetries) { + cb(err) + return + } + + let retryAfterHeader = headers != null && headers['retry-after'] + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader) + retryAfterHeader = isNaN(retryAfterHeader) + ? calculateRetryAfterHeader(retryAfterHeader) + : retryAfterHeader * 1e3 // Retry-After is in seconds + } + + const retryTimeout = + retryAfterHeader > 0 + ? Math.min(retryAfterHeader, maxTimeout) + : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout) + + state.currentTimeout = retryTimeout + + setTimeout(() => cb(null), retryTimeout) + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const headers = parseHeaders(rawHeaders) + + this.retryCount += 1 + + if (statusCode >= 300) { + this.abort( + new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Checkpoint for resume from where we left it + if (this.resume != null) { + this.resume = null + + if (statusCode !== 206) { + return true + } + + const contentRange = parseRangeHeader(headers['content-range']) + // If no content range + if (!contentRange) { + this.abort( + new RequestRetryError('Content-Range mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Let's start with a weak etag check + if (this.etag != null && this.etag !== headers.etag) { + this.abort( + new RequestRetryError('ETag mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + const { start, size, end = size } = contentRange + + assert(this.start === start, 'content-range mismatch') + assert(this.end == null || this.end === end, 'content-range mismatch') + + this.resume = resume + return true + } + + if (this.end == null) { + if (statusCode === 206) { + // First time we receive 206 + const range = parseRangeHeader(headers['content-range']) + + if (range == null) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const { start, size, end = size } = range + + assert( + start != null && Number.isFinite(start) && this.start !== start, + 'content-range mismatch' + ) + assert(Number.isFinite(start)) + assert( + end != null && Number.isFinite(end) && this.end !== end, + 'invalid content-length' + ) + + this.start = start + this.end = end + } + + // We make our best to checkpoint the body for further range headers + if (this.end == null) { + const contentLength = headers['content-length'] + this.end = contentLength != null ? Number(contentLength) : null + } + + assert(Number.isFinite(this.start)) + assert( + this.end == null || Number.isFinite(this.end), + 'invalid content-length' + ) + + this.resume = resume + this.etag = headers.etag != null ? headers.etag : null + + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const err = new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + + this.abort(err) + + return false + } + + onData (chunk) { + this.start += chunk.length + + return this.handler.onData(chunk) + } + + onComplete (rawTrailers) { + this.retryCount = 0 + return this.handler.onComplete(rawTrailers) + } + + onError (err) { + if (this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount++, currentTimeout: this.retryAfter }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + onRetry.bind(this) + ) + + function onRetry (err) { + if (err != null || this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + if (this.start !== 0) { + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + range: `bytes=${this.start}-${this.end ?? ''}` + } + } + } + + try { + this.dispatch(this.opts, this) + } catch (err) { + this.handler.onError(err) + } + } + } +} + +module.exports = RetryHandler + + +/***/ }), + +/***/ 6789: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const RedirectHandler = __nccwpck_require__(1962) +const RedirectHandler = __nccwpck_require__(7144) function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { return (dispatch) => { @@ -19503,14 +19958,14 @@ module.exports = createRedirectInterceptor /***/ }), -/***/ 6744: +/***/ 3626: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; -const utils_1 = __nccwpck_require__(7728); +const utils_1 = __nccwpck_require__(1746); // C headers var ERROR; (function (ERROR) { @@ -19788,7 +20243,7 @@ exports.SPECIAL_HEADERS = { /***/ }), -/***/ 7445: +/***/ 1931: /***/ ((module) => { module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=' @@ -19796,7 +20251,7 @@ module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn /***/ }), -/***/ 6442: +/***/ 271: /***/ ((module) => { module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==' @@ -19804,7 +20259,7 @@ module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn /***/ }), -/***/ 7728: +/***/ 1746: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -19826,14 +20281,14 @@ exports.enumToMap = enumToMap; /***/ }), -/***/ 8180: +/***/ 3667: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kClients } = __nccwpck_require__(1439) -const Agent = __nccwpck_require__(8162) +const { kClients } = __nccwpck_require__(7460) +const Agent = __nccwpck_require__(2438) const { kAgent, kMockAgentSet, @@ -19844,14 +20299,14 @@ const { kGetNetConnect, kOptions, kFactory -} = __nccwpck_require__(5056) -const MockClient = __nccwpck_require__(624) -const MockPool = __nccwpck_require__(3429) -const { matchValue, buildMockOptions } = __nccwpck_require__(2178) -const { InvalidArgumentError, UndiciError } = __nccwpck_require__(5767) -const Dispatcher = __nccwpck_require__(1312) -const Pluralizer = __nccwpck_require__(4615) -const PendingInterceptorsFormatter = __nccwpck_require__(2524) +} = __nccwpck_require__(631) +const MockClient = __nccwpck_require__(4927) +const MockPool = __nccwpck_require__(9726) +const { matchValue, buildMockOptions } = __nccwpck_require__(3713) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(51) +const Dispatcher = __nccwpck_require__(7978) +const Pluralizer = __nccwpck_require__(396) +const PendingInterceptorsFormatter = __nccwpck_require__(2443) class FakeWeakRef { constructor (value) { @@ -20005,15 +20460,15 @@ module.exports = MockAgent /***/ }), -/***/ 624: +/***/ 4927: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { promisify } = __nccwpck_require__(3837) -const Client = __nccwpck_require__(8224) -const { buildMockDispatch } = __nccwpck_require__(2178) +const Client = __nccwpck_require__(4256) +const { buildMockDispatch } = __nccwpck_require__(3713) const { kDispatches, kMockAgent, @@ -20022,10 +20477,10 @@ const { kOrigin, kOriginalDispatch, kConnected -} = __nccwpck_require__(5056) -const { MockInterceptor } = __nccwpck_require__(5666) -const Symbols = __nccwpck_require__(1439) -const { InvalidArgumentError } = __nccwpck_require__(5767) +} = __nccwpck_require__(631) +const { MockInterceptor } = __nccwpck_require__(4975) +const Symbols = __nccwpck_require__(7460) +const { InvalidArgumentError } = __nccwpck_require__(51) /** * MockClient provides an API that extends the Client to influence the mockDispatches. @@ -20072,13 +20527,13 @@ module.exports = MockClient /***/ }), -/***/ 463: +/***/ 2106: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { UndiciError } = __nccwpck_require__(5767) +const { UndiciError } = __nccwpck_require__(51) class MockNotMatchedError extends UndiciError { constructor (message) { @@ -20097,13 +20552,13 @@ module.exports = { /***/ }), -/***/ 5666: +/***/ 4975: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(2178) +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(3713) const { kDispatches, kDispatchKey, @@ -20111,9 +20566,9 @@ const { kDefaultTrailers, kContentLength, kMockDispatch -} = __nccwpck_require__(5056) -const { InvalidArgumentError } = __nccwpck_require__(5767) -const { buildURL } = __nccwpck_require__(6223) +} = __nccwpck_require__(631) +const { InvalidArgumentError } = __nccwpck_require__(51) +const { buildURL } = __nccwpck_require__(2014) /** * Defines the scope API for an interceptor reply @@ -20311,15 +20766,15 @@ module.exports.MockScope = MockScope /***/ }), -/***/ 3429: +/***/ 9726: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { promisify } = __nccwpck_require__(3837) -const Pool = __nccwpck_require__(9729) -const { buildMockDispatch } = __nccwpck_require__(2178) +const Pool = __nccwpck_require__(135) +const { buildMockDispatch } = __nccwpck_require__(3713) const { kDispatches, kMockAgent, @@ -20328,10 +20783,10 @@ const { kOrigin, kOriginalDispatch, kConnected -} = __nccwpck_require__(5056) -const { MockInterceptor } = __nccwpck_require__(5666) -const Symbols = __nccwpck_require__(1439) -const { InvalidArgumentError } = __nccwpck_require__(5767) +} = __nccwpck_require__(631) +const { MockInterceptor } = __nccwpck_require__(4975) +const Symbols = __nccwpck_require__(7460) +const { InvalidArgumentError } = __nccwpck_require__(51) /** * MockPool provides an API that extends the Pool to influence the mockDispatches. @@ -20378,7 +20833,7 @@ module.exports = MockPool /***/ }), -/***/ 5056: +/***/ 631: /***/ ((module) => { "use strict"; @@ -20409,21 +20864,21 @@ module.exports = { /***/ }), -/***/ 2178: +/***/ 3713: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { MockNotMatchedError } = __nccwpck_require__(463) +const { MockNotMatchedError } = __nccwpck_require__(2106) const { kDispatches, kMockAgent, kOriginalDispatch, kOrigin, kGetNetConnect -} = __nccwpck_require__(5056) -const { buildURL, nop } = __nccwpck_require__(6223) +} = __nccwpck_require__(631) +const { buildURL, nop } = __nccwpck_require__(2014) const { STATUS_CODES } = __nccwpck_require__(3685) const { types: { @@ -20768,7 +21223,7 @@ module.exports = { /***/ }), -/***/ 2524: +/***/ 2443: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -20816,7 +21271,7 @@ module.exports = class PendingInterceptorsFormatter { /***/ }), -/***/ 4615: +/***/ 396: /***/ ((module) => { "use strict"; @@ -20853,7 +21308,7 @@ module.exports = class Pluralizer { /***/ }), -/***/ 3408: +/***/ 4663: /***/ ((module) => { "use strict"; @@ -20978,16 +21433,16 @@ module.exports = class FixedQueue { /***/ }), -/***/ 1273: +/***/ 334: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const DispatcherBase = __nccwpck_require__(8188) -const FixedQueue = __nccwpck_require__(3408) -const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(1439) -const PoolStats = __nccwpck_require__(3860) +const DispatcherBase = __nccwpck_require__(854) +const FixedQueue = __nccwpck_require__(4663) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(7460) +const PoolStats = __nccwpck_require__(7236) const kClients = Symbol('clients') const kNeedDrain = Symbol('needDrain') @@ -21180,10 +21635,10 @@ module.exports = { /***/ }), -/***/ 3860: +/***/ 7236: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(1439) +const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(7460) const kPool = Symbol('pool') class PoolStats { @@ -21221,7 +21676,7 @@ module.exports = PoolStats /***/ }), -/***/ 9729: +/***/ 135: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -21233,14 +21688,14 @@ const { kNeedDrain, kAddClient, kGetDispatcher -} = __nccwpck_require__(1273) -const Client = __nccwpck_require__(8224) +} = __nccwpck_require__(334) +const Client = __nccwpck_require__(4256) const { InvalidArgumentError -} = __nccwpck_require__(5767) -const util = __nccwpck_require__(6223) -const { kUrl, kInterceptors } = __nccwpck_require__(1439) -const buildConnector = __nccwpck_require__(3311) +} = __nccwpck_require__(51) +const util = __nccwpck_require__(2014) +const { kUrl, kInterceptors } = __nccwpck_require__(7460) +const buildConnector = __nccwpck_require__(5599) const kOptions = Symbol('options') const kConnections = Symbol('connections') @@ -21323,19 +21778,19 @@ module.exports = Pool /***/ }), -/***/ 2498: +/***/ 6524: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(1439) +const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(7460) const { URL } = __nccwpck_require__(7310) -const Agent = __nccwpck_require__(8162) -const Pool = __nccwpck_require__(9729) -const DispatcherBase = __nccwpck_require__(8188) -const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(5767) -const buildConnector = __nccwpck_require__(3311) +const Agent = __nccwpck_require__(2438) +const Pool = __nccwpck_require__(135) +const DispatcherBase = __nccwpck_require__(854) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(51) +const buildConnector = __nccwpck_require__(5599) const kAgent = Symbol('proxy agent') const kClient = Symbol('proxy client') @@ -21394,6 +21849,9 @@ class ProxyAgent extends DispatcherBase { this[kProxyTls] = opts.proxyTls this[kProxyHeaders] = opts.headers || {} + const resolvedUrl = new URL(opts.uri) + const { origin, port, host, username, password } = resolvedUrl + if (opts.auth && opts.token) { throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') } else if (opts.auth) { @@ -21401,11 +21859,10 @@ class ProxyAgent extends DispatcherBase { this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` } else if (opts.token) { this[kProxyHeaders]['proxy-authorization'] = opts.token + } else if (username && password) { + this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` } - const resolvedUrl = new URL(opts.uri) - const { origin, port, host } = resolvedUrl - const connect = buildConnector({ ...opts.proxyTls }) this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) this[kClient] = clientFactory(resolvedUrl, { connect }) @@ -21429,7 +21886,7 @@ class ProxyAgent extends DispatcherBase { }) if (statusCode !== 200) { socket.on('error', () => {}).destroy() - callback(new RequestAbortedError('Proxy response !== 200 when HTTP Tunneling')) + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) } if (opts.protocol !== 'https:') { callback(null, socket) @@ -21518,7 +21975,7 @@ module.exports = ProxyAgent /***/ }), -/***/ 8581: +/***/ 1518: /***/ ((module) => { "use strict"; @@ -21623,27 +22080,27 @@ module.exports = { /***/ }), -/***/ 7610: +/***/ 3431: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const diagnosticsChannel = __nccwpck_require__(7643) -const { uid, states } = __nccwpck_require__(4009) +const { uid, states } = __nccwpck_require__(5044) const { kReadyState, kSentClose, kByteParser, kReceivedClose -} = __nccwpck_require__(4295) -const { fireEvent, failWebsocketConnection } = __nccwpck_require__(1310) -const { CloseEvent } = __nccwpck_require__(3458) -const { makeRequest } = __nccwpck_require__(8619) -const { fetching } = __nccwpck_require__(3360) -const { Headers } = __nccwpck_require__(7967) -const { getGlobalDispatcher } = __nccwpck_require__(398) -const { kHeadersList } = __nccwpck_require__(1439) +} = __nccwpck_require__(6437) +const { fireEvent, failWebsocketConnection } = __nccwpck_require__(1890) +const { CloseEvent } = __nccwpck_require__(7173) +const { makeRequest } = __nccwpck_require__(6814) +const { fetching } = __nccwpck_require__(3246) +const { Headers } = __nccwpck_require__(3767) +const { getGlobalDispatcher } = __nccwpck_require__(6223) +const { kHeadersList } = __nccwpck_require__(7460) const channels = {} channels.open = diagnosticsChannel.channel('undici:websocket:open') @@ -21922,7 +22379,7 @@ module.exports = { /***/ }), -/***/ 4009: +/***/ 5044: /***/ ((module) => { "use strict"; @@ -21981,14 +22438,14 @@ module.exports = { /***/ }), -/***/ 3458: +/***/ 7173: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { webidl } = __nccwpck_require__(5337) -const { kEnumerableProperty } = __nccwpck_require__(6223) +const { webidl } = __nccwpck_require__(8184) +const { kEnumerableProperty } = __nccwpck_require__(2014) const { MessagePort } = __nccwpck_require__(1267) /** @@ -22292,13 +22749,13 @@ module.exports = { /***/ }), -/***/ 9262: +/***/ 9537: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { maxUnsigned16Bit } = __nccwpck_require__(4009) +const { maxUnsigned16Bit } = __nccwpck_require__(5044) /** @type {import('crypto')} */ let crypto @@ -22373,7 +22830,7 @@ module.exports = { /***/ }), -/***/ 1213: +/***/ 1155: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -22381,10 +22838,10 @@ module.exports = { const { Writable } = __nccwpck_require__(2781) const diagnosticsChannel = __nccwpck_require__(7643) -const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(4009) -const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(4295) -const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(1310) -const { WebsocketFrameSend } = __nccwpck_require__(9262) +const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(5044) +const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(6437) +const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(1890) +const { WebsocketFrameSend } = __nccwpck_require__(9537) // This code was influenced by ws released under the MIT license. // Copyright (c) 2011 Einar Otto Stangvik @@ -22725,7 +23182,7 @@ module.exports = { /***/ }), -/***/ 4295: +/***/ 6437: /***/ ((module) => { "use strict"; @@ -22745,15 +23202,15 @@ module.exports = { /***/ }), -/***/ 1310: +/***/ 1890: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(4295) -const { states, opcodes } = __nccwpck_require__(4009) -const { MessageEvent, ErrorEvent } = __nccwpck_require__(3458) +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(6437) +const { states, opcodes } = __nccwpck_require__(5044) +const { MessageEvent, ErrorEvent } = __nccwpck_require__(7173) /* globals Blob */ @@ -22953,17 +23410,17 @@ module.exports = { /***/ }), -/***/ 6624: +/***/ 1917: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { webidl } = __nccwpck_require__(5337) -const { DOMException } = __nccwpck_require__(7213) -const { URLSerializer } = __nccwpck_require__(6822) -const { getGlobalOrigin } = __nccwpck_require__(4428) -const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(4009) +const { webidl } = __nccwpck_require__(8184) +const { DOMException } = __nccwpck_require__(3074) +const { URLSerializer } = __nccwpck_require__(834) +const { getGlobalOrigin } = __nccwpck_require__(4612) +const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(5044) const { kWebSocketURL, kReadyState, @@ -22972,13 +23429,13 @@ const { kResponse, kSentClose, kByteParser -} = __nccwpck_require__(4295) -const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(1310) -const { establishWebSocketConnection } = __nccwpck_require__(7610) -const { WebsocketFrameSend } = __nccwpck_require__(9262) -const { ByteParser } = __nccwpck_require__(1213) -const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(6223) -const { getGlobalDispatcher } = __nccwpck_require__(398) +} = __nccwpck_require__(6437) +const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(1890) +const { establishWebSocketConnection } = __nccwpck_require__(3431) +const { WebsocketFrameSend } = __nccwpck_require__(9537) +const { ByteParser } = __nccwpck_require__(1155) +const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(2014) +const { getGlobalDispatcher } = __nccwpck_require__(6223) const { types } = __nccwpck_require__(3837) let experimentalWarned = false @@ -23602,7 +24059,7 @@ module.exports = { /***/ }), -/***/ 8860: +/***/ 2228: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23666,29 +24123,29 @@ Object.defineProperty(exports, "parse", ({ } })); -var _v = _interopRequireDefault(__nccwpck_require__(2078)); +var _v = _interopRequireDefault(__nccwpck_require__(129)); -var _v2 = _interopRequireDefault(__nccwpck_require__(7788)); +var _v2 = _interopRequireDefault(__nccwpck_require__(7182)); -var _v3 = _interopRequireDefault(__nccwpck_require__(4205)); +var _v3 = _interopRequireDefault(__nccwpck_require__(9317)); -var _v4 = _interopRequireDefault(__nccwpck_require__(2795)); +var _v4 = _interopRequireDefault(__nccwpck_require__(7349)); -var _nil = _interopRequireDefault(__nccwpck_require__(2162)); +var _nil = _interopRequireDefault(__nccwpck_require__(6795)); -var _version = _interopRequireDefault(__nccwpck_require__(5315)); +var _version = _interopRequireDefault(__nccwpck_require__(2590)); -var _validate = _interopRequireDefault(__nccwpck_require__(6192)); +var _validate = _interopRequireDefault(__nccwpck_require__(9020)); -var _stringify = _interopRequireDefault(__nccwpck_require__(5354)); +var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); -var _parse = _interopRequireDefault(__nccwpck_require__(861)); +var _parse = _interopRequireDefault(__nccwpck_require__(3167)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), -/***/ 1755: +/***/ 4977: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23718,7 +24175,7 @@ exports["default"] = _default; /***/ }), -/***/ 2162: +/***/ 6795: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -23733,7 +24190,7 @@ exports["default"] = _default; /***/ }), -/***/ 861: +/***/ 3167: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23744,7 +24201,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(6192)); +var _validate = _interopRequireDefault(__nccwpck_require__(9020)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -23785,7 +24242,7 @@ exports["default"] = _default; /***/ }), -/***/ 4003: +/***/ 465: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -23800,7 +24257,7 @@ exports["default"] = _default; /***/ }), -/***/ 8795: +/***/ 8707: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23831,7 +24288,7 @@ function rng() { /***/ }), -/***/ 3899: +/***/ 4315: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23861,7 +24318,7 @@ exports["default"] = _default; /***/ }), -/***/ 5354: +/***/ 3174: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23872,7 +24329,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(6192)); +var _validate = _interopRequireDefault(__nccwpck_require__(9020)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -23907,7 +24364,7 @@ exports["default"] = _default; /***/ }), -/***/ 2078: +/***/ 129: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -23918,9 +24375,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(8795)); +var _rng = _interopRequireDefault(__nccwpck_require__(8707)); -var _stringify = _interopRequireDefault(__nccwpck_require__(5354)); +var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24021,7 +24478,7 @@ exports["default"] = _default; /***/ }), -/***/ 7788: +/***/ 7182: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24032,9 +24489,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(9629)); +var _v = _interopRequireDefault(__nccwpck_require__(4803)); -var _md = _interopRequireDefault(__nccwpck_require__(1755)); +var _md = _interopRequireDefault(__nccwpck_require__(4977)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24044,7 +24501,7 @@ exports["default"] = _default; /***/ }), -/***/ 9629: +/***/ 4803: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24056,9 +24513,9 @@ Object.defineProperty(exports, "__esModule", ({ exports["default"] = _default; exports.URL = exports.DNS = void 0; -var _stringify = _interopRequireDefault(__nccwpck_require__(5354)); +var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); -var _parse = _interopRequireDefault(__nccwpck_require__(861)); +var _parse = _interopRequireDefault(__nccwpck_require__(3167)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24129,7 +24586,7 @@ function _default(name, version, hashfunc) { /***/ }), -/***/ 4205: +/***/ 9317: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24140,9 +24597,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(8795)); +var _rng = _interopRequireDefault(__nccwpck_require__(8707)); -var _stringify = _interopRequireDefault(__nccwpck_require__(5354)); +var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24173,7 +24630,7 @@ exports["default"] = _default; /***/ }), -/***/ 2795: +/***/ 7349: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24184,9 +24641,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(9629)); +var _v = _interopRequireDefault(__nccwpck_require__(4803)); -var _sha = _interopRequireDefault(__nccwpck_require__(3899)); +var _sha = _interopRequireDefault(__nccwpck_require__(4315)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24196,7 +24653,7 @@ exports["default"] = _default; /***/ }), -/***/ 6192: +/***/ 9020: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24207,7 +24664,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _regex = _interopRequireDefault(__nccwpck_require__(4003)); +var _regex = _interopRequireDefault(__nccwpck_require__(465)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24220,7 +24677,7 @@ exports["default"] = _default; /***/ }), -/***/ 5315: +/***/ 2590: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24231,7 +24688,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(6192)); +var _validate = _interopRequireDefault(__nccwpck_require__(9020)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24472,7 +24929,7 @@ module.exports = require("zlib"); /***/ }), -/***/ 3186: +/***/ 2899: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -24481,10 +24938,10 @@ module.exports = require("zlib"); const WritableStream = (__nccwpck_require__(4492).Writable) const inherits = (__nccwpck_require__(7261).inherits) -const StreamSearch = __nccwpck_require__(3331) +const StreamSearch = __nccwpck_require__(482) -const PartStream = __nccwpck_require__(5785) -const HeaderParser = __nccwpck_require__(8981) +const PartStream = __nccwpck_require__(953) +const HeaderParser = __nccwpck_require__(8757) const DASH = 45 const B_ONEDASH = Buffer.from('-') @@ -24687,7 +25144,7 @@ module.exports = Dicer /***/ }), -/***/ 8981: +/***/ 8757: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -24695,9 +25152,9 @@ module.exports = Dicer const EventEmitter = (__nccwpck_require__(5673).EventEmitter) const inherits = (__nccwpck_require__(7261).inherits) -const getLimit = __nccwpck_require__(4323) +const getLimit = __nccwpck_require__(2173) -const StreamSearch = __nccwpck_require__(3331) +const StreamSearch = __nccwpck_require__(482) const B_DCRLF = Buffer.from('\r\n\r\n') const RE_CRLF = /\r\n/g @@ -24795,7 +25252,7 @@ module.exports = HeaderParser /***/ }), -/***/ 5785: +/***/ 953: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -24816,7 +25273,7 @@ module.exports = PartStream /***/ }), -/***/ 3331: +/***/ 482: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25052,7 +25509,7 @@ module.exports = SBMH /***/ }), -/***/ 1702: +/***/ 9638: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25060,11 +25517,11 @@ module.exports = SBMH const WritableStream = (__nccwpck_require__(4492).Writable) const { inherits } = __nccwpck_require__(7261) -const Dicer = __nccwpck_require__(3186) +const Dicer = __nccwpck_require__(2899) -const MultipartParser = __nccwpck_require__(7435) -const UrlencodedParser = __nccwpck_require__(8604) -const parseParams = __nccwpck_require__(2693) +const MultipartParser = __nccwpck_require__(3045) +const UrlencodedParser = __nccwpck_require__(3005) +const parseParams = __nccwpck_require__(2124) function Busboy (opts) { if (!(this instanceof Busboy)) { return new Busboy(opts) } @@ -25145,7 +25602,7 @@ module.exports.Dicer = Dicer /***/ }), -/***/ 7435: +/***/ 3045: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25161,12 +25618,12 @@ module.exports.Dicer = Dicer const { Readable } = __nccwpck_require__(4492) const { inherits } = __nccwpck_require__(7261) -const Dicer = __nccwpck_require__(3186) +const Dicer = __nccwpck_require__(2899) -const parseParams = __nccwpck_require__(2693) -const decodeText = __nccwpck_require__(9464) -const basename = __nccwpck_require__(1628) -const getLimit = __nccwpck_require__(4323) +const parseParams = __nccwpck_require__(2124) +const decodeText = __nccwpck_require__(7941) +const basename = __nccwpck_require__(8708) +const getLimit = __nccwpck_require__(2173) const RE_BOUNDARY = /^boundary$/i const RE_FIELD = /^form-data$/i @@ -25459,15 +25916,15 @@ module.exports = Multipart /***/ }), -/***/ 8604: +/***/ 3005: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Decoder = __nccwpck_require__(8660) -const decodeText = __nccwpck_require__(9464) -const getLimit = __nccwpck_require__(4323) +const Decoder = __nccwpck_require__(1361) +const decodeText = __nccwpck_require__(7941) +const getLimit = __nccwpck_require__(2173) const RE_CHARSET = /^charset$/i @@ -25657,7 +26114,7 @@ module.exports = UrlEncoded /***/ }), -/***/ 8660: +/***/ 1361: /***/ ((module) => { "use strict"; @@ -25719,7 +26176,7 @@ module.exports = Decoder /***/ }), -/***/ 1628: +/***/ 8708: /***/ ((module) => { "use strict"; @@ -25741,7 +26198,7 @@ module.exports = function basename (path) { /***/ }), -/***/ 9464: +/***/ 7941: /***/ (function(module) { "use strict"; @@ -25863,7 +26320,7 @@ module.exports = decodeText /***/ }), -/***/ 4323: +/***/ 2173: /***/ ((module) => { "use strict"; @@ -25887,14 +26344,14 @@ module.exports = function getLimit (limits, name, defaultLimit) { /***/ }), -/***/ 2693: +/***/ 2124: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; /* eslint-disable object-property-newline */ -const decodeText = __nccwpck_require__(9464) +const decodeText = __nccwpck_require__(7941) const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g @@ -26139,10 +26596,12 @@ const archList = [{ arch: x86_64, runner: 'ubuntu-latest', docker_tag: 'manylinux2014_x86_64-plugins-deps', + asset_tag: 'manylinux2014_x86_64', }, { arch: aarch64, runner: 'linux-arm64', docker_tag: 'manylinux2014_aarch64-plugins-deps', + asset_tag: 'manylinux2014_aarch64', }]; const pluginList = [{ @@ -26192,7 +26651,7 @@ let expandVariables = () => { return ret; }; -const core = __nccwpck_require__(2619); +const core = __nccwpck_require__(4136); try { output = JSON.stringify(expandVariables()); diff --git a/.github/actions/expand-variables/main.js b/.github/actions/expand-variables/main.js index 5a393dedb59b..adce1e1b0601 100644 --- a/.github/actions/expand-variables/main.js +++ b/.github/actions/expand-variables/main.js @@ -5,10 +5,12 @@ const archList = [{ arch: x86_64, runner: 'ubuntu-latest', docker_tag: 'manylinux2014_x86_64-plugins-deps', + asset_tag: 'manylinux2014_x86_64', }, { arch: aarch64, runner: 'linux-arm64', docker_tag: 'manylinux2014_aarch64-plugins-deps', + asset_tag: 'manylinux2014_aarch64', }]; const pluginList = [{ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1105a8e174b0..7ed7c19b33ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -73,8 +73,8 @@ jobs: with: version: ${{ needs.create_release.outputs.version }} matrix: - "[{'name':'manylinux 2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64'}, - {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" + "[{'name':'manylinux 2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64','asset_tag':'manylinux2014_x86_64'}, + {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64','asset_tag':'manylinux2014_aarch64'}]" release: true secrets: inherit diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index 423f683fa8a2..faf54b521afd 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -12,6 +12,9 @@ on: docker_tag: type: string required: true + asset_tag: + type: string + required: true plugins: type: string required: true @@ -103,7 +106,7 @@ jobs: steps: - id: prep run: | - echo "artifact=WasmEdge-plugin-${{ matrix.plugin }}-${{ inputs.version }}-${{ inputs.docker_tag }}.tar.gz" >> $GITHUB_OUTPUT + echo "artifact=WasmEdge-plugin-${{ matrix.plugin }}-${{ inputs.version }}-${{ inputs.asset_tag }}.tar.gz" >> $GITHUB_OUTPUT echo "filename=plugin_${{ matrix.plugin }}.tar.gz" >> $GITHUB_OUTPUT - uses: actions/cache/restore@v3 with: diff --git a/.github/workflows/reusable-build-extensions.yml b/.github/workflows/reusable-build-extensions.yml index 9da37f86e882..043d115f2985 100644 --- a/.github/workflows/reusable-build-extensions.yml +++ b/.github/workflows/reusable-build-extensions.yml @@ -35,6 +35,7 @@ jobs: arch: ${{ matrix.arch }} runner: ${{ matrix.runner }} docker_tag: ${{ matrix.docker_tag }} + asset_tag: ${{ matrix.asset_tag }} plugins: ${{ toJSON(matrix.plugins) }} version: ${{ inputs.version }} release: ${{ inputs.release }} From 30c3efadbd49eac5bd52636d4fe69575596bf205 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Tue, 5 Mar 2024 22:00:10 +0800 Subject: [PATCH 084/218] [Changelog] Update the changelog for the 0.14.0-alpha.3 pre-release. (#3258) Signed-off-by: YiYing He --- .CurrentChangelog.md | 8 ++++---- Changelog.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index 53ccc9ec510d..af005deb6b62 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.2 (2024-02-23) +### 0.14.0-alpha.3 (2024-03-05) Breaking changes: @@ -72,7 +72,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2230. + * Bump llama.cpp to b2334. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -123,6 +123,6 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-alpha.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 04389b1e84f4..6aab0962d3b2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.2 (2024-02-23) +### 0.14.0-alpha.3 (2024-03-05) Breaking changes: @@ -72,7 +72,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2230. + * Bump llama.cpp to b2334. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -123,9 +123,9 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hydai, richzw, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-alpha.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 2f455d9e3c9f5aaaa9d030ecb0a2f85e8416c25c Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 7 Mar 2024 11:21:04 +0800 Subject: [PATCH 085/218] [Installer] Support WasmEdge rustls plugin installation on the manylinux2014 aarch64 (#3262) Signed-off-by: hydai --- ...ckerfile.manylinux2014_plugins_deps_x86_64 | 24 +++++++++++++++++++ utils/install.py | 1 + 2 files changed, 25 insertions(+) create mode 100644 utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 diff --git a/utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 b/utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 new file mode 100644 index 000000000000..f3a89549b0a3 --- /dev/null +++ b/utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +ARG BASE=wasmedge/wasmedge:manylinux2014_x86_64 +ARG BUILDPLATFORM=x86_64 +FROM --platform=$BUILDPLATFORM ${BASE} + +MAINTAINER hydai hydai@secondstate.io + +ADD install-opencvmini.sh /root/ + +ENV PATH=/opt/rh/devtoolset-11/root/usr/bin${PATH:+:${PATH}} +ENV MANPATH=/opt/rh/devtoolset-11/root/usr/share/man${MANPATH:+:${MANPATH}} +ENV INFOPATH=/opt/rh/devtoolset-11/root/usr/share/info${INFOPATH:+:${INFOPATH}} +ENV PKG_CONFIG_PATH=/opt/rh/devtoolset-11/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} +ENV OPENCV_VERSION=4.8.0 + +WORKDIR /root/ + +RUN yum update -y \ + && yum install -y zlib-devel zlib-static cmake wget unzip \ + && bash /root/install-opencvmini.sh + +RUN yum clean all diff --git a/utils/install.py b/utils/install.py index 716c9e213293..4759f2a0ef4a 100644 --- a/utils/install.py +++ b/utils/install.py @@ -403,6 +403,7 @@ def compare(self, version2, separator=". |-", ignorecase=True): "ubuntu20.04" + "x86_64" + WASMEDGE_IMAGE_PLUGIN: VersionString("0.13.0"), "darwin" + "x86_64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), "darwin" + "arm64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), + "manylinux2014" + "aarch64" + WASMEDGE_RUSTLS: VersionString("0.13.5"), "manylinux2014" + "x86_64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), "ubuntu20.04" + "x86_64" + WASMEDGE_RUSTLS: VersionString("0.13.4"), "ubuntu20.04" + "aarch64" + WASMEDGE_RUSTLS: VersionString("0.13.5"), From cc6e61bb7a775931527ecffa017492a330457caf Mon Sep 17 00:00:00 2001 From: Charlie chan Date: Sat, 9 Mar 2024 00:05:18 +0800 Subject: [PATCH 086/218] [Docs] remove typo charctor '=' in readme file (#3268) Signed-off-by: chen zhengwei <13811807139@163.com> Co-authored-by: chen zhengwei <13811807139@163.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 388642e477a4..3df8dfa191a6 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ WasmEdge and its contained wasm program can be started from the [CLI](https://wa * [Embed WasmEdge into a host application](https://wasmedge.org/docs/embed/overview) * [Orchestrate and manage WasmEdge instances using container tools](https://wasmedge.org/docs/category/deploy-wasmedge-apps-in-kubernetes) * [Run a WasmEdge app as a Dapr microservice](https://wasmedge.org/docs/develop/rust/dapr) -= + # Community From b40f500713b730e5505ddc66c0c0858e42442b53 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Tue, 12 Mar 2024 00:37:38 +0800 Subject: [PATCH 087/218] [Plugin] Prevent from loading the same name plugin. (#3263) Signed-off-by: YiYing He --- lib/plugin/plugin.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/plugin/plugin.cpp b/lib/plugin/plugin.cpp index 0c403bc59f80..28c44a3be3f1 100644 --- a/lib/plugin/plugin.cpp +++ b/lib/plugin/plugin.cpp @@ -69,8 +69,6 @@ class CAPIPluginRegister { CAPIPluginRegister &operator=(const CAPIPluginRegister &) = delete; CAPIPluginRegister(const WasmEdge_PluginDescriptor *Desc) noexcept { - IncreaseNiftyCounter(); - ModuleDescriptions.resize(Desc->ModuleCount); for (size_t I = 0; I < ModuleDescriptions.size(); ++I) { ModuleDescriptions[I].Name = Desc->ModuleDescriptions[I].Name; @@ -352,7 +350,12 @@ bool Plugin::loadFile(const std::filesystem::path &Path) noexcept { if (auto GetDescriptor = Lib->get("GetDescriptor")) { - Plugin::registerPlugin(GetDescriptor()); + if (find(GetDescriptor()->Name)) { + spdlog::debug("Plugin: {} has already loaded."sv, GetDescriptor()->Name); + return true; + } else { + Plugin::registerPlugin(GetDescriptor()); + } } if (PluginRegistry.size() != Index + 1) { @@ -365,8 +368,13 @@ bool Plugin::loadFile(const std::filesystem::path &Path) noexcept { unlikely(!Descriptor)) { return false; } else { - CAPIPluginRegisters.push_back( - std::make_unique(Descriptor)); + if (find(Descriptor->Name)) { + spdlog::debug("Plugin: {} has already loaded."sv, Descriptor->Name); + return true; + } else { + CAPIPluginRegisters.push_back( + std::make_unique(Descriptor)); + } } } @@ -398,12 +406,13 @@ Span Plugin::plugins() noexcept { return PluginRegistry; } WASMEDGE_EXPORT void Plugin::registerPlugin(const PluginDescriptor *Desc) noexcept { - IncreaseNiftyCounter(); - assuming(NiftyCounter != 0); if (Desc->APIVersion != CurrentAPIVersion) { return; } + IncreaseNiftyCounter(); + assuming(NiftyCounter != 0); + const auto Index = PluginRegistry.size(); PluginRegistry.emplace_back(Desc); PluginNameLookup.emplace(Desc->Name, Index); From 54a79964de8e11c2cf3a1e65e9d4258bf1de5973 Mon Sep 17 00:00:00 2001 From: Hrushikesh Date: Tue, 12 Mar 2024 10:00:32 +0530 Subject: [PATCH 088/218] [Plugin] Initial support for FFmpeg (#2885) * added ffmpeg to cmake Signed-off-by: Hrushi20 * error.h and avformat.h file functions Signed-off-by: Hrushi20 * fix compile error Signed-off-by: Hrushi20 * avFormatContext, avInputFormat struct fields Signed-off-by: Hrushi20 * av_best_stream, stream, mediaType Signed-off-by: Hrushi20 * avCodec, avCodecParameters, AVCodecID Signed-off-by: Hrushi20 * avRational Signed-off-by: Hrushi20 * AVPixelFormat,AVFrame Signed-off-by: Hrushi20 * clean code, refactor Signed-off-by: Hrushi20 refactor Signed-off-by: Hrushi20 * avfilter, swscale Signed-off-by: Hrushi20 * bug fix Signed-off-by: Hrushi20 * init test Signed-off-by: Hrushi20 * naming plugin Signed-off-by: Hrushi20 * AVSample Signed-off-by: Hrushi20 * AVFrame, ChannelLayout Signed-off-by: Hrushi20 * added index while fetching data AVFrame Signed-off-by: Hrushi20 * AVRational Tests Signed-off-by: Hrushi20 * swscale tests init Signed-off-by: Hrushi20 * SwsFilter, SwsVector Signed-off-by: Hrushi20 swsvector Signed-off-by: Hrushi20 * swscale tests Signed-off-by: Hrushi20 * bug fix Signed-off-by: Hrushi20 * swresample init, swresample funcs Signed-off-by: Hrushi20 added swresample funcs Signed-off-by: Hrushi20 * swresample test Signed-off-by: Hrushikesh Rao Signed-off-by: Hrushi20 * refactor based on code style, add ffmpeg to github workflow Signed-off-by: Hrushi20 added plugin to workflow Signed-off-by: Hrushi20 added option Signed-off-by: Hrushi20 * swresample util functions Signed-off-by: Hrushi20 * added avChapters, avfilter version Signed-off-by: Hrushi20 * init avDictionary Signed-off-by: Hrushi20 * build ffmpeg, liniting, add ffmpeg dependencies Signed-off-by: Hrushi20 build ffmpeg Signed-off-by: Hrushi20 added ffmpeg dependency Signed-off-by: Hrushi20 added ffmpeg dependency Signed-off-by: Hrushi20 * AvDictionary functions Signed-off-by: Hrushi20 * download sample_video_file for test Signed-off-by: Hrushi20 * AVDictionary tests Signed-off-by: Hrushi20 * init avdevice Signed-off-by: Hrushi20 * AVInputFormat, AVOutputFormat funcs Signed-off-by: Hrushi20 * avformat tests init Signed-off-by: Hrushi20 * AvChapter tests Signed-off-by: Hrushi20 * AVChapterMut functions Signed-off-by: Hrushi20 * fixed AVChapter Metatdata bug Signed-off-by: Hrushi20 * AVStream, AVStreamMut functions Signed-off-by: Hrushi20 * init/deinit network func Signed-off-by: Hrushi20 * AVStream and AVStreamMut functions Signed-off-by: Hrushi20 * AVFormatCtx Input/Output functions Signed-off-by: Hrushi20 * AvFormatCtxStruct Test funcs Signed-off-by: Hrushi20 * AVFormat Functions test Signed-off-by: Hrushi20 * Bindings for AVPictureType, AVOptionType, AVRounding, AVColor, AVChromaLocation Signed-off-by: Hrushi20 * AVTime funcs Signed-off-by: Hrushi20 * AVFrame funcs Signed-off-by: Hrushi20 * AVRounding funcs Signed-off-by: Hrushi20 * Util to initialize AVFrame in test, AVFrame tests Init Signed-off-by: Hrushi20 * AVUtil Tests added Signed-off-by: Hrushi20 * install ffmpeg dependency, nasm Signed-off-by: Hrushi20 nasm dependency Signed-off-by: Hrushi20 * update ffmpeg cmake file Signed-off-by: Hrushi20 * AVcodecCtx Video Encoder funcs Signed-off-by: Hrushi20 * AVCodecCtx Video funcs, AVSendFrame Funcs, AVReceivePkt funcs Signed-off-by: Hrushi20 * AVCodec funs Signed-off-by: Hrushi20 * AVPacket funcs, Remux funcs Signed-off-by: Hrushi20 * null checks when setting AVDict Signed-off-by: Hrushi20 * AVCodecCtx funs for Encoder Signed-off-by: Hrushi20 * AVCodecCtx decoder funcs Signed-off-by: Hrushi20 * version, config, license, fetching strings(color, pixfmt,samplefmt) Signed-off-by: Hrushi20 * AVPacket Data, AVColorPrimaries bindings Signed-off-by: Hrushi20 * AVDict Null checks, AVUtil tests Signed-off-by: Hrushi20 * Swscale tests refactor Signed-off-by: Hrushi20 * AVCodec,AVCodecParameters Test Signed-off-by: Hrushi20 * AVPacket tests Signed-off-by: Hrushi20 * AVCodec funcs test init Signed-off-by: Hrushi20 * AVCodecCtx tests Signed-off-by: Hrushi20 AVCodecCtx tests Signed-off-by: Hrushi20 * AVcodec tests Signed-off-by: Hrushi20 * AVFilter funcs Signed-off-by: Hrushi20 * AVCodecId bindings updated Signed-off-by: Hrushi20 * Enhancements/bug fixes Signed-off-by: Hrushi20 * refactor swresample tests Signed-off-by: Hrushi20 * AVFilter tests Signed-off-by: Hrushi20 Filter module tests added Signed-off-by: Hrushi20 * uncomment cmake files Signed-off-by: Hrushi20 * ffmpeg tests refactor Signed-off-by: Hrushi20 * Update install-ffmpeg script, remove relative imports, update workflow Signed-off-by: Hrushi20 import header files utils.cpp Signed-off-by: Hrushi20 brew to install ffmpeg, indentation Signed-off-by: Hrushi20 update install-ffmpeg script Signed-off-by: Hrushi20 attempt to fix PKG_CONFIG_PATH Signed-off-by: Hrushi20 attempt to fix install-ffmpeg.sh script Signed-off-by: Hrushi20 attempt to fix install-ffmpeg.sh script Signed-off-by: Hrushi20 avformat_func tests, install-ffmpeg bash script Signed-off-by: Hrushi20 update workflow file, cmake styles Signed-off-by: Hrushi20 remove relative path in tests Signed-off-by: Hrushi20 * AVFrame Audio Funcs, AVCodecFuncs Signed-off-by: Hrushi20 * Added mutex lock Signed-off-by: Hrushi20 * comment avcodec_func tests, added AVInputFormat Tests Signed-off-by: Hrushi20 * fix swscale test Signed-off-by: Hrushi20 * ChLayoutMask, SampleFmtMask, PixelMask, AVCodecFunc tests uncommented Signed-off-by: Hrushi20 * Fix CI build Signed-off-by: Hrushi20 comment avcodec_open2 test Signed-off-by: Hrushi20 comment few avcodec_func tests Signed-off-by: Hrushi20 size of malloc function, replace avdict malloc to calloc Signed-off-by: Hrushi20 attempt to fix linux build Signed-off-by: Hrushi20 fix ffmpeg lib path error Signed-off-by: Hrushi20 uncomment send packet/receive frame test, added dummy file video Signed-off-by: Hrushi20 disable gmock, fix spell-check Signed-off-by: Hrushi20 fix linter bug Signed-off-by: Hrushi20 attempt fix linux build error Signed-off-by: Hrushi20 attempt fix linux build error Signed-off-by: Hrushi20 * swscale, sampleFmt, avCodec tests Signed-off-by: Hrushi20 * use nullptr, added sv to end of string, remove unwanted spaces, update code style Signed-off-by: Hrushi20 * initialize length with 0, type casting using const_cast, uncomment avframe_data test Signed-off-by: Hrushi20 * replace memmove() with std::copy_n() Signed-off-by: Hrushi20 * replace malloc -> av_malloc, calloc -> av_mallocz Signed-off-by: Hrushi20 * fix code format Signed-off-by: Hrushi20 * added TODO to missing tests Signed-off-by: Hrushi20 * update github workflow file Signed-off-by: Hrushi20 * fix ffmpeg CI build in release mode Signed-off-by: Hrushi20 * added yasm dependency Signed-off-by: Hrushi20 * remove yasm dependency arch Signed-off-by: Hrushi20 * enable gmock Signed-off-by: Hrushi20 * comment avcodec tests Signed-off-by: Hrushi20 * uncomment avfilter tests Signed-off-by: Hrushi20 * uncomment swresample/swscale Signed-off-by: Hrushi20 * uncomment avformat tests Signed-off-by: Hrushi20 * uncomment avPacket/avCodecCtx/avCodecParameters Signed-off-by: Hrushi20 * uncomment avcodec_func Signed-off-by: Hrushi20 * attempt to fix avcodec_func tests Signed-off-by: Hrushi20 * attempt to fix avCodec tests Signed-off-by: Hrushi20 * uncomment avcodec_func tests Signed-off-by: Hrushi20 * fix coding style, decouple plugin registration Signed-off-by: Hrushi20 * build fix manylinux Signed-off-by: Hrushi20 * reasoning for av_guess_codec Signed-off-by: Hrushi20 * fix variable format, initialize variable value, append sv to string literals Signed-off-by: Hrushi20 * Trigger Build Signed-off-by: Hrushi20 * fix code style, remove redundant imports Signed-off-by: Hrushi20 * fix av_read_frame test, logging in av_format test Signed-off-by: Hrushi20 * credit for sample_video in test Signed-off-by: Hrushi20 --------- Signed-off-by: Hrushi20 Signed-off-by: Hrushikesh Rao --- .github/workflows/build-extensions.yml | 57 +- .github/workflows/ignore_words | 2 + .github/workflows/release.yml | 47 +- CMakeLists.txt | 1 + cmake/Helper.cmake | 6 +- plugins/CMakeLists.txt | 9 +- plugins/wasmedge_ffmpeg/CMakeLists.txt | 88 + plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp | 241 + plugins/wasmedge_ffmpeg/avcodec/avCodec.h | 163 + .../avcodec/avCodecContext.cpp | 859 ++++ .../wasmedge_ffmpeg/avcodec/avCodecContext.h | 816 +++ .../avcodec/avCodecParameters.cpp | 38 + .../avcodec/avCodecParameters.h | 39 + plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp | 189 + plugins/wasmedge_ffmpeg/avcodec/avPacket.h | 173 + .../wasmedge_ffmpeg/avcodec/avcodec_base.h | 24 + .../wasmedge_ffmpeg/avcodec/avcodec_func.cpp | 338 ++ .../wasmedge_ffmpeg/avcodec/avcodec_func.h | 245 + plugins/wasmedge_ffmpeg/avcodec/module.cpp | 361 ++ plugins/wasmedge_ffmpeg/avcodec/module.h | 19 + .../wasmedge_ffmpeg/avdevice/avDevice_base.h | 25 + .../avdevice/avDevice_func.cpp | 124 + .../wasmedge_ffmpeg/avdevice/avDevice_func.h | 127 + plugins/wasmedge_ffmpeg/avdevice/module.cpp | 38 + plugins/wasmedge_ffmpeg/avdevice/module.h | 19 + plugins/wasmedge_ffmpeg/avfilter/avFilter.cpp | 149 + plugins/wasmedge_ffmpeg/avfilter/avFilter.h | 120 + .../wasmedge_ffmpeg/avfilter/avfilter_base.h | 25 + .../avfilter/avfilter_func.cpp | 300 ++ .../wasmedge_ffmpeg/avfilter/avfilter_func.h | 207 + .../avfilter/buffer_source_sink.cpp | 68 + .../avfilter/buffer_source_sink.h | 67 + plugins/wasmedge_ffmpeg/avfilter/module.cpp | 108 + plugins/wasmedge_ffmpeg/avfilter/module.h | 19 + .../wasmedge_ffmpeg/avformat/avChapter.cpp | 196 + plugins/wasmedge_ffmpeg/avformat/avChapter.h | 103 + .../avformat/avInputOutputFormat.cpp | 215 + .../avformat/avInputOutputFormat.h | 144 + plugins/wasmedge_ffmpeg/avformat/avStream.cpp | 285 ++ plugins/wasmedge_ffmpeg/avformat/avStream.h | 152 + .../avformat/avformatContext.cpp | 122 + .../avformat/avformatContext.h | 99 + .../wasmedge_ffmpeg/avformat/avformat_base.h | 25 + .../avformat/avformat_func.cpp | 383 ++ .../wasmedge_ffmpeg/avformat/avformat_func.h | 273 + plugins/wasmedge_ffmpeg/avformat/module.cpp | 193 + plugins/wasmedge_ffmpeg/avformat/module.h | 19 + .../wasmedge_ffmpeg/avutil/avDictionary.cpp | 159 + plugins/wasmedge_ffmpeg/avutil/avDictionary.h | 59 + plugins/wasmedge_ffmpeg/avutil/avFrame.cpp | 464 ++ plugins/wasmedge_ffmpeg/avutil/avFrame.h | 404 ++ plugins/wasmedge_ffmpeg/avutil/avRational.cpp | 169 + plugins/wasmedge_ffmpeg/avutil/avRational.h | 107 + plugins/wasmedge_ffmpeg/avutil/avTime.cpp | 32 + plugins/wasmedge_ffmpeg/avutil/avTime.h | 42 + plugins/wasmedge_ffmpeg/avutil/avutil_base.h | 25 + .../wasmedge_ffmpeg/avutil/avutil_func.cpp | 142 + plugins/wasmedge_ffmpeg/avutil/avutil_func.h | 208 + plugins/wasmedge_ffmpeg/avutil/error.cpp | 39 + plugins/wasmedge_ffmpeg/avutil/error.h | 36 + plugins/wasmedge_ffmpeg/avutil/module.cpp | 263 + plugins/wasmedge_ffmpeg/avutil/module.h | 19 + plugins/wasmedge_ffmpeg/avutil/pixfmt.cpp | 174 + plugins/wasmedge_ffmpeg/avutil/pixfmt.h | 132 + plugins/wasmedge_ffmpeg/avutil/samplefmt.cpp | 134 + plugins/wasmedge_ffmpeg/avutil/samplefmt.h | 105 + plugins/wasmedge_ffmpeg/bindings.h | 4425 +++++++++++++++++ plugins/wasmedge_ffmpeg/ffmpeg_env.cpp | 112 + plugins/wasmedge_ffmpeg/ffmpeg_env.h | 110 + plugins/wasmedge_ffmpeg/swresample/module.cpp | 40 + plugins/wasmedge_ffmpeg/swresample/module.h | 20 + .../swresample/swresample_base.h | 25 + .../swresample/swresample_func.cpp | 126 + .../swresample/swresample_func.h | 107 + plugins/wasmedge_ffmpeg/swscale/module.cpp | 74 + plugins/wasmedge_ffmpeg/swscale/module.h | 19 + .../wasmedge_ffmpeg/swscale/swscale_base.h | 25 + .../wasmedge_ffmpeg/swscale/swscale_func.cpp | 298 ++ .../wasmedge_ffmpeg/swscale/swscale_func.h | 226 + test/CMakeLists.txt | 30 +- test/plugins/CMakeLists.txt | 8 +- test/plugins/wasmedge_ffmpeg/CMakeLists.txt | 74 + .../wasmedge_ffmpeg/avcodec/avCodec.cpp | 365 ++ .../wasmedge_ffmpeg/avcodec/avCodecCtx.cpp | 1657 ++++++ .../avcodec/avCodecParameters.cpp | 75 + .../wasmedge_ffmpeg/avcodec/avPacket.cpp | 368 ++ .../wasmedge_ffmpeg/avcodec/avcodec_func.cpp | 574 +++ .../wasmedge_ffmpeg/avfilter/avfilter.cpp | 287 ++ .../avfilter/avfilter_func.cpp | 682 +++ .../wasmedge_ffmpeg/avformat/avChapter.cpp | 220 + .../avformat/avInputOutputContext.cpp | 207 + .../wasmedge_ffmpeg/avformat/avStream.cpp | 303 ++ .../avformat/avformatContext.cpp | 184 + .../avformat/avformat_func.cpp | 588 +++ .../wasmedge_ffmpeg/avutil/avDictionary.cpp | 151 + .../wasmedge_ffmpeg/avutil/avError.cpp | 65 + .../wasmedge_ffmpeg/avutil/avFrame.cpp | 781 +++ .../wasmedge_ffmpeg/avutil/avPixfmt.cpp | 244 + .../wasmedge_ffmpeg/avutil/avRational.cpp | 313 ++ .../wasmedge_ffmpeg/avutil/avSampleFmt.cpp | 201 + .../wasmedge_ffmpeg/avutil/avutil_func.cpp | 261 + test/plugins/wasmedge_ffmpeg/main.cpp | 6 + .../swresample/swresample_func.cpp | 255 + .../wasmedge_ffmpeg/swscale/swscale_func.cpp | 540 ++ test/plugins/wasmedge_ffmpeg/utils.cpp | 259 + test/plugins/wasmedge_ffmpeg/utils.h | 164 + utils/ffmpeg/download-ffmpeg-sample-video.sh | 22 + utils/ffmpeg/install-ffmpeg-v6.0.sh | 13 + 108 files changed, 24486 insertions(+), 51 deletions(-) create mode 100644 plugins/wasmedge_ffmpeg/CMakeLists.txt create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avCodec.h create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avCodecContext.cpp create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avCodecContext.h create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.h create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avPacket.h create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avcodec_base.h create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/avcodec/avcodec_func.h create mode 100644 plugins/wasmedge_ffmpeg/avcodec/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/avcodec/module.h create mode 100644 plugins/wasmedge_ffmpeg/avdevice/avDevice_base.h create mode 100644 plugins/wasmedge_ffmpeg/avdevice/avDevice_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/avdevice/avDevice_func.h create mode 100644 plugins/wasmedge_ffmpeg/avdevice/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/avdevice/module.h create mode 100644 plugins/wasmedge_ffmpeg/avfilter/avFilter.cpp create mode 100644 plugins/wasmedge_ffmpeg/avfilter/avFilter.h create mode 100644 plugins/wasmedge_ffmpeg/avfilter/avfilter_base.h create mode 100644 plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/avfilter/avfilter_func.h create mode 100644 plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.cpp create mode 100644 plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.h create mode 100644 plugins/wasmedge_ffmpeg/avfilter/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/avfilter/module.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/avChapter.cpp create mode 100644 plugins/wasmedge_ffmpeg/avformat/avChapter.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.cpp create mode 100644 plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/avStream.cpp create mode 100644 plugins/wasmedge_ffmpeg/avformat/avStream.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp create mode 100644 plugins/wasmedge_ffmpeg/avformat/avformatContext.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/avformat_base.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/avformat/avformat_func.h create mode 100644 plugins/wasmedge_ffmpeg/avformat/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/avformat/module.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/avDictionary.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/avFrame.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/avFrame.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/avRational.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/avRational.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/avTime.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/avTime.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/avutil_base.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/avutil_func.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/error.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/error.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/module.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/pixfmt.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/pixfmt.h create mode 100644 plugins/wasmedge_ffmpeg/avutil/samplefmt.cpp create mode 100644 plugins/wasmedge_ffmpeg/avutil/samplefmt.h create mode 100644 plugins/wasmedge_ffmpeg/bindings.h create mode 100644 plugins/wasmedge_ffmpeg/ffmpeg_env.cpp create mode 100644 plugins/wasmedge_ffmpeg/ffmpeg_env.h create mode 100644 plugins/wasmedge_ffmpeg/swresample/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/swresample/module.h create mode 100644 plugins/wasmedge_ffmpeg/swresample/swresample_base.h create mode 100644 plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/swresample/swresample_func.h create mode 100644 plugins/wasmedge_ffmpeg/swscale/module.cpp create mode 100644 plugins/wasmedge_ffmpeg/swscale/module.h create mode 100644 plugins/wasmedge_ffmpeg/swscale/swscale_base.h create mode 100644 plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp create mode 100644 plugins/wasmedge_ffmpeg/swscale/swscale_func.h create mode 100644 test/plugins/wasmedge_ffmpeg/CMakeLists.txt create mode 100644 test/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avcodec/avCodecCtx.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avfilter/avfilter.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avformat/avInputOutputContext.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avformat/avStream.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avError.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avPixfmt.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avRational.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avSampleFmt.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/main.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/utils.cpp create mode 100644 test/plugins/wasmedge_ffmpeg/utils.h create mode 100644 utils/ffmpeg/download-ffmpeg-sample-video.sh create mode 100755 utils/ffmpeg/install-ffmpeg-v6.0.sh diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index a498924804b1..bffc1aa6c611 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -97,7 +97,7 @@ jobs: OPENVINO_YEAR: "2023" PYTORCH_VERSION: "1.8.2" PYTORCH_INSTALL_TO: "." - needs: [get_version] + needs: [ get_version ] container: image: wasmedge/wasmedge:${{ matrix.docker_tag }} steps: @@ -192,11 +192,11 @@ jobs: env: output_prefix: build/plugins test_prefix: build/test/plugins - build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON - tar_names: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasm_bpf wasmedge_opencvmini wasmedge_zlib - test_bins: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmBpfTests wasmedgeOpencvminiTests wasmedgeZlibTests - output_bins: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmBpf.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeZlib.so - needs: [get_version] + build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON -DWASMEDGE_PLUGIN_FFMPEG=ON + tar_names: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasm_bpf wasmedge_opencvmini wasmedge_zlib wasmedge_ffmpeg + test_bins: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmBpfTests wasmedgeOpencvminiTests wasmedgeZlibTests wasmedgeFFmpegTests + output_bins: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmBpf.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeZlib.so libwasmedgePluginWasmEdgeFFmpeg.so + needs: [ get_version ] container: image: wasmedge/wasmedge:${{ matrix.docker_tag }} # Required for mounting debugfs @@ -213,14 +213,17 @@ jobs: apt install -y libelf-dev zlib1g-dev pkg-config apt install -y clang-15 apt install -y cargo + apt install -y yasm # Running tests of wasm_bpf requires proper ebpf running environment mount -t debugfs none /sys/kernel/debug + bash utils/ffmpeg/install-ffmpeg-v6.0.sh - name: Build plugins using ${{ matrix.compiler }} with ${{ matrix.build_type }} mode shell: bash run: | update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 100 update-alternatives --install /usr/bin/llvm-strip llvm-strip /usr/bin/llvm-strip-15 100 testbin_array=(${test_bins}) + export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} for (( i=0; i<${#testbin_array[@]}; i++ )); do @@ -230,6 +233,7 @@ jobs: - name: Test plugins shell: bash run: | + export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH plugin_array=(${tar_names}) testbin_array=(${test_bins}) for (( i=0; i<${#plugin_array[@]}; i++ )); @@ -295,6 +299,11 @@ jobs: with: name: WasmEdge-plugin-wasmedge_zlib-${{ needs.get_version.outputs.version }}-ubuntu22.04-${{ matrix.compiler }}.tar.gz path: plugin_wasmedge_zlib.tar.gz + - name: Upload artifact - wasmedge_ffmpeg + uses: actions/upload-artifact@v3 + with: + name: WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.get_version.outputs.version }}-ubuntu22.04-${{ matrix.compiler }}.tar.gz + path: plugin_wasmedge_ffmpeg.tar.gz # Due to the dependencies and exclusions of WASI-NN, build them saperately. build_wasinn_manylinux: @@ -327,19 +336,19 @@ jobs: env: output_prefix: build/plugins test_prefix: build/test/plugins - build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON + build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_FFMPEG=ON build_options_manylinux2014_x86_64: -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF build_options_manylinux2014_aarch64: - tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini + tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_ffmpeg tar_names_manylinux2014_x86_64: wasm_bpf tar_names_manylinux2014_aarch64: - test_bins_all_platforms: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests + test_bins_all_platforms: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests wasmedgeFFmpegTests test_bins_manylinux2014_x86_64: wasmBpfTests test_bins_manylinux2014_aarch64: - output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so + output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeFFmpeg.so output_bins_manylinux2014_x86_64: libwasmedgePluginWasmBpf.so output_bins_manylinux2014_aarch64: - needs: [get_version] + needs: [ get_version ] container: image: wasmedge/wasmedge:${{ matrix.docker_tag }} # Required for mounting debugfs @@ -357,11 +366,13 @@ jobs: bash ./utils/wasi-crypto/build-openssl.sh # Running tests of wasm_bpf requires proper ebpf running environment mount -t debugfs none /sys/kernel/debug + bash utils/ffmpeg/install-ffmpeg-v6.0.sh - name: Build and test plugins using g++ with ${{ matrix.build_type }} mode shell: bash run: | source "$HOME/.cargo/env" testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.asset_tag }}}) + export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.asset_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl for (( i=0; i<${#testbin_array[@]}; i++ )); do @@ -371,6 +382,7 @@ jobs: - name: Test plugins shell: bash run: | + export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.asset_tag }}}) for (( i=0; i<${#plugin_array[@]}; i++ )); @@ -438,6 +450,12 @@ jobs: name: WasmEdge-plugin-wasmedge_zlib-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz path: plugin_wasmedge_zlib.tar.gz + - name: Upload artifact - wasmedge_ffmpeg + uses: actions/upload-artifact@v3 + with: + name: WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + path: plugin_wasmedge_ffmpeg.tar.gz + build_macos: permissions: contents: write @@ -461,11 +479,11 @@ jobs: env: output_prefix: build/plugins test_prefix: build/test/plugins - build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON - tar_names: wasi_crypto wasi_logging wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini - test_bins: wasiCryptoTests wasiLoggingTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests - output_bins: libwasmedgePluginWasiCrypto.dylib libwasmedgePluginWasiLogging.dylib libwasmedgePluginWasmEdgeTensorflow.dylib libwasmedgePluginWasmEdgeTensorflowLite.dylib libwasmedgePluginWasmEdgeImage.dylib libwasmedgePluginWasmEdgeOpenCVMini.dylib - needs: [get_version] + build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_FFMPEG=ON + tar_names: wasi_crypto wasi_logging wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_ffmpeg + test_bins: wasiCryptoTests wasiLoggingTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests wasmedgeFFmpegTests + output_bins: libwasmedgePluginWasiCrypto.dylib libwasmedgePluginWasiLogging.dylib libwasmedgePluginWasmEdgeTensorflow.dylib libwasmedgePluginWasmEdgeTensorflowLite.dylib libwasmedgePluginWasmEdgeImage.dylib libwasmedgePluginWasmEdgeOpenCVMini.dylib libwasmedgePluginWasmEdgeFFmpeg.dylib + needs: [ get_version ] steps: - uses: actions/checkout@v3 with: @@ -473,7 +491,7 @@ jobs: - name: Build and install dependencies run: | eval $(/opt/homebrew/bin/brew shellenv) - brew install llvm@16 ninja cmake openssl opencv rust + brew install llvm@16 ninja cmake openssl opencv rust ffmpeg@6 - name: Build WasmEdge plugins using clang++ with ${{ matrix.build_type }} mode shell: bash run: | @@ -547,3 +565,8 @@ jobs: with: name: WasmEdge-plugin-wasmedge_opencvmini-${{ needs.get_version.outputs.version }}-${{ matrix.darwin_version }}_${{ matrix.arch }}.tar.gz path: plugin_wasmedge_opencvmini.tar.gz + - name: Upload artifact - wasmedge_ffmpeg + uses: actions/upload-artifact@v3 + with: + name: WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.get_version.outputs.version }}-${{ matrix.darwin_version }}_${{ matrix.arch }}.tar.gz + path: plugin_wasmedge_ffmpeg.tar.gz diff --git a/.github/workflows/ignore_words b/.github/workflows/ignore_words index 3e6db4519ce6..135b899353a1 100644 --- a/.github/workflows/ignore_words +++ b/.github/workflows/ignore_words @@ -17,3 +17,5 @@ unexpect cript wit createor +inout +anull \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7ed7c19b33ef..31102f8e4270 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -206,9 +206,9 @@ jobs: runs-on: ubuntu-latest env: output_prefix: build/plugins - build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON - tar_names: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasm_bpf wasmedge_opencvmini wasmedge_zlib - output_bins: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmBpf.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeZlib.so + build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON -DWASMEDGE_PLUGIN_FFMPEG=ON + tar_names: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasm_bpf wasmedge_opencvmini wasmedge_zlib wasmedge_ffmpeg + output_bins: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmBpf.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeZlib.so libwasmedgePluginWasmEdgeFFmpeg.so needs: create_release container: image: wasmedge/wasmedge:ubuntu-build-clang-plugins-deps @@ -226,10 +226,13 @@ jobs: apt install -y libssl-dev cmake g++ wget unzip apt install -y libelf-dev zlib1g-dev pkg-config apt install -y cargo + apt install -y yasm + bash utils/ffmpeg/install-ffmpeg-v6.0.sh - name: Build plugins shell: bash run: | outbin_array=(${output_bins}) + export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options} for (( i=0; i<${#outbin_array[@]}; i++ )); do @@ -242,6 +245,7 @@ jobs: - name: Prepare the plugins tar.gz package shell: bash run: | + export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH plugin_array=(${tar_names}) outbin_array=(${output_bins}) for (( i=0; i<${#plugin_array[@]}; i++ )); @@ -312,6 +316,12 @@ jobs: run: | mv plugin_wasmedge_zlib.tar.gz WasmEdge-plugin-wasmedge_zlib-${{ needs.create_release.outputs.version }}-ubuntu20.04_x86_64.tar.gz gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_zlib-${{ needs.create_release.outputs.version }}-ubuntu20.04_x86_64.tar.gz --clobber + - name: Upload wasmedge_ffmpeg plugin tar.gz package + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mv plugin_wasmedge_ffmpeg.tar.gz WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-ubuntu20.04_x86_64.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-ubuntu20.04_x86_64.tar.gz --clobber build_and_upload_wasinn_manylinux: name: Build and upload WASI-NN on manylinux @@ -338,13 +348,13 @@ jobs: runs-on: ${{ matrix.host_runner }} env: output_prefix: build/plugins - build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON + build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_FFMPEG=ON build_options_manylinux2014_x86_64: -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF build_options_manylinux2014_aarch64: - tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini + tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_ffmpeg tar_names_manylinux2014_x86_64: wasm_bpf tar_names_manylinux2014_aarch64: - output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so + output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeFFmpeg.so output_bins_manylinux2014_x86_64: libwasmedgePluginWasmBpf.so output_bins_manylinux2014_aarch64: needs: create_release @@ -365,11 +375,13 @@ jobs: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y source "$HOME/.cargo/env" bash ./utils/wasi-crypto/build-openssl.sh + bash utils/ffmpeg/install-ffmpeg-v6.0.sh - name: Build plugins shell: bash run: | source "$HOME/.cargo/env" outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) + export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.asset_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl for (( i=0; i<${#outbin_array[@]}; i++ )); do @@ -382,6 +394,7 @@ jobs: - name: Prepare the plugins tar.gz package shell: bash run: | + export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) for (( i=0; i<${#plugin_array[@]}; i++ )); @@ -444,6 +457,12 @@ jobs: run: | mv plugin_wasmedge_opencvmini.tar.gz WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber + - name: Upload wasmedge_ffmpeg plugin tar.gz package + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mv plugin_wasmedge_ffmpeg.tar.gz WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber build_and_upload_plugin_macos: strategy: @@ -463,9 +482,9 @@ jobs: runs-on: ${{ matrix.host_runner }} env: output_prefix: build/plugins - build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON - tar_names: wasi_crypto wasi_logging wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_zlib - output_bins: libwasmedgePluginWasiCrypto.dylib libwasmedgePluginWasiLogging.dylib libwasmedgePluginWasmEdgeTensorflow.dylib libwasmedgePluginWasmEdgeTensorflowLite.dylib libwasmedgePluginWasmEdgeImage.dylib libwasmedgePluginWasmEdgeOpenCVMini.dylib libwasmedgePluginWasmEdgeZlib.dylib + build_options: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_ZLIB=ON -DWASMEDGE_PLUGIN_FFMPEG=ON + tar_names: wasi_crypto wasi_logging wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_zlib wasmedge_ffmpeg + output_bins: libwasmedgePluginWasiCrypto.dylib libwasmedgePluginWasiLogging.dylib libwasmedgePluginWasmEdgeTensorflow.dylib libwasmedgePluginWasmEdgeTensorflowLite.dylib libwasmedgePluginWasmEdgeImage.dylib libwasmedgePluginWasmEdgeOpenCVMini.dylib libwasmedgePluginWasmEdgeZlib.dylib libwasmedgePluginWasmEdgeFFmpeg.dylib needs: create_release steps: - name: Checkout code @@ -478,7 +497,7 @@ jobs: - name: Install dependencies run: | eval $(/opt/homebrew/bin/brew shellenv) - brew install llvm@16 ninja cmake openssl wabt opencv rust gh + brew install llvm@16 ninja cmake openssl wabt opencv rust gh ffmpeg@6 - name: Build plugins shell: bash run: | @@ -556,6 +575,12 @@ jobs: eval $(/opt/homebrew/bin/brew shellenv) mv plugin_wasmedge_zlib.tar.gz WasmEdge-plugin-wasmedge_zlib-${{ needs.create_release.outputs.version }}-darwin_${{ matrix.arch }}.tar.gz gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_zlib-${{ needs.create_release.outputs.version }}-darwin_${{ matrix.arch }}.tar.gz --clobber + - name: Upload wasmedge_ffmpeg plugin tar.gz package + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mv plugin_wasmedge_ffmpeg.tar.gz WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-darwin_${{ matrix.arch }}.tar.gz + gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-darwin_${{ matrix.arch }}.tar.gz --clobber build_manylinux2014_runtime_only: name: Build runtime only on manylinux2014 platform @@ -601,7 +626,7 @@ jobs: include_bin: "--include-bin /usr/local/bin/wasmedge" name: Build DockerSlim Images needs: - [create_release, build_on_manylinux2014, build_manylinux2014_runtime_only] + [ create_release, build_on_manylinux2014, build_manylinux2014_runtime_only ] runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/CMakeLists.txt b/CMakeLists.txt index b086de24959f..e0dd01ae3034 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,7 @@ option(WASMEDGE_PLUGIN_TENSORFLOWLITE "Enable WasmEdge TensorFlow-Lite plugin." option(WASMEDGE_PLUGIN_RUSTLS "Enable WasmEdge Rustls plugin." OFF) option(WASMEDGE_PLUGIN_ZLIB "Enable WasmEdge zlib plugin." OFF) option(WASMEDGE_DISABLE_LIBTINFO "Disable linking against libtinfo when linking LLVM" OFF) +option(WASMEDGE_PLUGIN_FFMPEG "Enable WasmEdge ffmpeg plugin." OFF) if(WASMEDGE_BUILD_TOOLS AND WASMEDGE_BUILD_FUZZING) message(FATAL_ERROR "wasmedge tool and fuzzing tool are exclusive options.") diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 9dcd7d2065fc..5fcea2587db0 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -103,7 +103,7 @@ endif() if(WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DNOMINMAX -D_ITERATOR_DEBUG_LEVEL=0) - if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") list(APPEND WASMEDGE_CFLAGS -Wno-c++98-compat -Wno-c++98-compat-pedantic @@ -128,7 +128,7 @@ function(wasmedge_setup_target target) set_target_properties(${target} PROPERTIES CXX_STANDARD 17 CXX_EXTENSIONS OFF - CXX_VISIBILITY_PRESET hidden + # CXX_VISIBILITY_PRESET hidden ENABLE_EXPORTS ON POSITION_INDEPENDENT_CODE ON VISIBILITY_INLINES_HIDDEN ON @@ -235,7 +235,7 @@ if((WASMEDGE_LINK_LLVM_STATIC OR WASMEDGE_BUILD_STATIC_LIB) AND WASMEDGE_USE_LLV ${LLVM_LIBRARY_DIR}/liblldWasm.a ) endif() - if (APPLE AND LLVM_VERSION_MAJOR GREATER_EQUAL 15) + if(APPLE AND LLVM_VERSION_MAJOR GREATER_EQUAL 15) # For LLVM 15 or greater on MacOS find_package(zstd REQUIRED) get_filename_component(ZSTD_PATH "${zstd_LIBRARY}" DIRECTORY) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 91b64909b3f5..8de19e705cf4 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -57,7 +57,7 @@ endif() if(WASMEDGE_PLUGIN_WASI_OCR) add_subdirectory(wasi_ocr) endif() - + if(WASMEDGE_PLUGIN_OPENCVMINI) # Only Linux and MacOS support wasmedge_opencvmini now. if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") @@ -77,5 +77,8 @@ endif() if(WASMEDGE_PLUGIN_ZLIB) add_subdirectory(wasmedge_zlib) - -endif() \ No newline at end of file +endif() + +if(WASMEDGE_PLUGIN_FFMPEG) + add_subdirectory(wasmedge_ffmpeg) +endif() diff --git a/plugins/wasmedge_ffmpeg/CMakeLists.txt b/plugins/wasmedge_ffmpeg/CMakeLists.txt new file mode 100644 index 000000000000..e78dcaa83149 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/CMakeLists.txt @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +find_package(PkgConfig REQUIRED) +pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET + libavdevice + libavfilter + libavformat + libavcodec + libswresample + libswscale + libavutil +) + +wasmedge_add_library(wasmedgePluginWasmEdgeFFmpeg + SHARED + ffmpeg_env.cpp + + avcodec/module.cpp + avcodec/avcodec_func.cpp + avcodec/avCodecContext.cpp + avcodec/avCodec.cpp + avcodec/avCodecParameters.cpp + avcodec/avPacket.cpp + + avdevice/module.cpp + avdevice/avDevice_func.cpp + + avfilter/module.cpp + avfilter/avfilter_func.cpp + avfilter/buffer_source_sink.cpp + avfilter/avFilter.cpp + + avformat/module.cpp + avformat/avformat_func.cpp + avformat/avformatContext.cpp + avformat/avInputOutputFormat.cpp + avformat/avStream.cpp + avformat/avChapter.cpp + + avutil/module.cpp + avutil/avutil_func.cpp + avutil/error.cpp + avutil/avRational.cpp + avutil/avFrame.cpp + avutil/pixfmt.cpp + avutil/samplefmt.cpp + avutil/avDictionary.cpp + avutil/avTime.cpp + + swresample/module.cpp + swresample/swresample_func.cpp + + swscale/module.cpp + swscale/swscale_func.cpp + +) + +target_compile_options(wasmedgePluginWasmEdgeFFmpeg + PUBLIC + -DWASMEDGE_PLUGIN + -Wno-deprecated-declarations +) + +target_include_directories(wasmedgePluginWasmEdgeFFmpeg + PUBLIC + $ + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(wasmedgePluginWasmEdgeFFmpeg + PUBLIC + PkgConfig::LIBAV +) + +if(WASMEDGE_LINK_PLUGINS_STATIC) + target_link_libraries(wasmedgePluginWasmEdgeFFmpeg + PRIVATE + wasmedgeCAPI + ) +else() + target_link_libraries(wasmedgePluginWasmEdgeFFmpeg + PRIVATE + wasmedge_shared + ) +endif() + +install(TARGETS wasmedgePluginWasmEdgeFFmpeg DESTINATION ${CMAKE_INSTALL_LIBDIR}/wasmedge) diff --git a/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp b/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp new file mode 100644 index 000000000000..242ccab043d1 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp @@ -0,0 +1,241 @@ +#include "avCodec.h" + +extern "C" { +#include "libavcodec/avcodec.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +Expect AVCodecID::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return FFmpegUtils::CodecID::fromAVCodecID(AvCodec->id); +} + +Expect AVCodecType::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return FFmpegUtils::MediaType::fromMediaType(AvCodec->type); +} + +Expect AVCodecMaxLowres::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return AvCodec->max_lowres; +} + +Expect AVCodecCapabilities::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return AvCodec->capabilities; +} + +Expect AVCodecGetNameLen::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return strlen(AvCodec->name); +} + +Expect AVCodecGetName::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecId, uint32_t NamePtr, + uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + + const char *Name = AvCodec->name; + std::copy_n(Name, NameLen, NameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVCodecGetLongNameLen::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return strlen(AvCodec->long_name); +} + +Expect AVCodecGetLongName::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecId, + uint32_t LongNamePtr, + uint32_t LongNameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LongNameBuf, MemInst, char, LongNamePtr, LongNameLen, ""); + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + + const char *LongName = AvCodec->long_name; + std::copy_n(LongName, LongNameLen, LongNameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVCodecProfiles::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + if (AvCodec->profiles) + return 1; + return 0; +} + +Expect AVCodecPixFmtsIsNull::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + if (AvCodec->pix_fmts == nullptr) + return 1; + return 0; +} + +Expect AVCodecPixFmtsIter::body(const Runtime::CallingFrame &, + uint32_t AvCodecId, uint32_t Idx) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + AVPixelFormat const *PixelFormat = AvCodec->pix_fmts; + if (PixelFormat == nullptr) + return 0; + + uint32_t Curr = 0; + while (Curr < Idx) { + PixelFormat++; + Curr++; + } + + return FFmpegUtils::PixFmt::fromAVPixFmt(*PixelFormat); +} + +Expect +AVCodecSupportedFrameratesIsNull::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + if (AvCodec->supported_framerates == nullptr) + return 1; + return 0; +} + +Expect +AVCodecSupportedFrameratesIter::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecId, uint32_t Idx, + uint32_t NumPtr, uint32_t DenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(NumId, MemInst, int32_t, NumPtr, + "Failed when accessing the return NumPtr Memory"sv); + MEM_PTR_CHECK(DenId, MemInst, int32_t, DenPtr, + "Failed when accessing the return DenPtr Memory"sv); + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + AVRational const *Rational = AvCodec->supported_framerates; + + if (Rational == nullptr) { + *NumId = 0; + *DenId = 0; + return static_cast(ErrNo::Success); + } + + uint32_t Curr = 0; + while (Curr < Idx) { + Rational++; + Curr++; + } + + *NumId = Rational->num; + *DenId = Rational->den; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecSupportedSampleRatesIsNull::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + if (AvCodec->supported_samplerates == nullptr) + return 1; + return 0; +} + +Expect +AVCodecSupportedSampleRatesIter::body(const Runtime::CallingFrame &, + uint32_t AvCodecId, uint32_t Idx) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + const int32_t *SampleRates = AvCodec->supported_samplerates; + if (SampleRates == nullptr) + return 0; + + uint32_t Curr = 0; + while (Curr < Idx) { + SampleRates++; + Curr++; + } + + return *SampleRates; +} + +Expect AVCodecChannelLayoutIsNull::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + if (AvCodec->channel_layouts == nullptr) + return 1; + return 0; +} + +Expect AVCodecChannelLayoutIter::body(const Runtime::CallingFrame &, + uint32_t AvCodecId, + uint32_t Idx) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + const uint64_t *ChannelLayout = AvCodec->channel_layouts; + if (ChannelLayout == nullptr) + return 0; + + uint32_t Curr = 0; + while (Curr < Idx) { + ChannelLayout++; + Curr++; + } + + return FFmpegUtils::ChannelLayout::intoChannelLayoutID(*ChannelLayout); +} + +Expect AVCodecSampleFmtsIsNull::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + if (AvCodec->sample_fmts == nullptr) + return 1; + return 0; +} + +Expect AVCodecSampleFmtsIter::body(const Runtime::CallingFrame &, + uint32_t AvCodecId, uint32_t Idx) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + AVSampleFormat const *SampleFormat = AvCodec->sample_fmts; + if (SampleFormat == nullptr) + return 0; + + uint32_t Curr = 0; + while (Curr < Idx) { + SampleFormat++; + Curr++; + } + + return FFmpegUtils::SampleFmt::toSampleID(*SampleFormat); +} + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avCodec.h b/plugins/wasmedge_ffmpeg/avcodec/avCodec.h new file mode 100644 index 000000000000..da1b5fab1fc3 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avCodec.h @@ -0,0 +1,163 @@ +#pragma once +#include "avcodec_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +class AVCodecID : public WasmEdgeFFmpegAVCodec { +public: + AVCodecID(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecType : public WasmEdgeFFmpegAVCodec { +public: + AVCodecType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecMaxLowres : public WasmEdgeFFmpegAVCodec { +public: + AVCodecMaxLowres(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecCapabilities : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCapabilities(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecGetNameLen : public WasmEdgeFFmpegAVCodec { +public: + AVCodecGetNameLen(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecGetName : public WasmEdgeFFmpegAVCodec { +public: + AVCodecGetName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t NamePtr, uint32_t NameLen); +}; + +class AVCodecGetLongNameLen + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecGetLongNameLen(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecGetLongName : public WasmEdgeFFmpegAVCodec { +public: + AVCodecGetLongName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t LongNamePtr, uint32_t LongNameLen); +}; + +class AVCodecProfiles : public WasmEdgeFFmpegAVCodec { +public: + AVCodecProfiles(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecPixFmtsIsNull + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecPixFmtsIsNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecPixFmtsIter : public WasmEdgeFFmpegAVCodec { +public: + AVCodecPixFmtsIter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t Idx); +}; + +class AVCodecSupportedFrameratesIsNull + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSupportedFrameratesIsNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecSupportedFrameratesIter + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSupportedFrameratesIter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t Idx, uint32_t NumPtr, uint32_t DenPtr); +}; + +class AVCodecSupportedSampleRatesIsNull + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSupportedSampleRatesIsNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecSupportedSampleRatesIter + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSupportedSampleRatesIter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t Idx); +}; + +class AVCodecChannelLayoutIsNull + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecChannelLayoutIsNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecChannelLayoutIter + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecChannelLayoutIter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t Idx); +}; + +class AVCodecSampleFmtsIsNull + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSampleFmtsIsNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecSampleFmtsIter + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSampleFmtsIter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t Idx); +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avCodecContext.cpp b/plugins/wasmedge_ffmpeg/avcodec/avCodecContext.cpp new file mode 100644 index 000000000000..b766ae781add --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avCodecContext.cpp @@ -0,0 +1,859 @@ +#include "avCodecContext.h" + +extern "C" { +#include "libavcodec/avcodec.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +Expect AVCodecCtxCodecID::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVCodecID const AvCodecId = AvCodecCtx->codec_id; + return FFmpegUtils::CodecID::fromAVCodecID(AvCodecId); +} + +Expect AVCodecCtxCodecType::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVMediaType const AvMediaType = AvCodecCtx->codec_type; + return FFmpegUtils::MediaType::fromMediaType(AvMediaType); +} + +Expect AVCodecCtxSetCodecType::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t CodecTypeId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVMediaType const AvMediaType = + FFmpegUtils::MediaType::intoMediaType(CodecTypeId); + + AvCodecCtx->codec_type = AvMediaType; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetTimebase::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t Num, + int32_t Den) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVRational const Rational = av_make_q(Num, Den); + AvCodecCtx->time_base = Rational; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxTimeBase::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t NumPtr, + uint32_t DenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVRational const AvRational = AvCodecCtx->time_base; + *Num = AvRational.num; + *Den = AvRational.den; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxWidth::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->width; +} + +Expect AVCodecCtxSetWidth::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t Width) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->width = Width; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxHeight::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->height; +} + +Expect AVCodecCtxSetHeight::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Height) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->height = Height; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSampleAspectRatio::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t NumPtr, + uint32_t DenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + + const AVRational AvRational = AvCodecCtx->sample_aspect_ratio; + *Num = AvRational.num; + *Den = AvRational.den; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetSampleAspectRatio::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t Num, + int32_t Den) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + const AVRational AspectRatio = av_make_q(Num, Den); + AvCodecCtx->sample_aspect_ratio = AspectRatio; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxChannelLayout::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + // Deprecated method + uint64_t const AvChannel = AvCodecCtx->channel_layout; + return FFmpegUtils::ChannelLayout::intoChannelLayoutID(AvChannel); +} + +Expect AVCodecCtxSetChannelLayout::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint64_t ChannelLayoutId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + uint64_t const AvChannel = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutId); + AvCodecCtx->channel_layout = AvChannel; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxPixFormat::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVPixelFormat const PixFmt = AvCodecCtx->pix_fmt; + return FFmpegUtils::PixFmt::fromAVPixFmt(PixFmt); +} + +Expect AVCodecCtxSetPixFormat::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint32_t PixFmtId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVPixelFormat const PixFmt = FFmpegUtils::PixFmt::intoAVPixFmt(PixFmtId); + AvCodecCtx->pix_fmt = PixFmt; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSampleFormat::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVSampleFormat const AvSampleFormat = AvCodecCtx->sample_fmt; + return FFmpegUtils::SampleFmt::toSampleID(AvSampleFormat); +} + +Expect AVCodecCtxSetSampleFormat::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint32_t SampleFmtId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVSampleFormat const SampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFmtId); + AvCodecCtx->sample_fmt = SampleFormat; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSampleRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->sample_rate; +} + +Expect AVCodecCtxSetSampleRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t SampleRate) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->sample_rate = SampleRate; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetGopSize::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t GopSize) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->gop_size = GopSize; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMaxBFrames::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MaxBFrames) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->max_b_frames = MaxBFrames; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetBQuantFactor::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float BQuantFactor) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->b_quant_factor = BQuantFactor; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetBQuantOffset::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float BQuantOffset) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->b_quant_offset = BQuantOffset; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetIQuantFactor::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float IQuantFactor) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->i_quant_factor = IQuantFactor; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetIQuantOffset::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float IQuantOffset) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->i_quant_offset = IQuantOffset; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetLumiMasking::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float LumiMasking) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->lumi_masking = LumiMasking; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetTemporalCplxMasking::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float TemporalCplxMasking) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->temporal_cplx_masking = TemporalCplxMasking; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetSpatialCplxMasking::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float SpatialCplxMasking) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->spatial_cplx_masking = SpatialCplxMasking; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetPMasking::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float PMasking) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->p_masking = PMasking; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetDarkMasking::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + float DarkMasking) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->dark_masking = DarkMasking; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMeCmp::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t MeCmp) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->me_cmp = MeCmp; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMeSubCmp::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MeSubCmp) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->me_sub_cmp = MeSubCmp; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMbCmp::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t MbCmp) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->mb_cmp = MbCmp; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetIldctCmp::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t IldctCmp) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->ildct_cmp = IldctCmp; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetDiaSize::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t DiaSize) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->dia_size = DiaSize; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetLastPredictorsCount::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t LastPredictorCount) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->last_predictor_count = LastPredictorCount; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMePreCmp::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MePreCmp) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->me_pre_cmp = MePreCmp; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetPreDiaSize::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t PreDiaSize) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->pre_dia_size = PreDiaSize; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetMeSubpelQuality::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MeSubpelQuality) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->me_subpel_quality = MeSubpelQuality; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMeRange::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MeRange) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->me_range = MeRange; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMbDecision::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MbDecision) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->mb_decision = MbDecision; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMbLMin::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MbLMin) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->mb_lmin = MbLMin; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetMbLMax::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t MbLMax) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->mb_lmax = MbLMax; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxIntraDcPrecision::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->intra_dc_precision; +} + +Expect +AVCodecCtxSetIntraDcPrecision::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t IntraDcPrecision) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->intra_dc_precision = IntraDcPrecision; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetQMin::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t QMin) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->qmin = QMin; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetQMax::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t QMax) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->qmax = QMax; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetGlobalQuality::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t GlobalQuality) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->global_quality = GlobalQuality; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetColorspace::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ColorspaceId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVColorSpace const ColorSpace = + FFmpegUtils::ColorSpace::intoAVColorSpace(ColorspaceId); + AvCodecCtx->colorspace = ColorSpace; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxColorspace::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVColorSpace const Colorspace = AvCodecCtx->colorspace; + return FFmpegUtils::ColorSpace::fromAVColorSpace(Colorspace); +} + +Expect AVCodecCtxSetColorRange::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ColorRangeId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->color_range = static_cast(ColorRangeId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxColorRange::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVColorRange const ColorRange = AvCodecCtx->color_range; + return static_cast(ColorRange); +} + +Expect AVCodecCtxFrameSize::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->frame_size; +} + +Expect AVCodecCtxBitRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->bit_rate; +} + +Expect AVCodecCtxSetBitRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int64_t BitRate) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->bit_rate = BitRate; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxRcMaxRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->rc_max_rate; +} + +Expect AVCodecCtxSetRcMaxRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int64_t RcMaxRate) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->rc_max_rate = RcMaxRate; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetBitRateTolerance::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t BitRateTolerance) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->bit_rate_tolerance = BitRateTolerance; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetCompressionLevel::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t CompressionLevel) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->compression_level = CompressionLevel; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxFrameRate::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, + uint32_t NumPtr, uint32_t DenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + + AVRational const FrameRate = AvCodecCtx->framerate; + *Num = FrameRate.num; + *Den = FrameRate.den; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetFrameRate::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t Num, + int32_t Den) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVRational const Rational = av_make_q(Num, Den); + AvCodecCtx->framerate = Rational; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetFlags::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t Flags) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->flags = Flags; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetStrictStdCompliance::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ComplianceId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->strict_std_compliance = ComplianceId; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetDebug::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, int32_t Debug) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->debug = Debug; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxCodec::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, + uint32_t AvCodecPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AVCodecId, MemInst, uint32_t, AvCodecPtr, + "Failed to access Ptr for AvCodecPtr"sv); + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvCodec, *AVCodecId, const AVCodec); + + AvCodec = AvCodecCtx->codec; + if (AvCodec == nullptr) + return -1; + + FFMPEG_PTR_STORE(const_cast(AvCodec), AVCodecId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxChannels::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->channels; +} + +Expect AVCodecCtxSetChannels::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Channels) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->channels = Channels; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetSkipLoopFilter::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t AVDiscardId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->skip_loop_filter = static_cast(AVDiscardId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetSkipFrame::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t AVDiscardId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->skip_frame = static_cast(AVDiscardId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetSkipIdct::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t AVDiscardId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->skip_idct = static_cast(AVDiscardId); + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetErrorConcealment::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ErrorConcealment) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->error_concealment = ErrorConcealment; + return static_cast(ErrNo::Success); +} + +Expect +AVCodecCtxSetErrorRecognition::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ErrRecognition) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->err_recognition = ErrRecognition; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxDelay::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->delay; +} + +Expect AVCodecCtxSetSkipTop::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Value) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->skip_top = Value; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetSkipBottom::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Value) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->skip_bottom = Value; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxRefs::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->refs; +} + +Expect AVCodecCtxSetSliceFlags::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Value) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->slice_flags = Value; + return static_cast(ErrNo::Success); +} +Expect AVCodecCtxSetSliceCount::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Value) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->slice_count = Value; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxSetFieldOrder::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t Value) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->field_order = static_cast(Value); + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxColorTrc::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return static_cast(AvCodecCtx->color_trc); +} + +Expect +AVCodecCtxChromaSampleLocation::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVChromaLocation const Chroma = AvCodecCtx->chroma_sample_location; + return FFmpegUtils::ChromaLocation::fromAVChromaLocation(Chroma); +} + +Expect AVCodecCtxFrameNumber::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->frame_number; +} + +Expect AVCodecCtxBlockAlign::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->block_align; +} + +Expect +AVCodecCtxSetRequestSampleFmt::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint32_t SampleFmtId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVSampleFormat const SampleFmt = + FFmpegUtils::SampleFmt::fromSampleID(SampleFmtId); + AvCodecCtx->request_sample_fmt = SampleFmt; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxAudioServiceType::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVAudioServiceType const AudioServiceType = AvCodecCtx->audio_service_type; + return static_cast(AudioServiceType); +} + +Expect AVCodecCtxHasBFrames::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->has_b_frames; +} + +Expect +AVCodecCtxSetRequestChannelLayout::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint64_t ChannelLayoutId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->request_channel_layout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxActiveThreadType::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->active_thread_type; +} + +Expect AVCodecCtxSetThreadType::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ThreadType) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->thread_type = ThreadType; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxThreadCount::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return AvCodecCtx->thread_count; +} + +Expect AVCodecCtxSetThreadCount::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + int32_t ThreadCount) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AvCodecCtx->thread_count = ThreadCount; + return static_cast(ErrNo::Success); +} + +Expect AVCodecCtxColorPrimaries::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + AVColorPrimaries const ColorPrimaries = AvCodecCtx->color_primaries; + return FFmpegUtils::ColorPrimaries::fromAVColorPrimaries(ColorPrimaries); +} + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avCodecContext.h b/plugins/wasmedge_ffmpeg/avcodec/avCodecContext.h new file mode 100644 index 000000000000..ee39aa0be6bc --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avCodecContext.h @@ -0,0 +1,816 @@ +#pragma once +#include "avcodec_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +class AVCodecCtxCodecID : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxCodecID(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxCodecType : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxCodecType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetCodecType + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetCodecType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t CodecTypeId); +}; + +class AVCodecCtxSetTimebase + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetTimebase(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Num, int32_t Den); +}; + +class AVCodecCtxTimeBase : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxTimeBase(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t NumPtr, uint32_t DenPtr); +}; + +class AVCodecCtxWidth : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxWidth(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetWidth : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetWidth(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Width); +}; + +class AVCodecCtxHeight : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxHeight(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetHeight : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetHeight(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Height); +}; + +class AVCodecCtxSampleAspectRatio + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSampleAspectRatio(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t NumPtr, uint32_t DenPtr); +}; + +class AVCodecCtxSetSampleAspectRatio + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSampleAspectRatio(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Num, int32_t Den); +}; + +class AVCodecCtxChannelLayout + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetChannelLayout + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint64_t ChannelLayoutId); +}; + +class AVCodecCtxPixFormat : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxPixFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetPixFormat + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetPixFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t PixFmtId); +}; + +class AVCodecCtxSampleFormat + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSampleFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetSampleFormat + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSampleFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t SampleFmtId); +}; + +class AVCodecCtxSampleRate + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSampleRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetSampleRate + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSampleRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t SampleRate); +}; + +class AVCodecCtxSetGopSize + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetGopSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t GopSize); +}; + +class AVCodecCtxSetMaxBFrames + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMaxBFrames(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MaxBFrames); +}; + +class AVCodecCtxSetBQuantFactor + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetBQuantFactor(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float BQuantFactor); +}; + +class AVCodecCtxSetBQuantOffset + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetBQuantOffset(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float BQuantOffset); +}; + +class AVCodecCtxSetIQuantFactor + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetIQuantFactor(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float IQuantFactor); +}; + +class AVCodecCtxSetIQuantOffset + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetIQuantOffset(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float IQuantOffset); +}; + +class AVCodecCtxSetLumiMasking + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetLumiMasking(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float LumiMasking); +}; + +class AVCodecCtxSetTemporalCplxMasking + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetTemporalCplxMasking(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float TemporalCplxMasking); +}; + +class AVCodecCtxSetSpatialCplxMasking + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSpatialCplxMasking(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float SpatialCplxMasking); +}; + +class AVCodecCtxSetPMasking + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetPMasking(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float PMasking); +}; + +class AVCodecCtxSetDarkMasking + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetDarkMasking(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, float DarkMasking); +}; + +class AVCodecCtxSetMeCmp : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMeCmp(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MeCmp); +}; + +class AVCodecCtxSetMeSubCmp + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMeSubCmp(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MeSubCmp); +}; + +class AVCodecCtxSetMbCmp : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMbCmp(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MbCmp); +}; + +class AVCodecCtxSetIldctCmp + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetIldctCmp(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t IldctCmp); +}; + +class AVCodecCtxSetDiaSize + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetDiaSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t DiaSize); +}; + +class AVCodecCtxSetLastPredictorsCount + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetLastPredictorsCount(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t LastPredictorCount); +}; + +class AVCodecCtxSetMePreCmp + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMePreCmp(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MePreCmp); +}; + +class AVCodecCtxSetPreDiaSize + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetPreDiaSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t PreDiaSize); +}; + +class AVCodecCtxSetMeSubpelQuality + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMeSubpelQuality(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MeSubpelQuality); +}; + +class AVCodecCtxSetMeRange + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMeRange(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MeRange); +}; + +class AVCodecCtxSetMbDecision + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMbDecision(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MbDecision); +}; + +class AVCodecCtxSetMbLMin : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMbLMin(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MbLMin); +}; + +class AVCodecCtxSetMbLMax : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetMbLMax(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t MbLMax); +}; + +class AVCodecCtxIntraDcPrecision + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxIntraDcPrecision(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetIntraDcPrecision + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetIntraDcPrecision(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t IntraDcPrecision); +}; + +class AVCodecCtxSetQMin : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetQMin(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t QMin); +}; + +class AVCodecCtxSetQMax : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetQMax(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t QMax); +}; + +class AVCodecCtxSetGlobalQuality + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetGlobalQuality(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t GlobalQuality); +}; + +class AVCodecCtxSetColorspace + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetColorspace(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ColorspaceId); +}; + +class AVCodecCtxColorspace + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxColorspace(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetColorRange + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetColorRange(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ColorRange); +}; + +class AVCodecCtxColorRange + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxColorRange(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxFrameSize : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxFrameSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxBitRate : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxBitRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetBitRate + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetBitRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int64_t BitRate); +}; + +class AVCodecCtxRcMaxRate : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxRcMaxRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetRcMaxRate + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetRcMaxRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int64_t RcMaxRate); +}; + +class AVCodecCtxSetBitRateTolerance + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetBitRateTolerance(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t BitRateTolerance); +}; + +class AVCodecCtxSetCompressionLevel + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetCompressionLevel(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t CompressionLevel); +}; + +class AVCodecCtxFrameRate : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxFrameRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t NumPtr, uint32_t DenPtr); +}; + +class AVCodecCtxSetFrameRate + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetFrameRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Num, int32_t Den); +}; + +class AVCodecCtxSetFlags : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Flags); +}; + +class AVCodecCtxSetStrictStdCompliance + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetStrictStdCompliance(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ComplianceId); +}; + +class AVCodecCtxSetDebug : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetDebug(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Debug); +}; + +class AVCodecCtxCodec : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxCodec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t AvCodecPtr); +}; + +class AVCodecCtxChannels : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxChannels(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetChannels + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetChannels(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Channels); +}; + +class AVCodecCtxSetSkipLoopFilter + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSkipLoopFilter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t AVDicardId); +}; + +class AVCodecCtxSetSkipFrame + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSkipFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t AVDiscardId); +}; + +class AVCodecCtxSetSkipIdct + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSkipIdct(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t AVDicardId); +}; + +class AVCodecCtxSetErrorConcealment + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetErrorConcealment(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ErrorConcealment); +}; + +class AVCodecCtxSetErrorRecognition + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetErrorRecognition(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ErrorRecognition); +}; + +class AVCodecCtxDelay : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxDelay(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetSkipTop + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSkipTop(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Value); +}; + +class AVCodecCtxSetSkipBottom + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSkipBottom(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Value); +}; + +class AVCodecCtxRefs : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxRefs(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetSliceFlags + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSliceFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Flags); +}; + +class AVCodecCtxSetSliceCount + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetSliceCount(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Value); +}; + +class AVCodecCtxSetFieldOrder + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetFieldOrder(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t Value); +}; + +class AVCodecCtxColorTrc : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxColorTrc(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxChromaSampleLocation + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxChromaSampleLocation(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxFrameNumber + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxFrameNumber(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxBlockAlign + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxBlockAlign(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetRequestSampleFmt + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetRequestSampleFmt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t SampleFmtId); +}; + +class AVCodecCtxAudioServiceType + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxAudioServiceType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxHasBFrames + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxHasBFrames(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetRequestChannelLayout + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetRequestChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint64_t ChannelLayoutId); +}; + +class AVCodecCtxActiveThreadType + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxActiveThreadType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetThreadType + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetThreadType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ThreadType); +}; + +class AVCodecCtxThreadCount + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxThreadCount(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecCtxSetThreadCount + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxSetThreadCount(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, int32_t ThreadCount); +}; + +class AVCodecCtxColorPrimaries + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecCtxColorPrimaries(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp b/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp new file mode 100644 index 000000000000..9ffbd830be31 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp @@ -0,0 +1,38 @@ +#include "avCodecParameters.h" + +extern "C" { +#include "libavcodec/avcodec.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +Expect AVCodecParamCodecId::body(const Runtime::CallingFrame &, + uint32_t AvCodecParamId) { + + FFMPEG_PTR_FETCH(AvCodecParams, AvCodecParamId, AVCodecParameters); + return FFmpegUtils::CodecID::fromAVCodecID(AvCodecParams->codec_id); +} + +Expect AVCodecParamCodecType::body(const Runtime::CallingFrame &, + uint32_t AvCodecParamId) { + + FFMPEG_PTR_FETCH(AvCodecParams, AvCodecParamId, AVCodecParameters); + return FFmpegUtils::MediaType::fromMediaType(AvCodecParams->codec_type); +} + +Expect AVCodecParamSetCodecTag::body(const Runtime::CallingFrame &, + uint32_t AvCodecParamId, + uint32_t CodecTag) { + + FFMPEG_PTR_FETCH(AvCodecParams, AvCodecParamId, AVCodecParameters); + AvCodecParams->codec_tag = CodecTag; + return static_cast(ErrNo::Success); +} + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.h b/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.h new file mode 100644 index 000000000000..9e37b7fa2110 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.h @@ -0,0 +1,39 @@ +#pragma once +#include "avcodec_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +class AVCodecParamCodecId : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParamCodecId(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamId); +}; + +class AVCodecParamCodecType + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParamCodecType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamId); +}; + +class AVCodecParamSetCodecTag + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParamSetCodecTag(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamId, uint32_t CodecTag); +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp b/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp new file mode 100644 index 000000000000..892a0395a8c2 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp @@ -0,0 +1,189 @@ +#include "avPacket.h" + +extern "C" { +#include "libavcodec/packet.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +Expect AVPacketAlloc::body(const Runtime::CallingFrame &Frame, + uint32_t AvPacketPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AvPacketId, MemInst, uint32_t, AvPacketPtr, + "Failed when accessing the return AVCodecContext Memory"sv); + + FFMPEG_PTR_FETCH(AvPacket, *AvPacketId, AVPacket); // Initialize the packet. + AvPacket = av_packet_alloc(); + FFMPEG_PTR_STORE(AvPacket, AvPacketId); + return static_cast(ErrNo::Success); +} + +Expect AVNewPacket::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int32_t Size) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return av_new_packet(AvPacket, Size); +} + +Expect AVPacketRef::body(const Runtime::CallingFrame &, + uint32_t DestPacketId, uint32_t SrcPacketId) { + + FFMPEG_PTR_FETCH(DestAvPacket, DestPacketId, AVPacket); + FFMPEG_PTR_FETCH(SrcAvPacket, SrcPacketId, AVPacket); + + return av_packet_ref(DestAvPacket, SrcAvPacket); +} + +Expect AVPacketUnref::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); // Free packet. + av_packet_unref(AvPacket); + FFMPEG_PTR_DELETE(AvPacketId); + return static_cast(ErrNo::Success); +} + +Expect AVGrowPacket::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int32_t Size) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return av_grow_packet(AvPacket, Size); +} + +Expect AVShrinkPacket::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int32_t Size) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + av_shrink_packet(AvPacket, Size); + return static_cast(ErrNo::Success); +} + +Expect AVPacketStreamIndex::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->stream_index; +} + +Expect AVPacketSetStreamIndex::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, + int32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AvPacket->stream_index = StreamIdx; + return static_cast(ErrNo::Success); +} + +Expect AVPacketSize::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->size; +} + +Expect AVPacketFlags::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->flags; +} + +Expect AVPacketSetFlags::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int32_t Flags) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AvPacket->flags = Flags; + return static_cast(ErrNo::Success); +} + +Expect AVPacketPos::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->pos; +} + +Expect AVPacketSetPos::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int64_t Pos) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AvPacket->pos = Pos; + return static_cast(ErrNo::Success); +} + +Expect AVPacketDuration::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->duration; +} + +Expect AVPacketSetDuration::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, + int64_t Duration) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AvPacket->duration = Duration; + return static_cast(ErrNo::Success); +} + +Expect AVPacketDts::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->dts; +} + +Expect AVPacketSetDts::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int64_t Dts) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AvPacket->dts = Dts; + return static_cast(ErrNo::Success); +} + +Expect AVPacketPts::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + return AvPacket->pts; +} + +Expect AVPacketSetPts::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int64_t Pts) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AvPacket->pts = Pts; + return static_cast(ErrNo::Success); +} + +Expect AVPacketIsDataNull::body(const Runtime::CallingFrame &, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + if (AvPacket->data == nullptr) + return 1; + return 0; +} + +Expect AVPacketData::body(const Runtime::CallingFrame &Frame, + uint32_t AvPacketId, uint32_t DataPtr, + uint32_t DataLen) { + + MEMINST_CHECK(MemInst, Frame, 0) + MEM_SPAN_CHECK(Buffer, MemInst, uint8_t, DataPtr, DataLen, ""); + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + uint8_t *Data = AvPacket->data; + std::copy_n(Data, DataLen, Buffer.data()); + return static_cast(ErrNo::Success); +} + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avPacket.h b/plugins/wasmedge_ffmpeg/avcodec/avPacket.h new file mode 100644 index 000000000000..5ed513a846c0 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avPacket.h @@ -0,0 +1,173 @@ +#pragma once +#include "avcodec_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +class AVPacketAlloc : public WasmEdgeFFmpegAVCodec { +public: + AVPacketAlloc(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvPacketPtr); +}; + +class AVNewPacket : public WasmEdgeFFmpegAVCodec { +public: + AVNewPacket(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int32_t Size); +}; + +class AVPacketRef : public WasmEdgeFFmpegAVCodec { +public: + AVPacketRef(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t DestPacketId, uint32_t SrcPacketId); +}; + +class AVPacketUnref : public WasmEdgeFFmpegAVCodec { +public: + AVPacketUnref(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVGrowPacket : public WasmEdgeFFmpegAVCodec { +public: + AVGrowPacket(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int32_t Size); +}; + +class AVShrinkPacket : public WasmEdgeFFmpegAVCodec { +public: + AVShrinkPacket(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int32_t Size); +}; + +class AVPacketStreamIndex : public WasmEdgeFFmpegAVCodec { +public: + AVPacketStreamIndex(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketSetStreamIndex + : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSetStreamIndex(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int32_t StreamIdx); +}; + +class AVPacketSize : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketFlags : public WasmEdgeFFmpegAVCodec { +public: + AVPacketFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketSetFlags : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSetFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int32_t Flags); +}; + +class AVPacketPos : public WasmEdgeFFmpegAVCodec { +public: + AVPacketPos(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketSetPos : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSetPos(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int64_t Pos); +}; + +class AVPacketDuration : public WasmEdgeFFmpegAVCodec { +public: + AVPacketDuration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketSetDuration : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSetDuration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int64_t Duration); +}; + +class AVPacketDts : public WasmEdgeFFmpegAVCodec { +public: + AVPacketDts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketSetDts : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSetDts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int64_t Dts); +}; + +class AVPacketPts : public WasmEdgeFFmpegAVCodec { +public: + AVPacketPts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketSetPts : public WasmEdgeFFmpegAVCodec { +public: + AVPacketSetPts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + int64_t Pts); +}; + +class AVPacketIsDataNull : public WasmEdgeFFmpegAVCodec { +public: + AVPacketIsDataNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId); +}; + +class AVPacketData : public WasmEdgeFFmpegAVCodec { +public: + AVPacketData(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvPacketId, + uint32_t DataPtr, uint32_t DataLen); +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avcodec_base.h b/plugins/wasmedge_ffmpeg/avcodec/avcodec_base.h new file mode 100644 index 000000000000..e3365858b608 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avcodec_base.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +template +class WasmEdgeFFmpegAVCodec : public Runtime::HostFunction { +public: + WasmEdgeFFmpegAVCodec(std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp b/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp new file mode 100644 index 000000000000..91c0b9de0ae0 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp @@ -0,0 +1,338 @@ +#include "avcodec_func.h" + +extern "C" { +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +Expect AVCodecAllocContext3::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecId, + uint32_t AvCodecCtxPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AvCodecCtxId, MemInst, uint32_t, AvCodecCtxPtr, + "Failed when accessing the return AVCodecContext Memory"sv); + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, AVCodec); + + AVCodecContext *AvCodecCtx = avcodec_alloc_context3(AvCodec); + FFMPEG_PTR_STORE(AvCodecCtx, AvCodecCtxId); + return static_cast(ErrNo::Success); +} + +Expect +AVCodecParametersFromContext::body(const Runtime::CallingFrame &, + uint32_t AvCodecParamId, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecParam, AvCodecParamId, AVCodecParameters); + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + return avcodec_parameters_from_context(AvCodecParam, AvCodecCtx); +} + +Expect AVCodecParametersFree::body(const Runtime::CallingFrame &, + uint32_t AvCodecParamId) { + + FFMPEG_PTR_FETCH(AvCodecParam, AvCodecParamId, AVCodecParameters); + + avcodec_parameters_free(&AvCodecParam); + FFMPEG_PTR_DELETE(AvCodecParamId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecFreeContext::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + + avcodec_free_context(&AvCodecCtx); + FFMPEG_PTR_DELETE(AvCodecCtxId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecParametersAlloc::body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamPtr) { + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AvCodecParamId, MemInst, uint32_t, AvCodecParamPtr, + "Failed when accessing the return AVCodecParameters Memory"sv); + + FFMPEG_PTR_FETCH(AvCodecParam, *AvCodecParamId, AVCodecParameters); + AvCodecParam = avcodec_parameters_alloc(); + FFMPEG_PTR_STORE(AvCodecParam, AvCodecParamId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecGetType::body(const Runtime::CallingFrame &, + uint32_t AvCodecIdIndex) { + + AVCodecID const AvCodecId = + FFmpegUtils::CodecID::intoAVCodecID(AvCodecIdIndex); + AVMediaType const MediaType = avcodec_get_type(AvCodecId); + return FFmpegUtils::MediaType::fromMediaType(MediaType); +} + +Expect AVCodecOpen2::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, uint32_t AvCodecId, + uint32_t AvDictionaryId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvDictionary, AvDictionaryId, AVDictionary *); + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, AVCodec); + return avcodec_open2(AvCodecCtx, AvCodec, AvDictionary); +} + +Expect AVCodecFindDecoder::body(const Runtime::CallingFrame &Frame, + uint32_t ID, uint32_t AvCodecPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AVCodecId, MemInst, uint32_t, AvCodecPtr, + "Failed when accessing the return AVCodec Memory"sv); + + AVCodecID const Id = FFmpegUtils::CodecID::intoAVCodecID(ID); + + const AVCodec *AvCodec = avcodec_find_decoder(Id); + + // Setting AvCodec value as NULL. + if (AvCodec == nullptr) { + *AVCodecId = 0; + return static_cast(ErrNo::Success); + } + + FFMPEG_PTR_STORE(const_cast(AvCodec), AVCodecId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecIsEncoder::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return av_codec_is_encoder(AvCodec); +} + +Expect AVCodecIsDecoder::body(const Runtime::CallingFrame &, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + return av_codec_is_decoder(AvCodec); +} + +Expect AVCodecClose::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + int Res = avcodec_close(AvCodecCtx); + FFMPEG_PTR_DELETE(AvCodecCtxId); + return Res; +} + +Expect AVCodecParametersToContext::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint32_t AvCodecParamId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvCodecParam, AvCodecParamId, AVCodecParameters); + + return avcodec_parameters_to_context(AvCodecCtx, AvCodecParam); +} + +Expect AVCodecReceiveFrame::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AvCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return avcodec_receive_frame(AvCodecCtx, AvFrame); +} + +Expect AVCodecSendPacket::body(const Runtime::CallingFrame &, + uint32_t AvCodecCtxId, + uint32_t PacketId) { + + FFMPEG_PTR_FETCH(AVCodecCtx, AvCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvPacket, PacketId, + AVPacket); // Can send Null AVPacket, to close the stream. + return avcodec_send_packet(AVCodecCtx, AvPacket); +} + +Expect AVCodecFindEncoder::body(const Runtime::CallingFrame &Frame, + uint32_t ID, uint32_t AVCodecPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AVCodecId, MemInst, uint32_t, AVCodecPtr, + "Failed when accessing the return AVCodec Memory"sv); + + AVCodecID const Id = FFmpegUtils::CodecID::intoAVCodecID(ID); + + const AVCodec *AvCodec = avcodec_find_encoder(Id); + + // Setting AvCodec value as NULL. + if (AvCodec == nullptr) { + *AVCodecId = 0; + return static_cast(ErrNo::Success); + } + + FFMPEG_PTR_STORE(const_cast(AvCodec), AVCodecId); + return static_cast(ErrNo::Success); +} + +Expect AVCodecReceivePacket::body(const Runtime::CallingFrame &, + uint32_t AVCodecCtxId, + uint32_t PacketId) { + + FFMPEG_PTR_FETCH(AVCodecCtx, AVCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvPacket, PacketId, AVPacket); + return avcodec_receive_packet(AVCodecCtx, AvPacket); +} + +Expect AVCodecSendFrame::body(const Runtime::CallingFrame &, + uint32_t AVCodecCtxId, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AVCodecCtx, AVCodecCtxId, AVCodecContext); + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return avcodec_send_frame(AVCodecCtx, AvFrame); +} + +Expect +AVCodecFindDecoderByName::body(const Runtime::CallingFrame &Frame, + uint32_t AVCodecPtr, uint32_t NamePtr, + uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AVCodecId, MemInst, uint32_t, AVCodecPtr, + "Failed when accessing the return AVCodec Memory"sv); + MEM_PTR_CHECK(NameId, MemInst, char, NamePtr, + "Failed when accessing the return URL memory"sv); + + std::string Name; + std::copy_n(NameId, NameLen, std::back_inserter(Name)); + + AVCodec const *AvCodec = avcodec_find_decoder_by_name(Name.c_str()); + + if (AvCodec == nullptr) { + *AVCodecId = 0; + return static_cast(ErrNo::Success); + } + + FFMPEG_PTR_STORE(const_cast(AvCodec), AVCodecId); + return static_cast(ErrNo::Success); +} + +Expect +AVCodecFindEncoderByName::body(const Runtime::CallingFrame &Frame, + uint32_t AVCodecPtr, uint32_t NamePtr, + uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AVCodecId, MemInst, uint32_t, AVCodecPtr, + "Failed when accessing the return AVCodec Memory"sv); + MEM_PTR_CHECK(NameId, MemInst, char, NamePtr, + "Failed when accessing the return URL memory"sv); + + std::string Name; + std::copy_n(NameId, NameLen, std::back_inserter(Name)); + + AVCodec const *AvCodec = avcodec_find_encoder_by_name(Name.c_str()); + + if (AvCodec == nullptr) { + *AVCodecId = 0; + return static_cast(ErrNo::Success); + } + + FFMPEG_PTR_STORE(const_cast(AvCodec), AVCodecId); + return static_cast(ErrNo::Success); +} + +Expect AVPacketRescaleTs::body(const Runtime::CallingFrame &, + uint32_t AvPacketId, int32_t SrcNum, + int32_t SrcDen, int32_t DestNum, + int32_t DestDen) { + + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + AVRational const Src = av_make_q(SrcNum, SrcDen); + AVRational const Dest = av_make_q(DestNum, DestDen); + + av_packet_rescale_ts(AvPacket, Src, Dest); + return static_cast(ErrNo::Success); +} + +Expect AVPacketMakeWritable::body(const Runtime::CallingFrame &, + uint32_t AVPacketId) { + + FFMPEG_PTR_FETCH(AvPacket, AVPacketId, AVPacket); + return av_packet_make_writable(AvPacket); +} + +Expect AVCodecParametersCopy::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t AVCodecParamId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvCodecParam, AVCodecParamId, AVCodecParameters); + + AVStream **AvStream = AvFormatCtx->streams; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return avcodec_parameters_copy((*AvStream)->codecpar, AvCodecParam); +} + +Expect AVCodecVersion::body(const Runtime::CallingFrame &) { + return avcodec_version(); +} + +Expect AVCodecFlushBuffers::body(const Runtime::CallingFrame &, + uint32_t AVCodecCtxId) { + + FFMPEG_PTR_FETCH(AvCodecCtx, AVCodecCtxId, AVCodecContext); + avcodec_flush_buffers(AvCodecCtx); + return static_cast(ErrNo::Success); +} + +Expect +AVCodecConfigurationLength::body(const Runtime::CallingFrame &) { + const char *Config = avcodec_configuration(); + return strlen(Config); +} + +Expect AVCodecConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, + uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = avcodec_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVCodecLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = avcodec_license(); + return strlen(License); +} + +Expect AVCodecLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = avcodec_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.h b/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.h new file mode 100644 index 000000000000..3aabf3e1e6c2 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.h @@ -0,0 +1,245 @@ +#pragma once +#include "avcodec_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +class AVCodecAllocContext3 + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecAllocContext3(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t AvCodecCtxPtr); +}; + +class AVCodecParametersFromContext + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParametersFromContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamId, uint32_t AvCodecCtxId); +}; + +class AVCodecParametersFree + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParametersFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamId); +}; + +class AVCodecFreeContext : public WasmEdgeFFmpegAVCodec { +public: + AVCodecFreeContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId); +}; + +class AVCodecParametersAlloc + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParametersAlloc(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecParamPtr); +}; + +class AVCodecGetType : public WasmEdgeFFmpegAVCodec { +public: + AVCodecGetType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecOpen2 : public WasmEdgeFFmpegAVCodec { +public: + AVCodecOpen2(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t AvCodecId, + uint32_t AvDictionaryId); +}; + +class AVCodecFindDecoder : public WasmEdgeFFmpegAVCodec { +public: + AVCodecFindDecoder(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ID, + uint32_t AvCodecId); +}; + +class AVCodecIsEncoder : public WasmEdgeFFmpegAVCodec { +public: + AVCodecIsEncoder(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecIsDecoder : public WasmEdgeFFmpegAVCodec { +public: + AVCodecIsDecoder(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecClose : public WasmEdgeFFmpegAVCodec { +public: + AVCodecClose(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId); +}; + +class AVCodecParametersToContext + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParametersToContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AvCodecId, + uint32_t AvCodecParamId); +}; + +class AVCodecReceiveFrame : public WasmEdgeFFmpegAVCodec { +public: + AVCodecReceiveFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t FrameId); +}; + +class AVCodecSendPacket : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSendPacket(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvCodecCtxId, uint32_t PacketId); +}; + +class AVCodecFindEncoder : public WasmEdgeFFmpegAVCodec { +public: + AVCodecFindEncoder(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ID, + uint32_t AVCodecPtr); +}; + +class AVCodecReceivePacket + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecReceivePacket(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVCodecCtxId, uint32_t PacketId); +}; + +class AVCodecSendFrame : public WasmEdgeFFmpegAVCodec { +public: + AVCodecSendFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVCodecCtxId, uint32_t FrameId); +}; + +class AVCodecFindDecoderByName + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecFindDecoderByName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AVCodecPtr, + uint32_t NamePtr, uint32_t NameLen); +}; + +class AVCodecFindEncoderByName + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecFindEncoderByName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AVCodecPtr, + uint32_t NamePtr, uint32_t NameLen); +}; + +class AVPacketRescaleTs : public WasmEdgeFFmpegAVCodec { +public: + AVPacketRescaleTs(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AVPacketId, + int32_t SrcNum, int32_t SrcDen, int32_t DestNum, + int32_t DestDen); +}; + +class AVPacketMakeWritable + : public WasmEdgeFFmpegAVCodec { +public: + AVPacketMakeWritable(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t AVPacketId); +}; + +class AVCodecParametersCopy + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecParametersCopy(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVFormatCtxId, uint32_t AVCodecParamId, + uint32_t StreamIdx); +}; + +class AVCodecVersion : public WasmEdgeFFmpegAVCodec { +public: + AVCodecVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVCodecFlushBuffers : public WasmEdgeFFmpegAVCodec { +public: + AVCodecFlushBuffers(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVCodecCtxId); +}; + +class AVCodecConfigurationLength + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVCodecConfiguration + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class AVCodecLicenseLength + : public WasmEdgeFFmpegAVCodec { +public: + AVCodecLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVCodecLicense : public WasmEdgeFFmpegAVCodec { +public: + AVCodecLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVCodec(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/module.cpp b/plugins/wasmedge_ffmpeg/avcodec/module.cpp new file mode 100644 index 000000000000..1b9047555740 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/module.cpp @@ -0,0 +1,361 @@ +#include "module.h" +#include "avCodec.h" +#include "avCodecContext.h" +#include "avCodecParameters.h" +#include "avPacket.h" +#include "avcodec_func.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +WasmEdgeFFmpegAVCodecModule::WasmEdgeFFmpegAVCodecModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_avcodec") { + + // avcodec_func.h + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_alloc_context3", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_parameters_from_context", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_parameters_free", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_free_context", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_parameters_alloc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_get_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_open2", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_find_decoder", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_codec_is_encoder", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_codec_is_decoder", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_close", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_parameters_to_context", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_receive_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_send_packet", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_find_encoder", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_receive_packet", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_send_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_find_decoder_by_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_find_encoder_by_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_rescale_ts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_make_writable", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avcodec_avcodec_parameters_copy", + std::make_unique(Env)); // TODO: Write Test. + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_flush_buffers", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_license", + std::make_unique(Env)); + + // avCodecContext Struct fields access + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_codec_id", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_codec_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_codec_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_time_base", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_time_base", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_width", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_width", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_height", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_height", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_sample_aspect_ratio", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_sample_aspect_ratio", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_channel_layout", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_channel_layout", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_pix_fmt", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_pix_fmt", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_sample_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_sample_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_sample_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_sample_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_gop_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_max_b_frames", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_b_quant_factor", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_b_quant_offset", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_i_quant_factor", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_i_quant_offset", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_lumi_masking", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_temporal_cplx_masking", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_spatial_cplx_masking", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_p_masking", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_dark_masking", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_cmp", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_sub_cmp", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_cmp", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_ildct_cmp", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_dia_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_last_predictor_count", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_pre_cmp", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_pre_dia_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_subpel_quality", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_range", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_decision", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_lmin", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_lmax", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_intra_dc_precision", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_intra_dc_precision", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_qmin", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_qmax", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_global_quality", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_colorspace", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_colorspace", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_color_range", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_color_range", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_frame_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_bit_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_bit_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_rc_max_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_rc_max_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_bit_rate_tolerance", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_compression_level", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_framerate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_framerate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_flags", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_strict_std_compliance", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_debug", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_codec", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_channels", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_channels", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_loop_filter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_idct", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_error_concealment", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_err_recognition", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_delay", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_top", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_bottom", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_refs", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_slice_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_slice_count", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_field_order", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_color_trc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_chroma_sample_location", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_frame_number", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_block_align", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_request_sample_fmt", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_audio_service_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_has_b_frames", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_request_channel_layout", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_active_thread_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_thread_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_thread_count", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_set_thread_count", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodeccontext_color_primaries", + std::make_unique(Env)); + + // avCodec Struct fields access + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_id", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_max_lowres", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_capabilities", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_get_name_len", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_get_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_get_long_name_len", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_get_long_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_profiles", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_pix_fmts_is_null", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_pix_fmts_iter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_supported_framerate_is_null", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_supported_framerate_iter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_supported_samplerates_is_null", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_supported_samplerates_iter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_channel_layouts_is_null", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_channel_layouts_iter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_sample_fmts_is_null", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodec_sample_fmts_iter", + std::make_unique(Env)); + + // AVCodecParam Struct fields access. + addHostFunc("wasmedge_ffmpeg_avcodec_avcodecparam_codec_id", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodecparam_codec_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_avcodecparam_set_codec_tag", + std::make_unique(Env)); + + // AVPacket functions. + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_alloc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_new_packet", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_ref", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_unref", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_grow_packet", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_shrink_packet", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_stream_index", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_set_stream_index", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_set_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_pos", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_set_pos", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_duration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_set_duration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_dts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_set_dts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_pts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_set_pts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_is_data_null", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avcodec_av_packet_data", + std::make_unique(Env)); +} + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avcodec/module.h b/plugins/wasmedge_ffmpeg/avcodec/module.h new file mode 100644 index 000000000000..7d3776d63bb3 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avcodec/module.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVcodec { + +class WasmEdgeFFmpegAVCodecModule : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegAVCodecModule(std::shared_ptr Env); +}; + +} // namespace AVcodec +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avdevice/avDevice_base.h b/plugins/wasmedge_ffmpeg/avdevice/avDevice_base.h new file mode 100644 index 000000000000..06096dd41a7a --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avdevice/avDevice_base.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVDevice { + +template +class WasmEdgeFFmpegAVDevice : public Runtime::HostFunction { +public: + WasmEdgeFFmpegAVDevice( + std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace AVDevice +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avdevice/avDevice_func.cpp b/plugins/wasmedge_ffmpeg/avdevice/avDevice_func.cpp new file mode 100644 index 000000000000..b52763021e7d --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avdevice/avDevice_func.cpp @@ -0,0 +1,124 @@ +#include "avDevice_func.h" + +extern "C" { +#include "libavdevice/avdevice.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVDevice { + +Expect AVDeviceRegisterAll::body(const Runtime::CallingFrame &) { + avdevice_register_all(); + return {}; +} + +Expect AVDeviceVersion::body(const Runtime::CallingFrame &) { + return avdevice_version(); +} + +Expect AVDeviceListDevices::body(const Runtime::CallingFrame &Frame, + uint32_t AVFormatCtxId, + uint32_t AVDeviceInfoListPtr) { + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AVDeviceInfoListId, MemInst, uint32_t, AVDeviceInfoListPtr, "") + + FFMPEG_PTR_FETCH(AvFormatCtx, AVFormatCtxId, AVFormatContext); + + AVDeviceInfoList **AvDeviceInfoList = + static_cast(av_malloc(sizeof(AVDeviceInfoList *))); + + int Res = avdevice_list_devices(AvFormatCtx, AvDeviceInfoList); + FFMPEG_PTR_STORE(AvDeviceInfoList, AVDeviceInfoListId); + return Res; +} + +Expect AVInputAudioDeviceNext::body(const Runtime::CallingFrame &) { + spdlog::error("[WasmEdge-FFmpeg] AVInputAudioDeviceNext unimplemented"sv); + // av_input_audio_device_next(); + return static_cast(ErrNo::UnImplemented); +} + +Expect AVInputVideoDeviceNext::body(const Runtime::CallingFrame &) { + spdlog::error("[WasmEdge-FFmpeg] AVInputVideoDeviceNext unimplemented"sv); + // av_input_video_device_next(); + return static_cast(ErrNo::UnImplemented); +} + +Expect AVOutputAudioDeviceNext::body(const Runtime::CallingFrame &) { + spdlog::error("[WasmEdge-FFmpeg] AVOutputAudioDeviceNext unimplemented"sv); + // av_output_audio_device_next(); + return static_cast(ErrNo::UnImplemented); +} + +Expect AVOutputVideoDeviceNext::body(const Runtime::CallingFrame &) { + spdlog::error("[WasmEdge-FFmpeg] AVOutputVideoDeviceNext unimplemented"sv); + // av_output_video_device_next(); + return static_cast(ErrNo::UnImplemented); +} + +Expect AVDeviceFreeListDevices::body(const Runtime::CallingFrame &, + uint32_t AVDeviceInfoListId) { + + FFMPEG_PTR_FETCH(AvDeviceInfoList, AVDeviceInfoListId, AVDeviceInfoList *); + + avdevice_free_list_devices(AvDeviceInfoList); + FFMPEG_PTR_DELETE(AVDeviceInfoListId); + return static_cast(ErrNo::Success); +} + +Expect AVDeviceNbDevices::body(const Runtime::CallingFrame &, + uint32_t AVDeviceInfoListId) { + + FFMPEG_PTR_FETCH(AvDeviceInfoList, AVDeviceInfoListId, AVDeviceInfoList *); + return (*AvDeviceInfoList)->nb_devices; +} + +Expect AVDeviceDefaultDevice::body(const Runtime::CallingFrame &, + uint32_t AVDeviceInfoListId) { + + FFMPEG_PTR_FETCH(AvDeviceInfoList, AVDeviceInfoListId, AVDeviceInfoList *); + return (*AvDeviceInfoList)->default_device; +} + +Expect +AVDeviceConfigurationLength::body(const Runtime::CallingFrame &) { + const char *Config = avdevice_configuration(); + return strlen(Config); +} + +Expect AVDeviceConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, + uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = avdevice_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVDeviceLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = avdevice_license(); + return strlen(License); +} + +Expect AVDeviceLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, + uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = avdevice_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +} // namespace AVDevice +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/avdevice/avDevice_func.h b/plugins/wasmedge_ffmpeg/avdevice/avDevice_func.h new file mode 100644 index 000000000000..92a1309b3b8b --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avdevice/avDevice_func.h @@ -0,0 +1,127 @@ +#pragma once + +#include "avDevice_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVDevice { + +class AVDeviceRegisterAll : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceRegisterAll(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVDeviceVersion : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVDeviceListDevices : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceListDevices(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVFormatCtxId, uint32_t AVDeviceInfoListPtr); +}; + +class AVInputAudioDeviceNext + : public WasmEdgeFFmpegAVDevice { +public: + AVInputAudioDeviceNext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &); +}; + +class AVInputVideoDeviceNext + : public WasmEdgeFFmpegAVDevice { +public: + AVInputVideoDeviceNext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &); +}; + +class AVOutputAudioDeviceNext + : public WasmEdgeFFmpegAVDevice { +public: + AVOutputAudioDeviceNext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &); +}; + +class AVOutputVideoDeviceNext + : public WasmEdgeFFmpegAVDevice { +public: + AVOutputVideoDeviceNext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &); +}; + +class AVDeviceFreeListDevices + : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceFreeListDevices(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVDeviceInfoListId); +}; + +class AVDeviceNbDevices : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceNbDevices(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVDeviceInfoListId); +}; + +class AVDeviceDefaultDevice + : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceDefaultDevice(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVDeviceInfoListId); +}; + +class AVDeviceConfigurationLength + : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVDeviceConfiguration + : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class AVDeviceLicenseLength + : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVDeviceLicense : public WasmEdgeFFmpegAVDevice { +public: + AVDeviceLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVDevice(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +} // namespace AVDevice +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avdevice/module.cpp b/plugins/wasmedge_ffmpeg/avdevice/module.cpp new file mode 100644 index 000000000000..a47312d5dd1a --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avdevice/module.cpp @@ -0,0 +1,38 @@ +#include "module.h" +#include "avDevice_func.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVDevice { + +WasmEdgeFFmpegAVDeviceModule::WasmEdgeFFmpegAVDeviceModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_avdevice") { + + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_register_all", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_list_devices", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_free_list_devices", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_nb_devices", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_default_device", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avdevice_avdevice_license", + std::make_unique(Env)); +} + +} // namespace AVDevice +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avdevice/module.h b/plugins/wasmedge_ffmpeg/avdevice/module.h new file mode 100644 index 000000000000..57e291eb56be --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avdevice/module.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVDevice { + +class WasmEdgeFFmpegAVDeviceModule : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegAVDeviceModule(std::shared_ptr Env); +}; + +} // namespace AVDevice +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/avFilter.cpp b/plugins/wasmedge_ffmpeg/avfilter/avFilter.cpp new file mode 100644 index 000000000000..2d7fcf64c3c4 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/avFilter.cpp @@ -0,0 +1,149 @@ +#include "avFilter.h" + +extern "C" { +#include "libavfilter/avfilter.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +Expect AVFilterNameLength::body(const Runtime::CallingFrame &, + uint32_t FilterId) { + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + return strlen(Filter->name); +} + +Expect AVFilterName::body(const Runtime::CallingFrame &Frame, + uint32_t FilterId, uint32_t NamePtr, + uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + const char *Name = Filter->name; + std::copy_n(Name, NameLen, NameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFilterDescriptionLength::body(const Runtime::CallingFrame &, + uint32_t FilterId) { + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + return strlen(Filter->description); +} + +Expect AVFilterDescription::body(const Runtime::CallingFrame &Frame, + uint32_t FilterId, uint32_t DescPtr, + uint32_t DescLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(DescBuf, MemInst, char, DescPtr, DescLen, ""); + + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + const char *Desc = Filter->description; + std::copy_n(Desc, DescLen, DescBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFilterNbInputs::body(const Runtime::CallingFrame &, + uint32_t FilterId) { + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + return Filter->nb_inputs; +} + +Expect AVFilterNbOutputs::body(const Runtime::CallingFrame &, + uint32_t FilterId) { + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + return Filter->nb_outputs; +} + +Expect AVFilterFlags::body(const Runtime::CallingFrame &, + uint32_t FilterId) { + + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + return Filter->flags; +} + +Expect AVFilterInOutSetName::body(const Runtime::CallingFrame &Frame, + uint32_t InOutId, uint32_t NamePtr, + uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + + FFMPEG_PTR_FETCH(InOut, InOutId, AVFilterInOut); + + std::string Name; + std::copy_n(NameBuf.data(), NameLen, std::back_inserter(Name)); + char *CName = av_strdup(Name.c_str()); + if (CName == nullptr) + return static_cast(ErrNo::Success); + InOut->name = CName; + return static_cast(ErrNo::Success); +} + +Expect AVFilterInOutSetFilterCtx::body(const Runtime::CallingFrame &, + uint32_t InOutId, + uint32_t FilterCtxId) { + + FFMPEG_PTR_FETCH(InOut, InOutId, AVFilterInOut); + FFMPEG_PTR_FETCH(FilterCtx, FilterCtxId, AVFilterContext); + + InOut->filter_ctx = FilterCtx; + return static_cast(ErrNo::Success); +} + +Expect AVFilterInOutSetPadIdx::body(const Runtime::CallingFrame &, + uint32_t InOutId, int32_t PadIdx) { + + FFMPEG_PTR_FETCH(InOut, InOutId, AVFilterInOut); + InOut->pad_idx = PadIdx; + return static_cast(ErrNo::Success); +} + +Expect AVFilterInOutSetNext::body(const Runtime::CallingFrame &, + uint32_t InOutId, + uint32_t NextInOutId) { + + FFMPEG_PTR_FETCH(InOut, InOutId, AVFilterInOut); + FFMPEG_PTR_FETCH(NextInOut, NextInOutId, AVFilterInOut); + InOut->next = NextInOut; + return static_cast(ErrNo::Success); +} + +Expect +AVFilterGetInputsFilterPad::body(const Runtime::CallingFrame &Frame, + uint32_t FilterId, uint32_t FilterPadPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(FilterPadId, MemInst, uint32_t, FilterPadPtr, "") + + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + const AVFilterPad *FilterPad = Filter->inputs; + if (FilterPad == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_STORE(const_cast(FilterPad), FilterPadId); + return static_cast(ErrNo::Success); +} + +Expect +AVFilterGetOutputsFilterPad::body(const Runtime::CallingFrame &Frame, + uint32_t FilterId, uint32_t FilterPadPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(FilterPadId, MemInst, uint32_t, FilterPadPtr, "") + + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + const AVFilterPad *FilterPad = Filter->outputs; + if (FilterPad == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_STORE(const_cast(FilterPad), FilterPadId); + return static_cast(ErrNo::Success); +} + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/avFilter.h b/plugins/wasmedge_ffmpeg/avfilter/avFilter.h new file mode 100644 index 000000000000..1dbf650f36e8 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/avFilter.h @@ -0,0 +1,120 @@ +#pragma once + +#include "avfilter_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +class AVFilterNameLength : public WasmEdgeFFmpegAVFilter { +public: + AVFilterNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId); +}; + +class AVFilterName : public WasmEdgeFFmpegAVFilter { +public: + AVFilterName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId, + uint32_t NamePtr, uint32_t NameLen); +}; + +class AVFilterDescriptionLength + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterDescriptionLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId); +}; + +class AVFilterDescription : public WasmEdgeFFmpegAVFilter { +public: + AVFilterDescription(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId, + uint32_t DescPtr, uint32_t DescLen); +}; + +class AVFilterNbInputs : public WasmEdgeFFmpegAVFilter { +public: + AVFilterNbInputs(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId); +}; + +class AVFilterNbOutputs : public WasmEdgeFFmpegAVFilter { +public: + AVFilterNbOutputs(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId); +}; + +class AVFilterFlags : public WasmEdgeFFmpegAVFilter { +public: + AVFilterFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId); +}; + +class AVFilterInOutSetName + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterInOutSetName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t InOutId, + uint32_t NamePtr, uint32_t NameLen); +}; + +class AVFilterInOutSetFilterCtx + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterInOutSetFilterCtx(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t InOutId, + uint32_t FilterCtxId); +}; + +class AVFilterInOutSetPadIdx + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterInOutSetPadIdx(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t InOutId, + int32_t PadIdx); +}; + +class AVFilterInOutSetNext + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterInOutSetNext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t InOutId, + uint32_t NextInOutId); +}; + +class AVFilterGetInputsFilterPad + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGetInputsFilterPad(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId, + uint32_t FilterPadPtr); +}; + +class AVFilterGetOutputsFilterPad + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGetOutputsFilterPad(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId, + uint32_t FilterPadPtr); +}; + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/avfilter_base.h b/plugins/wasmedge_ffmpeg/avfilter/avfilter_base.h new file mode 100644 index 000000000000..7ed333d95ea3 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/avfilter_base.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +template +class WasmEdgeFFmpegAVFilter : public Runtime::HostFunction { +public: + WasmEdgeFFmpegAVFilter( + std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp b/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp new file mode 100644 index 000000000000..974a1b378ea0 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp @@ -0,0 +1,300 @@ +#include "avfilter_func.h" + +extern "C" { +#include "libavfilter/avfilter.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +Expect AVFilterGraphAlloc::body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(FilterGraphId, MemInst, uint32_t, FilterGraphPtr, "") + + FFMPEG_PTR_FETCH(FilterGraph, *FilterGraphId, AVFilterGraph); + + FilterGraph = avfilter_graph_alloc(); + if (FilterGraph == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_STORE(FilterGraph, FilterGraphId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterGraphConfig::body(const Runtime::CallingFrame &, + uint32_t FilterGraphId) { + + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + return avfilter_graph_config(FilterGraph, + nullptr); // log_ctx always NULL on Rust SDK. +} + +Expect AVFilterGraphFree::body(const Runtime::CallingFrame &, + uint32_t FilterGraphId) { + + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + avfilter_graph_free(&FilterGraph); + FFMPEG_PTR_DELETE(FilterGraphId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterGraphGetFilter::body(const Runtime::CallingFrame &Frame, + uint32_t FilterCtxPtr, + uint32_t FilterGraphId, + uint32_t NamePtr, + uint32_t NameSize) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(NameId, MemInst, char, NamePtr, + "Failed when accessing the return Name memory"sv); + MEM_PTR_CHECK(FilterCtxId, MemInst, uint32_t, FilterCtxPtr, ""); + + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + FFMPEG_PTR_FETCH(FilterCtx, *FilterCtxId, AVFilterContext); + + std::string Name; + std::copy_n(NameId, NameSize, std::back_inserter(Name)); + + FilterCtx = avfilter_graph_get_filter(FilterGraph, Name.c_str()); + if (FilterCtx == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_STORE(FilterCtx, FilterCtxId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterGraphParsePtr::body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId, + uint32_t FiltersString, + uint32_t FiltersSize, + uint32_t InputsId, + uint32_t OutputsId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(FiltersId, MemInst, char, FiltersString, ""); + + FFMPEG_PTR_FETCH(Inputs, InputsId, AVFilterInOut); + FFMPEG_PTR_FETCH(Outputs, OutputsId, AVFilterInOut); + FFMPEG_PTR_FETCH(FiltersGraph, FilterGraphId, AVFilterGraph); + + std::string Filters; + std::copy_n(FiltersId, FiltersSize, std::back_inserter(Filters)); + return avfilter_graph_parse_ptr(FiltersGraph, Filters.c_str(), &Inputs, + &Outputs, nullptr); +} + +Expect AVFilterInOutFree::body(const Runtime::CallingFrame &, + uint32_t InOutId) { + + FFMPEG_PTR_FETCH(InOut, InOutId, AVFilterInOut); + avfilter_inout_free(&InOut); + FFMPEG_PTR_DELETE(InOutId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterVersion::body(const Runtime::CallingFrame &) { + return avfilter_version(); +} + +Expect AVFilterGetByName::body(const Runtime::CallingFrame &Frame, + uint32_t FilterPtr, uint32_t StrPtr, + uint32_t StrLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(StrId, MemInst, char, StrPtr, + "Failed when accessing the return Str memory"sv); + MEM_PTR_CHECK(FilterId, MemInst, uint32_t, FilterPtr, + "Failed when accessing the return Filter memory"sv); + + FFMPEG_PTR_FETCH(Filter, *FilterId, const struct AVFilter); + std::string Name; + std::copy_n(StrId, StrLen, std::back_inserter(Name)); + + Filter = avfilter_get_by_name(Name.c_str()); + if (Filter == nullptr) + return static_cast(ErrNo::Success); + + FFMPEG_PTR_STORE(const_cast(Filter), FilterId); + return static_cast(ErrNo::Success); +} + +Expect +AVFilterConfigurationLength::body(const Runtime::CallingFrame &) { + + const char *Config = avfilter_configuration(); + return strlen(Config); +} + +Expect AVFilterConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, + uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = avfilter_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFilterLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = avfilter_license(); + return strlen(License); +} + +Expect AVFilterLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, + uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = avfilter_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFilterGraphCreateFilter::body( + const Runtime::CallingFrame &Frame, uint32_t FilterCtxPtr, + uint32_t FilterId, uint32_t NamePtr, uint32_t NameLen, uint32_t ArgsPtr, + uint32_t ArgsLen, uint32_t FilterGraphId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + MEM_SPAN_CHECK(ArgsBuf, MemInst, char, ArgsPtr, ArgsLen, ""); + MEM_PTR_CHECK(FilterCtxId, MemInst, uint32_t, FilterCtxPtr, "") + + FFMPEG_PTR_FETCH(FilterCtx, *FilterCtxId, AVFilterContext); + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + + std::string Name; + std::string Args; + std::copy_n(NameBuf.data(), NameLen, std::back_inserter(Name)); + std::copy_n(ArgsBuf.data(), ArgsLen, std::back_inserter(Args)); + + int Res = avfilter_graph_create_filter(&FilterCtx, Filter, Name.c_str(), + Args.c_str(), nullptr, FilterGraph); + if (Res < 0) + return Res; + + FFMPEG_PTR_STORE(FilterCtx, FilterCtxId); + return Res; +} + +Expect AVFilterInOutAlloc::body(const Runtime::CallingFrame &Frame, + uint32_t InOutPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(InOutId, MemInst, uint32_t, InOutPtr, "") + + FFMPEG_PTR_FETCH(InOut, *InOutId, AVFilterInOut); + InOut = avfilter_inout_alloc(); + if (InOut == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_STORE(InOut, InOutId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterPadGetNameLength::body(const Runtime::CallingFrame &, + uint32_t FilterPadId, + int32_t Idx) { + + FFMPEG_PTR_FETCH(FilterPad, FilterPadId, AVFilterPad); + + const char *Name = avfilter_pad_get_name(FilterPad, Idx); + return strlen(Name); +} + +Expect AVFilterPadGetName::body(const Runtime::CallingFrame &Frame, + uint32_t FilterPadId, int32_t Idx, + uint32_t NamePtr, uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + + FFMPEG_PTR_FETCH(FilterPad, FilterPadId, AVFilterPad); + + const char *Name = avfilter_pad_get_name(FilterPad, Idx); + std::copy_n(Name, NameLen, NameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFilterPadGetType::body(const Runtime::CallingFrame &, + uint32_t FilterPadId, int32_t Idx) { + + FFMPEG_PTR_FETCH(FilterPad, FilterPadId, AVFilterPad); + AVMediaType const MediaType = avfilter_pad_get_type(FilterPad, Idx); + return FFmpegUtils::MediaType::fromMediaType(MediaType); +} + +Expect AVFilterGraphDumpLength::body(const Runtime::CallingFrame &, + uint32_t FilterGraphId) { + + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + char *Graph = avfilter_graph_dump(FilterGraph, nullptr); + return strlen(Graph); +} + +Expect AVFilterGraphDump::body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId, + uint32_t GraphStrPtr, + uint32_t GraphStrLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(GraphStr, MemInst, char, GraphStrPtr, GraphStrLen, ""); + + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + + char *Graph = avfilter_graph_dump(FilterGraph, nullptr); + std::copy_n(Graph, GraphStrLen, GraphStr.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFilterFreeGraphStr::body(const Runtime::CallingFrame &, + uint32_t FilterGraphId) { + + FFMPEG_PTR_FETCH(FilterGraph, FilterGraphId, AVFilterGraph); + + char *Graph = avfilter_graph_dump(FilterGraph, nullptr); + av_free(Graph); + return static_cast(ErrNo::Success); +} + +Expect AVFilterDrop::body(const Runtime::CallingFrame &, + uint32_t FilterId) { + + FFMPEG_PTR_FETCH(Filter, FilterId, struct AVFilter); + if (Filter == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_DELETE(FilterId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterPadDrop::body(const Runtime::CallingFrame &, + uint32_t FilterPadId) { + + FFMPEG_PTR_FETCH(FilterPad, FilterPadId, AVFilterPad); + if (FilterPad == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_DELETE(FilterPadId); + return static_cast(ErrNo::Success); +} + +Expect AVFilterContextDrop::body(const Runtime::CallingFrame &, + uint32_t FilterCtxId) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterCtxId, AVFilterContext); + if (FilterCtx == nullptr) + return static_cast(ErrNo::Success); + FFMPEG_PTR_DELETE(FilterCtxId); + return static_cast(ErrNo::Success); +} + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.h b/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.h new file mode 100644 index 000000000000..b96914e206b8 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.h @@ -0,0 +1,207 @@ +#pragma once + +#include "avfilter_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +class AVFilterGraphAlloc : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphAlloc(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphPtr); +}; + +class AVFilterGraphConfig : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphConfig(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId); +}; + +class AVFilterGraphFree : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId); +}; + +class AVFilterGraphGetFilter + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphGetFilter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterCtxPtr, uint32_t FilterGraphId, + uint32_t NamePtr, uint32_t NameSize); +}; + +class AVFilterGraphParsePtr + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphParsePtr(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId, uint32_t FiltersString, + uint32_t FiltersSize, uint32_t InputsId, + uint32_t OutputsId); +}; + +class AVFilterInOutFree : public WasmEdgeFFmpegAVFilter { +public: + AVFilterInOutFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t InOutId); +}; + +class AVFilterVersion : public WasmEdgeFFmpegAVFilter { +public: + AVFilterVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFilterGetByName : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGetByName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterPtr, + uint32_t StrPtr, uint32_t StrLen); +}; + +class AVFilterConfigurationLength + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFilterConfiguration + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class AVFilterLicenseLength + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFilterLicense : public WasmEdgeFFmpegAVFilter { +public: + AVFilterLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +class AVFilterGraphCreateFilter + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphCreateFilter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterCtxPtr, uint32_t FilterId, + uint32_t NamePtr, uint32_t NameLen, uint32_t ArgsPtr, + uint32_t ArgsLen, uint32_t FilterGraphId); +}; + +class AVFilterInOutAlloc : public WasmEdgeFFmpegAVFilter { +public: + AVFilterInOutAlloc(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t InOutPtr); +}; + +class AVFilterPadGetNameLength + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterPadGetNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterPadId, + int32_t Idx); +}; + +class AVFilterPadGetName : public WasmEdgeFFmpegAVFilter { +public: + AVFilterPadGetName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterPadId, + int32_t Idx, uint32_t NamePtr, uint32_t NameLen); +}; + +class AVFilterPadGetType : public WasmEdgeFFmpegAVFilter { +public: + AVFilterPadGetType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterPadId, + int32_t Idx); +}; + +class AVFilterGraphDumpLength + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphDumpLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId); +}; + +class AVFilterGraphDump : public WasmEdgeFFmpegAVFilter { +public: + AVFilterGraphDump(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId, uint32_t GraphStrPtr, + uint32_t GraphStrLen); +}; + +class AVFilterFreeGraphStr + : public WasmEdgeFFmpegAVFilter { +public: + AVFilterFreeGraphStr(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterGraphId); +}; + +class AVFilterDrop : public WasmEdgeFFmpegAVFilter { +public: + AVFilterDrop(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FilterId); +}; + +class AVFilterPadDrop : public WasmEdgeFFmpegAVFilter { +public: + AVFilterPadDrop(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterPadId); +}; + +class AVFilterContextDrop : public WasmEdgeFFmpegAVFilter { +public: + AVFilterContextDrop(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterCtxId); +}; + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.cpp b/plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.cpp new file mode 100644 index 000000000000..0aed3697356e --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.cpp @@ -0,0 +1,68 @@ +#include "buffer_source_sink.h" +extern "C" { +#include "libavfilter/buffersink.h" +#include "libavfilter/buffersrc.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +Expect AVBufferSinkGetFrame::body(const Runtime::CallingFrame &, + uint32_t FilterContextId, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterContextId, AVFilterContext); + FFMPEG_PTR_FETCH(Frame, FrameId, AVFrame); + return av_buffersink_get_frame(FilterCtx, Frame); +} + +Expect AVBufferSinkGetSamples::body(const Runtime::CallingFrame &, + uint32_t FilterContextId, + uint32_t FrameId, + int32_t Samples) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterContextId, AVFilterContext); + FFMPEG_PTR_FETCH(Frame, FrameId, AVFrame); + return av_buffersink_get_samples(FilterCtx, Frame, Samples); +} + +Expect AvBufferSinkSetFrameSize::body(const Runtime::CallingFrame &, + uint32_t FilterContextId, + int32_t Value) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterContextId, AVFilterContext); + av_buffersink_set_frame_size(FilterCtx, Value); + return static_cast(ErrNo::Success); +} + +Expect +AVBufferSrcGetNbFailedRequests::body(const Runtime::CallingFrame &, + uint32_t FilterContextId) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterContextId, AVFilterContext); + return av_buffersrc_get_nb_failed_requests(FilterCtx); +} + +Expect AVBufferSrcAddFrame::body(const Runtime::CallingFrame &, + uint32_t FilterContextId, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterContextId, AVFilterContext); + FFMPEG_PTR_FETCH(Frame, FrameId, AVFrame); + return av_buffersrc_add_frame(FilterCtx, Frame); +} + +Expect AVBufferSrcClose::body(const Runtime::CallingFrame &, + uint32_t FilterContextId, int64_t Pts, + uint32_t Flags) { + + FFMPEG_PTR_FETCH(FilterCtx, FilterContextId, AVFilterContext); + return av_buffersrc_close(FilterCtx, Pts, Flags); +} + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.h b/plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.h new file mode 100644 index 000000000000..7119d5fa5ec3 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/buffer_source_sink.h @@ -0,0 +1,67 @@ +#pragma once + +#include "avfilter_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +class AVBufferSinkGetFrame + : public WasmEdgeFFmpegAVFilter { +public: + AVBufferSinkGetFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterContextId, uint32_t FrameId); +}; + +class AVBufferSinkGetSamples + : public WasmEdgeFFmpegAVFilter { +public: + AVBufferSinkGetSamples(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterContextId, uint32_t FrameId, + int32_t Samples); +}; + +class AvBufferSinkSetFrameSize + : public WasmEdgeFFmpegAVFilter { +public: + AvBufferSinkSetFrameSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterContextId, int32_t Value); +}; + +class AVBufferSrcGetNbFailedRequests + : public WasmEdgeFFmpegAVFilter { +public: + AVBufferSrcGetNbFailedRequests(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterContextId); +}; + +class AVBufferSrcAddFrame : public WasmEdgeFFmpegAVFilter { +public: + AVBufferSrcAddFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterContextId, uint32_t FrameId); +}; + +class AVBufferSrcClose : public WasmEdgeFFmpegAVFilter { +public: + AVBufferSrcClose(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFilter(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t FilterContextId, int64_t Pts, uint32_t Flags); +}; + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/module.cpp b/plugins/wasmedge_ffmpeg/avfilter/module.cpp new file mode 100644 index 000000000000..2c31e44f64e3 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/module.cpp @@ -0,0 +1,108 @@ +#include "module.h" +#include "avFilter.h" +#include "avfilter_func.h" +#include "buffer_source_sink.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +WasmEdgeFFmpegAVFilterModule::WasmEdgeFFmpegAVFilterModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_avfilter") { + + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_alloc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_config", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_free", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_get_filter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_parse_ptr", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_inout_free", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_get_by_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_license", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_create_filter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_inout_alloc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_pad_get_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_pad_get_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_pad_get_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_dump_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_graph_dump", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_free_graph_str", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_drop", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_pad_drop", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_context_drop", + std::make_unique(Env)); + + // buffersrc.h && buffersink.h + addHostFunc("wasmedge_ffmpeg_avfilter_av_buffersink_get_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_av_buffersink_get_samples", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_av_buffersink_set_frame_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_av_buffersrc_get_nb_failed_requests", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_av_buffersrc_add_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_av_buffersrc_close", + std::make_unique(Env)); + + // avfilter.h + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_description_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_description", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_nb_inputs", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_nb_outputs", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_inout_set_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_inout_set_filter_ctx", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_inout_set_pad_idx", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_inout_set_next", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_get_inputs_filter_pad", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avfilter_avfilter_get_outputs_filter_pad", + std::make_unique(Env)); +} + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avfilter/module.h b/plugins/wasmedge_ffmpeg/avfilter/module.h new file mode 100644 index 000000000000..2515e6ae516c --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avfilter/module.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFilter { + +class WasmEdgeFFmpegAVFilterModule : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegAVFilterModule(std::shared_ptr Env); +}; + +} // namespace AVFilter +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp b/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp new file mode 100644 index 000000000000..1d5f5c41a31c --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp @@ -0,0 +1,196 @@ +#include "avChapter.h" + +extern "C" { +#include "libavformat/avformat.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +Expect AVChapterId::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, uint32_t ChapterIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + return static_cast(*AvChapter)->id; +} + +Expect AVChapterSetId::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx, int64_t ChapterId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + (*AvChapter)->id = ChapterId; + return static_cast(ErrNo::Success); +} + +Expect AVChapterTimebase::body(const Runtime::CallingFrame &Frame, + uint32_t NumPtr, uint32_t DenPtr, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, ""); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, ""); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + AVRational const AvRational = static_cast(*AvChapter)->time_base; + *Num = AvRational.num; + *Den = AvRational.den; + return static_cast(ErrNo::Success); +} + +Expect AVChapterSetTimebase::body(const Runtime::CallingFrame &, + int32_t Num, int32_t Den, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVRational const Timebase = av_make_q(Num, Den); + + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + (*AvChapter)->time_base = Timebase; + return static_cast(ErrNo::Success); +} + +Expect AVChapterStart::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + return static_cast(*AvChapter)->start; +} + +Expect AVChapterSetStart::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx, + int64_t StartValue) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + (*AvChapter)->start = StartValue; + return static_cast(ErrNo::Success); +} + +Expect AVChapterEnd::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + return static_cast(*AvChapter)->end; +} + +Expect AVChapterSetEnd::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx, int64_t EndValue) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVChapter **AvChapter = AvFormatContext->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + (*AvChapter)->end = EndValue; + return static_cast(ErrNo::Success); +} + +Expect AVChapterMetadata::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx, uint32_t DictPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(DictId, MemInst, uint32_t, DictPtr, + "Failed when accessing the return AVDictionary memory"sv); + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + + AVDictionary **AvDictionary = + static_cast(av_malloc(sizeof(AVDictionary *))); + AVChapter **AvChapter = AvFormatCtx->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + *AvDictionary = (*AvChapter)->metadata; + FFMPEG_PTR_STORE(AvDictionary, DictId); + return static_cast(ErrNo::Success); +} + +Expect AVChapterSetMetadata::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t ChapterIdx, + uint32_t DictId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvDictionary, DictId, AVDictionary *); + + AVChapter **AvChapter = AvFormatCtx->chapters; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= ChapterIdx; I++) + AvChapter++; + + if (AvDictionary == nullptr) + (*AvChapter)->metadata = nullptr; + else + (*AvChapter)->metadata = *AvDictionary; + return static_cast(ErrNo::Success); +} + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avChapter.h b/plugins/wasmedge_ffmpeg/avformat/avChapter.h new file mode 100644 index 000000000000..bb40c0887794 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avChapter.h @@ -0,0 +1,103 @@ +#pragma once + +#include "avformat_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +class AVChapterId : public WasmEdgeFFmpegAVFormat { +public: + AVChapterId(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx); +}; + +class AVChapterSetId : public WasmEdgeFFmpegAVFormat { +public: + AVChapterSetId(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx, + int64_t ChapterId); +}; + +class AVChapterTimebase : public WasmEdgeFFmpegAVFormat { +public: + AVChapterTimebase(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t NumPtr, + uint32_t DenPtr, uint32_t AvFormatCtxId, + uint32_t ChapterIdx); +}; + +class AVChapterSetTimebase + : public WasmEdgeFFmpegAVFormat { +public: + AVChapterSetTimebase(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t Num, + int32_t Den, uint32_t AvFormatCtxId, + uint32_t ChapterIdx); +}; + +class AVChapterStart : public WasmEdgeFFmpegAVFormat { +public: + AVChapterStart(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx); +}; + +class AVChapterSetStart : public WasmEdgeFFmpegAVFormat { +public: + AVChapterSetStart(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx, + int64_t StartValue); +}; + +class AVChapterEnd : public WasmEdgeFFmpegAVFormat { +public: + AVChapterEnd(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx); +}; + +class AVChapterSetEnd : public WasmEdgeFFmpegAVFormat { +public: + AVChapterSetEnd(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx, + int64_t EndValue); +}; + +class AVChapterMetadata : public WasmEdgeFFmpegAVFormat { +public: + AVChapterMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx, + uint32_t DictPtr); +}; + +class AVChapterSetMetadata + : public WasmEdgeFFmpegAVFormat { +public: + AVChapterSetMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t ChapterIdx, + uint32_t DictId); +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.cpp b/plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.cpp new file mode 100644 index 000000000000..5c0628f22ecd --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.cpp @@ -0,0 +1,215 @@ +#include "avInputOutputFormat.h" + +extern "C" { +#include "libavformat/avformat.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +Expect AVIOFormatNameLength::body(const Runtime::CallingFrame &, + uint32_t AVIOFormatId, + uint32_t FormatType) { + + const char *Name; + + if (FormatType == 0) { + FFMPEG_PTR_FETCH(AvInputFormat, AVIOFormatId, AVInputFormat); + Name = AvInputFormat->name; + } else { + FFMPEG_PTR_FETCH(AvOutputFormat, AVIOFormatId, AVOutputFormat); + Name = AvOutputFormat->name; + } + + if (Name == nullptr) + return 0; + return strlen(Name); +} + +Expect AVInputFormatName::body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, + uint32_t NamePtr, uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + FFMPEG_PTR_FETCH(AvInputFormat, AVInputFormatId, AVInputFormat); + + const char *Name = AvInputFormat->name; + std::copy_n(Name, NameLen, NameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVOutputFormatName::body(const Runtime::CallingFrame &Frame, + uint32_t AVOutputFormatId, + uint32_t NamePtr, uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + FFMPEG_PTR_FETCH(AvOutputFormat, AVOutputFormatId, AVOutputFormat); + + const char *Name = AvOutputFormat->name; + std::copy_n(Name, NameLen, NameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVIOFormatLongNameLength::body(const Runtime::CallingFrame &, + uint32_t AVIOFormatId, + uint32_t FormatType) { + + const char *LongName; + + if (FormatType == 0) { + FFMPEG_PTR_FETCH(AvInputFormat, AVIOFormatId, AVInputFormat); + LongName = AvInputFormat->long_name; + } else { + FFMPEG_PTR_FETCH(AvOutputFormat, AVIOFormatId, AVOutputFormat); + LongName = AvOutputFormat->long_name; + } + + if (LongName == nullptr) + return 0; + return strlen(LongName); +} + +Expect AVInputFormatLongName::body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, + uint32_t LongNamePtr, + uint32_t LongNameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LongNameBuf, MemInst, char, LongNamePtr, LongNameLen, ""); + FFMPEG_PTR_FETCH(AvInputFormat, AVInputFormatId, AVInputFormat); + + const char *LongName = AvInputFormat->long_name; + std::copy_n(LongName, LongNameLen, LongNameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVOutputFormatLongName::body(const Runtime::CallingFrame &Frame, + uint32_t AVOutputFormatId, + uint32_t LongNamePtr, + uint32_t LongNameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LongNameBuf, MemInst, char, LongNamePtr, LongNameLen, ""); + FFMPEG_PTR_FETCH(AvOutputFormat, AVOutputFormatId, AVOutputFormat); + + const char *LongName = AvOutputFormat->long_name; + std::copy_n(LongName, LongNameLen, LongNameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVIOFormatExtensionsLength::body(const Runtime::CallingFrame &, + uint32_t AVIOFormatId, + uint32_t FormatType) { + + const char *Extensions; + + if (FormatType == 0) { + FFMPEG_PTR_FETCH(AvInputFormat, AVIOFormatId, AVInputFormat); + Extensions = AvInputFormat->extensions; + } else { + FFMPEG_PTR_FETCH(AvOutputFormat, AVIOFormatId, AVOutputFormat); + Extensions = AvOutputFormat->extensions; + } + + if (Extensions == nullptr) + return 0; + return strlen(Extensions); +} + +Expect +AVInputFormatExtensions::body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t ExtensionsPtr, + uint32_t ExtensionsLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ExtensionsBuf, MemInst, char, ExtensionsPtr, ExtensionsLen, + ""); + FFMPEG_PTR_FETCH(AvInputFormat, AVInputFormatId, AVInputFormat); + + const char *Extensions = AvInputFormat->extensions; + std::copy_n(Extensions, ExtensionsLen, ExtensionsBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect +AVOutputFormatExtensions::body(const Runtime::CallingFrame &Frame, + uint32_t AVOutputFormatId, + uint32_t ExtensionsPtr, uint32_t ExtensionsLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ExtensionsBuf, MemInst, char, ExtensionsPtr, ExtensionsLen, + ""); + FFMPEG_PTR_FETCH(AvOutputFormat, AVOutputFormatId, AVOutputFormat); + + const char *Extensions = AvOutputFormat->extensions; + std::copy_n(Extensions, ExtensionsLen, ExtensionsBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVIOFormatMimeTypeLength::body(const Runtime::CallingFrame &, + uint32_t AVIOFormatId, + uint32_t FormatType) { + const char *MimeType; + + if (FormatType == 0) { + FFMPEG_PTR_FETCH(AvInputFormat, AVIOFormatId, AVInputFormat); + MimeType = AvInputFormat->mime_type; + } else { + FFMPEG_PTR_FETCH(AvOutputFormat, AVIOFormatId, AVOutputFormat); + MimeType = AvOutputFormat->mime_type; + } + + if (MimeType == nullptr) + return 0; + return strlen(MimeType); +} + +Expect AVInputFormatMimeType::body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, + uint32_t MimeTypePtr, + uint32_t MimeTypeLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(MimeTypeBuf, MemInst, char, MimeTypePtr, MimeTypeLen, ""); + FFMPEG_PTR_FETCH(AvInputFormat, AVInputFormatId, AVInputFormat); + + const char *MimeType = AvInputFormat->mime_type; + std::copy_n(MimeType, MimeTypeLen, MimeTypeBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVOutputFormatMimeType::body(const Runtime::CallingFrame &Frame, + uint32_t AVOutputFormatId, + uint32_t MimeTypePtr, + uint32_t MimeTypeLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(MimeTypeBuf, MemInst, char, MimeTypePtr, MimeTypeLen, ""); + FFMPEG_PTR_FETCH(AvOutputFormat, AVOutputFormatId, AVOutputFormat); + + const char *MimeType = AvOutputFormat->mime_type; + std::copy_n(MimeType, MimeTypeLen, MimeTypeBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVOutputFormatFlags::body(const Runtime::CallingFrame &, + uint32_t AVOutputFormatId) { + + FFMPEG_PTR_FETCH(AvOutputFormat, AVOutputFormatId, AVOutputFormat); + return AvOutputFormat->flags; +} + +Expect AVInputOutputFormatFree::body(const Runtime::CallingFrame &, + uint32_t AVInputOutputId) { + FFMPEG_PTR_DELETE(AVInputOutputId); + return static_cast(ErrNo::Success); +} + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.h b/plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.h new file mode 100644 index 000000000000..9c815ff80a74 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avInputOutputFormat.h @@ -0,0 +1,144 @@ +#pragma once +#include "avformat_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +class AVIOFormatNameLength + : public WasmEdgeFFmpegAVFormat { +public: + AVIOFormatNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AVIOFormatId, + uint32_t FormatType); +}; + +class AVInputFormatName : public WasmEdgeFFmpegAVFormat { +public: + AVInputFormatName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t NamePtr, + uint32_t NameLen); +}; + +class AVOutputFormatName : public WasmEdgeFFmpegAVFormat { +public: + AVOutputFormatName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t NamePtr, + uint32_t NameLen); +}; + +class AVIOFormatLongNameLength + : public WasmEdgeFFmpegAVFormat { +public: + AVIOFormatLongNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AVIOFormatId, + uint32_t FormatType); +}; + +class AVInputFormatLongName + : public WasmEdgeFFmpegAVFormat { +public: + AVInputFormatLongName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t LongNamePtr, + uint32_t LongNameLen); +}; + +class AVOutputFormatLongName + : public WasmEdgeFFmpegAVFormat { +public: + AVOutputFormatLongName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t LongNamePtr, + uint32_t LongNameLen); +}; + +class AVIOFormatExtensionsLength + : public WasmEdgeFFmpegAVFormat { +public: + AVIOFormatExtensionsLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AVIOFormatId, + uint32_t FormatType); +}; + +class AVInputFormatExtensions + : public WasmEdgeFFmpegAVFormat { +public: + AVInputFormatExtensions(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t Extensions, + uint32_t ExtensionsLen); +}; + +class AVOutputFormatExtensions + : public WasmEdgeFFmpegAVFormat { +public: + AVOutputFormatExtensions(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t Extensions, + uint32_t ExtensionsLen); +}; + +class AVIOFormatMimeTypeLength + : public WasmEdgeFFmpegAVFormat { +public: + AVIOFormatMimeTypeLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AVIOFormatId, + uint32_t FormatType); +}; + +class AVInputFormatMimeType + : public WasmEdgeFFmpegAVFormat { +public: + AVInputFormatMimeType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t MimeTypePtr, + uint32_t MimeTypeLen); +}; + +class AVOutputFormatMimeType + : public WasmEdgeFFmpegAVFormat { +public: + AVOutputFormatMimeType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId, uint32_t MimeTypePtr, + uint32_t MimeTypeLen); +}; + +class AVOutputFormatFlags : public WasmEdgeFFmpegAVFormat { +public: + AVOutputFormatFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputFormatId); +}; + +class AVInputOutputFormatFree + : public WasmEdgeFFmpegAVFormat { +public: + AVInputOutputFormatFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputOutputId); +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avStream.cpp b/plugins/wasmedge_ffmpeg/avformat/avStream.cpp new file mode 100644 index 000000000000..1eaebef6915d --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avStream.cpp @@ -0,0 +1,285 @@ +#include "avStream.h" + +extern "C" { +#include "libavformat/avformat.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +Expect AVStreamId::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + // No check here (Check) + // Raw Pointer Iteration. + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast(*AvStream)->id; +} + +Expect AVStreamIndex::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast(*AvStream)->index; +} + +Expect AVStreamCodecPar::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + uint32_t StreamIdx, + uint32_t CodecParameterPtr) { + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(CodecParamId, MemInst, uint32_t, CodecParameterPtr, + "Failed when accessing the return CodecParameter Memory"sv); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVCodecParameters *CodecParam = + (static_cast(*AvStream))->codecpar; + FFMPEG_PTR_STORE(CodecParam, CodecParamId); + return static_cast(ErrNo::Success); +} + +Expect AVStreamTimebase::body(const Runtime::CallingFrame &Frame, + uint32_t NumPtr, uint32_t DenPtr, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, ""); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, ""); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVRational const AvRational = static_cast(*AvStream)->time_base; + *Num = AvRational.num; + *Den = AvRational.den; + return static_cast(ErrNo::Success); +} + +Expect AVStreamSetTimebase::body(const Runtime::CallingFrame &, + uint32_t Num, uint32_t Den, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + + AVStream **AvStream = AvFormatContext->streams; + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVRational const Timebase = av_make_q(Num, Den); + (*AvStream)->time_base = Timebase; + return static_cast(ErrNo::Success); +} + +Expect AVStreamDuration::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast(*AvStream)->duration; +} + +Expect AVStreamStartTime::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast(*AvStream)->start_time; +} + +Expect AVStreamNbFrames::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast(*AvStream)->nb_frames; +} + +Expect AVStreamDisposition::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast(*AvStream)->disposition; +} + +Expect AVStreamRFrameRate::body(const Runtime::CallingFrame &Frame, + uint32_t NumPtr, uint32_t DenPtr, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, ""); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, ""); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVRational const AvRational = + static_cast(*AvStream)->r_frame_rate; + *Num = AvRational.num; + *Den = AvRational.den; + return static_cast(ErrNo::Success); +} + +Expect AVStreamSetRFrameRate::body(const Runtime::CallingFrame &, + int32_t Num, int32_t Den, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + + AVStream **AvStream = AvFormatContext->streams; + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVRational const RFrameRate = av_make_q(Num, Den); + (*AvStream)->r_frame_rate = RFrameRate; + return static_cast(ErrNo::Success); +} + +Expect AVStreamAvgFrameRate::body(const Runtime::CallingFrame &Frame, + uint32_t NumPtr, uint32_t DenPtr, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, ""); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, ""); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVRational const AvRational = + static_cast(*AvStream)->avg_frame_rate; + *Num = AvRational.num; + *Den = AvRational.den; + return static_cast(ErrNo::Success); +} + +Expect AVStreamSetAvgFrameRate::body(const Runtime::CallingFrame &, + int32_t Num, int32_t Den, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVRational const AvgFrameRate = av_make_q(Num, Den); + (*AvStream)->avg_frame_rate = AvgFrameRate; + return static_cast(ErrNo::Success); +} + +Expect AVStreamMetadata::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + uint32_t StreamIdx, uint32_t DictPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(DictId, MemInst, uint32_t, DictPtr, + "Failed when accessing the return AVDictPtr Memory"sv); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + AVDictionary **AvDictionary = + static_cast(av_malloc(sizeof(AVDictionary *))); + + *AvDictionary = (*AvStream)->metadata; + FFMPEG_PTR_STORE(AvDictionary, DictId); + return static_cast(ErrNo::Success); +} + +Expect AVStreamSetMetadata::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx, uint32_t DictId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvDictionary, DictId, AVDictionary *); + + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + if (AvDictionary == nullptr) + (*AvStream)->metadata = nullptr; + else + (*AvStream)->metadata = *AvDictionary; + + return static_cast(ErrNo::Success); +} + +Expect AVStreamDiscard::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AVStream **AvStream = AvFormatContext->streams; + + for (unsigned int I = 1; I <= StreamIdx; I++) + AvStream++; + + return static_cast((*AvStream)->discard); +} + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avStream.h b/plugins/wasmedge_ffmpeg/avformat/avStream.h new file mode 100644 index 000000000000..4a8956ceaaa1 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avStream.h @@ -0,0 +1,152 @@ +#pragma once + +#include "avformat_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +class AVStreamId : public WasmEdgeFFmpegAVFormat { +public: + AVStreamId(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamIndex : public WasmEdgeFFmpegAVFormat { +public: + AVStreamIndex(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamCodecPar : public WasmEdgeFFmpegAVFormat { +public: + AVStreamCodecPar(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx, + uint32_t CodecParameterPtr); +}; + +class AVStreamTimebase : public WasmEdgeFFmpegAVFormat { +public: + AVStreamTimebase(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t NumPtr, + uint32_t DenPtr, uint32_t AvFormatCtxId, + uint32_t StreamIdx); +}; + +class AVStreamSetTimebase : public WasmEdgeFFmpegAVFormat { +public: + AVStreamSetTimebase(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t Num, + uint32_t Den, uint32_t AvFormatCtxId, + uint32_t StreamIdx); +}; + +class AVStreamDuration : public WasmEdgeFFmpegAVFormat { +public: + AVStreamDuration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamStartTime : public WasmEdgeFFmpegAVFormat { +public: + AVStreamStartTime(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamNbFrames : public WasmEdgeFFmpegAVFormat { +public: + AVStreamNbFrames(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamDisposition : public WasmEdgeFFmpegAVFormat { +public: + AVStreamDisposition(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamRFrameRate : public WasmEdgeFFmpegAVFormat { +public: + AVStreamRFrameRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t NumPtr, + uint32_t DenPtr, uint32_t AvFormatCtxId, + uint32_t StreamIdx); +}; + +class AVStreamSetRFrameRate + : public WasmEdgeFFmpegAVFormat { +public: + AVStreamSetRFrameRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t Num, + int32_t Den, uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamAvgFrameRate + : public WasmEdgeFFmpegAVFormat { +public: + AVStreamAvgFrameRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t NumPtr, + uint32_t DenPtr, uint32_t AvFormatCtxId, + uint32_t StreamIdx); +}; + +class AVStreamSetAvgFrameRate + : public WasmEdgeFFmpegAVFormat { +public: + AVStreamSetAvgFrameRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t Num, + int32_t Den, uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +class AVStreamMetadata : public WasmEdgeFFmpegAVFormat { +public: + AVStreamMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx, + uint32_t DictPtr); +}; + +class AVStreamSetMetadata : public WasmEdgeFFmpegAVFormat { +public: + AVStreamSetMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx, + uint32_t DictId); +}; + +class AVStreamDiscard : public WasmEdgeFFmpegAVFormat { +public: + AVStreamDiscard(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t StreamIdx); +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp b/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp new file mode 100644 index 000000000000..5c9515f8ea75 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp @@ -0,0 +1,122 @@ +#include "avformatContext.h" + +extern "C" { +#include "libavformat/avformat.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +Expect AVFormatCtxIFormat::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + uint32_t AvInputFormatPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AvInputFormatId, MemInst, uint32_t, AvInputFormatPtr, + "Failed when accessing the return AVInputFormat Memory"sv); + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + + AVInputFormat const *AvInputFormat = AvFormatCtx->iformat; + FFMPEG_PTR_STORE(const_cast(AvInputFormat), AvInputFormatId); + return static_cast(ErrNo::Success); +} + +Expect AVFormatCtxOFormat::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + uint32_t AvOutputFormatPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AvOutputFormatId, MemInst, uint32_t, AvOutputFormatPtr, + "Failed when accessing the return AVOutputFormat Memory"sv); + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + + AVOutputFormat const *AvOutputFormat = AvFormatCtx->oformat; + FFMPEG_PTR_STORE(const_cast(AvOutputFormat), + AvOutputFormatId); + return static_cast(ErrNo::Success); +} + +Expect AVFormatCtxProbeScore::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return AvFormatContext->probe_score; +} + +Expect AVFormatCtxNbStreams::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return AvFormatContext->nb_streams; +}; + +Expect AVFormatCtxBitRate::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return AvFormatContext->bit_rate; +} + +Expect AVFormatCtxDuration::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return AvFormatContext->duration; +} + +Expect AVFormatCtxNbChapters::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return AvFormatContext->nb_chapters; +} + +Expect AVFormatCtxSetNbChapters::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t NbChapters) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + AvFormatContext->nb_chapters = NbChapters; + return static_cast(ErrNo::Success); +} + +Expect AVFormatCtxMetadata::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + uint32_t DictPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(DictId, MemInst, uint32_t, DictPtr, + "Failed when accessing the return AVDictionary memory"sv); + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + + AVDictionary **AvDictionary = + static_cast(av_malloc(sizeof(AVDictionary *))); + + *AvDictionary = AvFormatCtx->metadata; + FFMPEG_PTR_STORE(AvDictionary, DictId); + return static_cast(ErrNo::Success); +} + +Expect AVFormatCtxSetMetadata::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t DictId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvDictionary, DictId, AVDictionary *); + + if (AvDictionary == nullptr) + AvFormatCtx->metadata = nullptr; + else + AvFormatCtx->metadata = *AvDictionary; + return static_cast(ErrNo::Success); +} + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avformatContext.h b/plugins/wasmedge_ffmpeg/avformat/avformatContext.h new file mode 100644 index 000000000000..90cd679e4987 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avformatContext.h @@ -0,0 +1,99 @@ +#pragma once + +#include "avformat_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +class AVFormatCtxIFormat : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxIFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t AvInputFormatPtr); +}; + +class AVFormatCtxOFormat : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxOFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t AvOutputFormatPtr); +}; + +class AVFormatCtxProbeScore + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxProbeScore(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatCtxNbStreams + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxNbStreams(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatCtxBitRate : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxBitRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatCtxDuration : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxDuration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatCtxNbChapters + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxNbChapters(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatCtxSetNbChapters + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxSetNbChapters(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t NbChapters); +}; + +class AVFormatCtxMetadata : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t DictPtr); +}; + +class AVFormatCtxSetMetadata + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCtxSetMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t DictId); +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avformat_base.h b/plugins/wasmedge_ffmpeg/avformat/avformat_base.h new file mode 100644 index 000000000000..28318eb2b871 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avformat_base.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +template +class WasmEdgeFFmpegAVFormat : public Runtime::HostFunction { +public: + WasmEdgeFFmpegAVFormat( + std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp b/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp new file mode 100644 index 000000000000..545894db0205 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp @@ -0,0 +1,383 @@ +#include "avformat_func.h" + +extern "C" { +#include "libavcodec/packet.h" +#include "libavformat/avformat.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +Expect AVFormatOpenInput::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxPtr, + uint32_t UrlPtr, uint32_t UrlSize, + uint32_t AvInputFormatId, + uint32_t AvDictionaryId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(urlId, MemInst, char, UrlPtr, + "Failed when accessing the return URL memory"sv); + MEM_PTR_CHECK(AvFormatCtxId, MemInst, uint32_t, AvFormatCtxPtr, + "Failed when accessing the return AVFormatContext Memory"sv); + + std::string TargetUrl; + std::copy_n(urlId, UrlSize, std::back_inserter(TargetUrl)); + + AVFormatContext *AvFormatContext = nullptr; + FFMPEG_PTR_FETCH(AvDictionary, AvDictionaryId, AVDictionary *); + FFMPEG_PTR_FETCH(AvInputFormat, AvInputFormatId, AVInputFormat); + + int const Res = avformat_open_input(&AvFormatContext, TargetUrl.c_str(), + AvInputFormat, AvDictionary); + FFMPEG_PTR_STORE(AvFormatContext, AvFormatCtxId); + return Res; +} + +Expect AVFormatFindStreamInfo::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t AvDictionaryId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvDictionary, AvDictionaryId, AVDictionary *); + return avformat_find_stream_info(AvFormatContext, AvDictionary); +} + +Expect AVFormatCloseInput::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + avformat_close_input(&AvFormatCtx); + FFMPEG_PTR_DELETE(AvFormatCtxId); + return static_cast(ErrNo::Success); +} + +Expect AVReadPause::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return av_read_pause(AvFormatContext); +} + +Expect AVReadPlay::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return av_read_play(AvFormatContext); +} + +Expect AVFormatSeekFile::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t StreamIdx, int64_t MinTs, + int64_t Ts, int64_t MaxTs, + int32_t Flags) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return avformat_seek_file(AvFormatContext, StreamIdx, MinTs, Ts, MaxTs, + Flags); +} + +Expect AVDumpFormat::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, int32_t Idx, + uint32_t UrlPtr, uint32_t UrlSize, + int32_t IsOutput) { + std::string TargetUrl; + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(UrlBuf, MemInst, char, UrlPtr, ""); + + std::copy_n(UrlBuf, UrlSize, std::back_inserter(TargetUrl)); + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + + av_dump_format(AvFormatCtx, Idx, TargetUrl.c_str(), IsOutput); + return static_cast(ErrNo::Success); +} + +Expect AVFormatFreeContext::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + avformat_free_context(AvFormatCtx); + FFMPEG_PTR_DELETE(AvFormatCtxId); + return static_cast(ErrNo::Success); +} + +Expect AVFindBestStream::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + int32_t MediaTypeId, + int32_t WantedStream, + int32_t RelatedStream, + uint32_t DecoderRetId, int32_t Flags) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(DecoderRet, DecoderRetId, const AVCodec *); + + AVMediaType const AvMediaType = + FFmpegUtils::MediaType::intoMediaType(MediaTypeId); + return av_find_best_stream(AvFormatContext, AvMediaType, WantedStream, + RelatedStream, DecoderRet, Flags); +} + +Expect AVReadFrame::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, uint32_t PacketId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvPacket, PacketId, AVPacket); + + return av_read_frame(AvFormatContext, AvPacket); +} + +Expect AVIOClose::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + avio_close(AvFormatCtx->pb); + return static_cast(ErrNo::Success); +} + +Expect AVFormatNetworkInit::body(const Runtime::CallingFrame &) { + return avformat_network_init(); +} + +Expect AVFormatNetworkDeInit::body(const Runtime::CallingFrame &) { + return avformat_network_deinit(); +} + +Expect AVFormatWriteHeader::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t DictId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvDict, DictId, AVDictionary *); + return avformat_write_header(AvFormatContext, AvDict); +} + +Expect AVFormatWriteTrailer::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId) { + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + return av_write_trailer(AvFormatContext); +} + +Expect AVFormatAllocOutputContext2::body( + const Runtime::CallingFrame &Frame, uint32_t AvFormatCtxPtr, + uint32_t AVOutputFormatId, uint32_t FormatNamePtr, uint32_t FormatLen, + uint32_t FileNamePtr, uint32_t FileNameLen) { + + std::string Format; + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(FileId, MemInst, char, FileNamePtr, + "Failed when accessing the return FileName memory"sv); + if (FormatLen > 0) { + MEM_PTR_CHECK(FormatId, MemInst, char, FormatNamePtr, + "Failed when accessing the return FormatName memory"sv); + + std::copy_n(FormatId, FormatLen, std::back_inserter(Format)); + } + MEM_PTR_CHECK(AvFormatCtxId, MemInst, uint32_t, AvFormatCtxPtr, + "Failed when accessing the return AVFormatContext Memory"sv); + + std::string File; + std::copy_n(FileId, FileNameLen, std::back_inserter(File)); + + AVFormatContext *AvFormatContext = nullptr; + FFMPEG_PTR_FETCH(AvOutputFormat, AVOutputFormatId, AVOutputFormat); + + int Res = 0; + if (FormatLen == 0) { + Res = avformat_alloc_output_context2(&AvFormatContext, AvOutputFormat, + nullptr, File.c_str()); + } else { + Res = avformat_alloc_output_context2(&AvFormatContext, AvOutputFormat, + Format.c_str(), File.c_str()); + } + FFMPEG_PTR_STORE(AvFormatContext, AvFormatCtxId); + return Res; +} + +Expect AVIOOpen::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t FileNamePtr, + uint32_t FileNameLen, int32_t Flags) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(FileId, MemInst, char, FileNamePtr, + "Failed when accessing the return FileName memory"sv); + + std::string File; + std::copy_n(FileId, FileNameLen, std::back_inserter(File)); + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + + return avio_open(&(AvFormatContext->pb), File.c_str(), Flags); +} + +Expect AVIOOpen2::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxtId, uint32_t UrlPtr, + uint32_t UrlLen, int32_t Flags, + uint32_t AVIOInterruptCBId, + uint32_t AVDictionaryId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(UrlId, MemInst, char, UrlPtr, + "Failed when accessing the return Url memory"sv); + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxtId, AVFormatContext); + FFMPEG_PTR_FETCH(AvDictionary, AVDictionaryId, AVDictionary *); + FFMPEG_PTR_FETCH(AvIOInterruptCB, AVIOInterruptCBId, AVIOInterruptCB); + + std::string TargetUrl; + std::copy_n(UrlId, UrlLen, std::back_inserter(TargetUrl)); + + return avio_open2(&(AvFormatCtx->pb), TargetUrl.c_str(), Flags, + AvIOInterruptCB, AvDictionary); +} + +Expect AVFormatVersion::body(const Runtime::CallingFrame &) { + return avformat_version(); +} + +Expect AVChapterMallocz::body(const Runtime::CallingFrame &Frame, + uint32_t AVChapterPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(AvChapterId, MemInst, uint32_t, AVChapterPtr, + "Failed to access Memory for AVChapterPtr"sv) + + AVChapter *AvChapter = + static_cast(av_mallocz(sizeof(AVChapter))); + FFMPEG_PTR_STORE(AvChapter, AvChapterId); + return static_cast(ErrNo::Success); +} + +Expect AVChapterDynarrayAdd::body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, + int32_t NbChaptersPtr, + uint32_t AvChapterId) { + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(NbChapters, MemInst, int32_t, NbChaptersPtr, + "Failed to access Memory for NbChaptersPtr"sv) + + FFMPEG_PTR_FETCH(AvFormatContext, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvChapter, AvChapterId, AVChapter); + + av_dynarray_add(&(AvFormatContext->chapters), NbChapters, AvChapter); + if (*(AvFormatContext->chapters) == nullptr && *(NbChapters) == 0) + return static_cast(ErrNo::InternalError); + return static_cast(ErrNo::Success); +} + +Expect AVFreeP::body(const Runtime::CallingFrame &, + uint32_t AvChapterId) { + + FFMPEG_PTR_FETCH(AvChapter, AvChapterId, AVChapter); + av_freep(AvChapter); + FFMPEG_PTR_DELETE(AvChapterId); + return static_cast(ErrNo::Success); +} + +Expect AVInterleavedWriteFrame::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + + return av_interleaved_write_frame(AvFormatCtx, AvPacket); +} + +Expect AVWriteFrame::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t AvPacketId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvPacket, AvPacketId, AVPacket); + + return av_write_frame(AvFormatCtx, AvPacket); +} + +Expect AVFormatNewStream::body(const Runtime::CallingFrame &, + uint32_t AvFormatCtxId, + uint32_t AvCodecId) { + + FFMPEG_PTR_FETCH(AvFormatCtx, AvFormatCtxId, AVFormatContext); + FFMPEG_PTR_FETCH(AvCodec, AvCodecId, const AVCodec); + AVStream *Stream = avformat_new_stream(AvFormatCtx, AvCodec); + if (Stream == nullptr) + return 0; + return 1; +} + +Expect AVGuessCodec::body(const Runtime::CallingFrame &Frame, + uint32_t AVIOFormatId, + uint32_t ShortNamePtr, + uint32_t ShortNameLen, uint32_t FileNamePtr, + uint32_t FileNameLen, uint32_t MimeTypePtr, + uint32_t MimeTypeLen, int32_t MediaTypeId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(ShortNameBuf, MemInst, char, ShortNamePtr, + "Failed when accessing the return ShortName memory"sv); + MEM_PTR_CHECK(FileNameBuf, MemInst, char, FileNamePtr, + "Failed when accessing the return FileName memory"sv); + MEM_PTR_CHECK(MimeTypeBuf, MemInst, char, MimeTypePtr, + "Failed when accessing the return MimeType memory"sv); + FFMPEG_PTR_FETCH(AvOutputFormat, AVIOFormatId, AVOutputFormat); + + std::string ShortName; + std::string FileName; + std::string MimeType; + std::copy_n(ShortNameBuf, ShortNameLen, std::back_inserter(ShortName)); + std::copy_n(FileNameBuf, FileNameLen, std::back_inserter(FileName)); + std::copy_n(MimeTypeBuf, MimeTypeLen, std::back_inserter(MimeType)); + + AVMediaType const MediaType = + FFmpegUtils::MediaType::intoMediaType(MediaTypeId); + AVCodecID const Id = + av_guess_codec(AvOutputFormat, ShortName.c_str(), FileName.c_str(), + MimeType.c_str(), MediaType); + + return FFmpegUtils::CodecID::fromAVCodecID(Id); +} + +Expect +AVFormatConfigurationLength::body(const Runtime::CallingFrame &) { + + const char *Config = avformat_configuration(); + return strlen(Config); +} + +Expect AVFormatConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, + uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = avformat_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFormatLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = avformat_license(); + return strlen(License); +} + +Expect AVFormatLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, + uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = avformat_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/avformat_func.h b/plugins/wasmedge_ffmpeg/avformat/avformat_func.h new file mode 100644 index 000000000000..3cc44a3379ae --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/avformat_func.h @@ -0,0 +1,273 @@ +#pragma once + +#include "avformat_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +class AVFormatOpenInput : public WasmEdgeFFmpegAVFormat { +public: + AVFormatOpenInput(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxPtr, uint32_t UrlPtr, + uint32_t UrlSize, uint32_t AvInputFormatId, + uint32_t AvDictionaryId); +}; + +class AVFormatFindStreamInfo + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatFindStreamInfo(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + uint32_t AvDictionaryId); +}; + +class AVFormatCloseInput : public WasmEdgeFFmpegAVFormat { +public: + AVFormatCloseInput(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVReadPause : public WasmEdgeFFmpegAVFormat { +public: + AVReadPause(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId); +}; + +class AVReadPlay : public WasmEdgeFFmpegAVFormat { +public: + AVReadPlay(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId); +}; + +class AVFormatSeekFile : public WasmEdgeFFmpegAVFormat { +public: + AVFormatSeekFile(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + uint32_t StreamIdx, int64_t MinTs, int64_t Ts, + int64_t MaxTs, int32_t Flags); +}; + +class AVDumpFormat : public WasmEdgeFFmpegAVFormat { +public: + AVDumpFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, int32_t Idx, uint32_t UrlPtr, + uint32_t UrlSize, int32_t IsOutput); +}; + +class AVFormatFreeContext : public WasmEdgeFFmpegAVFormat { +public: + AVFormatFreeContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxPtr); +}; + +class AVFindBestStream : public WasmEdgeFFmpegAVFormat { +public: + AVFindBestStream(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + int32_t MediaTypeId, int32_t WantedStream, + int32_t RelatedStream, uint32_t DecoderRetId, + int32_t Flags); +}; + +class AVReadFrame : public WasmEdgeFFmpegAVFormat { +public: + AVReadFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + uint32_t PacketId); +}; + +class AVIOClose : public WasmEdgeFFmpegAVFormat { +public: + AVIOClose(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatNetworkInit : public WasmEdgeFFmpegAVFormat { +public: + AVFormatNetworkInit(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFormatNetworkDeInit + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatNetworkDeInit(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFormatWriteHeader : public WasmEdgeFFmpegAVFormat { +public: + AVFormatWriteHeader(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t DictId); +}; + +class AVFormatWriteTrailer + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatWriteTrailer(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId); +}; + +class AVFormatAllocOutputContext2 + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatAllocOutputContext2(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxPtr, uint32_t AVOutputFormatId, + uint32_t FormatNamePtr, uint32_t FormatLen, + uint32_t FileNamePtr, uint32_t FileNameLen); +}; + +class AVIOOpen : public WasmEdgeFFmpegAVFormat { +public: + AVIOOpen(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxId, uint32_t FileNamePtr, + uint32_t FileNameLen, int32_t Flags); +}; + +class AVIOOpen2 : public WasmEdgeFFmpegAVFormat { +public: + AVIOOpen2(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvFormatCtxtId, uint32_t UrlPtr, + uint32_t UrlLen, int32_t Flags, + uint32_t AVIOInterruptCBId, uint32_t AVDictionaryId); +}; + +class AVFormatVersion : public WasmEdgeFFmpegAVFormat { +public: + AVFormatVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVChapterMallocz : public WasmEdgeFFmpegAVFormat { +public: + AVChapterMallocz(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVChapterPtr); +}; + +class AVChapterDynarrayAdd + : public WasmEdgeFFmpegAVFormat { +public: + AVChapterDynarrayAdd(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + int32_t NbChaptersPtr, uint32_t AvChapterId); +}; + +class AVFreeP : public WasmEdgeFFmpegAVFormat { +public: + AVFreeP(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + + Expect body(const Runtime::CallingFrame &, uint32_t AvChapterId); +}; + +class AVInterleavedWriteFrame + : public WasmEdgeFFmpegAVFormat { +public: + AVInterleavedWriteFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + uint32_t AvPacketId); +}; + +class AVWriteFrame : public WasmEdgeFFmpegAVFormat { +public: + AVWriteFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + + Expect body(const Runtime::CallingFrame &, uint32_t AvFormatCtxId, + uint32_t AvPacketId); +}; + +class AVFormatNewStream : public WasmEdgeFFmpegAVFormat { +public: + AVFormatNewStream(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVFormatCtxId, uint32_t AVCodecId); +}; + +class AVGuessCodec : public WasmEdgeFFmpegAVFormat { +public: + AVGuessCodec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AVInputOutputId, uint32_t ShortNamePtr, + uint32_t ShortNameLen, uint32_t FileNamePtr, + uint32_t FileNameLen, uint32_t MimeTypePtr, + uint32_t MimeTypeLen, int32_t MediaTypeId); +}; + +class AVFormatConfigurationLength + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFormatConfiguration + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class AVFormatLicenseLength + : public WasmEdgeFFmpegAVFormat { +public: + AVFormatLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVFormatLicense : public WasmEdgeFFmpegAVFormat { +public: + AVFormatLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVFormat(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/module.cpp b/plugins/wasmedge_ffmpeg/avformat/module.cpp new file mode 100644 index 000000000000..0d1ec1087bc6 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/module.cpp @@ -0,0 +1,193 @@ +#include "module.h" +#include "avChapter.h" +#include "avInputOutputFormat.h" +#include "avStream.h" +#include "avformatContext.h" +#include "avformat_func.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +WasmEdgeFFmpegAVFormatModule::WasmEdgeFFmpegAVFormatModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_avformat") { + + // avformat_func.h + addHostFunc("wasmedge_ffmpeg_avformat_avformat_open_input", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_find_stream_info", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_close_input", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_read_play", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_read_pause", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_dump_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_seek_file", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_free_context", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_find_best_stream", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_read_frame", // TODO: Write Test + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avio_close", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_network_init", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_network_deinit", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_write_header", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_write_trailer", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_alloc_output_context2", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avio_open", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avio_open2", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avchapter_mallocz", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avformat_avchapter_dynarray_add", // TODO: Write Test + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_avfreep", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_write_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_interleaved_write_frame", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avformat_avformat_new_stream", // TODO: Write Test + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_av_guess_codec", // TODO: Write Test + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformat_license", + std::make_unique(Env)); + + // avformatContext Struct functions. + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_iformat", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_oformat", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_probescope", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_nb_streams", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_duration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_bit_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_nb_chapters", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_set_nb_chapters", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_metadata", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avformatContext_set_metadata", + std::make_unique(Env)); + + // avInputFormat Struct functions. + addHostFunc("wasmedge_ffmpeg_avformat_avIOFormat_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avInputFormat_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avOutputFormat_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avIOFormat_long_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avInputFormat_long_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avOutputFormat_long_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avIOFormat_extensions_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avInputFormat_extensions", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avOutputFormat_extensions", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avIOFormat_mime_type_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avInputFormat_mime_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avOutputFormat_mime_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avOutputFormat_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avInputOutputFormat_free", + std::make_unique(Env)); + + // avStream Struct Functions. + addHostFunc("wasmedge_ffmpeg_avformat_avStream_id", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_index", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_codecpar", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_timebase", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_set_timebase", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_duration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_start_time", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_nb_frames", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_disposition", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_r_frame_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_set_r_frame_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_avg_frame_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_set_avg_frame_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_metadata", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_set_metadata", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avStream_discard", + std::make_unique(Env)); + + // avChapter Struct Functions. + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_id", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_set_id", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_timebase", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_set_timebase", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_start", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_set_start", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_end", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_set_end", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_metadata", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avformat_avChapter_set_metadata", + std::make_unique(Env)); +} + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avformat/module.h b/plugins/wasmedge_ffmpeg/avformat/module.h new file mode 100644 index 000000000000..4ab491ed22af --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avformat/module.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVFormat { + +class WasmEdgeFFmpegAVFormatModule : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegAVFormatModule(std::shared_ptr Env); +}; + +} // namespace AVFormat +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp b/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp new file mode 100644 index 000000000000..047f309c8d36 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp @@ -0,0 +1,159 @@ +#include "avDictionary.h" + +extern "C" { +#include "libavutil/dict.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVDictSet::body(const Runtime::CallingFrame &Frame, + uint32_t DictPtr, uint32_t KeyPtr, + uint32_t KeyLen, uint32_t ValuePtr, + uint32_t ValueLen, int32_t Flags) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(KeyBuf, MemInst, char, KeyPtr, + "Failed when accessing the return Key memory"sv); + MEM_PTR_CHECK(ValueBuf, MemInst, char, ValuePtr, + "Failed when accessing the return Value memory"sv); + MEM_PTR_CHECK(DictId, MemInst, uint32_t, DictPtr, + "Failed to access Memory for AVDict"sv) + + std::string Key; + std::string Value; + std::copy_n(KeyBuf, KeyLen, std::back_inserter(Key)); + std::copy_n(ValueBuf, ValueLen, std::back_inserter(Value)); + + int Res = 0; + + // Using Maybe::uninit(); in Rust. If Uninitialized, zero is + // passed. Else the Ptr contains a Number. + if (*DictId) { + FFMPEG_PTR_FETCH(AvDict, *DictId, AVDictionary *); + Res = av_dict_set(AvDict, Key.c_str(), Value.c_str(), Flags); + } else { + AVDictionary **AvDict = + static_cast(av_mallocz(sizeof(AVDictionary *))); + Res = av_dict_set(AvDict, Key.c_str(), Value.c_str(), Flags); + FFMPEG_PTR_STORE(AvDict, DictId); + } + + return Res; +} + +Expect AVDictCopy::body(const Runtime::CallingFrame &Frame, + uint32_t DestDictPtr, uint32_t SrcDictId, + uint32_t Flags) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(DestDictId, MemInst, uint32_t, DestDictPtr, + "Failed to access Memory for AVDict"sv) + + FFMPEG_PTR_FETCH(SrcAvDict, SrcDictId, AVDictionary *); + + int Res = 0; + + if (SrcAvDict == nullptr) + return static_cast(ErrNo::InternalError); + + if (*DestDictId) { + FFMPEG_PTR_FETCH(DestAvDict, *DestDictId, AVDictionary *); + Res = av_dict_copy(DestAvDict, *SrcAvDict, Flags); + } else { + AVDictionary **DestAvDict = + static_cast(av_mallocz(sizeof(AVDictionary *))); + av_dict_copy(DestAvDict, *SrcAvDict, Flags); + FFMPEG_PTR_STORE(DestAvDict, DestDictId); + } + + return Res; +} + +Expect AVDictGet::body(const Runtime::CallingFrame &Frame, + uint32_t DictId, uint32_t KeyPtr, + uint32_t KeyLen, uint32_t PrevDictEntryIdx, + uint32_t Flags, uint32_t KeyLenPtr, + uint32_t ValueLenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(KeyStr, MemInst, char, KeyPtr, + "Failed when accessing the return Key memory"sv); + MEM_PTR_CHECK(KeyLenId, MemInst, uint32_t, KeyLenPtr, + "Failed when accessing the return KeyLen memory"sv); + MEM_PTR_CHECK(ValueLenId, MemInst, uint32_t, ValueLenPtr, + "Failed when accessing the return ValueLen memory"sv); + + FFMPEG_PTR_FETCH(AvDict, DictId, AVDictionary *); + + // If Dict Not created return (i.e. 0 is passed as AVDictId) + if (AvDict == nullptr) + return static_cast(ErrNo::InternalError); + std::string Key; + std::copy_n(KeyStr, KeyLen, std::back_inserter(Key)); + + AVDictionaryEntry *DictEntry = nullptr; + uint32_t Curr = 0; + while (Curr <= PrevDictEntryIdx) { + DictEntry = av_dict_get(*AvDict, Key.c_str(), DictEntry, Flags); + Curr++; + } + + if (DictEntry == nullptr) + return static_cast(ErrNo::InternalError); + + *KeyLenId = strlen(DictEntry->key); + *ValueLenId = strlen(DictEntry->value); + return Curr; +} + +Expect AVDictGetKeyValue::body( + const Runtime::CallingFrame &Frame, uint32_t DictId, uint32_t KeyPtr, + uint32_t KeyLen, uint32_t ValBufPtr, uint32_t ValBufLen, uint32_t KeyBufPtr, + uint32_t KeyBufLen, uint32_t PrevDictEntryIdx, uint32_t Flags) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(KeyStr, MemInst, char, KeyPtr, + "Failed when accessing the return Key memory"sv); + MEM_SPAN_CHECK(KeyBuf, MemInst, char, KeyBufPtr, KeyBufLen, ""); + MEM_SPAN_CHECK(ValBuf, MemInst, char, ValBufPtr, ValBufLen, ""); + + FFMPEG_PTR_FETCH(AvDict, DictId, AVDictionary *); + + // If Dict Not created return (i.e. 0 is passed as AVDictId) + if (AvDict == nullptr) + return static_cast(ErrNo::InternalError); + + std::string Key; + std::copy_n(KeyStr, KeyLen, std::back_inserter(Key)); + + AVDictionaryEntry *DictEntry = nullptr; + uint32_t Curr = 0; + while (Curr <= PrevDictEntryIdx) { + DictEntry = av_dict_get(*AvDict, Key.c_str(), DictEntry, Flags); + Curr++; + } + if (DictEntry == nullptr) + return static_cast(ErrNo::InternalError); + std::copy_n(DictEntry->value, strlen(DictEntry->value), ValBuf.data()); + std::copy_n(DictEntry->key, strlen(DictEntry->key), KeyBuf.data()); + return Curr; +} + +Expect AVDictFree::body(const Runtime::CallingFrame &, + uint32_t DictId) { + + if (DictId == 0) + return static_cast(ErrNo::Success); + FFMPEG_PTR_FETCH(AvDict, DictId, AVDictionary *); + av_dict_free(AvDict); + FFMPEG_PTR_DELETE(DictId); + return static_cast(ErrNo::Success); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avDictionary.h b/plugins/wasmedge_ffmpeg/avutil/avDictionary.h new file mode 100644 index 000000000000..8d5a5ff1cc69 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avDictionary.h @@ -0,0 +1,59 @@ +#pragma once + +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVDictSet : public WasmEdgeFFmpegAVUtil { +public: + AVDictSet(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DictId, + uint32_t KeyPtr, uint32_t KeyLen, uint32_t ValuePtr, + uint32_t ValueLen, int32_t Flags); +}; + +class AVDictGet : public WasmEdgeFFmpegAVUtil { +public: + AVDictGet(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DictId, + uint32_t KeyPtr, uint32_t KeyLen, + uint32_t PrevDictEntryIdx, uint32_t Flags, + uint32_t KeyLenPtr, uint32_t ValueLenPtr); +}; + +class AVDictGetKeyValue : public WasmEdgeFFmpegAVUtil { +public: + AVDictGetKeyValue(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DictId, + uint32_t KeyPtr, uint32_t KeyLen, uint32_t ValBufPtr, + uint32_t ValBufLen, uint32_t KeyBufPtr, + uint32_t KeyBufLen, uint32_t PrevDictEntryIdx, + uint32_t Flags); +}; + +class AVDictCopy : public WasmEdgeFFmpegAVUtil { +public: + AVDictCopy(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DestDictId, + uint32_t SrcDictId, uint32_t Flags); +}; + +class AVDictFree : public WasmEdgeFFmpegAVUtil { +public: + AVDictFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DictId); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp b/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp new file mode 100644 index 000000000000..414031d9305d --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp @@ -0,0 +1,464 @@ +#include "avFrame.h" + +extern "C" { +#include "libavutil/frame.h" +#include "libavutil/pixfmt.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVFrameAlloc::body(const Runtime::CallingFrame &Frame, + uint32_t FramePtr) { + MEMINST_CHECK(MemInst, Frame, 0) + MEM_PTR_CHECK(FrameId, MemInst, uint32_t, FramePtr, + "Failed to access Memory for AVFrame"sv) + + AVFrame *AvFrame = av_frame_alloc(); + FFMPEG_PTR_STORE(AvFrame, FrameId); + return static_cast(ErrNo::Success); +} + +Expect AVFrameFree::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + av_frame_free(&AvFrame); + FFMPEG_PTR_DELETE(FrameId); + return static_cast(ErrNo::Success); +} + +Expect AVFrameWidth::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->width; +} + +Expect AVFrameHeight::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->height; +} + +Expect AVFrameSetHeight::body(const Runtime::CallingFrame &, + uint32_t FrameId, uint32_t Height) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->height = Height; + return static_cast(ErrNo::Success); +} + +Expect AVFrameSetWidth::body(const Runtime::CallingFrame &, + uint32_t FrameId, uint32_t Width) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->width = Width; + return static_cast(ErrNo::Success); +} + +Expect AVFrameVideoFormat::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + int const Format = AvFrame->format; + if (Format == -1) + return -1; + AVPixelFormat const PixelFormat = static_cast(Format); + return FFmpegUtils::PixFmt::fromAVPixFmt(PixelFormat); +} + +Expect AVFrameSetVideoFormat::body(const Runtime::CallingFrame &, + uint32_t FrameId, + uint32_t AvPixFormatId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(AvPixFormatId); + AvFrame->format = PixelFormat; + return static_cast(ErrNo::Success); +} + +Expect AVFrameIsNull::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->data[0] == nullptr; +} + +Expect AVFrameLinesize::body(const Runtime::CallingFrame &, + uint32_t FrameId, uint32_t Idx) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->linesize[Idx]; +} + +Expect AVFrameData::body(const Runtime::CallingFrame &Frame, + uint32_t FrameId, uint32_t FrameBufPtr, + uint32_t FrameBufLen, uint32_t Index) { + + MEMINST_CHECK(MemInst, Frame, 0) + MEM_SPAN_CHECK(Buffer, MemInst, uint8_t, FrameBufPtr, FrameBufLen, ""); + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + + uint8_t *Data = AvFrame->data[Index]; + std::copy_n(Data, FrameBufLen, Buffer.data()); + return static_cast(ErrNo::Success); +} + +Expect AVFrameGetBuffer::body(const Runtime::CallingFrame &, + uint32_t FrameId, int32_t Align) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return av_frame_get_buffer(AvFrame, Align); +} + +Expect AVFrameAudioFormat::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + int const Format = AvFrame->format; + if (Format == -1) + return -1; + + AVSampleFormat const SampleFormat = static_cast(Format); + return FFmpegUtils::SampleFmt::toSampleID(SampleFormat); +} + +Expect AVFrameSetAudioFormat::body(const Runtime::CallingFrame &, + uint32_t FrameId, + uint32_t SampleFormatId) { + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVSampleFormat const SampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFormatId); + AvFrame->format = SampleFormat; + return static_cast(ErrNo::Success); +} + +Expect AVFrameSetChannelLayout::body(const Runtime::CallingFrame &, + uint32_t FrameId, + uint64_t ChannelLayoutID) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + uint64_t const ChannelLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutID); + AvFrame->channel_layout = ChannelLayout; + return static_cast(ErrNo::Success); +} + +Expect AVFrameSetNbSamples::body(const Runtime::CallingFrame &, + uint32_t FrameId, int32_t Samples) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->nb_samples = Samples; + return static_cast(ErrNo::Success); +} + +Expect AVFrameNbSamples::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->nb_samples; +} + +Expect AVFrameSampleRate::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->sample_rate; +} + +Expect AVFrameSetSampleRate::body(const Runtime::CallingFrame &, + uint32_t FrameId, + int32_t SampleRate) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->sample_rate = SampleRate; + return static_cast(ErrNo::Success); +} + +Expect AVFrameChannels::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->channels; +} + +Expect AVFrameSetChannels::body(const Runtime::CallingFrame &, + uint32_t FrameId, int32_t Channels) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->channels = Channels; + return static_cast(ErrNo::Success); +} + +Expect AVFrameChannelLayout::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + uint64_t const ChannelLayout = AvFrame->channel_layout; + return FFmpegUtils::ChannelLayout::intoChannelLayoutID(ChannelLayout); +} + +Expect AVFrameBestEffortTimestamp::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->best_effort_timestamp; +} + +Expect AVFramePictType::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVPictureType const AvPictureType = AvFrame->pict_type; + return FFmpegUtils::PictureType::fromAVPictureType(AvPictureType); +} + +Expect AVFrameSetPictType::body(const Runtime::CallingFrame &, + uint32_t FrameId, int32_t PictureId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVPictureType const AvPictureType = + FFmpegUtils::PictureType::intoAVPictureType(PictureId); + + AvFrame->pict_type = AvPictureType; + return static_cast(ErrNo::Success); +} + +Expect AVFrameInterlacedFrame::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->interlaced_frame; +} + +Expect AVFrameTopFieldFirst::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->top_field_first; +} + +Expect AVFramePaletteHasChanged::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->palette_has_changed; +} + +Expect AVFrameColorSpace::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVColorSpace const AvColorSpace = AvFrame->colorspace; + return FFmpegUtils::ColorSpace::fromAVColorSpace(AvColorSpace); +} + +Expect AVFrameSetColorSpace::body(const Runtime::CallingFrame &, + uint32_t FrameId, + int32_t ColorSpaceId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->colorspace = FFmpegUtils::ColorSpace::intoAVColorSpace(ColorSpaceId); + return static_cast(ErrNo::Success); +} + +Expect AVFrameColorRange::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVColorRange const AvColorRange = AvFrame->color_range; + + return static_cast(AvColorRange); +} + +Expect AVFrameSetColorRange::body(const Runtime::CallingFrame &, + uint32_t FrameId, + int32_t ColorRangeId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->color_range = static_cast(ColorRangeId); + return static_cast(ErrNo::Success); +} + +Expect +AVFrameColorTransferCharacteristic::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVColorTransferCharacteristic const Characteristic = AvFrame->color_trc; + + // Can use the binding as well. Currently, Commented the binding. + return static_cast(Characteristic); +} + +Expect AVFrameSetColorTransferCharacteristic::body( + const Runtime::CallingFrame &, uint32_t FrameId, + int32_t ColorTransferCharacteristicId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->color_trc = + static_cast(ColorTransferCharacteristicId); + return static_cast(ErrNo::Success); +} + +Expect AVFrameChromaLocation::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVChromaLocation const AvChromaLocation = AvFrame->chroma_location; + return FFmpegUtils::ChromaLocation::fromAVChromaLocation(AvChromaLocation); +} + +Expect AVFrameCodedPictureNumber::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->coded_picture_number; +} + +Expect AVFrameDisplayPictureNumber::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->display_picture_number; +} + +Expect AVFrameRepeatPict::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->repeat_pict; +} + +Expect AVFrameFlags::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->flags; +} + +Expect AVFrameQuality::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->quality; +} + +Expect AVFrameMetadata::body(const Runtime::CallingFrame &Frame, + uint32_t FrameId, uint32_t DictPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(DictId, MemInst, uint32_t, DictPtr, + "Failed when accessing the return AVDictionary memory"sv); + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + + AVDictionary **AvDictionary = + static_cast(av_malloc(sizeof(AVDictionary *))); + + *AvDictionary = AvFrame->metadata; + FFMPEG_PTR_STORE(AvDictionary, DictId); + return static_cast(ErrNo::Success); +} + +Expect AVFrameSetMetadata::body(const Runtime::CallingFrame &, + uint32_t FrameId, uint32_t DictId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + FFMPEG_PTR_FETCH(AvDict, DictId, AVDictionary *); + + if (AvDict == nullptr) + AvFrame->metadata = nullptr; + else + AvFrame->metadata = *AvDict; + return static_cast(ErrNo::Success); +} + +Expect AVFrameKeyFrame::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->key_frame; +} + +Expect AVFramePts::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + return AvFrame->pts; +} + +Expect AVFrameSetPts::body(const Runtime::CallingFrame &, + uint32_t FrameId, int64_t Pts) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AvFrame->pts = Pts; + return static_cast(ErrNo::Success); +} + +Expect AVFrameCopy::body(const Runtime::CallingFrame &, + uint32_t DestFrameId, uint32_t SrcFrameId) { + + FFMPEG_PTR_FETCH(DestAvFrame, DestFrameId, AVFrame); + FFMPEG_PTR_FETCH(SrcAvFrame, SrcFrameId, AVFrame); + + av_frame_copy(DestAvFrame, SrcAvFrame); + return static_cast(ErrNo::Success); +} + +Expect AVFrameCopyProps::body(const Runtime::CallingFrame &, + uint32_t DestFrameId, + uint32_t SrcFrameId) { + + FFMPEG_PTR_FETCH(DestAvFrame, DestFrameId, AVFrame); + FFMPEG_PTR_FETCH(SrcAvFrame, SrcFrameId, AVFrame); + + av_frame_copy_props(DestAvFrame, SrcAvFrame); + return static_cast(ErrNo::Success); +} + +Expect +AVFrameSampleAspectRatio::body(const Runtime::CallingFrame &Frame, + uint32_t FrameId, uint32_t NumPtr, + uint32_t DenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0) + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + + MEM_PTR_CHECK(Num, MemInst, int32_t, NumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(Den, MemInst, int32_t, DenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const Rational = AvFrame->sample_aspect_ratio; + *Num = Rational.num; + *Den = Rational.den; + return static_cast(ErrNo::Success); +} + +Expect AVFrameColorPrimaries::body(const Runtime::CallingFrame &, + uint32_t FrameId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVColorPrimaries const ColorPrimaries = AvFrame->color_primaries; + return FFmpegUtils::ColorPrimaries::fromAVColorPrimaries(ColorPrimaries); +} + +Expect AVFrameSetColorPrimaries::body(const Runtime::CallingFrame &, + uint32_t FrameId, + int32_t ColorPrimariesId) { + + FFMPEG_PTR_FETCH(AvFrame, FrameId, AVFrame); + AVColorPrimaries const ColorPrimaries = + FFmpegUtils::ColorPrimaries::intoAVColorPrimaries(ColorPrimariesId); + AvFrame->color_primaries = ColorPrimaries; + return static_cast(ErrNo::Success); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avFrame.h b/plugins/wasmedge_ffmpeg/avutil/avFrame.h new file mode 100644 index 000000000000..3bceaa3ec8c5 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avFrame.h @@ -0,0 +1,404 @@ +#pragma once + +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVFrameAlloc : public WasmEdgeFFmpegAVUtil { +public: + AVFrameAlloc(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FramePtr); +}; + +class AVFrameFree : public WasmEdgeFFmpegAVUtil { +public: + AVFrameFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameWidth : public WasmEdgeFFmpegAVUtil { +public: + AVFrameWidth(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameHeight : public WasmEdgeFFmpegAVUtil { +public: + AVFrameHeight(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetWidth : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetWidth(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t Width); +}; + +class AVFrameSetHeight : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetHeight(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t Height); +}; + +class AVFrameVideoFormat : public WasmEdgeFFmpegAVUtil { +public: + AVFrameVideoFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetVideoFormat + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetVideoFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t AvPixFormatId); +}; + +class AVFrameIsNull : public WasmEdgeFFmpegAVUtil { +public: + AVFrameIsNull(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameLinesize : public WasmEdgeFFmpegAVUtil { +public: + AVFrameLinesize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t Idx); +}; + +class AVFrameData : public WasmEdgeFFmpegAVUtil { +public: + AVFrameData(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t FrameBufPtr, uint32_t FrameBufLen, + uint32_t Index); +}; + +class AVFrameGetBuffer : public WasmEdgeFFmpegAVUtil { +public: + AVFrameGetBuffer(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t Align); +}; + +class AVFrameAudioFormat : public WasmEdgeFFmpegAVUtil { +public: + AVFrameAudioFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetAudioFormat + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetAudioFormat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t SampleFormatId); +}; + +class AVFrameSetChannelLayout + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint64_t ChannelLayoutID); +}; + +class AVFrameSetNbSamples : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetNbSamples(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t Samples); +}; + +class AVFrameNbSamples : public WasmEdgeFFmpegAVUtil { +public: + AVFrameNbSamples(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSampleRate : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSampleRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetSampleRate : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetSampleRate(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t SampleRate); +}; + +class AVFrameChannels : public WasmEdgeFFmpegAVUtil { +public: + AVFrameChannels(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetChannels : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetChannels(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t Channels); +}; + +class AVFrameChannelLayout : public WasmEdgeFFmpegAVUtil { +public: + AVFrameChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameBestEffortTimestamp + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameBestEffortTimestamp(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFramePictType : public WasmEdgeFFmpegAVUtil { +public: + AVFramePictType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetPictType : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetPictType(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t PictureId); +}; + +class AVFrameInterlacedFrame + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameInterlacedFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameTopFieldFirst : public WasmEdgeFFmpegAVUtil { +public: + AVFrameTopFieldFirst(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFramePaletteHasChanged + : public WasmEdgeFFmpegAVUtil { +public: + AVFramePaletteHasChanged(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameColorSpace : public WasmEdgeFFmpegAVUtil { +public: + AVFrameColorSpace(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetColorSpace : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetColorSpace(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t ColorSpaceId); +}; + +class AVFrameColorRange : public WasmEdgeFFmpegAVUtil { +public: + AVFrameColorRange(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetColorRange : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetColorRange(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t ColorRangeId); +}; + +// color_transfer_characteristic + +class AVFrameColorTransferCharacteristic + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameColorTransferCharacteristic(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetColorTransferCharacteristic + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetColorTransferCharacteristic( + std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t ColorTransferCharacteristicId); +}; + +class AVFrameChromaLocation + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameChromaLocation(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameCodedPictureNumber + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameCodedPictureNumber(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameDisplayPictureNumber + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameDisplayPictureNumber(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameRepeatPict : public WasmEdgeFFmpegAVUtil { +public: + AVFrameRepeatPict(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameFlags : public WasmEdgeFFmpegAVUtil { +public: + AVFrameFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameQuality : public WasmEdgeFFmpegAVUtil { +public: + AVFrameQuality(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameMetadata : public WasmEdgeFFmpegAVUtil { +public: + AVFrameMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t DictPtr); +}; + +class AVFrameSetMetadata : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetMetadata(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t DictId); +}; + +class AVFrameKeyFrame : public WasmEdgeFFmpegAVUtil { +public: + AVFrameKeyFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFramePts : public WasmEdgeFFmpegAVUtil { +public: + AVFramePts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetPts : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetPts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int64_t Pts); +}; + +class AVFrameCopy : public WasmEdgeFFmpegAVUtil { +public: + AVFrameCopy(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DestFrameId, + uint32_t SrcFrameId); +}; + +class AVFrameCopyProps : public WasmEdgeFFmpegAVUtil { +public: + AVFrameCopyProps(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t DestFrameId, + uint32_t SrcFrameId); +}; + +class AVFrameSampleAspectRatio + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSampleAspectRatio(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + uint32_t NumPtr, uint32_t DenPtr); +}; + +class AVFrameColorPrimaries + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameColorPrimaries(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId); +}; + +class AVFrameSetColorPrimaries + : public WasmEdgeFFmpegAVUtil { +public: + AVFrameSetColorPrimaries(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t FrameId, + int32_t ColorPrimariesId); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avRational.cpp b/plugins/wasmedge_ffmpeg/avutil/avRational.cpp new file mode 100644 index 000000000000..8fbe81fd801f --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avRational.cpp @@ -0,0 +1,169 @@ +#include "avRational.h" + +extern "C" { +#include "libavutil/rational.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVAddQ::body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(CNum, MemInst, int32_t, CNumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(CDen, MemInst, int32_t, CDenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_make_q(BNum, BDen); + + AVRational const C = av_add_q(A, B); + *CNum = C.num; + *CDen = C.den; + + return static_cast(ErrNo::Success); +} + +Expect AVSubQ::body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(CNum, MemInst, int32_t, CNumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(CDen, MemInst, int32_t, CDenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_make_q(BNum, BDen); + + AVRational const C = av_sub_q(A, B); + *CNum = C.num; + *CDen = C.den; + return static_cast(ErrNo::Success); +} + +Expect AVMulQ::body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(CNum, MemInst, int32_t, CNumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(CDen, MemInst, int32_t, CDenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_make_q(BNum, BDen); + + AVRational const C = av_mul_q(A, B); + *CNum = C.num; + *CDen = C.den; + return static_cast(ErrNo::Success); +} + +Expect AVDivQ::body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(CNum, MemInst, int32_t, CNumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(CDen, MemInst, int32_t, CDenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_make_q(BNum, BDen); + + AVRational const C = av_div_q(A, B); + *CNum = C.num; + *CDen = C.den; + return static_cast(ErrNo::Success); +} + +Expect AVCmpQ::body(const Runtime::CallingFrame &, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen) { + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_make_q(BNum, BDen); + return av_cmp_q(A, B); +} + +Expect AVNearerQ::body(const Runtime::CallingFrame &, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + int32_t CNum, int32_t CDen) { + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_make_q(BNum, BDen); + AVRational const C = av_make_q(CNum, CDen); + + return av_nearer_q(A, B, C); +} + +Expect AVQ2d::body(const Runtime::CallingFrame &, int32_t ANum, + int32_t ADen) { + + AVRational const A = av_make_q(ANum, ADen); + return av_q2d(A); +} + +Expect AVD2Q::body(const Runtime::CallingFrame &Frame, double_t D, + int32_t Max, uint32_t ANumPtr, uint32_t ADenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(ANum, MemInst, int32_t, ANumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(ADen, MemInst, int32_t, ADenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const A = av_d2q(D, Max); + *ANum = A.num; + *ADen = A.den; + return static_cast(ErrNo::Success); +} + +Expect AVQ2IntFloat::body(const Runtime::CallingFrame &, int32_t ANum, + int32_t ADen) { + + AVRational const A = av_make_q(ANum, ADen); + return av_q2intfloat(A); +} + +Expect AVInvQ::body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, uint32_t BNumPtr, uint32_t BDenPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(BNum, MemInst, int32_t, BNumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(BDen, MemInst, int32_t, BDenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + + AVRational const A = av_make_q(ANum, ADen); + AVRational const B = av_inv_q(A); + + *BNum = B.num; + *BDen = B.den; + return static_cast(ErrNo::Success); +} + +Expect AVReduce::body(const Runtime::CallingFrame &Frame, + uint32_t ANumPtr, uint32_t ADenPtr, int64_t BNum, + int64_t BDen, int64_t Max) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(ANum, MemInst, int32_t, ANumPtr, + "Failed to access Numerator Ptr for AVRational"sv); + MEM_PTR_CHECK(ADen, MemInst, int32_t, ADenPtr, + "Failed to access Denominator Ptr for AVRational"sv); + return av_reduce(ANum, ADen, BNum, BDen, Max); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avRational.h b/plugins/wasmedge_ffmpeg/avutil/avRational.h new file mode 100644 index 000000000000..b158e6636df2 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avRational.h @@ -0,0 +1,107 @@ +#pragma once +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVAddQ : public WasmEdgeFFmpegAVUtil { +public: + AVAddQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr); +}; + +class AVSubQ : public WasmEdgeFFmpegAVUtil { +public: + AVSubQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr); +}; + +class AVMulQ : public WasmEdgeFFmpegAVUtil { +public: + AVMulQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr); +}; + +class AVDivQ : public WasmEdgeFFmpegAVUtil { +public: + AVDivQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, + uint32_t CNumPtr, uint32_t CDenPtr); +}; + +class AVCmpQ : public WasmEdgeFFmpegAVUtil { +public: + AVCmpQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen); +}; + +class AVNearerQ : public WasmEdgeFFmpegAVUtil { +public: + AVNearerQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, int32_t BNum, int32_t BDen, int32_t CNum, + int32_t CDen); +}; + +class AVQ2d : public WasmEdgeFFmpegAVUtil { +public: + AVQ2d(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen); +}; + +class AVD2Q : public WasmEdgeFFmpegAVUtil { +public: + AVD2Q(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, double_t D, + int32_t Max, uint32_t ANumPtr, uint32_t ADenPtr); +}; + +class AVQ2IntFloat : public WasmEdgeFFmpegAVUtil { +public: + AVQ2IntFloat(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen); +}; + +class AVInvQ : public WasmEdgeFFmpegAVUtil { +public: + AVInvQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ANum, + int32_t ADen, uint32_t BNumPtr, uint32_t BDenPtr); +}; + +class AVReduce : public WasmEdgeFFmpegAVUtil { +public: + AVReduce(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ANumPtr, + uint32_t ADenPtr, int64_t BNum, int64_t BDen, + int64_t Max); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avTime.cpp b/plugins/wasmedge_ffmpeg/avutil/avTime.cpp new file mode 100644 index 000000000000..1ebbb03a1920 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avTime.cpp @@ -0,0 +1,32 @@ +#include "avTime.h" + +extern "C" { +#include "libavutil/time.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVGetTime::body(const Runtime::CallingFrame &) { + return av_gettime(); +} + +Expect AVGetTimeRelative::body(const Runtime::CallingFrame &) { + return av_gettime_relative(); +} + +Expect +AVGetTimeRelativeIsMonotonic::body(const Runtime::CallingFrame &) { + return av_gettime_relative_is_monotonic(); +} + +Expect AVUSleep::body(const Runtime::CallingFrame &, uint32_t USec) { + return av_usleep(USec); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avTime.h b/plugins/wasmedge_ffmpeg/avutil/avTime.h new file mode 100644 index 000000000000..803e404a29b5 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avTime.h @@ -0,0 +1,42 @@ +#pragma once +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVGetTime : public WasmEdgeFFmpegAVUtil { +public: + AVGetTime(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVGetTimeRelative : public WasmEdgeFFmpegAVUtil { +public: + AVGetTimeRelative(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVGetTimeRelativeIsMonotonic + : public WasmEdgeFFmpegAVUtil { +public: + AVGetTimeRelativeIsMonotonic(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVUSleep : public WasmEdgeFFmpegAVUtil { +public: + AVUSleep(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t USec); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avutil_base.h b/plugins/wasmedge_ffmpeg/avutil/avutil_base.h new file mode 100644 index 000000000000..dcf352837b0a --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avutil_base.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +template +class WasmEdgeFFmpegAVUtil : public Runtime::HostFunction { +public: + WasmEdgeFFmpegAVUtil( + std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp b/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp new file mode 100644 index 000000000000..a1f20e4fc7ef --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp @@ -0,0 +1,142 @@ +#include "avutil_func.h" + +extern "C" { +#include "libavutil/avutil.h" +#include "libavutil/time.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVLogSetLevel::body(const Runtime::CallingFrame &, + int32_t LogLevelId) { + av_log_set_level(LogLevelId); + return {}; +} + +Expect AVLogGetLevel::body(const Runtime::CallingFrame &) { + return av_log_get_level(); +} + +Expect AVLogGetFlags::body(const Runtime::CallingFrame &) { + return av_log_get_flags(); +} + +Expect AVLogSetFlags::body(const Runtime::CallingFrame &, + int32_t FlagId) { + av_log_set_flags(FlagId); + return {}; +} + +Expect AVRescaleQ::body(const Runtime::CallingFrame &, int64_t A, + int32_t BNum, int32_t BDen, int32_t CNum, + int32_t CDen) { + + AVRational const B = av_make_q(BNum, BDen); + AVRational const C = av_make_q(CNum, CDen); + return av_rescale_q(A, B, C); +} + +Expect AVRescaleQRnd::body(const Runtime::CallingFrame &, int64_t A, + int32_t BNum, int32_t BDen, int32_t CNum, + int32_t CDen, int32_t RoundingId) { + + AVRational const B = av_make_q(BNum, BDen); + AVRational const C = av_make_q(CNum, CDen); + AVRounding const Rounding = FFmpegUtils::Rounding::intoAVRounding(RoundingId); + return av_rescale_q_rnd(A, B, C, Rounding); +} + +Expect AVUtilVersion::body(const Runtime::CallingFrame &) { + return avutil_version(); +} + +Expect +AVGetChannelLayoutNbChannels::body(const Runtime::CallingFrame &, + uint64_t ChannelLayoutId) { + uint64_t const ChannelLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutId); + return av_get_channel_layout_nb_channels(ChannelLayout); +} + +Expect AVGetChannelLayoutNameLen::body(const Runtime::CallingFrame &, + uint64_t ChannelLayoutId) { + + uint64_t const ChannelLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutId); + const char *ChName = av_get_channel_name(ChannelLayout); + if (ChName == nullptr) + return 0; + return strlen(ChName); +} + +Expect AVGetChannelLayoutName::body(const Runtime::CallingFrame &Frame, + uint64_t ChannelLayoutId, + uint32_t NamePtr, + uint32_t NameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(NameBuf, MemInst, char, NamePtr, NameLen, ""); + + uint64_t const ChannelLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutId); + const char *ChName = av_get_channel_name(ChannelLayout); + + std::copy_n(ChName, NameLen, NameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVGetChannelLayoutMask::body(const Runtime::CallingFrame &, + uint64_t ChannelLayoutId) { + + uint64_t const ChannelLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(ChannelLayoutId); + return ChannelLayout; +} + +Expect AVGetDefaultChannelLayout::body(const Runtime::CallingFrame &, + int32_t Number) { + uint64_t const ChannelLayout = av_get_default_channel_layout(Number); + return FFmpegUtils::ChannelLayout::intoChannelLayoutID(ChannelLayout); +} + +Expect AVUtilConfigurationLength::body(const Runtime::CallingFrame &) { + const char *Config = avutil_configuration(); + return strlen(Config); +} + +Expect AVUtilConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, + uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = avutil_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVUtilLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = avutil_license(); + return strlen(License); +} + +Expect AVUtilLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = avutil_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/avutil_func.h b/plugins/wasmedge_ffmpeg/avutil/avutil_func.h new file mode 100644 index 000000000000..1529e94fd51b --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/avutil_func.h @@ -0,0 +1,208 @@ +#pragma once +#include "avutil_base.h" + +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVLogSetLevel : public WasmEdgeFFmpegAVUtil { +public: + AVLogSetLevel(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t LogLevelId); +}; + +class AVLogGetLevel : public WasmEdgeFFmpegAVUtil { +public: + AVLogGetLevel(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVLogSetFlags : public WasmEdgeFFmpegAVUtil { +public: + AVLogSetFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t FlagsId); +}; + +class AVLogGetFlags : public WasmEdgeFFmpegAVUtil { +public: + AVLogGetFlags(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +// Option funcs. +class AVOptSetBin : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetBin(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSet : public WasmEdgeFFmpegAVUtil { +public: + AVOptSet(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetInt : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetInt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetDouble : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetDouble(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetQ : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetImageSize : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetImageSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetPixelFmt : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetPixelFmt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetSampleFmt : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetSampleFmt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVOptSetChannelLayout + : public WasmEdgeFFmpegAVUtil { +public: + AVOptSetChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVRescaleQ : public WasmEdgeFFmpegAVUtil { +public: + AVRescaleQ(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int64_t A, + int32_t BNum, int32_t BDen, int32_t CNum, int32_t CDen); +}; + +class AVRescaleQRnd : public WasmEdgeFFmpegAVUtil { +public: + AVRescaleQRnd(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &, int64_t A, int32_t BNum, + int32_t BDen, int32_t CNum, int32_t CDen, + int32_t RoundingId); +}; + +class AVUtilVersion : public WasmEdgeFFmpegAVUtil { +public: + AVUtilVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &); +}; + +class AVGetChannelLayoutNbChannels + : public WasmEdgeFFmpegAVUtil { +public: + AVGetChannelLayoutNbChannels(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint64_t ChannelLayoutId); +}; + +class AVGetChannelLayoutNameLen + : public WasmEdgeFFmpegAVUtil { +public: + AVGetChannelLayoutNameLen(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint64_t ChannelLayoutId); +}; + +class AVGetChannelLayoutName + : public WasmEdgeFFmpegAVUtil { +public: + AVGetChannelLayoutName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint64_t ChannelLayoutId, uint32_t NamePtr, + uint32_t NameLen); +}; + +class AVGetChannelLayoutMask + : public WasmEdgeFFmpegAVUtil { +public: + AVGetChannelLayoutMask(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint64_t ChannelLayoutId); +}; + +class AVGetDefaultChannelLayout + : public WasmEdgeFFmpegAVUtil { +public: + AVGetDefaultChannelLayout(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + int32_t ChannelLayoutId); +}; + +class AVUtilConfigurationLength + : public WasmEdgeFFmpegAVUtil { +public: + AVUtilConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVUtilConfiguration : public WasmEdgeFFmpegAVUtil { +public: + AVUtilConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class AVUtilLicenseLength : public WasmEdgeFFmpegAVUtil { +public: + AVUtilLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class AVUtilLicense : public WasmEdgeFFmpegAVUtil { +public: + AVUtilLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/error.cpp b/plugins/wasmedge_ffmpeg/avutil/error.cpp new file mode 100644 index 000000000000..d918ece516f8 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/error.cpp @@ -0,0 +1,39 @@ +#include "error.h" + +extern "C" { +#include "libavutil/error.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVUtilAVStrError::body(const Runtime::CallingFrame &Frame, + int32_t ErrNum, uint32_t ErrBuf, + uint32_t BufLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + + MEM_PTR_CHECK(ErrId, MemInst, char, ErrBuf, + "Failed when accessing the return URL memory"sv); + + std::string Error; + std::copy_n(ErrId, BufLen, std::back_inserter(Error)); + return av_strerror(ErrNum, const_cast(Error.c_str()), BufLen); +} + +Expect AVUtilAVError::body(const Runtime::CallingFrame &, + int32_t ErrNum) { + return AVERROR(ErrNum); +} + +Expect AVUtilAVUNError::body(const Runtime::CallingFrame &, + int32_t ErrNum) { + return AVUNERROR(ErrNum); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/error.h b/plugins/wasmedge_ffmpeg/avutil/error.h new file mode 100644 index 000000000000..a813715127d5 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/error.h @@ -0,0 +1,36 @@ +#pragma once + +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVUtilAVStrError : public WasmEdgeFFmpegAVUtil { +public: + AVUtilAVStrError(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ErrNum, + uint32_t ErrBuf, uint32_t BufLen); +}; + +class AVUtilAVError : public WasmEdgeFFmpegAVUtil { +public: + AVUtilAVError(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ErrNum); +}; + +class AVUtilAVUNError : public WasmEdgeFFmpegAVUtil { +public: + AVUtilAVUNError(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ErrNum); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/module.cpp b/plugins/wasmedge_ffmpeg/avutil/module.cpp new file mode 100644 index 000000000000..12588050b259 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/module.cpp @@ -0,0 +1,263 @@ +#include "module.h" +#include "avDictionary.h" +#include "avFrame.h" +#include "avRational.h" +#include "avTime.h" +#include "avutil_func.h" +#include "error.h" +#include "pixfmt.h" +#include "samplefmt.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +WasmEdgeFFmpegAVUtilModule::WasmEdgeFFmpegAVUtilModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_avutil") { + + // error.h + addHostFunc("wasmedge_ffmpeg_avutil_av_strerror", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_AVERROR", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_AVUNERROR", + std::make_unique(Env)); + + // rational.h + addHostFunc("wasmedge_ffmpeg_avutil_av_add_q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_sub_q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_mul_q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_div_q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_d2q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_q2d", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_inv_q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_q2intfloat", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_nearer_q", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_cmp_q", std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_reduce", + std::make_unique(Env)); + + // frame.h + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_alloc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_free", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_width", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_height", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_width", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_height", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_video_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_video_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_isnull", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_linesize", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_data", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_get_buffer", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_audio_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_audio_format", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_nb_samples", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_channel_layout", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_nb_samples", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_sample_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_sample_rate", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_channels", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_channels", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_channel_layout", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_best_effort_timestamp", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_pict_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_pict_type", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_interlaced_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_top_field_first", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_palette_has_changed", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_colorspace", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_colorspace", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_color_range", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_color_range", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_color_trc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_color_trc", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_chroma_location", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_coded_picture_number", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_display_picture_number", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_repeat_pict", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_quality", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_metadata", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_metadata", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_key_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_pts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_pts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_copy", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_copy_props", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_sample_aspect_ratio", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_set_color_primaries", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_frame_color_primaries", + std::make_unique(Env)); + + // pixfmt.h (Even AvPixFmtDesc is in this file) + addHostFunc("wasmedge_ffmpeg_avutil_avpixfmtdescriptor_nb_components", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avpixfmtdescriptor_log2_chromaw", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avpixfmtdescriptor_log2_chromah", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_transfer_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_transfer_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_range_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_range_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_space_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_space_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_primaries_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_color_primaries_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_pix_format_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_pix_format_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_pix_format_mask", + std::make_unique(Env)); + + // samplefmt.h + addHostFunc("wasmedge_ffmpeg_avutil_av_get_packed_sample_fmt", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_planar_sample_fmt", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_sample_fmt_is_planar", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_bytes_per_sample", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_sample_fmt", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_samples_get_buffer_size", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_samples_alloc_array_and_samples", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_sample_fmt_name_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_sample_fmt_name", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_sample_fmt_mask", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_freep", + std::make_unique(Env)); + + // dict.h + addHostFunc("wasmedge_ffmpeg_avutil_av_dict_set", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_dict_get", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_dict_get_key_value", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_dict_copy", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_dict_free", + std::make_unique(Env)); + + // avutil_func.h + addHostFunc("wasmedge_ffmpeg_avutil_av_log_set_level", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_log_get_level", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_log_set_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_log_get_flags", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_rescale_q", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_rescale_q_rnd", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_channel_layout_nb_channels", + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avutil_av_get_channel_layout_name_len", // TODO: Write + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avutil_av_get_channel_layout_name", // TODO: Write Test + std::make_unique(Env)); + addHostFunc( + "wasmedge_ffmpeg_avutil_av_get_channel_layout_mask", // TODO: Write Test + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_get_default_channel_layout", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avutil_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avutil_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avutil_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avutil_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_avutil_license", + std::make_unique(Env)); + + // time.h + addHostFunc("wasmedge_ffmpeg_avutil_av_gettime", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_gettime_relative", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_gettime_relative_is_monotonic", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_avutil_av_usleep", + std::make_unique(Env)); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/module.h b/plugins/wasmedge_ffmpeg/avutil/module.h new file mode 100644 index 000000000000..ebd35dba98ed --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/module.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class WasmEdgeFFmpegAVUtilModule : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegAVUtilModule(std::shared_ptr Env); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/pixfmt.cpp b/plugins/wasmedge_ffmpeg/avutil/pixfmt.cpp new file mode 100644 index 000000000000..9d5b55c2e36b --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/pixfmt.cpp @@ -0,0 +1,174 @@ +#include "pixfmt.h" +extern "C" { +#include "libavutil/pixdesc.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect +AvPixFmtDescriptorNbComponents::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + const AVPixFmtDescriptor *AvPixFmtDescriptor = + av_pix_fmt_desc_get(PixelFormat); + return AvPixFmtDescriptor->nb_components; +} + +Expect +AvPixFmtDescriptorLog2ChromaW::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + const AVPixFmtDescriptor *AvPixFmtDescriptor = + av_pix_fmt_desc_get(PixelFormat); + return AvPixFmtDescriptor->log2_chroma_w; +} + +Expect +AvPixFmtDescriptorLog2ChromaH::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + const AVPixFmtDescriptor *AvPixFmtDescriptor = + av_pix_fmt_desc_get(PixelFormat); + return AvPixFmtDescriptor->log2_chroma_h; +} + +Expect AVColorRangeNameLength::body(const Runtime::CallingFrame &, + int32_t RangeId) { + + AVColorRange const ColorRange = static_cast(RangeId); + const char *Name = av_color_range_name(ColorRange); + return strlen(Name); +} + +Expect AVColorRangeName::body(const Runtime::CallingFrame &Frame, + int32_t RangeId, uint32_t RangeNamePtr, + uint32_t RangeLength) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(RangeNameBuf, MemInst, char, RangeNamePtr, RangeLength, ""); + + AVColorRange const ColorRange = static_cast(RangeId); + const char *RangeName = av_color_range_name(ColorRange); + std::copy_n(RangeName, RangeLength, RangeNameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVColorTransferNameLength::body(const Runtime::CallingFrame &, + int32_t TransferId) { + + AVColorTransferCharacteristic const Characteristic = + static_cast(TransferId); + const char *Name = av_color_transfer_name(Characteristic); + return strlen(Name); +} + +Expect AVColorTransferName::body(const Runtime::CallingFrame &Frame, + int32_t TransferId, + uint32_t TransferNamePtr, + uint32_t TransferLength) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(TransferNameBuf, MemInst, char, TransferNamePtr, + TransferLength, ""); + + AVColorTransferCharacteristic const Characteristic = + static_cast(TransferId); + const char *TransferName = av_color_transfer_name(Characteristic); + std::copy_n(TransferName, TransferLength, TransferNameBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVColorSpaceNameLength::body(const Runtime::CallingFrame &, + int32_t ColorSpaceId) { + + AVColorSpace const ColorSpace = static_cast(ColorSpaceId); + const char *Name = av_color_space_name(ColorSpace); + return strlen(Name); +} + +Expect AVColorSpaceName::body(const Runtime::CallingFrame &Frame, + int32_t ColorSpaceId, + uint32_t ColorSpaceNamePtr, + uint32_t ColorSpaceLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ColorSpaceBuf, MemInst, char, ColorSpaceNamePtr, ColorSpaceLen, + ""); + + AVColorSpace const ColorSpace = static_cast(ColorSpaceId); + const char *ColorSpaceName = av_color_space_name(ColorSpace); + std::copy_n(ColorSpaceName, ColorSpaceLen, ColorSpaceBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVColorPrimariesNameLength::body(const Runtime::CallingFrame &, + int32_t ColorPrimariesId) { + + AVColorPrimaries const ColorPrimaries = + FFmpegUtils::ColorPrimaries::intoAVColorPrimaries(ColorPrimariesId); + const char *Name = av_color_primaries_name(ColorPrimaries); + return strlen(Name); +} + +Expect AVColorPrimariesName::body(const Runtime::CallingFrame &Frame, + int32_t ColorPrimariesId, + uint32_t ColorPrimariesNamePtr, + uint32_t ColorPrimariesLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ColorPrimariesBuf, MemInst, char, ColorPrimariesNamePtr, + ColorPrimariesLen, ""); + + AVColorPrimaries const ColorPrimaries = + FFmpegUtils::ColorPrimaries::intoAVColorPrimaries(ColorPrimariesId); + const char *PrimariesName = av_color_primaries_name(ColorPrimaries); + std::copy_n(PrimariesName, ColorPrimariesLen, ColorPrimariesBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVPixelFormatNameLength::body(const Runtime::CallingFrame &, + uint32_t AvPixFormatId) { + + AVPixelFormat const PixFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(AvPixFormatId); + const AVPixFmtDescriptor *PixFmtDescriptor = av_pix_fmt_desc_get(PixFormat); + + return strlen(PixFmtDescriptor->name); +} + +Expect AVPixelFormatName::body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId, + uint32_t PixFormatNamePtr, + uint32_t PixFormatNameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(PixFormatBuf, MemInst, char, PixFormatNamePtr, + PixFormatNameLen, ""); + + AVPixelFormat const PixFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + const AVPixFmtDescriptor *PixFmtDescriptor = av_pix_fmt_desc_get(PixFormat); + const char *PixFormatName = PixFmtDescriptor->name; + std::copy_n(PixFormatName, PixFormatNameLen, PixFormatBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVPixelFormatMask::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + return static_cast(PixelFormat); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/pixfmt.h b/plugins/wasmedge_ffmpeg/avutil/pixfmt.h new file mode 100644 index 000000000000..51126aa6178f --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/pixfmt.h @@ -0,0 +1,132 @@ +#pragma once +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AvPixFmtDescriptorNbComponents + : public WasmEdgeFFmpegAVUtil { +public: + AvPixFmtDescriptorNbComponents(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +class AvPixFmtDescriptorLog2ChromaW + : public WasmEdgeFFmpegAVUtil { +public: + AvPixFmtDescriptorLog2ChromaW(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +class AvPixFmtDescriptorLog2ChromaH + : public WasmEdgeFFmpegAVUtil { +public: + AvPixFmtDescriptorLog2ChromaH(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +class AVColorRangeNameLength + : public WasmEdgeFFmpegAVUtil { +public: + AVColorRangeNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t RangeId); +}; + +class AVColorRangeName : public WasmEdgeFFmpegAVUtil { +public: + AVColorRangeName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t RangeId, + uint32_t RangeName, uint32_t RangeLength); +}; + +class AVColorTransferNameLength + : public WasmEdgeFFmpegAVUtil { +public: + AVColorTransferNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t TransferId); +}; + +class AVColorTransferName : public WasmEdgeFFmpegAVUtil { +public: + AVColorTransferName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t TransferId, + uint32_t TransferNamePtr, uint32_t TransferLength); +}; + +class AVColorSpaceNameLength + : public WasmEdgeFFmpegAVUtil { +public: + AVColorSpaceNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + int32_t ColorSpaceId); +}; + +class AVColorSpaceName : public WasmEdgeFFmpegAVUtil { +public: + AVColorSpaceName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t ColorSpaceId, + uint32_t ColorSpaceNamePtr, uint32_t ColorSpaceLen); +}; + +class AVColorPrimariesNameLength + : public WasmEdgeFFmpegAVUtil { +public: + AVColorPrimariesNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + int32_t ColorPrimariesId); +}; + +class AVColorPrimariesName : public WasmEdgeFFmpegAVUtil { +public: + AVColorPrimariesName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + int32_t ColorPrimariesId, uint32_t ColorPrimariesNamePtr, + uint32_t ColorPrimariesLen); +}; + +class AVPixelFormatNameLength + : public WasmEdgeFFmpegAVUtil { +public: + AVPixelFormatNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t AvPixFormatId); +}; + +class AVPixelFormatName : public WasmEdgeFFmpegAVUtil { +public: + AVPixelFormatName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t PixFormatId, + uint32_t PixFormatNamePtr, uint32_t PixFormatNameLen); +}; + +class AVPixelFormatMask : public WasmEdgeFFmpegAVUtil { +public: + AVPixelFormatMask(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/samplefmt.cpp b/plugins/wasmedge_ffmpeg/avutil/samplefmt.cpp new file mode 100644 index 000000000000..f38914e6dde7 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/samplefmt.cpp @@ -0,0 +1,134 @@ +#include "samplefmt.h" +extern "C" { +#include "libavutil/samplefmt.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +Expect AVGetPlanarSampleFmt::body(const Runtime::CallingFrame &, + uint32_t SampleFormatId) { + AVSampleFormat const AvSampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFormatId); + AVSampleFormat const PlanarSampleFmt = + av_get_planar_sample_fmt(AvSampleFormat); + return FFmpegUtils::SampleFmt::toSampleID(PlanarSampleFmt); +} + +Expect AVGetPackedSampleFmt::body(const Runtime::CallingFrame &, + uint32_t SampleFormatId) { + AVSampleFormat const AvSampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFormatId); + AVSampleFormat const PackedSampleFmt = + av_get_packed_sample_fmt(AvSampleFormat); + return FFmpegUtils::SampleFmt::toSampleID(PackedSampleFmt); +} + +Expect AVSampleFmtIsPlanar::body(const Runtime::CallingFrame &, + uint32_t SampleFormatId) { + AVSampleFormat const AvSampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFormatId); + return av_sample_fmt_is_planar(AvSampleFormat); +} + +Expect AVGetBytesPerSample::body(const Runtime::CallingFrame &, + uint32_t SampleFormatId) { + AVSampleFormat const AvSampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFormatId); + return av_get_bytes_per_sample(AvSampleFormat); +} + +Expect AVGetSampleFmt::body(const Runtime::CallingFrame &Frame, + uint32_t Str, uint32_t StrLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(StrId, MemInst, char, Str, ""); + + std::string TargetUrl; + std::copy_n(StrId, StrLen, std::back_inserter(TargetUrl)); + + AVSampleFormat const AvSampleFormat = av_get_sample_fmt(TargetUrl.c_str()); + return FFmpegUtils::SampleFmt::toSampleID(AvSampleFormat); +} + +Expect AVSamplesGetBufferSize::body(const Runtime::CallingFrame &, + int32_t NbChannels, + int32_t NbSamples, + uint32_t SampleFormatId, + int32_t Align) { + AVSampleFormat const AvSampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFormatId); + return av_samples_get_buffer_size(nullptr, NbChannels, NbSamples, + AvSampleFormat, + Align); // linesize is NULL in RustSDK. +} + +Expect +AVSamplesAllocArrayAndSamples::body(const Runtime::CallingFrame &Frame, + uint32_t BufferPtr, uint32_t LinesizePtr, + int32_t NbChannels, int32_t NbSamples, + uint32_t SampleFmtId, int32_t Align) { + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(BufId, MemInst, uint32_t, BufferPtr, ""); + MEM_PTR_CHECK(LineSize, MemInst, int32_t, LinesizePtr, ""); + + FFMPEG_PTR_FETCH(Buf, *BufId, uint8_t *); + int LineSizeValue = 0; + AVSampleFormat const AvSampleFormat = + FFmpegUtils::SampleFmt::fromSampleID(SampleFmtId); + int Res = av_samples_alloc_array_and_samples( + &Buf, &LineSizeValue, NbChannels, NbSamples, AvSampleFormat, Align); + + *LineSize = LineSizeValue; + FFMPEG_PTR_STORE(Buf, BufId); + return Res; +} + +Expect AVGetSampleFmtNameLength::body(const Runtime::CallingFrame &, + uint32_t SampleFmtId) { + + AVSampleFormat const SampleFmt = + FFmpegUtils::SampleFmt::fromSampleID(SampleFmtId); + + const char *Name = av_get_sample_fmt_name(SampleFmt); + return strlen(Name); +} + +Expect AVGetSampleFmtName::body(const Runtime::CallingFrame &Frame, + uint32_t SampleFmtId, + uint32_t SampleFmtNamePtr, + uint32_t SampleFmtNameLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(SampleFmtBuf, MemInst, char, SampleFmtNamePtr, + SampleFmtNameLen, ""); + + AVSampleFormat const SampleFmt = + FFmpegUtils::SampleFmt::fromSampleID(SampleFmtId); + const char *Name = av_get_sample_fmt_name(SampleFmt); + std::copy_n(Name, SampleFmtNameLen, SampleFmtBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect AVGetSampleFmtMask::body(const Runtime::CallingFrame &, + uint32_t SampleFmtId) { + + AVSampleFormat const SampleFmt = + FFmpegUtils::SampleFmt::fromSampleID(SampleFmtId); + return static_cast(SampleFmt); +} + +Expect AVFreep::body(const Runtime::CallingFrame &, + uint32_t BufferId) { + FFMPEG_PTR_FETCH(Buffer, BufferId, uint8_t *); + av_freep(Buffer); + FFMPEG_PTR_DELETE(BufferId); + return static_cast(ErrNo::Success); +} + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/avutil/samplefmt.h b/plugins/wasmedge_ffmpeg/avutil/samplefmt.h new file mode 100644 index 000000000000..a61907793379 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/avutil/samplefmt.h @@ -0,0 +1,105 @@ +#pragma once +#include "avutil_base.h" +#include "runtime/callingframe.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace AVUtil { + +class AVGetPlanarSampleFmt : public WasmEdgeFFmpegAVUtil { +public: + AVGetPlanarSampleFmt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SampleFormatId); +}; + +class AVGetPackedSampleFmt : public WasmEdgeFFmpegAVUtil { +public: + AVGetPackedSampleFmt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SampleFormatId); +}; + +class AVSampleFmtIsPlanar : public WasmEdgeFFmpegAVUtil { +public: + AVSampleFmtIsPlanar(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SampleFormatId); +}; + +class AVGetBytesPerSample : public WasmEdgeFFmpegAVUtil { +public: + AVGetBytesPerSample(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SampleFormatId); +}; + +class AVGetSampleFmt : public WasmEdgeFFmpegAVUtil { +public: + AVGetSampleFmt(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t Str, + uint32_t StrLen); +}; + +class AVSamplesGetBufferSize + : public WasmEdgeFFmpegAVUtil { +public: + AVSamplesGetBufferSize(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, int32_t NbChannels, + int32_t NbSamples, uint32_t SampleFormatId, + int32_t Align); +}; + +class AVSamplesAllocArrayAndSamples + : public WasmEdgeFFmpegAVUtil { +public: + AVSamplesAllocArrayAndSamples(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t BufferPtr, + uint32_t LinesizePtr, int32_t NbChannels, + int32_t NbSamples, uint32_t SampleFmtId, int32_t Align); +}; + +class AVGetSampleFmtNameLength + : public WasmEdgeFFmpegAVUtil { +public: + AVGetSampleFmtNameLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SampleFmtId); +}; + +class AVGetSampleFmtName : public WasmEdgeFFmpegAVUtil { +public: + AVGetSampleFmtName(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SampleFmtId, + uint32_t SampleFmtNamePtr, uint32_t SampleFmtNameLen); +}; + +class AVGetSampleFmtMask : public WasmEdgeFFmpegAVUtil { +public: + AVGetSampleFmtMask(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SampleFmtId); +}; + +class AVFreep : public WasmEdgeFFmpegAVUtil { +public: + AVFreep(std::shared_ptr HostEnv) + : WasmEdgeFFmpegAVUtil(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t BufferId); +}; + +} // namespace AVUtil +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/bindings.h b/plugins/wasmedge_ffmpeg/bindings.h new file mode 100644 index 000000000000..748f59879fd5 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/bindings.h @@ -0,0 +1,4425 @@ +#pragma once + +extern "C" { +#include "libavcodec/avcodec.h" +#include "libavutil/avutil.h" +#include "libavutil/opt.h" +#include "libswresample/swresample.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace FFmpegUtils { +class MediaType { +public: + static AVMediaType intoMediaType(int32_t MediaTypeId) { + switch (MediaTypeId) { + case 0: + return AVMEDIA_TYPE_VIDEO; + case 1: + return AVMEDIA_TYPE_AUDIO; + case 2: + return AVMEDIA_TYPE_DATA; + case 3: + return AVMEDIA_TYPE_SUBTITLE; + case 4: + return AVMEDIA_TYPE_ATTACHMENT; + case 5: + return AVMEDIA_TYPE_NB; + default: + return AVMEDIA_TYPE_UNKNOWN; + } + } + + static int32_t fromMediaType(AVMediaType MediaType) { + switch (MediaType) { + case AVMEDIA_TYPE_VIDEO: + return 0; + case AVMEDIA_TYPE_AUDIO: + return 1; + case AVMEDIA_TYPE_DATA: + return 2; + case AVMEDIA_TYPE_SUBTITLE: + return 3; + case 4: + return AVMEDIA_TYPE_ATTACHMENT; + case 5: + return AVMEDIA_TYPE_NB; + default: + return AVMEDIA_TYPE_UNKNOWN; + } + } +}; + +class CodecID { +public: + static AVCodecID intoAVCodecID(uint32_t AvCodecIndex) { + switch (AvCodecIndex) { + case 0: + return AV_CODEC_ID_NONE; + case 1: + return AV_CODEC_ID_MPEG1VIDEO; + case 2: + return AV_CODEC_ID_MPEG2VIDEO; + case 3: + return AV_CODEC_ID_H261; + case 4: + return AV_CODEC_ID_H263; + case 5: + return AV_CODEC_ID_RV10; + case 6: + return AV_CODEC_ID_RV20; + case 7: + return AV_CODEC_ID_MJPEG; + case 8: + return AV_CODEC_ID_MJPEGB; + case 9: + return AV_CODEC_ID_LJPEG; + case 10: + return AV_CODEC_ID_SP5X; + case 11: + return AV_CODEC_ID_JPEGLS; + case 12: + return AV_CODEC_ID_MPEG4; + case 13: + return AV_CODEC_ID_RAWVIDEO; + case 14: + return AV_CODEC_ID_MSMPEG4V1; + case 15: + return AV_CODEC_ID_MSMPEG4V2; + case 16: + return AV_CODEC_ID_MSMPEG4V3; + case 17: + return AV_CODEC_ID_WMV1; + case 18: + return AV_CODEC_ID_WMV2; + case 19: + return AV_CODEC_ID_H263P; + case 20: + return AV_CODEC_ID_H263I; + case 21: + return AV_CODEC_ID_FLV1; + case 22: + return AV_CODEC_ID_SVQ1; + case 23: + return AV_CODEC_ID_SVQ3; + case 24: + return AV_CODEC_ID_DVVIDEO; + case 25: + return AV_CODEC_ID_HUFFYUV; + case 26: + return AV_CODEC_ID_CYUV; + case 27: + return AV_CODEC_ID_H264; + case 28: + return AV_CODEC_ID_INDEO3; + case 29: + return AV_CODEC_ID_VP3; + case 30: + return AV_CODEC_ID_THEORA; + case 31: + return AV_CODEC_ID_ASV1; + case 32: + return AV_CODEC_ID_ASV2; + case 33: + return AV_CODEC_ID_FFV1; + case 34: + return AV_CODEC_ID_4XM; + case 35: + return AV_CODEC_ID_VCR1; + case 36: + return AV_CODEC_ID_CLJR; + case 37: + return AV_CODEC_ID_MDEC; + case 38: + return AV_CODEC_ID_ROQ; + case 39: + return AV_CODEC_ID_INTERPLAY_VIDEO; + case 40: + return AV_CODEC_ID_XAN_WC3; + case 41: + return AV_CODEC_ID_XAN_WC4; + case 42: + return AV_CODEC_ID_RPZA; + case 43: + return AV_CODEC_ID_CINEPAK; + case 44: + return AV_CODEC_ID_WS_VQA; + case 45: + return AV_CODEC_ID_MSRLE; + case 46: + return AV_CODEC_ID_MSVIDEO1; + case 47: + return AV_CODEC_ID_IDCIN; + case 48: + return AV_CODEC_ID_8BPS; + case 49: + return AV_CODEC_ID_SMC; + case 50: + return AV_CODEC_ID_FLIC; + case 51: + return AV_CODEC_ID_TRUEMOTION1; + case 52: + return AV_CODEC_ID_VMDVIDEO; + case 53: + return AV_CODEC_ID_MSZH; + case 54: + return AV_CODEC_ID_ZLIB; + case 55: + return AV_CODEC_ID_QTRLE; + case 56: + return AV_CODEC_ID_TSCC; + case 57: + return AV_CODEC_ID_ULTI; + case 58: + return AV_CODEC_ID_QDRAW; + case 59: + return AV_CODEC_ID_VIXL; + case 60: + return AV_CODEC_ID_QPEG; + case 61: + return AV_CODEC_ID_PNG; + case 62: + return AV_CODEC_ID_PPM; + case 63: + return AV_CODEC_ID_PBM; + case 64: + return AV_CODEC_ID_PGM; + case 65: + return AV_CODEC_ID_PGMYUV; + case 66: + return AV_CODEC_ID_PAM; + case 67: + return AV_CODEC_ID_FFVHUFF; + case 68: + return AV_CODEC_ID_RV30; + case 69: + return AV_CODEC_ID_RV40; + case 70: + return AV_CODEC_ID_VC1; + case 71: + return AV_CODEC_ID_WMV3; + case 72: + return AV_CODEC_ID_LOCO; + case 73: + return AV_CODEC_ID_WNV1; + case 74: + return AV_CODEC_ID_AASC; + case 75: + return AV_CODEC_ID_INDEO2; + case 76: + return AV_CODEC_ID_FRAPS; + case 77: + return AV_CODEC_ID_TRUEMOTION2; + case 78: + return AV_CODEC_ID_BMP; + case 79: + return AV_CODEC_ID_CSCD; + case 80: + return AV_CODEC_ID_MMVIDEO; + case 81: + return AV_CODEC_ID_ZMBV; + case 82: + return AV_CODEC_ID_AVS; + case 83: + return AV_CODEC_ID_SMACKVIDEO; + case 84: + return AV_CODEC_ID_NUV; + case 85: + return AV_CODEC_ID_KMVC; + case 86: + return AV_CODEC_ID_FLASHSV; + case 87: + return AV_CODEC_ID_CAVS; + case 88: + return AV_CODEC_ID_JPEG2000; + case 89: + return AV_CODEC_ID_VMNC; + case 90: + return AV_CODEC_ID_VP5; + case 91: + return AV_CODEC_ID_VP6; + case 92: + return AV_CODEC_ID_VP6F; + case 93: + return AV_CODEC_ID_TARGA; + case 94: + return AV_CODEC_ID_DSICINVIDEO; + case 95: + return AV_CODEC_ID_TIERTEXSEQVIDEO; + case 96: + return AV_CODEC_ID_TIFF; + case 97: + return AV_CODEC_ID_GIF; + case 98: + return AV_CODEC_ID_DXA; + case 99: + return AV_CODEC_ID_DNXHD; + case 100: + return AV_CODEC_ID_THP; + case 101: + return AV_CODEC_ID_SGI; + case 102: + return AV_CODEC_ID_C93; + case 103: + return AV_CODEC_ID_BETHSOFTVID; + case 104: + return AV_CODEC_ID_PTX; + case 105: + return AV_CODEC_ID_TXD; + case 106: + return AV_CODEC_ID_VP6A; + case 107: + return AV_CODEC_ID_AMV; + case 108: + return AV_CODEC_ID_VB; + case 109: + return AV_CODEC_ID_PCX; + case 110: + return AV_CODEC_ID_SUNRAST; + case 111: + return AV_CODEC_ID_INDEO4; + case 112: + return AV_CODEC_ID_INDEO5; + case 113: + return AV_CODEC_ID_MIMIC; + case 114: + return AV_CODEC_ID_RL2; + case 115: + return AV_CODEC_ID_ESCAPE124; + case 116: + return AV_CODEC_ID_DIRAC; + case 117: + return AV_CODEC_ID_BFI; + case 118: + return AV_CODEC_ID_CMV; + case 119: + return AV_CODEC_ID_MOTIONPIXELS; + case 120: + return AV_CODEC_ID_TGV; + case 121: + return AV_CODEC_ID_TGQ; + case 122: + return AV_CODEC_ID_TQI; + case 123: + return AV_CODEC_ID_AURA; + case 124: + return AV_CODEC_ID_AURA2; + case 125: + return AV_CODEC_ID_V210X; + case 126: + return AV_CODEC_ID_TMV; + case 127: + return AV_CODEC_ID_V210; + case 128: + return AV_CODEC_ID_DPX; + case 129: + return AV_CODEC_ID_MAD; + case 130: + return AV_CODEC_ID_FRWU; + case 131: + return AV_CODEC_ID_FLASHSV2; + case 132: + return AV_CODEC_ID_CDGRAPHICS; + case 133: + return AV_CODEC_ID_R210; + case 134: + return AV_CODEC_ID_ANM; + case 135: + return AV_CODEC_ID_BINKVIDEO; + case 136: + return AV_CODEC_ID_IFF_ILBM; + case 137: + return AV_CODEC_ID_IFF_ILBM; + case 138: + return AV_CODEC_ID_KGV1; + case 139: + return AV_CODEC_ID_YOP; + case 140: + return AV_CODEC_ID_VP8; + case 141: + return AV_CODEC_ID_PICTOR; + case 142: + return AV_CODEC_ID_ANSI; + case 143: + return AV_CODEC_ID_A64_MULTI; + case 144: + return AV_CODEC_ID_A64_MULTI5; + case 145: + return AV_CODEC_ID_R10K; + case 146: + return AV_CODEC_ID_MXPEG; + case 147: + return AV_CODEC_ID_LAGARITH; + case 148: + return AV_CODEC_ID_PRORES; + case 149: + return AV_CODEC_ID_JV; + case 150: + return AV_CODEC_ID_DFA; + case 151: + return AV_CODEC_ID_WMV3IMAGE; + case 152: + return AV_CODEC_ID_VC1IMAGE; + case 153: + return AV_CODEC_ID_UTVIDEO; + case 154: + return AV_CODEC_ID_BMV_VIDEO; + case 155: + return AV_CODEC_ID_VBLE; + case 156: + return AV_CODEC_ID_DXTORY; + case 157: + return AV_CODEC_ID_V410; + case 158: + return AV_CODEC_ID_XWD; + case 159: + return AV_CODEC_ID_CDXL; + case 160: + return AV_CODEC_ID_XBM; + case 161: + return AV_CODEC_ID_ZEROCODEC; + case 162: + return AV_CODEC_ID_MSS1; + case 163: + return AV_CODEC_ID_MSA1; + case 164: + return AV_CODEC_ID_TSCC2; + case 165: + return AV_CODEC_ID_MTS2; + case 166: + return AV_CODEC_ID_CLLC; + case 167: + return AV_CODEC_ID_MSS2; + case 168: + return AV_CODEC_ID_VP9; + case 169: + return AV_CODEC_ID_AIC; + case 170: + return AV_CODEC_ID_ESCAPE130; + case 171: + return AV_CODEC_ID_G2M; + case 172: + return AV_CODEC_ID_WEBP; + case 173: + return AV_CODEC_ID_HNM4_VIDEO; + case 174: + return AV_CODEC_ID_HEVC; + case 175: + return AV_CODEC_ID_HEVC; + case 176: + return AV_CODEC_ID_FIC; + case 177: + return AV_CODEC_ID_ALIAS_PIX; + case 178: + return AV_CODEC_ID_BRENDER_PIX; + case 179: + return AV_CODEC_ID_PAF_VIDEO; + case 180: + return AV_CODEC_ID_EXR; + case 181: + return AV_CODEC_ID_VP7; + case 182: + return AV_CODEC_ID_SANM; + case 183: + return AV_CODEC_ID_SGIRLE; + case 184: + return AV_CODEC_ID_MVC1; + case 185: + return AV_CODEC_ID_MVC2; + case 186: + return AV_CODEC_ID_HQX; + case 187: + return AV_CODEC_ID_TDSC; + case 188: + return AV_CODEC_ID_HQ_HQA; + case 189: + return AV_CODEC_ID_HAP; + case 190: + return AV_CODEC_ID_DDS; + case 191: + return AV_CODEC_ID_DXV; + case 192: + return AV_CODEC_ID_SCREENPRESSO; + case 193: + return AV_CODEC_ID_RSCC; + /////////////////////////////// + // case 194: + // return AV_CODEC_ID_Y41P; + // case 194: + // return AV_CODEC_ID_AVS2; + case 194: + return AV_CODEC_ID_Y41P; + case 195: + return AV_CODEC_ID_AVRP; + case 196: + return AV_CODEC_ID_012V; + case 197: + return AV_CODEC_ID_AVUI; + case 198: + return AV_CODEC_ID_AYUV; + case 199: + return AV_CODEC_ID_TARGA_Y216; + case 200: + return AV_CODEC_ID_V308; + case 201: + return AV_CODEC_ID_V408; + case 202: + return AV_CODEC_ID_YUV4; + case 203: + return AV_CODEC_ID_AVRN; + case 204: + return AV_CODEC_ID_CPIA; + case 205: + return AV_CODEC_ID_XFACE; + case 206: + return AV_CODEC_ID_SNOW; + case 207: + return AV_CODEC_ID_SMVJPEG; + case 208: + return AV_CODEC_ID_APNG; + case 209: + return AV_CODEC_ID_DAALA; + case 210: + return AV_CODEC_ID_CFHD; + case 211: + return AV_CODEC_ID_TRUEMOTION2RT; + case 212: + return AV_CODEC_ID_M101; + case 213: + return AV_CODEC_ID_MAGICYUV; + case 214: + return AV_CODEC_ID_SHEERVIDEO; + case 215: + return AV_CODEC_ID_YLC; + case 216: + return AV_CODEC_ID_PCM_S16LE; + case 217: + return AV_CODEC_ID_PCM_S16BE; + case 218: + return AV_CODEC_ID_PCM_U16LE; + case 219: + return AV_CODEC_ID_PCM_U16BE; + case 220: + return AV_CODEC_ID_PCM_S8; + case 221: + return AV_CODEC_ID_PCM_U8; + case 222: + return AV_CODEC_ID_PCM_MULAW; + case 223: + return AV_CODEC_ID_PCM_ALAW; + case 224: + return AV_CODEC_ID_PCM_S32LE; + case 225: + return AV_CODEC_ID_PCM_S32BE; + case 226: + return AV_CODEC_ID_PCM_U32LE; + case 227: + return AV_CODEC_ID_PCM_U32BE; + case 228: + return AV_CODEC_ID_PCM_S24LE; + case 229: + return AV_CODEC_ID_PCM_S24BE; + case 230: + return AV_CODEC_ID_PCM_U24LE; + case 231: + return AV_CODEC_ID_PCM_U24BE; + case 232: + return AV_CODEC_ID_PCM_S24DAUD; + case 233: + return AV_CODEC_ID_PCM_ZORK; + case 234: + return AV_CODEC_ID_PCM_S16LE_PLANAR; + case 235: + return AV_CODEC_ID_PCM_DVD; + case 236: + return AV_CODEC_ID_PCM_F32BE; + case 237: + return AV_CODEC_ID_PCM_F32LE; + case 238: + return AV_CODEC_ID_PCM_F64BE; + case 239: + return AV_CODEC_ID_PCM_F64LE; + case 240: + return AV_CODEC_ID_PCM_BLURAY; + case 241: + return AV_CODEC_ID_PCM_LXF; + case 242: + return AV_CODEC_ID_S302M; + case 243: + return AV_CODEC_ID_PCM_S8_PLANAR; + case 244: + return AV_CODEC_ID_PCM_S24LE_PLANAR; + case 245: + return AV_CODEC_ID_PCM_S32LE_PLANAR; + case 246: + return AV_CODEC_ID_PCM_S16BE_PLANAR; + case 247: + return AV_CODEC_ID_PCM_S64LE; + case 248: + return AV_CODEC_ID_PCM_S64BE; + case 249: + return AV_CODEC_ID_ADPCM_IMA_QT; + case 250: + return AV_CODEC_ID_ADPCM_IMA_WAV; + case 251: + return AV_CODEC_ID_ADPCM_IMA_DK3; + case 252: + return AV_CODEC_ID_ADPCM_IMA_DK4; + case 253: + return AV_CODEC_ID_ADPCM_IMA_WS; + case 254: + return AV_CODEC_ID_ADPCM_IMA_SMJPEG; + case 255: + return AV_CODEC_ID_ADPCM_MS; + case 256: + return AV_CODEC_ID_ADPCM_4XM; + case 257: + return AV_CODEC_ID_ADPCM_XA; + case 258: + return AV_CODEC_ID_ADPCM_ADX; + case 259: + return AV_CODEC_ID_ADPCM_EA; + case 260: + return AV_CODEC_ID_ADPCM_G726; + case 261: + return AV_CODEC_ID_ADPCM_CT; + case 262: + return AV_CODEC_ID_ADPCM_SWF; + case 263: + return AV_CODEC_ID_ADPCM_YAMAHA; + case 264: + return AV_CODEC_ID_ADPCM_SBPRO_4; + case 265: + return AV_CODEC_ID_ADPCM_SBPRO_3; + case 266: + return AV_CODEC_ID_ADPCM_SBPRO_2; + case 267: + return AV_CODEC_ID_ADPCM_THP; + case 268: + return AV_CODEC_ID_ADPCM_IMA_AMV; + case 269: + return AV_CODEC_ID_ADPCM_EA_R1; + case 270: + return AV_CODEC_ID_ADPCM_EA_R3; + case 271: + return AV_CODEC_ID_ADPCM_EA_R2; + case 272: + return AV_CODEC_ID_ADPCM_IMA_EA_SEAD; + case 273: + return AV_CODEC_ID_ADPCM_IMA_EA_EACS; + case 274: + return AV_CODEC_ID_ADPCM_EA_XAS; + case 275: + return AV_CODEC_ID_ADPCM_EA_MAXIS_XA; + case 276: + return AV_CODEC_ID_ADPCM_IMA_ISS; + case 277: + return AV_CODEC_ID_ADPCM_G722; + case 278: + return AV_CODEC_ID_ADPCM_IMA_APC; + case 279: + return AV_CODEC_ID_ADPCM_VIMA; + case 280: + return AV_CODEC_ID_ADPCM_AFC; + case 281: + return AV_CODEC_ID_ADPCM_IMA_OKI; + case 282: + return AV_CODEC_ID_ADPCM_DTK; + case 283: + return AV_CODEC_ID_ADPCM_IMA_RAD; + case 284: + return AV_CODEC_ID_ADPCM_G726LE; + case 285: + return AV_CODEC_ID_ADPCM_THP_LE; + case 286: + return AV_CODEC_ID_ADPCM_PSX; + case 287: + return AV_CODEC_ID_ADPCM_AICA; + case 288: + return AV_CODEC_ID_ADPCM_IMA_DAT4; + case 289: + return AV_CODEC_ID_ADPCM_MTAF; + case 290: + return AV_CODEC_ID_AMR_NB; + case 291: + return AV_CODEC_ID_AMR_WB; + case 292: + return AV_CODEC_ID_RA_144; + case 293: + return AV_CODEC_ID_RA_288; + case 294: + return AV_CODEC_ID_ROQ_DPCM; + case 295: + return AV_CODEC_ID_INTERPLAY_DPCM; + case 296: + return AV_CODEC_ID_XAN_DPCM; + case 297: + return AV_CODEC_ID_SOL_DPCM; + case 298: + return AV_CODEC_ID_SDX2_DPCM; + case 299: + return AV_CODEC_ID_MP2; + case 300: + return AV_CODEC_ID_MP3; + case 301: + return AV_CODEC_ID_AAC; + case 302: + return AV_CODEC_ID_AC3; + case 303: + return AV_CODEC_ID_DTS; + case 304: + return AV_CODEC_ID_VORBIS; + case 305: + return AV_CODEC_ID_DVAUDIO; + case 306: + return AV_CODEC_ID_WMAV1; + case 307: + return AV_CODEC_ID_WMAV2; + case 308: + return AV_CODEC_ID_MACE3; + case 309: + return AV_CODEC_ID_MACE6; + case 310: + return AV_CODEC_ID_VMDAUDIO; + case 311: + return AV_CODEC_ID_FLAC; + case 312: + return AV_CODEC_ID_MP3ADU; + case 313: + return AV_CODEC_ID_MP3ON4; + case 314: + return AV_CODEC_ID_SHORTEN; + case 315: + return AV_CODEC_ID_ALAC; + case 316: + return AV_CODEC_ID_WESTWOOD_SND1; + case 317: + return AV_CODEC_ID_GSM; + case 318: + return AV_CODEC_ID_QDM2; + case 319: + return AV_CODEC_ID_COOK; + case 320: + return AV_CODEC_ID_TRUESPEECH; + case 321: + return AV_CODEC_ID_TTA; + case 322: + return AV_CODEC_ID_SMACKAUDIO; + case 323: + return AV_CODEC_ID_QCELP; + case 324: + return AV_CODEC_ID_WAVPACK; + case 325: + return AV_CODEC_ID_DSICINAUDIO; + case 326: + return AV_CODEC_ID_IMC; + case 327: + return AV_CODEC_ID_MUSEPACK7; + case 328: + return AV_CODEC_ID_MLP; + case 329: + return AV_CODEC_ID_GSM_MS; + case 330: + return AV_CODEC_ID_ATRAC3; + // #[cfg(feature = "ff_api_voxware")] + // case 331: + // return AV_CODEC_ID_VOXWARE; + case 332: + return AV_CODEC_ID_APE; + case 333: + return AV_CODEC_ID_NELLYMOSER; + case 334: + return AV_CODEC_ID_MUSEPACK8; + case 335: + return AV_CODEC_ID_SPEEX; + case 336: + return AV_CODEC_ID_WMAVOICE; + case 337: + return AV_CODEC_ID_WMAPRO; + case 338: + return AV_CODEC_ID_WMALOSSLESS; + case 339: + return AV_CODEC_ID_ATRAC3P; + case 340: + return AV_CODEC_ID_EAC3; + case 341: + return AV_CODEC_ID_SIPR; + case 342: + return AV_CODEC_ID_MP1; + case 343: + return AV_CODEC_ID_TWINVQ; + case 344: + return AV_CODEC_ID_TRUEHD; + case 345: + return AV_CODEC_ID_MP4ALS; + case 346: + return AV_CODEC_ID_ATRAC1; + case 347: + return AV_CODEC_ID_BINKAUDIO_RDFT; + case 348: + return AV_CODEC_ID_BINKAUDIO_DCT; + case 349: + return AV_CODEC_ID_AAC_LATM; + case 350: + return AV_CODEC_ID_QDMC; + case 351: + return AV_CODEC_ID_CELT; + case 352: + return AV_CODEC_ID_G723_1; + case 353: + return AV_CODEC_ID_G729; + case 354: + return AV_CODEC_ID_8SVX_EXP; + case 355: + return AV_CODEC_ID_8SVX_FIB; + case 356: + return AV_CODEC_ID_BMV_AUDIO; + case 357: + return AV_CODEC_ID_RALF; + case 358: + return AV_CODEC_ID_IAC; + case 359: + return AV_CODEC_ID_ILBC; + case 360: + return AV_CODEC_ID_OPUS; + case 361: + return AV_CODEC_ID_COMFORT_NOISE; + case 362: + return AV_CODEC_ID_TAK; + case 363: + return AV_CODEC_ID_METASOUND; + case 364: + return AV_CODEC_ID_PAF_AUDIO; + case 365: + return AV_CODEC_ID_ON2AVC; + case 366: + return AV_CODEC_ID_DSS_SP; + case 367: + return AV_CODEC_ID_CODEC2; + case 368: + return AV_CODEC_ID_FFWAVESYNTH; + case 369: + return AV_CODEC_ID_SONIC; + case 370: + return AV_CODEC_ID_SONIC_LS; + case 371: + return AV_CODEC_ID_EVRC; + case 372: + return AV_CODEC_ID_SMV; + case 373: + return AV_CODEC_ID_DSD_LSBF; + case 374: + return AV_CODEC_ID_DSD_MSBF; + case 375: + return AV_CODEC_ID_DSD_LSBF_PLANAR; + case 376: + return AV_CODEC_ID_DSD_MSBF_PLANAR; + case 377: + return AV_CODEC_ID_4GV; + case 378: + return AV_CODEC_ID_INTERPLAY_ACM; + case 379: + return AV_CODEC_ID_XMA1; + case 380: + return AV_CODEC_ID_XMA2; + case 381: + return AV_CODEC_ID_DST; + ///////////// + ///////////// + ///////////// + case 382: + return AV_CODEC_ID_DVD_SUBTITLE; + case 383: + return AV_CODEC_ID_DVB_SUBTITLE; + case 384: + return AV_CODEC_ID_TEXT; + case 385: + return AV_CODEC_ID_XSUB; + case 386: + return AV_CODEC_ID_SSA; + case 387: + return AV_CODEC_ID_MOV_TEXT; + case 388: + return AV_CODEC_ID_HDMV_PGS_SUBTITLE; + case 389: + return AV_CODEC_ID_DVB_TELETEXT; + case 390: + return AV_CODEC_ID_SRT; + case 391: + return AV_CODEC_ID_MICRODVD; + case 392: + return AV_CODEC_ID_EIA_608; + case 393: + return AV_CODEC_ID_JACOSUB; + case 394: + return AV_CODEC_ID_SAMI; + case 395: + return AV_CODEC_ID_REALTEXT; + case 396: + return AV_CODEC_ID_STL; + case 397: + return AV_CODEC_ID_SUBVIEWER1; + case 398: + return AV_CODEC_ID_SUBVIEWER; + case 399: + return AV_CODEC_ID_SUBRIP; + case 400: + return AV_CODEC_ID_WEBVTT; + case 401: + return AV_CODEC_ID_MPL2; + case 402: + return AV_CODEC_ID_VPLAYER; + case 403: + return AV_CODEC_ID_PJS; + case 404: + return AV_CODEC_ID_ASS; + case 405: + return AV_CODEC_ID_HDMV_TEXT_SUBTITLE; + case 406: + return AV_CODEC_ID_TTF; + case 407: + return AV_CODEC_ID_SCTE_35; + case 408: + return AV_CODEC_ID_BINTEXT; + case 409: + return AV_CODEC_ID_XBIN; + case 410: + return AV_CODEC_ID_IDF; + case 411: + return AV_CODEC_ID_OTF; + case 412: + return AV_CODEC_ID_SMPTE_KLV; + case 413: + return AV_CODEC_ID_DVD_NAV; + case 414: + return AV_CODEC_ID_TIMED_ID3; + case 415: + return AV_CODEC_ID_BIN_DATA; + case 416: + return AV_CODEC_ID_PROBE; + case 417: + return AV_CODEC_ID_MPEG2TS; + case 418: + return AV_CODEC_ID_MPEG4SYSTEMS; + case 419: + return AV_CODEC_ID_FFMETADATA; + case 420: + return AV_CODEC_ID_WRAPPED_AVFRAME; + case 421: + return AV_CODEC_ID_PSD; + case 422: + return AV_CODEC_ID_PIXLET; + case 423: + return AV_CODEC_ID_SPEEDHQ; + case 424: + return AV_CODEC_ID_CLEARVIDEO; + case 425: + return AV_CODEC_ID_FMVC; + case 426: + return AV_CODEC_ID_SCPR; + case 427: + return AV_CODEC_ID_XPM; + case 428: + return AV_CODEC_ID_AV1; + case 429: + return AV_CODEC_ID_PCM_F16LE; + case 430: + return AV_CODEC_ID_PCM_F24LE; + //////////// + case 431: + return AV_CODEC_ID_ATRAC3AL; + case 432: + return AV_CODEC_ID_ATRAC3PAL; + case 433: + return AV_CODEC_ID_BITPACKED; + case 434: + return AV_CODEC_ID_MSCC; + case 435: + return AV_CODEC_ID_SRGC; + case 436: + return AV_CODEC_ID_SVG; + case 437: + return AV_CODEC_ID_GDV; + case 438: + return AV_CODEC_ID_FITS; + case 439: + return AV_CODEC_ID_GREMLIN_DPCM; + case 440: + return AV_CODEC_ID_DOLBY_E; + case 441: + return AV_CODEC_ID_APTX; + case 442: + return AV_CODEC_ID_APTX_HD; + case 443: + return AV_CODEC_ID_SBC; + case 444: + return AV_CODEC_ID_AVS2; + case 445: + return AV_CODEC_ID_IMM4; + case 446: + return AV_CODEC_ID_PROSUMER; + case 447: + return AV_CODEC_ID_MWSC; + case 448: + return AV_CODEC_ID_WCMV; + case 449: + return AV_CODEC_ID_RASC; + case 450: + return AV_CODEC_ID_PCM_VIDC; + case 451: + return AV_CODEC_ID_ATRAC9; + case 452: + return AV_CODEC_ID_TTML; + case 453: + return AV_CODEC_ID_HYMT; + case 454: + return AV_CODEC_ID_ARBC; + case 455: + return AV_CODEC_ID_AGM; + case 456: + return AV_CODEC_ID_LSCR; + case 457: + return AV_CODEC_ID_VP4; + case 458: + return AV_CODEC_ID_ADPCM_AGM; + case 459: + return AV_CODEC_ID_HCOM; + case 460: + return AV_CODEC_ID_ARIB_CAPTION; + case 461: + return AV_CODEC_ID_IMM5; + case 462: + return AV_CODEC_ID_MVDV; + case 463: + return AV_CODEC_ID_MVHA; + case 464: + return AV_CODEC_ID_CDTOONS; + case 465: + return AV_CODEC_ID_MV30; + case 466: + return AV_CODEC_ID_NOTCHLC; + case 467: + return AV_CODEC_ID_PFM; + case 468: + return AV_CODEC_ID_ARGO; + case 469: + return AV_CODEC_ID_ADPCM_IMA_SSI; + case 470: + return AV_CODEC_ID_ADPCM_ZORK; + case 471: + return AV_CODEC_ID_ADPCM_IMA_APM; + case 472: + return AV_CODEC_ID_ADPCM_IMA_ALP; + case 473: + return AV_CODEC_ID_ADPCM_IMA_MTF; + case 474: + return AV_CODEC_ID_ADPCM_IMA_CUNNING; + case 475: + return AV_CODEC_ID_DERF_DPCM; + case 476: + return AV_CODEC_ID_ACELP_KELVIN; + case 477: + return AV_CODEC_ID_MPEGH_3D_AUDIO; + case 478: + return AV_CODEC_ID_SIREN; + case 479: + return AV_CODEC_ID_HCA; + case 480: + return AV_CODEC_ID_EPG; + case 481: + return AV_CODEC_ID_AVS3; + case 482: + return AV_CODEC_ID_PGX; + case 483: + return AV_CODEC_ID_MSP2; + case 484: + return AV_CODEC_ID_VVC; + case 485: + return AV_CODEC_ID_MOBICLIP; + case 486: + return AV_CODEC_ID_PHOTOCD; + case 487: + return AV_CODEC_ID_ADPCM_ARGO; + case 488: + return AV_CODEC_ID_CRI; + case 489: + return AV_CODEC_ID_IPU; + case 490: + return AV_CODEC_ID_SIMBIOSIS_IMX; + case 491: + return AV_CODEC_ID_SGA_VIDEO; + case 492: + return AV_CODEC_ID_PCM_SGA; + case 493: + return AV_CODEC_ID_ADPCM_IMA_MOFLEX; + case 494: + return AV_CODEC_ID_FASTAUDIO; + case 495: + return AV_CODEC_ID_GEM; + case 496: + return AV_CODEC_ID_ADPCM_IMA_ACORN; + case 497: + return AV_CODEC_ID_MSNSIREN; + case 498: + return AV_CODEC_ID_VBN; + case 499: + return AV_CODEC_ID_JPEGXL; + case 500: + return AV_CODEC_ID_QOI; + case 501: + return AV_CODEC_ID_PHM; + case 502: + return AV_CODEC_ID_DFPWM; + case 503: + return AV_CODEC_ID_RADIANCE_HDR; + case 504: + return AV_CODEC_ID_WBMP; + case 505: + return AV_CODEC_ID_MEDIA100; + case 506: + return AV_CODEC_ID_VQC; + case 507: + return AV_CODEC_ID_ADPCM_XMD; + case 508: + return AV_CODEC_ID_WADY_DPCM; + case 509: + return AV_CODEC_ID_CBD2_DPCM; + case 510: + return AV_CODEC_ID_BONK; + case 511: + return AV_CODEC_ID_MISC4; + case 512: + return AV_CODEC_ID_APAC; + case 513: + return AV_CODEC_ID_FTR; + case 514: + return AV_CODEC_ID_WAVARC; + case 515: + return AV_CODEC_ID_RKA; + case 516: + return AV_CODEC_ID_VNULL; + case 517: + return AV_CODEC_ID_ANULL; + // case 518: + // return AV_CODEC_ID_MPEG2VIDEO_XVMC; + default: + return AV_CODEC_ID_NONE; + }; + } + + // Convert AVCodecID to uint32_t for rust SDK. + static uint32_t fromAVCodecID(AVCodecID AvCodecId) { + switch (AvCodecId) { + case AV_CODEC_ID_NONE: + return 0; + case AV_CODEC_ID_MPEG1VIDEO: + return 1; + case AV_CODEC_ID_MPEG2VIDEO: + return 2; + case AV_CODEC_ID_H261: + return 3; + case AV_CODEC_ID_H263: + return 4; + case AV_CODEC_ID_RV10: + return 5; + case AV_CODEC_ID_RV20: + return 6; + case AV_CODEC_ID_MJPEG: + return 7; + case AV_CODEC_ID_MJPEGB: + return 8; + case AV_CODEC_ID_LJPEG: + return 9; + case AV_CODEC_ID_SP5X: + return 10; + case AV_CODEC_ID_JPEGLS: + return 11; + case AV_CODEC_ID_MPEG4: + return 12; + case AV_CODEC_ID_RAWVIDEO: + return 13; + case AV_CODEC_ID_MSMPEG4V1: + return 14; + case AV_CODEC_ID_MSMPEG4V2: + return 15; + case AV_CODEC_ID_MSMPEG4V3: + return 16; + case AV_CODEC_ID_WMV1: + return 17; + case AV_CODEC_ID_WMV2: + return 18; + case AV_CODEC_ID_H263P: + return 19; + case AV_CODEC_ID_H263I: + return 20; + case AV_CODEC_ID_FLV1: + return 21; + case AV_CODEC_ID_SVQ1: + return 22; + case AV_CODEC_ID_SVQ3: + return 23; + case AV_CODEC_ID_DVVIDEO: + return 24; + case AV_CODEC_ID_HUFFYUV: + return 25; + case AV_CODEC_ID_CYUV: + return 26; + case AV_CODEC_ID_H264: + return 27; + case AV_CODEC_ID_INDEO3: + return 28; + case AV_CODEC_ID_VP3: + return 29; + case AV_CODEC_ID_THEORA: + return 30; + case AV_CODEC_ID_ASV1: + return 31; + case AV_CODEC_ID_ASV2: + return 32; + case AV_CODEC_ID_FFV1: + return 33; + case AV_CODEC_ID_4XM: + return 34; + case AV_CODEC_ID_VCR1: + return 35; + case AV_CODEC_ID_CLJR: + return 36; + case AV_CODEC_ID_MDEC: + return 37; + case AV_CODEC_ID_ROQ: + return 38; + case AV_CODEC_ID_INTERPLAY_VIDEO: + return 39; + case AV_CODEC_ID_XAN_WC3: + return 40; + case AV_CODEC_ID_XAN_WC4: + return 41; + case AV_CODEC_ID_RPZA: + return 42; + case AV_CODEC_ID_CINEPAK: + return 43; + case AV_CODEC_ID_WS_VQA: + return 44; + case AV_CODEC_ID_MSRLE: + return 45; + case AV_CODEC_ID_MSVIDEO1: + return 46; + case AV_CODEC_ID_IDCIN: + return 47; + case AV_CODEC_ID_8BPS: + return 48; + case AV_CODEC_ID_SMC: + return 49; + case AV_CODEC_ID_FLIC: + return 50; + case AV_CODEC_ID_TRUEMOTION1: + return 51; + case AV_CODEC_ID_VMDVIDEO: + return 52; + case AV_CODEC_ID_MSZH: + return 53; + case AV_CODEC_ID_ZLIB: + return 54; + case AV_CODEC_ID_QTRLE: + return 55; + case AV_CODEC_ID_TSCC: + return 56; + case AV_CODEC_ID_ULTI: + return 57; + case AV_CODEC_ID_QDRAW: + return 58; + case AV_CODEC_ID_VIXL: + return 59; + case AV_CODEC_ID_QPEG: + return 60; + case AV_CODEC_ID_PNG: + return 61; + case AV_CODEC_ID_PPM: + return 62; + case AV_CODEC_ID_PBM: + return 63; + case AV_CODEC_ID_PGM: + return 64; + case AV_CODEC_ID_PGMYUV: + return 65; + case AV_CODEC_ID_PAM: + return 66; + case AV_CODEC_ID_FFVHUFF: + return 67; + case AV_CODEC_ID_RV30: + return 68; + case AV_CODEC_ID_RV40: + return 69; + case AV_CODEC_ID_VC1: + return 70; + case AV_CODEC_ID_WMV3: + return 71; + case AV_CODEC_ID_LOCO: + return 72; + case AV_CODEC_ID_WNV1: + return 73; + case AV_CODEC_ID_AASC: + return 74; + case AV_CODEC_ID_INDEO2: + return 75; + case AV_CODEC_ID_FRAPS: + return 76; + case AV_CODEC_ID_TRUEMOTION2: + return 77; + case AV_CODEC_ID_BMP: + return 78; + case AV_CODEC_ID_CSCD: + return 79; + case AV_CODEC_ID_MMVIDEO: + return 80; + case AV_CODEC_ID_ZMBV: + return 81; + case AV_CODEC_ID_AVS: + return 82; + case AV_CODEC_ID_SMACKVIDEO: + return 83; + case AV_CODEC_ID_NUV: + return 84; + case AV_CODEC_ID_KMVC: + return 85; + case AV_CODEC_ID_FLASHSV: + return 86; + case AV_CODEC_ID_CAVS: + return 87; + case AV_CODEC_ID_JPEG2000: + return 88; + case AV_CODEC_ID_VMNC: + return 89; + case AV_CODEC_ID_VP5: + return 90; + case AV_CODEC_ID_VP6: + return 91; + case AV_CODEC_ID_VP6F: + return 92; + case AV_CODEC_ID_TARGA: + return 93; + case AV_CODEC_ID_DSICINVIDEO: + return 94; + case AV_CODEC_ID_TIERTEXSEQVIDEO: + return 95; + case AV_CODEC_ID_TIFF: + return 96; + case AV_CODEC_ID_GIF: + return 97; + case AV_CODEC_ID_DXA: + return 98; + case AV_CODEC_ID_DNXHD: + return 99; + case AV_CODEC_ID_THP: + return 100; + case AV_CODEC_ID_SGI: + return 101; + case AV_CODEC_ID_C93: + return 102; + case AV_CODEC_ID_BETHSOFTVID: + return 103; + case AV_CODEC_ID_PTX: + return 104; + case AV_CODEC_ID_TXD: + return 105; + case AV_CODEC_ID_VP6A: + return 106; + case AV_CODEC_ID_AMV: + return 107; + case AV_CODEC_ID_VB: + return 108; + case AV_CODEC_ID_PCX: + return 109; + case AV_CODEC_ID_SUNRAST: + return 110; + case AV_CODEC_ID_INDEO4: + return 111; + case AV_CODEC_ID_INDEO5: + return 112; + case AV_CODEC_ID_MIMIC: + return 113; + case AV_CODEC_ID_RL2: + return 114; + case AV_CODEC_ID_ESCAPE124: + return 115; + case AV_CODEC_ID_DIRAC: + return 116; + case AV_CODEC_ID_BFI: + return 117; + case AV_CODEC_ID_CMV: + return 118; + case AV_CODEC_ID_MOTIONPIXELS: + return 119; + case AV_CODEC_ID_TGV: + return 120; + case AV_CODEC_ID_TGQ: + return 121; + case AV_CODEC_ID_TQI: + return 122; + case AV_CODEC_ID_AURA: + return 123; + case AV_CODEC_ID_AURA2: + return 124; + case AV_CODEC_ID_V210X: + return 125; + case AV_CODEC_ID_TMV: + return 126; + case AV_CODEC_ID_V210: + return 127; + case AV_CODEC_ID_DPX: + return 128; + case AV_CODEC_ID_MAD: + return 129; + case AV_CODEC_ID_FRWU: + return 130; + case AV_CODEC_ID_FLASHSV2: + return 131; + case AV_CODEC_ID_CDGRAPHICS: + return 132; + case AV_CODEC_ID_R210: + return 133; + case AV_CODEC_ID_ANM: + return 134; + case AV_CODEC_ID_BINKVIDEO: + return 135; + case AV_CODEC_ID_IFF_ILBM: + return 136; + // case AV_CODEC_ID_IFF_ILBM: + // return 137; + case AV_CODEC_ID_KGV1: + return 138; + case AV_CODEC_ID_YOP: + return 139; + case AV_CODEC_ID_VP8: + return 140; + case AV_CODEC_ID_PICTOR: + return 141; + case AV_CODEC_ID_ANSI: + return 142; + case AV_CODEC_ID_A64_MULTI: + return 143; + case AV_CODEC_ID_A64_MULTI5: + return 144; + case AV_CODEC_ID_R10K: + return 145; + case AV_CODEC_ID_MXPEG: + return 146; + case AV_CODEC_ID_LAGARITH: + return 147; + case AV_CODEC_ID_PRORES: + return 148; + case AV_CODEC_ID_JV: + return 149; + case AV_CODEC_ID_DFA: + return 150; + case AV_CODEC_ID_WMV3IMAGE: + return 151; + case AV_CODEC_ID_VC1IMAGE: + return 152; + case AV_CODEC_ID_UTVIDEO: + return 153; + case AV_CODEC_ID_BMV_VIDEO: + return 154; + case AV_CODEC_ID_VBLE: + return 155; + case AV_CODEC_ID_DXTORY: + return 156; + case AV_CODEC_ID_V410: + return 157; + case AV_CODEC_ID_XWD: + return 158; + case AV_CODEC_ID_CDXL: + return 159; + case AV_CODEC_ID_XBM: + return 160; + case AV_CODEC_ID_ZEROCODEC: + return 161; + case AV_CODEC_ID_MSS1: + return 162; + case AV_CODEC_ID_MSA1: + return 163; + case AV_CODEC_ID_TSCC2: + return 164; + case AV_CODEC_ID_MTS2: + return 165; + case AV_CODEC_ID_CLLC: + return 166; + case AV_CODEC_ID_MSS2: + return 167; + case AV_CODEC_ID_VP9: + return 168; + case AV_CODEC_ID_AIC: + return 169; + case AV_CODEC_ID_ESCAPE130: + return 170; + case AV_CODEC_ID_G2M: + return 171; + case AV_CODEC_ID_WEBP: + return 172; + case AV_CODEC_ID_HNM4_VIDEO: + return 173; + case AV_CODEC_ID_HEVC: + return 174; + // case AV_CODEC_ID_HEVC: + // return 175; + case AV_CODEC_ID_FIC: + return 176; + case AV_CODEC_ID_ALIAS_PIX: + return 177; + case AV_CODEC_ID_BRENDER_PIX: + return 178; + case AV_CODEC_ID_PAF_VIDEO: + return 179; + case AV_CODEC_ID_EXR: + return 180; + case AV_CODEC_ID_VP7: + return 181; + case AV_CODEC_ID_SANM: + return 182; + case AV_CODEC_ID_SGIRLE: + return 183; + case AV_CODEC_ID_MVC1: + return 184; + case AV_CODEC_ID_MVC2: + return 185; + case AV_CODEC_ID_HQX: + return 186; + case AV_CODEC_ID_TDSC: + return 187; + case AV_CODEC_ID_HQ_HQA: + return 188; + case AV_CODEC_ID_HAP: + return 189; + case AV_CODEC_ID_DDS: + return 190; + case AV_CODEC_ID_DXV: + return 191; + case AV_CODEC_ID_SCREENPRESSO: + return 192; + case AV_CODEC_ID_RSCC: + return 193; + /////////////////////////////// + // return ; + // case AV_CODEC_ID_Y41P: + // return ; + // case AV_CODEC_ID_AVS2: + case AV_CODEC_ID_Y41P: + return 194; + case AV_CODEC_ID_AVRP: + return 195; + case AV_CODEC_ID_012V: + return 196; + case AV_CODEC_ID_AVUI: + return 197; + case AV_CODEC_ID_AYUV: + return 198; + case AV_CODEC_ID_TARGA_Y216: + return 199; + case AV_CODEC_ID_V308: + return 200; + case AV_CODEC_ID_V408: + return 201; + case AV_CODEC_ID_YUV4: + return 202; + case AV_CODEC_ID_AVRN: + return 203; + case AV_CODEC_ID_CPIA: + return 204; + case AV_CODEC_ID_XFACE: + return 205; + case AV_CODEC_ID_SNOW: + return 206; + case AV_CODEC_ID_SMVJPEG: + return 207; + case AV_CODEC_ID_APNG: + return 208; + case AV_CODEC_ID_DAALA: + return 209; + case AV_CODEC_ID_CFHD: + return 210; + case AV_CODEC_ID_TRUEMOTION2RT: + return 211; + case AV_CODEC_ID_M101: + return 212; + case AV_CODEC_ID_MAGICYUV: + return 213; + case AV_CODEC_ID_SHEERVIDEO: + return 214; + case AV_CODEC_ID_YLC: + return 215; + // ================================= + // ================================= + // ================================= + case AV_CODEC_ID_PCM_S16LE: + return 216; + case AV_CODEC_ID_PCM_S16BE: + return 217; + case AV_CODEC_ID_PCM_U16LE: + return 218; + case AV_CODEC_ID_PCM_U16BE: + return 219; + case AV_CODEC_ID_PCM_S8: + return 220; + case AV_CODEC_ID_PCM_U8: + return 221; + case AV_CODEC_ID_PCM_MULAW: + return 222; + case AV_CODEC_ID_PCM_ALAW: + return 223; + case AV_CODEC_ID_PCM_S32LE: + return 224; + case AV_CODEC_ID_PCM_S32BE: + return 225; + case AV_CODEC_ID_PCM_U32LE: + return 226; + case AV_CODEC_ID_PCM_U32BE: + return 227; + case AV_CODEC_ID_PCM_S24LE: + return 228; + case AV_CODEC_ID_PCM_S24BE: + return 229; + case AV_CODEC_ID_PCM_U24LE: + return 230; + case AV_CODEC_ID_PCM_U24BE: + return 231; + case AV_CODEC_ID_PCM_S24DAUD: + return 232; + case AV_CODEC_ID_PCM_ZORK: + return 233; + case AV_CODEC_ID_PCM_S16LE_PLANAR: + return 234; + case AV_CODEC_ID_PCM_DVD: + return 235; + case AV_CODEC_ID_PCM_F32BE: + return 236; + case AV_CODEC_ID_PCM_F32LE: + return 237; + case AV_CODEC_ID_PCM_F64BE: + return 238; + case AV_CODEC_ID_PCM_F64LE: + return 239; + case AV_CODEC_ID_PCM_BLURAY: + return 240; + case AV_CODEC_ID_PCM_LXF: + return 241; + case AV_CODEC_ID_S302M: + return 242; + case AV_CODEC_ID_PCM_S8_PLANAR: + return 243; + case AV_CODEC_ID_PCM_S24LE_PLANAR: + return 244; + case AV_CODEC_ID_PCM_S32LE_PLANAR: + return 245; + case AV_CODEC_ID_PCM_S16BE_PLANAR: + return 246; + case AV_CODEC_ID_PCM_S64LE: + return 247; + case AV_CODEC_ID_PCM_S64BE: + return 248; + case AV_CODEC_ID_ADPCM_IMA_QT: + return 249; + case AV_CODEC_ID_ADPCM_IMA_WAV: + return 250; + case AV_CODEC_ID_ADPCM_IMA_DK3: + return 251; + case AV_CODEC_ID_ADPCM_IMA_DK4: + return 252; + case AV_CODEC_ID_ADPCM_IMA_WS: + return 253; + case AV_CODEC_ID_ADPCM_IMA_SMJPEG: + return 254; + case AV_CODEC_ID_ADPCM_MS: + return 255; + case AV_CODEC_ID_ADPCM_4XM: + return 256; + case AV_CODEC_ID_ADPCM_XA: + return 257; + case AV_CODEC_ID_ADPCM_ADX: + return 258; + case AV_CODEC_ID_ADPCM_EA: + return 259; + case AV_CODEC_ID_ADPCM_G726: + return 260; + case AV_CODEC_ID_ADPCM_CT: + return 261; + case AV_CODEC_ID_ADPCM_SWF: + return 262; + case AV_CODEC_ID_ADPCM_YAMAHA: + return 263; + case AV_CODEC_ID_ADPCM_SBPRO_4: + return 264; + case AV_CODEC_ID_ADPCM_SBPRO_3: + return 265; + case AV_CODEC_ID_ADPCM_SBPRO_2: + return 266; + case AV_CODEC_ID_ADPCM_THP: + return 267; + case AV_CODEC_ID_ADPCM_IMA_AMV: + return 268; + case AV_CODEC_ID_ADPCM_EA_R1: + return 269; + case AV_CODEC_ID_ADPCM_EA_R3: + return 270; + case AV_CODEC_ID_ADPCM_EA_R2: + return 271; + case AV_CODEC_ID_ADPCM_IMA_EA_SEAD: + return 272; + case AV_CODEC_ID_ADPCM_IMA_EA_EACS: + return 273; + case AV_CODEC_ID_ADPCM_EA_XAS: + return 274; + case AV_CODEC_ID_ADPCM_EA_MAXIS_XA: + return 275; + case AV_CODEC_ID_ADPCM_IMA_ISS: + return 276; + case AV_CODEC_ID_ADPCM_G722: + return 277; + case AV_CODEC_ID_ADPCM_IMA_APC: + return 278; + case AV_CODEC_ID_ADPCM_VIMA: + return 279; + case AV_CODEC_ID_ADPCM_AFC: + return 280; + case AV_CODEC_ID_ADPCM_IMA_OKI: + return 281; + case AV_CODEC_ID_ADPCM_DTK: + return 282; + case AV_CODEC_ID_ADPCM_IMA_RAD: + return 283; + case AV_CODEC_ID_ADPCM_G726LE: + return 284; + case AV_CODEC_ID_ADPCM_THP_LE: + return 285; + case AV_CODEC_ID_ADPCM_PSX: + return 286; + case AV_CODEC_ID_ADPCM_AICA: + return 287; + case AV_CODEC_ID_ADPCM_IMA_DAT4: + return 288; + case AV_CODEC_ID_ADPCM_MTAF: + return 289; + case AV_CODEC_ID_AMR_NB: + return 290; + case AV_CODEC_ID_AMR_WB: + return 291; + case AV_CODEC_ID_RA_144: + return 292; + case AV_CODEC_ID_RA_288: + return 293; + case AV_CODEC_ID_ROQ_DPCM: + return 294; + case AV_CODEC_ID_INTERPLAY_DPCM: + return 295; + case AV_CODEC_ID_XAN_DPCM: + return 296; + case AV_CODEC_ID_SOL_DPCM: + return 297; + case AV_CODEC_ID_SDX2_DPCM: + return 298; + case AV_CODEC_ID_MP2: + return 299; + case AV_CODEC_ID_MP3: + return 300; + case AV_CODEC_ID_AAC: + return 301; + case AV_CODEC_ID_AC3: + return 302; + case AV_CODEC_ID_DTS: + return 303; + case AV_CODEC_ID_VORBIS: + return 304; + case AV_CODEC_ID_DVAUDIO: + return 305; + case AV_CODEC_ID_WMAV1: + return 306; + case AV_CODEC_ID_WMAV2: + return 307; + case AV_CODEC_ID_MACE3: + return 308; + case AV_CODEC_ID_MACE6: + return 309; + case AV_CODEC_ID_VMDAUDIO: + return 310; + case AV_CODEC_ID_FLAC: + return 311; + case AV_CODEC_ID_MP3ADU: + return 312; + case AV_CODEC_ID_MP3ON4: + return 313; + case AV_CODEC_ID_SHORTEN: + return 314; + case AV_CODEC_ID_ALAC: + return 315; + case AV_CODEC_ID_WESTWOOD_SND1: + return 316; + case AV_CODEC_ID_GSM: + return 317; + case AV_CODEC_ID_QDM2: + return 318; + case AV_CODEC_ID_COOK: + return 319; + case AV_CODEC_ID_TRUESPEECH: + return 320; + case AV_CODEC_ID_TTA: + return 321; + case AV_CODEC_ID_SMACKAUDIO: + return 322; + case AV_CODEC_ID_QCELP: + return 323; + case AV_CODEC_ID_WAVPACK: + return 324; + case AV_CODEC_ID_DSICINAUDIO: + return 325; + case AV_CODEC_ID_IMC: + return 326; + case AV_CODEC_ID_MUSEPACK7: + return 327; + case AV_CODEC_ID_MLP: + return 328; + case AV_CODEC_ID_GSM_MS: + return 329; + case AV_CODEC_ID_ATRAC3: + return 330; + // #[cfg(feature = "ff_api_voxware")] + // case AV_CODEC_ID_VOXWARE: + // return 331; + case AV_CODEC_ID_APE: + return 332; + case AV_CODEC_ID_NELLYMOSER: + return 333; + case AV_CODEC_ID_MUSEPACK8: + return 334; + case AV_CODEC_ID_SPEEX: + return 335; + case AV_CODEC_ID_WMAVOICE: + return 336; + case AV_CODEC_ID_WMAPRO: + return 337; + case AV_CODEC_ID_WMALOSSLESS: + return 338; + case AV_CODEC_ID_ATRAC3P: + return 339; + case AV_CODEC_ID_EAC3: + return 340; + case AV_CODEC_ID_SIPR: + return 341; + case AV_CODEC_ID_MP1: + return 342; + case AV_CODEC_ID_TWINVQ: + return 343; + case AV_CODEC_ID_TRUEHD: + return 344; + case AV_CODEC_ID_MP4ALS: + return 345; + case AV_CODEC_ID_ATRAC1: + return 346; + case AV_CODEC_ID_BINKAUDIO_RDFT: + return 347; + case AV_CODEC_ID_BINKAUDIO_DCT: + return 348; + case AV_CODEC_ID_AAC_LATM: + return 349; + case AV_CODEC_ID_QDMC: + return 350; + case AV_CODEC_ID_CELT: + return 351; + case AV_CODEC_ID_G723_1: + return 352; + case AV_CODEC_ID_G729: + return 353; + case AV_CODEC_ID_8SVX_EXP: + return 354; + case AV_CODEC_ID_8SVX_FIB: + return 355; + case AV_CODEC_ID_BMV_AUDIO: + return 356; + case AV_CODEC_ID_RALF: + return 357; + case AV_CODEC_ID_IAC: + return 358; + case AV_CODEC_ID_ILBC: + return 359; + case AV_CODEC_ID_OPUS: + return 360; + case AV_CODEC_ID_COMFORT_NOISE: + return 361; + case AV_CODEC_ID_TAK: + return 362; + case AV_CODEC_ID_METASOUND: + return 363; + case AV_CODEC_ID_PAF_AUDIO: + return 364; + case AV_CODEC_ID_ON2AVC: + return 365; + case AV_CODEC_ID_DSS_SP: + return 366; + case AV_CODEC_ID_CODEC2: + return 367; + case AV_CODEC_ID_FFWAVESYNTH: + return 368; + case AV_CODEC_ID_SONIC: + return 369; + case AV_CODEC_ID_SONIC_LS: + return 370; + case AV_CODEC_ID_EVRC: + return 371; + case AV_CODEC_ID_SMV: + return 372; + case AV_CODEC_ID_DSD_LSBF: + return 373; + case AV_CODEC_ID_DSD_MSBF: + return 374; + case AV_CODEC_ID_DSD_LSBF_PLANAR: + return 375; + case AV_CODEC_ID_DSD_MSBF_PLANAR: + return 376; + case AV_CODEC_ID_4GV: + return 377; + case AV_CODEC_ID_INTERPLAY_ACM: + return 378; + case AV_CODEC_ID_XMA1: + return 379; + case AV_CODEC_ID_XMA2: + return 380; + case AV_CODEC_ID_DST: + return 381; + case AV_CODEC_ID_DVD_SUBTITLE: + return 382; + case AV_CODEC_ID_DVB_SUBTITLE: + return 383; + case AV_CODEC_ID_TEXT: + return 384; + case AV_CODEC_ID_XSUB: + return 385; + case AV_CODEC_ID_SSA: + return 386; + case AV_CODEC_ID_MOV_TEXT: + return 387; + case AV_CODEC_ID_HDMV_PGS_SUBTITLE: + return 388; + case AV_CODEC_ID_DVB_TELETEXT: + return 389; + case AV_CODEC_ID_SRT: + return 390; + case AV_CODEC_ID_MICRODVD: + return 391; + case AV_CODEC_ID_EIA_608: + return 392; + case AV_CODEC_ID_JACOSUB: + return 393; + case AV_CODEC_ID_SAMI: + return 394; + case AV_CODEC_ID_REALTEXT: + return 395; + case AV_CODEC_ID_STL: + return 396; + case AV_CODEC_ID_SUBVIEWER1: + return 397; + case AV_CODEC_ID_SUBVIEWER: + return 398; + case AV_CODEC_ID_SUBRIP: + return 399; + case AV_CODEC_ID_WEBVTT: + return 400; + case AV_CODEC_ID_MPL2: + return 401; + case AV_CODEC_ID_VPLAYER: + return 402; + case AV_CODEC_ID_PJS: + return 403; + case AV_CODEC_ID_ASS: + return 404; + case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: + return 405; + case AV_CODEC_ID_TTF: + return 406; + case AV_CODEC_ID_SCTE_35: + return 407; + case AV_CODEC_ID_BINTEXT: + return 408; + case AV_CODEC_ID_XBIN: + return 409; + case AV_CODEC_ID_IDF: + return 410; + case AV_CODEC_ID_OTF: + return 411; + case AV_CODEC_ID_SMPTE_KLV: + return 412; + case AV_CODEC_ID_DVD_NAV: + return 413; + case AV_CODEC_ID_TIMED_ID3: + return 414; + case AV_CODEC_ID_BIN_DATA: + return 415; + case AV_CODEC_ID_PROBE: + return 416; + case AV_CODEC_ID_MPEG2TS: + return 417; + case AV_CODEC_ID_MPEG4SYSTEMS: + return 418; + case AV_CODEC_ID_FFMETADATA: + return 419; + case AV_CODEC_ID_WRAPPED_AVFRAME: + return 420; + case AV_CODEC_ID_PSD: + return 421; + case AV_CODEC_ID_PIXLET: + return 422; + case AV_CODEC_ID_SPEEDHQ: + return 423; + case AV_CODEC_ID_CLEARVIDEO: + return 424; + case AV_CODEC_ID_FMVC: + return 425; + case AV_CODEC_ID_SCPR: + return 426; + case AV_CODEC_ID_XPM: + return 427; + case AV_CODEC_ID_AV1: + return 428; + case AV_CODEC_ID_PCM_F16LE: + return 429; + case AV_CODEC_ID_PCM_F24LE: + return 430; + //////////// + case AV_CODEC_ID_ATRAC3AL: + return 431; + case AV_CODEC_ID_ATRAC3PAL: + return 432; + case AV_CODEC_ID_BITPACKED: + return 433; + case AV_CODEC_ID_MSCC: + return 434; + case AV_CODEC_ID_SRGC: + return 435; + case AV_CODEC_ID_SVG: + return 436; + case AV_CODEC_ID_GDV: + return 437; + case AV_CODEC_ID_FITS: + return 438; + case AV_CODEC_ID_GREMLIN_DPCM: + return 439; + case AV_CODEC_ID_DOLBY_E: + return 440; + case AV_CODEC_ID_APTX: + return 441; + case AV_CODEC_ID_APTX_HD: + return 442; + case AV_CODEC_ID_SBC: + return 443; + case AV_CODEC_ID_AVS2: + return 444; + case AV_CODEC_ID_IMM4: + return 445; + case AV_CODEC_ID_PROSUMER: + return 446; + case AV_CODEC_ID_MWSC: + return 447; + case AV_CODEC_ID_WCMV: + return 448; + case AV_CODEC_ID_RASC: + return 449; + case AV_CODEC_ID_PCM_VIDC: + return 450; + case AV_CODEC_ID_ATRAC9: + return 451; + case AV_CODEC_ID_TTML: + return 452; + case AV_CODEC_ID_HYMT: + return 453; + case AV_CODEC_ID_ARBC: + return 454; + case AV_CODEC_ID_AGM: + return 455; + case AV_CODEC_ID_LSCR: + return 456; + case AV_CODEC_ID_VP4: + return 457; + case AV_CODEC_ID_ADPCM_AGM: + return 458; + case AV_CODEC_ID_HCOM: + return 459; + case AV_CODEC_ID_ARIB_CAPTION: + return 460; + case AV_CODEC_ID_IMM5: + return 461; + case AV_CODEC_ID_MVDV: + return 462; + case AV_CODEC_ID_MVHA: + return 463; + case AV_CODEC_ID_CDTOONS: + return 464; + case AV_CODEC_ID_MV30: + return 465; + case AV_CODEC_ID_NOTCHLC: + return 466; + case AV_CODEC_ID_PFM: + return 467; + case AV_CODEC_ID_ARGO: + return 468; + case AV_CODEC_ID_ADPCM_IMA_SSI: + return 469; + case AV_CODEC_ID_ADPCM_ZORK: + return 470; + case AV_CODEC_ID_ADPCM_IMA_APM: + return 471; + case AV_CODEC_ID_ADPCM_IMA_ALP: + return 472; + case AV_CODEC_ID_ADPCM_IMA_MTF: + return 473; + case AV_CODEC_ID_ADPCM_IMA_CUNNING: + return 474; + case AV_CODEC_ID_DERF_DPCM: + return 475; + case AV_CODEC_ID_ACELP_KELVIN: + return 476; + case AV_CODEC_ID_MPEGH_3D_AUDIO: + return 477; + case AV_CODEC_ID_SIREN: + return 478; + case AV_CODEC_ID_HCA: + return 479; + case AV_CODEC_ID_EPG: + return 480; + case AV_CODEC_ID_AVS3: + return 481; + case AV_CODEC_ID_PGX: + return 482; + case AV_CODEC_ID_MSP2: + return 483; + case AV_CODEC_ID_VVC: + return 484; + case AV_CODEC_ID_MOBICLIP: + return 485; + case AV_CODEC_ID_PHOTOCD: + return 486; + case AV_CODEC_ID_ADPCM_ARGO: + return 487; + case AV_CODEC_ID_CRI: + return 488; + case AV_CODEC_ID_IPU: + return 489; + case AV_CODEC_ID_SIMBIOSIS_IMX: + return 490; + case AV_CODEC_ID_SGA_VIDEO: + return 491; + case AV_CODEC_ID_PCM_SGA: + return 492; + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: + return 493; + case AV_CODEC_ID_FASTAUDIO: + return 494; + case AV_CODEC_ID_GEM: + return 495; + case AV_CODEC_ID_ADPCM_IMA_ACORN: + return 496; + case AV_CODEC_ID_MSNSIREN: + return 497; + case AV_CODEC_ID_VBN: + return 498; + case AV_CODEC_ID_JPEGXL: + return 499; + case AV_CODEC_ID_QOI: + return 500; + case AV_CODEC_ID_PHM: + return 501; + case AV_CODEC_ID_DFPWM: + return 502; + case AV_CODEC_ID_RADIANCE_HDR: + return 503; + case AV_CODEC_ID_WBMP: + return 504; + case AV_CODEC_ID_MEDIA100: + return 505; + case AV_CODEC_ID_VQC: + return 506; + case AV_CODEC_ID_ADPCM_XMD: + return 507; + case AV_CODEC_ID_WADY_DPCM: + return 508; + case AV_CODEC_ID_CBD2_DPCM: + return 509; + case AV_CODEC_ID_BONK: + return 510; + case AV_CODEC_ID_MISC4: + return 511; + case AV_CODEC_ID_APAC: + return 512; + case AV_CODEC_ID_FTR: + return 513; + case AV_CODEC_ID_WAVARC: + return 514; + case AV_CODEC_ID_RKA: + return 515; + case AV_CODEC_ID_VNULL: + return 516; + case AV_CODEC_ID_ANULL: + return 517; + // case AV_CODEC_ID_MPEG2VIDEO_XVMC: + // return 518; + default: + return 0; + } + } +}; + +class PixFmt { + +public: + static uint32_t fromAVPixFmt(AVPixelFormat AvPixelFormat) { + switch (AvPixelFormat) { + case AV_PIX_FMT_NONE: + return 0; + case AV_PIX_FMT_YUV420P: + return 1; + case AV_PIX_FMT_YUYV422: + return 2; + case AV_PIX_FMT_RGB24: + return 3; + case AV_PIX_FMT_BGR24: + return 4; + case AV_PIX_FMT_YUV422P: + return 5; + case AV_PIX_FMT_YUV444P: + return 7; + case AV_PIX_FMT_YUV410P: + return 8; + case AV_PIX_FMT_YUV411P: + return 9; + case AV_PIX_FMT_GRAY8: + return 10; + case AV_PIX_FMT_MONOWHITE: + return 11; + case AV_PIX_FMT_MONOBLACK: + return 12; + case AV_PIX_FMT_PAL8: + return 13; + case AV_PIX_FMT_YUVJ420P: + return 14; + case AV_PIX_FMT_YUVJ422P: + return 15; + case AV_PIX_FMT_YUVJ444P: + return 16; + // case AV_PIX_FMT_XVMC_MPEG2_MC : // Lower FFmpeg Version + // return 17; + // case AV_PIX_FMT_XVMC_MPEG2_IDCT : + // return 18; + case AV_PIX_FMT_UYVY422: + return 19; + case AV_PIX_FMT_UYYVYY411: + return 20; + case AV_PIX_FMT_BGR8: + return 21; + case AV_PIX_FMT_BGR4: + return 22; + case AV_PIX_FMT_BGR4_BYTE: + return 23; + case AV_PIX_FMT_RGB8: + return 24; + case AV_PIX_FMT_RGB4: + return 25; + case AV_PIX_FMT_RGB4_BYTE: + return 26; + case AV_PIX_FMT_NV12: + return 27; + case AV_PIX_FMT_NV21: + return 28; + case AV_PIX_FMT_ARGB: // Big Endian + return 29; + case AV_PIX_FMT_RGBA: // Big + return 30; + case AV_PIX_FMT_ABGR: // Big + return 31; + case AV_PIX_FMT_BGRA: // little + return 32; + case AV_PIX_FMT_GRAY16BE: // big + return 33; + case AV_PIX_FMT_GRAY16LE: + return 34; + case AV_PIX_FMT_YUV440P: + return 35; + case AV_PIX_FMT_YUVJ440P: + return 36; + case AV_PIX_FMT_YUVA420P: + return 37; + // case AV_PIX_FMT_VDPAU_H264 : + // return 38; + // case AV_PIX_FMT_VDPAU_MPEG1 : + // return 39; + // case AV_PIX_FMT_VDPAU_MPEG2 : + // return 40; + // case AV_PIX_FMT_VDPAU_WMV3 : // Conditional compile. + // return 41; + // case AV_PIX_FMT_VDPAU_VC1 : // ff_api_vdpau is present + // return 42; + case AV_PIX_FMT_RGB48BE: + return 43; + case AV_PIX_FMT_RGB48LE: + return 44; + case AV_PIX_FMT_RGB565BE: + return 45; + case AV_PIX_FMT_RGB565LE: + return 46; + case AV_PIX_FMT_RGB555BE: + return 47; + case AV_PIX_FMT_RGB555LE: + return 48; + case AV_PIX_FMT_BGR565BE: + return 49; + case AV_PIX_FMT_BGR565LE: + return 50; + case AV_PIX_FMT_BGR555BE: + return 51; + case AV_PIX_FMT_BGR555LE: + return 52; + // case AV_PIX_FMT_VAAPI_MOCO : + // return 53; + // case AV_PIX_FMT_VAAPI_IDCT : + // return 54; + // case AV_PIX_FMT_VAAPI_VLD : + // return 55; + // case AV_PIX_FMT_VAAPI : // ff_api_vdpau is present + // return 56; + case AV_PIX_FMT_YUV420P16LE: + return 57; + case AV_PIX_FMT_YUV420P16BE: + return 58; + case AV_PIX_FMT_YUV422P16LE: + return 59; + case AV_PIX_FMT_YUV422P16BE: + return 60; + case AV_PIX_FMT_YUV444P16LE: + return 61; + case AV_PIX_FMT_YUV444P16BE: + return 62; + // case AV_PIX_FMT_VDPAU_MPEG4 : // ff_api_vdpau is present + // return 63; + case AV_PIX_FMT_DXVA2_VLD: + return 64; + case AV_PIX_FMT_RGB444LE: + return 65; + case AV_PIX_FMT_RGB444BE: + return 66; + case AV_PIX_FMT_BGR444LE: + return 67; + case AV_PIX_FMT_BGR444BE: + return 68; + case AV_PIX_FMT_YA8: + return 69; + case AV_PIX_FMT_BGR48BE: + return 70; + case AV_PIX_FMT_BGR48LE: + return 71; + case AV_PIX_FMT_YUV420P9BE: + return 72; + case AV_PIX_FMT_YUV420P9LE: + return 73; + case AV_PIX_FMT_YUV420P10BE: + return 74; + case AV_PIX_FMT_YUV420P10LE: + return 75; + case AV_PIX_FMT_YUV422P10BE: + return 76; + case AV_PIX_FMT_YUV422P10LE: + return 77; + case AV_PIX_FMT_YUV444P9BE: + return 78; + case AV_PIX_FMT_YUV444P9LE: + return 79; + case AV_PIX_FMT_YUV444P10BE: + return 80; + case AV_PIX_FMT_YUV444P10LE: + return 81; + case AV_PIX_FMT_YUV422P9BE: + return 82; + case AV_PIX_FMT_YUV422P9LE: + return 83; + // case AV_PIX_FMT_VDA_VLD : // Lower than ffmpeg version 4 + // return 84; + case AV_PIX_FMT_GBRP: + return 85; + case AV_PIX_FMT_GBRP9BE: + return 86; + case AV_PIX_FMT_GBRP9LE: + return 87; + case AV_PIX_FMT_GBRP10BE: + return 88; + case AV_PIX_FMT_GBRP10LE: + return 89; + case AV_PIX_FMT_GBRP16BE: + return 90; + case AV_PIX_FMT_GBRP16LE: + return 91; + case AV_PIX_FMT_YUVA420P9BE: + return 92; + case AV_PIX_FMT_YUVA420P9LE: + return 93; + case AV_PIX_FMT_YUVA422P9BE: + return 94; + case AV_PIX_FMT_YUVA422P9LE: + return 95; + case AV_PIX_FMT_YUVA444P9BE: + return 96; + case AV_PIX_FMT_YUVA444P9LE: + return 97; + case AV_PIX_FMT_YUVA420P10BE: + return 98; + case AV_PIX_FMT_YUVA420P10LE: + return 99; + case AV_PIX_FMT_YUVA422P10BE: + return 100; + case AV_PIX_FMT_YUVA422P10LE: + return 101; + case AV_PIX_FMT_YUVA444P10BE: + return 102; + case AV_PIX_FMT_YUVA444P10LE: + return 103; + case AV_PIX_FMT_YUVA420P16BE: + return 104; + case AV_PIX_FMT_YUVA420P16LE: + return 105; + case AV_PIX_FMT_YUVA422P16BE: + return 106; + case AV_PIX_FMT_YUVA422P16LE: + return 107; + case AV_PIX_FMT_YUVA444P16BE: + return 108; + case AV_PIX_FMT_YUVA444P16LE: + return 109; + case AV_PIX_FMT_VDPAU: + return 110; + case AV_PIX_FMT_XYZ12LE: + return 111; + case AV_PIX_FMT_XYZ12BE: + return 112; + case AV_PIX_FMT_NV16: + return 113; + case AV_PIX_FMT_NV20LE: + return 114; + case AV_PIX_FMT_NV20BE: + return 115; + case AV_PIX_FMT_RGBA64BE: + return 116; + case AV_PIX_FMT_RGBA64LE: + return 117; + case AV_PIX_FMT_BGRA64BE: + return 118; + case AV_PIX_FMT_BGRA64LE: + return 119; + case AV_PIX_FMT_YVYU422: + return 120; + // case AV_PIX_FMT_VDA : // Lower than ffmpeg version 4. + // return 121; + case AV_PIX_FMT_YA16BE: // big + return 122; + case AV_PIX_FMT_YA16LE: + return 123; + case AV_PIX_FMT_QSV: + return 124; + case AV_PIX_FMT_MMAL: + return 125; + case AV_PIX_FMT_D3D11VA_VLD: + return 126; + case AV_PIX_FMT_CUDA: + return 127; + case AV_PIX_FMT_0RGB: // big + return 128; + case AV_PIX_FMT_RGB0: + return 129; + case AV_PIX_FMT_0BGR: // big + return 130; + case AV_PIX_FMT_BGR0: + return 131; + case AV_PIX_FMT_YUVA444P: + return 132; + case AV_PIX_FMT_YUVA422P: + return 133; + case AV_PIX_FMT_YUV420P12BE: + return 134; + case AV_PIX_FMT_YUV420P12LE: + return 135; + case AV_PIX_FMT_YUV420P14BE: + return 136; + case AV_PIX_FMT_YUV420P14LE: + return 137; + case AV_PIX_FMT_YUV422P12BE: + return 138; + case AV_PIX_FMT_YUV422P12LE: + return 139; + case AV_PIX_FMT_YUV422P14BE: + return 140; + case AV_PIX_FMT_YUV422P14LE: + return 141; + case AV_PIX_FMT_YUV444P12BE: + return 142; + case AV_PIX_FMT_YUV444P12LE: + return 143; + case AV_PIX_FMT_YUV444P14BE: + return 144; + case AV_PIX_FMT_YUV444P14LE: + return 146; + case AV_PIX_FMT_GBRP12BE: + return 147; + case AV_PIX_FMT_GBRP12LE: + return 148; + case AV_PIX_FMT_GBRP14BE: + return 149; + case AV_PIX_FMT_GBRP14LE: + return 150; + case AV_PIX_FMT_GBRAP: + return 151; + case AV_PIX_FMT_GBRAP16BE: + return 152; + case AV_PIX_FMT_GBRAP16LE: + return 153; + case AV_PIX_FMT_YUVJ411P: + return 154; + case AV_PIX_FMT_BAYER_BGGR8: + return 155; + case AV_PIX_FMT_BAYER_RGGB8: + return 156; + case AV_PIX_FMT_BAYER_GBRG8: + return 157; + case AV_PIX_FMT_BAYER_GRBG8: + return 158; + case AV_PIX_FMT_BAYER_BGGR16LE: + return 159; + case AV_PIX_FMT_BAYER_BGGR16BE: + return 160; + case AV_PIX_FMT_BAYER_RGGB16LE: + return 161; + case AV_PIX_FMT_BAYER_RGGB16BE: + return 162; + case AV_PIX_FMT_BAYER_GBRG16LE: + return 163; + case AV_PIX_FMT_BAYER_GBRG16BE: + return 164; + case AV_PIX_FMT_BAYER_GRBG16LE: + return 165; + case AV_PIX_FMT_BAYER_GRBG16BE: + return 166; + case AV_PIX_FMT_YUV440P10LE: + return 167; + case AV_PIX_FMT_YUV440P10BE: + return 168; + case AV_PIX_FMT_YUV440P12LE: + return 169; + case AV_PIX_FMT_YUV440P12BE: + return 170; + case AV_PIX_FMT_AYUV64LE: + return 171; + case AV_PIX_FMT_AYUV64BE: + return 172; + case AV_PIX_FMT_VIDEOTOOLBOX: + return 173; + case AV_PIX_FMT_XVMC: + return 174; + // case AV_PIX_FMT_RGB32: // IF format is this type, based on + // endianness, it resolves to big endian or small endian. + // return 175; // The Switch case contains both big and + // small endian, so No need to add these in switch case. + // case AV_PIX_FMT_RGB32_1: // Will Automatically resolve. + // return 176; + // case AV_PIX_FMT_BGR32: + // return 177; + // case AV_PIX_FMT_BGR32_1: + // return 178; + // case AV_PIX_FMT_0RGB32: + // return 179; + // case AV_PIX_FMT_0BGR32: + // return 180; + // case AV_PIX_FMT_GRAY16: + // return 181; + // case AV_PIX_FMT_YA16: + // return 182; + // case AV_PIX_FMT_RGB48: + // return 183; + // case AV_PIX_FMT_RGB565: + // return 184; + // case AV_PIX_FMT_RGB444: + // return 185; + // case AV_PIX_FMT_BGR48: + // return 186; + // case AV_PIX_FMT_BGR565: + // return 187; + // case AV_PIX_FMT_BGR555: + // return 188; + // case AV_PIX_FMT_BGR444: + // return 189; + // case AV_PIX_FMT_YUV420P9: + // return 190; + // case AV_PIX_FMT_YUV422P9: + // return 191; + // case AV_PIX_FMT_YUV444P9: + // return 192; + // case AV_PIX_FMT_YUV420P10: + // return 193; + // case AV_PIX_FMT_YUV422P10: + // return 194; + // case AV_PIX_FMT_YUV440P10: + // return 195; + // case AV_PIX_FMT_YUV444P10: + // return 196; + // case AV_PIX_FMT_YUV420P12: + // return 197; + // case AV_PIX_FMT_YUV422P12: + // return 198; + // case AV_PIX_FMT_YUV440P12: + // return 199; + // case AV_PIX_FMT_YUV444P12: + // return 200; + // case AV_PIX_FMT_YUV420P14: + // return 201; + // case AV_PIX_FMT_YUV422P14: + // return 202; + // case AV_PIX_FMT_YUV444P14: + // return 203; + // case AV_PIX_FMT_YUV420P16: + // return 204; + // case AV_PIX_FMT_YUV422P16: + // return 205; + // case AV_PIX_FMT_YUV444P16: + // return 206; + // case AV_PIX_FMT_GBRP9: + // return 207; + // case AV_PIX_FMT_GBRP10: + // return 208; + // case AV_PIX_FMT_GBRP12: + // return 209; + // case AV_PIX_FMT_GBRP14: + // return 210; + // case AV_PIX_FMT_GBRP16: + // return 211; + // case AV_PIX_FMT_GBRAP16: + // return 212; + // case AV_PIX_FMT_BAYER_BGGR16: + // return 213; + // case AV_PIX_FMT_BAYER_RGGB16: + // return 214; + // case AV_PIX_FMT_BAYER_GBRG16: + // return 215; + // case AV_PIX_FMT_BAYER_GRBG16: + // return 216; + // case AV_PIX_FMT_YUVA420P9: + // return 217; + // case AV_PIX_FMT_YUVA422P9: + // return 218; + // case AV_PIX_FMT_YUVA444P9: + // return 219; + // case AV_PIX_FMT_YUVA420P10: + // return 220; + // case AV_PIX_FMT_YUVA422P10: + // return 221; + // case AV_PIX_FMT_YUVA444P10: + // return 222; + // case AV_PIX_FMT_YUVA420P16: + // return 223; + // case AV_PIX_FMT_YUVA422P16: + // return 224; + // case AV_PIX_FMT_YUVA444P16: + // return 225; + // case AV_PIX_FMT_XYZ12: + // return 226; + // case AV_PIX_FMT_NV20: + // return 227; + // case AV_PIX_FMT_AYUV64: + // return 228; + case AV_PIX_FMT_P010LE: + return 229; + case AV_PIX_FMT_P010BE: + return 230; + case AV_PIX_FMT_GBRAP12BE: + return 231; + case AV_PIX_FMT_GBRAP12LE: + return 232; + case AV_PIX_FMT_GBRAP10LE: + return 233; + case AV_PIX_FMT_GBRAP10BE: + return 234; + case AV_PIX_FMT_MEDIACODEC: + return 235; + case AV_PIX_FMT_GRAY12BE: + return 236; + case AV_PIX_FMT_GRAY12LE: + return 237; + case AV_PIX_FMT_GRAY10BE: + return 238; + case AV_PIX_FMT_GRAY10LE: + return 239; + case AV_PIX_FMT_P016LE: + return 240; + case AV_PIX_FMT_P016BE: + return 241; + case AV_PIX_FMT_D3D11: + return 242; + case AV_PIX_FMT_GRAY9BE: + return 243; + case AV_PIX_FMT_GRAY9LE: + return 244; + case AV_PIX_FMT_GBRPF32BE: + return 245; + case AV_PIX_FMT_GBRPF32LE: + return 246; + case AV_PIX_FMT_GBRAPF32BE: + return 247; + case AV_PIX_FMT_GBRAPF32LE: + return 248; + case AV_PIX_FMT_DRM_PRIME: + return 249; + // Above ffmpeg 4.0 Need to add versions. + case AV_PIX_FMT_OPENCL: + return 250; + case AV_PIX_FMT_GRAY14BE: + return 251; + case AV_PIX_FMT_GRAY14LE: + return 252; + case AV_PIX_FMT_GRAYF32BE: + return 253; + case AV_PIX_FMT_GRAYF32LE: + return 254; + case AV_PIX_FMT_YUVA422P12BE: + return 255; + case AV_PIX_FMT_YUVA422P12LE: + return 256; + case AV_PIX_FMT_YUVA444P12BE: + return 257; + case AV_PIX_FMT_YUVA444P12LE: + return 258; + case AV_PIX_FMT_NV24: + return 259; + case AV_PIX_FMT_NV42: + return 260; + case AV_PIX_FMT_VULKAN: + return 261; + case AV_PIX_FMT_Y210BE: + return 262; + case AV_PIX_FMT_Y210LE: + return 263; + case AV_PIX_FMT_X2RGB10LE: + return 264; + case AV_PIX_FMT_X2RGB10BE: + return 265; + case AV_PIX_FMT_X2BGR10LE: + return 266; + case AV_PIX_FMT_X2BGR10BE: + return 267; + case AV_PIX_FMT_P210BE: + return 268; + case AV_PIX_FMT_P210LE: + return 269; + case AV_PIX_FMT_P410BE: + return 270; + case AV_PIX_FMT_P410LE: + return 271; + case AV_PIX_FMT_P216BE: + return 272; + case AV_PIX_FMT_P216LE: + return 273; + case AV_PIX_FMT_P416BE: + return 274; + case AV_PIX_FMT_P416LE: + return 275; + case AV_PIX_FMT_VUYA: + return 276; + case AV_PIX_FMT_RGBAF16BE: + return 277; + case AV_PIX_FMT_RGBAF16LE: + return 278; + case AV_PIX_FMT_VUYX: + return 279; + case AV_PIX_FMT_P012LE: + return 280; + case AV_PIX_FMT_P012BE: + return 281; + case AV_PIX_FMT_Y212BE: + return 282; + case AV_PIX_FMT_Y212LE: + return 283; + case AV_PIX_FMT_XV30BE: + return 284; + case AV_PIX_FMT_XV30LE: + return 285; + case AV_PIX_FMT_XV36BE: + return 286; + case AV_PIX_FMT_XV36LE: + return 287; + case AV_PIX_FMT_RGBF32BE: + return 288; + case AV_PIX_FMT_RGBF32LE: + return 289; + case AV_PIX_FMT_RGBAF32BE: + return 290; + case AV_PIX_FMT_RGBAF32LE: + return 291; + // case AV_PIX_FMT_RPI : + // return 292; + // case AV_PIX_FMT_SAND128 : + // return 293; + // case AV_PIX_FMT_SAND64_10 : + // return 294; + // case AV_PIX_FMT_SAND64_16 : + // return 295; + // case AV_PIX_FMT_RPI4_8 : // rpi turn on then only + // return 296; + // case AV_PIX_FMT_RPI4_10 : + // return 297; + // case AV_PIX_FMT_RGB555: // Little Endian, Big Endian WIll + // Resolve on it's own. + // return 298; + default: + return 0; + } + } + + static AVPixelFormat intoAVPixFmt(uint32_t AvPixFmtId) { + switch (AvPixFmtId) { + case 0: + return AV_PIX_FMT_NONE; + case 1: + return AV_PIX_FMT_YUV420P; + case 2: + return AV_PIX_FMT_YUYV422; + case 3: + return AV_PIX_FMT_RGB24; + case 4: + return AV_PIX_FMT_BGR24; + case 5: + return AV_PIX_FMT_YUV422P; + case 7: + return AV_PIX_FMT_YUV444P; + case 8: + return AV_PIX_FMT_YUV410P; + case 9: + return AV_PIX_FMT_YUV411P; + case 10: + return AV_PIX_FMT_GRAY8; + case 11: + return AV_PIX_FMT_MONOWHITE; + case 12: + return AV_PIX_FMT_MONOBLACK; + case 13: + return AV_PIX_FMT_PAL8; + case 14: + return AV_PIX_FMT_YUVJ420P; + case 15: + return AV_PIX_FMT_YUVJ422P; + case 16: + return AV_PIX_FMT_YUVJ444P; + // case 17: + // return AV_PIX_FMT_XVMC_MPEG2_MC ; // Lower FFmpeg Version + // case 18: + // return AV_PIX_FMT_XVMC_MPEG2_IDCT ; + case 19: + return AV_PIX_FMT_UYVY422; + case 20: + return AV_PIX_FMT_UYYVYY411; + case 21: + return AV_PIX_FMT_BGR8; + case 22: + return AV_PIX_FMT_BGR4; + case 23: + return AV_PIX_FMT_BGR4_BYTE; + case 24: + return AV_PIX_FMT_RGB8; + case 25: + return AV_PIX_FMT_RGB4; + case 26: + return AV_PIX_FMT_RGB4_BYTE; + case 27: + return AV_PIX_FMT_NV12; + case 28: + return AV_PIX_FMT_NV21; + case 29: + return AV_PIX_FMT_ARGB; + case 30: + return AV_PIX_FMT_RGBA; + case 31: + return AV_PIX_FMT_ABGR; + case 32: + return AV_PIX_FMT_BGRA; // Little + case 33: + return AV_PIX_FMT_GRAY16BE; + case 34: + return AV_PIX_FMT_GRAY16LE; + case 35: + return AV_PIX_FMT_YUV440P; + case 36: + return AV_PIX_FMT_YUVJ440P; + case 37: + return AV_PIX_FMT_YUVA420P; + // case 38: + // return AV_PIX_FMT_VDPAU_H264 ; + // case 39: + // return AV_PIX_FMT_VDPAU_MPEG1 ; + // case 40: + // return AV_PIX_FMT_VDPAU_MPEG2 ; + // case 41: + // return AV_PIX_FMT_VDPAU_WMV3 ; // Conditional compile. + // case 42: + // return AV_PIX_FMT_VDPAU_VC1 ; // ff_api_vdpau is present + case 43: + return AV_PIX_FMT_RGB48BE; + case 44: + return AV_PIX_FMT_RGB48LE; + case 45: + return AV_PIX_FMT_RGB565BE; + case 46: + return AV_PIX_FMT_RGB565LE; + case 47: + return AV_PIX_FMT_RGB555BE; + case 48: + return AV_PIX_FMT_RGB555LE; + case 49: + return AV_PIX_FMT_BGR565BE; + case 50: + return AV_PIX_FMT_BGR565LE; + case 51: + return AV_PIX_FMT_BGR555BE; + case 52: + return AV_PIX_FMT_BGR555LE; + // case 53: + // return AV_PIX_FMT_VAAPI_MOCO ; + // case 54: + // return AV_PIX_FMT_VAAPI_IDCT ; + // case 55: + // return AV_PIX_FMT_VAAPI_VLD ; + // case 56: + // return AV_PIX_FMT_VAAPI ; // ff_api_vdpau is present + case 57: + return AV_PIX_FMT_YUV420P16LE; + case 58: + return AV_PIX_FMT_YUV420P16BE; + case 59: + return AV_PIX_FMT_YUV422P16LE; + case 60: + return AV_PIX_FMT_YUV422P16BE; + case 61: + return AV_PIX_FMT_YUV444P16LE; + case 62: + return AV_PIX_FMT_YUV444P16BE; + // case 63: + // return AV_PIX_FMT_VDPAU_MPEG4 ; // ff_api_vdpau is present + case 64: + return AV_PIX_FMT_DXVA2_VLD; + case 65: + return AV_PIX_FMT_RGB444LE; + case 66: + return AV_PIX_FMT_RGB444BE; + case 67: + return AV_PIX_FMT_BGR444LE; + case 68: + return AV_PIX_FMT_BGR444BE; + case 69: + return AV_PIX_FMT_YA8; + case 70: + return AV_PIX_FMT_BGR48BE; + case 71: + return AV_PIX_FMT_BGR48LE; + case 72: + return AV_PIX_FMT_YUV420P9BE; + case 73: + return AV_PIX_FMT_YUV420P9LE; + case 74: + return AV_PIX_FMT_YUV420P10BE; + case 75: + return AV_PIX_FMT_YUV420P10LE; + case 76: + return AV_PIX_FMT_YUV422P10BE; + case 77: + return AV_PIX_FMT_YUV422P10LE; + case 78: + return AV_PIX_FMT_YUV444P9BE; + case 79: + return AV_PIX_FMT_YUV444P9LE; + case 80: + return AV_PIX_FMT_YUV444P10BE; + case 81: + return AV_PIX_FMT_YUV444P10LE; + case 82: + return AV_PIX_FMT_YUV422P9BE; + case 83: + return AV_PIX_FMT_YUV422P9LE; + // case 84: + // return AV_PIX_FMT_VDA_VLD ; // Lower than ffmpeg version 4 + case 85: + return AV_PIX_FMT_GBRP; + case 86: + return AV_PIX_FMT_GBRP9BE; + case 87: + return AV_PIX_FMT_GBRP9LE; + case 88: + return AV_PIX_FMT_GBRP10BE; + case 89: + return AV_PIX_FMT_GBRP10LE; + case 90: + return AV_PIX_FMT_GBRP16BE; + case 91: + return AV_PIX_FMT_GBRP16LE; + case 92: + return AV_PIX_FMT_YUVA420P9BE; + case 93: + return AV_PIX_FMT_YUVA420P9LE; + case 94: + return AV_PIX_FMT_YUVA422P9BE; + case 95: + return AV_PIX_FMT_YUVA422P9LE; + case 96: + return AV_PIX_FMT_YUVA444P9BE; + case 97: + return AV_PIX_FMT_YUVA444P9LE; + case 98: + return AV_PIX_FMT_YUVA420P10BE; + case 99: + return AV_PIX_FMT_YUVA420P10LE; + case 100: + return AV_PIX_FMT_YUVA422P10BE; + case 101: + return AV_PIX_FMT_YUVA422P10LE; + case 102: + return AV_PIX_FMT_YUVA444P10BE; + case 103: + return AV_PIX_FMT_YUVA444P10LE; + case 104: + return AV_PIX_FMT_YUVA420P16BE; + case 105: + return AV_PIX_FMT_YUVA420P16LE; + case 106: + return AV_PIX_FMT_YUVA422P16BE; + case 107: + return AV_PIX_FMT_YUVA422P16LE; + case 108: + return AV_PIX_FMT_YUVA444P16BE; + case 109: + return AV_PIX_FMT_YUVA444P16LE; + case 110: + return AV_PIX_FMT_VDPAU; + case 111: + return AV_PIX_FMT_XYZ12LE; + case 112: + return AV_PIX_FMT_XYZ12BE; + case 113: + return AV_PIX_FMT_NV16; + case 114: + return AV_PIX_FMT_NV20LE; + case 115: + return AV_PIX_FMT_NV20BE; + case 116: + return AV_PIX_FMT_RGBA64BE; + case 117: + return AV_PIX_FMT_RGBA64LE; + case 118: + return AV_PIX_FMT_BGRA64BE; + case 119: + return AV_PIX_FMT_BGRA64LE; + case 120: + return AV_PIX_FMT_YVYU422; + // case 121: + // return AV_PIX_FMT_VDA ; // Lower than ffmpeg version 4. + case 122: + return AV_PIX_FMT_YA16BE; + case 123: + return AV_PIX_FMT_YA16LE; + case 124: + return AV_PIX_FMT_QSV; + case 125: + return AV_PIX_FMT_MMAL; + case 126: + return AV_PIX_FMT_D3D11VA_VLD; + case 127: + return AV_PIX_FMT_CUDA; + case 128: + return AV_PIX_FMT_0RGB; + case 129: + return AV_PIX_FMT_RGB0; + case 130: + return AV_PIX_FMT_0BGR; + case 131: + return AV_PIX_FMT_BGR0; + case 132: + return AV_PIX_FMT_YUVA444P; + case 133: + return AV_PIX_FMT_YUVA422P; + case 134: + return AV_PIX_FMT_YUV420P12BE; + case 135: + return AV_PIX_FMT_YUV420P12LE; + case 136: + return AV_PIX_FMT_YUV420P14BE; + case 137: + return AV_PIX_FMT_YUV420P14LE; + case 138: + return AV_PIX_FMT_YUV422P12BE; + case 139: + return AV_PIX_FMT_YUV422P12LE; + case 140: + return AV_PIX_FMT_YUV422P14BE; + case 141: + return AV_PIX_FMT_YUV422P14LE; + case 142: + return AV_PIX_FMT_YUV444P12BE; + case 143: + return AV_PIX_FMT_YUV444P12LE; + case 144: + return AV_PIX_FMT_YUV444P14BE; + case 146: + return AV_PIX_FMT_YUV444P14LE; + case 147: + return AV_PIX_FMT_GBRP12BE; + case 148: + return AV_PIX_FMT_GBRP12LE; + case 149: + return AV_PIX_FMT_GBRP14BE; + case 150: + return AV_PIX_FMT_GBRP14LE; + case 151: + return AV_PIX_FMT_GBRAP; + case 152: + return AV_PIX_FMT_GBRAP16BE; + case 153: + return AV_PIX_FMT_GBRAP16LE; + case 154: + return AV_PIX_FMT_YUVJ411P; + case 155: + return AV_PIX_FMT_BAYER_BGGR8; + case 156: + return AV_PIX_FMT_BAYER_RGGB8; + case 157: + return AV_PIX_FMT_BAYER_GBRG8; + case 158: + return AV_PIX_FMT_BAYER_GRBG8; + case 159: + return AV_PIX_FMT_BAYER_BGGR16LE; + case 160: + return AV_PIX_FMT_BAYER_BGGR16BE; + case 161: + return AV_PIX_FMT_BAYER_RGGB16LE; + case 162: + return AV_PIX_FMT_BAYER_RGGB16BE; + case 163: + return AV_PIX_FMT_BAYER_GBRG16LE; + case 164: + return AV_PIX_FMT_BAYER_GBRG16BE; + case 165: + return AV_PIX_FMT_BAYER_GRBG16LE; + case 166: + return AV_PIX_FMT_BAYER_GRBG16BE; + case 167: + return AV_PIX_FMT_YUV440P10LE; + case 168: + return AV_PIX_FMT_YUV440P10BE; + case 169: + return AV_PIX_FMT_YUV440P12LE; + case 170: + return AV_PIX_FMT_YUV440P12BE; + case 171: + return AV_PIX_FMT_AYUV64LE; + case 172: + return AV_PIX_FMT_AYUV64BE; + case 173: + return AV_PIX_FMT_VIDEOTOOLBOX; + case 174: + return AV_PIX_FMT_XVMC; + case 175: + return AV_PIX_FMT_RGB32; + case 176: + return AV_PIX_FMT_RGB32_1; + case 177: + return AV_PIX_FMT_BGR32; + case 178: + return AV_PIX_FMT_BGR32_1; + case 179: + return AV_PIX_FMT_0RGB32; + case 180: + return AV_PIX_FMT_0BGR32; + case 181: + return AV_PIX_FMT_GRAY16; + case 182: + return AV_PIX_FMT_YA16; + case 183: + return AV_PIX_FMT_RGB48; + case 184: + return AV_PIX_FMT_RGB565; + case 185: + return AV_PIX_FMT_RGB444; + case 186: + return AV_PIX_FMT_BGR48; + case 187: + return AV_PIX_FMT_BGR565; + case 188: + return AV_PIX_FMT_BGR555; + case 189: + return AV_PIX_FMT_BGR444; + case 190: + return AV_PIX_FMT_YUV420P9; + case 191: + return AV_PIX_FMT_YUV422P9; + case 192: + return AV_PIX_FMT_YUV444P9; + case 193: + return AV_PIX_FMT_YUV420P10; + case 194: + return AV_PIX_FMT_YUV422P10; + case 195: + return AV_PIX_FMT_YUV440P10; + case 196: + return AV_PIX_FMT_YUV444P10; + case 197: + return AV_PIX_FMT_YUV420P12; + case 198: + return AV_PIX_FMT_YUV422P12; + case 199: + return AV_PIX_FMT_YUV440P12; + case 200: + return AV_PIX_FMT_YUV444P12; + case 201: + return AV_PIX_FMT_YUV420P14; + case 202: + return AV_PIX_FMT_YUV422P14; + case 203: + return AV_PIX_FMT_YUV444P14; + case 204: + return AV_PIX_FMT_YUV420P16; + case 205: + return AV_PIX_FMT_YUV422P16; + case 206: + return AV_PIX_FMT_YUV444P16; + case 207: + return AV_PIX_FMT_GBRP9; + case 208: + return AV_PIX_FMT_GBRP10; + case 209: + return AV_PIX_FMT_GBRP12; + case 210: + return AV_PIX_FMT_GBRP14; + case 211: + return AV_PIX_FMT_GBRP16; + case 212: + return AV_PIX_FMT_GBRAP16; + case 213: + return AV_PIX_FMT_BAYER_BGGR16; + case 214: + return AV_PIX_FMT_BAYER_RGGB16; + case 215: + return AV_PIX_FMT_BAYER_GBRG16; + case 216: + return AV_PIX_FMT_BAYER_GRBG16; + case 217: + return AV_PIX_FMT_YUVA420P9; + case 218: + return AV_PIX_FMT_YUVA422P9; + case 219: + return AV_PIX_FMT_YUVA444P9; + case 220: + return AV_PIX_FMT_YUVA420P10; + case 221: + return AV_PIX_FMT_YUVA422P10; + case 222: + return AV_PIX_FMT_YUVA444P10; + case 223: + return AV_PIX_FMT_YUVA420P16; + case 224: + return AV_PIX_FMT_YUVA422P16; + case 225: + return AV_PIX_FMT_YUVA444P16; + case 226: + return AV_PIX_FMT_XYZ12; + case 227: + return AV_PIX_FMT_NV20; + case 228: + return AV_PIX_FMT_AYUV64; + case 229: + return AV_PIX_FMT_P010LE; + case 230: + return AV_PIX_FMT_P010BE; + case 231: + return AV_PIX_FMT_GBRAP12BE; + case 232: + return AV_PIX_FMT_GBRAP12LE; + case 233: + return AV_PIX_FMT_GBRAP10LE; + case 234: + return AV_PIX_FMT_GBRAP10BE; + case 235: + return AV_PIX_FMT_MEDIACODEC; + case 236: + return AV_PIX_FMT_GRAY12BE; + case 237: + return AV_PIX_FMT_GRAY12LE; + case 238: + return AV_PIX_FMT_GRAY10BE; + case 239: + return AV_PIX_FMT_GRAY10LE; + case 240: + return AV_PIX_FMT_P016LE; + case 241: + return AV_PIX_FMT_P016BE; + case 242: + return AV_PIX_FMT_D3D11; + case 243: + return AV_PIX_FMT_GRAY9BE; + case 244: + return AV_PIX_FMT_GRAY9LE; + case 245: + return AV_PIX_FMT_GBRPF32BE; + case 246: + return AV_PIX_FMT_GBRPF32LE; + case 247: + return AV_PIX_FMT_GBRAPF32BE; + case 248: + return AV_PIX_FMT_GBRAPF32LE; + case 249: + return AV_PIX_FMT_DRM_PRIME; + + // Above ffmpeg 4.0 Need to add versions. + case 250: + return AV_PIX_FMT_OPENCL; + case 251: + return AV_PIX_FMT_GRAY14BE; + case 252: + return AV_PIX_FMT_GRAY14LE; + case 253: + return AV_PIX_FMT_GRAYF32BE; + case 254: + return AV_PIX_FMT_GRAYF32LE; + case 255: + return AV_PIX_FMT_YUVA422P12BE; + case 256: + return AV_PIX_FMT_YUVA422P12LE; + case 257: + return AV_PIX_FMT_YUVA444P12BE; + case 258: + return AV_PIX_FMT_YUVA444P12LE; + case 259: + return AV_PIX_FMT_NV24; + case 260: + return AV_PIX_FMT_NV42; + case 261: + return AV_PIX_FMT_VULKAN; + case 262: + return AV_PIX_FMT_Y210BE; + case 263: + return AV_PIX_FMT_Y210LE; + case 264: + return AV_PIX_FMT_X2RGB10LE; + case 265: + return AV_PIX_FMT_X2RGB10BE; + case 266: + return AV_PIX_FMT_X2BGR10LE; + case 267: + return AV_PIX_FMT_X2BGR10BE; + case 268: + return AV_PIX_FMT_P210BE; + case 269: + return AV_PIX_FMT_P210LE; + case 270: + return AV_PIX_FMT_P410BE; + case 271: + return AV_PIX_FMT_P410LE; + case 272: + return AV_PIX_FMT_P216BE; + case 273: + return AV_PIX_FMT_P216LE; + case 274: + return AV_PIX_FMT_P416BE; + case 275: + return AV_PIX_FMT_P416LE; + case 276: + return AV_PIX_FMT_VUYA; + case 277: + return AV_PIX_FMT_RGBAF16BE; + case 278: + return AV_PIX_FMT_RGBAF16LE; + case 279: + return AV_PIX_FMT_VUYX; + case 280: + return AV_PIX_FMT_P012LE; + case 281: + return AV_PIX_FMT_P012BE; + case 282: + return AV_PIX_FMT_Y212BE; + case 283: + return AV_PIX_FMT_Y212LE; + case 284: + return AV_PIX_FMT_XV30BE; + case 285: + return AV_PIX_FMT_XV30LE; + case 286: + return AV_PIX_FMT_XV36BE; + case 287: + return AV_PIX_FMT_XV36LE; + case 288: + return AV_PIX_FMT_RGBF32BE; + case 289: + return AV_PIX_FMT_RGBF32LE; + case 290: + return AV_PIX_FMT_RGBAF32BE; + case 291: + return AV_PIX_FMT_RGBAF32LE; + // case 292: + // return AV_PIX_FMT_RPI ; + // case 293: + // return AV_PIX_FMT_SAND128 ; + // case 294: + // return AV_PIX_FMT_SAND64_10 ; + // case 295: + // return AV_PIX_FMT_SAND64_16 ; + // case 296: + // return AV_PIX_FMT_RPI4_8 ; // rpi turn on then only + // case 297: + // return AV_PIX_FMT_RPI4_10 ; + case 298: + return AV_PIX_FMT_RGB555; + default: + return AV_PIX_FMT_NONE; + } + } +}; + +class SampleFmt { +public: + static AVSampleFormat fromSampleID(uint32_t SampleID) { + switch (SampleID) { + case 0: + return AV_SAMPLE_FMT_NONE; + case 1: + return AV_SAMPLE_FMT_U8; + case 2: + return AV_SAMPLE_FMT_S16; + case 3: + return AV_SAMPLE_FMT_S32; + case 4: + return AV_SAMPLE_FMT_FLT; + case 5: + return AV_SAMPLE_FMT_DBL; + case 6: + return AV_SAMPLE_FMT_U8P; + case 7: + return AV_SAMPLE_FMT_S16P; + case 8: + return AV_SAMPLE_FMT_S32P; + case 9: + return AV_SAMPLE_FMT_FLTP; + case 10: + return AV_SAMPLE_FMT_DBLP; + case 11: + return AV_SAMPLE_FMT_S64; + case 12: + return AV_SAMPLE_FMT_S64P; + case 13: + return AV_SAMPLE_FMT_NB; + default: + return AV_SAMPLE_FMT_NONE; + } + } + + static uint32_t toSampleID(AVSampleFormat AvSampleFormat) { + switch (AvSampleFormat) { + case AV_SAMPLE_FMT_NONE: + return 0; + case AV_SAMPLE_FMT_U8: + return 1; + case AV_SAMPLE_FMT_S16: + return 2; + case AV_SAMPLE_FMT_S32: + return 3; + case AV_SAMPLE_FMT_FLT: + return 4; + case AV_SAMPLE_FMT_DBL: + return 5; + case AV_SAMPLE_FMT_U8P: + return 6; + case AV_SAMPLE_FMT_S16P: + return 7; + case AV_SAMPLE_FMT_S32P: + return 8; + case AV_SAMPLE_FMT_FLTP: + return 9; + case AV_SAMPLE_FMT_DBLP: + return 10; + case AV_SAMPLE_FMT_S64: + return 11; + case AV_SAMPLE_FMT_S64P: + return 12; + case AV_SAMPLE_FMT_NB: + return 13; + default: + return 0; + } + } +}; + +// Could have avoided, but Did this to support older version of FFMPEG +// (V5,V4,V3) Version 6 FFmpeg uses AVChannelLayout Struct; +class ChannelLayout { +private: + const static uint64_t FRONT_LEFT = 1; + const static uint64_t FRONT_RIGHT = 1ULL << 1; + const static uint64_t FRONT_CENTER = 1ULL << 2; + const static uint64_t LOW_FREQUENCY = 1ULL << 3; + const static uint64_t BACK_LEFT = 1ULL << 4; + const static uint64_t BACK_RIGHT = 1ULL << 5; + const static uint64_t FRONT_LEFT_OF_CENTER = 1ULL << 6; + const static uint64_t FRONT_RIGHT_OF_CENTER = 1ULL << 7; + const static uint64_t BACK_CENTER = 1ULL << 8; + const static uint64_t SIDE_LEFT = 1ULL << 9; + const static uint64_t SIDE_RIGHT = 1ULL << 10; + const static uint64_t TOP_CENTER = 1ULL << 11; + const static uint64_t TOP_FRONT_LEFT = 1ULL << 12; + const static uint64_t TOP_FRONT_CENTER = 1ULL << 13; + const static uint64_t TOP_FRONT_RIGHT = 1ULL << 14; + const static uint64_t TOP_BACK_LEFT = 1ULL << 15; + const static uint64_t TOP_BACK_CENTER = 1ULL << 16; + const static uint64_t TOP_BACK_RIGHT = 1ULL << 17; + const static uint64_t STEREO_LEFT = 1ULL << 18; + const static uint64_t STEREO_RIGHT = 1ULL << 19; + const static uint64_t WIDE_LEFT = 1ULL << 20; + const static uint64_t WIDE_RIGHT = 1ULL << 21; + const static uint64_t SURROUND_DIRECT_LEFT = 1ULL << 22; + const static uint64_t SURROUND_DIRECT_RIGHT = 1ULL << 23; + const static uint64_t LOW_FREQUENCY_2 = 1ULL << 24; + const static uint64_t NATIVE = 1ULL << 25; + + const static uint64_t MONO = 1ULL << 26; + const static uint64_t STEREO = 1ULL << 27; + const static uint64_t _2POINT1 = 1ULL << 28; + const static uint64_t _2_1 = 1ULL << 29; + const static uint64_t SURROUND = 1ULL << 30; + const static uint64_t _3POINT1 = 1ULL << 31; + const static uint64_t _4POINT0 = 1ULL << 32; + const static uint64_t _4POINT1 = 1ULL << 33; + const static uint64_t _2_2 = 1ULL << 34; + const static uint64_t QUAD = 1ULL << 35; + const static uint64_t _5POINT0 = 1ULL << 36; + const static uint64_t _5POINT1 = 1ULL << 37; + const static uint64_t _5POINT0_BACK = 1ULL << 38; + const static uint64_t _5POINT1_BACK = 1ULL << 39; + const static uint64_t _6POINT0 = 1ULL << 40; + const static uint64_t _6POINT0_FRONT = 1ULL << 41; + const static uint64_t HEXAGONAL = 1ULL << 42; + const static uint64_t _6POINT1 = 1ULL << 43; + const static uint64_t _6POINT1_BACK = 1ULL << 44; + const static uint64_t _6POINT1_FRONT = 1ULL << 45; + const static uint64_t _7POINT0 = 1ULL << 46; + const static uint64_t _7POINT0_FRONT = 1ULL << 47; + const static uint64_t _7POINT1 = 1ULL << 48; + const static uint64_t _7POINT1_WIDE = 1ULL << 49; + const static uint64_t _7POINT1_WIDE_BACK = 1ULL << 50; + const static uint64_t OCTAGONAL = 1ULL << 51; + const static uint64_t HEXADECAGONAL = 1ULL << 52; + const static uint64_t STEREO_DOWNMIX = 1ULL << 53; + +public: + // Check This function. (Looks good, test it) + static uint64_t fromChannelLayoutID(uint64_t ChannelLayout) { + uint64_t Channel = 0UL; + if (ChannelLayout & FRONT_LEFT) + Channel |= AV_CH_FRONT_LEFT; + if (ChannelLayout & FRONT_RIGHT) + Channel |= AV_CH_FRONT_RIGHT; + if (ChannelLayout & FRONT_CENTER) + Channel |= AV_CH_FRONT_CENTER; + if (ChannelLayout & LOW_FREQUENCY) + Channel |= AV_CH_LOW_FREQUENCY; + if (ChannelLayout & BACK_LEFT) + Channel |= AV_CH_BACK_LEFT; + if (ChannelLayout & BACK_RIGHT) + Channel |= AV_CH_BACK_RIGHT; + if (ChannelLayout & FRONT_LEFT_OF_CENTER) + Channel |= AV_CH_FRONT_LEFT_OF_CENTER; + if (ChannelLayout & FRONT_RIGHT_OF_CENTER) + Channel |= AV_CH_FRONT_RIGHT_OF_CENTER; + if (ChannelLayout & BACK_CENTER) + Channel |= AV_CH_BACK_CENTER; + if (ChannelLayout & SIDE_LEFT) + Channel |= AV_CH_SIDE_LEFT; + if (ChannelLayout & SIDE_RIGHT) + Channel |= AV_CH_SIDE_RIGHT; + if (ChannelLayout & TOP_CENTER) + Channel |= AV_CH_TOP_CENTER; + if (ChannelLayout & TOP_FRONT_LEFT) + Channel |= AV_CH_TOP_FRONT_LEFT; + if (ChannelLayout & TOP_FRONT_CENTER) + Channel |= AV_CH_TOP_FRONT_CENTER; + if (ChannelLayout & TOP_FRONT_RIGHT) + Channel |= AV_CH_TOP_FRONT_RIGHT; + if (ChannelLayout & TOP_BACK_LEFT) + Channel |= AV_CH_TOP_BACK_LEFT; + if (ChannelLayout & TOP_BACK_CENTER) + Channel |= AV_CH_TOP_BACK_CENTER; + if (ChannelLayout & TOP_BACK_RIGHT) + Channel |= AV_CH_TOP_BACK_RIGHT; + if (ChannelLayout & STEREO_LEFT) + Channel |= AV_CH_STEREO_LEFT; + if (ChannelLayout & STEREO_RIGHT) + Channel |= AV_CH_STEREO_RIGHT; + if (ChannelLayout & WIDE_LEFT) + Channel |= AV_CH_WIDE_LEFT; + if (ChannelLayout & WIDE_RIGHT) + Channel |= AV_CH_WIDE_RIGHT; + if (ChannelLayout & SURROUND_DIRECT_LEFT) + Channel |= AV_CH_SURROUND_DIRECT_LEFT; + if (ChannelLayout & SURROUND_DIRECT_RIGHT) + Channel |= AV_CH_SURROUND_DIRECT_RIGHT; + if (ChannelLayout & LOW_FREQUENCY_2) + Channel |= AV_CH_LOW_FREQUENCY_2; + if (ChannelLayout & NATIVE) + Channel |= AV_CH_LAYOUT_NATIVE; + if (ChannelLayout & MONO) + Channel |= AV_CH_LAYOUT_MONO; + if (ChannelLayout & STEREO) + Channel |= AV_CH_LAYOUT_STEREO; + if (ChannelLayout & _2POINT1) + Channel |= AV_CH_LAYOUT_2POINT1; + if (ChannelLayout & _2_1) + Channel |= AV_CH_LAYOUT_2_1; + if (ChannelLayout & SURROUND) + Channel |= AV_CH_LAYOUT_SURROUND; + if (ChannelLayout & _3POINT1) + Channel |= AV_CH_LAYOUT_3POINT1; + if (ChannelLayout & _4POINT0) + Channel |= AV_CH_LAYOUT_4POINT0; + if (ChannelLayout & _4POINT1) + Channel |= AV_CH_LAYOUT_4POINT1; + if (ChannelLayout & _2_2) + Channel |= AV_CH_LAYOUT_2_2; + if (ChannelLayout & QUAD) + Channel |= AV_CH_LAYOUT_QUAD; + if (ChannelLayout & _5POINT0) + Channel |= AV_CH_LAYOUT_5POINT0; + if (ChannelLayout & _5POINT1) + Channel |= AV_CH_LAYOUT_5POINT1; + if (ChannelLayout & _5POINT0_BACK) + Channel |= AV_CH_LAYOUT_5POINT0_BACK; + if (ChannelLayout & _5POINT1_BACK) + Channel |= AV_CH_LAYOUT_5POINT1_BACK; + if (ChannelLayout & _6POINT0) + Channel |= AV_CH_LAYOUT_6POINT0; + if (ChannelLayout & _6POINT0_FRONT) + Channel |= AV_CH_LAYOUT_6POINT0_FRONT; + if (ChannelLayout & HEXAGONAL) + Channel |= AV_CH_LAYOUT_HEXAGONAL; + if (ChannelLayout & _6POINT1) + Channel |= AV_CH_LAYOUT_6POINT1; + if (ChannelLayout & _6POINT1_BACK) + Channel |= AV_CH_LAYOUT_6POINT1_BACK; + if (ChannelLayout & _6POINT1_FRONT) + Channel |= AV_CH_LAYOUT_6POINT1_FRONT; + if (ChannelLayout & _7POINT0) + Channel |= AV_CH_LAYOUT_7POINT0; + if (ChannelLayout & _7POINT0_FRONT) + Channel |= AV_CH_LAYOUT_7POINT0_FRONT; + if (ChannelLayout & _7POINT1) + Channel |= AV_CH_LAYOUT_7POINT1; + if (ChannelLayout & _7POINT1_WIDE) + Channel |= AV_CH_LAYOUT_7POINT1_WIDE; + if (ChannelLayout & _7POINT1_WIDE_BACK) + Channel |= AV_CH_LAYOUT_7POINT1_WIDE_BACK; + if (ChannelLayout & OCTAGONAL) + Channel |= AV_CH_LAYOUT_OCTAGONAL; + if (ChannelLayout & HEXADECAGONAL) + Channel |= AV_CH_LAYOUT_HEXADECAGONAL; + if (ChannelLayout & STEREO_DOWNMIX) + Channel |= AV_CH_LAYOUT_STEREO_DOWNMIX; + return Channel; + } + + // Perfect Logic :) + static uint64_t intoChannelLayoutID(uint64_t ChannelLayout) { + uint64_t Channel = 0; + if ((ChannelLayout & AV_CH_FRONT_LEFT) == AV_CH_FRONT_LEFT) + Channel |= FRONT_LEFT; + if ((ChannelLayout & AV_CH_FRONT_RIGHT) == AV_CH_FRONT_RIGHT) + Channel |= FRONT_RIGHT; + if ((ChannelLayout & AV_CH_FRONT_CENTER) == AV_CH_FRONT_CENTER) + Channel |= FRONT_CENTER; + if ((ChannelLayout & AV_CH_LOW_FREQUENCY) == AV_CH_LOW_FREQUENCY) + Channel |= LOW_FREQUENCY; + if ((ChannelLayout & AV_CH_BACK_LEFT) == AV_CH_BACK_LEFT) + Channel |= BACK_LEFT; + if ((ChannelLayout & AV_CH_BACK_RIGHT) == AV_CH_BACK_RIGHT) + Channel |= BACK_RIGHT; + if ((ChannelLayout & AV_CH_FRONT_LEFT_OF_CENTER) == + AV_CH_FRONT_LEFT_OF_CENTER) + Channel |= FRONT_LEFT_OF_CENTER; + if ((ChannelLayout & AV_CH_FRONT_RIGHT_OF_CENTER) == + AV_CH_FRONT_RIGHT_OF_CENTER) + Channel |= FRONT_RIGHT_OF_CENTER; + if ((ChannelLayout & AV_CH_BACK_CENTER) == AV_CH_BACK_CENTER) + Channel |= BACK_CENTER; + if ((ChannelLayout & AV_CH_SIDE_LEFT) == AV_CH_SIDE_LEFT) + Channel |= SIDE_LEFT; + if ((ChannelLayout & AV_CH_SIDE_RIGHT) == AV_CH_SIDE_RIGHT) + Channel |= SIDE_RIGHT; + if ((ChannelLayout & AV_CH_TOP_CENTER) == AV_CH_TOP_CENTER) + Channel |= TOP_CENTER; + if ((ChannelLayout & AV_CH_TOP_FRONT_LEFT) == AV_CH_TOP_FRONT_LEFT) + Channel |= TOP_FRONT_LEFT; + if ((ChannelLayout & AV_CH_TOP_FRONT_CENTER) == AV_CH_TOP_FRONT_CENTER) + Channel |= TOP_FRONT_CENTER; + if ((ChannelLayout & AV_CH_TOP_FRONT_RIGHT) == AV_CH_TOP_FRONT_RIGHT) + Channel |= TOP_FRONT_RIGHT; + if ((ChannelLayout & AV_CH_TOP_BACK_LEFT) == AV_CH_TOP_BACK_LEFT) + Channel |= TOP_BACK_LEFT; + if ((ChannelLayout & AV_CH_TOP_BACK_CENTER) == AV_CH_TOP_BACK_CENTER) + Channel |= TOP_BACK_CENTER; + if ((ChannelLayout & AV_CH_TOP_BACK_RIGHT) == AV_CH_TOP_BACK_RIGHT) + Channel |= TOP_BACK_RIGHT; + if ((ChannelLayout & AV_CH_STEREO_LEFT) == AV_CH_STEREO_LEFT) + Channel |= STEREO_LEFT; + if ((ChannelLayout & AV_CH_STEREO_RIGHT) == AV_CH_STEREO_RIGHT) + Channel |= STEREO_RIGHT; + if ((ChannelLayout & AV_CH_WIDE_LEFT) == AV_CH_WIDE_LEFT) + Channel |= WIDE_LEFT; + if ((ChannelLayout & AV_CH_WIDE_RIGHT) == AV_CH_WIDE_RIGHT) + Channel |= WIDE_RIGHT; + if ((ChannelLayout & AV_CH_SURROUND_DIRECT_LEFT) == + AV_CH_SURROUND_DIRECT_LEFT) + Channel |= SURROUND_DIRECT_LEFT; + if ((ChannelLayout & AV_CH_SURROUND_DIRECT_RIGHT) == + AV_CH_SURROUND_DIRECT_RIGHT) + Channel |= SURROUND_DIRECT_RIGHT; + if ((ChannelLayout & AV_CH_LOW_FREQUENCY_2) == AV_CH_LOW_FREQUENCY_2) + Channel |= LOW_FREQUENCY_2; + + // Channel Mask C; + if ((ChannelLayout & AV_CH_LAYOUT_NATIVE) == AV_CH_LAYOUT_NATIVE) + Channel |= NATIVE; + if ((ChannelLayout & AV_CH_LAYOUT_MONO) == AV_CH_LAYOUT_MONO) + Channel |= MONO; + if ((ChannelLayout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) + Channel |= STEREO; + if ((ChannelLayout & AV_CH_LAYOUT_2POINT1) == AV_CH_LAYOUT_2POINT1) + Channel |= _2POINT1; + if ((ChannelLayout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1) + Channel |= _2_1; + if ((ChannelLayout & AV_CH_LAYOUT_SURROUND) == AV_CH_LAYOUT_SURROUND) + Channel |= SURROUND; + if ((ChannelLayout & AV_CH_LAYOUT_3POINT1) == AV_CH_LAYOUT_3POINT1) + Channel |= _3POINT1; + if ((ChannelLayout & AV_CH_LAYOUT_4POINT0) == AV_CH_LAYOUT_4POINT0) + Channel |= _4POINT0; + if ((ChannelLayout & AV_CH_LAYOUT_4POINT1) == AV_CH_LAYOUT_4POINT1) + Channel |= _4POINT1; + if ((ChannelLayout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2) + Channel |= _2_2; + if ((ChannelLayout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD) + Channel |= QUAD; + if ((ChannelLayout & AV_CH_LAYOUT_5POINT0) == AV_CH_LAYOUT_5POINT0) + Channel |= _5POINT0; + if ((ChannelLayout & AV_CH_LAYOUT_5POINT1) == AV_CH_LAYOUT_5POINT1) + Channel |= _5POINT1; + if ((ChannelLayout & AV_CH_LAYOUT_5POINT0_BACK) == + AV_CH_LAYOUT_5POINT0_BACK) + Channel |= _5POINT0_BACK; + if ((ChannelLayout & AV_CH_LAYOUT_5POINT1_BACK) == + AV_CH_LAYOUT_5POINT1_BACK) + Channel |= _5POINT1_BACK; + if ((ChannelLayout & AV_CH_LAYOUT_6POINT0) == AV_CH_LAYOUT_6POINT0) + Channel |= _6POINT0; + if ((ChannelLayout & AV_CH_LAYOUT_6POINT0_FRONT) == + AV_CH_LAYOUT_6POINT0_FRONT) + Channel |= _6POINT0_FRONT; + if ((ChannelLayout & AV_CH_LAYOUT_HEXAGONAL) == AV_CH_LAYOUT_HEXAGONAL) + Channel |= HEXAGONAL; + if ((ChannelLayout & AV_CH_LAYOUT_6POINT1) == AV_CH_LAYOUT_6POINT1) + Channel |= _6POINT1; + if ((ChannelLayout & AV_CH_LAYOUT_6POINT1_BACK) == + AV_CH_LAYOUT_6POINT1_BACK) + Channel |= _6POINT1_BACK; + if ((ChannelLayout & AV_CH_LAYOUT_6POINT1_FRONT) == + AV_CH_LAYOUT_6POINT1_FRONT) + Channel |= _6POINT1_FRONT; + if ((ChannelLayout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0) + Channel |= _7POINT0; + if ((ChannelLayout & AV_CH_LAYOUT_7POINT0_FRONT) == + AV_CH_LAYOUT_7POINT0_FRONT) + Channel |= _7POINT0_FRONT; + if ((ChannelLayout & AV_CH_LAYOUT_7POINT1) == AV_CH_LAYOUT_7POINT1) + Channel |= _7POINT1; + if ((ChannelLayout & AV_CH_LAYOUT_7POINT1_WIDE) == + AV_CH_LAYOUT_7POINT1_WIDE) + Channel |= _7POINT1_WIDE; + if ((ChannelLayout & AV_CH_LAYOUT_7POINT1_WIDE_BACK) == + AV_CH_LAYOUT_7POINT1_WIDE_BACK) + Channel |= _7POINT1_WIDE_BACK; + if ((ChannelLayout & AV_CH_LAYOUT_OCTAGONAL) == AV_CH_LAYOUT_OCTAGONAL) + Channel |= OCTAGONAL; + if ((ChannelLayout & AV_CH_LAYOUT_HEXADECAGONAL) == + AV_CH_LAYOUT_HEXADECAGONAL) + Channel |= HEXADECAGONAL; + if ((ChannelLayout & AV_CH_LAYOUT_STEREO_DOWNMIX) == + AV_CH_LAYOUT_STEREO_DOWNMIX) + Channel |= STEREO_DOWNMIX; + return Channel; + } +}; + +class SWRFilterType { +public: + uint32_t fromSwrFilterType(SwrFilterType FilterType) { + switch (FilterType) { + case SWR_FILTER_TYPE_CUBIC: + return 1; + case SWR_FILTER_TYPE_BLACKMAN_NUTTALL: + return 2; + case SWR_FILTER_TYPE_KAISER: + return 3; + default: + return 1; + } + } + + SwrFilterType intoSwrFilterType(uint32_t FilterID) { + switch (FilterID) { + case 1: + return SWR_FILTER_TYPE_CUBIC; + case 2: + return SWR_FILTER_TYPE_BLACKMAN_NUTTALL; + case 3: + return SWR_FILTER_TYPE_KAISER; + default: + return SWR_FILTER_TYPE_CUBIC; + } + } +}; + +class SWREngine { +public: + SwrEngine intoSwrEngine(uint32_t EngineId) { + switch (EngineId) { + case 1: + return SWR_ENGINE_SWR; + case 2: + return SWR_ENGINE_SOXR; + default: + return SWR_ENGINE_SWR; + } + } + + uint32_t fromSwrEngine(SwrEngine Engine) { + switch (Engine) { + case SWR_ENGINE_SWR: + return 1; + case SWR_ENGINE_SOXR: + return 2; + case SWR_ENGINE_NB: + return 3; + default: + return SWR_ENGINE_SWR; + } + } +}; + +class SWRDitherType { +public: + SwrDitherType intoSwrDitherType(uint32_t SwrDitherId) { + switch (SwrDitherId) { + case 0: + return SWR_DITHER_NONE; + case 1: + return SWR_DITHER_RECTANGULAR; + case 2: + return SWR_DITHER_TRIANGULAR; + case 3: + return SWR_DITHER_TRIANGULAR_HIGHPASS; + case 64: + return SWR_DITHER_NS; + case 4: + return SWR_DITHER_NS_LIPSHITZ; + case 5: + return SWR_DITHER_NS_F_WEIGHTED; + case 6: + return SWR_DITHER_NS_MODIFIED_E_WEIGHTED; + case 7: + return SWR_DITHER_NS_IMPROVED_E_WEIGHTED; + case 8: + return SWR_DITHER_NS_SHIBATA; + case 9: + return SWR_DITHER_NS_LOW_SHIBATA; + case 10: + return SWR_DITHER_NS_HIGH_SHIBATA; + case 11: + return SWR_DITHER_NB; + default: + return SWR_DITHER_NONE; + } + } + + uint32_t fromSwrDitherType(SwrDitherType SwrDitherType) { + switch (SwrDitherType) { + case SWR_DITHER_NONE: + return 0; + case SWR_DITHER_RECTANGULAR: + return 1; + case SWR_DITHER_TRIANGULAR: + return 2; + case SWR_DITHER_TRIANGULAR_HIGHPASS: + return 3; + case SWR_DITHER_NS: + return 64; + case SWR_DITHER_NS_LIPSHITZ: + return 4; + case SWR_DITHER_NS_F_WEIGHTED: + return 5; + case SWR_DITHER_NS_MODIFIED_E_WEIGHTED: + return 6; + case SWR_DITHER_NS_IMPROVED_E_WEIGHTED: + return 7; + case SWR_DITHER_NS_SHIBATA: + return 8; + case SWR_DITHER_NS_LOW_SHIBATA: + return 9; + case SWR_DITHER_NS_HIGH_SHIBATA: + return 10; + case SWR_DITHER_NB: + return 11; + default: + return 0; + } + } +}; + +class ChromaLocation { +public: + static AVChromaLocation intoAVChromaLocation(int32_t ChromaLocationId) { + switch (ChromaLocationId) { + case 0: + return AVCHROMA_LOC_UNSPECIFIED; + case 1: + return AVCHROMA_LOC_LEFT; + case 2: + return AVCHROMA_LOC_CENTER; + case 3: + return AVCHROMA_LOC_TOPLEFT; + case 4: + return AVCHROMA_LOC_TOP; + case 5: + return AVCHROMA_LOC_BOTTOMLEFT; + case 6: + return AVCHROMA_LOC_BOTTOM; + default: + return AVCHROMA_LOC_UNSPECIFIED; + } + } + + static int32_t fromAVChromaLocation(AVChromaLocation ChromaLocation) { + switch (ChromaLocation) { + case AVCHROMA_LOC_UNSPECIFIED: + return 0; + case AVCHROMA_LOC_LEFT: + return 1; + case AVCHROMA_LOC_CENTER: + return 2; + case AVCHROMA_LOC_TOPLEFT: + return 3; + case AVCHROMA_LOC_TOP: + return 4; + case AVCHROMA_LOC_BOTTOMLEFT: + return 5; + case AVCHROMA_LOC_BOTTOM: + return 6; + default: + return 0; + } + } +}; + +class Rounding { + +public: + static AVRounding intoAVRounding(int32_t RoundingId) { + switch (RoundingId) { + case 0: + return AV_ROUND_ZERO; + case 1: + return AV_ROUND_INF; + case 2: + return AV_ROUND_DOWN; + case 3: + return AV_ROUND_UP; + case 4: + return AV_ROUND_NEAR_INF; + case 5: + return AV_ROUND_PASS_MINMAX; + default: + return AV_ROUND_ZERO; + } + } + + static int32_t fromAVRounding(AVRounding Rounding) { + switch (Rounding) { + case AV_ROUND_ZERO: + return 0; + case AV_ROUND_INF: + return 1; + case AV_ROUND_DOWN: + return 2; + case AV_ROUND_UP: + return 3; + case AV_ROUND_NEAR_INF: + return 4; + case AV_ROUND_PASS_MINMAX: + return 5; + default: + return 0; + } + } +}; + +class OptionType { + +public: + static AVOptionType intoAVOptionType(int32_t RoundingId) { + switch (RoundingId) { + case 0: + return AV_OPT_TYPE_FLAGS; + case 1: + return AV_OPT_TYPE_INT; + case 2: + return AV_OPT_TYPE_INT64; + case 3: + return AV_OPT_TYPE_DOUBLE; + case 4: + return AV_OPT_TYPE_FLOAT; + case 5: + return AV_OPT_TYPE_STRING; + case 6: + return AV_OPT_TYPE_RATIONAL; + case 7: + return AV_OPT_TYPE_BINARY; + case 8: + return AV_OPT_TYPE_DICT; + case 9: + return AV_OPT_TYPE_CONST; + case 10: + return AV_OPT_TYPE_IMAGE_SIZE; + case 11: + return AV_OPT_TYPE_PIXEL_FMT; + case 12: + return AV_OPT_TYPE_SAMPLE_FMT; + case 13: + return AV_OPT_TYPE_VIDEO_RATE; + case 14: + return AV_OPT_TYPE_DURATION; + case 15: + return AV_OPT_TYPE_COLOR; + case 16: + return AV_OPT_TYPE_CHANNEL_LAYOUT; + case 17: + return AV_OPT_TYPE_UINT64; + case 18: + return AV_OPT_TYPE_BOOL; + case 19: + return AV_OPT_TYPE_CHLAYOUT; + default: + return AV_OPT_TYPE_FLAGS; + } + } + + static int32_t fromAVOptionType(AVOptionType OptionType) { + switch (OptionType) { + case AV_OPT_TYPE_FLAGS: + return 0; + case AV_OPT_TYPE_INT: + return 1; + case AV_OPT_TYPE_INT64: + return 2; + case AV_OPT_TYPE_DOUBLE: + return 3; + case AV_OPT_TYPE_FLOAT: + return 4; + case AV_OPT_TYPE_STRING: + return 5; + case AV_OPT_TYPE_RATIONAL: + return 6; + case AV_OPT_TYPE_BINARY: + return 7; + case AV_OPT_TYPE_DICT: + return 8; + case AV_OPT_TYPE_CONST: + return 9; + case AV_OPT_TYPE_IMAGE_SIZE: + return 10; + case AV_OPT_TYPE_PIXEL_FMT: + return 11; + case AV_OPT_TYPE_SAMPLE_FMT: + return 12; + case AV_OPT_TYPE_VIDEO_RATE: + return 13; + case AV_OPT_TYPE_DURATION: + return 14; + case AV_OPT_TYPE_COLOR: + return 15; + case AV_OPT_TYPE_CHANNEL_LAYOUT: + return 16; + case AV_OPT_TYPE_UINT64: + return 17; + case AV_OPT_TYPE_BOOL: + return 18; + case AV_OPT_TYPE_CHLAYOUT: + return 19; + default: + return 0; + } + } +}; + +class PictureType { +public: + static AVPictureType intoAVPictureType(int32_t PictureId) { + switch (PictureId) { + case 0: + return AV_PICTURE_TYPE_NONE; + case 1: + return AV_PICTURE_TYPE_I; + case 2: + return AV_PICTURE_TYPE_P; + case 3: + return AV_PICTURE_TYPE_B; + case 4: + return AV_PICTURE_TYPE_S; + case 5: + return AV_PICTURE_TYPE_SI; + case 6: + return AV_PICTURE_TYPE_SP; + case 7: + return AV_PICTURE_TYPE_BI; + default: + return AV_PICTURE_TYPE_NONE; + } + }; + + static int32_t fromAVPictureType(AVPictureType PictureType) { + switch (PictureType) { + case AV_PICTURE_TYPE_NONE: + return 0; + case AV_PICTURE_TYPE_I: + return 1; + case AV_PICTURE_TYPE_P: + return 2; + case AV_PICTURE_TYPE_B: + return 3; + case AV_PICTURE_TYPE_S: + return 4; + case AV_PICTURE_TYPE_SI: + return 5; + case AV_PICTURE_TYPE_SP: + return 6; + case AV_PICTURE_TYPE_BI: + return 7; + default: + return 0; + } + } +}; + +// Direct mapping in rust. Not required. Can be used for decoupling (Clean +// Code). +// +// class ColorTransferCharacteristic { +// +// static AVColorTransferCharacteristic +// intoColorTransferCharacteristic(uint32_t ColorTransferCharacteristicId) { +// switch (ColorTransferCharacteristicId) { +// case 0: +// return AVCOL_TRC_RESERVED0; +// case 1: +// return AVCOL_TRC_BT709; +// case 2: +// return AVCOL_TRC_UNSPECIFIED; +// case 3: +// return AVCOL_TRC_RESERVED; +// case 4: +// return AVCOL_TRC_GAMMA22; +// case 5: +// return AVCOL_TRC_GAMMA28; +// case 6: +// return AVCOL_TRC_SMPTE170M; +// case 7: +// return AVCOL_TRC_SMPTE240M; +// case 8: +// return AVCOL_TRC_LINEAR; +// case 9: +// return AVCOL_TRC_LOG; +// case 10: +// return AVCOL_TRC_LOG_SQRT; +// case 11: +// return AVCOL_TRC_IEC61966_2_4; +// case 12: +// return AVCOL_TRC_BT1361_ECG; +// case 13: +// return AVCOL_TRC_IEC61966_2_1; +// case 14: +// return AVCOL_TRC_BT2020_10; +// case 15: +// return AVCOL_TRC_BT2020_12; +// case 16: +// return AVCOL_TRC_SMPTE2084; +// case 17: +// return AVCOL_TRC_SMPTE428; +// case 18: +// return AVCOL_TRC_ARIB_STD_B67; +// case 19: +// return AVCOL_TRC_NB; +// default: +// return AVCOL_TRC_RESERVED0; +// } +// }; +// +// static uint32_t +// fromColorTransferCharacteristic(uint32_t ColorTransferCharacteristic) { +// switch (ColorTransferCharacteristic) { +// case AVCOL_TRC_RESERVED0: +// return 0; +// case AVCOL_TRC_BT709: +// return 1; +// case AVCOL_TRC_UNSPECIFIED: +// return 2; +// case AVCOL_TRC_RESERVED: +// return 3; +// case AVCOL_TRC_GAMMA22: +// return 4; +// case AVCOL_TRC_GAMMA28: +// return 5; +// case AVCOL_TRC_SMPTE170M: +// return 6; +// case AVCOL_TRC_SMPTE240M: +// return 7; +// case AVCOL_TRC_LINEAR: +// return 8; +// case AVCOL_TRC_LOG: +// return 9; +// case AVCOL_TRC_LOG_SQRT: +// return 10; +// case AVCOL_TRC_IEC61966_2_4: +// return 11; +// case AVCOL_TRC_BT1361_ECG: +// return 12; +// case AVCOL_TRC_IEC61966_2_1: +// return 13; +// case AVCOL_TRC_BT2020_10: +// return 14; +// case AVCOL_TRC_BT2020_12: +// return 15; +// case AVCOL_TRC_SMPTE2084: +// return 16; +// case AVCOL_TRC_SMPTE428: +// return 17; +// case AVCOL_TRC_ARIB_STD_B67: +// return 18; +// case AVCOL_TRC_NB: +// return 19; +// default: +// return 0; +// } +// }; +//}; + +// We can keep or remove the binding. +class ColorSpace { + +public: + static AVColorSpace intoAVColorSpace(int32_t ColorSpaceId) { + + switch (ColorSpaceId) { + case 0: + return AVCOL_SPC_RGB; + case 1: + return AVCOL_SPC_BT709; + case 2: + return AVCOL_SPC_UNSPECIFIED; + case 3: + return AVCOL_SPC_RESERVED; + case 4: + return AVCOL_SPC_FCC; + case 5: + return AVCOL_SPC_BT470BG; + case 6: + return AVCOL_SPC_SMPTE170M; + case 7: + return AVCOL_SPC_SMPTE240M; + case 8: + return AVCOL_SPC_YCGCO; + case 9: + return AVCOL_SPC_BT2020_NCL; + case 10: + return AVCOL_SPC_BT2020_CL; + case 11: + return AVCOL_SPC_SMPTE2085; + case 12: + return AVCOL_SPC_CHROMA_DERIVED_NCL; + case 13: + return AVCOL_SPC_CHROMA_DERIVED_CL; + case 14: + return AVCOL_SPC_ICTCP; + default: + return AVCOL_SPC_RGB; + } + }; + + static int32_t fromAVColorSpace(AVColorSpace ColorSpace) { + + switch (ColorSpace) { + case AVCOL_SPC_RGB: + return 0; + case AVCOL_SPC_BT709: + return 1; + case AVCOL_SPC_UNSPECIFIED: + return 2; + case AVCOL_SPC_RESERVED: + return 3; + case AVCOL_SPC_FCC: + return 4; + case AVCOL_SPC_BT470BG: + return 5; + case AVCOL_SPC_SMPTE170M: + return 6; + case AVCOL_SPC_SMPTE240M: + return 7; + case AVCOL_SPC_YCGCO: + return 8; + case AVCOL_SPC_BT2020_NCL: + return 9; + case AVCOL_SPC_BT2020_CL: + return 10; + case AVCOL_SPC_SMPTE2085: + return 11; + case AVCOL_SPC_CHROMA_DERIVED_NCL: + return 12; + case AVCOL_SPC_CHROMA_DERIVED_CL: + return 13; + case AVCOL_SPC_ICTCP: + return 14; + default: + return 0; + } + }; +}; + +class FieldOrder { +public: + static AVFieldOrder intoAVFieldOrder(int32_t FieldOrderId) { + switch (FieldOrderId) { + case 0: + return AV_FIELD_UNKNOWN; + case 1: + return AV_FIELD_PROGRESSIVE; + case 2: + return AV_FIELD_TT; + case 3: + return AV_FIELD_BB; + case 4: + return AV_FIELD_TB; + case 5: + return AV_FIELD_BT; + default: + return AV_FIELD_UNKNOWN; + } + } + + static int32_t fromAVFieldOrder(AVFieldOrder FieldOrder) { + switch (FieldOrder) { + case AV_FIELD_UNKNOWN: + return 0; + case AV_FIELD_PROGRESSIVE: + return 1; + case AV_FIELD_TT: + return 2; + case AV_FIELD_BB: + return 3; + case AV_FIELD_TB: + return 4; + case AV_FIELD_BT: + return 5; + default: + return 0; + } + } +}; + +class ColorPrimaries { + +public: + static AVColorPrimaries intoAVColorPrimaries(int32_t ColorPrimariesId) { + switch (ColorPrimariesId) { + case 0: + return AVCOL_PRI_RESERVED0; + case 1: + return AVCOL_PRI_BT709; + case 2: + return AVCOL_PRI_UNSPECIFIED; + case 3: + return AVCOL_PRI_RESERVED; + case 4: + return AVCOL_PRI_BT470M; + case 5: + return AVCOL_PRI_BT470BG; + case 6: + return AVCOL_PRI_SMPTE170M; + case 7: + return AVCOL_PRI_SMPTE240M; + case 8: + return AVCOL_PRI_FILM; + case 9: + return AVCOL_PRI_BT2020; + case 10: + return AVCOL_PRI_SMPTE428; + case 11: + return AVCOL_PRI_SMPTE431; + case 12: + return AVCOL_PRI_SMPTE432; + case 13: + return AVCOL_PRI_JEDEC_P22; + case 14: + return AVCOL_PRI_EBU3213; + default: + return AVCOL_PRI_RESERVED0; + } + }; + + static int32_t fromAVColorPrimaries(AVColorPrimaries ColorPrimaries) { + switch (ColorPrimaries) { + case AVCOL_PRI_RESERVED0: + return 0; + case AVCOL_PRI_BT709: + return 1; + case AVCOL_PRI_UNSPECIFIED: + return 2; + case AVCOL_PRI_RESERVED: + return 3; + case AVCOL_PRI_BT470M: + return 4; + case AVCOL_PRI_BT470BG: + return 5; + case AVCOL_PRI_SMPTE170M: + return 6; + case AVCOL_PRI_SMPTE240M: + return 7; + case AVCOL_PRI_FILM: + return 8; + case AVCOL_PRI_BT2020: + return 9; + case AVCOL_PRI_SMPTE428: + return 10; + case AVCOL_PRI_SMPTE431: + return 11; + case AVCOL_PRI_SMPTE432: + return 12; + // #[cfg(not(feature = "ffmpeg_4_3"))] + // case AVCOL_PRI_JEDEC_P22: + // return 13; + case AVCOL_PRI_EBU3213: + return 14; + default: + return 0; + } + }; +}; + +} // namespace FFmpegUtils +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/ffmpeg_env.cpp b/plugins/wasmedge_ffmpeg/ffmpeg_env.cpp new file mode 100644 index 000000000000..f2705c4aed30 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/ffmpeg_env.cpp @@ -0,0 +1,112 @@ +#include "ffmpeg_env.h" +#include "avcodec/module.h" +#include "avdevice/module.h" +#include "avfilter/module.h" +#include "avformat/module.h" +#include "avutil/module.h" +#include "swresample/module.h" +#include "swscale/module.h" + +namespace WasmEdge { +namespace Host { +namespace { + +Runtime::Instance::ModuleInstance * +createAVCodec(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::AVcodec::WasmEdgeFFmpegAVCodecModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Runtime::Instance::ModuleInstance * +createAVDevice(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::AVDevice::WasmEdgeFFmpegAVDeviceModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Runtime::Instance::ModuleInstance * +createAVFilter(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::AVFilter::WasmEdgeFFmpegAVFilterModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Runtime::Instance::ModuleInstance * +createAVFormat(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::AVFormat::WasmEdgeFFmpegAVFormatModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Runtime::Instance::ModuleInstance * +createAVUtil(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::AVUtil::WasmEdgeFFmpegAVUtilModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Runtime::Instance::ModuleInstance * +createSWScale(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::SWScale::WasmEdgeFFmpegSWScaleModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Runtime::Instance::ModuleInstance * +createSWResample(const Plugin::PluginModule::ModuleDescriptor *) noexcept { + return new WasmEdgeFFmpeg::SWResample::WasmEdgeFFmpegSWResampleModule( + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::getInstance()); +} + +Plugin::Plugin::PluginDescriptor Descriptor{ + .Name = "wasmedge_ffmpeg", + .Description = "", + .APIVersion = Plugin::Plugin::CurrentAPIVersion, + .Version = {0, 0, 0, 1}, + .ModuleCount = 7, + .ModuleDescriptions = + (Plugin::PluginModule::ModuleDescriptor[]){ + { + .Name = "wasmedge_ffmpeg_avcodec", + .Description = "encoding/decoding library", + .Create = createAVCodec, + }, + { + .Name = "wasmedge_ffmpeg_avdevice", + .Description = "special devices muxing/demuxing library ", + .Create = createAVDevice, + }, + { + .Name = "wasmedge_ffmpeg_avfilter", + .Description = "graph-based frame editing library", + .Create = createAVFilter, + }, + { + .Name = "wasmedge_ffmpeg_avformat", + .Description = "I/O and muxing/demuxing library", + .Create = createAVFormat, + }, + { + .Name = "wasmedge_ffmpeg_avutil", + .Description = "utils utility library", + .Create = createAVUtil, + }, + { + .Name = "wasmedge_ffmpeg_swresample", + .Description = "audio resampling, format conversion and mixing", + .Create = createSWResample, + }, + { + .Name = "wasmedge_ffmpeg_swscale", + .Description = "color conversion and scaling library", + .Create = createSWScale, + }}, + .AddOptions = nullptr, +}; + +EXPORT_GET_DESCRIPTOR(Descriptor) + +} // namespace + +std::weak_ptr + WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::Instance = + std::make_shared(); + +std::shared_mutex WasmEdgeFFmpeg::WasmEdgeFFmpegEnv::Mutex; +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/ffmpeg_env.h b/plugins/wasmedge_ffmpeg/ffmpeg_env.h new file mode 100644 index 000000000000..e584fc5dbe8a --- /dev/null +++ b/plugins/wasmedge_ffmpeg/ffmpeg_env.h @@ -0,0 +1,110 @@ +#pragma once + +#include "bindings.h" +#include "plugin/plugin.h" + +#include "vector" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +class WasmEdgeFFmpegEnv { +public: + // Singleton + static std::shared_ptr getInstance() noexcept { + std::unique_lock Lock(Mutex); + std::shared_ptr EnvPtr = Instance.lock(); + if (!EnvPtr) { + EnvPtr.reset(new WasmEdgeFFmpegEnv()); + Instance = EnvPtr; + } + return EnvPtr; + } + + // Avoid copy constructor and overloading functions. + WasmEdgeFFmpegEnv(const WasmEdgeFFmpegEnv &) = delete; + void operator=(const WasmEdgeFFmpegEnv &) = delete; + + void alloc(void *Data, uint32_t *DataPtr) { + FfmpegPtrMap[FfmpegPtrAllocateKey++] = Data; + *DataPtr = FfmpegPtrAllocateKey - 1; + } + + void *fetchData(const size_t Index) { + if (Index >= FfmpegPtrAllocateKey) { + return nullptr; + } + // Check this condition. + if (FfmpegPtrMap[Index] == nullptr) { + return nullptr; + } + + return FfmpegPtrMap[Index]; + } + + void dealloc(size_t Index) { + + if (Index >= FfmpegPtrAllocateKey) { + return; + } + + FfmpegPtrMap.erase(Index); + } + + WasmEdgeFFmpegEnv() noexcept {} + +private: + // Using zero as NULL Value. + uint32_t FfmpegPtrAllocateKey = 1; + // Can update this to uint64_t to get more memory. + std::map FfmpegPtrMap; + static std::weak_ptr Instance; + static std::shared_mutex Mutex; +}; + +// Utils functions. +#define MEMINST_CHECK(Out, CallFrame, Index) \ + auto *Out = CallFrame.getMemoryByIndex(Index); \ + if (unlikely(Out == nullptr)) { \ + spdlog::error("[WasmEdge-FFmpeg] Memory instance not found."sv); \ + return static_cast(ErrNo::MissingMemory); \ + } + +#define FFMPEG_PTR_FETCH(StructPtr, FFmpegStructId, Type) \ + Type *StructPtr = nullptr; \ + if (FFmpegStructId != 0) \ + StructPtr = static_cast(Env.get()->fetchData(FFmpegStructId)); + +#define MEM_SPAN_CHECK(OutSpan, MemInst, Type, BufPtr, BufLen, Message) \ + auto OutSpan = MemInst->getSpan(BufPtr, BufLen); \ + if (unlikely(OutSpan.size() != BufLen)) { \ + spdlog::error("[WasmEdge-FFmpeg] "sv Message); \ + return static_cast(ErrNo::MissingMemory); \ + } + +#define FFMPEG_PTR_STORE(StructPtr, FFmpegStructId) \ + Env.get()->alloc(StructPtr, FFmpegStructId); + +#define FFMPEG_PTR_DELETE(FFmpegStructId) Env.get()->dealloc(FFmpegStructId); + +#define MEM_PTR_CHECK(OutPtr, MemInst, Type, Offset, Message) \ + Type *OutPtr = MemInst->getPointerOrNull(Offset); \ + if (unlikely(OutPtr == nullptr)) { \ + spdlog::error("[WasmEdge-FFmpeg] "sv Message); \ + return static_cast(ErrNo::MissingMemory); \ + } + +// Starting from 200 because, posix codes take values till 131. +// Hence using 200. +enum class ErrNo : int32_t { + Success = 0, // No error occurred. + MissingMemory = -201, // Caller module is missing a memory export. + NullStructId = -202, // Rust Sdk Passes null id. + InternalError = -203, + UnImplemented = -204 // Unimplemented funcs. +}; + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/swresample/module.cpp b/plugins/wasmedge_ffmpeg/swresample/module.cpp new file mode 100644 index 000000000000..00d617db3f3f --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swresample/module.cpp @@ -0,0 +1,40 @@ +#include "module.h" +#include "swresample_func.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWResample { + +WasmEdgeFFmpegSWResampleModule::WasmEdgeFFmpegSWResampleModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_swresample") { + + addHostFunc("wasmedge_ffmpeg_swresample_swresample_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swr_get_delay", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swr_init", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swr_alloc_set_opts", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_av_opt_set_dict", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swr_convert_frame", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swr_free", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swresample_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swresample_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swresample_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swresample_swresample_license", + std::make_unique(Env)); +} + +} // namespace SWResample +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swresample/module.h b/plugins/wasmedge_ffmpeg/swresample/module.h new file mode 100644 index 000000000000..a47d966bd876 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swresample/module.h @@ -0,0 +1,20 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWResample { + +class WasmEdgeFFmpegSWResampleModule + : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegSWResampleModule(std::shared_ptr Env); +}; + +} // namespace SWResample +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swresample/swresample_base.h b/plugins/wasmedge_ffmpeg/swresample/swresample_base.h new file mode 100644 index 000000000000..574dcd20c2ed --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swresample/swresample_base.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWResample { + +template +class WasmEdgeFFmpegSWResample : public Runtime::HostFunction { +public: + WasmEdgeFFmpegSWResample( + std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace SWResample +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp b/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp new file mode 100644 index 000000000000..a28e75200fe6 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp @@ -0,0 +1,126 @@ +#include "swresample_func.h" + +extern "C" { +#include "libavutil/avutil.h" +#include "libavutil/opt.h" +#include "libswresample/swresample.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWResample { + +Expect SWResampleVersion::body(const Runtime::CallingFrame &) { + return swresample_version(); +} + +Expect SWRGetDelay::body(const Runtime::CallingFrame &, + uint32_t SWRContextId, int64_t Base) { + + FFMPEG_PTR_FETCH(SWRContext, SWRContextId, SwrContext); + return swr_get_delay(SWRContext, Base); +} + +Expect SWRInit::body(const Runtime::CallingFrame &, + uint32_t SWRContextId) { + + FFMPEG_PTR_FETCH(SWRContext, SWRContextId, SwrContext); + return swr_init(SWRContext); +} + +Expect +SWRAllocSetOpts::body(const Runtime::CallingFrame &Frame, uint32_t SwrCtxPtr, + uint32_t SWRContextId, uint64_t OutChLayoutId, + uint32_t OutSampleFmtId, int32_t OutSampleRate, + uint64_t InChLayoutId, uint32_t InSampleFmtId, + int32_t InSampleRate, int32_t LogOffset) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwrCtxId, MemInst, uint32_t, SwrCtxPtr, "") + FFMPEG_PTR_FETCH(CurrSwrCtx, *SwrCtxId, SwrContext); + FFMPEG_PTR_FETCH(ExistSWRContext, SWRContextId, SwrContext); + + uint64_t const OutChLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(OutChLayoutId); + AVSampleFormat const OutSampleFmt = + FFmpegUtils::SampleFmt::fromSampleID(OutSampleFmtId); + uint64_t const InChLayout = + FFmpegUtils::ChannelLayout::fromChannelLayoutID(InChLayoutId); + AVSampleFormat const InSampleFmt = + FFmpegUtils::SampleFmt::fromSampleID(InSampleFmtId); + CurrSwrCtx = swr_alloc_set_opts( + ExistSWRContext, OutChLayout, OutSampleFmt, OutSampleRate, InChLayout, + InSampleFmt, InSampleRate, LogOffset, + nullptr); // Always being used as null in rust sdk. + FFMPEG_PTR_STORE(CurrSwrCtx, SwrCtxId); + return static_cast(ErrNo::Success); +} + +Expect AVOptSetDict::body(const Runtime::CallingFrame &, + uint32_t SWRContextId, uint32_t DictId) { + + FFMPEG_PTR_FETCH(SWRContext, SWRContextId, SwrContext); + FFMPEG_PTR_FETCH(AvDictionary, DictId, AVDictionary *); + return av_opt_set_dict(SWRContext, AvDictionary); +} + +Expect SWRConvertFrame::body(const Runtime::CallingFrame &, + uint32_t SWRContextId, + uint32_t FrameOutputId, + uint32_t FrameInputId) { + FFMPEG_PTR_FETCH(SWRContext, SWRContextId, SwrContext); + FFMPEG_PTR_FETCH(OuputFrame, FrameOutputId, AVFrame); + FFMPEG_PTR_FETCH(InputFrame, FrameInputId, AVFrame); + + return swr_convert_frame(SWRContext, OuputFrame, InputFrame); +} + +Expect SWRFree::body(const Runtime::CallingFrame &, + uint32_t SWRContextId) { + FFMPEG_PTR_FETCH(SWRContext, SWRContextId, SwrContext); + swr_close(SWRContext); + FFMPEG_PTR_DELETE(SWRContextId); + return static_cast(ErrNo::Success); +} + +Expect +SWResampleConfigurationLength::body(const Runtime::CallingFrame &) { + const char *Config = swresample_configuration(); + return strlen(Config); +} + +Expect +SWResampleConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = swresample_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect SWResampleLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = swresample_license(); + return strlen(License); +} + +Expect SWResampleLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, + uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = swresample_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +} // namespace SWResample +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swresample/swresample_func.h b/plugins/wasmedge_ffmpeg/swresample/swresample_func.h new file mode 100644 index 000000000000..b8dd8d7fc599 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swresample/swresample_func.h @@ -0,0 +1,107 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/callingframe.h" +#include "swresample_base.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWResample { + +class SWResampleVersion : public WasmEdgeFFmpegSWResample { +public: + SWResampleVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class SWRGetDelay : public WasmEdgeFFmpegSWResample { +public: + SWRGetDelay(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SWRContextId, int64_t Base); +}; + +class SWRInit : public WasmEdgeFFmpegSWResample { +public: + SWRInit(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SWRContextId); +}; + +class SWRAllocSetOpts : public WasmEdgeFFmpegSWResample { +public: + SWRAllocSetOpts(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwrCtxPtr, + uint32_t SWRContextId, uint64_t OutChLayout, + uint32_t OutSampleFmtId, int32_t OutSampleRate, + uint64_t InChLayout, uint32_t InSampleFmtId, + int32_t InSampleRate, int32_t LogOffset); +}; + +class AVOptSetDict : public WasmEdgeFFmpegSWResample { +public: + AVOptSetDict(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SWRContextId, uint32_t DictId); +}; + +class SWRConvertFrame : public WasmEdgeFFmpegSWResample { +public: + SWRConvertFrame(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SWRContextId, uint32_t FrameOutputId, + uint32_t FrameInputId); +}; + +class SWRFree : public WasmEdgeFFmpegSWResample { +public: + SWRFree(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SWRContextId); +}; + +class SWResampleConfigurationLength + : public WasmEdgeFFmpegSWResample { +public: + SWResampleConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class SWResampleConfiguration + : public WasmEdgeFFmpegSWResample { +public: + SWResampleConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class SWResampleLicenseLength + : public WasmEdgeFFmpegSWResample { +public: + SWResampleLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class SWResampleLicense : public WasmEdgeFFmpegSWResample { +public: + SWResampleLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWResample(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +} // namespace SWResample +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasmedge_ffmpeg/swscale/module.cpp b/plugins/wasmedge_ffmpeg/swscale/module.cpp new file mode 100644 index 000000000000..f33cadd47b41 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swscale/module.cpp @@ -0,0 +1,74 @@ +#include "module.h" +#include "swscale_func.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWScale { + +WasmEdgeFFmpegSWScaleModule::WasmEdgeFFmpegSWScaleModule( + std::shared_ptr Env) + : ModuleInstance("wasmedge_ffmpeg_swscale") { + + addHostFunc("wasmedge_ffmpeg_swscale_swscale_version", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_swscale_configuration_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_swscale_configuration", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_swscale_license_length", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_swscale_license", + std::make_unique(Env)); + + // SwsContext + addHostFunc("wasmedge_ffmpeg_swscale_sws_getContext", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_freeContext", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_scale", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getCachedContext", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_isSupportedInput", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_isSupportedOutput", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_isSupportedEndiannessConversion", + std::make_unique(Env)); + + // SwsFilter + addHostFunc("wasmedge_ffmpeg_swscale_sws_getDefaultFilter", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getLumaH", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getLumaV", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getChromaH", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getChromaV", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_freeFilter", + std::make_unique(Env)); + + // SwsVector + addHostFunc("wasmedge_ffmpeg_swscale_sws_allocVec", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getGaussianVec", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_scaleVec", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_normalizeVec", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getCoeffVecLength", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_getCoeff", + std::make_unique(Env)); + addHostFunc("wasmedge_ffmpeg_swscale_sws_freeVec", + std::make_unique(Env)); +} + +} // namespace SWScale +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swscale/module.h b/plugins/wasmedge_ffmpeg/swscale/module.h new file mode 100644 index 000000000000..bc53ee2f48cb --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swscale/module.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/instance/module.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWScale { + +class WasmEdgeFFmpegSWScaleModule : public Runtime::Instance::ModuleInstance { +public: + WasmEdgeFFmpegSWScaleModule(std::shared_ptr Env); +}; + +} // namespace SWScale +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swscale/swscale_base.h b/plugins/wasmedge_ffmpeg/swscale/swscale_base.h new file mode 100644 index 000000000000..32dc9cf1119f --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swscale/swscale_base.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ffmpeg_env.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWScale { + +template +class WasmEdgeFFmpegSWScale : public Runtime::HostFunction { +public: + WasmEdgeFFmpegSWScale( + std::shared_ptr HostEnv) + : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + std::shared_ptr Env; +}; + +} // namespace SWScale +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp b/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp new file mode 100644 index 000000000000..7b12660766ab --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp @@ -0,0 +1,298 @@ +#include "swscale_func.h" + +extern "C" { +#include "libavutil/frame.h" +#include "libswscale/swscale.h" +} + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWScale { + +Expect +SwsGetContext::body(const Runtime::CallingFrame &Frame, uint32_t SwsCtxPtr, + uint32_t SrcW, uint32_t SrcH, uint32_t SrcPixFormatId, + uint32_t DesW, uint32_t DesH, uint32_t DesPixFormatId, + int32_t Flags, uint32_t SrcFilterId, uint32_t DesFilterId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsCtxId, MemInst, uint32_t, SwsCtxPtr, + "Failed when accessing the return SWSContext Memory"sv) + + FFMPEG_PTR_FETCH(SwsCtx, *SwsCtxId, SwsContext) + FFMPEG_PTR_FETCH(SrcSwsFilter, SrcFilterId, SwsFilter) + FFMPEG_PTR_FETCH(DesSwsFilter, DesFilterId, SwsFilter) + + AVPixelFormat const SrcPixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(SrcPixFormatId); + AVPixelFormat const DestPixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(DesPixFormatId); + SwsCtx = sws_getContext(SrcW, SrcH, SrcPixelFormat, DesW, DesH, + DestPixelFormat, Flags, SrcSwsFilter, DesSwsFilter, + nullptr); // Not using param anywhere in Rust SDK. + if (SwsCtx == nullptr) + return static_cast(ErrNo::InternalError); + FFMPEG_PTR_STORE(SwsCtx, SwsCtxId); + return static_cast(ErrNo::Success); +} + +Expect SwsFreeContext::body(const Runtime::CallingFrame &, + uint32_t SwsCtxId) { + + FFMPEG_PTR_FETCH(SwsCtx, SwsCtxId, SwsContext) + sws_freeContext(SwsCtx); + FFMPEG_PTR_DELETE(SwsCtxId); + return static_cast(ErrNo::Success); +} + +Expect SwsScale::body(const Runtime::CallingFrame &, uint32_t SwsCtxId, + uint32_t InputFrameId, int32_t SrcSliceY, + int32_t SrcSliceH, uint32_t OutputFrameId) { + + FFMPEG_PTR_FETCH(SwsCtx, SwsCtxId, SwsContext); + FFMPEG_PTR_FETCH(InputFrame, InputFrameId, AVFrame); + FFMPEG_PTR_FETCH(OutputFrame, OutputFrameId, AVFrame); + return sws_scale(SwsCtx, InputFrame->data, InputFrame->linesize, SrcSliceY, + SrcSliceH, OutputFrame->data, OutputFrame->linesize); +} + +Expect SwsGetCachedContext::body( + const Runtime::CallingFrame &Frame, uint32_t SwsCachedCtxPtr, + uint32_t SwsCtxId, uint32_t SrcW, uint32_t SrcH, uint32_t SrcPixFormatId, + uint32_t DesW, uint32_t DesH, uint32_t DesPixFormatId, int32_t Flags, + uint32_t SrcFilterId, uint32_t DesFilterId) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsCachedCtxId, MemInst, uint32_t, SwsCachedCtxPtr, "") + + FFMPEG_PTR_FETCH(SwsCachedCtx, *SwsCachedCtxId, SwsContext); + FFMPEG_PTR_FETCH(SwsCtx, SwsCtxId, SwsContext); + FFMPEG_PTR_FETCH(SrcSwsFilter, SrcFilterId, SwsFilter) + FFMPEG_PTR_FETCH(DesSwsFilter, DesFilterId, SwsFilter) + + AVPixelFormat const SrcPixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(SrcPixFormatId); + AVPixelFormat const DestPixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(DesPixFormatId); + SwsCachedCtx = sws_getCachedContext(SwsCtx, SrcW, SrcH, SrcPixelFormat, DesW, + DesH, DestPixelFormat, Flags, + SrcSwsFilter, DesSwsFilter, nullptr); + if (SwsCachedCtx == nullptr) + return static_cast(ErrNo::InternalError); + + FFMPEG_PTR_STORE(SwsCachedCtx, SwsCachedCtxId); + return static_cast(ErrNo::Success); +} + +Expect SwsIsSupportedInput::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + return sws_isSupportedInput(PixelFormat); +} + +Expect SwsIsSupportedOutput::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + return sws_isSupportedOutput(PixelFormat); +} + +Expect +SwsIsSupportedEndiannessConversion::body(const Runtime::CallingFrame &, + uint32_t PixFormatId) { + AVPixelFormat const PixelFormat = + FFmpegUtils::PixFmt::intoAVPixFmt(PixFormatId); + return sws_isSupportedEndiannessConversion(PixelFormat); +} + +Expect SwsGetDefaultFilter::body( + const Runtime::CallingFrame &Frame, uint32_t SwsFilterPtr, float LumaGBlur, + float ChromaGBlur, float LumaSharpen, float ChromaSharpen, + float ChromaHShift, float ChromaVShift, int32_t Verbose) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsFilterId, MemInst, uint32_t, SwsFilterPtr, "") + + SwsFilter *Filter = + sws_getDefaultFilter(LumaGBlur, ChromaGBlur, LumaSharpen, ChromaSharpen, + ChromaHShift, ChromaVShift, Verbose); + if (Filter == nullptr) + return static_cast(ErrNo::InternalError); + FFMPEG_PTR_STORE(Filter, SwsFilterId); + return static_cast(ErrNo::Success); +} + +Expect SwsGetLumaH::body(const Runtime::CallingFrame &Frame, + uint32_t SwsFilterId, uint32_t SwsVectorPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsVectorId, MemInst, uint32_t, SwsVectorPtr, "") + FFMPEG_PTR_FETCH(Filter, SwsFilterId, SwsFilter); + + SwsVector *Vector = Filter->lumH; + FFMPEG_PTR_STORE(Vector, SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwsGetLumaV::body(const Runtime::CallingFrame &Frame, + uint32_t SwsFilterId, uint32_t SwsVectorPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsVectorId, MemInst, uint32_t, SwsVectorPtr, "") + FFMPEG_PTR_FETCH(Filter, SwsFilterId, SwsFilter); + + SwsVector *Vector = Filter->lumV; + FFMPEG_PTR_STORE(Vector, SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwsGetChromaH::body(const Runtime::CallingFrame &Frame, + uint32_t SwsFilterId, + uint32_t SwsVectorPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsVectorId, MemInst, uint32_t, SwsVectorPtr, "") + FFMPEG_PTR_FETCH(Filter, SwsFilterId, SwsFilter); + + SwsVector *Vector = Filter->chrH; + FFMPEG_PTR_STORE(Vector, SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwsGetChromaV::body(const Runtime::CallingFrame &Frame, + uint32_t SwsFilterId, + uint32_t SwsVectorPtr) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsVectorId, MemInst, uint32_t, SwsVectorPtr, "") + FFMPEG_PTR_FETCH(Filter, SwsFilterId, SwsFilter); + + SwsVector *Vector = Filter->chrV; + FFMPEG_PTR_STORE(Vector, SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwsFreeFilter::body(const Runtime::CallingFrame &, + uint32_t SwsFilterId) { + + FFMPEG_PTR_FETCH(Filter, SwsFilterId, SwsFilter); + sws_freeFilter(Filter); + FFMPEG_PTR_DELETE(SwsFilterId); + return static_cast(ErrNo::Success); +} + +Expect SwsAllocVec::body(const Runtime::CallingFrame &Frame, + uint32_t SwsVectorPtr, int32_t Length) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsVectorId, MemInst, uint32_t, SwsVectorPtr, "") + + SwsVector *Vector = sws_allocVec(Length); + FFMPEG_PTR_STORE(Vector, SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwsGetGaussianVec::body(const Runtime::CallingFrame &Frame, + uint32_t SwsVectorPtr, double Variance, + double Quality) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_PTR_CHECK(SwsVectorId, MemInst, uint32_t, SwsVectorPtr, "") + + SwsVector *Vector = sws_getGaussianVec(Variance, Quality); + FFMPEG_PTR_STORE(Vector, SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwsScaleVec::body(const Runtime::CallingFrame &, + uint32_t SwsVectorId, double Scalar) { + + FFMPEG_PTR_FETCH(Vector, SwsVectorId, SwsVector); + sws_scaleVec(Vector, Scalar); + return static_cast(ErrNo::Success); +} + +Expect SwsNormalizeVec::body(const Runtime::CallingFrame &, + uint32_t SwsVectorId, double Height) { + + FFMPEG_PTR_FETCH(Vector, SwsVectorId, SwsVector); + sws_normalizeVec(Vector, Height); + return static_cast(ErrNo::Success); +} + +Expect SwsGetCoeffVecLength::body(const Runtime::CallingFrame &, + uint32_t SwsVectorId) { + + FFMPEG_PTR_FETCH(Vector, SwsVectorId, SwsVector); + return Vector->length * + sizeof(double); // Getting the size in uint_8* (Cuz Passing uint8_t* + // array from Rust SDK). +} + +Expect SwsGetCoeff::body(const Runtime::CallingFrame &Frame, + uint32_t SwsVectorId, uint32_t CoeffBufPtr, + uint32_t Len) { + + MEMINST_CHECK(MemInst, Frame, 0) + MEM_SPAN_CHECK(Buffer, MemInst, uint8_t, CoeffBufPtr, Len, ""); + FFMPEG_PTR_FETCH(Vector, SwsVectorId, SwsVector); + + double *Coeff = Vector->coeff; + std::copy_n(Coeff, Len, Buffer.data()); + return static_cast(ErrNo::Success); +} + +Expect SwsFreeVec::body(const Runtime::CallingFrame &, + uint32_t SwsVectorId) { + + FFMPEG_PTR_FETCH(Vector, SwsVectorId, SwsVector); + sws_freeVec(Vector); + FFMPEG_PTR_DELETE(SwsVectorId); + return static_cast(ErrNo::Success); +} + +Expect SwscaleVersion::body(const Runtime::CallingFrame &) { + return swscale_version(); +} + +Expect +SwscaleConfigurationLength::body(const Runtime::CallingFrame &) { + const char *Config = swscale_configuration(); + return strlen(Config); +} + +Expect SwscaleConfiguration::body(const Runtime::CallingFrame &Frame, + uint32_t ConfigPtr, + uint32_t ConfigLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(ConfigBuf, MemInst, char, ConfigPtr, ConfigLen, ""); + + const char *Config = swscale_configuration(); + std::copy_n(Config, ConfigLen, ConfigBuf.data()); + return static_cast(ErrNo::Success); +} + +Expect SwscaleLicenseLength::body(const Runtime::CallingFrame &) { + + const char *License = swscale_license(); + return strlen(License); +} + +Expect SwscaleLicense::body(const Runtime::CallingFrame &Frame, + uint32_t LicensePtr, uint32_t LicenseLen) { + + MEMINST_CHECK(MemInst, Frame, 0); + MEM_SPAN_CHECK(LicenseBuf, MemInst, char, LicensePtr, LicenseLen, ""); + + const char *License = swscale_license(); + std::copy_n(License, LicenseLen, LicenseBuf.data()); + return static_cast(ErrNo::Success); +} + +} // namespace SWScale +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasmedge_ffmpeg/swscale/swscale_func.h b/plugins/wasmedge_ffmpeg/swscale/swscale_func.h new file mode 100644 index 000000000000..dfb7ffbf6be4 --- /dev/null +++ b/plugins/wasmedge_ffmpeg/swscale/swscale_func.h @@ -0,0 +1,226 @@ +#pragma once + +#include "runtime/callingframe.h" +#include "swscale_base.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +namespace SWScale { + +class SwsGetContext : public WasmEdgeFFmpegSWScale { +public: + SwsGetContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsCtxPtr, + uint32_t SrcW, uint32_t SrcH, uint32_t SrcPixFormatId, + uint32_t DesW, uint32_t DesH, uint32_t DesPixFormatId, + int32_t Flags, uint32_t SrcFilterId, + uint32_t DesFilterId); +}; + +class SwsFreeContext : public WasmEdgeFFmpegSWScale { +public: + SwsFreeContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsCtxId); +}; + +class SwsScale : public WasmEdgeFFmpegSWScale { +public: + SwsScale(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsCtxId, + uint32_t InputFrameId, int32_t SrcSliceY, + int32_t SrcSliceH, uint32_t OutputFrameId); +}; + +class SwsGetCachedContext : public WasmEdgeFFmpegSWScale { +public: + SwsGetCachedContext(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SwsCachedCtxPtr, uint32_t SwsCtxPtr, + uint32_t SrcW, uint32_t SrcH, uint32_t SrcPixFormatId, + uint32_t DesW, uint32_t DesH, uint32_t DesPixFormatId, + int32_t Flags, uint32_t SrcFilterId, + uint32_t DesFilterId); +}; + +class SwsIsSupportedInput : public WasmEdgeFFmpegSWScale { +public: + SwsIsSupportedInput(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +class SwsIsSupportedOutput + : public WasmEdgeFFmpegSWScale { +public: + SwsIsSupportedOutput(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +class SwsIsSupportedEndiannessConversion + : public WasmEdgeFFmpegSWScale { +public: + SwsIsSupportedEndiannessConversion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t PixFormatId); +}; + +class SwsGetDefaultFilter : public WasmEdgeFFmpegSWScale { +public: + SwsGetDefaultFilter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SwsFilterPtr, float LumaGBlur, + float ChromaGBlur, float LumaSharpen, + float ChromaSharpen, float ChromaHShift, + float ChromaVShift, int32_t Verbose); +}; + +class SwsGetLumaH : public WasmEdgeFFmpegSWScale { +public: + SwsGetLumaH(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsFilterId, + uint32_t SwsVectorPtr); +}; + +class SwsGetLumaV : public WasmEdgeFFmpegSWScale { +public: + SwsGetLumaV(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsFilterId, + uint32_t SwsVectorPtr); +}; + +class SwsGetChromaH : public WasmEdgeFFmpegSWScale { +public: + SwsGetChromaH(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsFilterId, + uint32_t SwsVectorPtr); +}; + +class SwsGetChromaV : public WasmEdgeFFmpegSWScale { +public: + SwsGetChromaV(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsFilterId, + uint32_t SwsVectorPtr); +}; + +class SwsFreeFilter : public WasmEdgeFFmpegSWScale { +public: + SwsFreeFilter(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SwsFilterId); +}; + +class SwsAllocVec : public WasmEdgeFFmpegSWScale { +public: + SwsAllocVec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SwsVectorPtr, int32_t Length); +}; + +class SwsGetGaussianVec : public WasmEdgeFFmpegSWScale { +public: + SwsGetGaussianVec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SwsVectorPtr, double Variance, double Quality); +}; + +class SwsScaleVec : public WasmEdgeFFmpegSWScale { +public: + SwsScaleVec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsVectorId, + double Scalar); +}; + +class SwsNormalizeVec : public WasmEdgeFFmpegSWScale { +public: + SwsNormalizeVec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t SwsVectorId, + double Height); +}; + +class SwsGetCoeffVecLength + : public WasmEdgeFFmpegSWScale { +public: + SwsGetCoeffVecLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t SwsVectorId); +}; + +class SwsGetCoeff : public WasmEdgeFFmpegSWScale { +public: + SwsGetCoeff(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &, uint32_t SwsVectorId, + uint32_t CoeffBuf, uint32_t Len); +}; + +class SwsFreeVec : public WasmEdgeFFmpegSWScale { +public: + SwsFreeVec(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, + uint32_t SwsVectorId); +}; + +class SwscaleVersion : public WasmEdgeFFmpegSWScale { +public: + SwscaleVersion(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class SwscaleConfigurationLength + : public WasmEdgeFFmpegSWScale { +public: + SwscaleConfigurationLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class SwscaleConfiguration + : public WasmEdgeFFmpegSWScale { +public: + SwscaleConfiguration(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t ConfigPtr, + uint32_t ConfigLen); +}; + +class SwscaleLicenseLength + : public WasmEdgeFFmpegSWScale { +public: + SwscaleLicenseLength(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame); +}; + +class SwscaleLicense : public WasmEdgeFFmpegSWScale { +public: + SwscaleLicense(std::shared_ptr HostEnv) + : WasmEdgeFFmpegSWScale(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t LicensePtr, + uint32_t LicenseLen); +}; + +} // namespace SWScale +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5400f42296ac..e6af74c29f94 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,8 +8,8 @@ else() FetchContent_Declare( GTest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.11.0 - GIT_SHALLOW TRUE + GIT_TAG release-1.11.0 + GIT_SHALLOW TRUE ) set(BUILD_GMOCK OFF CACHE BOOL "Builds the googlemock subproject" FORCE) set(INSTALL_GTEST OFF CACHE BOOL "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" FORCE) @@ -20,10 +20,10 @@ else() ) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS - ${WASMEDGE_CFLAGS} + DIRECTORY + APPEND + PROPERTY COMPILE_OPTIONS + ${WASMEDGE_CFLAGS} ) else() set_property( @@ -60,7 +60,7 @@ else() set(GTEST_BOTH_LIBRARIES "gtest;gtest_main") endif() -if (WASMEDGE_USE_LLVM) +if(WASMEDGE_USE_LLVM) add_subdirectory(aot) add_subdirectory(llvm) add_subdirectory(mixcall) @@ -70,11 +70,11 @@ add_subdirectory(spec) add_subdirectory(loader) add_subdirectory(executor) add_subdirectory(thread) -if (WASMEDGE_BUILD_SHARED_LIB) +if(WASMEDGE_BUILD_SHARED_LIB) add_subdirectory(api) add_subdirectory(externref) endif() -if (WASMEDGE_BUILD_PLUGINS) +if(WASMEDGE_BUILD_PLUGINS) add_subdirectory(plugins) endif() add_subdirectory(host/socket) @@ -93,15 +93,15 @@ if(WASMEDGE_BUILD_COVERAGE) DEPENDENCIES wasmedge BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" EXCLUDE - "${PROJECT_SOURCE_DIR}/thirdparty/*" - "${PROJECT_SOURCE_DIR}/test/*" - ) + "${PROJECT_SOURCE_DIR}/thirdparty/*" + "${PROJECT_SOURCE_DIR}/test/*" + ) setup_target_for_coverage_gcovr_xml( NAME codecov EXECUTABLE ctest -j ${PROCESSOR_COUNT} DEPENDENCIES wasmedge EXCLUDE - "${PROJECT_SOURCE_DIR}/thirdparty/*" - "${PROJECT_SOURCE_DIR}/test/*" - ) + "${PROJECT_SOURCE_DIR}/thirdparty/*" + "${PROJECT_SOURCE_DIR}/test/*" + ) endif() diff --git a/test/plugins/CMakeLists.txt b/test/plugins/CMakeLists.txt index 808507fd0021..211c0bbda2b0 100644 --- a/test/plugins/CMakeLists.txt +++ b/test/plugins/CMakeLists.txt @@ -1,14 +1,18 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC +if(WASMEDGE_PLUGIN_FFMPEG) + add_subdirectory(wasmedge_ffmpeg) +endif() + if(WASMEDGE_PLUGIN_PROCESS) - if (CMAKE_SYSTEM_NAME MATCHES "Linux") + if(CMAKE_SYSTEM_NAME MATCHES "Linux") add_subdirectory(wasmedge_process) endif() endif() if(WASMEDGE_PLUGIN_ZLIB) - add_subdirectory(wasmedge_zlib) + add_subdirectory(wasmedge_zlib) endif() if(WASMEDGE_PLUGIN_WASI_NN_BACKEND) diff --git a/test/plugins/wasmedge_ffmpeg/CMakeLists.txt b/test/plugins/wasmedge_ffmpeg/CMakeLists.txt new file mode 100644 index 000000000000..c35e0bc421ae --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/CMakeLists.txt @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +wasmedge_add_executable(wasmedgeFFmpegTests + main.cpp + + avcodec/avcodec_func.cpp + avcodec/avCodec.cpp + avcodec/avCodecParameters.cpp + avcodec/avPacket.cpp + avcodec/avCodecCtx.cpp + + avfilter/avfilter_func.cpp + avfilter/avfilter.cpp + + avformat/avformat_func.cpp + avformat/avformatContext.cpp + avformat/avInputOutputContext.cpp + avformat/avStream.cpp + avformat/avChapter.cpp + + avutil/avRational.cpp + avutil/avDictionary.cpp + avutil/avFrame.cpp + avutil/avutil_func.cpp + avutil/avError.cpp + avutil/avSampleFmt.cpp + avutil/avPixfmt.cpp + + swscale/swscale_func.cpp + + swresample/swresample_func.cpp + + utils.cpp +) + +# Downloading a sample file +execute_process( + COMMAND bash ${CMAKE_SOURCE_DIR}/utils/ffmpeg/download-ffmpeg-sample-video.sh ${CMAKE_CURRENT_BINARY_DIR}/ffmpeg-assets + RESULT_VARIABLE DOWNLOAD_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +add_dependencies(wasmedgeFFmpegTests + wasmedgePluginWasmEdgeFFmpeg +) + +target_include_directories(wasmedgeFFmpegTests + PUBLIC + $ + $ + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(wasmedgeFFmpegTests + PRIVATE + wasmedgePluginWasmEdgeFFmpeg + ${GTEST_BOTH_LIBRARIES} +) + +# Link to the WasmEdge library +if(WASMEDGE_LINK_PLUGINS_STATIC) + target_link_libraries(wasmedgeFFmpegTests + PRIVATE + wasmedgeCAPI + ) +else() + target_link_libraries(wasmedgeFFmpegTests + PRIVATE + wasmedge_shared + ) +endif() + +add_test(wasmedgeFFmpegTests wasmedgeFFmpegTests) diff --git a/test/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp b/test/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp new file mode 100644 index 000000000000..6eb3a3d4ebab --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avcodec/avCodec.cpp @@ -0,0 +1,365 @@ +#include "avcodec/avCodec.h" +#include "avcodec/module.h" +#include "utils.h" + +#include + +// Testing all AVCodecstruct + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVCodec) { + + ASSERT_TRUE(AVCodecMod != nullptr); + + uint32_t AVCodecPtr = UINT32_C(20); + uint32_t StringPtr = UINT32_C(68); + uint32_t NumeratorPtr = UINT32_C(72); + uint32_t DenominatorPtr = UINT32_C(76); + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + spdlog::info("Init FFmpeg Structs"sv); + initFFmpegStructs(AVCodecPtr, UINT32_C(24), UINT32_C(28), FileName, + UINT32_C(60), UINT32_C(64), UINT32_C(68), UINT32_C(72)); + + uint32_t AVCodecId = readUInt32(MemInst, AVCodecPtr); + auto *FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_id"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecID = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecId"sv); + { + EXPECT_TRUE(HostFuncAVCodecID.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 27); // H264 + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecType = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecType"sv); + { + EXPECT_TRUE(HostFuncAVCodecType.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), + 0); // MediaType is Video + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_max_lowres"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecMaxLowres = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecMaxLowres"sv); + { + EXPECT_TRUE(HostFuncAVCodecMaxLowres.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_capabilities"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCapabilities = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCapabilities &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecCapabilities"sv); + { + EXPECT_TRUE(HostFuncAVCodecCapabilities.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_TRUE(Result[0].get() > 0); + } + + int32_t Length = 0; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_get_name_len"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecGetNameLen = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecGetNameLen &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecGetNameLen"sv); + { + EXPECT_TRUE(HostFuncAVCodecGetNameLen.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_get_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecGetName = + dynamic_cast( + FuncInst->getHostFunc()); + + // Fill the Memory with 0. + fillMemContent(MemInst, StringPtr, Length); + spdlog::info("Testing AVCodecGetName"sv); + { + EXPECT_TRUE( + HostFuncAVCodecGetName.run(CallFrame, + std::initializer_list{ + AVCodecId, StringPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_get_long_name_len"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecGetLongNameLen = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecGetLongNameLen &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecGetLongNameLen"sv); + { + EXPECT_TRUE(HostFuncAVCodecGetLongNameLen.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_get_long_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecGetLongName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecGetLongName &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecGetLongName"sv); + { + EXPECT_TRUE(HostFuncAVCodecGetLongName.run( + CallFrame, + std::initializer_list{AVCodecId, StringPtr, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_profiles"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecProfiles = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecProfiles"sv); + { + EXPECT_TRUE(HostFuncAVCodecProfiles.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_pix_fmts_is_null"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecPixFmtIsNull = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecPixFmtsIsNull &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecPixFmtsIsNull"sv); + { + EXPECT_TRUE(HostFuncAVCodecPixFmtIsNull.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_pix_fmts_iter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecPixFmtIter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecPixFmtsIter &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecPixFmtsIter"sv); + { + uint32_t Idx = 0; + EXPECT_TRUE(HostFuncAVCodecPixFmtIter.run( + CallFrame, std::initializer_list{AVCodecId, Idx}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_supported_framerate_is_null"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSupportedFrameratesIsNull = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSupportedFrameratesIsNull + &>(FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSupportedFramratesIsNull"sv); + { + EXPECT_TRUE(HostFuncAVCodecSupportedFrameratesIsNull.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_supported_framerate_iter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSupportedFrameratesIter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSupportedFrameratesIter + &>(FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSupportedFrameratesIter"sv); + { + EXPECT_TRUE(HostFuncAVCodecSupportedFrameratesIter.run( + CallFrame, + std::initializer_list{AVCodecId, 1, NumeratorPtr, + DenominatorPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_supported_samplerates_is_null"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSupportedSampleRatesIsNull = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSupportedSampleRatesIsNull + &>(FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSupportedSampleRatesIsNull"sv); + { + EXPECT_TRUE(HostFuncAVCodecSupportedSampleRatesIsNull.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_supported_samplerates_iter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSupportedSampleRatesIter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSupportedSampleRatesIter + &>(FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSupportedSampleRatesIter"sv); + { + EXPECT_TRUE(HostFuncAVCodecSupportedSampleRatesIter.run( + CallFrame, std::initializer_list{AVCodecId, 0}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_channel_layouts_is_null"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecChannelLayoutIsNull = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecChannelLayoutIsNull &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecChannelLayoutIsNull"sv); + { + EXPECT_TRUE(HostFuncAVCodecChannelLayoutIsNull.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_channel_layouts_iter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecChannelLayoutIter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecChannelLayoutIter &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecChannelLayoutIter"sv); + { + EXPECT_TRUE(HostFuncAVCodecChannelLayoutIter.run( + CallFrame, std::initializer_list{AVCodecId, 0}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_sample_fmts_is_null"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSampleFmtsIsNull = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSampleFmtsIsNull &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSampleFmtsIsNull"sv); + { + EXPECT_TRUE(HostFuncAVCodecSampleFmtsIsNull.run( + CallFrame, std::initializer_list{AVCodecId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_sample_fmts_iter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSampleFmtsIter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSampleFmtsIter &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSampleFmtsIter"sv); + { + EXPECT_TRUE(HostFuncAVCodecSampleFmtsIter.run( + CallFrame, std::initializer_list{AVCodecId, 0}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } +} +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avcodec/avCodecCtx.cpp b/test/plugins/wasmedge_ffmpeg/avcodec/avCodecCtx.cpp new file mode 100644 index 000000000000..b89128f8971f --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avcodec/avCodecCtx.cpp @@ -0,0 +1,1657 @@ +#include "avcodec/avCodecContext.h" +#include "avcodec/module.h" +#include "utils.h" + +#include + +// Testing all AVCodecCtxstruct +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVCodecCtx) { + ASSERT_TRUE(AVCodecMod != nullptr); + + uint32_t AVCodecCtxPtr = UINT32_C(64); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFFmpegStructs(UINT32_C(20), UINT32_C(24), UINT32_C(28), FileName, + UINT32_C(60), AVCodecCtxPtr, UINT32_C(68), UINT32_C(72)); + uint32_t NumPtr = UINT32_C(76); + uint32_t DenPtr = UINT32_C(80); + uint32_t AVCodecPtr = UINT32_C(84); + + uint32_t AVCodecCtxId = readUInt32(MemInst, AVCodecCtxPtr); + + auto *FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_codec_id"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxCodecID = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxCodecID &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxCodecID.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 27); // H264 + } + + int32_t CodecType = 0; // MediaType Video + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_codec_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetCodecType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetCodecType &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetCodecType.run( + CallFrame, + std::initializer_list{AVCodecCtxId, CodecType}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_codec_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxCodecType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxCodecType &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxCodecType.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), CodecType); // MediaType Video + } + + int32_t Num = 5; + int32_t Den = 10; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_time_base"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetTimebase = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetTimebase &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetTimebase.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Num, Den}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_time_base"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxTimeBase = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxTimeBase &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxTimeBase.run( + CallFrame, + std::initializer_list{AVCodecCtxId, NumPtr, + DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + int32_t Numerator = readSInt32(MemInst, NumPtr); + int32_t Denominator = readSInt32(MemInst, DenPtr); + EXPECT_EQ(Numerator, Num); + EXPECT_EQ(Denominator, Den); + } + + int32_t Dimension = 200; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_width"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetWidth = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetWidth &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetWidth.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Dimension}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_width"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxWidth = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxWidth.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), Dimension); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_height"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetHeight = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetHeight &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetHeight.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Dimension}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_height"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxHeight = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxHeight.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), Dimension); + } + + Num = 10; + Den = 20; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_sample_aspect_ratio"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSampleAspectRatio = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSampleAspectRatio + &>(FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetSampleAspectRatio.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Num, Den}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_sample_aspect_ratio"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSampleAspectRatio = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSampleAspectRatio &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSampleAspectRatio.run( + CallFrame, + std::initializer_list{AVCodecCtxId, NumPtr, + DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + int32_t Numerator = readSInt32(MemInst, NumPtr); + int32_t Denominator = readSInt32(MemInst, DenPtr); + EXPECT_EQ(Numerator, Num); + EXPECT_EQ(Denominator, Den); + } + + uint64_t ChannelLayoutId = 1; // FRONT_LEFT; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_channel_layout"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetChannelLayout = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetChannelLayout &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetChannelLayout.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + ChannelLayoutId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_channel_layout"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxChannelLayout = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxChannelLayout &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxChannelLayout.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), ChannelLayoutId); + } + + uint32_t PixFormatId = 1; // YUV420P + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_pix_fmt"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetPixFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetPixFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetPixFormat.run( + CallFrame, + std::initializer_list{AVCodecCtxId, PixFormatId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_pix_fmt"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxPixFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxPixFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxPixFormat.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), PixFormatId); + } + + uint32_t SampleFmtId = 1; // SAMPLE_FMT_U8 + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_sample_format"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSampleFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSampleFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetSampleFormat.run( + CallFrame, + std::initializer_list{AVCodecCtxId, SampleFmtId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_sample_format"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSampleFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSampleFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSampleFormat.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), SampleFmtId); + } + + int32_t SampleRate = 500; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_sample_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSampleRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSampleRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetSampleRate.run( + CallFrame, + std::initializer_list{AVCodecCtxId, SampleRate}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_sample_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSampleRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSampleRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSampleRate.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), SampleRate); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_gop_size"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetGopSize = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetGopSize &>( + FuncInst->getHostFunc()); + + { + int32_t GopSize = 20; + EXPECT_TRUE(HostFuncAVCodecCtxSetGopSize.run( + CallFrame, + std::initializer_list{AVCodecCtxId, GopSize}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_max_b_frames"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMaxBFrames = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMaxBFrames &>( + FuncInst->getHostFunc()); + + { + int32_t MaxBFrames = 30; + EXPECT_TRUE(HostFuncAVCodecCtxSetMaxBFrames.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MaxBFrames}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_b_quant_factor"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetBQuantFactor = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetBQuantFactor &>( + FuncInst->getHostFunc()); + + { + float BQuantFactor = 12.32; + EXPECT_TRUE(HostFuncAVCodecCtxSetBQuantFactor.run( + CallFrame, + std::initializer_list{AVCodecCtxId, BQuantFactor}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_b_quant_offset"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetBQuantOffset = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetBQuantOffset &>( + FuncInst->getHostFunc()); + + { + float BQuantOffset = 3.53; + EXPECT_TRUE(HostFuncAVCodecCtxSetBQuantOffset.run( + CallFrame, + std::initializer_list{AVCodecCtxId, BQuantOffset}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_i_quant_factor"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetIQuantFactor = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetIQuantFactor &>( + FuncInst->getHostFunc()); + + { + float IQuantFactor = 3.435; + EXPECT_TRUE(HostFuncAVCodecCtxSetIQuantFactor.run( + CallFrame, + std::initializer_list{AVCodecCtxId, IQuantFactor}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_i_quant_offset"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetIQuantOffset = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetIQuantOffset &>( + FuncInst->getHostFunc()); + + { + float IQuantOffset = 6.322; + EXPECT_TRUE(HostFuncAVCodecCtxSetIQuantOffset.run( + CallFrame, + std::initializer_list{AVCodecCtxId, IQuantOffset}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_lumi_masking"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetLumiMasking = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetLumiMasking &>( + FuncInst->getHostFunc()); + + { + float LumiMasking = 54.32432; + EXPECT_TRUE(HostFuncAVCodecCtxSetLumiMasking.run( + CallFrame, + std::initializer_list{AVCodecCtxId, LumiMasking}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_temporal_cplx_masking"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetTemporalCplxMasking = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetTemporalCplxMasking + &>(FuncInst->getHostFunc()); + + { + float TemporialCplxMasking = 642.32; + EXPECT_TRUE(HostFuncAVCodecCtxSetTemporalCplxMasking.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + TemporialCplxMasking}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_spatial_cplx_masking"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSpatialCplxMasking = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSpatialCplxMasking + &>(FuncInst->getHostFunc()); + + { + float SpatialCplxMasking = 324.32; + EXPECT_TRUE(HostFuncAVCodecCtxSetSpatialCplxMasking.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + SpatialCplxMasking}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_p_masking"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetPMasking = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetPMasking &>( + FuncInst->getHostFunc()); + + { + float PMasking = 65.3245; + EXPECT_TRUE(HostFuncAVCodecCtxSetPMasking.run( + CallFrame, + std::initializer_list{AVCodecCtxId, PMasking}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_dark_masking"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetDarkMasking = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetDarkMasking &>( + FuncInst->getHostFunc()); + + { + float DarkMasking = 83.32; + EXPECT_TRUE(HostFuncAVCodecCtxSetDarkMasking.run( + CallFrame, + std::initializer_list{AVCodecCtxId, DarkMasking}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_cmp"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMeCmp = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMeCmp &>( + FuncInst->getHostFunc()); + + { + int32_t MeCmp = 532; + EXPECT_TRUE(HostFuncAVCodecCtxSetMeCmp.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MeCmp}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_sub_cmp"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMeSubCmp = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMeSubCmp &>( + FuncInst->getHostFunc()); + + { + int32_t MeSubCmp = 321; + EXPECT_TRUE(HostFuncAVCodecCtxSetMeSubCmp.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MeSubCmp}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_cmp"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMbCmp = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMbCmp &>( + FuncInst->getHostFunc()); + + { + int32_t MbCmp = 243; + EXPECT_TRUE(HostFuncAVCodecCtxSetMbCmp.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MbCmp}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_ildct_cmp"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetIldctCmp = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetIldctCmp &>( + FuncInst->getHostFunc()); + + { + int32_t IldctCmp = 3; + EXPECT_TRUE(HostFuncAVCodecCtxSetIldctCmp.run( + CallFrame, + std::initializer_list{AVCodecCtxId, IldctCmp}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_dia_size"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetDiaSize = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetDiaSize &>( + FuncInst->getHostFunc()); + + { + int32_t DiaSize = 9; + EXPECT_TRUE(HostFuncAVCodecCtxSetDiaSize.run( + CallFrame, + std::initializer_list{AVCodecCtxId, DiaSize}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_last_predictor_count"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetLastPredictorsCount = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetLastPredictorsCount + &>(FuncInst->getHostFunc()); + + { + int32_t LastPredictorCount = 21; + EXPECT_TRUE(HostFuncAVCodecCtxSetLastPredictorsCount.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + LastPredictorCount}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_pre_cmp"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMePreCmp = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMePreCmp &>( + FuncInst->getHostFunc()); + + { + int32_t MePreCmp = 53; + EXPECT_TRUE(HostFuncAVCodecCtxSetMePreCmp.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MePreCmp}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_pre_dia_size"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetPreDiaSize = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetPreDiaSize &>( + FuncInst->getHostFunc()); + + { + int32_t PreDiaSize = 74; + EXPECT_TRUE(HostFuncAVCodecCtxSetPreDiaSize.run( + CallFrame, + std::initializer_list{AVCodecCtxId, PreDiaSize}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_subpel_quality"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMeSubpelQuality = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMeSubpelQuality &>( + FuncInst->getHostFunc()); + + { + int32_t MeSubpelQuality = 85; + EXPECT_TRUE(HostFuncAVCodecCtxSetMeSubpelQuality.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + MeSubpelQuality}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_me_range"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMeRange = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMeRange &>( + FuncInst->getHostFunc()); + + { + int32_t SetMeRange = 31; + EXPECT_TRUE(HostFuncAVCodecCtxSetMeRange.run( + CallFrame, + std::initializer_list{AVCodecCtxId, SetMeRange}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_decision"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMbDecision = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMbDecision &>( + FuncInst->getHostFunc()); + + { + int32_t MbDecision = 78; + EXPECT_TRUE(HostFuncAVCodecCtxSetMbDecision.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MbDecision}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_lmin"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMbLMin = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMbLMin &>( + FuncInst->getHostFunc()); + + { + int32_t MbLMin = 11; + EXPECT_TRUE(HostFuncAVCodecCtxSetMbLMin.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MbLMin}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_mb_lmax"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetMbLMax = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetMbLMax &>( + FuncInst->getHostFunc()); + + { + int32_t MbLMax = 18; + EXPECT_TRUE(HostFuncAVCodecCtxSetMbLMax.run( + CallFrame, + std::initializer_list{AVCodecCtxId, MbLMax}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_intra_dc_precision"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + int32_t IntraDcPrecision = 323; + auto &HostFuncAVCodecCtxSetIntraDcPrecision = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetIntraDcPrecision &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetIntraDcPrecision.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + IntraDcPrecision}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_intra_dc_precision"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxIntraDcPrecision = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxIntraDcPrecision &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxIntraDcPrecision.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), IntraDcPrecision); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_qmin"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetQMin = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetQMin &>( + FuncInst->getHostFunc()); + + { + int32_t QMin = 10; + EXPECT_TRUE(HostFuncAVCodecCtxSetQMin.run( + CallFrame, + std::initializer_list{AVCodecCtxId, QMin}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_qmax"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetQMax = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetQMax &>( + FuncInst->getHostFunc()); + + { + int32_t QMax = 20; + EXPECT_TRUE(HostFuncAVCodecCtxSetQMax.run( + CallFrame, + std::initializer_list{AVCodecCtxId, QMax}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_global_quality"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetGlobalQuality = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetGlobalQuality &>( + FuncInst->getHostFunc()); + + { + int32_t GlobalQuality = 93; + EXPECT_TRUE(HostFuncAVCodecCtxSetGlobalQuality.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + GlobalQuality}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_colorspace"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetColorspace = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetColorspace &>( + FuncInst->getHostFunc()); + + int32_t ColorspaceId = 1; // AVCOL_SPC_BT709 + { + EXPECT_TRUE(HostFuncAVCodecCtxSetColorspace.run( + CallFrame, + std::initializer_list{AVCodecCtxId, ColorspaceId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_colorspace"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxColorspace = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxColorspace &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxColorspace.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), ColorspaceId); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_color_range"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetColorRange = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetColorRange &>( + FuncInst->getHostFunc()); + + int32_t ColorRangeId = 1; // MPEG + { + EXPECT_TRUE(HostFuncAVCodecCtxSetColorRange.run( + CallFrame, + std::initializer_list{AVCodecCtxId, ColorRangeId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_color_range"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxColorRange = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxColorRange &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxColorRange.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), ColorRangeId); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_frame_size"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxFrameSize = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxFrameSize &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxFrameSize.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_bit_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetBitRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetBitRate &>( + FuncInst->getHostFunc()); + + int64_t BitRate = 9932; + { + EXPECT_TRUE(HostFuncAVCodecCtxSetBitRate.run( + CallFrame, + std::initializer_list{AVCodecCtxId, BitRate}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_bit_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxBitRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxBitRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxBitRate.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), BitRate); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_rc_max_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + int64_t RcMaxRate = 3245; + auto &HostFuncAVCodecCtxSetRcMaxRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetRcMaxRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetRcMaxRate.run( + CallFrame, + std::initializer_list{AVCodecCtxId, RcMaxRate}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_rc_max_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxRcMaxRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxRcMaxRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxRcMaxRate.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), RcMaxRate); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_bit_rate_tolerance"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetBitRateTolerance = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetBitRateTolerance &>( + FuncInst->getHostFunc()); + + { + int32_t BitRateTolerance = 9543; + EXPECT_TRUE(HostFuncAVCodecCtxSetBitRateTolerance.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + BitRateTolerance}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_compression_level"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetCompressionLevel = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetCompressionLevel &>( + FuncInst->getHostFunc()); + + { + int32_t CompressionLevel = 934; + EXPECT_TRUE(HostFuncAVCodecCtxSetCompressionLevel.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + CompressionLevel}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_framerate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + Num = 20; + Den = 30; + auto &HostFuncAVCodecCtxSetFrameRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetFrameRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetFrameRate.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Num, Den}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_framerate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxFrameRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxFrameRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxFrameRate.run( + CallFrame, + std::initializer_list{AVCodecCtxId, NumPtr, + DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + int32_t Numerator = readSInt32(MemInst, NumPtr); + int32_t Denominator = readSInt32(MemInst, DenPtr); + EXPECT_EQ(Numerator, Num); + EXPECT_EQ(Denominator, Den); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_flags"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetFlags = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetFlags &>( + FuncInst->getHostFunc()); + + { + int32_t Flags = 3; + EXPECT_TRUE(HostFuncAVCodecCtxSetFlags.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Flags}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_strict_std_compliance"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetStrictStdCompliance = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetStrictStdCompliance + &>(FuncInst->getHostFunc()); + + { + int32_t ComplianceId = 3; + EXPECT_TRUE(HostFuncAVCodecCtxSetStrictStdCompliance.run( + CallFrame, + std::initializer_list{AVCodecCtxId, ComplianceId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_debug"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetDebug = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetDebug &>( + FuncInst->getHostFunc()); + + { + int32_t Debug = 50; + EXPECT_TRUE(HostFuncAVCodecCtxSetDebug.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Debug}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_codec"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxCodec = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxCodec.run( + CallFrame, + std::initializer_list{AVCodecCtxId, AVCodecPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, AVCodecPtr) > 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_channels"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetChannels = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetChannels &>( + FuncInst->getHostFunc()); + + int32_t Channels = 10; + { + EXPECT_TRUE(HostFuncAVCodecCtxSetChannels.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Channels}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_channels"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxChannels = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxChannels &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxChannels.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), Channels); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_loop_filter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSkipLoopFilter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSkipLoopFilter &>( + FuncInst->getHostFunc()); + + int32_t DiscardId = 16; // Bidirectional + { + EXPECT_TRUE(HostFuncAVCodecCtxSetSkipLoopFilter.run( + CallFrame, + std::initializer_list{AVCodecCtxId, DiscardId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSkipFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSkipFrame &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetSkipFrame.run( + CallFrame, + std::initializer_list{AVCodecCtxId, DiscardId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_idct"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSkipIdct = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSkipIdct &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetSkipIdct.run( + CallFrame, + std::initializer_list{AVCodecCtxId, DiscardId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_error_concealment"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetErrorConcealment = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetErrorConcealment &>( + FuncInst->getHostFunc()); + + { + int32_t ErrorConcealment = 99; + EXPECT_TRUE(HostFuncAVCodecCtxSetErrorConcealment.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + ErrorConcealment}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_err_recognition"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetErrorRecognition = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetErrorRecognition &>( + FuncInst->getHostFunc()); + + { + int32_t ErrorRecognition = 88; + EXPECT_TRUE(HostFuncAVCodecCtxSetErrorRecognition.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + ErrorRecognition}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_delay"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxDelay = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxDelay.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_top"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSkipTop = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSkipTop &>( + FuncInst->getHostFunc()); + + { + int32_t Value = 50; + EXPECT_TRUE(HostFuncAVCodecCtxSetSkipTop.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Value}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_skip_bottom"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSkipBottom = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSkipBottom &>( + FuncInst->getHostFunc()); + + { + int32_t Value = 60; + EXPECT_TRUE(HostFuncAVCodecCtxSetSkipBottom.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Value}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_refs"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxRefs = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxRefs.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 4); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_slice_flags"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSliceFlags = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSliceFlags &>( + FuncInst->getHostFunc()); + + { + int32_t Value = 70; + EXPECT_TRUE(HostFuncAVCodecCtxSetSliceFlags.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Value}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_slice_count"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetSliceCount = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetSliceCount &>( + FuncInst->getHostFunc()); + + { + int32_t Value = 100; + EXPECT_TRUE(HostFuncAVCodecCtxSetSliceCount.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Value}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_field_order"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetFieldOrder = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetFieldOrder &>( + FuncInst->getHostFunc()); + + { + int32_t Value = 200; + EXPECT_TRUE(HostFuncAVCodecCtxSetFieldOrder.run( + CallFrame, + std::initializer_list{AVCodecCtxId, Value}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_color_trc"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxColorTrc = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxColorTrc &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxColorTrc.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + ASSERT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_chroma_sample_location"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxChromaSampleLocation = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxChromaSampleLocation + &>(FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxChromaSampleLocation.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_frame_number"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxFrameNumber = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxFrameNumber &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxFrameNumber.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_block_align"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxBlockAlign = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxBlockAlign &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxBlockAlign.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_request_sample_fmt"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetRequestSampleFmt = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetRequestSampleFmt &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetRequestSampleFmt.run( + CallFrame, + std::initializer_list{AVCodecCtxId, SampleFmtId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_audio_service_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxAudioServiceType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxAudioServiceType &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxAudioServiceType.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_has_b_frames"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxHasBFrames = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxHasBFrames &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxHasBFrames.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + ASSERT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_request_channel_layout"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetRequestChannelLayout = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetRequestChannelLayout + &>(FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxSetRequestChannelLayout.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + ChannelLayoutId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_active_thread_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxActiveThreadType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxActiveThreadType &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxActiveThreadType.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_thread_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetThreadType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetThreadType &>( + FuncInst->getHostFunc()); + + { + int32_t ThreadType = 1; // Frame + EXPECT_TRUE(HostFuncAVCodecCtxSetThreadType.run( + CallFrame, + std::initializer_list{AVCodecCtxId, ThreadType}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_set_thread_count"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxSetThreadCount = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxSetThreadCount &>( + FuncInst->getHostFunc()); + + int32_t ThreadCount = 50; + { + EXPECT_TRUE(HostFuncAVCodecCtxSetThreadCount.run( + CallFrame, + std::initializer_list{AVCodecCtxId, ThreadCount}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_thread_count"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxThreadCount = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxThreadCount &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxThreadCount.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), ThreadCount); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_color_primaries"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecCtxColorPrimaries = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxColorPrimaries &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecCtxColorPrimaries.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp b/test/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp new file mode 100644 index 000000000000..1217914e73e5 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avcodec/avCodecParameters.cpp @@ -0,0 +1,75 @@ +#include "avcodec/avCodecParameters.h" +#include "avcodec/module.h" +#include "utils.h" + +#include + +// Testing all AVCodecstruct + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVCodecParameters) { + ASSERT_TRUE(AVCodecMod != nullptr); + + uint32_t AVCodecParamPtr = UINT32_C(60); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFFmpegStructs(UINT32_C(20), UINT32_C(24), UINT32_C(28), FileName, + AVCodecParamPtr, UINT32_C(64), UINT32_C(68), UINT32_C(72)); + + uint32_t AVCodecParamId = readUInt32(MemInst, AVCodecParamPtr); + + auto *FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodecparam_codec_id"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParamCodecId = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParamCodecId &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecParamCodecId.run( + CallFrame, std::initializer_list{AVCodecParamId}, + Result)); + EXPECT_EQ(Result[0].get(), 27); // H264 + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodecparam_codec_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParamCodecType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParamCodecType &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecParamCodecType.run( + CallFrame, std::initializer_list{AVCodecParamId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); // MediaType Video + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodecparam_set_codec_tag"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParamSetCodecTag = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParamSetCodecTag &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVCodecParamSetCodecTag.run( + CallFrame, + std::initializer_list{AVCodecParamId, 20}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp b/test/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp new file mode 100644 index 000000000000..4d7348a36565 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avcodec/avPacket.cpp @@ -0,0 +1,368 @@ +#include "avcodec/avPacket.h" +#include "avcodec/module.h" +#include "utils.h" + +#include + +// Testing all AVPacket + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVPacketTest) { + + ASSERT_TRUE(AVCodecMod != nullptr); + + uint32_t PacketPtr = UINT32_C(4); + uint32_t PacketPtr2 = UINT32_C(8); + uint32_t DataPtr = UINT32_C(12); + + auto *FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_alloc"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVPacketAlloc = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketAlloc.run( + CallFrame, std::initializer_list{PacketPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVPacketAlloc.run( + CallFrame, std::initializer_list{PacketPtr2}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t PacketId = readUInt32(MemInst, PacketPtr); + uint32_t PacketId2 = readUInt32(MemInst, PacketPtr2); + ASSERT_TRUE(PacketId > 0); + ASSERT_TRUE(PacketId2 > 0); + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_new_packet"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVNewPacket = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t Size = 40; + EXPECT_TRUE(HostFuncAVNewPacket.run( + CallFrame, std::initializer_list{PacketId, Size}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_grow_packet"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVGrowPacket = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t Size = 40; + EXPECT_TRUE(HostFuncAVGrowPacket.run( + CallFrame, std::initializer_list{PacketId, Size}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_shrink_packet"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVShrinkPacket = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t Size = 40; + EXPECT_TRUE(HostFuncAVShrinkPacket.run( + CallFrame, std::initializer_list{PacketId, Size}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + uint32_t StreamIdx = 3; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_set_stream_index"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSetStreamIndex = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketSetStreamIndex &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSetStreamIndex.run( + CallFrame, + std::initializer_list{PacketId, StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_stream_index"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketStreamIndex = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketStreamIndex &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketStreamIndex.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), StreamIdx); + } + + uint32_t Size = 0; + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_size"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSize = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSize.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + Size = Result[0].get(); + EXPECT_TRUE(Size > 0); + } + + uint32_t Flags = 5; + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_set_flags"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSetFlags = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSetFlags.run( + CallFrame, std::initializer_list{PacketId, Flags}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_flags"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketFlags = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketFlags.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), Flags); + } + + int64_t Pos = 500; + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_set_pos"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSetPos = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSetPos.run( + CallFrame, std::initializer_list{PacketId, Pos}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_pos"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketPos = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketPos.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), Pos); + } + + int64_t Duration = 100; + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_set_duration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSetDuration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketSetDuration &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSetDuration.run( + CallFrame, + std::initializer_list{PacketId, Duration}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_duration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketDuration = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketDuration.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), Duration); + } + + int64_t Dts = 1000; + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_set_dts"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSetDts = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSetDts.run( + CallFrame, std::initializer_list{PacketId, Dts}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_dts"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketDts = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketDts.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), Dts); + } + + int64_t Pts = 5000; + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_set_pts"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketSetPts = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketSetPts.run( + CallFrame, std::initializer_list{PacketId, Pts}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_pts"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketPts = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketPts.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), Pts); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_is_data_null"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketIsDataNull = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketIsDataNull &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketIsDataNull.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_data"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVPacketData = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketData.run( + CallFrame, + std::initializer_list{PacketId, DataPtr, Size}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_ref"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVPacketRef = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketRef.run( + CallFrame, + std::initializer_list{PacketId2, PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_unref"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVPacketUnref = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVPacketUnref.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp b/test/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp new file mode 100644 index 000000000000..d5fcc6b02577 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avcodec/avcodec_func.cpp @@ -0,0 +1,574 @@ +#include "avcodec/avcodec_func.h" +#include "avcodec/module.h" + +#include "utils.h" +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +// TODO: Commented functions need to be tested. + +TEST_F(FFmpegTest, AVCodecFunc) { + ASSERT_TRUE(AVCodecMod != nullptr); + + uint32_t CodecCtxPtr = UINT32_C(4); + uint32_t CodecParamPtr = UINT32_C(8); + uint32_t CodecParamPtr2 = UINT32_C(20); + uint32_t CodecDecoderPtr = UINT32_C(12); + uint32_t CodecEncoderPtr = UINT32_C(16); + uint32_t StrPtr = UINT32_C(32); + + uint32_t CodecNamePtr = UINT32_C(150); + std::string CodecName = "mpeg1video"; + spdlog::info("Filling memory CodecName into CodecNamePtr"sv); + fillMemContent(MemInst, CodecNamePtr, CodecName); + + uint32_t ID = 1; + + auto *FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_alloc_context3"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecAllocContext3 = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecAllocContext3 &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AvCodecAllocContext3"sv); + { + EXPECT_TRUE(HostFuncAVCodecAllocContext3.run( + CallFrame, std::initializer_list{0, CodecCtxPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t AVCodecCtxId = readUInt32(MemInst, CodecCtxPtr); + ASSERT_TRUE(AVCodecCtxId > 0); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_parameters_alloc"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParametersAlloc = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParametersAlloc &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecParametersAlloc"sv); + { + EXPECT_TRUE(HostFuncAVCodecParametersAlloc.run( + CallFrame, std::initializer_list{CodecParamPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVCodecParametersAlloc.run( + CallFrame, std::initializer_list{CodecParamPtr2}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t AVCodecParamId = readUInt32(MemInst, CodecParamPtr); + ASSERT_TRUE(AVCodecParamId > 0); + + uint32_t AVCodecParamId2 = readUInt32(MemInst, CodecParamPtr2); + ASSERT_TRUE(AVCodecParamId2 > 0); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_parameters_from_context"sv); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParametersFromContext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParametersFromContext &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecParametersFromContext"sv); + { + EXPECT_TRUE(HostFuncAVCodecParametersFromContext.run( + CallFrame, + std::initializer_list{AVCodecParamId, + AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_get_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecGetType = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecGetType"sv); + { + EXPECT_TRUE(HostFuncAVCodecGetType.run( + CallFrame, std::initializer_list{ID}, Result)); + EXPECT_EQ(Result[0].get(), 0); // Video Type + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_find_decoder"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecFindDecoder = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFindDecoder &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecFindDecoder"sv); + { + EXPECT_TRUE(HostFuncAVCodecFindDecoder.run( + CallFrame, + std::initializer_list{ID, CodecDecoderPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t AVCodecDecoderId = readUInt32(MemInst, CodecDecoderPtr); + ASSERT_TRUE(AVCodecDecoderId > 0); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_find_encoder"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecFindEncoder = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFindEncoder &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecFindEncoder"sv); + { + EXPECT_TRUE(HostFuncAVCodecFindEncoder.run( + CallFrame, + std::initializer_list{ID, CodecEncoderPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t AVCodecEncoderId = readUInt32(MemInst, CodecEncoderPtr); + ASSERT_TRUE(AVCodecEncoderId > 0); + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_open2"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecOpen2 = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecOpen2"sv); + // Invalid argument passed. Return -22 Error code. Means functionality + // working. + { + EXPECT_TRUE( + HostFuncAVCodecOpen2.run(CallFrame, + std::initializer_list{ + AVCodecCtxId, AVCodecEncoderId, 0}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_codec_is_encoder"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecIsEncoder = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecIsEncoder"sv); + { + EXPECT_TRUE(HostFuncAVCodecIsEncoder.run( + CallFrame, + std::initializer_list{AVCodecEncoderId}, Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_codec_is_decoder"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecIsDecoder = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecIsDecoder"sv); + { + EXPECT_TRUE(HostFuncAVCodecIsDecoder.run( + CallFrame, + std::initializer_list{AVCodecDecoderId}, Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_find_decoder_by_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecFindDecoderByName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFindDecoderByName &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecFindDecoderByName"sv); + { + uint32_t Length = CodecName.length(); + EXPECT_TRUE(HostFuncAVCodecFindDecoderByName.run( + CallFrame, + std::initializer_list{CodecDecoderPtr, + CodecNamePtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_find_encoder_by_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecFindEncoderByName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFindEncoderByName &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecFindEncoderByName"sv); + { + uint32_t Length = CodecName.length(); + EXPECT_TRUE(HostFuncAVCodecFindEncoderByName.run( + CallFrame, + std::initializer_list{CodecEncoderPtr, + CodecNamePtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_parameters_to_context"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParametersToContext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParametersToContext &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecParametersToContext"sv); + { + EXPECT_TRUE(HostFuncAVCodecParametersToContext.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + AVCodecParamId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + // TODO: Need FormatCtxId To test this func. + // FuncInst = AVCodecMod->findFuncExports( + // "wasmedge_ffmpeg_avcodec_avcodec_parameters_copy"); + // EXPECT_NE(FuncInst, nullptr); + // EXPECT_TRUE(FuncInst->isHostFunction()); + // + // auto &HostFuncAVCodecParametersCopy = dynamic_cast< + // WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParametersCopy &>( + // FuncInst->getHostFunc()); + // + // { + // EXPECT_TRUE(HostFuncAVCodecParametersCopy.run( + // CallFrame, std::initializer_list{}, Result)); + // EXPECT_EQ(Result[0].get(), + // static_cast(ErrNo::Success)); + // } + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_version"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecVersion = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecVersion"sv); + { + EXPECT_TRUE(HostFuncAVCodecVersion.run( + CallFrame, std::initializer_list{}, Result)); + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_configuration_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecConfigurationLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecConfigurationLength &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecConfigurationLength"sv); + int32_t Length = 0; + { + EXPECT_TRUE(HostFuncAVCodecConfigurationLength.run( + CallFrame, std::initializer_list{}, Result)); + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_configuration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecConfiguration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecConfiguration &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecConfiguration"sv); + { + EXPECT_TRUE(HostFuncAVCodecConfiguration.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_license_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecLicenseLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecLicenseLength &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecLicenseLength"sv); + { + EXPECT_TRUE(HostFuncAVCodecLicenseLength.run( + CallFrame, std::initializer_list{}, Result)); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_license"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecLicense = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecLicense"sv); + { + EXPECT_TRUE(HostFuncAVCodecLicense.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_free_context"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecFreeContext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFreeContext &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecFreeContext"sv); + { + EXPECT_TRUE(HostFuncAVCodecFreeContext.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_parameters_free"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecParametersFree = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParametersFree &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecParametersFree"sv); + { + EXPECT_TRUE(HostFuncAVCodecParametersFree.run( + CallFrame, std::initializer_list{AVCodecParamId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +TEST_F(FFmpegTest, SendPacketReceiveFrame) { + + std::string FileName = "ffmpeg-assets/dummy.mp4"; // 32 chars + uint32_t CodecCtxPtr = UINT32_C(64); + uint32_t FramePtr = UINT32_C(72); + uint32_t PacketPtr = UINT32_C(68); + initFFmpegStructs(UINT32_C(20), UINT32_C(24), UINT32_C(28), FileName, + UINT32_C(60), CodecCtxPtr, PacketPtr, FramePtr); + + uint32_t FrameId = readUInt32(MemInst, FramePtr); + uint32_t PacketId = readUInt32(MemInst, PacketPtr); + uint32_t CodecCtxId = readUInt32(MemInst, CodecCtxPtr); + + auto *FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_send_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSendFrame = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSendFrame"sv); + // Invalid Argument Error. Should Use Encoder, I'm using decoder + // Aim is to test the functionality. + { + EXPECT_TRUE(HostFuncAVCodecSendFrame.run( + CallFrame, + std::initializer_list{CodecCtxId, FrameId}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } + + // Invalid Argument Error. Should Use Encoder, I'm using decoder + // Aim is to test the functionality. + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_receive_packet"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecReceivePacket = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecReceivePacket &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecReceivePacket"sv); + { + EXPECT_TRUE(HostFuncAVCodecReceivePacket.run( + CallFrame, + std::initializer_list{CodecCtxId, PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_send_packet"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecSendPacket = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSendPacket &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecSendPacket"sv); + // Send packet to Decoder. + { + EXPECT_TRUE(HostFuncAVCodecSendPacket.run( + CallFrame, + std::initializer_list{CodecCtxId, PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_receive_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + // Decoder Receives the Packet as Frame. + auto &HostFuncAVCodecReceiveFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecReceiveFrame &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecReceiveFrame"sv); + { + EXPECT_TRUE(HostFuncAVCodecReceiveFrame.run( + CallFrame, + std::initializer_list{CodecCtxId, FrameId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_rescale_ts"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVPacketRescaleTs = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketRescaleTs &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVPacketRescaleTs"sv); + { + int32_t SrcNum = 2; + int32_t SrcDen = 3; + int32_t DestNum = 5; + int32_t DestDen = 9; + EXPECT_TRUE(HostFuncAVPacketRescaleTs.run( + CallFrame, + std::initializer_list{PacketId, SrcNum, SrcDen, + DestNum, DestDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_make_writable"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVPacketMakeWritable = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketMakeWritable &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVPacketMakeWritable"sv); + { + EXPECT_TRUE(HostFuncAVPacketMakeWritable.run( + CallFrame, std::initializer_list{PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_flush_buffers"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecFlushBuffers = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFlushBuffers &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecFlushBuffers"sv); + { + EXPECT_TRUE(HostFuncAVCodecFlushBuffers.run( + CallFrame, std::initializer_list{CodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_close"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVCodecClose = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVCodecClose"sv); + { + EXPECT_TRUE(HostFuncAVCodecClose.run( + CallFrame, std::initializer_list{CodecCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/avfilter/avfilter.cpp b/test/plugins/wasmedge_ffmpeg/avfilter/avfilter.cpp new file mode 100644 index 000000000000..589301641e5a --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avfilter/avfilter.cpp @@ -0,0 +1,287 @@ +#include "avfilter/avFilter.h" +#include "avfilter//avfilter_func.h" +#include "avfilter/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVFilterStructs) { + ASSERT_TRUE(AVFilterMod != nullptr); + + uint32_t FilterPtr = UINT32_C(8); + uint32_t InputFilterPadPtr = UINT32_C(12); + uint32_t OutputFilterPadPtr = UINT32_C(16); + uint32_t InputNamePtr = UINT32_C(100); + uint32_t StrPtr = UINT32_C(150); + + std::string InputName = std::string("abuffer"); + fillMemContent(MemInst, InputNamePtr, InputName); + + // ================================================================== + // Start Initialize AVFilter + // ================================================================== + + auto *FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_get_by_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGetByName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGetByName &>( + FuncInst->getHostFunc()); + + { + int32_t Length = InputName.length(); + EXPECT_TRUE(HostFuncAVFilterGetByName.run( + CallFrame, + std::initializer_list{FilterPtr, InputNamePtr, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t FilterId = readUInt32(MemInst, FilterPtr); + ASSERT_TRUE(FilterId > 0); + // ================================================================== + // End Initialize AVFilter + // ================================================================== + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_name_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterNameLength &>( + FuncInst->getHostFunc()); + + int32_t Length = 0; + { + EXPECT_TRUE(HostFuncAVFilterNameLength.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = + AVFilterMod->findFuncExports("wasmedge_ffmpeg_avfilter_avfilter_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterName = + dynamic_cast( + FuncInst->getHostFunc()); + + fillMemContent(MemInst, StrPtr, Length); + { + EXPECT_TRUE(HostFuncAVFilterName.run( + CallFrame, + std::initializer_list{FilterId, StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_description_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterDescriptionLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterDescriptionLength &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterDescriptionLength.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_description"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterDescription = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterDescription &>( + FuncInst->getHostFunc()); + + fillMemContent(MemInst, StrPtr, Length); + { + EXPECT_TRUE(HostFuncAVFilterDescription.run( + CallFrame, + std::initializer_list{FilterId, StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_nb_inputs"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterNbInputs = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterNbInputs &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterNbInputs.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_nb_outputs"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterNbOutputs = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterNbOutputs &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterNbOutputs.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = + AVFilterMod->findFuncExports("wasmedge_ffmpeg_avfilter_avfilter_flags"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterFlags = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterFlags.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_get_inputs_filter_pad"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGetInputsFilterPad = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGetInputsFilterPad &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterGetInputsFilterPad.run( + CallFrame, + std::initializer_list{FilterId, + InputFilterPadPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_get_outputs_filter_pad"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGetOutputsFilterPad = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGetOutputsFilterPad &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterGetOutputsFilterPad.run( + CallFrame, + std::initializer_list{FilterId, + OutputFilterPadPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t OutputFilterPadId = readUInt32(MemInst, OutputFilterPadPtr); + ASSERT_TRUE(OutputFilterPadId > 0); + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_pad_get_name_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterPadGetNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterPadGetNameLength &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterPadGetNameLength.run( + CallFrame, + std::initializer_list{OutputFilterPadId, 0}, + Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_pad_get_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterPadGetName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterPadGetName &>( + FuncInst->getHostFunc()); + + { + int32_t Idx = 0; + EXPECT_TRUE(HostFuncAVFilterPadGetName.run( + CallFrame, + std::initializer_list{OutputFilterPadId, Idx, + StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_pad_get_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterPadGetType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterPadGetType &>( + FuncInst->getHostFunc()); + + { + int32_t Idx = 0; + EXPECT_TRUE(HostFuncAVFilterPadGetType.run( + CallFrame, + std::initializer_list{OutputFilterPadId, Idx}, + Result)); + EXPECT_EQ(Result[0].get(), 1); // Audio + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_pad_drop"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterPadDrop = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterPadDrop.run( + CallFrame, + std::initializer_list{OutputFilterPadId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp b/test/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp new file mode 100644 index 000000000000..7a6675feb69d --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avfilter/avfilter_func.cpp @@ -0,0 +1,682 @@ +#include "avfilter//avfilter_func.h" +#include "avfilter/avFilter.h" +#include "avfilter/buffer_source_sink.h" +#include "avfilter/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVFilterFunc) { + + ASSERT_TRUE(AVFilterMod != nullptr); + + // Structs Ptr + uint32_t FilterGraphPtr = UINT32_C(4); + uint32_t FilterPtr = UINT32_C(8); + uint32_t Filter2Ptr = UINT32_C(12); + uint32_t InputFilterCtxPtr = UINT32_C(28); // AVFilterContext + uint32_t OutputFilterCtxPtr = UINT32_C(24); // AVFilterContext + uint32_t InputInOutPtr = UINT32_C(32); + uint32_t OutputInOutPtr = UINT32_C(36); + uint32_t FramePtr = UINT32_C(40); + + // Strings. + uint32_t InputNamePtr = UINT32_C(100); + uint32_t OutputNamePtr = UINT32_C(150); + uint32_t InputFilterNamePtr = UINT32_C(200); + uint32_t OutputFilterNamePtr = UINT32_C(250); + uint32_t ArgsPtr = UINT32_C(300); + uint32_t SpecPtr = UINT32_C(450); + uint32_t StrPtr = UINT32_C(500); + + std::string InputName = std::string("abuffer"); + fillMemContent(MemInst, InputNamePtr, InputName); + + std::string OutputName = std::string("abuffersink"); + fillMemContent(MemInst, OutputNamePtr, OutputName); + + std::string InputFilterName = std::string("in"); + fillMemContent(MemInst, InputFilterNamePtr, InputFilterName); + + std::string OutputFilterName = std::string("out"); + fillMemContent(MemInst, OutputFilterNamePtr, OutputFilterName); + + std::string Args = std::string( + "time_base=1/44100:sample_rate=44100:sample_fmt=fltp:channel_layout=0x3"); + fillMemContent(MemInst, ArgsPtr, Args); + + std::string SpecStr = std::string("anull"); + fillMemContent(MemInst, SpecPtr, SpecStr); + + initEmptyFrame(FramePtr); + uint32_t FrameId = readUInt32(MemInst, FramePtr); + + auto *FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_alloc"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphAlloc = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphAlloc &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterGraphAlloc.run( + CallFrame, std::initializer_list{FilterGraphPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t FilterGraphId = readUInt32(MemInst, FilterGraphPtr); + ASSERT_TRUE(FilterGraphId > 0); + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_get_by_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGetByName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGetByName &>( + FuncInst->getHostFunc()); + + { + int32_t Length = InputName.length(); + EXPECT_TRUE(HostFuncAVFilterGetByName.run( + CallFrame, + std::initializer_list{FilterPtr, InputNamePtr, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + Length = OutputName.length(); + EXPECT_TRUE(HostFuncAVFilterGetByName.run( + CallFrame, + std::initializer_list{Filter2Ptr, OutputNamePtr, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t FilterId = readUInt32(MemInst, FilterPtr); + uint32_t Filter2Id = readUInt32(MemInst, Filter2Ptr); + ASSERT_TRUE(FilterId > 0); + ASSERT_TRUE(Filter2Id > 0); + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_create_filter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphCreateFilter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphCreateFilter &>( + FuncInst->getHostFunc()); + + { + int32_t NameLen = InputFilterName.length(); + int32_t ArgsLen = Args.length(); + EXPECT_TRUE(HostFuncAVFilterGraphCreateFilter.run( + CallFrame, + std::initializer_list{ + InputFilterCtxPtr, FilterId, InputFilterNamePtr, NameLen, ArgsPtr, + ArgsLen, FilterGraphId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + writeUInt32(MemInst, 0, InputFilterCtxPtr); // Setting InputFilterCtx to 0 + + NameLen = OutputFilterName.length(); + EXPECT_TRUE(HostFuncAVFilterGraphCreateFilter.run( + CallFrame, + std::initializer_list{ + OutputFilterCtxPtr, Filter2Id, OutputFilterNamePtr, NameLen, 0, 0, + FilterGraphId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + writeUInt32(MemInst, 0, OutputFilterCtxPtr); // Setting OutputFilterCtx to 0 + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_inout_alloc"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterInOutAlloc = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterInOutAlloc &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterInOutAlloc.run( + CallFrame, std::initializer_list{InputInOutPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVFilterInOutAlloc.run( + CallFrame, std::initializer_list{OutputInOutPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t InputInOutId = readUInt32(MemInst, InputInOutPtr); + ASSERT_TRUE(InputInOutId > 0); + + uint32_t OutputInOutId = readUInt32(MemInst, OutputInOutPtr); + ASSERT_TRUE(OutputInOutId > 0); + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_get_filter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphGetFilter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphGetFilter &>( + FuncInst->getHostFunc()); + + { + int32_t Length = OutputFilterName.length(); + EXPECT_TRUE(HostFuncAVFilterGraphGetFilter.run( + CallFrame, + std::initializer_list{ + OutputFilterCtxPtr, FilterGraphId, OutputFilterNamePtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + Length = InputFilterName.length(); + EXPECT_TRUE(HostFuncAVFilterGraphGetFilter.run( + CallFrame, + std::initializer_list{ + InputFilterCtxPtr, FilterGraphId, InputFilterNamePtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + uint32_t OutputFilterCtxId = readUInt32(MemInst, OutputFilterCtxPtr); + ASSERT_TRUE(OutputFilterCtxId > 0); + + uint32_t InputFilterCtxId = readUInt32(MemInst, InputFilterCtxPtr); + ASSERT_TRUE(InputFilterCtxId > 0); + + // ================================================================== + // Setting InOutId Values for Filtering + // ================================================================== + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_inout_set_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterInOutSetName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterInOutSetName &>( + FuncInst->getHostFunc()); + + { + int32_t Length = InputFilterName.length(); + EXPECT_TRUE(HostFuncAVFilterInOutSetName.run( + CallFrame, + std::initializer_list{OutputInOutId, + InputFilterNamePtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + Length = OutputFilterName.length(); + EXPECT_TRUE(HostFuncAVFilterInOutSetName.run( + CallFrame, + std::initializer_list{ + InputInOutId, OutputFilterNamePtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_inout_set_filter_ctx"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterInOutSetFilterCtx = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterInOutSetFilterCtx &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterInOutSetFilterCtx.run( + CallFrame, + std::initializer_list{OutputInOutId, + InputFilterCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVFilterInOutSetFilterCtx.run( + CallFrame, + std::initializer_list{InputInOutId, + OutputFilterCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_inout_set_pad_idx"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterInOutSetPadIdx = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterInOutSetPadIdx &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterInOutSetPadIdx.run( + CallFrame, + std::initializer_list{OutputInOutId, 0}, Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVFilterInOutSetPadIdx.run( + CallFrame, std::initializer_list{InputInOutId, 0}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_inout_set_next"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterInOutSetNext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterInOutSetNext &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterInOutSetNext.run( + CallFrame, + std::initializer_list{OutputInOutId, 0}, Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVFilterInOutSetNext.run( + CallFrame, std::initializer_list{InputInOutId, 0}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + // ================================================================== + // End Setting InOutId Values for Filtering + // ================================================================== + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_parse_ptr"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphParsePtr = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphParsePtr &>( + FuncInst->getHostFunc()); + + { + int32_t Length = SpecStr.length(); + EXPECT_TRUE(HostFuncAVFilterGraphParsePtr.run( + CallFrame, + std::initializer_list{ + FilterGraphId, SpecPtr, Length, InputInOutId, OutputInOutId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_config"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphConfig = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphConfig &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterGraphConfig.run( + CallFrame, std::initializer_list{FilterGraphId}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_dump_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphDumpLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphDumpLength &>( + FuncInst->getHostFunc()); + + int32_t GraphStrLen = 0; + { + EXPECT_TRUE(HostFuncAVFilterGraphDumpLength.run( + CallFrame, std::initializer_list{FilterGraphId}, + Result)); + GraphStrLen = Result[0].get(); + ASSERT_TRUE(GraphStrLen > 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_dump"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphDump = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphDump &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterGraphDump.run( + CallFrame, + std::initializer_list{FilterGraphId, StrPtr, + GraphStrLen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + // Crashing the program. Checked even from Rust side. + + // FuncInst = AVFilterMod->findFuncExports( + // "wasmedge_ffmpeg_avfilter_avfilter_inout_free"); + // EXPECT_NE(FuncInst, nullptr); + // EXPECT_TRUE(FuncInst->isHostFunction()); + // + // auto &HostFuncAVFilterInOutFree = dynamic_cast< + // WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterInOutFree &>( + // FuncInst->getHostFunc()); + // + // { + // EXPECT_TRUE(HostFuncAVFilterInOutFree.run( + // CallFrame, + // std::initializer_list{InputInOutId}, Result)); + // EXPECT_EQ(Result[0].get(), + // static_cast(ErrNo::Success)); + // + // EXPECT_TRUE(HostFuncAVFilterInOutFree.run( + // CallFrame, + // std::initializer_list{OutputInOutId}, + // Result)); + // EXPECT_EQ(Result[0].get(), + // static_cast(ErrNo::Success)); + // } + + FuncInst = + AVFilterMod->findFuncExports("wasmedge_ffmpeg_avfilter_avfilter_version"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterVersion = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterVersion.run( + CallFrame, std::initializer_list{}, Result)); + ASSERT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_configuration_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterConfigurationLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterConfigurationLength &>( + FuncInst->getHostFunc()); + + int32_t Length = 0; + { + EXPECT_TRUE(HostFuncAVFilterConfigurationLength.run( + CallFrame, std::initializer_list{}, Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_configuration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterConfiguration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterConfiguration &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterConfiguration.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_license_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterLicenseLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterLicenseLength &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterLicenseLength.run( + CallFrame, std::initializer_list{}, Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = + AVFilterMod->findFuncExports("wasmedge_ffmpeg_avfilter_avfilter_license"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterLicense = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterLicense.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + // ================================================================== + // Start Test AVBufferSource, AVBufferSink Funcs + // ================================================================== + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_av_buffersrc_get_nb_failed_requests"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVBufferSrcGetNbFailedRequests = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVBufferSrcGetNbFailedRequests + &>(FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVBufferSrcGetNbFailedRequests.run( + CallFrame, + std::initializer_list{InputFilterCtxId}, Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_av_buffersrc_add_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVBufferSrcAddFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVBufferSrcAddFrame &>( + FuncInst->getHostFunc()); + + // Returning Error Code -22 (Invalid Argument), Due to Passing Empty Frame. + { + EXPECT_TRUE(HostFuncAVBufferSrcAddFrame.run( + CallFrame, + std::initializer_list{InputFilterCtxId, FrameId}, + Result)); + ASSERT_TRUE(Result[0].get()); + } + + // Need to send the last frame. Then only this test will pass. Else Null + // pointer exception. + // FuncInst = AVFilterMod->findFuncExports( + // "wasmedge_ffmpeg_avfilter_av_buffersrc_close"); + // EXPECT_NE(FuncInst, nullptr); + // EXPECT_TRUE(FuncInst->isHostFunction()); + // + // auto &HostFuncAVBufferSrcClose = dynamic_cast< + // WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVBufferSrcClose &>( + // FuncInst->getHostFunc()); + // + // { + // int64_t Pts = 20; + // uint32_t Flags = 30; + // EXPECT_TRUE(HostFuncAVBufferSrcClose.run( + // CallFrame, + // std::initializer_list{InputFilterCtxPtr, Pts, + // Flags}, + // Result)); + // EXPECT_EQ(Result[0].get(), + // static_cast(ErrNo::Success)); + // } + + // Passing Empty frames. Return AVERROR due to no frames presen Return AVERROR + // due to no frames present. + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_av_buffersink_get_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVBufferSinkGetFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVBufferSinkGetFrame &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVBufferSinkGetFrame.run( + CallFrame, + std::initializer_list{OutputFilterCtxId, FrameId}, + Result)); + ASSERT_TRUE(Result[0].get()); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_av_buffersink_get_samples"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVBufferSinkGetSamples = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVBufferSinkGetSamples &>( + FuncInst->getHostFunc()); + + // Passing Empty frames. Return AVERROR due to no frames presen Return AVERROR + // due to no frames present. + { + EXPECT_TRUE(HostFuncAVBufferSinkGetSamples.run( + CallFrame, + std::initializer_list{OutputFilterCtxId, FrameId, + 20}, + Result)); + ASSERT_TRUE(Result[0].get()); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_av_buffersink_set_frame_size"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAvBufferSinkSetFrameSize = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AvBufferSinkSetFrameSize &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAvBufferSinkSetFrameSize.run( + CallFrame, + std::initializer_list{OutputFilterCtxId, 30}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + // ================================================================== + // End Test AVBufferSource, AVBufferSink Funcs + // ================================================================== + + // ================================================================== + // Clean Memory + // ================================================================== + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_free_graph_str"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterFreeGraphStr = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterFreeGraphStr &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterFreeGraphStr.run( + CallFrame, std::initializer_list{FilterGraphId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVFilterMod->findFuncExports("wasmedge_ffmpeg_avfilter_avfilter_drop"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterDrop = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterDrop.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_context_drop"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterContextDrop = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterContextDrop &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterContextDrop.run( + CallFrame, + std::initializer_list{InputFilterCtxId}, Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVFilterContextDrop.run( + CallFrame, + std::initializer_list{OutputFilterCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFilterMod->findFuncExports( + "wasmedge_ffmpeg_avfilter_avfilter_graph_free"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + + auto &HostFuncAVFilterGraphFree = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::AVFilterGraphFree &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFilterGraphFree.run( + CallFrame, std::initializer_list{FilterGraphId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + // ================================================================== + // End Clean Memory + // ================================================================== +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp b/test/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp new file mode 100644 index 000000000000..94dd8c63258c --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avformat/avChapter.cpp @@ -0,0 +1,220 @@ +#include "avformat/avChapter.h" +#include "avformat/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +// Sample Video under test has only Single Chapter. +TEST_F(FFmpegTest, AVChapter) { + + ASSERT_TRUE(AVFormatMod != nullptr); + + uint32_t ChapterIdx = 0; + + uint32_t FormatCtxPtr = UINT32_C(4); + uint32_t NumPtr = UINT32_C(12); + uint32_t DenPtr = UINT32_C(16); + uint32_t DictionaryPtr = UINT32_C(20); + uint32_t FilePtr = UINT32_C(100); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFormatCtx(FormatCtxPtr, FilePtr, FileName); + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + + auto *FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avChapter_id"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterId = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVChapterId.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avChapter_timebase"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterTimebase = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVChapterTimebase &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVChapterTimebase.run( + CallFrame, + std::initializer_list{NumPtr, DenPtr, FormatCtxId, + ChapterIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + EXPECT_EQ(readSInt32(MemInst, NumPtr), 1); + EXPECT_TRUE(readSInt32(MemInst, DenPtr) >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avChapter_start"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterStart = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVChapterStart.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avChapter_end"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterEnd = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVChapterEnd.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avChapter_metadata"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterMetadata = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVChapterMetadata &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVChapterMetadata.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx, + DictionaryPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_TRUE(readUInt32(MemInst, DictionaryPtr) > 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avChapter_set_id"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterSetId = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int64_t ChapterId = 10000; + EXPECT_TRUE( + HostFuncAVChapterSetId.run(CallFrame, + std::initializer_list{ + FormatCtxId, ChapterIdx, ChapterId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + // Verify Set Data + EXPECT_TRUE(HostFuncAVChapterId.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx}, + Result)); + EXPECT_EQ(Result[0].get(), ChapterId); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avChapter_set_timebase"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterSetTimebase = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVChapterSetTimebase &>( + FuncInst->getHostFunc()); + + { + int32_t Num = 3; + int32_t Den = 4; + EXPECT_TRUE(HostFuncAVChapterSetTimebase.run( + CallFrame, + std::initializer_list{Num, Den, FormatCtxId, + ChapterIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + // Verify Set Data + EXPECT_TRUE(HostFuncAVChapterTimebase.run( + CallFrame, + std::initializer_list{NumPtr, DenPtr, FormatCtxId, + ChapterIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_EQ(readSInt32(MemInst, NumPtr), Num); + EXPECT_EQ(readSInt32(MemInst, DenPtr), Den); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avChapter_set_start"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterSetStart = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVChapterSetStart &>( + FuncInst->getHostFunc()); + + { + int64_t StartValue = 1000; + EXPECT_TRUE(HostFuncAVChapterSetStart.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx, + StartValue}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + // Verify Set Data + EXPECT_TRUE(HostFuncAVChapterStart.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx}, + Result)); + EXPECT_EQ(Result[0].get(), StartValue); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avChapter_set_end"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVChapterSetEnd = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int64_t EndValue = 99999; + EXPECT_TRUE( + HostFuncAVChapterSetEnd.run(CallFrame, + std::initializer_list{ + FormatCtxId, ChapterIdx, EndValue}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + // Verify Set Data + EXPECT_TRUE(HostFuncAVChapterEnd.run( + CallFrame, + std::initializer_list{FormatCtxId, ChapterIdx}, + Result)); + EXPECT_EQ(Result[0].get(), EndValue); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avformat/avInputOutputContext.cpp b/test/plugins/wasmedge_ffmpeg/avformat/avInputOutputContext.cpp new file mode 100644 index 000000000000..3a575551e539 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avformat/avInputOutputContext.cpp @@ -0,0 +1,207 @@ +#include "avformat/avInputOutputFormat.h" +#include "avformat/avformatContext.h" +#include "avformat/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVInputFormat) { + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + uint32_t FormatCtxPtr = UINT32_C(24); + uint32_t InputFormatPtr = UINT32_C(28); + + uint32_t StrBuf = UINT32_C(100); + initFFmpegStructs(UINT32_C(20), FormatCtxPtr, UINT32_C(28), FileName, + UINT32_C(60), UINT32_C(64), UINT32_C(68), UINT32_C(72)); + + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + + // ==================================================================== + // Initialize AVInputFormat + // ==================================================================== + + auto *FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_iformat"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxIFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxIFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxIFormat.run( + CallFrame, + std::initializer_list{FormatCtxId, + InputFormatPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_TRUE(readUInt32(MemInst, InputFormatPtr) > 0); + } + uint32_t InputFormatId = readUInt32(MemInst, InputFormatPtr); + + // ==================================================================== + // End Initialize AVInputFormat + // ==================================================================== + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avIOFormat_name_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOFormatNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVIOFormatNameLength &>( + FuncInst->getHostFunc()); + + int32_t Length = 0; + { + EXPECT_TRUE(HostFuncAVIOFormatNameLength.run( + CallFrame, + std::initializer_list{InputFormatId, 0}, Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avInputFormat_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVInputFormatName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVInputFormatName &>( + FuncInst->getHostFunc()); + + fillMemContent(MemInst, StrBuf, Length); + { + EXPECT_TRUE(HostFuncAVInputFormatName.run( + CallFrame, + std::initializer_list{InputFormatId, StrBuf, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avIOFormat_long_name_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOFormatLongNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVIOFormatLongNameLength &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVIOFormatLongNameLength.run( + CallFrame, + std::initializer_list{InputFormatId, 0}, Result)); + + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avInputFormat_long_name"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVInputFormatLongName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVInputFormatLongName &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVInputFormatLongName.run( + CallFrame, + std::initializer_list{InputFormatId, StrBuf, + Length}, + Result)); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avIOFormat_extensions_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOFormatExtensionsLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVIOFormatExtensionsLength &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVIOFormatExtensionsLength.run( + CallFrame, + std::initializer_list{InputFormatId, 0}, Result)); + + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avInputFormat_extensions"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVInputFormatExtensions = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVInputFormatExtensions &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVInputFormatExtensions.run( + CallFrame, + std::initializer_list{InputFormatId, StrBuf, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avIOFormat_mime_type_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOFormatMimeTypeLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVIOFormatMimeTypeLength &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVIOFormatMimeTypeLength.run( + CallFrame, + std::initializer_list{InputFormatId, 0}, Result)); + + Length = Result[0].get(); + ASSERT_TRUE(Length >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avInputFormat_mime_type"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVInputFormatMimeType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVInputFormatMimeType &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVInputFormatMimeType.run( + CallFrame, + std::initializer_list{InputFormatId, StrBuf, + Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avInputOutputFormat_free"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVInputOutputFormatFree = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVInputOutputFormatFree &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVInputOutputFormatFree.run( + CallFrame, std::initializer_list{InputFormatId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avformat/avStream.cpp b/test/plugins/wasmedge_ffmpeg/avformat/avStream.cpp new file mode 100644 index 000000000000..1fc2dadc46df --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avformat/avStream.cpp @@ -0,0 +1,303 @@ +#include "avformat/avStream.h" +#include "avformat/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +// Testing all AVFormat_funcs. +TEST_F(FFmpegTest, AVStreamStruct) { + + ASSERT_TRUE(AVFormatMod != nullptr); + + uint32_t StreamIdx = 0; + + uint32_t FormatCtxPtr = UINT32_C(4); + uint32_t CodecParameterPtr = UINT32_C(8); + uint32_t NumPtr = UINT32_C(12); + uint32_t DenPtr = UINT32_C(16); + uint32_t DictPtr = UINT32_C(20); + uint32_t FilePtr = UINT32_C(100); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFormatCtx(FormatCtxPtr, FilePtr, FileName); + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + + auto *FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avStream_id"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamId = + dynamic_cast( + FuncInst->getHostFunc()); + + uint32_t AvFormatCtxId = readUInt32(MemInst, FormatCtxPtr); + { + EXPECT_TRUE(HostFuncAVStreamId.run( + CallFrame, + std::initializer_list{AvFormatCtxId, StreamIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avStream_index"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamIndex = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVStreamIndex.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_codecpar"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamCodecPar = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamCodecPar &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVStreamCodecPar.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx, + CodecParameterPtr}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + ASSERT_TRUE(readUInt32(MemInst, CodecParameterPtr) > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_timebase"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamTimebase = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamTimebase &>( + FuncInst->getHostFunc()); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_set_timebase"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamSetTimebase = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamSetTimebase &>( + FuncInst->getHostFunc()); + + { + int32_t Num = 3; + int32_t Den = 4; + EXPECT_TRUE(HostFuncAVStreamSetTimebase.run( + CallFrame, + std::initializer_list{Num, Den, FormatCtxId, + StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVStreamTimebase.run( + CallFrame, + std::initializer_list{NumPtr, DenPtr, FormatCtxId, + StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_EQ(readUInt32(MemInst, NumPtr), Num); + EXPECT_EQ(readUInt32(MemInst, DenPtr), Den); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_duration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamDuration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamDuration &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVStreamDuration.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_start_time"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamStartTime = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamStartTime &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVStreamStartTime.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_nb_frames"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamNbFrames = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamNbFrames &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVStreamNbFrames.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_disposition"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamDisposition = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamDisposition &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVStreamDisposition.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_set_r_frame_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamSetRFrameRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamSetRFrameRate &>( + FuncInst->getHostFunc()); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_r_frame_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamRFrameRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamRFrameRate &>( + FuncInst->getHostFunc()); + + { + int32_t Num = 3; + int32_t Den = 4; + EXPECT_TRUE(HostFuncAVStreamSetRFrameRate.run( + CallFrame, + std::initializer_list{Num, Den, FormatCtxId, + StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVStreamRFrameRate.run( + CallFrame, + std::initializer_list{NumPtr, DenPtr, FormatCtxId, + StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_EQ(readUInt32(MemInst, NumPtr), Num); + EXPECT_EQ(readUInt32(MemInst, DenPtr), Den); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_set_avg_frame_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamSetAvgFrameRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamSetAvgFrameRate &>( + FuncInst->getHostFunc()); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_avg_frame_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamAvgFrameRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamAvgFrameRate &>( + FuncInst->getHostFunc()); + + { + int32_t Num = 3; + int32_t Den = 4; + + EXPECT_TRUE(HostFuncAVStreamSetAvgFrameRate.run( + CallFrame, + std::initializer_list{Num, Den, FormatCtxId, + StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVStreamAvgFrameRate.run( + CallFrame, + std::initializer_list{NumPtr, DenPtr, FormatCtxId, + StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_EQ(readUInt32(MemInst, NumPtr), Num); + EXPECT_EQ(readUInt32(MemInst, DenPtr), Den); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_metadata"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamMetadata = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamMetadata &>( + FuncInst->getHostFunc()); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_set_metadata"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamSetMetadata = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamSetMetadata &>( + FuncInst->getHostFunc()); + { + EXPECT_TRUE(HostFuncAVStreamMetadata.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx, + DictPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + uint32_t DictId = readUInt32(MemInst, DictPtr); + EXPECT_TRUE(HostFuncAVStreamSetMetadata.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx, + DictId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avStream_discard"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVStreamDiscard = + dynamic_cast( + FuncInst->getHostFunc()); + { + EXPECT_TRUE(HostFuncAVStreamDiscard.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp b/test/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp new file mode 100644 index 000000000000..ede24ec5c42d --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avformat/avformatContext.cpp @@ -0,0 +1,184 @@ +#include "avformat/avformatContext.h" +#include "avformat/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +// Testing all AVFormat_funcs. +TEST_F(FFmpegTest, AVFormatContextStruct) { + + uint32_t FormatCtxPtr = UINT32_C(4); + uint32_t InputFormatPtr = UINT32_C(8); + uint32_t OutputFormatPtr = UINT32_C(12); + uint32_t DicPtr = uint32_t(16); + uint32_t FilePtr = UINT32_C(100); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFormatCtx(FormatCtxPtr, FilePtr, FileName); + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + + auto *FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_iformat"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxIFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxIFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxIFormat.run( + CallFrame, + std::initializer_list{FormatCtxId, + InputFormatPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_TRUE(readUInt32(MemInst, InputFormatPtr) > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_oformat"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxOFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxOFormat &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxOFormat.run( + CallFrame, + std::initializer_list{FormatCtxId, + OutputFormatPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_TRUE(readUInt32(MemInst, InputFormatPtr) > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_probescope"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxProbeScore = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxProbeScore &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxProbeScore.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 100); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_nb_streams"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxNbStreams = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxNbStreams &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxNbStreams.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_duration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxDuration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxDuration &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxDuration.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0 || Result[0].get() < 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_bit_rate"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxBitRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxBitRate &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxBitRate.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_set_nb_chapters"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxSetNbChapters = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxSetNbChapters &>( + FuncInst->getHostFunc()); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_nb_chapters"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxNbChapters = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxNbChapters &>( + FuncInst->getHostFunc()); + { + uint32_t NbChapters = 200; + EXPECT_TRUE(HostFuncAVFormatCtxSetNbChapters.run( + CallFrame, + std::initializer_list{FormatCtxId, NbChapters}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_TRUE(HostFuncAVFormatCtxNbChapters.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_EQ(Result[0].get(), NbChapters); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_metadata"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxMetadata = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxMetadata &>( + FuncInst->getHostFunc()); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformatContext_set_metadata"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCtxSetMetadata = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCtxSetMetadata &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncAVFormatCtxMetadata.run( + CallFrame, + std::initializer_list{FormatCtxId, DicPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_TRUE(readUInt32(MemInst, DicPtr) > 0); + + uint32_t DictId = readUInt32(MemInst, DicPtr); + EXPECT_TRUE(HostFuncAVFormatCtxSetMetadata.run( + CallFrame, + std::initializer_list{FormatCtxId, DictId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp b/test/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp new file mode 100644 index 000000000000..c2fc4fee7e43 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avformat/avformat_func.cpp @@ -0,0 +1,588 @@ +#include "avformat/avformat_func.h" +#include "avformat/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +// Testing all AVFormat_funcs. +TEST_F(FFmpegTest, AVInputFormatFunc) { + + uint32_t FormatCtxPtr = UINT32_C(4); + uint32_t DictPtr = UINT32_C(16); + uint32_t KeyPtr = UINT32_C(100); + uint32_t ValuePtr = UINT32_C(200); + uint32_t StrPtr = UINT32_C(400); + + initDict(DictPtr, KeyPtr, std::string("Key"), ValuePtr, std::string("Value")); + uint32_t DictId = readUInt32(MemInst, DictPtr); + + uint32_t UrlStart = UINT32_C(300); + uint32_t UrlSize = 30; + fillMemContent(MemInst, UrlStart, UrlSize); + fillMemContent(MemInst, UrlStart, + std::string("ffmpeg-assets/sample_video.mp4")); + + auto *FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_open_input"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatOpenInput = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatOpenInput &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatOpenInput"sv); + { + // AVDict only + EXPECT_TRUE(HostFuncAVFormatOpenInput.run( + CallFrame, + std::initializer_list{ + FormatCtxPtr, UrlStart, UrlSize, UINT32_C(0), DictId}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + EXPECT_TRUE(readUInt32(MemInst, FormatCtxPtr) > 0); + + // No AVDict, No AVInputFormat + EXPECT_TRUE(HostFuncAVFormatOpenInput.run( + CallFrame, + std::initializer_list{ + FormatCtxPtr, UrlStart, UrlSize, UINT32_C(0), UINT32_C(0)}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + EXPECT_TRUE(readUInt32(MemInst, FormatCtxPtr) > 0); + } + + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_find_stream_info"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatFindStreamInfo = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatFindStreamInfo &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatFindStreamInfo"sv); + { + EXPECT_TRUE(HostFuncAVFormatFindStreamInfo.run( + CallFrame, + std::initializer_list{FormatCtxId, UINT32_C(0)}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_av_dump_format"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatAVDumpFormat = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVDumpFormat"sv); + { + EXPECT_TRUE(HostFuncAVFormatAVDumpFormat.run( + CallFrame, + std::initializer_list{ + FormatCtxId, 0, UINT32_C(100), UINT32_C(30), 0}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_av_find_best_stream"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFindBestStream = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFindBestStream &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFindBestStream"sv); + { + EXPECT_TRUE(HostFuncAVFindBestStream.run( + CallFrame, + std::initializer_list{ + FormatCtxId, UINT32_C(0), INT32_C(-1), INT32_C(-1), 0, 0}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_av_read_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVReadFrame = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVReadFrame"sv); + { + uint32_t PacketPtr = UINT32_C(520); + allocPacket(PacketPtr); + uint32_t PacketId = readUInt32(MemInst, PacketPtr); + EXPECT_TRUE(HostFuncAVReadFrame.run( + CallFrame, + std::initializer_list{FormatCtxId, PacketId}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_network_init"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatNetworkInit = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatNetworkInit &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatNetworkInit"sv); + { + EXPECT_TRUE(HostFuncAVFormatNetworkInit.run( + CallFrame, std::initializer_list{}, Result)); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_seek_file"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatSeekFile = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatSeekFile &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatSeekFile"sv); + { + uint32_t StreamIdx = -1; + int64_t MinTs = -10; + int64_t Ts = 0; + int64_t MaxTs = 10; + int32_t Flags = 0; + + // Try a network Fetch. + EXPECT_TRUE(HostFuncAVFormatSeekFile.run( + CallFrame, + std::initializer_list{FormatCtxId, StreamIdx, + MinTs, Ts, MaxTs, Flags}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_av_read_play"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatAVReadPlay = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVReadPlay"sv); + { + // Try a network Fetch. + EXPECT_TRUE(HostFuncAVFormatAVReadPlay.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_TRUE(Result[0].get() < 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_av_read_pause"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatAVReadPause = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVReadPause"sv); + { + // Try a network Fetch. + EXPECT_TRUE(HostFuncAVFormatAVReadPause.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_TRUE(Result[0].get() < 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_network_deinit"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatNetworkDeInit = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatNetworkDeInit &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatNetworkDeInit"sv); + { + EXPECT_TRUE(HostFuncAVFormatNetworkDeInit.run( + CallFrame, std::initializer_list{}, Result)); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_close_input"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatCloseInput = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatCloseInput &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatCloseInput"sv); + { + EXPECT_TRUE(HostFuncAVFormatCloseInput.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_free_context"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFreeContext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatFreeContext &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatFreeContext"sv); + { + EXPECT_TRUE(HostFuncAVFreeContext.run( + CallFrame, std::initializer_list{FormatCtxId}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avformat_version"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatVersion = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatVersion"sv); + { + EXPECT_TRUE(HostFuncAVFormatVersion.run( + CallFrame, std::initializer_list{}, Result)); + + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_configuration_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatConfigurationLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatConfigurationLength &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatConfigurationLength"sv); + int32_t Length = 0; + { + EXPECT_TRUE(HostFuncAVFormatConfigurationLength.run( + CallFrame, std::initializer_list{}, Result)); + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_configuration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatConfiguration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatConfiguration &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatConfiguration"sv); + { + EXPECT_TRUE(HostFuncAVFormatConfiguration.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_license_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatLicenseLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatLicenseLength &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatLicenseLength"sv); + { + EXPECT_TRUE(HostFuncAVFormatLicenseLength.run( + CallFrame, std::initializer_list{}, Result)); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avformat_license"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatLicense = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatLicense"sv); + { + EXPECT_TRUE(HostFuncAVFormatLicense.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + + EXPECT_TRUE(Result[0].get() >= 0); + } +} + +TEST_F(FFmpegTest, AVOutputFormatFunc) { + + uint32_t FormatCtxPtr = UINT32_C(4); + uint32_t DictPtr = UINT32_C(16); + uint32_t ChapterPtr = UINT32_C(20); + uint32_t FramePtr = UINT32_C(24); + uint32_t KeyPtr = UINT32_C(100); + uint32_t ValuePtr = UINT32_C(200); + + initDict(DictPtr, KeyPtr, std::string("Key"), ValuePtr, std::string("Value")); + initEmptyFrame(FramePtr); + uint32_t DictId = readUInt32(MemInst, DictPtr); + uint32_t FrameId = readUInt32(MemInst, FramePtr); + + uint32_t FormatStart = 300; + uint32_t FormatLen = 3; + uint32_t FileStart = 350; + uint32_t FileLen = 8; + fillMemContent(MemInst, FormatStart, FormatLen + FileLen); + + fillMemContent(MemInst, FormatStart, std::string("mp4")); + fillMemContent(MemInst, FileStart, std::string("test.mp4")); + + auto *FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_alloc_output_context2"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatAllocOutputContext2 = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatAllocOutputContext2 &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatAllocOutputContext2"sv); + { + EXPECT_TRUE(HostFuncAVFormatAllocOutputContext2.run( + CallFrame, + std::initializer_list{ + FormatCtxPtr, 0, FormatStart, FormatLen, FileStart, FileLen}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + + EXPECT_TRUE(HostFuncAVFormatAllocOutputContext2.run( + CallFrame, + std::initializer_list{ + FormatCtxPtr, readUInt32(MemInst, FormatCtxPtr), FormatStart, + FormatLen, FileStart, FileLen}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + + EXPECT_TRUE(HostFuncAVFormatAllocOutputContext2.run( + CallFrame, + std::initializer_list{FormatCtxPtr, 0, 0, 0, + FileStart, FileLen}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avio_open"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOOpen = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVIOOpen"sv); + { + uint32_t AvFormatCtxId = readUInt32(MemInst, FormatCtxPtr); + EXPECT_TRUE( + HostFuncAVIOOpen.run(CallFrame, + std::initializer_list{ + AvFormatCtxId, FileStart, FileLen, 2}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avio_open2"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOOpen2 = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVIOOpen2"sv); + { + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + EXPECT_TRUE(HostFuncAVIOOpen2.run( + CallFrame, + std::initializer_list{FormatCtxId, FileStart, + FileLen, 2, 0, DictId}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + } + + // TODO: This test modifies the input file. Unable to test. + // Added test on rust side. + // spdlog::info("Testing AVGuessCodec"sv); + // uint32_t EmptyStrPtr = UINT32_C(520); + // writeUInt32(MemInst, 0, EmptyStrPtr); + // { + // uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + // int32_t MediaTypeId = 0; // Video + // EXPECT_TRUE(HostFuncAVGuessCodec.run( + // CallFrame, + // std::initializer_list{FormatCtxId, + // EmptyStrPtr, 0, + // FilePtr, 32, + // EmptyStrPtr, 0, + // MediaTypeId}, + // Result)); + // EXPECT_EQ(Result[0].get(), 1); // AV_CODEC_ID_MPEG1VIDEO: + // } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_write_header"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatWriteHeader = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatWriteHeader &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFormatWriteHeader"sv); + { + // Did not set AVParameters, etc. Hence Giving Invalid Argument Error. + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + EXPECT_TRUE(HostFuncAVFormatWriteHeader.run( + CallFrame, + std::initializer_list{FormatCtxId, DictId}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } + + // Write Header above return invalid argument due to which below test won't + // work. The OutputFormatContext should Be configured using the input format + // context. Test on the Rust side. This is working as expected. + + // FuncInst = AVFormatMod->findFuncExports( + // "wasmedge_ffmpeg_avformat_avformat_write_trailer"); + // EXPECT_NE(FuncInst, nullptr); + // EXPECT_TRUE(FuncInst->isHostFunction()); + // auto &HostFuncAVFormatTrailer = dynamic_cast< + // WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatWriteTrailer &>( + // FuncInst->getHostFunc()); + // { + // // Did not set AVParameters, etc. Hence Giving Invalid Argument Error. + // uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + // EXPECT_TRUE(HostFuncAVFormatTrailer.run( + // CallFrame, std::initializer_list{FormatCtxId}, + // Result)); + // EXPECT_EQ(Result[0].get(), -22); + // } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avchapter_mallocz"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVIOClose = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVChapterMallocz &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVChapterMallocz"sv); + { + EXPECT_TRUE(HostFuncAVIOClose.run( + CallFrame, std::initializer_list{ChapterPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + // How to pass IntPtr + // + // FuncInst = AVFormatMod->findFuncExports( + // "wasmedge_ffmpeg_avformat_avchapter_dynarray_add"); + // EXPECT_NE(FuncInst, nullptr); + // EXPECT_TRUE(FuncInst->isHostFunction()); + // auto &HostFuncAVChapterDynarrayAdd = dynamic_cast< + // WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVChapterDynarrayAdd &>( + // FuncInst->getHostFunc()); + // // For the give input file, nb_chapter is 0; + // { + // uint32_t AvChapterId = readUInt32(MemInst, AvFormatCtxPtr); + // uint32_t AvFormatCtxId = readUInt32(MemInst, AvFormatCtxPtr); + // EXPECT_TRUE(HostFuncAVChapterDynarrayAdd.run( + // CallFrame, + // std::initializer_list{AvFormatCtxId, + // UINT32_C(0), + // AvChapterId}, + // Result)); + // EXPECT_EQ(Result[0].get(), + // static_cast(ErrNo::Success)); + // } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_avformat_avfreep"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVFormatAVFreep = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVFreeP"sv); + { + uint32_t ChapterId = readUInt32(MemInst, ChapterPtr); + EXPECT_TRUE(HostFuncAVFormatAVFreep.run( + CallFrame, std::initializer_list{ChapterId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_av_write_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVWriteFrame = + dynamic_cast( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVWriteFrame"sv); + // Passing Empty Frame, Hence giving Invalid Argument Error. + { + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + EXPECT_TRUE(HostFuncAVWriteFrame.run( + CallFrame, + std::initializer_list{FormatCtxId, FrameId}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_av_interleaved_write_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVInterleavedWriteFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVInterleavedWriteFrame &>( + FuncInst->getHostFunc()); + + spdlog::info("Testing AVInterleavedWriteFrame"sv); + // Passing Empty Frame, Hence giving Invalid Argument Error. + { + uint32_t FormatCtxId = readUInt32(MemInst, FormatCtxPtr); + EXPECT_TRUE(HostFuncAVInterleavedWriteFrame.run( + CallFrame, + std::initializer_list{FormatCtxId, FrameId}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp new file mode 100644 index 000000000000..cb4ad790ba01 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avDictionary.cpp @@ -0,0 +1,151 @@ +#include "avutil/avDictionary.h" +#include "avutil/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVDictionary) { + + uint32_t KeyStart = UINT32_C(1); + uint32_t KeyLen = 3; + uint32_t ValueStart = UINT32_C(4); + uint32_t ValueLen = 5; + uint32_t PrevDictEntryIdx = 0; // The Fetch the next Key value Node using an + // index. Passing Index from Rust side. + int32_t Flags = 0; + uint32_t NullDictId = UINT32_C(0); + + uint32_t DictPtr = UINT32_C(80); + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_dict_set"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVDictSet = + dynamic_cast( + FuncInst->getHostFunc()); + + // Fill 0 in WasmMemory. + fillMemContent(MemInst, KeyStart, KeyLen + ValueLen); + fillMemContent(MemInst, KeyStart, std::string("KEY")); + fillMemContent(MemInst, ValueStart, std::string("VALUE")); + + // Storing the above Key and Value in dict and using these in below tests + // (dict_get) to fetch Key,values. + { + EXPECT_TRUE(HostFuncAVDictSet.run( + CallFrame, + std::initializer_list{ + DictPtr, KeyStart, KeyLen, ValueStart, ValueLen, Flags}, + Result)); + EXPECT_TRUE(Result[0].get() >= 0); + ASSERT_TRUE(readUInt32(MemInst, DictPtr) > 0); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_dict_copy"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVDictCopy = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t DestDictPtr = UINT32_C(80); + uint32_t SrcDictId = readUInt32(MemInst, DictPtr); + EXPECT_TRUE( + HostFuncAVDictCopy.run(CallFrame, + std::initializer_list{ + DestDictPtr, SrcDictId, Flags}, + Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_dict_get"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVDictGet = + dynamic_cast( + FuncInst->getHostFunc()); + + { + // Store the string length of Key and value in below Pointers. + uint32_t KeyLenPtr = UINT32_C(56); + uint32_t ValueLenPtr = UINT32_C(60); + uint32_t DictId = readUInt32(MemInst, DictPtr); + EXPECT_TRUE(HostFuncAVDictGet.run( + CallFrame, + std::initializer_list{DictId, KeyStart, KeyLen, + PrevDictEntryIdx, Flags, + KeyLenPtr, ValueLenPtr}, + Result)); + EXPECT_TRUE(Result[0].get() == 1); + EXPECT_EQ(readUInt32(MemInst, KeyLenPtr), KeyLen); + EXPECT_EQ(readUInt32(MemInst, ValueLenPtr), ValueLen); + + // Pass a Null Dict and testing. + EXPECT_TRUE(HostFuncAVDictGet.run( + CallFrame, + std::initializer_list{ + NullDictId, KeyStart, KeyLen, PrevDictEntryIdx, Flags, KeyLenPtr, + ValueLenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), + static_cast(ErrNo::InternalError)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_dict_get_key_value"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVDictGetKeyValue = + dynamic_cast( + FuncInst->getHostFunc()); + + { + // Store the string of Key and value in below Buffer Pointers. + uint32_t KeyBufPtr = UINT32_C(36); + uint32_t ValueBufPtr = UINT32_C(40); + uint32_t DictId = readUInt32(MemInst, DictPtr); + EXPECT_TRUE(HostFuncAVDictGetKeyValue.run( + CallFrame, + std::initializer_list{ + DictId, KeyStart, KeyLen, ValueBufPtr, ValueLen, KeyBufPtr, + UINT32_C(3), PrevDictEntryIdx, Flags}, + Result)); + EXPECT_EQ(Result[0].get(), 1); + // Verify String. Read String from MemInst + + // Pass a Null Dict and testing. + EXPECT_TRUE(HostFuncAVDictGetKeyValue.run( + CallFrame, + std::initializer_list{ + NullDictId, KeyStart, KeyLen, ValueBufPtr, ValueLen, KeyBufPtr, + UINT32_C(3), PrevDictEntryIdx, Flags}, + Result)); + EXPECT_EQ(Result[0].get(), + static_cast(ErrNo::InternalError)); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_dict_free"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVDictFree = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t DictId = readUInt32(MemInst, DictPtr); + EXPECT_TRUE(HostFuncAVDictFree.run( + CallFrame, std::initializer_list{DictId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avError.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avError.cpp new file mode 100644 index 000000000000..454d38a2b336 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avError.cpp @@ -0,0 +1,65 @@ +#include "avutil/error.h" +#include "avutil/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVError) { + + ASSERT_TRUE(AVUtilMod != nullptr); + + int32_t ErrNum = 35; + + uint32_t ErrStartPtr = UINT32_C(100); + uint32_t ErrSize = 10; + fillMemContent(MemInst, ErrStartPtr, ErrSize); + + fillMemContent(MemInst, ErrStartPtr, std::string("Test Error")); + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_strerror"); + auto &HostFuncAVUtilAVStrError = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilAVStrError.run( + CallFrame, std::initializer_list{}, Result); + + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_AVERROR"); + auto &HostFuncAVUtilAVError = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilAVError.run( + CallFrame, std::initializer_list{ErrNum}, Result); + + EXPECT_EQ(Result[0].get(), + ErrNum * -1); // Returns Negative, convert to Positive + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_AVUNERROR"); + auto &HostFuncAVUtilAVUNError = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilAVUNError.run( + CallFrame, std::initializer_list{ErrNum}, Result); + + EXPECT_EQ(Result[0].get(), + ErrNum * -1); // Returns Negative, convert to Positive + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp new file mode 100644 index 000000000000..3f4c62699111 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avFrame.cpp @@ -0,0 +1,781 @@ +#include "avutil/avFrame.h" +#include "avutil/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVFrame) { + + uint32_t AVFramePtr = UINT32_C(72); + uint32_t AVFrame2Ptr = UINT32_C(40); + uint32_t DictPtr = UINT32_C(36); + uint32_t NumPtr = UINT32_C(80); + uint32_t DenPtr = UINT32_C(84); + uint32_t BufPtr = UINT32_C(200); // TO store Frame Data; + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFFmpegStructs(UINT32_C(12), UINT32_C(24), UINT32_C(28), FileName, + UINT32_C(60), UINT32_C(64), UINT32_C(68), AVFramePtr); + + initFFmpegStructs(UINT32_C(100), UINT32_C(104), UINT32_C(108), FileName, + UINT32_C(112), UINT32_C(116), UINT32_C(120), AVFrame2Ptr); + + uint32_t AVFrameId = readUInt32(MemInst, AVFramePtr); + uint32_t AVFrame2Id = readUInt32(MemInst, AVFrame2Ptr); + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_alloc"); + auto &HostFuncAVFrameAlloc = + dynamic_cast( + FuncInst->getHostFunc()); + + uint32_t EmptyFramePtr = UINT32_C(64); + + { + HostFuncAVFrameAlloc.run( + CallFrame, std::initializer_list{EmptyFramePtr}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + EXPECT_TRUE(readUInt32(MemInst, EmptyFramePtr) > 0); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_free"); + auto &HostFuncAVFrameFree = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t EmptyFrameId = readUInt32(MemInst, EmptyFramePtr); + HostFuncAVFrameFree.run( + CallFrame, std::initializer_list{EmptyFrameId}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_width"); + auto &HostFuncAVFrameWidth = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameWidth.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + + EXPECT_EQ(Result[0].get(), 1920); // Width + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_height"); + auto &HostFuncAVFrameHeight = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameHeight.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + + EXPECT_EQ(Result[0].get(), 1080); // Height + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_video_format"); + auto &HostFuncAVFrameVideoFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameVideoFormat &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameVideoFormat.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + + EXPECT_EQ(Result[0].get(), 1); // Video Format + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_isnull"); + auto &HostFuncAVFrameIsNull = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameIsNull.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_linesize"); + auto &HostFuncAVFrameLinesize = + dynamic_cast( + FuncInst->getHostFunc()); + + int32_t Stride = 0; + uint32_t Idx = 0; + { + HostFuncAVFrameLinesize.run( + CallFrame, std::initializer_list{AVFrameId, Idx}, + Result); + + Stride = Result[0].get(); + EXPECT_EQ(Stride, 1920); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_get_buffer"); + auto &HostFuncAVFrameGetBuffer = + dynamic_cast( + FuncInst->getHostFunc()); + { + // For video, it is 32. + int32_t Align = 32; + HostFuncAVFrameGetBuffer.run( + CallFrame, + std::initializer_list{AVFrameId, Align}, Result); + + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_best_effort_timestamp"); + auto &HostFuncAVFrameBestEffortTimestamp = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameBestEffortTimestamp &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameBestEffortTimestamp.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_pict_type"); + auto &HostFuncAVFramePictType = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFramePictType.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_interlaced_frame"); + auto &HostFuncAVFrameInterlacedFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameInterlacedFrame &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameInterlacedFrame.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_TRUE(Result[0].get() == 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_top_field_first"); + auto &HostFuncAVFrameTopFieldFirst = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameTopFieldFirst &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameTopFieldFirst.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_TRUE(Result[0].get() == 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_palette_has_changed"); + auto &HostFuncAVFramePaletteHasChanged = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFramePaletteHasChanged &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFramePaletteHasChanged.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_TRUE(Result[0].get() == 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_colorspace"); + auto &HostFuncAVFrameColorspace = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameColorspace.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 2); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_color_range"); + auto &HostFuncAVFrameColorRange = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameColorRange.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_color_trc"); + auto &HostAVFrameColorTransferCharacteristic = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameColorTransferCharacteristic + &>(FuncInst->getHostFunc()); + + { + HostAVFrameColorTransferCharacteristic.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 2); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_chroma_location"); + auto &HostAVFrameChromaLocation = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameChromaLocation &>( + FuncInst->getHostFunc()); + + { + HostAVFrameChromaLocation.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_coded_picture_number"); + auto &HostAVFrameCodedPictureNumber = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameCodedPictureNumber &>( + FuncInst->getHostFunc()); + + { + HostAVFrameCodedPictureNumber.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_display_picture_number"); + auto &HostAVFrameDisplayPictureNumber = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameDisplayPictureNumber &>( + FuncInst->getHostFunc()); + + { + HostAVFrameDisplayPictureNumber.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_repeat_pict"); + auto &HostAVFrameRepeatPict = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameRepeatPict.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_flags"); + auto &HostAVFrameFlags = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameFlags.run(CallFrame, + std::initializer_list{AVFrameId}, + Result); + EXPECT_TRUE(Result[0].get() != 1 << 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_quality"); + auto &HostAVFrameQuality = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameQuality.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_metadata"); + auto &HostAVFrameMetadata = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameMetadata.run( + CallFrame, + std::initializer_list{AVFrameId, DictPtr}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + uint32_t DictId = readUInt32(MemInst, DictPtr); + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_metadata"); + auto &HostAVFrameSetMetadata = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetMetadata &>( + FuncInst->getHostFunc()); + + { + HostAVFrameSetMetadata.run( + CallFrame, + std::initializer_list{AVFrameId, DictId}, Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_key_frame"); + auto &HostAVFrameKeyFrame = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameKeyFrame.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_pts"); + auto &HostAVFramePts = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFramePts.run(CallFrame, + std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_copy"); + auto &HostAVFrameCopy = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameCopy.run( + CallFrame, + std::initializer_list{AVFrame2Id, AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_copy_props"); + auto &HostAVFrameCopyProps = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostAVFrameCopyProps.run( + CallFrame, + std::initializer_list{AVFrame2Id, AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_set_width"); + auto &HostFuncAVFrameSetWidth = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t Width = 100; + HostFuncAVFrameSetWidth.run( + CallFrame, + std::initializer_list{AVFrameId, Width}, Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostFuncAVFrameWidth.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), Width); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_set_height"); + auto &HostFuncAVFrameSetHeight = + dynamic_cast( + FuncInst->getHostFunc()); + + int32_t Height = 100; + { + HostFuncAVFrameSetHeight.run( + CallFrame, + std::initializer_list{AVFrameId, Height}, Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostFuncAVFrameHeight.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), Height); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_data"); + auto &HostFuncAVFrameData = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t Size = 1; // Just reading One byte data for test. + fillMemContent(MemInst, BufPtr, Size); + HostFuncAVFrameData.run(CallFrame, + std::initializer_list{ + AVFrameId, BufPtr, Size, Idx}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_video_format"); + auto &HostFuncAVFrameSetVideoFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetVideoFormat &>( + FuncInst->getHostFunc()); + + { + uint32_t PixFormatId = 10; // GRAY8 + HostFuncAVFrameSetVideoFormat.run( + CallFrame, + std::initializer_list{AVFrameId, PixFormatId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostFuncAVFrameVideoFormat.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), PixFormatId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_pict_type"); + auto &HostFuncAVFrameSetPictType = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetPictType &>( + FuncInst->getHostFunc()); + + { + int32_t PictureId = 4; // AV_PICTURE_TYPE_S + HostFuncAVFrameSetPictType.run( + CallFrame, + std::initializer_list{AVFrameId, PictureId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostFuncAVFramePictType.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), PictureId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_colorspace"); + auto &HostFuncAVFrameSetColorSpace = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetColorSpace &>( + FuncInst->getHostFunc()); + + { + int32_t ColorSpaceId = 4; // FCC + HostFuncAVFrameSetColorSpace.run( + CallFrame, + std::initializer_list{AVFrameId, ColorSpaceId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostFuncAVFrameColorspace.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), ColorSpaceId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_color_range"); + auto &HostFuncAVFrameSetColorRange = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetColorRange &>( + FuncInst->getHostFunc()); + + { + int32_t ColorRangeId = 1; // MPEG + HostFuncAVFrameSetColorRange.run( + CallFrame, + std::initializer_list{AVFrameId, ColorRangeId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostFuncAVFrameColorRange.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), ColorRangeId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_color_trc"); + auto &HostFuncAVFrameSetColorTransferCharacteristic = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ColorTrcId = 5; // GAMMA28 + HostFuncAVFrameSetColorTransferCharacteristic.run( + CallFrame, + std::initializer_list{AVFrameId, ColorTrcId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostAVFrameColorTransferCharacteristic.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), ColorTrcId); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_set_pts"); + auto &HostFuncAVFrameSetPts = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int64_t Pts = 10; + HostFuncAVFrameSetPts.run( + CallFrame, std::initializer_list{AVFrameId, Pts}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + HostAVFramePts.run(CallFrame, + std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), Pts); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_sample_aspect_ratio"); + auto &HostFuncAVFrameSampleAspectRatio = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSampleAspectRatio &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameSampleAspectRatio.run( + CallFrame, + std::initializer_list{AVFrameId, NumPtr, DenPtr}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + int32_t ColorPrimariesId = 1; // BT709 + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_color_primaries"); + auto &HostFuncAVFrameSetColorPrimaries = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetColorPrimaries &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameSetColorPrimaries.run( + CallFrame, + std::initializer_list{AVFrameId, + ColorPrimariesId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_color_primaries"); + auto &HostFuncAVFrameColorPrimaries = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameColorPrimaries &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameColorPrimaries.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), ColorPrimariesId); + } + + // ========================================================================== + // AVFrame Audio Funcs. + // ========================================================================== + + // Setting the fields to Video Frame itself. + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_audio_format"); + auto &HostFuncAVFrameSetAudioFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetAudioFormat &>( + FuncInst->getHostFunc()); + + uint32_t SampleFormatId = 4; + { + HostFuncAVFrameSetAudioFormat.run( + CallFrame, + std::initializer_list{AVFrameId, SampleFormatId}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_audio_format"); + auto &HostFuncAVFrameAudioFormat = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameAudioFormat &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameAudioFormat.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), SampleFormatId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_nb_samples"); + auto &HostFuncAVFrameSetNbSamples = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetNbSamples &>( + FuncInst->getHostFunc()); + + int32_t NbSamples = 32; + { + HostFuncAVFrameSetNbSamples.run( + CallFrame, + std::initializer_list{AVFrameId, NbSamples}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_nb_samples"); + auto &HostFuncAVFrameNbSamples = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameNbSamples.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), NbSamples); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_sample_rate"); + auto &HostFuncAVFrameSetSampleRate = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetSampleRate &>( + FuncInst->getHostFunc()); + + int32_t SampleRate = 10; + { + HostFuncAVFrameSetSampleRate.run( + CallFrame, + std::initializer_list{AVFrameId, SampleRate}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_sample_rate"); + auto &HostFuncAVFrameSampleRate = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameSampleRate.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), SampleRate); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_channels"); + auto &HostFuncAVFrameSetChannels = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetChannels &>( + FuncInst->getHostFunc()); + + int32_t Channels = 3; + { + HostFuncAVFrameSetChannels.run( + CallFrame, + std::initializer_list{AVFrameId, Channels}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_channels"); + auto &HostFuncAVFrameChannels = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameChannels.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), Channels); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_set_channel_layout"); + auto &HostFuncAVFrameSetChannelLayout = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameSetChannelLayout &>( + FuncInst->getHostFunc()); + + uint64_t ChannelLayout = 1UL << 10; + { + HostFuncAVFrameSetChannelLayout.run( + CallFrame, + std::initializer_list{AVFrameId, ChannelLayout}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_frame_channel_layout"); + auto &HostFuncAVFrameChannelLayout = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVFrameChannelLayout &>( + FuncInst->getHostFunc()); + + { + HostFuncAVFrameChannelLayout.run( + CallFrame, std::initializer_list{AVFrameId}, + Result); + EXPECT_EQ(Result[0].get(), ChannelLayout); + } + + // ========================================================================== + // AVFrame Audio Funcs. + // ========================================================================== +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avPixfmt.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avPixfmt.cpp new file mode 100644 index 000000000000..afef37c12e33 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avPixfmt.cpp @@ -0,0 +1,244 @@ +#include "avutil/module.h" +#include "avutil/pixfmt.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVPixFmt) { + + uint32_t NamePtr = UINT32_C(4); + + auto *FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_avpixfmtdescriptor_nb_components"); + auto &HostFuncAVPixFmtDescriptorNbComponents = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AvPixFmtDescriptorNbComponents &>( + FuncInst->getHostFunc()); + + uint32_t PixFmtId = 3; // RGB24 + + { + HostFuncAVPixFmtDescriptorNbComponents.run( + CallFrame, std::initializer_list{PixFmtId}, + Result); + + EXPECT_EQ(Result[0].get(), PixFmtId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_avpixfmtdescriptor_log2_chromaw"); + auto &HostFuncAvPixFmtDescriptorLog2ChromaW = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AvPixFmtDescriptorLog2ChromaW &>( + FuncInst->getHostFunc()); + + { + HostFuncAvPixFmtDescriptorLog2ChromaW.run( + CallFrame, std::initializer_list{1}, Result); + + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_avpixfmtdescriptor_log2_chromah"); + auto &HostFuncAvPixFmtDescriptorLog2ChromaH = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AvPixFmtDescriptorLog2ChromaH &>( + FuncInst->getHostFunc()); + + { + HostFuncAvPixFmtDescriptorLog2ChromaH.run( + CallFrame, std::initializer_list{PixFmtId}, + Result); + + EXPECT_TRUE(Result[0].get() >= 0); + } + + int32_t Length = 0; + int32_t TransferCharacteristicId = 6; // (SMPTE170M) + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_color_transfer_name_length"); + auto &HostFuncAVColorTransferNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVColorTransferNameLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVColorTransferNameLength.run( + CallFrame, + std::initializer_list{TransferCharacteristicId}, + Result); + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill memory with zero. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_color_transfer_name"); + auto &HostFuncAVColorTransferName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVColorTransferName &>( + FuncInst->getHostFunc()); + + { + HostFuncAVColorTransferName.run( + CallFrame, + std::initializer_list{TransferCharacteristicId, + NamePtr, Length}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + int32_t ColorRangeId = 2; //; JPEG + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_color_range_name_length"); + auto &HostFuncAVColorRangeNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVColorRangeNameLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVColorRangeNameLength.run( + CallFrame, std::initializer_list{ColorRangeId}, + Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill memory with zero. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_color_range_name"); + auto &HostFuncAVColorRangeName = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVColorRangeName.run(CallFrame, + std::initializer_list{ + ColorRangeId, NamePtr, Length}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + int32_t ColorSpaceId = 1; // BT709 + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_color_space_name_length"); + auto &HostFuncAVColorSpaceNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVColorSpaceNameLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVColorSpaceNameLength.run( + CallFrame, std::initializer_list{ColorSpaceId}, + Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill memory with zero. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_color_space_name"); + auto &HostFuncAVColorSpaceName = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVColorSpaceName.run(CallFrame, + std::initializer_list{ + ColorSpaceId, NamePtr, Length}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + int32_t ColorPrimariesId = 1; // BT709 + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_color_primaries_name_length"); + auto &HostFuncAVColorPrimariesNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVColorPrimariesNameLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVColorPrimariesNameLength.run( + CallFrame, + std::initializer_list{ColorPrimariesId}, Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill memory with zero. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_color_primaries_name"); + auto &HostFuncAVColorPrimariesName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVColorPrimariesName &>( + FuncInst->getHostFunc()); + + { + HostFuncAVColorPrimariesName.run( + CallFrame, + std::initializer_list{ColorPrimariesId, NamePtr, + Length}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + PixFmtId = 1; // YUV420P + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_pix_format_name_length"); + auto &HostFuncAVPixFormatNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVPixelFormatNameLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVPixFormatNameLength.run( + CallFrame, std::initializer_list{PixFmtId}, + Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill memory with zero. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_pix_format_name"); + auto &HostFuncAVPixFormatName = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVPixFormatName.run( + CallFrame, + std::initializer_list{PixFmtId, NamePtr, Length}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_pix_format_mask"); + auto &HostFuncAVPixFormatMask = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t PixId = 3; // AV_PIX_FMT_RGB24: + HostFuncAVPixFormatMask.run( + CallFrame, std::initializer_list{PixId}, Result); + + EXPECT_EQ(Result[0].get(), + 2); // Verify Mask. Position of Pix in Enum. + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avRational.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avRational.cpp new file mode 100644 index 000000000000..250c0fec936b --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avRational.cpp @@ -0,0 +1,313 @@ +#include "avutil/avRational.h" +#include "avutil/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVRational) { + + ASSERT_TRUE(AVUtilMod != nullptr); + + uint32_t NumPtr = UINT32_C(4); + uint32_t DenPtr = UINT32_C(8); + + // Addition Function + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_add_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVAddQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = 3; + int32_t ADen = 4; + int32_t BNum = -6; + int32_t BDen = 7; + EXPECT_TRUE(HostFuncAVAddQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, NumPtr, DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_EQ(readSInt32(MemInst, NumPtr), -3); + EXPECT_EQ(readSInt32(MemInst, DenPtr), 28); + } + + // Subtraction Function + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_sub_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVSubQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = -843; + int32_t ADen = 11; + int32_t BNum = 38; + int32_t BDen = 12; + + writeSInt32(MemInst, 0, NumPtr); // Setting value of pointer to 0. + writeSInt32(MemInst, 0, DenPtr); // Setting value of pointer to 0. + EXPECT_TRUE(HostFuncAVSubQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, NumPtr, DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_EQ(readSInt32(MemInst, NumPtr), -5267); + EXPECT_EQ(readSInt32(MemInst, DenPtr), 66); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_mul_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVMulQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = -6; + int32_t ADen = 7; + int32_t BNum = 3; + int32_t BDen = 4; + + writeSInt32(MemInst, 0, NumPtr); // Setting value of pointer to 0. + writeSInt32(MemInst, 0, DenPtr); // Setting value of pointer to 0. + EXPECT_TRUE(HostFuncAVMulQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, NumPtr, DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_EQ(readSInt32(MemInst, NumPtr), -9); + EXPECT_EQ(readSInt32(MemInst, DenPtr), 14); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_div_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVDivQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = -6; + int32_t ADen = 7; + int32_t BNum = 3; + int32_t BDen = 4; + + writeSInt32(MemInst, 0, NumPtr); // Setting value of pointer to 0. + writeSInt32(MemInst, 0, DenPtr); // Setting value of pointer to 0. + EXPECT_TRUE(HostFuncAVDivQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, NumPtr, DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_EQ(readSInt32(MemInst, NumPtr), -8); + EXPECT_EQ(readSInt32(MemInst, DenPtr), 7); + } + + // How to Pass a Double functions. + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_d2q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVD2Q = + dynamic_cast( + FuncInst->getHostFunc()); + + { + double D = 5; + int32_t Max = 10; + + writeSInt32(MemInst, 0, NumPtr); // Setting value of pointer to 0. + writeSInt32(MemInst, 0, DenPtr); // Setting value of pointer to 0. + + EXPECT_TRUE(HostFuncAVD2Q.run( + CallFrame, + std::initializer_list{D, Max, NumPtr, DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_EQ(readSInt32(MemInst, NumPtr), 5); + EXPECT_EQ(readSInt32(MemInst, DenPtr), 1); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_q2d"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVQ2d = + dynamic_cast( + FuncInst->getHostFunc()); + + { + // Convert Rational Number to Double. + int32_t ANum = 1; + int32_t ADen = 2; + + writeSInt32(MemInst, 0, NumPtr); // Setting value of pointer to 0. + writeSInt32(MemInst, 0, DenPtr); // Setting value of pointer to 0. + EXPECT_TRUE(HostFuncAVQ2d.run( + CallFrame, std::initializer_list{ANum, ADen}, + Result)); + EXPECT_EQ(Result[0].get(), 0.5); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_inv_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncInvQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + // Inverse a Rational Number. + int32_t ANum = -3; + int32_t ADen = 4; + + writeSInt32(MemInst, 0, NumPtr); // Setting value of pointer to 0. + writeSInt32(MemInst, 0, DenPtr); // Setting value of pointer to 0. + EXPECT_TRUE(HostFuncInvQ.run( + CallFrame, + std::initializer_list{ANum, ADen, NumPtr, DenPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + + EXPECT_EQ(readSInt32(MemInst, NumPtr), 4); + EXPECT_EQ(readSInt32(MemInst, DenPtr), -3); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_q2intfloat"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVQ2IntFloat = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = 1; + int32_t ADen = 5; + + EXPECT_TRUE(HostFuncAVQ2IntFloat.run( + CallFrame, std::initializer_list{ANum, ADen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(1045220557)); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_nearer_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVNearerQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = 1; + int32_t ADen = 3; + int32_t BNum = 1; + int32_t BDen = 2; + int32_t CNum = -1; + int32_t CDen = 2; + + // B nearer to A + EXPECT_TRUE( + HostFuncAVNearerQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, CNum, CDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(1)); + + ANum = -1; + + // C nearer to A + EXPECT_TRUE( + HostFuncAVNearerQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, CNum, CDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(-1)); + + ANum = 0; + ADen = 0; + + // Both are at same distance + EXPECT_TRUE( + HostFuncAVNearerQ.run(CallFrame, + std::initializer_list{ + ANum, ADen, BNum, BDen, CNum, CDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(0)); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_cmp_q"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVCmpQ = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t ANum = 1; + int32_t ADen = 2; + int32_t BNum = 2; + int32_t BDen = 1; + // A < B + EXPECT_TRUE(HostFuncAVCmpQ.run( + CallFrame, + std::initializer_list{ANum, ADen, BNum, BDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(-1)); + + ANum = 2; + ADen = 1; + BNum = 1; + BDen = 2; + // A > B + EXPECT_TRUE(HostFuncAVCmpQ.run( + CallFrame, + std::initializer_list{ANum, ADen, BNum, BDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(1)); + + ANum = 2; + ADen = 1; + BNum = 2; + BDen = 1; + // A == B + EXPECT_TRUE(HostFuncAVCmpQ.run( + CallFrame, + std::initializer_list{ANum, ADen, BNum, BDen}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(0)); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_reduce"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVReduce = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int64_t ANum = 1; + int64_t ADen = 2; + int64_t Max = 3; + EXPECT_TRUE( + HostFuncAVReduce.run(CallFrame, + std::initializer_list{ + NumPtr, DenPtr, ANum, ADen, Max}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(1)); + } +} +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avSampleFmt.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avSampleFmt.cpp new file mode 100644 index 000000000000..c4f13e049368 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avSampleFmt.cpp @@ -0,0 +1,201 @@ +#include "avutil/module.h" +#include "avutil/samplefmt.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVSampleFmt) { + + ASSERT_TRUE(AVUtilMod != nullptr); + + uint32_t BufferPtr = UINT32_C(160); + uint32_t NamePtr = UINT32_C(80); + uint32_t LinesizePtr = UINT32_C(20); + + uint32_t SampleFmtId = 1; // AV_SAMPLE_FMT_S32 + auto *FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_packed_sample_fmt"); + auto &HostFuncAVGetPackedSampleFmt = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetPackedSampleFmt &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetPackedSampleFmt.run( + CallFrame, std::initializer_list{SampleFmtId}, + Result); + + EXPECT_EQ(Result[0].get(), SampleFmtId); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_planar_sample_fmt"); + auto &HostFuncAVGetPlanarSampleFmt = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetPlanarSampleFmt &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetPlanarSampleFmt.run( + CallFrame, std::initializer_list{SampleFmtId}, + Result); + + EXPECT_EQ(Result[0].get(), 6); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_sample_fmt_is_planar"); + auto &HostFuncAVSampleFmtIsPlanar = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVSampleFmtIsPlanar &>( + FuncInst->getHostFunc()); + + { + HostFuncAVSampleFmtIsPlanar.run( + CallFrame, std::initializer_list{SampleFmtId}, + Result); + + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_bytes_per_sample"); + auto &HostFuncAVGetBytesPerSample = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetBytesPerSample &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetBytesPerSample.run( + CallFrame, std::initializer_list{SampleFmtId}, + Result); + + EXPECT_TRUE(Result[0].get() >= 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_get_sample_fmt"); + auto &HostFuncAVGetSampleFmt = + dynamic_cast( + FuncInst->getHostFunc()); + + uint32_t SampleFmtStart = 100; + uint32_t SampleFmtSize = 2; + fillMemContent(MemInst, SampleFmtSize, SampleFmtSize); + + fillMemContent(MemInst, SampleFmtStart, std::string("u8")); + { + HostFuncAVGetSampleFmt.run(CallFrame, + std::initializer_list{ + SampleFmtStart, SampleFmtSize}, + Result); + + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_samples_get_buffer_size"); + auto &HostFuncAVSamplesGetBufferSize = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVSamplesGetBufferSize &>( + FuncInst->getHostFunc()); + + int32_t NbChannels = 1; + int32_t NbSamples = 5; + int32_t Align = 1; + int32_t BufSize = 0; + { + HostFuncAVSamplesGetBufferSize.run( + CallFrame, + std::initializer_list{NbChannels, NbSamples, + SampleFmtId, Align}, + Result); + + BufSize = Result[0].get(); + EXPECT_TRUE(BufSize); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_samples_alloc_array_and_samples"); + auto &HostFuncAVSamplesAllocArrayAndSamples = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVSamplesAllocArrayAndSamples &>( + FuncInst->getHostFunc()); + + { + HostFuncAVSamplesAllocArrayAndSamples.run( + CallFrame, + std::initializer_list{ + BufferPtr, LinesizePtr, NbChannels, NbSamples, SampleFmtId, Align}, + Result); + + EXPECT_TRUE(Result[0].get() >= 0); + } + + uint32_t BufId = readUInt32(MemInst, BufferPtr); + ASSERT_TRUE(BufId > 0); + + int32_t Length = 0; + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_sample_fmt_name_length"); + auto &HostFuncAVGetSampleFmtNameLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetSampleFmtNameLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetSampleFmtNameLength.run( + CallFrame, std::initializer_list{SampleFmtId}, + Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_sample_fmt_name"); + auto &HostFuncAVGetSampleFmtName = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetSampleFmtName &>( + FuncInst->getHostFunc()); + + // Fill Memory with 0. + fillMemContent(MemInst, NamePtr, Length); + { + HostFuncAVGetSampleFmtName.run(CallFrame, + std::initializer_list{ + SampleFmtId, NamePtr, Length}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_sample_fmt_mask"); + auto &HostFuncAVGetSampleFmtMask = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetSampleFmtMask &>( + FuncInst->getHostFunc()); + + { + uint32_t SampleId = 2; // AV_SAMPLE_FMT_S16; + HostFuncAVGetSampleFmtMask.run( + CallFrame, std::initializer_list{SampleId}, + Result); + + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_freep"); + auto &HostFuncAVFreep = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t BufferId = readUInt32(MemInst, BufferPtr); + HostFuncAVFreep.run(CallFrame, + std::initializer_list{BufferId}, + Result); + + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp b/test/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp new file mode 100644 index 000000000000..c6431ece35a7 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/avutil/avutil_func.cpp @@ -0,0 +1,261 @@ +#include "avutil/avutil_func.h" +#include "avutil/avTime.h" +#include "avutil/module.h" +#include "utils.h" + +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, AVUtilFunc) { + + ASSERT_TRUE(AVUtilMod != nullptr); + + uint32_t NamePtr = UINT32_C(4); + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_log_set_level"); + auto &HostFuncAVLogSetLevel = + dynamic_cast( + FuncInst->getHostFunc()); + + int32_t LogLvlId = 32; + { + HostFuncAVLogSetLevel.run( + CallFrame, std::initializer_list{LogLvlId}, + Result); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_log_get_level"); + auto &HostFuncAVLogGetLevel = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVLogGetLevel.run( + CallFrame, std::initializer_list{}, Result); + EXPECT_EQ(Result[0].get(), LogLvlId); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_log_set_flags"); + auto &HostFuncAVLogSetFlags = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVLogSetFlags.run( + CallFrame, std::initializer_list{1}, Result); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_log_get_flags"); + auto &HostFuncAVLogGetFlags = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVLogGetFlags.run( + CallFrame, std::initializer_list{1}, Result); + + EXPECT_EQ(Result[0].get(), 32); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_rescale_q"); + auto &HostFuncAVRescaleQ = + dynamic_cast( + FuncInst->getHostFunc()); + + int64_t A = 20; + int32_t BNum = 5; + int32_t BDen = 10; + int32_t CNum = 5; + int32_t CDen = 20; + + { + HostFuncAVRescaleQ.run( + CallFrame, + std::initializer_list{A, BNum, BDen, CNum, CDen}, + Result); + + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_rescale_q_rnd"); + auto &HostFuncAVRescaleQRnd = + dynamic_cast( + FuncInst->getHostFunc()); + + { + int32_t RoundingId = 2; + HostFuncAVRescaleQRnd.run(CallFrame, + std::initializer_list{ + A, BNum, BDen, CNum, CDen, RoundingId}, + Result); + + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_avutil_version"); + auto &HostFuncAVUtilVersion = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilVersion.run( + CallFrame, std::initializer_list{}, Result); + + EXPECT_TRUE(Result[0].get() > 0); + } + + uint64_t ChannelId = 1; // FRONT_LEFT + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_channel_layout_nb_channels"); + auto &HostFuncAVGetChannelLayoutNbChannels = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetChannelLayoutNbChannels &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetChannelLayoutNbChannels.run( + CallFrame, std::initializer_list{ChannelId}, + Result); + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_get_default_channel_layout"); + auto &HostFuncAVGetDefaultChannelLayout = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetDefaultChannelLayout &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetDefaultChannelLayout.run( + CallFrame, std::initializer_list{ChannelId}, + Result); + EXPECT_TRUE(Result[0].get() > 0); + } + + uint32_t Length = 0; + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_avutil_configuration_length"); + auto &HostFuncAVUtilConfigurationLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVUtilConfigurationLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilConfigurationLength.run( + CallFrame, std::initializer_list{}, Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill NamePtr with 0. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_avutil_configuration"); + auto &HostFuncAVUtilConfiguration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVUtilConfiguration &>( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilConfiguration.run( + CallFrame, std::initializer_list{NamePtr, Length}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_avutil_license_length"); + auto &HostFuncAVUtilLicenseLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVUtilLicenseLength &>( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilLicenseLength.run( + CallFrame, std::initializer_list{}, Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill NamePtr with 0. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_avutil_license"); + auto &HostFuncAVUtilLicense = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVUtilLicense.run( + CallFrame, std::initializer_list{NamePtr, Length}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +TEST_F(FFmpegTest, AVTime) { + + ASSERT_TRUE(AVUtilMod != nullptr); + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_gettime"); + auto &HostFuncAVGetTime = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVGetTime.run( + CallFrame, std::initializer_list{}, Result); + + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_gettime_relative"); + auto &HostFuncAVGetTimeRelative = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVGetTimeRelative.run( + CallFrame, std::initializer_list{}, Result); + + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = AVUtilMod->findFuncExports( + "wasmedge_ffmpeg_avutil_av_gettime_relative_is_monotonic"); + auto &HostFuncAVGetTimeRelativeIsMonotonic = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::AVGetTimeRelativeIsMonotonic &>( + FuncInst->getHostFunc()); + + { + HostFuncAVGetTimeRelativeIsMonotonic.run( + CallFrame, std::initializer_list{}, Result); + + EXPECT_EQ(Result[0].get(), 1); + } + + FuncInst = AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_usleep"); + auto &HostFuncAVUSleep = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncAVUSleep.run( + CallFrame, std::initializer_list{1000}, Result); + + EXPECT_EQ(Result[0].get(), 0); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/main.cpp b/test/plugins/wasmedge_ffmpeg/main.cpp new file mode 100644 index 000000000000..852694a07a86 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/main.cpp @@ -0,0 +1,6 @@ +#include + +GTEST_API_ int main(int Argc, char **Argv) { + testing::InitGoogleTest(&Argc, Argv); + return RUN_ALL_TESTS(); +} diff --git a/test/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp b/test/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp new file mode 100644 index 000000000000..c5879355923b --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/swresample/swresample_func.cpp @@ -0,0 +1,255 @@ +#include "swresample/swresample_func.h" +#include "swresample/module.h" + +#include "utils.h" +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +TEST_F(FFmpegTest, SWResampleFunc) { + + ASSERT_TRUE(SWResampleMod != nullptr); + + uint32_t DictPtr = UINT32_C(4); + uint32_t SWResamplePtr = UINT32_C(8); + uint32_t FramePtr = UINT32_C(72); + uint32_t Frame2Ptr = UINT32_C(16); + uint32_t KeyPtr = UINT32_C(100); + uint32_t ValuePtr = UINT32_C(200); + + initDict(DictPtr, KeyPtr, std::string("Key"), ValuePtr, std::string("Value")); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFFmpegStructs(UINT32_C(20), UINT32_C(24), UINT32_C(28), FileName, + UINT32_C(60), UINT32_C(64), UINT32_C(68), FramePtr); + + uint32_t StrPtr = UINT32_C(76); + initEmptyFrame(Frame2Ptr); + + uint32_t DictId = readUInt32(MemInst, DictPtr); + uint32_t FrameId = readUInt32(MemInst, FramePtr); + uint32_t Frame2Id = readUInt32(MemInst, Frame2Ptr); + + auto *FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swresample_version"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSWResampleVersion = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWResampleVersion &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSWResampleVersion.run(CallFrame, {}, Result)); + ASSERT_TRUE(Result[0].get() > 0); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swr_alloc_set_opts"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrAllocSetOpts = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWRAllocSetOpts &>( + FuncInst->getHostFunc()); + + // Testing with Null Old SwrCtx. Hence 2nd argument is 0. + { + uint32_t SWRCtxId = 0; + uint64_t OutChLayoutId = 1 << 1; // Front Right + uint32_t OutSampleFmtId = 2; // AV_SAMPLE_FMT_S16 + int32_t OutSampleRate = 30; + uint64_t InChLayoutId = 1 << 2; // FRONT_CENTER + uint32_t InSampleFmtId = 3; // AV_SAMPLE_FMT_S32 + int32_t SampleRate = 40; + int32_t LogOffset = 1; + + EXPECT_TRUE(HostFuncSwrAllocSetOpts.run( + CallFrame, + std::initializer_list{ + SWResamplePtr, SWRCtxId, OutChLayoutId, OutSampleFmtId, + OutSampleRate, InChLayoutId, InSampleFmtId, SampleRate, LogOffset}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SWResamplePtr) > 0); + } + + // Test with Existing SwrCtx. + uint32_t SwrId = readUInt32(MemInst, SWResamplePtr); + { + uint32_t SWRCtxId = SwrId; + uint64_t OutChLayoutId = 1 << 1; // Front Right + uint32_t OutSampleFmtId = 2; // AV_SAMPLE_FMT_S16 + int32_t OutSampleRate = 30; + uint64_t InChLayoutId = 1 << 2; // FRONT_CENTER + uint32_t InSampleFmtId = 3; // AV_SAMPLE_FMT_S32 + int32_t SampleRate = 40; + int32_t LogOffset = 1; + EXPECT_TRUE(HostFuncSwrAllocSetOpts.run( + CallFrame, + std::initializer_list{ + SWResamplePtr, SWRCtxId, OutChLayoutId, OutSampleFmtId, + OutSampleRate, InChLayoutId, InSampleFmtId, SampleRate, LogOffset}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SWResamplePtr) > 0); + } + + FuncInst = + SWResampleMod->findFuncExports("wasmedge_ffmpeg_swresample_swr_free"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrFree = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSwrFree.run( + CallFrame, std::initializer_list{SwrId}, Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + SWResampleMod->findFuncExports("wasmedge_ffmpeg_swresample_swr_init"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrInit = + dynamic_cast( + FuncInst->getHostFunc()); + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrInit.run( + CallFrame, std::initializer_list{SwrId}, Result)); + ASSERT_TRUE(Result[0].get() >= 0); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_av_opt_set_dict"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncAVOptSetDict = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t EmptyDictId = 0; + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncAVOptSetDict.run( + CallFrame, + std::initializer_list{SwrId, EmptyDictId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncAVOptSetDict.run( + CallFrame, std::initializer_list{SwrId, DictId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swr_convert_frame"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrConvertFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWRConvertFrame &>( + FuncInst->getHostFunc()); + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrConvertFrame.run( + CallFrame, + std::initializer_list{SwrId, Frame2Id, FrameId}, + Result)); + ASSERT_TRUE(Result[0].get()); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swr_get_delay"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrGetDelay = + dynamic_cast( + FuncInst->getHostFunc()); + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrGetDelay.run( + CallFrame, std::initializer_list{SwrId, 1}, + Result)); + EXPECT_EQ(Result[0].get(), 0); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swresample_configuration_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrConfigLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWResampleConfigurationLength + &>(FuncInst->getHostFunc()); + + int32_t Length = 0; + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrConfigLength.run( + CallFrame, std::initializer_list{}, Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swresample_configuration"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrConfig = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWResampleConfiguration &>( + FuncInst->getHostFunc()); + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrConfig.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swresample_license_length"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrLicenseLen = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWResampleLicenseLength &>( + FuncInst->getHostFunc()); + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrLicenseLen.run( + CallFrame, std::initializer_list{}, Result)); + + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = SWResampleMod->findFuncExports( + "wasmedge_ffmpeg_swresample_swresample_license"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwrLicense = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::SWResampleLicense &>( + FuncInst->getHostFunc()); + + { + SwrId = readUInt32(MemInst, SWResamplePtr); + EXPECT_TRUE(HostFuncSwrLicense.run( + CallFrame, std::initializer_list{StrPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/test/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp b/test/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp new file mode 100644 index 000000000000..cfe4b38c06a1 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/swscale/swscale_func.cpp @@ -0,0 +1,540 @@ +#include "swscale/swscale_func.h" +#include "swscale/module.h" + +#include "utils.h" +#include + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +// ============================================================================ +// This test deals with funcs related to SwsContext +// ============================================================================ + +TEST_F(FFmpegTest, SwsContext) { + + ASSERT_TRUE(SWScaleMod != nullptr); + + auto *FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getContext"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetContext = + dynamic_cast( + FuncInst->getHostFunc()); + + uint32_t SWScalePtr = UINT32_C(4); + uint32_t SWCachedScalePtr = UINT32_C(8); + uint32_t FramePtr = UINT32_C(72); + uint32_t Frame2Ptr = UINT32_C(124); + + std::string FileName = "ffmpeg-assets/sample_video.mp4"; // 32 chars + initFFmpegStructs(UINT32_C(12), UINT32_C(24), UINT32_C(28), FileName, + UINT32_C(60), UINT32_C(64), UINT32_C(68), FramePtr); + + initEmptyFrame(Frame2Ptr); + + uint32_t FrameId = readUInt32(MemInst, FramePtr); + uint32_t Frame2Id = readUInt32(MemInst, Frame2Ptr); + + uint32_t YUV420PId = 1; // YUV420P AVPixFormatId (From Bindings.h) + uint32_t RGB24Id = 3; // RGB24 AVPixFormatId (From Bindings.h) + uint32_t XVMCId = 174; // XVMC AVPixFormatId (From Bindings.h) + + uint32_t SrcWidth = 100; + uint32_t SrcHeight = 100; + uint32_t DestWidth = 200; + uint32_t DestHeight = 200; + int32_t Flags = 8; + uint32_t SrcFilterId = 0; + uint32_t DestFilterId = 0; + + // Allocating SWScale... + // Filter ID for source and destination is Null. + { + EXPECT_TRUE(HostFuncSwsGetContext.run( + CallFrame, + std::initializer_list{ + SWScalePtr, SrcWidth, SrcHeight, YUV420PId, DestWidth, DestHeight, + RGB24Id, Flags, SrcFilterId, DestFilterId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SWScalePtr) > 0); + } + + uint32_t SWSScaleId = readUInt32(MemInst, SWScalePtr); + ASSERT_TRUE(SWSScaleId > 0); + + // Checking correctness of function. Returns Invalid Argument Error. + FuncInst = SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_scale"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsScale = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE( + HostFuncSwsScale.run(CallFrame, + std::initializer_list{ + SWSScaleId, FrameId, 20, 40, Frame2Id}, + Result)); + EXPECT_EQ(Result[0].get(), -22); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_sws_getCachedContext"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetCachedContext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwsGetCachedContext &>( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSwsGetCachedContext.run( + CallFrame, + std::initializer_list{ + SWCachedScalePtr, SWSScaleId, SrcWidth, SrcHeight, YUV420PId, + DestWidth, DestHeight, RGB24Id, Flags, SrcFilterId, DestFilterId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SWCachedScalePtr) > 0); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_sws_isSupportedInput"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsIsSupportedInput = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwsIsSupportedInput &>( + FuncInst->getHostFunc()); + + { + // AV_PIX_FMT_RGB24 is supported Pixel Format + EXPECT_TRUE(HostFuncSwsIsSupportedInput.run( + CallFrame, std::initializer_list{RGB24Id}, + Result)); + ASSERT_TRUE(Result[0].get() > 0); + + // AV_PIX_FMT_XVMC is not supported Pixel Format + EXPECT_TRUE(HostFuncSwsIsSupportedInput.run( + CallFrame, std::initializer_list{XVMCId}, + Result)); + ASSERT_TRUE(Result[0].get() == 0); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_sws_isSupportedOutput"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsIsSupportedOutput = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwsIsSupportedOutput &>( + FuncInst->getHostFunc()); + + { + // AV_PIX_FMT_RGB24 is supported Pixel Format + EXPECT_TRUE(HostFuncSwsIsSupportedOutput.run( + CallFrame, std::initializer_list{RGB24Id}, + Result)); + ASSERT_TRUE(Result[0].get() > 0); + + // AV_PIX_FMT_XVMC is not supported Pixel Format + EXPECT_TRUE(HostFuncSwsIsSupportedOutput.run( + CallFrame, std::initializer_list{XVMCId}, + Result)); + ASSERT_TRUE(Result[0].get() == 0); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_sws_isSupportedEndiannessConversion"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsIsSupportedEndiannessConversion = + dynamic_cast( + FuncInst->getHostFunc()); + + { + // AV_PIX_FMT_XVMC is not supported Pixel Format for + EXPECT_TRUE(HostFuncSwsIsSupportedEndiannessConversion.run( + CallFrame, std::initializer_list{XVMCId}, + Result)); + ASSERT_TRUE(Result[0].get() == 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_freeContext"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsFreeContext = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSwsFreeContext.run( + CallFrame, std::initializer_list{SWSScaleId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + { + uint32_t InvalidDestWidth = -200; + uint32_t InvalidDestHeight = -200; + uint32_t SWScalePtrInvalid = UINT32_C(80); + EXPECT_TRUE(HostFuncSwsGetContext.run( + CallFrame, + std::initializer_list{ + SWScalePtrInvalid, SrcWidth, SrcHeight, YUV420PId, InvalidDestWidth, + InvalidDestHeight, RGB24Id, Flags, SrcFilterId, DestFilterId}, + Result)); + EXPECT_EQ(Result[0].get(), + static_cast(ErrNo::InternalError)); + ASSERT_TRUE(readUInt32(MemInst, SWScalePtrInvalid) == 0); + } +} + +// ============================================================================ +// This test deals with funcs related to SwsFilter. +// ============================================================================ + +TEST_F(FFmpegTest, SwsFilter) { + + ASSERT_TRUE(SWScaleMod != nullptr); + auto *FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_sws_getDefaultFilter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetDefaultFilter = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwsGetDefaultFilter &>( + FuncInst->getHostFunc()); + + uint32_t SwsFilterPtr = UINT32_C(40); + { + float LumaGBlur = 10.5; + float ChromaGBlur = 10.5; + float LumaSharpen = 10.5; + float ChromaSharpen = 10.5; + float ChromaHShift = 10.5; + float ChromaVShift = 10.5; + int32_t Verbose = 1; + + EXPECT_TRUE(HostFuncSwsGetDefaultFilter.run( + CallFrame, + std::initializer_list{ + SwsFilterPtr, LumaGBlur, ChromaGBlur, LumaSharpen, ChromaSharpen, + ChromaHShift, ChromaVShift, Verbose}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsFilterPtr) > 0); + } + + uint32_t FilterId = readUInt32(MemInst, SwsFilterPtr); + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getLumaH"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetLumaH = + dynamic_cast( + FuncInst->getHostFunc()); + + uint32_t SwsVectorPtr = UINT32_C(20); + { + EXPECT_TRUE(HostFuncSwsGetLumaH.run( + CallFrame, + std::initializer_list{FilterId, SwsVectorPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsVectorPtr) > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getLumaV"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetLumaV = + dynamic_cast( + FuncInst->getHostFunc()); + + { + writeUInt32(MemInst, UINT32_C(0), SwsVectorPtr); + EXPECT_TRUE(HostFuncSwsGetLumaV.run( + CallFrame, + std::initializer_list{FilterId, SwsVectorPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsVectorPtr) > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getChromaH"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetChromaH = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSwsGetChromaH.run( + CallFrame, + std::initializer_list{FilterId, SwsVectorPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsVectorPtr) > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getChromaV"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetChromaV = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSwsGetChromaV.run( + CallFrame, + std::initializer_list{FilterId, SwsVectorPtr}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsVectorPtr) > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_freeFilter"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsFreeFilter = + dynamic_cast( + FuncInst->getHostFunc()); + + { + EXPECT_TRUE(HostFuncSwsFreeFilter.run( + CallFrame, std::initializer_list{FilterId}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +// ============================================================================ +// This test deals with funcs related to SwsVector. +// ============================================================================ + +TEST_F(FFmpegTest, SwsVector) { + + ASSERT_TRUE(SWScaleMod != nullptr); + uint32_t SwsVectorPtr = UINT32_C(40); + uint32_t CoeffPtr = UINT32_C(100); + + auto *FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_allocVec"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsAllocVec = + dynamic_cast( + FuncInst->getHostFunc()); + + { + writeUInt32(MemInst, UINT32_C(0), SwsVectorPtr); + int32_t Length = 20; + EXPECT_TRUE(HostFuncSwsAllocVec.run( + CallFrame, + std::initializer_list{SwsVectorPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsVectorPtr) > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getGaussianVec"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetGaussianVec = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwsGetGaussianVec &>( + FuncInst->getHostFunc()); + + { + writeUInt32(MemInst, UINT32_C(0), SwsVectorPtr); + double Variance = 20.5; + double Quality = 4.3; + EXPECT_TRUE(HostFuncSwsGetGaussianVec.run( + CallFrame, + std::initializer_list{SwsVectorPtr, Variance, + Quality}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + ASSERT_TRUE(readUInt32(MemInst, SwsVectorPtr) > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_scaleVec"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsScaleVec = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t SwsVecId = readUInt32(MemInst, SwsVectorPtr); + double Scalar = 20.35; + EXPECT_TRUE(HostFuncSwsScaleVec.run( + CallFrame, + std::initializer_list{SwsVecId, Scalar}, Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_normalizeVec"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsNormalizeVec = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t SwsVecId = readUInt32(MemInst, SwsVectorPtr); + double Height = 4.3; + EXPECT_TRUE(HostFuncSwsNormalizeVec.run( + CallFrame, + std::initializer_list{SwsVecId, Height}, Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_sws_getCoeffVecLength"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetCoeffVecLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwsGetCoeffVecLength &>( + FuncInst->getHostFunc()); + + int Length = 0; + { + uint32_t SwsVecId = readUInt32(MemInst, SwsVectorPtr); + EXPECT_TRUE(HostFuncSwsGetCoeffVecLength.run( + CallFrame, std::initializer_list{SwsVecId}, + Result)); + Length = Result[0].get(); + ASSERT_TRUE(Length > 0); + } + + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_getCoeff"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsGetCoeff = + dynamic_cast( + FuncInst->getHostFunc()); + + fillMemContent(MemInst, CoeffPtr, Length); + { + uint32_t SwsVecId = readUInt32(MemInst, SwsVectorPtr); + EXPECT_TRUE(HostFuncSwsGetCoeff.run( + CallFrame, + std::initializer_list{SwsVecId, CoeffPtr, Length}, + Result)); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_sws_freeVec"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncSwsFreeVec = + dynamic_cast( + FuncInst->getHostFunc()); + + { + uint32_t SwsVecId = readUInt32(MemInst, SwsVectorPtr); + EXPECT_TRUE(HostFuncSwsFreeVec.run( + CallFrame, std::initializer_list{SwsVecId}, + Result)); + } +} + +// ============================================================================ +// This test deals with funcs related to Version, Configuration and License +// ============================================================================ + +TEST_F(FFmpegTest, SWScaleVersion) { + + ASSERT_TRUE(SWScaleMod != nullptr); + + uint32_t Length = 0; + uint32_t NamePtr = UINT32_C(8); + + auto *FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_swscale_version"); + auto &HostFuncSwscaleVersion = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncSwscaleVersion.run( + CallFrame, std::initializer_list{}, Result); + + EXPECT_TRUE(Result[0].get() > 0); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_swscale_configuration_length"); + auto &HostFuncSwscaleConfigurationLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwscaleConfigurationLength &>( + FuncInst->getHostFunc()); + + { + HostFuncSwscaleConfigurationLength.run( + CallFrame, std::initializer_list{}, Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Testing Version, Configuration, License + // Fill NamePtr with 0. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_swscale_configuration"); + auto &HostFuncSwscaleConfiguration = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwscaleConfiguration &>( + FuncInst->getHostFunc()); + + { + HostFuncSwscaleConfiguration.run( + CallFrame, std::initializer_list{NamePtr, Length}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } + + FuncInst = SWScaleMod->findFuncExports( + "wasmedge_ffmpeg_swscale_swscale_license_length"); + auto &HostFuncSwscaleLicenseLength = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::SwscaleLicenseLength &>( + FuncInst->getHostFunc()); + + { + HostFuncSwscaleLicenseLength.run( + CallFrame, std::initializer_list{}, Result); + + Length = Result[0].get(); + EXPECT_TRUE(Length > 0); + } + + // Fill NamePtr with 0. + fillMemContent(MemInst, NamePtr, Length); + FuncInst = + SWScaleMod->findFuncExports("wasmedge_ffmpeg_swscale_swscale_license"); + auto &HostFuncSwscaleLicense = + dynamic_cast( + FuncInst->getHostFunc()); + + { + HostFuncSwscaleLicense.run( + CallFrame, std::initializer_list{NamePtr, Length}, + Result); + EXPECT_EQ(Result[0].get(), static_cast(ErrNo::Success)); + } +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/utils.cpp b/test/plugins/wasmedge_ffmpeg/utils.cpp new file mode 100644 index 000000000000..cef6ba40adf6 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/utils.cpp @@ -0,0 +1,259 @@ +#include "utils.h" +#include "avcodec/avCodecContext.h" +#include "avcodec/avPacket.h" +#include "avcodec/avcodec_func.h" +#include "avformat/avStream.h" +#include "avformat/avformat_func.h" +#include "avutil/avDictionary.h" +#include "avutil/avFrame.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { + +void FFmpegTest::initEmptyFrame(uint32_t FramePtr) { + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_frame_alloc"); + auto &HostFuncAVFrameAlloc = + dynamic_cast( + FuncInst->getHostFunc()); + HostFuncAVFrameAlloc.run( + CallFrame, std::initializer_list{FramePtr}, Result); +} + +void FFmpegTest::initFFmpegStructs(uint32_t AVCodecPtr, uint32_t AVFormatCtxPtr, + uint32_t FilePtr, std::string FileName, + uint32_t CodecParameterPtr, + uint32_t AVCodecCtxPtr, uint32_t PacketPtr, + uint32_t FramePtr) { + initFormatCtx(AVFormatCtxPtr, FilePtr, FileName); + + uint32_t AvFormatCtxId = readUInt32(MemInst, AVFormatCtxPtr); + + auto *FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_av_find_best_stream"); + auto &HostFuncAVFindBestStream = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFindBestStream &>( + FuncInst->getHostFunc()); + uint32_t MediaTypeId = 0; // Video + uint32_t WantedStream = -1; + uint32_t RelatedStream = -1; + uint32_t DecoderRetId = 0; + uint32_t Flags = 0; + HostFuncAVFindBestStream.run(CallFrame, + std::initializer_list{ + AvFormatCtxId, MediaTypeId, WantedStream, + RelatedStream, DecoderRetId, Flags}, + Result); + + uint32_t StreamIdx = Result[0].get(); + + FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avStream_codecpar"); + + auto &HostFuncAVStreamCodecpar = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVStreamCodecPar &>( + FuncInst->getHostFunc()); + + HostFuncAVStreamCodecpar.run(CallFrame, + std::initializer_list{ + AvFormatCtxId, StreamIdx, CodecParameterPtr}, + Result); + + uint32_t CodecParametersId = readUInt32(MemInst, CodecParameterPtr); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_alloc_context3"); + auto &HostFuncAVCodecAllocContext3 = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecAllocContext3 &>( + FuncInst->getHostFunc()); + + HostFuncAVCodecAllocContext3.run( + CallFrame, std::initializer_list{0, AVCodecCtxPtr}, + Result); + + uint32_t AVCodecCtxId = readUInt32(MemInst, AVCodecCtxPtr); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_parameters_to_context"); + auto &HostFuncAVCodecParametersToContext = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecParametersToContext &>( + FuncInst->getHostFunc()); + + HostFuncAVCodecParametersToContext.run( + CallFrame, + std::initializer_list{AVCodecCtxId, + CodecParametersId}, + Result); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodeccontext_codec_id"); + auto &HostFuncAVCodecContextCodecId = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecCtxCodecID &>( + FuncInst->getHostFunc()); + + HostFuncAVCodecContextCodecId.run( + CallFrame, std::initializer_list{AVCodecCtxId}, + Result); + + uint32_t CodecId = Result[0].get(); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_find_decoder"); + auto &HostFuncAVCodecFindDecoder = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecFindDecoder &>( + FuncInst->getHostFunc()); + + HostFuncAVCodecFindDecoder.run( + CallFrame, + std::initializer_list{CodecId, AVCodecPtr}, Result); + + uint32_t AVCodecId = readUInt32(MemInst, AVCodecPtr); + + FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_avcodec_open2"); + auto &HostFuncAVCodecOpen2 = + dynamic_cast( + FuncInst->getHostFunc()); + + HostFuncAVCodecOpen2.run( + CallFrame, + std::initializer_list{AVCodecCtxId, AVCodecId, 0}, + Result); + + initEmptyFrame(FramePtr); + uint32_t FrameId = readUInt32(MemInst, FramePtr); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_receive_frame"); + auto &HostFuncAVCodecReceiveFrame = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecReceiveFrame &>( + FuncInst->getHostFunc()); + + FuncInst = + AVFormatMod->findFuncExports("wasmedge_ffmpeg_avformat_av_read_frame"); + auto &HostFuncAVReadFrame = + dynamic_cast( + FuncInst->getHostFunc()); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_avcodec_send_packet"); + auto &HostFuncAVCodecSendPacket = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVCodecSendPacket &>( + FuncInst->getHostFunc()); + + FuncInst = AVCodecMod->findFuncExports( + "wasmedge_ffmpeg_avcodec_av_packet_stream_index"); + auto &HostFuncAVPacketStreamIndex = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::AVPacketStreamIndex &>( + FuncInst->getHostFunc()); + + while (true) { + + HostFuncAVCodecReceiveFrame.run( + CallFrame, + std::initializer_list{AVCodecCtxId, FrameId}, + Result); + + // Error returned by FFmpeg are negative. + int32_t Error = Result[0].get() * -1; + + if (Error == EAGAIN) { + while (true) { + + allocPacket(PacketPtr); + + uint32_t PackedId = readUInt32(MemInst, PacketPtr); + + while (true) { + HostFuncAVReadFrame.run(CallFrame, + std::initializer_list{ + AvFormatCtxId, PackedId}, + Result); + + int32_t Res = Result[0].get(); + if (Res == 0 || Res == AVERROR_EOF) { + break; + } + } + + HostFuncAVPacketStreamIndex.run( + CallFrame, + std::initializer_list{AVCodecCtxId, FrameId}, + Result); + + uint32_t PacketStreamIdx = Result[0].get(); + + if (PacketStreamIdx != StreamIdx) { + continue; + } + + HostFuncAVCodecSendPacket.run( + CallFrame, + std::initializer_list{AVCodecCtxId, PackedId}, + Result); + break; + } + } else { + break; + } + } +} + +void FFmpegTest::initFormatCtx(uint32_t AVFormatCtxPtr, uint32_t FilePtr, + std::string FileName) { + + int32_t Length = FileName.length(); + fillMemContent(MemInst, FilePtr, Length); + fillMemContent(MemInst, FilePtr, FileName); + + auto *FuncInst = AVFormatMod->findFuncExports( + "wasmedge_ffmpeg_avformat_avformat_open_input"); + auto &HostFuncAVFormatOpenInput = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::AVFormatOpenInput &>( + FuncInst->getHostFunc()); + HostFuncAVFormatOpenInput.run( + CallFrame, + std::initializer_list{ + AVFormatCtxPtr, FilePtr, Length, UINT32_C(0), UINT32_C(0)}, + Result); +} + +void FFmpegTest::initDict(uint32_t DictPtr, uint32_t KeyPtr, std::string Key, + uint32_t ValuePtr, std::string Value) { + + uint32_t KeyLen = Key.length(); + uint32_t ValueLen = Value.length(); + fillMemContent(MemInst, KeyPtr, KeyLen + ValueLen); + fillMemContent(MemInst, KeyPtr, Key); + fillMemContent(MemInst, ValuePtr, Value); + + auto *FuncInst = + AVUtilMod->findFuncExports("wasmedge_ffmpeg_avutil_av_dict_set"); + auto &HostFuncAVDictSet = + dynamic_cast( + FuncInst->getHostFunc()); + + HostFuncAVDictSet.run(CallFrame, + std::initializer_list{ + DictPtr, KeyPtr, KeyLen, ValuePtr, ValueLen, 0}, + Result); +} + +void FFmpegTest::allocPacket(uint32_t PacketPtr) { + + auto *FuncInst = + AVCodecMod->findFuncExports("wasmedge_ffmpeg_avcodec_av_packet_alloc"); + auto &HostFuncAVPacketAlloc = + dynamic_cast( + FuncInst->getHostFunc()); + + HostFuncAVPacketAlloc.run( + CallFrame, std::initializer_list{PacketPtr}, + Result); +} + +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_ffmpeg/utils.h b/test/plugins/wasmedge_ffmpeg/utils.h new file mode 100644 index 000000000000..9128bacd73c4 --- /dev/null +++ b/test/plugins/wasmedge_ffmpeg/utils.h @@ -0,0 +1,164 @@ +#pragma once +#include "avcodec/module.h" +#include "avfilter/module.h" +#include "avformat/module.h" +#include "avutil/module.h" +#include "common/types.h" +#include "runtime/callingframe.h" +#include "runtime/instance/module.h" +#include "swresample/module.h" +#include "swscale/module.h" +#include "gtest/gtest.h" + +namespace WasmEdge { +namespace Host { +namespace WasmEdgeFFmpeg { +inline void writeUInt32(WasmEdge::Runtime::Instance::MemoryInstance *MemInst, + uint32_t Value, uint32_t &Ptr) { + uint32_t *BufPtr = MemInst->getPointer(Ptr); + *BufPtr = Value; +} + +inline void fillMemContent(WasmEdge::Runtime::Instance::MemoryInstance *MemInst, + uint32_t Offset, uint32_t Cnt, + uint8_t C = 0) noexcept { + std::fill_n(MemInst->getPointer(Offset), Cnt, C); +} + +inline void fillMemContent(WasmEdge::Runtime::Instance::MemoryInstance *MemInst, + uint32_t Offset, const std::string &Str) noexcept { + char *Buf = MemInst->getPointer(Offset); + std::copy_n(Str.c_str(), Str.length(), Buf); +} + +inline void writeSInt32(WasmEdge::Runtime::Instance::MemoryInstance *MemInst, + int32_t Value, uint32_t &Ptr) { + int32_t *BufPtr = MemInst->getPointer(Ptr); + *BufPtr = Value; +} + +inline int32_t readSInt32(WasmEdge::Runtime::Instance::MemoryInstance *MemInst, + uint32_t &Ptr) { + int32_t *BufPtr = MemInst->getPointer(Ptr); + return *BufPtr; +} + +inline uint32_t readUInt32(WasmEdge::Runtime::Instance::MemoryInstance *MemInst, + uint32_t &Ptr) { + uint32_t *BufPtr = MemInst->getPointer(Ptr); + return *BufPtr; +} + +class FFmpegTest : public ::testing::Test { +public: + FFmpegTest() : Mod(""), CallFrame(nullptr, &Mod) { + Mod.addHostMemory( + "memory", std::make_unique( + WasmEdge::AST::MemoryType(1))); + MemInst = Mod.findMemoryExports("memory"); + + using namespace std::literals::string_view_literals; + WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( + "../../../plugins/wasmedge_ffmpeg/" + "libwasmedgePluginWasmEdgeFFmpeg" WASMEDGE_LIB_EXTENSION)); + if (const auto *Plugin = + WasmEdge::Plugin::Plugin::find("wasmedge_ffmpeg"sv)) { + if (const auto *Module = + Plugin->findModule("wasmedge_ffmpeg_avformat"sv)) { + AVFormatMod = dynamic_cast( + Module->create().release()); + } + if (const auto *Module = Plugin->findModule("wasmedge_ffmpeg_avutil"sv)) { + AVUtilMod = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::WasmEdgeFFmpegAVUtilModule + *>(Module->create().release()); + } + if (const auto *Module = + Plugin->findModule("wasmedge_ffmpeg_swscale"sv)) { + SWScaleMod = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::WasmEdgeFFmpegSWScaleModule + *>(Module->create().release()); + } + if (const auto *Module = + Plugin->findModule("wasmedge_ffmpeg_avcodec"sv)) { + AVCodecMod = dynamic_cast< + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::WasmEdgeFFmpegAVCodecModule + *>(Module->create().release()); + } + if (const auto *Module = + Plugin->findModule("wasmedge_ffmpeg_swresample"sv)) { + SWResampleMod = + dynamic_cast( + Module->create().release()); + } + if (const auto *Module = + Plugin->findModule("wasmedge_ffmpeg_avfilter"sv)) { + AVFilterMod = dynamic_cast( + Module->create().release()); + } + } + } + + ~FFmpegTest() override { + if (AVUtilMod) { + delete AVUtilMod; + } + if (AVCodecMod) { + delete AVCodecMod; + } + if (SWScaleMod) { + delete SWScaleMod; + } + if (SWResampleMod) { + delete SWResampleMod; + } + if (AVFormatMod) { + delete AVFormatMod; + } + if (AVFilterMod) { + delete AVFilterMod; + } + } + +protected: + void initEmptyFrame(uint32_t FramePtr); + + void initDict(uint32_t DictPtr, uint32_t KeyPtr, std::string Key, + uint32_t ValuePtr, std::string Value); + void initFFmpegStructs(uint32_t AVCodecPtr, uint32_t AVFormatCtxPtr, + uint32_t FilePtr, std::string FileName, + uint32_t CodecParameterPtr, uint32_t AVCodecCtxPtr, + uint32_t PacketPtr, uint32_t FramePtr); + + void initFormatCtx(uint32_t AVFormatCtxPtr, uint32_t FilePtr, + std::string FileName); + void allocPacket(uint32_t PacketPtr); + + // Result of Funcs to be stored here. + std::array Result = {UINT32_C(0)}; + + // Create the calling frame with memory instance. + WasmEdge::Runtime::Instance::ModuleInstance Mod; + WasmEdge::Runtime::Instance::MemoryInstance *MemInst; + WasmEdge::Runtime::CallingFrame CallFrame; + + // Wasm Modules. + WasmEdge::Host::WasmEdgeFFmpeg::AVFormat::WasmEdgeFFmpegAVFormatModule + *AVFormatMod = nullptr; + WasmEdge::Host::WasmEdgeFFmpeg::AVUtil::WasmEdgeFFmpegAVUtilModule + *AVUtilMod = nullptr; + WasmEdge::Host::WasmEdgeFFmpeg::SWResample::WasmEdgeFFmpegSWResampleModule + *SWResampleMod = nullptr; + WasmEdge::Host::WasmEdgeFFmpeg::SWScale::WasmEdgeFFmpegSWScaleModule + *SWScaleMod = nullptr; + WasmEdge::Host::WasmEdgeFFmpeg::AVcodec::WasmEdgeFFmpegAVCodecModule + *AVCodecMod = nullptr; + WasmEdge::Host::WasmEdgeFFmpeg::AVFilter::WasmEdgeFFmpegAVFilterModule + *AVFilterMod = nullptr; +}; +} // namespace WasmEdgeFFmpeg +} // namespace Host +} // namespace WasmEdge \ No newline at end of file diff --git a/utils/ffmpeg/download-ffmpeg-sample-video.sh b/utils/ffmpeg/download-ffmpeg-sample-video.sh new file mode 100644 index 000000000000..fabbf84ab9b2 --- /dev/null +++ b/utils/ffmpeg/download-ffmpeg-sample-video.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-FileCopyrightText: 2019-2022 Second State INC + +# The below video used is sourced from an ffmpeg-libav-tutorial repository. +# Source: https://github.com/leandromoreira/ffmpeg-libav-tutorial/blob/master/LICENSE. +TODIR=$1 +SAMPLE_VIDEO=https://raw.githubusercontent.com/Hrushi20/rust-ffmpeg/master/assets/bunny.mp4 +if [[ $# -eq 0 ]]; then + TODIR=. +fi +if [ ! -d $TODIR ]; then + mkdir $TODIR +fi +if [ ! -d $TODIR ]; then + mkdir $TODIR +fi + +if [ ! -f $TODIR/sample_video.mp4 ]; then + curl -sL $SAMPLE_VIDEO -o $TODIR/sample_video.mp4 + cp $TODIR/sample_video.mp4 $TODIR/dummy.mp4 # Dummy file to manipulate and run tests on file. +fi diff --git a/utils/ffmpeg/install-ffmpeg-v6.0.sh b/utils/ffmpeg/install-ffmpeg-v6.0.sh new file mode 100755 index 000000000000..72ac145898a6 --- /dev/null +++ b/utils/ffmpeg/install-ffmpeg-v6.0.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +rm -rf FFmpeg-n6.0 ffmpeg.zip +echo $(pwd) + +curl -sL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n6.0.zip -o ffmpeg.zip + +unzip ffmpeg.zip + +mkdir -p FFmpeg-n6.0/output +cd FFmpeg-n6.0 +./configure --prefix=$(pwd)/output --enable-gpl --enable-nonfree --enable-shared --disable-static +make && make install +cd .. \ No newline at end of file From 9084bbc8f244312ee49257228f36b98769f39a74 Mon Sep 17 00:00:00 2001 From: "LO, CHIN-HAO" <49036880+hankluo6@users.noreply.github.com> Date: Tue, 12 Mar 2024 02:22:44 -0400 Subject: [PATCH 089/218] [Installer] Add rustls plugin's name into env file (#3265) Signed-off-by: hankluo6 --- utils/install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/install.py b/utils/install.py index 4759f2a0ef4a..be71670a7a68 100644 --- a/utils/install.py +++ b/utils/install.py @@ -178,8 +178,8 @@ def extract_archive( fname = fname[:-5] + "lib" if fname.startswith("/usr") and "lib64" in fname: fname = fname.replace("lib64", "lib", 1) - # ggml-metal.metal is downloaded if we download ggml plugin on macOS - if "Plugin" in fname or fname == "ggml-metal.metal": + + if to_path.endswith("Plugins"): if is_default_path(args): fname = fname.replace( join(ipath, CONST_lib_dir, "wasmedge/"), "" From 155ac84e6b4981d5a8f42cfa83c8645b9254dbca Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 12 Mar 2024 18:24:37 +0800 Subject: [PATCH 090/218] [CI] Change the runner from linux-arm64 to linux-arm64-v2 (#3270) Signed-off-by: hydai --- .github/actions/expand-variables/dist/index.js | 2 +- .github/actions/expand-variables/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/expand-variables/dist/index.js b/.github/actions/expand-variables/dist/index.js index f2260c8e3ad0..63c774096b5e 100644 --- a/.github/actions/expand-variables/dist/index.js +++ b/.github/actions/expand-variables/dist/index.js @@ -26599,7 +26599,7 @@ const archList = [{ asset_tag: 'manylinux2014_x86_64', }, { arch: aarch64, - runner: 'linux-arm64', + runner: 'linux-arm64-v2', docker_tag: 'manylinux2014_aarch64-plugins-deps', asset_tag: 'manylinux2014_aarch64', }]; diff --git a/.github/actions/expand-variables/main.js b/.github/actions/expand-variables/main.js index adce1e1b0601..acb644d4953a 100644 --- a/.github/actions/expand-variables/main.js +++ b/.github/actions/expand-variables/main.js @@ -8,7 +8,7 @@ const archList = [{ asset_tag: 'manylinux2014_x86_64', }, { arch: aarch64, - runner: 'linux-arm64', + runner: 'linux-arm64-v2', docker_tag: 'manylinux2014_aarch64-plugins-deps', asset_tag: 'manylinux2014_aarch64', }]; From 7db12131217df21811cfab42e3747fc752c16cab Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Mon, 11 Mar 2024 17:44:46 +0800 Subject: [PATCH 091/218] [CI] Refactor manylinux plugins * Fix PKG_CONFIG_PATH Signed-off-by: Yi Huang --- .../actions/expand-variables/dist/index.js | 982 +++++++++--------- .github/actions/expand-variables/main.js | 54 + .../expand-variables/package-lock.json | 160 ++- .github/actions/expand-variables/package.json | 3 +- .github/workflows/build-extensions.yml | 146 +-- ...reusable-build-extensions-on-manylinux.yml | 63 +- .../workflows/reusable-build-extensions.yml | 2 +- 7 files changed, 774 insertions(+), 636 deletions(-) diff --git a/.github/actions/expand-variables/dist/index.js b/.github/actions/expand-variables/dist/index.js index 63c774096b5e..8bfced48c123 100644 --- a/.github/actions/expand-variables/dist/index.js +++ b/.github/actions/expand-variables/dist/index.js @@ -1,7 +1,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 3651: +/***/ 8452: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -28,7 +28,7 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; const os = __importStar(__nccwpck_require__(2037)); -const utils_1 = __nccwpck_require__(1324); +const utils_1 = __nccwpck_require__(9842); /** * Commands * @@ -100,7 +100,7 @@ function escapeProperty(s) { /***/ }), -/***/ 4136: +/***/ 5662: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -135,12 +135,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(3651); -const file_command_1 = __nccwpck_require__(2533); -const utils_1 = __nccwpck_require__(1324); +const command_1 = __nccwpck_require__(8452); +const file_command_1 = __nccwpck_require__(1941); +const utils_1 = __nccwpck_require__(9842); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); -const oidc_utils_1 = __nccwpck_require__(6354); +const oidc_utils_1 = __nccwpck_require__(5904); /** * The code to exit an action */ @@ -425,17 +425,17 @@ exports.getIDToken = getIDToken; /** * Summary exports */ -var summary_1 = __nccwpck_require__(6817); +var summary_1 = __nccwpck_require__(7035); Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); /** * @deprecated use core.summary */ -var summary_2 = __nccwpck_require__(6817); +var summary_2 = __nccwpck_require__(7035); Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); /** * Path exports */ -var path_utils_1 = __nccwpck_require__(8040); +var path_utils_1 = __nccwpck_require__(4039); Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); @@ -443,7 +443,7 @@ Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: funct /***/ }), -/***/ 2533: +/***/ 1941: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -474,8 +474,8 @@ exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); -const uuid_1 = __nccwpck_require__(2228); -const utils_1 = __nccwpck_require__(1324); +const uuid_1 = __nccwpck_require__(8689); +const utils_1 = __nccwpck_require__(9842); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { @@ -508,7 +508,7 @@ exports.prepareKeyValueMessage = prepareKeyValueMessage; /***/ }), -/***/ 6354: +/***/ 5904: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -524,9 +524,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(5957); -const auth_1 = __nccwpck_require__(1410); -const core_1 = __nccwpck_require__(4136); +const http_client_1 = __nccwpck_require__(4498); +const auth_1 = __nccwpck_require__(1562); +const core_1 = __nccwpck_require__(5662); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -592,7 +592,7 @@ exports.OidcClient = OidcClient; /***/ }), -/***/ 8040: +/***/ 4039: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -657,7 +657,7 @@ exports.toPlatformPath = toPlatformPath; /***/ }), -/***/ 6817: +/***/ 7035: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -947,7 +947,7 @@ exports.summary = _summary; /***/ }), -/***/ 1324: +/***/ 9842: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -994,7 +994,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 1410: +/***/ 1562: /***/ (function(__unused_webpack_module, exports) { "use strict"; @@ -1082,7 +1082,7 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 5957: +/***/ 4498: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1124,9 +1124,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; const http = __importStar(__nccwpck_require__(3685)); const https = __importStar(__nccwpck_require__(5687)); -const pm = __importStar(__nccwpck_require__(1456)); -const tunnel = __importStar(__nccwpck_require__(796)); -const undici_1 = __nccwpck_require__(2606); +const pm = __importStar(__nccwpck_require__(864)); +const tunnel = __importStar(__nccwpck_require__(2618)); +const undici_1 = __nccwpck_require__(4445); var HttpCodes; (function (HttpCodes) { HttpCodes[HttpCodes["OK"] = 200] = "OK"; @@ -1745,7 +1745,7 @@ const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCa /***/ }), -/***/ 1456: +/***/ 864: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -1834,15 +1834,15 @@ function isLoopbackAddress(host) { /***/ }), -/***/ 796: +/***/ 2618: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(6891); +module.exports = __nccwpck_require__(4658); /***/ }), -/***/ 6891: +/***/ 4658: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2114,32 +2114,32 @@ exports.debug = debug; // for test /***/ }), -/***/ 2606: +/***/ 4445: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Client = __nccwpck_require__(4256) -const Dispatcher = __nccwpck_require__(7978) -const errors = __nccwpck_require__(51) -const Pool = __nccwpck_require__(135) -const BalancedPool = __nccwpck_require__(1438) -const Agent = __nccwpck_require__(2438) -const util = __nccwpck_require__(2014) +const Client = __nccwpck_require__(2914) +const Dispatcher = __nccwpck_require__(2804) +const errors = __nccwpck_require__(6330) +const Pool = __nccwpck_require__(9944) +const BalancedPool = __nccwpck_require__(2503) +const Agent = __nccwpck_require__(9614) +const util = __nccwpck_require__(2423) const { InvalidArgumentError } = errors -const api = __nccwpck_require__(4908) -const buildConnector = __nccwpck_require__(5599) -const MockClient = __nccwpck_require__(4927) -const MockAgent = __nccwpck_require__(3667) -const MockPool = __nccwpck_require__(9726) -const mockErrors = __nccwpck_require__(2106) -const ProxyAgent = __nccwpck_require__(6524) -const RetryHandler = __nccwpck_require__(5112) -const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(6223) -const DecoratorHandler = __nccwpck_require__(1509) -const RedirectHandler = __nccwpck_require__(7144) -const createRedirectInterceptor = __nccwpck_require__(6789) +const api = __nccwpck_require__(6813) +const buildConnector = __nccwpck_require__(8074) +const MockClient = __nccwpck_require__(4454) +const MockAgent = __nccwpck_require__(580) +const MockPool = __nccwpck_require__(4002) +const mockErrors = __nccwpck_require__(5603) +const ProxyAgent = __nccwpck_require__(4080) +const RetryHandler = __nccwpck_require__(1010) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(6835) +const DecoratorHandler = __nccwpck_require__(3860) +const RedirectHandler = __nccwpck_require__(9644) +const createRedirectInterceptor = __nccwpck_require__(8573) let hasCrypto try { @@ -2222,7 +2222,7 @@ if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { let fetchImpl = null module.exports.fetch = async function fetch (resource) { if (!fetchImpl) { - fetchImpl = (__nccwpck_require__(3246).fetch) + fetchImpl = (__nccwpck_require__(7628).fetch) } try { @@ -2235,20 +2235,20 @@ if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { throw err } } - module.exports.Headers = __nccwpck_require__(3767).Headers - module.exports.Response = __nccwpck_require__(6476).Response - module.exports.Request = __nccwpck_require__(6814).Request - module.exports.FormData = __nccwpck_require__(4089).FormData - module.exports.File = __nccwpck_require__(8731).File - module.exports.FileReader = __nccwpck_require__(7689).FileReader + module.exports.Headers = __nccwpck_require__(2836).Headers + module.exports.Response = __nccwpck_require__(786).Response + module.exports.Request = __nccwpck_require__(3437).Request + module.exports.FormData = __nccwpck_require__(9188).FormData + module.exports.File = __nccwpck_require__(3442).File + module.exports.FileReader = __nccwpck_require__(7872).FileReader - const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(4612) + const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(4767) module.exports.setGlobalOrigin = setGlobalOrigin module.exports.getGlobalOrigin = getGlobalOrigin - const { CacheStorage } = __nccwpck_require__(5420) - const { kConstruct } = __nccwpck_require__(1837) + const { CacheStorage } = __nccwpck_require__(1012) + const { kConstruct } = __nccwpck_require__(2182) // Cache & CacheStorage are tightly coupled with fetch. Even if it may run // in an older version of Node, it doesn't have any use without fetch. @@ -2256,21 +2256,21 @@ if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { } if (util.nodeMajor >= 16) { - const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(2739) + const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(49) module.exports.deleteCookie = deleteCookie module.exports.getCookies = getCookies module.exports.getSetCookies = getSetCookies module.exports.setCookie = setCookie - const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(834) + const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6515) module.exports.parseMIMEType = parseMIMEType module.exports.serializeAMimeType = serializeAMimeType } if (util.nodeMajor >= 18 && hasCrypto) { - const { WebSocket } = __nccwpck_require__(1917) + const { WebSocket } = __nccwpck_require__(7183) module.exports.WebSocket = WebSocket } @@ -2289,20 +2289,20 @@ module.exports.mockErrors = mockErrors /***/ }), -/***/ 2438: +/***/ 9614: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { InvalidArgumentError } = __nccwpck_require__(51) -const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(7460) -const DispatcherBase = __nccwpck_require__(854) -const Pool = __nccwpck_require__(135) -const Client = __nccwpck_require__(4256) -const util = __nccwpck_require__(2014) -const createRedirectInterceptor = __nccwpck_require__(6789) -const { WeakRef, FinalizationRegistry } = __nccwpck_require__(4142)() +const { InvalidArgumentError } = __nccwpck_require__(6330) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(5724) +const DispatcherBase = __nccwpck_require__(996) +const Pool = __nccwpck_require__(9944) +const Client = __nccwpck_require__(2914) +const util = __nccwpck_require__(2423) +const createRedirectInterceptor = __nccwpck_require__(8573) +const { WeakRef, FinalizationRegistry } = __nccwpck_require__(4987)() const kOnConnect = Symbol('onConnect') const kOnDisconnect = Symbol('onDisconnect') @@ -2445,11 +2445,11 @@ module.exports = Agent /***/ }), -/***/ 9670: +/***/ 3121: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const { addAbortListener } = __nccwpck_require__(2014) -const { RequestAbortedError } = __nccwpck_require__(51) +const { addAbortListener } = __nccwpck_require__(2423) +const { RequestAbortedError } = __nccwpck_require__(6330) const kListener = Symbol('kListener') const kSignal = Symbol('kSignal') @@ -2506,16 +2506,16 @@ module.exports = { /***/ }), -/***/ 9725: +/***/ 5643: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { AsyncResource } = __nccwpck_require__(852) -const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(51) -const util = __nccwpck_require__(2014) -const { addSignal, removeSignal } = __nccwpck_require__(9670) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(6330) +const util = __nccwpck_require__(2423) +const { addSignal, removeSignal } = __nccwpck_require__(3121) class ConnectHandler extends AsyncResource { constructor (opts, callback) { @@ -2618,7 +2618,7 @@ module.exports = connect /***/ }), -/***/ 6346: +/***/ 9745: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -2633,10 +2633,10 @@ const { InvalidArgumentError, InvalidReturnValueError, RequestAbortedError -} = __nccwpck_require__(51) -const util = __nccwpck_require__(2014) +} = __nccwpck_require__(6330) +const util = __nccwpck_require__(2423) const { AsyncResource } = __nccwpck_require__(852) -const { addSignal, removeSignal } = __nccwpck_require__(9670) +const { addSignal, removeSignal } = __nccwpck_require__(3121) const assert = __nccwpck_require__(9491) const kResume = Symbol('resume') @@ -2875,21 +2875,21 @@ module.exports = pipeline /***/ }), -/***/ 3055: +/***/ 1567: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Readable = __nccwpck_require__(7767) +const Readable = __nccwpck_require__(1121) const { InvalidArgumentError, RequestAbortedError -} = __nccwpck_require__(51) -const util = __nccwpck_require__(2014) -const { getResolveErrorBodyCallback } = __nccwpck_require__(2588) +} = __nccwpck_require__(6330) +const util = __nccwpck_require__(2423) +const { getResolveErrorBodyCallback } = __nccwpck_require__(9992) const { AsyncResource } = __nccwpck_require__(852) -const { addSignal, removeSignal } = __nccwpck_require__(9670) +const { addSignal, removeSignal } = __nccwpck_require__(3121) class RequestHandler extends AsyncResource { constructor (opts, callback) { @@ -3063,7 +3063,7 @@ module.exports.RequestHandler = RequestHandler /***/ }), -/***/ 2275: +/***/ 9468: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -3074,11 +3074,11 @@ const { InvalidArgumentError, InvalidReturnValueError, RequestAbortedError -} = __nccwpck_require__(51) -const util = __nccwpck_require__(2014) -const { getResolveErrorBodyCallback } = __nccwpck_require__(2588) +} = __nccwpck_require__(6330) +const util = __nccwpck_require__(2423) +const { getResolveErrorBodyCallback } = __nccwpck_require__(9992) const { AsyncResource } = __nccwpck_require__(852) -const { addSignal, removeSignal } = __nccwpck_require__(9670) +const { addSignal, removeSignal } = __nccwpck_require__(3121) class StreamHandler extends AsyncResource { constructor (opts, factory, callback) { @@ -3291,16 +3291,16 @@ module.exports = stream /***/ }), -/***/ 4348: +/***/ 6160: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(51) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(6330) const { AsyncResource } = __nccwpck_require__(852) -const util = __nccwpck_require__(2014) -const { addSignal, removeSignal } = __nccwpck_require__(9670) +const util = __nccwpck_require__(2423) +const { addSignal, removeSignal } = __nccwpck_require__(3121) const assert = __nccwpck_require__(9491) class UpgradeHandler extends AsyncResource { @@ -3404,22 +3404,22 @@ module.exports = upgrade /***/ }), -/***/ 4908: +/***/ 6813: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -module.exports.request = __nccwpck_require__(3055) -module.exports.stream = __nccwpck_require__(2275) -module.exports.pipeline = __nccwpck_require__(6346) -module.exports.upgrade = __nccwpck_require__(4348) -module.exports.connect = __nccwpck_require__(9725) +module.exports.request = __nccwpck_require__(1567) +module.exports.stream = __nccwpck_require__(9468) +module.exports.pipeline = __nccwpck_require__(9745) +module.exports.upgrade = __nccwpck_require__(6160) +module.exports.connect = __nccwpck_require__(5643) /***/ }), -/***/ 7767: +/***/ 1121: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -3429,9 +3429,9 @@ module.exports.connect = __nccwpck_require__(9725) const assert = __nccwpck_require__(9491) const { Readable } = __nccwpck_require__(2781) -const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(51) -const util = __nccwpck_require__(2014) -const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(2014) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(6330) +const util = __nccwpck_require__(2423) +const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(2423) let Blob @@ -3749,14 +3749,14 @@ function consumeFinish (consume, err) { /***/ }), -/***/ 2588: +/***/ 9992: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const assert = __nccwpck_require__(9491) const { ResponseStatusCodeError -} = __nccwpck_require__(51) -const { toUSVString } = __nccwpck_require__(2014) +} = __nccwpck_require__(6330) +const { toUSVString } = __nccwpck_require__(2423) async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { assert(body) @@ -3802,7 +3802,7 @@ module.exports = { getResolveErrorBodyCallback } /***/ }), -/***/ 1438: +/***/ 2503: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -3811,7 +3811,7 @@ module.exports = { getResolveErrorBodyCallback } const { BalancedPoolMissingUpstreamError, InvalidArgumentError -} = __nccwpck_require__(51) +} = __nccwpck_require__(6330) const { PoolBase, kClients, @@ -3819,10 +3819,10 @@ const { kAddClient, kRemoveClient, kGetDispatcher -} = __nccwpck_require__(334) -const Pool = __nccwpck_require__(135) -const { kUrl, kInterceptors } = __nccwpck_require__(7460) -const { parseOrigin } = __nccwpck_require__(2014) +} = __nccwpck_require__(8324) +const Pool = __nccwpck_require__(9944) +const { kUrl, kInterceptors } = __nccwpck_require__(5724) +const { parseOrigin } = __nccwpck_require__(2423) const kFactory = Symbol('factory') const kOptions = Symbol('options') @@ -4000,24 +4000,24 @@ module.exports = BalancedPool /***/ }), -/***/ 4482: +/***/ 5271: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kConstruct } = __nccwpck_require__(1837) -const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(9212) -const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(2014) -const { kHeadersList } = __nccwpck_require__(7460) -const { webidl } = __nccwpck_require__(8184) -const { Response, cloneResponse } = __nccwpck_require__(6476) -const { Request } = __nccwpck_require__(6814) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(4030) -const { fetching } = __nccwpck_require__(3246) -const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(9567) +const { kConstruct } = __nccwpck_require__(2182) +const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(7290) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(2423) +const { kHeadersList } = __nccwpck_require__(5724) +const { webidl } = __nccwpck_require__(194) +const { Response, cloneResponse } = __nccwpck_require__(786) +const { Request } = __nccwpck_require__(3437) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(8042) +const { fetching } = __nccwpck_require__(7628) +const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(6890) const assert = __nccwpck_require__(9491) -const { getGlobalDispatcher } = __nccwpck_require__(6223) +const { getGlobalDispatcher } = __nccwpck_require__(6835) /** * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation @@ -4846,16 +4846,16 @@ module.exports = { /***/ }), -/***/ 5420: +/***/ 1012: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kConstruct } = __nccwpck_require__(1837) -const { Cache } = __nccwpck_require__(4482) -const { webidl } = __nccwpck_require__(8184) -const { kEnumerableProperty } = __nccwpck_require__(2014) +const { kConstruct } = __nccwpck_require__(2182) +const { Cache } = __nccwpck_require__(5271) +const { webidl } = __nccwpck_require__(194) +const { kEnumerableProperty } = __nccwpck_require__(2423) class CacheStorage { /** @@ -4998,28 +4998,28 @@ module.exports = { /***/ }), -/***/ 1837: +/***/ 2182: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; module.exports = { - kConstruct: (__nccwpck_require__(7460).kConstruct) + kConstruct: (__nccwpck_require__(5724).kConstruct) } /***/ }), -/***/ 9212: +/***/ 7290: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const assert = __nccwpck_require__(9491) -const { URLSerializer } = __nccwpck_require__(834) -const { isValidHeaderName } = __nccwpck_require__(9567) +const { URLSerializer } = __nccwpck_require__(6515) +const { isValidHeaderName } = __nccwpck_require__(6890) /** * @see https://url.spec.whatwg.org/#concept-url-equals @@ -5068,7 +5068,7 @@ module.exports = { /***/ }), -/***/ 4256: +/***/ 2914: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -5082,10 +5082,10 @@ const assert = __nccwpck_require__(9491) const net = __nccwpck_require__(1808) const http = __nccwpck_require__(3685) const { pipeline } = __nccwpck_require__(2781) -const util = __nccwpck_require__(2014) -const timers = __nccwpck_require__(1518) -const Request = __nccwpck_require__(8751) -const DispatcherBase = __nccwpck_require__(854) +const util = __nccwpck_require__(2423) +const timers = __nccwpck_require__(5534) +const Request = __nccwpck_require__(3985) +const DispatcherBase = __nccwpck_require__(996) const { RequestContentLengthMismatchError, ResponseContentLengthMismatchError, @@ -5099,8 +5099,8 @@ const { HTTPParserError, ResponseExceededMaxSizeError, ClientDestroyedError -} = __nccwpck_require__(51) -const buildConnector = __nccwpck_require__(5599) +} = __nccwpck_require__(6330) +const buildConnector = __nccwpck_require__(8074) const { kUrl, kReset, @@ -5152,7 +5152,7 @@ const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest -} = __nccwpck_require__(7460) +} = __nccwpck_require__(5724) /** @type {import('http2')} */ let http2 @@ -5558,16 +5558,16 @@ function onHTTP2GoAway (code) { resume(client) } -const constants = __nccwpck_require__(3626) -const createRedirectInterceptor = __nccwpck_require__(6789) +const constants = __nccwpck_require__(3) +const createRedirectInterceptor = __nccwpck_require__(8573) const EMPTY_BUF = Buffer.alloc(0) async function lazyllhttp () { - const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(1931) : undefined + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(2516) : undefined let mod try { - mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(271), 'base64')) + mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(6390), 'base64')) } catch (e) { /* istanbul ignore next */ @@ -5575,7 +5575,7 @@ async function lazyllhttp () { // being enabled, but the occurring of this other error // * https://github.com/emscripten-core/emscripten/issues/11495 // got me to remove that check to avoid breaking Node 12. - mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(1931), 'base64')) + mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(2516), 'base64')) } return await WebAssembly.instantiate(mod, { @@ -7359,7 +7359,7 @@ module.exports = Client /***/ }), -/***/ 4142: +/***/ 4987: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -7367,7 +7367,7 @@ module.exports = Client /* istanbul ignore file: only for Node 12 */ -const { kConnected, kSize } = __nccwpck_require__(7460) +const { kConnected, kSize } = __nccwpck_require__(5724) class CompatWeakRef { constructor (value) { @@ -7415,7 +7415,7 @@ module.exports = function () { /***/ }), -/***/ 2040: +/***/ 8266: /***/ ((module) => { "use strict"; @@ -7435,16 +7435,16 @@ module.exports = { /***/ }), -/***/ 2739: +/***/ 49: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { parseSetCookie } = __nccwpck_require__(7151) -const { stringify, getHeadersList } = __nccwpck_require__(2285) -const { webidl } = __nccwpck_require__(8184) -const { Headers } = __nccwpck_require__(3767) +const { parseSetCookie } = __nccwpck_require__(5706) +const { stringify, getHeadersList } = __nccwpck_require__(6791) +const { webidl } = __nccwpck_require__(194) +const { Headers } = __nccwpck_require__(2836) /** * @typedef {Object} Cookie @@ -7627,15 +7627,15 @@ module.exports = { /***/ }), -/***/ 7151: +/***/ 5706: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(2040) -const { isCTLExcludingHtab } = __nccwpck_require__(2285) -const { collectASequenceOfCodePointsFast } = __nccwpck_require__(834) +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(8266) +const { isCTLExcludingHtab } = __nccwpck_require__(6791) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(6515) const assert = __nccwpck_require__(9491) /** @@ -7952,14 +7952,14 @@ module.exports = { /***/ }), -/***/ 2285: +/***/ 6791: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const assert = __nccwpck_require__(9491) -const { kHeadersList } = __nccwpck_require__(7460) +const { kHeadersList } = __nccwpck_require__(5724) function isCTLExcludingHtab (value) { if (value.length === 0) { @@ -8251,7 +8251,7 @@ module.exports = { /***/ }), -/***/ 5599: +/***/ 8074: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -8259,8 +8259,8 @@ module.exports = { const net = __nccwpck_require__(1808) const assert = __nccwpck_require__(9491) -const util = __nccwpck_require__(2014) -const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(51) +const util = __nccwpck_require__(2423) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(6330) let tls // include tls conditionally since it is not always available @@ -8448,7 +8448,7 @@ module.exports = buildConnector /***/ }), -/***/ 51: +/***/ 6330: /***/ ((module) => { "use strict"; @@ -8686,7 +8686,7 @@ module.exports = { /***/ }), -/***/ 8751: +/***/ 3985: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -8695,10 +8695,10 @@ module.exports = { const { InvalidArgumentError, NotSupportedError -} = __nccwpck_require__(51) +} = __nccwpck_require__(6330) const assert = __nccwpck_require__(9491) -const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(7460) -const util = __nccwpck_require__(2014) +const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(5724) +const util = __nccwpck_require__(2423) // tokenRegExp and headerCharRegex have been lifted from // https://github.com/nodejs/node/blob/main/lib/_http_common.js @@ -8893,7 +8893,7 @@ class Request { } if (!extractBody) { - extractBody = (__nccwpck_require__(7030).extractBody) + extractBody = (__nccwpck_require__(3979).extractBody) } const [bodyStream, contentType] = extractBody(body) @@ -9193,7 +9193,7 @@ module.exports = Request /***/ }), -/***/ 7460: +/***/ 5724: /***/ ((module) => { module.exports = { @@ -9263,18 +9263,18 @@ module.exports = { /***/ }), -/***/ 2014: +/***/ 2423: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const assert = __nccwpck_require__(9491) -const { kDestroyed, kBodyUsed } = __nccwpck_require__(7460) +const { kDestroyed, kBodyUsed } = __nccwpck_require__(5724) const { IncomingMessage } = __nccwpck_require__(3685) const stream = __nccwpck_require__(2781) const net = __nccwpck_require__(1808) -const { InvalidArgumentError } = __nccwpck_require__(51) +const { InvalidArgumentError } = __nccwpck_require__(6330) const { Blob } = __nccwpck_require__(4300) const nodeUtil = __nccwpck_require__(3837) const { stringify } = __nccwpck_require__(3477) @@ -9782,19 +9782,19 @@ module.exports = { /***/ }), -/***/ 854: +/***/ 996: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Dispatcher = __nccwpck_require__(7978) +const Dispatcher = __nccwpck_require__(2804) const { ClientDestroyedError, ClientClosedError, InvalidArgumentError -} = __nccwpck_require__(51) -const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(7460) +} = __nccwpck_require__(6330) +const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(5724) const kDestroyed = Symbol('destroyed') const kClosed = Symbol('closed') @@ -9982,7 +9982,7 @@ module.exports = DispatcherBase /***/ }), -/***/ 7978: +/***/ 2804: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -10009,14 +10009,14 @@ module.exports = Dispatcher /***/ }), -/***/ 7030: +/***/ 3979: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Busboy = __nccwpck_require__(9638) -const util = __nccwpck_require__(2014) +const Busboy = __nccwpck_require__(9452) +const util = __nccwpck_require__(2423) const { ReadableStreamFrom, isBlobLike, @@ -10024,18 +10024,18 @@ const { readableStreamClose, createDeferredPromise, fullyReadBody -} = __nccwpck_require__(9567) -const { FormData } = __nccwpck_require__(4089) -const { kState } = __nccwpck_require__(4030) -const { webidl } = __nccwpck_require__(8184) -const { DOMException, structuredClone } = __nccwpck_require__(3074) +} = __nccwpck_require__(6890) +const { FormData } = __nccwpck_require__(9188) +const { kState } = __nccwpck_require__(8042) +const { webidl } = __nccwpck_require__(194) +const { DOMException, structuredClone } = __nccwpck_require__(4091) const { Blob, File: NativeFile } = __nccwpck_require__(4300) -const { kBodyUsed } = __nccwpck_require__(7460) +const { kBodyUsed } = __nccwpck_require__(5724) const assert = __nccwpck_require__(9491) -const { isErrored } = __nccwpck_require__(2014) +const { isErrored } = __nccwpck_require__(2423) const { isUint8Array, isArrayBuffer } = __nccwpck_require__(9830) -const { File: UndiciFile } = __nccwpck_require__(8731) -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(834) +const { File: UndiciFile } = __nccwpck_require__(3442) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6515) let ReadableStream = globalThis.ReadableStream @@ -10622,7 +10622,7 @@ module.exports = { /***/ }), -/***/ 3074: +/***/ 4091: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -10781,12 +10781,12 @@ module.exports = { /***/ }), -/***/ 834: +/***/ 6515: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const assert = __nccwpck_require__(9491) const { atob } = __nccwpck_require__(4300) -const { isomorphicDecode } = __nccwpck_require__(9567) +const { isomorphicDecode } = __nccwpck_require__(6890) const encoder = new TextEncoder() @@ -11415,7 +11415,7 @@ module.exports = { /***/ }), -/***/ 8731: +/***/ 3442: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -11423,11 +11423,11 @@ module.exports = { const { Blob, File: NativeFile } = __nccwpck_require__(4300) const { types } = __nccwpck_require__(3837) -const { kState } = __nccwpck_require__(4030) -const { isBlobLike } = __nccwpck_require__(9567) -const { webidl } = __nccwpck_require__(8184) -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(834) -const { kEnumerableProperty } = __nccwpck_require__(2014) +const { kState } = __nccwpck_require__(8042) +const { isBlobLike } = __nccwpck_require__(6890) +const { webidl } = __nccwpck_require__(194) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6515) +const { kEnumerableProperty } = __nccwpck_require__(2423) const encoder = new TextEncoder() class File extends Blob { @@ -11767,16 +11767,16 @@ module.exports = { File, FileLike, isFileLike } /***/ }), -/***/ 4089: +/***/ 9188: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(9567) -const { kState } = __nccwpck_require__(4030) -const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(8731) -const { webidl } = __nccwpck_require__(8184) +const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(6890) +const { kState } = __nccwpck_require__(8042) +const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(3442) +const { webidl } = __nccwpck_require__(194) const { Blob, File: NativeFile } = __nccwpck_require__(4300) /** @type {globalThis['File']} */ @@ -12040,7 +12040,7 @@ module.exports = { FormData } /***/ }), -/***/ 4612: +/***/ 4767: /***/ ((module) => { "use strict"; @@ -12088,7 +12088,7 @@ module.exports = { /***/ }), -/***/ 3767: +/***/ 2836: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -12096,15 +12096,15 @@ module.exports = { -const { kHeadersList, kConstruct } = __nccwpck_require__(7460) -const { kGuard } = __nccwpck_require__(4030) -const { kEnumerableProperty } = __nccwpck_require__(2014) +const { kHeadersList, kConstruct } = __nccwpck_require__(5724) +const { kGuard } = __nccwpck_require__(8042) +const { kEnumerableProperty } = __nccwpck_require__(2423) const { makeIterator, isValidHeaderName, isValidHeaderValue -} = __nccwpck_require__(9567) -const { webidl } = __nccwpck_require__(8184) +} = __nccwpck_require__(6890) +const { webidl } = __nccwpck_require__(194) const assert = __nccwpck_require__(9491) const kHeadersMap = Symbol('headers map') @@ -12685,7 +12685,7 @@ module.exports = { /***/ }), -/***/ 3246: +/***/ 7628: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -12699,9 +12699,9 @@ const { makeAppropriateNetworkError, filterResponse, makeResponse -} = __nccwpck_require__(6476) -const { Headers } = __nccwpck_require__(3767) -const { Request, makeRequest } = __nccwpck_require__(6814) +} = __nccwpck_require__(786) +const { Headers } = __nccwpck_require__(2836) +const { Request, makeRequest } = __nccwpck_require__(3437) const zlib = __nccwpck_require__(9796) const { bytesMatch, @@ -12732,10 +12732,10 @@ const { urlIsLocal, urlIsHttpHttpsScheme, urlHasHttpsScheme -} = __nccwpck_require__(9567) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(4030) +} = __nccwpck_require__(6890) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(8042) const assert = __nccwpck_require__(9491) -const { safelyExtractBody } = __nccwpck_require__(7030) +const { safelyExtractBody } = __nccwpck_require__(3979) const { redirectStatusSet, nullBodyStatus, @@ -12743,15 +12743,15 @@ const { requestBodyHeader, subresourceSet, DOMException -} = __nccwpck_require__(3074) -const { kHeadersList } = __nccwpck_require__(7460) +} = __nccwpck_require__(4091) +const { kHeadersList } = __nccwpck_require__(5724) const EE = __nccwpck_require__(2361) const { Readable, pipeline } = __nccwpck_require__(2781) -const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(2014) -const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(834) +const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(2423) +const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(6515) const { TransformStream } = __nccwpck_require__(5356) -const { getGlobalDispatcher } = __nccwpck_require__(6223) -const { webidl } = __nccwpck_require__(8184) +const { getGlobalDispatcher } = __nccwpck_require__(6835) +const { webidl } = __nccwpck_require__(194) const { STATUS_CODES } = __nccwpck_require__(3685) const GET_OR_HEAD = ['GET', 'HEAD'] @@ -14841,7 +14841,7 @@ module.exports = { /***/ }), -/***/ 6814: +/***/ 3437: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -14849,17 +14849,17 @@ module.exports = { -const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(7030) -const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(3767) -const { FinalizationRegistry } = __nccwpck_require__(4142)() -const util = __nccwpck_require__(2014) +const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(3979) +const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(2836) +const { FinalizationRegistry } = __nccwpck_require__(4987)() +const util = __nccwpck_require__(2423) const { isValidHTTPToken, sameOrigin, normalizeMethod, makePolicyContainer, normalizeMethodRecord -} = __nccwpck_require__(9567) +} = __nccwpck_require__(6890) const { forbiddenMethodsSet, corsSafeListedMethodsSet, @@ -14869,13 +14869,13 @@ const { requestCredentials, requestCache, requestDuplex -} = __nccwpck_require__(3074) +} = __nccwpck_require__(4091) const { kEnumerableProperty } = util -const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(4030) -const { webidl } = __nccwpck_require__(8184) -const { getGlobalOrigin } = __nccwpck_require__(4612) -const { URLSerializer } = __nccwpck_require__(834) -const { kHeadersList, kConstruct } = __nccwpck_require__(7460) +const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(8042) +const { webidl } = __nccwpck_require__(194) +const { getGlobalOrigin } = __nccwpck_require__(4767) +const { URLSerializer } = __nccwpck_require__(6515) +const { kHeadersList, kConstruct } = __nccwpck_require__(5724) const assert = __nccwpck_require__(9491) const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(2361) @@ -15795,15 +15795,15 @@ module.exports = { Request, makeRequest } /***/ }), -/***/ 6476: +/***/ 786: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { Headers, HeadersList, fill } = __nccwpck_require__(3767) -const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(7030) -const util = __nccwpck_require__(2014) +const { Headers, HeadersList, fill } = __nccwpck_require__(2836) +const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(3979) +const util = __nccwpck_require__(2423) const { kEnumerableProperty } = util const { isValidReasonPhrase, @@ -15813,18 +15813,18 @@ const { serializeJavascriptValueToJSONString, isErrorLike, isomorphicEncode -} = __nccwpck_require__(9567) +} = __nccwpck_require__(6890) const { redirectStatusSet, nullBodyStatus, DOMException -} = __nccwpck_require__(3074) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(4030) -const { webidl } = __nccwpck_require__(8184) -const { FormData } = __nccwpck_require__(4089) -const { getGlobalOrigin } = __nccwpck_require__(4612) -const { URLSerializer } = __nccwpck_require__(834) -const { kHeadersList, kConstruct } = __nccwpck_require__(7460) +} = __nccwpck_require__(4091) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(8042) +const { webidl } = __nccwpck_require__(194) +const { FormData } = __nccwpck_require__(9188) +const { getGlobalOrigin } = __nccwpck_require__(4767) +const { URLSerializer } = __nccwpck_require__(6515) +const { kHeadersList, kConstruct } = __nccwpck_require__(5724) const assert = __nccwpck_require__(9491) const { types } = __nccwpck_require__(3837) @@ -16374,7 +16374,7 @@ module.exports = { /***/ }), -/***/ 4030: +/***/ 8042: /***/ ((module) => { "use strict"; @@ -16392,16 +16392,16 @@ module.exports = { /***/ }), -/***/ 9567: +/***/ 6890: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(3074) -const { getGlobalOrigin } = __nccwpck_require__(4612) +const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(4091) +const { getGlobalOrigin } = __nccwpck_require__(4767) const { performance } = __nccwpck_require__(4074) -const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(2014) +const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(2423) const assert = __nccwpck_require__(9491) const { isUint8Array } = __nccwpck_require__(9830) @@ -17471,14 +17471,14 @@ module.exports = { /***/ }), -/***/ 8184: +/***/ 194: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { types } = __nccwpck_require__(3837) -const { hasOwn, toUSVString } = __nccwpck_require__(9567) +const { hasOwn, toUSVString } = __nccwpck_require__(6890) /** @type {import('../../types/webidl').Webidl} */ const webidl = {} @@ -18125,7 +18125,7 @@ module.exports = { /***/ }), -/***/ 8603: +/***/ 7958: /***/ ((module) => { "use strict"; @@ -18423,7 +18423,7 @@ module.exports = { /***/ }), -/***/ 7689: +/***/ 7872: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -18433,16 +18433,16 @@ const { staticPropertyDescriptors, readOperation, fireAProgressEvent -} = __nccwpck_require__(698) +} = __nccwpck_require__(9326) const { kState, kError, kResult, kEvents, kAborted -} = __nccwpck_require__(4514) -const { webidl } = __nccwpck_require__(8184) -const { kEnumerableProperty } = __nccwpck_require__(2014) +} = __nccwpck_require__(1116) +const { webidl } = __nccwpck_require__(194) +const { kEnumerableProperty } = __nccwpck_require__(2423) class FileReader extends EventTarget { constructor () { @@ -18775,13 +18775,13 @@ module.exports = { /***/ }), -/***/ 9354: +/***/ 8738: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { webidl } = __nccwpck_require__(8184) +const { webidl } = __nccwpck_require__(194) const kState = Symbol('ProgressEvent state') @@ -18861,7 +18861,7 @@ module.exports = { /***/ }), -/***/ 4514: +/***/ 1116: /***/ ((module) => { "use strict"; @@ -18879,7 +18879,7 @@ module.exports = { /***/ }), -/***/ 698: +/***/ 9326: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -18891,11 +18891,11 @@ const { kResult, kAborted, kLastProgressEventFired -} = __nccwpck_require__(4514) -const { ProgressEvent } = __nccwpck_require__(9354) -const { getEncoding } = __nccwpck_require__(8603) -const { DOMException } = __nccwpck_require__(3074) -const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(834) +} = __nccwpck_require__(1116) +const { ProgressEvent } = __nccwpck_require__(8738) +const { getEncoding } = __nccwpck_require__(7958) +const { DOMException } = __nccwpck_require__(4091) +const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(6515) const { types } = __nccwpck_require__(3837) const { StringDecoder } = __nccwpck_require__(1576) const { btoa } = __nccwpck_require__(4300) @@ -19279,7 +19279,7 @@ module.exports = { /***/ }), -/***/ 6223: +/***/ 6835: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -19288,8 +19288,8 @@ module.exports = { // We include a version number for the Dispatcher API. In case of breaking changes, // this version number must be increased to avoid conflicts. const globalDispatcher = Symbol.for('undici.globalDispatcher.1') -const { InvalidArgumentError } = __nccwpck_require__(51) -const Agent = __nccwpck_require__(2438) +const { InvalidArgumentError } = __nccwpck_require__(6330) +const Agent = __nccwpck_require__(9614) if (getGlobalDispatcher() === undefined) { setGlobalDispatcher(new Agent()) @@ -19319,7 +19319,7 @@ module.exports = { /***/ }), -/***/ 1509: +/***/ 3860: /***/ ((module) => { "use strict"; @@ -19362,16 +19362,16 @@ module.exports = class DecoratorHandler { /***/ }), -/***/ 7144: +/***/ 9644: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const util = __nccwpck_require__(2014) -const { kBodyUsed } = __nccwpck_require__(7460) +const util = __nccwpck_require__(2423) +const { kBodyUsed } = __nccwpck_require__(5724) const assert = __nccwpck_require__(9491) -const { InvalidArgumentError } = __nccwpck_require__(51) +const { InvalidArgumentError } = __nccwpck_require__(6330) const EE = __nccwpck_require__(2361) const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] @@ -19586,14 +19586,14 @@ module.exports = RedirectHandler /***/ }), -/***/ 5112: +/***/ 1010: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const assert = __nccwpck_require__(9491) -const { kRetryHandlerDefaultRetry } = __nccwpck_require__(7460) -const { RequestRetryError } = __nccwpck_require__(51) -const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(2014) +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(5724) +const { RequestRetryError } = __nccwpck_require__(6330) +const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(2423) function calculateRetryAfterHeader (retryAfter) { const current = Date.now() @@ -19929,13 +19929,13 @@ module.exports = RetryHandler /***/ }), -/***/ 6789: +/***/ 8573: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const RedirectHandler = __nccwpck_require__(7144) +const RedirectHandler = __nccwpck_require__(9644) function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { return (dispatch) => { @@ -19958,14 +19958,14 @@ module.exports = createRedirectInterceptor /***/ }), -/***/ 3626: +/***/ 3: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; -const utils_1 = __nccwpck_require__(1746); +const utils_1 = __nccwpck_require__(5448); // C headers var ERROR; (function (ERROR) { @@ -20243,7 +20243,7 @@ exports.SPECIAL_HEADERS = { /***/ }), -/***/ 1931: +/***/ 2516: /***/ ((module) => { module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=' @@ -20251,7 +20251,7 @@ module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn /***/ }), -/***/ 271: +/***/ 6390: /***/ ((module) => { module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==' @@ -20259,7 +20259,7 @@ module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn /***/ }), -/***/ 1746: +/***/ 5448: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -20281,14 +20281,14 @@ exports.enumToMap = enumToMap; /***/ }), -/***/ 3667: +/***/ 580: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kClients } = __nccwpck_require__(7460) -const Agent = __nccwpck_require__(2438) +const { kClients } = __nccwpck_require__(5724) +const Agent = __nccwpck_require__(9614) const { kAgent, kMockAgentSet, @@ -20299,14 +20299,14 @@ const { kGetNetConnect, kOptions, kFactory -} = __nccwpck_require__(631) -const MockClient = __nccwpck_require__(4927) -const MockPool = __nccwpck_require__(9726) -const { matchValue, buildMockOptions } = __nccwpck_require__(3713) -const { InvalidArgumentError, UndiciError } = __nccwpck_require__(51) -const Dispatcher = __nccwpck_require__(7978) -const Pluralizer = __nccwpck_require__(396) -const PendingInterceptorsFormatter = __nccwpck_require__(2443) +} = __nccwpck_require__(4932) +const MockClient = __nccwpck_require__(4454) +const MockPool = __nccwpck_require__(4002) +const { matchValue, buildMockOptions } = __nccwpck_require__(7335) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(6330) +const Dispatcher = __nccwpck_require__(2804) +const Pluralizer = __nccwpck_require__(2326) +const PendingInterceptorsFormatter = __nccwpck_require__(9006) class FakeWeakRef { constructor (value) { @@ -20460,15 +20460,15 @@ module.exports = MockAgent /***/ }), -/***/ 4927: +/***/ 4454: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { promisify } = __nccwpck_require__(3837) -const Client = __nccwpck_require__(4256) -const { buildMockDispatch } = __nccwpck_require__(3713) +const Client = __nccwpck_require__(2914) +const { buildMockDispatch } = __nccwpck_require__(7335) const { kDispatches, kMockAgent, @@ -20477,10 +20477,10 @@ const { kOrigin, kOriginalDispatch, kConnected -} = __nccwpck_require__(631) -const { MockInterceptor } = __nccwpck_require__(4975) -const Symbols = __nccwpck_require__(7460) -const { InvalidArgumentError } = __nccwpck_require__(51) +} = __nccwpck_require__(4932) +const { MockInterceptor } = __nccwpck_require__(1659) +const Symbols = __nccwpck_require__(5724) +const { InvalidArgumentError } = __nccwpck_require__(6330) /** * MockClient provides an API that extends the Client to influence the mockDispatches. @@ -20527,13 +20527,13 @@ module.exports = MockClient /***/ }), -/***/ 2106: +/***/ 5603: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { UndiciError } = __nccwpck_require__(51) +const { UndiciError } = __nccwpck_require__(6330) class MockNotMatchedError extends UndiciError { constructor (message) { @@ -20552,13 +20552,13 @@ module.exports = { /***/ }), -/***/ 4975: +/***/ 1659: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(3713) +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(7335) const { kDispatches, kDispatchKey, @@ -20566,9 +20566,9 @@ const { kDefaultTrailers, kContentLength, kMockDispatch -} = __nccwpck_require__(631) -const { InvalidArgumentError } = __nccwpck_require__(51) -const { buildURL } = __nccwpck_require__(2014) +} = __nccwpck_require__(4932) +const { InvalidArgumentError } = __nccwpck_require__(6330) +const { buildURL } = __nccwpck_require__(2423) /** * Defines the scope API for an interceptor reply @@ -20766,15 +20766,15 @@ module.exports.MockScope = MockScope /***/ }), -/***/ 9726: +/***/ 4002: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const { promisify } = __nccwpck_require__(3837) -const Pool = __nccwpck_require__(135) -const { buildMockDispatch } = __nccwpck_require__(3713) +const Pool = __nccwpck_require__(9944) +const { buildMockDispatch } = __nccwpck_require__(7335) const { kDispatches, kMockAgent, @@ -20783,10 +20783,10 @@ const { kOrigin, kOriginalDispatch, kConnected -} = __nccwpck_require__(631) -const { MockInterceptor } = __nccwpck_require__(4975) -const Symbols = __nccwpck_require__(7460) -const { InvalidArgumentError } = __nccwpck_require__(51) +} = __nccwpck_require__(4932) +const { MockInterceptor } = __nccwpck_require__(1659) +const Symbols = __nccwpck_require__(5724) +const { InvalidArgumentError } = __nccwpck_require__(6330) /** * MockPool provides an API that extends the Pool to influence the mockDispatches. @@ -20833,7 +20833,7 @@ module.exports = MockPool /***/ }), -/***/ 631: +/***/ 4932: /***/ ((module) => { "use strict"; @@ -20864,21 +20864,21 @@ module.exports = { /***/ }), -/***/ 3713: +/***/ 7335: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { MockNotMatchedError } = __nccwpck_require__(2106) +const { MockNotMatchedError } = __nccwpck_require__(5603) const { kDispatches, kMockAgent, kOriginalDispatch, kOrigin, kGetNetConnect -} = __nccwpck_require__(631) -const { buildURL, nop } = __nccwpck_require__(2014) +} = __nccwpck_require__(4932) +const { buildURL, nop } = __nccwpck_require__(2423) const { STATUS_CODES } = __nccwpck_require__(3685) const { types: { @@ -21223,7 +21223,7 @@ module.exports = { /***/ }), -/***/ 2443: +/***/ 9006: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -21271,7 +21271,7 @@ module.exports = class PendingInterceptorsFormatter { /***/ }), -/***/ 396: +/***/ 2326: /***/ ((module) => { "use strict"; @@ -21308,7 +21308,7 @@ module.exports = class Pluralizer { /***/ }), -/***/ 4663: +/***/ 6998: /***/ ((module) => { "use strict"; @@ -21433,16 +21433,16 @@ module.exports = class FixedQueue { /***/ }), -/***/ 334: +/***/ 8324: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const DispatcherBase = __nccwpck_require__(854) -const FixedQueue = __nccwpck_require__(4663) -const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(7460) -const PoolStats = __nccwpck_require__(7236) +const DispatcherBase = __nccwpck_require__(996) +const FixedQueue = __nccwpck_require__(6998) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(5724) +const PoolStats = __nccwpck_require__(4822) const kClients = Symbol('clients') const kNeedDrain = Symbol('needDrain') @@ -21635,10 +21635,10 @@ module.exports = { /***/ }), -/***/ 7236: +/***/ 4822: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(7460) +const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(5724) const kPool = Symbol('pool') class PoolStats { @@ -21676,7 +21676,7 @@ module.exports = PoolStats /***/ }), -/***/ 135: +/***/ 9944: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -21688,14 +21688,14 @@ const { kNeedDrain, kAddClient, kGetDispatcher -} = __nccwpck_require__(334) -const Client = __nccwpck_require__(4256) +} = __nccwpck_require__(8324) +const Client = __nccwpck_require__(2914) const { InvalidArgumentError -} = __nccwpck_require__(51) -const util = __nccwpck_require__(2014) -const { kUrl, kInterceptors } = __nccwpck_require__(7460) -const buildConnector = __nccwpck_require__(5599) +} = __nccwpck_require__(6330) +const util = __nccwpck_require__(2423) +const { kUrl, kInterceptors } = __nccwpck_require__(5724) +const buildConnector = __nccwpck_require__(8074) const kOptions = Symbol('options') const kConnections = Symbol('connections') @@ -21778,19 +21778,19 @@ module.exports = Pool /***/ }), -/***/ 6524: +/***/ 4080: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(7460) +const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(5724) const { URL } = __nccwpck_require__(7310) -const Agent = __nccwpck_require__(2438) -const Pool = __nccwpck_require__(135) -const DispatcherBase = __nccwpck_require__(854) -const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(51) -const buildConnector = __nccwpck_require__(5599) +const Agent = __nccwpck_require__(9614) +const Pool = __nccwpck_require__(9944) +const DispatcherBase = __nccwpck_require__(996) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(6330) +const buildConnector = __nccwpck_require__(8074) const kAgent = Symbol('proxy agent') const kClient = Symbol('proxy client') @@ -21975,7 +21975,7 @@ module.exports = ProxyAgent /***/ }), -/***/ 1518: +/***/ 5534: /***/ ((module) => { "use strict"; @@ -22080,27 +22080,27 @@ module.exports = { /***/ }), -/***/ 3431: +/***/ 9489: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; const diagnosticsChannel = __nccwpck_require__(7643) -const { uid, states } = __nccwpck_require__(5044) +const { uid, states } = __nccwpck_require__(6927) const { kReadyState, kSentClose, kByteParser, kReceivedClose -} = __nccwpck_require__(6437) -const { fireEvent, failWebsocketConnection } = __nccwpck_require__(1890) -const { CloseEvent } = __nccwpck_require__(7173) -const { makeRequest } = __nccwpck_require__(6814) -const { fetching } = __nccwpck_require__(3246) -const { Headers } = __nccwpck_require__(3767) -const { getGlobalDispatcher } = __nccwpck_require__(6223) -const { kHeadersList } = __nccwpck_require__(7460) +} = __nccwpck_require__(3555) +const { fireEvent, failWebsocketConnection } = __nccwpck_require__(3542) +const { CloseEvent } = __nccwpck_require__(7973) +const { makeRequest } = __nccwpck_require__(3437) +const { fetching } = __nccwpck_require__(7628) +const { Headers } = __nccwpck_require__(2836) +const { getGlobalDispatcher } = __nccwpck_require__(6835) +const { kHeadersList } = __nccwpck_require__(5724) const channels = {} channels.open = diagnosticsChannel.channel('undici:websocket:open') @@ -22379,7 +22379,7 @@ module.exports = { /***/ }), -/***/ 5044: +/***/ 6927: /***/ ((module) => { "use strict"; @@ -22438,14 +22438,14 @@ module.exports = { /***/ }), -/***/ 7173: +/***/ 7973: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { webidl } = __nccwpck_require__(8184) -const { kEnumerableProperty } = __nccwpck_require__(2014) +const { webidl } = __nccwpck_require__(194) +const { kEnumerableProperty } = __nccwpck_require__(2423) const { MessagePort } = __nccwpck_require__(1267) /** @@ -22749,13 +22749,13 @@ module.exports = { /***/ }), -/***/ 9537: +/***/ 6772: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { maxUnsigned16Bit } = __nccwpck_require__(5044) +const { maxUnsigned16Bit } = __nccwpck_require__(6927) /** @type {import('crypto')} */ let crypto @@ -22830,7 +22830,7 @@ module.exports = { /***/ }), -/***/ 1155: +/***/ 1579: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -22838,10 +22838,10 @@ module.exports = { const { Writable } = __nccwpck_require__(2781) const diagnosticsChannel = __nccwpck_require__(7643) -const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(5044) -const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(6437) -const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(1890) -const { WebsocketFrameSend } = __nccwpck_require__(9537) +const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(6927) +const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(3555) +const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(3542) +const { WebsocketFrameSend } = __nccwpck_require__(6772) // This code was influenced by ws released under the MIT license. // Copyright (c) 2011 Einar Otto Stangvik @@ -23182,7 +23182,7 @@ module.exports = { /***/ }), -/***/ 6437: +/***/ 3555: /***/ ((module) => { "use strict"; @@ -23202,15 +23202,15 @@ module.exports = { /***/ }), -/***/ 1890: +/***/ 3542: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(6437) -const { states, opcodes } = __nccwpck_require__(5044) -const { MessageEvent, ErrorEvent } = __nccwpck_require__(7173) +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(3555) +const { states, opcodes } = __nccwpck_require__(6927) +const { MessageEvent, ErrorEvent } = __nccwpck_require__(7973) /* globals Blob */ @@ -23410,17 +23410,17 @@ module.exports = { /***/ }), -/***/ 1917: +/***/ 7183: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const { webidl } = __nccwpck_require__(8184) -const { DOMException } = __nccwpck_require__(3074) -const { URLSerializer } = __nccwpck_require__(834) -const { getGlobalOrigin } = __nccwpck_require__(4612) -const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(5044) +const { webidl } = __nccwpck_require__(194) +const { DOMException } = __nccwpck_require__(4091) +const { URLSerializer } = __nccwpck_require__(6515) +const { getGlobalOrigin } = __nccwpck_require__(4767) +const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(6927) const { kWebSocketURL, kReadyState, @@ -23429,13 +23429,13 @@ const { kResponse, kSentClose, kByteParser -} = __nccwpck_require__(6437) -const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(1890) -const { establishWebSocketConnection } = __nccwpck_require__(3431) -const { WebsocketFrameSend } = __nccwpck_require__(9537) -const { ByteParser } = __nccwpck_require__(1155) -const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(2014) -const { getGlobalDispatcher } = __nccwpck_require__(6223) +} = __nccwpck_require__(3555) +const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(3542) +const { establishWebSocketConnection } = __nccwpck_require__(9489) +const { WebsocketFrameSend } = __nccwpck_require__(6772) +const { ByteParser } = __nccwpck_require__(1579) +const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(2423) +const { getGlobalDispatcher } = __nccwpck_require__(6835) const { types } = __nccwpck_require__(3837) let experimentalWarned = false @@ -24059,7 +24059,7 @@ module.exports = { /***/ }), -/***/ 2228: +/***/ 8689: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24123,29 +24123,29 @@ Object.defineProperty(exports, "parse", ({ } })); -var _v = _interopRequireDefault(__nccwpck_require__(129)); +var _v = _interopRequireDefault(__nccwpck_require__(4333)); -var _v2 = _interopRequireDefault(__nccwpck_require__(7182)); +var _v2 = _interopRequireDefault(__nccwpck_require__(3223)); -var _v3 = _interopRequireDefault(__nccwpck_require__(9317)); +var _v3 = _interopRequireDefault(__nccwpck_require__(3166)); -var _v4 = _interopRequireDefault(__nccwpck_require__(7349)); +var _v4 = _interopRequireDefault(__nccwpck_require__(3828)); -var _nil = _interopRequireDefault(__nccwpck_require__(6795)); +var _nil = _interopRequireDefault(__nccwpck_require__(4956)); -var _version = _interopRequireDefault(__nccwpck_require__(2590)); +var _version = _interopRequireDefault(__nccwpck_require__(1564)); -var _validate = _interopRequireDefault(__nccwpck_require__(9020)); +var _validate = _interopRequireDefault(__nccwpck_require__(7368)); -var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); +var _stringify = _interopRequireDefault(__nccwpck_require__(2157)); -var _parse = _interopRequireDefault(__nccwpck_require__(3167)); +var _parse = _interopRequireDefault(__nccwpck_require__(8659)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), -/***/ 4977: +/***/ 4919: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24175,7 +24175,7 @@ exports["default"] = _default; /***/ }), -/***/ 6795: +/***/ 4956: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -24190,7 +24190,7 @@ exports["default"] = _default; /***/ }), -/***/ 3167: +/***/ 8659: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24201,7 +24201,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(9020)); +var _validate = _interopRequireDefault(__nccwpck_require__(7368)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24242,7 +24242,7 @@ exports["default"] = _default; /***/ }), -/***/ 465: +/***/ 5872: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -24257,7 +24257,7 @@ exports["default"] = _default; /***/ }), -/***/ 8707: +/***/ 7931: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24288,7 +24288,7 @@ function rng() { /***/ }), -/***/ 4315: +/***/ 3445: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24318,7 +24318,7 @@ exports["default"] = _default; /***/ }), -/***/ 3174: +/***/ 2157: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24329,7 +24329,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(9020)); +var _validate = _interopRequireDefault(__nccwpck_require__(7368)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24364,7 +24364,7 @@ exports["default"] = _default; /***/ }), -/***/ 129: +/***/ 4333: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24375,9 +24375,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(8707)); +var _rng = _interopRequireDefault(__nccwpck_require__(7931)); -var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); +var _stringify = _interopRequireDefault(__nccwpck_require__(2157)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24478,7 +24478,7 @@ exports["default"] = _default; /***/ }), -/***/ 7182: +/***/ 3223: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24489,9 +24489,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(4803)); +var _v = _interopRequireDefault(__nccwpck_require__(1892)); -var _md = _interopRequireDefault(__nccwpck_require__(4977)); +var _md = _interopRequireDefault(__nccwpck_require__(4919)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24501,7 +24501,7 @@ exports["default"] = _default; /***/ }), -/***/ 4803: +/***/ 1892: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24513,9 +24513,9 @@ Object.defineProperty(exports, "__esModule", ({ exports["default"] = _default; exports.URL = exports.DNS = void 0; -var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); +var _stringify = _interopRequireDefault(__nccwpck_require__(2157)); -var _parse = _interopRequireDefault(__nccwpck_require__(3167)); +var _parse = _interopRequireDefault(__nccwpck_require__(8659)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24586,7 +24586,7 @@ function _default(name, version, hashfunc) { /***/ }), -/***/ 9317: +/***/ 3166: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24597,9 +24597,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(8707)); +var _rng = _interopRequireDefault(__nccwpck_require__(7931)); -var _stringify = _interopRequireDefault(__nccwpck_require__(3174)); +var _stringify = _interopRequireDefault(__nccwpck_require__(2157)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24630,7 +24630,7 @@ exports["default"] = _default; /***/ }), -/***/ 7349: +/***/ 3828: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24641,9 +24641,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(4803)); +var _v = _interopRequireDefault(__nccwpck_require__(1892)); -var _sha = _interopRequireDefault(__nccwpck_require__(4315)); +var _sha = _interopRequireDefault(__nccwpck_require__(3445)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24653,7 +24653,7 @@ exports["default"] = _default; /***/ }), -/***/ 9020: +/***/ 7368: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24664,7 +24664,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _regex = _interopRequireDefault(__nccwpck_require__(465)); +var _regex = _interopRequireDefault(__nccwpck_require__(5872)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24677,7 +24677,7 @@ exports["default"] = _default; /***/ }), -/***/ 2590: +/***/ 1564: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -24688,7 +24688,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(9020)); +var _validate = _interopRequireDefault(__nccwpck_require__(7368)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -24929,7 +24929,7 @@ module.exports = require("zlib"); /***/ }), -/***/ 2899: +/***/ 7464: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -24938,10 +24938,10 @@ module.exports = require("zlib"); const WritableStream = (__nccwpck_require__(4492).Writable) const inherits = (__nccwpck_require__(7261).inherits) -const StreamSearch = __nccwpck_require__(482) +const StreamSearch = __nccwpck_require__(9477) -const PartStream = __nccwpck_require__(953) -const HeaderParser = __nccwpck_require__(8757) +const PartStream = __nccwpck_require__(8258) +const HeaderParser = __nccwpck_require__(4874) const DASH = 45 const B_ONEDASH = Buffer.from('-') @@ -25144,7 +25144,7 @@ module.exports = Dicer /***/ }), -/***/ 8757: +/***/ 4874: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25152,9 +25152,9 @@ module.exports = Dicer const EventEmitter = (__nccwpck_require__(5673).EventEmitter) const inherits = (__nccwpck_require__(7261).inherits) -const getLimit = __nccwpck_require__(2173) +const getLimit = __nccwpck_require__(9281) -const StreamSearch = __nccwpck_require__(482) +const StreamSearch = __nccwpck_require__(9477) const B_DCRLF = Buffer.from('\r\n\r\n') const RE_CRLF = /\r\n/g @@ -25252,7 +25252,7 @@ module.exports = HeaderParser /***/ }), -/***/ 953: +/***/ 8258: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25273,7 +25273,7 @@ module.exports = PartStream /***/ }), -/***/ 482: +/***/ 9477: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25509,7 +25509,7 @@ module.exports = SBMH /***/ }), -/***/ 9638: +/***/ 9452: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25517,11 +25517,11 @@ module.exports = SBMH const WritableStream = (__nccwpck_require__(4492).Writable) const { inherits } = __nccwpck_require__(7261) -const Dicer = __nccwpck_require__(2899) +const Dicer = __nccwpck_require__(7464) -const MultipartParser = __nccwpck_require__(3045) -const UrlencodedParser = __nccwpck_require__(3005) -const parseParams = __nccwpck_require__(2124) +const MultipartParser = __nccwpck_require__(5409) +const UrlencodedParser = __nccwpck_require__(9232) +const parseParams = __nccwpck_require__(9741) function Busboy (opts) { if (!(this instanceof Busboy)) { return new Busboy(opts) } @@ -25602,7 +25602,7 @@ module.exports.Dicer = Dicer /***/ }), -/***/ 3045: +/***/ 5409: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; @@ -25618,12 +25618,12 @@ module.exports.Dicer = Dicer const { Readable } = __nccwpck_require__(4492) const { inherits } = __nccwpck_require__(7261) -const Dicer = __nccwpck_require__(2899) +const Dicer = __nccwpck_require__(7464) -const parseParams = __nccwpck_require__(2124) -const decodeText = __nccwpck_require__(7941) -const basename = __nccwpck_require__(8708) -const getLimit = __nccwpck_require__(2173) +const parseParams = __nccwpck_require__(9741) +const decodeText = __nccwpck_require__(6897) +const basename = __nccwpck_require__(2149) +const getLimit = __nccwpck_require__(9281) const RE_BOUNDARY = /^boundary$/i const RE_FIELD = /^form-data$/i @@ -25916,15 +25916,15 @@ module.exports = Multipart /***/ }), -/***/ 3005: +/***/ 9232: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const Decoder = __nccwpck_require__(1361) -const decodeText = __nccwpck_require__(7941) -const getLimit = __nccwpck_require__(2173) +const Decoder = __nccwpck_require__(8698) +const decodeText = __nccwpck_require__(6897) +const getLimit = __nccwpck_require__(9281) const RE_CHARSET = /^charset$/i @@ -26114,7 +26114,7 @@ module.exports = UrlEncoded /***/ }), -/***/ 1361: +/***/ 8698: /***/ ((module) => { "use strict"; @@ -26176,7 +26176,7 @@ module.exports = Decoder /***/ }), -/***/ 8708: +/***/ 2149: /***/ ((module) => { "use strict"; @@ -26198,7 +26198,7 @@ module.exports = function basename (path) { /***/ }), -/***/ 7941: +/***/ 6897: /***/ (function(module) { "use strict"; @@ -26320,7 +26320,7 @@ module.exports = decodeText /***/ }), -/***/ 2173: +/***/ 9281: /***/ ((module) => { "use strict"; @@ -26344,14 +26344,14 @@ module.exports = function getLimit (limits, name, defaultLimit) { /***/ }), -/***/ 2124: +/***/ 9741: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; /* eslint-disable object-property-newline */ -const decodeText = __nccwpck_require__(7941) +const decodeText = __nccwpck_require__(6897) const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g @@ -26621,6 +26621,60 @@ const pluginList = [{ options: '-DWASMEDGE_PLUGIN_WASI_NN_BACKEND=PyTorch', archList: [x86_64], }], +}, { + name: 'wasm_bpf', + bin: 'libwasmedgePluginWasmBpf.so', + testBin: 'wasmBpfTests', + options: '-DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF', + archList: [x86_64], +}, { + name: 'wasi_crypto', + bin: 'libwasmedgePluginWasiCrypto.so', + testBin: 'wasiCryptoTests', + options: '-DWASMEDGE_PLUGIN_WASI_CRYPTO=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasi_logging', + bin: 'libwasmedgePluginWasiLogging.so', + testBin: 'wasiLoggingTests', + options: '-DWASMEDGE_PLUGIN_WASI_LOGGING=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_process', + bin: 'libwasmedgePluginWasmEdgeProcess.so', + testBin: 'wasmedgeProcessTests', + options: '-DWASMEDGE_PLUGIN_PROCESS=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_tensorflow', + bin: 'libwasmedgePluginWasmEdgeTensorflow.so', + testBin: 'wasmedgeTensorflowTests', + options: '-DWASMEDGE_PLUGIN_TENSORFLOW=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_tensorflowlite', + bin: 'libwasmedgePluginWasmEdgeTensorflowLite.so', + testBin: 'wasmedgeTensorflowLiteTests', + options: '-DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_image', + bin: 'libwasmedgePluginWasmEdgeImage.so', + testBin: 'wasmedgeImageTests', + options: '-DWASMEDGE_PLUGIN_IMAGE=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_opencvmini', + bin: 'libwasmedgePluginWasmEdgeOpenCVMini.so', + testBin: 'wasmedgeOpencvminiTests', + options: '-DWASMEDGE_PLUGIN_OPENCVMINI=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_ffmpeg', + bin: 'libwasmedgePluginWasmEdgeFFmpeg.so', + testBin: 'wasmedgeFFmpegTests', + options: '-DWASMEDGE_PLUGIN_FFMPEG=ON', + archList: [aarch64, x86_64], }]; let expandVariables = () => { @@ -26651,7 +26705,7 @@ let expandVariables = () => { return ret; }; -const core = __nccwpck_require__(4136); +const core = __nccwpck_require__(5662); try { output = JSON.stringify(expandVariables()); diff --git a/.github/actions/expand-variables/main.js b/.github/actions/expand-variables/main.js index acb644d4953a..94ac9260b94a 100644 --- a/.github/actions/expand-variables/main.js +++ b/.github/actions/expand-variables/main.js @@ -30,6 +30,60 @@ const pluginList = [{ options: '-DWASMEDGE_PLUGIN_WASI_NN_BACKEND=PyTorch', archList: [x86_64], }], +}, { + name: 'wasm_bpf', + bin: 'libwasmedgePluginWasmBpf.so', + testBin: 'wasmBpfTests', + options: '-DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF', + archList: [x86_64], +}, { + name: 'wasi_crypto', + bin: 'libwasmedgePluginWasiCrypto.so', + testBin: 'wasiCryptoTests', + options: '-DWASMEDGE_PLUGIN_WASI_CRYPTO=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasi_logging', + bin: 'libwasmedgePluginWasiLogging.so', + testBin: 'wasiLoggingTests', + options: '-DWASMEDGE_PLUGIN_WASI_LOGGING=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_process', + bin: 'libwasmedgePluginWasmEdgeProcess.so', + testBin: 'wasmedgeProcessTests', + options: '-DWASMEDGE_PLUGIN_PROCESS=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_tensorflow', + bin: 'libwasmedgePluginWasmEdgeTensorflow.so', + testBin: 'wasmedgeTensorflowTests', + options: '-DWASMEDGE_PLUGIN_TENSORFLOW=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_tensorflowlite', + bin: 'libwasmedgePluginWasmEdgeTensorflowLite.so', + testBin: 'wasmedgeTensorflowLiteTests', + options: '-DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_image', + bin: 'libwasmedgePluginWasmEdgeImage.so', + testBin: 'wasmedgeImageTests', + options: '-DWASMEDGE_PLUGIN_IMAGE=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_opencvmini', + bin: 'libwasmedgePluginWasmEdgeOpenCVMini.so', + testBin: 'wasmedgeOpencvminiTests', + options: '-DWASMEDGE_PLUGIN_OPENCVMINI=ON', + archList: [aarch64, x86_64], +}, { + name: 'wasmedge_ffmpeg', + bin: 'libwasmedgePluginWasmEdgeFFmpeg.so', + testBin: 'wasmedgeFFmpegTests', + options: '-DWASMEDGE_PLUGIN_FFMPEG=ON', + archList: [aarch64, x86_64], }]; let expandVariables = () => { diff --git a/.github/actions/expand-variables/package-lock.json b/.github/actions/expand-variables/package-lock.json index ff8f198e6275..b49a4ecf905d 100644 --- a/.github/actions/expand-variables/package-lock.json +++ b/.github/actions/expand-variables/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@actions/core": "^1.10.1" + "@actions/core": "^1.10.1", + "@actions/github": "^6.0.0" } }, "node_modules/@actions/core": { @@ -21,6 +22,17 @@ "uuid": "^8.3.2" } }, + "node_modules/@actions/github": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", + "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", + "dependencies": { + "@actions/http-client": "^2.2.0", + "@octokit/core": "^5.0.1", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + } + }, "node_modules/@actions/http-client": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", @@ -38,6 +50,142 @@ "node": ">=14" } }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.1.0.tgz", + "integrity": "sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz", + "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==", + "dependencies": { + "@octokit/types": "^12.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", + "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", + "dependencies": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^12.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/request": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.2.0.tgz", + "integrity": "sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==", + "dependencies": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", + "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", + "dependencies": { + "@octokit/types": "^12.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -57,6 +205,11 @@ "node": ">=14.0" } }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -64,6 +217,11 @@ "bin": { "uuid": "dist/bin/uuid" } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" } } } diff --git a/.github/actions/expand-variables/package.json b/.github/actions/expand-variables/package.json index 5391a153491d..d357eecb171b 100644 --- a/.github/actions/expand-variables/package.json +++ b/.github/actions/expand-variables/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { - "@actions/core": "^1.10.1" + "@actions/core": "^1.10.1", + "@actions/github": "^6.0.0" } } diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index bffc1aa6c611..d9b8aef4af00 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -305,157 +305,15 @@ jobs: name: WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.get_version.outputs.version }}-ubuntu22.04-${{ matrix.compiler }}.tar.gz path: plugin_wasmedge_ffmpeg.tar.gz - # Due to the dependencies and exclusions of WASI-NN, build them saperately. - build_wasinn_manylinux: + build_manylinux: permissions: contents: write - name: WASI-NN (manylinux, g++, Release) + name: manylinux, g++, Release needs: get_version uses: ./.github/workflows/reusable-build-extensions.yml with: version: ${{ needs.get_version.outputs.version }} - build_manylinux: - permissions: - contents: write - strategy: - matrix: - include: - - name: Plugins_x86_64 - host_runner: ubuntu-latest - docker_tag: manylinux2014_x86_64-plugins-deps - asset_tag: manylinux2014_x86_64 - build_type: Release - - name: Plugins_aarch64 - host_runner: linux-arm64-v2 - docker_tag: manylinux2014_aarch64-plugins-deps - asset_tag: manylinux2014_aarch64 - build_type: Release - name: Plugins (${{ matrix.docker_tag }}, g++, ${{ matrix.build_type }}) - runs-on: ${{ matrix.host_runner }} - env: - output_prefix: build/plugins - test_prefix: build/test/plugins - build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_FFMPEG=ON - build_options_manylinux2014_x86_64: -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF - build_options_manylinux2014_aarch64: - tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_ffmpeg - tar_names_manylinux2014_x86_64: wasm_bpf - tar_names_manylinux2014_aarch64: - test_bins_all_platforms: wasiCryptoTests wasiLoggingTests wasmedgeProcessTests wasmedgeTensorflowTests wasmedgeTensorflowLiteTests wasmedgeImageTests wasmedgeOpencvminiTests wasmedgeFFmpegTests - test_bins_manylinux2014_x86_64: wasmBpfTests - test_bins_manylinux2014_aarch64: - output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeFFmpeg.so - output_bins_manylinux2014_x86_64: libwasmedgePluginWasmBpf.so - output_bins_manylinux2014_aarch64: - needs: [ get_version ] - container: - image: wasmedge/wasmedge:${{ matrix.docker_tag }} - # Required for mounting debugfs - # Tests of wasm_bpf also require privileges - options: --privileged - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Build and install dependencies - run: | - yum update -y - yum install -y zlib-devel zlib-static cmake curl - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y - bash ./utils/wasi-crypto/build-openssl.sh - # Running tests of wasm_bpf requires proper ebpf running environment - mount -t debugfs none /sys/kernel/debug - bash utils/ffmpeg/install-ffmpeg-v6.0.sh - - name: Build and test plugins using g++ with ${{ matrix.build_type }} mode - shell: bash - run: | - source "$HOME/.cargo/env" - testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.asset_tag }}}) - export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.asset_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl - for (( i=0; i<${#testbin_array[@]}; i++ )); - do - echo "Building ${testbin_array[$i]} :" - cmake --build build --target ${testbin_array[$i]} - done - - name: Test plugins - shell: bash - run: | - export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH - plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) - testbin_array=(${test_bins_all_platforms} ${test_bins_${{ matrix.asset_tag }}}) - for (( i=0; i<${#plugin_array[@]}; i++ )); - do - echo "Testing ${plugin_array[$i]} :" - cd ${test_prefix}/${plugin_array[$i]} - ./${testbin_array[$i]} - cd - - done - - name: Prepare the WasmEdge plugins tar.gz package - shell: bash - run: | - plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) - outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) - for (( i=0; i<${#plugin_array[@]}; i++ )); - do - echo "Copying ${plugin_array[$i]} :" - cp ${output_prefix}/${plugin_array[$i]}/${outbin_array[$i]} ${outbin_array[$i]} - tar -zcvf plugin_${plugin_array[$i]}.tar.gz ${outbin_array[$i]} - done - - name: Upload artifact - wasi_crypto - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasi_crypto-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasi_crypto.tar.gz - - name: Upload artifact - wasi_logging - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasi_logging-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasi_logging.tar.gz - - name: Upload artifact - wasmedge_process - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_process-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_process.tar.gz - - name: Upload artifact - wasmedge_tensorflow - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_tensorflow-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_tensorflow.tar.gz - - name: Upload artifact - wasmedge_tensorflowlite - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_tensorflowlite.tar.gz - - name: Upload artifact - wasmedge_image - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_image-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_image.tar.gz - - name: Upload artifact - wasm_bpf - if: contains(matrix.docker_tag, 'manylinux2014_x86_64') - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasm_bpf-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasm_bpf.tar.gz - - name: Upload artifact - wasmedge_opencvmini - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_opencvmini-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_opencvmini.tar.gz - - name: Upload artifact - wasmedge_zlib - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_zlib-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_zlib.tar.gz - - - name: Upload artifact - wasmedge_ffmpeg - uses: actions/upload-artifact@v3 - with: - name: WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.get_version.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - path: plugin_wasmedge_ffmpeg.tar.gz - build_macos: permissions: contents: write diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index faf54b521afd..437746e6d1ec 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -35,6 +35,23 @@ env: jobs: prepare: + name: Prepare variables + runs-on: ${{ inputs.runner }} + outputs: + cache_key_ws: ${{ steps.prep.outputs.cache_key_ws }} + cache_path_ws: ${{ steps.prep.outputs.cache_path_ws }} + cache_key_h: ${{ steps.prep.outputs.cache_key_h }} + cache_path_h: ${{ steps.prep.outputs.cache_path_h }} + steps: + - id: prep + run: | + echo "cache_key_ws=${{ github.workflow }}-${{ github.head_ref || github.ref }}-${{ inputs.docker_tag }}-1-${{ github.run_id }}" >> $GITHUB_OUTPUT + echo "cache_path_ws=${{ github.workspace }}" >> $GITHUB_OUTPUT + echo "cache_key_h=${{ github.workflow }}-${{ github.head_ref || github.ref }}-${{ inputs.docker_tag }}-2-${{ github.run_id }}" >> $GITHUB_OUTPUT + echo "cache_path_h=$HOME" >> $GITHUB_OUTPUT + + prepare_cache: + needs: [prepare] name: Prepare files (${{ inputs.docker_tag }}) runs-on: ${{ inputs.runner }} container: @@ -42,18 +59,7 @@ jobs: # Required for mounting debugfs # Tests of wasm_bpf also require privileges options: --privileged - outputs: - cache_key1: ${{ steps.prep.outputs.cache_key1 }} - cache_path1: ${{ steps.prep.outputs.cache_path1 }} - cache_key2: ${{ steps.prep.outputs.cache_key2 }} - cache_path2: ${{ steps.prep.outputs.cache_path2 }} steps: - - id: prep - run: | - echo "cache_key1=${{ github.workflow }}-${{ github.head_ref || github.ref }}-${{ inputs.docker_tag }}-1-${{ github.run_id }}" >> $GITHUB_OUTPUT - echo "cache_path1=${{ github.workspace }}" >> $GITHUB_OUTPUT - echo "cache_key2=${{ github.workflow }}-${{ github.head_ref || github.ref }}-${{ inputs.docker_tag }}-2-${{ github.run_id }}" >> $GITHUB_OUTPUT - echo "cache_path2=$HOME" >> $GITHUB_OUTPUT - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -64,14 +70,15 @@ jobs: shell: bash run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y + source "$HOME/.cargo/env" + mkdir -p build bash ./utils/wasi-nn/install-pytorch.sh --disable-cxx11-abi - source "$HOME/.cargo/env" bash ./utils/wasi-crypto/build-openssl.sh + bash ./utils/ffmpeg/install-ffmpeg-v6.0.sh - name: Build ${{ matrix.plugin }} shell: bash run: | - source "$HOME/.cargo/env" export Torch_DIR=$(pwd)/${PYTORCH_INSTALL_TO}/libtorch if [[ ${build_tests} != "On" ]]; then target=${bin_name%.*} @@ -81,15 +88,15 @@ jobs: cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl - uses: actions/cache/save@v3 with: - key: ${{ steps.prep.outputs.cache_key1 }} - path: ${{ steps.prep.outputs.cache_path1 }} + key: ${{ needs.prepare.outputs.cache_key_ws }} + path: ${{ needs.prepare.outputs.cache_path_ws }} - uses: actions/cache/save@v3 with: - key: ${{ steps.prep.outputs.cache_key2 }} - path: ${{ steps.prep.outputs.cache_path2 }} + key: ${{ needs.prepare.outputs.cache_key_h }} + path: ${{ needs.prepare.outputs.cache_path_h }} build_on_manylinux: - needs: [prepare] + needs: [prepare, prepare_cache] strategy: fail-fast: false max-parallel: 1 @@ -97,7 +104,11 @@ jobs: include: ${{ fromJSON(inputs.plugins) }} name: ${{ matrix.plugin }} (${{ inputs.docker_tag }}) runs-on: ${{ inputs.runner }} - container: wasmedge/wasmedge:${{ inputs.docker_tag }} + container: + image: wasmedge/wasmedge:${{ inputs.docker_tag }} + # Required for mounting debugfs + # Tests of wasm_bpf also require privileges + options: --privileged env: bin_name: ${{ matrix.bin }} target: ${{ inputs.release && matrix.bin || matrix.testBin }} @@ -110,21 +121,22 @@ jobs: echo "filename=plugin_${{ matrix.plugin }}.tar.gz" >> $GITHUB_OUTPUT - uses: actions/cache/restore@v3 with: - key: ${{ needs.prepare.outputs.cache_key1 }} - path: ${{ needs.prepare.outputs.cache_path1 }} + key: ${{ needs.prepare.outputs.cache_key_ws }} + path: ${{ needs.prepare.outputs.cache_path_ws }} - uses: actions/cache/restore@v3 with: - key: ${{ needs.prepare.outputs.cache_key2 }} - path: ${{ needs.prepare.outputs.cache_path2 }} + key: ${{ needs.prepare.outputs.cache_key_h }} + path: ${{ needs.prepare.outputs.cache_path_h }} - name: Install dependencies shell: bash run: | - mkdir -p build - bash ./utils/wasi-nn/install-pytorch.sh --disable-cxx11-abi + # Running tests of wasm_bpf requires proper ebpf running environment + mount -t debugfs none /sys/kernel/debug - name: Build ${{ matrix.plugin }} shell: bash run: | export Torch_DIR=$(pwd)/${PYTORCH_INSTALL_TO}/libtorch + export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig:$PKG_CONFIG_PATH if [[ ${build_tests} != "On" ]]; then target=${bin_name%.*} target=${target#lib} @@ -138,6 +150,7 @@ jobs: - name: Test ${{ matrix.plugin }} if: ${{ !inputs.release }} run: | + export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH cd ${test_dir} ./${target} cd - diff --git a/.github/workflows/reusable-build-extensions.yml b/.github/workflows/reusable-build-extensions.yml index 043d115f2985..e3b523ee4933 100644 --- a/.github/workflows/reusable-build-extensions.yml +++ b/.github/workflows/reusable-build-extensions.yml @@ -29,7 +29,7 @@ jobs: fail-fast: false matrix: include: ${{ fromJSON(needs.prepare.outputs.matrix) }} - name: Build all plugins on ${{ matrix.docker_tag }} + name: ${{ matrix.arch }} uses: ./.github/workflows/reusable-build-extensions-on-manylinux.yml with: arch: ${{ matrix.arch }} From 8b2fcfa5f4f58f40f0db471c5ca1b5ac82695213 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Wed, 13 Mar 2024 01:01:48 +0800 Subject: [PATCH 092/218] [Docker] Add zlib dependencies Signed-off-by: Yi Huang --- utils/docker/Dockerfile.manylinux2014-build-plugins-deps | 3 ++- utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/docker/Dockerfile.manylinux2014-build-plugins-deps b/utils/docker/Dockerfile.manylinux2014-build-plugins-deps index 45bcd857cf1a..3c7fc7aa0725 100644 --- a/utils/docker/Dockerfile.manylinux2014-build-plugins-deps +++ b/utils/docker/Dockerfile.manylinux2014-build-plugins-deps @@ -6,7 +6,8 @@ ENV MANPATH /opt/rh/devtoolset-11/root/usr/share/man${MANPATH:+:${MANPATH}} ENV INFOPATH /opt/rh/devtoolset-11/root/usr/share/info${INFOPATH:+:${INFOPATH}} ENV PKG_CONFIG_PATH /opt/rh/devtoolset-11/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} -RUN cd && (yum check-update || true) && yum install -y cmake wget unzip +RUN cd && (yum check-update || true) && \ + yum install -y cmake wget unzip zlib-devel zlib-static COPY install-opencvmini.sh . ENV OPENCV_VERSION=4.8.0 diff --git a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps index 60b8a044bbcd..634fb8a05512 100644 --- a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps +++ b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps @@ -6,7 +6,8 @@ ENV MANPATH /opt/rh/gcc-toolset-13/root/usr/share/man${MANPATH:+:${MANPATH}} ENV INFOPATH /opt/rh/gcc-toolset-13/root/usr/share/info${INFOPATH:+:${INFOPATH}} ENV PKG_CONFIG_PATH /opt/rh/gcc-toolset-13/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} -RUN cd && (yum check-update || true) && yum install -y wget unzip +RUN cd && (yum check-update || true) && \ + yum install -y wget unzip zlib-devel zlib-static COPY install-opencvmini.sh . ENV OPENCV_VERSION=4.8.0 From 442355a517616409731d5c1cfec77bb26d4af7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Wed, 13 Mar 2024 16:56:21 +0800 Subject: [PATCH 093/218] [Misc] update error message about magic header (#3273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn Co-authored-by: hydai --- lib/loader/ast/component.cpp | 1 + lib/loader/loader.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/loader/ast/component.cpp b/lib/loader/ast/component.cpp index 37ffb7283921..2b86a06ed022 100644 --- a/lib/loader/ast/component.cpp +++ b/lib/loader/ast/component.cpp @@ -31,6 +31,7 @@ Expect, std::vector>> Loader::loadPreamble() { } std::vector WasmMagic = {0x00, 0x61, 0x73, 0x6D}; if (*Magic != WasmMagic) { + spdlog::error("Might an invalid wasm file"); return logLoadError(ErrCode::Value::MalformedMagic, FMgr.getLastOffset(), ASTNodeAttr::Component); } diff --git a/lib/loader/loader.cpp b/lib/loader/loader.cpp index 4e3a5022092a..c99d9257f24f 100644 --- a/lib/loader/loader.cpp +++ b/lib/loader/loader.cpp @@ -169,6 +169,7 @@ Loader::parseWasmUnit(Span Code) { case FileMgr::FileHeader::DLL: case FileMgr::FileHeader::MachO_32: case FileMgr::FileHeader::MachO_64: + spdlog::error("Might an invalid wasm file"); spdlog::error(ErrCode::Value::MalformedMagic); spdlog::error( " The AOT compiled WASM shared library is not supported for loading " From 36c21eea7a32345bafed1360ae08da81da39c82c Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Wed, 13 Mar 2024 17:54:58 +0800 Subject: [PATCH 094/218] [Runtime] Due to tracing GC, remove ref count. (#3274) Signed-off-by: YiYing He --- include/runtime/instance/array.h | 11 +++-------- include/runtime/instance/struct.h | 9 ++------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/include/runtime/instance/array.h b/include/runtime/instance/array.h index 6518b630b1c8..175c971e0fcf 100644 --- a/include/runtime/instance/array.h +++ b/include/runtime/instance/array.h @@ -29,18 +29,17 @@ class ArrayInstance : public CompositeBase { ArrayInstance() = delete; ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, const uint32_t Size) noexcept - : CompositeBase(Mod, Idx), RefCount(1), - Data(Size, static_cast(0)) { + : CompositeBase(Mod, Idx), Data(Size, static_cast(0)) { assuming(ModInst); } ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, const uint32_t Size, const ValVariant &Init) noexcept - : CompositeBase(Mod, Idx), RefCount(1), Data(Size, Init) { + : CompositeBase(Mod, Idx), Data(Size, Init) { assuming(ModInst); } ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, std::vector &&Init) noexcept - : CompositeBase(Mod, Idx), RefCount(1), Data(std::move(Init)) { + : CompositeBase(Mod, Idx), Data(std::move(Init)) { assuming(ModInst); } @@ -57,9 +56,6 @@ class ArrayInstance : public CompositeBase { return static_cast(Data.size()); } - /// Get reference count. - uint32_t getRefCount() const noexcept { return RefCount; } - /// Get boundary index. uint32_t getBoundIdx() const noexcept { return std::max(static_cast(Data.size()), UINT32_C(1)) - @@ -69,7 +65,6 @@ class ArrayInstance : public CompositeBase { private: /// \name Data of array instance. /// @{ - uint32_t RefCount; std::vector Data; /// @} }; diff --git a/include/runtime/instance/struct.h b/include/runtime/instance/struct.h index be72143ec7d9..281c275c0fcc 100644 --- a/include/runtime/instance/struct.h +++ b/include/runtime/instance/struct.h @@ -29,13 +29,12 @@ class StructInstance : public CompositeBase { StructInstance() = delete; StructInstance(const ModuleInstance *Mod, const uint32_t Idx, const uint32_t MemberCnt) noexcept - : CompositeBase(Mod, Idx), RefCount(1), - Data(MemberCnt, static_cast(0)) { + : CompositeBase(Mod, Idx), Data(MemberCnt, static_cast(0)) { assuming(ModInst); } StructInstance(const ModuleInstance *Mod, const uint32_t Idx, std::vector &&Init) noexcept - : CompositeBase(Mod, Idx), RefCount(1), Data(std::move(Init)) { + : CompositeBase(Mod, Idx), Data(std::move(Init)) { assuming(ModInst); } @@ -43,13 +42,9 @@ class StructInstance : public CompositeBase { ValVariant &getField(uint32_t Idx) noexcept { return Data[Idx]; } const ValVariant &getField(uint32_t Idx) const noexcept { return Data[Idx]; } - /// Get reference count. - uint32_t getRefCount() const noexcept { return RefCount; } - private: /// \name Data of struct instance. /// @{ - uint32_t RefCount; std::vector Data; /// @} }; From 74114c80db169f14f511124cb21cdfd6e50ce85d Mon Sep 17 00:00:00 2001 From: YiYing He Date: Tue, 12 Mar 2024 13:37:39 +0800 Subject: [PATCH 095/218] [Plugin] Fix option toggle for wasmedge_process plugin. Signed-off-by: YiYing He --- include/po/argument_parser.h | 2 -- lib/api/wasmedge.cpp | 4 +++- test/api/APIUnitTest.cpp | 2 +- test/plugins/unittest/testplugin.cpp | 6 +++++- test/plugins/unittest/testplugin.h | 12 ++++++++++++ test/plugins/unittest/unittest_c.cpp | 8 +++++--- test/plugins/unittest/unittest_cpp.cpp | 16 +++++++++++++++- 7 files changed, 41 insertions(+), 9 deletions(-) diff --git a/include/po/argument_parser.h b/include/po/argument_parser.h index 54d30925abe3..a294d69293de 100644 --- a/include/po/argument_parser.h +++ b/include/po/argument_parser.h @@ -140,8 +140,6 @@ class ArgumentParser { const ArgumentDescriptor &CurrentDesc = ArgumentDescriptors[Iter->second]; if (CurrentDesc.max_nargs() == 0) { return false; - CurrentDesc.default_value(); - return true; } CurrentDesc.raw_value(Value); diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index 618c2b0924dc..caa3906483fc 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -2014,7 +2014,9 @@ WasmEdge_ModuleInstanceInitWasmEdgeProcess(const char *const *AllowedCmds, Parser.set_raw_value>( "allow-command"sv, std::vector(AllowedCmds, AllowedCmds + CmdsLen)); - Parser.set_raw_value("allow-command-all"sv, AllowAll); + if (AllowAll) { + Parser.set_raw_value("allow-command-all"sv); + } } } diff --git a/test/api/APIUnitTest.cpp b/test/api/APIUnitTest.cpp index 35ebebeaf4f6..ebed175c8377 100644 --- a/test/api/APIUnitTest.cpp +++ b/test/api/APIUnitTest.cpp @@ -3677,7 +3677,7 @@ TEST(APICoreTest, Plugin) { EXPECT_EQ(ModCxt, nullptr); ModCxt = WasmEdge_PluginCreateModule(PluginCxt, Names[0]); EXPECT_NE(ModCxt, nullptr); - EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModCxt, Names, 15), 4U); + EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModCxt, Names, 15), 5U); WasmEdge_ModuleInstanceDelete(ModCxt); } #endif diff --git a/test/plugins/unittest/testplugin.cpp b/test/plugins/unittest/testplugin.cpp index 565b77c87b3b..7cc550135d39 100644 --- a/test/plugins/unittest/testplugin.cpp +++ b/test/plugins/unittest/testplugin.cpp @@ -19,12 +19,16 @@ PO::Option WasmEdgePluginTestEnv::CmdName(PO::Description("Test for input name."sv), PO::DefaultValue(std::string(""))); +PO::Option + WasmEdgePluginTestEnv::CmdOpt(PO::Description("Test for option."sv)); + namespace { void addOptions(const Plugin::Plugin::PluginDescriptor *, PO::ArgumentParser &Parser) noexcept { Parser.add_option("arg"sv, WasmEdgePluginTestEnv::CmdArgs) - .add_option("name"sv, WasmEdgePluginTestEnv::CmdName); + .add_option("name"sv, WasmEdgePluginTestEnv::CmdName) + .add_option("opt"sv, WasmEdgePluginTestEnv::CmdOpt); } Runtime::Instance::ModuleInstance * diff --git a/test/plugins/unittest/testplugin.h b/test/plugins/unittest/testplugin.h index d7373c9c6e12..b6bdbd34e3b1 100644 --- a/test/plugins/unittest/testplugin.h +++ b/test/plugins/unittest/testplugin.h @@ -20,6 +20,7 @@ class WasmEdgePluginTestEnv { static PO::List CmdArgs; static PO::Option CmdName; + static PO::Option CmdOpt; }; template @@ -62,6 +63,16 @@ class WasmEdgePluginTestFuncArgLen } }; +class WasmEdgePluginTestFuncOpt + : public WasmEdgePluginTestFunc { +public: + WasmEdgePluginTestFuncOpt(WasmEdgePluginTestEnv &HostEnv) + : WasmEdgePluginTestFunc(HostEnv) {} + Expect body(const Runtime::CallingFrame &) { + return static_cast(Env.CmdOpt.value()); + } +}; + class WasmEdgePluginTestFuncNameSize : public WasmEdgePluginTestFunc { public: @@ -79,6 +90,7 @@ class WasmEdgePluginTestModule : public Runtime::Instance::ModuleInstance { addHostFunc("add", std::make_unique(Env)); addHostFunc("sub", std::make_unique(Env)); addHostFunc("arg_len", std::make_unique(Env)); + addHostFunc("opt", std::make_unique(Env)); addHostFunc("name_size", std::make_unique(Env)); } diff --git a/test/plugins/unittest/unittest_c.cpp b/test/plugins/unittest/unittest_c.cpp index 19f229932345..a1ccb94d11a7 100644 --- a/test/plugins/unittest/unittest_c.cpp +++ b/test/plugins/unittest/unittest_c.cpp @@ -152,9 +152,9 @@ TEST(wasmedgePluginTests, C_Module) { // Create the wasmedge_plugintest_cpp_module module instance. auto *ModInstCPP = createModuleCPP(); ASSERT_FALSE(ModInstCPP == nullptr); - EXPECT_EQ(WasmEdge_ModuleInstanceListFunctionLength(ModInstCPP), 4U); + EXPECT_EQ(WasmEdge_ModuleInstanceListFunctionLength(ModInstCPP), 5U); std::memset(NameBuf, 0, sizeof(WasmEdge_String) * 16); - EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModInstCPP, NameBuf, 16), 4U); + EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModInstCPP, NameBuf, 16), 5U); EXPECT_TRUE( WasmEdge_StringIsEqual(NameBuf[0], WasmEdge_StringWrap("add", 3U))); EXPECT_TRUE( @@ -162,7 +162,9 @@ TEST(wasmedgePluginTests, C_Module) { EXPECT_TRUE( WasmEdge_StringIsEqual(NameBuf[2], WasmEdge_StringWrap("name_size", 9U))); EXPECT_TRUE( - WasmEdge_StringIsEqual(NameBuf[3], WasmEdge_StringWrap("sub", 3U))); + WasmEdge_StringIsEqual(NameBuf[3], WasmEdge_StringWrap("opt", 3U))); + EXPECT_TRUE( + WasmEdge_StringIsEqual(NameBuf[4], WasmEdge_StringWrap("sub", 3U))); WasmEdge_ModuleInstanceDelete(ModInstCPP); } diff --git a/test/plugins/unittest/unittest_cpp.cpp b/test/plugins/unittest/unittest_cpp.cpp index 00efc45e2b20..345bdbfd058f 100644 --- a/test/plugins/unittest/unittest_cpp.cpp +++ b/test/plugins/unittest/unittest_cpp.cpp @@ -40,6 +40,7 @@ WasmEdge::Runtime::Instance::ModuleInstance *createModuleCPP() { Parser.set_raw_value("name"sv, std::string("test_name")); Parser.set_raw_value>( "arg"sv, std::vector({"arg0", "arg1", "arg2", "arg3"})); + Parser.set_raw_value("opt"sv); if (const auto *Module = Plugin->findModule("wasmedge_plugintest_cpp_module"sv)) { return Module->create().release(); @@ -83,6 +84,18 @@ TEST(wasmedgePluginTests, CPP_Run) { EXPECT_TRUE(HostFuncInst2.run(CallFrame, {}, RetVal)); EXPECT_EQ(RetVal[0].get(), 9); + // Get the function "opt". + auto *FuncInst3 = TestModCPP->findFuncExports("opt"); + EXPECT_NE(FuncInst3, nullptr); + EXPECT_TRUE(FuncInst3->isHostFunction()); + auto &HostFuncInst3 = + dynamic_cast( + FuncInst3->getHostFunc()); + + // Test: Run function successfully. + EXPECT_TRUE(HostFuncInst3.run(CallFrame, {}, RetVal)); + EXPECT_EQ(RetVal[0].get(), 1); + delete TestModCPP; // Create the wasmedge_plugintest_c_module module instance. @@ -98,10 +111,11 @@ TEST(wasmedgePluginTests, CPP_Module) { auto *TestModCPP = dynamic_cast( createModuleCPP()); ASSERT_FALSE(TestModCPP == nullptr); - EXPECT_EQ(TestModCPP->getFuncExportNum(), 4U); + EXPECT_EQ(TestModCPP->getFuncExportNum(), 5U); EXPECT_NE(TestModCPP->findFuncExports("add"), nullptr); EXPECT_NE(TestModCPP->findFuncExports("sub"), nullptr); EXPECT_NE(TestModCPP->findFuncExports("arg_len"), nullptr); + EXPECT_NE(TestModCPP->findFuncExports("opt"), nullptr); EXPECT_NE(TestModCPP->findFuncExports("name_size"), nullptr); delete TestModCPP; From fbfa518b0dbd8f34fde16f6a50a685803d4841d7 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 14 Mar 2024 21:30:08 +0800 Subject: [PATCH 096/218] [JIT] Use custom allocator from tensorflow, fix #3257 Signed-off-by: Shen-Ta Hsieh --- lib/llvm/llvm.h | 163 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 2 deletions(-) diff --git a/lib/llvm/llvm.h b/lib/llvm/llvm.h index c45fcf99c595..31ac95d478fb 100644 --- a/lib/llvm/llvm.h +++ b/lib/llvm/llvm.h @@ -2200,6 +2200,7 @@ class OrcLLJIT { #if WASMEDGE_OS_WINDOWS #include #include +#include #include #endif @@ -2272,9 +2273,167 @@ bool SectionIterator::isEHFrame() const noexcept { } #if WASMEDGE_OS_WINDOWS +class DefaultMMapper final : public llvm::SectionMemoryManager::MemoryMapper { +public: + llvm::sys::MemoryBlock allocateMappedMemory( + llvm::SectionMemoryManager::AllocationPurpose /*Purpose*/, + size_t NumBytes, const llvm::sys::MemoryBlock *const NearBlock, + unsigned Flags, std::error_code &EC) override { + return llvm::sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags, + EC); + } + std::error_code protectMappedMemory(const llvm::sys::MemoryBlock &Block, + unsigned Flags) override { + return llvm::sys::Memory::protectMappedMemory(Block, Flags); + } + + std::error_code releaseMappedMemory(llvm::sys::MemoryBlock &M) override { + return llvm::sys::Memory::releaseMappedMemory(M); + } +}; + +class ContiguousSectionMemoryManager : public llvm::RTDyldMemoryManager { +public: + explicit ContiguousSectionMemoryManager( + llvm::SectionMemoryManager::MemoryMapper *UnownedMM = nullptr) + : MMapper(UnownedMM), OwnedMMapper(nullptr) { + if (!MMapper) { + OwnedMMapper = std::make_unique(); + MMapper = OwnedMMapper.get(); + } + } + + ~ContiguousSectionMemoryManager() noexcept override { + using namespace std::literals; + if (Preallocated.allocatedSize() != 0) { + auto EC = MMapper->releaseMappedMemory(Preallocated); + if (EC) { + spdlog::error("releaseMappedMemory failed with error: {}"sv, + EC.message()); + } + } + } + + bool needsToReserveAllocationSpace() override { return true; } + + void reserveAllocationSpace(uintptr_t CodeSize, llvm::Align CodeAlign, + uintptr_t RODataSize, llvm::Align RODataAlign, + uintptr_t RWDataSize, + llvm::Align RWDataAlign) override { + using namespace std::literals; + assuming(Preallocated.allocatedSize() == 0); + + static const size_t PageSize = llvm::sys::Process::getPageSizeEstimate(); + assuming(CodeAlign.value() <= PageSize); + assuming(RODataAlign.value() <= PageSize); + assuming(RWDataAlign.value() <= PageSize); + CodeSize = roundUpTo(CodeSize + CodeAlign.value(), PageSize); + RODataSize = roundUpTo(RODataSize + RODataAlign.value(), PageSize); + RWDataSize = roundUpTo(RWDataSize + RWDataAlign.value(), PageSize); + const uintptr_t TotalSize = + CodeSize + RODataSize + RWDataSize + PageSize * 3; + + std::error_code EC; + Preallocated = MMapper->allocateMappedMemory( + llvm::SectionMemoryManager::AllocationPurpose::Code, TotalSize, nullptr, + llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE, EC); + if (EC) { + spdlog::error("allocateMappedMemory failed with error: {}"sv, + EC.message()); + return; + } + + auto base = reinterpret_cast(Preallocated.base()); + CodeMem = CodeFree = + llvm::sys::MemoryBlock(reinterpret_cast(base), CodeSize); + base += CodeSize; + RODataMem = RODataFree = + llvm::sys::MemoryBlock(reinterpret_cast(base), RODataSize); + base += RODataSize; + RWDataMem = RWDataFree = + llvm::sys::MemoryBlock(reinterpret_cast(base), RWDataSize); + } + + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned /*SectionID*/, + llvm::StringRef /*SectionName*/, + bool IsReadOnly) override { + if (IsReadOnly) { + return Allocate(RODataFree, Size, Alignment); + } else { + return Allocate(RWDataFree, Size, Alignment); + } + } + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned /*SectionID*/, + llvm::StringRef /*SectionName*/) override { + return Allocate(CodeFree, Size, Alignment); + } + + bool finalizeMemory(std::string *ErrMsg) override { + std::error_code EC; + + EC = MMapper->protectMappedMemory(CodeMem, llvm::sys::Memory::MF_READ | + llvm::sys::Memory::MF_EXEC); + if (EC) { + if (ErrMsg) { + *ErrMsg = EC.message(); + } + return true; + } + EC = MMapper->protectMappedMemory(RODataMem, llvm::sys::Memory::MF_READ); + if (EC) { + if (ErrMsg) { + *ErrMsg = EC.message(); + } + return true; + } + + llvm::sys::Memory::InvalidateInstructionCache(CodeMem.base(), + CodeMem.allocatedSize()); + return false; + } + +private: + llvm::sys::MemoryBlock Preallocated; + + // Sections must be in the order code < rodata < rwdata. + llvm::sys::MemoryBlock CodeMem; + llvm::sys::MemoryBlock RODataMem; + llvm::sys::MemoryBlock RWDataMem; + + llvm::sys::MemoryBlock CodeFree; + llvm::sys::MemoryBlock RODataFree; + llvm::sys::MemoryBlock RWDataFree; + + llvm::SectionMemoryManager::MemoryMapper *MMapper; + std::unique_ptr OwnedMMapper; + + uint8_t *Allocate(llvm::sys::MemoryBlock &FreeBlock, std::uintptr_t Size, + unsigned alignment) { + using namespace std::literals; + const auto Base = reinterpret_cast(FreeBlock.base()); + const auto Start = roundUpTo(Base, alignment); + const uintptr_t PaddedSize = (Start - Base) + Size; + if (PaddedSize > FreeBlock.allocatedSize()) { + spdlog::error("Failed to satisfy suballocation request for {}"sv, Size); + return nullptr; + } + FreeBlock = + llvm::sys::MemoryBlock(reinterpret_cast(Base + PaddedSize), + FreeBlock.allocatedSize() - PaddedSize); + return reinterpret_cast(Start); + } + + static uintptr_t roundUpTo(uintptr_t Value, uintptr_t Divisor) noexcept { + return ((Value + (Divisor - 1)) / Divisor) * Divisor; + } +}; + // Register stack unwind info for JIT functions -class Win64EHManager : public llvm::SectionMemoryManager { - using Base = llvm::SectionMemoryManager; +class Win64EHManager : public ContiguousSectionMemoryManager { + using Base = ContiguousSectionMemoryManager; uint64_t CodeAddress = 0; public: From bfd27d857083b2c72ff07959b4eb370fd9739fb8 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 14 Mar 2024 16:47:22 +0800 Subject: [PATCH 097/218] [Misc] Disable warning in clang-18 Signed-off-by: Shen-Ta Hsieh --- cmake/Helper.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 5fcea2587db0..00d81cde8ae3 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -89,6 +89,12 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 18.0.0) + list(APPEND WASMEDGE_CFLAGS + -Wno-switch-default + ) + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0.0) list(APPEND WASMEDGE_CFLAGS -Wno-error=return-std-move-in-c++11 From 163584c8d9c0b34ef8a1cd3a19a03c6f593eceac Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Thu, 14 Mar 2024 16:29:05 +0800 Subject: [PATCH 098/218] [Misc] Upgrade spdlog to 1.13.0 * Use external fmt 10.2.1 Signed-off-by: Shen-Ta Hsieh --- lib/common/CMakeLists.txt | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/common/CMakeLists.txt b/lib/common/CMakeLists.txt index 7207ec0813e8..144240fe743f 100644 --- a/lib/common/CMakeLists.txt +++ b/lib/common/CMakeLists.txt @@ -5,28 +5,30 @@ find_package(spdlog QUIET) if(spdlog_FOUND) else() FetchContent_Declare( - spdlog - GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG v1.11.0 + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 10.2.1 GIT_SHALLOW TRUE ) - set(SPDLOG_BUILD_SHARED OFF CACHE BOOL "Build shared library" FORCE) + FetchContent_MakeAvailable(fmt) + wasmedge_setup_target(fmt) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - get_property( - compile_options - DIRECTORY - PROPERTY COMPILE_OPTIONS - ) - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS - ${WASMEDGE_CFLAGS} + target_compile_options(fmt + PUBLIC -Wno-missing-noreturn - -Wno-missing-variable-declarations + PRIVATE + -Wno-sign-conversion ) - unset(compile_options) endif() + + FetchContent_Declare( + spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG v1.13.0 + GIT_SHALLOW TRUE + ) + set(SPDLOG_BUILD_SHARED OFF CACHE BOOL "Build shared library" FORCE) + set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "Use external fmt library instead of bundled" FORCE) FetchContent_MakeAvailable(spdlog) wasmedge_setup_target(spdlog) endif() From 36ccdb7880f456cf71e95ec06591ca439fdbbca3 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Fri, 15 Mar 2024 12:12:40 +0800 Subject: [PATCH 099/218] [Changelog] Update the changelog for the 0.14.0-rc.1 pre-release. Signed-off-by: YiYing He --- .CurrentChangelog.md | 10 +++++++--- Changelog.md | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index af005deb6b62..361075876119 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.3 (2024-03-05) +### 0.14.0-rc.1 (2024-03-15) Breaking changes: @@ -32,6 +32,7 @@ Breaking changes: Features: +* Bumpped `spdlog` to `v1.13.0`. * [Proposal]: Apply new propoals. * Supported WASM Typed Function References proposal. * Added the `WasmEdge_Proposal_FunctionReferences` for the configuration in WasmEdge C API. @@ -89,6 +90,7 @@ Features: * Add `mmproj` option to set the projection model. * Add `image` option to set the image. * Support embedding generation. +* [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. Fixed issues: @@ -109,6 +111,8 @@ Fixed issues: * Checking `fd_prestat_dir_name` buffer size. * Checking `filestat_set_times` for invalid flags. * Checking validation of file descriptor in `socket_accept` (#3041). +* Fixed duplicated loading of the same plug-in. +* Fixed option toggle for `wasmedge_process` plug-in. Tests: @@ -123,6 +127,6 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.1-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 6aab0962d3b2..9602641a622b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.3 (2024-03-05) +### 0.14.0-rc.1 (2024-03-15) Breaking changes: @@ -32,6 +32,7 @@ Breaking changes: Features: +* Bumpped `spdlog` to `v1.13.0`. * [Proposal]: Apply new propoals. * Supported WASM Typed Function References proposal. * Added the `WasmEdge_Proposal_FunctionReferences` for the configuration in WasmEdge C API. @@ -89,6 +90,7 @@ Features: * Add `mmproj` option to set the projection model. * Add `image` option to set the image. * Support embedding generation. +* [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. Fixed issues: @@ -109,6 +111,8 @@ Fixed issues: * Checking `fd_prestat_dir_name` buffer size. * Checking `filestat_set_times` for invalid flags. * Checking validation of file descriptor in `socket_accept` (#3041). +* Fixed duplicated loading of the same plug-in. +* Fixed option toggle for `wasmedge_process` plug-in. Tests: @@ -123,9 +127,9 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Dhruv Jain, Draco, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.1-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 150776b28d18169f93896b39af1e7058f47aa101 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Fri, 15 Mar 2024 13:29:45 +0800 Subject: [PATCH 100/218] [CI] Ensure git safe directory for building extensions on manylinux. Signed-off-by: YiYing He --- .github/workflows/reusable-build-extensions-on-manylinux.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index 437746e6d1ec..88d7e5416f3d 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -127,6 +127,9 @@ jobs: with: key: ${{ needs.prepare.outputs.cache_key_h }} path: ${{ needs.prepare.outputs.cache_path_h }} + - name: Ensure git safe directory + run: | + git config --global --add safe.directory $(pwd) - name: Install dependencies shell: bash run: | From 29bc750b4143db3ba913046da5c8c33d96862f22 Mon Sep 17 00:00:00 2001 From: dm4 Date: Sat, 16 Mar 2024 00:28:04 +0800 Subject: [PATCH 101/218] [WASI-NN] ggml: set LlamaNInputs correctly when llava inference (#3286) Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index eee077970be0..f46ee6b6afcc 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -771,7 +771,6 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, if (GraphRef.MMProjModelPath == ""sv) { // Text only prompt. CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); - CxtRef.LlamaNInputs = CxtRef.LlamaInputs.size(); } else { // Handle llava format prompt. @@ -851,6 +850,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, EmbdInputAfterImage.begin(), EmbdInputAfterImage.end()); } + CxtRef.LlamaNInputs = CxtRef.LlamaInputs.size(); if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: set the input...Done"sv); } From 86a70fa20b249eb9b3913e9935304a3deb080a49 Mon Sep 17 00:00:00 2001 From: hydai Date: Mon, 18 Mar 2024 11:05:22 +0800 Subject: [PATCH 102/218] [Installer] Allow users to install the specific build number of the ggml plugin (#3281) * [Installer] Allow users to install the specific build number of the ggml plugin * [CI] Add the build number jobs for verifying the wasi-nn-ggml installation Signed-off-by: hydai --- .../workflows/test-python-install-script.yml | 15 +++++++ utils/install.py | 40 ++++++++++++++++--- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-python-install-script.yml b/.github/workflows/test-python-install-script.yml index 55f6b82b925d..2a4116bc9446 100644 --- a/.github/workflows/test-python-install-script.yml +++ b/.github/workflows/test-python-install-script.yml @@ -197,6 +197,21 @@ jobs: ls ~/new_wasmedge/plugin/ | grep .so && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) ${{ matrix.python3_ex }} utils/install.py -v 0.10.0-alpha.1 -p /usr ls /usr/lib/wasmedge/ | grep libwasmedgePluginWasmEdgeProcess.so && echo "Pass: Plugins found" || (echo "Fail: Plugins not found" && exit 1) + - name: Plugin install test - WasmEdge WASI-NN-GGML + run: | + # Without the build number + ${{ matrix.python2_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) + + ${{ matrix.python3_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) + + # With the build number + ${{ matrix.python2_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-b2334 + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) + + ${{ matrix.python3_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-b2334 + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) - name: Plugin install test - WasmEdge rustls if: ${{ matrix.name != 'manylinux2014 aarch64' }} run: | diff --git a/utils/install.py b/utils/install.py index be71670a7a68..2f376e1f3412 100644 --- a/utils/install.py +++ b/utils/install.py @@ -1156,10 +1156,39 @@ def install_plugins(args, compat): if len(args.plugins) >= 1: for plugin_name in args.plugins: plugin_version_supplied = None + plugin_wasi_nn_ggml_bypass_check = False if plugin_name.find(":") != -1: plugin_name, plugin_version_supplied = plugin_name.split(":") - if plugin_name not in PLUGINS_AVAILABLE: + # Split the WASI-NN-GGML plugin and the others + if plugin_name.startswith(WASI_NN_GGML): + # Re-write the plugin name if the build number is supplied + # E.g. wasi_nn-ggml-b2330, wasi_nn-ggml-cuda-b2330, wasi_nn-ggml-cuda-11-b2330 + # "https://github.com/second-state/WASI-NN-GGML-PLUGIN-REGISTRY/raw/main/" + # "$VERSION$/" + # "$BUILD_NUMBER$/" + # "WasmEdge-plugin" + # "-$PLUGIN_NAME$" + # "-$VERSION$" + # "-$DIST$" + # "_$ARCH$" # ".tar.gz" + # If the build number is supplied, bypass the checks + plugin_wasi_nn_ggml_bypass_check = True + if plugin_name.startswith(WASI_NN_GGML) and "-b" in plugin_name: + [plugin_name, plugin_build_number] = plugin_name.split("-b") + url_root = "https://github.com/second-state/WASI-NN-GGML-PLUGIN-REGISTRY/raw/main/" + url_root += "$VERSION$/b$BUILD_NUMBER$/WasmEdge-plugin-$PLUGIN_NAME$-$VERSION$-$DIST$_$ARCH$.tar.gz" + url_root = url_root.replace("$BUILD_NUMBER$", plugin_build_number) + + # Re-write the plugin name if CUDA is available + if plugin_name == WASI_NN_GGML and compat.cuda: + plugin_name = WASI_NN_GGML_CUDA + + # Normal plugin + if ( + plugin_name not in PLUGINS_AVAILABLE + and not plugin_wasi_nn_ggml_bypass_check + ): logging.error( "%s plugin not found, available names - %s", plugin_name, @@ -1167,11 +1196,10 @@ def install_plugins(args, compat): ) continue - # Re-write the plugin name if CUDA is available - if plugin_name == WASI_NN_GGML and compat.cuda: - plugin_name = WASI_NN_GGML_CUDA - - if compat.dist + compat.machine + plugin_name not in SUPPORTTED_PLUGINS: + if ( + compat.dist + compat.machine + plugin_name not in SUPPORTTED_PLUGINS + and not plugin_wasi_nn_ggml_bypass_check + ): logging.error( "Plugin not compatible: %s", compat.dist + compat.machine + plugin_name, From 9dc1ac5a5685cd05fb4a5aea7c3914b0d571edbc Mon Sep 17 00:00:00 2001 From: hydai Date: Mon, 18 Mar 2024 13:42:43 +0800 Subject: [PATCH 103/218] [WASI-NN] ggml backend: bump llama.cpp b2450 Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- plugins/wasi_nn/ggml.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 86a48cefc764..c0cab2e7edba 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2334 + GIT_TAG b2450 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index f46ee6b6afcc..bf300f35d7a2 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -348,7 +348,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, llama_context_params ContextParams = llama_context_default_params(); ContextParams.n_ctx = GraphRef.CtxSize; ContextParams.n_batch = GraphRef.BatchSize; - ContextParams.embedding = GraphRef.Embedding; + ContextParams.embeddings = GraphRef.Embedding; auto *LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); From e99b642fab6a2de0212b742fff407bbf091cb34f Mon Sep 17 00:00:00 2001 From: hydai Date: Mon, 18 Mar 2024 14:24:38 +0800 Subject: [PATCH 104/218] [CI] remove max-parallel limitation to speed up Signed-off-by: hydai --- .github/workflows/reusable-build-extensions-on-manylinux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index 88d7e5416f3d..44be8267b276 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -99,7 +99,6 @@ jobs: needs: [prepare, prepare_cache] strategy: fail-fast: false - max-parallel: 1 matrix: include: ${{ fromJSON(inputs.plugins) }} name: ${{ matrix.plugin }} (${{ inputs.docker_tag }}) From ab3bd60325a80a8dae0ee20556cdd6266854920b Mon Sep 17 00:00:00 2001 From: hydai Date: Mon, 18 Mar 2024 16:48:12 +0800 Subject: [PATCH 105/218] [WASI-NN] ggml: downgrade to b2370 to fix the metal segfault issue (#3290) Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index c0cab2e7edba..2cf32885ab49 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2450 + GIT_TAG b2370 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) From d3c27848d780cabc25572152015a4320e51659af Mon Sep 17 00:00:00 2001 From: YiYing He Date: Tue, 19 Mar 2024 17:26:57 +0800 Subject: [PATCH 106/218] [Executor] Fix reference type of init array with default value. Signed-off-by: YiYing He --- include/executor/executor.h | 6 ++- include/runtime/instance/array.h | 5 --- include/runtime/instance/struct.h | 5 --- lib/executor/engine/refInstr.cpp | 65 ++++++++++--------------------- lib/executor/helper.cpp | 35 +++++++++++++++++ 5 files changed, 61 insertions(+), 55 deletions(-) diff --git a/include/executor/executor.h b/include/executor/executor.h index d0de566c141e..1186f381402e 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -274,7 +274,7 @@ class Executor { AST::InstrView::iterator &PC) noexcept; /// @} - /// \name Helper Functions for getting instances. + /// \name Helper Functions for getting instances or types. /// @{ /// Helper function for get defined type by index. const AST::SubType *getDefTypeByIdx(Runtime::StackManager &StackMgr, @@ -303,6 +303,10 @@ class Executor { /// Helper function for get data instance by index. Runtime::Instance::DataInstance * getDataInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; + + /// Helper function for converting into bottom abstract heap type. + TypeCode toBottomType(Runtime::StackManager &StackMgr, + const ValType &Type) const; /// @} /// \name Run instructions functions diff --git a/include/runtime/instance/array.h b/include/runtime/instance/array.h index 175c971e0fcf..446025dea696 100644 --- a/include/runtime/instance/array.h +++ b/include/runtime/instance/array.h @@ -27,11 +27,6 @@ namespace Instance { class ArrayInstance : public CompositeBase { public: ArrayInstance() = delete; - ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, - const uint32_t Size) noexcept - : CompositeBase(Mod, Idx), Data(Size, static_cast(0)) { - assuming(ModInst); - } ArrayInstance(const ModuleInstance *Mod, const uint32_t Idx, const uint32_t Size, const ValVariant &Init) noexcept : CompositeBase(Mod, Idx), Data(Size, Init) { diff --git a/include/runtime/instance/struct.h b/include/runtime/instance/struct.h index 281c275c0fcc..df6cb1754b41 100644 --- a/include/runtime/instance/struct.h +++ b/include/runtime/instance/struct.h @@ -27,11 +27,6 @@ namespace Instance { class StructInstance : public CompositeBase { public: StructInstance() = delete; - StructInstance(const ModuleInstance *Mod, const uint32_t Idx, - const uint32_t MemberCnt) noexcept - : CompositeBase(Mod, Idx), Data(MemberCnt, static_cast(0)) { - assuming(ModInst); - } StructInstance(const ModuleInstance *Mod, const uint32_t Idx, std::vector &&Init) noexcept : CompositeBase(Mod, Idx), Data(std::move(Init)) { diff --git a/lib/executor/engine/refInstr.cpp b/lib/executor/engine/refInstr.cpp index ecfbdf616e2e..0782c34c2c4c 100644 --- a/lib/executor/engine/refInstr.cpp +++ b/lib/executor/engine/refInstr.cpp @@ -56,39 +56,8 @@ std::vector packVals(const ValType &Type, Expect Executor::runRefNullOp(Runtime::StackManager &StackMgr, const ValType &Type) const noexcept { - TypeCode Bot; // A null reference is typed with the least type in its respective hierarchy. - if (Type.isAbsHeapType()) { - switch (Type.getHeapTypeCode()) { - case TypeCode::NullFuncRef: - case TypeCode::FuncRef: - Bot = TypeCode::NullFuncRef; - break; - case TypeCode::NullExternRef: - case TypeCode::ExternRef: - Bot = TypeCode::NullExternRef; - break; - case TypeCode::NullRef: - case TypeCode::AnyRef: - case TypeCode::EqRef: - case TypeCode::I31Ref: - case TypeCode::StructRef: - case TypeCode::ArrayRef: - Bot = TypeCode::NullRef; - break; - default: - assumingUnreachable(); - } - } else { - const auto &CompType = (*StackMgr.getModule()->getType(Type.getTypeIndex())) - ->getCompositeType(); - if (CompType.isFunc()) { - Bot = TypeCode::NullFuncRef; - } else { - Bot = TypeCode::NullRef; - } - } - StackMgr.push(RefVariant(Bot)); + StackMgr.push(RefVariant(toBottomType(StackMgr, Type))); return {}; } @@ -135,21 +104,26 @@ Expect Executor::runStructNewOp(Runtime::StackManager &StackMgr, const auto &CompType = getDefTypeByIdx(StackMgr, DefIndex)->getCompositeType(); uint32_t N = static_cast(CompType.getFieldTypes().size()); + std::vector Vals; if (IsDefault) { - auto *Inst = - const_cast(StackMgr.getModule()) - ->newStruct(DefIndex, N); - StackMgr.push(RefVariant(Inst->getDefType(), Inst)); + Vals.resize(N); + for (uint32_t I = 0; I < N; I++) { + const auto &VType = CompType.getFieldTypes()[I].getStorageType(); + Vals[I] = VType.isRefType() + ? ValVariant(RefVariant(toBottomType(StackMgr, VType))) + : ValVariant(static_cast(0)); + } } else { - auto Vals = StackMgr.pop(N); + Vals = StackMgr.pop(N); for (uint32_t I = 0; I < N; I++) { Vals[I] = packVal(CompType.getFieldTypes()[I].getStorageType(), Vals[I]); } - auto *Inst = - const_cast(StackMgr.getModule()) - ->newStruct(DefIndex, std::move(Vals)); - StackMgr.push(RefVariant(Inst->getDefType(), Inst)); } + auto *Inst = + const_cast(StackMgr.getModule()) + ->newStruct(DefIndex, std::move(Vals)); + StackMgr.push(RefVariant(Inst->getDefType(), Inst)); + return {}; } @@ -197,9 +171,12 @@ Expect Executor::runArrayNewOp(Runtime::StackManager &StackMgr, getDefTypeByIdx(StackMgr, DefIndex)->getCompositeType(); const auto &VType = CompType.getFieldTypes()[0].getStorageType(); if (InitCnt == 0) { + auto InitVal = VType.isRefType() + ? ValVariant(RefVariant(toBottomType(StackMgr, VType))) + : ValVariant(static_cast(0)); auto *Inst = const_cast(StackMgr.getModule()) - ->newArray(DefIndex, ValCnt); + ->newArray(DefIndex, ValCnt, InitVal); StackMgr.push(RefVariant(Inst->getDefType(), Inst)); } else if (InitCnt == 1) { auto *Inst = @@ -242,7 +219,7 @@ Executor::runArrayNewDataOp(Runtime::StackManager &StackMgr, /// This may be changed after applying the garbage collection mechanism. auto *Inst = const_cast(StackMgr.getModule()) - ->newArray(Instr.getTargetIndex(), N); + ->newArray(Instr.getTargetIndex(), N, 0U); for (uint32_t Idx = 0; Idx < N; Idx++) { // The value has been packed. Inst->getData(Idx) = DataInst.loadValue(S + Idx * BSize, BSize); @@ -509,7 +486,7 @@ Executor::runRefTestOp(const Runtime::Instance::ModuleInstance *ModInst, ValVariant &Val, const AST::Instruction &Instr, bool IsCast) const noexcept { // Copy the value type here due to handling the externalized case. - auto VT = Val.get().getType(); + auto &VT = Val.get().getType(); if (VT.isExternalized()) { VT = ValType(TypeCode::Ref, TypeCode::ExternRef); } diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 7ac06956c047..3582686bc300 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -281,5 +281,40 @@ Executor::getDataInstByIdx(Runtime::StackManager &StackMgr, return ModInst->unsafeGetData(Idx); } +TypeCode Executor::toBottomType(Runtime::StackManager &StackMgr, + const ValType &Type) const { + if (Type.isRefType()) { + if (Type.isAbsHeapType()) { + switch (Type.getHeapTypeCode()) { + case TypeCode::NullFuncRef: + case TypeCode::FuncRef: + return TypeCode::NullFuncRef; + case TypeCode::NullExternRef: + case TypeCode::ExternRef: + return TypeCode::NullExternRef; + case TypeCode::NullRef: + case TypeCode::AnyRef: + case TypeCode::EqRef: + case TypeCode::I31Ref: + case TypeCode::StructRef: + case TypeCode::ArrayRef: + return TypeCode::NullRef; + default: + assumingUnreachable(); + } + } else { + const auto &CompType = + (*StackMgr.getModule()->getType(Type.getTypeIndex())) + ->getCompositeType(); + if (CompType.isFunc()) { + return TypeCode::NullFuncRef; + } else { + return TypeCode::NullRef; + } + } + } else { + return Type.getCode(); + } +} } // namespace Executor } // namespace WasmEdge From 13850057ce426c1fc02d10abee878fa1e04edeff Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 15 Mar 2024 16:33:07 +0800 Subject: [PATCH 107/218] [Docker] Remove an accident Signed-off-by: Yi Huang --- ...ckerfile.manylinux2014_plugins_deps_x86_64 | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 diff --git a/utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 b/utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 deleted file mode 100644 index f3a89549b0a3..000000000000 --- a/utils/docker/Dockerfile.manylinux2014_plugins_deps_x86_64 +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# SPDX-FileCopyrightText: 2019-2022 Second State INC - -ARG BASE=wasmedge/wasmedge:manylinux2014_x86_64 -ARG BUILDPLATFORM=x86_64 -FROM --platform=$BUILDPLATFORM ${BASE} - -MAINTAINER hydai hydai@secondstate.io - -ADD install-opencvmini.sh /root/ - -ENV PATH=/opt/rh/devtoolset-11/root/usr/bin${PATH:+:${PATH}} -ENV MANPATH=/opt/rh/devtoolset-11/root/usr/share/man${MANPATH:+:${MANPATH}} -ENV INFOPATH=/opt/rh/devtoolset-11/root/usr/share/info${INFOPATH:+:${INFOPATH}} -ENV PKG_CONFIG_PATH=/opt/rh/devtoolset-11/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} -ENV OPENCV_VERSION=4.8.0 - -WORKDIR /root/ - -RUN yum update -y \ - && yum install -y zlib-devel zlib-static cmake wget unzip \ - && bash /root/install-opencvmini.sh - -RUN yum clean all From 8af4be124197fc916cbd56856a618a37002f2171 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 15 Mar 2024 19:50:30 +0800 Subject: [PATCH 108/218] [CI] Move dependencies to docker image Signed-off-by: Yi Huang --- .github/workflows/docker.yml | 4 +-- ...reusable-build-extensions-on-manylinux.yml | 23 +++------------- ...ockerfile.manylinux2014-build-plugins-deps | 26 ++++++++++++++++-- ...ckerfile.manylinux_2_28-build-plugins-deps | 27 +++++++++++++++++-- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4e1ac1cc9ffe..d1b3aa9f715e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -238,7 +238,7 @@ jobs: uses: docker/build-push-action@v5 with: build-args: BASE=wasmedge/wasmedge:manylinux2014_x86_64 - context: ./utils/docker + context: ./utils file: utils/docker/Dockerfile.manylinux2014-build-plugins-deps platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} @@ -295,7 +295,7 @@ jobs: uses: docker/build-push-action@v5 with: build-args: BASE=wasmedge/wasmedge:manylinux_2_28_x86_64 - context: ./utils/docker + context: ./utils file: utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index 44be8267b276..1f4fe48d5ae3 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -28,10 +28,6 @@ on: env: build_tests: ${{ inputs.release && 'Off' || 'On' }} build_type: Release - OPENVINO_VERSION: "2023.0.2" - OPENVINO_YEAR: "2023" - PYTORCH_VERSION: "1.8.2" - PYTORCH_INSTALL_TO: "." jobs: prepare: @@ -71,21 +67,17 @@ jobs: run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y source "$HOME/.cargo/env" - - mkdir -p build - bash ./utils/wasi-nn/install-pytorch.sh --disable-cxx11-abi - bash ./utils/wasi-crypto/build-openssl.sh - bash ./utils/ffmpeg/install-ffmpeg-v6.0.sh - name: Build ${{ matrix.plugin }} shell: bash run: | - export Torch_DIR=$(pwd)/${PYTORCH_INSTALL_TO}/libtorch if [[ ${build_tests} != "On" ]]; then target=${bin_name%.*} target=${target#lib} fi - cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl + mkdir -p build + cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_PLUGIN_WASI_LOGGING=ON + cmake --build build --target wasmedgePluginWasiLogging - uses: actions/cache/save@v3 with: key: ${{ needs.prepare.outputs.cache_key_ws }} @@ -137,8 +129,6 @@ jobs: - name: Build ${{ matrix.plugin }} shell: bash run: | - export Torch_DIR=$(pwd)/${PYTORCH_INSTALL_TO}/libtorch - export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig:$PKG_CONFIG_PATH if [[ ${build_tests} != "On" ]]; then target=${bin_name%.*} target=${target#lib} @@ -152,7 +142,6 @@ jobs: - name: Test ${{ matrix.plugin }} if: ${{ !inputs.release }} run: | - export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH cd ${test_dir} ./${target} cd - @@ -162,12 +151,6 @@ jobs: with: name: ${{ steps.prep.outputs.artifact }} path: ${{ steps.prep.outputs.filename }} - - name: Install gh on manylinux - if: ${{ inputs.release }} - run: | - type -p yum-config-manager >/dev/null || sudo yum install yum-utils - yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo - yum install -y gh - name: Upload WasmEdge ${{ matrix.plugin }} plugin tar.gz package if: ${{ inputs.release }} env: diff --git a/utils/docker/Dockerfile.manylinux2014-build-plugins-deps b/utils/docker/Dockerfile.manylinux2014-build-plugins-deps index 3c7fc7aa0725..4762b087db86 100644 --- a/utils/docker/Dockerfile.manylinux2014-build-plugins-deps +++ b/utils/docker/Dockerfile.manylinux2014-build-plugins-deps @@ -8,9 +8,31 @@ ENV PKG_CONFIG_PATH /opt/rh/devtoolset-11/root/usr/lib64/pkgconfig${PKG_CONFIG_P RUN cd && (yum check-update || true) && \ yum install -y cmake wget unzip zlib-devel zlib-static +RUN yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \ + yum install -y gh -COPY install-opencvmini.sh . -ENV OPENCV_VERSION=4.8.0 +WORKDIR /root + +COPY docker/install-opencvmini.sh . +ENV OPENCV_VERSION "4.8.0" RUN [ "/bin/bash", "install-opencvmini.sh" ] +COPY wasi-nn/install-pytorch.sh . +ENV PYTORCH_VERSION "1.8.2" +ENV PYTORCH_INSTALL_TO "/root" +ENV Torch_DIR "/root/libtorch" +RUN [ "/bin/bash", "install-pytorch.sh", "--disable-cxx11-abi" ] + +COPY wasi-crypto/build-openssl.sh . +ENV OPENSSL_ROOT_DIR "/root/openssl-1.1.1n/openssl" +RUN [ "/bin/bash", "build-openssl.sh" ] + +COPY ffmpeg/install-ffmpeg-v6.0.sh . +RUN [ "/bin/bash", "install-ffmpeg-v6.0.sh" ] +ENV PKG_CONFIG_PATH /root/FFmpeg-n6.0/output/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} +ENV LD_LIBRARY_PATH /root/FFmpeg-n6.0/output/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} + +ENV OPENVINO_VERSION "2023.0.2" +ENV OPENVINO_YEAR "2023" + RUN yum clean all diff --git a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps index 634fb8a05512..c8ed5dbf74b4 100644 --- a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps +++ b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps @@ -8,9 +8,32 @@ ENV PKG_CONFIG_PATH /opt/rh/gcc-toolset-13/root/usr/lib64/pkgconfig${PKG_CONFIG_ RUN cd && (yum check-update || true) && \ yum install -y wget unzip zlib-devel zlib-static +RUN yum install -y yum-utils && \ + yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \ + yum install -y gh -COPY install-opencvmini.sh . -ENV OPENCV_VERSION=4.8.0 +WORKDIR /root + +COPY docker/install-opencvmini.sh . +ENV OPENCV_VERSION "4.8.0" RUN [ "/bin/bash", "install-opencvmini.sh" ] +COPY wasi-nn/install-pytorch.sh . +ENV PYTORCH_VERSION "1.8.2" +ENV PYTORCH_INSTALL_TO "/root" +ENV Torch_DIR "/root/libtorch" +RUN [ "/bin/bash", "install-pytorch.sh", "--disable-cxx11-abi" ] + +COPY wasi-crypto/build-openssl.sh . +ENV OpenSSL_DIR "/root/openssl-1.1.1n/openssl" +RUN [ "/bin/bash", "build-openssl.sh" ] + +COPY ffmpeg/install-ffmpeg-v6.0.sh . +RUN [ "/bin/bash", "install-ffmpeg-v6.0.sh" ] +ENV PKG_CONFIG_PATH /root/FFmpeg-n6.0/output/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} +ENV LD_LIBRARY_PATH /root/FFmpeg-n6.0/output/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} + +ENV OPENVINO_VERSION "2023.0.2" +ENV OPENVINO_YEAR "2023" + RUN yum clean all From 720d1d3c5417e43918a7248e3c6f3fe3b7c2dc8e Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 19 Mar 2024 08:30:44 +0800 Subject: [PATCH 109/218] [WASI-NN] ggml: downgrade to b2334 to fix the embedding issue Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- plugins/wasi_nn/ggml.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 2cf32885ab49..86a48cefc764 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2370 + GIT_TAG b2334 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index bf300f35d7a2..f46ee6b6afcc 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -348,7 +348,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, llama_context_params ContextParams = llama_context_default_params(); ContextParams.n_ctx = GraphRef.CtxSize; ContextParams.n_batch = GraphRef.BatchSize; - ContextParams.embeddings = GraphRef.Embedding; + ContextParams.embedding = GraphRef.Embedding; auto *LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); From 7c3507d7c39dd822b8cf8afd479f24d9210afbac Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 20 Mar 2024 09:24:14 +0800 Subject: [PATCH 110/218] [Changelog] Update the changelog for the 0.14.0-rc.2 pre-release. Signed-off-by: YiYing He --- .CurrentChangelog.md | 4 ++-- Changelog.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index 361075876119..53132071ecb2 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.1 (2024-03-15) +### 0.14.0-rc.2 (2024-03-20) Breaking changes: @@ -129,4 +129,4 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.1-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 9602641a622b..4b8406015080 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.1 (2024-03-15) +### 0.14.0-rc.2 (2024-03-20) Breaking changes: @@ -129,7 +129,7 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.1-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 8ac5a91886d0665171127ec8974e3b67b4ec9fa3 Mon Sep 17 00:00:00 2001 From: dm4 Date: Tue, 19 Mar 2024 18:22:47 +0800 Subject: [PATCH 111/218] [WASI-NN] ggml: use new metal file Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 86a48cefc764..8696fd76bf53 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -174,6 +174,7 @@ if(BACKEND STREQUAL "ggml") TARGET wasmedgePluginWasiNN POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/llama-src/ggml-metal.metal ggml-metal.metal + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/bin/default.metallib default.metallib ) endif() endif() From 30651887a1dc4a12960afc6e85cc0d441aacd428 Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 21 Mar 2024 10:44:14 +0800 Subject: [PATCH 112/218] [WASI-NN] rpc: implement `load_by_name_with_config` Signed-off-by: dm4 --- .../wasi_nn_rpcserver/wasi_nn_rpcserver.h | 41 +++++++++++++++++++ lib/wasi_nn_rpc/wasi_ephemeral_nn.proto | 10 +++++ plugins/wasi_nn/wasinnfunc.cpp | 30 ++++++++++---- test/plugins/wasi_nn/wasi_nn.cpp | 27 ++++++++++++ 4 files changed, 100 insertions(+), 8 deletions(-) diff --git a/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h b/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h index 10cd68579b78..2bebf9afd105 100644 --- a/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h +++ b/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h @@ -131,6 +131,47 @@ class GraphService final : public wasi_ephemeral_nn::Graph::Service { return grpc::Status::OK; } + /* + Expect + WasiNNLoadByNameWithConfig::bodyImpl( + const Runtime::CallingFrame &Frame, + uint32_t NamePtr, uint32_t NameLen, + uint32_t ConfigPtr, uint32_t ConfigLen, + uint32_t GraphIdPtr + ) + */ + virtual grpc::Status LoadByNameWithConfig( + grpc::ServerContext * /*RPCContext*/, + const wasi_ephemeral_nn::LoadByNameWithConfigRequest *RPCRequest, + wasi_ephemeral_nn::LoadByNameWithConfigResult *RPCResult) { + std::string_view FuncName = "load_by_name_with_config"sv; + auto Name = RPCRequest->name(); + auto Config = RPCRequest->config(); + uint32_t NamePtr = UINT32_C(0); + uint32_t NameLen = Name.size(); // does not include the '\0' terminator + uint32_t ConfigPtr = + Name.size() + 1; // 1 is for the '\0' terminator of Name + uint32_t ConfigLen = Config.size(); // does not include the '\0' terminator + uint32_t OutPtr = + NamePtr + NameLen + 1 + ConfigLen + 1; // 1 is for the '\0' terminator + uint32_t MemorySize = OutPtr + 4; // 4 is for sizeof(OutPtr) + + HostFuncCaller HostFuncCaller(NNMod, FuncName, MemorySize); + auto &MemInst = HostFuncCaller.getMemInst(); + std::vector NameVec(Name.begin(), Name.end()); + std::vector ConfigVec(Config.begin(), Config.end()); + writeBinaries(MemInst, NameVec, NamePtr); + writeBinaries(MemInst, ConfigVec, ConfigPtr); + uint32_t Errno = + HostFuncCaller.call({NamePtr, NameLen, ConfigPtr, ConfigLen, OutPtr}); + if (Errno != 0) { + return createRPCStatusFromErrno(FuncName, Errno); + } + uint32_t GraphHandle = *MemInst.getPointer(OutPtr); + RPCResult->set_graph_handle(GraphHandle); + return grpc::Status::OK; + } + private: const Runtime::Instance::ModuleInstance &NNMod; }; diff --git a/lib/wasi_nn_rpc/wasi_ephemeral_nn.proto b/lib/wasi_nn_rpc/wasi_ephemeral_nn.proto index 3ed030e455dc..e3bf4ae9a282 100644 --- a/lib/wasi_nn_rpc/wasi_ephemeral_nn.proto +++ b/lib/wasi_nn_rpc/wasi_ephemeral_nn.proto @@ -44,9 +44,19 @@ message LoadByNameResult { uint32 graph_handle = 1; } +message LoadByNameWithConfigRequest { + string name = 1; + string config = 2; +} + +message LoadByNameWithConfigResult { + uint32 graph_handle = 1; +} + service Graph { // No support for Load yet rpc LoadByName(LoadByNameRequest) returns (LoadByNameResult) {}; + rpc LoadByNameWithConfig(LoadByNameWithConfigRequest) returns (LoadByNameWithConfigResult) {}; } message SetInputRequest { diff --git a/plugins/wasi_nn/wasinnfunc.cpp b/plugins/wasi_nn/wasinnfunc.cpp index 6ccf2b459126..defaf6aeb690 100644 --- a/plugins/wasi_nn/wasinnfunc.cpp +++ b/plugins/wasi_nn/wasinnfunc.cpp @@ -157,14 +157,6 @@ WasiNNLoadByName::bodyImpl(const Runtime::CallingFrame &Frame, uint32_t NamePtr, Expect WasiNNLoadByNameWithConfig::bodyImpl( const Runtime::CallingFrame &Frame, uint32_t NamePtr, uint32_t NameLen, uint32_t ConfigPtr, uint32_t ConfigLen, uint32_t GraphIdPtr) { -#ifdef WASMEDGE_BUILD_WASI_NN_RPC - if (Env.NNRPCChannel != nullptr) { - // TODO: implement RPC for LoadByNameWithConfig - spdlog::error( - "[WASI-NN] RPC client is not implemented for LoadByNameWithConfig"sv); - return WASINN::ErrNo::UnsupportedOperation; - } -#endif auto *MemInst = Frame.getMemoryByIndex(0); if (MemInst == nullptr) { return Unexpect(ErrCode::Value::HostFuncError); @@ -192,6 +184,28 @@ Expect WasiNNLoadByNameWithConfig::bodyImpl( return WASINN::ErrNo::InvalidArgument; } +#ifdef WASMEDGE_BUILD_WASI_NN_RPC + if (Env.NNRPCChannel != nullptr) { + auto Stub = wasi_ephemeral_nn::Graph::NewStub(Env.NNRPCChannel); + grpc::ClientContext ClientContext; + wasi_ephemeral_nn::LoadByNameWithConfigRequest Req; + auto NameStrView = MemInst->getStringView(NamePtr, NameLen); + auto ConfigStrView = MemInst->getStringView(ConfigPtr, ConfigLen); + Req.set_name(NameStrView.data(), NameStrView.size()); + Req.set_config(ConfigStrView.data(), ConfigStrView.size()); + wasi_ephemeral_nn::LoadByNameWithConfigResult Res; + auto Status = Stub->LoadByNameWithConfig(&ClientContext, Req, &Res); + if (!Status.ok()) { + spdlog::error( + "[WASI-NN] Failed when calling remote LoadByNameWithConfig: {}"sv, + Status.error_message()); + return WASINN::ErrNo::RuntimeError; + } + *GraphId = Res.graph_handle(); + return WASINN::ErrNo::Success; + } +#endif // ifdef WASMEDGE_BUILD_WASI_NN_RPC + // Get the model std::string ModelName(reinterpret_cast(Name), NameLen); std::vector ModelConfig(reinterpret_cast(Config), diff --git a/test/plugins/wasi_nn/wasi_nn.cpp b/test/plugins/wasi_nn/wasi_nn.cpp index 381952024e1c..f5d5572da2da 100644 --- a/test/plugins/wasi_nn/wasi_nn.cpp +++ b/test/plugins/wasi_nn/wasi_nn.cpp @@ -1525,6 +1525,13 @@ TEST(WasiNNTest, GGMLBackendWithRPC) { EXPECT_TRUE(FuncInst->isHostFunction()); auto &HostFuncLoadByName = dynamic_cast(FuncInst->getHostFunc()); + // Get the function "load_by_name_with_config". + FuncInst = NNMod->findFuncExports("load_by_name_with_config"); + EXPECT_NE(FuncInst, nullptr); + EXPECT_TRUE(FuncInst->isHostFunction()); + auto &HostFuncLoadByNameWithConfig = + dynamic_cast( + FuncInst->getHostFunc()); // Get the function "init_execution_context". FuncInst = NNMod->findFuncExports("init_execution_context"); EXPECT_NE(FuncInst, nullptr); @@ -1565,6 +1572,26 @@ TEST(WasiNNTest, GGMLBackendWithRPC) { BuilderPtr += 4; } + // Test: load_by_name_with_config -- load successfully. + { + std::string Name = "default"; + std::string Config = "{}"; + std::vector NameVec(Name.begin(), Name.end()); + std::vector ConfigVec(Config.begin(), Config.end()); + uint32_t ConfigPtr = LoadEntryPtr + NameVec.size(); + writeBinaries(MemInst, NameVec, LoadEntryPtr); + writeBinaries(MemInst, ConfigVec, ConfigPtr); + EXPECT_TRUE(HostFuncLoadByNameWithConfig.run( + CallFrame, + std::initializer_list{ + LoadEntryPtr, static_cast(NameVec.size()), ConfigPtr, + static_cast(ConfigVec.size()), BuilderPtr}, + Errno)); + EXPECT_EQ(Errno[0].get(), static_cast(ErrNo::Success)); + EXPECT_EQ(*MemInst.getPointer(BuilderPtr), 0); + BuilderPtr += 4; + } + // GGML WASI-NN init_execution_context tests. // Test: init_execution_context -- graph id invalid. { From 946ca3061765e1d89a7833ebbf7f5b293a150467 Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 21 Mar 2024 15:48:53 +0800 Subject: [PATCH 113/218] [WASI-NN] ggml: bump llama.cpp b2479 and fix embeddings Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- plugins/wasi_nn/ggml.cpp | 136 ++++++++++++++++----------------- 2 files changed, 68 insertions(+), 70 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 8696fd76bf53..dd80a29bb7bd 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -49,7 +49,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2334 + GIT_TAG b2479 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index f46ee6b6afcc..5309f9aa9b09 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -277,6 +277,7 @@ Expect setupContextParam(Graph &GraphRef, ContextParams.n_batch = GraphRef.BatchSize; ContextParams.n_threads = GraphRef.Threads; ContextParams.n_threads_batch = GraphRef.Threads; + ContextParams.embeddings = GraphRef.Embedding; return ErrNo::Success; } @@ -315,6 +316,48 @@ void buildOutputEmbedding(std::string &Embedding, int32_t NEmbd, Embedding = OS.str(); } +ErrNo evaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, + std::vector Tokens, int &NPast) noexcept { + uint32_t NCtx = llama_n_ctx(LlamaContext); + + // End the inference if the context is full. + if (NPast + static_cast(Tokens.size()) > NCtx) { + if (GraphRef.EnableLog) { + spdlog::info( + "[WASI-NN] GGML backend: the context if full ({} / {} tokens). Please increase your context size."sv, + NPast + static_cast(Tokens.size()), NCtx); + } + return ErrNo::ContextFull; + } + + for (int I = 0; I < static_cast(Tokens.size()); + I += GraphRef.BatchSize) { + int NEval = static_cast(Tokens.size()) - I; + if (NEval > static_cast(GraphRef.BatchSize)) { + NEval = GraphRef.BatchSize; + } + // llama_batch_get_one(*token, n_tokens, position, sequence_id) + // This will return batch for single sequence of tokens starting at + // position. + const llama_seq_id SequenceId = 0; + auto Status = + llama_decode(LlamaContext, + llama_batch_get_one(&Tokens[I], NEval, NPast, SequenceId)); + if (Status == 1) { + spdlog::error( + "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); + return ErrNo::RuntimeError; + } else if (Status < 0) { + spdlog::error( + "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); + return ErrNo::RuntimeError; + } + NPast += NEval; + } + + return ErrNo::Success; +} + Expect getEmbedding(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { auto &CxtRef = Env.NNContext[ContextId].get(); @@ -346,18 +389,30 @@ Expect getEmbedding(WasiNNEnvironment &Env, } // Initialize the llama context. llama_context_params ContextParams = llama_context_default_params(); - ContextParams.n_ctx = GraphRef.CtxSize; - ContextParams.n_batch = GraphRef.BatchSize; - ContextParams.embedding = GraphRef.Embedding; + setupContextParam(GraphRef, ContextParams); auto *LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); + // Prepare variables; + int32_t NPast = 0; // Get the context size. const uint64_t NCtx = llama_n_ctx(LlamaContext); // Minus 4 for the special tokens. (Such as , , ... tokens.) const uint64_t MaxTokensListSize = NCtx - 4; // Use the const sequence id here. const llama_seq_id SequenceId = 0; + // Return value. + auto ReturnCode = ErrNo::Success; + + // Add BOS if not present. + if (CxtRef.LlamaInputs.front() != llama_token_bos(GraphRef.LlamaModel)) { + CxtRef.LlamaInputs.insert(CxtRef.LlamaInputs.begin(), + llama_token_bos(GraphRef.LlamaModel)); + } + // Add EOS if not present. + if (CxtRef.LlamaInputs.back() != llama_token_eos(GraphRef.LlamaModel)) { + CxtRef.LlamaInputs.push_back(llama_token_eos(GraphRef.LlamaModel)); + } // Check if the input is too long. if (static_cast(CxtRef.LlamaInputs.size()) > MaxTokensListSize) { @@ -369,32 +424,17 @@ Expect getEmbedding(WasiNNEnvironment &Env, return ErrNo::PromptTooLong; } - int NPast = 0; - while (!CxtRef.LlamaInputs.empty()) { - const uint64_t NTokens = (ContextParams.n_batch > CxtRef.LlamaInputs.size()) - ? CxtRef.LlamaInputs.size() - : ContextParams.n_batch; - auto Status = llama_decode(LlamaContext, - llama_batch_get_one(CxtRef.LlamaInputs.data(), - NTokens, NPast, SequenceId)); - if (Status == 1) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: try " - "reducing the size of the batch or increasing the size of context"sv); - return ErrNo::RuntimeError; - } - if (Status < 0) { - spdlog::error("[WASI-NN] GGML backend: failed to llama_decode: internal " - "fatal error. Please open an issue on GitHub"sv); - return ErrNo::RuntimeError; - } - - NPast += NTokens; - CxtRef.LlamaInputs.erase(CxtRef.LlamaInputs.begin(), - CxtRef.LlamaInputs.begin() + NTokens); + // Evaluate input tokens. + ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, + CxtRef.LlamaInputs, NPast); + if (ReturnCode != ErrNo::Success) { + spdlog::error("[WASI-NN] GGML backend: failed to evaluate input tokens."sv); + return ReturnCode; } + const int32_t NEmbd = llama_n_embd(GraphRef.LlamaModel); - const auto *Embeddings = llama_get_embeddings(LlamaContext); + auto *Embeddings = llama_get_embeddings_seq(LlamaContext, SequenceId); + llama_embd_normalize(Embeddings, Embeddings, NEmbd); details::buildOutputEmbedding(CxtRef.LlamaOutputs, NEmbd, Embeddings); @@ -418,48 +458,6 @@ Expect getEmbedding(WasiNNEnvironment &Env, return ErrNo::Success; } -ErrNo evaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, - std::vector Tokens, int &NPast) noexcept { - uint32_t NCtx = llama_n_ctx(LlamaContext); - - // End the inference if the context is full. - if (NPast + static_cast(Tokens.size()) > NCtx) { - if (GraphRef.EnableLog) { - spdlog::info( - "[WASI-NN] GGML backend: the context if full ({} / {} tokens). Please increase your context size."sv, - NPast + static_cast(Tokens.size()), NCtx); - } - return ErrNo::ContextFull; - } - - for (int I = 0; I < static_cast(Tokens.size()); - I += GraphRef.BatchSize) { - int NEval = static_cast(Tokens.size()) - I; - if (NEval > static_cast(GraphRef.BatchSize)) { - NEval = GraphRef.BatchSize; - } - // llama_batch_get_one(*token, n_tokens, position, sequence_id) - // This will return batch for single sequence of tokens starting at - // position. - const llama_seq_id SequenceId = 0; - auto Status = - llama_decode(LlamaContext, - llama_batch_get_one(&Tokens[I], NEval, NPast, SequenceId)); - if (Status == 1) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); - return ErrNo::RuntimeError; - } else if (Status < 0) { - spdlog::error( - "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); - return ErrNo::RuntimeError; - } - NPast += NEval; - } - - return ErrNo::Success; -} - const std::string_view Base64ImageTagPrefix = ""sv; From 5cf7a039a40b84e41bc9ecdcfcb9208c61e90035 Mon Sep 17 00:00:00 2001 From: dm4 Date: Fri, 22 Mar 2024 10:09:27 +0800 Subject: [PATCH 114/218] [WASI-NN] ggml: clear inputs before setting it Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 5309f9aa9b09..f796cdb2e6ce 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -766,6 +766,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, const bool AddBos = llama_should_add_bos_token(GraphRef.LlamaModel); std::string Prompt(reinterpret_cast(Tensor.Tensor.data()), Tensor.Tensor.size()); + CxtRef.LlamaInputs.clear(); if (GraphRef.MMProjModelPath == ""sv) { // Text only prompt. CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); From 2f5655af5044db7a1ad49810c9ae6bdf1d8e555d Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 22 Mar 2024 13:28:46 +0800 Subject: [PATCH 115/218] [Installer] Reset the url_root due to the wasi-nn-ggml plugin with build number workaround (#3299) Signed-off-by: hydai --- utils/install.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utils/install.py b/utils/install.py index 2f376e1f3412..0db114b3baf6 100644 --- a/utils/install.py +++ b/utils/install.py @@ -1155,6 +1155,11 @@ def install_plugins(args, compat): if len(args.plugins) >= 1: for plugin_name in args.plugins: + # Reset the url_root, due to the wasi-nn-ggml plugin with the build number will change the url + url_root = "https://github.com/WasmEdge/WasmEdge/releases/download/" + url_root += ( + "$VERSION$/WasmEdge-plugin-$PLUGIN_NAME$-$VERSION$-$DIST$_$ARCH$.tar.gz" + ) plugin_version_supplied = None plugin_wasi_nn_ggml_bypass_check = False if plugin_name.find(":") != -1: From b2dadd71149dc7221834150091f8d13aad9b0e2e Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Fri, 22 Mar 2024 19:55:38 +0800 Subject: [PATCH 116/218] [Changelog] Update the changelog for the 0.14.0-rc.3 pre-release. (#3301) --- .CurrentChangelog.md | 6 +++--- Changelog.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index 53132071ecb2..eb99237dbce6 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.2 (2024-03-20) +### 0.14.0-rc.3 (2024-03-22) Breaking changes: @@ -73,7 +73,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2334. + * Bump llama.cpp to b2479. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -129,4 +129,4 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 4b8406015080..9877d706e92c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.2 (2024-03-20) +### 0.14.0-rc.3 (2024-03-22) Breaking changes: @@ -73,7 +73,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2334. + * Bump llama.cpp to b2479. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -129,7 +129,7 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.2-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 7ee6d4d8c7e0fae68b58a4064cd6ef7803caf38a Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 25 Mar 2024 15:38:19 +0800 Subject: [PATCH 117/218] [Test] Update for spec test imports. Signed-off-by: YiYing He --- test/api/hostfunc_c.c | 52 ++++++++++++++++++------------------------- test/spec/hostfunc.h | 4 ++-- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/test/api/hostfunc_c.c b/test/api/hostfunc_c.c index 769345bf53ef..d9055b91adcf 100644 --- a/test/api/hostfunc_c.c +++ b/test/api/hostfunc_c.c @@ -19,23 +19,22 @@ #if defined(_MSC_VER) && !defined(__clang__) // MSVC #define MAYBE_UNUSED -#pragma warning( disable : 4100 ) // unreferenced formal parameter +#pragma warning(disable : 4100) // unreferenced formal parameter #else #define MAYBE_UNUSED __attribute__((unused)) #endif -WasmEdge_Result SpecTestPrint(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, - const WasmEdge_Value *In MAYBE_UNUSED, - WasmEdge_Value *Out MAYBE_UNUSED) { +WasmEdge_Result +SpecTestPrint(void *Data MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, + const WasmEdge_Value *In MAYBE_UNUSED, + WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; } WasmEdge_Result SpecTestPrintI32(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, const WasmEdge_Value *In MAYBE_UNUSED, WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; @@ -43,8 +42,7 @@ SpecTestPrintI32(void *Data MAYBE_UNUSED, WasmEdge_Result SpecTestPrintI64(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, const WasmEdge_Value *In MAYBE_UNUSED, WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; @@ -52,8 +50,7 @@ SpecTestPrintI64(void *Data MAYBE_UNUSED, WasmEdge_Result SpecTestPrintF32(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, const WasmEdge_Value *In MAYBE_UNUSED, WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; @@ -61,28 +58,23 @@ SpecTestPrintF32(void *Data MAYBE_UNUSED, WasmEdge_Result SpecTestPrintF64(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, const WasmEdge_Value *In MAYBE_UNUSED, WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; } -WasmEdge_Result -SpecTestPrintI32F32(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, - const WasmEdge_Value *In MAYBE_UNUSED, - WasmEdge_Value *Out MAYBE_UNUSED) { +WasmEdge_Result SpecTestPrintI32F32( + void *Data MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, + const WasmEdge_Value *In MAYBE_UNUSED, WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; } -WasmEdge_Result -SpecTestPrintF64F64(void *Data MAYBE_UNUSED, - const WasmEdge_CallingFrameContext *CallFrameCxt - MAYBE_UNUSED, - const WasmEdge_Value *In MAYBE_UNUSED, - WasmEdge_Value *Out MAYBE_UNUSED) { +WasmEdge_Result SpecTestPrintF64F64( + void *Data MAYBE_UNUSED, + const WasmEdge_CallingFrameContext *CallFrameCxt MAYBE_UNUSED, + const WasmEdge_Value *In MAYBE_UNUSED, WasmEdge_Value *Out MAYBE_UNUSED) { return WasmEdge_Result_Success; } @@ -235,8 +227,8 @@ WasmEdge_ModuleInstanceContext *createSpecTestModule(void) { // Add host global "global_f32": const 666.0 HostGType = WasmEdge_GlobalTypeCreate(WasmEdge_ValTypeGenF32(), WasmEdge_Mutability_Const); - HostGlobal = - WasmEdge_GlobalInstanceCreate(HostGType, WasmEdge_ValueGenF32(666.0)); + HostGlobal = WasmEdge_GlobalInstanceCreate( + HostGType, WasmEdge_ValueGenF32((float)666.6)); WasmEdge_GlobalTypeDelete(HostGType); HostName = WasmEdge_StringCreateByCString("global_f32"); WasmEdge_ModuleInstanceAddGlobal(HostMod, HostName, HostGlobal); @@ -245,8 +237,8 @@ WasmEdge_ModuleInstanceContext *createSpecTestModule(void) { // Add host global "global_f64": const 666.0 HostGType = WasmEdge_GlobalTypeCreate(WasmEdge_ValTypeGenF64(), WasmEdge_Mutability_Const); - HostGlobal = - WasmEdge_GlobalInstanceCreate(HostGType, WasmEdge_ValueGenF64(666.0)); + HostGlobal = WasmEdge_GlobalInstanceCreate( + HostGType, WasmEdge_ValueGenF64((double)666.6)); WasmEdge_GlobalTypeDelete(HostGType); HostName = WasmEdge_StringCreateByCString("global_f64"); WasmEdge_ModuleInstanceAddGlobal(HostMod, HostName, HostGlobal); diff --git a/test/spec/hostfunc.h b/test/spec/hostfunc.h index 2d35abfff11d..7151d3583bbc 100644 --- a/test/spec/hostfunc.h +++ b/test/spec/hostfunc.h @@ -94,11 +94,11 @@ class SpecTestModule : public Runtime::Instance::ModuleInstance { addHostGlobal( "global_f32", std::make_unique( - AST::GlobalType(TypeCode::F32, ValMut::Const), float(666))); + AST::GlobalType(TypeCode::F32, ValMut::Const), float(666.6))); addHostGlobal( "global_f64", std::make_unique( - AST::GlobalType(TypeCode::F64, ValMut::Const), double(666))); + AST::GlobalType(TypeCode::F64, ValMut::Const), double(666.6))); } ~SpecTestModule() noexcept override = default; }; From fb6ee3eb99a9f7788366aa7a0b6737e3f1326f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Tue, 26 Mar 2024 02:54:55 +0800 Subject: [PATCH 118/218] [Misc] fix typo (#3305) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- .CurrentChangelog.md | 2 +- Changelog.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index eb99237dbce6..edfed58592c2 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -42,7 +42,7 @@ Features: * Users can use the `--enable-gc` to enable the proposal in `wasmedge` and `wasmedgec` tools. * Component Model proposal (experimental, loader phase only). * Added the `WasmEdge_Proposal_Component` for the configuration in WasmEdge C API. - * Users can use the `--enable-function-reference` to enable the proposal in `wasmedge` tool. + * Users can use the `--enable-component` to enable the proposal in `wasmedge` tool. * [JIT]: Support LLVM JIT. * [C API]: New C API for supporting the new proposals. * `WasmEdge_ValType` related APIs can help developers to generate or compare value types. diff --git a/Changelog.md b/Changelog.md index 9877d706e92c..301a274a4363 100644 --- a/Changelog.md +++ b/Changelog.md @@ -42,7 +42,7 @@ Features: * Users can use the `--enable-gc` to enable the proposal in `wasmedge` and `wasmedgec` tools. * Component Model proposal (experimental, loader phase only). * Added the `WasmEdge_Proposal_Component` for the configuration in WasmEdge C API. - * Users can use the `--enable-function-reference` to enable the proposal in `wasmedge` tool. + * Users can use the `--enable-component` to enable the proposal in `wasmedge` tool. * [JIT]: Support LLVM JIT. * [C API]: New C API for supporting the new proposals. * `WasmEdge_ValType` related APIs can help developers to generate or compare value types. From aef203acebe543a7552746fa6040ed6df213c417 Mon Sep 17 00:00:00 2001 From: dm4 Date: Tue, 26 Mar 2024 16:17:05 +0800 Subject: [PATCH 119/218] [WASI-NN] ggml: set LLAMA_METAL_EMBED_LIBRARY=ON Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index dd80a29bb7bd..278c91535b25 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -38,6 +38,7 @@ if(BACKEND STREQUAL "ggml") if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL) message(STATUS "WASI-NN GGML LLAMA backend: Enable LLAMA_METAL") set(LLAMA_METAL ON) + set(LLAMA_METAL_EMBED_LIBRARY ON) else() message(STATUS "WASI-NN GGML LLAMA backend: Disable LLAMA_METAL") set(LLAMA_METAL OFF) @@ -174,7 +175,7 @@ if(BACKEND STREQUAL "ggml") TARGET wasmedgePluginWasiNN POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/llama-src/ggml-metal.metal ggml-metal.metal - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/bin/default.metallib default.metallib + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/llama-src/ggml-common.h ggml-common.h ) endif() endif() From 4f93c5e2b5c140b7402f31982fd969dd69a40068 Mon Sep 17 00:00:00 2001 From: dm4 Date: Tue, 26 Mar 2024 16:36:38 +0800 Subject: [PATCH 120/218] [WASI-NN] ggml: bump llama.cpp b2534 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 16 ++++++++-------- thirdparty/ggml/ggml.patch | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 278c91535b25..16b6e8564807 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -10,15 +10,15 @@ if(BACKEND STREQUAL "ggml") set(LLAMA_ACCELERATE OFF) if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_CUBLAS) - message(STATUS "WASI-NN GGML LLAMA backend: Enable LLAMA_CUBLAS") - set(LLAMA_CUBLAS ON) - # We need to set GGML_USE_CUBLAS for clip from llava. - add_compile_definitions(GGML_USE_CUBLAS) - # If CUBLAS is ON, then OpenBLAS should be OFF. + message(STATUS "WASI-NN GGML LLAMA backend: Enable LLAMA_CUDA") + set(LLAMA_CUDA ON) + # We need to set GGML_USE_CUDA for clip from llava. + add_compile_definitions(GGML_USE_CUDA) + # If CUDA is ON, then OpenBLAS should be OFF. set(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_BLAS OFF) else() - message(STATUS "WASI-NN GGML LLAMA backend: Disable LLAMA_CUBLAS") - set(LLAMA_CUBLAS OFF) + message(STATUS "WASI-NN GGML LLAMA backend: Disable LLAMA_CUDA") + set(LLAMA_CUDA OFF) endif() if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_BLAS) @@ -50,7 +50,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2479 + GIT_TAG b2534 PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched GIT_SHALLOW FALSE ) diff --git a/thirdparty/ggml/ggml.patch b/thirdparty/ggml/ggml.patch index d1b369e24a13..af9d0598b52e 100644 --- a/thirdparty/ggml/ggml.patch +++ b/thirdparty/ggml/ggml.patch @@ -20,7 +20,7 @@ index ef9e4ba7..a1b49793 100644 size_t model_size = 0; @@ -937,18 +939,18 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - #ifdef GGML_USE_CUBLAS + #ifdef GGML_USE_CUDA new_clip->backend = ggml_backend_cuda_init(0); - printf("%s: CLIP using CUDA backend\n", __func__); + if (verbosity >= 1) printf("%s: CLIP using CUDA backend\n", __func__); From 34021f1c7e35f01a3ff33bff3cc2bfc138e9fa34 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 31 Jan 2024 15:48:23 +0800 Subject: [PATCH 121/218] [CI] Bump action/checkout from v3 to v4 Signed-off-by: hydai --- .github/workflows/IWYU_scan.yml | 6 +++--- .github/workflows/bindings-java.yml | 6 +++--- .github/workflows/build-extensions.yml | 10 +++++----- .github/workflows/build_for_openwrt.yml | 2 +- .github/workflows/build_for_riscv.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/docker.yml | 4 ++-- .github/workflows/mdbook.yml | 4 ++-- .github/workflows/misc-linters.yml | 2 +- .github/workflows/release.yml | 14 +++++++------- .../workflows/reusable-build-on-alpine-static.yml | 2 +- .github/workflows/reusable-build-on-android.yml | 2 +- .../workflows/reusable-build-on-debian-static.yml | 2 +- .github/workflows/reusable-build-on-fedora.yml | 4 ++-- .github/workflows/reusable-build-on-macos.yml | 2 +- .github/workflows/reusable-build-on-ubuntu.yml | 6 +++--- .../workflows/reusable-build-on-windows-msvc.yml | 2 +- .github/workflows/reusable-build-on-windows.yml | 2 +- .github/workflows/reusable-call-linter.yml | 2 +- .../workflows/reusable-create-source-tarball.yml | 2 +- .github/workflows/static-code-analysis.yml | 2 +- .github/workflows/test-install-script.yml | 2 +- .github/workflows/wasi-testsuite.yml | 4 ++-- 23 files changed, 43 insertions(+), 43 deletions(-) diff --git a/.github/workflows/IWYU_scan.yml b/.github/workflows/IWYU_scan.yml index b026b0b514a6..c068177f4e4f 100644 --- a/.github/workflows/IWYU_scan.yml +++ b/.github/workflows/IWYU_scan.yml @@ -40,7 +40,7 @@ jobs: outputs: version: ${{ steps.prep.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory @@ -76,7 +76,7 @@ jobs: make install cd .. - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory @@ -102,7 +102,7 @@ jobs: needs: get_version steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/bindings-java.yml b/.github/workflows/bindings-java.yml index c4907d2714b7..715e06eb6208 100644 --- a/.github/workflows/bindings-java.yml +++ b/.github/workflows/bindings-java.yml @@ -38,7 +38,7 @@ jobs: image: wasmedge/wasmedge:ubuntu-build-clang steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Ensure git safe directory run: | @@ -95,7 +95,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -159,7 +159,7 @@ jobs: WASMEDGE_PLUGIN_PATH: ${{ github.workspace }}\build\wasmedge\plugins\wasmedge_process LD_LIBRARY_PATH: ${{ github.workspace }}\build\lib\api steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index d9b8aef4af00..5f09be8c62e3 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -55,7 +55,7 @@ jobs: outputs: version: ${{ steps.prep.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory @@ -101,7 +101,7 @@ jobs: container: image: wasmedge/wasmedge:${{ matrix.docker_tag }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory @@ -203,7 +203,7 @@ jobs: # Tests of wasm_bpf also require privileges options: --privileged steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install dependencies @@ -327,7 +327,7 @@ jobs: build_type: Release arch: x86_64 - name: Plugins_MacOS_arm64 - system: MacOS 13 (arm64) + system: MacOS 14 (arm64) host_runner: macos-14 darwin_version: darwin_22 build_type: Release @@ -343,7 +343,7 @@ jobs: output_bins: libwasmedgePluginWasiCrypto.dylib libwasmedgePluginWasiLogging.dylib libwasmedgePluginWasmEdgeTensorflow.dylib libwasmedgePluginWasmEdgeTensorflowLite.dylib libwasmedgePluginWasmEdgeImage.dylib libwasmedgePluginWasmEdgeOpenCVMini.dylib libwasmedgePluginWasmEdgeFFmpeg.dylib needs: [ get_version ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and install dependencies diff --git a/.github/workflows/build_for_openwrt.yml b/.github/workflows/build_for_openwrt.yml index 832f06d753f3..5c370f2f57c2 100644 --- a/.github/workflows/build_for_openwrt.yml +++ b/.github/workflows/build_for_openwrt.yml @@ -44,7 +44,7 @@ jobs: needs: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/build_for_riscv.yml b/.github/workflows/build_for_riscv.yml index ab069318ce1d..8e32531ebe1e 100644 --- a/.github/workflows/build_for_riscv.yml +++ b/.github/workflows/build_for_riscv.yml @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest needs: lint steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8c3f00a91b96..3e23b8ef0f52 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -69,7 +69,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Ensure git safe directory run: | git config --global --add safe.directory $(pwd) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d1b3aa9f715e..1426d4b3ec92 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -59,7 +59,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -204,7 +204,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index 990541d0ed8c..e2dd640b8125 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory @@ -49,7 +49,7 @@ jobs: && (needs.lint-markdown.result == 'success' || needs.lint-markdown.result == 'skipped') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Ensure git safe directory run: | git config --global --add safe.directory $(pwd) diff --git a/.github/workflows/misc-linters.yml b/.github/workflows/misc-linters.yml index a45ce285eb12..8c07c3276b8a 100644 --- a/.github/workflows/misc-linters.yml +++ b/.github/workflows/misc-linters.yml @@ -17,7 +17,7 @@ jobs: name: misc linters runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Ensure git safe directory run: | git config --global --add safe.directory $(pwd) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 31102f8e4270..8ded2be64f7e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Ensure git safe directory run: | git config --global --add safe.directory $(pwd) @@ -135,7 +135,7 @@ jobs: image: wasmedge/wasmedge:ubuntu-20.04-build-clang steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Grant the safe directory for git @@ -214,7 +214,7 @@ jobs: image: wasmedge/wasmedge:ubuntu-build-clang-plugins-deps steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Grant the safe directory for git @@ -474,7 +474,7 @@ jobs: darwin_version: darwin_21 arch: x86_64 - name: Plugins_MacOS_arm64 - system: MacOS 13 (arm64) + system: MacOS 14 (arm64) host_runner: macos-14 darwin_version: darwin_22 arch: arm64 @@ -488,7 +488,7 @@ jobs: needs: create_release steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Grant the safe directory for git @@ -630,7 +630,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Prepare tarball uses: actions/download-artifact@v3 with: @@ -686,7 +686,7 @@ jobs: needs: create_release steps: - name: checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Grant the safe directory for git run: | diff --git a/.github/workflows/reusable-build-on-alpine-static.yml b/.github/workflows/reusable-build-on-alpine-static.yml index 17b0214cd963..4a7e0cd4d063 100644 --- a/.github/workflows/reusable-build-on-alpine-static.yml +++ b/.github/workflows/reusable-build-on-alpine-static.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-build-on-android.yml b/.github/workflows/reusable-build-on-android.yml index 2c5544385cbb..94d38950817b 100644 --- a/.github/workflows/reusable-build-on-android.yml +++ b/.github/workflows/reusable-build-on-android.yml @@ -23,7 +23,7 @@ jobs: container: image: wasmedge/wasmedge:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install dependency diff --git a/.github/workflows/reusable-build-on-debian-static.yml b/.github/workflows/reusable-build-on-debian-static.yml index 88ce4b9e9230..afd4f4c4b63a 100644 --- a/.github/workflows/reusable-build-on-debian-static.yml +++ b/.github/workflows/reusable-build-on-debian-static.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-build-on-fedora.yml b/.github/workflows/reusable-build-on-fedora.yml index b1b66bc1f219..319543505033 100644 --- a/.github/workflows/reusable-build-on-fedora.yml +++ b/.github/workflows/reusable-build-on-fedora.yml @@ -28,7 +28,7 @@ jobs: dnf update -y dnf install -y cmake ninja-build llvm llvm-devel lld-devel clang git file rpm-build dpkg-dev spdlog-devel \ pkgconf-pkg-config protobuf-c-compiler grpc-cpp grpc-plugins grpc-devel - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Grant the safe directory for git @@ -52,5 +52,5 @@ jobs: if: ${{ !inputs.release }} uses: actions/upload-artifact@v3 with: - name: WasmEdge-${{ inputs.version }}-fedora35.tar.gz + name: WasmEdge-${{ inputs.version }}-fedora.tar.gz path: build/WasmEdge-${{ inputs.version }}-Linux.tar.gz diff --git a/.github/workflows/reusable-build-on-macos.yml b/.github/workflows/reusable-build-on-macos.yml index 4ddba4d9e119..592bd61d3364 100644 --- a/.github/workflows/reusable-build-on-macos.yml +++ b/.github/workflows/reusable-build-on-macos.yml @@ -29,7 +29,7 @@ jobs: BUILD_TESTS: ON BUILD_TYPE: Debug steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-build-on-ubuntu.yml b/.github/workflows/reusable-build-on-ubuntu.yml index aeee6beeb88a..a217256e62ec 100644 --- a/.github/workflows/reusable-build-on-ubuntu.yml +++ b/.github/workflows/reusable-build-on-ubuntu.yml @@ -11,10 +11,10 @@ on: required: true release: type: boolean - + permissions: contents: read - + jobs: build_on_ubuntu: permissions: @@ -39,7 +39,7 @@ jobs: run: | apt-get update apt-get install -y pkg-config - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-build-on-windows-msvc.yml b/.github/workflows/reusable-build-on-windows-msvc.yml index 41d09b8b7c92..5b7bd4e1fdfa 100644 --- a/.github/workflows/reusable-build-on-windows-msvc.yml +++ b/.github/workflows/reusable-build-on-windows-msvc.yml @@ -21,7 +21,7 @@ jobs: env: build_tests: ON steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-build-on-windows.yml b/.github/workflows/reusable-build-on-windows.yml index 35f47afb8114..b166e48bcddb 100644 --- a/.github/workflows/reusable-build-on-windows.yml +++ b/.github/workflows/reusable-build-on-windows.yml @@ -18,7 +18,7 @@ jobs: env: build_tests: ON steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-call-linter.yml b/.github/workflows/reusable-call-linter.yml index 2eb54de5b0ea..02cb6c730169 100644 --- a/.github/workflows/reusable-call-linter.yml +++ b/.github/workflows/reusable-call-linter.yml @@ -10,7 +10,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/reusable-create-source-tarball.yml b/.github/workflows/reusable-create-source-tarball.yml index ed8c26d44fdb..28e47546cd2f 100644 --- a/.github/workflows/reusable-create-source-tarball.yml +++ b/.github/workflows/reusable-create-source-tarball.yml @@ -19,7 +19,7 @@ jobs: name: Create source tarball runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Ensure git safe directory diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml index d4fd3039a811..7772a2d90b66 100644 --- a/.github/workflows/static-code-analysis.yml +++ b/.github/workflows/static-code-analysis.yml @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Ensure git safe directory run: | git config --global --add safe.directory $(pwd) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 8641f3d6329a..c97fcb5946fe 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -171,7 +171,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/wasi-testsuite.yml b/.github/workflows/wasi-testsuite.yml index b846d35ed55a..b02ec72e26fe 100644 --- a/.github/workflows/wasi-testsuite.yml +++ b/.github/workflows/wasi-testsuite.yml @@ -35,7 +35,7 @@ jobs: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: WasmEdge - name: Ensure git safe directory @@ -64,7 +64,7 @@ jobs: echo "$GITHUB_WORKSPACE/WasmEdge/build/tools/wasmedge" >> $GITHUB_PATH - name: Checkout wasi-testsuite - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: WebAssembly/wasi-testsuite ref: prod/testsuite-base From 25ec384fb1a5e3cdca9db064a69d487b7681726e Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 31 Jan 2024 16:13:47 +0800 Subject: [PATCH 122/218] [CI] Force rm to avoid 'No such file or directory' error Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index c97fcb5946fe..397ac30b3b9a 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -186,6 +186,12 @@ jobs: rm -f ~/.bashrc bash utils/install.sh -D if ls -a ~ | grep .bashrc; then echo "Fail: Bashrc found" && exit 1; else echo "Pass: Bashrc not found"; fi; + - name: Check for bashrc generation + if: ${{ matrix.name == 'MacOS-arm64' }} + run: | + rm -rf ~/.zshenv + bash utils/install.sh -D + if ls -a ~ | grep .zshenv; then echo echo "Pass: zshenv found"; else "Fail: zshenv not found" && exit 1; fi; - name: Uninstall WasmEdge run: | bash utils/uninstall.sh -q -V From ff0deb20910274bd16d11636ce759f69af3579d7 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 31 Jan 2024 16:29:46 +0800 Subject: [PATCH 123/218] [CI] Install zsh on macos-14 Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 5 +++++ .github/workflows/test-python-install-script.yml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 397ac30b3b9a..0bd1d1d762ca 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -175,6 +175,11 @@ jobs: with: fetch-depth: 0 + - name: Install zsh + run: | + eval $(/opt/homebrew/bin/brew shellenv) + ${{ matrix.package_manager }} install zsh + - name: Install WasmEdge latest release run: | bash utils/install.sh -D diff --git a/.github/workflows/test-python-install-script.yml b/.github/workflows/test-python-install-script.yml index 2a4116bc9446..383d8d9d56cd 100644 --- a/.github/workflows/test-python-install-script.yml +++ b/.github/workflows/test-python-install-script.yml @@ -361,7 +361,7 @@ jobs: shell: zsh {0} run: | eval $(/opt/homebrew/bin/brew shellenv) - ${{ matrix.package_manager }} install python + ${{ matrix.package_manager }} install python zsh - name: Install WasmEdge latest release shell: zsh {0} From 0fb3e7bf0c0dc34025fd44e1a2c0c6a9f93fa5d9 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 15 Mar 2024 14:18:22 +0800 Subject: [PATCH 124/218] [CI] Remove job that was moved to reusable workflows Signed-off-by: Yi Huang --- .github/workflows/release.yml | 136 +--------------------------------- 1 file changed, 2 insertions(+), 134 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8ded2be64f7e..3652177d76c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -323,8 +323,8 @@ jobs: mv plugin_wasmedge_ffmpeg.tar.gz WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-ubuntu20.04_x86_64.tar.gz gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-ubuntu20.04_x86_64.tar.gz --clobber - build_and_upload_wasinn_manylinux: - name: Build and upload WASI-NN on manylinux + build_and_upload_plugins_manylinux: + name: Build and upload plugins on manylinux needs: create_release uses: ./.github/workflows/reusable-build-extensions.yml with: @@ -332,138 +332,6 @@ jobs: release: true secrets: inherit - build_and_upload_plugin_manylinux: - strategy: - matrix: - include: - - name: Plugins_x86_64 - host_runner: ubuntu-latest - docker_tag: manylinux2014_x86_64-plugins-deps - asset_tag: manylinux2014_x86_64 - - name: Plugins_aarch64 - host_runner: linux-arm64-v2 - docker_tag: manylinux2014_aarch64-plugins-deps - asset_tag: manylinux2014_aarch64 - name: Build and upload plugins on ${{ matrix.docker_tag }} - runs-on: ${{ matrix.host_runner }} - env: - output_prefix: build/plugins - build_options_all_platforms: -DWASMEDGE_PLUGIN_WASI_CRYPTO=ON -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DWASMEDGE_PLUGIN_PROCESS=ON -DWASMEDGE_PLUGIN_TENSORFLOW=ON -DWASMEDGE_PLUGIN_TENSORFLOWLITE=ON -DWASMEDGE_PLUGIN_IMAGE=ON -DWASMEDGE_PLUGIN_OPENCVMINI=ON -DWASMEDGE_PLUGIN_FFMPEG=ON - build_options_manylinux2014_x86_64: -DWASMEDGE_PLUGIN_WASM_BPF=ON -DWASMEDGE_PLUGIN_WASM_BPF_BUILD_LIBBPF_WITH_PKG_CONF=OFF - build_options_manylinux2014_aarch64: - tar_names_all_platforms: wasi_crypto wasi_logging wasmedge_process wasmedge_tensorflow wasmedge_tensorflowlite wasmedge_image wasmedge_opencvmini wasmedge_ffmpeg - tar_names_manylinux2014_x86_64: wasm_bpf - tar_names_manylinux2014_aarch64: - output_bins_all_platforms: libwasmedgePluginWasiCrypto.so libwasmedgePluginWasiLogging.so libwasmedgePluginWasmEdgeProcess.so libwasmedgePluginWasmEdgeTensorflow.so libwasmedgePluginWasmEdgeTensorflowLite.so libwasmedgePluginWasmEdgeImage.so libwasmedgePluginWasmEdgeOpenCVMini.so libwasmedgePluginWasmEdgeFFmpeg.so - output_bins_manylinux2014_x86_64: libwasmedgePluginWasmBpf.so - output_bins_manylinux2014_aarch64: - needs: create_release - container: - image: wasmedge/wasmedge:${{ matrix.docker_tag }} - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Grant the safe directory for git - run: | - git config --global --add safe.directory $(pwd) - - name: Build and install dependencies - run: | - yum update -y - yum install -y zlib-devel zlib-static cmake curl wget unzip - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y - source "$HOME/.cargo/env" - bash ./utils/wasi-crypto/build-openssl.sh - bash utils/ffmpeg/install-ffmpeg-v6.0.sh - - name: Build plugins - shell: bash - run: | - source "$HOME/.cargo/env" - outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) - export PKG_CONFIG_PATH=$(pwd)/FFmpeg-n6.0/output/lib/pkgconfig - cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF ${build_options_all_platforms} ${build_options_${{ matrix.asset_tag }}} -DOPENSSL_ROOT_DIR=$(pwd)/openssl-1.1.1n/openssl - for (( i=0; i<${#outbin_array[@]}; i++ )); - do - echo "Building ${outbin_array[$i]} :" - outtarget=${outbin_array[$i]} - outtarget=${outtarget%.*} - outtarget=${outtarget#lib} - cmake --build build --target ${outtarget} - done - - name: Prepare the plugins tar.gz package - shell: bash - run: | - export LD_LIBRARY_PATH=$(pwd)/FFmpeg-n6.0/output/lib:$LD_LIBRARY_PATH - plugin_array=(${tar_names_all_platforms} ${tar_names_${{ matrix.asset_tag }}}) - outbin_array=(${output_bins_all_platforms} ${output_bins_${{ matrix.asset_tag }}}) - for (( i=0; i<${#plugin_array[@]}; i++ )); - do - echo "Copying ${plugin_array[$i]} :" - cp ${output_prefix}/${plugin_array[$i]}/${outbin_array[$i]} ${outbin_array[$i]} - tar -zcvf plugin_${plugin_array[$i]}.tar.gz ${outbin_array[$i]} - done - - name: Install gh on manylinux - run: | - type -p yum-config-manager >/dev/null || sudo yum install yum-utils - yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo - yum install -y gh - - name: Upload wasi_crypto plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasi_crypto.tar.gz WasmEdge-plugin-wasi_crypto-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasi_crypto-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasi_logging plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasi_logging.tar.gz WasmEdge-plugin-wasi_logging-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasi_logging-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasmedge_process plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_process.tar.gz WasmEdge-plugin-wasmedge_process-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_process-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasmedge_tensorflow plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_tensorflow.tar.gz WasmEdge-plugin-wasmedge_tensorflow-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_tensorflow-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasmedge_tensorflowlite plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_tensorflowlite.tar.gz WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_tensorflowlite-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasmedge_image plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_image.tar.gz WasmEdge-plugin-wasmedge_image-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_image-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasm_bpf plugin tar.gz package - if: contains(matrix.docker_tag, 'manylinux2014_x86_64') - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasm_bpf.tar.gz WasmEdge-plugin-wasm_bpf-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasm_bpf-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasmedge_opencvmini plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_opencvmini.tar.gz WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_opencvmini-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - - name: Upload wasmedge_ffmpeg plugin tar.gz package - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mv plugin_wasmedge_ffmpeg.tar.gz WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz - gh release upload ${{ needs.create_release.outputs.version }} WasmEdge-plugin-wasmedge_ffmpeg-${{ needs.create_release.outputs.version }}-${{ matrix.asset_tag }}.tar.gz --clobber - build_and_upload_plugin_macos: strategy: matrix: From 7fdbd471fa8b6cb629ff61a96e6ac4434b6463c0 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Wed, 27 Mar 2024 12:43:22 +0800 Subject: [PATCH 125/218] [WASI-NN] Support windows build * Rewrite shellscripts to cmake * Add compile flags for llama * Fix compile warnings Signed-off-by: Shen-Ta Hsieh --- cmake/WASINNDeps.cmake | 70 +++++----- include/plugin/plugin.h | 1 + plugins/wasi_nn/CMakeLists.txt | 15 ++- plugins/wasi_nn/ggml.cpp | 87 ++++++------ plugins/wasi_nn/wasinnenv.cpp | 4 + test/plugins/wasi_nn/CMakeLists.txt | 107 +++++++-------- test/plugins/wasi_nn/wasi_nn.cpp | 142 +++++++++++++------- utils/wasi-nn/download-ggml-fixtures.sh | 17 --- utils/wasi-nn/download-openvino-fixtures.sh | 25 ---- utils/wasi-nn/download-pytorch-fixtures.sh | 19 --- utils/wasi-nn/download-tflite-fixtures.sh | 19 --- 11 files changed, 245 insertions(+), 261 deletions(-) delete mode 100755 utils/wasi-nn/download-ggml-fixtures.sh delete mode 100755 utils/wasi-nn/download-openvino-fixtures.sh delete mode 100755 utils/wasi-nn/download-pytorch-fixtures.sh delete mode 100755 utils/wasi-nn/download-tflite-fixtures.sh diff --git a/cmake/WASINNDeps.cmake b/cmake/WASINNDeps.cmake index 43f235cf5b9a..b0de24c32b25 100644 --- a/cmake/WASINNDeps.cmake +++ b/cmake/WASINNDeps.cmake @@ -7,41 +7,43 @@ if(NOT WASMEDGE_DEPS_VERSION) set(WASMEDGE_DEPS_VERSION "TF-2.12.0-CC") endif() -# Set the system name and hash of TF and TFLite releases. -if(ANDROID) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "android_aarch64") - set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "2d7dcd7381479d9ffc0968ea66e24a5207b404c7f2ccbdddec6f2a4d6f9813f2") - elseif() - message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") - endif() -elseif(APPLE) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") - set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "darwin_x86_64") - set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "60da72a093cf65d733ca2cb9f331356a1637acfe1645050809bd0cf056b1520f") - set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "04b58f4b97220633a8e299a63aba73d9a1f228904081e7d5f18e78d1e38d5f00") - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") - set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "darwin_arm64") - set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "2ede6d96c7563eb826331469d7d0a1f51c9b1ca311f4398d841f679a5b96705a") - set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "cb4562a80ac2067bdabe2464b80e129b9d8ddc6d97ad1a2d7215e06a1e1e8cda") - else() - message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") - endif() -elseif(UNIX) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") - set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "manylinux2014_x86_64") - set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "266465acd642a9d2d80e56c93aa0a255597bfb3034a826bb2225e61f2bebe2e2") - set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "110a06bcda1fdc3e744b1728157b66981e235de130f3a34755684e6adcf08341") - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "manylinux2014_aarch64") - set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "9c15a3aeeda614c9677fe8980d8fa2cd9600072c4701b8a8189225855b9ca1a8") - set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "672b81d3f4b5a6c25dc9bbc3b8c6ac1c0357cfab8105b2a85b8bb8c0b59afcb4") +function(wasmedge_setup_tf_variables) + # Set the system name and hash of TF and TFLite releases. + if(ANDROID) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "android_aarch64" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "2d7dcd7381479d9ffc0968ea66e24a5207b404c7f2ccbdddec6f2a4d6f9813f2" PARENT_SCOPE) + elseif() + message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") + endif() + elseif(APPLE) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") + set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "darwin_x86_64" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "60da72a093cf65d733ca2cb9f331356a1637acfe1645050809bd0cf056b1520f" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "04b58f4b97220633a8e299a63aba73d9a1f228904081e7d5f18e78d1e38d5f00" PARENT_SCOPE) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "darwin_arm64" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "2ede6d96c7563eb826331469d7d0a1f51c9b1ca311f4398d841f679a5b96705a" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "cb4562a80ac2067bdabe2464b80e129b9d8ddc6d97ad1a2d7215e06a1e1e8cda" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") + endif() + elseif(UNIX) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") + set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "manylinux2014_x86_64" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "266465acd642a9d2d80e56c93aa0a255597bfb3034a826bb2225e61f2bebe2e2" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "110a06bcda1fdc3e744b1728157b66981e235de130f3a34755684e6adcf08341" PARENT_SCOPE) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(WASMEDGE_TENSORFLOW_SYSTEM_NAME "manylinux2014_aarch64" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TF_HASH "9c15a3aeeda614c9677fe8980d8fa2cd9600072c4701b8a8189225855b9ca1a8" PARENT_SCOPE) + set(WASMEDGE_TENSORFLOW_DEPS_TFLITE_HASH "672b81d3f4b5a6c25dc9bbc3b8c6ac1c0357cfab8105b2a85b8bb8c0b59afcb4" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") + endif() else() - message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") + message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}") endif() -else() - message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}") -endif() +endfunction() function(wasmedge_setup_tf_headers) FetchContent_Declare( @@ -60,6 +62,7 @@ function(wasmedge_setup_tf_headers) endfunction() function(wasmedge_setup_tflite_lib) + wasmedge_setup_tf_variables() # Fetch Tensorflow-lite library. FetchContent_Declare( wasmedge_tensorflow_lib_tflite @@ -96,6 +99,7 @@ function(wasmedge_setup_tflite_lib) endfunction() function(wasmedge_setup_tf_lib) + wasmedge_setup_tf_variables() # Fetch Tensorflow-lite library. FetchContent_Declare( wasmedge_tensorflow_lib_tf diff --git a/include/plugin/plugin.h b/include/plugin/plugin.h index 92f08bc0d138..d8f432e5a1ad 100644 --- a/include/plugin/plugin.h +++ b/include/plugin/plugin.h @@ -30,6 +30,7 @@ #endif #define EXPORT_GET_DESCRIPTOR(Descriptor) \ + extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor(); \ extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor() { \ return &Descriptor; \ } diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 16b6e8564807..77b977891e9c 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -46,12 +46,25 @@ if(BACKEND STREQUAL "ggml") # setup llama.cpp message(STATUS "Downloading llama.cpp source") + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options( + -Wno-cast-align + -Wno-cast-qual + -Wno-disabled-macro-expansion + -Wno-exceptions + -Wno-float-conversion + -Wno-implicit-fallthrough + -Wno-implicit-float-conversion + -Wno-unused-macros + ) + endif() include(FetchContent) FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git GIT_TAG b2534 - PATCH_COMMAND test -f ggml.patched || git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch && ${CMAKE_COMMAND} -E touch ggml.patched + PATCH_COMMAND git checkout . + COMMAND git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index f796cdb2e6ce..43afec1df6a9 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -19,7 +19,7 @@ namespace WasmEdge::Host::WASINN::GGML { #ifdef WASMEDGE_PLUGIN_WASI_NN_BACKEND_GGML -namespace details { +namespace { Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, bool *IsModelUpdated = nullptr) noexcept { simdjson::dom::parser Parser; @@ -264,10 +264,11 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, } Expect setupGPTParam(Graph &GraphRef, gpt_params &GPTParams) { - GPTParams.sparams.temp = GraphRef.Temp; - GPTParams.sparams.top_p = GraphRef.TopP; - GPTParams.sparams.penalty_repeat = GraphRef.RepeatPenalty; - GPTParams.sparams.penalty_present = GraphRef.PresencePenalty; + GPTParams.sparams.temp = static_cast(GraphRef.Temp); + GPTParams.sparams.top_p = static_cast(GraphRef.TopP); + GPTParams.sparams.penalty_repeat = static_cast(GraphRef.RepeatPenalty); + GPTParams.sparams.penalty_present = + static_cast(GraphRef.PresencePenalty); return ErrNo::Success; } @@ -425,8 +426,8 @@ Expect getEmbedding(WasiNNEnvironment &Env, } // Evaluate input tokens. - ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, - CxtRef.LlamaInputs, NPast); + ReturnCode = evaluateTokens(GraphRef, LlamaContext, + std::move(CxtRef.LlamaInputs), NPast); if (ReturnCode != ErrNo::Success) { spdlog::error("[WASI-NN] GGML backend: failed to evaluate input tokens."sv); return ReturnCode; @@ -436,7 +437,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, auto *Embeddings = llama_get_embeddings_seq(LlamaContext, SequenceId); llama_embd_normalize(Embeddings, Embeddings, NEmbd); - details::buildOutputEmbedding(CxtRef.LlamaOutputs, NEmbd, Embeddings); + buildOutputEmbedding(CxtRef.LlamaOutputs, NEmbd, Embeddings); if (GraphRef.EnableDebugLog) { spdlog::info( @@ -463,7 +464,7 @@ const std::string_view Base64ImageBytesPrefix = ";base64,"sv; const std::string_view Base64ImageTagSuffix = "\">"sv; const std::string_view PromptImagePlaceholder = ""sv; -bool containsBase64Image(Graph &GraphRef, std::string Prompt) noexcept { +bool containsBase64Image(Graph &GraphRef, std::string_view Prompt) noexcept { // Check if the prompt contains a base64 image. // Follow this link for the supported image formats: // https://github.com/ggerganov/llama.cpp/blob/master/common/stb_image.h @@ -490,7 +491,7 @@ bool containsBase64Image(Graph &GraphRef, std::string Prompt) noexcept { struct llava_image_embed * loadBase64ImageFromPrompt(Graph &GraphRef, clip_ctx *ClipContext, - std::string Prompt) noexcept { + std::string_view Prompt) noexcept { // Load the base64 image from the prompt. // Follow this link for the supported image formats: // https://github.com/ggerganov/llama.cpp/blob/master/common/stb_image.h @@ -559,7 +560,7 @@ ErrNo replaceBase64ImagePlaceholderInPrompt(std::string &Prompt) noexcept { return ErrNo::Success; } -} // namespace details +} // namespace Expect load(WasiNNEnvironment &Env, Span> Builders, [[maybe_unused]] Device Device, uint32_t &GraphId) noexcept { @@ -595,7 +596,7 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, const std::string Metadata(reinterpret_cast(Builders[1].data()), Builders[1].size()); // Ignore context or model updates when initializing the graph. - auto Res = details::parseMetadata(GraphRef, Metadata); + auto Res = parseMetadata(GraphRef, Metadata); if (Res != ErrNo::Success) { spdlog::error("[WASI-NN] GGML backend: Failed to parse metadata."sv); Env.NNGraph.pop_back(); @@ -709,8 +710,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, } const std::string Metadata(reinterpret_cast(Tensor.Tensor.data()), Tensor.Tensor.size()); - auto Res = - details::parseMetadata(GraphRef, Metadata, &IsModelParamsUpdated); + auto Res = parseMetadata(GraphRef, Metadata, &IsModelParamsUpdated); if (Res != ErrNo::Success) { spdlog::error("[WASI-NN] GGML backend: Failed to parse metadata."sv); @@ -752,7 +752,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, spdlog::info("[WASI-NN][Debug] GGML backend: init llama context"sv); } llama_context_params ContextParams = llama_context_default_params(); - details::setupContextParam(GraphRef, ContextParams); + setupContextParam(GraphRef, ContextParams); auto LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); if (GraphRef.EnableDebugLog) { @@ -774,7 +774,7 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, // Handle llava format prompt. // Check if the prompt contains a base64 image. - bool ContainsBase64Image = details::containsBase64Image(GraphRef, Prompt); + bool ContainsBase64Image = containsBase64Image(GraphRef, Prompt); if (GraphRef.ImagePath == ""sv && ContainsBase64Image == false) { spdlog::error( "[WASI-NN] GGML backend: Error: when using llava model, " @@ -804,9 +804,9 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, if (ContainsBase64Image) { // Load the base64 image from the prompt. CxtRef.LlavaImageEmbd = - details::loadBase64ImageFromPrompt(GraphRef, ClipContext, Prompt); + loadBase64ImageFromPrompt(GraphRef, ClipContext, Prompt); // Replace the base64 image in the prompt with a placeholder. - auto Res = details::replaceBase64ImagePlaceholderInPrompt(Prompt); + auto Res = replaceBase64ImagePlaceholderInPrompt(Prompt); if (Res != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: Error: unable to replace the base64 image in the prompt."sv); @@ -826,15 +826,15 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, } // We split prompt by as placeholder and save the position. - auto PlaceholderPosition = Prompt.find(details::PromptImagePlaceholder); + auto PlaceholderPosition = Prompt.find(PromptImagePlaceholder); if (PlaceholderPosition == std::string::npos) { spdlog::error( "[WASI-NN] GGML backend: Error: unable to find the placeholder in the llava prompt."sv); return ErrNo::InvalidArgument; } std::string PromptBeforeImage = Prompt.substr(0, PlaceholderPosition); - std::string PromptAfterImage = Prompt.substr( - PlaceholderPosition + details::PromptImagePlaceholder.length()); + std::string PromptAfterImage = + Prompt.substr(PlaceholderPosition + PromptImagePlaceholder.length()); std::vector EmbdInputBeforeImage = llama_tokenize(LlamaContext, PromptBeforeImage, AddBos, true); std::vector EmbdInputAfterImage = @@ -878,7 +878,7 @@ Expect getOutput(WasiNNEnvironment &Env, uint32_t ContextId, // Index 1 is for the metadata of the outputs. if (Index == 1) { std::string Metadata; - auto Res = details::buildOutputMetadata(CxtRef, Metadata); + auto Res = buildOutputMetadata(CxtRef, Metadata); if (Res != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: Failed to build output metadata."sv); @@ -903,7 +903,7 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { } if (GraphRef.Embedding) { - return details::getEmbedding(Env, ContextId); + return getEmbedding(Env, ContextId); } if (CxtRef.LlamaInputs.size() == 0) { @@ -926,8 +926,8 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // Initialize the llama context. gpt_params GPTParams; llama_context_params ContextParams = llama_context_default_params(); - details::setupGPTParam(GraphRef, GPTParams); - details::setupContextParam(GraphRef, ContextParams); + setupGPTParam(GraphRef, GPTParams); + setupContextParam(GraphRef, ContextParams); auto LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); struct llama_sampling_context *CtxSampling = @@ -955,8 +955,8 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // Evaluate input tokens. if (CxtRef.LlavaImageEmbd == nullptr) { // Text only prompt. - ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, - CxtRef.LlamaInputs, NPast); + ReturnCode = evaluateTokens(GraphRef, LlamaContext, + std::move(CxtRef.LlamaInputs), NPast); if (ReturnCode != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: failed to evaluate input tokens."sv); @@ -970,8 +970,8 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { std::vector EmbdInputAfterImage(CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition, CxtRef.LlamaInputs.end()); - ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, - EmbdInputBeforeImage, NPast); + ReturnCode = evaluateTokens(GraphRef, LlamaContext, + std::move(EmbdInputBeforeImage), NPast); if (ReturnCode != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: failed to evaluate input tokens before image."sv); @@ -984,8 +984,8 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { "[WASI-NN] GGML backend: failed to evaluate embed image tokens."sv); return ErrNo::RuntimeError; } - ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, - EmbdInputAfterImage, NPast); + ReturnCode = evaluateTokens(GraphRef, LlamaContext, + std::move(EmbdInputAfterImage), NPast); if (ReturnCode != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: failed to evaluate input tokens after image."sv); @@ -1027,7 +1027,7 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { break; } // Evaluate the output token. - ReturnCode = details::evaluateTokens(GraphRef, LlamaContext, {Id}, NPast); + ReturnCode = evaluateTokens(GraphRef, LlamaContext, {Id}, NPast); if (ReturnCode != ErrNo::Success) { break; } @@ -1065,7 +1065,7 @@ Expect getOutputSingle(WasiNNEnvironment &Env, uint32_t ContextId, // Index 1 is for the metadata of the outputs. if (Index == 1) { std::string Metadata; - auto Res = details::buildOutputMetadata(CxtRef, Metadata); + auto Res = buildOutputMetadata(CxtRef, Metadata); if (Res != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: Failed to build output metadata."sv); @@ -1113,8 +1113,8 @@ Expect computeSingle(WasiNNEnvironment &Env, // Initialize the llama context. gpt_params GPTParams; llama_context_params ContextParams = llama_context_default_params(); - details::setupGPTParam(GraphRef, GPTParams); - details::setupContextParam(GraphRef, ContextParams); + setupGPTParam(GraphRef, GPTParams); + setupContextParam(GraphRef, ContextParams); CxtRef.LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); CxtRef.LlamaSampling = llama_sampling_init(GPTParams.sparams); @@ -1140,8 +1140,9 @@ Expect computeSingle(WasiNNEnvironment &Env, // Evaluate input tokens. if (CxtRef.LlavaImageEmbd == nullptr) { // Text only prompt. - ReturnCode = details::evaluateTokens( - GraphRef, CxtRef.LlamaContext, CxtRef.LlamaInputs, CxtRef.LlamaNPast); + ReturnCode = + evaluateTokens(GraphRef, CxtRef.LlamaContext, + std::move(CxtRef.LlamaInputs), CxtRef.LlamaNPast); if (ReturnCode != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: failed to evaluate input tokens."sv); @@ -1156,8 +1157,8 @@ Expect computeSingle(WasiNNEnvironment &Env, CxtRef.LlamaInputs.begin() + CxtRef.LlavaImagePosition, CxtRef.LlamaInputs.end()); ReturnCode = - details::evaluateTokens(GraphRef, CxtRef.LlamaContext, - EmbdInputBeforeImage, CxtRef.LlamaNPast); + evaluateTokens(GraphRef, CxtRef.LlamaContext, + std::move(EmbdInputBeforeImage), CxtRef.LlamaNPast); if (ReturnCode != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: failed to evaluate input tokens before image."sv); @@ -1172,8 +1173,8 @@ Expect computeSingle(WasiNNEnvironment &Env, return ErrNo::RuntimeError; } ReturnCode = - details::evaluateTokens(GraphRef, CxtRef.LlamaContext, - EmbdInputAfterImage, CxtRef.LlamaNPast); + evaluateTokens(GraphRef, CxtRef.LlamaContext, + std::move(EmbdInputAfterImage), CxtRef.LlamaNPast); if (ReturnCode != ErrNo::Success) { spdlog::error( "[WASI-NN] GGML backend: failed to evaluate input tokens after image."sv); @@ -1205,8 +1206,8 @@ Expect computeSingle(WasiNNEnvironment &Env, } // Evaluate the output token if not EOS. if (ReturnCode != ErrNo::EndOfSequence) { - ReturnCode = details::evaluateTokens(GraphRef, CxtRef.LlamaContext, {Id}, - CxtRef.LlamaNPast); + ReturnCode = + evaluateTokens(GraphRef, CxtRef.LlamaContext, {Id}, CxtRef.LlamaNPast); } if (GraphRef.EnableDebugLog) { spdlog::info( diff --git a/plugins/wasi_nn/wasinnenv.cpp b/plugins/wasi_nn/wasinnenv.cpp index 6a4038a10f0a..83090a63c553 100644 --- a/plugins/wasi_nn/wasinnenv.cpp +++ b/plugins/wasi_nn/wasinnenv.cpp @@ -15,6 +15,7 @@ namespace Host { namespace WASINN { +namespace { Runtime::Instance::ModuleInstance * create(const Plugin::PluginModule::ModuleDescriptor *) noexcept { return new WasiNNModule; @@ -48,6 +49,7 @@ bool load(const std::filesystem::path &Path, std::vector &Data) { File.close(); return true; } +} // namespace WasiNNEnvironment::WasiNNEnvironment() noexcept { #ifdef WASMEDGE_BUILD_WASI_NN_RPC @@ -129,6 +131,7 @@ PO::Option WasiNNEnvironment::NNRPCURI( PO::MetaVar("URI"sv), PO::DefaultValue(std::string(""))); #endif +namespace { void addOptions(const Plugin::Plugin::PluginDescriptor *, PO::ArgumentParser &Parser) noexcept { Parser.add_option("nn-preload"sv, WasiNNEnvironment::NNModels); @@ -156,6 +159,7 @@ Plugin::Plugin::PluginDescriptor Descriptor{ }, .AddOptions = addOptions, }; +} // namespace EXPORT_GET_DESCRIPTOR(Descriptor) diff --git a/test/plugins/wasi_nn/CMakeLists.txt b/test/plugins/wasi_nn/CMakeLists.txt index fe68a8faeed9..3abca1945bf4 100644 --- a/test/plugins/wasi_nn/CMakeLists.txt +++ b/test/plugins/wasi_nn/CMakeLists.txt @@ -5,65 +5,66 @@ wasmedge_add_executable(wasiNNTests wasi_nn.cpp ) +function(download URL OUTPUT HASH) + file(DOWNLOAD + ${URL} + ${OUTPUT} + SHOW_PROGRESS + EXPECTED_HASH ${HASH} + ) +endfunction() + # Prepare the testing data for each backends. foreach(BACKEND ${WASMEDGE_PLUGIN_WASI_NN_BACKEND}) string(TOLOWER ${BACKEND} BACKEND) if(BACKEND MATCHES "openvino") - message( STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures") - execute_process( - COMMAND bash ${CMAKE_SOURCE_DIR}/utils/wasi-nn/download-openvino-fixtures.sh ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures - RESULT_VARIABLE DOWNLOAD_ERROR - OUTPUT_STRIP_TRAILING_WHITESPACE) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures/mobilenet.bin CHECKSUM_WEIGHT) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures/mobilenet.xml CHECKSUM_DESCRIP) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures/tensor-1x224x224x3-f32.bgr CHECKSUM_TENSOR) - if(NOT CHECKSUM_WEIGHT STREQUAL "ae096b1f735f1e8e54bac8b2a42303bd") - message(FATAL_ERROR "mobilenet.bin downloaded with wrong md5") - endif() - if(NOT CHECKSUM_DESCRIP STREQUAL "4ea3a14273587ce5c1662018878f9f90") - message(FATAL_ERROR "mobilenet.xml downloaded with wrong md5") - endif() - if(NOT CHECKSUM_TENSOR STREQUAL "bfca546f4a3b5e6da49b7bd728e2799a") - message(FATAL_ERROR "tensor-1x224x224x3-f32.bgr downloaded with wrong md5") - endif() + message(STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures") + download( + https://github.com/intel/openvino-rs/raw/v0.3.3/crates/openvino/tests/fixtures/mobilenet/mobilenet.bin + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures/mobilenet.bin + MD5=ae096b1f735f1e8e54bac8b2a42303bd + ) + download( + https://github.com/intel/openvino-rs/raw/v0.3.3/crates/openvino/tests/fixtures/mobilenet/mobilenet.xml + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures/mobilenet.xml + MD5=4ea3a14273587ce5c1662018878f9f90 + ) + download( + https://github.com/intel/openvino-rs/raw/v0.3.3/crates/openvino/tests/fixtures/mobilenet/tensor-1x224x224x3-f32.bgr + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_openvino_fixtures/tensor-1x224x224x3-f32.bgr + MD5=bfca546f4a3b5e6da49b7bd728e2799a + ) elseif(BACKEND MATCHES "pytorch") - message( STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures") - execute_process( - COMMAND bash ${CMAKE_SOURCE_DIR}/utils/wasi-nn/download-pytorch-fixtures.sh ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures - RESULT_VARIABLE DOWNLOAD_ERROR - OUTPUT_STRIP_TRAILING_WHITESPACE) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures/mobilenet.pt CHECKSUM_WEIGHT) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures/image-1x3x224x224.rgb CHECKSUM_IMAGE) - if(NOT CHECKSUM_WEIGHT STREQUAL "234f446d2446e0f6fd8ed700c0b4b63b") - message(FATAL_ERROR "mobilenet.pt downloaded with wrong md5") - endif() - if(NOT CHECKSUM_IMAGE STREQUAL "551caa6f3b66c1d953655228462570a1") - message(FATAL_ERROR "image-1x3x224x224.rgb downloaded with wrong md5") - endif() + message(STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures") + download( + https://github.com/second-state/WasmEdge-WASINN-examples/raw/master/pytorch-mobilenet-image/mobilenet.pt + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures/mobilenet.pt + MD5=234f446d2446e0f6fd8ed700c0b4b63b + ) + download( + https://github.com/second-state/WasmEdge-WASINN-examples/raw/master/pytorch-mobilenet-image/image-1x3x224x224.rgb + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_pytorch_fixtures/image-1x3x224x224.rgb + MD5=551caa6f3b66c1d953655228462570a1 + ) elseif(BACKEND STREQUAL "tensorflowlite") - message( STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures") - execute_process( - COMMAND bash ${CMAKE_SOURCE_DIR}/utils/wasi-nn/download-tflite-fixtures.sh ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures - RESULT_VARIABLE DOWNLOAD_ERROR - OUTPUT_STRIP_TRAILING_WHITESPACE) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures/lite-model_aiy_vision_classifier_birds_V1_3.tflite CHECKSUM_WEIGHT) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures/birdx224x224x3.rgb CHECKSUM_IMAGE) - if(NOT CHECKSUM_WEIGHT STREQUAL "3e59cc3a99afeeb819c2c38b319a7938") - message(FATAL_ERROR "downloaded tflite model with wrong md5") - endif() - if(NOT CHECKSUM_IMAGE STREQUAL "ad51c39cfe35d2ef35c4052b78cb3c55") - message(FATAL_ERROR "downloaded bird.jpg fixture with wrong md5") - endif() + message(STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures") + download( + https://raw.githubusercontent.com/gusye1234/WasmEdge-WASINN-examples/demo-tflite-image/tflite-birds_v1-image/lite-model_aiy_vision_classifier_birds_V1_3.tflite + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures/lite-model_aiy_vision_classifier_birds_V1_3.tflite + MD5=3e59cc3a99afeeb819c2c38b319a7938 + ) + download( + https://raw.githubusercontent.com/gusye1234/WasmEdge-WASINN-examples/demo-tflite-image/tflite-birds_v1-image/birdx224x224x3.rgb + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_tflite_fixtures/birdx224x224x3.rgb + MD5=ad51c39cfe35d2ef35c4052b78cb3c55 + ) elseif(BACKEND STREQUAL "ggml") - message( STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures") - execute_process( - COMMAND bash ${CMAKE_SOURCE_DIR}/utils/wasi-nn/download-ggml-fixtures.sh ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures - RESULT_VARIABLE DOWNLOAD_ERROR - OUTPUT_STRIP_TRAILING_WHITESPACE) - file(MD5 ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures/orca_mini.gguf CHECKSUM_MODEL) - if(NOT CHECKSUM_MODEL STREQUAL "f895f00678bfbf89f70d6d25f20a7b5f") - message(FATAL_ERROR "orca_mini.gguf downloaded with wrong md5") - endif() + message(STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures") + download( + https://huggingface.co/TheBloke/orca_mini_v3_7B-GGUF/resolve/main/orca_mini_v3_7b.Q2_K.gguf + ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures/orca_mini.gguf + MD5=f895f00678bfbf89f70d6d25f20a7b5f + ) else() # Add the other backend test files fetching here. endif() @@ -107,4 +108,4 @@ if(WASMEDGE_BUILD_WASI_NN_RPC) PRIVATE wasiNNRPC ) -endif() \ No newline at end of file +endif() diff --git a/test/plugins/wasi_nn/wasi_nn.cpp b/test/plugins/wasi_nn/wasi_nn.cpp index f5d5572da2da..20287914fa8e 100644 --- a/test/plugins/wasi_nn/wasi_nn.cpp +++ b/test/plugins/wasi_nn/wasi_nn.cpp @@ -46,10 +46,10 @@ inline std::vector readEntireFile(const std::string &Path) { return {}; } Fin.seekg(0, std::ios::end); - std::vector Buf(static_cast(Fin.tellg())); + std::vector Buf(static_cast(Fin.tellg())); Fin.seekg(0, std::ios::beg); if (!Fin.read(reinterpret_cast(Buf.data()), - static_cast(Buf.size()))) { + static_cast(Buf.size()))) { return {}; } Fin.close(); @@ -75,6 +75,9 @@ void writeFatPointer(WasmEdge::Runtime::Instance::MemoryInstance &MemInst, writeUInt32(MemInst, PtrSize, Ptr); } +#if defined(WASMEDGE_PLUGIN_WASI_NN_BACKEND_OPENVINO) || \ + defined(WASMEDGE_PLUGIN_WASI_NN_BACKEND_TORCH) || \ + defined(WASMEDGE_PLUGIN_WASI_NN_BACKEND_TFLITE) template std::vector classSort(WasmEdge::Span Array) { std::vector Indices(Array.size()); @@ -86,6 +89,7 @@ std::vector classSort(WasmEdge::Span Array) { }); return Indices; } +#endif } // namespace #endif @@ -194,9 +198,10 @@ TEST(WasiNNTest, OpenVINOBackend) { // Test: load -- OpenVINO model xml ptr out of bounds. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, OutBoundPtr, XmlRead.size(), BuilderPtr); - writeFatPointer(MemInst, StorePtr + XmlRead.size(), WeightRead.size(), + writeFatPointer(MemInst, OutBoundPtr, static_cast(XmlRead.size()), BuilderPtr); + writeFatPointer(MemInst, StorePtr + static_cast(XmlRead.size()), + static_cast(WeightRead.size()), BuilderPtr); { EXPECT_TRUE(HostFuncLoad.run( CallFrame, @@ -209,8 +214,10 @@ TEST(WasiNNTest, OpenVINOBackend) { // Test: load -- OpenVINO model bin ptr out of bounds. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, StorePtr, XmlRead.size(), BuilderPtr); - writeFatPointer(MemInst, OutBoundPtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, StorePtr, static_cast(XmlRead.size()), + BuilderPtr); + writeFatPointer(MemInst, OutBoundPtr, + static_cast(WeightRead.size()), BuilderPtr); { EXPECT_TRUE(HostFuncLoad.run( CallFrame, @@ -223,9 +230,10 @@ TEST(WasiNNTest, OpenVINOBackend) { // Test: load -- wrong builders' length. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, StorePtr, XmlRead.size(), BuilderPtr); - writeFatPointer(MemInst, StorePtr + XmlRead.size(), WeightRead.size(), + writeFatPointer(MemInst, StorePtr, static_cast(XmlRead.size()), BuilderPtr); + writeFatPointer(MemInst, StorePtr + static_cast(XmlRead.size()), + static_cast(WeightRead.size()), BuilderPtr); writeBinaries(MemInst, XmlRead, StorePtr); writeBinaries(MemInst, WeightRead, StorePtr + XmlRead.size()); StorePtr += (XmlRead.size() + WeightRead.size()); @@ -326,10 +334,12 @@ TEST(WasiNNTest, OpenVINOBackend) { // OpenVINO WASI-NN set_input tests. SetInputEntryPtr = BuilderPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); writeBinaries(MemInst, TensorDim, StorePtr); writeBinaries(MemInst, TensorData, StorePtr + TensorDim.size() * 4); @@ -375,10 +385,12 @@ TEST(WasiNNTest, OpenVINOBackend) { // Test: set_input -- tensor type not FP32. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(2), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(2), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, @@ -391,10 +403,12 @@ TEST(WasiNNTest, OpenVINOBackend) { // Test: set_input -- set input successfully. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, @@ -598,7 +612,8 @@ TEST(WasiNNTest, PyTorchBackend) { } // Test: load -- Torch model bin ptr out of bounds. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, OutBoundPtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, OutBoundPtr, + static_cast(WeightRead.size()), BuilderPtr); { EXPECT_TRUE(HostFuncLoad.run(CallFrame, std::initializer_list{ @@ -612,7 +627,8 @@ TEST(WasiNNTest, PyTorchBackend) { // Test: load -- wrong builders' length. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, StorePtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, StorePtr, static_cast(WeightRead.size()), + BuilderPtr); writeBinaries(MemInst, WeightRead, StorePtr); StorePtr += WeightRead.size(); { @@ -717,10 +733,12 @@ TEST(WasiNNTest, PyTorchBackend) { // Torch WASI-NN set_input tests. SetInputEntryPtr = BuilderPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); writeBinaries(MemInst, TensorDim, StorePtr); writeBinaries(MemInst, TensorData, StorePtr + TensorDim.size() * 4); @@ -739,10 +757,12 @@ TEST(WasiNNTest, PyTorchBackend) { // Test: set_input -- tensor type not FP32. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(2), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(2), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, @@ -755,10 +775,12 @@ TEST(WasiNNTest, PyTorchBackend) { // Test: set_input -- set input successfully. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, @@ -966,7 +988,8 @@ TEST(WasiNNTest, TFLiteBackend) { } // Test: load -- model bin ptr out of bounds. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, OutBoundPtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, OutBoundPtr, + static_cast(WeightRead.size()), BuilderPtr); { EXPECT_TRUE( HostFuncLoad.run(CallFrame, @@ -981,7 +1004,8 @@ TEST(WasiNNTest, TFLiteBackend) { // Test: load -- wrong builders' length. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, StorePtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, StorePtr, static_cast(WeightRead.size()), + BuilderPtr); writeBinaries(MemInst, WeightRead, StorePtr); StorePtr += WeightRead.size(); { @@ -1089,10 +1113,12 @@ TEST(WasiNNTest, TFLiteBackend) { // Torch WASI-NN set_input tests. SetInputEntryPtr = BuilderPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); writeBinaries(MemInst, TensorDim, StorePtr); writeBinaries(MemInst, TensorData, StorePtr + TensorDim.size() * 4); @@ -1111,11 +1137,13 @@ TEST(WasiNNTest, TFLiteBackend) { // Test: set_input -- set input successfully. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), + BuilderPtr); // Tensor type U8 writeUInt32(MemInst, UINT32_C(2), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), - BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, @@ -1318,7 +1346,8 @@ TEST(WasiNNTest, GGMLBackend) { // Test: load -- GGML model bin ptr out of bounds. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, OutBoundPtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, OutBoundPtr, + static_cast(WeightRead.size()), BuilderPtr); { EXPECT_TRUE(HostFuncLoad.run(CallFrame, std::initializer_list{ @@ -1332,7 +1361,8 @@ TEST(WasiNNTest, GGMLBackend) { // Test: load -- wrong metadata encoding when builders length > 1. BuilderPtr = LoadEntryPtr; - writeFatPointer(MemInst, StorePtr, WeightRead.size(), BuilderPtr); + writeFatPointer(MemInst, StorePtr, static_cast(WeightRead.size()), + BuilderPtr); writeBinaries(MemInst, WeightRead, StorePtr); StorePtr += WeightRead.size(); { @@ -1383,12 +1413,16 @@ TEST(WasiNNTest, GGMLBackend) { // GGML WASI-NN set_input tests. SetInputEntryPtr = BuilderPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); writeBinaries(MemInst, TensorDim, StorePtr); - writeBinaries(MemInst, TensorData, StorePtr + TensorDim.size() * 4); + writeBinaries(MemInst, TensorData, + StorePtr + + static_cast(TensorDim.size()) * 4); // Test: set_input -- context id exceeds. { @@ -1403,10 +1437,12 @@ TEST(WasiNNTest, GGMLBackend) { // Test: set_input -- set input successfully. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, @@ -1615,10 +1651,12 @@ TEST(WasiNNTest, GGMLBackendWithRPC) { // GGML WASI-NN set_input tests. SetInputEntryPtr = BuilderPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); writeBinaries(MemInst, TensorDim, StorePtr); writeBinaries(MemInst, TensorData, StorePtr + TensorDim.size() * 4); @@ -1634,10 +1672,12 @@ TEST(WasiNNTest, GGMLBackendWithRPC) { // Test: set_input -- set input successfully. BuilderPtr = SetInputEntryPtr; - writeFatPointer(MemInst, StorePtr, TensorDim.size(), BuilderPtr); - writeUInt32(MemInst, UINT32_C(1), BuilderPtr); - writeFatPointer(MemInst, StorePtr + TensorDim.size() * 4, TensorData.size(), + writeFatPointer(MemInst, StorePtr, static_cast(TensorDim.size()), BuilderPtr); + writeUInt32(MemInst, UINT32_C(1), BuilderPtr); + writeFatPointer(MemInst, + StorePtr + static_cast(TensorDim.size()) * 4, + static_cast(TensorData.size()), BuilderPtr); { EXPECT_TRUE( HostFuncSetInput.run(CallFrame, diff --git a/utils/wasi-nn/download-ggml-fixtures.sh b/utils/wasi-nn/download-ggml-fixtures.sh deleted file mode 100755 index bb635925998f..000000000000 --- a/utils/wasi-nn/download-ggml-fixtures.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# SPDX-FileCopyrightText: 2019-2023 Second State INC - -TODIR=$1 -if [[ $# -eq 0 ]]; then - TODIR=. -fi -MODEL=orca_mini.gguf -FIXTURE=https://huggingface.co/TheBloke/orca_mini_v3_7B-GGUF/resolve/main/orca_mini_v3_7b.Q2_K.gguf -if [ ! -d $TODIR ]; then - mkdir $TODIR -fi - -if [ ! -f $TODIR/$MODEL ]; then - curl -sL $FIXTURE -o $TODIR/$MODEL -fi diff --git a/utils/wasi-nn/download-openvino-fixtures.sh b/utils/wasi-nn/download-openvino-fixtures.sh deleted file mode 100755 index 02a243da995d..000000000000 --- a/utils/wasi-nn/download-openvino-fixtures.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# SPDX-FileCopyrightText: 2019-2022 Second State INC - -TODIR=$1 -if [[ $# -eq 0 ]]; then - TODIR=. -fi -FIXTURE=https://github.com/intel/openvino-rs/raw/v0.3.3/crates/openvino/tests/fixtures/mobilenet/ -if [ ! -d $TODIR ]; then - mkdir $TODIR -fi -if [ ! -d $TODIR ]; then - mkdir $TODIR -fi - -if [ ! -f $TODIR/mobilenet.bin ]; then - curl -sL $FIXTURE/mobilenet.bin -o $TODIR/mobilenet.bin -fi -if [ ! -f $TODIR/mobilenet.xml ]; then - curl -sL $FIXTURE/mobilenet.xml -o $TODIR/mobilenet.xml -fi -if [ ! -f $TODIR/tensor-1x224x224x3-f32.bgr ]; then - curl -sL $FIXTURE/tensor-1x224x224x3-f32.bgr -o $TODIR/tensor-1x224x224x3-f32.bgr -fi diff --git a/utils/wasi-nn/download-pytorch-fixtures.sh b/utils/wasi-nn/download-pytorch-fixtures.sh deleted file mode 100755 index 6a6aab91b7cb..000000000000 --- a/utils/wasi-nn/download-pytorch-fixtures.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# SPDX-FileCopyrightText: 2019-2022 Second State INC - -TODIR=$1 -if [[ $# -eq 0 ]]; then - TODIR=. -fi -FIXTURE=https://github.com/second-state/WasmEdge-WASINN-examples/raw/master/pytorch-mobilenet-image/ -if [ ! -d $TODIR ]; then - mkdir $TODIR -fi - -if [ ! -f $TODIR/mobilenet.pt ]; then - curl -sL $FIXTURE/mobilenet.pt -o $TODIR/mobilenet.pt -fi -if [ ! -f $TODIR/image-1x3x224x224.rgb ]; then - curl -sL $FIXTURE/image-1x3x224x224.rgb -o $TODIR/image-1x3x224x224.rgb -fi diff --git a/utils/wasi-nn/download-tflite-fixtures.sh b/utils/wasi-nn/download-tflite-fixtures.sh deleted file mode 100755 index 959d7fee10af..000000000000 --- a/utils/wasi-nn/download-tflite-fixtures.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# SPDX-FileCopyrightText: 2019-2022 Second State INC - -TODIR=$1 -if [[ $# -eq 0 ]]; then - TODIR=. -fi -FIXTURE=https://raw.githubusercontent.com/gusye1234/WasmEdge-WASINN-examples/demo-tflite-image/tflite-birds_v1-image -if [ ! -d $TODIR ]; then - mkdir $TODIR -fi - -if [ ! -f $TODIR/lite-model_aiy_vision_classifier_birds_V1_3.tflite ]; then - curl -sL $FIXTURE/lite-model_aiy_vision_classifier_birds_V1_3.tflite -o $TODIR/lite-model_aiy_vision_classifier_birds_V1_3.tflite -fi -if [ ! -f $TODIR/birdx224x224x3.rgb ]; then - curl -sL $FIXTURE/birdx224x224x3.rgb -o $TODIR/birdx224x224x3.rgb -fi From aaba2e971946ee4ea0626a3e25f68709443e0841 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Wed, 27 Mar 2024 14:35:45 +0800 Subject: [PATCH 126/218] [Plugin] Add WASMEDGE_LIB_PREFIX for windows * Change std::string arguments to std::string_view Signed-off-by: Shen-Ta Hsieh --- CMakeLists.txt | 2 +- cmake/Helper.cmake | 1 - include/common/defines.h | 3 + test/api/APIUnitTest.cpp | 284 ++++++++---------- test/plugins/CMakeLists.txt | 4 +- test/plugins/unittest/CMakeLists.txt | 9 +- test/plugins/unittest/testplugin.c | 20 +- test/plugins/unittest/testplugin.cpp | 29 +- test/plugins/unittest/unittest_c.cpp | 6 +- test/plugins/unittest/unittest_cpp.cpp | 6 +- test/plugins/wasi_crypto/helper.h | 4 +- test/plugins/wasi_logging/wasi_logging.cpp | 4 +- test/plugins/wasi_nn/wasi_nn.cpp | 6 +- test/plugins/wasm_bpf/simple_map_test.cpp | 6 +- test/plugins/wasm_bpf/simple_ringbuf_test.cpp | 6 +- test/plugins/wasm_bpf/wasm_bpf.cpp | 6 +- test/plugins/wasmedge_ffmpeg/utils.h | 6 +- .../plugins/wasmedge_image/wasmedge_image.cpp | 4 +- .../wasmedge_opencvmini.cpp | 4 +- .../wasmedge_process/wasmedge_process.cpp | 4 +- .../wasmedge_rustls/wasmedge_rustls.cpp | 6 +- .../wasmedge_tensorflow.cpp | 4 +- .../wasmedge_tensorflowlite.cpp | 4 +- test/plugins/wasmedge_zlib/wasmedge_zlib.cpp | 4 +- 24 files changed, 212 insertions(+), 220 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0dd01ae3034..d972312785d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ HunterGate( LOCAL ) -project(WasmEdge) +project(WasmEdge LANGUAGES CXX C) # Overwrite it if you want to use static MSVC runtime library. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 00d81cde8ae3..9660c2e78561 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -18,7 +18,6 @@ endif() if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") list(APPEND WASMEDGE_CFLAGS - /std:c++17 /WX /W4 /we5030 # treat unknown attribute as error diff --git a/include/common/defines.h b/include/common/defines.h index 96e358a8722d..9ac468837606 100644 --- a/include/common/defines.h +++ b/include/common/defines.h @@ -19,6 +19,7 @@ #define WASMEDGE_OS_LINUX 1 #define WASMEDGE_OS_MACOS 0 #define WASMEDGE_OS_WINDOWS 0 +#define WASMEDGE_LIB_PREFIX "lib" #define WASMEDGE_LIB_EXTENSION ".so" #elif defined(macintosh) || defined(Macintosh) || \ @@ -27,6 +28,7 @@ #define WASMEDGE_OS_LINUX 0 #define WASMEDGE_OS_MACOS 1 #define WASMEDGE_OS_WINDOWS 0 +#define WASMEDGE_LIB_PREFIX "lib" #define WASMEDGE_LIB_EXTENSION ".dylib" #elif defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || \ @@ -35,6 +37,7 @@ #define WASMEDGE_OS_LINUX 0 #define WASMEDGE_OS_MACOS 0 #define WASMEDGE_OS_WINDOWS 1 +#define WASMEDGE_LIB_PREFIX "" #define WASMEDGE_LIB_EXTENSION ".dll" #else diff --git a/test/api/APIUnitTest.cpp b/test/api/APIUnitTest.cpp index ebed175c8377..aef4d3ce2007 100644 --- a/test/api/APIUnitTest.cpp +++ b/test/api/APIUnitTest.cpp @@ -19,6 +19,8 @@ #include "system/winapi.h" #endif +using namespace std::literals; + namespace { std::vector TestWasm = { @@ -459,7 +461,8 @@ bool isErrMatch(WasmEdge_ErrCategory ErrCate, uint32_t Code, } TEST(APICoreTest, Version) { - EXPECT_EQ(std::string(WASMEDGE_VERSION), std::string(WasmEdge_VersionGet())); + EXPECT_EQ(std::string_view(WASMEDGE_VERSION), + std::string_view(WasmEdge_VersionGet())); EXPECT_EQ(static_cast(WASMEDGE_VERSION_MAJOR), WasmEdge_VersionGetMajor()); EXPECT_EQ(static_cast(WASMEDGE_VERSION_MINOR), @@ -830,89 +833,89 @@ TEST(APICoreTest, ImportType) { EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[0]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[0]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-add")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-add"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[0]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[1]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[1]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-sub")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-sub"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[1]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[2]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[2]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-mul")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-mul"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[2]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[3]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[3]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-div")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-div"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[3]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); std::memset(ImpTypes, 0, sizeof(const WasmEdge_ImportTypeContext *) * 20); EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, ImpTypes, 20), 14U); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[4]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[4]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-term")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-term"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[4]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[5]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[5]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-fail")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-fail"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[5]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[6]), WasmEdge_ExternalType_Global); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[6]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("glob-i32")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-i32"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[6]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[7]), WasmEdge_ExternalType_Global); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[7]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("glob-i64")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-i64"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[7]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[8]), WasmEdge_ExternalType_Global); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[8]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("glob-f32")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-f32"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[8]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[9]), WasmEdge_ExternalType_Global); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[9]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("glob-f64")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-f64"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[9]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[10]), WasmEdge_ExternalType_Table); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[10]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("tab-func")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tab-func"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[10]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[11]), WasmEdge_ExternalType_Table); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[11]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("tab-ext")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tab-ext"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[11]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[12]), WasmEdge_ExternalType_Memory); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[12]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("mem1")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "mem1"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[12]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[13]), WasmEdge_ExternalType_Memory); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[13]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("mem2")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "mem2"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[13]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("dummy")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); // Import type get external type EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(nullptr), @@ -922,15 +925,15 @@ TEST(APICoreTest, ImportType) { // Import type get module name Name = WasmEdge_ImportTypeGetModuleName(nullptr); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), ""sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[0]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("extern")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); // Import type get external name Name = WasmEdge_ImportTypeGetExternalName(nullptr); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), ""sv); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[0]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-add")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-add"sv); // Import type get function type EXPECT_EQ(WasmEdge_ImportTypeGetFunctionType(nullptr, nullptr), nullptr); @@ -1011,70 +1014,69 @@ TEST(APICoreTest, ExportType) { EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[0]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[0]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-1")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-1"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[1]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[1]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-2")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-2"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[2]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[2]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-3")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-3"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[3]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[3]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-4")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-4"sv); std::memset(ExpTypes, 0, sizeof(const WasmEdge_ExportTypeContext *) * 20); EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, ExpTypes, 20), 16U); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[4]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[4]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-add")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-add"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[5]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[5]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-mul-2")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-mul-2"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[6]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[6]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), - std::string("func-call-indirect")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-call-indirect"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[7]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[7]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-host-add")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-host-add"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[8]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[8]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-host-sub")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-host-sub"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[9]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[9]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-host-mul")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-host-mul"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[10]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[10]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-host-div")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-host-div"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[11]), WasmEdge_ExternalType_Table); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[11]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("tab-func")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tab-func"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[12]), WasmEdge_ExternalType_Table); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[12]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("tab-ext")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tab-ext"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[13]), WasmEdge_ExternalType_Memory); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[13]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("mem")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "mem"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[14]), WasmEdge_ExternalType_Global); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[14]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("glob-mut-i32")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-mut-i32"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[15]), WasmEdge_ExternalType_Global); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[15]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("glob-const-f32")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-const-f32"sv); // Export type get external type EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(nullptr), @@ -1084,9 +1086,9 @@ TEST(APICoreTest, ExportType) { // Export type get external name Name = WasmEdge_ExportTypeGetExternalName(nullptr); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), ""sv); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[0]); - EXPECT_EQ(std::string(Name.Buf, Name.Length), std::string("func-1")); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-1"sv); // Export type get function type EXPECT_EQ(WasmEdge_ExportTypeGetFunctionType(nullptr, nullptr), nullptr); @@ -1779,21 +1781,21 @@ TEST(APICoreTest, Store) { EXPECT_EQ(WasmEdge_StoreListModule(Store, nullptr, 15), 2U); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_StoreListModule(Store, Names, 1), 2U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("extern")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "extern"sv); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_StoreListModule(Store, Names, 15), 2U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("extern")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("module")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "extern"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "module"sv); // Module instance get module name Names[0] = WasmEdge_ModuleInstanceGetModuleName(nullptr); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), ""sv); Names[0] = WasmEdge_ModuleInstanceGetModuleName(ModCxt); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), ""sv); Names[0] = WasmEdge_ModuleInstanceGetModuleName(ModRegCxt); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("module")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "module"sv); Names[0] = WasmEdge_ModuleInstanceGetModuleName(HostMod); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("extern")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "extern"sv); // Module instance list function exports EXPECT_EQ(WasmEdge_ModuleInstanceListFunctionLength(ModCxt), 11U); @@ -1802,30 +1804,24 @@ TEST(APICoreTest, Store) { EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModCxt, nullptr, 15), 11U); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModCxt, Names, 4), 11U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("func-1")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("func-2")); - EXPECT_EQ(std::string(Names[2].Buf, Names[2].Length), std::string("func-3")); - EXPECT_EQ(std::string(Names[3].Buf, Names[3].Length), std::string("func-4")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "func-1"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "func-2"sv); + EXPECT_EQ(std::string_view(Names[2].Buf, Names[2].Length), "func-3"sv); + EXPECT_EQ(std::string_view(Names[3].Buf, Names[3].Length), "func-4"sv); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListFunction(ModCxt, Names, 15), 11U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("func-1")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("func-2")); - EXPECT_EQ(std::string(Names[2].Buf, Names[2].Length), std::string("func-3")); - EXPECT_EQ(std::string(Names[3].Buf, Names[3].Length), std::string("func-4")); - EXPECT_EQ(std::string(Names[4].Buf, Names[4].Length), - std::string("func-add")); - EXPECT_EQ(std::string(Names[5].Buf, Names[5].Length), - std::string("func-call-indirect")); - EXPECT_EQ(std::string(Names[6].Buf, Names[6].Length), - std::string("func-host-add")); - EXPECT_EQ(std::string(Names[7].Buf, Names[7].Length), - std::string("func-host-div")); - EXPECT_EQ(std::string(Names[8].Buf, Names[8].Length), - std::string("func-host-mul")); - EXPECT_EQ(std::string(Names[9].Buf, Names[9].Length), - std::string("func-host-sub")); - EXPECT_EQ(std::string(Names[10].Buf, Names[10].Length), - std::string("func-mul-2")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "func-1"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "func-2"sv); + EXPECT_EQ(std::string_view(Names[2].Buf, Names[2].Length), "func-3"sv); + EXPECT_EQ(std::string_view(Names[3].Buf, Names[3].Length), "func-4"sv); + EXPECT_EQ(std::string_view(Names[4].Buf, Names[4].Length), "func-add"sv); + EXPECT_EQ(std::string_view(Names[5].Buf, Names[5].Length), + "func-call-indirect"sv); + EXPECT_EQ(std::string_view(Names[6].Buf, Names[6].Length), "func-host-add"sv); + EXPECT_EQ(std::string_view(Names[7].Buf, Names[7].Length), "func-host-div"sv); + EXPECT_EQ(std::string_view(Names[8].Buf, Names[8].Length), "func-host-mul"sv); + EXPECT_EQ(std::string_view(Names[9].Buf, Names[9].Length), "func-host-sub"sv); + EXPECT_EQ(std::string_view(Names[10].Buf, Names[10].Length), "func-mul-2"sv); // Module instance find function EXPECT_NE(WasmEdge_ModuleInstanceFindFunction(ModCxt, Names[7]), nullptr); @@ -1839,12 +1835,11 @@ TEST(APICoreTest, Store) { EXPECT_EQ(WasmEdge_ModuleInstanceListTable(ModCxt, nullptr, 15), 2U); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListTable(ModCxt, Names, 1), 2U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("tab-ext")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "tab-ext"sv); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListTable(ModCxt, Names, 15), 2U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("tab-ext")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), - std::string("tab-func")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "tab-ext"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "tab-func"sv); // Module instance find table EXPECT_NE(WasmEdge_ModuleInstanceFindTable(ModCxt, Names[1]), nullptr); @@ -1859,7 +1854,7 @@ TEST(APICoreTest, Store) { EXPECT_EQ(WasmEdge_ModuleInstanceListMemory(ModCxt, Names, 0), 1U); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListMemory(ModCxt, Names, 15), 1U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("mem")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "mem"sv); // Module instance find memory EXPECT_NE(WasmEdge_ModuleInstanceFindMemory(ModCxt, Names[0]), nullptr); @@ -1873,14 +1868,13 @@ TEST(APICoreTest, Store) { EXPECT_EQ(WasmEdge_ModuleInstanceListGlobal(ModCxt, nullptr, 15), 2U); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListGlobal(ModCxt, Names, 1), 2U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), - std::string("glob-const-f32")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), + "glob-const-f32"sv); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_ModuleInstanceListGlobal(ModCxt, Names, 15), 2U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), - std::string("glob-const-f32")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), - std::string("glob-mut-i32")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), + "glob-const-f32"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "glob-mut-i32"sv); // Module instance find global EXPECT_NE(WasmEdge_ModuleInstanceFindGlobal(ModCxt, Names[1]), nullptr); @@ -3302,17 +3296,15 @@ TEST(APICoreTest, VM) { EXPECT_EQ(WasmEdge_VMListRegisteredModule(VM, nullptr, 20), 16U); std::memset(Names, 0, sizeof(WasmEdge_String) * 20); EXPECT_EQ(WasmEdge_VMListRegisteredModule(VM, Names, 1), 16U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("extern")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "extern"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), ""sv); std::memset(Names, 0, sizeof(WasmEdge_String) * 20); EXPECT_EQ(WasmEdge_VMListRegisteredModule(VM, Names, 20), 16U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("extern")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), - std::string("reg-wasm-ast")); - EXPECT_EQ(std::string(Names[2].Buf, Names[2].Length), - std::string("reg-wasm-buffer")); - EXPECT_EQ(std::string(Names[3].Buf, Names[3].Length), - std::string("reg-wasm-file")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "extern"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "reg-wasm-ast"sv); + EXPECT_EQ(std::string_view(Names[2].Buf, Names[2].Length), + "reg-wasm-buffer"sv); + EXPECT_EQ(std::string_view(Names[3].Buf, Names[3].Length), "reg-wasm-file"sv); // VM load wasm from file EXPECT_TRUE(WasmEdge_ResultOK(WasmEdge_VMLoadWasmFromFile(VM, TPath))); @@ -3512,54 +3504,42 @@ TEST(APICoreTest, VM) { std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_VMGetFunctionList(VM, Names, nullptr, 15), 11U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("func-1")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("func-2")); - EXPECT_EQ(std::string(Names[2].Buf, Names[2].Length), std::string("func-3")); - EXPECT_EQ(std::string(Names[3].Buf, Names[3].Length), std::string("func-4")); - EXPECT_EQ(std::string(Names[4].Buf, Names[4].Length), - std::string("func-add")); - EXPECT_EQ(std::string(Names[5].Buf, Names[5].Length), - std::string("func-call-indirect")); - EXPECT_EQ(std::string(Names[6].Buf, Names[6].Length), - std::string("func-host-add")); - EXPECT_EQ(std::string(Names[7].Buf, Names[7].Length), - std::string("func-host-div")); - EXPECT_EQ(std::string(Names[8].Buf, Names[8].Length), - std::string("func-host-mul")); - EXPECT_EQ(std::string(Names[9].Buf, Names[9].Length), - std::string("func-host-sub")); - EXPECT_EQ(std::string(Names[10].Buf, Names[10].Length), - std::string("func-mul-2")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "func-1"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "func-2"sv); + EXPECT_EQ(std::string_view(Names[2].Buf, Names[2].Length), "func-3"sv); + EXPECT_EQ(std::string_view(Names[3].Buf, Names[3].Length), "func-4"sv); + EXPECT_EQ(std::string_view(Names[4].Buf, Names[4].Length), "func-add"sv); + EXPECT_EQ(std::string_view(Names[5].Buf, Names[5].Length), + "func-call-indirect"sv); + EXPECT_EQ(std::string_view(Names[6].Buf, Names[6].Length), "func-host-add"sv); + EXPECT_EQ(std::string_view(Names[7].Buf, Names[7].Length), "func-host-div"sv); + EXPECT_EQ(std::string_view(Names[8].Buf, Names[8].Length), "func-host-mul"sv); + EXPECT_EQ(std::string_view(Names[9].Buf, Names[9].Length), "func-host-sub"sv); + EXPECT_EQ(std::string_view(Names[10].Buf, Names[10].Length), "func-mul-2"sv); EXPECT_EQ(WasmEdge_VMGetFunctionList(VM, nullptr, nullptr, 15), 11U); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_VMGetFunctionList(VM, Names, FuncTypes, 4), 11U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("func-1")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("func-2")); - EXPECT_EQ(std::string(Names[2].Buf, Names[2].Length), std::string("func-3")); - EXPECT_EQ(std::string(Names[3].Buf, Names[3].Length), std::string("func-4")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "func-1"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "func-2"sv); + EXPECT_EQ(std::string_view(Names[2].Buf, Names[2].Length), "func-3"sv); + EXPECT_EQ(std::string_view(Names[3].Buf, Names[3].Length), "func-4"sv); std::memset(Names, 0, sizeof(WasmEdge_String) * 15); EXPECT_EQ(WasmEdge_VMGetFunctionList(VM, Names, FuncTypes, 15), 11U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("func-1")); - EXPECT_EQ(std::string(Names[1].Buf, Names[1].Length), std::string("func-2")); - EXPECT_EQ(std::string(Names[2].Buf, Names[2].Length), std::string("func-3")); - EXPECT_EQ(std::string(Names[3].Buf, Names[3].Length), std::string("func-4")); - EXPECT_EQ(std::string(Names[4].Buf, Names[4].Length), - std::string("func-add")); - EXPECT_EQ(std::string(Names[5].Buf, Names[5].Length), - std::string("func-call-indirect")); - EXPECT_EQ(std::string(Names[6].Buf, Names[6].Length), - std::string("func-host-add")); - EXPECT_EQ(std::string(Names[7].Buf, Names[7].Length), - std::string("func-host-div")); - EXPECT_EQ(std::string(Names[8].Buf, Names[8].Length), - std::string("func-host-mul")); - EXPECT_EQ(std::string(Names[9].Buf, Names[9].Length), - std::string("func-host-sub")); - EXPECT_EQ(std::string(Names[10].Buf, Names[10].Length), - std::string("func-mul-2")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), "func-1"sv); + EXPECT_EQ(std::string_view(Names[1].Buf, Names[1].Length), "func-2"sv); + EXPECT_EQ(std::string_view(Names[2].Buf, Names[2].Length), "func-3"sv); + EXPECT_EQ(std::string_view(Names[3].Buf, Names[3].Length), "func-4"sv); + EXPECT_EQ(std::string_view(Names[4].Buf, Names[4].Length), "func-add"sv); + EXPECT_EQ(std::string_view(Names[5].Buf, Names[5].Length), + "func-call-indirect"sv); + EXPECT_EQ(std::string_view(Names[6].Buf, Names[6].Length), "func-host-add"sv); + EXPECT_EQ(std::string_view(Names[7].Buf, Names[7].Length), "func-host-div"sv); + EXPECT_EQ(std::string_view(Names[8].Buf, Names[8].Length), "func-host-mul"sv); + EXPECT_EQ(std::string_view(Names[9].Buf, Names[9].Length), "func-host-sub"sv); + EXPECT_EQ(std::string_view(Names[10].Buf, Names[10].Length), "func-mul-2"sv); // VM get active module EXPECT_NE(WasmEdge_VMGetActiveModule(VM), nullptr); @@ -3622,15 +3602,15 @@ TEST(APICoreTest, VM) { WasmEdge_VMDelete(VM); } -#if defined(WASMEDGE_BUILD_PLUGINS) && WASMEDGE_OS_LINUX +#if defined(WASMEDGE_BUILD_PLUGINS) TEST(APICoreTest, Plugin) { WasmEdge_String Names[15]; // Load from the specific path EXPECT_EQ(WasmEdge_PluginListPluginsLength(), 0U); WasmEdge_PluginLoadFromPath( - "../plugins/unittest/" - "libwasmedgePluginTestModuleCPP" WASMEDGE_LIB_EXTENSION); + "../plugins/unittest/" WASMEDGE_LIB_PREFIX + "wasmedgePluginTestModuleCPP" WASMEDGE_LIB_EXTENSION); EXPECT_EQ(WasmEdge_PluginListPluginsLength(), 1U); // Get the loaded plugin length @@ -3638,8 +3618,8 @@ TEST(APICoreTest, Plugin) { EXPECT_EQ(WasmEdge_PluginListPlugins(nullptr, 0), 1U); EXPECT_EQ(WasmEdge_PluginListPlugins(Names, 0), 1U); EXPECT_EQ(WasmEdge_PluginListPlugins(Names, 15), 1U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), - std::string("wasmedge_plugintest_cpp")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), + "wasmedge_plugintest_cpp"sv); // Find the plugin context const WasmEdge_PluginContext *PluginCxt = @@ -3650,10 +3630,10 @@ TEST(APICoreTest, Plugin) { // Get plugin name Names[0] = WasmEdge_PluginGetPluginName(PluginCxt); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), - std::string("wasmedge_plugintest_cpp")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), + "wasmedge_plugintest_cpp"sv); Names[0] = WasmEdge_PluginGetPluginName(nullptr); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), ""sv); // List modules in the plugin EXPECT_EQ(WasmEdge_PluginListModuleLength(nullptr), 0U); @@ -3663,10 +3643,10 @@ TEST(APICoreTest, Plugin) { EXPECT_EQ(WasmEdge_PluginListModule(nullptr, nullptr, 0), 0U); EXPECT_EQ(WasmEdge_PluginListModule(PluginCxt, nullptr, 0), 1U); EXPECT_EQ(WasmEdge_PluginListModule(PluginCxt, Names, 0), 1U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), std::string("")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), ""sv); EXPECT_EQ(WasmEdge_PluginListModule(PluginCxt, Names, 15), 1U); - EXPECT_EQ(std::string(Names[0].Buf, Names[0].Length), - std::string("wasmedge_plugintest_cpp_module")); + EXPECT_EQ(std::string_view(Names[0].Buf, Names[0].Length), + "wasmedge_plugintest_cpp_module"sv); // Create the module WasmEdge_ModuleInstanceContext *ModCxt = diff --git a/test/plugins/CMakeLists.txt b/test/plugins/CMakeLists.txt index 211c0bbda2b0..eeb1950b3212 100644 --- a/test/plugins/CMakeLists.txt +++ b/test/plugins/CMakeLists.txt @@ -61,6 +61,4 @@ if(WASMEDGE_PLUGIN_RUSTLS) add_subdirectory(wasmedge_rustls) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(unittest) -endif() +add_subdirectory(unittest) diff --git a/test/plugins/unittest/CMakeLists.txt b/test/plugins/unittest/CMakeLists.txt index 4631c0b44e35..d1614c068caf 100644 --- a/test/plugins/unittest/CMakeLists.txt +++ b/test/plugins/unittest/CMakeLists.txt @@ -2,15 +2,22 @@ # SPDX-FileCopyrightText: 2019-2022 Second State INC # The test plugin module in C API +enable_language(C) + wasmedge_add_library(wasmedgePluginTestModuleC SHARED testplugin.c -) + ) set_target_properties(wasmedgePluginTestModuleC PROPERTIES C_STANDARD 11 ) +# remove cxx_standard for msvc +set_property(TARGET wasmedgePluginTestModuleC PROPERTY + CXX_STANDARD +) + target_compile_options(wasmedgePluginTestModuleC PUBLIC -DWASMEDGE_PLUGIN diff --git a/test/plugins/unittest/testplugin.c b/test/plugins/unittest/testplugin.c index a0536101d982..70eb27bd13ac 100644 --- a/test/plugins/unittest/testplugin.c +++ b/test/plugins/unittest/testplugin.c @@ -12,15 +12,15 @@ static WasmEdge_String NameString; static const char NameCString[] = "name"; static const WasmEdge_String NameStringDefaultValue = {.Buf = NameCString, .Length = 4}; -void Finalizer(void *Data) { +static void Finalizer(void *Data) { printf("Deallocate host data\n"); free((int32_t *)Data); } -WasmEdge_Result HostFuncAdd(void *Data, - const WasmEdge_CallingFrameContext *CallFrameCxt - __attribute__((unused)), - const WasmEdge_Value *In, WasmEdge_Value *Out) { +static WasmEdge_Result +HostFuncAdd(void *Data, const WasmEdge_CallingFrameContext *CallFrameCxt, + const WasmEdge_Value *In, WasmEdge_Value *Out) { + (void)CallFrameCxt; /* * Host function to calculate A + B, * and accumulate (A + B) to the host data. @@ -34,10 +34,10 @@ WasmEdge_Result HostFuncAdd(void *Data, return WasmEdge_Result_Success; } -WasmEdge_Result HostFuncSub(void *Data, - const WasmEdge_CallingFrameContext *CallFrameCxt - __attribute__((unused)), - const WasmEdge_Value *In, WasmEdge_Value *Out) { +static WasmEdge_Result +HostFuncSub(void *Data, const WasmEdge_CallingFrameContext *CallFrameCxt, + const WasmEdge_Value *In, WasmEdge_Value *Out) { + (void)CallFrameCxt; /* * Host function to calculate A - B, * and accumulate (A - B) to the host data. @@ -51,7 +51,7 @@ WasmEdge_Result HostFuncSub(void *Data, return WasmEdge_Result_Success; } -WasmEdge_ModuleInstanceContext * +static WasmEdge_ModuleInstanceContext * CreateTestModule(const struct WasmEdge_ModuleDescriptor *Desc) { /* Allocate and initialize a host data. */ printf("Allocate host data\n"); diff --git a/test/plugins/unittest/testplugin.cpp b/test/plugins/unittest/testplugin.cpp index 7cc550135d39..581dfb5f26da 100644 --- a/test/plugins/unittest/testplugin.cpp +++ b/test/plugins/unittest/testplugin.cpp @@ -36,21 +36,22 @@ create(const Plugin::PluginModule::ModuleDescriptor *) noexcept { return new WasmEdgePluginTestModule; } +static Plugin::PluginModule::ModuleDescriptor MD[]{ + { + /* Name */ "wasmedge_plugintest_cpp_module", + /* Description */ "This is for the plugin tests in WasmEdge.", + /* Create */ create, + }, +}; + Plugin::Plugin::PluginDescriptor Descriptor{ - .Name = "wasmedge_plugintest_cpp", - .Description = "", - .APIVersion = Plugin::Plugin::CurrentAPIVersion, - .Version = {0, 10, 0, 0}, - .ModuleCount = 1, - .ModuleDescriptions = - (Plugin::PluginModule::ModuleDescriptor[]){ - { - .Name = "wasmedge_plugintest_cpp_module", - .Description = "This is for the plugin tests in WasmEdge.", - .Create = create, - }, - }, - .AddOptions = addOptions, + /* Name */ "wasmedge_plugintest_cpp", + /* Description */ "", + /* APIVersion */ Plugin::Plugin::CurrentAPIVersion, + /* Version */ {0, 10, 0, 0}, + /* ModuleCount */ 1, + /* ModuleDescriptions */ MD, + /* AddOptions */ addOptions, }; EXPORT_GET_DESCRIPTOR(Descriptor) diff --git a/test/plugins/unittest/unittest_c.cpp b/test/plugins/unittest/unittest_c.cpp index a1ccb94d11a7..5397c9ca35c4 100644 --- a/test/plugins/unittest/unittest_c.cpp +++ b/test/plugins/unittest/unittest_c.cpp @@ -11,7 +11,8 @@ namespace { WasmEdge_ModuleInstanceContext *createModuleC() { WasmEdge_PluginLoadFromPath( - "./libwasmedgePluginTestModuleC" WASMEDGE_LIB_EXTENSION); + "./" WASMEDGE_LIB_PREFIX + "wasmedgePluginTestModuleC" WASMEDGE_LIB_EXTENSION); WasmEdge_String Str = WasmEdge_StringCreateByCString("wasmedge_plugintest_c"); const WasmEdge_PluginContext *PluginCxt = WasmEdge_PluginFind(Str); WasmEdge_StringDelete(Str); @@ -28,7 +29,8 @@ WasmEdge_ModuleInstanceContext *createModuleC() { WasmEdge_ModuleInstanceContext *createModuleCPP() { WasmEdge_PluginLoadFromPath( - "./libwasmedgePluginTestModuleCPP" WASMEDGE_LIB_EXTENSION); + "./" WASMEDGE_LIB_PREFIX + "wasmedgePluginTestModuleCPP" WASMEDGE_LIB_EXTENSION); WasmEdge_String Str = WasmEdge_StringCreateByCString("wasmedge_plugintest_cpp"); const WasmEdge_PluginContext *PluginCxt = WasmEdge_PluginFind(Str); diff --git a/test/plugins/unittest/unittest_cpp.cpp b/test/plugins/unittest/unittest_cpp.cpp index 345bdbfd058f..81af0d5ebfd0 100644 --- a/test/plugins/unittest/unittest_cpp.cpp +++ b/test/plugins/unittest/unittest_cpp.cpp @@ -18,7 +18,8 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModuleC() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "./libwasmedgePluginTestModuleC" WASMEDGE_LIB_EXTENSION)); + "./" WASMEDGE_LIB_PREFIX + "wasmedgePluginTestModuleC" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_plugintest_c"sv)) { if (const auto *Module = @@ -32,7 +33,8 @@ WasmEdge::Runtime::Instance::ModuleInstance *createModuleC() { WasmEdge::Runtime::Instance::ModuleInstance *createModuleCPP() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "./libwasmedgePluginTestModuleCPP" WASMEDGE_LIB_EXTENSION)); + "./" WASMEDGE_LIB_PREFIX + "wasmedgePluginTestModuleCPP" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_plugintest_cpp"sv)) { WasmEdge::PO::ArgumentParser Parser; diff --git a/test/plugins/wasi_crypto/helper.h b/test/plugins/wasi_crypto/helper.h index beb1a33988f4..9feefc443fc2 100644 --- a/test/plugins/wasi_crypto/helper.h +++ b/test/plugins/wasi_crypto/helper.h @@ -63,8 +63,8 @@ class WasiCryptoTest : public ::testing::Test { using namespace std::literals::string_view_literals; Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasi_crypto/" - "libwasmedgePluginWasiCrypto" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasi_crypto/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasiCrypto" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasi_crypto"sv)) { if (const auto *Module = Plugin->findModule("wasi_crypto_asymmetric_common"sv)) { diff --git a/test/plugins/wasi_logging/wasi_logging.cpp b/test/plugins/wasi_logging/wasi_logging.cpp index d1c36c021541..a3720f2cb64a 100644 --- a/test/plugins/wasi_logging/wasi_logging.cpp +++ b/test/plugins/wasi_logging/wasi_logging.cpp @@ -14,8 +14,8 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasi_logging/" - "libwasmedgePluginWasiLogging" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasi_logging/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasiLogging" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasi_logging"sv)) { if (const auto *Module = Plugin->findModule("wasi:logging/logging"sv)) { return Module->create().release(); diff --git a/test/plugins/wasi_nn/wasi_nn.cpp b/test/plugins/wasi_nn/wasi_nn.cpp index 20287914fa8e..806c33a3f62e 100644 --- a/test/plugins/wasi_nn/wasi_nn.cpp +++ b/test/plugins/wasi_nn/wasi_nn.cpp @@ -24,9 +24,9 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance * createModule(std::string_view NNRPCURI = "") { using namespace std::literals::string_view_literals; - WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasi_nn/" - "libwasmedgePluginWasiNN" WASMEDGE_LIB_EXTENSION)); + WasmEdge::Plugin::Plugin::load( + std::filesystem::u8path("../../../plugins/wasi_nn/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasiNN" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasi_nn"sv)) { WasmEdge::PO::ArgumentParser Parser; Plugin->registerOptions(Parser); diff --git a/test/plugins/wasm_bpf/simple_map_test.cpp b/test/plugins/wasm_bpf/simple_map_test.cpp index 9a86892cc795..51ef2f5a5400 100644 --- a/test/plugins/wasm_bpf/simple_map_test.cpp +++ b/test/plugins/wasm_bpf/simple_map_test.cpp @@ -23,9 +23,9 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; - WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasm_bpf/" - "libwasmedgePluginWasmBpf" WASMEDGE_LIB_EXTENSION)); + WasmEdge::Plugin::Plugin::load( + std::filesystem::u8path("../../../plugins/wasm_bpf/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmBpf" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasm_bpf"sv)) { if (const auto *Module = Plugin->findModule("wasm_bpf"sv)) { return Module->create().release(); diff --git a/test/plugins/wasm_bpf/simple_ringbuf_test.cpp b/test/plugins/wasm_bpf/simple_ringbuf_test.cpp index f7052105263e..ac3899342c6c 100644 --- a/test/plugins/wasm_bpf/simple_ringbuf_test.cpp +++ b/test/plugins/wasm_bpf/simple_ringbuf_test.cpp @@ -19,9 +19,9 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; - WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasm_bpf/" - "libwasmedgePluginWasmBpf" WASMEDGE_LIB_EXTENSION)); + WasmEdge::Plugin::Plugin::load( + std::filesystem::u8path("../../../plugins/wasm_bpf/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmBpf" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasm_bpf"sv)) { if (const auto *Module = Plugin->findModule("wasm_bpf"sv)) { return Module->create().release(); diff --git a/test/plugins/wasm_bpf/wasm_bpf.cpp b/test/plugins/wasm_bpf/wasm_bpf.cpp index 9bf84f87bedf..3e5dbd0ee2fc 100644 --- a/test/plugins/wasm_bpf/wasm_bpf.cpp +++ b/test/plugins/wasm_bpf/wasm_bpf.cpp @@ -31,9 +31,9 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; - WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasm_bpf/" - "libwasmedgePluginWasmBpf" WASMEDGE_LIB_EXTENSION)); + WasmEdge::Plugin::Plugin::load( + std::filesystem::u8path("../../../plugins/wasm_bpf/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmBpf" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasm_bpf"sv)) { if (const auto *Module = Plugin->findModule("wasm_bpf"sv)) { return Module->create().release(); diff --git a/test/plugins/wasmedge_ffmpeg/utils.h b/test/plugins/wasmedge_ffmpeg/utils.h index 9128bacd73c4..6c95138e4274 100644 --- a/test/plugins/wasmedge_ffmpeg/utils.h +++ b/test/plugins/wasmedge_ffmpeg/utils.h @@ -59,8 +59,8 @@ class FFmpegTest : public ::testing::Test { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_ffmpeg/" - "libwasmedgePluginWasmEdgeFFmpeg" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_ffmpeg/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeFFmpeg" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_ffmpeg"sv)) { if (const auto *Module = @@ -161,4 +161,4 @@ class FFmpegTest : public ::testing::Test { }; } // namespace WasmEdgeFFmpeg } // namespace Host -} // namespace WasmEdge \ No newline at end of file +} // namespace WasmEdge diff --git a/test/plugins/wasmedge_image/wasmedge_image.cpp b/test/plugins/wasmedge_image/wasmedge_image.cpp index 0583c1c762fc..a5ea33563b82 100644 --- a/test/plugins/wasmedge_image/wasmedge_image.cpp +++ b/test/plugins/wasmedge_image/wasmedge_image.cpp @@ -17,8 +17,8 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_image/" - "libwasmedgePluginWasmEdgeImage" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_image/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeImage" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_image"sv)) { if (const auto *Module = Plugin->findModule("wasmedge_image"sv)) { return Module->create().release(); diff --git a/test/plugins/wasmedge_opencvmini/wasmedge_opencvmini.cpp b/test/plugins/wasmedge_opencvmini/wasmedge_opencvmini.cpp index 926e1330f2b6..d3b570c9d2dc 100644 --- a/test/plugins/wasmedge_opencvmini/wasmedge_opencvmini.cpp +++ b/test/plugins/wasmedge_opencvmini/wasmedge_opencvmini.cpp @@ -17,8 +17,8 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_opencvmini/" - "libwasmedgePluginWasmEdgeOpenCVMini" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_opencvmini/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeOpenCVMini" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_opencvmini"sv)) { if (const auto *Module = Plugin->findModule("wasmedge_opencvmini"sv)) { diff --git a/test/plugins/wasmedge_process/wasmedge_process.cpp b/test/plugins/wasmedge_process/wasmedge_process.cpp index 9c25f41233ed..96e66b1270d0 100644 --- a/test/plugins/wasmedge_process/wasmedge_process.cpp +++ b/test/plugins/wasmedge_process/wasmedge_process.cpp @@ -19,8 +19,8 @@ WasmEdge::Runtime::CallingFrame DummyCallFrame(nullptr, nullptr); WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_process/" - "libwasmedgePluginWasmEdgeProcess" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_process/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeProcess" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_process"sv)) { if (const auto *Module = Plugin->findModule("wasmedge_process"sv)) { diff --git a/test/plugins/wasmedge_rustls/wasmedge_rustls.cpp b/test/plugins/wasmedge_rustls/wasmedge_rustls.cpp index 1e758cf0fdc4..f34d3a7848a4 100644 --- a/test/plugins/wasmedge_rustls/wasmedge_rustls.cpp +++ b/test/plugins/wasmedge_rustls/wasmedge_rustls.cpp @@ -15,9 +15,9 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; - WasmEdge::Plugin::Plugin::load( - std::filesystem::u8path("../../../plugins/wasmedge_rustls/" - "libwasmedge_rustls" WASMEDGE_LIB_EXTENSION)); + WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( + "../../../plugins/wasmedge_rustls/" WASMEDGE_LIB_PREFIX + "wasmedge_rustls" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("rustls"sv)) { if (const auto *Module = Plugin->findModule("rustls_client"sv)) { return Module->create().release(); diff --git a/test/plugins/wasmedge_tensorflow/wasmedge_tensorflow.cpp b/test/plugins/wasmedge_tensorflow/wasmedge_tensorflow.cpp index 253ab8281741..0b0617d3c6ca 100644 --- a/test/plugins/wasmedge_tensorflow/wasmedge_tensorflow.cpp +++ b/test/plugins/wasmedge_tensorflow/wasmedge_tensorflow.cpp @@ -17,8 +17,8 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_tensorflow/" - "libwasmedgePluginWasmEdgeTensorflow" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_tensorflow/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeTensorflow" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_tensorflow"sv)) { if (const auto *Module = Plugin->findModule("wasmedge_tensorflow"sv)) { diff --git a/test/plugins/wasmedge_tensorflowlite/wasmedge_tensorflowlite.cpp b/test/plugins/wasmedge_tensorflowlite/wasmedge_tensorflowlite.cpp index b0cfa5c3b1c9..ebddf267e10e 100644 --- a/test/plugins/wasmedge_tensorflowlite/wasmedge_tensorflowlite.cpp +++ b/test/plugins/wasmedge_tensorflowlite/wasmedge_tensorflowlite.cpp @@ -17,8 +17,8 @@ namespace { WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_tensorflowlite/" - "libwasmedgePluginWasmEdgeTensorflowLite" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_tensorflowlite/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeTensorflowLite" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_tensorflowlite"sv)) { if (const auto *Module = Plugin->findModule("wasmedge_tensorflowlite"sv)) { diff --git a/test/plugins/wasmedge_zlib/wasmedge_zlib.cpp b/test/plugins/wasmedge_zlib/wasmedge_zlib.cpp index d526178ab593..1bf5bdc3d9ab 100644 --- a/test/plugins/wasmedge_zlib/wasmedge_zlib.cpp +++ b/test/plugins/wasmedge_zlib/wasmedge_zlib.cpp @@ -20,8 +20,8 @@ WasmEdge::Runtime::CallingFrame DummyCallFrame(nullptr, nullptr); WasmEdge::Runtime::Instance::ModuleInstance *createModule() { using namespace std::literals::string_view_literals; WasmEdge::Plugin::Plugin::load(std::filesystem::u8path( - "../../../plugins/wasmedge_zlib/" - "libwasmedgePluginWasmEdgeZlib" WASMEDGE_LIB_EXTENSION)); + "../../../plugins/wasmedge_zlib/" WASMEDGE_LIB_PREFIX + "wasmedgePluginWasmEdgeZlib" WASMEDGE_LIB_EXTENSION)); if (const auto *Plugin = WasmEdge::Plugin::Plugin::find("wasmedge_zlib"sv)) { if (const auto *Module = Plugin->findModule("wasmedge_zlib"sv)) { return Module->create().release(); From c06fcc46d6615c309fe8ee3fd17a02118271516c Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 2 Apr 2024 01:20:59 +0800 Subject: [PATCH 127/218] [CI] Fix the wrong package manager name Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 0bd1d1d762ca..9d8e81137f72 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -178,7 +178,7 @@ jobs: - name: Install zsh run: | eval $(/opt/homebrew/bin/brew shellenv) - ${{ matrix.package_manager }} install zsh + brew install zsh - name: Install WasmEdge latest release run: | From 7301d08f73b2543f594433c4e56f4891ee331a72 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 3 Apr 2024 08:44:48 +0800 Subject: [PATCH 128/218] [Installer] Support a pure bash script installer (#3313) * [Installer] Add the pure bash script installer - detect cuda 11 and cuda 12 for the ggml plugin - Fix the cuda detection issue on the Jetson platform - Support the rustls plugin in the pure bash installer - Use a more compact progress bar for curl (#3315) - Add the installer v2 workflow for verifying the behavior --------- Signed-off-by: hydai Signed-off-by: hydai --- .github/workflows/test-installer-v2.yml | 98 +++++ utils/install_v2.sh | 541 ++++++++++++++++++++++++ 2 files changed, 639 insertions(+) create mode 100644 .github/workflows/test-installer-v2.yml create mode 100755 utils/install_v2.sh diff --git a/.github/workflows/test-installer-v2.yml b/.github/workflows/test-installer-v2.yml new file mode 100644 index 000000000000..73653f8c5233 --- /dev/null +++ b/.github/workflows/test-installer-v2.yml @@ -0,0 +1,98 @@ +name: test-installer-v2 + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - master + paths: + - '.github/workflows/test-installer-v2.yml' + - 'utils/install_v2.sh' + - 'utils/uninstall.sh' + pull_request: + branches: + - master + paths: + - '.github/workflows/test-installer-v2.yml' + - 'utils/install_v2.sh' + - 'utils/uninstall.sh' + +jobs: + verify-installer-v2: + strategy: + fail-fast: false + matrix: + include: + - name: CentOS 9 Stream + host_runner: ubuntu-latest + docker_image: quay.io/centos/centos:stream9 + extra_setup_command: yum update -y && yum install -y which + - name: Ubuntu 20.04 + host_runner: ubuntu-latest + docker_image: ubuntu:20.04 + extra_setup_command: apt update -y && apt install -y curl + name: ${{ matrix.name }} + runs-on: ${{ matrix.host_runner }} + container: + image: ${{ matrix.docker_image }} + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup + run: | + ${{ matrix.extra_setup_command }} + - name: Run installer-v2 + run: | + # It will install WasmEdge and the GGML plugin + bash utils/install_v2.sh -V + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Re-install installer-v2 + run: | + # It should uninstall the previous installation and install WasmEdge and the GGML plugin again + bash utils/install_v2.sh -V + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Uninstall WasmEdge + run: | + bash utils/uninstall.sh -q -V + + macos: + strategy: + fail-fast: false + matrix: + include: + - name: Mac M1 + host_runner: macos-14 + - name: Mac Intel + host_runner: macos-latest + name: ${{ matrix.name }} + runs-on: ${{ matrix.host_runner }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install zsh + run: | + eval $(/opt/homebrew/bin/brew shellenv) + brew install zsh + + - name: Run installer-v2 + run: | + # It will install WasmEdge and the GGML plugin + bash utils/install_v2.sh -V + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.dylib && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Re-install installer-v2 + run: | + # It should uninstall the previous installation and install WasmEdge and the GGML plugin again + bash utils/install_v2.sh -V + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.dylib && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Uninstall WasmEdge + run: | + bash utils/uninstall.sh -q -V diff --git a/utils/install_v2.sh b/utils/install_v2.sh new file mode 100755 index 000000000000..9743307189a4 --- /dev/null +++ b/utils/install_v2.sh @@ -0,0 +1,541 @@ +#!/usr/bin/env bash + +# This is the bootstrap Unix shell script for installing WasmEdge. +# It will detect the platform and architecture, download the corresponding +# WasmEdge release package, and install it to the specified path. + +set -e + +RED=$'\e[0;31m' +GREEN=$'\e[0;32m' +YELLOW=$'\e[0;33m' +NC=$'\e[0m' # No Color +TMP_DIR="/tmp/wasmedge.$$" + +info() { + command printf '\e[0;32mInfo\e[0m: %s\n\n' "$1" +} + +warn() { + command printf '\e[0;33mWarn\e[0m: %s\n\n' "$1" +} + +error() { + command printf '\e[0;31mError\e[0m: %s\n\n' "$1" 1>&2 +} + +eprintf() { + command printf '%s\n' "$1" 1>&2 +} + +detect_cuda() { + local cuda="" + cuda=$(/usr/local/cuda/bin/nvcc --version 2>/dev/null | grep "Cuda compilation tools" | cut -f5 -d ' ' | cut -f1 -d ',') + if [[ "${cuda}" =~ "12" ]]; then + cuda="12" + elif [[ "${cuda}" =~ "11" ]]; then + cuda="11" + else + cuda=$(nvidia-smi -q 2>/dev/null | grep CUDA | cut -f2 -d ':' | cut -f2 -d ' ') + if [[ "${cuda}" =~ "12" ]]; then + cuda="12" + elif [[ "${cuda}" =~ "11" ]]; then + cuda="11" + fi + fi + + echo ${cuda} +} + +_realpath() { + [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" +} + +_downloader() { + local url=$1 + if ! command -v curl &>/dev/null; then + if ! command -v wget &>/dev/null; then + error "Cannot find wget or curl" + eprintf "Please install wget or curl" + exit 1 + else + wget -c --directory-prefix="$TMP_DIR" "$url" + fi + else + pushd "$TMP_DIR" + curl --progress-bar -L -OC0 "$url" + popd + fi +} + +_extractor() { + local prefix="$IPKG" + if ! command -v tar &>/dev/null; then + error "Cannot find tar" + eprintf "Please install tar" + exit_clean 1 + else + local opt + opt=$(tar "$@" 2>&1) + for var in $opt; do + local filtered=${var//$prefix/} + filtered=${filtered//"lib64"/"lib"} + if [[ "$filtered" =~ "x" ]]; then + continue + fi + if [ ! -d "$IPATH/$filtered" ] ; then + if [[ "$filtered" =~ "Plugin" ]] || [[ "$filtered" =~ "plugin" ]] || [[ "$filtered" =~ "ggml" ]]; then + # Plugins installation is handled in install function + continue + fi + if [[ "$2" =~ "lib" ]] && [[ ! "$IPATH/$filtered" =~ "/lib/" ]]; then + echo "#$IPATH/lib/$filtered" >>"$IPATH/env" + local _re_ + [[ "$OS" == "Linux" ]] && _re_='.[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}$' + [[ "$OS" == "Darwin" ]] && _re_='[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}.' + if [[ "$filtered" =~ $_re_ ]]; then + local _f_ _f2_ _f3_ _f4_ + _f_=${filtered//$_re_/} + _f2_=${filtered#$_f_} + _f2_=${BASH_REMATCH[*]} + + IFS=. read -r var1 var2 <<<"$(if [[ "$filtered" =~ $_re_ ]]; then + echo "${BASH_REMATCH[*]#.}" + fi)" + + _f3_=${filtered//${_f2_}/} # libsome.so.xx.yy.zz --> libsome.so + [[ "$OS" == "Linux" ]] && _f4_="$_f3_.$var1" # libsome.so.xx.yy.zz --> libsome.so.xx + [[ "$OS" == "Darwin" ]] && _f4_="${filtered//.${_f2_}dylib/}"".$var1.dylib" # libsome.xx.yy.zz.dylib --> libsome.xx.dylib + + ln -sf "$IPATH/lib/$filtered" "$IPATH/lib/$_f3_" + echo "#$IPATH/lib/$_f3_" >>"$IPATH/env" + + ln -sf "$IPATH/lib/$filtered" "$IPATH/lib/$_f4_" + echo "#$IPATH/lib/$_f4_" >>"$IPATH/env" + fi + elif [[ "$2" =~ "bin" ]] && [[ ! "$IPATH/$filtered" =~ "/bin/" ]]; then + echo "#$IPATH/bin/$filtered" >>"$IPATH/env" + else + echo "#$IPATH/$filtered" >>"$IPATH/env" + fi + fi + done + fi +} + +if [ "$__HOME__" = "" ]; then + __HOME__="$HOME" +fi + +get_latest_release() { + echo "0.13.5" +} + +VERSION=$(get_latest_release) + +check_os_arch() { + [ -z "${ARCH}" ] && ARCH=$(uname -m) + [ -z "${OS}" ] && OS=$(uname) + RELEASE_PKG="ubuntu20.04_x86_64.tar.gz" + IPKG="WasmEdge-${VERSION}-${OS}" + _LD_LIBRARY_PATH_="LD_LIBRARY_PATH" + + case ${OS} in + 'Linux') + case ${ARCH} in + 'x86_64') ARCH="x86_64";; + 'arm64' | 'armv8*' | 'aarch64') ARCH="aarch64" ;; + 'amd64') ARCH="x86_64" ;; + *) + error "Detected ${OS}-${ARCH} - currently unsupported" + eprintf "Use --OS and --ARCH to specify the OS and ARCH" + exit 1 + ;; + esac + if [ "${LEGACY}" == 1 ]; then + RELEASE_PKG="manylinux2014_${ARCH}.tar.gz" + else + RELEASE_PKG="ubuntu20.04_${ARCH}.tar.gz" + fi + _LD_LIBRARY_PATH_="LD_LIBRARY_PATH" + + ;; + 'Darwin') + case ${ARCH} in + 'x86_64') ARCH="x86_64" ;; + 'arm64' | 'arm' | 'aarch64') ARCH="arm64" ;; + *) + error "Detected ${OS}-${ARCH} - currently unsupported" + eprintf "Use --OS and --ARCH to specify the OS and ARCH" + exit 1 + ;; + esac + RELEASE_PKG="darwin_${ARCH}.tar.gz" + _LD_LIBRARY_PATH_="DYLD_LIBRARY_PATH" + + ;; + *) + error "Detected ${OS}-${ARCH} - currently unsupported" + eprintf "Use --OS and --ARCH to specify the OS and ARCH" + exit 1 + ;; + esac + + info "Detected ${OS}-${ARCH}" +} + +IPATH="$__HOME__/.wasmedge" +VERBOSE=0 +LEGACY=0 + +set_ENV() { + ENV="#!/bin/sh + # wasmedge shell setup + # affix colons on either side of \$PATH to simplify matching + case ":\"\${PATH}\":" in + *:\"$1/bin\":*) + ;; + *) + # Prepending path in case a system-installed wasmedge needs to be overridden + if [ -n \"\${PATH}\" ]; then + export PATH=\"$1/bin\":\$PATH + else + export PATH=\"$1/bin\" + fi + ;; +esac +case ":\"\${"$_LD_LIBRARY_PATH_"}\":" in + *:\"$1/lib\":*) + ;; + *) + # Prepending path in case a system-installed wasmedge libs needs to be overridden + if [ -n \"\${"$_LD_LIBRARY_PATH_"}\" ]; then + export $_LD_LIBRARY_PATH_=\"$1/lib\":\$$_LD_LIBRARY_PATH_ + else + export $_LD_LIBRARY_PATH_=\"$1/lib\" + fi + ;; +esac +case ":\"\${"LIBRARY_PATH"}\":" in + *:\"$1/lib\":*) + ;; + *) + if [ -n \"\${LIBRARY_PATH}\" ]; then + export LIBRARY_PATH=\"$1/lib\":\$LIBRARY_PATH + else + export LIBRARY_PATH=\"$1/lib\" + fi + ;; +esac +case ":\"\${"C_INCLUDE_PATH"}\":" in + *:\"$1/include\":*) + ;; + *) + if [ -n \"\${C_INCLUDE_PATH}\" ]; then + export C_INCLUDE_PATH=\"$1/include\":\$C_INCLUDE_PATH + else + export C_INCLUDE_PATH=\"$1/include\" + fi + ;; +esac +case ":\"\${"CPLUS_INCLUDE_PATH"}\":" in + *:\"$1/include\":*) + ;; + *) + if [ -n \"\${CPLUS_INCLUDE_PATH}\" ]; then + export CPLUS_INCLUDE_PATH=\"$1/include\":\$CPLUS_INCLUDE_PATH + else + export CPLUS_INCLUDE_PATH=\"$1/include\" + fi + ;; +esac" +} + +usage() { + cat < [-V] + WasmEdge installation. + Mandatory arguments to long options are mandatory for short options too. + Long options should be assigned with '=' + + -h, --help Display help + + -p, --path=[/usr/local] Prefix / Path to install + + -l, --legacy Enable legacy OS support. + For CentOS 7. + + -V, --verbose Run script in verbose mode. + Will print out each step + of execution. + + Example: + ./$0 -p $IPATH --verbose + + Or + ./$0 --path=/usr/local --verbose + + About: + + - wasmedge is the runtime that executes the wasm program or the AOT compiled + shared library format or universal wasm format programs. + +EOF +} + +on_exit() { + cat <>"$IPATH/env" + else + echo "#$IPATH/plugin/$_plugin_name_" >>"$IPATH/env" + fi + fi + done + fi + else + cp -rf "$TMP_DIR/$dir/$var"/* "$IPATH/$var" + fi + done +} + +get_wasmedge_release() { + info "Fetching WasmEdge-$VERSION" + _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-$VERSION-$RELEASE_PKG" + _extractor -C "${TMP_DIR}" -vxzf "$TMP_DIR/WasmEdge-$VERSION-$RELEASE_PKG" +} + +get_wasmedge_ggml_plugin() { + info "Fetching WasmEdge-GGML-Plugin" + local CUDA_EXT="" + cuda=$(detect_cuda) + info "Detected CUDA version: ${cuda}" + if [ "${cuda}" == "12" ]; then + CUDA_EXT="-cuda" + elif [ "${cuda}" == "11" ]; then + if [ "${ARCH}" == "aarch64" ]; then + CUDA_EXT="-cuda" + else + CUDA_EXT="-cuda-11" + fi + else + CUDA_EXT="" + fi + _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}-$VERSION-$RELEASE_PKG" + local TMP_PLUGIN_DIR="${TMP_DIR}/${IPKG}/plugin" + mkdir -p "${TMP_PLUGIN_DIR}" + _extractor -C "${TMP_PLUGIN_DIR}" -vxzf "${TMP_DIR}/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}-${VERSION}-${RELEASE_PKG}" +} + +get_wasmedge_rustls_plugin() { + info "Fetching WasmEdge-Rustls-Plugin" + _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-plugin-wasmedge_rustls-$VERSION-$RELEASE_PKG" + local TMP_PLUGIN_DIR="${TMP_DIR}/${IPKG}/plugin" + mkdir -p "${TMP_PLUGIN_DIR}" + _extractor -C "${TMP_PLUGIN_DIR}" -vxzf "${TMP_DIR}/WasmEdge-plugin-wasmedge_rustls-${VERSION}-${RELEASE_PKG}" +} + +wasmedge_checks() { + if [ "${ARCH}" == $(uname -m) ] && [ "${OS}" == $(uname) ] ; then + # Check only MAJOR.MINOR.PATCH + local version=$1 + shift + for var in "$@"; do + if [ "$var" == "" ]; then + continue + fi + local V=$("$IPATH/bin/$var" --version | sed 's/^.*[^0-9]\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/') + local V_=$(echo $version | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/') + if [ "$V" = "$V_" ]; then + echo "${GREEN}Installation of $var-$version successful${NC}" + else + echo "${YELLOW}version $V_ does not match $V for $var-$version${NC}" + exit 1 + fi + done + fi + # Bypass if cross compile +} + +main() { + + trap on_exit EXIT + + # getopt is in the util-linux package, + # it'll probably be fine, but it's of course a good thing to keep in mind. + + local OPTIND + while getopts "e:hp:v:r:u:V-:" OPT; do + # support long options: https://stackoverflow.com/a/28466267/519360 + if [ "$OPT" = "-" ]; then # long option: reformulate OPT and OPTARG + OPT="${OPTARG%%=*}" # extract long option name + OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty) + OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=` + fi + case "$OPT" in + h | help) + usage + trap - EXIT + exit 0 + ;; + l | legacy) + LEGACY=1 + ;; + v | version) + VERSION="${OPTARG}" + ;; + V | verbose) + VERBOSE=1 + ;; + p | path) + IPATH="$(_realpath "${OPTARG}")" + ;; + os) + OS="${OPTARG^}" + ;; + arch) + ARCH="${OPTARG}" + ;; + ?) + exit 2 + ;; + ??*) + error "Illegal option -- ${OPTARG}" + exit 1 + ;; + *) + error "Unknown error" + eprintf "please raise an issue on GitHub with the command you ran." + exit 1 + ;; + esac + done + + shift $((OPTIND - 1)) # remove parsed options and args from $@ list + + if [ ! $VERBOSE == 0 ]; then + echo "Verbose Mode" + set -xv + fi + + check_os_arch + + # Run the uninstaller to remove any previous installations + if [ -f "$IPATH/bin/wasmedge" ]; then + bash <(curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/uninstall.sh) -p "$IPATH" -q + fi + + set_ENV "$IPATH" + mkdir -p "$IPATH" + mkdir -p "$TMP_DIR" + # Setup the plugin folder if the installation path is not in the system path + [[ "$IPATH" =~ ^"/usr" ]] || mkdir -p "$IPATH/plugin" + + echo "$ENV" >"$IPATH/env" + echo "# Please do not edit comments below this for uninstallation purpose" >> "$IPATH/env" + + local _source="source \"$IPATH/env\"" + local _grep=$(cat "$__HOME__/.profile" 2>/dev/null | grep "$IPATH/env") + if [ "$_grep" = "" ]; then + [ -f "$__HOME__/.profile" ] && echo "$_source" >>"$__HOME__/.profile" + fi + + local _shell_ _shell_rc + _shell_="${SHELL#${SHELL%/*}/}" + _shell_rc=".""$_shell_""rc" + + if [[ "$_shell_" =~ "zsh" ]]; then + local _grep=$(cat "$__HOME__/.zprofile" 2>/dev/null | grep "$IPATH/env") + if [ "$_grep" = "" ]; then + [ -f "$__HOME__/.zprofile" ] && echo "$_source" >>"$__HOME__/.zprofile" + fi + elif [[ "$_shell_" =~ "bash" ]]; then + local _grep=$(cat "$__HOME__/.bash_profile" 2>/dev/null | grep "$IPATH/env") + if [ "$_grep" = "" ]; then + [ -f "$__HOME__/.bash_profile" ] && echo "$_source" >>"$__HOME__/.bash_profile" + fi + fi + + local _grep=$(cat "$__HOME__/$_shell_rc" | grep "$IPATH/env") + if [ "$_grep" = "" ]; then + [ -f "$__HOME__/$_shell_rc" ] && echo "$_source" >>"$__HOME__/$_shell_rc" + fi + + if [ -d "$IPATH" ]; then + info "WasmEdge Installation at $IPATH" + make_dirs "include" "lib" "bin" + + get_wasmedge_release + get_wasmedge_ggml_plugin + get_wasmedge_rustls_plugin + install "$IPKG" "include" "lib" "bin" "plugin" + wasmedge_checks "$VERSION" "wasmedge" + else + error "Installation path invalid" + eprintf "Please provide a valid path" + exit 1 + fi + + trap - EXIT + cleanup + end_message +} + +end_message() { + case ":${PATH}:" in + *:"${IPATH%"/"}/bin":*) + echo "${GREEN}WasmEdge binaries accessible${NC}" + ;; + *) + echo "${GREEN}source $IPATH/env${NC} to use wasmedge binaries" + ;; + esac +} + +main "$@" From d14146f0f432317a7be2e2b68b013470bbf02eac Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 3 Apr 2024 11:07:43 +0800 Subject: [PATCH 129/218] [Example] Fix the get-string plugin example. Signed-off-by: YiYing He --- examples/plugin/get-string/getstring.cpp | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/plugin/get-string/getstring.cpp b/examples/plugin/get-string/getstring.cpp index 8dcc274ac870..1335c9cd3a32 100644 --- a/examples/plugin/get-string/getstring.cpp +++ b/examples/plugin/get-string/getstring.cpp @@ -78,22 +78,22 @@ create(const Plugin::PluginModule::ModuleDescriptor *) noexcept { } Plugin::Plugin::PluginDescriptor Descriptor{ - .Name = "plugin_name", - .Description = "Example plugin", - .APIVersion = Plugin::Plugin::CurrentAPIVersion, - .Version = {0, 13, 4, 0}, - .ModuleCount = 1, - .ModuleDescriptions = - (Plugin::PluginModule::ModuleDescriptor[]){ - { - .Name = "module_name", - .Description = "Example module", - .Create = create, - }, + /* Name */ "plugin_name", + /* Description */ "Example plugin", + /* APIVersion */ Plugin::Plugin::CurrentAPIVersion, + /* Version */ {0, 13, 5, 0}, + /* ModuleCount */ 1, + /* ModuleDescriptions */ + (Plugin::PluginModule::ModuleDescriptor[]){ + { + /* Name */ "module_name", + /* Description */ "Example module", + /* Create */ create, }, - .AddOptions = addOptions, + }, + /* AddOptions */ addOptions, }; -Plugin::PluginRegister Register(&Descriptor); +EXPORT_GET_DESCRIPTOR(Descriptor) } // namespace From c6b1ff2f357c0bdcb6f2c7cf4068e35f8aec06fe Mon Sep 17 00:00:00 2001 From: YiYing He Date: Fri, 29 Mar 2024 03:48:13 +0800 Subject: [PATCH 130/218] [Serializer] Fix multi-byte opcode serialization. Signed-off-by: YiYing He --- lib/loader/serialize/serial_instruction.cpp | 22 ++++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/loader/serialize/serial_instruction.cpp b/lib/loader/serialize/serial_instruction.cpp index 5be7b130bd8a..f029b105d7db 100644 --- a/lib/loader/serialize/serial_instruction.cpp +++ b/lib/loader/serialize/serial_instruction.cpp @@ -6,15 +6,6 @@ namespace WasmEdge { namespace Loader { -namespace { -void serializeOpCode(OpCode Code, std::vector &OutVec) { - if (static_cast(Code) >= 0x100U) { - OutVec.push_back(static_cast(Code) >> 8); - } - OutVec.push_back(static_cast(Code) & 0xFFU); -} -} // namespace - // Serialize instruction. See "include/loader/serialize.h". Expect Serializer::serializeInstruction(const AST::Instruction &Instr, @@ -40,9 +31,6 @@ Serializer::serializeInstruction(const AST::Instruction &Instr, return {}; }; - // Instruction: OpCode + immediate. - serializeOpCode(Instr.getOpCode(), OutVec); - // Check with proposals. if (auto Res = Conf.isInstrNeedProposal(Instr.getOpCode()); unlikely(Res.has_value())) { @@ -50,6 +38,16 @@ Serializer::serializeInstruction(const AST::Instruction &Instr, ASTNodeAttr::Instruction); } + // Serialize OpCode. + uint32_t Num = static_cast(Instr.getOpCode()); + if (Num >= 0x100U) { + OutVec.push_back(static_cast(Num >> 8)); + serializeU32(Num & 0xFFU, OutVec); + } else { + OutVec.push_back(static_cast(Num & 0xFFU)); + } + + // Serialize immediate. switch (Instr.getOpCode()) { // Control instructions. case OpCode::Unreachable: From 769f01d509233325cee7720424696257466165e2 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 3 Apr 2024 19:38:06 +0800 Subject: [PATCH 131/218] [Installer] v2: disable rustls by default. Enable it via --rustls option (#3324) --- utils/install_v2.sh | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/utils/install_v2.sh b/utils/install_v2.sh index 9743307189a4..3d84b3b75d24 100755 --- a/utils/install_v2.sh +++ b/utils/install_v2.sh @@ -148,7 +148,7 @@ check_os_arch() { 'amd64') ARCH="x86_64" ;; *) error "Detected ${OS}-${ARCH} - currently unsupported" - eprintf "Use --OS and --ARCH to specify the OS and ARCH" + eprintf "Use --os and --arch to specify the OS and ARCH" exit 1 ;; esac @@ -166,7 +166,7 @@ check_os_arch() { 'arm64' | 'arm' | 'aarch64') ARCH="arm64" ;; *) error "Detected ${OS}-${ARCH} - currently unsupported" - eprintf "Use --OS and --ARCH to specify the OS and ARCH" + eprintf "Use --os and --arch to specify the OS and ARCH" exit 1 ;; esac @@ -176,7 +176,7 @@ check_os_arch() { ;; *) error "Detected ${OS}-${ARCH} - currently unsupported" - eprintf "Use --OS and --ARCH to specify the OS and ARCH" + eprintf "Use --os and --arch to specify the OS and ARCH" exit 1 ;; esac @@ -187,6 +187,7 @@ check_os_arch() { IPATH="$__HOME__/.wasmedge" VERBOSE=0 LEGACY=0 +ENABLE_RUSTLS=0 set_ENV() { ENV="#!/bin/sh @@ -260,15 +261,26 @@ usage() { -h, --help Display help - -p, --path=[/usr/local] Prefix / Path to install + --legacy Enable legacy OS support. + E.g., CentOS 7. - -l, --legacy Enable legacy OS support. - For CentOS 7. + -v, --version Install the specific version. -V, --verbose Run script in verbose mode. Will print out each step of execution. + -p, --path=[/usr/local] Prefix / Path to install + + --rustls Install the Rustls plugin. + Default is disabled. + + --os=[Linux/Darwin] Set the OS. + Default is detected OS. + + --arch[x86_64/aarch64/arm64] Set the ARCH. + Default is detected ARCH. + Example: ./$0 -p $IPATH --verbose @@ -436,6 +448,9 @@ main() { p | path) IPATH="$(_realpath "${OPTARG}")" ;; + rustls) + ENABLE_RUSTLS=1 + ;; os) OS="${OPTARG^}" ;; @@ -513,7 +528,11 @@ main() { get_wasmedge_release get_wasmedge_ggml_plugin - get_wasmedge_rustls_plugin + + if [ "${ENABLE_RUSTLS}" == 1 ]; then + get_wasmedge_rustls_plugin + fi + install "$IPKG" "include" "lib" "bin" "plugin" wasmedge_checks "$VERSION" "wasmedge" else From d98ad2f658c6a8e685028ea99c427723b5030e59 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 3 Apr 2024 14:25:20 +0800 Subject: [PATCH 132/218] [Changelog] Update the changelog for the 0.14.0-rc.4 pre-release. Signed-off-by: YiYing He --- .CurrentChangelog.md | 10 ++++++---- Changelog.md | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index edfed58592c2..c18eae1b3db7 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.3 (2024-03-22) +### 0.14.0-rc.4 (2024-04-03) Breaking changes: @@ -73,7 +73,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2479. + * Bump llama.cpp to b2534. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -90,6 +90,7 @@ Features: * Add `mmproj` option to set the projection model. * Add `image` option to set the image. * Support embedding generation. + * Support Windows build. * [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. Fixed issues: @@ -116,8 +117,9 @@ Fixed issues: Tests: -* Updated the WASM spec tests to the date 2023/10/26. +* Updated the WASM spec tests to the date 2024/02/17. * Added the spec tests for the Typed Function Reference proposal. +* Added the spec tests for the GC proposal. Known issues: @@ -129,4 +131,4 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 301a274a4363..c4291d54e4c4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.3 (2024-03-22) +### 0.14.0-rc.4 (2024-04-03) Breaking changes: @@ -73,7 +73,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2479. + * Bump llama.cpp to b2534. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -90,6 +90,7 @@ Features: * Add `mmproj` option to set the projection model. * Add `image` option to set the image. * Support embedding generation. + * Support Windows build. * [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. Fixed issues: @@ -116,8 +117,9 @@ Fixed issues: Tests: -* Updated the WASM spec tests to the date 2023/10/26. +* Updated the WASM spec tests to the date 2024/02/17. * Added the spec tests for the Typed Function Reference proposal. +* Added the spec tests for the GC proposal. Known issues: @@ -129,7 +131,7 @@ Thank all the contributors who made this release possible! Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.3-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 95d7530e56a4b2c2935d61e5b7ac3ee57c56b432 Mon Sep 17 00:00:00 2001 From: dm4 Date: Tue, 2 Apr 2024 22:44:51 +0800 Subject: [PATCH 133/218] [WASI-NN] ggml: support grammar Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 12 ++++++++++++ plugins/wasi_nn/ggml.h | 1 + 2 files changed, 13 insertions(+) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 43afec1df6a9..79d823c943dd 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -254,6 +254,16 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, return ErrNo::InvalidArgument; } } + if (Doc.at_key("grammar").error() == simdjson::SUCCESS) { + std::string_view Grammar; + auto Err = Doc["grammar"].get().get(Grammar); + if (Err) { + spdlog::error( + "[WASI-NN] GGML backend: Unable to retrieve the grammar option."sv); + return ErrNo::InvalidArgument; + } + GraphRef.Grammar = Grammar; + } // Check if the model is updated. if (IsModelUpdated && ModelParams.n_gpu_layers != GraphRef.NGPULayers) { @@ -269,6 +279,7 @@ Expect setupGPTParam(Graph &GraphRef, gpt_params &GPTParams) { GPTParams.sparams.penalty_repeat = static_cast(GraphRef.RepeatPenalty); GPTParams.sparams.penalty_present = static_cast(GraphRef.PresencePenalty); + GPTParams.sparams.grammar = GraphRef.Grammar; return ErrNo::Success; } @@ -590,6 +601,7 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, GraphRef.RepeatPenalty = SamplingDefault.penalty_repeat; GraphRef.PresencePenalty = SamplingDefault.penalty_present; GraphRef.FrequencyPenalty = SamplingDefault.penalty_freq; + GraphRef.Grammar = SamplingDefault.grammar; // If the graph builder length > 1, the data of builder[1] is the metadata. if (Builders.size() > 1) { diff --git a/plugins/wasi_nn/ggml.h b/plugins/wasi_nn/ggml.h index 67c70fcc30fd..f8978d2985d0 100644 --- a/plugins/wasi_nn/ggml.h +++ b/plugins/wasi_nn/ggml.h @@ -45,6 +45,7 @@ struct Graph { double RepeatPenalty = 1.10; double PresencePenalty = 0.00; double FrequencyPenalty = 0.00; + std::string Grammar; }; struct Context { From dd6165430491b45dea84bc60f79d3b8bbf1679ca Mon Sep 17 00:00:00 2001 From: redismongo <166003694+redismongo@users.noreply.github.com> Date: Fri, 5 Apr 2024 01:54:44 +0800 Subject: [PATCH 134/218] [Misc] chore: remove repetitive word (#3325) Signed-off-by: redismongo --- thirdparty/blake3/blake3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thirdparty/blake3/blake3.c b/thirdparty/blake3/blake3.c index 692f4b021648..4d4d89f56d31 100644 --- a/thirdparty/blake3/blake3.c +++ b/thirdparty/blake3/blake3.c @@ -427,7 +427,7 @@ INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) { // of the whole tree, and it would need to be ROOT finalized. We can't // compress it until we know. // 2) This 64 KiB input might complete a larger tree, whose root node is -// similarly going to be the the root of the whole tree. For example, maybe +// similarly going to be the root of the whole tree. For example, maybe // we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the // node at the root of the 256 KiB subtree until we know how to finalize it. // From 85a1934674fa3fbc874abc55132128656b68a4a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 03:36:50 +0800 Subject: [PATCH 135/218] [CI] Bump undici from 5.28.3 to 5.28.4 in /.github/actions/expand-variables (#3326) Bumps [undici](https://github.com/nodejs/undici) from 5.28.3 to 5.28.4. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v5.28.3...v5.28.4) --- updated-dependencies: - dependency-name: undici dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/expand-variables/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/expand-variables/package-lock.json b/.github/actions/expand-variables/package-lock.json index b49a4ecf905d..0fc98f445bfb 100644 --- a/.github/actions/expand-variables/package-lock.json +++ b/.github/actions/expand-variables/package-lock.json @@ -195,9 +195,9 @@ } }, "node_modules/undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dependencies": { "@fastify/busboy": "^2.0.0" }, From e290b42beacb67bd38442b2cccafe68aadd02bc8 Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 10 Apr 2024 15:11:02 +0800 Subject: [PATCH 136/218] [WASI-NN] ggml: update ggml to b2636 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 77b977891e9c..17e995559fd5 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -62,7 +62,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2534 + GIT_TAG b2636 PATCH_COMMAND git checkout . COMMAND git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch GIT_SHALLOW FALSE From 63e90f5c7c84377b7f97b8cff9973c7b91bc7305 Mon Sep 17 00:00:00 2001 From: dm4 Date: Fri, 12 Apr 2024 12:44:59 +0800 Subject: [PATCH 137/218] [WASI-NN] ggml: fix embedding with batch decode Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 68 ++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 79d823c943dd..c6fd6a410e8d 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -370,6 +370,57 @@ ErrNo evaluateTokens(Graph &GraphRef, struct llama_context *LlamaContext, return ErrNo::Success; } +void batchAddSeq(llama_batch &Batch, const std::vector &Tokens, + llama_seq_id SequenceId) noexcept { + for (int I = 0; I < static_cast(Tokens.size()); I++) { + // llama_batch_add_seq(llama_batch, llama_token, llama_pos, + // std::vector, logits); + llama_batch_add(Batch, Tokens[I], I, {SequenceId}, + I == static_cast(Tokens.size()) - 1); + } +} + +ErrNo batchDecode(llama_context *LlamaContext, llama_batch &Batch, + float *Output, int NEmbd) noexcept { + // Clear previous kv_cache values (irrelevant for embeddings) + llama_kv_cache_clear(LlamaContext); + + // Decode the batch. + auto Status = llama_decode(LlamaContext, Batch); + if (Status == 1) { + spdlog::error( + "[WASI-NN] GGML backend: failed to llama_decode: try reducing the size of the batch or increasing the size of context"sv); + return ErrNo::RuntimeError; + } else if (Status < 0) { + spdlog::error( + "[WASI-NN] GGML backend: failed to llama_decode: internal fatal error. Please open an issue on GitHub"sv); + return ErrNo::RuntimeError; + } + + for (int I = 0; I < Batch.n_tokens; I++) { + if (!Batch.logits[I]) { + continue; + } + + // Try to get sequence embeddings. + auto *Embd = llama_get_embeddings_seq(LlamaContext, Batch.seq_id[I][0]); + if (Embd == nullptr) { + Embd = llama_get_embeddings_ith(LlamaContext, I); + if (Embd == nullptr) { + spdlog::error( + "[WASI-NN] GGML backend: failed to get embeddings for token {}"sv, + I); + continue; + } + } + + // Normalize the embeddings. + llama_embd_normalize(Embd, Output, NEmbd); + } + + return ErrNo::Success; +} + Expect getEmbedding(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { auto &CxtRef = Env.NNContext[ContextId].get(); @@ -405,8 +456,6 @@ Expect getEmbedding(WasiNNEnvironment &Env, auto *LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); - // Prepare variables; - int32_t NPast = 0; // Get the context size. const uint64_t NCtx = llama_n_ctx(LlamaContext); // Minus 4 for the special tokens. (Such as , , ... tokens.) @@ -436,19 +485,18 @@ Expect getEmbedding(WasiNNEnvironment &Env, return ErrNo::PromptTooLong; } - // Evaluate input tokens. - ReturnCode = evaluateTokens(GraphRef, LlamaContext, - std::move(CxtRef.LlamaInputs), NPast); + const int32_t NEmbd = llama_n_embd(GraphRef.LlamaModel); + struct llama_batch Batch = + llama_batch_init(GraphRef.BatchSize, /* embd */ 0, /* n_seq_max */ 1); + std::vector Embeddings(NEmbd); + batchAddSeq(Batch, CxtRef.LlamaInputs, SequenceId); + ReturnCode = batchDecode(LlamaContext, Batch, Embeddings.data(), NEmbd); if (ReturnCode != ErrNo::Success) { spdlog::error("[WASI-NN] GGML backend: failed to evaluate input tokens."sv); return ReturnCode; } - const int32_t NEmbd = llama_n_embd(GraphRef.LlamaModel); - auto *Embeddings = llama_get_embeddings_seq(LlamaContext, SequenceId); - llama_embd_normalize(Embeddings, Embeddings, NEmbd); - - buildOutputEmbedding(CxtRef.LlamaOutputs, NEmbd, Embeddings); + buildOutputEmbedding(CxtRef.LlamaOutputs, NEmbd, Embeddings.data()); if (GraphRef.EnableDebugLog) { spdlog::info( From 7211fdabef4f62e83f3a1dd353afe9171ebabdcf Mon Sep 17 00:00:00 2001 From: dm4 Date: Mon, 15 Apr 2024 21:48:05 +0800 Subject: [PATCH 138/218] [WASI-NN] ggml: fix input size checking of computeSingle (#3336) --- plugins/wasi_nn/ggml.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index c6fd6a410e8d..f85b2b68e9f3 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -1151,13 +1151,15 @@ Expect computeSingle(WasiNNEnvironment &Env, if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: computeSingleToken"sv); } - if (CxtRef.LlamaInputs.size() == 0) { - spdlog::error("[WASI-NN] GGML backend: Llama input is not set!"sv); - return ErrNo::InvalidArgument; - } // New compute single token context. if (CxtRef.LlamaContext == nullptr) { + // Check if the input is set before setting up the context. + if (CxtRef.LlamaInputs.size() == 0) { + spdlog::error("[WASI-NN] GGML backend: Llama input is not set!"sv); + return ErrNo::InvalidArgument; + } + // Clear the outputs. if (GraphRef.EnableDebugLog) { spdlog::info( From 161548aa50f0786059559f44ab30145230b3f749 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 10 Apr 2024 17:49:55 +0800 Subject: [PATCH 139/218] [Common] Refactor the OpCode. 1. Internal OpCode enum doesn't use the real binary now. 2. For the loader, convert the binary into enum. 3. For the serializer, convert the enum back into the binary. Signed-off-by: YiYing He --- include/common/enum.inc | 1181 ++++++++++--------- include/common/enum_ast.hpp | 28 +- lib/loader/ast/instruction.cpp | 119 +- lib/loader/serialize/serial_instruction.cpp | 44 +- 4 files changed, 768 insertions(+), 604 deletions(-) diff --git a/include/common/enum.inc b/include/common/enum.inc index 4bb4c50c716b..7fe9bc816db6 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -85,605 +85,628 @@ A(Sec_AOT, "aot section") #ifdef UseOpCode #define O Line +#define OFB Line_FB +#define OFC Line_FC +#define OFD Line_FD +#define OFE Line_FE + +// OpCode: +// NAME | STRING | CODE [ | EXTEND ] // Control instructions (part 1) -O(Unreachable, 0x00, "unreachable") -O(Nop, 0x01, "nop") -O(Block, 0x02, "block") -O(Loop, 0x03, "loop") -O(If, 0x04, "if") -O(Else, 0x05, "else") -O(End, 0x0B, "end") -O(Br, 0x0C, "br") -O(Br_if, 0x0D, "br_if") -O(Br_table, 0x0E, "br_table") -O(Return, 0x0F, "return") -O(Call, 0x10, "call") -O(Call_indirect, 0x11, "call_indirect") -O(Return_call, 0x12, "return_call") -O(Return_call_indirect, 0x13, "return_call_indirect") -O(Call_ref, 0x14, "call_ref") -O(Return_call_ref, 0x15, "return_call_ref") +O(Unreachable, "unreachable", 0x00) +O(Nop, "nop", 0x01) +O(Block, "block", 0x02) +O(Loop, "loop", 0x03) +O(If, "if", 0x04) +O(Else, "else", 0x05) +// 0x06 ~ 0x0A: Reserved +O(End, "end", 0x0B) +O(Br, "br", 0x0C) +O(Br_if, "br_if", 0x0D) +O(Br_table, "br_table", 0x0E) +O(Return, "return", 0x0F) +O(Call, "call", 0x10) +O(Call_indirect, "call_indirect", 0x11) +O(Return_call, "return_call", 0x12) +O(Return_call_indirect, "return_call_indirect", 0x13) +O(Call_ref, "call_ref", 0x14) +O(Return_call_ref, "return_call_ref", 0x15) +// 0x16 ~ 0x19: Reserved // Parametric Instructions -O(Drop, 0x1A, "drop") -O(Select, 0x1B, "select") -O(Select_t, 0x1C, "select") +O(Drop, "drop", 0x1A) +O(Select, "select", 0x1B) +O(Select_t, "select", 0x1C) +// 0x1D ~ 0x1F: Reserved // Variable Instructions -O(Local__get, 0x20, "local.get") -O(Local__set, 0x21, "local.set") -O(Local__tee, 0x22, "local.tee") -O(Global__get, 0x23, "global.get") -O(Global__set, 0x24, "global.set") +O(Local__get, "local.get", 0x20) +O(Local__set, "local.set", 0x21) +O(Local__tee, "local.tee", 0x22) +O(Global__get, "global.get", 0x23) +O(Global__set, "global.set", 0x24) // Table Instructions (part 1) -O(Table__get, 0x25, "table.get") -O(Table__set, 0x26, "table.set") +O(Table__get, "table.get", 0x25) +O(Table__set, "table.set", 0x26) +// 0x27: Reserved // Memory Instructions (part 1) -O(I32__load, 0x28, "i32.load") -O(I64__load, 0x29, "i64.load") -O(F32__load, 0x2A, "f32.load") -O(F64__load, 0x2B, "f64.load") -O(I32__load8_s, 0x2C, "i32.load8_s") -O(I32__load8_u, 0x2D, "i32.load8_u") -O(I32__load16_s, 0x2E, "i32.load16_s") -O(I32__load16_u, 0x2F, "i32.load16_u") -O(I64__load8_s, 0x30, "i64.load8_s") -O(I64__load8_u, 0x31, "i64.load8_u") -O(I64__load16_s, 0x32, "i64.load16_s") -O(I64__load16_u, 0x33, "i64.load16_u") -O(I64__load32_s, 0x34, "i64.load32_s") -O(I64__load32_u, 0x35, "i64.load32_u") -O(I32__store, 0x36, "i32.store") -O(I64__store, 0x37, "i64.store") -O(F32__store, 0x38, "f32.store") -O(F64__store, 0x39, "f64.store") -O(I32__store8, 0x3A, "i32.store8") -O(I32__store16, 0x3B, "i32.store16") -O(I64__store8, 0x3C, "i64.store8") -O(I64__store16, 0x3D, "i64.store16") -O(I64__store32, 0x3E, "i64.store32") -O(Memory__size, 0x3F, "memory.size") -O(Memory__grow, 0x40, "memory.grow") +O(I32__load, "i32.load", 0x28) +O(I64__load, "i64.load", 0x29) +O(F32__load, "f32.load", 0x2A) +O(F64__load, "f64.load", 0x2B) +O(I32__load8_s, "i32.load8_s", 0x2C) +O(I32__load8_u, "i32.load8_u", 0x2D) +O(I32__load16_s, "i32.load16_s", 0x2E) +O(I32__load16_u, "i32.load16_u", 0x2F) +O(I64__load8_s, "i64.load8_s", 0x30) +O(I64__load8_u, "i64.load8_u", 0x31) +O(I64__load16_s, "i64.load16_s", 0x32) +O(I64__load16_u, "i64.load16_u", 0x33) +O(I64__load32_s, "i64.load32_s", 0x34) +O(I64__load32_u, "i64.load32_u", 0x35) +O(I32__store, "i32.store", 0x36) +O(I64__store, "i64.store", 0x37) +O(F32__store, "f32.store", 0x38) +O(F64__store, "f64.store", 0x39) +O(I32__store8, "i32.store8", 0x3A) +O(I32__store16, "i32.store16", 0x3B) +O(I64__store8, "i64.store8", 0x3C) +O(I64__store16, "i64.store16", 0x3D) +O(I64__store32, "i64.store32", 0x3E) +O(Memory__size, "memory.size", 0x3F) +O(Memory__grow, "memory.grow", 0x40) // Const numeric instructions -O(I32__const, 0x41, "i32.const") -O(I64__const, 0x42, "i64.const") -O(F32__const, 0x43, "f32.const") -O(F64__const, 0x44, "f64.const") +O(I32__const, "i32.const", 0x41) +O(I64__const, "i64.const", 0x42) +O(F32__const, "f32.const", 0x43) +O(F64__const, "f64.const", 0x44) // Numeric instructions -O(I32__eqz, 0x45, "i32.eqz") -O(I32__eq, 0x46, "i32.eq") -O(I32__ne, 0x47, "i32.ne") -O(I32__lt_s, 0x48, "i32.lt_s") -O(I32__lt_u, 0x49, "i32.lt_u") -O(I32__gt_s, 0x4A, "i32.gt_s") -O(I32__gt_u, 0x4B, "i32.gt_u") -O(I32__le_s, 0x4C, "i32.le_s") -O(I32__le_u, 0x4D, "i32.le_u") -O(I32__ge_s, 0x4E, "i32.ge_s") -O(I32__ge_u, 0x4F, "i32.ge_u") -O(I64__eqz, 0x50, "i64.eqz") -O(I64__eq, 0x51, "i64.eq") -O(I64__ne, 0x52, "i64.ne") -O(I64__lt_s, 0x53, "i64.lt_s") -O(I64__lt_u, 0x54, "i64.lt_u") -O(I64__gt_s, 0x55, "i64.gt_s") -O(I64__gt_u, 0x56, "i64.gt_u") -O(I64__le_s, 0x57, "i64.le_s") -O(I64__le_u, 0x58, "i64.le_u") -O(I64__ge_s, 0x59, "i64.ge_s") -O(I64__ge_u, 0x5A, "i64.ge_u") -O(F32__eq, 0x5B, "f32.eq") -O(F32__ne, 0x5C, "f32.ne") -O(F32__lt, 0x5D, "f32.lt") -O(F32__gt, 0x5E, "f32.gt") -O(F32__le, 0x5F, "f32.le") -O(F32__ge, 0x60, "f32.ge") -O(F64__eq, 0x61, "f64.eq") -O(F64__ne, 0x62, "f64.ne") -O(F64__lt, 0x63, "f64.lt") -O(F64__gt, 0x64, "f64.gt") -O(F64__le, 0x65, "f64.le") -O(F64__ge, 0x66, "f64.ge") -O(I32__clz, 0x67, "i32.clz") -O(I32__ctz, 0x68, "i32.ctz") -O(I32__popcnt, 0x69, "i32.popcnt") -O(I32__add, 0x6A, "i32.add") -O(I32__sub, 0x6B, "i32.sub") -O(I32__mul, 0x6C, "i32.mul") -O(I32__div_s, 0x6D, "i32.div_s") -O(I32__div_u, 0x6E, "i32.div_u") -O(I32__rem_s, 0x6F, "i32.rem_s") -O(I32__rem_u, 0x70, "i32.rem_u") -O(I32__and, 0x71, "i32.and") -O(I32__or, 0x72, "i32.or") -O(I32__xor, 0x73, "i32.xor") -O(I32__shl, 0x74, "i32.shl") -O(I32__shr_s, 0x75, "i32.shr_s") -O(I32__shr_u, 0x76, "i32.shr_u") -O(I32__rotl, 0x77, "i32.rotl") -O(I32__rotr, 0x78, "i32.rotr") -O(I64__clz, 0x79, "i64.clz") -O(I64__ctz, 0x7a, "i64.ctz") -O(I64__popcnt, 0x7b, "i64.popcnt") -O(I64__add, 0x7c, "i64.add") -O(I64__sub, 0x7d, "i64.sub") -O(I64__mul, 0x7e, "i64.mul") -O(I64__div_s, 0x7f, "i64.div_s") -O(I64__div_u, 0x80, "i64.div_u") -O(I64__rem_s, 0x81, "i64.rem_s") -O(I64__rem_u, 0x82, "i64.rem_u") -O(I64__and, 0x83, "i64.and") -O(I64__or, 0x84, "i64.or") -O(I64__xor, 0x85, "i64.xor") -O(I64__shl, 0x86, "i64.shl") -O(I64__shr_s, 0x87, "i64.shr_s") -O(I64__shr_u, 0x88, "i64.shr_u") -O(I64__rotl, 0x89, "i64.rotl") -O(I64__rotr, 0x8A, "i64.rotr") -O(F32__abs, 0x8B, "f32.abs") -O(F32__neg, 0x8C, "f32.neg") -O(F32__ceil, 0x8D, "f32.ceil") -O(F32__floor, 0x8E, "f32.floor") -O(F32__trunc, 0x8F, "f32.trunc") -O(F32__nearest, 0x90, "f32.nearest") -O(F32__sqrt, 0x91, "f32.sqrt") -O(F32__add, 0x92, "f32.add") -O(F32__sub, 0x93, "f32.sub") -O(F32__mul, 0x94, "f32.mul") -O(F32__div, 0x95, "f32.div") -O(F32__min, 0x96, "f32.min") -O(F32__max, 0x97, "f32.max") -O(F32__copysign, 0x98, "f32.copysign") -O(F64__abs, 0x99, "f64.abs") -O(F64__neg, 0x9A, "f64.neg") -O(F64__ceil, 0x9B, "f64.ceil") -O(F64__floor, 0x9C, "f64.floor") -O(F64__trunc, 0x9D, "f64.trunc") -O(F64__nearest, 0x9E, "f64.nearest") -O(F64__sqrt, 0x9F, "f64.sqrt") -O(F64__add, 0xA0, "f64.add") -O(F64__sub, 0xA1, "f64.sub") -O(F64__mul, 0xA2, "f64.mul") -O(F64__div, 0xA3, "f64.div") -O(F64__min, 0xA4, "f64.min") -O(F64__max, 0xA5, "f64.max") -O(F64__copysign, 0xA6, "f64.copysign") -O(I32__wrap_i64, 0xA7, "i32.wrap_i64") -O(I32__trunc_f32_s, 0xA8, "i32.trunc_f32_s") -O(I32__trunc_f32_u, 0xA9, "i32.trunc_f32_u") -O(I32__trunc_f64_s, 0xAA, "i32.trunc_f64_s") -O(I32__trunc_f64_u, 0xAB, "i32.trunc_f64_u") -O(I64__extend_i32_s, 0xAC, "i64.extend_i32_s") -O(I64__extend_i32_u, 0xAD, "i64.extend_i32_u") -O(I64__trunc_f32_s, 0xAE, "i64.trunc_f32_s") -O(I64__trunc_f32_u, 0xAF, "i64.trunc_f32_u") -O(I64__trunc_f64_s, 0xB0, "i64.trunc_f64_s") -O(I64__trunc_f64_u, 0xB1, "i64.trunc_f64_u") -O(F32__convert_i32_s, 0xB2, "f32.convert_i32_s") -O(F32__convert_i32_u, 0xB3, "f32.convert_i32_u") -O(F32__convert_i64_s, 0xB4, "f32.convert_i64_s") -O(F32__convert_i64_u, 0xB5, "f32.convert_i64_u") -O(F32__demote_f64, 0xB6, "f32.demote_f64") -O(F64__convert_i32_s, 0xB7, "f64.convert_i32_s") -O(F64__convert_i32_u, 0xB8, "f64.convert_i32_u") -O(F64__convert_i64_s, 0xB9, "f64.convert_i64_s") -O(F64__convert_i64_u, 0xBA, "f64.convert_i64_u") -O(F64__promote_f32, 0xBB, "f64.promote_f32") -O(I32__reinterpret_f32, 0xBC, "i32.reinterpret_f32") -O(I64__reinterpret_f64, 0xBD, "i64.reinterpret_f64") -O(F32__reinterpret_i32, 0xBE, "f32.reinterpret_i32") -O(F64__reinterpret_i64, 0xBF, "f64.reinterpret_i64") -O(I32__extend8_s, 0xC0, "i32.extend8_s") -O(I32__extend16_s, 0xC1, "i32.extend16_s") -O(I64__extend8_s, 0xC2, "i64.extend8_s") -O(I64__extend16_s, 0xC3, "i64.extend16_s") -O(I64__extend32_s, 0xC4, "i64.extend32_s") +O(I32__eqz, "i32.eqz", 0x45) +O(I32__eq, "i32.eq", 0x46) +O(I32__ne, "i32.ne", 0x47) +O(I32__lt_s, "i32.lt_s", 0x48) +O(I32__lt_u, "i32.lt_u", 0x49) +O(I32__gt_s, "i32.gt_s", 0x4A) +O(I32__gt_u, "i32.gt_u", 0x4B) +O(I32__le_s, "i32.le_s", 0x4C) +O(I32__le_u, "i32.le_u", 0x4D) +O(I32__ge_s, "i32.ge_s", 0x4E) +O(I32__ge_u, "i32.ge_u", 0x4F) +O(I64__eqz, "i64.eqz", 0x50) +O(I64__eq, "i64.eq", 0x51) +O(I64__ne, "i64.ne", 0x52) +O(I64__lt_s, "i64.lt_s", 0x53) +O(I64__lt_u, "i64.lt_u", 0x54) +O(I64__gt_s, "i64.gt_s", 0x55) +O(I64__gt_u, "i64.gt_u", 0x56) +O(I64__le_s, "i64.le_s", 0x57) +O(I64__le_u, "i64.le_u", 0x58) +O(I64__ge_s, "i64.ge_s", 0x59) +O(I64__ge_u, "i64.ge_u", 0x5A) +O(F32__eq, "f32.eq", 0x5B) +O(F32__ne, "f32.ne", 0x5C) +O(F32__lt, "f32.lt", 0x5D) +O(F32__gt, "f32.gt", 0x5E) +O(F32__le, "f32.le", 0x5F) +O(F32__ge, "f32.ge", 0x60) +O(F64__eq, "f64.eq", 0x61) +O(F64__ne, "f64.ne", 0x62) +O(F64__lt, "f64.lt", 0x63) +O(F64__gt, "f64.gt", 0x64) +O(F64__le, "f64.le", 0x65) +O(F64__ge, "f64.ge", 0x66) +O(I32__clz, "i32.clz", 0x67) +O(I32__ctz, "i32.ctz", 0x68) +O(I32__popcnt, "i32.popcnt", 0x69) +O(I32__add, "i32.add", 0x6A) +O(I32__sub, "i32.sub", 0x6B) +O(I32__mul, "i32.mul", 0x6C) +O(I32__div_s, "i32.div_s", 0x6D) +O(I32__div_u, "i32.div_u", 0x6E) +O(I32__rem_s, "i32.rem_s", 0x6F) +O(I32__rem_u, "i32.rem_u", 0x70) +O(I32__and, "i32.and", 0x71) +O(I32__or, "i32.or", 0x72) +O(I32__xor, "i32.xor", 0x73) +O(I32__shl, "i32.shl", 0x74) +O(I32__shr_s, "i32.shr_s", 0x75) +O(I32__shr_u, "i32.shr_u", 0x76) +O(I32__rotl, "i32.rotl", 0x77) +O(I32__rotr, "i32.rotr", 0x78) +O(I64__clz, "i64.clz", 0x79) +O(I64__ctz, "i64.ctz", 0x7A) +O(I64__popcnt, "i64.popcnt", 0x7B) +O(I64__add, "i64.add", 0x7C) +O(I64__sub, "i64.sub", 0x7D) +O(I64__mul, "i64.mul", 0x7E) +O(I64__div_s, "i64.div_s", 0x7F) +O(I64__div_u, "i64.div_u", 0x80) +O(I64__rem_s, "i64.rem_s", 0x81) +O(I64__rem_u, "i64.rem_u", 0x82) +O(I64__and, "i64.and", 0x83) +O(I64__or, "i64.or", 0x84) +O(I64__xor, "i64.xor", 0x85) +O(I64__shl, "i64.shl", 0x86) +O(I64__shr_s, "i64.shr_s", 0x87) +O(I64__shr_u, "i64.shr_u", 0x88) +O(I64__rotl, "i64.rotl", 0x89) +O(I64__rotr, "i64.rotr", 0x8A) +O(F32__abs, "f32.abs", 0x8B) +O(F32__neg, "f32.neg", 0x8C) +O(F32__ceil, "f32.ceil", 0x8D) +O(F32__floor, "f32.floor", 0x8E) +O(F32__trunc, "f32.trunc", 0x8F) +O(F32__nearest, "f32.nearest", 0x90) +O(F32__sqrt, "f32.sqrt", 0x91) +O(F32__add, "f32.add", 0x92) +O(F32__sub, "f32.sub", 0x93) +O(F32__mul, "f32.mul", 0x94) +O(F32__div, "f32.div", 0x95) +O(F32__min, "f32.min", 0x96) +O(F32__max, "f32.max", 0x97) +O(F32__copysign, "f32.copysign", 0x98) +O(F64__abs, "f64.abs", 0x99) +O(F64__neg, "f64.neg", 0x9A) +O(F64__ceil, "f64.ceil", 0x9B) +O(F64__floor, "f64.floor", 0x9C) +O(F64__trunc, "f64.trunc", 0x9D) +O(F64__nearest, "f64.nearest", 0x9E) +O(F64__sqrt, "f64.sqrt", 0x9F) +O(F64__add, "f64.add", 0xA0) +O(F64__sub, "f64.sub", 0xA1) +O(F64__mul, "f64.mul", 0xA2) +O(F64__div, "f64.div", 0xA3) +O(F64__min, "f64.min", 0xA4) +O(F64__max, "f64.max", 0xA5) +O(F64__copysign, "f64.copysign", 0xA6) +O(I32__wrap_i64, "i32.wrap_i64", 0xA7) +O(I32__trunc_f32_s, "i32.trunc_f32_s", 0xA8) +O(I32__trunc_f32_u, "i32.trunc_f32_u", 0xA9) +O(I32__trunc_f64_s, "i32.trunc_f64_s", 0xAA) +O(I32__trunc_f64_u, "i32.trunc_f64_u", 0xAB) +O(I64__extend_i32_s, "i64.extend_i32_s", 0xAC) +O(I64__extend_i32_u, "i64.extend_i32_u", 0xAD) +O(I64__trunc_f32_s, "i64.trunc_f32_s", 0xAE) +O(I64__trunc_f32_u, "i64.trunc_f32_u", 0xAF) +O(I64__trunc_f64_s, "i64.trunc_f64_s", 0xB0) +O(I64__trunc_f64_u, "i64.trunc_f64_u", 0xB1) +O(F32__convert_i32_s, "f32.convert_i32_s", 0xB2) +O(F32__convert_i32_u, "f32.convert_i32_u", 0xB3) +O(F32__convert_i64_s, "f32.convert_i64_s", 0xB4) +O(F32__convert_i64_u, "f32.convert_i64_u", 0xB5) +O(F32__demote_f64, "f32.demote_f64", 0xB6) +O(F64__convert_i32_s, "f64.convert_i32_s", 0xB7) +O(F64__convert_i32_u, "f64.convert_i32_u", 0xB8) +O(F64__convert_i64_s, "f64.convert_i64_s", 0xB9) +O(F64__convert_i64_u, "f64.convert_i64_u", 0xBA) +O(F64__promote_f32, "f64.promote_f32", 0xBB) +O(I32__reinterpret_f32, "i32.reinterpret_f32", 0xBC) +O(I64__reinterpret_f64, "i64.reinterpret_f64", 0xBD) +O(F32__reinterpret_i32, "f32.reinterpret_i32", 0xBE) +O(F64__reinterpret_i64, "f64.reinterpret_i64", 0xBF) +O(I32__extend8_s, "i32.extend8_s", 0xC0) +O(I32__extend16_s, "i32.extend16_s", 0xC1) +O(I64__extend8_s, "i64.extend8_s", 0xC2) +O(I64__extend16_s, "i64.extend16_s", 0xC3) +O(I64__extend32_s, "i64.extend32_s", 0xC4) +// 0xC5 ~ 0xCF: Reserved // Reference Instructions -O(Ref__null, 0xD0, "ref.null") -O(Ref__is_null, 0xD1, "ref.is_null") -O(Ref__func, 0xD2, "ref.func") -O(Ref__eq, 0xD3, "ref.eq") -O(Ref__as_non_null, 0xD4, "ref.as_non_null") +O(Ref__null, "ref.null", 0xD0) +O(Ref__is_null, "ref.is_null", 0xD1) +O(Ref__func, "ref.func", 0xD2) +O(Ref__eq, "ref.eq", 0xD3) +O(Ref__as_non_null, "ref.as_non_null", 0xD4) // Control Instructions (part 2) -O(Br_on_null, 0xD5, "br_on_null") -O(Br_on_non_null, 0xD6, "br_on_non_null") - -// GC Instructions -O(Struct__new, 0xFB00, "struct.new") -O(Struct__new_default, 0xFB01, "struct.new_default") -O(Struct__get, 0xFB02, "struct.get") -O(Struct__get_s, 0xFB03, "struct.get_s") -O(Struct__get_u, 0xFB04, "struct.get_u") -O(Struct__set, 0xFB05, "struct.set") -O(Array__new, 0xFB06, "array.new") -O(Array__new_default, 0xFB07, "array.new_default") -O(Array__new_fixed, 0xFB08, "array.new_fixed") -O(Array__new_data, 0xFB09, "array.new_data") -O(Array__new_elem, 0xFB0A, "array.new_elem") -O(Array__get, 0xFB0B, "array.get") -O(Array__get_s, 0xFB0C, "array.get_s") -O(Array__get_u, 0xFB0D, "array.get_u") -O(Array__set, 0xFB0E, "array.set") -O(Array__len, 0xFB0F, "array.len") -O(Array__fill, 0xFB10, "array.fill") -O(Array__copy, 0xFB11, "array.copy") -O(Array__init_data, 0xFB12, "array.init_data") -O(Array__init_elem, 0xFB13, "array.init_elem") -O(Ref__test, 0xFB14, "ref.test (ref)") -O(Ref__test_null, 0xFB15, "ref.test (ref.null)") -O(Ref__cast, 0xFB16, "ref.cast (ref)") -O(Ref__cast_null, 0xFB17, "ref.cast (ref.null)") -O(Br_on_cast, 0xFB18, "br_on_cast") -O(Br_on_cast_fail, 0xFB19, "br_on_cast_fail") -O(Any__convert_extern, 0xFB1A, "any.convert_extern") -O(Extern__convert_any, 0xFB1B, "extern.convert_any") -O(Ref__i31, 0xFB1C, "ref.i31") -O(I31__get_s, 0xFB1D, "i31.get_s") -O(I31__get_u, 0xFB1E, "i31.get_u") - -// Saturating Truncation Instructions -O(I32__trunc_sat_f32_s, 0xFC00, "i32.trunc_sat_f32_s") -O(I32__trunc_sat_f32_u, 0xFC01, "i32.trunc_sat_f32_u") -O(I32__trunc_sat_f64_s, 0xFC02, "i32.trunc_sat_f64_s") -O(I32__trunc_sat_f64_u, 0xFC03, "i32.trunc_sat_f64_u") -O(I64__trunc_sat_f32_s, 0xFC04, "i64.trunc_sat_f32_s") -O(I64__trunc_sat_f32_u, 0xFC05, "i64.trunc_sat_f32_u") -O(I64__trunc_sat_f64_s, 0xFC06, "i64.trunc_sat_f64_s") -O(I64__trunc_sat_f64_u, 0xFC07, "i64.trunc_sat_f64_u") - -// Memory Instructions (part 2) -O(Memory__init, 0xFC08, "memory.init") -O(Data__drop, 0xFC09, "data.drop") -O(Memory__copy, 0xFC0A, "memory.copy") -O(Memory__fill, 0xFC0B, "memory.fill") - -// Table Instructions (part 2) -O(Table__init, 0xFC0C, "table.init") -O(Elem__drop, 0xFC0D, "elem.drop") -O(Table__copy, 0xFC0E, "table.copy") -O(Table__grow, 0xFC0F, "table.grow") -O(Table__size, 0xFC10, "table.size") -O(Table__fill, 0xFC11, "table.fill") - -// SIMD Memory Instructions -O(V128__load, 0xFD00, "v128.load") -O(V128__load8x8_s, 0xFD01, "v128.load8x8_s") -O(V128__load8x8_u, 0xFD02, "v128.load8x8_u") -O(V128__load16x4_s, 0xFD03, "v128.load16x4_s") -O(V128__load16x4_u, 0xFD04, "v128.load16x4_u") -O(V128__load32x2_s, 0xFD05, "v128.load32x2_s") -O(V128__load32x2_u, 0xFD06, "v128.load32x2_u") -O(V128__load8_splat, 0xFD07, "v128.load8_splat") -O(V128__load16_splat, 0xFD08, "v128.load16_splat") -O(V128__load32_splat, 0xFD09, "v128.load32_splat") -O(V128__load64_splat, 0xFD0A, "v128.load64_splat") -O(V128__load32_zero, 0xFD5C, "v128.load32_zero") -O(V128__load64_zero, 0xFD5D, "v128.load64_zero") -O(V128__store, 0xFD0B, "v128.store") -O(V128__load8_lane, 0xFD54, "v128.load8_lane") -O(V128__load16_lane, 0xFD55, "v128.load16_lane") -O(V128__load32_lane, 0xFD56, "v128.load32_lane") -O(V128__load64_lane, 0xFD57, "v128.load64_lane") -O(V128__store8_lane, 0xFD58, "v128.store8_lane") -O(V128__store16_lane, 0xFD59, "v128.store16_lane") -O(V128__store32_lane, 0xFD5A, "v128.store32_lane") -O(V128__store64_lane, 0xFD5B, "v128.store64_lane") - -// SIMD Const Instructions -O(V128__const, 0xFD0C, "v128.const") - -// SIMD Shuffle Instructions -O(I8x16__shuffle, 0xFD0D, "i8x16.shuffle") - -// SIMD Lane Instructions -O(I8x16__extract_lane_s, 0xFD15, "i8x16.extract_lane_s") -O(I8x16__extract_lane_u, 0xFD16, "i8x16.extract_lane_u") -O(I8x16__replace_lane, 0xFD17, "i8x16.replace_lane") -O(I16x8__extract_lane_s, 0xFD18, "i16x8.extract_lane_s") -O(I16x8__extract_lane_u, 0xFD19, "i16x8.extract_lane_u") -O(I16x8__replace_lane, 0xFD1A, "i16x8.replace_lane") -O(I32x4__extract_lane, 0xFD1B, "i32x4.extract_lane") -O(I32x4__replace_lane, 0xFD1C, "i32x4.replace_lane") -O(I64x2__extract_lane, 0xFD1D, "i64x2.extract_lane") -O(I64x2__replace_lane, 0xFD1E, "i64x2.replace_lane") -O(F32x4__extract_lane, 0xFD1F, "f32x4.extract_lane") -O(F32x4__replace_lane, 0xFD20, "f32x4.replace_lane") -O(F64x2__extract_lane, 0xFD21, "f64x2.extract_lane") -O(F64x2__replace_lane, 0xFD22, "f64x2.replace_lane") - -// SIMD Numeric Instructions -O(I8x16__swizzle, 0xFD0E, "i8x16.swizzle") -O(I8x16__splat, 0xFD0F, "i8x16.splat") -O(I16x8__splat, 0xFD10, "i16x8.splat") -O(I32x4__splat, 0xFD11, "i32x4.splat") -O(I64x2__splat, 0xFD12, "i64x2.splat") -O(F32x4__splat, 0xFD13, "f32x4.splat") -O(F64x2__splat, 0xFD14, "f64x2.splat") - -O(I8x16__eq, 0xFD23, "i8x16.eq") -O(I8x16__ne, 0xFD24, "i8x16.ne") -O(I8x16__lt_s, 0xFD25, "i8x16.lt_s") -O(I8x16__lt_u, 0xFD26, "i8x16.lt_u") -O(I8x16__gt_s, 0xFD27, "i8x16.gt_s") -O(I8x16__gt_u, 0xFD28, "i8x16.gt_u") -O(I8x16__le_s, 0xFD29, "i8x16.le_s") -O(I8x16__le_u, 0xFD2A, "i8x16.le_u") -O(I8x16__ge_s, 0xFD2B, "i8x16.ge_s") -O(I8x16__ge_u, 0xFD2C, "i8x16.ge_u") - -O(I16x8__eq, 0xFD2D, "i16x8.eq") -O(I16x8__ne, 0xFD2E, "i16x8.ne") -O(I16x8__lt_s, 0xFD2F, "i16x8.lt_s") -O(I16x8__lt_u, 0xFD30, "i16x8.lt_u") -O(I16x8__gt_s, 0xFD31, "i16x8.gt_s") -O(I16x8__gt_u, 0xFD32, "i16x8.gt_u") -O(I16x8__le_s, 0xFD33, "i16x8.le_s") -O(I16x8__le_u, 0xFD34, "i16x8.le_u") -O(I16x8__ge_s, 0xFD35, "i16x8.ge_s") -O(I16x8__ge_u, 0xFD36, "i16x8.ge_u") - -O(I32x4__eq, 0xFD37, "i32x4.eq") -O(I32x4__ne, 0xFD38, "i32x4.ne") -O(I32x4__lt_s, 0xFD39, "i32x4.lt_s") -O(I32x4__lt_u, 0xFD3A, "i32x4.lt_u") -O(I32x4__gt_s, 0xFD3B, "i32x4.gt_s") -O(I32x4__gt_u, 0xFD3C, "i32x4.gt_u") -O(I32x4__le_s, 0xFD3D, "i32x4.le_s") -O(I32x4__le_u, 0xFD3E, "i32x4.le_u") -O(I32x4__ge_s, 0xFD3F, "i32x4.ge_s") -O(I32x4__ge_u, 0xFD40, "i32x4.ge_u") - -O(I64x2__eq, 0xFDD6, "i64x2.eq") -O(I64x2__ne, 0xFDD7, "i64x2.ne") -O(I64x2__lt_s, 0xFDD8, "i64x2.lt_s") -O(I64x2__gt_s, 0xFDD9, "i64x2.gt_s") -O(I64x2__le_s, 0xFDDA, "i64x2.le_s") -O(I64x2__ge_s, 0xFDDB, "i64x2.ge_s") - -O(F32x4__eq, 0xFD41, "f32x4.eq") -O(F32x4__ne, 0xFD42, "f32x4.ne") -O(F32x4__lt, 0xFD43, "f32x4.lt") -O(F32x4__gt, 0xFD44, "f32x4.gt") -O(F32x4__le, 0xFD45, "f32x4.le") -O(F32x4__ge, 0xFD46, "f32x4.ge") - -O(F64x2__eq, 0xFD47, "f64x2.eq") -O(F64x2__ne, 0xFD48, "f64x2.ne") -O(F64x2__lt, 0xFD49, "f64x2.lt") -O(F64x2__gt, 0xFD4A, "f64x2.gt") -O(F64x2__le, 0xFD4B, "f64x2.le") -O(F64x2__ge, 0xFD4C, "f64x2.ge") - -O(V128__not, 0xFD4D, "v128.not") -O(V128__and, 0xFD4E, "v128.and") -O(V128__andnot, 0xFD4F, "v128.andnot") -O(V128__or, 0xFD50, "v128.or") -O(V128__xor, 0xFD51, "v128.xor") -O(V128__bitselect, 0xFD52, "v128.bitselect") -O(V128__any_true, 0xFD53, "v128.any_true") - -O(I8x16__abs, 0xFD60, "i8x16.abs") -O(I8x16__neg, 0xFD61, "i8x16.neg") -O(I8x16__popcnt, 0xFD62, "i8x16.popcnt") -O(I8x16__all_true, 0xFD63, "i8x16.all_true") -O(I8x16__bitmask, 0xFD64, "i8x16.bitmask") -O(I8x16__narrow_i16x8_s, 0xFD65, "i8x16.narrow_i16x8_s") -O(I8x16__narrow_i16x8_u, 0xFD66, "i8x16.narrow_i16x8_u") -O(I8x16__shl, 0xFD6B, "i8x16.shl") -O(I8x16__shr_s, 0xFD6C, "i8x16.shr_s") -O(I8x16__shr_u, 0xFD6D, "i8x16.shr_u") -O(I8x16__add, 0xFD6E, "i8x16.add") -O(I8x16__add_sat_s, 0xFD6F, "i8x16.add_sat_s") -O(I8x16__add_sat_u, 0xFD70, "i8x16.add_sat_u") -O(I8x16__sub, 0xFD71, "i8x16.sub") -O(I8x16__sub_sat_s, 0xFD72, "i8x16.sub_sat_s") -O(I8x16__sub_sat_u, 0xFD73, "i8x16.sub_sat_u") -O(I8x16__min_s, 0xFD76, "i8x16.min_s") -O(I8x16__min_u, 0xFD77, "i8x16.min_u") -O(I8x16__max_s, 0xFD78, "i8x16.max_s") -O(I8x16__max_u, 0xFD79, "i8x16.max_u") -O(I8x16__avgr_u, 0xFD7B, "i8x16.avgr_u") - -O(I16x8__abs, 0xFD80, "i16x8.abs") -O(I16x8__neg, 0xFD81, "i16x8.neg") -O(I16x8__all_true, 0xFD83, "i16x8.all_true") -O(I16x8__bitmask, 0xFD84, "i16x8.bitmask") -O(I16x8__narrow_i32x4_s, 0xFD85, "i16x8.narrow_i32x4_s") -O(I16x8__narrow_i32x4_u, 0xFD86, "i16x8.narrow_i32x4_u") -O(I16x8__extend_low_i8x16_s, 0xFD87, "i16x8.extend_low_i8x16_s") -O(I16x8__extend_high_i8x16_s, 0xFD88, "i16x8.extend_high_i8x16_s") -O(I16x8__extend_low_i8x16_u, 0xFD89, "i16x8.extend_low_i8x16_u") -O(I16x8__extend_high_i8x16_u, 0xFD8A, "i16x8.extend_high_i8x16_u") -O(I16x8__shl, 0xFD8B, "i16x8.shl") -O(I16x8__shr_s, 0xFD8C, "i16x8.shr_s") -O(I16x8__shr_u, 0xFD8D, "i16x8.shr_u") -O(I16x8__add, 0xFD8E, "i16x8.add") -O(I16x8__add_sat_s, 0xFD8F, "i16x8.add_sat_s") -O(I16x8__add_sat_u, 0xFD90, "i16x8.add_sat_u") -O(I16x8__sub, 0xFD91, "i16x8.sub") -O(I16x8__sub_sat_s, 0xFD92, "i16x8.sub_sat_s") -O(I16x8__sub_sat_u, 0xFD93, "i16x8.sub_sat_u") -O(I16x8__mul, 0xFD95, "i16x8.mul") -O(I16x8__min_s, 0xFD96, "i16x8.min_s") -O(I16x8__min_u, 0xFD97, "i16x8.min_u") -O(I16x8__max_s, 0xFD98, "i16x8.max_s") -O(I16x8__max_u, 0xFD99, "i16x8.max_u") -O(I16x8__avgr_u, 0xFD9B, "i16x8.avgr_u") -O(I16x8__extmul_low_i8x16_s, 0xFD9C, "i16x8.extmul_low_i8x16_s") -O(I16x8__extmul_high_i8x16_s, 0xFD9D, "i16x8.extmul_high_i8x16_s") -O(I16x8__extmul_low_i8x16_u, 0xFD9E, "i16x8.extmul_low_i8x16_u") -O(I16x8__extmul_high_i8x16_u, 0xFD9F, "i16x8.extmul_high_i8x16_u") -O(I16x8__q15mulr_sat_s, 0xFD82, "i16x8.q15mulr_sat_s") -O(I16x8__extadd_pairwise_i8x16_s, 0xFD7C, "i16x8.extadd_pairwise_i8x16_s") -O(I16x8__extadd_pairwise_i8x16_u, 0xFD7D, "i16x8.extadd_pairwise_i8x16_u") - -O(I32x4__abs, 0xFDA0, "i32x4.abs") -O(I32x4__neg, 0xFDA1, "i32x4.neg") -O(I32x4__all_true, 0xFDA3, "i32x4.all_true") -O(I32x4__bitmask, 0xFDA4, "i32x4.bitmask") -O(I32x4__extend_low_i16x8_s, 0xFDA7, "i32x4.extend_low_i16x8_s") -O(I32x4__extend_high_i16x8_s, 0xFDA8, "i32x4.extend_high_i16x8_s") -O(I32x4__extend_low_i16x8_u, 0xFDA9, "i32x4.extend_low_i16x8_u") -O(I32x4__extend_high_i16x8_u, 0xFDAA, "i32x4.extend_high_i16x8_u") -O(I32x4__shl, 0xFDAB, "i32x4.shl") -O(I32x4__shr_s, 0xFDAC, "i32x4.shr_s") -O(I32x4__shr_u, 0xFDAD, "i32x4.shr_u") -O(I32x4__add, 0xFDAE, "i32x4.add") -O(I32x4__sub, 0xFDB1, "i32x4.sub") -O(I32x4__mul, 0xFDB5, "i32x4.mul") -O(I32x4__min_s, 0xFDB6, "i32x4.min_s") -O(I32x4__min_u, 0xFDB7, "i32x4.min_u") -O(I32x4__max_s, 0xFDB8, "i32x4.max_s") -O(I32x4__max_u, 0xFDB9, "i32x4.max_u") -O(I32x4__dot_i16x8_s, 0xFDBA, "i32x4.dot_i16x8_s") -O(I32x4__extmul_low_i16x8_s, 0xFDBC, "i32x4.extmul_low_i16x8_s") -O(I32x4__extmul_high_i16x8_s, 0xFDBD, "i32x4.extmul_high_i16x8_s") -O(I32x4__extmul_low_i16x8_u, 0xFDBE, "i32x4.extmul_low_i16x8_u") -O(I32x4__extmul_high_i16x8_u, 0xFDBF, "i32x4.extmul_high_i16x8_u") -O(I32x4__extadd_pairwise_i16x8_s, 0xFD7E, "i32x4.extadd_pairwise_i16x8_s") -O(I32x4__extadd_pairwise_i16x8_u, 0xFD7F, "i32x4.extadd_pairwise_i16x8_u") - -O(I64x2__abs, 0xFDC0, "i64x2.abs") -O(I64x2__neg, 0xFDC1, "i64x2.neg") -O(I64x2__all_true, 0xFDC3, "i64x2.all_true") -O(I64x2__bitmask, 0xFDC4, "i64x2.bitmask") -O(I64x2__extend_low_i32x4_s, 0xFDC7, "i64x2.extend_low_i32x4_s") -O(I64x2__extend_high_i32x4_s, 0xFDC8, "i64x2.extend_high_i32x4_s") -O(I64x2__extend_low_i32x4_u, 0xFDC9, "i64x2.extend_low_i32x4_u") -O(I64x2__extend_high_i32x4_u, 0xFDCA, "i64x2.extend_high_i32x4_u") -O(I64x2__shl, 0xFDCB, "i64x2.shl") -O(I64x2__shr_s, 0xFDCC, "i64x2.shr_s") -O(I64x2__shr_u, 0xFDCD, "i64x2.shr_u") -O(I64x2__add, 0xFDCE, "i64x2.add") -O(I64x2__sub, 0xFDD1, "i64x2.sub") -O(I64x2__mul, 0xFDD5, "i64x2.mul") -O(I64x2__extmul_low_i32x4_s, 0xFDDC, "i64x2.extmul_low_i32x4_s") -O(I64x2__extmul_high_i32x4_s, 0xFDDD, "i64x2.extmul_high_i32x4_s") -O(I64x2__extmul_low_i32x4_u, 0xFDDE, "i64x2.extmul_low_i32x4_u") -O(I64x2__extmul_high_i32x4_u, 0xFDDF, "i64x2.extmul_high_i32x4_u") - -O(F32x4__abs, 0xFDE0, "f32x4.abs") -O(F32x4__neg, 0xFDE1, "f32x4.neg") -O(F32x4__sqrt, 0xFDE3, "f32x4.sqrt") -O(F32x4__add, 0xFDE4, "f32x4.add") -O(F32x4__sub, 0xFDE5, "f32x4.sub") -O(F32x4__mul, 0xFDE6, "f32x4.mul") -O(F32x4__div, 0xFDE7, "f32x4.div") -O(F32x4__min, 0xFDE8, "f32x4.min") -O(F32x4__max, 0xFDE9, "f32x4.max") -O(F32x4__pmin, 0xFDEA, "f32x4.pmin") -O(F32x4__pmax, 0xFDEB, "f32x4.pmax") -O(F32x4__ceil, 0xFD67, "f32x4.ceil") -O(F32x4__floor, 0xFD68, "f32x4.floor") -O(F32x4__trunc, 0xFD69, "f32x4.trunc") -O(F32x4__nearest, 0xFD6A, "f32x4.nearest") - -O(F64x2__abs, 0xFDEC, "f64x2.abs") -O(F64x2__neg, 0xFDED, "f64x2.neg") -O(F64x2__sqrt, 0xFDEF, "f64x2.sqrt") -O(F64x2__add, 0xFDF0, "f64x2.add") -O(F64x2__sub, 0xFDF1, "f64x2.sub") -O(F64x2__mul, 0xFDF2, "f64x2.mul") -O(F64x2__div, 0xFDF3, "f64x2.div") -O(F64x2__min, 0xFDF4, "f64x2.min") -O(F64x2__max, 0xFDF5, "f64x2.max") -O(F64x2__pmin, 0xFDF6, "f64x2.pmin") -O(F64x2__pmax, 0xFDF7, "f64x2.pmax") -O(F64x2__ceil, 0xFD74, "f64x2.ceil") -O(F64x2__floor, 0xFD75, "f64x2.floor") -O(F64x2__trunc, 0xFD7A, "f64x2.trunc") -O(F64x2__nearest, 0xFD94, "f64x2.nearest") - -O(I32x4__trunc_sat_f32x4_s, 0xFDF8, "i32x4.trunc_sat_f32x4_s") -O(I32x4__trunc_sat_f32x4_u, 0xFDF9, "i32x4.trunc_sat_f32x4_u") -O(F32x4__convert_i32x4_s, 0xFDFA, "f32x4.convert_i32x4_s") -O(F32x4__convert_i32x4_u, 0xFDFB, "f32x4.convert_i32x4_u") -O(I32x4__trunc_sat_f64x2_s_zero, 0xFDFC, "i32x4.trunc_sat_f64x2_s_zero") -O(I32x4__trunc_sat_f64x2_u_zero, 0xFDFD, "i32x4.trunc_sat_f64x2_u_zero") -O(F64x2__convert_low_i32x4_s, 0xFDFE, "f64x2.convert_low_i32x4_s") -O(F64x2__convert_low_i32x4_u, 0xFDFF, "f64x2.convert_low_i32x4_u") -O(F32x4__demote_f64x2_zero, 0xFD5E, "f32x4.demote_f64x2_zero") -O(F64x2__promote_low_f32x4, 0xFD5F, "f64x2.promote_low_f32x4") - -// Atomic instructions -O(Memory__atomic__notify, 0xFE00, "memory.atomic.notify") -O(Memory__atomic__wait32, 0xFE01, "memory.atomic.wait32") -O(Memory__atomic__wait64, 0xFE02, "memory.atomic.wait64") -O(Atomic__fence, 0xFE03, "atomic.fence") - -O(I32__atomic__load, 0xFE10, "i32.atomic.load") -O(I64__atomic__load, 0xFE11, "i64.atomic.load") -O(I32__atomic__load8_u, 0xFE12, "i32.atomic.load8_u") -O(I32__atomic__load16_u, 0xFE13, "i32.atomic.load16_u") -O(I64__atomic__load8_u, 0xFE14, "i64.atomic.load8_u") -O(I64__atomic__load16_u, 0xFE15, "i64.atomic.load16_u") -O(I64__atomic__load32_u, 0xFE16, "i64.atomic.load32_u") -O(I32__atomic__store, 0xFE17, "i32.atomic.store") -O(I64__atomic__store, 0xFE18, "i64.atomic.store") -O(I32__atomic__store8, 0xFE19, "i32.atomic.store8") -O(I32__atomic__store16, 0xFE1A, "i32.atomic.store16") -O(I64__atomic__store8, 0xFE1B, "i64.atomic.store8") -O(I64__atomic__store16, 0xFE1C, "i64.atomic.store16") -O(I64__atomic__store32, 0xFE1D, "i64.atomic.store32") - -O(I32__atomic__rmw__add, 0xFE1E, "i32.atomic.rmw.add") -O(I64__atomic__rmw__add, 0xFE1F, "i64.atomic.rmw.add") -O(I32__atomic__rmw8__add_u, 0xFE20, "i32.atomic.rmw8.add_u") -O(I32__atomic__rmw16__add_u, 0xFE21, "i32.atomic.rmw16.add_u") -O(I64__atomic__rmw8__add_u, 0xFE22, "i64.atomic.rmw8.add_u") -O(I64__atomic__rmw16__add_u, 0xFE23, "i64.atomic.rmw16.add_u") -O(I64__atomic__rmw32__add_u, 0xFE24, "i64.atomic.rmw32.add_u") -O(I32__atomic__rmw__sub, 0xFE25, "i32.atomic.rmw.sub") -O(I64__atomic__rmw__sub, 0xFE26, "i64.atomic.rmw.sub") -O(I32__atomic__rmw8__sub_u, 0xFE27, "i32.atomic.rmw8.sub_u") -O(I32__atomic__rmw16__sub_u, 0xFE28, "i32.atomic.rmw16.sub_u") -O(I64__atomic__rmw8__sub_u, 0xFE29, "i64.atomic.rmw8.sub_u") -O(I64__atomic__rmw16__sub_u, 0xFE2A, "i64.atomic.rmw16.sub_u") -O(I64__atomic__rmw32__sub_u, 0xFE2B, "i64.atomic.rmw32.sub_u") -O(I32__atomic__rmw__and, 0xFE2C, "i32.atomic.rmw.and") -O(I64__atomic__rmw__and, 0xFE2D, "i64.atomic.rmw.and") -O(I32__atomic__rmw8__and_u, 0xFE2E, "i32.atomic.rmw8.and_u") -O(I32__atomic__rmw16__and_u, 0xFE2F, "i32.atomic.rmw16.and_u") -O(I64__atomic__rmw8__and_u, 0xFE30, "i64.atomic.rmw8.and_u") -O(I64__atomic__rmw16__and_u, 0xFE31, "i64.atomic.rmw16.and_u") -O(I64__atomic__rmw32__and_u, 0xFE32, "i64.atomic.rmw32.and_u") -O(I32__atomic__rmw__or, 0xFE33, "i32.atomic.rmw.or") -O(I64__atomic__rmw__or, 0xFE34, "i64.atomic.rmw.or") -O(I32__atomic__rmw8__or_u, 0xFE35, "i32.atomic.rmw8.or_u") -O(I32__atomic__rmw16__or_u, 0xFE36, "i32.atomic.rmw16.or_u") -O(I64__atomic__rmw8__or_u, 0xFE37, "i64.atomic.rmw8.or_u") -O(I64__atomic__rmw16__or_u, 0xFE38, "i64.atomic.rmw16.or_u") -O(I64__atomic__rmw32__or_u, 0xFE39, "i64.atomic.rmw32.or_u") -O(I32__atomic__rmw__xor, 0xFE3A, "i32.atomic.rmw.xor") -O(I64__atomic__rmw__xor, 0xFE3B, "i64.atomic.rmw.xor") -O(I32__atomic__rmw8__xor_u, 0xFE3C, "i32.atomic.rmw8.xor_u") -O(I32__atomic__rmw16__xor_u, 0xFE3D, "i32.atomic.rmw16.xor_u") -O(I64__atomic__rmw8__xor_u, 0xFE3E, "i64.atomic.rmw8.xor_u") -O(I64__atomic__rmw16__xor_u, 0xFE3F, "i64.atomic.rmw16.xor_u") -O(I64__atomic__rmw32__xor_u, 0xFE40, "i64.atomic.rmw32.xor_u") -O(I32__atomic__rmw__xchg, 0xFE41, "i32.atomic.rmw.xchg") -O(I64__atomic__rmw__xchg, 0xFE42, "i64.atomic.rmw.xchg") -O(I32__atomic__rmw8__xchg_u, 0xFE43, "i32.atomic.rmw8.xchg_u") -O(I32__atomic__rmw16__xchg_u, 0xFE44, "i32.atomic.rmw16.xchg_u") -O(I64__atomic__rmw8__xchg_u, 0xFE45, "i64.atomic.rmw8.xchg_u") -O(I64__atomic__rmw16__xchg_u, 0xFE46, "i64.atomic.rmw16.xchg_u") -O(I64__atomic__rmw32__xchg_u, 0xFE47, "i64.atomic.rmw32.xchg_u") -O(I32__atomic__rmw__cmpxchg, 0xFE48, "i32.atomic.rmw.cmpxchg") -O(I64__atomic__rmw__cmpxchg, 0xFE49, "i64.atomic.rmw.cmpxchg") -O(I32__atomic__rmw8__cmpxchg_u, 0xFE4A, "i32.atomic.rmw8.cmpxchg_u") -O(I32__atomic__rmw16__cmpxchg_u, 0xFE4B, "i32.atomic.rmw16.cmpxchg_u") -O(I64__atomic__rmw8__cmpxchg_u, 0xFE4C, "i64.atomic.rmw8.cmpxchg_u") -O(I64__atomic__rmw16__cmpxchg_u, 0xFE4D, "i64.atomic.rmw16.cmpxchg_u") -O(I64__atomic__rmw32__cmpxchg_u, 0xFE4E, "i64.atomic.rmw32.cmpxchg_u") +O(Br_on_null, "br_on_null", 0xD5) +O(Br_on_non_null, "br_on_non_null", 0xD6) +// 0xD7 ~ 0xFA: Reserved + +// 0xFB prefix - GC Instructions +OFB(Struct__new, "struct.new", 0xFB, 0) +OFB(Struct__new_default, "struct.new_default", 0xFB, 1) +OFB(Struct__get, "struct.get", 0xFB, 2) +OFB(Struct__get_s, "struct.get_s", 0xFB, 3) +OFB(Struct__get_u, "struct.get_u", 0xFB, 4) +OFB(Struct__set, "struct.set", 0xFB, 5) +OFB(Array__new, "array.new", 0xFB, 6) +OFB(Array__new_default, "array.new_default", 0xFB, 7) +OFB(Array__new_fixed, "array.new_fixed", 0xFB, 8) +OFB(Array__new_data, "array.new_data", 0xFB, 9) +OFB(Array__new_elem, "array.new_elem", 0xFB, 10) +OFB(Array__get, "array.get", 0xFB, 11) +OFB(Array__get_s, "array.get_s", 0xFB, 12) +OFB(Array__get_u, "array.get_u", 0xFB, 13) +OFB(Array__set, "array.set", 0xFB, 14) +OFB(Array__len, "array.len", 0xFB, 15) +OFB(Array__fill, "array.fill", 0xFB, 16) +OFB(Array__copy, "array.copy", 0xFB, 17) +OFB(Array__init_data, "array.init_data", 0xFB, 18) +OFB(Array__init_elem, "array.init_elem", 0xFB, 19) +OFB(Ref__test, "ref.test (ref)", 0xFB, 20) +OFB(Ref__test_null, "ref.test (ref.null)", 0xFB, 21) +OFB(Ref__cast, "ref.cast (ref)", 0xFB, 22) +OFB(Ref__cast_null, "ref.cast (ref.null)", 0xFB, 23) +OFB(Br_on_cast, "br_on_cast", 0xFB, 24) +OFB(Br_on_cast_fail, "br_on_cast_fail", 0xFB, 25) +OFB(Any__convert_extern, "any.convert_extern", 0xFB, 26) +OFB(Extern__convert_any, "extern.convert_any", 0xFB, 27) +OFB(Ref__i31, "ref.i31", 0xFB, 28) +OFB(I31__get_s, "i31.get_s", 0xFB, 29) +OFB(I31__get_u, "i31.get_u", 0xFB, 30) + +// 0xFC prefix - Saturating Truncation Instructions +OFC(I32__trunc_sat_f32_s, "i32.trunc_sat_f32_s", 0xFC, 0) +OFC(I32__trunc_sat_f32_u, "i32.trunc_sat_f32_u", 0xFC, 1) +OFC(I32__trunc_sat_f64_s, "i32.trunc_sat_f64_s", 0xFC, 2) +OFC(I32__trunc_sat_f64_u, "i32.trunc_sat_f64_u", 0xFC, 3) +OFC(I64__trunc_sat_f32_s, "i64.trunc_sat_f32_s", 0xFC, 4) +OFC(I64__trunc_sat_f32_u, "i64.trunc_sat_f32_u", 0xFC, 5) +OFC(I64__trunc_sat_f64_s, "i64.trunc_sat_f64_s", 0xFC, 6) +OFC(I64__trunc_sat_f64_u, "i64.trunc_sat_f64_u", 0xFC, 7) + +// 0xFC prefix - Memory Instructions (part 2) +OFC(Memory__init, "memory.init", 0xFC, 8) +OFC(Data__drop, "data.drop", 0xFC, 9) +OFC(Memory__copy, "memory.copy", 0xFC, 10) +OFC(Memory__fill, "memory.fill", 0xFC, 11) + +// 0xFC prefix - Table Instructions (part 2) +OFC(Table__init, "table.init", 0xFC, 12) +OFC(Elem__drop, "elem.drop", 0xFC, 13) +OFC(Table__copy, "table.copy", 0xFC, 14) +OFC(Table__grow, "table.grow", 0xFC, 15) +OFC(Table__size, "table.size", 0xFC, 16) +OFC(Table__fill, "table.fill", 0xFC, 17) + +// 0xFD prefix - Vector Memory Instructions (part 1) +OFD(V128__load, "v128.load", 0xFD, 0) +OFD(V128__load8x8_s, "v128.load8x8_s", 0xFD, 1) +OFD(V128__load8x8_u, "v128.load8x8_u", 0xFD, 2) +OFD(V128__load16x4_s, "v128.load16x4_s", 0xFD, 3) +OFD(V128__load16x4_u, "v128.load16x4_u", 0xFD, 4) +OFD(V128__load32x2_s, "v128.load32x2_s", 0xFD, 5) +OFD(V128__load32x2_u, "v128.load32x2_u", 0xFD, 6) +OFD(V128__load8_splat, "v128.load8_splat", 0xFD, 7) +OFD(V128__load16_splat, "v128.load16_splat", 0xFD, 8) +OFD(V128__load32_splat, "v128.load32_splat", 0xFD, 9) +OFD(V128__load64_splat, "v128.load64_splat", 0xFD, 10) +OFD(V128__store, "v128.store", 0xFD, 11) + +// 0xFD prefix - Vector Numeric Instructions (part 1) +OFD(V128__const, "v128.const", 0xFD, 12) +OFD(I8x16__shuffle, "i8x16.shuffle", 0xFD, 13) +OFD(I8x16__swizzle, "i8x16.swizzle", 0xFD, 14) +OFD(I8x16__splat, "i8x16.splat", 0xFD, 15) +OFD(I16x8__splat, "i16x8.splat", 0xFD, 16) +OFD(I32x4__splat, "i32x4.splat", 0xFD, 17) +OFD(I64x2__splat, "i64x2.splat", 0xFD, 18) +OFD(F32x4__splat, "f32x4.splat", 0xFD, 19) +OFD(F64x2__splat, "f64x2.splat", 0xFD, 20) + +// 0xFD prefix - Vector Lane Instructions +OFD(I8x16__extract_lane_s, "i8x16.extract_lane_s", 0xFD, 21) +OFD(I8x16__extract_lane_u, "i8x16.extract_lane_u", 0xFD, 22) +OFD(I8x16__replace_lane, "i8x16.replace_lane", 0xFD, 23) +OFD(I16x8__extract_lane_s, "i16x8.extract_lane_s", 0xFD, 24) +OFD(I16x8__extract_lane_u, "i16x8.extract_lane_u", 0xFD, 25) +OFD(I16x8__replace_lane, "i16x8.replace_lane", 0xFD, 26) +OFD(I32x4__extract_lane, "i32x4.extract_lane", 0xFD, 27) +OFD(I32x4__replace_lane, "i32x4.replace_lane", 0xFD, 28) +OFD(I64x2__extract_lane, "i64x2.extract_lane", 0xFD, 29) +OFD(I64x2__replace_lane, "i64x2.replace_lane", 0xFD, 30) +OFD(F32x4__extract_lane, "f32x4.extract_lane", 0xFD, 31) +OFD(F32x4__replace_lane, "f32x4.replace_lane", 0xFD, 32) +OFD(F64x2__extract_lane, "f64x2.extract_lane", 0xFD, 33) +OFD(F64x2__replace_lane, "f64x2.replace_lane", 0xFD, 34) + +// 0xFD prefix - Vector Numeric Instructions (part 2) +OFD(I8x16__eq, "i8x16.eq", 0xFD, 35) +OFD(I8x16__ne, "i8x16.ne", 0xFD, 36) +OFD(I8x16__lt_s, "i8x16.lt_s", 0xFD, 37) +OFD(I8x16__lt_u, "i8x16.lt_u", 0xFD, 38) +OFD(I8x16__gt_s, "i8x16.gt_s", 0xFD, 39) +OFD(I8x16__gt_u, "i8x16.gt_u", 0xFD, 40) +OFD(I8x16__le_s, "i8x16.le_s", 0xFD, 41) +OFD(I8x16__le_u, "i8x16.le_u", 0xFD, 42) +OFD(I8x16__ge_s, "i8x16.ge_s", 0xFD, 43) +OFD(I8x16__ge_u, "i8x16.ge_u", 0xFD, 44) +OFD(I16x8__eq, "i16x8.eq", 0xFD, 45) +OFD(I16x8__ne, "i16x8.ne", 0xFD, 46) +OFD(I16x8__lt_s, "i16x8.lt_s", 0xFD, 47) +OFD(I16x8__lt_u, "i16x8.lt_u", 0xFD, 48) +OFD(I16x8__gt_s, "i16x8.gt_s", 0xFD, 49) +OFD(I16x8__gt_u, "i16x8.gt_u", 0xFD, 50) +OFD(I16x8__le_s, "i16x8.le_s", 0xFD, 51) +OFD(I16x8__le_u, "i16x8.le_u", 0xFD, 52) +OFD(I16x8__ge_s, "i16x8.ge_s", 0xFD, 53) +OFD(I16x8__ge_u, "i16x8.ge_u", 0xFD, 54) +OFD(I32x4__eq, "i32x4.eq", 0xFD, 55) +OFD(I32x4__ne, "i32x4.ne", 0xFD, 56) +OFD(I32x4__lt_s, "i32x4.lt_s", 0xFD, 57) +OFD(I32x4__lt_u, "i32x4.lt_u", 0xFD, 58) +OFD(I32x4__gt_s, "i32x4.gt_s", 0xFD, 59) +OFD(I32x4__gt_u, "i32x4.gt_u", 0xFD, 60) +OFD(I32x4__le_s, "i32x4.le_s", 0xFD, 61) +OFD(I32x4__le_u, "i32x4.le_u", 0xFD, 62) +OFD(I32x4__ge_s, "i32x4.ge_s", 0xFD, 63) +OFD(I32x4__ge_u, "i32x4.ge_u", 0xFD, 64) +OFD(F32x4__eq, "f32x4.eq", 0xFD, 65) +OFD(F32x4__ne, "f32x4.ne", 0xFD, 66) +OFD(F32x4__lt, "f32x4.lt", 0xFD, 67) +OFD(F32x4__gt, "f32x4.gt", 0xFD, 68) +OFD(F32x4__le, "f32x4.le", 0xFD, 69) +OFD(F32x4__ge, "f32x4.ge", 0xFD, 70) +OFD(F64x2__eq, "f64x2.eq", 0xFD, 71) +OFD(F64x2__ne, "f64x2.ne", 0xFD, 72) +OFD(F64x2__lt, "f64x2.lt", 0xFD, 73) +OFD(F64x2__gt, "f64x2.gt", 0xFD, 74) +OFD(F64x2__le, "f64x2.le", 0xFD, 75) +OFD(F64x2__ge, "f64x2.ge", 0xFD, 76) +OFD(V128__not, "v128.not", 0xFD, 77) +OFD(V128__and, "v128.and", 0xFD, 78) +OFD(V128__andnot, "v128.andnot", 0xFD, 79) +OFD(V128__or, "v128.or", 0xFD, 80) +OFD(V128__xor, "v128.xor", 0xFD, 81) +OFD(V128__bitselect, "v128.bitselect", 0xFD, 82) +OFD(V128__any_true, "v128.any_true", 0xFD, 83) + +// 0xFD prefix - Vector Memory Instructions (part 2) +OFD(V128__load8_lane, "v128.load8_lane", 0xFD, 84) +OFD(V128__load16_lane, "v128.load16_lane", 0xFD, 85) +OFD(V128__load32_lane, "v128.load32_lane", 0xFD, 86) +OFD(V128__load64_lane, "v128.load64_lane", 0xFD, 87) +OFD(V128__store8_lane, "v128.store8_lane", 0xFD, 88) +OFD(V128__store16_lane, "v128.store16_lane", 0xFD, 89) +OFD(V128__store32_lane, "v128.store32_lane", 0xFD, 90) +OFD(V128__store64_lane, "v128.store64_lane", 0xFD, 91) +OFD(V128__load32_zero, "v128.load32_zero", 0xFD, 92) +OFD(V128__load64_zero, "v128.load64_zero", 0xFD, 93) + +// 0xFD prefix - Vector Numeric Instructions (part 3) +OFD(F32x4__demote_f64x2_zero, "f32x4.demote_f64x2_zero", 0xFD, 94) +OFD(F64x2__promote_low_f32x4, "f64x2.promote_low_f32x4", 0xFD, 95) +OFD(I8x16__abs, "i8x16.abs", 0xFD, 96) +OFD(I8x16__neg, "i8x16.neg", 0xFD, 97) +OFD(I8x16__popcnt, "i8x16.popcnt", 0xFD, 98) +OFD(I8x16__all_true, "i8x16.all_true", 0xFD, 99) +OFD(I8x16__bitmask, "i8x16.bitmask", 0xFD, 100) +OFD(I8x16__narrow_i16x8_s, "i8x16.narrow_i16x8_s", 0xFD, 101) +OFD(I8x16__narrow_i16x8_u, "i8x16.narrow_i16x8_u", 0xFD, 102) +OFD(F32x4__ceil, "f32x4.ceil", 0xFD, 103) +OFD(F32x4__floor, "f32x4.floor", 0xFD, 104) +OFD(F32x4__trunc, "f32x4.trunc", 0xFD, 105) +OFD(F32x4__nearest, "f32x4.nearest", 0xFD, 106) +OFD(I8x16__shl, "i8x16.shl", 0xFD, 107) +OFD(I8x16__shr_s, "i8x16.shr_s", 0xFD, 108) +OFD(I8x16__shr_u, "i8x16.shr_u", 0xFD, 109) +OFD(I8x16__add, "i8x16.add", 0xFD, 110) +OFD(I8x16__add_sat_s, "i8x16.add_sat_s", 0xFD, 111) +OFD(I8x16__add_sat_u, "i8x16.add_sat_u", 0xFD, 112) +OFD(I8x16__sub, "i8x16.sub", 0xFD, 113) +OFD(I8x16__sub_sat_s, "i8x16.sub_sat_s", 0xFD, 114) +OFD(I8x16__sub_sat_u, "i8x16.sub_sat_u", 0xFD, 115) +OFD(F64x2__ceil, "f64x2.ceil", 0xFD, 116) +OFD(F64x2__floor, "f64x2.floor", 0xFD, 117) +OFD(I8x16__min_s, "i8x16.min_s", 0xFD, 118) +OFD(I8x16__min_u, "i8x16.min_u", 0xFD, 119) +OFD(I8x16__max_s, "i8x16.max_s", 0xFD, 120) +OFD(I8x16__max_u, "i8x16.max_u", 0xFD, 121) +OFD(F64x2__trunc, "f64x2.trunc", 0xFD, 122) +OFD(I8x16__avgr_u, "i8x16.avgr_u", 0xFD, 123) +OFD(I16x8__extadd_pairwise_i8x16_s, "i16x8.extadd_pairwise_i8x16_s", 0xFD, 124) +OFD(I16x8__extadd_pairwise_i8x16_u, "i16x8.extadd_pairwise_i8x16_u", 0xFD, 125) +OFD(I32x4__extadd_pairwise_i16x8_s, "i32x4.extadd_pairwise_i16x8_s", 0xFD, 126) +OFD(I32x4__extadd_pairwise_i16x8_u, "i32x4.extadd_pairwise_i16x8_u", 0xFD, 127) +OFD(I16x8__abs, "i16x8.abs", 0xFD, 128) +OFD(I16x8__neg, "i16x8.neg", 0xFD, 129) +OFD(I16x8__q15mulr_sat_s, "i16x8.q15mulr_sat_s", 0xFD, 130) +OFD(I16x8__all_true, "i16x8.all_true", 0xFD, 131) +OFD(I16x8__bitmask, "i16x8.bitmask", 0xFD, 132) +OFD(I16x8__narrow_i32x4_s, "i16x8.narrow_i32x4_s", 0xFD, 133) +OFD(I16x8__narrow_i32x4_u, "i16x8.narrow_i32x4_u", 0xFD, 134) +OFD(I16x8__extend_low_i8x16_s, "i16x8.extend_low_i8x16_s", 0xFD, 135) +OFD(I16x8__extend_high_i8x16_s, "i16x8.extend_high_i8x16_s", 0xFD, 136) +OFD(I16x8__extend_low_i8x16_u, "i16x8.extend_low_i8x16_u", 0xFD, 137) +OFD(I16x8__extend_high_i8x16_u, "i16x8.extend_high_i8x16_u", 0xFD, 138) +OFD(I16x8__shl, "i16x8.shl", 0xFD, 139) +OFD(I16x8__shr_s, "i16x8.shr_s", 0xFD, 140) +OFD(I16x8__shr_u, "i16x8.shr_u", 0xFD, 141) +OFD(I16x8__add, "i16x8.add", 0xFD, 142) +OFD(I16x8__add_sat_s, "i16x8.add_sat_s", 0xFD, 143) +OFD(I16x8__add_sat_u, "i16x8.add_sat_u", 0xFD, 144) +OFD(I16x8__sub, "i16x8.sub", 0xFD, 145) +OFD(I16x8__sub_sat_s, "i16x8.sub_sat_s", 0xFD, 146) +OFD(I16x8__sub_sat_u, "i16x8.sub_sat_u", 0xFD, 147) +OFD(F64x2__nearest, "f64x2.nearest", 0xFD, 148) +OFD(I16x8__mul, "i16x8.mul", 0xFD, 149) +OFD(I16x8__min_s, "i16x8.min_s", 0xFD, 150) +OFD(I16x8__min_u, "i16x8.min_u", 0xFD, 151) +OFD(I16x8__max_s, "i16x8.max_s", 0xFD, 152) +OFD(I16x8__max_u, "i16x8.max_u", 0xFD, 153) +// 0xFD 154: Reserved +OFD(I16x8__avgr_u, "i16x8.avgr_u", 0xFD, 155) +OFD(I16x8__extmul_low_i8x16_s, "i16x8.extmul_low_i8x16_s", 0xFD, 156) +OFD(I16x8__extmul_high_i8x16_s, "i16x8.extmul_high_i8x16_s", 0xFD, 157) +OFD(I16x8__extmul_low_i8x16_u, "i16x8.extmul_low_i8x16_u", 0xFD, 158) +OFD(I16x8__extmul_high_i8x16_u, "i16x8.extmul_high_i8x16_u", 0xFD, 159) +OFD(I32x4__abs, "i32x4.abs", 0xFD, 160) +OFD(I32x4__neg, "i32x4.neg", 0xFD, 161) +// 0xFD 162: Reserved +OFD(I32x4__all_true, "i32x4.all_true", 0xFD, 163) +OFD(I32x4__bitmask, "i32x4.bitmask", 0xFD, 164) +// 0xFD 165: Reserved +// 0xFD 166: Reserved +OFD(I32x4__extend_low_i16x8_s, "i32x4.extend_low_i16x8_s", 0xFD, 167) +OFD(I32x4__extend_high_i16x8_s, "i32x4.extend_high_i16x8_s", 0xFD, 168) +OFD(I32x4__extend_low_i16x8_u, "i32x4.extend_low_i16x8_u", 0xFD, 169) +OFD(I32x4__extend_high_i16x8_u, "i32x4.extend_high_i16x8_u", 0xFD, 170) +OFD(I32x4__shl, "i32x4.shl", 0xFD, 171) +OFD(I32x4__shr_s, "i32x4.shr_s", 0xFD, 172) +OFD(I32x4__shr_u, "i32x4.shr_u", 0xFD, 173) +OFD(I32x4__add, "i32x4.add", 0xFD, 174) +// 0xFD 175: Reserved +// 0xFD 176: Reserved +OFD(I32x4__sub, "i32x4.sub", 0xFD, 177) +// 0xFD 178: Reserved +// 0xFD 179: Reserved +// 0xFD 180: Reserved +OFD(I32x4__mul, "i32x4.mul", 0xFD, 181) +OFD(I32x4__min_s, "i32x4.min_s", 0xFD, 182) +OFD(I32x4__min_u, "i32x4.min_u", 0xFD, 183) +OFD(I32x4__max_s, "i32x4.max_s", 0xFD, 184) +OFD(I32x4__max_u, "i32x4.max_u", 0xFD, 185) +OFD(I32x4__dot_i16x8_s, "i32x4.dot_i16x8_s", 0xFD, 186) +// 0xFD 187: Reserved +OFD(I32x4__extmul_low_i16x8_s, "i32x4.extmul_low_i16x8_s", 0xFD, 188) +OFD(I32x4__extmul_high_i16x8_s, "i32x4.extmul_high_i16x8_s", 0xFD, 189) +OFD(I32x4__extmul_low_i16x8_u, "i32x4.extmul_low_i16x8_u", 0xFD, 190) +OFD(I32x4__extmul_high_i16x8_u, "i32x4.extmul_high_i16x8_u", 0xFD, 191) +OFD(I64x2__abs, "i64x2.abs", 0xFD, 192) +OFD(I64x2__neg, "i64x2.neg", 0xFD, 193) +// 0xFD 194: Reserved +OFD(I64x2__all_true, "i64x2.all_true", 0xFD, 195) +OFD(I64x2__bitmask, "i64x2.bitmask", 0xFD, 196) +// 0xFD 197: Reserved +// 0xFD 198: Reserved +OFD(I64x2__extend_low_i32x4_s, "i64x2.extend_low_i32x4_s", 0xFD, 199) +OFD(I64x2__extend_high_i32x4_s, "i64x2.extend_high_i32x4_s", 0xFD, 200) +OFD(I64x2__extend_low_i32x4_u, "i64x2.extend_low_i32x4_u", 0xFD, 201) +OFD(I64x2__extend_high_i32x4_u, "i64x2.extend_high_i32x4_u", 0xFD, 202) +OFD(I64x2__shl, "i64x2.shl", 0xFD, 203) +OFD(I64x2__shr_s, "i64x2.shr_s", 0xFD, 204) +OFD(I64x2__shr_u, "i64x2.shr_u", 0xFD, 205) +OFD(I64x2__add, "i64x2.add", 0xFD, 206) +// 0xFD 207: Reserved +// 0xFD 208: Reserved +OFD(I64x2__sub, "i64x2.sub", 0xFD, 209) +// 0xFD 210: Reserved +// 0xFD 211: Reserved +// 0xFD 212: Reserved +OFD(I64x2__mul, "i64x2.mul", 0xFD, 213) +OFD(I64x2__eq, "i64x2.eq", 0xFD, 214) +OFD(I64x2__ne, "i64x2.ne", 0xFD, 215) +OFD(I64x2__lt_s, "i64x2.lt_s", 0xFD, 216) +OFD(I64x2__gt_s, "i64x2.gt_s", 0xFD, 217) +OFD(I64x2__le_s, "i64x2.le_s", 0xFD, 218) +OFD(I64x2__ge_s, "i64x2.ge_s", 0xFD, 219) +OFD(I64x2__extmul_low_i32x4_s, "i64x2.extmul_low_i32x4_s", 0xFD, 220) +OFD(I64x2__extmul_high_i32x4_s, "i64x2.extmul_high_i32x4_s", 0xFD, 221) +OFD(I64x2__extmul_low_i32x4_u, "i64x2.extmul_low_i32x4_u", 0xFD, 222) +OFD(I64x2__extmul_high_i32x4_u, "i64x2.extmul_high_i32x4_u", 0xFD, 223) +OFD(F32x4__abs, "f32x4.abs", 0xFD, 224) +OFD(F32x4__neg, "f32x4.neg", 0xFD, 225) +// 0xFD 226: Reserved +OFD(F32x4__sqrt, "f32x4.sqrt", 0xFD, 227) +OFD(F32x4__add, "f32x4.add", 0xFD, 228) +OFD(F32x4__sub, "f32x4.sub", 0xFD, 229) +OFD(F32x4__mul, "f32x4.mul", 0xFD, 230) +OFD(F32x4__div, "f32x4.div", 0xFD, 231) +OFD(F32x4__min, "f32x4.min", 0xFD, 232) +OFD(F32x4__max, "f32x4.max", 0xFD, 233) +OFD(F32x4__pmin, "f32x4.pmin", 0xFD, 234) +OFD(F32x4__pmax, "f32x4.pmax", 0xFD, 235) +OFD(F64x2__abs, "f64x2.abs", 0xFD, 236) +OFD(F64x2__neg, "f64x2.neg", 0xFD, 237) +OFD(F64x2__sqrt, "f64x2.sqrt", 0xFD, 239) +OFD(F64x2__add, "f64x2.add", 0xFD, 240) +OFD(F64x2__sub, "f64x2.sub", 0xFD, 241) +OFD(F64x2__mul, "f64x2.mul", 0xFD, 242) +OFD(F64x2__div, "f64x2.div", 0xFD, 243) +OFD(F64x2__min, "f64x2.min", 0xFD, 244) +OFD(F64x2__max, "f64x2.max", 0xFD, 245) +OFD(F64x2__pmin, "f64x2.pmin", 0xFD, 246) +OFD(F64x2__pmax, "f64x2.pmax", 0xFD, 247) +OFD(I32x4__trunc_sat_f32x4_s, "i32x4.trunc_sat_f32x4_s", 0xFD, 248) +OFD(I32x4__trunc_sat_f32x4_u, "i32x4.trunc_sat_f32x4_u", 0xFD, 249) +OFD(F32x4__convert_i32x4_s, "f32x4.convert_i32x4_s", 0xFD, 250) +OFD(F32x4__convert_i32x4_u, "f32x4.convert_i32x4_u", 0xFD, 251) +OFD(I32x4__trunc_sat_f64x2_s_zero, "i32x4.trunc_sat_f64x2_s_zero", 0xFD, 252) +OFD(I32x4__trunc_sat_f64x2_u_zero, "i32x4.trunc_sat_f64x2_u_zero", 0xFD, 253) +OFD(F64x2__convert_low_i32x4_s, "f64x2.convert_low_i32x4_s", 0xFD, 254) +OFD(F64x2__convert_low_i32x4_u, "f64x2.convert_low_i32x4_u", 0xFD, 255) + +// 0xFE prefix - Atomic instructions +OFE(Memory__atomic__notify, "memory.atomic.notify", 0xFE, 0) +OFE(Memory__atomic__wait32, "memory.atomic.wait32", 0xFE, 1) +OFE(Memory__atomic__wait64, "memory.atomic.wait64", 0xFE, 2) +OFE(Atomic__fence, "atomic.fence", 0xFE, 3) +// 0xFE 4 ~ 15: Reserved +OFE(I32__atomic__load, "i32.atomic.load", 0xFE, 16) +OFE(I64__atomic__load, "i64.atomic.load", 0xFE, 17) +OFE(I32__atomic__load8_u, "i32.atomic.load8_u", 0xFE, 18) +OFE(I32__atomic__load16_u, "i32.atomic.load16_u", 0xFE, 19) +OFE(I64__atomic__load8_u, "i64.atomic.load8_u", 0xFE, 20) +OFE(I64__atomic__load16_u, "i64.atomic.load16_u", 0xFE, 21) +OFE(I64__atomic__load32_u, "i64.atomic.load32_u", 0xFE, 22) +OFE(I32__atomic__store, "i32.atomic.store", 0xFE, 23) +OFE(I64__atomic__store, "i64.atomic.store", 0xFE, 24) +OFE(I32__atomic__store8, "i32.atomic.store8", 0xFE, 25) +OFE(I32__atomic__store16, "i32.atomic.store16", 0xFE, 26) +OFE(I64__atomic__store8, "i64.atomic.store8", 0xFE, 27) +OFE(I64__atomic__store16, "i64.atomic.store16", 0xFE, 28) +OFE(I64__atomic__store32, "i64.atomic.store32", 0xFE, 29) +OFE(I32__atomic__rmw__add, "i32.atomic.rmw.add", 0xFE, 30) +OFE(I64__atomic__rmw__add, "i64.atomic.rmw.add", 0xFE, 31) +OFE(I32__atomic__rmw8__add_u, "i32.atomic.rmw8.add_u", 0xFE, 32) +OFE(I32__atomic__rmw16__add_u, "i32.atomic.rmw16.add_u", 0xFE, 33) +OFE(I64__atomic__rmw8__add_u, "i64.atomic.rmw8.add_u", 0xFE, 34) +OFE(I64__atomic__rmw16__add_u, "i64.atomic.rmw16.add_u", 0xFE, 35) +OFE(I64__atomic__rmw32__add_u, "i64.atomic.rmw32.add_u", 0xFE, 36) +OFE(I32__atomic__rmw__sub, "i32.atomic.rmw.sub", 0xFE, 37) +OFE(I64__atomic__rmw__sub, "i64.atomic.rmw.sub", 0xFE, 38) +OFE(I32__atomic__rmw8__sub_u, "i32.atomic.rmw8.sub_u", 0xFE, 39) +OFE(I32__atomic__rmw16__sub_u, "i32.atomic.rmw16.sub_u", 0xFE, 40) +OFE(I64__atomic__rmw8__sub_u, "i64.atomic.rmw8.sub_u", 0xFE, 41) +OFE(I64__atomic__rmw16__sub_u, "i64.atomic.rmw16.sub_u", 0xFE, 42) +OFE(I64__atomic__rmw32__sub_u, "i64.atomic.rmw32.sub_u", 0xFE, 43) +OFE(I32__atomic__rmw__and, "i32.atomic.rmw.and", 0xFE, 44) +OFE(I64__atomic__rmw__and, "i64.atomic.rmw.and", 0xFE, 45) +OFE(I32__atomic__rmw8__and_u, "i32.atomic.rmw8.and_u", 0xFE, 46) +OFE(I32__atomic__rmw16__and_u, "i32.atomic.rmw16.and_u", 0xFE, 47) +OFE(I64__atomic__rmw8__and_u, "i64.atomic.rmw8.and_u", 0xFE, 48) +OFE(I64__atomic__rmw16__and_u, "i64.atomic.rmw16.and_u", 0xFE, 49) +OFE(I64__atomic__rmw32__and_u, "i64.atomic.rmw32.and_u", 0xFE, 50) +OFE(I32__atomic__rmw__or, "i32.atomic.rmw.or", 0xFE, 51) +OFE(I64__atomic__rmw__or, "i64.atomic.rmw.or", 0xFE, 52) +OFE(I32__atomic__rmw8__or_u, "i32.atomic.rmw8.or_u", 0xFE, 53) +OFE(I32__atomic__rmw16__or_u, "i32.atomic.rmw16.or_u", 0xFE, 54) +OFE(I64__atomic__rmw8__or_u, "i64.atomic.rmw8.or_u", 0xFE, 55) +OFE(I64__atomic__rmw16__or_u, "i64.atomic.rmw16.or_u", 0xFE, 56) +OFE(I64__atomic__rmw32__or_u, "i64.atomic.rmw32.or_u", 0xFE, 57) +OFE(I32__atomic__rmw__xor, "i32.atomic.rmw.xor", 0xFE, 58) +OFE(I64__atomic__rmw__xor, "i64.atomic.rmw.xor", 0xFE, 59) +OFE(I32__atomic__rmw8__xor_u, "i32.atomic.rmw8.xor_u", 0xFE, 60) +OFE(I32__atomic__rmw16__xor_u, "i32.atomic.rmw16.xor_u", 0xFE, 61) +OFE(I64__atomic__rmw8__xor_u, "i64.atomic.rmw8.xor_u", 0xFE, 62) +OFE(I64__atomic__rmw16__xor_u, "i64.atomic.rmw16.xor_u", 0xFE, 63) +OFE(I64__atomic__rmw32__xor_u, "i64.atomic.rmw32.xor_u", 0xFE, 64) +OFE(I32__atomic__rmw__xchg, "i32.atomic.rmw.xchg", 0xFE, 65) +OFE(I64__atomic__rmw__xchg, "i64.atomic.rmw.xchg", 0xFE, 66) +OFE(I32__atomic__rmw8__xchg_u, "i32.atomic.rmw8.xchg_u", 0xFE, 67) +OFE(I32__atomic__rmw16__xchg_u, "i32.atomic.rmw16.xchg_u", 0xFE, 68) +OFE(I64__atomic__rmw8__xchg_u, "i64.atomic.rmw8.xchg_u", 0xFE, 69) +OFE(I64__atomic__rmw16__xchg_u, "i64.atomic.rmw16.xchg_u", 0xFE, 70) +OFE(I64__atomic__rmw32__xchg_u, "i64.atomic.rmw32.xchg_u", 0xFE, 71) +OFE(I32__atomic__rmw__cmpxchg, "i32.atomic.rmw.cmpxchg", 0xFE, 72) +OFE(I64__atomic__rmw__cmpxchg, "i64.atomic.rmw.cmpxchg", 0xFE, 73) +OFE(I32__atomic__rmw8__cmpxchg_u, "i32.atomic.rmw8.cmpxchg_u", 0xFE, 74) +OFE(I32__atomic__rmw16__cmpxchg_u, "i32.atomic.rmw16.cmpxchg_u", 0xFE, 75) +OFE(I64__atomic__rmw8__cmpxchg_u, "i64.atomic.rmw8.cmpxchg_u", 0xFE, 76) +OFE(I64__atomic__rmw16__cmpxchg_u, "i64.atomic.rmw16.cmpxchg_u", 0xFE, 77) +OFE(I64__atomic__rmw32__cmpxchg_u, "i64.atomic.rmw32.cmpxchg_u", 0xFE, 78) #undef O +#undef OFB +#undef OFC +#undef OFD +#undef OFE #endif // UseOpCode // enum_configure.h diff --git a/include/common/enum_ast.hpp b/include/common/enum_ast.hpp index b2526fcef136..0b6f16582808 100644 --- a/include/common/enum_ast.hpp +++ b/include/common/enum_ast.hpp @@ -46,15 +46,22 @@ static inline constexpr auto ASTNodeAttrStr = []() constexpr { #undef UseASTNodeAttr }; return DenseEnumMap(Array); -} -(); +}(); /// Instruction opcode enumeration class. -enum class OpCode : uint16_t { +enum class OpCode : uint32_t { #define UseOpCode -#define Line(NAME, VALUE, STRING) NAME = VALUE, +#define Line(NAME, STRING, PREFIX) NAME, +#define Line_FB(NAME, STRING, PREFIX, EXTEND) NAME, +#define Line_FC(NAME, STRING, PREFIX, EXTEND) NAME, +#define Line_FD(NAME, STRING, PREFIX, EXTEND) NAME, +#define Line_FE(NAME, STRING, PREFIX, EXTEND) NAME, #include "enum.inc" #undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE #undef UseOpCode }; @@ -63,14 +70,21 @@ static inline constexpr const auto OpCodeStr = []() constexpr { using namespace std::literals::string_view_literals; std::pair Array[] = { #define UseOpCode -#define Line(NAME, VALUE, STRING) {OpCode::NAME, STRING}, +#define Line(NAME, STRING, PREFIX) {OpCode::NAME, STRING}, +#define Line_FB(NAME, STRING, PREFIX, EXTEND) {OpCode::NAME, STRING}, +#define Line_FC(NAME, STRING, PREFIX, EXTEND) {OpCode::NAME, STRING}, +#define Line_FD(NAME, STRING, PREFIX, EXTEND) {OpCode::NAME, STRING}, +#define Line_FE(NAME, STRING, PREFIX, EXTEND) {OpCode::NAME, STRING}, #include "enum.inc" #undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE #undef UseOpCode }; return SpareEnumMap(Array); -} -(); +}(); } // namespace WasmEdge diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index 2f35e643a47d..8088c37e9f88 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -12,24 +12,124 @@ namespace Loader { // OpCode loader. See "include/loader/loader.h". Expect Loader::loadOpCode() { - uint16_t Payload; + uint8_t Prefix; if (auto B1 = FMgr.readByte()) { - Payload = (*B1); + Prefix = (*B1); } else { return Unexpect(B1); } - if (Payload == 0xFBU || Payload == 0xFCU || Payload == 0xFDU || - Payload == 0xFEU) { - // 2-bytes OpCode case. + if (Prefix >= 0xFBU && Prefix <= 0xFEU) { + // Multi-byte OpCode case. + uint32_t Extend; if (auto B2 = FMgr.readU32()) { - Payload <<= 8; - Payload += static_cast(*B2); + Extend = (*B2); } else { return Unexpect(B2); } + if (Prefix == 0xFBU) { + switch (Extend) { +#define UseOpCode +#define Line(NAME, STRING, PREFIX) +#define Line_FB(NAME, STRING, PREFIX, EXTEND) \ + case EXTEND: \ + return OpCode::NAME; +#define Line_FC(NAME, STRING, PREFIX, EXTEND) +#define Line_FD(NAME, STRING, PREFIX, EXTEND) +#define Line_FE(NAME, STRING, PREFIX, EXTEND) +#include "common/enum.inc" +#undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE +#undef UseOpCode + default: + return Unexpect(ErrCode::Value::IllegalOpCode); + } + } else if (Prefix == 0xFCU) { + switch (Extend) { +#define UseOpCode +#define Line(NAME, STRING, PREFIX) +#define Line_FB(NAME, STRING, PREFIX, EXTEND) +#define Line_FC(NAME, STRING, PREFIX, EXTEND) \ + case EXTEND: \ + return OpCode::NAME; +#define Line_FD(NAME, STRING, PREFIX, EXTEND) +#define Line_FE(NAME, STRING, PREFIX, EXTEND) +#include "common/enum.inc" +#undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE +#undef UseOpCode + default: + return Unexpect(ErrCode::Value::IllegalOpCode); + } + } else if (Prefix == 0xFDU) { + switch (Extend) { +#define UseOpCode +#define Line(NAME, STRING, PREFIX) +#define Line_FB(NAME, STRING, PREFIX, EXTEND) +#define Line_FC(NAME, STRING, PREFIX, EXTEND) +#define Line_FD(NAME, STRING, PREFIX, EXTEND) \ + case EXTEND: \ + return OpCode::NAME; +#define Line_FE(NAME, STRING, PREFIX, EXTEND) +#include "common/enum.inc" +#undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE +#undef UseOpCode + default: + return Unexpect(ErrCode::Value::IllegalOpCode); + } + } else { + switch (Extend) { +#define UseOpCode +#define Line(NAME, STRING, PREFIX) +#define Line_FB(NAME, STRING, PREFIX, EXTEND) +#define Line_FC(NAME, STRING, PREFIX, EXTEND) +#define Line_FD(NAME, STRING, PREFIX, EXTEND) +#define Line_FE(NAME, STRING, PREFIX, EXTEND) \ + case EXTEND: \ + return OpCode::NAME; +#include "common/enum.inc" +#undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE +#undef UseOpCode + default: + return Unexpect(ErrCode::Value::IllegalOpCode); + } + } + } else { + // Single-byte OpCode case. + switch (Prefix) { +#define UseOpCode +#define Line(NAME, STRING, PREFIX) \ + case PREFIX: \ + return OpCode::NAME; +#define Line_FB(NAME, STRING, PREFIX, EXTEND) +#define Line_FC(NAME, STRING, PREFIX, EXTEND) +#define Line_FD(NAME, STRING, PREFIX, EXTEND) +#define Line_FE(NAME, STRING, PREFIX, EXTEND) +#include "common/enum.inc" +#undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE +#undef UseOpCode + default: + return Unexpect(ErrCode::Value::IllegalOpCode); + } } - return static_cast(Payload); } // Load instruction sequence. See "include/loader/loader.h". @@ -1020,8 +1120,7 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return readMemImmediate(); default: - return logLoadError(ErrCode::Value::IllegalOpCode, Instr.getOffset(), - ASTNodeAttr::Instruction); + assumingUnreachable(); } } diff --git a/lib/loader/serialize/serial_instruction.cpp b/lib/loader/serialize/serial_instruction.cpp index f029b105d7db..e28660049fd9 100644 --- a/lib/loader/serialize/serial_instruction.cpp +++ b/lib/loader/serialize/serial_instruction.cpp @@ -39,12 +39,41 @@ Serializer::serializeInstruction(const AST::Instruction &Instr, } // Serialize OpCode. - uint32_t Num = static_cast(Instr.getOpCode()); - if (Num >= 0x100U) { - OutVec.push_back(static_cast(Num >> 8)); - serializeU32(Num & 0xFFU, OutVec); - } else { - OutVec.push_back(static_cast(Num & 0xFFU)); + switch (Instr.getOpCode()) { +#define UseOpCode +#define Line(NAME, STRING, PREFIX) \ + case OpCode::NAME: \ + OutVec.push_back(static_cast(PREFIX)); \ + break; +#define Line_FB(NAME, STRING, PREFIX, EXTEND) \ + case OpCode::NAME: \ + OutVec.push_back(static_cast(PREFIX)); \ + serializeU32(EXTEND, OutVec); \ + break; +#define Line_FC(NAME, STRING, PREFIX, EXTEND) \ + case OpCode::NAME: \ + OutVec.push_back(static_cast(PREFIX)); \ + serializeU32(EXTEND, OutVec); \ + break; +#define Line_FD(NAME, STRING, PREFIX, EXTEND) \ + case OpCode::NAME: \ + OutVec.push_back(static_cast(PREFIX)); \ + serializeU32(EXTEND, OutVec); \ + break; +#define Line_FE(NAME, STRING, PREFIX, EXTEND) \ + case OpCode::NAME: \ + OutVec.push_back(static_cast(PREFIX)); \ + serializeU32(EXTEND, OutVec); \ + break; +#include "common/enum.inc" +#undef Line +#undef Line_FB +#undef Line_FC +#undef Line_FD +#undef Line_FE +#undef UseOpCode + default: + assumingUnreachable(); } // Serialize immediate. @@ -726,8 +755,7 @@ Serializer::serializeInstruction(const AST::Instruction &Instr, return serializeMemImmediate(); default: - return logSerializeError(ErrCode::Value::IllegalOpCode, - ASTNodeAttr::Instruction); + assumingUnreachable(); } } From 0fd768bf544d521ecce5065cf0f35b11a4526d22 Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 18 Apr 2024 09:17:00 +0800 Subject: [PATCH 140/218] [CI] Deprecated mdbook workflow, use WasmEdge/docs instead (#3339) Signed-off-by: hydai --- .github/workflows/mdbook.yml | 88 ------------------------------------ 1 file changed, 88 deletions(-) delete mode 100644 .github/workflows/mdbook.yml diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml deleted file mode 100644 index e2dd640b8125..000000000000 --- a/.github/workflows/mdbook.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: MDBOOK - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -on: - workflow_dispatch: - inputs: - logLevel: - description: 'Log level' - required: true - default: 'info' - push: - branches: [ master ] - paths: - - 'docs/**' - pull_request: - branches: [ master ] - paths: - - 'docs/**' - -jobs: - lint-markdown: - if: ${{ github.event_name != 'push' }} - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Ensure git safe directory - run: | - git config --global --add safe.directory $(pwd) - - - name: Lint markdown format - uses: github/super-linter/slim@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DEFAULT_BRANCH: master - FILTER_REGEX_INCLUDE: .*docs/.*md$ - VALIDATE_ALL_CODEBASE: false - VALIDATE_MARKDOWN: true - - build-mdbook: - needs: lint-markdown - if: | - always() - && (needs.lint-markdown.result == 'success' || needs.lint-markdown.result == 'skipped') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Ensure git safe directory - run: | - git config --global --add safe.directory $(pwd) - - - name: Setup mdBook - uses: peaceiris/actions-mdbook@v1 - with: - mdbook-version: 'latest' - - - name: Install mdBook preprocessors - run: | - cargo install mdbook-variables --locked - - - name: Create work dir - run: | - cd docs/book/ - mkdir target - - - name: Build English version - run: | - cd docs/book/en - mdbook build - cp -r book ../target/en - - - name: Publish EN version - if: ${{ github.event_name == 'push' }} - uses: cpina/github-action-push-to-another-repository@main - env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB_WWW }} - with: - source-directory: 'docs/book/target' - destination-github-username: 'WasmEdge' - destination-repository-name: 'www' - target-directory: 'book' - user-email: michael@secondstate.io - target-branch: main From 2b171bd202255abba524dd59e187407d5eb20055 Mon Sep 17 00:00:00 2001 From: "Shen-Ta Hsieh(BestSteve)" Date: Thu, 18 Apr 2024 10:23:41 +0800 Subject: [PATCH 141/218] [Plugin] Handle API version mismatch error (#3329) * Remove currently unused `NiftyCounter` related mechanism Signed-off-by: Shen-Ta Hsieh --- include/plugin/plugin.h | 6 +-- lib/plugin/plugin.cpp | 90 ++++++++++++++--------------------------- 2 files changed, 33 insertions(+), 63 deletions(-) diff --git a/include/plugin/plugin.h b/include/plugin/plugin.h index d8f432e5a1ad..e89013ad31f3 100644 --- a/include/plugin/plugin.h +++ b/include/plugin/plugin.h @@ -146,8 +146,8 @@ class Plugin { std::filesystem::path path() const noexcept { return Path; } private: - static std::vector &PluginRegistry; - static std::unordered_map &PluginNameLookup; + static std::vector PluginRegistry; + static std::unordered_map PluginNameLookup; std::filesystem::path Path; const PluginDescriptor *Desc = nullptr; @@ -158,7 +158,7 @@ class Plugin { static bool loadFile(const std::filesystem::path &Path) noexcept; public: - WASMEDGE_EXPORT static void + WASMEDGE_EXPORT static bool registerPlugin(const PluginDescriptor *Desc) noexcept; }; diff --git a/lib/plugin/plugin.cpp b/lib/plugin/plugin.cpp index 28c44a3be3f1..6883d129e248 100644 --- a/lib/plugin/plugin.cpp +++ b/lib/plugin/plugin.cpp @@ -36,32 +36,6 @@ template <> struct Parser { namespace Plugin { namespace { -static unsigned int NiftyCounter = 0; -static std::aligned_storage_t), - alignof(std::vector)> - PluginRegistryStorage; -static std::aligned_storage_t< - sizeof(std::unordered_map), - alignof(std::unordered_map)> - PluginNameLookupStorage; - -void IncreaseNiftyCounter() noexcept { - if (NiftyCounter++ == 0) { - new (&PluginRegistryStorage) std::vector(); - new (&PluginNameLookupStorage) - std::unordered_map(); - } -} - -void DecreaseNiftyCounter() noexcept { - if (--NiftyCounter == 0) { - reinterpret_cast &>(PluginRegistryStorage) - .~vector(); - reinterpret_cast &>( - PluginNameLookupStorage) - .~unordered_map(); - } -} class CAPIPluginRegister { public: @@ -165,9 +139,9 @@ class CAPIPluginRegister { } } - Plugin::registerPlugin(&Descriptor); + Result = Plugin::registerPlugin(&Descriptor); } - ~CAPIPluginRegister() noexcept { DecreaseNiftyCounter(); } + bool result() const noexcept { return Result; } private: static Runtime::Instance::ModuleInstance * @@ -211,6 +185,8 @@ class CAPIPluginRegister { static std::unordered_map DescriptionLookup; + + bool Result = false; }; std::unordered_map @@ -220,11 +196,9 @@ std::vector> CAPIPluginRegisters; } // namespace -std::vector &Plugin::PluginRegistry = - reinterpret_cast &>(PluginRegistryStorage); -std::unordered_map &Plugin::PluginNameLookup = - reinterpret_cast &>( - PluginNameLookupStorage); +std::vector WasmEdge::Plugin::Plugin::PluginRegistry; +std::unordered_map + WasmEdge::Plugin::Plugin::PluginNameLookup; std::vector Plugin::getDefaultPluginPaths() noexcept { using namespace std::literals::string_view_literals; @@ -341,8 +315,7 @@ WASMEDGE_EXPORT bool Plugin::load(const std::filesystem::path &Path) noexcept { } bool Plugin::loadFile(const std::filesystem::path &Path) noexcept { - const auto Index = PluginRegistry.size(); - + bool Result = false; auto Lib = std::make_shared(); if (auto Res = Lib->load(Path); unlikely(!Res)) { return false; @@ -350,15 +323,10 @@ bool Plugin::loadFile(const std::filesystem::path &Path) noexcept { if (auto GetDescriptor = Lib->get("GetDescriptor")) { - if (find(GetDescriptor()->Name)) { - spdlog::debug("Plugin: {} has already loaded."sv, GetDescriptor()->Name); - return true; - } else { - Plugin::registerPlugin(GetDescriptor()); - } + Result = Plugin::registerPlugin(GetDescriptor()); } - if (PluginRegistry.size() != Index + 1) { + if (!Result) { // Check C interface if (auto GetDescriptor = Lib->get( "WasmEdge_Plugin_GetDescriptor"); @@ -368,16 +336,17 @@ bool Plugin::loadFile(const std::filesystem::path &Path) noexcept { unlikely(!Descriptor)) { return false; } else { - if (find(Descriptor->Name)) { - spdlog::debug("Plugin: {} has already loaded."sv, Descriptor->Name); - return true; - } else { - CAPIPluginRegisters.push_back( - std::make_unique(Descriptor)); - } + Result = + CAPIPluginRegisters + .emplace_back(std::make_unique(Descriptor)) + ->result(); } } + if (!Result) { + return false; + } + auto &Plugin = PluginRegistry.back(); Plugin.Path = Path; Plugin.Lib = std::move(Lib); @@ -393,31 +362,32 @@ void Plugin::addPluginOptions(PO::ArgumentParser &Parser) noexcept { } WASMEDGE_EXPORT const Plugin *Plugin::find(std::string_view Name) noexcept { - if (NiftyCounter != 0) { - if (auto Iter = PluginNameLookup.find(Name); - Iter != PluginNameLookup.end()) { - return std::addressof(PluginRegistry[Iter->second]); - } + if (auto Iter = PluginNameLookup.find(Name); Iter != PluginNameLookup.end()) { + return std::addressof(PluginRegistry[Iter->second]); } return nullptr; } Span Plugin::plugins() noexcept { return PluginRegistry; } -WASMEDGE_EXPORT void +WASMEDGE_EXPORT bool Plugin::registerPlugin(const PluginDescriptor *Desc) noexcept { if (Desc->APIVersion != CurrentAPIVersion) { - return; + spdlog::debug( + "Plugin: API version {} of plugin {} is not match to current {}."sv, + Desc->APIVersion, Desc->Name, CurrentAPIVersion); + return false; + } + if (PluginNameLookup.find(Desc->Name) != PluginNameLookup.end()) { + spdlog::debug("Plugin: {} has already loaded."sv, Desc->Name); + return false; } - - IncreaseNiftyCounter(); - assuming(NiftyCounter != 0); const auto Index = PluginRegistry.size(); PluginRegistry.emplace_back(Desc); PluginNameLookup.emplace(Desc->Name, Index); - return; + return true; } Plugin::Plugin(const PluginDescriptor *D) noexcept : Desc(D) { From 5767a1ff6013644d5fc2ee81cffeff723b1d6783 Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 18 Apr 2024 11:19:43 +0800 Subject: [PATCH 142/218] [CI] Bump codecov-action from v3 to v4 (#3340) * Inherit secrets from the calling workflow to the reusable one * Ref: https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-inputs-and-secrets-in-a-reusable-workflow Signed-off-by: hydai --- .github/workflows/build.yml | 1 + .github/workflows/reusable-build-on-ubuntu.yml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4b05b412021e..c255046d8e6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -124,6 +124,7 @@ jobs: needs: [get_version, lint] name: Ubuntu uses: ./.github/workflows/reusable-build-on-ubuntu.yml + secrets: inherit with: version: ${{ needs.get_version.outputs.version }} matrix: "[{'name':'ubuntu-22.04','compiler':'g++','build_type':'Debug','docker_tag':'ubuntu-build-gcc','tests':true}, diff --git a/.github/workflows/reusable-build-on-ubuntu.yml b/.github/workflows/reusable-build-on-ubuntu.yml index a217256e62ec..70ed6e75823c 100644 --- a/.github/workflows/reusable-build-on-ubuntu.yml +++ b/.github/workflows/reusable-build-on-ubuntu.yml @@ -102,9 +102,10 @@ jobs: gh release upload ${{ inputs.version }} WasmEdge-${{ inputs.version }}-ubuntu20.04_x86_64.tar.gz --clobber - name: Create and upload coverage report to Codecov if: ${{ matrix.coverage }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./build/codecov.xml name: codecov-wasmedge fail_ci_if_error: true + verbose: true From d828dcddfe6bb35deb3c7407ae9ce7879ca9c206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Thu, 18 Apr 2024 15:43:16 +0800 Subject: [PATCH 143/218] [component] a super minor bug (#3341) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn Co-authored-by: hydai --- lib/loader/ast/component/type.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/loader/ast/component/type.cpp b/lib/loader/ast/component/type.cpp index 55667be7819a..f2d75427b774 100644 --- a/lib/loader/ast/component/type.cpp +++ b/lib/loader/ast/component/type.cpp @@ -362,7 +362,7 @@ Expect Loader::loadType(FuncType &Ty) { // ps: rs: // => (func ps rs) if (auto Res = loadVec( - Ty.getParamList(), [this](LabelValType LV) { return loadType(LV); }); + Ty.getParamList(), [this](LabelValType &LV) { return loadType(LV); }); !Res) { return Unexpect(Res); } From 87dc202b726c2fea7e47f8ffbf3a1ca5a183ad0f Mon Sep 17 00:00:00 2001 From: dm4 Date: Tue, 16 Apr 2024 14:37:48 +0800 Subject: [PATCH 144/218] [WASI-NN] ggml: add ErrNo::ModelNotFound Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 7 +++++++ plugins/wasi_nn/types.h | 1 + 2 files changed, 8 insertions(+) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index f85b2b68e9f3..25da580000ec 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -709,6 +710,12 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, spdlog::info( "[WASI-NN][Debug] GGML backend: Finished handling model path."sv); } + // Check if the model exists. + if (!std::filesystem::exists(std::filesystem::u8path(ModelFilePath))) { + spdlog::error("[WASI-NN] GGML backend: Model file not found."sv); + Env.NNGraph.pop_back(); + return ErrNo::ModelNotFound; + } if (GraphRef.EnableDebugLog) { spdlog::info( diff --git a/plugins/wasi_nn/types.h b/plugins/wasi_nn/types.h index 453b320bed5f..f14350b49188 100644 --- a/plugins/wasi_nn/types.h +++ b/plugins/wasi_nn/types.h @@ -21,6 +21,7 @@ enum class ErrNo : uint32_t { EndOfSequence = 100, // End of Sequence Found. ContextFull = 101, // Context Full. PromptTooLong = 102, // Prompt Too Long. + ModelNotFound = 103, // Model Not Found. }; enum class TensorType : uint8_t { F16 = 0, F32 = 1, U8 = 2, I32 = 3 }; From 0546a398135fc79a6ec3f8107d6e57b6f26dcf90 Mon Sep 17 00:00:00 2001 From: dm4 Date: Thu, 18 Apr 2024 16:37:28 +0800 Subject: [PATCH 145/218] [CI] Add ffmpeg path to pkg-config on macOS Signed-off-by: dm4 --- .github/workflows/build-extensions.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 5f09be8c62e3..65fe612aa492 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -355,6 +355,7 @@ jobs: run: | eval $(/opt/homebrew/bin/brew shellenv) testbin_array=(${test_bins}) + export PKG_CONFIG_PATH="$(brew --prefix)/opt/ffmpeg@6/lib/pkgconfig:$PKG_CONFIG_PATH" export LLVM_DIR="$(brew --prefix)/opt/llvm@16/lib/cmake" export CC=clang export CXX=clang++ From b89d007fbdd76164f9536b113b931cd6fbde2561 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 19 Apr 2024 12:25:48 +0800 Subject: [PATCH 146/218] [WASI-NN] ggml: bump tp b2694 to fix the MoE segfault (#3345) Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 17e995559fd5..5c153f07b410 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -62,7 +62,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2636 + GIT_TAG b2694 PATCH_COMMAND git checkout . COMMAND git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch GIT_SHALLOW FALSE From 48dd6dec43ecfd5234754de5a56ed044f924505c Mon Sep 17 00:00:00 2001 From: dm4 Date: Mon, 22 Apr 2024 17:17:43 +0800 Subject: [PATCH 147/218] [WASI-NN] ggml: add unload function Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 11 +++++++++++ plugins/wasi_nn/ggml.h | 2 ++ plugins/wasi_nn/wasinnenv.h | 11 +++++++++++ plugins/wasi_nn/wasinnfunc.cpp | 28 ++++++++++++++++++++++++++++ plugins/wasi_nn/wasinnfunc.h | 12 ++++++++++++ plugins/wasi_nn/wasinnmodule.cpp | 1 + 6 files changed, 65 insertions(+) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 25da580000ec..8af214bd02c3 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -1336,6 +1336,17 @@ Expect finiSingle(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { return ErrNo::Success; } +Expect unload(WasiNNEnvironment &Env, uint32_t GraphId) noexcept { + auto &GraphRef = Env.NNGraph[GraphId].get(); + if (GraphRef.LlamaModel != nullptr) { + llama_free_model(GraphRef.LlamaModel); + GraphRef.LlamaModel = nullptr; + } + Env.NNGraph.erase(Env.NNGraph.begin() + GraphId); + Env.mdRemoveById(GraphId); + return ErrNo::Success; +} + #else namespace { Expect reportBackendNotSupported() noexcept { diff --git a/plugins/wasi_nn/ggml.h b/plugins/wasi_nn/ggml.h index f8978d2985d0..e334ca5df16c 100644 --- a/plugins/wasi_nn/ggml.h +++ b/plugins/wasi_nn/ggml.h @@ -96,4 +96,6 @@ Expect computeSingle(WASINN::WasiNNEnvironment &Env, uint32_t ContextId) noexcept; Expect finiSingle(WASINN::WasiNNEnvironment &Env, uint32_t ContextId) noexcept; +Expect unload(WASINN::WasiNNEnvironment &Env, + uint32_t GraphId) noexcept; } // namespace WasmEdge::Host::WASINN::GGML diff --git a/plugins/wasi_nn/wasinnenv.h b/plugins/wasi_nn/wasinnenv.h index bc83b73900a7..e1e45b2fa7c0 100644 --- a/plugins/wasi_nn/wasinnenv.h +++ b/plugins/wasi_nn/wasinnenv.h @@ -168,6 +168,17 @@ struct WasiNNEnvironment : return false; } + void mdRemoveById(uint32_t GraphId) noexcept { + std::unique_lock Lock(MdMutex); + for (auto It = MdMap.begin(); It != MdMap.end();) { + if (It->second == static_cast(GraphId)) { + It = MdMap.erase(It); + } else { + ++It; + } + } + } + Expect mdBuild(std::string Name, uint32_t &GraphId, Callback Load, std::vector Config = std::vector()) noexcept { diff --git a/plugins/wasi_nn/wasinnfunc.cpp b/plugins/wasi_nn/wasinnfunc.cpp index defaf6aeb690..6e609d4f7bc7 100644 --- a/plugins/wasi_nn/wasinnfunc.cpp +++ b/plugins/wasi_nn/wasinnfunc.cpp @@ -576,5 +576,33 @@ WasiNNFiniSingle::bodyImpl(const Runtime::CallingFrame &Frame, } } +Expect WasiNNUnload::bodyImpl(const Runtime::CallingFrame &Frame, + uint32_t GraphId) { +#ifdef WASMEDGE_BUILD_WASI_NN_RPC + if (Env.NNRPCChannel != nullptr) { + // TODO: implement RPC for unload + spdlog::error("[WASI-NN] RPC client is not implemented for unload"sv); + return WASINN::ErrNo::UnsupportedOperation; + } +#endif + auto *MemInst = Frame.getMemoryByIndex(0); + if (MemInst == nullptr) { + return Unexpect(ErrCode::Value::HostFuncError); + } + + if (Env.NNGraph.size() <= GraphId) { + spdlog::error("[WASI-NN] unload: GraphId {} does not exist."sv, GraphId); + return WASINN::ErrNo::InvalidArgument; + } + + switch (Env.NNGraph[GraphId].getBackend()) { + case WASINN::Backend::GGML: + return WASINN::GGML::unload(Env, GraphId); + default: + spdlog::error("[WASI-NN] unlaod: Only GGML backend supports unload."sv); + return WASINN::ErrNo::InvalidArgument; + } +} + } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasi_nn/wasinnfunc.h b/plugins/wasi_nn/wasinnfunc.h index 7dcfbd2ad24c..dcda910cd2e8 100644 --- a/plugins/wasi_nn/wasinnfunc.h +++ b/plugins/wasi_nn/wasinnfunc.h @@ -161,5 +161,17 @@ class WasiNNFiniSingle : public WasiNN { uint32_t Context); }; +class WasiNNUnload : public WasiNN { +public: + WasiNNUnload(WASINN::WasiNNEnvironment &HostEnv) : WasiNN(HostEnv) {} + Expect body(const Runtime::CallingFrame &Frame, uint32_t GraphId) { + return bodyImpl(Frame, GraphId).map(castErrNo); + } + +private: + Expect bodyImpl(const Runtime::CallingFrame &Frame, + uint32_t GraphId); +}; + } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasi_nn/wasinnmodule.cpp b/plugins/wasi_nn/wasinnmodule.cpp index c224640527c0..b2b2c6d5e4bc 100644 --- a/plugins/wasi_nn/wasinnmodule.cpp +++ b/plugins/wasi_nn/wasinnmodule.cpp @@ -21,6 +21,7 @@ WasiNNModule::WasiNNModule() : ModuleInstance("wasi_ephemeral_nn") { addHostFunc("compute", std::make_unique(Env)); addHostFunc("compute_single", std::make_unique(Env)); addHostFunc("fini_single", std::make_unique(Env)); + addHostFunc("unload", std::make_unique(Env)); } } // namespace Host From 50bd62f7362ef1ca5719842ea5b0e751ccc85a2b Mon Sep 17 00:00:00 2001 From: dm4 Date: Tue, 23 Apr 2024 11:52:06 +0800 Subject: [PATCH 148/218] [WASI-NN] ggml: bump llama.cpp b2715 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- plugins/wasi_nn/ggml.cpp | 10 ++-- thirdparty/ggml/ggml.patch | 94 ++-------------------------------- 3 files changed, 9 insertions(+), 97 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 5c153f07b410..601f735ea080 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -62,7 +62,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2694 + GIT_TAG b2715 PATCH_COMMAND git checkout . COMMAND git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch GIT_SHALLOW FALSE diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 8af214bd02c3..401abbf0a832 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -472,7 +472,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, llama_token_bos(GraphRef.LlamaModel)); } // Add EOS if not present. - if (CxtRef.LlamaInputs.back() != llama_token_eos(GraphRef.LlamaModel)) { + if (!llama_token_is_eog(GraphRef.LlamaModel, CxtRef.LlamaInputs.back())) { CxtRef.LlamaInputs.push_back(llama_token_eos(GraphRef.LlamaModel)); } @@ -1086,8 +1086,8 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { break; } // Deal with end of text token. - if (llama_sampling_last(CtxSampling) == - llama_token_eos(GraphRef.LlamaModel)) { + if (llama_token_is_eog(GraphRef.LlamaModel, + llama_sampling_last(CtxSampling))) { if (GraphRef.EnableLog) { spdlog::info("[WASI-NN] GGML backend: EOS token found"sv); } @@ -1266,8 +1266,8 @@ Expect computeSingle(WasiNNEnvironment &Env, CxtRef.LlamaOutputTokens.emplace_back(Id); CxtRef.LlamaOutputs += llama_token_to_piece(CxtRef.LlamaContext, Id); // Deal with end of text token. - if (llama_sampling_last(CxtRef.LlamaSampling) == - llama_token_eos(GraphRef.LlamaModel)) { + if (llama_token_is_eog(GraphRef.LlamaModel, + llama_sampling_last(CxtRef.LlamaSampling))) { ReturnCode = ErrNo::EndOfSequence; if (GraphRef.EnableLog) { spdlog::info("[WASI-NN] GGML backend: EOS token found"sv); diff --git a/thirdparty/ggml/ggml.patch b/thirdparty/ggml/ggml.patch index af9d0598b52e..fe547217f925 100644 --- a/thirdparty/ggml/ggml.patch +++ b/thirdparty/ggml/ggml.patch @@ -1,93 +1,5 @@ -diff --git a/examples/llava/clip.cpp b/examples/llava/clip.cpp -index ef9e4ba7..a1b49793 100644 ---- a/examples/llava/clip.cpp -+++ b/examples/llava/clip.cpp -@@ -859,6 +859,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - - // kv - const int n_kv = gguf_get_n_kv(ctx); -+ if (verbosity >= 1) { - printf("%s: loaded meta data with %d key-value pairs and %d tensors from %s\n", - __func__, n_kv, n_tensors, fname); - { -@@ -898,6 +899,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - printf("%s: - type %4s: %4d tensors\n", __func__, ggml_type_name(kv.first), kv.second); - } - } -+ } - - // data - size_t model_size = 0; -@@ -937,18 +939,18 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - - #ifdef GGML_USE_CUDA - new_clip->backend = ggml_backend_cuda_init(0); -- printf("%s: CLIP using CUDA backend\n", __func__); -+ if (verbosity >= 1) printf("%s: CLIP using CUDA backend\n", __func__); - #endif - - #ifdef GGML_USE_METAL - new_clip->backend = ggml_backend_metal_init(); -- printf("%s: CLIP using Metal backend\n", __func__); -+ if (verbosity >= 1) printf("%s: CLIP using Metal backend\n", __func__); - #endif - - - if (!new_clip->backend) { - new_clip->backend = ggml_backend_cpu_init(); -- printf("%s: CLIP using CPU backend\n", __func__); -+ if (verbosity >= 1) printf("%s: CLIP using CPU backend\n", __func__); - } - - // model size and capabilities -@@ -980,7 +982,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - } - } - -- printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, model_size / (1024.0 * 1024.0), n_tensors); -+ if (verbosity >= 1) printf("%s: params backend buffer size = % 6.2f MB (%i tensors)\n", __func__, model_size / (1024.0 * 1024.0), n_tensors); - - // load tensors - { -@@ -1216,7 +1218,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { - ggml_cgraph * gf = clip_image_build_graph(new_clip, &batch); - ggml_gallocr_reserve(new_clip->compute_alloc, gf); - size_t compute_memory_buffer_size = ggml_gallocr_get_buffer_size(new_clip->compute_alloc, 0); -- printf("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); -+ if (verbosity >= 1) printf("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); - } - - return new_clip; -diff --git a/examples/llava/llava.cpp b/examples/llava/llava.cpp -index 98012816..e8567d8f 100644 ---- a/examples/llava/llava.cpp -+++ b/examples/llava/llava.cpp -@@ -257,7 +257,7 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli - } - } - const int64_t t_img_enc_batch_us = ggml_time_us(); -- printf("%s: %d segments encoded in %8.2f ms\n", __func__, (int)img_res_v.size, (t_img_enc_batch_us - t_img_enc_start_us) / 1000.0); -+ // printf("%s: %d segments encoded in %8.2f ms\n", __func__, (int)img_res_v.size, (t_img_enc_batch_us - t_img_enc_start_us) / 1000.0); - - const int32_t * image_grid = clip_image_grid(ctx_clip); - -@@ -290,12 +290,12 @@ static bool encode_image_with_clip(clip_ctx * ctx_clip, int n_threads, const cli - // clip_image_save_to_bmp(*tmp, "image_feature.bmp"); - } - -- printf("%s: image embedding created: %d tokens\n", __func__, *n_img_pos); -+ // printf("%s: image embedding created: %d tokens\n", __func__, *n_img_pos); - - const int64_t t_img_enc_end_us = ggml_time_us(); - float t_img_enc_ms = (t_img_enc_end_us - t_img_enc_start_us) / 1000.0; - -- printf("\n%s: image encoded in %8.2f ms by CLIP (%8.2f ms per image patch)\n", __func__, t_img_enc_ms, t_img_enc_ms / *n_img_pos); -+ // printf("\n%s: image encoded in %8.2f ms by CLIP (%8.2f ms per image patch)\n", __func__, t_img_enc_ms, t_img_enc_ms / *n_img_pos); - - return true; - } diff --git a/examples/llava/llava.h b/examples/llava/llava.h -index 2d40f3f1..8897b3d8 100644 +index 19212f6e..40a731c5 100644 --- a/examples/llava/llava.h +++ b/examples/llava/llava.h @@ -18,6 +18,7 @@ @@ -99,10 +11,10 @@ index 2d40f3f1..8897b3d8 100644 #ifdef __cplusplus extern "C" { diff --git a/llama.cpp b/llama.cpp -index 30d5eb32..9c940162 100644 +index a25d115c..860b38c5 100644 --- a/llama.cpp +++ b/llama.cpp -@@ -13266,7 +13266,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { +@@ -17462,7 +17462,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { static void llama_log_callback_default(ggml_log_level level, const char * text, void * user_data) { (void) level; From 9bb51c5ee22f7bef7103dfbbbe27637b57b9add4 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 23 Apr 2024 15:17:36 +0800 Subject: [PATCH 149/218] [WASI-NN] propagate LLAMA_NATIVE for setting the AVX/AVX2/FMA features Signed-off-by: hydai --- CMakeLists.txt | 1 + plugins/wasi_nn/CMakeLists.txt | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d972312785d8..3d33124b8633 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ option(WASMEDGE_LINK_LLVM_STATIC "Statically link the LLVM library into the Wasm option(WASMEDGE_LINK_TOOLS_STATIC "Statically link the wasmedge and wasmedgec tools. Will forcefully link the LLVM library statically." OFF) option(WASMEDGE_ENABLE_UB_SANITIZER "Enable undefined behavior sanitizer." OFF) set(WASMEDGE_PLUGIN_WASI_NN_BACKEND "" CACHE STRING "Enable WasmEdge Wasi-NN plugin with backends.") +option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_NATIVE "Enable LLAMA_NATIVE(AVX/AVX2/FMA) in the WASI-NN GGML backend" ON) option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_BLAS "Enable LLAMA_BLAS in the WASI-NN GGML backend" ON) option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_CUBLAS "Enable LLAMA_CUBLAS in the WASI-NN GGML backend" OFF) option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL "Enable LLAMA_METAL in the WASI-NN GGML backend" OFF) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 601f735ea080..c414068ead2e 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -9,6 +9,13 @@ if(BACKEND STREQUAL "ggml") set(LLAMA_METAL_NDEBUG ON) set(LLAMA_ACCELERATE OFF) + if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_NATIVE) + message(STATUS "WASI-NN GGML LLAMA backend: Enable LLAMA_NATIVE(AVX/AVX2/FMA)") + set(LLAMA_NATIVE ON) + else() + set(LLAMA_NATIVE OFF) + endif() + if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_CUBLAS) message(STATUS "WASI-NN GGML LLAMA backend: Enable LLAMA_CUDA") set(LLAMA_CUDA ON) From 326f5b34bd0be4b78f2706494b633b3e4a20493c Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 23 Apr 2024 15:18:02 +0800 Subject: [PATCH 150/218] [WASI-NN] disable LLAMA_BLAS by default Signed-off-by: hydai --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d33124b8633..8b6a5742cf31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ option(WASMEDGE_LINK_TOOLS_STATIC "Statically link the wasmedge and wasmedgec to option(WASMEDGE_ENABLE_UB_SANITIZER "Enable undefined behavior sanitizer." OFF) set(WASMEDGE_PLUGIN_WASI_NN_BACKEND "" CACHE STRING "Enable WasmEdge Wasi-NN plugin with backends.") option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_NATIVE "Enable LLAMA_NATIVE(AVX/AVX2/FMA) in the WASI-NN GGML backend" ON) -option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_BLAS "Enable LLAMA_BLAS in the WASI-NN GGML backend" ON) +option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_BLAS "Enable LLAMA_BLAS in the WASI-NN GGML backend" OFF) option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_CUBLAS "Enable LLAMA_CUBLAS in the WASI-NN GGML backend" OFF) option(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL "Enable LLAMA_METAL in the WASI-NN GGML backend" OFF) # Currently supported WASI-NN backend: "OpenVINO" on Linux x86_64 From d8a6ec3452011f386be7deebaeec7ac4a9db565d Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Tue, 23 Apr 2024 20:04:35 +0800 Subject: [PATCH 151/218] [CMake] Bump simdjson to 3.9.1 and fix compiler flag. (#3357) Signed-off-by: YiYing He --- cmake/Helper.cmake | 5 +++++ plugins/wasi_nn/CMakeLists.txt | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 9660c2e78561..1021c8a52fe7 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -104,6 +104,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") -Wno-reserved-identifier ) endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13) + list(APPEND WASMEDGE_CFLAGS + -Wno-error=template-id-cdtor + -Wno-error=dangling-reference + ) endif() if(WIN32) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index c414068ead2e..58dfe39c8e80 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -89,7 +89,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( simdjson GIT_REPOSITORY https://github.com/simdjson/simdjson.git - GIT_TAG tags/v3.2.1 + GIT_TAG tags/v3.9.1 GIT_SHALLOW TRUE) if(MSVC) From 0ec8f502c42a529929a8a0a517f69e1e068e320b Mon Sep 17 00:00:00 2001 From: YiYing He Date: Thu, 25 Apr 2024 20:57:00 +0800 Subject: [PATCH 152/218] [Executor] Clean unused bits of values when passing in/out invokation and host function. Signed-off-by: YiYing He --- include/executor/executor.h | 3 +++ lib/executor/executor.cpp | 7 +++++-- lib/executor/helper.cpp | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/executor/executor.h b/include/executor/executor.h index 1186f381402e..eaab47b36565 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -307,6 +307,9 @@ class Executor { /// Helper function for converting into bottom abstract heap type. TypeCode toBottomType(Runtime::StackManager &StackMgr, const ValType &Type) const; + + /// Helper function for clean the unused bits of numeric values in ValVariant. + void cleanNumericVal(ValVariant &Val, const ValType &Type) const noexcept; /// @} /// \name Run instructions functions diff --git a/lib/executor/executor.cpp b/lib/executor/executor.cpp index 8f15d5bb3c59..65b7e06aa568 100644 --- a/lib/executor/executor.cpp +++ b/lib/executor/executor.cpp @@ -124,8 +124,8 @@ Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst, auto Val = StackMgr.pop(); const auto &RType = RTypes[RTypes.size() - I - 1]; if (RType.isRefType()) { - // For the types of the return values, they should be transformed into - // abstract heap types due to the opaque of type indices. + // For the reference type cases of the return values, they should be + // transformed into abstract heap types due to the opaque of type indices. auto &RefType = Val.get().getType(); if (RefType.isExternalized()) { // First handle the forced externalized value type case. @@ -150,6 +150,9 @@ Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst, // typing rule of the null references. Returns[RTypes.size() - I - 1] = std::make_pair(Val, RefType); } else { + // For the number type cases of the return values, the unused bits should + // be erased due to the security issue. + cleanNumericVal(Val, RType); Returns[RTypes.size() - I - 1] = std::make_pair(Val, RType); } } diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 3582686bc300..41c361d837a4 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -69,6 +69,11 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, // Run host function. Span Args = StackMgr.getTopSpan(ArgsN); + for (uint32_t I = 0; I < ArgsN; I++) { + // For the number type cases of the arguments, the unused bits should be + // erased due to the security issue. + cleanNumericVal(Args[I], FuncType.getParamTypes()[I]); + } std::vector Rets(RetsN); auto Ret = HostFunc.run(CallFrame, std::move(Args), Rets); @@ -316,5 +321,40 @@ TypeCode Executor::toBottomType(Runtime::StackManager &StackMgr, return Type.getCode(); } } + +void Executor::cleanNumericVal(ValVariant &Val, + const ValType &Type) const noexcept { + if (Type.isNumType()) { + switch (Type.getCode()) { + case TypeCode::I32: { + uint32_t V = Val.get(); + Val.emplace(static_cast(0)); + Val.emplace(V); + break; + } + case TypeCode::F32: { + float V = Val.get(); + Val.emplace(static_cast(0)); + Val.emplace(V); + break; + } + case TypeCode::I64: { + uint64_t V = Val.get(); + Val.emplace(static_cast(0)); + Val.emplace(V); + break; + } + case TypeCode::F64: { + double V = Val.get(); + Val.emplace(static_cast(0)); + Val.emplace(V); + break; + } + default: + break; + } + } +} + } // namespace Executor } // namespace WasmEdge From d1c7efebc6b3722327de186496c0cc85a2c664e1 Mon Sep 17 00:00:00 2001 From: hydai Date: Fri, 26 Apr 2024 11:06:03 +0800 Subject: [PATCH 153/218] [WASI-NN] ggml: bump tp b2734 to support phi-3-mini (#3364) Signed-off-by: hydai --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 58dfe39c8e80..51001ddb1335 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -69,7 +69,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2715 + GIT_TAG b2734 PATCH_COMMAND git checkout . COMMAND git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch GIT_SHALLOW FALSE From dac81e0c6ebb5a49c6555cd6bc4f414d7e30dc02 Mon Sep 17 00:00:00 2001 From: dm4 Date: Fri, 26 Apr 2024 13:47:25 +0800 Subject: [PATCH 154/218] [WASI-NN] ggml: add llama log callback (#3365) Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 -- plugins/wasi_nn/ggml.cpp | 29 ++++++++++++++++++++++++++++- thirdparty/ggml/ggml.patch | 29 ----------------------------- 3 files changed, 28 insertions(+), 32 deletions(-) delete mode 100644 thirdparty/ggml/ggml.patch diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 51001ddb1335..14768036fb81 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -70,8 +70,6 @@ if(BACKEND STREQUAL "ggml") llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git GIT_TAG b2734 - PATCH_COMMAND git checkout . - COMMAND git apply ${CMAKE_SOURCE_DIR}/thirdparty/ggml/ggml.patch GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 401abbf0a832..0ccbfad383d7 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -21,6 +21,31 @@ namespace WasmEdge::Host::WASINN::GGML { #ifdef WASMEDGE_PLUGIN_WASI_NN_BACKEND_GGML namespace { + +void LlamaLogCallback(ggml_log_level LogLevel, const char *LogText, + void *UserData) { + Graph GraphRef = *static_cast(UserData); + if (!GraphRef.EnableLog) { + return; + } + std::string Text(LogText); + // Remove the trailing newlines. + Text = Text.erase(Text.find_last_not_of("\n") + 1); + // Skip for "." + if (Text == ".") { + return; + } + if (LogLevel == GGML_LOG_LEVEL_ERROR) { + spdlog::error("[WASI-NN] llama.cpp: {}"sv, Text); + } else if (LogLevel == GGML_LOG_LEVEL_WARN) { + spdlog::warn("[WASI-NN] llama.cpp: {}"sv, Text); + } else if (LogLevel == GGML_LOG_LEVEL_INFO) { + spdlog::info("[WASI-NN] llama.cpp: {}"sv, Text); + } else if (LogLevel == GGML_LOG_LEVEL_DEBUG) { + spdlog::debug("[WASI-NN] llama.cpp: {}"sv, Text); + } +} + Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, bool *IsModelUpdated = nullptr) noexcept { simdjson::dom::parser Parser; @@ -72,7 +97,6 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, "[WASI-NN] GGML backend: Unable to retrieve the enable-log option."sv); return ErrNo::InvalidArgument; } - llama_log_set(nullptr, &GraphRef.EnableLog); } if (Doc.at_key("enable-debug-log").error() == simdjson::SUCCESS) { auto Err = Doc["enable-debug-log"].get().get(GraphRef.EnableDebugLog); @@ -652,6 +676,9 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, GraphRef.FrequencyPenalty = SamplingDefault.penalty_freq; GraphRef.Grammar = SamplingDefault.grammar; + // Set llama log callback. + llama_log_set(LlamaLogCallback, &GraphRef); + // If the graph builder length > 1, the data of builder[1] is the metadata. if (Builders.size() > 1) { const std::string Metadata(reinterpret_cast(Builders[1].data()), diff --git a/thirdparty/ggml/ggml.patch b/thirdparty/ggml/ggml.patch deleted file mode 100644 index fe547217f925..000000000000 --- a/thirdparty/ggml/ggml.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/examples/llava/llava.h b/examples/llava/llava.h -index 19212f6e..40a731c5 100644 ---- a/examples/llava/llava.h -+++ b/examples/llava/llava.h -@@ -18,6 +18,7 @@ - #endif - - struct clip_ctx; -+struct clip_image_u8; - - #ifdef __cplusplus - extern "C" { -diff --git a/llama.cpp b/llama.cpp -index a25d115c..860b38c5 100644 ---- a/llama.cpp -+++ b/llama.cpp -@@ -17462,7 +17462,9 @@ static void llama_log_internal(ggml_log_level level, const char * format, ...) { - - static void llama_log_callback_default(ggml_log_level level, const char * text, void * user_data) { - (void) level; -- (void) user_data; -- fputs(text, stderr); -- fflush(stderr); -+ bool * enable_log = static_cast(user_data); -+ if (enable_log && *enable_log) { -+ fputs(text, stderr); -+ fflush(stderr); -+ } - } From ee7cb040fe9733d526e134ce92915420f03d3c61 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 26 Apr 2024 14:13:31 +0800 Subject: [PATCH 155/218] [CMake] Fix GNU version for `template-id-cdtor` Signed-off-by: Yi Huang --- cmake/Helper.cmake | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 1021c8a52fe7..0314385c7d43 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -41,11 +41,6 @@ else() -Werror -Wno-error=pedantic ) - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13) - list(APPEND WASMEDGE_CFLAGS - -Wno-error=dangling-reference - ) - endif() endif() if(WASMEDGE_ENABLE_UB_SANITIZER) @@ -104,11 +99,17 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") -Wno-reserved-identifier ) endif() -elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13) - list(APPEND WASMEDGE_CFLAGS - -Wno-error=template-id-cdtor - -Wno-error=dangling-reference - ) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13) + list(APPEND WASMEDGE_CFLAGS + -Wno-error=dangling-reference + ) + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14) + list(APPEND WASMEDGE_CFLAGS + -Wno-error=template-id-cdtor + ) + endif() endif() if(WIN32) From ba72db771d181146666151765ff3b3cc3192f6b5 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 14:09:41 +0800 Subject: [PATCH 156/218] [CI] Update IWYU to 0.22 * Use 0.21 on macos * Use ninja-build for IWYU build Signed-off-by: Shen-Ta Hsieh --- .github/workflows/IWYU_scan.yml | 50 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/.github/workflows/IWYU_scan.yml b/.github/workflows/IWYU_scan.yml index c068177f4e4f..26824b46c1fe 100644 --- a/.github/workflows/IWYU_scan.yml +++ b/.github/workflows/IWYU_scan.yml @@ -68,13 +68,10 @@ jobs: run: | dnf update -y dnf install -y cmake ninja-build llvm llvm-devel lld-devel clang git file rpm-build dpkg-dev clang-devel spdlog-devel - curl -L -O https://github.com/include-what-you-use/include-what-you-use/archive/refs/tags/0.20.zip - unzip 0.20.zip - mkdir build && cd build - cmake -G "Unix Makefiles" ../include-what-you-use-0.20 - make -j - make install - cd .. + curl -L -O https://github.com/include-what-you-use/include-what-you-use/archive/refs/tags/0.22.zip + unzip 0.22.zip + cmake -Bbuild-iwyu -GNinja -DCMAKE_BUILD_TYPE=Release include-what-you-use-0.22 + cmake --build build-iwyu --target install - uses: actions/checkout@v4 with: @@ -115,21 +112,38 @@ jobs: # Unlink python@3.11 to fix brew link 2to3 conflict. brew unlink python@3.11 brew install llvm ninja cmake - export LLVM_DIR="/usr/local/opt/llvm/lib/cmake" - export Clang_DIR="/usr/local/opt/llvm/lib/cmake/clang" + export LLVM_DIR="$(brew --prefix)/opt/llvm/lib/cmake" + export Clang_DIR="$(brew --prefix)/opt/llvm/lib/cmake/clang" + export IWYU_PREFIX="$(brew --prefix)/opt/iwyu" export CC=clang export CXX=clang++ cd ../../ - curl -L -O https://github.com/include-what-you-use/include-what-you-use/archive/refs/tags/0.20.zip - unzip 0.20.zip - mkdir build && cd build - cmake -G "Unix Makefiles" ../include-what-you-use-0.20 - make -j install - cd ../WasmEdge/WasmEdge - - cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=ON -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=include-what-you-use -DWASMEDGE_BUILD_PACKAGE="TGZ" . - cmake --build build > iwyu_macos.log + curl -L -O https://github.com/include-what-you-use/include-what-you-use/archive/refs/tags/0.21.zip + unzip 0.21.zip + patch -p1 -d include-what-you-use-0.21 <hasDefinition()) + + return true; + + + // Make sure all the types we report in the recursive TraverseDecl + // calls, below, end up in the cache for class_decl. + EOF + cmake -Bbuild-iwyu -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$IWYU_PREFIX" include-what-you-use-0.21 + cmake --build build-iwyu --target install + cd WasmEdge/WasmEdge + + cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=ON -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="xcrun;$IWYU_PREFIX/bin/include-what-you-use" -DWASMEDGE_BUILD_PACKAGE="TGZ" . + cmake --build build > iwyu_macOS.log - uses: actions/upload-artifact@v3 with: From 7b2d268816595210fb8cb40ee2aabb65ef78239f Mon Sep 17 00:00:00 2001 From: Harry Chiang Date: Tue, 10 Oct 2023 22:42:35 +0800 Subject: [PATCH 157/218] [Misc] Add exception handling proposal on interpreter mode (#2459) Signed-off-by: Harry Chiang --- include/api/wasmedge/wasmedge.h | 111 ++++++++++++++++++- include/ast/description.h | 3 + include/ast/instruction.h | 137 ++++++++++++++++++++++-- include/ast/module.h | 3 + include/ast/section.h | 16 ++- include/ast/type.h | 29 +++++ include/common/configure.h | 7 ++ include/common/enum.inc | 75 ++++++++----- include/driver/tool.h | 4 + include/executor/executor.h | 28 ++++- include/loader/loader.h | 13 +++ include/runtime/instance/module.h | 35 +++++- include/runtime/instance/tag.h | 42 ++++++++ include/runtime/stackmgr.h | 153 +++++++++++++++++++++++++-- include/validator/formchecker.h | 3 + include/validator/validator.h | 1 + lib/api/wasmedge.cpp | 95 +++++++++++++++++ lib/driver/runtimeTool.cpp | 4 + lib/executor/CMakeLists.txt | 1 + lib/executor/engine/controlInstr.cpp | 62 +++++++++-- lib/executor/engine/engine.cpp | 17 ++- lib/executor/helper.cpp | 49 ++++++++- lib/executor/instantiate/export.cpp | 3 + lib/executor/instantiate/import.cpp | 24 +++++ lib/executor/instantiate/module.cpp | 5 + lib/executor/instantiate/tag.cpp | 23 ++++ lib/loader/ast/description.cpp | 16 +++ lib/loader/ast/instruction.cpp | 128 ++++++++++++++++++---- lib/loader/ast/module.cpp | 18 +++- lib/loader/ast/section.cpp | 7 ++ lib/loader/ast/type.cpp | 23 ++++ lib/loader/loader.cpp | 22 ++++ lib/validator/formchecker.cpp | 148 +++++++++++++++++++++++--- lib/validator/validator.cpp | 54 ++++++++++ test/loader/descriptionTest.cpp | 2 +- test/spec/CMakeLists.txt | 2 +- test/spec/spectest.cpp | 30 ++++++ test/spec/spectest.h | 1 + 38 files changed, 1297 insertions(+), 97 deletions(-) create mode 100644 include/runtime/instance/tag.h create mode 100644 lib/executor/instantiate/tag.cpp diff --git a/include/api/wasmedge/wasmedge.h b/include/api/wasmedge/wasmedge.h index caa01edbc761..a87e3992211c 100644 --- a/include/api/wasmedge/wasmedge.h +++ b/include/api/wasmedge/wasmedge.h @@ -114,6 +114,9 @@ typedef struct WasmEdge_MemoryTypeContext WasmEdge_MemoryTypeContext; /// Opaque struct of WasmEdge table type. typedef struct WasmEdge_TableTypeContext WasmEdge_TableTypeContext; +/// Opaque struct of WasmEdge tag type. +typedef struct WasmEdge_TagTypeContext WasmEdge_TagTypeContext; + /// Opaque struct of WasmEdge global type. typedef struct WasmEdge_GlobalTypeContext WasmEdge_GlobalTypeContext; @@ -151,6 +154,9 @@ typedef struct WasmEdge_TableInstanceContext WasmEdge_TableInstanceContext; /// Opaque struct of WasmEdge memory instance. typedef struct WasmEdge_MemoryInstanceContext WasmEdge_MemoryInstanceContext; +/// Opaque struct of WasmEdge tag instance. +typedef struct WasmEdge_TagInstanceContext WasmEdge_TagInstanceContext; + /// Opaque struct of WasmEdge global instance. typedef struct WasmEdge_GlobalInstanceContext WasmEdge_GlobalInstanceContext; @@ -1340,6 +1346,18 @@ WasmEdge_MemoryTypeDelete(WasmEdge_MemoryTypeContext *Cxt); // <<<<<<<< WasmEdge memory type functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +// >>>>>>>> WasmEdge tag type functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +/// Get the function type from a tag type. +/// +/// \param Cxt the WasmEdge_TagTypeContext. +/// +/// \returns pointer to function type context of the tag type, NULL if failed. +WASMEDGE_CAPI_EXPORT extern const WasmEdge_FunctionTypeContext * +WasmEdge_TagTypeGetFunctionType(const WasmEdge_TagTypeContext *Cxt); + +// <<<<<<<< WasmEdge tag type functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + // >>>>>>>> WasmEdge global type functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> /// Creation of the WasmEdge_GlobalTypeContext. @@ -1465,6 +1483,22 @@ WASMEDGE_CAPI_EXPORT extern const WasmEdge_MemoryTypeContext * WasmEdge_ImportTypeGetMemoryType(const WasmEdge_ASTModuleContext *ASTCxt, const WasmEdge_ImportTypeContext *Cxt); +/// Get the external value (which is tag type) from an import type. +/// +/// The import type context should be the one queried from the AST module +/// context, or this function will cause unexpected error. +/// The tag type context links to the tag type in the import type context +/// and the AST module context. +/// +/// \param ASTCxt the WasmEdge_ASTModuleContext. +/// \param Cxt the WasmEdge_ImportTypeContext which queried from the `ASTCxt`. +/// +/// \returns the tag type. NULL if failed or the external type of the import +/// type is not `WasmEdge_ExternalType_TagType`. +WASMEDGE_CAPI_EXPORT extern const WasmEdge_TagTypeContext * +WasmEdge_ImportTypeGetTagType(const WasmEdge_ASTModuleContext *ASTCxt, + const WasmEdge_ImportTypeContext *Cxt); + /// Get the external value (which is global type) from an import type. /// /// The import type context should be the one queried from the AST module @@ -1556,6 +1590,22 @@ WASMEDGE_CAPI_EXPORT extern const WasmEdge_MemoryTypeContext * WasmEdge_ExportTypeGetMemoryType(const WasmEdge_ASTModuleContext *ASTCxt, const WasmEdge_ExportTypeContext *Cxt); +/// Get the external value (which is tag type) from an export type. +/// +/// The export type context should be the one queried from the AST module +/// context, or this function will cause unexpected error. +/// The tag type context links to the tag type in the export type context +/// and the AST module context. +/// +/// \param ASTCxt the WasmEdge_ASTModuleContext. +/// \param Cxt the WasmEdge_ExportTypeContext which queried from the `ASTCxt`. +/// +/// \returns the tag type. NULL if failed or the external type of the export +/// type is not `WasmEdge_ExternalType_Tag`. +WASMEDGE_CAPI_EXPORT extern const WasmEdge_TagTypeContext * +WasmEdge_ExportTypeGetTagType(const WasmEdge_ASTModuleContext *ASTCxt, + const WasmEdge_ExportTypeContext *Cxt); + /// Get the external value (which is global type) from an export type. /// /// The export type context should be the one queried from the AST module @@ -2012,7 +2062,7 @@ WasmEdge_StoreDelete(WasmEdge_StoreContext *Cxt); /// /// Create a module instance context with exported module name for host /// instances. Developer can use this API to create a module instance for -/// collecting host functions, tables, memories, and globals. +/// collecting host functions, tables, memories, tags, and globals. /// The caller owns the object and should call `WasmEdge_ModuleInstanceDelete` /// to destroy it. /// @@ -2208,6 +2258,21 @@ WASMEDGE_CAPI_EXPORT extern WasmEdge_MemoryInstanceContext * WasmEdge_ModuleInstanceFindMemory(const WasmEdge_ModuleInstanceContext *Cxt, const WasmEdge_String Name); +/// Get the exported tag instance context of a module instance. +/// +/// The result tag instance context links to the tag instance in the +/// module instance context and owned by the module instance context. +/// +/// This function is thread-safe. +/// +/// \param Cxt the WasmEdge_ModuleInstanceContext. +/// \param Name the tag name WasmEdge_String. +/// +/// \returns pointer to the tag instance context. NULL if not found. +WASMEDGE_CAPI_EXPORT extern WasmEdge_TagInstanceContext * +WasmEdge_ModuleInstanceFindTag(const WasmEdge_ModuleInstanceContext *Cxt, + const WasmEdge_String Name); + /// Get the exported global instance context of a module instance. /// /// The result global instance context links to the global instance in the @@ -2311,6 +2376,35 @@ WASMEDGE_CAPI_EXPORT extern uint32_t WasmEdge_ModuleInstanceListMemory(const WasmEdge_ModuleInstanceContext *Cxt, WasmEdge_String *Names, const uint32_t Len); +/// Get the length of exported tag list of a module instance. +/// +/// This function is thread-safe. +/// +/// \param Cxt the WasmEdge_ModuleInstanceContext. +/// +/// \returns length of the exported tag list. +WASMEDGE_CAPI_EXPORT extern uint32_t +WasmEdge_ModuleInstanceListTagLength(const WasmEdge_ModuleInstanceContext *Cxt); + +/// List the exported tag names of a module instance. +/// +/// The returned tag names filled into the `Names` array are linked to the +/// exported names of tags of the module instance context, and the caller +/// should __NOT__ call the `WasmEdge_StringDelete`. +/// If the `Names` buffer length is smaller than the result of the exported +/// tag list size, the overflowed return values will be discarded. +/// +/// This function is thread-safe. +/// +/// \param Cxt the WasmEdge_ModuleInstanceContext. +/// \param [out] Names the output WasmEdge_String buffer of the tag names. +/// \param Len the buffer length. +/// +/// \returns actual exported tag list size. +WASMEDGE_CAPI_EXPORT extern uint32_t +WasmEdge_ModuleInstanceListTag(const WasmEdge_ModuleInstanceContext *Cxt, + WasmEdge_String *Names, const uint32_t Len); + /// Get the length of exported global list of a module instance. /// /// This function is thread-safe. @@ -2814,6 +2908,21 @@ WasmEdge_MemoryInstanceDelete(WasmEdge_MemoryInstanceContext *Cxt); // <<<<<<<< WasmEdge memory instance functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +// >>>>>>>> WasmEdge tag instance functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +/// Get the tag type context from a tag instance. +/// +/// The tag type context links to the tag type in the tag instance +/// context and owned by the context. +/// +/// \param Cxt the WasmEdge_TagInstanceContext. +/// +/// \returns pointer to context, NULL if failed. +WASMEDGE_CAPI_EXPORT extern const WasmEdge_TagTypeContext * +WasmEdge_TagInstanceGetTagType(const WasmEdge_TagInstanceContext *Cxt); + +// <<<<<<<< WasmEdge tag instance functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + // >>>>>>>> WasmEdge global instance functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> /// Creation of the WasmEdge_GlobalInstanceContext. diff --git a/include/ast/description.h b/include/ast/description.h index 08b7679d9cfd..444a4625532b 100644 --- a/include/ast/description.h +++ b/include/ast/description.h @@ -59,6 +59,8 @@ class ImportDesc : public Desc { MemoryType &getExternalMemoryType() noexcept { return MemType; } const GlobalType &getExternalGlobalType() const noexcept { return GlobType; } GlobalType &getExternalGlobalType() noexcept { return GlobType; } + const TagType &getExternalTagType() const noexcept { return TgType; } + TagType &getExternalTagType() noexcept { return TgType; } private: /// \name Data of ImportDesc: Module name, External name, and content node. @@ -68,6 +70,7 @@ class ImportDesc : public Desc { TableType TabType; MemoryType MemType; GlobalType GlobType; + TagType TgType; /// @} }; diff --git a/include/ast/instruction.h b/include/ast/instruction.h index a9bda963ffb8..eae13faaa8b1 100644 --- a/include/ast/instruction.h +++ b/include/ast/instruction.h @@ -28,8 +28,10 @@ class Instruction { public: struct JumpDescriptor { uint32_t TargetIndex; - uint32_t StackEraseBegin; - uint32_t StackEraseEnd; + uint32_t ValueStackEraseBegin; + uint32_t ValueStackEraseEnd; + uint32_t HandlerStackOffset; + uint32_t CaughtStackOffset; int32_t PCOffset; }; struct BrCastDescriptor { @@ -48,9 +50,16 @@ class Instruction { Data.Num.Low = static_cast(0); Data.Num.High = static_cast(0); #endif + // Initializing JumpCatchAll to check whether it is set during loading phase + Data.TryBlock.JumpCatchAll = 0; + Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; Flags.IsAllocBrCast = false; + Flags.IsAllocJumpCatchList = false; + Flags.IsTryLast = false; + Flags.IsCatchLast = false; + Flags.IsDelegate = false; } /// Copy constructor. @@ -67,6 +76,11 @@ class Instruction { Data.SelectT.ValTypeList); } else if (Flags.IsAllocBrCast) { Data.BrCast = new BrCastDescriptor(*Instr.Data.BrCast); + } else if (Flags.IsAllocJumpCatchList) { + Data.TryBlock.JumpCatchList = + new uint32_t[Data.TryBlock.JumpCatchListSize]; + std::copy_n(Instr.Data.TryBlock.JumpCatchList, + Data.TryBlock.JumpCatchListSize, Data.TryBlock.JumpCatchList); } } @@ -77,6 +91,7 @@ class Instruction { Instr.Flags.IsAllocLabelList = false; Instr.Flags.IsAllocValTypeList = false; Instr.Flags.IsAllocBrCast = false; + Instr.Flags.IsAllocJumpCatchList = false; } /// Destructor. @@ -98,12 +113,21 @@ class Instruction { uint32_t getOffset() const noexcept { return Offset; } /// Getter and setter of block type. - const BlockType &getBlockType() const noexcept { return Data.Blocks.ResType; } + const BlockType &getBlockType() const noexcept { + return Code == OpCode::Try ? Data.TryBlock.ResType : Data.Blocks.ResType; + } void setBlockType(const ValType &VType) noexcept { - Data.Blocks.ResType.setData(VType); + Code == OpCode::Try ? Data.TryBlock.ResType.setData(VType) + : Data.Blocks.ResType.setData(VType); + } + void setBlockType(uint32_t Idx) noexcept { + Code == OpCode::Try ? Data.TryBlock.ResType.setData(Idx) + : Data.Blocks.ResType.setData(Idx); + } + void setEmptyBlockType() noexcept { + Code == OpCode::Try ? Data.TryBlock.ResType.setEmpty() + : Data.Blocks.ResType.setEmpty(); } - void setBlockType(uint32_t Idx) noexcept { Data.Blocks.ResType.setData(Idx); } - void setEmptyBlockType() noexcept { Data.Blocks.ResType.setEmpty(); } /// Getter and setter of jump count to End instruction. uint32_t getJumpEnd() const noexcept { return Data.Blocks.JumpEnd; } @@ -187,6 +211,74 @@ class Instruction { uint8_t getMemoryLane() const noexcept { return Data.Memories.MemLane; } uint8_t &getMemoryLane() noexcept { return Data.Memories.MemLane; } + /// Getter and setter of jump catch list. + void setJumpCatchList(const std::vector &CatchList) { + reset(); + if (!CatchList.empty()) { + Data.TryBlock.JumpCatchListSize = static_cast(CatchList.size()); + Data.TryBlock.JumpCatchList = new uint32_t[CatchList.size()]; + Flags.IsAllocJumpCatchList = true; + std::copy_n(CatchList.begin(), CatchList.size(), + Data.TryBlock.JumpCatchList); + } + } + Span getJumpCatchList() const noexcept { + return Span( + Data.TryBlock.JumpCatchList, + Flags.IsAllocJumpCatchList ? Data.TryBlock.JumpCatchListSize : 0); + } + Span getJumpCatchList() noexcept { + return Span( + Data.TryBlock.JumpCatchList, + Flags.IsAllocJumpCatchList ? Data.TryBlock.JumpCatchListSize : 0); + } + + /// Getter and setter of jump count to catch_all instruction. + uint32_t getJumpCatchAll() const noexcept { + return Data.TryBlock.JumpCatchAll; + } + void setJumpCatchAll(const uint32_t Cnt) noexcept { + Data.TryBlock.JumpCatchAll = Cnt; + } + + /// Getter and setter of jump count to the end of try block. + uint32_t getTryBlockJumpEnd() const noexcept { return Data.TryBlock.JumpEnd; } + void setTryBlockJumpEnd(const uint32_t Cnt) noexcept { + Data.TryBlock.JumpEnd = Cnt; + } + + /// Getter and setter of number of block type parameter. + uint32_t getTryBlockParamNum() const noexcept { + return Data.TryBlock.BlockParamNum; + } + void setTryBlockParamNum(const uint32_t Num) noexcept { + Data.TryBlock.BlockParamNum = Num; + } + + /// Getter and setter of jump count to delegate instruction. + uint32_t getDelegateIdx() const noexcept { return Data.TryBlock.DelegateIdx; } + void setDelegateIdx(const uint32_t Cnt) noexcept { + Data.TryBlock.DelegateIdx = Cnt; + } + + /// Getter and setter of VSize + uint32_t getTryBlockVSize() const noexcept { return Data.TryBlock.VSize; } + void setTryBlockVSize(const uint32_t Num) noexcept { + Data.TryBlock.VSize = Num; + } + + /// Getter and setter of HOffset + uint32_t getTryBlockHOffset() const noexcept { return Data.TryBlock.HOffset; } + void setTryBlockHOffset(const uint32_t Num) noexcept { + Data.TryBlock.HOffset = Num; + } + + /// Getter and setter of COffset + uint32_t getTryBlockCOffset() const noexcept { return Data.TryBlock.COffset; } + void setTryBlockCOffset(const uint32_t Num) noexcept { + Data.TryBlock.COffset = Num; + } + /// Getter and setter of the constant value. ValVariant getNum() const noexcept { #if defined(__x86_64__) || defined(__aarch64__) || \ @@ -216,6 +308,18 @@ class Instruction { const BrCastDescriptor &getBrCast() const noexcept { return *Data.BrCast; } BrCastDescriptor &getBrCast() noexcept { return *Data.BrCast; } + /// Getter and setter of IsTryLast for End instruction. + bool isTryLast() const noexcept { return Flags.IsTryLast; } + void setTryLast(bool Last = true) noexcept { Flags.IsTryLast = Last; } + + /// Getter and setter of IsCatchLast for End instruction. + bool isCatchLast() const noexcept { return Flags.IsCatchLast; } + void setCatchLast(bool Last = true) noexcept { Flags.IsCatchLast = Last; } + + /// Getter and setter of IsDelegate for Try instruction. + bool isDelegate() const noexcept { return Flags.IsDelegate; } + void setDelegate(bool Last = true) noexcept { Flags.IsDelegate = Last; } + private: /// Release allocated resources. void reset() noexcept { @@ -227,10 +331,14 @@ class Instruction { delete[] Data.SelectT.ValTypeList; } else if (Flags.IsAllocBrCast) { delete Data.BrCast; + } else if (Flags.IsAllocJumpCatchList) { + Data.TryBlock.JumpCatchListSize = 0; + delete[] Data.TryBlock.JumpCatchList; } Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; Flags.IsAllocBrCast = false; + Flags.IsAllocJumpCatchList = false; } /// Swap function. @@ -291,6 +399,19 @@ class Instruction { bool IsLast; // Type 10: TypeCastBranch. BrCastDescriptor *BrCast; + // Type 11: Try Block + struct { + uint32_t JumpCatchListSize; + uint32_t *JumpCatchList; + uint32_t JumpCatchAll; + uint32_t JumpEnd; + uint32_t BlockParamNum; + uint32_t DelegateIdx; + uint32_t VSize; + uint32_t HOffset; + uint32_t COffset; + BlockType ResType; + } TryBlock; } Data; uint32_t Offset = 0; OpCode Code = OpCode::End; @@ -298,6 +419,10 @@ class Instruction { bool IsAllocLabelList : 1; bool IsAllocValTypeList : 1; bool IsAllocBrCast : 1; + bool IsAllocJumpCatchList : 1; + bool IsTryLast : 1; + bool IsCatchLast : 1; + bool IsDelegate : 1; } Flags; /// @} }; diff --git a/include/ast/module.h b/include/ast/module.h index 887e5f21fcac..f1d07621b23d 100644 --- a/include/ast/module.h +++ b/include/ast/module.h @@ -63,6 +63,8 @@ class Module { DataSection &getDataSection() { return DataSec; } const DataCountSection &getDataCountSection() const { return DataCountSec; } DataCountSection &getDataCountSection() { return DataCountSec; } + const TagSection &getTagSection() const { return TagSec; } + TagSection &getTagSection() { return TagSec; } const AOTSection &getAOTSection() const { return AOTSec; } AOTSection &getAOTSection() { return AOTSec; } @@ -98,6 +100,7 @@ class Module { CodeSection CodeSec; DataSection DataSec; DataCountSection DataCountSec; + TagSection TagSec; /// @} /// \name Data of AOT. diff --git a/include/ast/section.h b/include/ast/section.h index 5605999c3df9..5590231aff04 100644 --- a/include/ast/section.h +++ b/include/ast/section.h @@ -223,7 +223,7 @@ class DataSection : public Section { /// AST DataCountSection node. class DataCountSection : public Section { public: - /// Getter and of content. + /// Getter and setter of content. std::optional getContent() const noexcept { return Content; } void setContent(uint32_t Val) noexcept { Content = Val; } @@ -234,6 +234,20 @@ class DataCountSection : public Section { /// @} }; +/// AST TagSection node. +class TagSection : public Section { +public: + /// Getter of content vector. + Span getContent() const noexcept { return Content; } + std::vector &getContent() noexcept { return Content; } + +private: + /// \name Data of TagSection. + /// @{ + std::vector Content; + /// @} +}; + class AOTSection { public: /// Getter and setter of version. diff --git a/include/ast/type.h b/include/ast/type.h index 252ef02f9e8e..aaf76a335178 100644 --- a/include/ast/type.h +++ b/include/ast/type.h @@ -731,5 +731,34 @@ class GlobalType { /// @} }; +class TagType { +public: + TagType() = default; + TagType(const TagType &T, const FunctionType *F) noexcept + : Attribute(T.getAttribute()), TypeIdx(T.getTypeIdx()), Type(F) {} + + /// Getter and setter of Attribute. + uint8_t getAttribute() const noexcept { return Attribute; } + void setAttribute(uint8_t Attr) noexcept { Attribute = Attr; } + + /// Getter and setter of TypeIdx. + uint32_t getTypeIdx() const noexcept { return TypeIdx; } + void setTypeIdx(uint32_t TyIdx) noexcept { TypeIdx = TyIdx; } + + // Getter and setter of FunctionType. + const FunctionType &getFuncType() const noexcept { return *Type; } + void setFuncType(FunctionType *FuncType) noexcept { Type = FuncType; } + + // Getter of the size of value that is associated with the tag. + uint32_t getAssocValSize() const noexcept { + return static_cast(Type->getParamTypes().size()); + } + +private: + uint8_t Attribute; + uint32_t TypeIdx; + const FunctionType *Type; +}; + } // namespace AST } // namespace WasmEdge diff --git a/include/common/configure.h b/include/common/configure.h index a0d9e88056c9..31f1d25b7f2d 100644 --- a/include/common/configure.h +++ b/include/common/configure.h @@ -353,9 +353,16 @@ class Configure { } } else if (Code == OpCode::Ref__eq || (Code >= OpCode::Struct__new && Code <= OpCode::I31__get_u)) { + // These instructions are for GC proposal. if (!hasProposal(Proposal::GC)) { return Proposal::GC; } + } else if ((Code >= OpCode::Try && Code <= OpCode::Rethrow) || + Code == OpCode::Delegate || Code == OpCode::Catch_all) { + // These instructions are for ExceptionHandling proposal. + if (!hasProposal(Proposal::ExceptionHandling)) { + return Proposal::ExceptionHandling; + } } return {}; } diff --git a/include/common/enum.inc b/include/common/enum.inc index 7fe9bc816db6..c1be62bb5c3c 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -59,6 +59,7 @@ A(Sec_Element, "element section") A(Sec_Code, "code section") A(Sec_Data, "data section") A(Sec_DataCount, "data count section") +A(Sec_Tag, "tag section") A(Desc_Import, "import description") A(Desc_Export, "export description") A(Seg_Table, "table segment") @@ -100,7 +101,11 @@ O(Block, "block", 0x02) O(Loop, "loop", 0x03) O(If, "if", 0x04) O(Else, "else", 0x05) -// 0x06 ~ 0x0A: Reserved +O(Try, "try", 0x06) +O(Catch, "catch", 0x07) +O(Throw, "throw", 0x08) +O(Rethrow, "rethrow", 0x09) +// 0x0A: Reserved O(End, "end", 0x0B) O(Br, "br", 0x0C) O(Br_if, "br_if", 0x0D) @@ -112,7 +117,10 @@ O(Return_call, "return_call", 0x12) O(Return_call_indirect, "return_call_indirect", 0x13) O(Call_ref, "call_ref", 0x14) O(Return_call_ref, "return_call_ref", 0x15) -// 0x16 ~ 0x19: Reserved +// 0x16: Reserved +// 0x17: Reserved +O(Delegate, "delegate", 0x18) +O(Catch_all, "catch_all", 0x19) // Parametric Instructions O(Drop, "drop", 0x1A) @@ -865,58 +873,64 @@ E(InvalidTableIdx, 0x0207, "unknown table") E(InvalidMemoryIdx, 0x0208, "unknown memory") // Global index not defined E(InvalidGlobalIdx, 0x0209, "unknown global") +// Tag index not defined +E(InvalidTagIdx, 0x020A, "unknown tag") // Element segment index not defined -E(InvalidElemIdx, 0x020A, "unknown elem segment") +E(InvalidElemIdx, 0x020B, "unknown elem segment") // Data segment index not defined -E(InvalidDataIdx, 0x020B, "unknown data segment") +E(InvalidDataIdx, 0x020C, "unknown data segment") // Undeclared reference -E(InvalidRefIdx, 0x020C, "undeclared function reference") +E(InvalidRefIdx, 0x020D, "undeclared function reference") // Should be constant expression -E(ConstExprRequired, 0x020D, "constant expression required") +E(ConstExprRequired, 0x020E, "constant expression required") // Export name conflicted -E(DupExportName, 0x020E, "duplicate export name") +E(DupExportName, 0x020F, "duplicate export name") // Tried to store to const global value -E(ImmutableGlobal, 0x020F, "global is immutable") +E(ImmutableGlobal, 0x0210, "global is immutable") // Tried to store to const field of structure -E(ImmutableField, 0x0210, "field is immutable") +E(ImmutableField, 0x0211, "field is immutable") // Tried to store to const array -E(ImmutableArray, 0x0211, "array is immutable") +E(ImmutableArray, 0x0212, "array is immutable") // Invalid result arity in select t* instruction -E(InvalidResultArity, 0x0212, "invalid result arity") +E(InvalidResultArity, 0x0213, "invalid result arity") // #Tables > 1 (without Ref-types proposal) -E(MultiTables, 0x0213, "multiple tables") +E(MultiTables, 0x0214, "multiple tables") // #Memories > 1 -E(MultiMemories, 0x0214, "multiple memories") +E(MultiMemories, 0x0215, "multiple memories") // Invalid Limit grammar -E(InvalidLimit, 0x0215, "size minimum must not be greater than maximum") +E(InvalidLimit, 0x0216, "size minimum must not be greater than maximum") // Memory pages > 65536 -E(InvalidMemPages, 0x0216, "memory size must be at most 65536 pages (4GiB)") +E(InvalidMemPages, 0x0217, "memory size must be at most 65536 pages (4GiB)") // Invalid start function signature -E(InvalidStartFunc, 0x0217, "start function") +E(InvalidStartFunc, 0x0218, "start function") // Invalid lane index -E(InvalidLaneIdx, 0x0218, "invalid lane index") +E(InvalidLaneIdx, 0x0219, "invalid lane index") // Invalid uninitialized local -E(InvalidUninitLocal, 0x0219, "uninitialized local") +E(InvalidUninitLocal, 0x021A, "uninitialized local") // Defaultable field type required -E(InvalidNotDefaultableField, 0x021A, "field type is not defaultable") +E(InvalidNotDefaultableField, 0x021B, "field type is not defaultable") // Defaultable array type required -E(InvalidNotDefaultableArray, 0x021B, "array type is not defaultable") +E(InvalidNotDefaultableArray, 0x021C, "array type is not defaultable") // Unpacked field type required, but got packed one -E(InvalidPackedField, 0x021C, "field is packed") +E(InvalidPackedField, 0x021D, "field is packed") // Unpacked array type required, but got packed one -E(InvalidPackedArray, 0x021D, "array is packed") +E(InvalidPackedArray, 0x021E, "array is packed") // Packed field type required, but got unpacked one -E(InvalidUnpackedField, 0x021E, "field is unpacked") +E(InvalidUnpackedField, 0x021F, "field is unpacked") // Packed array type required, but got unpacked one -E(InvalidUnpackedArray, 0x021F, "array is unpacked") +E(InvalidUnpackedArray, 0x0220, "array is unpacked") // Invalid Br ref type -E(InvalidBrRefType, 0x0220, "invalid br ref type") +E(InvalidBrRefType, 0x0221, "invalid br ref type") // 2 array types not matched -E(ArrayTypesMismatch, 0x0221, "array types do not match") +E(ArrayTypesMismatch, 0x0222, "array types do not match") // Should be numeric type in array type -E(ArrayTypesNumtypeRequired, 0x0222, "array type is not numeric or vector") +E(ArrayTypesNumtypeRequired, 0x0223, "array type is not numeric or vector") // Sub type matching or validation failed -E(InvalidSubType, 0x0223, "sub type") +E(InvalidSubType, 0x0224, "sub type") +// Invalid Tag type +E(InvalidTag, 0x0225, "non-empty tag result type") +// Invalid rethrow label +E(InvalidRethrowLabel, 0x0226, "invalid rethrow label") // @} // Instantiation phase @@ -983,6 +997,8 @@ E(AccessNullArray, 0x0415, "null array reference") E(AccessNullI31, 0x0416, "null i31 reference") // Fail to cast reference E(CastFailed, 0x0417, "cast failure") +// Uncaught Exception +E(UncaughtException, 0x0418, "uncaught exception") // @} // Component model phase @@ -1072,6 +1088,8 @@ I(Element, "element") I(Data, "data") I(Lane, "lane") I(Field, "field") +I(TagType, "tag type") +I(Tag, "tag") #undef I #endif // UseIndexCategory @@ -1128,6 +1146,7 @@ E(Function, 0x00U, "function") E(Table, 0x01U, "table") E(Memory, 0x02U, "memory") E(Global, 0x03U, "global") +E(Tag, 0x04U, "tag") #undef E #endif // UseExternalType diff --git a/include/driver/tool.h b/include/driver/tool.h index 35d123490864..cf9515e4ad1f 100644 --- a/include/driver/tool.h +++ b/include/driver/tool.h @@ -65,6 +65,8 @@ struct DriverToolOptions { PropGC(PO::Description("Enable GC proposal, this is experimental"sv)), PropComponent(PO::Description( "Enable Component Model proposal, this is experimental"sv)), + PropExceptionHandling( + PO::Description("Enable Exception handling proposal"sv)), PropAll(PO::Description("Enable all features"sv)), ConfEnableInstructionCounting(PO::Description( "Enable generating code for counting Wasm instructions executed."sv)), @@ -113,6 +115,7 @@ struct DriverToolOptions { PO::Option PropFunctionReference; PO::Option PropGC; PO::Option PropComponent; + PO::Option PropExceptionHandling; PO::Option PropAll; PO::Option ConfEnableInstructionCounting; PO::Option ConfEnableGasMeasuring; @@ -153,6 +156,7 @@ struct DriverToolOptions { .add_option("enable-function-reference"sv, PropFunctionReference) .add_option("enable-gc"sv, PropGC) .add_option("enable-component"sv, PropComponent) + .add_option("enable-exception-handling"sv, PropExceptionHandling) .add_option("enable-all"sv, PropAll) .add_option("time-limit"sv, TimeLim) .add_option("gas-limit"sv, GasLim) diff --git a/include/executor/executor.h b/include/executor/executor.h index eaab47b36565..ec8615496eaf 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -231,6 +231,10 @@ class Executor { Expect instantiate(Runtime::Instance::ModuleInstance &ModInst, const AST::MemorySection &MemSec); + /// Instantiateion of Tag Instances. + Expect instantiate(Runtime::Instance::ModuleInstance &ModInst, + const AST::TagSection &TagSec); + /// Instantiation of Global Instances. Expect instantiate(Runtime::StackManager &StackMgr, Runtime::Instance::ModuleInstance &ModInst, @@ -269,9 +273,16 @@ class Executor { /// Helper function for branching to label. Expect branchToLabel(Runtime::StackManager &StackMgr, - uint32_t EraseBegin, uint32_t EraseEnd, - int32_t PCOffset, + uint32_t ValueStackEraseBegin, + uint32_t ValueStackEraseEnd, + uint32_t HandlerStackOffset, + uint32_t CaughtStackOffset, int32_t PCOffset, AST::InstrView::iterator &PC) noexcept; + + /// Helper function for throwing an exception. + Expect throwException(Runtime::StackManager &StackMgr, + Runtime::Instance::TagInstance *, + AST::InstrView::iterator &PC) noexcept; /// @} /// \name Helper Functions for getting instances or types. @@ -292,6 +303,10 @@ class Executor { Runtime::Instance::MemoryInstance * getMemInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; + /// Helper function for get tag instance by index. + Runtime::Instance::TagInstance * + getTagInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; + /// Helper function for get global instance by index. Runtime::Instance::GlobalInstance * getGlobInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const; @@ -318,6 +333,15 @@ class Executor { Expect runIfElseOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; + Expect runTryOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; + Expect runThrowOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; + Expect runRethrowOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; Expect runBrOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; diff --git a/include/loader/loader.h b/include/loader/loader.h index 6db703b6bf40..b5b2aaa7b5e1 100644 --- a/include/loader/loader.h +++ b/include/loader/loader.h @@ -82,6 +82,9 @@ template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { return ASTNodeAttr::Seg_Element; } +template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { + return ASTNodeAttr::Sec_Tag; +} template <> inline ASTNodeAttr NodeAttrFromAST() noexcept { return ASTNodeAttr::Sec_Alias; @@ -275,6 +278,14 @@ class Loader { } return {}; } + /// @} + + /// \name Helper function to set the function type for tag + /// @{ + void setTagFunctionType(AST::TagSection &TagSec, + AST::ImportSection &ImportSec, + AST::TypeSection &TypeSec); + /// @} template Expect loadSectionContentVec(T &Sec, ElemLoader &&Func) { @@ -297,6 +308,7 @@ class Loader { Expect loadSection(AST::CodeSection &Sec); Expect loadSection(AST::DataSection &Sec); Expect loadSection(AST::DataCountSection &Sec); + Expect loadSection(AST::TagSection &Sec); Expect loadSection(AST::Component::ComponentSection &Sec); Expect loadSection(AST::CoreModuleSection &Sec); Expect loadSection(AST::Component::CoreInstanceSection &Sec); @@ -334,6 +346,7 @@ class Loader { Expect loadType(AST::MemoryType &MemType); Expect loadType(AST::TableType &TabType); Expect loadType(AST::GlobalType &GlobType); + Expect loadType(AST::TagType &TgType); Expect loadType(AST::Component::DefType &Ty); Expect loadType(AST::Component::FuncType &Ty); diff --git a/include/runtime/instance/module.h b/include/runtime/instance/module.h index 4f0252c02a7a..704dce93c448 100644 --- a/include/runtime/instance/module.h +++ b/include/runtime/instance/module.h @@ -24,6 +24,7 @@ #include "runtime/instance/memory.h" #include "runtime/instance/struct.h" #include "runtime/instance/table.h" +#include "runtime/instance/tag.h" #include #include @@ -56,7 +57,8 @@ inline constexpr const bool IsEntityV = std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v; + std::is_same_v || + std::is_same_v; /// Return true if T is an instance. template @@ -140,6 +142,10 @@ class ModuleInstance { std::shared_lock Lock(Mutex); return unsafeFindExports(ExpMems, ExtName); } + TagInstance *findTagExports(std::string_view ExtName) const noexcept { + std::shared_lock Lock(Mutex); + return unsafeFindExports(ExpTags, ExtName); + } GlobalInstance *findGlobalExports(std::string_view ExtName) const noexcept { std::shared_lock Lock(Mutex); return unsafeFindExports(ExpGlobals, ExtName); @@ -158,6 +164,10 @@ class ModuleInstance { std::shared_lock Lock(Mutex); return static_cast(ExpMems.size()); } + uint32_t getTagExportNum() const noexcept { + std::shared_lock Lock(Mutex); + return static_cast(ExpTags.size()); + } uint32_t getGlobalExportNum() const noexcept { std::shared_lock Lock(Mutex); return static_cast(ExpGlobals.size()); @@ -180,6 +190,11 @@ class ModuleInstance { return std::forward(CallBack)(ExpMems); } template + auto getTagExports(CallbackT &&CallBack) const noexcept { + std::shared_lock Lock(Mutex); + return std::forward(CallBack)(ExpTags); + } + template auto getGlobalExports(CallbackT &&CallBack) const noexcept { std::shared_lock Lock(Mutex); return std::forward(CallBack)(ExpGlobals); @@ -210,6 +225,10 @@ class ModuleInstance { std::unique_lock Lock(Mutex); unsafeAddInstance(OwnedMemInsts, MemInsts, std::forward(Values)...); } + template void addTag(Args &&...Values) { + std::unique_lock Lock(Mutex); + unsafeAddInstance(OwnedTagInsts, TagInsts, std::forward(Values)...); + } template void addGlobal(Args &&...Values) { std::unique_lock Lock(Mutex); unsafeAddInstance(OwnedGlobInsts, GlobInsts, std::forward(Values)...); @@ -248,6 +267,10 @@ class ModuleInstance { std::unique_lock Lock(Mutex); unsafeImportInstance(MemInsts, Mem); } + void importTag(TagInstance *Tg) { + std::unique_lock Lock(Mutex); + unsafeImportInstance(TagInsts, Tg); + } void importGlobal(GlobalInstance *Glob) { std::unique_lock Lock(Mutex); ImpGlobalNum++; @@ -271,6 +294,10 @@ class ModuleInstance { std::unique_lock Lock(Mutex); ExpGlobals.insert_or_assign(std::string(Name), GlobInsts[Idx]); } + void exportTag(std::string_view Name, uint32_t Idx) { + std::unique_lock Lock(Mutex); + ExpTags.insert_or_assign(std::string(Name), TagInsts[Idx]); + } /// Get defined type list. Span getTypeList() const noexcept { return Types; } @@ -320,6 +347,9 @@ class ModuleInstance { MemoryInstance *unsafeGetMemory(uint32_t Idx) const noexcept { return MemInsts[Idx]; } + TagInstance *unsafeGetTag(uint32_t Idx) const noexcept { + return TagInsts[Idx]; + } Expect getGlobal(uint32_t Idx) const noexcept { std::shared_lock Lock(Mutex); if (Idx >= GlobInsts.size()) { @@ -467,6 +497,7 @@ class ModuleInstance { std::vector> OwnedFuncInsts; std::vector> OwnedTabInsts; std::vector> OwnedMemInsts; + std::vector> OwnedTagInsts; std::vector> OwnedGlobInsts; std::vector> OwnedElemInsts; std::vector> OwnedDataInsts; @@ -477,6 +508,7 @@ class ModuleInstance { std::vector FuncInsts; std::vector TabInsts; std::vector MemInsts; + std::vector TagInsts; std::vector GlobInsts; std::vector ElemInsts; std::vector DataInsts; @@ -488,6 +520,7 @@ class ModuleInstance { std::map> ExpFuncs; std::map> ExpTables; std::map> ExpMems; + std::map> ExpTags; std::map> ExpGlobals; /// Start function instance. diff --git a/include/runtime/instance/tag.h b/include/runtime/instance/tag.h new file mode 100644 index 000000000000..cf0b63e6c131 --- /dev/null +++ b/include/runtime/instance/tag.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +//===-- wasmedge/runtime/instance/tag.h - Tag Instance definition ---===// +// +// Part of the WasmEdge Project. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the tag instance definition in store manager. +/// +//===----------------------------------------------------------------------===// +#pragma once + +#include "ast/type.h" + +namespace WasmEdge { +namespace Runtime { +namespace Instance { + +class TagInstance { +public: + TagInstance() = delete; + TagInstance(const AST::TagType &T, const AST::FunctionType *F) noexcept + : TgType(T, F) {} + + /// Getter of tag type. + const AST::TagType &getTagType() const noexcept { return TgType; } + + uint32_t getAssocValSize() const noexcept { return TgType.getAssocValSize(); } + +private: + /// \name Data of tag instance. + /// @{ + AST::TagType TgType; + /// @} +}; + +} // namespace Instance +} // namespace Runtime +} // namespace WasmEdge diff --git a/include/runtime/stackmgr.h b/include/runtime/stackmgr.h index ef9b521fd755..6fccdbf92514 100644 --- a/include/runtime/stackmgr.h +++ b/include/runtime/stackmgr.h @@ -23,19 +23,46 @@ namespace Runtime { class StackManager { public: + using Value = ValVariant; + struct Frame { Frame() = delete; Frame(const Instance::ModuleInstance *Mod, AST::InstrView::iterator FromIt, - uint32_t L, uint32_t A, uint32_t V) noexcept - : Module(Mod), From(FromIt), Locals(L), Arity(A), VPos(V) {} + uint32_t L, uint32_t A, uint32_t V, uint32_t H, uint32_t C) noexcept + : Module(Mod), From(FromIt), Locals(L), Arity(A), VPos(V), HPos(H), + CPos(C) {} const Instance::ModuleInstance *Module; AST::InstrView::iterator From; uint32_t Locals; uint32_t Arity; uint32_t VPos; + uint32_t HPos; + uint32_t CPos; }; - using Value = ValVariant; + struct Handler { + Handler(AST::InstrView::iterator E, uint32_t V, uint32_t F, uint32_t H, + uint32_t C) + : CatchCaluse(), EndIt(E), VPos(V), FPos(F), HPos(H), CPos(C) {} + // nullptr stands for catch all clause + std::vector< + std::pair> + CatchCaluse; + AST::InstrView::iterator EndIt; + uint32_t VPos; + uint32_t FPos; + uint32_t HPos; + uint32_t CPos; + }; + + struct Exception { + Exception(Runtime::Instance::TagInstance *T, Span &V, + AST::InstrView::iterator E) + : TagInst(T), Val(V.begin(), V.end()), EndIt(E) {} + Runtime::Instance::TagInstance *TagInst; + std::vector Val; + AST::InstrView::iterator EndIt; + }; /// Stack manager provides the stack control for Wasm execution with VALIDATED /// modules. All operations of instructions passed validation, therefore no @@ -68,7 +95,12 @@ class StackManager { ValueStack.push_back(std::forward(Val)); } - /// Unsafe pop and return the top entry. + /// Push a vector of value to stack + void pushValVec(const std::vector &ValVec) { + ValueStack.insert(ValueStack.end(), ValVec.begin(), ValVec.end()); + } + + /// Unsafe Pop and return the top entry. Value pop() { Value V = std::move(ValueStack.back()); ValueStack.pop_back(); @@ -90,7 +122,9 @@ class StackManager { uint32_t Arity = 0, bool IsTailCall = false) noexcept { if (likely(!IsTailCall)) { FrameStack.emplace_back(Module, From, LocalNum, Arity, - static_cast(ValueStack.size())); + static_cast(ValueStack.size()), + static_cast(HandlerStack.size()), + static_cast(CaughtStack.size())); } else { assuming(!FrameStack.empty()); assuming(FrameStack.back().VPos >= FrameStack.back().Locals); @@ -99,6 +133,10 @@ class StackManager { ValueStack.erase(ValueStack.begin() + FrameStack.back().VPos - FrameStack.back().Locals, ValueStack.end() - LocalNum); + HandlerStack.erase(HandlerStack.begin() + FrameStack.back().HPos, + HandlerStack.end()); + CaughtStack.erase(CaughtStack.begin() + FrameStack.back().HPos, + CaughtStack.end()); FrameStack.back().Module = Module; FrameStack.back().Locals = LocalNum; FrameStack.back().Arity = Arity; @@ -120,22 +158,119 @@ class StackManager { return From; } - /// Unsafe erase stack. - void stackErase(uint32_t EraseBegin, uint32_t EraseEnd) noexcept { + // Push handler for try-delegate block + void pushHandler(AST::InstrView::iterator EndIt, uint32_t VSize, + uint32_t HOffset, uint32_t COffset) noexcept { + // The POS is the stack size after jumping to the label + HandlerStack.emplace_back( + EndIt, VSize, static_cast(FrameStack.size()), + static_cast(HandlerStack.size()) - HOffset, + static_cast(CaughtStack.size()) - COffset); + } + + // Push handler for try-catch block + void pushHandler(AST::InstrView::iterator EndIt, + uint32_t BlockParamNum) noexcept { + HandlerStack.emplace_back( + EndIt, static_cast(ValueStack.size()) - BlockParamNum, + static_cast(FrameStack.size()), + static_cast(HandlerStack.size()), + static_cast(CaughtStack.size())); + } + + // Push a handler to the current try block + void addCatchCaluseToLastHandler(Runtime::Instance::TagInstance *T, + AST::InstrView::iterator It) noexcept { + HandlerStack.back().CatchCaluse.emplace_back(T, It); + } + + // Erase the stacks so that the exception handler is on the top of the stack + // Associated Value should remain on top of ValueStack. + Handler popToTopHandler(uint32_t AssocValSize) noexcept { + auto TopHandler = std::move(HandlerStack.back()); + HandlerStack.pop_back(); + assuming(ValueStack.size() - AssocValSize >= TopHandler.VPos); + ValueStack.erase(ValueStack.begin() + TopHandler.VPos, + ValueStack.end() - AssocValSize); + FrameStack.erase(FrameStack.begin() + TopHandler.FPos, FrameStack.end()); + HandlerStack.erase(HandlerStack.begin() + TopHandler.HPos, + HandlerStack.end()); + CaughtStack.erase(CaughtStack.begin() + TopHandler.CPos, CaughtStack.end()); + return TopHandler; + } + + // Unsafe pop top exception handler + AST::InstrView::iterator popHandler() noexcept { + auto EndIt = HandlerStack.back().EndIt; + HandlerStack.pop_back(); + return EndIt; + } + + // Check whether handler stack is empty + bool isHandlerStackEmpty() noexcept { return HandlerStack.empty(); } + + // Push a caught exception to the stack + void pushCaught(Runtime::Instance::TagInstance *T, Span V, + AST::InstrView::iterator E) noexcept { + CaughtStack.emplace_back(T, V, E); + } + + // Unsafe pop top caught exception + AST::InstrView::iterator popCaught() noexcept { + auto EndIt = CaughtStack.back().EndIt; + CaughtStack.pop_back(); + return EndIt; + } + + /// Unsafe Getter of top N-th value entry of stack. + Exception &getCaughtTopN(uint32_t Offset) noexcept { + assuming(0 < Offset && Offset <= CaughtStack.size()); + return *(CaughtStack.end() - Offset); + } + + /// Unsafe erase value stack. + void eraseValueStack(uint32_t EraseBegin, uint32_t EraseEnd) noexcept { assuming(EraseEnd <= EraseBegin && EraseBegin <= ValueStack.size()); ValueStack.erase(ValueStack.end() - EraseBegin, ValueStack.end() - EraseEnd); } + // Unsafe erase top Num element of exception handler stack + void eraseHandlerStack(uint32_t Num) noexcept { + HandlerStack.erase(HandlerStack.end() - Num, HandlerStack.end()); + } + + // Unsafe erase top Num element of caught exception stack + void eraseCaughtStack(uint32_t Num) noexcept { + CaughtStack.erase(CaughtStack.end() - Num, CaughtStack.end()); + } + /// Unsafe leave top label. - AST::InstrView::iterator maybePopFrame(AST::InstrView::iterator PC) noexcept { + AST::InstrView::iterator + maybePopFrameOrHandlerOrCaught(AST::InstrView::iterator PC) noexcept { if (FrameStack.size() > 1 && PC->isLast()) { // Noted that there's always a base frame in stack. return popFrame(); } + if (PC->isTryLast()) { + return popHandler(); + } + if (PC->isCatchLast()) { + return popCaught(); + } return PC; } + // Unsafe leave try-block or catch-block + AST::InstrView::iterator + popHandlerOrCaught(AST::InstrView::iterator PC) noexcept { + if (PC->isTryLast()) { + return popHandler(); + } else { + return popCaught(); + } + } + /// Unsafe getter of module address. const Instance::ModuleInstance *getModule() const noexcept { assuming(!FrameStack.empty()); @@ -153,6 +288,8 @@ class StackManager { /// @{ std::vector ValueStack; std::vector FrameStack; + std::vector HandlerStack; + std::vector CaughtStack; /// @} }; diff --git a/include/validator/formchecker.h b/include/validator/formchecker.h index 4e189ba37b13..3af5cf83225d 100644 --- a/include/validator/formchecker.h +++ b/include/validator/formchecker.h @@ -51,6 +51,7 @@ class FormChecker { void addData(const AST::DataSegment &Data); void addRef(const uint32_t FuncIdx); void addLocal(const ValType &V, bool Initialized); + void addTag(const uint32_t TypeIdx); std::vector result() { return ValStack; } auto &getTypes() { return Types; } @@ -58,6 +59,7 @@ class FormChecker { auto &getTables() { return Tables; } auto &getMemories() { return Mems; } auto &getGlobals() { return Globals; } + auto &getTags() { return Tags; } uint32_t getNumImportFuncs() const { return NumImportFuncs; } uint32_t getNumImportGlobals() const { return NumImportGlobals; } @@ -137,6 +139,7 @@ class FormChecker { std::vector Locals; std::vector LocalInits; std::vector Returns; + std::vector Tags; /// Running stack. std::vector CtrlStack; diff --git a/include/validator/validator.h b/include/validator/validator.h index 3b5991d668b5..bde267be62b7 100644 --- a/include/validator/validator.h +++ b/include/validator/validator.h @@ -67,6 +67,7 @@ class Validator { Expect validate(const AST::DataSection &DataSec); Expect validate(const AST::StartSection &StartSec); Expect validate(const AST::ExportSection &ExportSec); + Expect validate(const AST::TagSection &TagSec); /// Validate const expression Expect validateConstExpr(AST::InstrView Instrs, diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index caa3906483fc..fba3a1c51d9b 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -56,6 +56,9 @@ struct WasmEdge_TableTypeContext {}; // WasmEdge_MemoryTypeContext implementation. struct WasmEdge_MemoryTypeContext {}; +// WasmEdge_TagTypeContext implementation. +struct WasmEdge_TagTypeContext {}; + // WasmEdge_GlobalTypeContext implementation. struct WasmEdge_GlobalTypeContext {}; @@ -101,6 +104,9 @@ struct WasmEdge_TableInstanceContext {}; // WasmEdge_MemoryInstanceContext implementation. struct WasmEdge_MemoryInstanceContext {}; +// WasmEdge_TagInstanceContext implementation. +struct WasmEdge_TagInstanceContext {}; + // WasmEdge_GlobalInstanceContext implementation. struct WasmEdge_GlobalInstanceContext {}; @@ -332,6 +338,7 @@ CONVTO(TabType, AST::TableType, TableType, ) CONVTO(TabType, AST::TableType, TableType, const) CONVTO(MemType, AST::MemoryType, MemoryType, ) CONVTO(MemType, AST::MemoryType, MemoryType, const) +CONVTO(TagType, AST::TagType, TagType, const) CONVTO(GlobType, AST::GlobalType, GlobalType, ) CONVTO(GlobType, AST::GlobalType, GlobalType, const) CONVTO(ImpType, AST::ImportDesc, ImportType, const) @@ -346,6 +353,7 @@ CONVTO(Func, Runtime::Instance::FunctionInstance, FunctionInstance, ) CONVTO(Func, Runtime::Instance::FunctionInstance, FunctionInstance, const) CONVTO(Tab, Runtime::Instance::TableInstance, TableInstance, ) CONVTO(Mem, Runtime::Instance::MemoryInstance, MemoryInstance, ) +CONVTO(Tag, Runtime::Instance::TagInstance, TagInstance, ) CONVTO(Glob, Runtime::Instance::GlobalInstance, GlobalInstance, ) CONVTO(CallFrame, Runtime::CallingFrame, CallingFrame, const) CONVTO(Plugin, Plugin::Plugin, Plugin, const) @@ -366,6 +374,7 @@ CONVFROM(TabType, AST::TableType, TableType, ) CONVFROM(TabType, AST::TableType, TableType, const) CONVFROM(MemType, AST::MemoryType, MemoryType, ) CONVFROM(MemType, AST::MemoryType, MemoryType, const) +CONVFROM(TagType, AST::TagType, TagType, const) CONVFROM(GlobType, AST::GlobalType, GlobalType, ) CONVFROM(GlobType, AST::GlobalType, GlobalType, const) CONVFROM(ImpType, AST::ImportDesc, ImportType, const) @@ -383,6 +392,7 @@ CONVFROM(Tab, Runtime::Instance::TableInstance, TableInstance, ) CONVFROM(Tab, Runtime::Instance::TableInstance, TableInstance, const) CONVFROM(Mem, Runtime::Instance::MemoryInstance, MemoryInstance, ) CONVFROM(Mem, Runtime::Instance::MemoryInstance, MemoryInstance, const) +CONVFROM(Tag, Runtime::Instance::TagInstance, TagInstance, const) CONVFROM(Glob, Runtime::Instance::GlobalInstance, GlobalInstance, ) CONVFROM(Glob, Runtime::Instance::GlobalInstance, GlobalInstance, const) CONVFROM(CallFrame, Runtime::CallingFrame, CallingFrame, const) @@ -1306,6 +1316,18 @@ WasmEdge_MemoryTypeDelete(WasmEdge_MemoryTypeContext *Cxt) { // <<<<<<<< WasmEdge memory type functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +// >>>>>>>> WasmEdge tag type functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +WASMEDGE_CAPI_EXPORT const WasmEdge_FunctionTypeContext * +WasmEdge_TagTypeGetFunctionType(const WasmEdge_TagTypeContext *Cxt) { + if (Cxt) { + return toFuncTypeCxt(&fromTagTypeCxt(Cxt)->getFuncType()); + } + return nullptr; +} + +// <<<<<<<< WasmEdge tag type functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + // >>>>>>>> WasmEdge global type functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WASMEDGE_CAPI_EXPORT WasmEdge_GlobalTypeContext * @@ -1405,6 +1427,16 @@ WasmEdge_ImportTypeGetMemoryType(const WasmEdge_ASTModuleContext *ASTCxt, return nullptr; } +WASMEDGE_CAPI_EXPORT const WasmEdge_TagTypeContext * +WasmEdge_ImportTypeGetTagType(const WasmEdge_ASTModuleContext *ASTCxt, + const WasmEdge_ImportTypeContext *Cxt) { + if (ASTCxt && Cxt && + fromImpTypeCxt(Cxt)->getExternalType() == WasmEdge::ExternalType::Tag) { + return toTagTypeCxt(&fromImpTypeCxt(Cxt)->getExternalTagType()); + } + return nullptr; +} + WASMEDGE_CAPI_EXPORT const WasmEdge_GlobalTypeContext * WasmEdge_ImportTypeGetGlobalType(const WasmEdge_ASTModuleContext *ASTCxt, const WasmEdge_ImportTypeContext *Cxt) { @@ -1545,6 +1577,30 @@ WasmEdge_ExportTypeGetMemoryType(const WasmEdge_ASTModuleContext *ASTCxt, return nullptr; } +WASMEDGE_CAPI_EXPORT const WasmEdge_TagTypeContext * +WasmEdge_ExportTypeGetTagType(const WasmEdge_ASTModuleContext *ASTCxt, + const WasmEdge_ExportTypeContext *Cxt) { + if (ASTCxt && Cxt && + fromExpTypeCxt(Cxt)->getExternalType() == WasmEdge::ExternalType::Tag) { + // `external_index` = `tag_type_index` + `import_tag_nums` + uint32_t ExtIdx = fromExpTypeCxt(Cxt)->getExternalIndex(); + const auto &ImpDescs = + fromASTModCxt(ASTCxt)->getImportSection().getContent(); + for (auto &&ImpDesc : ImpDescs) { + if (ImpDesc.getExternalType() == WasmEdge::ExternalType::Tag) { + ExtIdx--; + } + } + // Get the tag type + const auto &TagDescs = fromASTModCxt(ASTCxt)->getTagSection().getContent(); + if (ExtIdx >= TagDescs.size()) { + return nullptr; + } + return toTagTypeCxt(&TagDescs[ExtIdx]); + } + return nullptr; +} + WASMEDGE_CAPI_EXPORT const WasmEdge_GlobalTypeContext * WasmEdge_ExportTypeGetGlobalType(const WasmEdge_ASTModuleContext *ASTCxt, const WasmEdge_ExportTypeContext *Cxt) { @@ -2065,6 +2121,15 @@ WasmEdge_ModuleInstanceFindMemory(const WasmEdge_ModuleInstanceContext *Cxt, return nullptr; } +WASMEDGE_CAPI_EXPORT WasmEdge_TagInstanceContext * +WasmEdge_ModuleInstanceFindTag(const WasmEdge_ModuleInstanceContext *Cxt, + const WasmEdge_String Name) { + if (Cxt) { + return toTagCxt(fromModCxt(Cxt)->findTagExports(genStrView(Name))); + } + return nullptr; +} + WASMEDGE_CAPI_EXPORT WasmEdge_GlobalInstanceContext * WasmEdge_ModuleInstanceFindGlobal(const WasmEdge_ModuleInstanceContext *Cxt, const WasmEdge_String Name) { @@ -2129,6 +2194,24 @@ WasmEdge_ModuleInstanceListMemory(const WasmEdge_ModuleInstanceContext *Cxt, return 0; } +WASMEDGE_CAPI_EXPORT uint32_t WasmEdge_ModuleInstanceListTagLength( + const WasmEdge_ModuleInstanceContext *Cxt) { + if (Cxt) { + return fromModCxt(Cxt)->getTagExportNum(); + } + return 0; +} + +WASMEDGE_CAPI_EXPORT uint32_t +WasmEdge_ModuleInstanceListTag(const WasmEdge_ModuleInstanceContext *Cxt, + WasmEdge_String *Names, const uint32_t Len) { + if (Cxt) { + return fromModCxt(Cxt)->getTagExports( + [&](auto &Map) { return fillMap(Map, Names, Len); }); + } + return 0; +} + WASMEDGE_CAPI_EXPORT uint32_t WasmEdge_ModuleInstanceListGlobalLength( const WasmEdge_ModuleInstanceContext *Cxt) { if (Cxt) { @@ -2471,6 +2554,18 @@ WasmEdge_MemoryInstanceDelete(WasmEdge_MemoryInstanceContext *Cxt) { // <<<<<<<< WasmEdge memory instance functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +// >>>>>>>> WasmEdge tag instance functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +WASMEDGE_CAPI_EXPORT const WasmEdge_TagTypeContext * +WasmEdge_TagInstanceGetTagType(const WasmEdge_TagInstanceContext *Cxt) { + if (Cxt) { + return toTagTypeCxt(&fromTagCxt(Cxt)->getTagType()); + } + return nullptr; +} + +// <<<<<<<< WasmEdge tag instance functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + // >>>>>>>> WasmEdge global instance functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WASMEDGE_CAPI_EXPORT WasmEdge_GlobalInstanceContext * diff --git a/lib/driver/runtimeTool.cpp b/lib/driver/runtimeTool.cpp index 8a4214551898..5989dde8c25a 100644 --- a/lib/driver/runtimeTool.cpp +++ b/lib/driver/runtimeTool.cpp @@ -76,6 +76,9 @@ int Tool(struct DriverToolOptions &Opt) noexcept { Conf.addProposal(Proposal::Component); spdlog::warn("component model is enabled, this is experimental."); } + if (Opt.PropExceptionHandling.value()) { + Conf.addProposal(Proposal::ExceptionHandling); + } if (Opt.PropAll.value()) { Conf.addProposal(Proposal::MultiMemories); Conf.addProposal(Proposal::TailCall); @@ -85,6 +88,7 @@ int Tool(struct DriverToolOptions &Opt) noexcept { Conf.addProposal(Proposal::Component); spdlog::warn("GC proposal is enabled, this is experimental."); spdlog::warn("component model is enabled, this is experimental."); + Conf.addProposal(Proposal::ExceptionHandling); } std::optional Timeout; diff --git a/lib/executor/CMakeLists.txt b/lib/executor/CMakeLists.txt index d9eb7232fda0..9b5238f89a39 100644 --- a/lib/executor/CMakeLists.txt +++ b/lib/executor/CMakeLists.txt @@ -11,6 +11,7 @@ wasmedge_add_library(wasmedgeExecutor instantiate/data.cpp instantiate/export.cpp instantiate/module.cpp + instantiate/tag.cpp engine/proxy.cpp engine/controlInstr.cpp engine/tableInstr.cpp diff --git a/lib/executor/engine/controlInstr.cpp b/lib/executor/engine/controlInstr.cpp index b383f81f71f8..282b220bad92 100644 --- a/lib/executor/engine/controlInstr.cpp +++ b/lib/executor/engine/controlInstr.cpp @@ -33,12 +33,53 @@ Expect Executor::runIfElseOp(Runtime::StackManager &StackMgr, return {}; } +Expect Executor::runTryOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { + if (Instr.isDelegate()) { + StackMgr.pushHandler(PC + Instr.getTryBlockJumpEnd(), + Instr.getTryBlockVSize(), Instr.getTryBlockHOffset(), + Instr.getTryBlockCOffset()); + + } else { + StackMgr.pushHandler(PC + Instr.getTryBlockJumpEnd(), + Instr.getTryBlockParamNum()); + for (auto CatchOffset : Instr.getJumpCatchList()) { + auto CatchInstrIt = PC + CatchOffset; + StackMgr.addCatchCaluseToLastHandler( + getTagInstByIdx(StackMgr, CatchInstrIt->getTargetIndex()), + CatchInstrIt); + } + if (auto CatchAllOffset = Instr.getJumpCatchAll(); CatchAllOffset) { + auto CatchAllInstrIt = PC + CatchAllOffset; + StackMgr.addCatchCaluseToLastHandler(nullptr, CatchAllInstrIt); + } + } + return {}; +} + +Expect Executor::runThrowOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { + auto *TagInst = getTagInstByIdx(StackMgr, Instr.getTargetIndex()); + return throwException(StackMgr, TagInst, PC); +} + +Expect Executor::runRethrowOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { + auto Exception = StackMgr.getCaughtTopN(Instr.getJump().CaughtStackOffset); + StackMgr.pushValVec(Exception.Val); + return throwException(StackMgr, Exception.TagInst, PC); +} + Expect Executor::runBrOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept { - return branchToLabel(StackMgr, Instr.getJump().StackEraseBegin, - Instr.getJump().StackEraseEnd, Instr.getJump().PCOffset, - PC); + auto &JumpDesc = Instr.getJump(); + return branchToLabel(StackMgr, JumpDesc.ValueStackEraseBegin, + JumpDesc.ValueStackEraseEnd, JumpDesc.HandlerStackOffset, + JumpDesc.CaughtStackOffset, JumpDesc.PCOffset, PC); } Expect Executor::runBrIfOp(Runtime::StackManager &StackMgr, @@ -80,13 +121,16 @@ Expect Executor::runBrTableOp(Runtime::StackManager &StackMgr, auto LabelTable = Instr.getLabelList(); const auto LabelTableSize = static_cast(LabelTable.size() - 1); if (Value < LabelTableSize) { - return branchToLabel(StackMgr, LabelTable[Value].StackEraseBegin, - LabelTable[Value].StackEraseEnd, - LabelTable[Value].PCOffset, PC); + auto &JumpDesc = LabelTable[Value]; + return branchToLabel(StackMgr, JumpDesc.ValueStackEraseBegin, + JumpDesc.ValueStackEraseEnd, + JumpDesc.HandlerStackOffset, + JumpDesc.CaughtStackOffset, JumpDesc.PCOffset, PC); } - return branchToLabel(StackMgr, LabelTable[LabelTableSize].StackEraseBegin, - LabelTable[LabelTableSize].StackEraseEnd, - LabelTable[LabelTableSize].PCOffset, PC); + auto &JumpDesc = LabelTable[LabelTableSize]; + return branchToLabel(StackMgr, JumpDesc.ValueStackEraseBegin, + JumpDesc.ValueStackEraseEnd, JumpDesc.HandlerStackOffset, + JumpDesc.CaughtStackOffset, JumpDesc.PCOffset, PC); } Expect Executor::runBrOnCastOp(Runtime::StackManager &StackMgr, diff --git a/lib/executor/engine/engine.cpp b/lib/executor/engine/engine.cpp index 1b3bac1c9681..4502928d5c1b 100644 --- a/lib/executor/engine/engine.cpp +++ b/lib/executor/engine/engine.cpp @@ -139,8 +139,17 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, PC += PC->getJumpEnd(); [[fallthrough]]; case OpCode::End: - PC = StackMgr.maybePopFrame(PC); + PC = StackMgr.maybePopFrameOrHandlerOrCaught(PC); return {}; + case OpCode::Try: + return runTryOp(StackMgr, Instr, PC); + case OpCode::Catch: + PC = StackMgr.popHandlerOrCaught(PC); + return {}; + case OpCode::Throw: + return runThrowOp(StackMgr, Instr, PC); + case OpCode::Rethrow: + return runRethrowOp(StackMgr, Instr, PC); case OpCode::Br: return runBrOp(StackMgr, Instr, PC); case OpCode::Br_if: @@ -169,6 +178,12 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, return runCallRefOp(StackMgr, Instr, PC); case OpCode::Return_call_ref: return runCallRefOp(StackMgr, Instr, PC, true); + case OpCode::Delegate: + PC = StackMgr.popHandler(); + return {}; + case OpCode::Catch_all: + PC = StackMgr.popHandlerOrCaught(PC); + return {}; // Reference Instructions case OpCode::Ref__null: diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 41c361d837a4..4214ff24de5b 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -195,7 +195,10 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, } Expect Executor::branchToLabel(Runtime::StackManager &StackMgr, - uint32_t EraseBegin, uint32_t EraseEnd, + uint32_t ValueStackEraseBegin, + uint32_t ValueStackEraseEnd, + uint32_t HandlerStackOffset, + uint32_t CaughtStackOffset, int32_t PCOffset, AST::InstrView::iterator &PC) noexcept { // Check stop token @@ -204,12 +207,43 @@ Expect Executor::branchToLabel(Runtime::StackManager &StackMgr, return Unexpect(ErrCode::Value::Interrupted); } - StackMgr.stackErase(EraseBegin, EraseEnd); + StackMgr.eraseValueStack(ValueStackEraseBegin, ValueStackEraseEnd); + StackMgr.eraseHandlerStack(HandlerStackOffset); + StackMgr.eraseCaughtStack(CaughtStackOffset); // PC need to -1 here because the PC will increase in the next iteration. PC += (PCOffset - 1); return {}; } +Expect Executor::throwException(Runtime::StackManager &StackMgr, + Runtime::Instance::TagInstance *TagInst, + AST::InstrView::iterator &PC) noexcept { + while (!StackMgr.isHandlerStackEmpty()) { + auto AssocValSize = TagInst->getAssocValSize(); + // The value that associated with the exception should remain on the stack + auto ExceptionHandler = StackMgr.popToTopHandler(AssocValSize); + if (!ExceptionHandler.CatchCaluse.empty()) { + for (auto &[CatchTagInst, StartIt] : ExceptionHandler.CatchCaluse) { + if (CatchTagInst == nullptr || TagInst == CatchTagInst) { + PC = StartIt; + StackMgr.pushCaught(TagInst, StackMgr.getTopSpan(AssocValSize), + ExceptionHandler.EndIt); + if (CatchTagInst == nullptr) { + StackMgr.eraseValueStack(AssocValSize, 0); + } + return {}; + } + } + } else { + // The stack has transformed to the state after jumping to the label by + // StackMgr.popToTopHandler(AssocValSize) + return throwException(StackMgr, TagInst, PC); + } + } + spdlog::error(ErrCode::Value::UncaughtException); + return Unexpect(ErrCode::Value::UncaughtException); +} + const AST::SubType *Executor::getDefTypeByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const { const auto *ModInst = StackMgr.getModule(); @@ -253,6 +287,17 @@ Executor::getMemInstByIdx(Runtime::StackManager &StackMgr, return ModInst->unsafeGetMemory(Idx); } +Runtime::Instance::TagInstance * +Executor::getTagInstByIdx(Runtime::StackManager &StackMgr, + const uint32_t Idx) const { + const auto *ModInst = StackMgr.getModule(); + // When top frame is dummy frame, cannot find instance. + if (unlikely(ModInst == nullptr)) { + return nullptr; + } + return ModInst->unsafeGetTag(Idx); +} + Runtime::Instance::GlobalInstance * Executor::getGlobInstByIdx(Runtime::StackManager &StackMgr, const uint32_t Idx) const { diff --git a/lib/executor/instantiate/export.cpp b/lib/executor/instantiate/export.cpp index d7daa24e6cf5..435f64cb9051 100644 --- a/lib/executor/instantiate/export.cpp +++ b/lib/executor/instantiate/export.cpp @@ -33,6 +33,9 @@ Expect Executor::instantiate(Runtime::Instance::ModuleInstance &ModInst, case ExternalType::Table: ModInst.exportTable(ExtName, ExtIdx); break; + case ExternalType::Tag: + ModInst.exportTag(ExtName, ExtIdx); + break; default: break; } diff --git a/lib/executor/instantiate/import.cpp b/lib/executor/instantiate/import.cpp index ade278b99b3d..c475a9de381a 100644 --- a/lib/executor/instantiate/import.cpp +++ b/lib/executor/instantiate/import.cpp @@ -70,6 +70,11 @@ checkImportMatched(std::string_view ModName, std::string_view ExtName, return {}; } break; + case ExternalType::Tag: + if (auto Res = ModInst.findTagExports(ExtName); likely(Res != nullptr)) { + return {}; + } + break; default: return logUnknownError(ModName, ExtName, ExtType); } @@ -87,6 +92,9 @@ checkImportMatched(std::string_view ModName, std::string_view ExtName, return logMatchError(ModName, ExtName, ExtType, ExtType, ExternalType::Memory); } + if (ModInst.findTagExports(ExtName)) { + return logMatchError(ModName, ExtName, ExtType, ExtType, ExternalType::Tag); + } if (ModInst.findGlobalExports(ExtName)) { return logMatchError(ModName, ExtName, ExtType, ExtType, ExternalType::Global); @@ -244,6 +252,22 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, ModInst.importMemory(ImpInst); break; } + case ExternalType::Tag: { + // Get tag type. External type checked in validation. + const auto &T = ImpDesc.getExternalTagType(); + // Import matching. + auto *TargetInst = TargetModInst->findTagExports(ExtName); + const auto &TargetType = TargetInst->getTagType().getFuncType(); + const auto *TType = *ModInst.getFuncType(T.getTypeIdx()); + if (TargetType != *TType) { + return logMatchError(ModName, ExtName, ExtType, TType->getParamTypes(), + TType->getReturnTypes(), + TargetType.getParamTypes(), + TargetType.getReturnTypes()); + } + ModInst.importTag(TargetInst); + break; + } case ExternalType::Global: { // Get global type. External type checked in validation. const auto &GlobType = ImpDesc.getExternalGlobalType(); diff --git a/lib/executor/instantiate/module.cpp b/lib/executor/instantiate/module.cpp index 79647fd9f8b7..fc645c47f42d 100644 --- a/lib/executor/instantiate/module.cpp +++ b/lib/executor/instantiate/module.cpp @@ -70,6 +70,11 @@ Executor::instantiate(Runtime::StoreManager &StoreMgr, const AST::Module &Mod, // This function will always success. instantiate(*ModInst, MemSec); + // Instantiate TagSection (TagSec) + const AST::TagSection &TagSec = Mod.getTagSection(); + // This function will always success. + instantiate(*ModInst, TagSec); + // Push a new frame {ModInst, locals:none} StackMgr.pushFrame(ModInst.get(), AST::InstrView::iterator(), 0, 0); diff --git a/lib/executor/instantiate/tag.cpp b/lib/executor/instantiate/tag.cpp new file mode 100644 index 000000000000..4d07364ad0a3 --- /dev/null +++ b/lib/executor/instantiate/tag.cpp @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2022 Second State INC + +#include "executor/executor.h" + +namespace WasmEdge { +namespace Executor { + +// Instantiate tag instance. See "include/executor/executor.h". +Expect Executor::instantiate(Runtime::Instance::ModuleInstance &ModInst, + const AST::TagSection &TagSec) { + + // Iterate through tags from tag section to instantiate + for (const auto &TgType : TagSec.getContent()) { + // Add Tag with corresponding Type. + auto FuncTypePtr = *ModInst.getFuncType(TgType.getTypeIdx()); + ModInst.addTag(TgType, FuncTypePtr); + } + return {}; +} + +} // namespace Executor +} // namespace WasmEdge diff --git a/lib/loader/ast/description.cpp b/lib/loader/ast/description.cpp index fcfe5a66885b..18a408d3e561 100644 --- a/lib/loader/ast/description.cpp +++ b/lib/loader/ast/description.cpp @@ -66,6 +66,15 @@ Expect Loader::loadDesc(AST::ImportDesc &ImpDesc) { } return {}; } + case ExternalType::Tag: { + if (!Conf.hasProposal(Proposal::ExceptionHandling)) { + return logNeedProposal(ErrCode::Value::MalformedImportKind, + Proposal::ExceptionHandling, FMgr.getLastOffset(), + ASTNodeAttr::Module); + } + // Read the Tag type node. + return loadType(ImpDesc.getExternalTagType()); + } default: return logLoadError(ErrCode::Value::MalformedImportKind, FMgr.getLastOffset(), ASTNodeAttr::Desc_Import); @@ -96,6 +105,13 @@ Expect Loader::loadDesc(AST::ExportDesc &ExpDesc) { case ExternalType::Memory: case ExternalType::Global: break; + case ExternalType::Tag: + if (!Conf.hasProposal(Proposal::ExceptionHandling)) { + return logNeedProposal(ErrCode::Value::MalformedImportKind, + Proposal::ExceptionHandling, FMgr.getLastOffset(), + ASTNodeAttr::Module); + } + break; default: return logLoadError(ErrCode::Value::MalformedExportKind, FMgr.getLastOffset(), ASTNodeAttr::Desc_Export); diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index 8088c37e9f88..5f24195e4fbd 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -4,6 +4,7 @@ #include "loader/loader.h" #include +#include #include #include @@ -136,7 +137,9 @@ Expect Loader::loadOpCode() { Expect Loader::loadInstrSeq(std::optional SizeBound) { OpCode Code; AST::InstrVec Instrs; - std::vector> BlockStack; + + // The third argument stores the Pos of all `catch` inside the try-block. + std::vector>> BlockStack; uint32_t Cnt = 0; bool IsReachEnd = false; // Read opcode until the End code of the top block. @@ -155,12 +158,16 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { return logNeedProposal(ErrCode::Value::IllegalOpCode, Res.value(), Offset, ASTNodeAttr::Instruction); } - - // Process the instructions which contain a block. - if (Code == OpCode::Block || Code == OpCode::Loop || Code == OpCode::If) { - BlockStack.push_back(std::make_pair(Code, Cnt)); - } else if (Code == OpCode::Else) { - if (BlockStack.size() == 0 || BlockStack.back().first != OpCode::If) { + switch (Code) { + case OpCode::Block: + case OpCode::Loop: + case OpCode::If: + case OpCode::Try: + BlockStack.emplace_back(Code, Cnt, 0); + break; + case OpCode::Else: { + if (BlockStack.size() == 0 || + std::get<0>(BlockStack.back()) != OpCode::If) { // An Else instruction appeared outside the If-block. if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { return logLoadError(ErrCode::Value::ENDCodeExpected, Offset, @@ -170,7 +177,7 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { ASTNodeAttr::Instruction); } } - uint32_t Pos = BlockStack.back().second; + uint32_t Pos = std::get<1>(BlockStack.back()); if (Instrs[Pos].getJumpElse() > 0) { // An Else instruction appeared before in this If-block. if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { @@ -182,23 +189,93 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { } } Instrs[Pos].setJumpElse(Cnt - Pos); - } else if (Code == OpCode::End) { + break; + } + case OpCode::Catch: { + if (BlockStack.size() == 0) { + // A Catch instruction appeared outside a try-block. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + auto &[BackOp, Pos, CatchList] = BlockStack.back(); + if (BackOp != OpCode::Try) { + // A Catch instruction appeared outside a try-block. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + if (Instrs[Pos].getJumpCatchAll() != 0) { + // A Catch shouldn't behind a Catch_all in the same block. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + // Set it to Instruction object after parsing the whole try block + CatchList.push_back(Cnt - Pos); + break; + } + case OpCode::Catch_all: { + if (BlockStack.size() == 0 || + std::get<0>(BlockStack.back()) != OpCode::Try) { + // A Catch_all instruction appeared outside a try-block. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + uint32_t Pos = std::get<1>(BlockStack.back()); + if (Instrs[Pos].getJumpCatchAll() != 0) { + // A try block may contain only one Catch_all instruction. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + Instrs[Pos].setJumpCatchAll(Cnt - Pos); + break; + } + case OpCode::Delegate: { + if (BlockStack.size() == 0) { + // A Delegate instruction appeared outside a try-block. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + const auto &[BackOp, Pos, CatchList] = BlockStack.back(); + if (BackOp != OpCode::Try) { + // A Delegate instruction appeared outside a try-block. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + if (!CatchList.empty() || Instrs[Pos].getJumpCatchAll() != 0) { + // A Try-Delegate block shouldn't contain Catch or Catch_all. + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + Instrs[Pos].setDelegate(); + Instrs[Pos].setTryBlockJumpEnd(Cnt - Pos); + // Pop the block stack after parsing the delegate instruction + break; + } + case OpCode::End: if (BlockStack.size() > 0) { - uint32_t Pos = BlockStack.back().second; - Instrs[Pos].setJumpEnd(Cnt - Pos); - if (BlockStack.back().first == OpCode::If) { - if (Instrs[Pos].getJumpElse() == 0) { - // If block without else. Set the else jump the same as end jump. - Instrs[Pos].setJumpElse(Cnt - Pos); - } else { - const uint32_t ElsePos = Pos + Instrs[Pos].getJumpElse(); - Instrs[ElsePos].setJumpEnd(Cnt - ElsePos); + const auto &[BackOp, Pos, CatchList] = BlockStack.back(); + if (BackOp == OpCode::Block || BackOp == OpCode::Loop || + BackOp == OpCode::If) { + Instrs[Pos].setJumpEnd(Cnt - Pos); + if (BackOp == OpCode::If) { + if (Instrs[Pos].getJumpElse() == 0) { + // If block without else. Set the else jump the same as end jump. + Instrs[Pos].setJumpElse(Cnt - Pos); + } else { + const uint32_t ElsePos = Pos + Instrs[Pos].getJumpElse(); + Instrs[ElsePos].setJumpEnd(Cnt - ElsePos); + } } + } else if (BackOp == OpCode::Try) { + Instrs[Pos].setTryBlockJumpEnd(Cnt - Pos); + Instrs[Pos].setJumpCatchList(CatchList); } BlockStack.pop_back(); } else { IsReachEnd = true; } + break; + default: + break; } // Create the instruction node and load contents. @@ -206,6 +283,11 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { if (auto Res = loadInstruction(Instrs.back()); !Res) { return Unexpect(Res); } + if (Code == OpCode::Delegate) { + uint32_t Pos = std::get<1>(BlockStack.back()); + Instrs[Pos].setDelegateIdx(Instrs.back().getJump().TargetIndex); + BlockStack.pop_back(); + } if (Code == OpCode::End) { if (IsReachEnd) { Instrs.back().setLast(true); @@ -293,11 +375,13 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { case OpCode::Return: case OpCode::End: case OpCode::Else: + case OpCode::Catch_all: return {}; case OpCode::Block: case OpCode::Loop: - case OpCode::If: { + case OpCode::If: + case OpCode::Try: { auto StartOffset = FMgr.getOffset(); // Read the block return type. if (auto Res = FMgr.readS33()) { @@ -337,6 +421,8 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { case OpCode::Br_if: case OpCode::Br_on_null: case OpCode::Br_on_non_null: + case OpCode::Delegate: + case OpCode::Rethrow: return readU32(Instr.getJump().TargetIndex); case OpCode::Br_table: { @@ -385,6 +471,10 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return {}; } + case OpCode::Catch: + case OpCode::Throw: + return readU32(Instr.getTargetIndex()); + // Reference Instructions. case OpCode::Ref__null: case OpCode::Ref__test_null: diff --git a/lib/loader/ast/module.cpp b/lib/loader/ast/module.cpp index dd26dc1d017a..db9a4e17ac9e 100644 --- a/lib/loader/ast/module.cpp +++ b/lib/loader/ast/module.cpp @@ -23,7 +23,7 @@ Expect Loader::loadModuleInBound(AST::Module &Mod, // Variables to record the loaded section types. HasDataSection = false; - std::bitset<0x0DU> Secs; + std::bitset<0x0EU> Secs; uint64_t Offset = FMgr.getOffset(); @@ -149,6 +149,19 @@ Expect Loader::loadModuleInBound(AST::Module &Mod, HasDataSection = true; Secs.set(NewSectionId); break; + case 0x0D: + // This section is for ExceptionHandling proposal. + if (!Conf.hasProposal(Proposal::ExceptionHandling)) { + return logNeedProposal(ErrCode::Value::MalformedSection, + Proposal::ExceptionHandling, + FMgr.getLastOffset(), ASTNodeAttr::Module); + } + if (auto Res = loadSection(Mod.getTagSection()); !Res) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Module)); + return Unexpect(Res); + } + Secs.set(NewSectionId); + break; default: return logLoadError(ErrCode::Value::MalformedSection, FMgr.getLastOffset(), ASTNodeAttr::Module); @@ -157,6 +170,9 @@ Expect Loader::loadModuleInBound(AST::Module &Mod, Offset = FMgr.getOffset(); } + setTagFunctionType(Mod.getTagSection(), Mod.getImportSection(), + Mod.getTypeSection()); + // Verify the function section and code section are matched. if (Mod.getFunctionSection().getContent().size() != Mod.getCodeSection().getContent().size()) { diff --git a/lib/loader/ast/section.cpp b/lib/loader/ast/section.cpp index 0e42a26d1f52..2afe17dbce7c 100644 --- a/lib/loader/ast/section.cpp +++ b/lib/loader/ast/section.cpp @@ -209,6 +209,13 @@ Expect Loader::loadSection(AST::DataCountSection &Sec) { }); } +Expect Loader::loadSection(AST::TagSection &Sec) { + return loadSectionContent(Sec, [this, &Sec]() { + return loadSectionContentVec( + Sec, [this](AST::TagType &TgType) { return loadType(TgType); }); + }); +} + Expect Loader::loadSection(AST::Component::ComponentSection &Sec) { auto ResPreamble = Loader::loadPreamble(); if (!ResPreamble) { diff --git a/lib/loader/ast/type.cpp b/lib/loader/ast/type.cpp index bea3657a724a..00cfee42e734 100644 --- a/lib/loader/ast/type.cpp +++ b/lib/loader/ast/type.cpp @@ -432,5 +432,28 @@ Expect Loader::loadType(AST::GlobalType &GlobType) { return {}; } +// Load binary to construct Tag node. See "include/loader/loader.h". +Expect Loader::loadType(AST::TagType &TgType) { + if (auto Res = FMgr.readByte()) { + // The preserved byte for future extension possibility for tag + // It supports only 0x00 currently, which is for exception handling. + if (unlikely(*Res != 0x00)) { + return logLoadError(ErrCode::Value::ExpectedZeroByte, + FMgr.getLastOffset(), ASTNodeAttr::Sec_Tag); + } + TgType.setAttribute(*Res); + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Sec_Tag); + } + if (auto Res = FMgr.readU32()) { + TgType.setTypeIdx(*Res); + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Sec_Tag); + } + return {}; +} + } // namespace Loader } // namespace WasmEdge diff --git a/lib/loader/loader.cpp b/lib/loader/loader.cpp index c99d9257f24f..66a740b9c8b4 100644 --- a/lib/loader/loader.cpp +++ b/lib/loader/loader.cpp @@ -215,5 +215,27 @@ Expect> Loader::serializeModule(const AST::Module &Mod) { return Ser.serializeModule(Mod); } +// Helper function to set the function type for tag. +void Loader::setTagFunctionType(AST::TagSection &TagSec, + AST::ImportSection &ImportSec, + AST::TypeSection &TypeSec) { + auto &TypeVec = TypeSec.getContent(); + for (auto &TgType : TagSec.getContent()) { + auto TypeIdx = TgType.getTypeIdx(); + // Invalid type index would be checked during validation + if (TypeIdx < TypeVec.size()) { + TgType.setFuncType(&TypeVec[TypeIdx]); + } + } + for (auto &Desc : ImportSec.getContent()) { + auto &TgType = Desc.getExternalTagType(); + auto TypeIdx = TgType.getTypeIdx(); + // Invalid type index would be checked during validation + if (TypeIdx < TypeVec.size()) { + TgType.setFuncType(&TypeVec[TypeIdx]); + } + } +} + } // namespace Loader } // namespace WasmEdge diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index b66e8e40050a..67a86d97a3dc 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -41,6 +41,7 @@ void FormChecker::reset(bool CleanGlobal) { Datas.clear(); Elems.clear(); Refs.clear(); + Tags.clear(); NumImportFuncs = 0; NumImportGlobals = 0; } @@ -111,6 +112,8 @@ void FormChecker::addLocal(const ValType &V, bool Initialized) { } } +void FormChecker::addTag(const uint32_t TypeIdx) { Tags.push_back(TypeIdx); } + ValType FormChecker::VTypeToAST(const VType &V) { if (!V) { return TypeCode::I32; @@ -199,6 +202,20 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return static_cast(CtrlStack.size()) - UINT32_C(1) - N; }; + // Helper lambda for counting the try and catch. + auto countCtrlStackType = + [this](uint32_t N) -> std::pair { + uint32_t CatchCnt = 0, TryCnt = 0; + for (auto It = CtrlStack.begin() + N; It != CtrlStack.end(); It++) { + if (It->Code == OpCode::Try) + TryCnt++; + if (It->Code == OpCode::Catch || It->Code == OpCode::Catch_all) { + CatchCnt++; + } + } + return {TryCnt, CatchCnt}; + }; + // Helper lambda for checking memory index and perform transformation. auto checkMemAndTrans = [this, &Instr](Span Take, @@ -261,13 +278,17 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { }; // Helper lambda for recording jump data. - auto recordJump = [this, &Instr](AST::Instruction::JumpDescriptor &Jump, - uint32_t Arity, CtrlFrame &Frame) -> void { + auto recordJump = [this, &Instr, &countCtrlStackType]( + AST::Instruction::JumpDescriptor &Jump, uint32_t Arity, + uint32_t D) -> void { const uint32_t Remain = - static_cast(ValStack.size() - Frame.Height); - Jump.StackEraseBegin = Remain + Arity; - Jump.StackEraseEnd = Arity; - Jump.PCOffset = static_cast(Frame.Jump - &Instr); + static_cast(ValStack.size() - CtrlStack[D].Height); + Jump.ValueStackEraseBegin = Remain + Arity; + Jump.ValueStackEraseEnd = Arity; + auto [TryCnt, CatchCnt] = countCtrlStackType(D); + Jump.HandlerStackOffset = TryCnt; + Jump.CaughtStackOffset = CatchCnt; + Jump.PCOffset = static_cast(CtrlStack[D].Jump - &Instr); }; // Helper lambda for unpacking a value type. @@ -315,6 +336,28 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return unreachable(); case OpCode::Nop: return {}; + + case OpCode::Try: + if (Instr.getOpCode() == OpCode::Try && Instr.isDelegate()) { + if (auto D = checkCtrlStackDepth(Instr.getDelegateIdx()); !D) { + return Unexpect(D); + } else { + // Delegate to the label itself, not before the label. + auto [TryCnt, CatchCnt] = countCtrlStackType(*D + 1); + auto &NonConstInstr = const_cast(Instr); + if (*D + 1 < CtrlStack.size()) { + NonConstInstr.setTryBlockVSize( + static_cast(Locals.size() + CtrlStack[*D + 1].Height)); + } else { + NonConstInstr.setTryBlockVSize( + static_cast(Locals.size() + ValStack.size())); + } + // The try block itself may push an additional handler to stack. + NonConstInstr.setTryBlockHOffset(TryCnt); + NonConstInstr.setTryBlockCOffset(CatchCnt); + } + } + [[fallthrough]]; case OpCode::If: case OpCode::Block: case OpCode::Loop: { @@ -332,6 +375,10 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } } + if (Instr.getOpCode() == OpCode::Try) { + const_cast(Instr).setTryBlockParamNum( + static_cast(T1.size())); + } // Pop and check [t1*] if (auto Res = popTypes(T1); !Res) { return Unexpect(Res); @@ -353,20 +400,89 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { case OpCode::Else: if (auto Res = popCtrl()) { - pushCtrl((*Res).StartTypes, (*Res).EndTypes, Res->Jump, - Instr.getOpCode()); + pushCtrl(Res->StartTypes, Res->EndTypes, Res->Jump, Instr.getOpCode()); + } else { + return Unexpect(Res); + } + return {}; + + case OpCode::Catch: + if (CtrlStack.back().Code == OpCode::Try) { + const_cast(Instr).setTryLast(); + } + if (auto Res = popCtrl()) { + auto N = Instr.getTargetIndex(); + if (N >= Tags.size()) { + return logOutOfRange(ErrCode::Value::InvalidTagIdx, + ErrInfo::IndexCategory::Tag, N, + static_cast(Tags.size())); + } + // Validity of the tag type has been checked in tag section + const auto &[T3, T4] = Types[Tags[N]]; + pushCtrl(T3, Res->EndTypes, Res->Jump, Instr.getOpCode()); + } else { + return Unexpect(Res); + } + return {}; + case OpCode::Catch_all: + if (CtrlStack.back().Code == OpCode::Try) { + const_cast(Instr).setTryLast(); + } + if (auto Res = popCtrl()) { + pushCtrl({}, Res->EndTypes, Res->Jump, Instr.getOpCode()); + } else { + return Unexpect(Res); + } + return {}; + case OpCode::Delegate: + if (auto Res = popCtrl()) { + pushTypes(Res->EndTypes); } else { return Unexpect(Res); } return {}; case OpCode::End: + if (auto Code = CtrlStack.back().Code; Code == OpCode::Try) { + const_cast(Instr).setTryLast(); + } else if (Code == OpCode::Catch || Code == OpCode::Catch_all) { + const_cast(Instr).setCatchLast(); + } if (auto Res = popCtrl()) { - pushTypes((*Res).EndTypes); + pushTypes(Res->EndTypes); } else { return Unexpect(Res); } return {}; + case OpCode::Throw: { + auto N = Instr.getTargetIndex(); + if (N >= Tags.size()) { + return logOutOfRange(ErrCode::Value::InvalidTagIdx, + ErrInfo::IndexCategory::Tag, N, + static_cast(Tags.size())); + } + auto &[TTypes, _] = Types[Tags[N]]; + if (auto Res = popTypes(TTypes); !Res) { + return Unexpect(Res); + } + return unreachable(); + } + case OpCode::Rethrow: { + auto LabelIdx = Instr.getJump().TargetIndex; + if (auto D = checkCtrlStackDepth(LabelIdx); !D) { + return Unexpect(D); + } else if (auto LabelCode = CtrlStack[*D].Code; + LabelCode != OpCode::Catch && LabelCode != OpCode::Catch_all) { + spdlog::error(ErrCode::Value::InvalidRethrowLabel); + return Unexpect(ErrCode::Value::InvalidRethrowLabel); + } else { + auto [TryCnt, CatchCnt] = countCtrlStackType(*D); + auto &Jump = const_cast(Instr).getJump(); + Jump.CaughtStackOffset = CatchCnt; + return unreachable(); + } + } + case OpCode::Br: if (auto D = checkCtrlStackDepth(Instr.getJump().TargetIndex); !D) { return Unexpect(D); @@ -377,7 +493,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } recordJump(const_cast(Instr).getJump(), - static_cast(NTypes.size()), CtrlStack[*D]); + static_cast(NTypes.size()), *D); return unreachable(); } case OpCode::Br_if: @@ -393,7 +509,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } recordJump(const_cast(Instr).getJump(), - static_cast(NTypes.size()), CtrlStack[*D]); + static_cast(NTypes.size()), *D); pushTypes(NTypes); return {}; } @@ -434,7 +550,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } } recordJump(LabelTable[LabelIdx], static_cast(NTypes.size()), - CtrlStack[*N]); + *N); pushTypes(TypeBuf); } else { return Unexpect(N); @@ -445,7 +561,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } recordJump(LabelTable[LabelTableSize], - static_cast(NTypes.size()), CtrlStack[*M]); + static_cast(NTypes.size()), *M); return unreachable(); } else { return Unexpect(M); @@ -465,7 +581,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } recordJump(const_cast(Instr).getJump(), - static_cast(NTypes.size()), CtrlStack[*D]); + static_cast(NTypes.size()), *D); pushTypes(NTypes); if ((*ResT).has_value()) { pushType((*ResT)->toNonNullableRef()); @@ -499,7 +615,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } recordJump(const_cast(Instr).getJump(), - static_cast(NTypes.size()), CtrlStack[*D]); + static_cast(NTypes.size()), *D); // Push types [t*]. NTypes.pop_back(); pushTypes(NTypes); @@ -999,7 +1115,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } recordJump(const_cast(Instr).getBrCast().Jump, - static_cast(NTypes.size()), CtrlStack[*D]); + static_cast(NTypes.size()), *D); // For br_on_cast, push types [t* rt1']. // For Br_on_cast_fail, push types [t* rt2]. RTP = Instr.getOpCode() == OpCode::Br_on_cast ? RT1P : RT2; diff --git a/lib/validator/validator.cpp b/lib/validator/validator.cpp index 7985910fc712..43e6fbb5efe1 100644 --- a/lib/validator/validator.cpp +++ b/lib/validator/validator.cpp @@ -81,6 +81,13 @@ Expect Validator::validate(const AST::Module &Mod) { return Unexpect(Res); } + // Validate tag section and register tags into FormChecker. + if (auto Res = validate(Mod.getTagSection()); !Res) { + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Sec_Tag)); + spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Module)); + return Unexpect(Res); + } + // Validate export section. if (auto Res = validate(Mod.getExportSection()); !Res) { spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Sec_Export)); @@ -448,6 +455,20 @@ Expect Validator::validate(const AST::ImportDesc &ImpDesc) { Checker.addMemory(MemType); return {}; } + case ExternalType::Tag: { + const auto &T = ImpDesc.getExternalTagType(); + // Tag type index must exist in context. + auto TagTypeIdx = T.getTypeIdx(); + if (TagTypeIdx >= Checker.getTypes().size()) { + spdlog::error(ErrCode::Value::InvalidTagIdx); + spdlog::error(ErrInfo::InfoForbidIndex( + ErrInfo::IndexCategory::TagType, TagTypeIdx, + static_cast(Checker.getTypes().size()))); + return Unexpect(ErrCode::Value::InvalidTagIdx); + } + Checker.addTag(TagTypeIdx); + return {}; + } case ExternalType::Global: { const auto &GlobType = ImpDesc.getExternalGlobalType(); // Global type must be valid. @@ -495,6 +516,15 @@ Expect Validator::validate(const AST::ExportDesc &ExpDesc) { return Unexpect(ErrCode::Value::InvalidMemoryIdx); } return {}; + case ExternalType::Tag: + if (Id >= Checker.getTags().size()) { + spdlog::error(ErrCode::Value::InvalidTagIdx); + spdlog::error(ErrInfo::InfoForbidIndex( + ErrInfo::IndexCategory::Tag, Id, + static_cast(Checker.getTags().size()))); + return Unexpect(ErrCode::Value::InvalidTagIdx); + } + return {}; case ExternalType::Global: if (Id >= Checker.getGlobals().size()) { spdlog::error(ErrCode::Value::InvalidGlobalIdx); @@ -723,6 +753,30 @@ Expect Validator::validate(const AST::ExportSection &ExportSec) { return {}; } +Expect Validator::validate(const AST::TagSection &TagSec) { + const auto &TagVec = TagSec.getContent(); + const auto &TypeVec = Checker.getTypes(); + + // Check if type id of tag is valid in context. + for (auto &T : TagVec) { + auto TagTypeIdx = T.getTypeIdx(); + if (TagTypeIdx >= TypeVec.size()) { + spdlog::error(ErrCode::Value::InvalidTagIdx); + spdlog::error( + ErrInfo::InfoForbidIndex(ErrInfo::IndexCategory::TagType, TagTypeIdx, + static_cast(TypeVec.size()))); + return Unexpect(ErrCode::Value::InvalidTagIdx); + } + auto &[T1, T2] = TypeVec[TagTypeIdx]; + if (!T2.empty()) { + spdlog::error(ErrCode::Value::InvalidTag); + return Unexpect(ErrCode::Value::InvalidTag); + } + Checker.addTag(TagTypeIdx); + } + return {}; +} + // Validate constant expression. See "include/validator/validator.h". Expect Validator::validateConstExpr(AST::InstrView Instrs, Span Returns) { diff --git a/test/loader/descriptionTest.cpp b/test/loader/descriptionTest.cpp index 981ed19a2dc0..7f6b855f11ee 100644 --- a/test/loader/descriptionTest.cpp +++ b/test/loader/descriptionTest.cpp @@ -179,7 +179,7 @@ TEST(DescriptionTest, LoadExportDesc) { 0x0AU, // Content size = 10 0x01U, // Vector length = 1 0x06U, 0x4CU, 0x6FU, 0x61U, 0x64U, 0x65U, 0x72U, // External name: Loader - 0x04U, 0x00U // Invalid external type + 0x05U, 0x00U // Invalid external type }; EXPECT_FALSE(Ldr.parseModule(prefixedVec(Vec))); diff --git a/test/spec/CMakeLists.txt b/test/spec/CMakeLists.txt index 24ed7d86f068..efad35596ba8 100644 --- a/test/spec/CMakeLists.txt +++ b/test/spec/CMakeLists.txt @@ -76,7 +76,7 @@ function(wasmedge_copy_spec_testsuite proposal) message(STATUS "Copying test suite to ${CMAKE_CURRENT_BINARY_DIR}/testSuites/${proposal} -- done") endfunction() -foreach(PROPOSAL core multi-memory tail-call extended-const threads function-references gc) +foreach(PROPOSAL core multi-memory tail-call extended-const threads function-references gc exception-handling) wasmedge_copy_spec_testsuite(${PROPOSAL}) endforeach() diff --git a/test/spec/spectest.cpp b/test/spec/spectest.cpp index f3a83bc1e55f..60311f6cd14c 100644 --- a/test/spec/spectest.cpp +++ b/test/spec/spectest.cpp @@ -85,6 +85,7 @@ SpecTest::CommandID resolveCommand(std::string_view Name) { {"assert_unlinkable"sv, SpecTest::CommandID::AssertUnlinkable}, {"assert_uninstantiable"sv, SpecTest::CommandID::AssertUninstantiable}, + {"assert_exception"sv, SpecTest::CommandID::AssertException}, }; if (auto Iter = CommandMapping.find(Name); Iter != CommandMapping.end()) { return Iter->second; @@ -259,6 +260,9 @@ static const TestsuiteProposal TestsuiteProposals[] = { {"function-references"sv, {Proposal::FunctionReferences, Proposal::TailCall}}, {"gc"sv, {Proposal::GC}, WasmEdge::SpecTest::TestMode::Interpreter}, + {"exception-handling"sv, + {Proposal::ExceptionHandling, Proposal::TailCall}, + WasmEdge::SpecTest::TestMode::Interpreter}, }; } // namespace @@ -709,6 +713,20 @@ void SpecTest::run(std::string_view Proposal, std::string_view UnitName) { stringContains(Text, WasmEdge::ErrCodeStr[Res.error().getEnum()])); } }; + auto ExceptionInvoke = [&](const simdjson::dom::object &Action, + uint64_t LineNumber) { + const auto ModName = GetModuleName(Action); + const std::string_view Field = Action["field"]; + simdjson::dom::array Args = Action["args"]; + const auto Params = parseValueList(Args); + + if (auto Res = onInvoke(ModName, std::string(Field), Params.first, + Params.second)) { + EXPECT_NE(LineNumber, LineNumber); + } else { + EXPECT_EQ(Res.error(), WasmEdge::ErrCode::Value::UncaughtException); + } + }; // Command processing. Return true for expected result. auto RunCommand = [&](const simdjson::dom::object &Cmd) { @@ -810,6 +828,18 @@ void SpecTest::run(std::string_view Proposal, std::string_view UnitName) { TrapInstantiate(Filename, std::string(Text)); return; } + case CommandID::AssertException: { + const simdjson::dom::object &Action = Cmd["action"]; + const std::string_view ActType = Action["type"]; + const uint64_t LineNumber = Cmd["line"]; + // TODO: Check expected exception type + if (ActType == "invoke"sv) { + ExceptionInvoke(Action, LineNumber); + return; + } + EXPECT_TRUE(false); + return; + } default:; } } diff --git a/test/spec/spectest.h b/test/spec/spectest.h index 9d53ae5cd5c2..53e2c4222e9b 100644 --- a/test/spec/spectest.h +++ b/test/spec/spectest.h @@ -44,6 +44,7 @@ class SpecTest { AssertInvalid, AssertUnlinkable, AssertUninstantiable, + AssertException, }; enum class TestMode : uint8_t { From 85219594e80e930189c9d78701318f9fae8d8026 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Thu, 7 Mar 2024 18:16:33 +0800 Subject: [PATCH 158/218] [Misc] Fix exception-handling proposal with GC proposal. Signed-off-by: YiYing He --- include/ast/type.h | 26 ++++++++++---------- include/executor/executor.h | 5 +--- include/runtime/instance/tag.h | 6 ++--- lib/api/wasmedge.cpp | 5 +++- lib/executor/engine/controlInstr.cpp | 20 ++++------------ lib/executor/helper.cpp | 24 +++++++++---------- lib/executor/instantiate/import.cpp | 32 ++++++++++++++----------- lib/executor/instantiate/tag.cpp | 7 +++--- lib/loader/ast/type.cpp | 16 +++++++------ lib/loader/loader.cpp | 16 +++++++------ lib/validator/formchecker.cpp | 36 +++++++++++++--------------- lib/validator/validator.cpp | 15 ++++++++---- 12 files changed, 101 insertions(+), 107 deletions(-) diff --git a/include/ast/type.h b/include/ast/type.h index aaf76a335178..55e08c266ebc 100644 --- a/include/ast/type.h +++ b/include/ast/type.h @@ -734,30 +734,30 @@ class GlobalType { class TagType { public: TagType() = default; - TagType(const TagType &T, const FunctionType *F) noexcept - : Attribute(T.getAttribute()), TypeIdx(T.getTypeIdx()), Type(F) {} - - /// Getter and setter of Attribute. - uint8_t getAttribute() const noexcept { return Attribute; } - void setAttribute(uint8_t Attr) noexcept { Attribute = Attr; } + TagType(const uint32_t TIdx, const SubType *S) noexcept + : TypeIdx(TIdx), Type(S) {} /// Getter and setter of TypeIdx. uint32_t getTypeIdx() const noexcept { return TypeIdx; } - void setTypeIdx(uint32_t TyIdx) noexcept { TypeIdx = TyIdx; } + void setTypeIdx(uint32_t TIdx) noexcept { TypeIdx = TIdx; } - // Getter and setter of FunctionType. - const FunctionType &getFuncType() const noexcept { return *Type; } - void setFuncType(FunctionType *FuncType) noexcept { Type = FuncType; } + // Getter and setter of Defined Type. + const SubType &getDefType() const noexcept { return *Type; } + void setDefType(const SubType *DefType) noexcept { Type = DefType; } // Getter of the size of value that is associated with the tag. uint32_t getAssocValSize() const noexcept { - return static_cast(Type->getParamTypes().size()); + if (Type && Type->getCompositeType().isFunc()) { + return static_cast( + Type->getCompositeType().getFuncType().getParamTypes().size()); + } else { + return 0; + } } private: - uint8_t Attribute; uint32_t TypeIdx; - const FunctionType *Type; + const SubType *Type; }; } // namespace AST diff --git a/include/executor/executor.h b/include/executor/executor.h index ec8615496eaf..c7f5c1b9107b 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -273,10 +273,7 @@ class Executor { /// Helper function for branching to label. Expect branchToLabel(Runtime::StackManager &StackMgr, - uint32_t ValueStackEraseBegin, - uint32_t ValueStackEraseEnd, - uint32_t HandlerStackOffset, - uint32_t CaughtStackOffset, int32_t PCOffset, + const AST::Instruction::JumpDescriptor &JumpDesc, AST::InstrView::iterator &PC) noexcept; /// Helper function for throwing an exception. diff --git a/include/runtime/instance/tag.h b/include/runtime/instance/tag.h index cf0b63e6c131..6307faffe0f3 100644 --- a/include/runtime/instance/tag.h +++ b/include/runtime/instance/tag.h @@ -22,14 +22,12 @@ namespace Instance { class TagInstance { public: TagInstance() = delete; - TagInstance(const AST::TagType &T, const AST::FunctionType *F) noexcept - : TgType(T, F) {} + TagInstance(const AST::TagType &T, const AST::SubType *F) noexcept + : TgType(T.getTypeIdx(), F) {} /// Getter of tag type. const AST::TagType &getTagType() const noexcept { return TgType; } - uint32_t getAssocValSize() const noexcept { return TgType.getAssocValSize(); } - private: /// \name Data of tag instance. /// @{ diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index fba3a1c51d9b..4c58cf8e484a 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -1321,7 +1321,10 @@ WasmEdge_MemoryTypeDelete(WasmEdge_MemoryTypeContext *Cxt) { WASMEDGE_CAPI_EXPORT const WasmEdge_FunctionTypeContext * WasmEdge_TagTypeGetFunctionType(const WasmEdge_TagTypeContext *Cxt) { if (Cxt) { - return toFuncTypeCxt(&fromTagTypeCxt(Cxt)->getFuncType()); + const auto &CompType = fromTagTypeCxt(Cxt)->getDefType().getCompositeType(); + if (CompType.isFunc()) { + return toFuncTypeCxt(&CompType.getFuncType()); + } } return nullptr; } diff --git a/lib/executor/engine/controlInstr.cpp b/lib/executor/engine/controlInstr.cpp index 282b220bad92..29e9daf7f5eb 100644 --- a/lib/executor/engine/controlInstr.cpp +++ b/lib/executor/engine/controlInstr.cpp @@ -76,10 +76,7 @@ Expect Executor::runRethrowOp(Runtime::StackManager &StackMgr, Expect Executor::runBrOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept { - auto &JumpDesc = Instr.getJump(); - return branchToLabel(StackMgr, JumpDesc.ValueStackEraseBegin, - JumpDesc.ValueStackEraseEnd, JumpDesc.HandlerStackOffset, - JumpDesc.CaughtStackOffset, JumpDesc.PCOffset, PC); + return branchToLabel(StackMgr, Instr.getJump(), PC); } Expect Executor::runBrIfOp(Runtime::StackManager &StackMgr, @@ -121,16 +118,9 @@ Expect Executor::runBrTableOp(Runtime::StackManager &StackMgr, auto LabelTable = Instr.getLabelList(); const auto LabelTableSize = static_cast(LabelTable.size() - 1); if (Value < LabelTableSize) { - auto &JumpDesc = LabelTable[Value]; - return branchToLabel(StackMgr, JumpDesc.ValueStackEraseBegin, - JumpDesc.ValueStackEraseEnd, - JumpDesc.HandlerStackOffset, - JumpDesc.CaughtStackOffset, JumpDesc.PCOffset, PC); + return branchToLabel(StackMgr, LabelTable[Value], PC); } - auto &JumpDesc = LabelTable[LabelTableSize]; - return branchToLabel(StackMgr, JumpDesc.ValueStackEraseBegin, - JumpDesc.ValueStackEraseEnd, JumpDesc.HandlerStackOffset, - JumpDesc.CaughtStackOffset, JumpDesc.PCOffset, PC); + return branchToLabel(StackMgr, LabelTable[LabelTableSize], PC); } Expect Executor::runBrOnCastOp(Runtime::StackManager &StackMgr, @@ -154,9 +144,7 @@ Expect Executor::runBrOnCastOp(Runtime::StackManager &StackMgr, if (AST::TypeMatcher::matchType(ModInst->getTypeList(), Instr.getBrCast().RType2, GotTypeList, VT) != IsReverse) { - return branchToLabel(StackMgr, Instr.getBrCast().Jump.StackEraseBegin, - Instr.getBrCast().Jump.StackEraseEnd, - Instr.getBrCast().Jump.PCOffset, PC); + return branchToLabel(StackMgr, Instr.getBrCast().Jump, PC); } return {}; } diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 4214ff24de5b..f2aae8a47df6 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -194,24 +194,22 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, } } -Expect Executor::branchToLabel(Runtime::StackManager &StackMgr, - uint32_t ValueStackEraseBegin, - uint32_t ValueStackEraseEnd, - uint32_t HandlerStackOffset, - uint32_t CaughtStackOffset, - int32_t PCOffset, - AST::InstrView::iterator &PC) noexcept { - // Check stop token +Expect +Executor::branchToLabel(Runtime::StackManager &StackMgr, + const AST::Instruction::JumpDescriptor &JumpDesc, + AST::InstrView::iterator &PC) noexcept { + // Check the stop token. if (unlikely(StopToken.exchange(0, std::memory_order_relaxed))) { spdlog::error(ErrCode::Value::Interrupted); return Unexpect(ErrCode::Value::Interrupted); } - StackMgr.eraseValueStack(ValueStackEraseBegin, ValueStackEraseEnd); - StackMgr.eraseHandlerStack(HandlerStackOffset); - StackMgr.eraseCaughtStack(CaughtStackOffset); + StackMgr.eraseValueStack(JumpDesc.ValueStackEraseBegin, + JumpDesc.ValueStackEraseEnd); + StackMgr.eraseHandlerStack(JumpDesc.HandlerStackOffset); + StackMgr.eraseCaughtStack(JumpDesc.CaughtStackOffset); // PC need to -1 here because the PC will increase in the next iteration. - PC += (PCOffset - 1); + PC += (JumpDesc.PCOffset - 1); return {}; } @@ -219,7 +217,7 @@ Expect Executor::throwException(Runtime::StackManager &StackMgr, Runtime::Instance::TagInstance *TagInst, AST::InstrView::iterator &PC) noexcept { while (!StackMgr.isHandlerStackEmpty()) { - auto AssocValSize = TagInst->getAssocValSize(); + auto AssocValSize = TagInst->getTagType().getAssocValSize(); // The value that associated with the exception should remain on the stack auto ExceptionHandler = StackMgr.popToTopHandler(AssocValSize); if (!ExceptionHandler.CatchCaluse.empty()) { diff --git a/lib/executor/instantiate/import.cpp b/lib/executor/instantiate/import.cpp index c475a9de381a..1e87c190ce30 100644 --- a/lib/executor/instantiate/import.cpp +++ b/lib/executor/instantiate/import.cpp @@ -152,13 +152,13 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, uint32_t TypeIdx = ImpDesc.getExternalFuncTypeIdx(); // Import matching. auto *ImpInst = ImpModInst->findFuncExports(ExtName); - const auto &ExpDefType = **ModInst.getType(TypeIdx); // External function type should match the import function type in // description. - if (!AST::TypeMatcher::matchType( - ModInst.getTypeList(), *ExpDefType.getTypeIndex(), - ImpModInst->getTypeList(), ImpInst->getTypeIndex())) { + if (!AST::TypeMatcher::matchType(ModInst.getTypeList(), TypeIdx, + ImpModInst->getTypeList(), + ImpInst->getTypeIndex())) { + const auto &ExpDefType = **ModInst.getType(TypeIdx); bool IsMatchV2 = false; const auto &ExpFuncType = ExpDefType.getCompositeType().getFuncType(); const auto &ImpFuncType = ImpInst->getFuncType(); @@ -254,18 +254,22 @@ Expect Executor::instantiate(Runtime::StoreManager &StoreMgr, } case ExternalType::Tag: { // Get tag type. External type checked in validation. - const auto &T = ImpDesc.getExternalTagType(); + const auto &TagType = ImpDesc.getExternalTagType(); // Import matching. - auto *TargetInst = TargetModInst->findTagExports(ExtName); - const auto &TargetType = TargetInst->getTagType().getFuncType(); - const auto *TType = *ModInst.getFuncType(T.getTypeIdx()); - if (TargetType != *TType) { - return logMatchError(ModName, ExtName, ExtType, TType->getParamTypes(), - TType->getReturnTypes(), - TargetType.getParamTypes(), - TargetType.getReturnTypes()); + auto *ImpInst = ImpModInst->findTagExports(ExtName); + if (!AST::TypeMatcher::matchType( + ModInst.getTypeList(), TagType.getTypeIdx(), + ImpModInst->getTypeList(), ImpInst->getTagType().getTypeIdx())) { + const auto &ExpFuncType = + TagType.getDefType().getCompositeType().getFuncType(); + const auto &ImpFuncType = + ImpInst->getTagType().getDefType().getCompositeType().getFuncType(); + return logMatchError( + ModName, ExtName, ExtType, ExpFuncType.getParamTypes(), + ExpFuncType.getReturnTypes(), ImpFuncType.getParamTypes(), + ImpFuncType.getReturnTypes()); } - ModInst.importTag(TargetInst); + ModInst.importTag(ImpInst); break; } case ExternalType::Global: { diff --git a/lib/executor/instantiate/tag.cpp b/lib/executor/instantiate/tag.cpp index 4d07364ad0a3..008b9eb24f37 100644 --- a/lib/executor/instantiate/tag.cpp +++ b/lib/executor/instantiate/tag.cpp @@ -9,12 +9,11 @@ namespace Executor { // Instantiate tag instance. See "include/executor/executor.h". Expect Executor::instantiate(Runtime::Instance::ModuleInstance &ModInst, const AST::TagSection &TagSec) { - - // Iterate through tags from tag section to instantiate + // Iterate through the tags to instantiate the tag instances. for (const auto &TgType : TagSec.getContent()) { // Add Tag with corresponding Type. - auto FuncTypePtr = *ModInst.getFuncType(TgType.getTypeIdx()); - ModInst.addTag(TgType, FuncTypePtr); + auto SubTypePtr = *ModInst.getType(TgType.getTypeIdx()); + ModInst.addTag(TgType, SubTypePtr); } return {}; } diff --git a/lib/loader/ast/type.cpp b/lib/loader/ast/type.cpp index 00cfee42e734..343afc9ff633 100644 --- a/lib/loader/ast/type.cpp +++ b/lib/loader/ast/type.cpp @@ -438,19 +438,21 @@ Expect Loader::loadType(AST::TagType &TgType) { // The preserved byte for future extension possibility for tag // It supports only 0x00 currently, which is for exception handling. if (unlikely(*Res != 0x00)) { - return logLoadError(ErrCode::Value::ExpectedZeroByte, - FMgr.getLastOffset(), ASTNodeAttr::Sec_Tag); + spdlog::error(ErrCode::Value::ExpectedZeroByte); + spdlog::error(ErrInfo::InfoLoading(FMgr.getLastOffset())); + return Unexpect(ErrCode::Value::ExpectedZeroByte); } - TgType.setAttribute(*Res); } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Sec_Tag); + spdlog::error(Res.error()); + spdlog::error(ErrInfo::InfoLoading(FMgr.getLastOffset())); + return Unexpect(Res); } if (auto Res = FMgr.readU32()) { TgType.setTypeIdx(*Res); } else { - return logLoadError(Res.error(), FMgr.getLastOffset(), - ASTNodeAttr::Sec_Tag); + spdlog::error(Res.error()); + spdlog::error(ErrInfo::InfoLoading(FMgr.getLastOffset())); + return Unexpect(Res); } return {}; } diff --git a/lib/loader/loader.cpp b/lib/loader/loader.cpp index 66a740b9c8b4..508f7f37f2ad 100644 --- a/lib/loader/loader.cpp +++ b/lib/loader/loader.cpp @@ -222,17 +222,19 @@ void Loader::setTagFunctionType(AST::TagSection &TagSec, auto &TypeVec = TypeSec.getContent(); for (auto &TgType : TagSec.getContent()) { auto TypeIdx = TgType.getTypeIdx(); - // Invalid type index would be checked during validation + // Invalid type index would be checked during validation. if (TypeIdx < TypeVec.size()) { - TgType.setFuncType(&TypeVec[TypeIdx]); + TgType.setDefType(&TypeVec[TypeIdx]); } } for (auto &Desc : ImportSec.getContent()) { - auto &TgType = Desc.getExternalTagType(); - auto TypeIdx = TgType.getTypeIdx(); - // Invalid type index would be checked during validation - if (TypeIdx < TypeVec.size()) { - TgType.setFuncType(&TypeVec[TypeIdx]); + if (Desc.getExternalType() == ExternalType::Tag) { + auto &TgType = Desc.getExternalTagType(); + auto TypeIdx = TgType.getTypeIdx(); + // Invalid type index would be checked during validation. + if (TypeIdx < TypeVec.size()) { + TgType.setDefType(&TypeVec[TypeIdx]); + } } } } diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index 67a86d97a3dc..5bec1d3f2d2a 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -411,15 +411,13 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { const_cast(Instr).setTryLast(); } if (auto Res = popCtrl()) { - auto N = Instr.getTargetIndex(); - if (N >= Tags.size()) { - return logOutOfRange(ErrCode::Value::InvalidTagIdx, - ErrInfo::IndexCategory::Tag, N, - static_cast(Tags.size())); + if (auto CompType = + checkDefinedType(Instr.getTargetIndex(), TypeCode::Func)) { + pushCtrl((*CompType)->getFuncType().getParamTypes(), Res->EndTypes, + Res->Jump, Instr.getOpCode()); + } else { + return Unexpect(CompType); } - // Validity of the tag type has been checked in tag section - const auto &[T3, T4] = Types[Tags[N]]; - pushCtrl(T3, Res->EndTypes, Res->Jump, Instr.getOpCode()); } else { return Unexpect(Res); } @@ -454,19 +452,17 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } return {}; - case OpCode::Throw: { - auto N = Instr.getTargetIndex(); - if (N >= Tags.size()) { - return logOutOfRange(ErrCode::Value::InvalidTagIdx, - ErrInfo::IndexCategory::Tag, N, - static_cast(Tags.size())); - } - auto &[TTypes, _] = Types[Tags[N]]; - if (auto Res = popTypes(TTypes); !Res) { - return Unexpect(Res); + case OpCode::Throw: + if (auto CompType = + checkDefinedType(Instr.getTargetIndex(), TypeCode::Func)) { + const auto &FType = (*CompType)->getFuncType(); + if (auto Res = popTypes(FType.getParamTypes()); !Res) { + return Unexpect(Res); + } + return unreachable(); + } else { + return Unexpect(CompType); } - return unreachable(); - } case OpCode::Rethrow: { auto LabelIdx = Instr.getJump().TargetIndex; if (auto D = checkCtrlStackDepth(LabelIdx); !D) { diff --git a/lib/validator/validator.cpp b/lib/validator/validator.cpp index 43e6fbb5efe1..0f8a0a80dc6a 100644 --- a/lib/validator/validator.cpp +++ b/lib/validator/validator.cpp @@ -753,13 +753,14 @@ Expect Validator::validate(const AST::ExportSection &ExportSec) { return {}; } +// Validate Tag section. See "include/validator/validator.h". Expect Validator::validate(const AST::TagSection &TagSec) { const auto &TagVec = TagSec.getContent(); const auto &TypeVec = Checker.getTypes(); // Check if type id of tag is valid in context. - for (auto &T : TagVec) { - auto TagTypeIdx = T.getTypeIdx(); + for (auto &TagType : TagVec) { + auto TagTypeIdx = TagType.getTypeIdx(); if (TagTypeIdx >= TypeVec.size()) { spdlog::error(ErrCode::Value::InvalidTagIdx); spdlog::error( @@ -767,8 +768,14 @@ Expect Validator::validate(const AST::TagSection &TagSec) { static_cast(TypeVec.size()))); return Unexpect(ErrCode::Value::InvalidTagIdx); } - auto &[T1, T2] = TypeVec[TagTypeIdx]; - if (!T2.empty()) { + auto &CompType = TypeVec[TagTypeIdx]->getCompositeType(); + if (!CompType.isFunc()) { + spdlog::error(ErrCode::Value::InvalidTagIdx); + spdlog::error(" Defined type index {} is not a function type.", + TagTypeIdx); + return Unexpect(ErrCode::Value::InvalidTagIdx); + } + if (!CompType.getFuncType().getReturnTypes().empty()) { spdlog::error(ErrCode::Value::InvalidTag); return Unexpect(ErrCode::Value::InvalidTag); } From a0176b018ec524d754215ae08bfb937b5067a191 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 20 Mar 2024 09:31:21 +0800 Subject: [PATCH 159/218] [Misc] Update exception-handling proposal to the newest spec. Signed-off-by: YiYing He --- include/ast/instruction.h | 207 +++++++-------------- include/common/configure.h | 4 +- include/common/enum.inc | 29 +-- include/common/types.h | 6 +- include/executor/executor.h | 12 +- include/runtime/stackmgr.h | 144 ++++----------- lib/executor/engine/controlInstr.cpp | 53 +++--- lib/executor/engine/engine.cpp | 19 +- lib/executor/helper.cpp | 39 ++-- lib/loader/ast/instruction.cpp | 222 ++++++++++------------- lib/loader/ast/type.cpp | 14 ++ lib/validator/formchecker.cpp | 170 ++++++++--------- lib/validator/validator.cpp | 4 +- test/loader/serializeInstructionTest.cpp | 20 +- test/spec/spectest.cpp | 6 + 15 files changed, 378 insertions(+), 571 deletions(-) diff --git a/include/ast/instruction.h b/include/ast/instruction.h index eae13faaa8b1..09f84443eaac 100644 --- a/include/ast/instruction.h +++ b/include/ast/instruction.h @@ -31,13 +31,25 @@ class Instruction { uint32_t ValueStackEraseBegin; uint32_t ValueStackEraseEnd; uint32_t HandlerStackOffset; - uint32_t CaughtStackOffset; int32_t PCOffset; }; struct BrCastDescriptor { struct JumpDescriptor Jump; ValType RType1, RType2; }; + struct CatchDescriptor { + bool IsAll : 1; + bool IsRef : 1; + uint32_t TagIndex; + uint32_t LabelIndex; + struct JumpDescriptor Jump; + }; + struct TryDescriptor { + BlockType ResType; + uint32_t BlockParamNum; + uint32_t JumpEnd; + std::vector Catch; + }; public: /// Constructor assigns the OpCode and the Offset. @@ -50,23 +62,20 @@ class Instruction { Data.Num.Low = static_cast(0); Data.Num.High = static_cast(0); #endif - // Initializing JumpCatchAll to check whether it is set during loading phase - Data.TryBlock.JumpCatchAll = 0; - + Flags.IsAllocJump = false; Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; Flags.IsAllocBrCast = false; - Flags.IsAllocJumpCatchList = false; - Flags.IsTryLast = false; - Flags.IsCatchLast = false; - Flags.IsDelegate = false; + Flags.IsAllocTryCatch = false; } /// Copy constructor. Instruction(const Instruction &Instr) noexcept : Data(Instr.Data), Offset(Instr.Offset), Code(Instr.Code), Flags(Instr.Flags) { - if (Flags.IsAllocLabelList) { + if (Flags.IsAllocJump) { + Data.Jump = new JumpDescriptor(*Instr.Data.Jump); + } else if (Flags.IsAllocLabelList) { Data.BrTable.LabelList = new JumpDescriptor[Data.BrTable.LabelListSize]; std::copy_n(Instr.Data.BrTable.LabelList, Data.BrTable.LabelListSize, Data.BrTable.LabelList); @@ -76,11 +85,8 @@ class Instruction { Data.SelectT.ValTypeList); } else if (Flags.IsAllocBrCast) { Data.BrCast = new BrCastDescriptor(*Instr.Data.BrCast); - } else if (Flags.IsAllocJumpCatchList) { - Data.TryBlock.JumpCatchList = - new uint32_t[Data.TryBlock.JumpCatchListSize]; - std::copy_n(Instr.Data.TryBlock.JumpCatchList, - Data.TryBlock.JumpCatchListSize, Data.TryBlock.JumpCatchList); + } else if (Flags.IsAllocTryCatch) { + Data.TryCatch = new TryDescriptor(*Instr.Data.TryCatch); } } @@ -88,10 +94,11 @@ class Instruction { Instruction(Instruction &&Instr) noexcept : Data(Instr.Data), Offset(Instr.Offset), Code(Instr.Code), Flags(Instr.Flags) { + Instr.Flags.IsAllocJump = false; Instr.Flags.IsAllocLabelList = false; Instr.Flags.IsAllocValTypeList = false; Instr.Flags.IsAllocBrCast = false; - Instr.Flags.IsAllocJumpCatchList = false; + Instr.Flags.IsAllocTryCatch = false; } /// Destructor. @@ -113,21 +120,8 @@ class Instruction { uint32_t getOffset() const noexcept { return Offset; } /// Getter and setter of block type. - const BlockType &getBlockType() const noexcept { - return Code == OpCode::Try ? Data.TryBlock.ResType : Data.Blocks.ResType; - } - void setBlockType(const ValType &VType) noexcept { - Code == OpCode::Try ? Data.TryBlock.ResType.setData(VType) - : Data.Blocks.ResType.setData(VType); - } - void setBlockType(uint32_t Idx) noexcept { - Code == OpCode::Try ? Data.TryBlock.ResType.setData(Idx) - : Data.Blocks.ResType.setData(Idx); - } - void setEmptyBlockType() noexcept { - Code == OpCode::Try ? Data.TryBlock.ResType.setEmpty() - : Data.Blocks.ResType.setEmpty(); - } + const BlockType &getBlockType() const noexcept { return Data.Blocks.ResType; } + BlockType &getBlockType() noexcept { return Data.Blocks.ResType; } /// Getter and setter of jump count to End instruction. uint32_t getJumpEnd() const noexcept { return Data.Blocks.JumpEnd; } @@ -161,13 +155,27 @@ class Instruction { Flags.IsAllocLabelList ? Data.BrTable.LabelListSize : 0); } - /// Getter and setter of IsLast for End instruction. - bool isLast() const noexcept { return Data.IsLast; } - void setLast(bool Last = true) noexcept { Data.IsLast = Last; } + /// Getter and setter of expression end for End instruction. + bool isExprLast() const noexcept { return Data.EndFlags.IsExprLast; } + void setExprLast(bool Last = true) noexcept { + Data.EndFlags.IsExprLast = Last; + } + + /// Getter and setter of try block end for End instruction. + bool isTryBlockLast() const noexcept { return Data.EndFlags.IsTryBlockLast; } + void setTryBlockLast(bool Last = true) noexcept { + Data.EndFlags.IsTryBlockLast = Last; + } /// Getter and setter of Jump for Br* instruction. - const JumpDescriptor &getJump() const noexcept { return Data.Jump; } - JumpDescriptor &getJump() noexcept { return Data.Jump; } + void setJump(uint32_t LabelIdx) { + reset(); + Data.Jump = new JumpDescriptor(); + Flags.IsAllocJump = true; + Data.Jump->TargetIndex = LabelIdx; + } + const JumpDescriptor &getJump() const noexcept { return *Data.Jump; } + JumpDescriptor &getJump() noexcept { return *Data.Jump; } /// Getter and setter of selecting value types list. void setValTypeListSize(uint32_t Size) { @@ -211,74 +219,6 @@ class Instruction { uint8_t getMemoryLane() const noexcept { return Data.Memories.MemLane; } uint8_t &getMemoryLane() noexcept { return Data.Memories.MemLane; } - /// Getter and setter of jump catch list. - void setJumpCatchList(const std::vector &CatchList) { - reset(); - if (!CatchList.empty()) { - Data.TryBlock.JumpCatchListSize = static_cast(CatchList.size()); - Data.TryBlock.JumpCatchList = new uint32_t[CatchList.size()]; - Flags.IsAllocJumpCatchList = true; - std::copy_n(CatchList.begin(), CatchList.size(), - Data.TryBlock.JumpCatchList); - } - } - Span getJumpCatchList() const noexcept { - return Span( - Data.TryBlock.JumpCatchList, - Flags.IsAllocJumpCatchList ? Data.TryBlock.JumpCatchListSize : 0); - } - Span getJumpCatchList() noexcept { - return Span( - Data.TryBlock.JumpCatchList, - Flags.IsAllocJumpCatchList ? Data.TryBlock.JumpCatchListSize : 0); - } - - /// Getter and setter of jump count to catch_all instruction. - uint32_t getJumpCatchAll() const noexcept { - return Data.TryBlock.JumpCatchAll; - } - void setJumpCatchAll(const uint32_t Cnt) noexcept { - Data.TryBlock.JumpCatchAll = Cnt; - } - - /// Getter and setter of jump count to the end of try block. - uint32_t getTryBlockJumpEnd() const noexcept { return Data.TryBlock.JumpEnd; } - void setTryBlockJumpEnd(const uint32_t Cnt) noexcept { - Data.TryBlock.JumpEnd = Cnt; - } - - /// Getter and setter of number of block type parameter. - uint32_t getTryBlockParamNum() const noexcept { - return Data.TryBlock.BlockParamNum; - } - void setTryBlockParamNum(const uint32_t Num) noexcept { - Data.TryBlock.BlockParamNum = Num; - } - - /// Getter and setter of jump count to delegate instruction. - uint32_t getDelegateIdx() const noexcept { return Data.TryBlock.DelegateIdx; } - void setDelegateIdx(const uint32_t Cnt) noexcept { - Data.TryBlock.DelegateIdx = Cnt; - } - - /// Getter and setter of VSize - uint32_t getTryBlockVSize() const noexcept { return Data.TryBlock.VSize; } - void setTryBlockVSize(const uint32_t Num) noexcept { - Data.TryBlock.VSize = Num; - } - - /// Getter and setter of HOffset - uint32_t getTryBlockHOffset() const noexcept { return Data.TryBlock.HOffset; } - void setTryBlockHOffset(const uint32_t Num) noexcept { - Data.TryBlock.HOffset = Num; - } - - /// Getter and setter of COffset - uint32_t getTryBlockCOffset() const noexcept { return Data.TryBlock.COffset; } - void setTryBlockCOffset(const uint32_t Num) noexcept { - Data.TryBlock.COffset = Num; - } - /// Getter and setter of the constant value. ValVariant getNum() const noexcept { #if defined(__x86_64__) || defined(__aarch64__) || \ @@ -308,22 +248,21 @@ class Instruction { const BrCastDescriptor &getBrCast() const noexcept { return *Data.BrCast; } BrCastDescriptor &getBrCast() noexcept { return *Data.BrCast; } - /// Getter and setter of IsTryLast for End instruction. - bool isTryLast() const noexcept { return Flags.IsTryLast; } - void setTryLast(bool Last = true) noexcept { Flags.IsTryLast = Last; } - - /// Getter and setter of IsCatchLast for End instruction. - bool isCatchLast() const noexcept { return Flags.IsCatchLast; } - void setCatchLast(bool Last = true) noexcept { Flags.IsCatchLast = Last; } - - /// Getter and setter of IsDelegate for Try instruction. - bool isDelegate() const noexcept { return Flags.IsDelegate; } - void setDelegate(bool Last = true) noexcept { Flags.IsDelegate = Last; } + /// Getter and setter of try block info for try_table instruction. + void setTryCatch() { + reset(); + Data.TryCatch = new TryDescriptor(); + Flags.IsAllocTryCatch = true; + } + const TryDescriptor &getTryCatch() const noexcept { return *Data.TryCatch; } + TryDescriptor &getTryCatch() noexcept { return *Data.TryCatch; } private: /// Release allocated resources. void reset() noexcept { - if (Flags.IsAllocLabelList) { + if (Flags.IsAllocJump) { + delete Data.Jump; + } else if (Flags.IsAllocLabelList) { Data.BrTable.LabelListSize = 0; delete[] Data.BrTable.LabelList; } else if (Flags.IsAllocValTypeList) { @@ -331,14 +270,14 @@ class Instruction { delete[] Data.SelectT.ValTypeList; } else if (Flags.IsAllocBrCast) { delete Data.BrCast; - } else if (Flags.IsAllocJumpCatchList) { - Data.TryBlock.JumpCatchListSize = 0; - delete[] Data.TryBlock.JumpCatchList; + } else if (Flags.IsAllocTryCatch) { + delete Data.TryCatch; } + Flags.IsAllocJump = false; Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; Flags.IsAllocBrCast = false; - Flags.IsAllocJumpCatchList = false; + Flags.IsAllocTryCatch = false; } /// Swap function. @@ -365,7 +304,7 @@ class Instruction { uint32_t StackOffset; } Indices; // Type 3: Jump. - JumpDescriptor Jump; + JumpDescriptor *Jump; // Type 4: LabelList. struct { uint32_t LabelListSize; @@ -395,34 +334,24 @@ class Instruction { uint64_t High; } Num; #endif - // Type 9: IsLast. - bool IsLast; + // Type 9: End flags. + struct { + bool IsExprLast : 1; + bool IsTryBlockLast : 1; + } EndFlags; // Type 10: TypeCastBranch. BrCastDescriptor *BrCast; - // Type 11: Try Block - struct { - uint32_t JumpCatchListSize; - uint32_t *JumpCatchList; - uint32_t JumpCatchAll; - uint32_t JumpEnd; - uint32_t BlockParamNum; - uint32_t DelegateIdx; - uint32_t VSize; - uint32_t HOffset; - uint32_t COffset; - BlockType ResType; - } TryBlock; + // Type 11: Try Block. + TryDescriptor *TryCatch; } Data; uint32_t Offset = 0; OpCode Code = OpCode::End; struct { + bool IsAllocJump : 1; bool IsAllocLabelList : 1; bool IsAllocValTypeList : 1; bool IsAllocBrCast : 1; - bool IsAllocJumpCatchList : 1; - bool IsTryLast : 1; - bool IsCatchLast : 1; - bool IsDelegate : 1; + bool IsAllocTryCatch : 1; } Flags; /// @} }; diff --git a/include/common/configure.h b/include/common/configure.h index 31f1d25b7f2d..c3e33508f0c2 100644 --- a/include/common/configure.h +++ b/include/common/configure.h @@ -357,8 +357,8 @@ class Configure { if (!hasProposal(Proposal::GC)) { return Proposal::GC; } - } else if ((Code >= OpCode::Try && Code <= OpCode::Rethrow) || - Code == OpCode::Delegate || Code == OpCode::Catch_all) { + } else if (Code == OpCode::Throw || Code == OpCode::Throw_ref || + Code == OpCode::Try_table) { // These instructions are for ExceptionHandling proposal. if (!hasProposal(Proposal::ExceptionHandling)) { return Proposal::ExceptionHandling; diff --git a/include/common/enum.inc b/include/common/enum.inc index c1be62bb5c3c..5f6ab310e414 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -101,11 +101,11 @@ O(Block, "block", 0x02) O(Loop, "loop", 0x03) O(If, "if", 0x04) O(Else, "else", 0x05) -O(Try, "try", 0x06) -O(Catch, "catch", 0x07) +// 0x06: Reserved +// 0x07: Reserved O(Throw, "throw", 0x08) -O(Rethrow, "rethrow", 0x09) -// 0x0A: Reserved +// 0x09: Reserved +O(Throw_ref, "throw_ref", 0x0A) O(End, "end", 0x0B) O(Br, "br", 0x0C) O(Br_if, "br_if", 0x0D) @@ -119,14 +119,18 @@ O(Call_ref, "call_ref", 0x14) O(Return_call_ref, "return_call_ref", 0x15) // 0x16: Reserved // 0x17: Reserved -O(Delegate, "delegate", 0x18) -O(Catch_all, "catch_all", 0x19) +// 0x18: Reserved +// 0x19: Reserved // Parametric Instructions O(Drop, "drop", 0x1A) O(Select, "select", 0x1B) O(Select_t, "select", 0x1C) -// 0x1D ~ 0x1F: Reserved +// 0x1D: Reserved +// 0x1E: Reserved + +// Control instructions (part 2) +O(Try_table, "try_table", 0x1F) // Variable Instructions O(Local__get, "local.get", 0x20) @@ -928,9 +932,7 @@ E(ArrayTypesNumtypeRequired, 0x0223, "array type is not numeric or vector") // Sub type matching or validation failed E(InvalidSubType, 0x0224, "sub type") // Invalid Tag type -E(InvalidTag, 0x0225, "non-empty tag result type") -// Invalid rethrow label -E(InvalidRethrowLabel, 0x0226, "invalid rethrow label") +E(InvalidTagResultType, 0x0225, "non-empty tag result type") // @} // Instantiation phase @@ -995,10 +997,12 @@ E(AccessNullStruct, 0x0414, "null structure reference") E(AccessNullArray, 0x0415, "null array reference") // Access to null i31 reference E(AccessNullI31, 0x0416, "null i31 reference") +// Access to null exception reference +E(AccessNullException, 0x0417, "null exception reference") // Fail to cast reference -E(CastFailed, 0x0417, "cast failure") +E(CastFailed, 0x0418, "cast failure") // Uncaught Exception -E(UncaughtException, 0x0418, "uncaught exception") +E(UncaughtException, 0x0419, "uncaught exception") // @} // Component model phase @@ -1117,6 +1121,7 @@ T(EqRef, 0x6D, "eq") // -0x13 for heap type T(I31Ref, 0x6C, "i31") // -0x14 for heap type T(StructRef, 0x6B, "struct") // -0x15 for heap type T(ArrayRef, 0x6A, "array") // -0x16 for heap type +T(ExnRef, 0x69, "exn") // -0x17 for reference type T(Ref, 0x64, "ref") // -0x1C for reference type T(RefNull, 0x63, "ref_null") // -0x1D for reference type T(Func, 0x60, "func") // -0x20 for composite type diff --git a/include/common/types.h b/include/common/types.h index 8376a4bd0ec2..e0614486e83f 100644 --- a/include/common/types.h +++ b/include/common/types.h @@ -72,8 +72,10 @@ using floatx4_t = SIMDArray; // | | (vectype) | (func-ref proposal) | // | 1st: | 0x78, 0x77, | 0x73, 0x72, 0x71, | // | Externalize | (packedtype) | 0x6E, 0x6D, 0x6C, | -// | | 0x64, 0x63 | 0x6B, 0x6A | +// | | 0x64, 0x63 | 0x6B, 0x6A, | // | | (reftype) | (GC proposal) | +// | | | 0x69 | +// | | | (Exception handling proposal) // ----------------------------------------------------------------------------- // In order to compress the various value type definitions into uint64_t length, // WasmEdge implements the ValType class for extending the value types. @@ -125,6 +127,7 @@ class ValType { case TypeCode::I31Ref: case TypeCode::StructRef: case TypeCode::ArrayRef: + case TypeCode::ExnRef: // Abstract heap type Inner.Data.Code = TypeCode::RefNull; Inner.Data.HTCode = C; @@ -237,6 +240,7 @@ class ValType { case TypeCode::I31Ref: case TypeCode::StructRef: case TypeCode::ArrayRef: + case TypeCode::ExnRef: return true; default: return false; diff --git a/include/executor/executor.h b/include/executor/executor.h index c7f5c1b9107b..c9e5385ed3e3 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -330,15 +330,12 @@ class Executor { Expect runIfElseOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; - Expect runTryOp(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept; Expect runThrowOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; - Expect runRethrowOp(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept; + Expect runThrowRefOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; Expect runBrOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept; @@ -372,6 +369,9 @@ class Executor { const AST::Instruction &Instr, AST::InstrView::iterator &PC, bool IsTailCall = false) noexcept; + Expect runTryTableOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept; /// ======= Variable instructions ======= Expect runLocalGetOp(Runtime::StackManager &StackMgr, uint32_t StackOffset) const noexcept; diff --git a/include/runtime/stackmgr.h b/include/runtime/stackmgr.h index 6fccdbf92514..c046085cde50 100644 --- a/include/runtime/stackmgr.h +++ b/include/runtime/stackmgr.h @@ -28,40 +28,24 @@ class StackManager { struct Frame { Frame() = delete; Frame(const Instance::ModuleInstance *Mod, AST::InstrView::iterator FromIt, - uint32_t L, uint32_t A, uint32_t V, uint32_t H, uint32_t C) noexcept - : Module(Mod), From(FromIt), Locals(L), Arity(A), VPos(V), HPos(H), - CPos(C) {} + uint32_t L, uint32_t A, uint32_t V, uint32_t H) noexcept + : Module(Mod), From(FromIt), Locals(L), Arity(A), VPos(V), HPos(H) {} const Instance::ModuleInstance *Module; AST::InstrView::iterator From; uint32_t Locals; uint32_t Arity; uint32_t VPos; uint32_t HPos; - uint32_t CPos; }; struct Handler { - Handler(AST::InstrView::iterator E, uint32_t V, uint32_t F, uint32_t H, - uint32_t C) - : CatchCaluse(), EndIt(E), VPos(V), FPos(F), HPos(H), CPos(C) {} - // nullptr stands for catch all clause - std::vector< - std::pair> - CatchCaluse; - AST::InstrView::iterator EndIt; + Handler(AST::InstrView::iterator TryIt, uint32_t V, uint32_t F, + Span C) + : Try(TryIt), VPos(V), FPos(F), CatchClause(C) {} + AST::InstrView::iterator Try; uint32_t VPos; uint32_t FPos; - uint32_t HPos; - uint32_t CPos; - }; - - struct Exception { - Exception(Runtime::Instance::TagInstance *T, Span &V, - AST::InstrView::iterator E) - : TagInst(T), Val(V.begin(), V.end()), EndIt(E) {} - Runtime::Instance::TagInstance *TagInst; - std::vector Val; - AST::InstrView::iterator EndIt; + Span CatchClause; }; /// Stack manager provides the stack control for Wasm execution with VALIDATED @@ -70,6 +54,7 @@ class StackManager { StackManager() noexcept { ValueStack.reserve(2048U); FrameStack.reserve(16U); + HandlerStack.reserve(16U); } ~StackManager() = default; @@ -123,8 +108,7 @@ class StackManager { if (likely(!IsTailCall)) { FrameStack.emplace_back(Module, From, LocalNum, Arity, static_cast(ValueStack.size()), - static_cast(HandlerStack.size()), - static_cast(CaughtStack.size())); + static_cast(HandlerStack.size())); } else { assuming(!FrameStack.empty()); assuming(FrameStack.back().VPos >= FrameStack.back().Locals); @@ -135,12 +119,11 @@ class StackManager { ValueStack.end() - LocalNum); HandlerStack.erase(HandlerStack.begin() + FrameStack.back().HPos, HandlerStack.end()); - CaughtStack.erase(CaughtStack.begin() + FrameStack.back().HPos, - CaughtStack.end()); FrameStack.back().Module = Module; FrameStack.back().Locals = LocalNum; FrameStack.back().Arity = Arity; FrameStack.back().VPos = static_cast(ValueStack.size()); + FrameStack.back().HPos = static_cast(HandlerStack.size()); } } @@ -158,76 +141,33 @@ class StackManager { return From; } - // Push handler for try-delegate block - void pushHandler(AST::InstrView::iterator EndIt, uint32_t VSize, - uint32_t HOffset, uint32_t COffset) noexcept { - // The POS is the stack size after jumping to the label + /// Push handler for try-catch block. + void + pushHandler(AST::InstrView::iterator TryIt, uint32_t BlockParamNum, + Span Catch) noexcept { HandlerStack.emplace_back( - EndIt, VSize, static_cast(FrameStack.size()), - static_cast(HandlerStack.size()) - HOffset, - static_cast(CaughtStack.size()) - COffset); - } - - // Push handler for try-catch block - void pushHandler(AST::InstrView::iterator EndIt, - uint32_t BlockParamNum) noexcept { - HandlerStack.emplace_back( - EndIt, static_cast(ValueStack.size()) - BlockParamNum, - static_cast(FrameStack.size()), - static_cast(HandlerStack.size()), - static_cast(CaughtStack.size())); - } - - // Push a handler to the current try block - void addCatchCaluseToLastHandler(Runtime::Instance::TagInstance *T, - AST::InstrView::iterator It) noexcept { - HandlerStack.back().CatchCaluse.emplace_back(T, It); + TryIt, static_cast(ValueStack.size()) - BlockParamNum, + static_cast(FrameStack.size()), Catch); } - // Erase the stacks so that the exception handler is on the top of the stack - // Associated Value should remain on top of ValueStack. - Handler popToTopHandler(uint32_t AssocValSize) noexcept { + /// Erase the stacks until the exception handler is on the top of the stack. + /// Pop the top handler and associated Values should remain on the top of + /// ValueStack. + Handler popTopHandler(uint32_t AssocValSize) noexcept { + assuming(!HandlerStack.empty()); + assuming(HandlerStack.back().VPos <= ValueStack.size() - AssocValSize); + ValueStack.erase(ValueStack.begin() + HandlerStack.back().VPos, + ValueStack.end() - AssocValSize); + FrameStack.erase(FrameStack.begin() + HandlerStack.back().FPos, + FrameStack.end()); auto TopHandler = std::move(HandlerStack.back()); HandlerStack.pop_back(); - assuming(ValueStack.size() - AssocValSize >= TopHandler.VPos); - ValueStack.erase(ValueStack.begin() + TopHandler.VPos, - ValueStack.end() - AssocValSize); - FrameStack.erase(FrameStack.begin() + TopHandler.FPos, FrameStack.end()); - HandlerStack.erase(HandlerStack.begin() + TopHandler.HPos, - HandlerStack.end()); - CaughtStack.erase(CaughtStack.begin() + TopHandler.CPos, CaughtStack.end()); return TopHandler; } - // Unsafe pop top exception handler - AST::InstrView::iterator popHandler() noexcept { - auto EndIt = HandlerStack.back().EndIt; - HandlerStack.pop_back(); - return EndIt; - } - - // Check whether handler stack is empty + /// Check whether handler stack is empty bool isHandlerStackEmpty() noexcept { return HandlerStack.empty(); } - // Push a caught exception to the stack - void pushCaught(Runtime::Instance::TagInstance *T, Span V, - AST::InstrView::iterator E) noexcept { - CaughtStack.emplace_back(T, V, E); - } - - // Unsafe pop top caught exception - AST::InstrView::iterator popCaught() noexcept { - auto EndIt = CaughtStack.back().EndIt; - CaughtStack.pop_back(); - return EndIt; - } - - /// Unsafe Getter of top N-th value entry of stack. - Exception &getCaughtTopN(uint32_t Offset) noexcept { - assuming(0 < Offset && Offset <= CaughtStack.size()); - return *(CaughtStack.end() - Offset); - } - /// Unsafe erase value stack. void eraseValueStack(uint32_t EraseBegin, uint32_t EraseEnd) noexcept { assuming(EraseEnd <= EraseBegin && EraseBegin <= ValueStack.size()); @@ -235,42 +175,24 @@ class StackManager { ValueStack.end() - EraseEnd); } - // Unsafe erase top Num element of exception handler stack + /// Unsafe erase top Num element of exception handler stack void eraseHandlerStack(uint32_t Num) noexcept { HandlerStack.erase(HandlerStack.end() - Num, HandlerStack.end()); } - // Unsafe erase top Num element of caught exception stack - void eraseCaughtStack(uint32_t Num) noexcept { - CaughtStack.erase(CaughtStack.end() - Num, CaughtStack.end()); - } - /// Unsafe leave top label. AST::InstrView::iterator - maybePopFrameOrHandlerOrCaught(AST::InstrView::iterator PC) noexcept { - if (FrameStack.size() > 1 && PC->isLast()) { + maybePopFrameOrHandler(AST::InstrView::iterator PC) noexcept { + if (FrameStack.size() > 1 && PC->isExprLast()) { // Noted that there's always a base frame in stack. return popFrame(); } - if (PC->isTryLast()) { - return popHandler(); - } - if (PC->isCatchLast()) { - return popCaught(); + if (PC->isTryBlockLast()) { + HandlerStack.pop_back(); } return PC; } - // Unsafe leave try-block or catch-block - AST::InstrView::iterator - popHandlerOrCaught(AST::InstrView::iterator PC) noexcept { - if (PC->isTryLast()) { - return popHandler(); - } else { - return popCaught(); - } - } - /// Unsafe getter of module address. const Instance::ModuleInstance *getModule() const noexcept { assuming(!FrameStack.empty()); @@ -281,6 +203,7 @@ class StackManager { void reset() noexcept { ValueStack.clear(); FrameStack.clear(); + HandlerStack.clear(); } private: @@ -289,7 +212,6 @@ class StackManager { std::vector ValueStack; std::vector FrameStack; std::vector HandlerStack; - std::vector CaughtStack; /// @} }; diff --git a/lib/executor/engine/controlInstr.cpp b/lib/executor/engine/controlInstr.cpp index 29e9daf7f5eb..6bf9606c641f 100644 --- a/lib/executor/engine/controlInstr.cpp +++ b/lib/executor/engine/controlInstr.cpp @@ -33,44 +33,26 @@ Expect Executor::runIfElseOp(Runtime::StackManager &StackMgr, return {}; } -Expect Executor::runTryOp(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept { - if (Instr.isDelegate()) { - StackMgr.pushHandler(PC + Instr.getTryBlockJumpEnd(), - Instr.getTryBlockVSize(), Instr.getTryBlockHOffset(), - Instr.getTryBlockCOffset()); - - } else { - StackMgr.pushHandler(PC + Instr.getTryBlockJumpEnd(), - Instr.getTryBlockParamNum()); - for (auto CatchOffset : Instr.getJumpCatchList()) { - auto CatchInstrIt = PC + CatchOffset; - StackMgr.addCatchCaluseToLastHandler( - getTagInstByIdx(StackMgr, CatchInstrIt->getTargetIndex()), - CatchInstrIt); - } - if (auto CatchAllOffset = Instr.getJumpCatchAll(); CatchAllOffset) { - auto CatchAllInstrIt = PC + CatchAllOffset; - StackMgr.addCatchCaluseToLastHandler(nullptr, CatchAllInstrIt); - } - } - return {}; -} - Expect Executor::runThrowOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC) noexcept { auto *TagInst = getTagInstByIdx(StackMgr, Instr.getTargetIndex()); + // The args will be popped from stack in the throw function. return throwException(StackMgr, TagInst, PC); } -Expect Executor::runRethrowOp(Runtime::StackManager &StackMgr, - const AST::Instruction &Instr, - AST::InstrView::iterator &PC) noexcept { - auto Exception = StackMgr.getCaughtTopN(Instr.getJump().CaughtStackOffset); - StackMgr.pushValVec(Exception.Val); - return throwException(StackMgr, Exception.TagInst, PC); +Expect Executor::runThrowRefOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { + const auto Ref = StackMgr.pop().get(); + if (Ref.isNull()) { + spdlog::error(ErrCode::Value::AccessNullException); + spdlog::error( + ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); + return Unexpect(ErrCode::Value::AccessNullException); + } + auto *TagInst = Ref.getPtr(); + return throwException(StackMgr, TagInst, PC); } Expect Executor::runBrOp(Runtime::StackManager &StackMgr, @@ -178,7 +160,6 @@ Expect Executor::runCallRefOp(Runtime::StackManager &StackMgr, const AST::Instruction &Instr, AST::InstrView::iterator &PC, bool IsTailCall) noexcept { - const auto Ref = StackMgr.pop().get(); if (Ref.isNull()) { spdlog::error(ErrCode::Value::AccessNullFunc); @@ -266,5 +247,13 @@ Expect Executor::runCallIndirectOp(Runtime::StackManager &StackMgr, return {}; } +Expect Executor::runTryTableOp(Runtime::StackManager &StackMgr, + const AST::Instruction &Instr, + AST::InstrView::iterator &PC) noexcept { + const auto &TryDesc = Instr.getTryCatch(); + StackMgr.pushHandler(PC, TryDesc.BlockParamNum, TryDesc.Catch); + return {}; +} + } // namespace Executor } // namespace WasmEdge diff --git a/lib/executor/engine/engine.cpp b/lib/executor/engine/engine.cpp index 4502928d5c1b..945d6bf24599 100644 --- a/lib/executor/engine/engine.cpp +++ b/lib/executor/engine/engine.cpp @@ -139,17 +139,12 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, PC += PC->getJumpEnd(); [[fallthrough]]; case OpCode::End: - PC = StackMgr.maybePopFrameOrHandlerOrCaught(PC); - return {}; - case OpCode::Try: - return runTryOp(StackMgr, Instr, PC); - case OpCode::Catch: - PC = StackMgr.popHandlerOrCaught(PC); + PC = StackMgr.maybePopFrameOrHandler(PC); return {}; case OpCode::Throw: return runThrowOp(StackMgr, Instr, PC); - case OpCode::Rethrow: - return runRethrowOp(StackMgr, Instr, PC); + case OpCode::Throw_ref: + return runThrowRefOp(StackMgr, Instr, PC); case OpCode::Br: return runBrOp(StackMgr, Instr, PC); case OpCode::Br_if: @@ -178,12 +173,8 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, return runCallRefOp(StackMgr, Instr, PC); case OpCode::Return_call_ref: return runCallRefOp(StackMgr, Instr, PC, true); - case OpCode::Delegate: - PC = StackMgr.popHandler(); - return {}; - case OpCode::Catch_all: - PC = StackMgr.popHandlerOrCaught(PC); - return {}; + case OpCode::Try_table: + return runTryTableOp(StackMgr, Instr, PC); // Reference Instructions case OpCode::Ref__null: diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index f2aae8a47df6..e818c9fa7bbc 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -207,7 +207,6 @@ Executor::branchToLabel(Runtime::StackManager &StackMgr, StackMgr.eraseValueStack(JumpDesc.ValueStackEraseBegin, JumpDesc.ValueStackEraseEnd); StackMgr.eraseHandlerStack(JumpDesc.HandlerStackOffset); - StackMgr.eraseCaughtStack(JumpDesc.CaughtStackOffset); // PC need to -1 here because the PC will increase in the next iteration. PC += (JumpDesc.PCOffset - 1); return {}; @@ -216,26 +215,28 @@ Executor::branchToLabel(Runtime::StackManager &StackMgr, Expect Executor::throwException(Runtime::StackManager &StackMgr, Runtime::Instance::TagInstance *TagInst, AST::InstrView::iterator &PC) noexcept { + assuming(TagInst); while (!StackMgr.isHandlerStackEmpty()) { auto AssocValSize = TagInst->getTagType().getAssocValSize(); - // The value that associated with the exception should remain on the stack - auto ExceptionHandler = StackMgr.popToTopHandler(AssocValSize); - if (!ExceptionHandler.CatchCaluse.empty()) { - for (auto &[CatchTagInst, StartIt] : ExceptionHandler.CatchCaluse) { - if (CatchTagInst == nullptr || TagInst == CatchTagInst) { - PC = StartIt; - StackMgr.pushCaught(TagInst, StackMgr.getTopSpan(AssocValSize), - ExceptionHandler.EndIt); - if (CatchTagInst == nullptr) { - StackMgr.eraseValueStack(AssocValSize, 0); - } - return {}; - } + // The value that associated with the exception should remain on the stack. + auto ExnHandler = StackMgr.popTopHandler(AssocValSize); + // Checking through the catch clause. + for (const auto &C : ExnHandler.CatchClause) { + if (!C.IsAll && getTagInstByIdx(StackMgr, C.TagIndex) != TagInst) { + // For catching a specific tag, should check the equivalence of tag + // address. + continue; } - } else { - // The stack has transformed to the state after jumping to the label by - // StackMgr.popToTopHandler(AssocValSize) - return throwException(StackMgr, TagInst, PC); + if (C.IsRef) { + // For catching a exception reference, push the reference value onto + // stack. + StackMgr.push( + RefVariant(ValType(TypeCode::Ref, TypeCode::ExnRef), TagInst)); + } + // When being here, an exception is caught. Move the PC to the try block + // and branch to the label. + PC = ExnHandler.Try; + return branchToLabel(StackMgr, C.Jump, PC); } } spdlog::error(ErrCode::Value::UncaughtException); @@ -347,6 +348,8 @@ TypeCode Executor::toBottomType(Runtime::StackManager &StackMgr, case TypeCode::StructRef: case TypeCode::ArrayRef: return TypeCode::NullRef; + case TypeCode::ExnRef: + return TypeCode::ExnRef; default: assumingUnreachable(); } diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index 5f24195e4fbd..b7d38b6ede2f 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -4,7 +4,6 @@ #include "loader/loader.h" #include -#include #include #include @@ -137,9 +136,7 @@ Expect Loader::loadOpCode() { Expect Loader::loadInstrSeq(std::optional SizeBound) { OpCode Code; AST::InstrVec Instrs; - - // The third argument stores the Pos of all `catch` inside the try-block. - std::vector>> BlockStack; + std::vector> BlockStack; uint32_t Cnt = 0; bool IsReachEnd = false; // Read opcode until the End code of the top block. @@ -158,16 +155,13 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { return logNeedProposal(ErrCode::Value::IllegalOpCode, Res.value(), Offset, ASTNodeAttr::Instruction); } - switch (Code) { - case OpCode::Block: - case OpCode::Loop: - case OpCode::If: - case OpCode::Try: - BlockStack.emplace_back(Code, Cnt, 0); - break; - case OpCode::Else: { - if (BlockStack.size() == 0 || - std::get<0>(BlockStack.back()) != OpCode::If) { + + // Process the instructions which contain a block. + if (Code == OpCode::Block || Code == OpCode::Loop || Code == OpCode::If || + Code == OpCode::Try_table) { + BlockStack.push_back(std::make_pair(Code, Cnt)); + } else if (Code == OpCode::Else) { + if (BlockStack.size() == 0 || BlockStack.back().first != OpCode::If) { // An Else instruction appeared outside the If-block. if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { return logLoadError(ErrCode::Value::ENDCodeExpected, Offset, @@ -177,7 +171,7 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { ASTNodeAttr::Instruction); } } - uint32_t Pos = std::get<1>(BlockStack.back()); + uint32_t Pos = BlockStack.back().second; if (Instrs[Pos].getJumpElse() > 0) { // An Else instruction appeared before in this If-block. if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { @@ -189,72 +183,22 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { } } Instrs[Pos].setJumpElse(Cnt - Pos); - break; } - case OpCode::Catch: { - if (BlockStack.size() == 0) { - // A Catch instruction appeared outside a try-block. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - auto &[BackOp, Pos, CatchList] = BlockStack.back(); - if (BackOp != OpCode::Try) { - // A Catch instruction appeared outside a try-block. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - if (Instrs[Pos].getJumpCatchAll() != 0) { - // A Catch shouldn't behind a Catch_all in the same block. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - // Set it to Instruction object after parsing the whole try block - CatchList.push_back(Cnt - Pos); - break; - } - case OpCode::Catch_all: { - if (BlockStack.size() == 0 || - std::get<0>(BlockStack.back()) != OpCode::Try) { - // A Catch_all instruction appeared outside a try-block. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - uint32_t Pos = std::get<1>(BlockStack.back()); - if (Instrs[Pos].getJumpCatchAll() != 0) { - // A try block may contain only one Catch_all instruction. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - Instrs[Pos].setJumpCatchAll(Cnt - Pos); - break; - } - case OpCode::Delegate: { - if (BlockStack.size() == 0) { - // A Delegate instruction appeared outside a try-block. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - const auto &[BackOp, Pos, CatchList] = BlockStack.back(); - if (BackOp != OpCode::Try) { - // A Delegate instruction appeared outside a try-block. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - if (!CatchList.empty() || Instrs[Pos].getJumpCatchAll() != 0) { - // A Try-Delegate block shouldn't contain Catch or Catch_all. - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } - Instrs[Pos].setDelegate(); - Instrs[Pos].setTryBlockJumpEnd(Cnt - Pos); - // Pop the block stack after parsing the delegate instruction - break; + + // Create the instruction node and load contents. + Instrs.emplace_back(Code, static_cast(Offset)); + if (auto Res = loadInstruction(Instrs.back()); !Res) { + return Unexpect(Res); } - case OpCode::End: + + // Process the End instruction. + if (Code == OpCode::End) { if (BlockStack.size() > 0) { - const auto &[BackOp, Pos, CatchList] = BlockStack.back(); + Instrs.back().setExprLast(false); + const auto &[BackOp, Pos] = BlockStack.back(); if (BackOp == OpCode::Block || BackOp == OpCode::Loop || BackOp == OpCode::If) { + Instrs.back().setTryBlockLast(false); Instrs[Pos].setJumpEnd(Cnt - Pos); if (BackOp == OpCode::If) { if (Instrs[Pos].getJumpElse() == 0) { @@ -265,35 +209,15 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { Instrs[ElsePos].setJumpEnd(Cnt - ElsePos); } } - } else if (BackOp == OpCode::Try) { - Instrs[Pos].setTryBlockJumpEnd(Cnt - Pos); - Instrs[Pos].setJumpCatchList(CatchList); + } else if (BackOp == OpCode::Try_table) { + Instrs.back().setTryBlockLast(true); + Instrs[Pos].getTryCatch().JumpEnd = Cnt - Pos; } BlockStack.pop_back(); } else { + Instrs.back().setExprLast(true); IsReachEnd = true; } - break; - default: - break; - } - - // Create the instruction node and load contents. - Instrs.emplace_back(Code, static_cast(Offset)); - if (auto Res = loadInstruction(Instrs.back()); !Res) { - return Unexpect(Res); - } - if (Code == OpCode::Delegate) { - uint32_t Pos = std::get<1>(BlockStack.back()); - Instrs[Pos].setDelegateIdx(Instrs.back().getJump().TargetIndex); - BlockStack.pop_back(); - } - if (Code == OpCode::End) { - if (IsReachEnd) { - Instrs.back().setLast(true); - } else { - Instrs.back().setLast(false); - } } Cnt++; } while (!IsReachEnd); @@ -368,20 +292,7 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return {}; }; - switch (Instr.getOpCode()) { - // Control instructions. - case OpCode::Unreachable: - case OpCode::Nop: - case OpCode::Return: - case OpCode::End: - case OpCode::Else: - case OpCode::Catch_all: - return {}; - - case OpCode::Block: - case OpCode::Loop: - case OpCode::If: - case OpCode::Try: { + auto readBlockType = [this](BlockType &Dst) -> Expect { auto StartOffset = FMgr.getOffset(); // Read the block return type. if (auto Res = FMgr.readS33()) { @@ -389,13 +300,13 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { TypeCode TypeByte = static_cast((*Res) & INT64_C(0x7F)); if (TypeByte == TypeCode::Epsilon) { // Empty case. - Instr.setEmptyBlockType(); + Dst.setEmpty(); } else { // Value type case. Seek back to the origin offset and read the // valtype. FMgr.seek(StartOffset); if (auto TypeRes = loadValType(ASTNodeAttr::Instruction)) { - Instr.setBlockType(*TypeRes); + Dst.setData(*TypeRes); } else { // The AST node information is handled. return Unexpect(TypeRes); @@ -408,22 +319,87 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { Proposal::MultiValue, FMgr.getLastOffset(), ASTNodeAttr::Instruction); } - Instr.setBlockType(static_cast(*Res)); + Dst.setData(static_cast(*Res)); } } else { return logLoadError(Res.error(), FMgr.getLastOffset(), ASTNodeAttr::Instruction); } return {}; + }; + + switch (Instr.getOpCode()) { + // Control instructions. + case OpCode::Unreachable: + case OpCode::Nop: + case OpCode::Return: + case OpCode::Throw_ref: + case OpCode::End: + case OpCode::Else: + return {}; + + case OpCode::Block: + case OpCode::Loop: + case OpCode::If: + return readBlockType(Instr.getBlockType()); + + case OpCode::Try_table: { + Instr.setTryCatch(); + // Read the result type. + if (auto Res = readBlockType(Instr.getTryCatch().ResType); !Res) { + return Unexpect(Res); + } + uint32_t VecCnt = 0; + // Read the vector of catch. + if (auto Res = loadVecCnt()) { + VecCnt = *Res; + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Instruction); + } + Instr.getTryCatch().Catch.resize(VecCnt); + for (uint32_t I = 0; I < VecCnt; ++I) { + auto &Desc = Instr.getTryCatch().Catch[I]; + // Read the catch flag. + if (auto Res = FMgr.readByte()) { + if (*Res & 0x01U) { + Desc.IsRef = true; + } + if (*Res & 0x02U) { + Desc.IsAll = true; + } + } else { + return logLoadError(Res.error(), FMgr.getLastOffset(), + ASTNodeAttr::Instruction); + } + if (!Desc.IsAll) { + // Read the tag index. + if (auto Res = readU32(Desc.TagIndex); !Res) { + return Unexpect(Res); + } + } + // Read the label index. + if (auto Res = readU32(Desc.LabelIndex); !Res) { + return Unexpect(Res); + } + } + return {}; } + case OpCode::Throw: + return readU32(Instr.getTargetIndex()); + case OpCode::Br: case OpCode::Br_if: case OpCode::Br_on_null: - case OpCode::Br_on_non_null: - case OpCode::Delegate: - case OpCode::Rethrow: - return readU32(Instr.getJump().TargetIndex); + case OpCode::Br_on_non_null: { + uint32_t LabelIdx = 0; + if (auto Res = readU32(LabelIdx); !Res) { + return Unexpect(Res); + } + Instr.setJump(LabelIdx); + return {}; + } case OpCode::Br_table: { uint32_t VecCnt = 0; @@ -471,10 +447,6 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return {}; } - case OpCode::Catch: - case OpCode::Throw: - return readU32(Instr.getTargetIndex()); - // Reference Instructions. case OpCode::Ref__null: case OpCode::Ref__test_null: diff --git a/lib/loader/ast/type.cpp b/lib/loader/ast/type.cpp index 343afc9ff633..748980dc1dd5 100644 --- a/lib/loader/ast/type.cpp +++ b/lib/loader/ast/type.cpp @@ -42,6 +42,13 @@ Expect Loader::loadHeapType(TypeCode TC, ASTNodeAttr From) { FMgr.getLastOffset(), From); } return ValType(TC, HTCode); + case TypeCode::ExnRef: + if (!Conf.hasProposal(Proposal::ExceptionHandling)) { + return logNeedProposal(ErrCode::Value::MalformedValType, + Proposal::ExceptionHandling, + FMgr.getLastOffset(), From); + } + return ValType(TC, HTCode); default: return logLoadError(ErrCode::Value::MalformedRefType, FMgr.getLastOffset(), From); @@ -162,6 +169,13 @@ Expect Loader::loadValType(ASTNodeAttr From, bool IsStorageType) { FMgr.getLastOffset(), From); } return ValType(Code); + case TypeCode::ExnRef: + if (!Conf.hasProposal(Proposal::ExceptionHandling)) { + return logNeedProposal(ErrCode::Value::MalformedValType, + Proposal::ExceptionHandling, + FMgr.getLastOffset(), From); + } + return ValType(Code); case TypeCode::Ref: case TypeCode::RefNull: if (!Conf.hasProposal(Proposal::FunctionReferences)) { diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index 5bec1d3f2d2a..a660968c4e39 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -203,17 +203,14 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { }; // Helper lambda for counting the try and catch. - auto countCtrlStackType = - [this](uint32_t N) -> std::pair { - uint32_t CatchCnt = 0, TryCnt = 0; + auto countCtrlStackType = [this](uint32_t N) -> uint32_t { + uint32_t TryCnt = 0; for (auto It = CtrlStack.begin() + N; It != CtrlStack.end(); It++) { - if (It->Code == OpCode::Try) + if (It->Code == OpCode::Try_table) { TryCnt++; - if (It->Code == OpCode::Catch || It->Code == OpCode::Catch_all) { - CatchCnt++; } } - return {TryCnt, CatchCnt}; + return TryCnt; }; // Helper lambda for checking memory index and perform transformation. @@ -285,9 +282,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { static_cast(ValStack.size() - CtrlStack[D].Height); Jump.ValueStackEraseBegin = Remain + Arity; Jump.ValueStackEraseEnd = Arity; - auto [TryCnt, CatchCnt] = countCtrlStackType(D); - Jump.HandlerStackOffset = TryCnt; - Jump.CaughtStackOffset = CatchCnt; + Jump.HandlerStackOffset = countCtrlStackType(D); Jump.PCOffset = static_cast(CtrlStack[D].Jump - &Instr); }; @@ -337,34 +332,17 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { case OpCode::Nop: return {}; - case OpCode::Try: - if (Instr.getOpCode() == OpCode::Try && Instr.isDelegate()) { - if (auto D = checkCtrlStackDepth(Instr.getDelegateIdx()); !D) { - return Unexpect(D); - } else { - // Delegate to the label itself, not before the label. - auto [TryCnt, CatchCnt] = countCtrlStackType(*D + 1); - auto &NonConstInstr = const_cast(Instr); - if (*D + 1 < CtrlStack.size()) { - NonConstInstr.setTryBlockVSize( - static_cast(Locals.size() + CtrlStack[*D + 1].Height)); - } else { - NonConstInstr.setTryBlockVSize( - static_cast(Locals.size() + ValStack.size())); - } - // The try block itself may push an additional handler to stack. - NonConstInstr.setTryBlockHOffset(TryCnt); - NonConstInstr.setTryBlockCOffset(CatchCnt); - } - } - [[fallthrough]]; - case OpCode::If: case OpCode::Block: - case OpCode::Loop: { + case OpCode::Loop: + case OpCode::If: + case OpCode::Try_table: { // Get blocktype [t1*] -> [t2*] and check valtype first. std::vector Buffer(1); Span T1, T2; - if (auto Res = checkBlockType(Buffer, Instr.getBlockType())) { + const auto &BType = (Instr.getOpCode() == OpCode::Try_table) + ? Instr.getTryCatch().ResType + : Instr.getBlockType(); + if (auto Res = checkBlockType(Buffer, BType)) { std::tie(T1, T2) = std::move(*Res); } else { return Unexpect(Res); @@ -375,14 +353,51 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(Res); } } - if (Instr.getOpCode() == OpCode::Try) { - const_cast(Instr).setTryBlockParamNum( - static_cast(T1.size())); - } // Pop and check [t1*] if (auto Res = popTypes(T1); !Res) { return Unexpect(Res); } + // For the try_table instruction, validate the handlers. + if (Instr.getOpCode() == OpCode::Try_table) { + const auto &TryDesc = Instr.getTryCatch(); + const_cast(TryDesc).BlockParamNum = + static_cast(T1.size()); + // Validate catch clause. + for (const auto &C : TryDesc.Catch) { + if (!C.IsAll) { + // Check tag index. + if (unlikely(C.TagIndex >= Tags.size())) { + return logOutOfRange(ErrCode::Value::InvalidTagIdx, + ErrInfo::IndexCategory::Tag, C.TagIndex, + static_cast(Tags.size())); + } + // Result type of tag index are checked in tag section. + } + if (auto D = checkCtrlStackDepth(C.LabelIndex)) { + pushCtrl({}, getLabelTypes(CtrlStack[*D]), &Instr + TryDesc.JumpEnd, + Instr.getOpCode()); + std::vector NTypes; + if (!C.IsAll) { + // The type is checked as a function type. + NTypes = Types[Tags[C.TagIndex]] + ->getCompositeType() + .getFuncType() + .getParamTypes(); + } + if (C.IsRef) { + NTypes.emplace_back(ValType(TypeCode::ExnRef)); + } + pushTypes(NTypes); + if (auto Res = popCtrl(); !Res) { + return Unexpect(Res); + } + recordJump(const_cast(C.Jump), + static_cast(NTypes.size()), *D); + } else { + return Unexpect(D); + } + } + } // Push ctrl frame ([t1*], [t2*]) const AST::Instruction *From = Instr.getOpCode() == OpCode::Loop ? &Instr @@ -406,45 +421,29 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } return {}; - case OpCode::Catch: - if (CtrlStack.back().Code == OpCode::Try) { - const_cast(Instr).setTryLast(); + case OpCode::Throw: + if (unlikely(Instr.getTargetIndex() >= Tags.size())) { + return logOutOfRange(ErrCode::Value::InvalidTagIdx, + ErrInfo::IndexCategory::Tag, Instr.getTargetIndex(), + static_cast(Tags.size())); } - if (auto Res = popCtrl()) { - if (auto CompType = - checkDefinedType(Instr.getTargetIndex(), TypeCode::Func)) { - pushCtrl((*CompType)->getFuncType().getParamTypes(), Res->EndTypes, - Res->Jump, Instr.getOpCode()); - } else { - return Unexpect(CompType); + if (auto CompType = + checkDefinedType(Tags[Instr.getTargetIndex()], TypeCode::Func)) { + std::vector Input = (*CompType)->getFuncType().getParamTypes(); + if (auto Res = popTypes(Input); !Res) { + return Unexpect(Res); } + return unreachable(); } else { - return Unexpect(Res); - } - return {}; - case OpCode::Catch_all: - if (CtrlStack.back().Code == OpCode::Try) { - const_cast(Instr).setTryLast(); - } - if (auto Res = popCtrl()) { - pushCtrl({}, Res->EndTypes, Res->Jump, Instr.getOpCode()); - } else { - return Unexpect(Res); + return Unexpect(CompType); } - return {}; - case OpCode::Delegate: - if (auto Res = popCtrl()) { - pushTypes(Res->EndTypes); - } else { + case OpCode::Throw_ref: + if (auto Res = popType(TypeCode::ExnRef); !Res) { return Unexpect(Res); } - return {}; + return unreachable(); + case OpCode::End: - if (auto Code = CtrlStack.back().Code; Code == OpCode::Try) { - const_cast(Instr).setTryLast(); - } else if (Code == OpCode::Catch || Code == OpCode::Catch_all) { - const_cast(Instr).setCatchLast(); - } if (auto Res = popCtrl()) { pushTypes(Res->EndTypes); } else { @@ -452,33 +451,6 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } return {}; - case OpCode::Throw: - if (auto CompType = - checkDefinedType(Instr.getTargetIndex(), TypeCode::Func)) { - const auto &FType = (*CompType)->getFuncType(); - if (auto Res = popTypes(FType.getParamTypes()); !Res) { - return Unexpect(Res); - } - return unreachable(); - } else { - return Unexpect(CompType); - } - case OpCode::Rethrow: { - auto LabelIdx = Instr.getJump().TargetIndex; - if (auto D = checkCtrlStackDepth(LabelIdx); !D) { - return Unexpect(D); - } else if (auto LabelCode = CtrlStack[*D].Code; - LabelCode != OpCode::Catch && LabelCode != OpCode::Catch_all) { - spdlog::error(ErrCode::Value::InvalidRethrowLabel); - return Unexpect(ErrCode::Value::InvalidRethrowLabel); - } else { - auto [TryCnt, CatchCnt] = countCtrlStackType(*D); - auto &Jump = const_cast(Instr).getJump(); - Jump.CaughtStackOffset = CatchCnt; - return unreachable(); - } - } - case OpCode::Br: if (auto D = checkCtrlStackDepth(Instr.getJump().TargetIndex); !D) { return Unexpect(D); @@ -566,7 +538,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { case OpCode::Br_on_null: // D is the last D element of control stack. - if (auto D = checkCtrlStackDepth(Instr.getTargetIndex())) { + if (auto D = checkCtrlStackDepth(Instr.getJump().TargetIndex)) { const auto NTypes = getLabelTypes(CtrlStack[*D]); if (auto ResT = popType()) { if ((*ResT).has_value() && !(*ResT)->isRefType()) { @@ -592,7 +564,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(D); } case OpCode::Br_on_non_null: - if (auto D = checkCtrlStackDepth(Instr.getTargetIndex())) { + if (auto D = checkCtrlStackDepth(Instr.getJump().TargetIndex)) { // Get the result type of the label. (Should be [t* rt].) auto LabelTypes = getLabelTypes(CtrlStack[*D]); std::vector NTypes(LabelTypes.begin(), LabelTypes.end()); diff --git a/lib/validator/validator.cpp b/lib/validator/validator.cpp index 0f8a0a80dc6a..54ade3f4b323 100644 --- a/lib/validator/validator.cpp +++ b/lib/validator/validator.cpp @@ -776,8 +776,8 @@ Expect Validator::validate(const AST::TagSection &TagSec) { return Unexpect(ErrCode::Value::InvalidTagIdx); } if (!CompType.getFuncType().getReturnTypes().empty()) { - spdlog::error(ErrCode::Value::InvalidTag); - return Unexpect(ErrCode::Value::InvalidTag); + spdlog::error(ErrCode::Value::InvalidTagResultType); + return Unexpect(ErrCode::Value::InvalidTagResultType); } Checker.addTag(TagTypeIdx); } diff --git a/test/loader/serializeInstructionTest.cpp b/test/loader/serializeInstructionTest.cpp index ab19f4c46d35..2342af2acd63 100644 --- a/test/loader/serializeInstructionTest.cpp +++ b/test/loader/serializeInstructionTest.cpp @@ -42,7 +42,7 @@ TEST(SerializeInstructionTest, SerializeBlockControlInstruction) { WasmEdge::AST::Instruction I32Eq(WasmEdge::OpCode::I32__eq); WasmEdge::AST::Instruction I32Ne(WasmEdge::OpCode::I32__ne); - Block.setEmptyBlockType(); + Block.getBlockType().setEmpty(); Instructions = {Block, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -59,7 +59,7 @@ TEST(SerializeInstructionTest, SerializeBlockControlInstruction) { }; EXPECT_EQ(Output, Expected); - Loop.setEmptyBlockType(); + Loop.getBlockType().setEmpty(); Instructions = {Loop, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -76,7 +76,7 @@ TEST(SerializeInstructionTest, SerializeBlockControlInstruction) { }; EXPECT_EQ(Output, Expected); - Loop.setEmptyBlockType(); + Loop.getBlockType().setEmpty(); Instructions = {Block, I32Eqz, I32Eq, I32Ne, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -94,7 +94,7 @@ TEST(SerializeInstructionTest, SerializeBlockControlInstruction) { }; EXPECT_EQ(Output, Expected); - Loop.setEmptyBlockType(); + Loop.getBlockType().setEmpty(); Instructions = {Loop, I32Eqz, I32Eq, I32Ne, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -132,7 +132,7 @@ TEST(SerializeInstructionTest, SerializeIfElseControlInstruction) { WasmEdge::AST::Instruction I32Eq(WasmEdge::OpCode::I32__eq); WasmEdge::AST::Instruction I32Ne(WasmEdge::OpCode::I32__ne); - If.setEmptyBlockType(); + If.getBlockType().setEmpty(); Instructions = {If, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -149,7 +149,7 @@ TEST(SerializeInstructionTest, SerializeIfElseControlInstruction) { }; EXPECT_EQ(Output, Expected); - If.setEmptyBlockType(); + If.getBlockType().setEmpty(); Instructions = {If, Else, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -167,7 +167,7 @@ TEST(SerializeInstructionTest, SerializeIfElseControlInstruction) { }; EXPECT_EQ(Output, Expected); - If.setEmptyBlockType(); + If.getBlockType().setEmpty(); Instructions = {If, I32Eqz, I32Eq, I32Ne, End, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -185,7 +185,7 @@ TEST(SerializeInstructionTest, SerializeIfElseControlInstruction) { }; EXPECT_EQ(Output, Expected); - If.setEmptyBlockType(); + If.getBlockType().setEmpty(); Instructions = {If, I32Eqz, I32Eq, I32Ne, Else, I32Eqz, I32Eq, I32Ne, End, End}; Output = {}; @@ -220,7 +220,7 @@ TEST(SerializeInstructionTest, SerializeBrControlInstruction) { WasmEdge::AST::Instruction BrIf(WasmEdge::OpCode::Br_if); WasmEdge::AST::Instruction End(WasmEdge::OpCode::End); - Br.getJump().TargetIndex = 0xFFFFFFFFU; + Br.setJump(0xFFFFFFFFU); Instructions = {Br, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -236,7 +236,7 @@ TEST(SerializeInstructionTest, SerializeBrControlInstruction) { }; EXPECT_EQ(Output, Expected); - BrIf.getJump().TargetIndex = 0xFFFFFFFFU; + BrIf.setJump(0xFFFFFFFFU); Instructions = {BrIf, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); diff --git a/test/spec/spectest.cpp b/test/spec/spectest.cpp index 60311f6cd14c..5c488285cb0a 100644 --- a/test/spec/spectest.cpp +++ b/test/spec/spectest.cpp @@ -435,6 +435,12 @@ bool SpecTest::compare(const std::pair &Expected, return false; } return IsRefMatch(Got.first.get()); + } else if (TypeStr == "exnref"sv) { + if (!Got.second.isRefType() || + Got.second.getHeapTypeCode() != TypeCode::ExnRef) { + return false; + } + return IsRefMatch(Got.first.get()); } else if (TypeStr == "i32"sv) { if (Got.second.getCode() != TypeCode::I32) { return false; From 7e2fce5f01ab590f325b785f62ec01c67c17df65 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Wed, 3 Apr 2024 23:04:30 +0800 Subject: [PATCH 160/218] [Executor] Simplify the handler stack in stack manager for reduce cost of br instructions. Signed-off-by: YiYing He --- include/ast/instruction.h | 29 ++----- include/executor/executor.h | 2 +- include/runtime/stackmgr.h | 101 ++++++++++++----------- lib/executor/engine/controlInstr.cpp | 4 +- lib/executor/helper.cpp | 27 +++--- lib/loader/ast/instruction.cpp | 10 +-- lib/validator/formchecker.cpp | 21 +---- test/loader/serializeInstructionTest.cpp | 4 +- 8 files changed, 85 insertions(+), 113 deletions(-) diff --git a/include/ast/instruction.h b/include/ast/instruction.h index 09f84443eaac..23658222db2b 100644 --- a/include/ast/instruction.h +++ b/include/ast/instruction.h @@ -28,9 +28,8 @@ class Instruction { public: struct JumpDescriptor { uint32_t TargetIndex; - uint32_t ValueStackEraseBegin; - uint32_t ValueStackEraseEnd; - uint32_t HandlerStackOffset; + uint32_t StackEraseBegin; + uint32_t StackEraseEnd; int32_t PCOffset; }; struct BrCastDescriptor { @@ -62,7 +61,6 @@ class Instruction { Data.Num.Low = static_cast(0); Data.Num.High = static_cast(0); #endif - Flags.IsAllocJump = false; Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; Flags.IsAllocBrCast = false; @@ -73,9 +71,7 @@ class Instruction { Instruction(const Instruction &Instr) noexcept : Data(Instr.Data), Offset(Instr.Offset), Code(Instr.Code), Flags(Instr.Flags) { - if (Flags.IsAllocJump) { - Data.Jump = new JumpDescriptor(*Instr.Data.Jump); - } else if (Flags.IsAllocLabelList) { + if (Flags.IsAllocLabelList) { Data.BrTable.LabelList = new JumpDescriptor[Data.BrTable.LabelListSize]; std::copy_n(Instr.Data.BrTable.LabelList, Data.BrTable.LabelListSize, Data.BrTable.LabelList); @@ -94,7 +90,6 @@ class Instruction { Instruction(Instruction &&Instr) noexcept : Data(Instr.Data), Offset(Instr.Offset), Code(Instr.Code), Flags(Instr.Flags) { - Instr.Flags.IsAllocJump = false; Instr.Flags.IsAllocLabelList = false; Instr.Flags.IsAllocValTypeList = false; Instr.Flags.IsAllocBrCast = false; @@ -168,14 +163,8 @@ class Instruction { } /// Getter and setter of Jump for Br* instruction. - void setJump(uint32_t LabelIdx) { - reset(); - Data.Jump = new JumpDescriptor(); - Flags.IsAllocJump = true; - Data.Jump->TargetIndex = LabelIdx; - } - const JumpDescriptor &getJump() const noexcept { return *Data.Jump; } - JumpDescriptor &getJump() noexcept { return *Data.Jump; } + const JumpDescriptor &getJump() const noexcept { return Data.Jump; } + JumpDescriptor &getJump() noexcept { return Data.Jump; } /// Getter and setter of selecting value types list. void setValTypeListSize(uint32_t Size) { @@ -260,9 +249,7 @@ class Instruction { private: /// Release allocated resources. void reset() noexcept { - if (Flags.IsAllocJump) { - delete Data.Jump; - } else if (Flags.IsAllocLabelList) { + if (Flags.IsAllocLabelList) { Data.BrTable.LabelListSize = 0; delete[] Data.BrTable.LabelList; } else if (Flags.IsAllocValTypeList) { @@ -273,7 +260,6 @@ class Instruction { } else if (Flags.IsAllocTryCatch) { delete Data.TryCatch; } - Flags.IsAllocJump = false; Flags.IsAllocLabelList = false; Flags.IsAllocValTypeList = false; Flags.IsAllocBrCast = false; @@ -304,7 +290,7 @@ class Instruction { uint32_t StackOffset; } Indices; // Type 3: Jump. - JumpDescriptor *Jump; + JumpDescriptor Jump; // Type 4: LabelList. struct { uint32_t LabelListSize; @@ -347,7 +333,6 @@ class Instruction { uint32_t Offset = 0; OpCode Code = OpCode::End; struct { - bool IsAllocJump : 1; bool IsAllocLabelList : 1; bool IsAllocValTypeList : 1; bool IsAllocBrCast : 1; diff --git a/include/executor/executor.h b/include/executor/executor.h index c9e5385ed3e3..18408cbfccc4 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -278,7 +278,7 @@ class Executor { /// Helper function for throwing an exception. Expect throwException(Runtime::StackManager &StackMgr, - Runtime::Instance::TagInstance *, + Runtime::Instance::TagInstance &TagInst, AST::InstrView::iterator &PC) noexcept; /// @} diff --git a/include/runtime/stackmgr.h b/include/runtime/stackmgr.h index c046085cde50..385d2655e63b 100644 --- a/include/runtime/stackmgr.h +++ b/include/runtime/stackmgr.h @@ -16,6 +16,7 @@ #include "ast/instruction.h" #include "runtime/instance/module.h" +#include #include namespace WasmEdge { @@ -25,27 +26,26 @@ class StackManager { public: using Value = ValVariant; + struct Handler { + Handler(AST::InstrView::iterator TryIt, uint32_t V, + Span C) + : Try(TryIt), VPos(V), CatchClause(C) {} + AST::InstrView::iterator Try; + uint32_t VPos; + Span CatchClause; + }; + struct Frame { Frame() = delete; Frame(const Instance::ModuleInstance *Mod, AST::InstrView::iterator FromIt, - uint32_t L, uint32_t A, uint32_t V, uint32_t H) noexcept - : Module(Mod), From(FromIt), Locals(L), Arity(A), VPos(V), HPos(H) {} + uint32_t L, uint32_t A, uint32_t V) noexcept + : Module(Mod), From(FromIt), Locals(L), Arity(A), VPos(V) {} const Instance::ModuleInstance *Module; AST::InstrView::iterator From; uint32_t Locals; uint32_t Arity; uint32_t VPos; - uint32_t HPos; - }; - - struct Handler { - Handler(AST::InstrView::iterator TryIt, uint32_t V, uint32_t F, - Span C) - : Try(TryIt), VPos(V), FPos(F), CatchClause(C) {} - AST::InstrView::iterator Try; - uint32_t VPos; - uint32_t FPos; - Span CatchClause; + std::vector HandlerStack; }; /// Stack manager provides the stack control for Wasm execution with VALIDATED @@ -54,7 +54,6 @@ class StackManager { StackManager() noexcept { ValueStack.reserve(2048U); FrameStack.reserve(16U); - HandlerStack.reserve(16U); } ~StackManager() = default; @@ -85,7 +84,7 @@ class StackManager { ValueStack.insert(ValueStack.end(), ValVec.begin(), ValVec.end()); } - /// Unsafe Pop and return the top entry. + /// Unsafe pop and return the top entry. Value pop() { Value V = std::move(ValueStack.back()); ValueStack.pop_back(); @@ -105,10 +104,9 @@ class StackManager { void pushFrame(const Instance::ModuleInstance *Module, AST::InstrView::iterator From, uint32_t LocalNum = 0, uint32_t Arity = 0, bool IsTailCall = false) noexcept { - if (likely(!IsTailCall)) { + if (!IsTailCall) { FrameStack.emplace_back(Module, From, LocalNum, Arity, - static_cast(ValueStack.size()), - static_cast(HandlerStack.size())); + static_cast(ValueStack.size())); } else { assuming(!FrameStack.empty()); assuming(FrameStack.back().VPos >= FrameStack.back().Locals); @@ -117,13 +115,11 @@ class StackManager { ValueStack.erase(ValueStack.begin() + FrameStack.back().VPos - FrameStack.back().Locals, ValueStack.end() - LocalNum); - HandlerStack.erase(HandlerStack.begin() + FrameStack.back().HPos, - HandlerStack.end()); FrameStack.back().Module = Module; FrameStack.back().Locals = LocalNum; FrameStack.back().Arity = Arity; FrameStack.back().VPos = static_cast(ValueStack.size()); - FrameStack.back().HPos = static_cast(HandlerStack.size()); + FrameStack.back().HandlerStack.clear(); } } @@ -145,29 +141,45 @@ class StackManager { void pushHandler(AST::InstrView::iterator TryIt, uint32_t BlockParamNum, Span Catch) noexcept { - HandlerStack.emplace_back( - TryIt, static_cast(ValueStack.size()) - BlockParamNum, - static_cast(FrameStack.size()), Catch); + assuming(!FrameStack.empty()); + FrameStack.back().HandlerStack.emplace_back( + TryIt, static_cast(ValueStack.size()) - BlockParamNum, Catch); + } + + /// Pop the top handler on the stack. + std::optional popTopHandler(uint32_t AssocValSize) noexcept { + while (!FrameStack.empty()) { + auto &Frame = FrameStack.back(); + if (!Frame.HandlerStack.empty()) { + auto TopHandler = std::move(Frame.HandlerStack.back()); + Frame.HandlerStack.pop_back(); + assuming(TopHandler.VPos <= ValueStack.size() - AssocValSize); + ValueStack.erase(ValueStack.begin() + TopHandler.VPos, + ValueStack.end() - AssocValSize); + return TopHandler; + } + FrameStack.pop_back(); + } + return std::nullopt; } - /// Erase the stacks until the exception handler is on the top of the stack. - /// Pop the top handler and associated Values should remain on the top of - /// ValueStack. - Handler popTopHandler(uint32_t AssocValSize) noexcept { - assuming(!HandlerStack.empty()); - assuming(HandlerStack.back().VPos <= ValueStack.size() - AssocValSize); - ValueStack.erase(ValueStack.begin() + HandlerStack.back().VPos, - ValueStack.end() - AssocValSize); - FrameStack.erase(FrameStack.begin() + HandlerStack.back().FPos, - FrameStack.end()); - auto TopHandler = std::move(HandlerStack.back()); - HandlerStack.pop_back(); - return TopHandler; + /// Unsafe remove inactive handler. + void removeInactiveHandler(AST::InstrView::iterator PC) noexcept { + assuming(!FrameStack.empty()); + // First pop the inactive handlers. Br instructions may cause the handlers + // in current frame becomes inactive. + auto &HandlerStack = FrameStack.back().HandlerStack; + while (!HandlerStack.empty()) { + auto &Handler = HandlerStack.back(); + if (PC < Handler.Try || + PC > Handler.Try + Handler.Try->getTryCatch().JumpEnd) { + HandlerStack.pop_back(); + } else { + break; + } + } } - /// Check whether handler stack is empty - bool isHandlerStackEmpty() noexcept { return HandlerStack.empty(); } - /// Unsafe erase value stack. void eraseValueStack(uint32_t EraseBegin, uint32_t EraseEnd) noexcept { assuming(EraseEnd <= EraseBegin && EraseBegin <= ValueStack.size()); @@ -175,11 +187,6 @@ class StackManager { ValueStack.end() - EraseEnd); } - /// Unsafe erase top Num element of exception handler stack - void eraseHandlerStack(uint32_t Num) noexcept { - HandlerStack.erase(HandlerStack.end() - Num, HandlerStack.end()); - } - /// Unsafe leave top label. AST::InstrView::iterator maybePopFrameOrHandler(AST::InstrView::iterator PC) noexcept { @@ -188,7 +195,7 @@ class StackManager { return popFrame(); } if (PC->isTryBlockLast()) { - HandlerStack.pop_back(); + FrameStack.back().HandlerStack.pop_back(); } return PC; } @@ -203,7 +210,6 @@ class StackManager { void reset() noexcept { ValueStack.clear(); FrameStack.clear(); - HandlerStack.clear(); } private: @@ -211,7 +217,6 @@ class StackManager { /// @{ std::vector ValueStack; std::vector FrameStack; - std::vector HandlerStack; /// @} }; diff --git a/lib/executor/engine/controlInstr.cpp b/lib/executor/engine/controlInstr.cpp index 6bf9606c641f..6c53c63df022 100644 --- a/lib/executor/engine/controlInstr.cpp +++ b/lib/executor/engine/controlInstr.cpp @@ -38,7 +38,7 @@ Expect Executor::runThrowOp(Runtime::StackManager &StackMgr, AST::InstrView::iterator &PC) noexcept { auto *TagInst = getTagInstByIdx(StackMgr, Instr.getTargetIndex()); // The args will be popped from stack in the throw function. - return throwException(StackMgr, TagInst, PC); + return throwException(StackMgr, *TagInst, PC); } Expect Executor::runThrowRefOp(Runtime::StackManager &StackMgr, @@ -52,7 +52,7 @@ Expect Executor::runThrowRefOp(Runtime::StackManager &StackMgr, return Unexpect(ErrCode::Value::AccessNullException); } auto *TagInst = Ref.getPtr(); - return throwException(StackMgr, TagInst, PC); + return throwException(StackMgr, *TagInst, PC); } Expect Executor::runBrOp(Runtime::StackManager &StackMgr, diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index e818c9fa7bbc..7b7ddbb7a6d8 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -204,25 +204,26 @@ Executor::branchToLabel(Runtime::StackManager &StackMgr, return Unexpect(ErrCode::Value::Interrupted); } - StackMgr.eraseValueStack(JumpDesc.ValueStackEraseBegin, - JumpDesc.ValueStackEraseEnd); - StackMgr.eraseHandlerStack(JumpDesc.HandlerStackOffset); + StackMgr.eraseValueStack(JumpDesc.StackEraseBegin, JumpDesc.StackEraseEnd); // PC need to -1 here because the PC will increase in the next iteration. PC += (JumpDesc.PCOffset - 1); return {}; } Expect Executor::throwException(Runtime::StackManager &StackMgr, - Runtime::Instance::TagInstance *TagInst, + Runtime::Instance::TagInstance &TagInst, AST::InstrView::iterator &PC) noexcept { - assuming(TagInst); - while (!StackMgr.isHandlerStackEmpty()) { - auto AssocValSize = TagInst->getTagType().getAssocValSize(); - // The value that associated with the exception should remain on the stack. - auto ExnHandler = StackMgr.popTopHandler(AssocValSize); + StackMgr.removeInactiveHandler(PC); + auto AssocValSize = TagInst.getTagType().getAssocValSize(); + while (true) { + // Pop the top handler. + auto Handler = StackMgr.popTopHandler(AssocValSize); + if (!Handler.has_value()) { + break; + } // Checking through the catch clause. - for (const auto &C : ExnHandler.CatchClause) { - if (!C.IsAll && getTagInstByIdx(StackMgr, C.TagIndex) != TagInst) { + for (const auto &C : Handler->CatchClause) { + if (!C.IsAll && getTagInstByIdx(StackMgr, C.TagIndex) != &TagInst) { // For catching a specific tag, should check the equivalence of tag // address. continue; @@ -231,11 +232,11 @@ Expect Executor::throwException(Runtime::StackManager &StackMgr, // For catching a exception reference, push the reference value onto // stack. StackMgr.push( - RefVariant(ValType(TypeCode::Ref, TypeCode::ExnRef), TagInst)); + RefVariant(ValType(TypeCode::Ref, TypeCode::ExnRef), &TagInst)); } // When being here, an exception is caught. Move the PC to the try block // and branch to the label. - PC = ExnHandler.Try; + PC = Handler->Try; return branchToLabel(StackMgr, C.Jump, PC); } } diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index b7d38b6ede2f..607b08f78c3b 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -392,14 +392,8 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { case OpCode::Br: case OpCode::Br_if: case OpCode::Br_on_null: - case OpCode::Br_on_non_null: { - uint32_t LabelIdx = 0; - if (auto Res = readU32(LabelIdx); !Res) { - return Unexpect(Res); - } - Instr.setJump(LabelIdx); - return {}; - } + case OpCode::Br_on_non_null: + return readU32(Instr.getJump().TargetIndex); case OpCode::Br_table: { uint32_t VecCnt = 0; diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index a660968c4e39..b6bcb282f2ed 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -202,17 +202,6 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return static_cast(CtrlStack.size()) - UINT32_C(1) - N; }; - // Helper lambda for counting the try and catch. - auto countCtrlStackType = [this](uint32_t N) -> uint32_t { - uint32_t TryCnt = 0; - for (auto It = CtrlStack.begin() + N; It != CtrlStack.end(); It++) { - if (It->Code == OpCode::Try_table) { - TryCnt++; - } - } - return TryCnt; - }; - // Helper lambda for checking memory index and perform transformation. auto checkMemAndTrans = [this, &Instr](Span Take, @@ -275,14 +264,12 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { }; // Helper lambda for recording jump data. - auto recordJump = [this, &Instr, &countCtrlStackType]( - AST::Instruction::JumpDescriptor &Jump, uint32_t Arity, - uint32_t D) -> void { + auto recordJump = [this, &Instr](AST::Instruction::JumpDescriptor &Jump, + uint32_t Arity, uint32_t D) -> void { const uint32_t Remain = static_cast(ValStack.size() - CtrlStack[D].Height); - Jump.ValueStackEraseBegin = Remain + Arity; - Jump.ValueStackEraseEnd = Arity; - Jump.HandlerStackOffset = countCtrlStackType(D); + Jump.StackEraseBegin = Remain + Arity; + Jump.StackEraseEnd = Arity; Jump.PCOffset = static_cast(CtrlStack[D].Jump - &Instr); }; diff --git a/test/loader/serializeInstructionTest.cpp b/test/loader/serializeInstructionTest.cpp index 2342af2acd63..2c9133abbd32 100644 --- a/test/loader/serializeInstructionTest.cpp +++ b/test/loader/serializeInstructionTest.cpp @@ -220,7 +220,7 @@ TEST(SerializeInstructionTest, SerializeBrControlInstruction) { WasmEdge::AST::Instruction BrIf(WasmEdge::OpCode::Br_if); WasmEdge::AST::Instruction End(WasmEdge::OpCode::End); - Br.setJump(0xFFFFFFFFU); + Br.getJump().TargetIndex = 0xFFFFFFFFU; Instructions = {Br, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); @@ -236,7 +236,7 @@ TEST(SerializeInstructionTest, SerializeBrControlInstruction) { }; EXPECT_EQ(Output, Expected); - BrIf.setJump(0xFFFFFFFFU); + BrIf.getJump().TargetIndex = 0xFFFFFFFFU; Instructions = {BrIf, End}; Output = {}; EXPECT_TRUE(Ser.serializeSection(createCodeSec(Instructions), Output)); From 95ff7021e801916d8c663e604f1d9104eeedc7a0 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Tue, 9 Apr 2024 14:54:30 +0800 Subject: [PATCH 161/218] [Test] Add API test for tags. Signed-off-by: YiYing He --- test/api/APIUnitTest.cpp | 274 ++++++++++++++++++++------------ test/api/apiTestData/import.wat | 10 ++ 2 files changed, 186 insertions(+), 98 deletions(-) diff --git a/test/api/APIUnitTest.cpp b/test/api/APIUnitTest.cpp index aef4d3ce2007..9a3b365276db 100644 --- a/test/api/APIUnitTest.cpp +++ b/test/api/APIUnitTest.cpp @@ -93,86 +93,90 @@ std::vector TestWasm = { 0xd, 0x2, 0x0, 0x4, 0x67, 0x2d, 0x6d, 0x69, 0x1, 0x4, 0x67, 0x2d, 0x63, 0x66}; std::vector ImportWasm = { - 0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1d, 0x5, 0x60, - 0x0, 0x1, 0x7f, 0x60, 0x2, 0x6f, 0x7f, 0x1, 0x7f, 0x60, 0x2, 0x7f, - 0x7f, 0x1, 0x7f, 0x60, 0x2, 0x7f, 0x7f, 0x2, 0x7f, 0x7f, 0x60, 0x1, - 0x7f, 0x1, 0x7f, 0x2, 0xfb, 0x1, 0xe, 0x6, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x8, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x61, 0x64, 0x64, 0x0, - 0x1, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x8, 0x66, 0x75, 0x6e, - 0x63, 0x2d, 0x73, 0x75, 0x62, 0x0, 0x1, 0x6, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x8, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x6d, 0x75, 0x6c, 0x0, - 0x1, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x8, 0x66, 0x75, 0x6e, - 0x63, 0x2d, 0x64, 0x69, 0x76, 0x0, 0x1, 0x6, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x74, 0x65, 0x72, 0x6d, - 0x0, 0x0, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x9, 0x66, 0x75, - 0x6e, 0x63, 0x2d, 0x66, 0x61, 0x69, 0x6c, 0x0, 0x0, 0x5, 0x64, 0x75, - 0x6d, 0x6d, 0x79, 0x8, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x69, 0x33, 0x32, - 0x3, 0x7f, 0x1, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x8, 0x67, 0x6c, - 0x6f, 0x62, 0x2d, 0x69, 0x36, 0x34, 0x3, 0x7e, 0x0, 0x5, 0x64, 0x75, - 0x6d, 0x6d, 0x79, 0x8, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x66, 0x33, 0x32, - 0x3, 0x7d, 0x1, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x8, 0x67, 0x6c, - 0x6f, 0x62, 0x2d, 0x66, 0x36, 0x34, 0x3, 0x7c, 0x0, 0x5, 0x64, 0x75, - 0x6d, 0x6d, 0x79, 0x8, 0x74, 0x61, 0x62, 0x2d, 0x66, 0x75, 0x6e, 0x63, - 0x1, 0x70, 0x1, 0xa, 0x14, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x7, - 0x74, 0x61, 0x62, 0x2d, 0x65, 0x78, 0x74, 0x1, 0x6f, 0x1, 0xa, 0x1e, - 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x4, 0x6d, 0x65, 0x6d, 0x31, 0x2, - 0x1, 0x1, 0x3, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x4, 0x6d, 0x65, - 0x6d, 0x32, 0x2, 0x0, 0x2, 0x3, 0xc, 0xb, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x7, 0x2, 0x70, 0x0, - 0xa, 0x6f, 0x0, 0xa, 0x5, 0x4, 0x1, 0x1, 0x1, 0x3, 0x6, 0xf, - 0x2, 0x7f, 0x1, 0x41, 0x8e, 0x1, 0xb, 0x7d, 0x0, 0x43, 0xae, 0x47, - 0x45, 0x44, 0xb, 0x7, 0xcd, 0x1, 0x10, 0x6, 0x66, 0x75, 0x6e, 0x63, - 0x2d, 0x31, 0x0, 0x6, 0x6, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x32, 0x0, - 0x7, 0x6, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x33, 0x0, 0x8, 0x6, 0x66, - 0x75, 0x6e, 0x63, 0x2d, 0x34, 0x0, 0x9, 0x8, 0x66, 0x75, 0x6e, 0x63, - 0x2d, 0x61, 0x64, 0x64, 0x0, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x2d, - 0x6d, 0x75, 0x6c, 0x2d, 0x32, 0x0, 0xb, 0x12, 0x66, 0x75, 0x6e, 0x63, - 0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x2d, 0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x0, 0xc, 0xd, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x68, 0x6f, - 0x73, 0x74, 0x2d, 0x61, 0x64, 0x64, 0x0, 0xd, 0xd, 0x66, 0x75, 0x6e, - 0x63, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x75, 0x62, 0x0, 0xe, - 0xd, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x6d, - 0x75, 0x6c, 0x0, 0xf, 0xd, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x68, 0x6f, - 0x73, 0x74, 0x2d, 0x64, 0x69, 0x76, 0x0, 0x10, 0x8, 0x74, 0x61, 0x62, - 0x2d, 0x66, 0x75, 0x6e, 0x63, 0x1, 0x2, 0x7, 0x74, 0x61, 0x62, 0x2d, - 0x65, 0x78, 0x74, 0x1, 0x3, 0x3, 0x6d, 0x65, 0x6d, 0x2, 0x2, 0xc, - 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x6d, 0x75, 0x74, 0x2d, 0x69, 0x33, 0x32, - 0x3, 0x4, 0xe, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x2d, 0x66, 0x33, 0x32, 0x3, 0x5, 0x9, 0xc, 0x1, 0x2, 0x2, - 0x41, 0x2, 0xb, 0x0, 0x4, 0x6, 0x7, 0x8, 0x9, 0xa, 0x5e, 0xb, - 0x4, 0x0, 0x41, 0x1, 0xb, 0x4, 0x0, 0x41, 0x2, 0xb, 0x4, 0x0, - 0x41, 0x3, 0xb, 0x4, 0x0, 0x41, 0x4, 0xb, 0x7, 0x0, 0x20, 0x0, - 0x20, 0x1, 0x6a, 0xb, 0xc, 0x0, 0x20, 0x0, 0x41, 0x2, 0x6c, 0x20, - 0x1, 0x41, 0x2, 0x6c, 0xb, 0x7, 0x0, 0x20, 0x0, 0x11, 0x0, 0x2, - 0xb, 0xa, 0x0, 0x41, 0x0, 0x25, 0x3, 0x20, 0x0, 0x10, 0x0, 0xb, - 0xa, 0x0, 0x41, 0x1, 0x25, 0x3, 0x20, 0x0, 0x10, 0x1, 0xb, 0xa, - 0x0, 0x41, 0x2, 0x25, 0x3, 0x20, 0x0, 0x10, 0x2, 0xb, 0xa, 0x0, - 0x41, 0x3, 0x25, 0x3, 0x20, 0x0, 0x10, 0x3, 0xb, 0xb, 0x10, 0x1, - 0x0, 0x41, 0xa, 0xb, 0xa, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, - 0x7, 0x8, 0x9, 0x0, 0x8f, 0x2, 0x4, 0x6e, 0x61, 0x6d, 0x65, 0x1, - 0x8d, 0x1, 0x11, 0x0, 0x7, 0x65, 0x2d, 0x66, 0x2d, 0x61, 0x64, 0x64, - 0x1, 0x7, 0x65, 0x2d, 0x66, 0x2d, 0x73, 0x75, 0x62, 0x2, 0x7, 0x65, - 0x2d, 0x66, 0x2d, 0x6d, 0x75, 0x6c, 0x3, 0x7, 0x65, 0x2d, 0x66, 0x2d, - 0x64, 0x69, 0x76, 0x4, 0x8, 0x65, 0x2d, 0x66, 0x2d, 0x74, 0x65, 0x72, - 0x6d, 0x5, 0x8, 0x65, 0x2d, 0x66, 0x2d, 0x66, 0x61, 0x69, 0x6c, 0x6, - 0x3, 0x66, 0x2d, 0x31, 0x7, 0x3, 0x66, 0x2d, 0x32, 0x8, 0x3, 0x66, - 0x2d, 0x33, 0x9, 0x3, 0x66, 0x2d, 0x34, 0xa, 0x5, 0x66, 0x2d, 0x61, - 0x64, 0x64, 0xb, 0x7, 0x66, 0x2d, 0x6d, 0x75, 0x6c, 0x2d, 0x32, 0xc, - 0xa, 0x66, 0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x2d, 0x69, 0x6e, 0x64, 0xd, - 0x7, 0x66, 0x2d, 0x65, 0x2d, 0x61, 0x64, 0x64, 0xe, 0x7, 0x66, 0x2d, - 0x65, 0x2d, 0x73, 0x75, 0x62, 0xf, 0x7, 0x66, 0x2d, 0x65, 0x2d, 0x6d, - 0x75, 0x6c, 0x10, 0x7, 0x66, 0x2d, 0x65, 0x2d, 0x64, 0x69, 0x76, 0x2, - 0x45, 0x11, 0x0, 0x2, 0x0, 0x0, 0x1, 0x0, 0x1, 0x2, 0x0, 0x0, - 0x1, 0x0, 0x2, 0x2, 0x0, 0x0, 0x1, 0x0, 0x3, 0x2, 0x0, 0x0, - 0x1, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7, 0x0, 0x8, 0x0, - 0x9, 0x0, 0xa, 0x2, 0x0, 0x0, 0x1, 0x0, 0xb, 0x2, 0x0, 0x0, - 0x1, 0x0, 0xc, 0x1, 0x0, 0x0, 0xd, 0x1, 0x0, 0x0, 0xe, 0x1, - 0x0, 0x0, 0xf, 0x1, 0x0, 0x0, 0x10, 0x1, 0x0, 0x0, 0x4, 0xf, - 0x2, 0x0, 0x5, 0x74, 0x79, 0x70, 0x65, 0x30, 0x1, 0x5, 0x74, 0x79, - 0x70, 0x65, 0x31, 0x5, 0xb, 0x2, 0x2, 0x3, 0x74, 0x2d, 0x66, 0x3, - 0x3, 0x74, 0x2d, 0x65, 0x6, 0x4, 0x1, 0x0, 0x1, 0x6d, 0x7, 0xd, - 0x2, 0x4, 0x4, 0x67, 0x2d, 0x6d, 0x69, 0x5, 0x4, 0x67, 0x2d, 0x63, - 0x66}; + 0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x34, 0xa, 0x60, + 0x0, 0x1, 0x7f, 0x60, 0x2, 0x6f, 0x7f, 0x1, 0x7f, 0x60, 0x1, 0x7c, + 0x0, 0x60, 0x2, 0x7c, 0x7e, 0x0, 0x60, 0x0, 0x0, 0x60, 0x4, 0x7f, + 0x7e, 0x7d, 0x7c, 0x0, 0x60, 0x1, 0x7d, 0x0, 0x60, 0x2, 0x7f, 0x7f, + 0x1, 0x7f, 0x60, 0x2, 0x7f, 0x7f, 0x2, 0x7f, 0x7f, 0x60, 0x1, 0x7f, + 0x1, 0x7f, 0x2, 0xa5, 0x2, 0x11, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x8, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x61, 0x64, 0x64, 0x0, 0x1, + 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x8, 0x66, 0x75, 0x6e, 0x63, + 0x2d, 0x73, 0x75, 0x62, 0x0, 0x1, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x8, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x6d, 0x75, 0x6c, 0x0, 0x1, + 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x8, 0x66, 0x75, 0x6e, 0x63, + 0x2d, 0x64, 0x69, 0x76, 0x0, 0x1, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x74, 0x65, 0x72, 0x6d, 0x0, + 0x0, 0x6, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x9, 0x66, 0x75, 0x6e, + 0x63, 0x2d, 0x66, 0x61, 0x69, 0x6c, 0x0, 0x0, 0x5, 0x64, 0x75, 0x6d, + 0x6d, 0x79, 0x8, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x69, 0x33, 0x32, 0x3, + 0x7f, 0x1, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x8, 0x67, 0x6c, 0x6f, + 0x62, 0x2d, 0x69, 0x36, 0x34, 0x3, 0x7e, 0x0, 0x5, 0x64, 0x75, 0x6d, + 0x6d, 0x79, 0x8, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x66, 0x33, 0x32, 0x3, + 0x7d, 0x1, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x8, 0x67, 0x6c, 0x6f, + 0x62, 0x2d, 0x66, 0x36, 0x34, 0x3, 0x7c, 0x0, 0x5, 0x64, 0x75, 0x6d, + 0x6d, 0x79, 0x8, 0x74, 0x61, 0x62, 0x2d, 0x66, 0x75, 0x6e, 0x63, 0x1, + 0x70, 0x1, 0xa, 0x14, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x7, 0x74, + 0x61, 0x62, 0x2d, 0x65, 0x78, 0x74, 0x1, 0x6f, 0x1, 0xa, 0x1e, 0x5, + 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x4, 0x6d, 0x65, 0x6d, 0x31, 0x2, 0x1, + 0x1, 0x3, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x4, 0x6d, 0x65, 0x6d, + 0x32, 0x2, 0x0, 0x2, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x4, 0x74, + 0x61, 0x67, 0x31, 0x4, 0x0, 0x2, 0x5, 0x64, 0x75, 0x6d, 0x6d, 0x79, + 0x4, 0x74, 0x61, 0x67, 0x32, 0x4, 0x0, 0x3, 0x5, 0x64, 0x75, 0x6d, + 0x6d, 0x79, 0x4, 0x74, 0x61, 0x67, 0x33, 0x4, 0x0, 0x4, 0x3, 0xc, + 0xb, 0x0, 0x0, 0x0, 0x0, 0x7, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, + 0x4, 0x7, 0x2, 0x70, 0x0, 0xa, 0x6f, 0x0, 0xa, 0x5, 0x4, 0x1, + 0x1, 0x1, 0x3, 0xd, 0x7, 0x3, 0x0, 0x5, 0x0, 0x4, 0x0, 0x6, + 0x6, 0xf, 0x2, 0x7f, 0x1, 0x41, 0x8e, 0x1, 0xb, 0x7d, 0x0, 0x43, + 0xae, 0x47, 0x45, 0x44, 0xb, 0x7, 0xe5, 0x1, 0x13, 0x6, 0x66, 0x75, + 0x6e, 0x63, 0x2d, 0x31, 0x0, 0x6, 0x6, 0x66, 0x75, 0x6e, 0x63, 0x2d, + 0x32, 0x0, 0x7, 0x6, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x33, 0x0, 0x8, + 0x6, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x34, 0x0, 0x9, 0x8, 0x66, 0x75, + 0x6e, 0x63, 0x2d, 0x61, 0x64, 0x64, 0x0, 0xa, 0xa, 0x66, 0x75, 0x6e, + 0x63, 0x2d, 0x6d, 0x75, 0x6c, 0x2d, 0x32, 0x0, 0xb, 0x12, 0x66, 0x75, + 0x6e, 0x63, 0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x2d, 0x69, 0x6e, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x0, 0xc, 0xd, 0x66, 0x75, 0x6e, 0x63, 0x2d, + 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x61, 0x64, 0x64, 0x0, 0xd, 0xd, 0x66, + 0x75, 0x6e, 0x63, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x75, 0x62, + 0x0, 0xe, 0xd, 0x66, 0x75, 0x6e, 0x63, 0x2d, 0x68, 0x6f, 0x73, 0x74, + 0x2d, 0x6d, 0x75, 0x6c, 0x0, 0xf, 0xd, 0x66, 0x75, 0x6e, 0x63, 0x2d, + 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x64, 0x69, 0x76, 0x0, 0x10, 0x8, 0x74, + 0x61, 0x62, 0x2d, 0x66, 0x75, 0x6e, 0x63, 0x1, 0x2, 0x7, 0x74, 0x61, + 0x62, 0x2d, 0x65, 0x78, 0x74, 0x1, 0x3, 0x3, 0x6d, 0x65, 0x6d, 0x2, + 0x2, 0x5, 0x74, 0x61, 0x67, 0x2d, 0x31, 0x4, 0x3, 0x5, 0x74, 0x61, + 0x67, 0x2d, 0x32, 0x4, 0x4, 0x5, 0x74, 0x61, 0x67, 0x2d, 0x33, 0x4, + 0x5, 0xc, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x6d, 0x75, 0x74, 0x2d, 0x69, + 0x33, 0x32, 0x3, 0x4, 0xe, 0x67, 0x6c, 0x6f, 0x62, 0x2d, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x2d, 0x66, 0x33, 0x32, 0x3, 0x5, 0x9, 0xc, 0x1, + 0x2, 0x2, 0x41, 0x2, 0xb, 0x0, 0x4, 0x6, 0x7, 0x8, 0x9, 0xa, + 0x5e, 0xb, 0x4, 0x0, 0x41, 0x1, 0xb, 0x4, 0x0, 0x41, 0x2, 0xb, + 0x4, 0x0, 0x41, 0x3, 0xb, 0x4, 0x0, 0x41, 0x4, 0xb, 0x7, 0x0, + 0x20, 0x0, 0x20, 0x1, 0x6a, 0xb, 0xc, 0x0, 0x20, 0x0, 0x41, 0x2, + 0x6c, 0x20, 0x1, 0x41, 0x2, 0x6c, 0xb, 0x7, 0x0, 0x20, 0x0, 0x11, + 0x0, 0x2, 0xb, 0xa, 0x0, 0x41, 0x0, 0x25, 0x3, 0x20, 0x0, 0x10, + 0x0, 0xb, 0xa, 0x0, 0x41, 0x1, 0x25, 0x3, 0x20, 0x0, 0x10, 0x1, + 0xb, 0xa, 0x0, 0x41, 0x2, 0x25, 0x3, 0x20, 0x0, 0x10, 0x2, 0xb, + 0xa, 0x0, 0x41, 0x3, 0x25, 0x3, 0x20, 0x0, 0x10, 0x3, 0xb, 0xb, + 0x10, 0x1, 0x0, 0x41, 0xa, 0xb, 0xa, 0x0, 0x1, 0x2, 0x3, 0x4, + 0x5, 0x6, 0x7, 0x8, 0x9, 0x0, 0xe0, 0x1, 0x4, 0x6e, 0x61, 0x6d, + 0x65, 0x1, 0x8d, 0x1, 0x11, 0x0, 0x7, 0x65, 0x2d, 0x66, 0x2d, 0x61, + 0x64, 0x64, 0x1, 0x7, 0x65, 0x2d, 0x66, 0x2d, 0x73, 0x75, 0x62, 0x2, + 0x7, 0x65, 0x2d, 0x66, 0x2d, 0x6d, 0x75, 0x6c, 0x3, 0x7, 0x65, 0x2d, + 0x66, 0x2d, 0x64, 0x69, 0x76, 0x4, 0x8, 0x65, 0x2d, 0x66, 0x2d, 0x74, + 0x65, 0x72, 0x6d, 0x5, 0x8, 0x65, 0x2d, 0x66, 0x2d, 0x66, 0x61, 0x69, + 0x6c, 0x6, 0x3, 0x66, 0x2d, 0x31, 0x7, 0x3, 0x66, 0x2d, 0x32, 0x8, + 0x3, 0x66, 0x2d, 0x33, 0x9, 0x3, 0x66, 0x2d, 0x34, 0xa, 0x5, 0x66, + 0x2d, 0x61, 0x64, 0x64, 0xb, 0x7, 0x66, 0x2d, 0x6d, 0x75, 0x6c, 0x2d, + 0x32, 0xc, 0xa, 0x66, 0x2d, 0x63, 0x61, 0x6c, 0x6c, 0x2d, 0x69, 0x6e, + 0x64, 0xd, 0x7, 0x66, 0x2d, 0x65, 0x2d, 0x61, 0x64, 0x64, 0xe, 0x7, + 0x66, 0x2d, 0x65, 0x2d, 0x73, 0x75, 0x62, 0xf, 0x7, 0x66, 0x2d, 0x65, + 0x2d, 0x6d, 0x75, 0x6c, 0x10, 0x7, 0x66, 0x2d, 0x65, 0x2d, 0x64, 0x69, + 0x76, 0x4, 0xf, 0x2, 0x0, 0x5, 0x74, 0x79, 0x70, 0x65, 0x30, 0x1, + 0x5, 0x74, 0x79, 0x70, 0x65, 0x31, 0x5, 0xb, 0x2, 0x2, 0x3, 0x74, + 0x2d, 0x66, 0x3, 0x3, 0x74, 0x2d, 0x65, 0x6, 0x4, 0x1, 0x2, 0x1, + 0x6d, 0x7, 0xd, 0x2, 0x4, 0x4, 0x67, 0x2d, 0x6d, 0x69, 0x5, 0x4, + 0x67, 0x2d, 0x63, 0x66, 0xb, 0x16, 0x3, 0x3, 0x5, 0x74, 0x61, 0x67, + 0x2d, 0x31, 0x4, 0x5, 0x74, 0x61, 0x67, 0x2d, 0x32, 0x5, 0x5, 0x74, + 0x61, 0x67, 0x2d, 0x33}; std::vector FibonacciWasm = { 0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x6, 0x1, @@ -814,7 +818,10 @@ TEST(APICoreTest, ImportType) { const WasmEdge_ImportTypeContext *ImpTypes[20]; WasmEdge_Limit Lim; WasmEdge_String Name; - WasmEdge_LoaderContext *Loader = WasmEdge_LoaderCreate(nullptr); + WasmEdge_ConfigureContext *Conf = WasmEdge_ConfigureCreate(); + WasmEdge_ConfigureAddProposal(Conf, WasmEdge_Proposal_ExceptionHandling); + WasmEdge_LoaderContext *Loader = WasmEdge_LoaderCreate(Conf); + WasmEdge_ConfigureDelete(Conf); // Load AST module from buffer EXPECT_TRUE(WasmEdge_ResultOK(WasmEdge_LoaderParseFromBytes( @@ -825,11 +832,11 @@ TEST(APICoreTest, ImportType) { // AST list imports EXPECT_EQ(WasmEdge_ASTModuleListImportsLength(nullptr), 0U); - EXPECT_EQ(WasmEdge_ASTModuleListImportsLength(Mod), 14U); + EXPECT_EQ(WasmEdge_ASTModuleListImportsLength(Mod), 17U); EXPECT_EQ(WasmEdge_ASTModuleListImports(nullptr, ImpTypes, 20), 0U); - EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, nullptr, 20), 14U); + EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, nullptr, 20), 17U); std::memset(ImpTypes, 0, sizeof(const WasmEdge_ImportTypeContext *) * 20); - EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, ImpTypes, 4), 14U); + EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, ImpTypes, 4), 17U); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[0]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[0]); @@ -855,7 +862,7 @@ TEST(APICoreTest, ImportType) { Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[3]); EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "extern"sv); std::memset(ImpTypes, 0, sizeof(const WasmEdge_ImportTypeContext *) * 20); - EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, ImpTypes, 20), 14U); + EXPECT_EQ(WasmEdge_ASTModuleListImports(Mod, ImpTypes, 20), 17U); EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[4]), WasmEdge_ExternalType_Function); Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[4]); @@ -916,6 +923,24 @@ TEST(APICoreTest, ImportType) { EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "mem2"sv); Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[13]); EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); + EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[14]), + WasmEdge_ExternalType_Tag); + Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[14]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tag1"sv); + Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[14]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); + EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[15]), + WasmEdge_ExternalType_Tag); + Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[15]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tag2"sv); + Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[15]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); + EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(ImpTypes[16]), + WasmEdge_ExternalType_Tag); + Name = WasmEdge_ImportTypeGetExternalName(ImpTypes[16]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tag3"sv); + Name = WasmEdge_ImportTypeGetModuleName(ImpTypes[16]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "dummy"sv); // Import type get external type EXPECT_EQ(WasmEdge_ImportTypeGetExternalType(nullptr), @@ -974,6 +999,25 @@ TEST(APICoreTest, ImportType) { WasmEdge_ImportTypeGetMemoryType(Mod, ImpTypes[13])), Lim)); + // Import type get tag type + EXPECT_EQ(WasmEdge_ImportTypeGetTagType(nullptr, nullptr), nullptr); + EXPECT_EQ(WasmEdge_ImportTypeGetTagType(Mod, nullptr), nullptr); + EXPECT_EQ(WasmEdge_ImportTypeGetTagType(nullptr, ImpTypes[15]), nullptr); + EXPECT_EQ(WasmEdge_ImportTypeGetTagType(Mod, ImpTypes[0]), nullptr); + EXPECT_NE(WasmEdge_ImportTypeGetTagType(Mod, ImpTypes[15]), nullptr); + EXPECT_EQ(WasmEdge_TagTypeGetFunctionType(nullptr), nullptr); + EXPECT_NE(WasmEdge_TagTypeGetFunctionType( + WasmEdge_ImportTypeGetTagType(Mod, ImpTypes[15])), + nullptr); + EXPECT_EQ( + WasmEdge_FunctionTypeGetParametersLength(WasmEdge_TagTypeGetFunctionType( + WasmEdge_ImportTypeGetTagType(Mod, ImpTypes[15]))), + 2U); + EXPECT_EQ( + WasmEdge_FunctionTypeGetReturnsLength(WasmEdge_TagTypeGetFunctionType( + WasmEdge_ImportTypeGetTagType(Mod, ImpTypes[15]))), + 0U); + // Import type get global type EXPECT_EQ(WasmEdge_ImportTypeGetGlobalType(nullptr, nullptr), nullptr); EXPECT_EQ(WasmEdge_ImportTypeGetGlobalType(Mod, nullptr), nullptr); @@ -995,7 +1039,10 @@ TEST(APICoreTest, ExportType) { const WasmEdge_ExportTypeContext *ExpTypes[20]; WasmEdge_Limit Lim; WasmEdge_String Name; - WasmEdge_LoaderContext *Loader = WasmEdge_LoaderCreate(nullptr); + WasmEdge_ConfigureContext *Conf = WasmEdge_ConfigureCreate(); + WasmEdge_ConfigureAddProposal(Conf, WasmEdge_Proposal_ExceptionHandling); + WasmEdge_LoaderContext *Loader = WasmEdge_LoaderCreate(Conf); + WasmEdge_ConfigureDelete(Conf); // Load AST module from buffer EXPECT_TRUE(WasmEdge_ResultOK(WasmEdge_LoaderParseFromBytes( @@ -1006,11 +1053,11 @@ TEST(APICoreTest, ExportType) { // AST list exports EXPECT_EQ(WasmEdge_ASTModuleListExportsLength(nullptr), 0U); - EXPECT_EQ(WasmEdge_ASTModuleListExportsLength(Mod), 16U); + EXPECT_EQ(WasmEdge_ASTModuleListExportsLength(Mod), 19U); EXPECT_EQ(WasmEdge_ASTModuleListExports(nullptr, ExpTypes, 20), 0U); - EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, nullptr, 20), 16U); + EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, nullptr, 20), 19U); std::memset(ExpTypes, 0, sizeof(const WasmEdge_ExportTypeContext *) * 20); - EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, ExpTypes, 4), 16U); + EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, ExpTypes, 4), 19U); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[0]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[0]); @@ -1028,7 +1075,7 @@ TEST(APICoreTest, ExportType) { Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[3]); EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "func-4"sv); std::memset(ExpTypes, 0, sizeof(const WasmEdge_ExportTypeContext *) * 20); - EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, ExpTypes, 20), 16U); + EXPECT_EQ(WasmEdge_ASTModuleListExports(Mod, ExpTypes, 20), 19U); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[4]), WasmEdge_ExternalType_Function); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[4]); @@ -1070,18 +1117,30 @@ TEST(APICoreTest, ExportType) { Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[13]); EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "mem"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[14]), - WasmEdge_ExternalType_Global); + WasmEdge_ExternalType_Tag); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[14]); - EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-mut-i32"sv); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tag-1"sv); EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[15]), - WasmEdge_ExternalType_Global); + WasmEdge_ExternalType_Tag); Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[15]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tag-2"sv); + EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[16]), + WasmEdge_ExternalType_Tag); + Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[16]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "tag-3"sv); + EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[17]), + WasmEdge_ExternalType_Global); + Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[17]); + EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-mut-i32"sv); + EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[18]), + WasmEdge_ExternalType_Global); + Name = WasmEdge_ExportTypeGetExternalName(ExpTypes[18]); EXPECT_EQ(std::string_view(Name.Buf, Name.Length), "glob-const-f32"sv); // Export type get external type EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(nullptr), WasmEdge_ExternalType_Function); - EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[15]), + EXPECT_EQ(WasmEdge_ExportTypeGetExternalType(ExpTypes[18]), WasmEdge_ExternalType_Global); // Export type get external name @@ -1129,16 +1188,35 @@ TEST(APICoreTest, ExportType) { WasmEdge_ExportTypeGetMemoryType(Mod, ExpTypes[13])), Lim)); + // Export type get tag type + EXPECT_EQ(WasmEdge_ExportTypeGetTagType(nullptr, nullptr), nullptr); + EXPECT_EQ(WasmEdge_ExportTypeGetTagType(Mod, nullptr), nullptr); + EXPECT_EQ(WasmEdge_ExportTypeGetTagType(nullptr, ExpTypes[14]), nullptr); + EXPECT_EQ(WasmEdge_ExportTypeGetTagType(Mod, ExpTypes[0]), nullptr); + EXPECT_NE(WasmEdge_ExportTypeGetTagType(Mod, ExpTypes[14]), nullptr); + EXPECT_EQ(WasmEdge_TagTypeGetFunctionType(nullptr), nullptr); + EXPECT_NE(WasmEdge_TagTypeGetFunctionType( + WasmEdge_ExportTypeGetTagType(Mod, ExpTypes[14])), + nullptr); + EXPECT_EQ( + WasmEdge_FunctionTypeGetParametersLength(WasmEdge_TagTypeGetFunctionType( + WasmEdge_ExportTypeGetTagType(Mod, ExpTypes[14]))), + 4U); + EXPECT_EQ( + WasmEdge_FunctionTypeGetReturnsLength(WasmEdge_TagTypeGetFunctionType( + WasmEdge_ExportTypeGetTagType(Mod, ExpTypes[14]))), + 0U); + // Export type get global type EXPECT_EQ(WasmEdge_ExportTypeGetGlobalType(nullptr, nullptr), nullptr); EXPECT_EQ(WasmEdge_ExportTypeGetGlobalType(Mod, nullptr), nullptr); - EXPECT_EQ(WasmEdge_ExportTypeGetGlobalType(nullptr, ExpTypes[15]), nullptr); + EXPECT_EQ(WasmEdge_ExportTypeGetGlobalType(nullptr, ExpTypes[18]), nullptr); EXPECT_EQ(WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[0]), nullptr); - EXPECT_NE(WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[15]), nullptr); + EXPECT_NE(WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[18]), nullptr); EXPECT_TRUE(WasmEdge_ValTypeIsF32(WasmEdge_GlobalTypeGetValType( - WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[15])))); + WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[18])))); EXPECT_EQ(WasmEdge_GlobalTypeGetMutability( - WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[15])), + WasmEdge_ExportTypeGetGlobalType(Mod, ExpTypes[18])), WasmEdge_Mutability_Const); WasmEdge_LoaderDelete(Loader); diff --git a/test/api/apiTestData/import.wat b/test/api/apiTestData/import.wat index 12eaa02b4c41..5b27ea46ecc1 100644 --- a/test/api/apiTestData/import.wat +++ b/test/api/apiTestData/import.wat @@ -15,6 +15,9 @@ (import "dummy" "tab-ext" (table 10 30 externref)) (import "dummy" "mem1" (memory 1 3)) (import "dummy" "mem2" (memory 2)) + (import "dummy" "tag1" (tag (param f64))) + (import "dummy" "tag2" (tag (param f64 i64))) + (import "dummy" "tag3" (tag)) (export "func-1" (func $f-1)) (export "func-2" (func $f-2)) (export "func-3" (func $f-3)) @@ -29,9 +32,16 @@ (export "tab-func" (table $t-f)) (export "tab-ext" (table $t-e)) (export "mem" (memory $m)) + (export "tag-1" (tag $tag-1)) + (export "tag-2" (tag $tag-2)) + (export "tag-3" (tag $tag-3)) (export "glob-mut-i32" (global $g-mi)) (export "glob-const-f32" (global $g-cf)) + (tag $tag-1 (param i32 i64 f32 f64)) + (tag $tag-2) + (tag $tag-3 (param f32)) + (func $f-1 (result i32) (i32.const 1)) (func $f-2 (result i32) (i32.const 2)) (func $f-3 (result i32) (i32.const 3)) From ad29362d941dc1ec4bf209b039ab52466fdcb8f8 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Tue, 16 Apr 2024 19:08:02 +0800 Subject: [PATCH 162/218] [Misc] Support old `try`, `catch`, and `catch_all` instructions for exception-handling proposal. Signed-off-by: YiYing He --- include/ast/instruction.h | 19 ++++++ include/common/configure.h | 4 +- include/common/enum.inc | 12 ++-- lib/executor/engine/engine.cpp | 9 +++ lib/executor/helper.cpp | 9 +++ lib/loader/ast/instruction.cpp | 114 +++++++++++++++++++++++++-------- lib/validator/formchecker.cpp | 74 ++++++++++++++++++++- test/spec/CMakeLists.txt | 2 +- test/spec/spectest.cpp | 4 ++ 9 files changed, 211 insertions(+), 36 deletions(-) diff --git a/include/ast/instruction.h b/include/ast/instruction.h index 23658222db2b..c2bbe9f22530 100644 --- a/include/ast/instruction.h +++ b/include/ast/instruction.h @@ -37,6 +37,8 @@ class Instruction { ValType RType1, RType2; }; struct CatchDescriptor { + // LEGACY-EH: remove this flag after deprecating legacy EH. + bool IsLegacy : 1; bool IsAll : 1; bool IsRef : 1; uint32_t TagIndex; @@ -49,6 +51,13 @@ class Instruction { uint32_t JumpEnd; std::vector Catch; }; + // LEGACY-EH: remove this struct after deprecating legacy EH. + struct CatchDescriptorLegacy { + uint32_t TagIndex; + uint32_t LabelIndex; + uint32_t CatchIndex; + uint32_t CatchPCOffset; + }; public: /// Constructor assigns the OpCode and the Offset. @@ -208,6 +217,13 @@ class Instruction { uint8_t getMemoryLane() const noexcept { return Data.Memories.MemLane; } uint8_t &getMemoryLane() noexcept { return Data.Memories.MemLane; } + // LEGACY-EH: remove these functions after deprecating legacy EH. + /// Getter and setter of legacy Catch for Catch* instructions. + const CatchDescriptorLegacy &getCatchLegacy() const noexcept { + return Data.CatchLegacy; + } + CatchDescriptorLegacy &getCatchLegacy() noexcept { return Data.CatchLegacy; } + /// Getter and setter of the constant value. ValVariant getNum() const noexcept { #if defined(__x86_64__) || defined(__aarch64__) || \ @@ -329,6 +345,9 @@ class Instruction { BrCastDescriptor *BrCast; // Type 11: Try Block. TryDescriptor *TryCatch; + // LEGACY-EH: remove the this case after deprecating legacy EH. + // Type 12: Legacy Catch descriptor. + CatchDescriptorLegacy CatchLegacy; } Data; uint32_t Offset = 0; OpCode Code = OpCode::End; diff --git a/include/common/configure.h b/include/common/configure.h index c3e33508f0c2..bc62eea16ae8 100644 --- a/include/common/configure.h +++ b/include/common/configure.h @@ -357,8 +357,10 @@ class Configure { if (!hasProposal(Proposal::GC)) { return Proposal::GC; } - } else if (Code == OpCode::Throw || Code == OpCode::Throw_ref || + } else if ((Code >= OpCode::Try && Code <= OpCode::Throw_ref) || + Code == OpCode::Delegate || Code == OpCode::Catch_all || Code == OpCode::Try_table) { + // LEGACY-EH: remove the old instructions after deprecating legacy EH. // These instructions are for ExceptionHandling proposal. if (!hasProposal(Proposal::ExceptionHandling)) { return Proposal::ExceptionHandling; diff --git a/include/common/enum.inc b/include/common/enum.inc index 5f6ab310e414..cf55fbdc8424 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -101,10 +101,10 @@ O(Block, "block", 0x02) O(Loop, "loop", 0x03) O(If, "if", 0x04) O(Else, "else", 0x05) -// 0x06: Reserved -// 0x07: Reserved +O(Try, "try", 0x06) // For legacy EH proposal +O(Catch, "catch", 0x07) // For legacy EH proposal O(Throw, "throw", 0x08) -// 0x09: Reserved +O(Rethrow, "rethrow", 0x09) // For legacy EH proposal O(Throw_ref, "throw_ref", 0x0A) O(End, "end", 0x0B) O(Br, "br", 0x0C) @@ -119,8 +119,8 @@ O(Call_ref, "call_ref", 0x14) O(Return_call_ref, "return_call_ref", 0x15) // 0x16: Reserved // 0x17: Reserved -// 0x18: Reserved -// 0x19: Reserved +O(Delegate, "delegate", 0x18) // For legacy EH proposal +O(Catch_all, "catch_all", 0x19) // For legacy EH proposal // Parametric Instructions O(Drop, "drop", 0x1A) @@ -315,7 +315,7 @@ O(Ref__func, "ref.func", 0xD2) O(Ref__eq, "ref.eq", 0xD3) O(Ref__as_non_null, "ref.as_non_null", 0xD4) -// Control Instructions (part 2) +// Control Instructions (part 3) O(Br_on_null, "br_on_null", 0xD5) O(Br_on_non_null, "br_on_non_null", 0xD6) // 0xD7 ~ 0xFA: Reserved diff --git a/lib/executor/engine/engine.cpp b/lib/executor/engine/engine.cpp index 945d6bf24599..605498527059 100644 --- a/lib/executor/engine/engine.cpp +++ b/lib/executor/engine/engine.cpp @@ -141,6 +141,9 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, case OpCode::End: PC = StackMgr.maybePopFrameOrHandler(PC); return {}; + // LEGACY-EH: remove the `Try` cases after deprecating legacy EH. + case OpCode::Try: + return runTryTableOp(StackMgr, Instr, PC); case OpCode::Throw: return runThrowOp(StackMgr, Instr, PC); case OpCode::Throw_ref: @@ -173,6 +176,12 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, return runCallRefOp(StackMgr, Instr, PC); case OpCode::Return_call_ref: return runCallRefOp(StackMgr, Instr, PC, true); + // LEGACY-EH: remove the `Catch` cases after deprecating legacy EH. + case OpCode::Catch: + case OpCode::Catch_all: + PC -= Instr.getCatchLegacy().CatchPCOffset; + PC += PC->getTryCatch().JumpEnd; + return {}; case OpCode::Try_table: return runTryTableOp(StackMgr, Instr, PC); diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 7b7ddbb7a6d8..91e315483315 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -236,6 +236,15 @@ Expect Executor::throwException(Runtime::StackManager &StackMgr, } // When being here, an exception is caught. Move the PC to the try block // and branch to the label. + + // LEGACY-EH: remove this condition after deprecating legacy EH. + // For legacy catch/catch_all, the target block to jump is inside the try + // block, and it must pass through the end instruction of the try block + // and pop the handler. Therefore push the handler back here. + if (C.IsLegacy) { + StackMgr.pushHandler(Handler->Try, 0, {}); + } + PC = Handler->Try; return branchToLabel(StackMgr, C.Jump, PC); } diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index 607b08f78c3b..b217fdc58de7 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -156,33 +156,58 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { ASTNodeAttr::Instruction); } - // Process the instructions which contain a block. - if (Code == OpCode::Block || Code == OpCode::Loop || Code == OpCode::If || - Code == OpCode::Try_table) { - BlockStack.push_back(std::make_pair(Code, Cnt)); - } else if (Code == OpCode::Else) { + auto logIllegalOpCode = [this, &Offset, + &SizeBound]() -> Unexpected { + if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { + return logLoadError(ErrCode::Value::ENDCodeExpected, Offset, + ASTNodeAttr::Instruction); + } else { + return logLoadError(ErrCode::Value::IllegalOpCode, Offset, + ASTNodeAttr::Instruction); + } + }; + + // Process the instruction which contains a block. + switch (Code) { + case OpCode::Block: + case OpCode::Loop: + case OpCode::If: + // LEGACY-EH: remove the `Try` after deprecating legacy EH. + case OpCode::Try: + case OpCode::Try_table: + BlockStack.emplace_back(Code, Cnt); + break; + case OpCode::Else: { if (BlockStack.size() == 0 || BlockStack.back().first != OpCode::If) { // An Else instruction appeared outside the If-block. - if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { - return logLoadError(ErrCode::Value::ENDCodeExpected, Offset, - ASTNodeAttr::Instruction); - } else { - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } + return logIllegalOpCode(); } uint32_t Pos = BlockStack.back().second; if (Instrs[Pos].getJumpElse() > 0) { // An Else instruction appeared before in this If-block. - if (SizeBound.has_value() && FMgr.getOffset() > SizeBound.value()) { - return logLoadError(ErrCode::Value::ENDCodeExpected, Offset, - ASTNodeAttr::Instruction); - } else { - return logLoadError(ErrCode::Value::IllegalOpCode, Offset, - ASTNodeAttr::Instruction); - } + return logIllegalOpCode(); } Instrs[Pos].setJumpElse(Cnt - Pos); + break; + } + // LEGACY-EH: remove the `Catch` cases after deprecating legacy EH. + case OpCode::Catch: + case OpCode::Catch_all: { + if (BlockStack.size() == 0 || BlockStack.back().first != OpCode::Try) { + // A Catch/Catch_all instruction appeared outside a try-block. + return logIllegalOpCode(); + } + auto Pos = BlockStack.back().second; + auto &CatchClause = Instrs[Pos].getTryCatch().Catch; + if (CatchClause.size() > 0 && CatchClause.back().IsAll) { + // A Catch shouldn't behind a Catch_all in the same block. + // And also a try block may contain only one Catch_all instruction. + return logIllegalOpCode(); + } + break; + } + default: + break; } // Create the instruction node and load contents. @@ -191,8 +216,8 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { return Unexpect(Res); } - // Process the End instruction. if (Code == OpCode::End) { + // Post process the End instruction. if (BlockStack.size() > 0) { Instrs.back().setExprLast(false); const auto &[BackOp, Pos] = BlockStack.back(); @@ -209,7 +234,8 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { Instrs[ElsePos].setJumpEnd(Cnt - ElsePos); } } - } else if (BackOp == OpCode::Try_table) { + } else if (BackOp == OpCode::Try || BackOp == OpCode::Try_table) { + // LEGACY-EH: remove the `Try` case after deprecating legacy EH. Instrs.back().setTryBlockLast(true); Instrs[Pos].getTryCatch().JumpEnd = Cnt - Pos; } @@ -218,6 +244,19 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { Instrs.back().setExprLast(true); IsReachEnd = true; } + } else if (Code == OpCode::Catch || Code == OpCode::Catch_all) { + // LEGACY-EH: remove these cases after deprecating legacy EH. + uint32_t Pos = BlockStack.back().second; + auto &CatchClause = Instrs[Pos].getTryCatch().Catch; + auto &CatchDesc = Instrs.back().getCatchLegacy(); + CatchDesc.CatchPCOffset = Cnt - Pos; + CatchDesc.CatchIndex = static_cast(CatchClause.size()); + CatchClause.push_back({true, + Code == OpCode::Catch_all, + false, + Code == OpCode::Catch ? CatchDesc.TagIndex : 0, + 0, + {0, 0, 0, 0}}); } Cnt++; } while (!IsReachEnd); @@ -336,6 +375,8 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { case OpCode::Throw_ref: case OpCode::End: case OpCode::Else: + // LEGACY-EH: remove the `Catch_all` case after deprecating legacy EH. + case OpCode::Catch_all: return {}; case OpCode::Block: @@ -362,12 +403,10 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { auto &Desc = Instr.getTryCatch().Catch[I]; // Read the catch flag. if (auto Res = FMgr.readByte()) { - if (*Res & 0x01U) { - Desc.IsRef = true; - } - if (*Res & 0x02U) { - Desc.IsAll = true; - } + // LEGACY-EH: remove this flag after deprecating legacy EH. + Desc.IsLegacy = false; + Desc.IsRef = (*Res & 0x01U) ? true : false; + Desc.IsAll = (*Res & 0x02U) ? true : false; } else { return logLoadError(Res.error(), FMgr.getLastOffset(), ASTNodeAttr::Instruction); @@ -386,15 +425,36 @@ Expect Loader::loadInstruction(AST::Instruction &Instr) { return {}; } + // LEGACY-EH: remove the `Try` case after deprecating legacy EH. + case OpCode::Try: + Instr.setTryCatch(); + return readBlockType(Instr.getTryCatch().ResType); + + // LEGACY-EH: remove the `Catch` case after deprecating legacy EH. + case OpCode::Catch: + return readU32(Instr.getCatchLegacy().TagIndex); + case OpCode::Throw: return readU32(Instr.getTargetIndex()); + // LEGACY-EH: remove the `Rethrow` case after deprecating legacy EH. + case OpCode::Rethrow: + spdlog::error(ErrCode::Value::IllegalOpCode); + spdlog::error(" Deprecated `rethrow` instruction."); + return Unexpect(ErrCode::Value::IllegalOpCode); + case OpCode::Br: case OpCode::Br_if: case OpCode::Br_on_null: case OpCode::Br_on_non_null: return readU32(Instr.getJump().TargetIndex); + // LEGACY-EH: remove the `Delegate` case after deprecating legacy EH. + case OpCode::Delegate: + spdlog::error(ErrCode::Value::IllegalOpCode); + spdlog::error(" Deprecated `delegate` instruction."); + return Unexpect(ErrCode::Value::IllegalOpCode); + case OpCode::Br_table: { uint32_t VecCnt = 0; // Read the vector of labels. diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index b6bcb282f2ed..02bb4a37cea8 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -322,11 +322,15 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { case OpCode::Block: case OpCode::Loop: case OpCode::If: + // LEGACY-EH: remove the `Try` case after deprecating legacy EH. + case OpCode::Try: case OpCode::Try_table: { // Get blocktype [t1*] -> [t2*] and check valtype first. std::vector Buffer(1); Span T1, T2; - const auto &BType = (Instr.getOpCode() == OpCode::Try_table) + // LEGACY-EH: remove the `Try` case after deprecating legacy EH. + const auto &BType = (Instr.getOpCode() == OpCode::Try || + Instr.getOpCode() == OpCode::Try_table) ? Instr.getTryCatch().ResType : Instr.getBlockType(); if (auto Res = checkBlockType(Buffer, BType)) { @@ -384,6 +388,11 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { return Unexpect(D); } } + } else if (Instr.getOpCode() == OpCode::Try) { + // LEGACY-EH: remove the `Try` case after deprecating legacy EH. + const auto &TryDesc = Instr.getTryCatch(); + const_cast(TryDesc).BlockParamNum = + static_cast(T1.size()); } // Push ctrl frame ([t1*], [t2*]) const AST::Instruction *From = Instr.getOpCode() == OpCode::Loop @@ -408,6 +417,36 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } return {}; + // LEGACY-EH: remove the `Catch` after deprecating legacy EH. + case OpCode::Catch: { + const auto &CatchDesc = Instr.getCatchLegacy(); + // Check tag index. + if (unlikely(CatchDesc.TagIndex >= Tags.size())) { + return logOutOfRange(ErrCode::Value::InvalidTagIdx, + ErrInfo::IndexCategory::Tag, CatchDesc.TagIndex, + static_cast(Tags.size())); + } + const auto &NTypes = Types[Tags[CatchDesc.TagIndex]] + ->getCompositeType() + .getFuncType() + .getParamTypes(); + const auto &TryInstr = *(&Instr - CatchDesc.CatchPCOffset); + const auto &Catch = TryInstr.getTryCatch().Catch[CatchDesc.CatchIndex]; + if (auto Res = popCtrl()) { + // The continue block PC offset is the next of this instruction. + auto &Jump = const_cast(Catch.Jump); + Jump.StackEraseBegin = + static_cast(ValStack.size() - Res->Height) + + static_cast(NTypes.size()); + Jump.StackEraseEnd = static_cast(NTypes.size()); + Jump.PCOffset = static_cast(CatchDesc.CatchPCOffset + 1); + pushCtrl(NTypes, Res->EndTypes, Res->Jump, Instr.getOpCode()); + } else { + return Unexpect(Res); + } + return {}; + } + case OpCode::Throw: if (unlikely(Instr.getTargetIndex() >= Tags.size())) { return logOutOfRange(ErrCode::Value::InvalidTagIdx, @@ -424,6 +463,13 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } else { return Unexpect(CompType); } + + // LEGACY-EH: remove the `Rethrow` after deprecating legacy EH. + case OpCode::Rethrow: + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(" Deprecated `rethrow` instruction."); + return Unexpect(ErrCode::Value::TypeCheckFailed); + case OpCode::Throw_ref: if (auto Res = popType(TypeCode::ExnRef); !Res) { return Unexpect(Res); @@ -550,6 +596,7 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } else { return Unexpect(D); } + case OpCode::Br_on_non_null: if (auto D = checkCtrlStackDepth(Instr.getJump().TargetIndex)) { // Get the result type of the label. (Should be [t* rt].) @@ -704,6 +751,31 @@ Expect FormChecker::checkInstr(const AST::Instruction &Instr) { } } + // LEGACY-EH: remove the `Catch_all` after deprecating legacy EH. + case OpCode::Catch_all: { + const auto &CatchDesc = Instr.getCatchLegacy(); + const auto &TryInstr = *(&Instr - CatchDesc.CatchPCOffset); + const auto &Catch = TryInstr.getTryCatch().Catch[CatchDesc.CatchIndex]; + if (auto Res = popCtrl()) { + // The continue block PC offset is the next of this instruction. + auto &Jump = const_cast(Catch.Jump); + Jump.StackEraseBegin = + static_cast(ValStack.size() - Res->Height); + Jump.StackEraseEnd = 0; + Jump.PCOffset = static_cast(CatchDesc.CatchPCOffset + 1); + pushCtrl({}, Res->EndTypes, Res->Jump, Instr.getOpCode()); + } else { + return Unexpect(Res); + } + return {}; + } + + // LEGACY-EH: remove the `Delegate` after deprecating legacy EH. + case OpCode::Delegate: + spdlog::error(ErrCode::Value::TypeCheckFailed); + spdlog::error(" Deprecated `delegate` instruction."); + return Unexpect(ErrCode::Value::TypeCheckFailed); + // Reference Instructions. case OpCode::Ref__null: if (auto Res = validate(Instr.getValType())) { diff --git a/test/spec/CMakeLists.txt b/test/spec/CMakeLists.txt index efad35596ba8..c8883d3994dc 100644 --- a/test/spec/CMakeLists.txt +++ b/test/spec/CMakeLists.txt @@ -76,7 +76,7 @@ function(wasmedge_copy_spec_testsuite proposal) message(STATUS "Copying test suite to ${CMAKE_CURRENT_BINARY_DIR}/testSuites/${proposal} -- done") endfunction() -foreach(PROPOSAL core multi-memory tail-call extended-const threads function-references gc exception-handling) +foreach(PROPOSAL core multi-memory tail-call extended-const threads function-references gc exception-handling exception-handling-legacy) wasmedge_copy_spec_testsuite(${PROPOSAL}) endforeach() diff --git a/test/spec/spectest.cpp b/test/spec/spectest.cpp index 5c488285cb0a..bb2bbf5fc77d 100644 --- a/test/spec/spectest.cpp +++ b/test/spec/spectest.cpp @@ -263,6 +263,10 @@ static const TestsuiteProposal TestsuiteProposals[] = { {"exception-handling"sv, {Proposal::ExceptionHandling, Proposal::TailCall}, WasmEdge::SpecTest::TestMode::Interpreter}, + // LEGACY-EH: remove the legacy EH test after deprecating legacy EH. + {"exception-handling-legacy"sv, + {Proposal::ExceptionHandling, Proposal::TailCall}, + WasmEdge::SpecTest::TestMode::Interpreter}, }; } // namespace From 7ae3f6dea4d16e0d44d1ff605a823d83573fc3ab Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Wed, 24 Apr 2024 09:52:12 +0800 Subject: [PATCH 163/218] [WASI] Handle APPEND flag ourself * linux pwritev has a bug with O_APPEND didn't care about offset * macos didn't have pwritev Signed-off-by: Shen-Ta Hsieh --- include/host/wasi/inode.h | 20 +++++++++++++++----- lib/host/wasi/inode-linux.cpp | 19 ++++++++++--------- lib/host/wasi/inode-macos.cpp | 17 ++++++++--------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/include/host/wasi/inode.h b/include/host/wasi/inode.h index c53ce420be3c..286c7fc46e8a 100644 --- a/include/host/wasi/inode.h +++ b/include/host/wasi/inode.h @@ -53,21 +53,30 @@ struct FdHolder { FdHolder(const FdHolder &) = delete; FdHolder &operator=(const FdHolder &) = delete; FdHolder(FdHolder &&RHS) noexcept - : Fd(std::exchange(RHS.Fd, -1)), Cleanup(RHS.Cleanup) {} + : Fd(std::exchange(RHS.Fd, -1)), Cleanup(RHS.Cleanup), + Append(RHS.Append) { + RHS.Cleanup = true; + RHS.Append = false; + } FdHolder &operator=(FdHolder &&RHS) noexcept { using std::swap; swap(Fd, RHS.Fd); + Cleanup = RHS.Cleanup; + Append = RHS.Append; + RHS.Cleanup = true; + RHS.Append = false; return *this; } - constexpr FdHolder() noexcept = default; + constexpr FdHolder() noexcept : Fd(-1), Cleanup(true), Append(false) {} ~FdHolder() noexcept { if (Cleanup) { reset(); } } - explicit constexpr FdHolder(int Fd, bool Cleanup = true) noexcept - : Fd(Fd), Cleanup(Cleanup) {} + explicit constexpr FdHolder(int Fd, bool Cleanup = true, + bool Append = false) noexcept + : Fd(Fd), Cleanup(Cleanup), Append(Append) {} constexpr bool ok() const noexcept { return Fd >= 0; } void reset() noexcept; int release() noexcept { return std::exchange(Fd, -1); } @@ -77,7 +86,8 @@ struct FdHolder { } int getFd() noexcept { return Fd; } int Fd = -1; - bool Cleanup = true; + bool Cleanup : 1; + mutable bool Append : 1; }; struct DirHolder { diff --git a/lib/host/wasi/inode-linux.cpp b/lib/host/wasi/inode-linux.cpp index 27932936baa0..655713ef17a4 100644 --- a/lib/host/wasi/inode-linux.cpp +++ b/lib/host/wasi/inode-linux.cpp @@ -87,9 +87,6 @@ constexpr int openFlags(__wasi_oflags_t OpenFlags, __wasi_fdflags_t FdFlags, } // Convert file descriptor flags. - if ((FdFlags & __WASI_FDFLAGS_APPEND) != 0) { - Flags |= O_APPEND; - } if ((FdFlags & __WASI_FDFLAGS_DSYNC) != 0) { #ifdef O_DSYNC Flags |= O_DSYNC; @@ -171,7 +168,8 @@ WasiExpect INode::open(std::string Path, __wasi_oflags_t OpenFlags, if (auto NewFd = ::open(Path.c_str(), Flags, 0644); unlikely(NewFd < 0)) { return WasiUnexpect(fromErrNo(errno)); } else { - INode New(NewFd); + INode New(NewFd, true, FdFlags & __WASI_FDFLAGS_APPEND); + #ifndef O_CLOEXEC if (auto Res = ::fcntl(New.Fd, F_SETFD, FD_CLOEXEC); unlikely(Res != 0)) { return WasiUnexpect(fromErrNo(errno)); @@ -220,7 +218,7 @@ WasiExpect INode::fdFdstatGet(__wasi_fdstat_t &FdStat) const noexcept { FdStat.fs_filetype = unsafeFiletype(); FdStat.fs_flags = static_cast<__wasi_fdflags_t>(0); - if (FdFlags & O_APPEND) { + if (Append) { FdStat.fs_flags |= __WASI_FDFLAGS_APPEND; } if (FdFlags & O_DSYNC) { @@ -243,9 +241,6 @@ INode::fdFdstatSetFlags(__wasi_fdflags_t FdFlags) const noexcept { if (FdFlags & __WASI_FDFLAGS_NONBLOCK) { SysFlag |= O_NONBLOCK; } - if (FdFlags & __WASI_FDFLAGS_APPEND) { - SysFlag |= O_APPEND; - } if (FdFlags & __WASI_FDFLAGS_DSYNC) { SysFlag |= O_DSYNC; } @@ -260,6 +255,7 @@ INode::fdFdstatSetFlags(__wasi_fdflags_t FdFlags) const noexcept { return WasiUnexpect(fromErrNo(errno)); } + Append = FdFlags & __WASI_FDFLAGS_APPEND; return {}; } @@ -578,6 +574,10 @@ WasiExpect INode::fdWrite(Span> IOVs, ++SysIOVsSize; } + if (Append) { + ::lseek(Fd, 0, SEEK_END); + } + if (auto Res = ::writev(Fd, SysIOVs, SysIOVsSize); unlikely(Res < 0)) { return WasiUnexpect(fromErrNo(errno)); } else { @@ -733,7 +733,8 @@ WasiExpect INode::pathOpen(std::string Path, __wasi_oflags_t OpenFlags, unlikely(NewFd < 0)) { return WasiUnexpect(fromErrNo(errno)); } else { - INode New(NewFd); + INode New(NewFd, true, FdFlags & __WASI_FDFLAGS_APPEND); + #ifndef O_CLOEXEC if (auto Res = ::fcntl(New.Fd, F_SETFD, FD_CLOEXEC); unlikely(Res != 0)) { return WasiUnexpect(fromErrNo(errno)); diff --git a/lib/host/wasi/inode-macos.cpp b/lib/host/wasi/inode-macos.cpp index cc461aa653a8..a1ecda950f2e 100644 --- a/lib/host/wasi/inode-macos.cpp +++ b/lib/host/wasi/inode-macos.cpp @@ -78,9 +78,6 @@ constexpr int openFlags(__wasi_oflags_t OpenFlags, __wasi_fdflags_t FdFlags, } // Convert file descriptor flags. - if ((FdFlags & __WASI_FDFLAGS_APPEND) != 0) { - Flags |= O_APPEND; - } if ((FdFlags & (__WASI_FDFLAGS_DSYNC | __WASI_FDFLAGS_RSYNC | __WASI_FDFLAGS_SYNC)) != 0) { Flags |= O_SYNC; @@ -142,7 +139,7 @@ WasiExpect INode::open(std::string Path, __wasi_oflags_t OpenFlags, if (auto NewFd = ::open(Path.c_str(), Flags, 0644); unlikely(NewFd < 0)) { return WasiUnexpect(fromErrNo(errno)); } else { - return INode(NewFd); + return INode(NewFd, true, FdFlags & __WASI_FDFLAGS_APPEND); } } @@ -207,7 +204,7 @@ WasiExpect INode::fdFdstatGet(__wasi_fdstat_t &FdStat) const noexcept { FdStat.fs_filetype = unsafeFiletype(); FdStat.fs_flags = static_cast<__wasi_fdflags_t>(0); - if (FdFlags & O_APPEND) { + if (Append) { FdStat.fs_flags |= __WASI_FDFLAGS_APPEND; } if (FdFlags & O_DSYNC) { @@ -230,9 +227,6 @@ INode::fdFdstatSetFlags(__wasi_fdflags_t FdFlags) const noexcept { if (FdFlags & __WASI_FDFLAGS_NONBLOCK) { SysFlag |= O_NONBLOCK; } - if (FdFlags & __WASI_FDFLAGS_APPEND) { - SysFlag |= O_APPEND; - } if (FdFlags & __WASI_FDFLAGS_DSYNC) { SysFlag |= O_DSYNC; } @@ -247,6 +241,7 @@ INode::fdFdstatSetFlags(__wasi_fdflags_t FdFlags) const noexcept { return WasiUnexpect(fromErrNo(errno)); } + Append = FdFlags & __WASI_FDFLAGS_APPEND; return {}; } @@ -546,6 +541,10 @@ WasiExpect INode::fdWrite(Span> IOVs, ++SysIOVsSize; } + if (Append) { + ::lseek(Fd, 0, SEEK_END); + } + if (auto Res = ::writev(Fd, SysIOVs, SysIOVsSize); unlikely(Res < 0)) { return WasiUnexpect(fromErrNo(errno)); } else { @@ -697,7 +696,7 @@ WasiExpect INode::pathOpen(std::string Path, __wasi_oflags_t OpenFlags, unlikely(NewFd < 0)) { return WasiUnexpect(fromErrNo(errno)); } else { - return INode(NewFd); + return INode(NewFd, true, FdFlags & __WASI_FDFLAGS_APPEND); } } From d819d3b563afb6c913e9d922f73c2406dc053396 Mon Sep 17 00:00:00 2001 From: LFsWang <7088579+LFsWang@users.noreply.github.com> Date: Mon, 29 Apr 2024 19:52:49 +0800 Subject: [PATCH 164/218] [WASI] Let pathReadlink on Windows resolve the reparse point as POSIX readlink() (#3370) Signed-off-by: LFsWang --- lib/host/wasi/inode-win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/host/wasi/inode-win.cpp b/lib/host/wasi/inode-win.cpp index a4d07ea1f718..fed85ef37361 100644 --- a/lib/host/wasi/inode-win.cpp +++ b/lib/host/wasi/inode-win.cpp @@ -1393,7 +1393,7 @@ WasiExpect INode::pathReadlink(std::string Path, Span Buffer, // Fill the Buffer with the contents of the link HandleHolder Link(FullPath, FILE_GENERIC_READ_, FILE_SHARE_READ_, - OPEN_EXISTING_, FILE_FLAG_OPEN_REPARSE_POINT_); + OPEN_EXISTING_, 0); if (unlikely(!Link.ok())) { return WasiUnexpect(detail::fromLastError(GetLastError())); From 7fc7355388fbe0a7c89e48f42424b66298ee92a4 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 12:00:08 +0800 Subject: [PATCH 165/218] [WASI] Add missing callback routine for `ReadFileEx` and `WriteFileEx` * Rename variables for better meaning Signed-off-by: Shen-Ta Hsieh --- lib/host/wasi/inode-win.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/host/wasi/inode-win.cpp b/lib/host/wasi/inode-win.cpp index fed85ef37361..d876fdd54ac8 100644 --- a/lib/host/wasi/inode-win.cpp +++ b/lib/host/wasi/inode-win.cpp @@ -25,6 +25,9 @@ namespace WASI { namespace { +inline void WASMEDGE_WINAPI_WINAPI_CC +EmptyOverlappedCompletionRoutine(DWORD_, DWORD_, LPOVERLAPPED_) noexcept {} + #if WINAPI_PARTITION_DESKTOP inline constexpr uint64_t combineHighLow(uint32_t HighPart, uint32_t LowPart) noexcept { @@ -960,7 +963,7 @@ WasiExpect INode::fdPread(Span> IOVs, Query.OffsetHigh = LocalOffset.HighPart; Query.hEvent = nullptr; if (!ReadFileEx(Handle, IOV.data(), static_cast(IOV.size()), - &Query, nullptr)) { + &Query, &EmptyOverlappedCompletionRoutine)) { if (unlikely(GetLastError() != ERROR_IO_PENDING_)) { Result = WasiUnexpect(detail::fromLastError(GetLastError())); Queries.resize(I); @@ -1009,7 +1012,7 @@ WasiExpect INode::fdPwrite(Span> IOVs, } Query.hEvent = nullptr; if (!WriteFileEx(Handle, IOV.data(), static_cast(IOV.size()), - &Query, nullptr)) { + &Query, &EmptyOverlappedCompletionRoutine)) { if (const auto Error = GetLastError(); unlikely(Error != ERROR_IO_PENDING_ && Error != ERROR_HANDLE_EOF_)) { Result = WasiUnexpect(detail::fromLastError(Error)); @@ -1025,9 +1028,9 @@ WasiExpect INode::fdPwrite(Span> IOVs, NWritten = 0; for (size_t I = 0; I < Queries.size(); ++I) { auto &Query = Queries[I]; - DWORD_ NumberOfBytesRead = 0; + DWORD_ NumberOfBytesWrite = 0; if (unlikely( - !GetOverlappedResult(Handle, &Query, &NumberOfBytesRead, true))) { + !GetOverlappedResult(Handle, &Query, &NumberOfBytesWrite, true))) { Result = WasiUnexpect(detail::fromLastError(GetLastError())); CancelIo(Handle); for (size_t J = I + 1; J < Queries.size(); ++J) { @@ -1035,7 +1038,7 @@ WasiExpect INode::fdPwrite(Span> IOVs, } break; } - NWritten += NumberOfBytesRead; + NWritten += NumberOfBytesWrite; } return Result; @@ -1059,7 +1062,7 @@ WasiExpect INode::fdRead(Span> IOVs, Query.OffsetHigh = static_cast(LocalOffset.HighPart); Query.hEvent = nullptr; if (!ReadFileEx(Handle, IOV.data(), static_cast(IOV.size()), - &Query, nullptr)) { + &Query, &EmptyOverlappedCompletionRoutine)) { if (unlikely(GetLastError() != ERROR_IO_PENDING_)) { Result = WasiUnexpect(detail::fromLastError(GetLastError())); Queries.resize(I); @@ -1191,7 +1194,7 @@ WasiExpect INode::fdWrite(Span> IOVs, } Query.hEvent = nullptr; if (!WriteFileEx(Handle, IOV.data(), static_cast(IOV.size()), - &Query, nullptr)) { + &Query, &EmptyOverlappedCompletionRoutine)) { if (const auto Error = GetLastError(); unlikely(Error != ERROR_IO_PENDING_ && Error != ERROR_HANDLE_EOF_)) { Result = WasiUnexpect(detail::fromLastError(Error)); @@ -1207,9 +1210,9 @@ WasiExpect INode::fdWrite(Span> IOVs, NWritten = 0; for (size_t I = 0; I < Queries.size(); ++I) { auto &Query = Queries[I]; - DWORD_ NumberOfBytesRead = 0; + DWORD_ NumberOfBytesWrite = 0; if (unlikely( - !GetOverlappedResult(Handle, &Query, &NumberOfBytesRead, true))) { + !GetOverlappedResult(Handle, &Query, &NumberOfBytesWrite, true))) { Result = WasiUnexpect(detail::fromLastError(GetLastError())); CancelIo(Handle); for (size_t J = I + 1; J < Queries.size(); ++J) { @@ -1217,7 +1220,7 @@ WasiExpect INode::fdWrite(Span> IOVs, } break; } - NWritten += NumberOfBytesRead; + NWritten += NumberOfBytesWrite; } if (!Append) { From a9ea961b25a1558fca38021535ef0c1c6b9a9d8f Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 12:01:38 +0800 Subject: [PATCH 166/218] [Plugin] Use cmake commands for cross-platform support Signed-off-by: Shen-Ta Hsieh --- plugins/wasmedge_rustls/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/wasmedge_rustls/CMakeLists.txt b/plugins/wasmedge_rustls/CMakeLists.txt index 56069740f2ea..739aea924d21 100644 --- a/plugins/wasmedge_rustls/CMakeLists.txt +++ b/plugins/wasmedge_rustls/CMakeLists.txt @@ -6,14 +6,14 @@ else() set(TARGET_DIR "release") endif() -set(RS_SO ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR}/libwasmedge_rustls${CMAKE_SHARED_LIBRARY_SUFFIX}) +set(RS_SO ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}wasmedge_rustls${CMAKE_SHARED_LIBRARY_SUFFIX}) set(WASMEDGE_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/../../lib/api) add_custom_target(wasmedge_rustls ALL - COMMAND WASMEDGE_LIB_DIR=${WASMEDGE_LIB_DIR} LD_LIBARAY_PATH=${WASMEDGE_LIB_DIR} CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} ${CARGO_CMD} - COMMAND cp ${RS_SO} ${CMAKE_CURRENT_BINARY_DIR} - COMMAND rm -rf ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR} + COMMAND ${CMAKE_COMMAND} -E env WASMEDGE_LIB_DIR=${WASMEDGE_LIB_DIR} CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} -- ${CARGO_CMD} + COMMAND ${CMAKE_COMMAND} -E copy ${RS_SO} ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS wasmedge_shared ) From 870f5d70f3a52b09fab7988d7cbdefee8ea1d5ea Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 19:25:40 +0800 Subject: [PATCH 167/218] [LOG] Rename common/log.h to common/spdlog.h to to prevent name conflict with llama.cpp Signed-off-by: Shen-Ta Hsieh --- include/common/enum_ast.hpp | 6 +++--- include/common/enum_errcode.hpp | 6 +++--- include/common/errcode.h | 2 +- include/common/errinfo.h | 2 +- include/common/{log.h => spdlog.h} | 2 +- include/common/statistics.h | 2 +- include/host/mock/log.h | 2 +- include/host/wasi/error.h | 2 +- include/runtime/instance/memory.h | 2 +- include/runtime/instance/table.h | 2 +- lib/common/CMakeLists.txt | 2 +- lib/common/{log.cpp => spdlog.cpp} | 2 +- lib/driver/fuzzPO.cpp | 2 +- lib/driver/runtimeTool.cpp | 2 +- lib/driver/uniTool.cpp | 2 +- lib/driver/wasiNNRPCServerTool.cpp | 2 +- lib/executor/executor.cpp | 2 +- lib/executor/helper.cpp | 2 +- lib/executor/instantiate/data.cpp | 2 +- lib/executor/instantiate/elem.cpp | 2 +- lib/executor/instantiate/import.cpp | 2 +- lib/executor/instantiate/module.cpp | 2 +- lib/host/wasi/environ.cpp | 2 +- lib/host/wasi/inode-macos.cpp | 2 +- lib/host/wasi/vinode.cpp | 2 +- lib/host/wasi/wasifunc.cpp | 2 +- lib/llvm/compiler.cpp | 2 +- lib/llvm/jit.cpp | 2 +- lib/loader/aot_section.cpp | 2 +- lib/loader/shared_library.cpp | 2 +- lib/po/argument_parser.cpp | 2 +- lib/system/fault.cpp | 2 +- lib/validator/formchecker.cpp | 2 +- plugins/wasi_crypto/utils/evp_wrapper.h | 2 +- plugins/wasi_nn/types.h | 2 +- plugins/wasi_nn/wasinnenv.h | 2 +- plugins/wasi_nn/wasinnfunc.cpp | 2 +- plugins/wasi_ocr/wasiocrenv.h | 2 +- plugins/wasi_ocr/wasiocrfunc.cpp | 2 +- plugins/wasmedge_image/image_func.cpp | 2 +- plugins/wasmedge_tensorflow/tensorflow_func.cpp | 2 +- plugins/wasmedge_tensorflowlite/tensorflowlite_func.cpp | 2 +- test/executor/ExecutorTest.cpp | 2 +- test/host/socket/wasi_socket.cpp | 2 +- test/llvm/LLVMcoreTest.cpp | 2 +- test/spec/spectest.cpp | 2 +- test/thread/ThreadTest.cpp | 2 +- 47 files changed, 51 insertions(+), 51 deletions(-) rename include/common/{log.h => spdlog.h} (95%) rename lib/common/{log.cpp => spdlog.cpp} (95%) diff --git a/include/common/enum_ast.hpp b/include/common/enum_ast.hpp index 0b6f16582808..be41833a9cb2 100644 --- a/include/common/enum_ast.hpp +++ b/include/common/enum_ast.hpp @@ -17,9 +17,9 @@ #pragma once -#include "dense_enum_map.h" -#include "log.h" -#include "spare_enum_map.h" +#include "common/dense_enum_map.h" +#include "common/spare_enum_map.h" +#include "common/spdlog.h" #include #include diff --git a/include/common/enum_errcode.hpp b/include/common/enum_errcode.hpp index 643d3178286d..a50f49dfbfdd 100644 --- a/include/common/enum_errcode.hpp +++ b/include/common/enum_errcode.hpp @@ -14,9 +14,9 @@ #pragma once -#include "dense_enum_map.h" -#include "log.h" -#include "spare_enum_map.h" +#include "common/dense_enum_map.h" +#include "common/spare_enum_map.h" +#include "common/spdlog.h" #include #include diff --git a/include/common/errcode.h b/include/common/errcode.h index 8dcc2c53b70e..4f73a121eb78 100644 --- a/include/common/errcode.h +++ b/include/common/errcode.h @@ -16,7 +16,7 @@ #include "common/enum_errcode.hpp" #include "common/expected.h" #include "common/hexstr.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/include/common/errinfo.h b/include/common/errinfo.h index 975e127f744e..a18bb1c36eba 100644 --- a/include/common/errinfo.h +++ b/include/common/errinfo.h @@ -19,7 +19,7 @@ #include "common/enum_errinfo.hpp" #include "common/enum_types.hpp" #include "common/filesystem.h" -#include "common/log.h" +#include "common/spdlog.h" #include "common/types.h" #include diff --git a/include/common/log.h b/include/common/spdlog.h similarity index 95% rename from include/common/log.h rename to include/common/spdlog.h index fa3ec2df93b6..b42970a18ea6 100644 --- a/include/common/log.h +++ b/include/common/spdlog.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC -//===-- wasmedge/common/log.h - Logging system ----------------------------===// +//===-- wasmedge/common/spdlog.h - Logging system -------------------------===// // // Part of the WasmEdge Project. // diff --git a/include/common/statistics.h b/include/common/statistics.h index d06f8460f71d..1f7b10beea48 100644 --- a/include/common/statistics.h +++ b/include/common/statistics.h @@ -16,8 +16,8 @@ #include "common/configure.h" #include "common/enum_ast.hpp" #include "common/errcode.h" -#include "common/log.h" #include "common/span.h" +#include "common/spdlog.h" #include "common/timer.h" #include diff --git a/include/host/mock/log.h b/include/host/mock/log.h index d25c2cc57f04..6978b260c0b1 100644 --- a/include/host/mock/log.h +++ b/include/host/mock/log.h @@ -5,7 +5,7 @@ #include -#include "common/log.h" +#include "common/spdlog.h" namespace WasmEdge { namespace Host { diff --git a/include/host/wasi/error.h b/include/host/wasi/error.h index 3c294d54e1fc..9fc889761e4c 100644 --- a/include/host/wasi/error.h +++ b/include/host/wasi/error.h @@ -4,7 +4,7 @@ #pragma once #include "common/expected.h" -#include "common/log.h" +#include "common/spdlog.h" #include "wasi/api.hpp" #include diff --git a/include/runtime/instance/memory.h b/include/runtime/instance/memory.h index b6a414c3dc23..c60788964162 100644 --- a/include/runtime/instance/memory.h +++ b/include/runtime/instance/memory.h @@ -16,7 +16,7 @@ #include "ast/type.h" #include "common/errcode.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include "system/allocator.h" #include diff --git a/include/runtime/instance/table.h b/include/runtime/instance/table.h index e2fc29630fa6..9d8251a7e003 100644 --- a/include/runtime/instance/table.h +++ b/include/runtime/instance/table.h @@ -17,7 +17,7 @@ #include "ast/type.h" #include "common/errcode.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/lib/common/CMakeLists.txt b/lib/common/CMakeLists.txt index 144240fe743f..bf2bf37e32ac 100644 --- a/lib/common/CMakeLists.txt +++ b/lib/common/CMakeLists.txt @@ -35,7 +35,7 @@ endif() wasmedge_add_library(wasmedgeCommon hexstr.cpp - log.cpp + spdlog.cpp errinfo.cpp int128.cpp ) diff --git a/lib/common/log.cpp b/lib/common/spdlog.cpp similarity index 95% rename from lib/common/log.cpp rename to lib/common/spdlog.cpp index c3af5bfe8d06..a6da7c1743f7 100644 --- a/lib/common/log.cpp +++ b/lib/common/spdlog.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2019-2022 Second State INC -#include "common/log.h" +#include "common/spdlog.h" namespace WasmEdge { namespace Log { diff --git a/lib/driver/fuzzPO.cpp b/lib/driver/fuzzPO.cpp index ef50657e08c3..987b0b7e2937 100644 --- a/lib/driver/fuzzPO.cpp +++ b/lib/driver/fuzzPO.cpp @@ -3,7 +3,7 @@ #ifdef WASMEDGE_BUILD_FUZZING #include "driver/fuzzPO.h" -#include "common/log.h" +#include "common/spdlog.h" #include "common/version.h" #include "po/argument_parser.h" diff --git a/lib/driver/runtimeTool.cpp b/lib/driver/runtimeTool.cpp index 5989dde8c25a..33d8a2b55e3a 100644 --- a/lib/driver/runtimeTool.cpp +++ b/lib/driver/runtimeTool.cpp @@ -3,7 +3,7 @@ #include "common/configure.h" #include "common/filesystem.h" -#include "common/log.h" +#include "common/spdlog.h" #include "common/types.h" #include "common/version.h" #include "driver/tool.h" diff --git a/lib/driver/uniTool.cpp b/lib/driver/uniTool.cpp index 03f4af7c3ccb..06db2ae2ac93 100644 --- a/lib/driver/uniTool.cpp +++ b/lib/driver/uniTool.cpp @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #include "driver/unitool.h" -#include "common/log.h" +#include "common/spdlog.h" #include "driver/compiler.h" #include "driver/tool.h" #include "po/argument_parser.h" diff --git a/lib/driver/wasiNNRPCServerTool.cpp b/lib/driver/wasiNNRPCServerTool.cpp index a760f06d9673..c3e52868a13f 100644 --- a/lib/driver/wasiNNRPCServerTool.cpp +++ b/lib/driver/wasiNNRPCServerTool.cpp @@ -1,4 +1,4 @@ -#include "common/log.h" +#include "common/spdlog.h" #include "driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h" #include "plugin/plugin.h" #include "po/argument_parser.h" diff --git a/lib/executor/executor.cpp b/lib/executor/executor.cpp index 65b7e06aa568..f7bad204fb64 100644 --- a/lib/executor/executor.cpp +++ b/lib/executor/executor.cpp @@ -4,7 +4,7 @@ #include "executor/executor.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" namespace WasmEdge { namespace Executor { diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 91e315483315..8a5ea5676587 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -3,7 +3,7 @@ #include "executor/executor.h" -#include "common/log.h" +#include "common/spdlog.h" #include "system/fault.h" #include diff --git a/lib/executor/instantiate/data.cpp b/lib/executor/instantiate/data.cpp index 3e1d6ec13b63..88bdb40b19b4 100644 --- a/lib/executor/instantiate/data.cpp +++ b/lib/executor/instantiate/data.cpp @@ -4,7 +4,7 @@ #include "executor/executor.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include diff --git a/lib/executor/instantiate/elem.cpp b/lib/executor/instantiate/elem.cpp index 9643b396c465..8e8b1e900474 100644 --- a/lib/executor/instantiate/elem.cpp +++ b/lib/executor/instantiate/elem.cpp @@ -4,7 +4,7 @@ #include "executor/executor.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/lib/executor/instantiate/import.cpp b/lib/executor/instantiate/import.cpp index 1e87c190ce30..a6803caf6644 100644 --- a/lib/executor/instantiate/import.cpp +++ b/lib/executor/instantiate/import.cpp @@ -4,7 +4,7 @@ #include "executor/executor.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/lib/executor/instantiate/module.cpp b/lib/executor/instantiate/module.cpp index fc645c47f42d..d1e7a98b3d38 100644 --- a/lib/executor/instantiate/module.cpp +++ b/lib/executor/instantiate/module.cpp @@ -4,7 +4,7 @@ #include "executor/executor.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/lib/host/wasi/environ.cpp b/lib/host/wasi/environ.cpp index be0d904704bb..f813923c12a9 100644 --- a/lib/host/wasi/environ.cpp +++ b/lib/host/wasi/environ.cpp @@ -3,7 +3,7 @@ #include "host/wasi/environ.h" #include "common/errcode.h" -#include "common/log.h" +#include "common/spdlog.h" #include "host/wasi/vfs.h" #include "host/wasi/vinode.h" diff --git a/lib/host/wasi/inode-macos.cpp b/lib/host/wasi/inode-macos.cpp index a1ecda950f2e..9dd091b4d5c0 100644 --- a/lib/host/wasi/inode-macos.cpp +++ b/lib/host/wasi/inode-macos.cpp @@ -5,7 +5,7 @@ #if WASMEDGE_OS_MACOS #include "common/errcode.h" -#include "common/log.h" +#include "common/spdlog.h" #include "common/variant.h" #include "host/wasi/environ.h" #include "host/wasi/inode.h" diff --git a/lib/host/wasi/vinode.cpp b/lib/host/wasi/vinode.cpp index f112d525ee20..31bbe4ed8372 100644 --- a/lib/host/wasi/vinode.cpp +++ b/lib/host/wasi/vinode.cpp @@ -3,7 +3,7 @@ #include "host/wasi/vinode.h" #include "common/errcode.h" -#include "common/log.h" +#include "common/spdlog.h" #include "host/wasi/environ.h" #include "host/wasi/vfs.h" #include diff --git a/lib/host/wasi/wasifunc.cpp b/lib/host/wasi/wasifunc.cpp index a534f617ede9..440c00549a97 100644 --- a/lib/host/wasi/wasifunc.cpp +++ b/lib/host/wasi/wasifunc.cpp @@ -3,7 +3,7 @@ #include "host/wasi/wasifunc.h" #include "common/filesystem.h" -#include "common/log.h" +#include "common/spdlog.h" #include "executor/executor.h" #include "host/wasi/environ.h" #include "runtime/instance/memory.h" diff --git a/lib/llvm/compiler.cpp b/lib/llvm/compiler.cpp index 8f5e5a341bba..e474d3f7942a 100644 --- a/lib/llvm/compiler.cpp +++ b/lib/llvm/compiler.cpp @@ -6,7 +6,7 @@ #include "aot/version.h" #include "common/defines.h" #include "common/filesystem.h" -#include "common/log.h" +#include "common/spdlog.h" #include "data.h" #include "llvm.h" diff --git a/lib/llvm/jit.cpp b/lib/llvm/jit.cpp index 8aa3835e82b4..545c48ffee4f 100644 --- a/lib/llvm/jit.cpp +++ b/lib/llvm/jit.cpp @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #include "llvm/jit.h" -#include "common/log.h" +#include "common/spdlog.h" #include "data.h" #include "llvm.h" diff --git a/lib/loader/aot_section.cpp b/lib/loader/aot_section.cpp index 39f7f32571d7..bc09eb4adf23 100644 --- a/lib/loader/aot_section.cpp +++ b/lib/loader/aot_section.cpp @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #include "loader/aot_section.h" -#include "common/log.h" +#include "common/spdlog.h" #include "system/allocator.h" #if WASMEDGE_OS_LINUX || WASMEDGE_OS_MACOS diff --git a/lib/loader/shared_library.cpp b/lib/loader/shared_library.cpp index 8383d9a205f4..7fb6dfd64502 100644 --- a/lib/loader/shared_library.cpp +++ b/lib/loader/shared_library.cpp @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #include "loader/shared_library.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/lib/po/argument_parser.cpp b/lib/po/argument_parser.cpp index 3baafd51d5bc..2e9d7d50ec41 100644 --- a/lib/po/argument_parser.cpp +++ b/lib/po/argument_parser.cpp @@ -3,7 +3,7 @@ #include "po/argument_parser.h" #include "common/defines.h" -#include "common/log.h" +#include "common/spdlog.h" #include "system/winapi.h" #include diff --git a/lib/system/fault.cpp b/lib/system/fault.cpp index e3e954f7bbd7..5ed50f6ba094 100644 --- a/lib/system/fault.cpp +++ b/lib/system/fault.cpp @@ -5,7 +5,7 @@ #include "common/config.h" #include "common/defines.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/lib/validator/formchecker.cpp b/lib/validator/formchecker.cpp index 02bb4a37cea8..fffc61e90b36 100644 --- a/lib/validator/formchecker.cpp +++ b/lib/validator/formchecker.cpp @@ -4,7 +4,7 @@ #include "validator/formchecker.h" #include "common/errinfo.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/plugins/wasi_crypto/utils/evp_wrapper.h b/plugins/wasi_crypto/utils/evp_wrapper.h index 67b4ecfbfd2d..d6edc89b9da6 100644 --- a/plugins/wasi_crypto/utils/evp_wrapper.h +++ b/plugins/wasi_crypto/utils/evp_wrapper.h @@ -17,8 +17,8 @@ #include "utils/error.h" #include "utils/secret_vec.h" -#include "common/log.h" #include "common/span.h" +#include "common/spdlog.h" #include #include diff --git a/plugins/wasi_nn/types.h b/plugins/wasi_nn/types.h index f14350b49188..81a06eeebdbb 100644 --- a/plugins/wasi_nn/types.h +++ b/plugins/wasi_nn/types.h @@ -2,8 +2,8 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #pragma once -#include "common/log.h" #include "common/span.h" +#include "common/spdlog.h" #include namespace WasmEdge::Host::WASINN { diff --git a/plugins/wasi_nn/wasinnenv.h b/plugins/wasi_nn/wasinnenv.h index e1e45b2fa7c0..260a1659545a 100644 --- a/plugins/wasi_nn/wasinnenv.h +++ b/plugins/wasi_nn/wasinnenv.h @@ -3,7 +3,7 @@ #pragma once -#include "common/log.h" +#include "common/spdlog.h" #include "plugin/plugin.h" #include #include diff --git a/plugins/wasi_nn/wasinnfunc.cpp b/plugins/wasi_nn/wasinnfunc.cpp index 6e609d4f7bc7..8466eaa433d1 100644 --- a/plugins/wasi_nn/wasinnfunc.cpp +++ b/plugins/wasi_nn/wasinnfunc.cpp @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2019-2022 Second State INC #include "wasinnfunc.h" -#include "common/log.h" +#include "common/spdlog.h" #include "wasinnenv.h" #include diff --git a/plugins/wasi_ocr/wasiocrenv.h b/plugins/wasi_ocr/wasiocrenv.h index 9e90a5efe6d9..14ec756238b1 100644 --- a/plugins/wasi_ocr/wasiocrenv.h +++ b/plugins/wasi_ocr/wasiocrenv.h @@ -3,7 +3,7 @@ #pragma once -#include "common/log.h" +#include "common/spdlog.h" #include "plugin/plugin.h" #include diff --git a/plugins/wasi_ocr/wasiocrfunc.cpp b/plugins/wasi_ocr/wasiocrfunc.cpp index a1d17d816723..f63bd021a8b1 100644 --- a/plugins/wasi_ocr/wasiocrfunc.cpp +++ b/plugins/wasi_ocr/wasiocrfunc.cpp @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2023 Second State INC #include "wasiocrfunc.h" -#include "common/log.h" +#include "common/spdlog.h" #include #include diff --git a/plugins/wasmedge_image/image_func.cpp b/plugins/wasmedge_image/image_func.cpp index 58d626493257..0088ebffe72e 100644 --- a/plugins/wasmedge_image/image_func.cpp +++ b/plugins/wasmedge_image/image_func.cpp @@ -3,8 +3,8 @@ #include "image_func.h" -#include "common/log.h" #include "common/span.h" +#include "common/spdlog.h" #include #include diff --git a/plugins/wasmedge_tensorflow/tensorflow_func.cpp b/plugins/wasmedge_tensorflow/tensorflow_func.cpp index eed2b4fc64ec..6b4ba440facf 100644 --- a/plugins/wasmedge_tensorflow/tensorflow_func.cpp +++ b/plugins/wasmedge_tensorflow/tensorflow_func.cpp @@ -3,8 +3,8 @@ #include "tensorflow_func.h" -#include "common/log.h" #include "common/span.h" +#include "common/spdlog.h" #include "tensorflow/c/c_api.h" diff --git a/plugins/wasmedge_tensorflowlite/tensorflowlite_func.cpp b/plugins/wasmedge_tensorflowlite/tensorflowlite_func.cpp index 18af8a1bf892..0976dd13aa28 100644 --- a/plugins/wasmedge_tensorflowlite/tensorflowlite_func.cpp +++ b/plugins/wasmedge_tensorflowlite/tensorflowlite_func.cpp @@ -3,8 +3,8 @@ #include "tensorflowlite_func.h" -#include "common/log.h" #include "common/span.h" +#include "common/spdlog.h" #include "tensorflow/lite/c/c_api.h" diff --git a/test/executor/ExecutorTest.cpp b/test/executor/ExecutorTest.cpp index 4597e6977af1..cbf20048cd99 100644 --- a/test/executor/ExecutorTest.cpp +++ b/test/executor/ExecutorTest.cpp @@ -14,7 +14,7 @@ /// //===----------------------------------------------------------------------===// -#include "common/log.h" +#include "common/spdlog.h" #include "vm/vm.h" #include "../spec/hostfunc.h" diff --git a/test/host/socket/wasi_socket.cpp b/test/host/socket/wasi_socket.cpp index 8e10f8fd11b8..0a29d5e5f76b 100644 --- a/test/host/socket/wasi_socket.cpp +++ b/test/host/socket/wasi_socket.cpp @@ -9,12 +9,12 @@ #include "system/winapi.h" #include #include +#include #include #include #include #include #include -#include #if !WASMEDGE_OS_WINDOWS #include diff --git a/test/llvm/LLVMcoreTest.cpp b/test/llvm/LLVMcoreTest.cpp index 49f195d5cd28..0a1948a10d4b 100644 --- a/test/llvm/LLVMcoreTest.cpp +++ b/test/llvm/LLVMcoreTest.cpp @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// #include "common/defines.h" -#include "common/log.h" +#include "common/spdlog.h" #include "vm/vm.h" #include "llvm/codegen.h" #include "llvm/compiler.h" diff --git a/test/spec/spectest.cpp b/test/spec/spectest.cpp index bb2bbf5fc77d..c3c127fa55be 100644 --- a/test/spec/spectest.cpp +++ b/test/spec/spectest.cpp @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// #include "spectest.h" -#include "common/log.h" +#include "common/spdlog.h" #include "simdjson.h" #include diff --git a/test/thread/ThreadTest.cpp b/test/thread/ThreadTest.cpp index 9fc902dd5afb..4867a9975c6c 100644 --- a/test/thread/ThreadTest.cpp +++ b/test/thread/ThreadTest.cpp @@ -12,7 +12,7 @@ /// //===----------------------------------------------------------------------===// -#include "common/log.h" +#include "common/spdlog.h" #include "vm/vm.h" #ifdef WASMEDGE_USE_LLVM From 0a36dc8853ffc29bbc6fefa55ad49440aae935bc Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 11:57:56 +0800 Subject: [PATCH 168/218] [Misc] Use `add_compile_options` for shorter code in setting subproject options * Add utf-8 option for MSVC Signed-off-by: Shen-Ta Hsieh --- cmake/Helper.cmake | 1 + plugins/wasi_nn/CMakeLists.txt | 92 +++++++++++++++++------------ test/CMakeLists.txt | 30 ++-------- test/plugins/wasi_nn/CMakeLists.txt | 7 ++- test/spec/CMakeLists.txt | 22 ++----- 5 files changed, 73 insertions(+), 79 deletions(-) diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 0314385c7d43..53685b54d40e 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -18,6 +18,7 @@ endif() if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") list(APPEND WASMEDGE_CFLAGS + /utf-8 /WX /W4 /we5030 # treat unknown attribute as error diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 14768036fb81..424af4ab0eab 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -53,16 +53,42 @@ if(BACKEND STREQUAL "ggml") # setup llama.cpp message(STATUS "Downloading llama.cpp source") - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(MSVC) add_compile_options( + /utf-8 + /wd4067 # unexpected tokens following preprocessor directive - expected a newline + /wd4101 # 'identifier' : unreferenced local variable + /wd4189 # 'identifier' : local variable is initialized but not referenced + /wd4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data + /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data + /wd4297 # 'function' : function assumed not to throw an exception but does + /wd4456 # declaration of 'identifier' hides previous local declaration + /wd4505 # 'function' : unreferenced local function has been removed + ) + endif() + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + add_compile_options( + $<$:-Wno-exceptions> + -Wno-cast-align + -Wno-cast-qual + -Wno-float-conversion + -Wno-implicit-fallthrough + -Wno-unused-macros + -Wno-unused-function + -Wno-unused-variable + ) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options( + $<$:-Wno-exceptions> -Wno-cast-align -Wno-cast-qual -Wno-disabled-macro-expansion - -Wno-exceptions -Wno-float-conversion -Wno-implicit-fallthrough -Wno-implicit-float-conversion -Wno-unused-macros + -Wno-unused-function + -Wno-unused-variable ) endif() include(FetchContent) @@ -92,15 +118,7 @@ if(BACKEND STREQUAL "ggml") if(MSVC) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - get_property( - compile_options - DIRECTORY - PROPERTY COMPILE_OPTIONS - ) - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( -Wno-undef -Wno-suggest-override -Wno-documentation @@ -116,15 +134,11 @@ if(BACKEND STREQUAL "ggml") -Wno-format-nonliteral -Wno-unused-exception-parameter -Wno-unused-member-function - ) - unset(compile_options) + ) elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( /wd4100 # unreferenced formal parameter - ) + ) endif() endif() @@ -165,35 +179,39 @@ target_include_directories(wasmedgePluginWasiNN if(BACKEND STREQUAL "ggml") # Setup llava from llama.cpp wasmedge_add_library(llava OBJECT - ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava/clip.cpp - ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava/llava.cpp + ${llama_SOURCE_DIR}/examples/llava/clip.cpp + ${llama_SOURCE_DIR}/examples/llava/llava.cpp ) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(llava PRIVATE -Wno-error=unused-variable -Wno-error=unused-function) + endif() target_link_libraries(llava PRIVATE ggml llama) target_include_directories(llava PUBLIC - ${CMAKE_BINARY_DIR}/_deps/llama-src - ${CMAKE_BINARY_DIR}/_deps/llama-src/common - ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava - ) - target_compile_options(llava PRIVATE - -Wno-error=unused-function - -Wno-error=unused-variable - -Wno-unused-function - -Wno-unused-variable + ${llama_SOURCE_DIR} + ${llama_SOURCE_DIR}/common + ${llama_SOURCE_DIR}/examples/llava ) - wasmedge_setup_target(llava) - # Setup include and link from llama.cpp - target_include_directories(wasmedgePluginWasiNN PUBLIC - ${CMAKE_BINARY_DIR}/_deps/llama-src - ${CMAKE_BINARY_DIR}/_deps/llama-src/examples/llava + target_include_directories(wasmedgePluginWasiNN PRIVATE + ${llama_SOURCE_DIR} + ${llama_SOURCE_DIR}examples/llava + ) + target_link_libraries(wasmedgePluginWasiNN PRIVATE + common + simdjson::simdjson + llava ) - target_link_libraries(wasmedgePluginWasiNN PRIVATE common simdjson::simdjson llava) + if(MSVC) + target_compile_options(wasmedgePluginWasiNN PUBLIC + /wd4067 # unexpected tokens following preprocessor directive - expected a newline + ) + endif() if(WASMEDGE_PLUGIN_WASI_NN_GGML_LLAMA_METAL) add_custom_command( TARGET wasmedgePluginWasiNN POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/llama-src/ggml-metal.metal ggml-metal.metal - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/_deps/llama-src/ggml-common.h ggml-common.h + COMMAND ${CMAKE_COMMAND} -E copy ${llama_SOURCE_DIR}/ggml-metal.metal ggml-metal.metal + COMMAND ${CMAKE_COMMAND} -E copy ${llama_SOURCE_DIR}/ggml-common.h ggml-common.h ) endif() endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e6af74c29f94..fd701cb9bd3c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,50 +13,30 @@ else() ) set(BUILD_GMOCK OFF CACHE BOOL "Builds the googlemock subproject" FORCE) set(INSTALL_GTEST OFF CACHE BOOL "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" FORCE) - get_property( - compile_options - DIRECTORY - PROPERTY COMPILE_OPTIONS - ) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( ${WASMEDGE_CFLAGS} ) else() - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( ${WASMEDGE_CFLAGS} -Wno-language-extension-token -Wno-missing-noreturn -Wno-shift-sign-overflow -Wno-undef -Wno-unused-member-function - -Wno-zero-as-null-pointer-constant + $<$:-Wno-zero-as-null-pointer-constant> -Wno-deprecated ) if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( -Wno-suggest-destructor-override - -Wno-suggest-override + $<$:-Wno-suggest-override> ) endif() endif() FetchContent_MakeAvailable(GTest) - set_property( - DIRECTORY - PROPERTY COMPILE_OPTIONS - ${compile_options} - ) - unset(compile_options) set(GTEST_BOTH_LIBRARIES "gtest;gtest_main") endif() diff --git a/test/plugins/wasi_nn/CMakeLists.txt b/test/plugins/wasi_nn/CMakeLists.txt index 3abca1945bf4..8674aaf1e152 100644 --- a/test/plugins/wasi_nn/CMakeLists.txt +++ b/test/plugins/wasi_nn/CMakeLists.txt @@ -59,12 +59,17 @@ foreach(BACKEND ${WASMEDGE_PLUGIN_WASI_NN_BACKEND}) MD5=ad51c39cfe35d2ef35c4052b78cb3c55 ) elseif(BACKEND STREQUAL "ggml") - message(STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures") + message(STATUS "Download ML artifacts to ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures") download( https://huggingface.co/TheBloke/orca_mini_v3_7B-GGUF/resolve/main/orca_mini_v3_7b.Q2_K.gguf ${CMAKE_CURRENT_BINARY_DIR}/wasinn_ggml_fixtures/orca_mini.gguf MD5=f895f00678bfbf89f70d6d25f20a7b5f ) + if(MSVC) + target_compile_options(wasiNNTests PUBLIC + /wd4067 # unexpected tokens following preprocessor directive - expected a newline + ) + endif() else() # Add the other backend test files fetching here. endif() diff --git a/test/spec/CMakeLists.txt b/test/spec/CMakeLists.txt index c8883d3994dc..2e814f412140 100644 --- a/test/spec/CMakeLists.txt +++ b/test/spec/CMakeLists.txt @@ -26,15 +26,7 @@ else() if(MSVC) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - get_property( - compile_options - DIRECTORY - PROPERTY COMPILE_OPTIONS - ) - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( -Wno-undef -Wno-suggest-override -Wno-documentation @@ -50,15 +42,13 @@ else() -Wno-format-nonliteral -Wno-unused-exception-parameter -Wno-unused-member-function - ) - unset(compile_options) + -Wno-missing-prototypes + ) elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - set_property( - DIRECTORY - APPEND - PROPERTY COMPILE_OPTIONS + add_compile_options( /wd4100 # unreferenced formal parameter - ) + /wd4505 # unreferenced local function has been removed + ) endif() endif() From 67434d48fc3a4d7da1bc115273ca9a12c03a9615 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 13:23:37 +0800 Subject: [PATCH 169/218] [Test] Don't use reference to a temporary object Signed-off-by: Shen-Ta Hsieh --- test/spec/spectest.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/spec/spectest.cpp b/test/spec/spectest.cpp index c3c127fa55be..6f6f04d684dd 100644 --- a/test/spec/spectest.cpp +++ b/test/spec/spectest.cpp @@ -799,7 +799,7 @@ void SpecTest::run(std::string_view Proposal, std::string_view UnitName) { } case CommandID::AssertTrap: { const simdjson::dom::object &Action = Cmd["action"]; - const std::string_view &Text = Cmd["text"]; + const std::string_view Text = Cmd["text"]; const uint64_t LineNumber = Cmd["line"]; TrapInvoke(Action, std::string(Text), LineNumber); return; @@ -809,32 +809,32 @@ void SpecTest::run(std::string_view Proposal, std::string_view UnitName) { return; } case CommandID::AssertMalformed: { - const std::string_view &ModType = Cmd["module_type"]; + const std::string_view ModType = Cmd["module_type"]; if (ModType != "binary"sv) { // TODO: Wat is not supported in WasmEdge yet. return; } - const std::string_view &Name = Cmd["filename"]; + const std::string_view Name = Cmd["filename"]; const auto Filename = (TestsuiteRoot / Proposal / UnitName / Name).u8string(); - const std::string_view &Text = Cmd["text"]; + const std::string_view Text = Cmd["text"]; TrapLoad(Filename, std::string(Text)); return; } case CommandID::AssertInvalid: { - const std::string_view &Name = Cmd["filename"]; + const std::string_view Name = Cmd["filename"]; const auto Filename = (TestsuiteRoot / Proposal / UnitName / Name).u8string(); - const std::string_view &Text = Cmd["text"]; + const std::string_view Text = Cmd["text"]; TrapValidate(Filename, std::string(Text)); return; } case CommandID::AssertUnlinkable: case CommandID::AssertUninstantiable: { - const std::string_view &Name = Cmd["filename"]; + const std::string_view Name = Cmd["filename"]; const auto Filename = (TestsuiteRoot / Proposal / UnitName / Name).u8string(); - const std::string_view &Text = Cmd["text"]; + const std::string_view Text = Cmd["text"]; TrapInstantiate(Filename, std::string(Text)); return; } From 2944f6fc493b8abd4d3d58dfcff7e49b981c1156 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 12:01:00 +0800 Subject: [PATCH 170/218] [WASI-NN] Use standard c++ syntax for MSVC compiler Signed-off-by: Shen-Ta Hsieh --- plugins/wasi_nn/wasinnenv.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/plugins/wasi_nn/wasinnenv.cpp b/plugins/wasi_nn/wasinnenv.cpp index 83090a63c553..b2228ff4208c 100644 --- a/plugins/wasi_nn/wasinnenv.cpp +++ b/plugins/wasi_nn/wasinnenv.cpp @@ -143,21 +143,22 @@ void addOptions(const Plugin::Plugin::PluginDescriptor *, #endif } +static Plugin::PluginModule::ModuleDescriptor MD[] = { + { + /* Name */ "wasi_nn", + /* Description */ "", + /* Create */ create, + }, +}; + Plugin::Plugin::PluginDescriptor Descriptor{ - .Name = "wasi_nn", - .Description = "", - .APIVersion = Plugin::Plugin::CurrentAPIVersion, - .Version = {0, 10, 1, 0}, - .ModuleCount = 1, - .ModuleDescriptions = - (Plugin::PluginModule::ModuleDescriptor[]){ - { - .Name = "wasi_nn", - .Description = "", - .Create = create, - }, - }, - .AddOptions = addOptions, + /* Name */ "wasi_nn", + /* Description */ "", + /* APIVersion */ Plugin::Plugin::CurrentAPIVersion, + /* Version */ {0, 10, 1, 0}, + /* ModuleCount */ 1, + /* ModuleDescriptions */ MD, + /* AddOptions */ addOptions, }; } // namespace From 7ad233b6022f63f123582e3bf95d942275212af7 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 12:34:43 +0800 Subject: [PATCH 171/218] [WASI-NN] Add windows build * Fix compiler warning for variable size Signed-off-by: Shen-Ta Hsieh --- .github/workflows/build-extensions.yml | 59 ++++++++++++++++++++++++++ plugins/wasi_nn/ggml.cpp | 10 ++--- test/plugins/wasi_nn/wasi_nn.cpp | 9 ++-- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index 65fe612aa492..4197227fa1d0 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -173,6 +173,65 @@ jobs: name: WasmEdge-plugin-wasi_nn-ggml-${{ needs.get_version.outputs.version }}-ubuntu22.04-${{ matrix.compiler }}.tar.gz path: plugin_wasi_nn-ggml.tar.gz + build_windows_wasi_nn: + permissions: + contents: write + name: WASI-NN (Windows Server 2022) + runs-on: windows-2022 + env: + output_dir: build/plugins/wasi_nn + test_dir: build/test/plugins/wasi_nn + build_options: -DWASMEDGE_PLUGIN_WASI_NN_BACKEND=GGML + tar_names: wasi_nn-ggml + test_bin: wasiNNTests + output_bin: wasmedgePluginWasiNN.dll + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Ensure git safe directory + run: | + git config --global --add safe.directory $(pwd) + - name: Install dependency + uses: crazy-max/ghaction-chocolatey@v3 + with: + args: install cmake ninja vswhere + - uses: GuillaumeFalourd/setup-windows10-sdk-action@v2 + with: + sdk-version: 19041 + - name: Build WasmEdge + run: | + $vsPath = (vswhere -latest -property installationPath) + Import-Module (Join-Path $vsPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll") + Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64 -winsdk=10.0.19041.0" + $llvm = "LLVM-16.0.6-win64-MultiThreadedDLL.zip" + curl -sLO https://github.com/WasmEdge/llvm-windows/releases/download/llvmorg-16.0.6/LLVM-16.0.6-win64-MultiThreadedDLL.zip -o $llvm + Expand-Archive -Path $llvm + $llvm_dir = "$pwd\\LLVM-16.0.6-win64-MultiThreadedDLL\\LLVM-16.0.6-win64\\lib\\cmake\\llvm" + $cmake_sys_version = "10.0.19041.0" + cmake -Bbuild -GNinja "-DCMAKE_SYSTEM_VERSION=$cmake_sys_version" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL "-DLLVM_DIR=$llvm_dir" -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF + + Write-Output "Building $Env:tar_names backend:" + cmake -Bbuild -GNinja "$Env:build_options" + cmake --build build --target "$Env:test_bin" + + $Env:PATH += ";$pwd\\build\\lib\\api" + Write-Output "Testing $Env:tar_names backend:" + cmake -E chdir "$Env:test_dir" "$Env:test_bin" + + Write-Output "Copying $Env:tar_names backend:" + Copy-Item "$Env:output_dir/$Env:output_bin" -Destination "./$Env:output_bin" + + Write-Output "Compress-Archive -Path $Env:output_bin -DestinationPath plugin_${Env:tar_names}.zip -CompressionLevel Optimal" + Compress-Archive -Path "$Env:output_bin" -DestinationPath "plugin_${Env:tar_names}.zip" -CompressionLevel Optimal + ls "plugin_${Env:tar_names}.zip" + - name: Upload artifact - wasi_nn-ggml + uses: actions/upload-artifact@v3 + with: + name: WasmEdge-plugin-wasi_nn-ggml-${{ needs.get_version.outputs.version }}-windows.zip + path: plugin_wasi_nn-ggml.zip + + build_ubuntu: permissions: contents: write diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 0ccbfad383d7..18057a7e97e6 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -702,10 +702,10 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, } // Handle the model path. auto Weight = Builders[0]; - const std::string BinModel(reinterpret_cast(Weight.data()), - Weight.size()); + const std::string_view BinModel(reinterpret_cast(Weight.data()), + Weight.size()); std::string ModelFilePath; - if (BinModel.substr(0, 8) == "preload:") { + if (BinModel.substr(0, 8) == "preload:"sv) { ModelFilePath = BinModel.substr(8); } else { if (GraphRef.EnableDebugLog) { @@ -716,7 +716,7 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, // TODO: pass the model directly to ggml // Write ggml model to file. ModelFilePath = "ggml-model.bin"sv; - std::ofstream TempFile(ModelFilePath); + std::ofstream TempFile(ModelFilePath, std::ios::out | std::ios::binary); if (!TempFile) { spdlog::error( "[WASI-NN] GGML backend: Failed to create the temporary file. " @@ -726,7 +726,7 @@ Expect load(WasiNNEnvironment &Env, Span> Builders, Env.NNGraph.pop_back(); return ErrNo::InvalidArgument; } - TempFile << BinModel; + TempFile.write(BinModel.data(), BinModel.size()); TempFile.close(); if (GraphRef.EnableDebugLog) { spdlog::info( diff --git a/test/plugins/wasi_nn/wasi_nn.cpp b/test/plugins/wasi_nn/wasi_nn.cpp index 806c33a3f62e..e8ccdeaf1496 100644 --- a/test/plugins/wasi_nn/wasi_nn.cpp +++ b/test/plugins/wasi_nn/wasi_nn.cpp @@ -41,11 +41,10 @@ createModule(std::string_view NNRPCURI = "") { } inline std::vector readEntireFile(const std::string &Path) { - std::ifstream Fin(Path, std::ios::binary | std::ios::ate); + std::ifstream Fin(Path, std::ios::in | std::ios::binary | std::ios::ate); if (!Fin) { return {}; } - Fin.seekg(0, std::ios::end); std::vector Buf(static_cast(Fin.tellg())); Fin.seekg(0, std::ios::beg); if (!Fin.read(reinterpret_cast(Buf.data()), @@ -58,7 +57,7 @@ inline std::vector readEntireFile(const std::string &Path) { template void writeBinaries(WasmEdge::Runtime::Instance::MemoryInstance &MemInst, - std::vector Binaries, uint32_t Ptr) noexcept { + WasmEdge::Span Binaries, uint32_t Ptr) noexcept { std::copy(Binaries.begin(), Binaries.end(), MemInst.getPointer(Ptr)); } @@ -1364,7 +1363,7 @@ TEST(WasiNNTest, GGMLBackend) { writeFatPointer(MemInst, StorePtr, static_cast(WeightRead.size()), BuilderPtr); writeBinaries(MemInst, WeightRead, StorePtr); - StorePtr += WeightRead.size(); + StorePtr += static_cast(WeightRead.size()); { EXPECT_TRUE(HostFuncLoad.run(CallFrame, std::initializer_list{ @@ -1451,7 +1450,7 @@ TEST(WasiNNTest, GGMLBackend) { Errno)); EXPECT_EQ(Errno[0].get(), static_cast(ErrNo::Success)); } - StorePtr += (TensorDim.size() * 4 + TensorData.size()); + StorePtr += static_cast(TensorDim.size() * 4 + TensorData.size()); // GGML WASI-NN compute tests. // Test: compute -- context id exceeds. From d2addafc75c221c5c0d00c2eed8dd2d5f0ce4fe3 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Tue, 30 Apr 2024 02:57:46 +0800 Subject: [PATCH 172/218] [Changelog] Update the changelog for the 0.14.0-alpha.4 pre-release. (#3367) Signed-off-by: YiYing He Signed-off-by: dm4 Co-authored-by: dm4 --- .CurrentChangelog.md | 33 +++++++++++++++++++++++++++++---- Changelog.md | 33 +++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index c18eae1b3db7..8e170eba8b9f 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.4 (2024-04-03) +### 0.14.0-alpha.4 (2024-04-29) Breaking changes: @@ -29,10 +29,20 @@ Breaking changes: * `WasmEdge_VMRunWasmFromBytes()` API has the same function as `WasmEdge_VMRunWasmFromBuffer()` and will replace it in the future. * `WasmEdge_VMAsyncRunWasmFromBytes()` API has the same function as `WasmEdge_VMAsyncRunWasmFromBuffer()` and will replace it in the future. * `WasmEdge_VMLoadWasmFromBytes()` API has the same function as `WasmEdge_VMLoadWasmFromBuffer()` and will replace it in the future. + * New APIs for WASM Exception-Handling proposal. + * Added the `WasmEdge_TagTypeContext` struct. + * Added the `WasmEdge_TagInstanceContext` struct. + * Added the `WasmEdge_TagTypeGetFunctionType()` API for retrieving the function type from a tag type. + * Added the `WasmEdge_ImportTypeGetTagType()` API for retrieving the tag type from an import type. + * Added the `WasmEdge_ExportTypeGetTagType()` API for retrieving the tag type from an export type. + * Added the `WasmEdge_ModuleInstanceFindTag()` API for finding an exported tag instance from a module instance. + * Added the `WasmEdge_ModuleInstanceListTagLength()` and `WasmEdge_ModuleInstanceListTag()` APIs for listing the exported tag instances of a module instance. +* Refactored the `OpCode` mechanism for speeding up and supporting WASM multi-bytes instruction OpCodes. Features: * Bumpped `spdlog` to `v1.13.0`. +* Bumpped `simdjson` to `v3.9.1`. * [Proposal]: Apply new propoals. * Supported WASM Typed Function References proposal. * Added the `WasmEdge_Proposal_FunctionReferences` for the configuration in WasmEdge C API. @@ -40,6 +50,10 @@ Features: * Supported WASM GC proposal (interpreter only). * Added the `WasmEdge_Proposal_GC` for the configuration in WasmEdge C API. * Users can use the `--enable-gc` to enable the proposal in `wasmedge` and `wasmedgec` tools. + * Supported WASM Exception-Handling proposal (interpreter only). + * Added the `WasmEdge_Proposal_ExceptionHandling` for the configuration in WasmEdge C API. + * Users can use the `--enable-exception-handling` to enable the proposal in `wasmedge` and `wasmedgec` tools. + * This proposal supports old deprecated `try`, `catch`, and `catch_all` instructions, and will remove them in the future version. * Component Model proposal (experimental, loader phase only). * Added the `WasmEdge_Proposal_Component` for the configuration in WasmEdge C API. * Users can use the `--enable-component` to enable the proposal in `wasmedge` tool. @@ -73,22 +87,31 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2534. + * Bump llama.cpp to b2734. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. * `repeat-penalty`: set repeat penalty for inference. + * `top-p`: set top-p for inference. + * `grammar`: set grammar syntax for inference. + * `main-gpu`: set the main GPU for inference. + * `tensor-split`: set the tensor split for inference. * Add `enable-debug-log` option to show more debug information. * Default enable Metal on macOS. * Introduce `load_by_name_with_config()` to load model with metadata. * Introduce single token inference by `compute_single`, `get_output_single`, and `fini_single` + * Introduce `unload()` function to release the model. * Add some llama errors to WASI-NN. * `EndOfSequence`: returned when encounter `` token on single token inferece. * `ContextFull`: returned when the context is full. * `PromptTooLong`: returned when the input size is too large. + * `ModelNotFound`: returned when the model is not found. * Support Llava and Gemma inference. * Add `mmproj` option to set the projection model. * Add `image` option to set the image. + * Improve logging mechanism. + * Show the version of `llama.cpp` in the metadata. + * Support Phi-3-Mini model. * Support embedding generation. * Support Windows build. * [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. @@ -99,6 +122,7 @@ Fixed issues: * [Executor]: Minor fixes. * Fixed integer overflow on `memGrow` boundary check. * Refined the slice copy in table instances. + * Cleaned the unused bits of WASM return values to avoid security issues. * [WASI]: Minor fixes. * Fixed the function signature matching for WASI imports when backwarding supporting older version. (#3073) * Fixed large timestamp causing overflow (#3106). @@ -118,6 +142,7 @@ Fixed issues: Tests: * Updated the WASM spec tests to the date 2024/02/17. +* Updated the spec tests for the Exception Handling proposal. * Added the spec tests for the Typed Function Reference proposal. * Added the spec tests for the GC proposal. @@ -129,6 +154,6 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, redismongo, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-alpha.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index c4291d54e4c4..19d29c14f3c9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.4 (2024-04-03) +### 0.14.0-alpha.4 (2024-04-29) Breaking changes: @@ -29,10 +29,20 @@ Breaking changes: * `WasmEdge_VMRunWasmFromBytes()` API has the same function as `WasmEdge_VMRunWasmFromBuffer()` and will replace it in the future. * `WasmEdge_VMAsyncRunWasmFromBytes()` API has the same function as `WasmEdge_VMAsyncRunWasmFromBuffer()` and will replace it in the future. * `WasmEdge_VMLoadWasmFromBytes()` API has the same function as `WasmEdge_VMLoadWasmFromBuffer()` and will replace it in the future. + * New APIs for WASM Exception-Handling proposal. + * Added the `WasmEdge_TagTypeContext` struct. + * Added the `WasmEdge_TagInstanceContext` struct. + * Added the `WasmEdge_TagTypeGetFunctionType()` API for retrieving the function type from a tag type. + * Added the `WasmEdge_ImportTypeGetTagType()` API for retrieving the tag type from an import type. + * Added the `WasmEdge_ExportTypeGetTagType()` API for retrieving the tag type from an export type. + * Added the `WasmEdge_ModuleInstanceFindTag()` API for finding an exported tag instance from a module instance. + * Added the `WasmEdge_ModuleInstanceListTagLength()` and `WasmEdge_ModuleInstanceListTag()` APIs for listing the exported tag instances of a module instance. +* Refactored the `OpCode` mechanism for speeding up and supporting WASM multi-bytes instruction OpCodes. Features: * Bumpped `spdlog` to `v1.13.0`. +* Bumpped `simdjson` to `v3.9.1`. * [Proposal]: Apply new propoals. * Supported WASM Typed Function References proposal. * Added the `WasmEdge_Proposal_FunctionReferences` for the configuration in WasmEdge C API. @@ -40,6 +50,10 @@ Features: * Supported WASM GC proposal (interpreter only). * Added the `WasmEdge_Proposal_GC` for the configuration in WasmEdge C API. * Users can use the `--enable-gc` to enable the proposal in `wasmedge` and `wasmedgec` tools. + * Supported WASM Exception-Handling proposal (interpreter only). + * Added the `WasmEdge_Proposal_ExceptionHandling` for the configuration in WasmEdge C API. + * Users can use the `--enable-exception-handling` to enable the proposal in `wasmedge` and `wasmedgec` tools. + * This proposal supports old deprecated `try`, `catch`, and `catch_all` instructions, and will remove them in the future version. * Component Model proposal (experimental, loader phase only). * Added the `WasmEdge_Proposal_Component` for the configuration in WasmEdge C API. * Users can use the `--enable-component` to enable the proposal in `wasmedge` tool. @@ -73,22 +87,31 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2534. + * Bump llama.cpp to b2734. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. * `repeat-penalty`: set repeat penalty for inference. + * `top-p`: set top-p for inference. + * `grammar`: set grammar syntax for inference. + * `main-gpu`: set the main GPU for inference. + * `tensor-split`: set the tensor split for inference. * Add `enable-debug-log` option to show more debug information. * Default enable Metal on macOS. * Introduce `load_by_name_with_config()` to load model with metadata. * Introduce single token inference by `compute_single`, `get_output_single`, and `fini_single` + * Introduce `unload()` function to release the model. * Add some llama errors to WASI-NN. * `EndOfSequence`: returned when encounter `` token on single token inferece. * `ContextFull`: returned when the context is full. * `PromptTooLong`: returned when the input size is too large. + * `ModelNotFound`: returned when the model is not found. * Support Llava and Gemma inference. * Add `mmproj` option to set the projection model. * Add `image` option to set the image. + * Improve logging mechanism. + * Show the version of `llama.cpp` in the metadata. + * Support Phi-3-Mini model. * Support embedding generation. * Support Windows build. * [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. @@ -99,6 +122,7 @@ Fixed issues: * [Executor]: Minor fixes. * Fixed integer overflow on `memGrow` boundary check. * Refined the slice copy in table instances. + * Cleaned the unused bits of WASM return values to avoid security issues. * [WASI]: Minor fixes. * Fixed the function signature matching for WASI imports when backwarding supporting older version. (#3073) * Fixed large timestamp causing overflow (#3106). @@ -118,6 +142,7 @@ Fixed issues: Tests: * Updated the WASM spec tests to the date 2024/02/17. +* Updated the spec tests for the Exception Handling proposal. * Added the spec tests for the Typed Function Reference proposal. * Added the spec tests for the GC proposal. @@ -129,9 +154,9 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, redismongo, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-alpha.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 862349c5ed24562267a47c5e813ef73e8339524e Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 30 Apr 2024 08:58:03 +0800 Subject: [PATCH 173/218] [CI] ffmpeg plugin: fix pkg-config issue(ffmpeg path) in the release workflow on macOS Signed-off-by: hydai --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3652177d76c3..5ea9fce7eef0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -372,6 +372,7 @@ jobs: eval $(/opt/homebrew/bin/brew shellenv) outbin_array=(${output_bins}) export LLVM_DIR="$(brew --prefix)/opt/llvm@16/lib/cmake" + export PKG_CONFIG_PATH="$(brew --prefix)/opt/ffmpeg@6/lib/pkgconfig:$PKG_CONFIG_PATH" export CC=clang export CXX=clang++ cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl ${build_options} From b74b8b5c71499f7d57d6f96b98e6e7ace4d8ca03 Mon Sep 17 00:00:00 2001 From: hugo-syn <61210734+hugo-syn@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:38:10 +0200 Subject: [PATCH 174/218] [Misc] chore: fix typos (#3378) Signed-off-by: hugo-syn --- thirdparty/wasi_crypto/api.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thirdparty/wasi_crypto/api.hpp b/thirdparty/wasi_crypto/api.hpp index 8d6f60817d28..306526b51c3b 100644 --- a/thirdparty/wasi_crypto/api.hpp +++ b/thirdparty/wasi_crypto/api.hpp @@ -400,7 +400,7 @@ static_assert(alignof(__wasi_algorithm_type_e_t) == 2, "witx calculated align"); /** * Version of a managed key. * - * A version can be an arbitrary `u64` integer, with the expection of some reserved values. + * A version can be an arbitrary `u64` integer, with the exception of some reserved values. */ using __wasi_version_t = uint64_t; @@ -544,7 +544,7 @@ static_assert(alignof(__wasi_symmetric_key_t) == 4, "witx calculated align"); * * This object type can't be directly created from raw bytes. They are only returned by functions computing MACs. * - * The host is reponsible for securely wiping them from memory on close. + * The host is responsible for securely wiping them from memory on close. */ using __wasi_symmetric_tag_t = int32_t; From a066d25f4c8e99538903240b58c4e56c39e20997 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 1 May 2024 17:15:18 +0800 Subject: [PATCH 175/218] [WASI-NN] ggml: fix missing implemented body (#3379) Signed-off-by: hydai --- plugins/wasi_nn/ggml.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 18057a7e97e6..4430fa66dcac 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -1401,6 +1401,19 @@ Expect getOutput(WasiNNEnvironment &, uint32_t, uint32_t, Span, Expect compute(WasiNNEnvironment &, uint32_t) noexcept { return reportBackendNotSupported(); } +Expect getOutputSingle(WasiNNEnvironment &, uint32_t, uint32_t, + Span, uint32_t &) noexcept { + return reportBackendNotSupported(); +} +Expect computeSingle(WasiNNEnvironment &, uint32_t) noexcept { + return reportBackendNotSupported(); +} +Expect finiSingle(WasiNNEnvironment &, uint32_t) noexcept { + return reportBackendNotSupported(); +} +Expect unload(WasiNNEnvironment &, uint32_t) noexcept { + return reportBackendNotSupported(); +} #endif } // namespace WasmEdge::Host::WASINN::GGML From 6a338141f06c0ac01d5965949df74a4ae379cbbc Mon Sep 17 00:00:00 2001 From: dm4 Date: Fri, 3 May 2024 16:08:42 +0800 Subject: [PATCH 176/218] [WASI-NN] ggml: support ubatch-size (#3383) Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 53 ++++++++++++++++++++++++---------------- plugins/wasi_nn/ggml.h | 1 + 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 4430fa66dcac..467bde221c76 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -75,6 +75,7 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, // Context parameters (used by the llama context): // ctx-size: uint64_t // batch-size: uint64_t + // ubatch-size: uint64_t // threads: uint64_t // Sampling parameters (used by the llama sampling context). // temp: double @@ -82,6 +83,7 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, // repeat-penalty: double // presence-penalty: double // frequency-penalty: double + // grammar: string // Get the current llama parameters. llama_model_params ModelParams = llama_model_default_params(); @@ -226,6 +228,14 @@ Expect parseMetadata(Graph &GraphRef, const std::string &Metadata, return ErrNo::InvalidArgument; } } + if (Doc.at_key("ubatch-size").error() == simdjson::SUCCESS) { + auto Err = Doc["ubatch-size"].get().get(GraphRef.UBatchSize); + if (Err) { + spdlog::error( + "[WASI-NN] GGML backend: Unable to retrieve the ubatch-size option."sv); + return ErrNo::InvalidArgument; + } + } if (Doc.at_key("threads").error() == simdjson::SUCCESS) { auto Err = Doc["threads"].get().get(GraphRef.Threads); if (Err) { @@ -312,6 +322,7 @@ Expect setupContextParam(Graph &GraphRef, llama_context_params &ContextParams) { ContextParams.n_ctx = GraphRef.CtxSize; ContextParams.n_batch = GraphRef.BatchSize; + ContextParams.n_ubatch = GraphRef.UBatchSize; ContextParams.n_threads = GraphRef.Threads; ContextParams.n_threads_batch = GraphRef.Threads; ContextParams.embeddings = GraphRef.Embedding; @@ -478,34 +489,30 @@ Expect getEmbedding(WasiNNEnvironment &Env, // Initialize the llama context. llama_context_params ContextParams = llama_context_default_params(); setupContextParam(GraphRef, ContextParams); + // For non-causal models, batch size must be equal to ubatch size + ContextParams.n_ubatch = ContextParams.n_batch; auto *LlamaContext = llama_new_context_with_model(GraphRef.LlamaModel, ContextParams); - // Get the context size. - const uint64_t NCtx = llama_n_ctx(LlamaContext); - // Minus 4 for the special tokens. (Such as , , ... tokens.) - const uint64_t MaxTokensListSize = NCtx - 4; // Use the const sequence id here. const llama_seq_id SequenceId = 0; // Return value. auto ReturnCode = ErrNo::Success; - // Add BOS if not present. - if (CxtRef.LlamaInputs.front() != llama_token_bos(GraphRef.LlamaModel)) { - CxtRef.LlamaInputs.insert(CxtRef.LlamaInputs.begin(), - llama_token_bos(GraphRef.LlamaModel)); - } - // Add EOS if not present. - if (!llama_token_is_eog(GraphRef.LlamaModel, CxtRef.LlamaInputs.back())) { - CxtRef.LlamaInputs.push_back(llama_token_eos(GraphRef.LlamaModel)); + // Add SEP if not present. + if (CxtRef.LlamaInputs.back() != llama_token_sep(GraphRef.LlamaModel)) { + CxtRef.LlamaInputs.push_back(llama_token_sep(GraphRef.LlamaModel)); } // Check if the input is too long. - if (static_cast(CxtRef.LlamaInputs.size()) > MaxTokensListSize) { + if (static_cast(CxtRef.LlamaInputs.size()) > + ContextParams.n_batch) { if (GraphRef.EnableLog) { - spdlog::info("[WASI-NN] GGML backend: the prompt is too long. Your input " - "has {} tokens. Please reduce it to {} tokens."sv, - CxtRef.LlamaInputs.size(), MaxTokensListSize); + spdlog::info( + "[WASI-NN] GGML backend: the prompt is too long. " + "Your input has {} tokens exceeds batch size {}. " + "Please reduce the input size or increase your batch-size."sv, + CxtRef.LlamaInputs.size(), ContextParams.n_batch); } return ErrNo::PromptTooLong; } @@ -857,13 +864,15 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: set the input"sv); } - const bool AddBos = llama_should_add_bos_token(GraphRef.LlamaModel); + const bool AddSpecial = true; + const bool ParseSpecial = true; std::string Prompt(reinterpret_cast(Tensor.Tensor.data()), Tensor.Tensor.size()); CxtRef.LlamaInputs.clear(); if (GraphRef.MMProjModelPath == ""sv) { // Text only prompt. - CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddBos, true); + CxtRef.LlamaInputs = + llama_tokenize(LlamaContext, Prompt, AddSpecial, ParseSpecial); } else { // Handle llava format prompt. @@ -929,10 +938,12 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, std::string PromptBeforeImage = Prompt.substr(0, PlaceholderPosition); std::string PromptAfterImage = Prompt.substr(PlaceholderPosition + PromptImagePlaceholder.length()); - std::vector EmbdInputBeforeImage = - llama_tokenize(LlamaContext, PromptBeforeImage, AddBos, true); + std::vector EmbdInputBeforeImage = llama_tokenize( + LlamaContext, PromptBeforeImage, AddSpecial, ParseSpecial); + // Do not add special token (such as , , ... tokens.) to the + // tokens after the image. std::vector EmbdInputAfterImage = - llama_tokenize(LlamaContext, PromptAfterImage, false, true); + llama_tokenize(LlamaContext, PromptAfterImage, false, ParseSpecial); CxtRef.LlavaImagePosition = EmbdInputBeforeImage.size(); CxtRef.LlamaInputs.reserve(EmbdInputBeforeImage.size() + EmbdInputAfterImage.size()); diff --git a/plugins/wasi_nn/ggml.h b/plugins/wasi_nn/ggml.h index e334ca5df16c..25c02caa6abc 100644 --- a/plugins/wasi_nn/ggml.h +++ b/plugins/wasi_nn/ggml.h @@ -38,6 +38,7 @@ struct Graph { // Context parameters: uint64_t CtxSize; uint64_t BatchSize; + uint64_t UBatchSize; uint64_t Threads; // Sampling parameters: double Temp = 0.80; From d8ea5b95f1faed17e070f4a317b0f1612a5f3879 Mon Sep 17 00:00:00 2001 From: dm4 Date: Fri, 3 May 2024 16:11:28 +0800 Subject: [PATCH 177/218] [WASI-NN] ggml: bump llama.cpp b2781 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 424af4ab0eab..0899b8917cd4 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -95,7 +95,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2734 + GIT_TAG b2781 GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) From 74a1e1a8ad723a4fbc45b112c9d90ea81aca066c Mon Sep 17 00:00:00 2001 From: hydai Date: Sun, 5 May 2024 17:16:51 +0800 Subject: [PATCH 178/218] [Installer] enable pre-built noavx ggml plugin on Ubuntu 20.04 (#3385) Signed-off-by: hydai Signed-off-by: hydai --- .github/workflows/test-install-script.yml | 10 ++++++ .github/workflows/test-installer-v2.yml | 6 ++++ .../workflows/test-python-install-script.yml | 13 +++++-- utils/install.py | 3 ++ utils/install_v2.sh | 36 +++++++++++++------ 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test-install-script.yml b/.github/workflows/test-install-script.yml index 9d8e81137f72..108fc32ce20a 100644 --- a/.github/workflows/test-install-script.yml +++ b/.github/workflows/test-install-script.yml @@ -133,6 +133,16 @@ jobs: - name: Uninstall WasmEdge with wasi_nn-ggml run: | bash utils/uninstall.sh -q -V + - name: Install WasmEdge and wasi_nn-ggml-noavx plugin (0.13.5) + if: ${{ matrix.docker_image == 'ubuntu:20.04' }} + run: | + # Currently, we only support noavx build on ubuntu 20.04 + bash utils/install.sh -v 0.13.5 --plugins wasi_nn-ggml-noavx -D + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Uninstall WasmEdge with wasi_nn-ggml-noavx + if: ${{ matrix.docker_image == 'ubuntu:20.04' }} + run: | + bash utils/uninstall.sh -q -V - name: Install versions multiple times run: | bash utils/install.sh -e all -D diff --git a/.github/workflows/test-installer-v2.yml b/.github/workflows/test-installer-v2.yml index 73653f8c5233..45cc1d660469 100644 --- a/.github/workflows/test-installer-v2.yml +++ b/.github/workflows/test-installer-v2.yml @@ -57,6 +57,12 @@ jobs: # It should uninstall the previous installation and install WasmEdge and the GGML plugin again bash utils/install_v2.sh -V ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Run installer-v2 with noavx option + if: ${{ matrix.docker_image == 'ubuntu:20.04' }} + run: | + # It will install WasmEdge and the noavx GGML plugin + bash utils/install_v2.sh -V --noavx + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) - name: Uninstall WasmEdge run: | bash utils/uninstall.sh -q -V diff --git a/.github/workflows/test-python-install-script.yml b/.github/workflows/test-python-install-script.yml index 383d8d9d56cd..75828e3d5122 100644 --- a/.github/workflows/test-python-install-script.yml +++ b/.github/workflows/test-python-install-script.yml @@ -207,10 +207,19 @@ jobs: ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) # With the build number - ${{ matrix.python2_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-b2334 + ${{ matrix.python2_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-b2781 ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) - ${{ matrix.python3_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-b2334 + ${{ matrix.python3_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-b2781 + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) + - name: Plugin install test - WasmEdge WASI-NN-GGML-noavx + if: ${{ matrix.name == 'Ubuntu 20.04' }} + run: | + # Without the build number + ${{ matrix.python2_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-noavx + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) + + ${{ matrix.python3_ex }} utils/install.py -v 0.13.5 --plugins wasi_nn-ggml-noavx ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: Plugins found" || (echo "Fail: Wasmedge WASI-NN GGML Plugin not found" && exit 1) - name: Plugin install test - WasmEdge rustls if: ${{ matrix.name != 'manylinux2014 aarch64' }} diff --git a/utils/install.py b/utils/install.py index 0db114b3baf6..eb6fe81d9936 100644 --- a/utils/install.py +++ b/utils/install.py @@ -339,6 +339,7 @@ def compare(self, version2, separator=". |-", ignorecase=True): WASI_NN_TENSORFLOW_LITE = "wasi_nn-tensorflowlite" WASI_NN_GGML = "wasi_nn-ggml" WASI_NN_GGML_CUDA = "wasi_nn-ggml-cuda" +WASI_NN_GGML_NOAVX = "wasi_nn-ggml-noavx" WASI_NN_GGML_BLAS = "wasi_nn-ggml-blas" WASMEDGE_TENSORFLOW_PLUGIN = WASMEDGE.lower() + "_" + TENSORFLOW WASMEDGE_TENSORFLOW_LITE_PLUGIN = WASMEDGE.lower() + "_" + TENSORFLOW_LITE_P @@ -353,6 +354,7 @@ def compare(self, version2, separator=". |-", ignorecase=True): WASI_NN_TENSORFLOW_LITE, WASI_NN_GGML, WASI_NN_GGML_CUDA, + WASI_NN_GGML_NOAVX, WASI_NN_GGML_BLAS, WASMEDGE_TENSORFLOW_PLUGIN, WASMEDGE_TENSORFLOW_LITE_PLUGIN, @@ -370,6 +372,7 @@ def compare(self, version2, separator=". |-", ignorecase=True): "ubuntu20.04" + "x86_64" + WASI_NN_PYTORCH: VersionString("0.11.1-alpha.1"), "ubuntu20.04" + "x86_64" + WASI_NN_GGML: VersionString("0.13.4"), "ubuntu20.04" + "aarch64" + WASI_NN_GGML: VersionString("0.13.5"), + "ubuntu20.04" + "x86_64" + WASI_NN_GGML_NOAVX: VersionString("0.13.5"), "ubuntu20.04" + "x86_64" + WASI_NN_GGML_CUDA: VersionString("0.13.4"), "ubuntu20.04" + "aarch64" + WASI_NN_GGML_CUDA: VersionString("0.13.5"), "ubuntu20.04" + "x86_64" + WASI_NN_GGML_BLAS: VersionString("0.13.5"), diff --git a/utils/install_v2.sh b/utils/install_v2.sh index 3d84b3b75d24..ef93996bd37a 100755 --- a/utils/install_v2.sh +++ b/utils/install_v2.sh @@ -188,6 +188,7 @@ IPATH="$__HOME__/.wasmedge" VERBOSE=0 LEGACY=0 ENABLE_RUSTLS=0 +ENABLE_NOAVX=0 set_ENV() { ENV="#!/bin/sh @@ -272,6 +273,9 @@ usage() { -p, --path=[/usr/local] Prefix / Path to install + --noavx Install the GGML noavx plugin. + Default is disabled. + --rustls Install the Rustls plugin. Default is disabled. @@ -366,23 +370,30 @@ get_wasmedge_release() { get_wasmedge_ggml_plugin() { info "Fetching WasmEdge-GGML-Plugin" local CUDA_EXT="" - cuda=$(detect_cuda) - info "Detected CUDA version: ${cuda}" - if [ "${cuda}" == "12" ]; then - CUDA_EXT="-cuda" - elif [ "${cuda}" == "11" ]; then - if [ "${ARCH}" == "aarch64" ]; then + local NOAVX_EXT="" + if [ "${ENABLE_NOAVX}" == "1" ]; then + # If noavx is given, it will only use CPU with noavx instructions. + info "NOAVX option is given: Use the noavx CPU version." + NOAVX_EXT="-noavx" + else + cuda=$(detect_cuda) + info "Detected CUDA version: ${cuda}" + if [ "${cuda}" == "12" ]; then CUDA_EXT="-cuda" + elif [ "${cuda}" == "11" ]; then + if [ "${ARCH}" == "aarch64" ]; then + CUDA_EXT="-cuda" + else + CUDA_EXT="-cuda-11" + fi else - CUDA_EXT="-cuda-11" + CUDA_EXT="" fi - else - CUDA_EXT="" fi - _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}-$VERSION-$RELEASE_PKG" + _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}${NOAVX_EXT}-$VERSION-$RELEASE_PKG" local TMP_PLUGIN_DIR="${TMP_DIR}/${IPKG}/plugin" mkdir -p "${TMP_PLUGIN_DIR}" - _extractor -C "${TMP_PLUGIN_DIR}" -vxzf "${TMP_DIR}/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}-${VERSION}-${RELEASE_PKG}" + _extractor -C "${TMP_PLUGIN_DIR}" -vxzf "${TMP_DIR}/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}${NOAVX_EXT}-${VERSION}-${RELEASE_PKG}" } get_wasmedge_rustls_plugin() { @@ -448,6 +459,9 @@ main() { p | path) IPATH="$(_realpath "${OPTARG}")" ;; + noavx) + ENABLE_NOAVX=1 + ;; rustls) ENABLE_RUSTLS=1 ;; From 8c922ba2b2539fa6b165527aec99bfbdbbf74497 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Tue, 7 May 2024 15:25:46 +0800 Subject: [PATCH 179/218] [Executor] Fix the handler popping for exception-handling proposal. (#3387) Signed-off-by: YiYing He --- include/ast/instruction.h | 13 ++++++++++++- lib/executor/engine/engine.cpp | 4 ++-- lib/executor/helper.cpp | 12 ++++-------- lib/loader/ast/instruction.cpp | 12 ++++++++++-- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/include/ast/instruction.h b/include/ast/instruction.h index c2bbe9f22530..9e8e85f9f32d 100644 --- a/include/ast/instruction.h +++ b/include/ast/instruction.h @@ -171,6 +171,15 @@ class Instruction { Data.EndFlags.IsTryBlockLast = Last; } + // LEGACY-EH: remove these functions after deprecating legacy EH. + /// Getter and setter of try block end for End instruction. + bool isLegacyTryBlockLast() const noexcept { + return Data.EndFlags.IsLegacyTryBlockLast; + } + void setLegacyTryBlockLast(bool Last = true) noexcept { + Data.EndFlags.IsLegacyTryBlockLast = Last; + } + /// Getter and setter of Jump for Br* instruction. const JumpDescriptor &getJump() const noexcept { return Data.Jump; } JumpDescriptor &getJump() noexcept { return Data.Jump; } @@ -340,12 +349,14 @@ class Instruction { struct { bool IsExprLast : 1; bool IsTryBlockLast : 1; + // LEGACY-EH: remove this flag after deprecating legacy EH. + bool IsLegacyTryBlockLast : 1; } EndFlags; // Type 10: TypeCastBranch. BrCastDescriptor *BrCast; // Type 11: Try Block. TryDescriptor *TryCatch; - // LEGACY-EH: remove the this case after deprecating legacy EH. + // LEGACY-EH: remove this case after deprecating legacy EH. // Type 12: Legacy Catch descriptor. CatchDescriptorLegacy CatchLegacy; } Data; diff --git a/lib/executor/engine/engine.cpp b/lib/executor/engine/engine.cpp index 605498527059..e5b54e69b065 100644 --- a/lib/executor/engine/engine.cpp +++ b/lib/executor/engine/engine.cpp @@ -136,8 +136,8 @@ Expect Executor::execute(Runtime::StackManager &StackMgr, return Unexpect(ErrCode::Value::CostLimitExceeded); } } - PC += PC->getJumpEnd(); - [[fallthrough]]; + PC += PC->getJumpEnd() - 1; + return {}; case OpCode::End: PC = StackMgr.maybePopFrameOrHandler(PC); return {}; diff --git a/lib/executor/helper.cpp b/lib/executor/helper.cpp index 8a5ea5676587..9f6dfea51645 100644 --- a/lib/executor/helper.cpp +++ b/lib/executor/helper.cpp @@ -31,6 +31,10 @@ Executor::enterFunction(Runtime::StackManager &StackMgr, const uint32_t RetsN = static_cast(FuncType.getReturnTypes().size()); + // For the exception handler, remove the inactive handlers caused by the + // branches. + StackMgr.removeInactiveHandler(RetIt - 1); + if (Func.isHostFunction()) { // Host function case: Push args and call function. auto &HostFunc = Func.getHostFunc(); @@ -237,14 +241,6 @@ Expect Executor::throwException(Runtime::StackManager &StackMgr, // When being here, an exception is caught. Move the PC to the try block // and branch to the label. - // LEGACY-EH: remove this condition after deprecating legacy EH. - // For legacy catch/catch_all, the target block to jump is inside the try - // block, and it must pass through the end instruction of the try block - // and pop the handler. Therefore push the handler back here. - if (C.IsLegacy) { - StackMgr.pushHandler(Handler->Try, 0, {}); - } - PC = Handler->Try; return branchToLabel(StackMgr, C.Jump, PC); } diff --git a/lib/loader/ast/instruction.cpp b/lib/loader/ast/instruction.cpp index b217fdc58de7..08353525be5b 100644 --- a/lib/loader/ast/instruction.cpp +++ b/lib/loader/ast/instruction.cpp @@ -224,6 +224,8 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { if (BackOp == OpCode::Block || BackOp == OpCode::Loop || BackOp == OpCode::If) { Instrs.back().setTryBlockLast(false); + // LEGACY-EH: remove this after deprecating legacy EH. + Instrs.back().setLegacyTryBlockLast(false); Instrs[Pos].setJumpEnd(Cnt - Pos); if (BackOp == OpCode::If) { if (Instrs[Pos].getJumpElse() == 0) { @@ -234,9 +236,15 @@ Expect Loader::loadInstrSeq(std::optional SizeBound) { Instrs[ElsePos].setJumpEnd(Cnt - ElsePos); } } - } else if (BackOp == OpCode::Try || BackOp == OpCode::Try_table) { - // LEGACY-EH: remove the `Try` case after deprecating legacy EH. + } else if (BackOp == OpCode::Try_table) { Instrs.back().setTryBlockLast(true); + // LEGACY-EH: remove this after deprecating legacy EH. + Instrs.back().setLegacyTryBlockLast(false); + Instrs[Pos].getTryCatch().JumpEnd = Cnt - Pos; + } else if (BackOp == OpCode::Try) { + // LEGACY-EH: remove the `Try` case after deprecating legacy EH. + Instrs.back().setTryBlockLast(false); + Instrs.back().setLegacyTryBlockLast(true); Instrs[Pos].getTryCatch().JumpEnd = Cnt - Pos; } BlockStack.pop_back(); From d7b44319c0733b98e646e8b19ac348d779234107 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Wed, 8 May 2024 12:12:44 +0800 Subject: [PATCH 180/218] [Changelog] Update the changelog for the 0.14.0-rc.5 pre-release. (#3391) Signed-off-by: YiYing He --- .CurrentChangelog.md | 8 ++++---- Changelog.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index 8e170eba8b9f..98045764a399 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.4 (2024-04-29) +### 0.14.0-rc.5 (2024-05-08) Breaking changes: @@ -87,7 +87,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2734. + * Bump llama.cpp to b2781. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -154,6 +154,6 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, redismongo, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Harry Chiang, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LFsWang, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hugo-syn, hydai, redismongo, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.5-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index 19d29c14f3c9..bd75a653efba 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-alpha.4 (2024-04-29) +### 0.14.0-rc.5 (2024-05-08) Breaking changes: @@ -87,7 +87,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2734. + * Bump llama.cpp to b2781. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -154,9 +154,9 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hydai, redismongo, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Harry Chiang, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LFsWang, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hugo-syn, hydai, redismongo, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-alpha.4-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-rc.5-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From ea8af32b730b5a5c75c461a1b8f8a9932cf436a6 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Thu, 9 May 2024 19:51:19 +0800 Subject: [PATCH 181/218] [Loader] Fix heap type syntax checking. (#3395) --- lib/loader/ast/type.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/loader/ast/type.cpp b/lib/loader/ast/type.cpp index 748980dc1dd5..a4daf99efef2 100644 --- a/lib/loader/ast/type.cpp +++ b/lib/loader/ast/type.cpp @@ -12,7 +12,11 @@ namespace Loader { Expect Loader::loadHeapType(TypeCode TC, ASTNodeAttr From) { if (auto Res = FMgr.readS33()) { if (*Res < 0) { - // FuncRef or ExternRef case. + if (*Res < -64) { + // For checking the invalid s33 value which is larger than 1 byte. + return logLoadError(ErrCode::Value::MalformedRefType, + FMgr.getLastOffset(), From); + } TypeCode HTCode = static_cast(static_cast((*Res) & INT64_C(0x7F))); switch (HTCode) { From 59f5013cbedbe96c021b45f8f8f1a93a5b3a88d1 Mon Sep 17 00:00:00 2001 From: LFsWang <7088579+LFsWang@users.noreply.github.com> Date: Tue, 14 May 2024 16:21:11 +0800 Subject: [PATCH 182/218] [Misc] Fix the return value of fdAllocate (#3401) Signed-off-by: Sylveon --- lib/host/wasi/inode-linux.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/host/wasi/inode-linux.cpp b/lib/host/wasi/inode-linux.cpp index 655713ef17a4..59b3fa5a352d 100644 --- a/lib/host/wasi/inode-linux.cpp +++ b/lib/host/wasi/inode-linux.cpp @@ -193,7 +193,9 @@ WasiExpect INode::fdAdvise(__wasi_filesize_t Offset, WasiExpect INode::fdAllocate(__wasi_filesize_t Offset, __wasi_filesize_t Len) const noexcept { if (auto Res = ::posix_fallocate(Fd, Offset, Len); unlikely(Res != 0)) { - return WasiUnexpect(fromErrNo(errno)); + // https://man7.org/linux/man-pages/man3/posix_fallocate.3.html + // posix_fallocate will not set errno, use return the value directly. + return WasiUnexpect(fromErrNo(Res)); } return {}; From 955d0b680a8e6a0716776e4fddc6d2b2682a6517 Mon Sep 17 00:00:00 2001 From: LFsWang Date: Tue, 7 May 2024 17:01:40 +0800 Subject: [PATCH 183/218] [Misc] Fix time conversion constant on Windows Signed-off-by: LFsWang --- lib/host/wasi/win.h | 5 ++++- test/host/wasi/wasi.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/host/wasi/win.h b/lib/host/wasi/win.h index 1e98edb4ef7e..d13874f4bd54 100644 --- a/lib/host/wasi/win.h +++ b/lib/host/wasi/win.h @@ -208,7 +208,10 @@ using FiletimeDuration = std::chrono::duration< std::ratio_multiply, std::chrono::nanoseconds::period>>; /// from 1601-01-01 to 1970-01-01, 134774 days static inline constexpr const FiletimeDuration NTToUnixEpoch = - std::chrono::seconds{134774u * 86400u}; + std::chrono::seconds{134774LL * 86400LL}; + +static_assert(std::chrono::duration_cast(NTToUnixEpoch) + .count() == 11644473600LL); static constexpr __wasi_timestamp_t fromFiletime(FILETIME_ FileTime) noexcept { using std::chrono::duration_cast; diff --git a/test/host/wasi/wasi.cpp b/test/host/wasi/wasi.cpp index e57d5c547b2f..8b6414d27de0 100644 --- a/test/host/wasi/wasi.cpp +++ b/test/host/wasi/wasi.cpp @@ -223,7 +223,7 @@ convertFiletime(WasmEdge::winapi::FILETIME_ FileTime) noexcept { std::chrono::nanoseconds::period>>; /// from 1601-01-01 to 1970-01-01, 134774 days constexpr const FiletimeDuration NTToUnixEpoch = - std::chrono::seconds{134774u * 86400u}; + std::chrono::seconds{134774LL * 86400LL}; WasmEdge::winapi::ULARGE_INTEGER_ Temp = { /* LowPart */ FileTime.dwLowDateTime, /* HighPart */ FileTime.dwHighDateTime}; auto Duration = duration_cast(FiletimeDuration{Temp.QuadPart} - From a8ccc936c162622016d940b009c58530031695dd Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Tue, 7 May 2024 17:54:18 +0800 Subject: [PATCH 184/218] [CI] Build and release on manylinux_2_28 x86_64 Signed-off-by: Yi Huang --- .github/workflows/build.yml | 19 +++++++++++++++---- .github/workflows/release.yml | 15 +++++++++++++-- .../workflows/reusable-build-on-manylinux.yml | 4 ++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c255046d8e6a..65352f7f0d65 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,16 +89,27 @@ jobs: matrix: "[{'name':'MacOS 12 (x86_64)','runner':'macos-12','darwin_version':21,'arch':'x86_64'}, {'name':'MacOS 13 (arm64)','runner':'macos-14','darwin_version':22,'arch':'arm64'}]" - build_on_manylinux_2014: + build_on_manylinux2014: permissions: contents: write needs: [get_version, lint] - name: Manylinux2014 + name: Manylinux2014 (deprecated) uses: ./.github/workflows/reusable-build-on-manylinux.yml with: version: ${{ needs.get_version.outputs.version }} - matrix: "[{'name':'manylinux 2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64'}, - {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" + matrix: "[{'name':'manylinux2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64'}, + {'name':'manylinux2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" + + # TODO: add aarch64 + build_on_manylinux_2_28: + permissions: + contents: write + needs: [get_version, lint] + name: Manylinux_2_28 + uses: ./.github/workflows/reusable-build-on-manylinux.yml + with: + version: ${{ needs.get_version.outputs.version }} + matrix: "[{'name':'manylinux_2_28 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux_2_28_x86_64'}]" build_on_debian_static: permissions: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ea9fce7eef0..e9502775ba95 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -73,8 +73,19 @@ jobs: with: version: ${{ needs.create_release.outputs.version }} matrix: - "[{'name':'manylinux 2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64','asset_tag':'manylinux2014_x86_64'}, - {'name':'manylinux 2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64','asset_tag':'manylinux2014_aarch64'}]" + "[{'name':'manylinux2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64','asset_tag':'manylinux2014_x86_64'}, + {'name':'manylinux2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64','asset_tag':'manylinux2014_aarch64'}]" + release: true + secrets: inherit + + # TODO: Add aarch64 + build_on_manylinux_2_28: + needs: create_release + uses: ./.github/workflows/reusable-build-on-manylinux.yml + with: + version: ${{ needs.create_release.outputs.version }} + matrix: + "[{'name':'manylinux_2_28 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux_2_28_x86_64','asset_tag':'manylinux_2_28_x86_64'}]" release: true secrets: inherit diff --git a/.github/workflows/reusable-build-on-manylinux.yml b/.github/workflows/reusable-build-on-manylinux.yml index dada9ac53af9..852e71cafe31 100644 --- a/.github/workflows/reusable-build-on-manylinux.yml +++ b/.github/workflows/reusable-build-on-manylinux.yml @@ -11,10 +11,10 @@ on: required: true release: type: boolean - + permissions: contents: read - + jobs: build_on_manylinux: permissions: From ff072f2b759d8fec969bcbfdde3d04162b7083fc Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 15 May 2024 12:03:53 +0800 Subject: [PATCH 185/218] [WASI-NN] ggml: add more debug log Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 95 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 467bde221c76..70a0f7021bc2 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -544,7 +544,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, llama_free(LlamaContext); if (GraphRef.EnableDebugLog) { - spdlog::info("[WASI-NN][Debug] GGML backend: compute...Done"sv); + spdlog::info("[WASI-NN][Debug] GGML backend: getEmbedding...Done"sv); } return ErrNo::Success; @@ -587,6 +587,10 @@ loadBase64ImageFromPrompt(Graph &GraphRef, clip_ctx *ClipContext, // Follow this link for the supported image formats: // https://github.com/ggerganov/llama.cpp/blob/master/common/stb_image.h + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: loadBase64ImageFromPrompt"sv); + } + // Find ` load(WasiNNEnvironment &Env, Span> Builders, Expect initExecCtx(WasiNNEnvironment &Env, uint32_t GraphId, uint32_t &ContextId) noexcept { + auto &GraphRef = Env.NNGraph[GraphId].get(); + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: initExecCtx"sv); + } Env.NNContext.emplace_back(GraphId, Env.NNGraph[GraphId]); ContextId = Env.NNContext.size() - 1; - auto &GraphRef = Env.NNGraph[GraphId].get(); if (GraphRef.EnableLog) { spdlog::info("[WASI-NN] GGML backend: llama_system_info: {}"sv, llama_print_system_info()); } + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: initExecCtx...Done"sv); + } return ErrNo::Success; } @@ -871,11 +886,21 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, CxtRef.LlamaInputs.clear(); if (GraphRef.MMProjModelPath == ""sv) { // Text only prompt. + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: tokenize text prompt"sv); + } CxtRef.LlamaInputs = llama_tokenize(LlamaContext, Prompt, AddSpecial, ParseSpecial); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: tokenize text prompt...Done"sv); + } } else { // Handle llava format prompt. - + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: handle llava format prompt"sv); + } // Check if the prompt contains a base64 image. bool ContainsBase64Image = containsBase64Image(GraphRef, Prompt); if (GraphRef.ImagePath == ""sv && ContainsBase64Image == false) { @@ -953,6 +978,10 @@ Expect setInput(WasiNNEnvironment &Env, uint32_t ContextId, CxtRef.LlamaInputs.insert(CxtRef.LlamaInputs.end(), EmbdInputAfterImage.begin(), EmbdInputAfterImage.end()); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: handle llava format prompt...Done"sv); + } } CxtRef.LlamaNInputs = CxtRef.LlamaInputs.size(); if (GraphRef.EnableDebugLog) { @@ -980,6 +1009,11 @@ Expect getOutput(WasiNNEnvironment &Env, uint32_t ContextId, uint32_t Index, Span OutBuffer, uint32_t &BytesWritten) noexcept { auto &CxtRef = Env.NNContext[ContextId].get(); + auto &GraphRef = Env.NNGraph[CxtRef.GraphId].get(); + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: getOutput with Index {}"sv, + Index); + } // Index 1 is for the metadata of the outputs. if (Index == 1) { std::string Metadata; @@ -991,12 +1025,22 @@ Expect getOutput(WasiNNEnvironment &Env, uint32_t ContextId, } std::copy_n(Metadata.data(), Metadata.length(), OutBuffer.data()); BytesWritten = Metadata.length(); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: getOutput with Index {}...Done"sv, + Index); + } return ErrNo::Success; } std::copy_n(CxtRef.LlamaOutputs.data(), CxtRef.LlamaOutputs.length(), OutBuffer.data()); BytesWritten = CxtRef.LlamaOutputs.length(); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: getOutput with Index {}...Done"sv, + Index); + } return ErrNo::Success; } @@ -1149,12 +1193,20 @@ Expect compute(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // We free the contexts here to keep the ggml plugin stateless. // Users could fully control the contexts by themselves via their prompt. + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: delete llama context to make it stateless"sv); + } llama_sampling_free(CtxSampling); llama_free(LlamaContext); if (CxtRef.LlavaImageEmbd != nullptr) { llava_image_embed_free(CxtRef.LlavaImageEmbd); CxtRef.LlavaImageEmbd = nullptr; } + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: delete llama context to make it stateless...Done"sv); + } if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: compute...Done"sv); @@ -1167,6 +1219,12 @@ Expect getOutputSingle(WasiNNEnvironment &Env, uint32_t ContextId, uint32_t Index, Span OutBuffer, uint32_t &BytesWritten) noexcept { auto &CxtRef = Env.NNContext[ContextId].get(); + auto &GraphRef = Env.NNGraph[CxtRef.GraphId].get(); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: getOutputSingle with Index {}"sv, + Index); + } // Index 1 is for the metadata of the outputs. if (Index == 1) { std::string Metadata; @@ -1178,12 +1236,22 @@ Expect getOutputSingle(WasiNNEnvironment &Env, uint32_t ContextId, } std::copy_n(Metadata.data(), Metadata.length(), OutBuffer.data()); BytesWritten = Metadata.length(); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: getOutputSingle with Index {}...Done"sv, + Index); + } return ErrNo::Success; } std::string LastToken = llama_token_to_piece(CxtRef.LlamaContext, CxtRef.LlamaOutputTokens.back()); std::copy_n(LastToken.data(), LastToken.length(), OutBuffer.data()); BytesWritten = LastToken.length(); + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: getOutputSingle with Index {}...Done"sv, + Index); + } return ErrNo::Success; } @@ -1333,6 +1401,10 @@ Expect finiSingle(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { auto &CxtRef = Env.NNContext[ContextId].get(); auto &GraphRef = Env.NNGraph[CxtRef.GraphId].get(); + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: finiSingle"sv); + } + // Logging for the llama timings. if (GraphRef.EnableLog) { llama_print_timings(CxtRef.LlamaContext); @@ -1371,17 +1443,34 @@ Expect finiSingle(WasiNNEnvironment &Env, uint32_t ContextId) noexcept { // Reset the context variables. CxtRef.LlamaNPast = 0; + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: finiSingle...Done"sv); + } + return ErrNo::Success; } Expect unload(WasiNNEnvironment &Env, uint32_t GraphId) noexcept { auto &GraphRef = Env.NNGraph[GraphId].get(); + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: unload"sv); + } if (GraphRef.LlamaModel != nullptr) { + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: unload: free llama model"sv); + } llama_free_model(GraphRef.LlamaModel); GraphRef.LlamaModel = nullptr; + if (GraphRef.EnableDebugLog) { + spdlog::info( + "[WASI-NN][Debug] GGML backend: unload: free llama model...Done"sv); + } } Env.NNGraph.erase(Env.NNGraph.begin() + GraphId); Env.mdRemoveById(GraphId); + if (GraphRef.EnableDebugLog) { + spdlog::info("[WASI-NN][Debug] GGML backend: unload...Done"sv); + } return ErrNo::Success; } From 7ce2b3a18cc501779dedb43cee2dc61ae7473e98 Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 15 May 2024 15:22:08 +0800 Subject: [PATCH 186/218] [WASI-NN] ggml: free the llama batch Signed-off-by: dm4 --- plugins/wasi_nn/ggml.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/wasi_nn/ggml.cpp b/plugins/wasi_nn/ggml.cpp index 70a0f7021bc2..e84c0a299eb2 100644 --- a/plugins/wasi_nn/ggml.cpp +++ b/plugins/wasi_nn/ggml.cpp @@ -542,6 +542,7 @@ Expect getEmbedding(WasiNNEnvironment &Env, // We free the contexts here to keep the ggml plugin stateless. // Users could fully control the contexts by themselves via their prompt. llama_free(LlamaContext); + llama_batch_free(Batch); if (GraphRef.EnableDebugLog) { spdlog::info("[WASI-NN][Debug] GGML backend: getEmbedding...Done"sv); From 3a5e0a29d5bf095ee5f047704d42bb26bfad519c Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 15 May 2024 15:27:40 +0800 Subject: [PATCH 187/218] [WASI-NN] ggml: bump llama.cpp b2879 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 0899b8917cd4..28b5e01bbbe5 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -95,7 +95,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2781 + GIT_TAG b2879 GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) From 9092047888141ede169cbc9aa7850a4d357a74cc Mon Sep 17 00:00:00 2001 From: YiYing He Date: Thu, 16 May 2024 10:08:30 +0800 Subject: [PATCH 188/218] [Misc] Update the description of proposal enumeration. Signed-off-by: YiYing He --- include/common/enum.inc | 33 +++++++++++++++++++-------------- lib/common/errinfo.cpp | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/include/common/enum.inc b/include/common/enum.inc index cf55fbdc8424..66f21489d47f 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -725,23 +725,28 @@ OFE(I64__atomic__rmw32__cmpxchg_u, "i64.atomic.rmw32.cmpxchg_u", 0xFE, 78) #ifdef UseProposal #define P Line -P(ImportExportMutGlobals, "Import/Export of mutable globals") -P(NonTrapFloatToIntConversions, "Non-trapping float-to-int conversions") -P(SignExtensionOperators, "Sign-extension operators") -P(MultiValue, "Multi-value returns") -P(BulkMemoryOperations, "Bulk memory operations") -P(ReferenceTypes, "Reference types") +// Finished and standardized proposals +P(ImportExportMutGlobals, "Import/Export of Mutable Globals") +P(NonTrapFloatToIntConversions, "Non-trapping float-to-int Conversions") +P(SignExtensionOperators, "Sign-extension Operators") +P(MultiValue, "Multi-value") +P(BulkMemoryOperations, "Bulk Memory Operations") +P(ReferenceTypes, "Reference Types") P(SIMD, "Fixed-width SIMD") -P(TailCall, "Tail call") -P(MultiMemories, "Multiple memories") +// Phase 4 proposals +P(TailCall, "Tail Call") +P(ExtendedConst, "Extended Const Expressions") +P(FunctionReferences, "Typed Function References") +P(GC, "Garbage Collection") +P(MultiMemories, "Multiple Memories") +P(Threads, "Threads") +P(RelaxSIMD, "Relaxed SIMD") +// Phase 3 proposals P(Annotations, "Custom Annotation Syntax in the Text Format") P(Memory64, "Memory64") -P(ExceptionHandling, "Exception handling") -P(ExtendedConst, "Extended const") -P(Threads, "Threads") -P(FunctionReferences, "Typed Function References") -P(Component, "Component model") -P(GC, "GC proposal") +P(ExceptionHandling, "Exception Handling") +// Phase 1 proposals +P(Component, "Component Model") #undef P #endif // UseProposal diff --git a/lib/common/errinfo.cpp b/lib/common/errinfo.cpp index f2bd01bfea24..188a183602d7 100644 --- a/lib/common/errinfo.cpp +++ b/lib/common/errinfo.cpp @@ -305,7 +305,7 @@ fmt::formatter::format( Iter != WasmEdge::ProposalStr.end()) { fmt::format_to( std::back_inserter(Buffer), - " This instruction or syntax requires enabling proposal {}"sv, + " This instruction or syntax requires enabling {} proposal"sv, Iter->second); } else { fmt::format_to(std::back_inserter(Buffer), From 3f73cd41b42a43f3718b0d08f6bcdaef5cb4f238 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 17 May 2024 16:40:03 +0800 Subject: [PATCH 189/218] [CI] Build and release on manylinux_2_28 aarch64 Signed-off-by: Yi Huang --- .github/workflows/build.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65352f7f0d65..dd980a7981c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -100,7 +100,6 @@ jobs: matrix: "[{'name':'manylinux2014 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux2014_x86_64'}, {'name':'manylinux2014 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux2014_aarch64'}]" - # TODO: add aarch64 build_on_manylinux_2_28: permissions: contents: write @@ -109,7 +108,8 @@ jobs: uses: ./.github/workflows/reusable-build-on-manylinux.yml with: version: ${{ needs.get_version.outputs.version }} - matrix: "[{'name':'manylinux_2_28 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux_2_28_x86_64'}]" + matrix: "[{'name':'manylinux_2_28 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux_2_28_x86_64'}, + {'name':'manylinux_2_28 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux_2_28_aarch64'}]" build_on_debian_static: permissions: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e9502775ba95..8b8a4d610132 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,14 +78,14 @@ jobs: release: true secrets: inherit - # TODO: Add aarch64 build_on_manylinux_2_28: needs: create_release uses: ./.github/workflows/reusable-build-on-manylinux.yml with: version: ${{ needs.create_release.outputs.version }} matrix: - "[{'name':'manylinux_2_28 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux_2_28_x86_64','asset_tag':'manylinux_2_28_x86_64'}]" + "[{'name':'manylinux_2_28 x86_64','runner':'ubuntu-latest','docker_tag':'manylinux_2_28_x86_64','asset_tag':'manylinux_2_28_x86_64'}, + {'name':'manylinux_2_28 aarch64','runner':'linux-arm64-v2','docker_tag':'manylinux_2_28_aarch64','asset_tag':'manylinux_2_28_aarch64'}]" release: true secrets: inherit From 9f9b4cde0f4c867ec4331599e531705ab369bc46 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Fri, 10 May 2024 17:40:21 +0800 Subject: [PATCH 190/218] [CI] Refactor with matrix Signed-off-by: Yi Huang --- .github/workflows/docker.yml | 103 +++++++++++------------------------ 1 file changed, 32 insertions(+), 71 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1426d4b3ec92..5e8c7d098571 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -195,12 +195,30 @@ jobs: org.opencontainers.image.created=${{ needs.prep.outputs.created }} org.opencontainers.image.revision=${{ github.sha }} - build-manylinux2014_x86_64: - name: build-manylinux2014_x86_64 - runs-on: ubuntu-latest + build-manylinux-docker-images: + strategy: + fail-fast: false + matrix: + include: + - name: manylinux2014 x86_64 + docker_tag: manylinux2014_x86_64 + dockerfile: utils/docker/Dockerfile.manylinux2014_x86_64 + dockerfile_plugin: utils/docker/Dockerfile.manylinux2014-build-plugins-deps + target_platforms: linux/amd64 + host_runner: ubuntu-latest + host_container: wasmedge/wasmedge:ci-image-base + - name: manylinux_2_28 x86_64 + docker_tag: manylinux_2_28_x86_64 + dockerfile: utils/docker/Dockerfile.manylinux_2_28_x86_64 + dockerfile_plugin: utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps + target_platforms: linux/amd64 + host_runner: ubuntu-latest + host_container: wasmedge/wasmedge:ci-image-base + name: build ${{ matrix.name }} + runs-on: ${{ matrix.host_runner }} needs: [prep] container: - image: wasmedge/wasmedge:ci-image-base + image: ${{ matrix.host_container }} steps: - name: Checkout code @@ -216,72 +234,15 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: "Rebuild wasmedge/wasmedge:manylinux2014_x86_64" - uses: docker/build-push-action@v5 - with: - build-args: BASE=quay.io/pypa/manylinux2014_x86_64 - context: ./utils/docker - file: utils/docker/Dockerfile.manylinux2014_x86_64 - platforms: linux/amd64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ needs.prep.outputs.docker_image }}:manylinux2014_x86_64 - labels: | - org.opencontainers.image.title=${{ github.event.repository.name }} - org.opencontainers.image.description=${{ github.event.repository.description }} - org.opencontainers.image.url=${{ github.event.repository.html_url }} - org.opencontainers.image.source=${{ github.event.repository.clone_url }} - org.opencontainers.image.version=${{ needs.prep.outputs.version }} - org.opencontainers.image.created=${{ needs.prep.outputs.created }} - org.opencontainers.image.revision=${{ github.sha }} - - - name: "Rebuild wasmedge/wasmedge:manylinux2014_x86_64-plugins-deps" - uses: docker/build-push-action@v5 - with: - build-args: BASE=wasmedge/wasmedge:manylinux2014_x86_64 - context: ./utils - file: utils/docker/Dockerfile.manylinux2014-build-plugins-deps - platforms: linux/amd64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ needs.prep.outputs.docker_image }}:manylinux2014_x86_64-plugins-deps - labels: | - org.opencontainers.image.title=${{ github.event.repository.name }} - org.opencontainers.image.description=${{ github.event.repository.description }} - org.opencontainers.image.url=${{ github.event.repository.html_url }} - org.opencontainers.image.source=${{ github.event.repository.clone_url }} - org.opencontainers.image.version=${{ needs.prep.outputs.version }} - org.opencontainers.image.created=${{ needs.prep.outputs.created }} - org.opencontainers.image.revision=${{ github.sha }} - - build-manylinux_2_28_x86_64: - name: build-manylinux_2_28_x86_64 - runs-on: ubuntu-latest - needs: [prep] - container: - image: wasmedge/wasmedge:ci-image-base - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - - name: "Rebuild wasmedge/wasmedge:manylinux_2_28_x86_64" + - name: "Rebuild wasmedge/wasmedge:${{ matrix.docker_tag }}" uses: docker/build-push-action@v5 with: - build-args: BASE=quay.io/pypa/manylinux_2_28_x86_64 + build-args: BASE=quay.io/pypa/${{ matrix.docker_tag }} context: ./utils/docker - file: utils/docker/Dockerfile.manylinux_2_28_x86_64 - platforms: linux/amd64 + file: ${{ matrix.dockerfile }} + platforms: ${{ matrix.target_platforms }} push: ${{ github.event_name != 'pull_request' }} - tags: ${{ needs.prep.outputs.docker_image }}:manylinux_2_28_x86_64 + tags: ${{ needs.prep.outputs.docker_image }}:${{ matrix.docker_tag }} labels: | org.opencontainers.image.title=${{ github.event.repository.name }} org.opencontainers.image.description=${{ github.event.repository.description }} @@ -291,15 +252,15 @@ jobs: org.opencontainers.image.created=${{ needs.prep.outputs.created }} org.opencontainers.image.revision=${{ github.sha }} - - name: "Rebuild wasmedge/wasmedge:manylinux_2_28_x86_64-plugins-deps" + - name: "Rebuild wasmedge/wasmedge:${{ matrix.docker_tag }}-plugins-deps" uses: docker/build-push-action@v5 with: - build-args: BASE=wasmedge/wasmedge:manylinux_2_28_x86_64 + build-args: BASE=wasmedge/wasmedge:${{ matrix.docker_tag }} context: ./utils - file: utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps - platforms: linux/amd64 + file: ${{ matrix.dockerfile_plugin }} + platforms: ${{ matrix.target_platforms }} push: ${{ github.event_name != 'pull_request' }} - tags: ${{ needs.prep.outputs.docker_image }}:manylinux_2_28_x86_64-plugins-deps + tags: ${{ needs.prep.outputs.docker_image }}:${{ matrix.docker_tag }}-plugins-deps labels: | org.opencontainers.image.title=${{ github.event.repository.name }} org.opencontainers.image.description=${{ github.event.repository.description }} From c216ab3a75f75a5f62ad9738dc9e980c02126054 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Thu, 16 May 2024 16:35:39 +0800 Subject: [PATCH 191/218] [CI] Add aarch64 for `ci-image-base` Signed-off-by: Yi Huang --- .github/workflows/docker.yml | 45 +++++++++++++++----------- utils/docker/Dockerfile.ci-image-base | 2 +- utils/docker/docker-bake.ci-image-base | 26 +++++++++++++++ 3 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 utils/docker/docker-bake.ci-image-base diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5e8c7d098571..cbccd61b9ad6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -50,9 +50,33 @@ jobs: echo "docker_image=$DOCKER_IMAGE" >> $GITHUB_OUTPUT echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT + bake-base-images: + name: Bake `ci-image-base` + needs: [prep] + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Bake and Push + uses: docker/bake-action@v4 + with: + files: utils/docker/docker-bake.ci-image-base + push: ${{ github.event_name != 'pull_request' }} + build-docker-images: name: build-docker-images - needs: [prep] + needs: [prep, bake-base-images] runs-on: ubuntu-latest container: image: wasmedge/wasmedge:ci-image-base @@ -71,23 +95,6 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: "Rebuild wasmedge/wasmedge:ci-image-base" - uses: docker/build-push-action@v5 - with: - context: ./utils/docker - file: utils/docker/Dockerfile.ci-image-base - platforms: linux/amd64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ needs.prep.outputs.docker_image }}:ci-image-base - labels: | - org.opencontainers.image.title=${{ github.event.repository.name }} - org.opencontainers.image.description=${{ github.event.repository.description }} - org.opencontainers.image.url=${{ github.event.repository.html_url }} - org.opencontainers.image.source=${{ github.event.repository.clone_url }} - org.opencontainers.image.version=${{ needs.prep.outputs.version }} - org.opencontainers.image.created=${{ needs.prep.outputs.created }} - org.opencontainers.image.revision=${{ github.sha }} - - name: "Rebuild wasmedge/wasmedge:ubuntu-base" uses: docker/build-push-action@v5 with: @@ -196,6 +203,7 @@ jobs: org.opencontainers.image.revision=${{ github.sha }} build-manylinux-docker-images: + needs: [prep, bake-base-images] strategy: fail-fast: false matrix: @@ -216,7 +224,6 @@ jobs: host_container: wasmedge/wasmedge:ci-image-base name: build ${{ matrix.name }} runs-on: ${{ matrix.host_runner }} - needs: [prep] container: image: ${{ matrix.host_container }} diff --git a/utils/docker/Dockerfile.ci-image-base b/utils/docker/Dockerfile.ci-image-base index 4c7fa368fa56..92f7bd67d8ed 100644 --- a/utils/docker/Dockerfile.ci-image-base +++ b/utils/docker/Dockerfile.ci-image-base @@ -13,7 +13,7 @@ RUN apt update && apt upgrade -y \ RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - RUN add-apt-repository \ - "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" diff --git a/utils/docker/docker-bake.ci-image-base b/utils/docker/docker-bake.ci-image-base new file mode 100644 index 000000000000..0054032c0912 --- /dev/null +++ b/utils/docker/docker-bake.ci-image-base @@ -0,0 +1,26 @@ +group "default" { + targets = [ + "x86_64", + "aarch64" + ] +} + +target "base" { + dockerfile = "./utils/docker/Dockerfile.ci-image-base" + context = "." +} + +target "x86_64" { + inherits = ["base"] + platforms = ["linux/amd64"] + tags = [ + "wasmedge/wasmedge:ci-image-base", + "wasmedge/wasmedge:ci-image-base_x86_64" + ] +} + +target "aarch64" { + inherits = ["base"] + platforms = ["linux/arm64"] + tags = ["wasmedge/wasmedge:ci-image-base_aarch64"] +} From cd4fc7f59c08b77b8381463d50c42a7840b70c3a Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Thu, 16 May 2024 20:56:11 +0800 Subject: [PATCH 192/218] [CI] Build manylinux aarch64 Signed-off-by: Yi Huang --- .github/workflows/docker.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index cbccd61b9ad6..c88c8eb1835e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -222,6 +222,20 @@ jobs: target_platforms: linux/amd64 host_runner: ubuntu-latest host_container: wasmedge/wasmedge:ci-image-base + - name: manylinux2014 aarch64 + docker_tag: manylinux2014_aarch64 + dockerfile: utils/docker/Dockerfile.manylinux2014_aarch64 + dockerfile_plugin: utils/docker/Dockerfile.manylinux2014-build-plugins-deps + target_platforms: linux/arm64 + host_runner: linux-arm64-v2 + host_container: wasmedge/wasmedge:ci-image-base_aarch64 + - name: manylinux_2_28 aarch64 + docker_tag: manylinux_2_28_aarch64 + dockerfile: utils/docker/Dockerfile.manylinux_2_28_aarch64 + dockerfile_plugin: utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps + target_platforms: linux/arm64 + host_runner: linux-arm64-v2 + host_container: wasmedge/wasmedge:ci-image-base_aarch64 name: build ${{ matrix.name }} runs-on: ${{ matrix.host_runner }} container: From d9bec87783fde4f241dc3b89fa121c750a9ebd27 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Mon, 20 May 2024 16:19:55 +0800 Subject: [PATCH 193/218] [WASI-NN] Hide unsupported flags from nvcc Signed-off-by: Shen-Ta Hsieh --- plugins/wasi_nn/CMakeLists.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 28b5e01bbbe5..a35418aabac3 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -55,15 +55,16 @@ if(BACKEND STREQUAL "ggml") message(STATUS "Downloading llama.cpp source") if(MSVC) add_compile_options( - /utf-8 - /wd4067 # unexpected tokens following preprocessor directive - expected a newline - /wd4101 # 'identifier' : unreferenced local variable - /wd4189 # 'identifier' : local variable is initialized but not referenced - /wd4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data - /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data - /wd4297 # 'function' : function assumed not to throw an exception but does - /wd4456 # declaration of 'identifier' hides previous local declaration - /wd4505 # 'function' : unreferenced local function has been removed + $<$:/utf-8> + $<$:-Xcompiler=/utf-8> + $<$:/wd4067> # unexpected tokens following preprocessor directive - expected a newline + $<$:/wd4101> # 'identifier' : unreferenced local variable + $<$:/wd4189> # 'identifier' : local variable is initialized but not referenced + $<$:/wd4244> # 'argument' : conversion from 'type1' to 'type2', possible loss of data + $<$:/wd4267> # 'var' : conversion from 'size_t' to 'type', possible loss of data + $<$:/wd4297> # 'function' : function assumed not to throw an exception but does + $<$:/wd4456> # declaration of 'identifier' hides previous local declaration + $<$:/wd4505> # 'function' : unreferenced local function has been removed ) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") From 3759c7003fbba8b2e0f1efa99e366b9d531b5513 Mon Sep 17 00:00:00 2001 From: Shen-Ta Hsieh Date: Tue, 23 Apr 2024 12:34:43 +0800 Subject: [PATCH 194/218] [WASI-NN] Fix compiler warning for variable size Signed-off-by: Shen-Ta Hsieh --- .../wasi_nn_rpcserver/wasi_nn_rpcserver.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h b/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h index 2bebf9afd105..443730303c2b 100644 --- a/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h +++ b/include/driver/wasi_nn_rpc/wasi_nn_rpcserver/wasi_nn_rpcserver.h @@ -114,7 +114,8 @@ class GraphService final : public wasi_ephemeral_nn::Graph::Service { std::string_view FuncName = "load_by_name"sv; auto Name = RPCRequest->name(); uint32_t NamePtr = UINT32_C(0); - uint32_t NameLen = Name.size(); // does not include the '\0' terminator + uint32_t NameLen = static_cast( + Name.size()); // does not include the '\0' terminator uint32_t OutPtr = NamePtr + NameLen + 1; // 1 is for the '\0' terminator uint32_t MemorySize = OutPtr + 4; // 4 is for sizeof(OutPtr) @@ -148,9 +149,10 @@ class GraphService final : public wasi_ephemeral_nn::Graph::Service { auto Name = RPCRequest->name(); auto Config = RPCRequest->config(); uint32_t NamePtr = UINT32_C(0); - uint32_t NameLen = Name.size(); // does not include the '\0' terminator - uint32_t ConfigPtr = - Name.size() + 1; // 1 is for the '\0' terminator of Name + uint32_t NameLen = static_cast( + Name.size()); // does not include the '\0' terminator + uint32_t ConfigPtr = static_cast( + Name.size() + 1); // 1 is for the '\0' terminator of Name uint32_t ConfigLen = Config.size(); // does not include the '\0' terminator uint32_t OutPtr = NamePtr + NameLen + 1 + ConfigLen + 1; // 1 is for the '\0' terminator @@ -232,7 +234,7 @@ class GraphExecutionContextResourceService final uint32_t TensorDimSize = TensorDim.size(); uint32_t TensorTy = Tensor.ty(); auto TensorData = Tensor.data(); - uint32_t TensorDataSize = TensorData.size(); + uint32_t TensorDataSize = static_cast(TensorData.size()); /* clang-format off */ /** From adb635a6ac848cd0a67692382d503b4043a62bef Mon Sep 17 00:00:00 2001 From: dm4 Date: Mon, 20 May 2024 16:18:50 +0800 Subject: [PATCH 195/218] [WASI-NN] ggml: bump llama.cpp b2943 Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index a35418aabac3..285a727f38b5 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -96,7 +96,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2879 + GIT_TAG b2943 GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) From e0e3039bb4809f195844ce66550822d0997d5ff8 Mon Sep 17 00:00:00 2001 From: Sylveon Date: Sun, 19 May 2024 17:41:15 +0800 Subject: [PATCH 196/218] [Misc] dladdr for Windows Signed-off-by: LFsWang --- include/system/winapi.h | 26 ++++++++++++++++++++++++++ lib/plugin/plugin.cpp | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/include/system/winapi.h b/include/system/winapi.h index ee60c6355493..913f872e2242 100644 --- a/include/system/winapi.h +++ b/include/system/winapi.h @@ -1694,4 +1694,30 @@ inline ULONG_ RtlNtStatusToDosError(NTSTATUS_ Status) noexcept { } // namespace WasmEdge::winapi #endif +extern "C" { +WASMEDGE_WINAPI_SYMBOL_IMPORT +WasmEdge::winapi::BOOL_ WASMEDGE_WINAPI_WINAPI_CC GetModuleHandleExW( + WasmEdge::winapi::DWORD_ dwFlags, WasmEdge::winapi::LPCWSTR_ lpModuleName, + WasmEdge::winapi::HMODULE_ *phModule); + +WASMEDGE_WINAPI_SYMBOL_IMPORT +WasmEdge::winapi::DWORD_ WASMEDGE_WINAPI_WINAPI_CC GetModuleFileNameW( + WasmEdge::winapi::HMODULE_ hModule, WasmEdge::winapi::LPWSTR_ lpFilename, + WasmEdge::winapi::DWORD_ nSize); +} // extern "C" + +namespace WasmEdge::winapi { +using ::GetModuleFileNameW; +using ::GetModuleHandleExW; +} // namespace WasmEdge::winapi + +namespace WasmEdge::winapi { +static inline constexpr const DWORD_ GET_MODULE_HANDLE_EX_FLAG_PIN_ = + 0x00000001L; +static inline constexpr const DWORD_ + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT_ = 0x00000002L; +static inline constexpr const DWORD_ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS_ = + 0x00000004L; +} // namespace WasmEdge::winapi + #endif diff --git a/lib/plugin/plugin.cpp b/lib/plugin/plugin.cpp index 6883d129e248..4b4ac85db18d 100644 --- a/lib/plugin/plugin.cpp +++ b/lib/plugin/plugin.cpp @@ -14,6 +14,33 @@ #include #elif WASMEDGE_OS_WINDOWS #include "system/winapi.h" + +static bool GetFunctionModuleFileName(void *FuncPtr, + std::filesystem::path &Path) { + WasmEdge::winapi::HMODULE_ Module = nullptr; + + if (!WasmEdge::winapi::GetModuleHandleExW( + WasmEdge::winapi::GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS_ | + WasmEdge::winapi::GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT_, + reinterpret_cast(FuncPtr), &Module)) { + return false; + } + + std::vector Buffer; + WasmEdge::winapi::DWORD_ CopiedSize; + do { + Buffer.resize(Buffer.size() + WasmEdge::winapi::MAX_PATH_); + CopiedSize = WasmEdge::winapi::GetModuleFileNameW( + Module, Buffer.data(), + static_cast(Buffer.size())); + if (CopiedSize == 0) { + return false; + } + } while (CopiedSize >= Buffer.size()); + + Path.assign(std::wstring_view(Buffer.data(), CopiedSize)); + return true; +} #endif namespace WasmEdge { @@ -257,9 +284,15 @@ std::vector Plugin::getDefaultPluginPaths() noexcept { return std::vector(); } #elif WASMEDGE_OS_WINDOWS - // FIXME: Use the `dladdr`. // Global plugin directory. - Result.push_back(std::filesystem::u8path(kGlobalPluginDir)); + if (std::filesystem::path Path; GetFunctionModuleFileName( + reinterpret_cast(Plugin::getDefaultPluginPaths), Path)) { + Result.push_back(Path.parent_path()); + } else { + spdlog::error("Failed to get the path of the current module."sv); + return std::vector(); + } + // Local home plugin directory. std::filesystem::path Home; if (const auto HomeEnv = ::getenv("USERPROFILE")) { From 609e805f63a207e90f6b17c3a6f8af7d00367a58 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Thu, 16 May 2024 18:55:31 +0800 Subject: [PATCH 197/218] [Examples] Update wasi-logging example. Signed-off-by: YiYing He --- examples/plugin/wasi-logging/Cargo.toml | 2 +- examples/plugin/wasi-logging/README.md | 100 ++++++++++++------- examples/plugin/wasi-logging/src/lib.rs | 24 +++-- examples/plugin/wasi-logging/wit/logging.wit | 2 +- examples/plugin/wasi-logging/wit/world.wit | 6 +- 5 files changed, 85 insertions(+), 49 deletions(-) diff --git a/examples/plugin/wasi-logging/Cargo.toml b/examples/plugin/wasi-logging/Cargo.toml index caaa5b40caae..b86184556d15 100644 --- a/examples/plugin/wasi-logging/Cargo.toml +++ b/examples/plugin/wasi-logging/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev="2ec8e3e256f493b62c561a68300ec09c03d040c4" } +wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "9b50b8e78940af080ed3b7c0238e11b04a4bd17b" } diff --git a/examples/plugin/wasi-logging/README.md b/examples/plugin/wasi-logging/README.md index a64889aa6a04..b660a4b4774c 100644 --- a/examples/plugin/wasi-logging/README.md +++ b/examples/plugin/wasi-logging/README.md @@ -1,10 +1,10 @@ -# WasmEdge WASI-Logging example. +# WasmEdge WASI-Logging example This is an example of using the WASI-Logging plugin of WasmEdge in Rust. ## Prerequisites -### Install Rust. +### Install Rust Follow the instructions below to install Rust and wasm32-wasi target. @@ -13,7 +13,7 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup target add wasm32-wasi ``` -### Install WasmEdge and WASI-Logging plugin. +### Install WasmEdge and WASI-Logging plugin Build wasmedge from scratch with the WASI-Logging plugin enabled. @@ -29,14 +29,14 @@ export WASMEDGE_PLUGIN_PATH=$PWD/plugins/wasi_logging If you install WasmEdge using the install script, you can copy library `wasmedge/build/plugins/wasi_logging/libwasmedgePluginWasiLogging.so` to `$HOME/.wasmedge/plugin/` -### (Optional) Download WASI-Logging WIT files +### (Optional) Download WASI-Logging WIT files In the example, we already prepare the WIT files in `wit` directory. The WIT files are from [wasi-logging](https://github.com/WebAssembly/wasi-logging) repo. You can get the same WIT files by doing the following steps. -``` +```sh git clone https://github.com/WebAssembly/wasi-logging.git cd wasi-logging -git checkout 0a6225ba5f3e90cf72fb75a9796e3e92ff006a65 +git checkout 3293e84de91a1ead98a1b4362f95ac8af5a16ddd cp -r wit /path/to/wasmedge/examples/plugin/wasi-logging ``` @@ -48,6 +48,10 @@ cargo build --target wasm32-wasi Then we get `target/wasm32-wasi/debug/wasi-logging-example.wasm`. +## Logging context + +For the logging context of the `log` function in Rust, developers can use the `""` or `"stdout"` to log to the console, use the `"stderr"` to log to standard error output, or use the file name to log into the target file. + ## Run the example We can run this example with `wasmedge` like @@ -58,32 +62,60 @@ wasmedge target/wasm32-wasi/debug/wasi-logging-example.wasm This example should run successfully and print out the log as follow. +```sh +[2024-05-21 13:43:53.240] [info] =================================== +[2024-05-21 13:43:53.240] [info] Stdout Message Demo +[2024-05-21 13:43:53.240] [info] ----------------------------------- +[2024-05-21 13:43:53.240] [trace] Trace Level Message +[2024-05-21 13:43:53.240] [debug] Debug Level Message +[2024-05-21 13:43:53.240] [info] Info Level Message +[2024-05-21 13:43:53.240] [warning] Warn Level Message +[2024-05-21 13:43:53.240] [error] Error Level Message +[2024-05-21 13:43:53.240] [critical] Critical Level Message +[2024-05-21 13:43:53.240] [info] =================================== +[2024-05-21 13:43:53.240] [info] Stderr Message Demo +[2024-05-21 13:43:53.240] [info] ----------------------------------- +[2024-05-21 13:43:53.240] [trace] Trace Level Message +[2024-05-21 13:43:53.240] [debug] Debug Level Message +[2024-05-21 13:43:53.240] [info] Info Level Message +[2024-05-21 13:43:53.240] [warning] Warn Level Message +[2024-05-21 13:43:53.240] [error] Error Level Message +[2024-05-21 13:43:53.240] [critical] Critical Level Message +[2024-05-21 13:43:53.240] [info] =================================== +[2024-05-21 13:43:53.240] [info] File Message Demo: log/output.log +[2024-05-21 13:43:53.240] [info] ----------------------------------- +[2024-05-21 13:43:53.240] [info] =================================== +[2024-05-21 13:43:53.240] [info] File Message Demo: log/output2.log +[2024-05-21 13:43:53.240] [info] ----------------------------------- +[2024-05-21 13:43:53.240] [info] =================================== +[2024-05-21 13:43:53.240] [info] File Message Demo: continue to log/output.log +[2024-05-21 13:43:53.240] [info] ----------------------------------- +``` + +The log file `log/output.log` will be generated: + +```text +[2024-05-21 13:44:50.966] [trace] Trace Level Message +[2024-05-21 13:44:50.966] [debug] Debug Level Message +[2024-05-21 13:44:50.966] [info] Info Level Message +[2024-05-21 13:44:50.966] [warning] Warn Level Message +[2024-05-21 13:44:50.966] [error] Error Level Message +[2024-05-21 13:44:50.966] [critical] Critical Level Message +[2024-05-21 13:44:50.966] [trace] Trace Level Message +[2024-05-21 13:44:50.966] [debug] Debug Level Message +[2024-05-21 13:44:50.966] [info] Info Level Message +[2024-05-21 13:44:50.966] [warning] Warn Level Message +[2024-05-21 13:44:50.966] [error] Error Level Message +[2024-05-21 13:44:50.966] [critical] Critical Level Message +``` + +The log file `log/output2.log` will be generated: + +```text +[2024-05-21 13:44:50.966] [trace] Trace Level Message +[2024-05-21 13:44:50.966] [debug] Debug Level Message +[2024-05-21 13:44:50.966] [info] Info Level Message +[2024-05-21 13:44:50.966] [warning] Warn Level Message +[2024-05-21 13:44:50.966] [error] Error Level Message +[2024-05-21 13:44:50.966] [critical] Critical Level Message ``` -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] =================================== -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] Demo 1: Stdout Message Demo -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] ----------------------------------- -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [trace] Context: Trace Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [debug] Context: Debug Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] Context: Info Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [warning] Context: Warn Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [error] Context: Error Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [critical] Context: Critical Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] =================================== -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] Demo 2: Stdout Message Without Context -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] ----------------------------------- -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [trace] Trace Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [debug] Debug Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] Info Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [warning] Warn Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [error] Error Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [critical] Critical Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] =================================== -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] Demo 3: Stderr Message Demo -[2023-06-08 05:33:55.950] [wasi_logging_stdout] [info] ----------------------------------- -[2023-06-08 05:33:55.950] [wasi_logging_stderr] [trace] stderr: Trace Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stderr] [debug] stderr: Debug Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stderr] [info] stderr: Info Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stderr] [warning] stderr: Warn Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stderr] [error] stderr: Error Level Message -[2023-06-08 05:33:55.950] [wasi_logging_stderr] [critical] stderr: Critical Level Message -``` \ No newline at end of file diff --git a/examples/plugin/wasi-logging/src/lib.rs b/examples/plugin/wasi-logging/src/lib.rs index 3359a7df90c3..82a5eb23a378 100644 --- a/examples/plugin/wasi-logging/src/lib.rs +++ b/examples/plugin/wasi-logging/src/lib.rs @@ -5,10 +5,10 @@ use wasi::logging::logging::{ log, }; -fn title_bar(context: &str, message: &str) { - log(Level::Info, "", "==================================="); - log(Level::Info, context, message); - log(Level::Info, "", "-----------------------------------"); +fn title_bar(message: &str) { + log(Level::Info, "stdout", "==================================="); + log(Level::Info, "stdout", message); + log(Level::Info, "stdout", "-----------------------------------"); } fn demo_template(context: &str) { @@ -21,10 +21,14 @@ fn demo_template(context: &str) { } pub fn wasi_logging_demo() { - title_bar("Demo 1", "Stdout Message Demo"); - demo_template("Context"); - title_bar("Demo 2", "Stdout Message Without Context"); - demo_template(""); - title_bar("Demo 3", "Stderr Message Demo"); + title_bar("Stdout Message Demo"); + demo_template("stdout"); + title_bar("Stderr Message Demo"); demo_template("stderr"); -} \ No newline at end of file + title_bar("File Message Demo: log/output.log"); + demo_template("log/output.log"); + title_bar("File Message Demo: log/output2.log"); + demo_template("log/output2.log"); + title_bar("File Message Demo: continue to log/output.log"); + demo_template("log/output.log"); +} diff --git a/examples/plugin/wasi-logging/wit/logging.wit b/examples/plugin/wasi-logging/wit/logging.wit index 1711576367c2..8c0bdf821ef2 100644 --- a/examples/plugin/wasi-logging/wit/logging.wit +++ b/examples/plugin/wasi-logging/wit/logging.wit @@ -31,5 +31,5 @@ interface logging { /// sent, a context, which is an uninterpreted string meant to help /// consumers group similar messages, and a string containing the message /// text. - log: func(level: level, context: string, message: string) + log: func(level: level, context: string, message: string); } diff --git a/examples/plugin/wasi-logging/wit/world.wit b/examples/plugin/wasi-logging/wit/world.wit index c873010734a2..ede6286430b6 100644 --- a/examples/plugin/wasi-logging/wit/world.wit +++ b/examples/plugin/wasi-logging/wit/world.wit @@ -1,5 +1,5 @@ -package wasi:logging +package wasi:logging; -world example-world { - import logging +world imports { + import logging; } From 83c1bdb8008bb15f08620b29321c88f4202af75b Mon Sep 17 00:00:00 2001 From: YiYing He Date: Mon, 20 May 2024 17:48:15 +0800 Subject: [PATCH 198/218] [Plugin] Refactor the wasi-logging plugin. 1. Rename the files. 2. Add the file sink. 3. Refine the architecture. Signed-off-by: YiYing He --- plugins/wasi_logging/base.h | 28 ++++++ plugins/wasi_logging/env.cpp | 9 +- plugins/wasi_logging/env.h | 36 +++++++ plugins/wasi_logging/func.cpp | 96 +++++++++++-------- .../wasi_logging/{wasi_logging => }/func.h | 11 ++- plugins/wasi_logging/module.cpp | 12 ++- .../wasi_logging/{wasi_logging => }/module.h | 10 +- plugins/wasi_logging/wasi_logging/base.h | 22 ----- plugins/wasi_logging/wasi_logging/enum.h | 13 --- plugins/wasi_logging/wasi_logging/env.h | 22 ----- test/plugins/wasi_logging/wasi_logging.cpp | 18 ++-- 11 files changed, 158 insertions(+), 119 deletions(-) create mode 100644 plugins/wasi_logging/base.h create mode 100644 plugins/wasi_logging/env.h rename plugins/wasi_logging/{wasi_logging => }/func.h (55%) rename plugins/wasi_logging/{wasi_logging => }/module.h (57%) delete mode 100644 plugins/wasi_logging/wasi_logging/base.h delete mode 100644 plugins/wasi_logging/wasi_logging/enum.h delete mode 100644 plugins/wasi_logging/wasi_logging/env.h diff --git a/plugins/wasi_logging/base.h b/plugins/wasi_logging/base.h new file mode 100644 index 000000000000..dc1c51ca9a73 --- /dev/null +++ b/plugins/wasi_logging/base.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + +#pragma once + +#include "env.h" + +#include "common/errcode.h" +#include "runtime/callingframe.h" +#include "runtime/hostfunc.h" + +namespace WasmEdge { +namespace Host { +namespace WASILogging { + +enum class LogLevel : uint32_t { Trace, Debug, Info, Warn, Error, Critical }; + +template class Func : public Runtime::HostFunction { +public: + Func(LogEnv &HostEnv) : Runtime::HostFunction(0), Env(HostEnv) {} + +protected: + LogEnv &Env; +}; + +} // namespace WASILogging +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_logging/env.cpp b/plugins/wasi_logging/env.cpp index 0e5160a19c2a..97f2b1419d69 100644 --- a/plugins/wasi_logging/env.cpp +++ b/plugins/wasi_logging/env.cpp @@ -1,5 +1,8 @@ -#include "wasi_logging/env.h" -#include "wasi_logging/module.h" +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + +#include "env.h" +#include "module.h" namespace WasmEdge { namespace Host { @@ -32,4 +35,4 @@ EXPORT_GET_DESCRIPTOR(Descriptor) } // namespace } // namespace Host -} // namespace WasmEdge \ No newline at end of file +} // namespace WasmEdge diff --git a/plugins/wasi_logging/env.h b/plugins/wasi_logging/env.h new file mode 100644 index 000000000000..838c785000d5 --- /dev/null +++ b/plugins/wasi_logging/env.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + +#pragma once + +#include "plugin/plugin.h" + +#include +#include + +namespace WasmEdge { +namespace Host { +namespace WASILogging { + +class LogEnv { +public: + LogEnv() noexcept { + // TODO: Use the config in WasmEdge to set the logging level. + StdoutLogger->set_level(spdlog::level::trace); + StderrLogger->set_level(spdlog::level::trace); + StdoutLogger->set_pattern(DefFormat); + StderrLogger->set_pattern(DefFormat); + } + + const std::shared_ptr StdoutLogger = + spdlog::stdout_color_mt("wasi_logging_stdout"); + const std::shared_ptr StderrLogger = + spdlog::stderr_color_mt("wasi_logging_stderr"); + const std::string DefFormat = "[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v"; + std::shared_ptr FileLogger; + std::string LogFileName; +}; + +} // namespace WASILogging +} // namespace Host +} // namespace WasmEdge diff --git a/plugins/wasi_logging/func.cpp b/plugins/wasi_logging/func.cpp index 5f0a2c0106b4..9d44d4c3598e 100644 --- a/plugins/wasi_logging/func.cpp +++ b/plugins/wasi_logging/func.cpp @@ -1,85 +1,99 @@ -#include "wasi_logging/func.h" -#include "wasi_logging/enum.h" +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + +#include "func.h" + #include namespace WasmEdge { namespace Host { +namespace WASILogging { using namespace std::literals; -Expect WasiLoggingLog::body(const Runtime::CallingFrame &Frame, - uint32_t Level, uint32_t CxtPtr, - uint32_t CxtLen, uint32_t MsgPtr, - uint32_t MsgLen) { +Expect Log::body(const Runtime::CallingFrame &Frame, uint32_t Level, + uint32_t CxtPtr, uint32_t CxtLen, uint32_t MsgPtr, + uint32_t MsgLen) { // Check memory instance from module. auto *MemInst = Frame.getMemoryByIndex(0); if (MemInst == nullptr) { return Unexpect(ErrCode::Value::HostFuncError); } - // Get Buffer Pointer + // Get Buffer Pointer. char *CxtBuf = MemInst->getPointer(CxtPtr); char *MsgBuf = MemInst->getPointer(MsgPtr); if (CxtBuf == nullptr || MsgBuf == nullptr) { return Unexpect(ErrCode::Value::HostFuncError); } - // Copy Context String and Message String - std::string CxtStr, MsgStr; - std::copy_n(CxtBuf, CxtLen, std::back_inserter(CxtStr)); - std::copy_n(MsgBuf, MsgLen, std::back_inserter(MsgStr)); + // Get Context and Message string_view + std::string_view CxtSV(CxtBuf, CxtLen); + std::string_view MsgSV(MsgBuf, MsgLen); // Setup Logger for Stdout or Stderr - CxtStr == "stderr"sv ? Env.isCxtStrStderr = true : Env.isCxtStrStderr = false; - auto logger = Env.isCxtStrStderr ? Env.StderrLogger : Env.StdoutLogger; - - // Construct Spdlog Message - std::string SpdlogMsg; - if (!CxtStr.empty()) { - SpdlogMsg = CxtStr + ": " + MsgStr; + std::shared_ptr Logger; + if (CxtSV == "stdout"sv || CxtSV == ""sv) { + Logger = Env.StdoutLogger; + } else if (CxtSV == "stderr"sv) { + Logger = Env.StderrLogger; } else { - SpdlogMsg = MsgStr; + if (CxtSV != Env.LogFileName) { + try { + spdlog::drop("wasi_logging_file"); + Env.FileLogger = + spdlog::basic_logger_mt("wasi_logging_file", std::string(CxtSV)); + Env.FileLogger->set_pattern(Env.DefFormat); + Env.LogFileName = CxtSV; + // TODO: Use the config in WasmEdge to set the logging level. + Env.FileLogger->set_level(spdlog::level::trace); + } catch (const spdlog::spdlog_ex &Ex) { + spdlog::error("[WasiLogging] Cannot log into file: {}"sv, Ex.what()); + return Unexpect(ErrCode::Value::HostFuncError); + } + } + Logger = Env.FileLogger; } // Print Message by Logging Level - switch (Level) { - case WASILOGGING::WasiLoggingLevel::Trace: - logger->trace(SpdlogMsg); + switch (static_cast(Level)) { + case LogLevel::Trace: + Logger->trace(MsgSV); break; - case WASILOGGING::WasiLoggingLevel::Debug: - logger->debug(SpdlogMsg); + case LogLevel::Debug: + Logger->debug(MsgSV); break; - case WASILOGGING::WasiLoggingLevel::Info: - logger->info(SpdlogMsg); + case LogLevel::Info: + Logger->info(MsgSV); break; - case WASILOGGING::WasiLoggingLevel::Warn: - logger->warn(SpdlogMsg); + case LogLevel::Warn: + Logger->warn(MsgSV); break; - case WASILOGGING::WasiLoggingLevel::Error: - logger->error(SpdlogMsg); + case LogLevel::Error: + Logger->error(MsgSV); break; - case WASILOGGING::WasiLoggingLevel::Critical: - logger->critical(SpdlogMsg); + case LogLevel::Critical: + Logger->critical(MsgSV); break; default: spdlog::error("[WasiLogging] Unrecognized Logging Level: {}"sv, Level); spdlog::error("[WasiLogging] Trace Level = {}"sv, - static_cast(WASILOGGING::WasiLoggingLevel::Trace)); + static_cast(LogLevel::Trace)); spdlog::error("[WasiLogging] Debug Level = {}"sv, - static_cast(WASILOGGING::WasiLoggingLevel::Debug)); + static_cast(LogLevel::Debug)); spdlog::error("[WasiLogging] Info Level = {}"sv, - static_cast(WASILOGGING::WasiLoggingLevel::Info)); + static_cast(LogLevel::Info)); spdlog::error("[WasiLogging] Warn Level = {}"sv, - static_cast(WASILOGGING::WasiLoggingLevel::Warn)); + static_cast(LogLevel::Warn)); spdlog::error("[WasiLogging] Error Level = {}"sv, - static_cast(WASILOGGING::WasiLoggingLevel::Error)); - spdlog::error( - "[WasiLogging] Critical Level = {}"sv, - static_cast(WASILOGGING::WasiLoggingLevel::Critical)); + static_cast(LogLevel::Error)); + spdlog::error("[WasiLogging] Critical Level = {}"sv, + static_cast(LogLevel::Critical)); return Unexpect(ErrCode::Value::HostFuncError); } return {}; } +} // namespace WASILogging } // namespace Host -} // namespace WasmEdge \ No newline at end of file +} // namespace WasmEdge diff --git a/plugins/wasi_logging/wasi_logging/func.h b/plugins/wasi_logging/func.h similarity index 55% rename from plugins/wasi_logging/wasi_logging/func.h rename to plugins/wasi_logging/func.h index f7631e985c8b..60e81c9dcb6c 100644 --- a/plugins/wasi_logging/wasi_logging/func.h +++ b/plugins/wasi_logging/func.h @@ -1,17 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + #pragma once -#include "wasi_logging/base.h" +#include "base.h" namespace WasmEdge { namespace Host { +namespace WASILogging { -class WasiLoggingLog : public WasiLogging { +class Log : public Func { public: - WasiLoggingLog(WasiLoggingEnvironment &HostEnv) : WasiLogging(HostEnv) {} + Log(LogEnv &HostEnv) : Func(HostEnv) {} Expect body(const Runtime::CallingFrame &Frame, uint32_t Level, uint32_t CxtPtr, uint32_t CxtLen, uint32_t MsgPtr, uint32_t MsgLen); }; +} // namespace WASILogging } // namespace Host } // namespace WasmEdge diff --git a/plugins/wasi_logging/module.cpp b/plugins/wasi_logging/module.cpp index 6ebd7879f46f..938ecc20c309 100644 --- a/plugins/wasi_logging/module.cpp +++ b/plugins/wasi_logging/module.cpp @@ -1,5 +1,9 @@ -#include "wasi_logging/module.h" -#include "wasi_logging/func.h" +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + +#include "module.h" +#include "func.h" + #include namespace WasmEdge { @@ -9,8 +13,8 @@ using namespace std::literals; WasiLoggingModule::WasiLoggingModule() : ModuleInstance("wasi:logging/logging"sv) { - addHostFunc("log"sv, std::make_unique(Env)); + addHostFunc("log"sv, std::make_unique(Env)); } } // namespace Host -} // namespace WasmEdge \ No newline at end of file +} // namespace WasmEdge diff --git a/plugins/wasi_logging/wasi_logging/module.h b/plugins/wasi_logging/module.h similarity index 57% rename from plugins/wasi_logging/wasi_logging/module.h rename to plugins/wasi_logging/module.h index 12504522beeb..9cf1260e21cb 100644 --- a/plugins/wasi_logging/wasi_logging/module.h +++ b/plugins/wasi_logging/module.h @@ -1,7 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + #pragma once +#include "env.h" + #include "runtime/instance/module.h" -#include "wasi_logging/env.h" namespace WasmEdge { namespace Host { @@ -10,10 +14,10 @@ class WasiLoggingModule : public Runtime::Instance::ModuleInstance { public: WasiLoggingModule(); - WasiLoggingEnvironment &getEnv() { return Env; } + WASILogging::LogEnv &getEnv() { return Env; } private: - WasiLoggingEnvironment Env; + WASILogging::LogEnv Env; }; } // namespace Host diff --git a/plugins/wasi_logging/wasi_logging/base.h b/plugins/wasi_logging/wasi_logging/base.h deleted file mode 100644 index 11b5504af764..000000000000 --- a/plugins/wasi_logging/wasi_logging/base.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "wasi_logging/env.h" - -#include "common/errcode.h" -#include "runtime/callingframe.h" -#include "runtime/hostfunc.h" - -namespace WasmEdge { -namespace Host { - -template class WasiLogging : public Runtime::HostFunction { -public: - WasiLogging(WasiLoggingEnvironment &HostEnv) - : Runtime::HostFunction(0), Env(HostEnv) {} - -protected: - WasiLoggingEnvironment &Env; -}; - -} // namespace Host -} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasi_logging/wasi_logging/enum.h b/plugins/wasi_logging/wasi_logging/enum.h deleted file mode 100644 index 5c4e2e2549a7..000000000000 --- a/plugins/wasi_logging/wasi_logging/enum.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -namespace WasmEdge { -namespace Host { -namespace WASILOGGING { - -enum WasiLoggingLevel : uint32_t { Trace, Debug, Info, Warn, Error, Critical }; - -} // namespace WASILOGGING -} // namespace Host -} // namespace WasmEdge \ No newline at end of file diff --git a/plugins/wasi_logging/wasi_logging/env.h b/plugins/wasi_logging/wasi_logging/env.h deleted file mode 100644 index 2c199f96a7c0..000000000000 --- a/plugins/wasi_logging/wasi_logging/env.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "plugin/plugin.h" -#include -namespace WasmEdge { -namespace Host { - -class WasiLoggingEnvironment { -public: - WasiLoggingEnvironment() noexcept { - StdoutLogger->set_level(spdlog::level::trace); - StderrLogger->set_level(spdlog::level::trace); - } - bool isCxtStrStderr = false; - inline const static std::shared_ptr StdoutLogger = - spdlog::stdout_color_mt("wasi_logging_stdout"); - inline const static std::shared_ptr StderrLogger = - spdlog::stderr_color_mt("wasi_logging_stderr"); -}; - -} // namespace Host -} // namespace WasmEdge diff --git a/test/plugins/wasi_logging/wasi_logging.cpp b/test/plugins/wasi_logging/wasi_logging.cpp index a3720f2cb64a..471b72975d01 100644 --- a/test/plugins/wasi_logging/wasi_logging.cpp +++ b/test/plugins/wasi_logging/wasi_logging.cpp @@ -1,12 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2019-2024 Second State INC + +#include "func.h" +#include "module.h" + #include "common/defines.h" #include "runtime/instance/module.h" -#include "wasi_logging/func.h" -#include "wasi_logging/module.h" #include -#include #include #include + +#include #include namespace { @@ -56,7 +61,7 @@ TEST(WasiLoggingTests, func_log) { // Clear the memory[0, 32]. fillMemContent(MemInst, 0, 32); // Set strings in memory - fillMemContent(MemInst, 0, std::string("CxtStr")); + fillMemContent(MemInst, 0, std::string("stdout")); fillMemContent(MemInst, 8, std::string("stderr")); fillMemContent(MemInst, 16, std::string("MsgStr")); @@ -65,7 +70,7 @@ TEST(WasiLoggingTests, func_log) { EXPECT_NE(FuncInst, nullptr); EXPECT_TRUE(FuncInst->isHostFunction()); auto &HostFuncInst = - dynamic_cast(FuncInst->getHostFunc()); + dynamic_cast(FuncInst->getHostFunc()); // Show All Level EXPECT_TRUE(HostFuncInst.run( @@ -99,7 +104,6 @@ TEST(WasiLoggingTests, func_log) { std::initializer_list{ UINT32_C(5), UINT32_C(0), UINT32_C(6), UINT32_C(16), UINT32_C(6)}, {})); - EXPECT_FALSE(WasiLoggingMod->getEnv().isCxtStrStderr); // Stderr Context EXPECT_TRUE(HostFuncInst.run( @@ -107,7 +111,6 @@ TEST(WasiLoggingTests, func_log) { std::initializer_list{ UINT32_C(0), UINT32_C(8), UINT32_C(6), UINT32_C(16), UINT32_C(6)}, {})); - EXPECT_TRUE(WasiLoggingMod->getEnv().isCxtStrStderr); // UnKnown Level EXPECT_FALSE(HostFuncInst.run( @@ -115,7 +118,6 @@ TEST(WasiLoggingTests, func_log) { std::initializer_list{ UINT32_C(6), UINT32_C(0), UINT32_C(6), UINT32_C(16), UINT32_C(6)}, {})); - EXPECT_FALSE(WasiLoggingMod->getEnv().isCxtStrStderr); delete WasiLoggingMod; } From 3900f4a63b469a3f3b9ec075a1eead11494614ad Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 22 May 2024 15:09:11 +0800 Subject: [PATCH 199/218] [WASI-NN] ggml: bump llama.cpp b2961 (#3418) Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index 285a727f38b5..e66acd561bf5 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -96,7 +96,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2943 + GIT_TAG b2961 GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) From 40df1acfac24173a53f0f7256b7430a269fca986 Mon Sep 17 00:00:00 2001 From: dm4 Date: Wed, 22 May 2024 17:57:39 +0800 Subject: [PATCH 200/218] [WASI-NN] ggml: bump llama.cpp b2963 (#3419) Signed-off-by: dm4 --- plugins/wasi_nn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wasi_nn/CMakeLists.txt b/plugins/wasi_nn/CMakeLists.txt index e66acd561bf5..45236ef33676 100644 --- a/plugins/wasi_nn/CMakeLists.txt +++ b/plugins/wasi_nn/CMakeLists.txt @@ -96,7 +96,7 @@ if(BACKEND STREQUAL "ggml") FetchContent_Declare( llama GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git - GIT_TAG b2961 + GIT_TAG b2963 GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(llama) From 207004a93625564c9da6250ecb4c5afd11c0bc93 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Mon, 20 May 2024 19:49:17 +0800 Subject: [PATCH 201/218] [CI] Add OPENSSL_ROOT_DIR Signed-off-by: Yi Huang --- .github/workflows/reusable-build-extensions-on-manylinux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-build-extensions-on-manylinux.yml b/.github/workflows/reusable-build-extensions-on-manylinux.yml index 1f4fe48d5ae3..d050d7da022a 100644 --- a/.github/workflows/reusable-build-extensions-on-manylinux.yml +++ b/.github/workflows/reusable-build-extensions-on-manylinux.yml @@ -76,7 +76,7 @@ jobs: fi mkdir -p build - cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_PLUGIN_WASI_LOGGING=ON + cmake -Bbuild -GNinja -DWASMEDGE_BUILD_TESTS=${build_tests} -DCMAKE_BUILD_TYPE=${build_type} -DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_PLUGIN_WASI_LOGGING=ON -DOPENSSL_ROOT_DIR=${OpenSSL_DIR} cmake --build build --target wasmedgePluginWasiLogging - uses: actions/cache/save@v3 with: From b0a0775dd1b55fb6d4a1cbc4ac80b33363eb0550 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Mon, 20 May 2024 14:35:39 +0800 Subject: [PATCH 202/218] [CI] Build extensions on manylinux_2_28 aarch64 Signed-off-by: Yi Huang --- .github/actions/expand-variables/dist/index.js | 5 +++++ .github/actions/expand-variables/main.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/.github/actions/expand-variables/dist/index.js b/.github/actions/expand-variables/dist/index.js index 8bfced48c123..5838734091d6 100644 --- a/.github/actions/expand-variables/dist/index.js +++ b/.github/actions/expand-variables/dist/index.js @@ -26602,6 +26602,11 @@ const archList = [{ runner: 'linux-arm64-v2', docker_tag: 'manylinux2014_aarch64-plugins-deps', asset_tag: 'manylinux2014_aarch64', +}, { + arch: aarch64, + runner: 'linux-arm64-v2', + docker_tag: 'manylinux_2_28_aarch64-plugins-deps', + asset_tag: 'manylinux_2_28_aarch64', }]; const pluginList = [{ diff --git a/.github/actions/expand-variables/main.js b/.github/actions/expand-variables/main.js index 94ac9260b94a..216fb2e65581 100644 --- a/.github/actions/expand-variables/main.js +++ b/.github/actions/expand-variables/main.js @@ -11,6 +11,11 @@ const archList = [{ runner: 'linux-arm64-v2', docker_tag: 'manylinux2014_aarch64-plugins-deps', asset_tag: 'manylinux2014_aarch64', +}, { + arch: aarch64, + runner: 'linux-arm64-v2', + docker_tag: 'manylinux_2_28_aarch64-plugins-deps', + asset_tag: 'manylinux_2_28_aarch64', }]; const pluginList = [{ From b82dc59f680c1bf1700adf27f322491dfddf26c3 Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Wed, 22 May 2024 02:08:41 +0800 Subject: [PATCH 203/218] [WASI-Crypto] Fix compile error on gcc 13 Signed-off-by: Yi Huang --- plugins/wasi_crypto/utils/handles_manager.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/wasi_crypto/utils/handles_manager.h b/plugins/wasi_crypto/utils/handles_manager.h index ba01f157989a..2282a283a2eb 100644 --- a/plugins/wasi_crypto/utils/handles_manager.h +++ b/plugins/wasi_crypto/utils/handles_manager.h @@ -48,7 +48,8 @@ template class BaseHandlesManager { BaseHandlesManager &operator=(BaseHandlesManager &&) noexcept = delete; /// @param TypeID A unique number - BaseHandlesManager(uint8_t TypeID) noexcept : LastHandle{TypeID, 0} {} + explicit BaseHandlesManager(uint8_t TypeID) noexcept + : LastHandle{TypeID, 0} {} WasiCryptoExpect close(HandleType Handle) noexcept { std::unique_lock Lock{Mutex}; @@ -140,6 +141,8 @@ class RcHandlesManager ManagerType>::HandleWrapper; public: + using detail::BaseHandlesManager::BaseHandlesManager; + /// Get the return copy. WasiCryptoExpect get(HandleType Handle) noexcept { std::shared_lock Lock{this->Mutex}; @@ -184,6 +187,8 @@ class RefHandlesManager ManagerType>::HandleWrapper; public: + using detail::BaseHandlesManager::BaseHandlesManager; + /// Get the return reference. WasiCryptoExpect> get(HandleType Handle) noexcept { From dd897455d5d00f59f1818fe3a0fa1ae8c59e621b Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Wed, 22 May 2024 18:07:55 +0800 Subject: [PATCH 204/218] [Misc] Remove dup files Signed-off-by: Yi Huang --- .github/workflows/docker.yml | 4 ++-- utils/docker/Dockerfile.build-plugins-deps | 2 +- .../Dockerfile.manylinux2014-build-plugins-deps | 2 +- .../Dockerfile.manylinux_2_28-build-plugins-deps | 2 +- utils/docker/build.sh | 2 +- utils/docker/install-opencvmini.sh | 16 ---------------- utils/opencvmini/install-opencvmini.sh | 5 +++-- 7 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 utils/docker/install-opencvmini.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c88c8eb1835e..4ec32cb71f2e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -152,7 +152,7 @@ jobs: uses: docker/build-push-action@v5 with: build-args: BASE=wasmedge/wasmedge:ubuntu-build-clang - context: ./utils/docker + context: ./utils file: ./utils/docker/Dockerfile.build-plugins-deps platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} @@ -170,7 +170,7 @@ jobs: uses: docker/build-push-action@v5 with: build-args: BASE=wasmedge/wasmedge:ubuntu-build-gcc - context: ./utils/docker + context: ./utils file: ./utils/docker/Dockerfile.build-plugins-deps platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} diff --git a/utils/docker/Dockerfile.build-plugins-deps b/utils/docker/Dockerfile.build-plugins-deps index 21c73d977aaa..ae797d66466b 100644 --- a/utils/docker/Dockerfile.build-plugins-deps +++ b/utils/docker/Dockerfile.build-plugins-deps @@ -7,6 +7,6 @@ RUN apt update && apt install -y \ RUN rm -rf /var/lib/apt/lists/* -COPY install-opencvmini.sh . +COPY opencvmini/install-opencvmini.sh . ENV OPENCV_VERSION=4.8.0 RUN [ "/bin/bash", "install-opencvmini.sh" ] diff --git a/utils/docker/Dockerfile.manylinux2014-build-plugins-deps b/utils/docker/Dockerfile.manylinux2014-build-plugins-deps index 4762b087db86..359f44512ec4 100644 --- a/utils/docker/Dockerfile.manylinux2014-build-plugins-deps +++ b/utils/docker/Dockerfile.manylinux2014-build-plugins-deps @@ -13,7 +13,7 @@ RUN yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.rep WORKDIR /root -COPY docker/install-opencvmini.sh . +COPY opencvmini/install-opencvmini.sh . ENV OPENCV_VERSION "4.8.0" RUN [ "/bin/bash", "install-opencvmini.sh" ] diff --git a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps index c8ed5dbf74b4..4be4bf9743c3 100644 --- a/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps +++ b/utils/docker/Dockerfile.manylinux_2_28-build-plugins-deps @@ -14,7 +14,7 @@ RUN yum install -y yum-utils && \ WORKDIR /root -COPY docker/install-opencvmini.sh . +COPY opencvmini/install-opencvmini.sh . ENV OPENCV_VERSION "4.8.0" RUN [ "/bin/bash", "install-opencvmini.sh" ] diff --git a/utils/docker/build.sh b/utils/docker/build.sh index 3d99a86ffc3d..bdcea629c9a2 100755 --- a/utils/docker/build.sh +++ b/utils/docker/build.sh @@ -15,7 +15,7 @@ function docker_build local NAME_TAG=${NAME}:${TAG} echo "Building docker image \"${NAME_TAG}\" from file \"${FILENAME}\"." - ( set -x; docker build "$@" -f "${FILENAME}" -t "${NAME_TAG}" . ) + ( set -x; docker build "$@" -f "docker/${FILENAME}" -t "${NAME_TAG}" . ) if [[ "${TAG}" == im-* ]]; then INTERMEDIATES+=( "${NAME_TAG}" ) diff --git a/utils/docker/install-opencvmini.sh b/utils/docker/install-opencvmini.sh deleted file mode 100644 index f66ef586b6b0..000000000000 --- a/utils/docker/install-opencvmini.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# SPDX-FileCopyrightText: 2019-2023 Second State INC - -wget -O opencv.zip https://github.com/opencv/opencv/archive/refs/tags/${OPENCV_VERSION}.zip - -unzip opencv.zip -mv opencv-${OPENCV_VERSION} opencv - -mkdir -p opencv/build && cd opencv/build -# Configure -cmake -GNinja .. -# Build -cmake --build . -# Install to system -cmake --install . diff --git a/utils/opencvmini/install-opencvmini.sh b/utils/opencvmini/install-opencvmini.sh index ac5128efd0cc..bd95a9029665 100644 --- a/utils/opencvmini/install-opencvmini.sh +++ b/utils/opencvmini/install-opencvmini.sh @@ -1,11 +1,12 @@ #!/usr/bin/env bash # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # SPDX-FileCopyrightText: 2019-2023 Second State INC +OPENCV_VERSION=${OPENCV_VERSION:-4.8.0} -wget -O opencv.zip https://github.com/opencv/opencv/archive/refs/tags/4.8.0.zip +wget -O opencv.zip https://github.com/opencv/opencv/archive/refs/tags/${OPENCV_VERSION}.zip unzip opencv.zip -mv opencv-4.8.0 opencv +mv opencv-${OPENCV_VERSION} opencv mkdir -p opencv/build && cd opencv/build # Configure From 6a8e555091e3dcb27c8ca7abe74f9ca5c96cf226 Mon Sep 17 00:00:00 2001 From: Yi-Ying He Date: Thu, 23 May 2024 01:40:42 +0800 Subject: [PATCH 205/218] [Changelog] Update the changelog for the 0.14.0 release. (#3404) Signed-off-by: YiYing He --- .CurrentChangelog.md | 11 +++++++---- Changelog.md | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.CurrentChangelog.md b/.CurrentChangelog.md index 98045764a399..b571a2af6ced 100644 --- a/.CurrentChangelog.md +++ b/.CurrentChangelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.5 (2024-05-08) +### 0.14.0 (2024-05-22) Breaking changes: @@ -87,7 +87,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2781. + * Bump llama.cpp to b2963. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -115,6 +115,7 @@ Features: * Support embedding generation. * Support Windows build. * [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. +* [Plugin] Updated `wasi-logging` plug-in for supporting logging into file. Fixed issues: @@ -132,12 +133,14 @@ Fixed issues: * Fixed `path_readlink` for not following symbolic link issue. * Fixed `path_open` for checking `O_TRUNC` rights. * Fixed `path_open` for removing path relative rights on file. + * Fixed `fd_allocate` return error value. * Checking `path_symlink` for creating a symlink to an absolute path. * Checking `fd_prestat_dir_name` buffer size. * Checking `filestat_set_times` for invalid flags. * Checking validation of file descriptor in `socket_accept` (#3041). * Fixed duplicated loading of the same plug-in. * Fixed option toggle for `wasmedge_process` plug-in. +* Fixed the plug-in searching path on Windows. Tests: @@ -154,6 +157,6 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Harry Chiang, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LFsWang, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hugo-syn, hydai, redismongo, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Harry Chiang, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LFsWang, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Sylveon, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hugo-syn, hydai, redismongo, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.5-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-src.tar.gz instead of the zip or tarball provided by GitHub directly. diff --git a/Changelog.md b/Changelog.md index bd75a653efba..8f1c3869a62f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.14.0-rc.5 (2024-05-08) +### 0.14.0 (2024-05-22) Breaking changes: @@ -87,7 +87,7 @@ Features: * [Tools]: Print the plug-in versions when using the `--version` option. * [Installer]: Enabled `ggml-blas` and `rustls` plugin supporting (#3032) (#3108). * [WASI-NN] ggml backend: - * Bump llama.cpp to b2781. + * Bump llama.cpp to b2963. * Support llama.cpp options: * `threads`: the thread number for inference. * `temp`: set temperature for inference. @@ -115,6 +115,7 @@ Features: * Support embedding generation. * Support Windows build. * [Plugin] Initial support for `wasmedge_ffmpeg` plug-in. +* [Plugin] Updated `wasi-logging` plug-in for supporting logging into file. Fixed issues: @@ -132,12 +133,14 @@ Fixed issues: * Fixed `path_readlink` for not following symbolic link issue. * Fixed `path_open` for checking `O_TRUNC` rights. * Fixed `path_open` for removing path relative rights on file. + * Fixed `fd_allocate` return error value. * Checking `path_symlink` for creating a symlink to an absolute path. * Checking `fd_prestat_dir_name` buffer size. * Checking `filestat_set_times` for invalid flags. * Checking validation of file descriptor in `socket_accept` (#3041). * Fixed duplicated loading of the same plug-in. * Fixed option toggle for `wasmedge_process` plug-in. +* Fixed the plug-in searching path on Windows. Tests: @@ -154,9 +157,9 @@ Known issues: Thank all the contributors who made this release possible! -Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Harry Chiang, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LFsWang, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hugo-syn, hydai, redismongo, richzw, tannal, vincent, zhumeme +Abhinandan Udupa, Akihiro Suda, Charlie chan, Dhruv Jain, Draco, Harry Chiang, Hrushikesh, Ikko Eltociear Ashimine, Khagan (Khan) Karimov, LFsWang, LO, CHIN-HAO, Little Willy, Lîm Tsú-thuàn, Meenu Yadav, Omkar Acharekar, Saiyam Pathak, Sarrah Bastawala, Shen-Ta Hsieh, Shreyas Atre, Sylveon, Yage Hu, Yi Huang, Yi-Ying He, alabulei1, am009, dm4, hetvishastri, hugo-syn, hydai, redismongo, richzw, tannal, vincent, zhumeme -If you want to build from source, please use WasmEdge-0.14.0-rc.5-src.tar.gz instead of the zip or tarball provided by GitHub directly. +If you want to build from source, please use WasmEdge-0.14.0-src.tar.gz instead of the zip or tarball provided by GitHub directly. ### 0.13.5 (2023-11-03) From 72c304463dca1f4bf78ad9a8d932430449142057 Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 23 May 2024 03:07:46 +0800 Subject: [PATCH 206/218] [Installer] v2: allow users to specify the ggml version (#3422) Signed-off-by: hydai --- .github/workflows/test-installer-v2.yml | 11 ++++++ utils/install_v2.sh | 51 ++++++++++++++++++++----- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-installer-v2.yml b/.github/workflows/test-installer-v2.yml index 45cc1d660469..a28b23831ec8 100644 --- a/.github/workflows/test-installer-v2.yml +++ b/.github/workflows/test-installer-v2.yml @@ -63,6 +63,11 @@ jobs: # It will install WasmEdge and the noavx GGML plugin bash utils/install_v2.sh -V --noavx ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Run installer-v2 with ggml build number b2963 + run: | + # It will install WasmEdge and the b2963 GGML plugin + bash utils/install_v2.sh -V --ggmlbn=b2963 + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.so && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) - name: Uninstall WasmEdge run: | bash utils/uninstall.sh -q -V @@ -99,6 +104,12 @@ jobs: # It should uninstall the previous installation and install WasmEdge and the GGML plugin again bash utils/install_v2.sh -V ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.dylib && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) + - name: Run installer-v2 with ggml build number b2963 + if: ${{ matrix.host_runner == 'macos-14' }} + run: | + # It will install WasmEdge and the b2963 GGML plugin + bash utils/install_v2.sh -V --ggmlbn=b2963 + ls ~/.wasmedge/plugin/ | grep libwasmedgePluginWasiNN.dylib && echo "Pass: WASI_NN-ggml Plugin found" || (echo "Fail: WASI_NN-ggml not found" && exit 1) - name: Uninstall WasmEdge run: | bash utils/uninstall.sh -q -V diff --git a/utils/install_v2.sh b/utils/install_v2.sh index ef93996bd37a..83e4b0c86b06 100755 --- a/utils/install_v2.sh +++ b/utils/install_v2.sh @@ -28,20 +28,35 @@ eprintf() { command printf '%s\n' "$1" 1>&2 } -detect_cuda() { +detect_cuda_nvcc() { local cuda="" cuda=$(/usr/local/cuda/bin/nvcc --version 2>/dev/null | grep "Cuda compilation tools" | cut -f5 -d ' ' | cut -f1 -d ',') if [[ "${cuda}" =~ "12" ]]; then cuda="12" elif [[ "${cuda}" =~ "11" ]]; then cuda="11" - else - cuda=$(nvidia-smi -q 2>/dev/null | grep CUDA | cut -f2 -d ':' | cut -f2 -d ' ') - if [[ "${cuda}" =~ "12" ]]; then - cuda="12" - elif [[ "${cuda}" =~ "11" ]]; then - cuda="11" - fi + fi + + echo ${cuda} +} + +detect_cuda_nvidia_smi() { + local cuda="" + cuda=$(nvidia-smi -q 2>/dev/null | grep CUDA | cut -f2 -d ':' | cut -f2 -d ' ') + if [[ "${cuda}" =~ "12" ]]; then + cuda="12" + elif [[ "${cuda}" =~ "11" ]]; then + cuda="11" + fi + + echo ${cuda} +} + +detect_cuda() { + local cuda="" + cuda=$(detect_cuda_nvcc) + if [[ "${cuda}" == "" ]]; then + cuda=$(detect_cuda_nvidia_smi) fi echo ${cuda} @@ -189,6 +204,7 @@ VERBOSE=0 LEGACY=0 ENABLE_RUSTLS=0 ENABLE_NOAVX=0 +GGML_BUILD_NUMBER="" set_ENV() { ENV="#!/bin/sh @@ -279,6 +295,9 @@ usage() { --rustls Install the Rustls plugin. Default is disabled. + --ggmlbn=[b2963] Install the specific GGML plugin. + Default is the latest. + --os=[Linux/Darwin] Set the OS. Default is detected OS. @@ -378,6 +397,9 @@ get_wasmedge_ggml_plugin() { else cuda=$(detect_cuda) info "Detected CUDA version: ${cuda}" + info "CUDA version from nvcc: $(detect_cuda_nvcc)" + info "CUDA version from nvidia-smi: $(detect_cuda_nvidia_smi)" + if [ "${cuda}" == "12" ]; then CUDA_EXT="-cuda" elif [ "${cuda}" == "11" ]; then @@ -390,7 +412,15 @@ get_wasmedge_ggml_plugin() { CUDA_EXT="" fi fi - _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}${NOAVX_EXT}-$VERSION-$RELEASE_PKG" + + if [ "$GGML_BUILD_NUMBER" == "" ]; then + info "Use default GGML plugin" + _downloader "https://github.com/WasmEdge/WasmEdge/releases/download/$VERSION/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}${NOAVX_EXT}-$VERSION-$RELEASE_PKG" + else + info "Use ${GGML_BUILD_NUMBER} GGML plugin" + _downloader "https://github.com/second-state/WASI-NN-GGML-PLUGIN-REGISTRY/raw/main/${VERSION}/${GGML_BUILD_NUMBER}/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}${NOAVX_EXT}-$VERSION-$RELEASE_PKG" + fi + local TMP_PLUGIN_DIR="${TMP_DIR}/${IPKG}/plugin" mkdir -p "${TMP_PLUGIN_DIR}" _extractor -C "${TMP_PLUGIN_DIR}" -vxzf "${TMP_DIR}/WasmEdge-plugin-wasi_nn-ggml${CUDA_EXT}${NOAVX_EXT}-${VERSION}-${RELEASE_PKG}" @@ -459,6 +489,9 @@ main() { p | path) IPATH="$(_realpath "${OPTARG}")" ;; + ggmlbn) + GGML_BUILD_NUMBER="${OPTARG}" + ;; noavx) ENABLE_NOAVX=1 ;; From 3e74fd9322fe69201dd35ae2b04999676c520997 Mon Sep 17 00:00:00 2001 From: Yi Date: Thu, 23 May 2024 03:58:45 +0800 Subject: [PATCH 207/218] [CI] Fix `sudo` not found on manylinux (#3423) Signed-off-by: Yi Huang --- .github/workflows/release.yml | 2 +- .github/workflows/reusable-build-on-manylinux.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b8a4d610132..c47392e42917 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -484,7 +484,7 @@ jobs: path: build/WasmEdge-${{ needs.create_release.outputs.version }}-Linux.tar.gz - name: Install gh on manylinux run: | - type -p yum-config-manager >/dev/null || sudo yum install yum-utils + type -p yum-config-manager >/dev/null || yum install yum-utils yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo yum install -y gh - name: Upload ${{ matrix.name }} tar.gz package diff --git a/.github/workflows/reusable-build-on-manylinux.yml b/.github/workflows/reusable-build-on-manylinux.yml index 852e71cafe31..cc9db78896cb 100644 --- a/.github/workflows/reusable-build-on-manylinux.yml +++ b/.github/workflows/reusable-build-on-manylinux.yml @@ -45,7 +45,7 @@ jobs: - name: Install gh on manylinux if: ${{ inputs.release }} run: | - type -p yum-config-manager >/dev/null || sudo yum install yum-utils + type -p yum-config-manager >/dev/null || yum install yum-utils yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo yum install -y gh - name: Upload rpm package From 7022836fe65b145bffaa046306408e908cfc61df Mon Sep 17 00:00:00 2001 From: Yi Huang Date: Thu, 23 May 2024 11:47:15 +0800 Subject: [PATCH 208/218] [CI] Fix `yum install` with `-y` Signed-off-by: Yi Huang --- .github/workflows/release.yml | 2 +- .github/workflows/reusable-build-on-manylinux.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c47392e42917..1832749958b9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -484,7 +484,7 @@ jobs: path: build/WasmEdge-${{ needs.create_release.outputs.version }}-Linux.tar.gz - name: Install gh on manylinux run: | - type -p yum-config-manager >/dev/null || yum install yum-utils + type -p yum-config-manager >/dev/null || yum install -y yum-utils yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo yum install -y gh - name: Upload ${{ matrix.name }} tar.gz package diff --git a/.github/workflows/reusable-build-on-manylinux.yml b/.github/workflows/reusable-build-on-manylinux.yml index cc9db78896cb..58c3d925b5a0 100644 --- a/.github/workflows/reusable-build-on-manylinux.yml +++ b/.github/workflows/reusable-build-on-manylinux.yml @@ -45,7 +45,7 @@ jobs: - name: Install gh on manylinux if: ${{ inputs.release }} run: | - type -p yum-config-manager >/dev/null || yum install yum-utils + type -p yum-config-manager >/dev/null || yum install -y yum-utils yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo yum install -y gh - name: Upload rpm package From 83a15645edf77670759919a506a8844cdc9d9ed5 Mon Sep 17 00:00:00 2001 From: turuslan Date: Fri, 17 May 2024 15:32:20 +0500 Subject: [PATCH 209/218] qdrvm Signed-off-by: turuslan --- CMakeLists.txt | 8 ++++++-- lib/llvm/codegen.cpp | 9 ++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b6a5742cf31..b7dccc73b303 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,8 @@ endif() include(cmake/HunterGate.cmake) HunterGate( - URL https://github.com/qdrvm/hunter/archive/b6c44ccfd5d9d0e87628737303084b4cfa9e200e.zip - SHA1 cecd3a154449c1b39fcf5dfaf1bed2c6bce0f67a + URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm11.zip + SHA1 20620ee1e2e9738b2d4561be2622d71e8c73bee9 LOCAL ) @@ -155,7 +155,11 @@ if(WASMEDGE_BUILD_COVERAGE) append_coverage_compiler_flags() endif() +<<<<<<< HEAD if(WASMEDGE_BUILD_AOT_RUNTIME) +======= +if(WASMEDGE_USE_LLVM) +>>>>>>> b38d24e9 (qdrvm) hunter_add_package(ZLIB) hunter_add_package(LLVM) hunter_add_package(LLD) diff --git a/lib/llvm/codegen.cpp b/lib/llvm/codegen.cpp index 35a414df72b6..bbb1ff1e9abd 100644 --- a/lib/llvm/codegen.cpp +++ b/lib/llvm/codegen.cpp @@ -482,7 +482,13 @@ Expect outputWasmLibrary(LLVM::Context LLContext, spdlog::info("output start"); - std::ofstream OS(OutputPath, std::ios_base::binary); + std::filesystem::path OutputPathTmp(OutputPath); + OutputPathTmp.replace_extension("%%%%%%%%%%.wasm"); + OutputPathTmp = createTemp(OutputPathTmp); + if (OutputPathTmp.empty()) { + return WasmEdge::Unexpect(WasmEdge::ErrCode::Value::IllegalPath); + } + std::ofstream OS(OutputPathTmp, std::ios_base::binary); if (!OS) { spdlog::error("output failed."); return Unexpect(ErrCode::Value::IllegalPath); @@ -495,6 +501,7 @@ Expect outputWasmLibrary(LLVM::Context LLContext, std::error_code Error; std::filesystem::remove(SharedObjectName, Error); + std::filesystem::rename(OutputPathTmp, OutputPath); spdlog::info("output done"); return {}; From 3edd74bceb544a901b6120de9bb4ff08ddc93e34 Mon Sep 17 00:00:00 2001 From: Harrm Date: Wed, 22 May 2024 11:39:02 +0300 Subject: [PATCH 210/218] Expose JIT Add compiler-rt to LLVM fix cmake config file fix cmake config file fix cmake config file fix cmake config file Fixing cmake config Fixing cmake config Fixing cmake config Fixing cmake config Benchmarking jit Benchmarking jit benchmarking jit benchmarking jit Hunterize spdlog Try newer fmt Try newer spdlog Revert to hunterized spdlog Fix config Try to fix config Try to fix config Try to fix config --- CMakeLists.txt | 9 +++++++-- cmake/Hunter/config.cmake | 18 ++++++++++++++++++ cmake/wasmedge-config.cmake | 30 ++++++++++++++++++++---------- include/api/wasmedge/wasmedge.h | 12 +++++++++--- include/common/enum.inc | 4 +++- lib/api/CMakeLists.txt | 12 +++++++----- lib/api/libwasmedge.lds | 2 +- lib/api/wasmedge.cpp | 25 +++++++++++++++++++++++++ lib/common/CMakeLists.txt | 33 +++------------------------------ lib/llvm/jit.cpp | 4 ++++ lib/loader/ast/module.cpp | 2 ++ 11 files changed, 99 insertions(+), 52 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7dccc73b303..fd923796553d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,10 +7,15 @@ if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) endif() +set(HUNTER_CACHE_SERVERS + "https://github.com/qdrvm/hunter-binary-cache" + CACHE STRING "Binary cache server" +) + include(cmake/HunterGate.cmake) HunterGate( - URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm11.zip - SHA1 20620ee1e2e9738b2d4561be2622d71e8c73bee9 + URL https://github.com/qdrvm/hunter/archive/refs/heads/update/boost-1.85.zip + SHA1 40c34d168dfa7d2a44d146928befa2d9d5680a71 LOCAL ) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake index 684d9615017b..e7f6175c1d22 100644 --- a/cmake/Hunter/config.cmake +++ b/cmake/Hunter/config.cmake @@ -19,3 +19,21 @@ hunter_config( LLVM_ENABLE_PROJECTS=lld;clang LLVM_TARGETS_TO_BUILD=${ARCHITECTURE};BPF ) + +hunter_config( + fmt + URL + https://github.com/fmtlib/fmt/archive/refs/tags/10.2.1.tar.gz + SHA1 + d223964b782d2562d6722ffe67027204c6035453 + CMAKE_ARGS + CMAKE_POSITION_INDEPENDENT_CODE=TRUE +) + +hunter_config( + spdlog + VERSION 1.12.0-p0 + CMAKE_ARGS + SPDLOG_BUILD_PIC=ON + SPDLOG_FMT_EXTERNAL=ON +) diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index b410c53b00bb..4b43fda1ba1d 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -1,16 +1,26 @@ -add_library(WasmEdge::WasmEdge STATIC IMPORTED) +set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.so") +set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.a") +set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.a") + +if (EXISTS "${WASMEDGE_SHARED_LIB}") + add_library(WasmEdge::WasmEdge SHARED IMPORTED) + set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_SHARED_LIB}") + +elseif(EXISTS "${WASMEDGE_STATIC_LIB_DEBUG}" AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + add_library(WasmEdge::WasmEdge STATIC IMPORTED) + set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_STATIC_LIB_DEBUG}") + +elseif(EXISTS "${WASMEDGE_STATIC_LIB}") + add_library(WasmEdge::WasmEdge STATIC IMPORTED) + set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_STATIC_LIB}") + +else() + message(FATAL_ERROR "WasmEdge not found in ${WASMEDGE_ROOT}") +endif() + target_include_directories(WasmEdge::WasmEdge INTERFACE "${WASMEDGE_ROOT}/include") target_link_libraries(WasmEdge::WasmEdge INTERFACE curses) if(APPLE) target_link_libraries(WasmEdge::WasmEdge INTERFACE xar) endif() -set(WASMEDGE_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.a") -set(WASMEDGE_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.a") -if(NOT EXISTS "${WASMEDGE_LIB}") - set(WASMEDGE_LIB "${WASMEDGE_LIB_DEBUG}") -endif() -set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_LIB}") -if(EXISTS "${WASMEDGE_LIB_DEBUG}") - set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION_DEBUG "${WASMEDGE_LIB_DEBUG}") -endif() diff --git a/include/api/wasmedge/wasmedge.h b/include/api/wasmedge/wasmedge.h index a87e3992211c..d6f9ea8d373c 100644 --- a/include/api/wasmedge/wasmedge.h +++ b/include/api/wasmedge/wasmedge.h @@ -1790,6 +1790,11 @@ WasmEdge_LoaderSerializeASTModule(WasmEdge_LoaderContext *Cxt, const WasmEdge_ASTModuleContext *ASTCxt, WasmEdge_Bytes *Buf); +WASMEDGE_CAPI_EXPORT extern WasmEdge_Result +WasmEdge_LoaderPrepareForJIT(WasmEdge_LoaderContext *Ctx, + WasmEdge_ASTModuleContext *ASTCxt, + const WasmEdge_ConfigureContext *ConfCxt); + /// Deletion of the WasmEdge_LoaderContext. /// /// After calling this function, the context will be destroyed and should @@ -4196,9 +4201,10 @@ typedef struct WasmEdge_DataSegment { /// \param Len the buffer length. /// /// \returns actual data segment list size. -WASMEDGE_CAPI_EXPORT extern uint32_t WasmEdge_ASTModuleListDataSegments( - const WasmEdge_ASTModuleContext *Cxt, WasmEdge_DataSegment *Segments, - const uint32_t Len); +WASMEDGE_CAPI_EXPORT extern uint32_t +WasmEdge_ASTModuleListDataSegments(const WasmEdge_ASTModuleContext *Cxt, + WasmEdge_DataSegment *Segments, + const uint32_t Len); // <<<<<<<< [qdrvm] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/include/common/enum.inc b/include/common/enum.inc index 66f21489d47f..2151b39b3361 100644 --- a/include/common/enum.inc +++ b/include/common/enum.inc @@ -793,8 +793,10 @@ E(NonNullRequired, 0x0009, "set null value into non-nullable value type") E(SetValueToConst, 0x000A, "set value into const") // Set value failed due to mismatch value type E(SetValueErrorType, 0x000B, "set value type mismatch") +// JIT is disabled +E(JITDisabled, 0x000C, "JIT is disabled in this build") // User defined error -E(UserDefError, 0x000C, "user defined error code") +E(UserDefError, 0x000D, "user defined error code") // Load phase // @{ diff --git a/lib/api/CMakeLists.txt b/lib/api/CMakeLists.txt index e79917183aa3..44052571d2c2 100644 --- a/lib/api/CMakeLists.txt +++ b/lib/api/CMakeLists.txt @@ -201,10 +201,12 @@ if(WASMEDGE_BUILD_STATIC_LIB) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${WASMEDGE_LIBRARY_NAME}" DESTINATION ${CMAKE_INSTALL_LIBDIR} ) - install(FILES ${WASMEDGE_CAPI_HEADERS} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wasmedge - ) - install(FILES ${PROJECT_SOURCE_DIR}/cmake/wasmedge-config.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wasmedge) endif() + +install(FILES ${WASMEDGE_CAPI_HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wasmedge +) + +install(FILES ${PROJECT_SOURCE_DIR}/cmake/wasmedge-config.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wasmedge) diff --git a/lib/api/libwasmedge.lds b/lib/api/libwasmedge.lds index b186937777bd..afc57677c545 100644 --- a/lib/api/libwasmedge.lds +++ b/lib/api/libwasmedge.lds @@ -4,7 +4,7 @@ extern "C++" { WasmEdge::* }; - + llvm_orc_*; local: *; }; diff --git a/lib/api/wasmedge.cpp b/lib/api/wasmedge.cpp index 4c58cf8e484a..bc9525aba205 100644 --- a/lib/api/wasmedge.cpp +++ b/lib/api/wasmedge.cpp @@ -4,6 +4,7 @@ #include "wasmedge/wasmedge.h" #include "common/defines.h" +#include "common/enum_errcode.hpp" #include "driver/compiler.h" #include "driver/tool.h" #include "driver/unitool.h" @@ -13,6 +14,7 @@ #include "vm/vm.h" #include "llvm/codegen.h" #include "llvm/compiler.h" +#include "llvm/jit.h" #ifdef WASMEDGE_BUILD_FUZZING #include "driver/fuzzPO.h" @@ -1793,6 +1795,29 @@ WASMEDGE_CAPI_EXPORT WasmEdge_Result WasmEdge_LoaderSerializeASTModule( Cxt, ASTCxt, Buf); } +WASMEDGE_CAPI_EXPORT extern WasmEdge_Result +WasmEdge_LoaderPrepareForJIT(WasmEdge_LoaderContext *Ctx, + WasmEdge_ASTModuleContext *ASTCxt, + const WasmEdge_ConfigureContext *ConfCxt) { +#ifdef WASMEDGE_USE_LLVM + LLVM::Compiler Compiler(ConfCxt->Conf); + LLVM::JIT JIT(ConfCxt->Conf); + auto *Mod = fromASTModCxt(ASTCxt); + if (auto Res = Compiler.compile(*Mod); !Res) { + const auto Err = static_cast(Res.error()); + return genWasmEdge_Result(Err); + } else if (auto Res2 = JIT.load(std::move(*Res)); !Res2) { + const auto Err = static_cast(Res2.error()); + return genWasmEdge_Result(Err); + } else { + fromLoaderCxt(Ctx)->loadExecutable(*Mod, std::move(*Res2)); + } + return genWasmEdge_Result(ErrCode::Value::Success); +#else + return genWasmEdge_Result(ErrCode::Value::JITDisabled); +#endif +} + WASMEDGE_CAPI_EXPORT void WasmEdge_LoaderDelete(WasmEdge_LoaderContext *Cxt) { delete fromLoaderCxt(Cxt); } diff --git a/lib/common/CMakeLists.txt b/lib/common/CMakeLists.txt index bf2bf37e32ac..6a05e75a0200 100644 --- a/lib/common/CMakeLists.txt +++ b/lib/common/CMakeLists.txt @@ -1,37 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2019-2022 Second State INC -find_package(spdlog QUIET) -if(spdlog_FOUND) -else() - FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG 10.2.1 - GIT_SHALLOW TRUE - ) - FetchContent_MakeAvailable(fmt) - wasmedge_setup_target(fmt) - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(fmt - PUBLIC - -Wno-missing-noreturn - PRIVATE - -Wno-sign-conversion - ) - endif() +hunter_add_package(fmt) +hunter_add_package(spdlog) - FetchContent_Declare( - spdlog - GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG v1.13.0 - GIT_SHALLOW TRUE - ) - set(SPDLOG_BUILD_SHARED OFF CACHE BOOL "Build shared library" FORCE) - set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "Use external fmt library instead of bundled" FORCE) - FetchContent_MakeAvailable(spdlog) - wasmedge_setup_target(spdlog) -endif() +find_package(spdlog CONFIG REQUIRED) wasmedge_add_library(wasmedgeCommon hexstr.cpp diff --git a/lib/llvm/jit.cpp b/lib/llvm/jit.cpp index 545c48ffee4f..01e7cdfa10f5 100644 --- a/lib/llvm/jit.cpp +++ b/lib/llvm/jit.cpp @@ -64,6 +64,8 @@ std::vector> JITLibrary::getCodes(size_t Offset, } Expect> JIT::load(Data D) noexcept { + spdlog::info("jit load start"); + OrcLLJIT J; if (auto Res = OrcLLJIT::create(); !Res) { spdlog::error("{}"sv, Res.error().message().string_view()); @@ -88,6 +90,8 @@ Expect> JIT::load(Data D) noexcept { return Unexpect(ErrCode::Value::HostFuncError); } + spdlog::info("jit load end"); + return std::make_shared(std::move(J)); } } // namespace WasmEdge::LLVM diff --git a/lib/loader/ast/module.cpp b/lib/loader/ast/module.cpp index db9a4e17ac9e..a9cd745a9a7e 100644 --- a/lib/loader/ast/module.cpp +++ b/lib/loader/ast/module.cpp @@ -202,6 +202,7 @@ Expect Loader::loadModule(AST::Module &Mod) { // Setup symbols from loaded binary. See "include/loader/loader.h". Expect Loader::loadExecutable(AST::Module &Mod, std::shared_ptr Exec) { + spdlog::info("load executable start"); auto &SubTypes = Mod.getTypeSection().getContent(); for (auto &SubType : SubTypes) { if (unlikely(!SubType.getCompositeType().isFunc())) { @@ -259,6 +260,7 @@ Expect Loader::loadExecutable(AST::Module &Mod, *Symbol = IntrinsicsTable; } } + spdlog::info("load executable end"); return {}; } From 24b798b0f60434716945d5ec0f2d0a56ad1a7ca3 Mon Sep 17 00:00:00 2001 From: Harrm Date: Thu, 6 Jun 2024 16:45:23 +0300 Subject: [PATCH 211/218] Update hunter url --- CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd923796553d..6a8ec5ab8067 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,8 @@ set(HUNTER_CACHE_SERVERS include(cmake/HunterGate.cmake) HunterGate( - URL https://github.com/qdrvm/hunter/archive/refs/heads/update/boost-1.85.zip - SHA1 40c34d168dfa7d2a44d146928befa2d9d5680a71 + URL https://github.com/qdrvm/hunter/archive/b1bc7f1f71da2520c37a6cc1b47e4213f16c7e93.zip + SHA1 fdbee4d3477245ced66c11558cddf229451be212 LOCAL ) @@ -160,11 +160,7 @@ if(WASMEDGE_BUILD_COVERAGE) append_coverage_compiler_flags() endif() -<<<<<<< HEAD -if(WASMEDGE_BUILD_AOT_RUNTIME) -======= if(WASMEDGE_USE_LLVM) ->>>>>>> b38d24e9 (qdrvm) hunter_add_package(ZLIB) hunter_add_package(LLVM) hunter_add_package(LLD) From 1c3e0888a335f7056ff81866890d9b56a0e00b81 Mon Sep 17 00:00:00 2001 From: Harrm Date: Thu, 6 Jun 2024 16:47:58 +0300 Subject: [PATCH 212/218] clang-format --- include/executor/executor.h | 8 +++++--- lib/executor/instantiate/data.cpp | 3 ++- lib/system/fault.cpp | 3 +-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/executor/executor.h b/include/executor/executor.h index 18408cbfccc4..b63366cdf443 100644 --- a/include/executor/executor.h +++ b/include/executor/executor.h @@ -188,7 +188,8 @@ class Executor { } // [qdrvm] - Expect dataSegmentOffset(Runtime::StackManager &StackMgr, const AST::DataSegment &DataSeg); + Expect dataSegmentOffset(Runtime::StackManager &StackMgr, + const AST::DataSegment &DataSeg); private: /// Run Wasm bytecode expression for initialization. @@ -848,8 +849,9 @@ class Executor { }; struct SavedThreadLocal { - SavedThreadLocal() : SavedThis(This), SavedCurrentStack(CurrentStack), SavedExecutionContext(ExecutionContext) { - } + SavedThreadLocal() + : SavedThis(This), SavedCurrentStack(CurrentStack), + SavedExecutionContext(ExecutionContext) {} SavedThreadLocal(const SavedThreadLocal &) = delete; SavedThreadLocal(SavedThreadLocal &&) = delete; diff --git a/lib/executor/instantiate/data.cpp b/lib/executor/instantiate/data.cpp index 88bdb40b19b4..78359b0b27a9 100644 --- a/lib/executor/instantiate/data.cpp +++ b/lib/executor/instantiate/data.cpp @@ -94,7 +94,8 @@ Expect Executor::initMemory(Runtime::StackManager &StackMgr, return {}; } -Expect Executor::dataSegmentOffset(Runtime::StackManager &StackMgr, const AST::DataSegment &DataSeg) { +Expect Executor::dataSegmentOffset(Runtime::StackManager &StackMgr, + const AST::DataSegment &DataSeg) { if (DataSeg.getMode() == AST::DataSegment::DataMode::Active) { if (auto Res = runExpression(StackMgr, DataSeg.getExpr().getInstrs()); unlikely(!Res)) { diff --git a/lib/system/fault.cpp b/lib/system/fault.cpp index 5ed50f6ba094..10b2e0630401 100644 --- a/lib/system/fault.cpp +++ b/lib/system/fault.cpp @@ -46,8 +46,7 @@ void signalHandler(int Signal, siginfo_t *Siginfo, void *) { } void enableHandler() noexcept { - [[maybe_unused]] - struct sigaction Action {}; + [[maybe_unused]] struct sigaction Action {}; Action.sa_sigaction = &signalHandler; Action.sa_flags = SA_SIGINFO; // sigaction(SIGFPE, &Action, nullptr); From d58dd08f6a3b5ecc65e7f94c6e2afe40e5fca467 Mon Sep 17 00:00:00 2001 From: Harrm Date: Thu, 6 Jun 2024 17:05:17 +0300 Subject: [PATCH 213/218] Hunter tag --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a8ec5ab8067..b2daf6189eda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,8 @@ set(HUNTER_CACHE_SERVERS include(cmake/HunterGate.cmake) HunterGate( - URL https://github.com/qdrvm/hunter/archive/b1bc7f1f71da2520c37a6cc1b47e4213f16c7e93.zip - SHA1 fdbee4d3477245ced66c11558cddf229451be212 + URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm14.zip + SHA1 6fc0eb2ab6b85cec6f43d247eb43c0ab0ecdaa65 LOCAL ) From 4a748c1c4109e024c147ca3f0215ffbafe21fd54 Mon Sep 17 00:00:00 2001 From: Harrm Date: Fri, 7 Jun 2024 12:35:52 +0300 Subject: [PATCH 214/218] Fix for Mac --- cmake/wasmedge-config.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index 4b43fda1ba1d..2b529aa0c3e1 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -1,7 +1,7 @@ -set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.so") -set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.a") -set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.a") +set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.${CMAKE_SHARED_LIBRARY_SUFFIX}") +set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.${CMAKE_STATIC_LIBRARY_SUFFIX}") if (EXISTS "${WASMEDGE_SHARED_LIB}") add_library(WasmEdge::WasmEdge SHARED IMPORTED) From 91469719c72fe60e86982430f1554b151304382d Mon Sep 17 00:00:00 2001 From: Harrm Date: Fri, 7 Jun 2024 13:20:34 +0300 Subject: [PATCH 215/218] Fixing mac --- cmake/wasmedge-config.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index 2b529aa0c3e1..d1239cb8f3cb 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -16,7 +16,11 @@ elseif(EXISTS "${WASMEDGE_STATIC_LIB}") set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_STATIC_LIB}") else() - message(FATAL_ERROR "WasmEdge not found in ${WASMEDGE_ROOT}") + message(FATAL_ERROR "WasmEdge not found in ${WASMEDGE_ROOT}!") + message(FATAL_ERROR "Tried:") + message(FATAL_ERROR " - ${WASMEDGE_SHARED_LIB}") + message(FATAL_ERROR " - ${WASMEDGE_STATIC_LIB}") + message(FATAL_ERROR " - ${WASMEDGE_STATIC_LIB_DEBUG}") endif() target_include_directories(WasmEdge::WasmEdge INTERFACE "${WASMEDGE_ROOT}/include") From 8eb8170b8727f7382d35aefe13aceab5dcc4f121 Mon Sep 17 00:00:00 2001 From: Harrm Date: Fri, 7 Jun 2024 13:23:48 +0300 Subject: [PATCH 216/218] Fixing mac --- cmake/wasmedge-config.cmake | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index d1239cb8f3cb..2901e81b2e3c 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -16,11 +16,12 @@ elseif(EXISTS "${WASMEDGE_STATIC_LIB}") set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_STATIC_LIB}") else() - message(FATAL_ERROR "WasmEdge not found in ${WASMEDGE_ROOT}!") - message(FATAL_ERROR "Tried:") - message(FATAL_ERROR " - ${WASMEDGE_SHARED_LIB}") - message(FATAL_ERROR " - ${WASMEDGE_STATIC_LIB}") - message(FATAL_ERROR " - ${WASMEDGE_STATIC_LIB_DEBUG}") + message("WasmEdge not found in ${WASMEDGE_ROOT}!" + "Tried:" + " - ${WASMEDGE_SHARED_LIB}" + " - ${WASMEDGE_STATIC_LIB}" + " - ${WASMEDGE_STATIC_LIB_DEBUG}" + ) endif() target_include_directories(WasmEdge::WasmEdge INTERFACE "${WASMEDGE_ROOT}/include") From 3ca50ba90bdca3329909515c3399e997ffd771ac Mon Sep 17 00:00:00 2001 From: Harrm Date: Fri, 7 Jun 2024 13:27:50 +0300 Subject: [PATCH 217/218] Fixing mac --- cmake/wasmedge-config.cmake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index 2901e81b2e3c..1b401ae00c4a 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -1,7 +1,7 @@ -set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.${CMAKE_SHARED_LIBRARY_SUFFIX}") -set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/lib/libwasmedge.${CMAKE_STATIC_LIBRARY_SUFFIX}") -set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged.${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/lib/libwasmedge${CMAKE_SHARED_LIBRARY_SUFFIX}") +set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/lib/libwasmedge${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged${CMAKE_STATIC_LIBRARY_SUFFIX}") if (EXISTS "${WASMEDGE_SHARED_LIB}") add_library(WasmEdge::WasmEdge SHARED IMPORTED) @@ -16,11 +16,11 @@ elseif(EXISTS "${WASMEDGE_STATIC_LIB}") set_property(TARGET WasmEdge::WasmEdge PROPERTY IMPORTED_LOCATION "${WASMEDGE_STATIC_LIB}") else() - message("WasmEdge not found in ${WASMEDGE_ROOT}!" - "Tried:" - " - ${WASMEDGE_SHARED_LIB}" - " - ${WASMEDGE_STATIC_LIB}" - " - ${WASMEDGE_STATIC_LIB_DEBUG}" + message(FATAL_ERROR "WasmEdge not found in ${WASMEDGE_ROOT}!\n" + "Tried:\n" + " - ${WASMEDGE_SHARED_LIB}\n" + " - ${WASMEDGE_STATIC_LIB}\n" + " - ${WASMEDGE_STATIC_LIB_DEBUG}\n" ) endif() From 77357b31d54e4201b15a2fd4030ed8ced2f04df9 Mon Sep 17 00:00:00 2001 From: Harrm Date: Fri, 1 Nov 2024 15:29:47 +0300 Subject: [PATCH 218/218] Update wasmedge-config.cmake Signed-off-by: Harrm --- cmake/wasmedge-config.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/wasmedge-config.cmake b/cmake/wasmedge-config.cmake index 1b401ae00c4a..58dfd78422bc 100644 --- a/cmake/wasmedge-config.cmake +++ b/cmake/wasmedge-config.cmake @@ -1,7 +1,8 @@ +include(GNUInstallDirs) -set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/lib/libwasmedge${CMAKE_SHARED_LIBRARY_SUFFIX}") -set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/lib/libwasmedge${CMAKE_STATIC_LIBRARY_SUFFIX}") -set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/lib/libwasmedged${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(WASMEDGE_SHARED_LIB "${WASMEDGE_ROOT}/${CMAKE_INSTALL_LIBDIR}/libwasmedge${CMAKE_SHARED_LIBRARY_SUFFIX}") +set(WASMEDGE_STATIC_LIB "${WASMEDGE_ROOT}/${CMAKE_INSTALL_LIBDIR}/libwasmedge${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(WASMEDGE_STATIC_LIB_DEBUG "${WASMEDGE_ROOT}/${CMAKE_INSTALL_LIBDIR}/libwasmedged${CMAKE_STATIC_LIBRARY_SUFFIX}") if (EXISTS "${WASMEDGE_SHARED_LIB}") add_library(WasmEdge::WasmEdge SHARED IMPORTED)