Skip to content

[wasm] Emit the 'V' thunk signature-key char for Vector128<T>/Vector<T> args#131246

Merged
lewing merged 5 commits into
dotnet:mainfrom
lewing:wasi-r2r-thunk-v128-key
Jul 23, 2026
Merged

[wasm] Emit the 'V' thunk signature-key char for Vector128<T>/Vector<T> args#131246
lewing merged 5 commits into
dotnet:mainfrom
lewing:wasi-r2r-thunk-v128-key

Conversation

@lewing

@lewing lewing commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

The interp↔R2R thunk ABI encodes a wasm v128 argument as the signature-key char 'V'. crossgen2 (WasmLowering) already generates interp→R2R thunks that encode a supported Vector128<T> / 16-byte Vector<T> parameter as v128'V' (WasmValueType.V128 => 'V', predicate IsWasmV128Type).

But the VM-side signature-key builder in src/coreclr/vm/wasm/helpers.cpp classified such a 16-byte vector as a generic by-ref struct (ToStruct'S16'), so at runtime the VM built a key that did not match the crossgen2-generated 'V' thunk:

crossgen2 thunk key:  …V…
VM runtime lookup:    …S16…   → LookupThunk returns NULL
                              → "WASM calli missing for key" (missing thunk)

for any interp→R2R call passing a Vector128<T> (or a 16-byte Vector<T>) by value.

Fix

Classify a supported vector base type — an intrinsic type with a single numeric generic argument that is Vector128<T>, or a 16-byte Vector<T> — as the new ConvertType::ToV128, emitted as 'V', matching WasmLowering's v128 encoding so the runtime resolves the correct v128-passing thunk. Single-field structs wrapping a v128 recurse through the existing single-field unwrap path and land on ToV128 as well, matching crossgen2. Mirrors the JIT's TYP_SIMD16 recognition and WasmLowering.IsWasmV128Type.

Validation

  • WASI CoreCLR build (clr -os wasi -c Release): 0W/0E; helpers.cpp object recompiles clean.
  • Validated against the System.Runtime.CompilerServices.Unsafe library suite under R2R (128/128), which exercises Vector128 interp↔R2R boundaries (previously failed with a missing thunk).

Note

This PR was authored with the assistance of GitHub Copilot.

…T> args

The interp<->R2R thunk ABI encodes a wasm v128 argument as the signature-key char
'V'. crossgen2 (WasmLowering) already generates interp->R2R thunks that encode a
supported Vector128<T> / 16-byte Vector<T> parameter as v128 => 'V'. But the VM-side
signature-key builder in helpers.cpp classified such a 16-byte vector as a generic
by-ref struct ('S16'), so at runtime it built a key that did not match the
crossgen2-generated 'V' thunk:

  crossgen2 thunk key:  ...V...
  VM runtime lookup:    ...S16...   -> LookupThunk returns NULL
                                    -> "WASM calli missing for key" (missing thunk)

for any interp->R2R call passing a Vector128<T> (or a 16-byte Vector<T>) by value.

Classify a supported vector base type (an intrinsic type with a single numeric generic
argument) that is Vector128<T>, or a 16-byte Vector<T>, as the new ConvertType::ToV128,
emitted as 'V' -- matching WasmLowering's v128 encoding -- so the runtime resolves the
correct v128-passing thunk. Mirrors the JIT's TYP_SIMD16 recognition and
WasmLowering.IsWasmV128Type.

Verified: WASI CoreCLR build (clr -os wasi -c Release) 0W/0E; validated against the
System.Runtime.CompilerServices.Unsafe library suite under R2R (128/128), which
exercises Vector128 interp<->R2R boundaries.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2902374a-f352-4c46-bcec-8a35c97733ae
Copilot AI review requested due to automatic review settings July 23, 2026 00:08
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@lewing
lewing marked this pull request as ready for review July 23, 2026 00:09
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 CoreCLR wasm thunk signature-key builder so that by-value Vector128<T> (and 16-byte Vector<T>) parameters are classified as wasm v128 and encoded using the 'V' signature-key character, aligning VM runtime thunk lookup with crossgen2’s thunk key generation.

Changes:

  • Add a new ConvertType::ToV128 classification for supported vector base types.
  • Detect Vector128<T> and 16-byte Vector<T> (with supported numeric T) as v128 in LowerTypeHandle.
  • Emit 'V' for the new ToV128 case when building the signature key.

