feat: add WAMR WebAssembly engine support for Halide JIT#9116
Conversation
|
I sent this pr a little early but i would love feedback. v8 is a very large dep and is causing issues and we cant use wabt. wamr is a perfect drop in. |
4df6609 to
6223372
Compare
|
I just tried this... it is possible to use standard mechanisms to use WAMR. I would push directly, but I notice you prefer to force-push, @soldair, so to avoid losing work, I'll provide you with a patch file instead. This boils down to two changes:
I've also opened bytecodealliance/wasm-micro-runtime#4932 to nudge upstream into also using standard mechanisms for pulling in dependencies. 0001-Use-standard-mechanisms-to-use-WAMR.patch Patch contentsFrom 6c5c846544ba9e0a3775e3aeefc744705809072f Mon Sep 17 00:00:00 2001
From: Alex Reinking <areinking@adobe.com>
Date: Thu, 30 Apr 2026 15:30:06 -0400
Subject: [PATCH] Use standard mechanisms to use WAMR
- Rather than building WAMR in-line with Halide, add a vcpkg port
to manage building WAMR. The WAMR build uses FetchContent to
acquire simde, which is unnecessary, so we patch around it.
- Use find_package to import WAMR into the build, mirroring the
approach for V8 and wabt.
---
cmake/vcpkg/wamr/portfile.cmake | 21 +++++++++++++++
cmake/vcpkg/wamr/remove-fetchcontent.patch | 19 ++++++++++++++
cmake/vcpkg/wamr/vcpkg.json | 18 +++++++++++++
src/CMakeLists.txt | 30 +++++-----------------
vcpkg.json | 12 ++++++---
5 files changed, 73 insertions(+), 27 deletions(-)
create mode 100644 cmake/vcpkg/wamr/portfile.cmake
create mode 100644 cmake/vcpkg/wamr/remove-fetchcontent.patch
create mode 100644 cmake/vcpkg/wamr/vcpkg.json
diff --git a/cmake/vcpkg/wamr/portfile.cmake b/cmake/vcpkg/wamr/portfile.cmake
new file mode 100644
index 000000000..05593b8de
--- /dev/null
+++ b/cmake/vcpkg/wamr/portfile.cmake
@@ -0,0 +1,21 @@
+vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
+
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO bytecodealliance/wasm-micro-runtime
+ REF 8c18e3f68b16c4bcaf05996b2636f6ed2b4cf629 # WAMR-2.4.4
+ SHA512 2378ab44e6ea3cd9bfede86a413c5d5503b8cd0d072bbee7099bd149897a58d74b57c06214f6b163242f5ac8bcdbb81a59632016ebd4c12a717786e1c387c9e3
+ PATCHES remove-fetchcontent.patch
+)
+
+vcpkg_cmake_configure(SOURCE_PATH "${SOURCE_PATH}")
+
+vcpkg_cmake_install()
+vcpkg_cmake_config_fixup(PACKAGE_NAME iwasm CONFIG_PATH lib/cmake/iwasm)
+
+vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
+
+file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/debug/include"
+ "${CURRENT_PACKAGES_DIR}/debug/share"
+)
diff --git a/cmake/vcpkg/wamr/remove-fetchcontent.patch b/cmake/vcpkg/wamr/remove-fetchcontent.patch
new file mode 100644
index 000000000..936f4dbf2
--- /dev/null
+++ b/cmake/vcpkg/wamr/remove-fetchcontent.patch
@@ -0,0 +1,19 @@
+diff --git a/core/iwasm/libraries/simde/simde.cmake b/core/iwasm/libraries/simde/simde.cmake
+--- a/core/iwasm/libraries/simde/simde.cmake
++++ b/core/iwasm/libraries/simde/simde.cmake
+@@ -15,14 +15,5 @@ add_definitions (-DWASM_ENABLE_SIMDE=1)
+
+ include_directories(${LIB_SIMDE_DIR} ${LIB_SIMDE_DIR}/simde)
+
+-include(FetchContent)
+-
+-FetchContent_Declare(
+- simde
+- GIT_REPOSITORY https://github.com/simd-everywhere/simde
+- GIT_TAG v0.8.2
+-)
+-
+-message("-- Fetching simde ..")
+-FetchContent_MakeAvailable(simde)
++find_path(simde_SOURCE_DIR simde/wasm/simd128.h)
+ include_directories("${simde_SOURCE_DIR}")
diff --git a/cmake/vcpkg/wamr/vcpkg.json b/cmake/vcpkg/wamr/vcpkg.json
new file mode 100644
index 000000000..b4a61bb6d
--- /dev/null
+++ b/cmake/vcpkg/wamr/vcpkg.json
@@ -0,0 +1,18 @@
+{
+ "name": "wamr",
+ "version-semver": "2.4.4",
+ "description": "WebAssembly Micro Runtime (WAMR)",
+ "homepage": "https://github.com/bytecodealliance/wasm-micro-runtime",
+ "license": "Apache-2.0",
+ "dependencies": [
+ "simde",
+ {
+ "name": "vcpkg-cmake",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-config",
+ "host": true
+ }
+ ]
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1e1f8e9b5..18624abc9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -591,38 +591,20 @@ if (Halide_WASM_BACKEND STREQUAL "wabt")
find_package(wabt REQUIRED)
_Halide_pkgdep(wabt)
- target_link_libraries(Halide PRIVATE wabt::wabt)
target_compile_definitions(Halide PRIVATE WITH_WABT)
+ target_link_libraries(Halide PRIVATE wabt::wabt)
elseif (Halide_WASM_BACKEND STREQUAL "V8")
find_package(V8 REQUIRED)
_Halide_pkgdep(V8)
+
target_compile_definitions(Halide PRIVATE WITH_V8)
target_link_libraries(Halide PRIVATE V8::V8)
elseif (Halide_WASM_BACKEND STREQUAL "WAMR")
- set(Halide_WAMR_ROOT_DIR "" CACHE PATH "Path to root directory of WAMR repository sources")
-
- if ("${Halide_WAMR_ROOT_DIR}" STREQUAL "")
- if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../wasm-micro-runtime/build-scripts/runtime_lib.cmake")
- set(WAMR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../wasm-micro-runtime")
- else()
- message(FATAL_ERROR "WAMR backend requires specifying Halide_WAMR_ROOT_DIR or cloning wasm-micro-runtime adjacent to the Halide repository.")
- endif()
- else()
- set(WAMR_ROOT_DIR "${Halide_WAMR_ROOT_DIR}")
- endif()
-
- set(WAMR_BUILD_PLATFORM "linux")
- set(WAMR_BUILD_TARGET "X86_64")
- set(WAMR_BUILD_INTERP 1)
- set(WAMR_BUILD_FAST_INTERP 1)
- set(WAMR_BUILD_REF_TYPES 1)
- set(WAMR_BUILD_SIMD 1)
- set(WAMR_BUILD_LIB_SIMDE 1)
- include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
- add_library(wamr_lib STATIC ${WAMR_RUNTIME_LIB_SOURCE})
- target_link_libraries(Halide PRIVATE wamr_lib)
+ find_package(iwasm REQUIRED)
+ _Halide_pkgdep(iwasm)
+
target_compile_definitions(Halide PRIVATE WITH_WAMR)
- target_include_directories(Halide PRIVATE "${WAMR_ROOT_DIR}/core/iwasm/include")
+ target_link_libraries(Halide PRIVATE iwasm::vmlib)
elseif (Halide_WASM_BACKEND)
message(FATAL_ERROR "Unknown Halide_WASM_BACKEND `${Halide_WASM_BACKEND}`")
endif ()
diff --git a/vcpkg.json b/vcpkg.json
index 6a404753c..5d7b4c293 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -45,7 +45,7 @@
"default-features": false,
"features": [
"serialization",
- "wasm-executor"
+ "wasm-executor-wabt"
]
}
]
@@ -180,11 +180,17 @@
}
]
},
- "wasm-executor": {
- "description": "Include built-in WASM executor",
+ "wasm-executor-wabt": {
+ "description": "Include wabt-based WASM executor",
"dependencies": [
"wabt"
]
+ },
+ "wasm-executor-wamr": {
+ "description": "Include wamr-based WASM executor",
+ "dependencies": [
+ "wamr"
+ ]
}
}
}
--
2.50.1 (Apple Git-155) |
|
please feel free to push any time. i'm not typically a force pusher just a product of a tool i was using. 😅 i'll apply this patch |
|
Testing this locally, I'm seeing issues with finding Halide's extern funcs feature. Also seeing issues with some surprisingly moderate allocation sizes (e.g. 48KB). |
|
Thanks for looking. If you have a command handy ill make sure everything passes and @ you when i think we're doing ok. I thought i had been running all the tests. I'm very new to this project 😅 |
|
Here's how I'm testing locally. You'll have to adapt my paths to yours. $ source ~/dev/emsdk/emsdk_env.sh
$ export VCPKG_ROOT=$HOME/dev/vcpkg
$ cmake --preset macOS-vcpkg -DHalide_WASM_BACKEND=WAMR -DHalide_TARGET=wasm-32-wasmrt-wasm_simd128
$ cmake --build build/macOS-vcpkg
$ ctest --test-dir build/macOS-vcpkg -j$(sysctl -n hw.physicalcpu)Even after your latest commit, I'm still seeing a few failures: Complete CTest failures & outputOnce everything works locally, I can add a buildbot configuration for this backend. |
…jit_externs test - Support dynamic extern callbacks in WAMR using template native dispatched wrappers. - Raise WAMR memory heap size threshold, synchronize stack overrides configuration using environment variables HL_WASM_HEAP_SIZE, HL_WASM_STACK_SIZE. - Renamed test to test/correctness/wasm_jit_externs.cpp with Wasm executor capability checks.
|
I reproed the errors locally. it seems like i had the wrong jit target cached. They should be resolved. I'm on linux so im not sure if i should have a vcpkg preset but im hoping im fine? if not ill learn about it. |
|
opps haha |
|
Note that CTest does not honor the HL_JIT_TARGET environment variable. You have to go through the Halide_TARGET cache variable. |
|
I'm still seeing a few test failures: (halide) areinking@Alexanders-MacBook-Pro Halide % ctest --test-dir build/macOS-vcpkg --rerun-failed --output-on-failure
Test project /Users/areinking/dev/Halide/build/macOS-vcpkg
Start 37: correctness_align_bounds
1/3 Test #37: correctness_align_bounds .........Subprocess aborted***Exception: 0.34 sec
Internal error at /Users/areinking/dev/Halide/src/WasmExecutor.cpp:3232
Condition failed: call_success
Error: wasm_runtime_call_wasm_a failed: Exception: invalid local type
Start 69: correctness_callable_errors
2/3 Test #69: correctness_callable_errors ......Subprocess aborted***Exception: 0.10 sec
Saw expected: (NO ERROR)
Internal error at /Users/areinking/dev/Halide/src/WasmExecutor.cpp:3198
Condition failed: wbuf
Error: hostbuf_to_wasmbuf_wamr failed
Start 128: correctness_exception
3/3 Test #128: correctness_exception ............Subprocess aborted***Exception: 0.10 sec
Expected compile error:
Error: Implicit cast from float32 to int in argument 1 in call to "f0" is not allowed. Use an explicit cast.
Expected compile error:
Error: Can't index into a reference to Func "f0", because it does not return a Tuple.
Expected compile error:
Error: In update definition 0 of Func "f0":
Tuple element 0 of update definition has type float32, but pure definition has type int32
Expected compile error:
Error: In update definition 0 of Func "f0":
Undefined expression in right-hand-side of update.
Expected internal error:
Internal error at /Users/areinking/dev/Halide/src/IR.cpp:40
Condition failed: a.defined()
Error: Add of undefined
Expected internal error:
Internal error at /Users/areinking/dev/Halide/src/ModulusRemainder.cpp:161
Error: modulus_remainder of bool
Internal error at /Users/areinking/dev/Halide/src/WasmExecutor.cpp:3198
Condition failed: wbuf
Error: hostbuf_to_wasmbuf_wamr failed
0% tests passed, 3 tests failed out of 3
Label Time Summary:
correctness = 0.53 sec*proc (3 tests)
Total Test time (real) = 0.55 sec
The following tests FAILED:
37 - correctness_align_bounds (Subprocess aborted) correctness
69 - correctness_callable_errors (Subprocess aborted) correctness
128 - correctness_exception (Subprocess aborted) correctness
Errors while running CTest |
|
@soldair - I'm seeing syntax errors in CI? Are you still interested in advancing this PR? |
|
I am definitely interested. I'll sync and get these fixed today. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9116 +/- ##
=======================================
Coverage ? 69.18%
=======================================
Files ? 254
Lines ? 78258
Branches ? 18726
=======================================
Hits ? 54146
Misses ? 18518
Partials ? 5594 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
CI was failing due to #9133 renaming |
|
Some kind of build issue with wamr on 32-bit targets. Will investigate. |
Explicitly set WAMR_BUILD_TARGET in the WAMR vcpkg port based on VCPKG_TARGET_ARCHITECTURE. This bypasses a bug in WAMR's automatic target detection when cross-compiling or building for 32-bit targets, which incorrectly fallback-classified 32-bit ARM (arm-linux) as X86_32, causing compiler errors. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
|
Looks like we need to set |
This prevents WAMR from defaulting to the host OS when cross-compiling, which previously caused compile/link failures when building Linux targets on non-Linux hosts. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
…to turn on some asm features for windows. this should also fix the arm-64 build. ill check the any new ailures give it another click for me =) and any suggestions would be appreciated.
MSVC C compiler in legacy/C99 mode does not support standard _Alignof keyword, which WAMR uses in platform_wasi_types.h. Instead, MSVC expects the __alignof compiler builtin. This patch overrides _Alignof to __alignof when compiling with MSVC in C mode, preventing syntax errors in win_file.c and other platform source files. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
…e in CI 1. Windows MSVC: C99 mode does not support standard _Alignof, which WAMR uses in platform_wasi_types.h. Preprocessors or headers expand it to GCC-style __builtin_alignof, which cl.exe fails to compile. We explicitly map both _Alignof and __builtin_alignof to MSVC's native __alignof builtin in C mode. 2. macOS arm64: WAMR's version.cmake writes core/version.h directly inside the source tree at configure time. When vcpkg runs parallel configure steps for Release/Debug concurrently, they race to overwrite version.h, causing transient 'No such file or directory' failures. Since version.h is already committed in the source archive with correct versions, we regex-patch version.cmake to completely disable the configure_file call. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
|
I opened a pr to my fork so i can trigger the actions. I'll comment here when it's green. |
Instead of dynamically patching platform_wasi_types.h header which is fragile, we leverage modern CMake's add_compile_definitions inside the patched CMakeLists.txt when compiling under MSVC. This defines _Alignof=__alignof and __builtin_alignof=__alignof globally at compilation time, resolving all MSVC C99 alignment syntax errors cleanly. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
MSVC C compiler in legacy C99 mode does not support _Alignof. Using add_compile_definitions to map it to __alignof / __builtin_alignof fails because MSVC's parser bypasses macro expansion for __builtin_... tokens and fails. Instead, we patch platform_wasi_types.h to implement _Alignof(Type) using the standard C99 offsetof trick: offsetof(struct { char c; Type member; }, member). This is completely standard, does not rely on compiler builtins, and compiles flawlessly on MSVC.
TAG=agy
CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
Using standard offsetof macro inside _Alignof definition can expand to MSVC's compiler builtin __builtin_offsetof, which fails to compile on cl.exe in C99 mode when passed anonymous struct declarations. Instead, we implement the classic C99 offsetof raw cast directly: ((size_t)&(((struct { char c; Type member; }*)0)->member)). This bypasses all compiler builtins entirely and compiles flawlessly on MSVC.
TAG=agy
CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
…on MSVC C++ and C standard compilers reject defining new structs inside type specifiers (e.g. inside casts or sizeof), making the offsetof raw cast trick fail on strictly compliant toolchains. Instead, we patch WAMR's platform_wasi_types.h header to directly map the standard _Alignof to MSVC's native __alignof keyword in C mode. Since this is done after standard header includes, it cleanly overrides any system-defined __builtin_alignof macros while avoiding type definition syntax errors. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
…ntax errors Standard C99 does not support _Alignof / _Static_assert, leading WAMR to use compiler builtins. MSVC C compiler in legacy C99 mode fails with syntax errors because it maps _Alignof to __builtin_alignof which is not supported natively. VS 2022 fully supports standard C11 natively. We patch WAMR's root CMakeLists.txt to set CMAKE_C_STANDARD to 11 on MSVC (falling back to 99 elsewhere). This resolves all alignment compile errors natively without requiring any header pollution or macro redefinition hacks. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
The custom Halide CMake style checker python script check_cmake_style.py does not parse string literals and was tripped by our enable_language() patch code represented inside a string literal. We append # nolint to the string line to explicitly bypass the custom style check. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
Resolved conflicts in src/CMakeLists.txt and test/correctness/CMakeLists.txt by cleanly adding WAMR JIT backend and wasm_jit_externs correctness test to the latest upstream lists. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
Formatted portfile.cmake cleanly using cmtk and moved the # nolint comment inside the string literal of the enable_language() patch. This prevents the auto-formatter from relocating the comment, satisfying both the auto-formatter and the custom CMake style checks. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
|
OK! i think everything is finally in order =) |
|
@soldair - great! Thanks! I'm running it now on the private buildbots. Will review soon. |
…MSVC If MSVC is used and the target is x86/x64, check for ml/ml64 assembler. If not found, set WAMR_BUILD_INVOKE_NATIVE_GENERAL=1 to use the pure C fallback, avoiding configure failures due to missing ASM_MASM support. TAG=agy CONV=61a7f0a6-c030-4b48-8580-77f4afa4c8a1
|
I'm going to add a workflow to the buildbots to test this. |
|
It looks like there are still Windows build issues and |
This option requires additional dependencies on Windows, but we only need support for .wasm binaries, not .aot.
This PR introduces Wasm Micro Runtime (WAMR) integration as an execution engine backend alternative inside the
WasmModuleJIT runtime harness, in addition to supporting standard co-existence of fallback configurations alongside legacy engines (wabt/v8).Design Background
Halide WebAssembly testing has historically targeted
wabtorV8modules. WAMR provides smaller execution footprint constraints suitable for constrained evaluation targets and embedding environments.Technical Enhancements
src/WasmExecutor.cpp.FetchContentmodule downloads.__extendhfsf2,__truncsfhf2half-float native implementations and mathematical POSIX wrappers.Fixes #
Breaking changes
None. Code coexistence preserves logic paths for previous backends
wabt/v8.Checklist