From fa44ed2f3406e8524ad2b225289dcfecf1ad67c2 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Fri, 5 Jun 2026 15:11:25 -0500 Subject: [PATCH] [wasi] Enable PackedSimd intrinsics and ILLink substitutions The mono interpreter only emitted wasm packed-simd intrinsic opcodes when HOST_BROWSER was defined. On WASI the interpreter returned FALSE for every PackedSimd method, so calls fell through to the C# method body which recursively calls itself, producing a stack overflow (observed with ConvertNarrowingSaturateUnsigned and other PackedSimd intrinsics). Additionally, WasiApp.targets did not inject the ILLink substitutions that fold PackedSimd.IsSupported to a constant, so even with WasmEnableSIMD=false the simd code paths survived trimming and the call sites still recursed. Changes: * src/mono/mono/mini/interp/interp-simd.h, interp-simd.c, interp-nosimd.c, transform-simd.c: extend the HOST_BROWSER gates around the wasm packed-simd intrinsic tables and emission to also cover HOST_WASI. The mono-wasm-simd static library is already built with -msimd128 for both hosts in cmake. * src/mono/wasi/build/WasiApp.targets: add _ExtraTrimmerArgs for the WasmIntrinsics.xml / NoWasmIntrinsics.xml substitutions, mirroring BrowserWasmApp.targets, and uncomment the -msimd128 clang flag when WasmEnableSIMD=true. * src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/ Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj: package the two ILLink.Substitutions.*.xml files next to WasiApp.targets in the WASI SDK so $(MSBuildThisFileDirectory) resolves at app build time. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/mono/mono/mini/interp/interp-nosimd.c | 4 ++-- src/mono/mono/mini/interp/interp-simd.c | 10 ++++++++-- src/mono/mono/mini/interp/interp-simd.h | 2 +- src/mono/mono/mini/interp/transform-simd.c | 16 ++++++++-------- ...soft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj | 3 +++ src/mono/wasi/build/WasiApp.targets | 5 ++++- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/mono/mono/mini/interp/interp-nosimd.c b/src/mono/mono/mini/interp/interp-nosimd.c index 63bcf2783ec087..215864eaac4976 100644 --- a/src/mono/mono/mini/interp/interp-nosimd.c +++ b/src/mono/mono/mini/interp/interp-nosimd.c @@ -6,7 +6,7 @@ gboolean interp_simd_enabled = FALSE; -#ifdef HOST_BROWSER +#if HOST_BROWSER || HOST_WASI int interp_simd_p_p_wasm_opcode_table [] = { }; @@ -17,7 +17,7 @@ int interp_simd_p_pp_wasm_opcode_table [] = { int interp_simd_p_ppp_wasm_opcode_table [] = { }; -#endif // HOST_BROWSER +#endif // HOST_BROWSER || HOST_WASI PP_SIMD_Method interp_simd_p_p_table [] = { }; diff --git a/src/mono/mono/mini/interp/interp-simd.c b/src/mono/mono/mini/interp/interp-simd.c index cdc6a951c5f92a..b779813fa745d3 100644 --- a/src/mono/mono/mini/interp/interp-simd.c +++ b/src/mono/mono/mini/interp/interp-simd.c @@ -2,7 +2,7 @@ #include "interp-internals.h" #include "interp-simd.h" -#if HOST_BROWSER +#if HOST_BROWSER || HOST_WASI #include #endif @@ -611,6 +611,12 @@ interp_v128_i8_shuffle (gpointer res, gpointer v1, gpointer v2) // https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/wasm_simd128.h // In this context V means Vector128 and P means void* pointer. #ifdef HOST_BROWSER +#define HOST_WASM_SIMD 1 +#elif defined(HOST_WASI) +#define HOST_WASM_SIMD 1 +#endif + +#if HOST_WASM_SIMD static v128_t _interp_wasm_simd_assert_not_reached (v128_t lhs, v128_t rhs) { @@ -931,7 +937,7 @@ int interp_simd_p_ppp_wasm_opcode_table [] = { #undef INTERP_SIMD_INTRINSIC_P_PPP #define INTERP_SIMD_INTRINSIC_P_PPP(a,b,c) -#endif // HOST_BROWSER +#endif // HOST_WASM_SIMD #undef INTERP_SIMD_INTRINSIC_P_P #define INTERP_SIMD_INTRINSIC_P_P(a,b,c) b, diff --git a/src/mono/mono/mini/interp/interp-simd.h b/src/mono/mono/mini/interp/interp-simd.h index 8e0222613e44a2..92bf8b849aee09 100644 --- a/src/mono/mono/mini/interp/interp-simd.h +++ b/src/mono/mono/mini/interp/interp-simd.h @@ -13,7 +13,7 @@ extern PP_SIMD_Method interp_simd_p_p_table []; extern PPP_SIMD_Method interp_simd_p_pp_table []; extern PPPP_SIMD_Method interp_simd_p_ppp_table []; -#if HOST_BROWSER +#if HOST_BROWSER || HOST_WASI extern int interp_simd_p_p_wasm_opcode_table []; extern int interp_simd_p_pp_wasm_opcode_table []; extern int interp_simd_p_ppp_wasm_opcode_table []; diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index 6f689433361847..b41bfc796d20fd 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -517,7 +517,7 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature if (csignature->hasthis) return FALSE; -#ifdef HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) if (emit_sri_packedsimd (td, cmethod, csignature)) return TRUE; #endif @@ -731,7 +731,7 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature static gboolean emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) { -#ifdef HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) if (emit_sri_packedsimd (td, cmethod, csignature)) return TRUE; #endif @@ -775,7 +775,7 @@ emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignatur static gboolean emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature, gboolean newobj) { -#ifdef HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) if (emit_sri_packedsimd (td, cmethod, csignature)) return TRUE; #endif @@ -876,7 +876,7 @@ emit_sn_vector4 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs return TRUE; } -#if HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) #define PSIMD_ARGTYPE_I1 MONO_TYPE_I1 #define PSIMD_ARGTYPE_I2 MONO_TYPE_I2 @@ -1122,7 +1122,7 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature // We don't want to emit the IsSupported or IsHardwareAccelerated methods for Vector* here return FALSE; } -#if HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) interp_add_ins (td, MINT_LDC_I4_1); #else interp_add_ins (td, MINT_LDC_I4_0); @@ -1133,7 +1133,7 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) return FALSE; -#if HOST_BROWSER +#if defined(HOST_BROWSER) || defined(HOST_WASI) if (!is_packedsimd) { // transform the method name from the Vector(128|) name to the packed simd name // FIXME: This is a hack, but it works for now. @@ -1311,9 +1311,9 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature interp_add_ins (td, simd_opcode); td->last_ins->data [0] = simd_intrins; -#else // HOST_BROWSER +#else // defined(HOST_BROWSER) || defined(HOST_WASI) return FALSE; -#endif // HOST_BROWSER +#endif // defined(HOST_BROWSER) || defined(HOST_WASI) opcode_added: emit_common_simd_epilogue (td, vector_klass, csignature, vector_size, TRUE); diff --git a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj index 54dc01747f7d07..5ca1aa5809efec 100644 --- a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj +++ b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj @@ -15,6 +15,9 @@ + + + diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index 6b8bb0547302c4..c2feed788dee57 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -46,6 +46,9 @@ false full + <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'false'">$(_ExtraTrimmerArgs) --substitutions "$(MSBuildThisFileDirectory)ILLink.Substitutions.WasmIntrinsics.xml" + <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' == 'false'">$(_ExtraTrimmerArgs) --substitutions "$(MSBuildThisFileDirectory)ILLink.Substitutions.NoWasmIntrinsics.xml" + false @@ -245,7 +248,7 @@ <_WasiClangCommonFlags Include="-v" Condition="'$(WasiClangVerbose)' != 'false'" /> - + <_WasiClangCommonFlags Include="-msimd128" Condition="'$(WasmEnableSIMD)' == 'true'" /> <_WasmCommonCFlags Include="-DGEN_PINVOKE=1" /> <_WasmCommonCFlags Condition="'$(_WasmShouldAOT)' == 'true'" Include="-DENABLE_AOT=1" />