Comment thread src/coreclr/vm/wasm/helpers.cpp
@lewing

lewing commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

cc @dotnet/wasm-eng

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 23, 2026 00:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated
Comment thread src/coreclr/vm/wasm/helpers.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 23, 2026 00:22
Comment thread src/coreclr/vm/wasm/helpers.cpp
Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

src/coreclr/vm/wasm/helpers.cpp:1042

  • CoreLibBinder::GetClassIfExist(CLASS__VECTOR128T) / GetClassIfExist(CLASS__VECTORT) are called unconditionally for every valuetype processed by LowerTypeHandle, even though the result is only needed when the type is an intrinsic vector candidate. Since GetSignatureKey runs under GC_NOTRIGGER, it’s best to minimize binder lookups here; you can move these lookups inside the isSupportedVectorBaseType check, and only query CLASS__VECTORT when size == 16.
        PTR_MethodTable pVector128MT = CoreLibBinder::GetClassIfExist(CLASS__VECTOR128T);
        PTR_MethodTable pVectorTMT = CoreLibBinder::GetClassIfExist(CLASS__VECTORT);

        bool isSupportedVectorBaseType =
            pMT->IsIntrinsicType() &&
            (pMT->GetNumGenericArgs() == 1) &&
            CorIsNumericalType(pMT->GetInstantiation()[0].GetSignatureCorElementType());

src/coreclr/vm/wasm/helpers.cpp:1126

  • GetSignatureKey references docs/design/coreclr/botr/readytorun-format.md as the documentation for wasm signature string encoding, but that doc currently doesn’t list the V encoding for v128 in the return/parameter tables. Since this change introduces/uses V, the docs should be updated to include it so the three codebases stay aligned.
            case ConvertType::ToF32:       c = 'f'; break;
            case ConvertType::ToF64:       c = 'd'; break;
            case ConvertType::ToV128:      c = 'V'; break;
            case ConvertType::ToEmpty:     c = 'e'; break;

…at.md

Add the 'V' token to the return-type and explicit-parameter tables of the
"Wasm Signature String Encoding" section. 'V' encodes a wasm v128 value
(Vector128<T>, or a 16-byte Vector<T>) passed/returned by value, matching
crossgen2's WasmLowering (WasmValueType.V128 => 'V') and the CoreCLR runtime
key-builder. Keeps the shared-encoding doc in sync with the three codebases.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2902374a-f352-4c46-bcec-8a35c97733ae
Copilot AI review requested due to automatic review settings July 23, 2026 00:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

docs/design/coreclr/botr/readytorun-format.md:1089

  • Same as above: consider using "e.g." so the V parameter description doesn't imply only Vector128<T>/Vector<T> can produce a v128 lowering (wrapper structs can too).
| `V` | `v128` parameter (a `Vector128<T>`, or a 16-byte `Vector<T>`, passed by value) |

Comment thread src/coreclr/vm/wasm/helpers.cpp
Comment thread docs/design/coreclr/botr/readytorun-format.md
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@lewing

lewing commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

I forgot merging a suggestion would require another reivew.

@lewing
lewing enabled auto-merge (squash) July 23, 2026 01:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

src/coreclr/vm/wasm/helpers.cpp:1040

  • The v128 classification probe runs for any intrinsic generic value type with a single numeric generic argument (e.g., Span, ByReference), even though only 16-byte types can ever lower to wasm v128. Adding a size == 16 guard avoids two CoreLibBinder::GetClassIfExist(...) lookups on non-v128 types while keeping Vector128/Vector behavior unchanged.
        bool isSupportedVectorBaseType =
            pMT->IsIntrinsicType() &&
            (pMT->GetNumGenericArgs() == 1) &&
            CorIsNumericalType(pMT->GetInstantiation()[0].GetSignatureCorElementType());

docs/design/coreclr/botr/readytorun-format.md:1062

  • This section says the encoding is "shared across three codebases", but the CoreCLR WasmAppBuilder SignatureMapper implementation currently doesn’t emit/parse the newly documented V (v128) token. Either update WasmAppBuilder to handle V, or clarify here that WasmAppBuilder currently implements only a subset of the encoding.
| `V` | returns `v128` (a `Vector128<T>`, or a 16-byte `Vector<T>`) |

@lewing
lewing merged commit 413da79 into dotnet:main Jul 23, 2026
52 checks passed
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.

3 participants