Skip to content

Support for interface dispatch on native AOT/WASM - #135763

Merged
MichalStrehovsky merged 5 commits into
dotnet:mainfrom
MichalStrehovsky:nativeaot-wasm-interface-dispatch
Oct 21, 2026
Merged

MichalStrehovsky merged 5 commits into
dotnet:mainfrom
MichalStrehovsky:nativeaot-wasm-interface-dispatch

Conversation

@MichalStrehovsky

Copy link
Copy Markdown
Member

Part of a series of pull requests that enable compiling, linking, and running a Console.WriteLine hello world on WASI/native AOT.

Summary

Resolve NativeAOT Wasm interface targets and call them indirectly with the actual method signature, rather than using the arbitrary-signature RhpInterfaceDispatch stub.

ILC reports CORINFO_VIRTUALCALL_LDVIRTFTN, retains concrete or generic dispatch-cell lookups, and requests null-instance checks. RyuJIT passes the receiver and cell to CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT; Wasm maps that to the existing fixed-signature RhpResolveInterfaceMethod rather than the unsupported fast helper.

The existing generic-virtual-method path is retained. The importer also enables NativeAOT Wasm's existing ReadyToRun resolver for class-virtual ldvirtftn, covering delegates bound to class virtual methods. Non-Wasm NativeAOT stub selection and the CoreCLR Wasm fallback are preserved.

Validation

  • Checked Wasm JIT, native x64 JIT, ILC, and crossgen2 builds - passed.
  • Local verify-interface-codegen.ps1 - 6/6 Wasm cases compiled and passed Wasm validation; no case imported RhpInterfaceDispatch, and the concrete/generic call cases imported RhpResolveInterfaceMethod.
  • The same script's 6/6 Windows x64 compilation controls passed.

The cases cover concrete interface calls, shared generic methods/types, interface delegates, and class-virtual delegates. These are codegen checks, not interface-dispatch execution tests.

These results are from the combined local bringup tree, including prerequisite NativeAOT/Wasm enablement, not a fresh build of this isolated main-based branch. The probe script is a local fixture, not a test added by this PR.

Note

This PR description was generated by GitHub Copilot.

Cannot use VSD, so use a resolver. We might want to do something with the perf later.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c78266f3-08e3-4918-b2e5-9fe0ddf2ca17
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

@azure-pipelines

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

Comment thread src/coreclr/jit/importer.cpp Resolved

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.

🟡 Changes recommended

Unsupported generic lookups can crash compilation, and standalone virtual function-pointer lookups lack required receiver null checks.

3 open findings
What changed in this PR

Advances NativeAOT/WASI support by resolving interface targets before calling them with their actual signatures.

Changes:

  • Selects Wasm-specific interface lookup behavior and the fixed-signature resolver.
  • Adds importer support for interface lookups and enables class-virtual function-pointer resolution.

Validation here was limited to source inspection; no builds or tests were run.

File Description
src/​coreclr/​tools/​aot/​ILCompiler.RyuJit/​JitInterface/​CorInfoImpl.RyuJit.cs Selects Wasm dispatch lookups, resolver, and null-check requirements.
src/​coreclr/​jit/​importer.cpp Imports Wasm interface lookups and enables NativeAOT class-virtual resolution.

🧠 Review effort: Balanced

Comment thread src/coreclr/jit/importer.cpp Resolved
Comment thread src/coreclr/jit/importer.cpp Resolved
Comment thread src/coreclr/jit/importer.cpp Resolved
MichalStrehovsky and others added 2 commits October 15, 2026 16:39
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c78266f3-08e3-4918-b2e5-9fe0ddf2ca17
Propagate unsupported generic dictionary lookups out of ldvirtftn import and the indirect-call importer. Request explicit receiver null checks for Wasm interface and class-virtual resolvers, tagging the class helper argument as the this pointer. Simplify the Wasm R2R comment as requested.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c78266f3-08e3-4918-b2e5-9fe0ddf2ca17
@MichalStrehovsky

Copy link
Copy Markdown
Member Author

@dotnet/jit-contrib could someone have a look? this is blocking progress for native AOT WASM. We cannot start testing anything in the CI if interface dispatch doesn't work and native AOT WASM already got broken twice since I started working on it.

@MichalStrehovsky

Copy link
Copy Markdown
Member Author

@dotnet/jit-contrib could someone have a look? this is blocking progress for native AOT WASM. We cannot start testing anything in the CI if interface dispatch doesn't work and native AOT WASM already got broken twice since I started working on it.

@adamperlin @EgorBo could you have a look please? I thought I can wait for Jakob to be back but he's still not back and this is getting really blocking.

@EgorBo

EgorBo commented Oct 20, 2026

Copy link
Copy Markdown
Member

@MichalStrehovsky it looks like we need to apply this patch:

    bool IsGenericVirtual(Compiler* compiler) const
    {
        return (gtCallType == CT_INDIRECT && (gtControlExpr->IsHelperCall(CORINFO_HELP_VIRTUAL_FUNC_PTR) ||
                                              gtControlExpr->IsHelperCall(CORINFO_HELP_GVMLOOKUP_FOR_SLOT) ||
+                                             gtControlExpr->IsHelperCall(CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT)
#ifdef FEATURE_READYTORUN
                                              || gtControlExpr->IsHelperCall(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR)
#endif
                                                  ));
    }

for divirtualizations to work.
Other than that LGTM I think. CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT might also need some VN treatment for CSE, but not sure (perf only, not correctness).

Treat CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT like the other virtual function
lookup helpers: make calls through it devirtualization candidates and model
it as a pure helper so lookups can be CSE'd and hoisted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d0ebd8c9-e09f-4780-8ee2-7381f7a0b5fd
@MichalStrehovsky

Copy link
Copy Markdown
Member Author

Thanks for the reviews! I ran some additional validation - enabled this on Windows and ran a decent subset of src/tests tree with it. This should work, we can do perf fixes later.

@MichalStrehovsky
MichalStrehovsky merged commit cd54044 into dotnet:main Oct 21, 2026
127 of 129 checks passed
@MichalStrehovsky
MichalStrehovsky deleted the nativeaot-wasm-interface-dispatch branch October 21, 2026 03:28
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-NativeAOT-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants