Skip to content

[wasi] Enable PackedSimd intrinsics and ILLink substitutions#129051

Closed
lewing wants to merge 1 commit into
dotnet:mainfrom
lewing:wasi-packedsimd-intrinsics
Closed

[wasi] Enable PackedSimd intrinsics and ILLink substitutions#129051
lewing wants to merge 1 commit into
dotnet:mainfrom
lewing:wasi-packedsimd-intrinsics

Conversation

@lewing
Copy link
Copy Markdown
Member

@lewing lewing commented Jun 5, 2026

Note

This PR description was AI-generated with GitHub Copilot.

Problem

Calling System.Runtime.Intrinsics.Wasm.PackedSimd.ConvertNarrowingSaturateUnsigned (and other PackedSimd intrinsics) in a WASI app crashes with a stack overflow, because the C# fallback for each intrinsic recursively calls itself when the runtime fails to substitute it.

Two separate things contribute:

  1. Mono interpreter (WASI, SIMD enabled). `src/mono/mono/mini/interp/transform-simd.c` only emits the interpreter's wasm packed-simd opcodes when `HOST_BROWSER` is defined. On WASI `emit_sri_packedsimd` always returns `FALSE`, so the C# body runs and recurses.
  2. WASI SDK / MSBuild (any SIMD setting). `WasiApp.targets` does not inject the ILLink `WasmIntrinsics.xml` / `NoWasmIntrinsics.xml` substitutions that `BrowserWasmApp.targets` uses to fold `PackedSimd.IsSupported` to a constant. Without that, `WasmEnableSIMD=false` apps still keep the simd call sites alive and trip the same recursion.

Changes

Interpreter (b): Extend the `HOST_BROWSER` gates to also cover `HOST_WASI` so the interpreter substitutes PackedSimd intrinsics on WASI. The `mono-wasm-simd` static library is already built with `-msimd128` for both hosts (`src/mono/mono/mini/CMakeLists.txt` line 484).

  • `src/mono/mono/mini/interp/interp-simd.h` — extern table declarations.
  • `src/mono/mono/mini/interp/interp-simd.c` — `<wasm_simd128.h>` include and the wasm intrinsic block (now under a `HOST_WASM_SIMD` helper macro).
  • `src/mono/mono/mini/interp/interp-nosimd.c` — empty fallback tables provided for WASI too.
  • `src/mono/mono/mini/interp/transform-simd.c` — every `HOST_BROWSER` gate around `emit_sri_packedsimd` switched to `defined(HOST_BROWSER) || defined(HOST_WASI)`.

MSBuild / SDK (a, c):

  • `src/mono/wasi/build/WasiApp.targets` — add `_ExtraTrimmerArgs` for the two substitution XMLs (mirrors `BrowserWasmApp.targets:33-34`), and uncomment `-msimd128` for `WasmEnableSIMD=true`.
  • `src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj` — ship the two `ILLink.Substitutions.*.xml` files (reused from `$(BrowserProjectRoot)`) next to `WasiApp.targets` in the WASI SDK pack so `$(MSBuildThisFileDirectory)` resolves at app build time.

Verification

  • WASI mono native built cleanly with `WasmEnableSIMD=true`: `libmono-wasm-simd.a`, `libmono-wasm-nosimd.a`, `transform.c.obj` (includes `transform-simd.c`), and `interp-simd.c.obj` all built with `HOST_WASI` defined.
  • An unrelated pre-existing wasi-sysroot link failure (`undefined symbol: gethostname` in `libSystem.Native.a`) blocks the final `dotnet.wasm` link; reproduced on `main`, not affected by these changes.

Draft

Marked draft for review and to confirm there are no other WASI-only PackedSimd test gaps before un-drafting.

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>
Copilot AI review requested due to automatic review settings June 5, 2026 20:11
@lewing lewing closed this Jun 5, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @vitek-karas, @BrzVlad, @kotlarmilos
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Mono WASI toolchain and interpreter so System.Runtime.Intrinsics.Wasm.PackedSimd intrinsics can be substituted/trimmed correctly on WASI (matching existing browser-WASM behavior), avoiding falling back to the managed recursive implementations.

Changes:

  • Enable interpreter-side PackedSimd intrinsic emission on WASI by extending existing HOST_BROWSER gates to also include HOST_WASI.
  • Add ILLink substitution XMLs to the WASI SDK pack and pass the appropriate --substitutions file based on WasmEnableSIMD.
  • Enable -msimd128 for the WASI clang toolchain when WasmEnableSIMD=true.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/mono/wasi/build/WasiApp.targets Adds ILLink substitutions for Wasm intrinsics and enables -msimd128 for WASI builds when SIMD is on.
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj Packs the ILLink substitution XMLs into the WASI SDK so they can be consumed at app build time.
src/mono/mono/mini/interp/transform-simd.c Extends PackedSimd emission gates from browser-only to browser-or-WASI.
src/mono/mono/mini/interp/interp-simd.h Exposes wasm opcode tables for WASI builds alongside browser builds.
src/mono/mono/mini/interp/interp-simd.c Enables wasm SIMD header inclusion and opcode table generation for WASI builds.
src/mono/mono/mini/interp/interp-nosimd.c Provides empty fallback wasm opcode tables for WASI (parity with browser).

Comment thread src/mono/wasi/build/WasiApp.targets
lewing added a commit to lewing/runtime that referenced this pull request Jun 6, 2026
…n XMLs

The XML files only sit next to WasiApp.targets in the packaged WASI SDK.
For in-tree builds they live under $(BrowserProjectRoot)build\, so detect
the local file with Exists() and fall back to the browser build dir when
absent.

Addresses review feedback on PR dotnet#129051.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants