Skip to content

Add support for inline pinvokes to Wasm Ryujit#130384

Merged
davidwrighton merged 5 commits into
dotnet:mainfrom
davidwrighton:AddInlinedPInvokesToWasmRyujit
Jul 21, 2026
Merged

Add support for inline pinvokes to Wasm Ryujit#130384
davidwrighton merged 5 commits into
dotnet:mainfrom
davidwrighton:AddInlinedPInvokesToWasmRyujit

Conversation

@davidwrighton

@davidwrighton davidwrighton commented Jul 8, 2026

Copy link
Copy Markdown
Member
  • They should always be READYTORUN_FIXUP_PInvokeTarget instead of READYTORUN_FIXUP_IndirectPInvokeTarget
  • There is a debug version of JIT_PinvokeEnd which validates that sp == the __stack_pointer global. I believe our codegen will maintain this invariant, so we should be ok to skip resetting the __stack_pointer global before calls to the C++ implementation of JIT_PInvokeEnd
  • One detail which is no longer true after this work is merged is that the __stack_pointer global will be set to increasingly unpredictable values during execution. This is not a new phenomena, as it was happening during EH flow, but now it will happen in normal execution flow. Since the interpreter to R2R thunks will reset the stack before we return to any emscripten compiled code, we should be ok with this.

- They should always be READYTORUN_FIXUP_PInvokeTarget instead of READYTORUN_FIXUP_IndirectPInvokeTarget
- There is a debug version of JIT_PinvokeEnd which validates that sp == the __stack_pointer global. I believe our codegen will maintain this invariant, so we should be ok to skip resetting the __stack_pointer global before calls to the C++ implementation of JIT_PInvokeEnd
- One detail which is no longer true after this work is merged is that the __stack_pointer global will be set to increasingly unpredictable values during execution. This is not a new phenomena, as it was happening during EH flow, but now it will happen in normal execution flow. Since the interpreter to R2R thunks will reset the stack before we return to any emscripten compiled code, we should be ok with this.

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 changes the Wasm/CoreCLR and ReadyToRun toolchain to enable (or move toward enabling) inlined P/Invoke sequences in Wasm RyuJIT / R2R scenarios, primarily by adjusting how P/Invoke targets are represented in R2R fixups and how the runtime establishes stackwalk state for inlined P/Invokes on Wasm.

Changes:

  • Updates Wasm InlinedCallFrame register display logic to derive IP/SP/FP from an R2R stack pointer in the “inlined P/Invoke” case.
  • Introduces Wasm implementations/wrappers for JIT_PInvokeBegin/JIT_PInvokeEnd and adjusts fixup handling so Wasm uses READYTORUN_FIXUP_PInvokeTarget (not indirect).
  • Gates READYTORUN_FIXUP_IndirectPInvokeTarget handling in the runtime behind HAS_PINVOKE_IMPORT_PRECODE.

Reviewed changes

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

File Description
src/coreclr/vm/wasm/helpers.cpp Adds Wasm-specific inlined P/Invoke frame setup and stackwalk register-display logic; introduces Wasm JIT_PInvokeBegin/End implementations/wrappers.
src/coreclr/vm/jitinterface.cpp Wraps READYTORUN_FIXUP_IndirectPInvokeTarget runtime fixup support with HAS_PINVOKE_IMPORT_PRECODE.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs Forces Wasm ReadyToRun compilations to use direct P/Invoke target fixups (and adds explanatory comments).

Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated
Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated
Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated
Comment thread src/coreclr/vm/wasm/helpers.cpp
Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated
Comment thread src/coreclr/vm/wasm/helpers.cpp Outdated
Comment thread src/coreclr/vm/wasm/helpers.cpp
Comment thread src/coreclr/vm/wasm/helpers.cpp
@pavelsavara pavelsavara added the arch-wasm WebAssembly architecture label Jul 10, 2026
@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.

@AndyAyersMS

Copy link
Copy Markdown
Member

Locally I have these ai-supplied fixes on top of this. Think they were also called out above.

  1. Rebase glue for  InlinedCallFrame::UpdateRegDisplay_Impl  — adapts Add support for inline pinvokes to Wasm Ryujit #130384's  INLINED_PINVOKE_FROM_R2R  handling to main's current  InlinedCallFrame  field layout: uses  m_pCallerReturnAddress  (dac_cast to  TADDR ) instead of the PR's  m_CallerReturnAddress , and casts  m_pCallSiteSP  into a local.

  2. DEBUG  JIT_PInvokeEnd  fix — the debug variant is supposed to validate that R2R codegen kept  sp == __stack_pointer  across the call, but the naked asm was doing  global.set __stack_pointer  (resetting it, like Begin) and passing the wrong arg. Fixed to  global.get  so it reads the current global and passes it as arg2 for the  _ASSERTE(sp == stack_pointer_global_value)  check; also changed  JIT_PInvokeEndImpl  return type from  void*  to  void .

lewing added a commit to lewing/runtime that referenced this pull request Jul 13, 2026
David's dotnet#130384 draft was written against pre-dotnet#130363 main. Adapt to build:
- dac_cast<TADDR>(m_pCallSiteSP): m_pCallSiteSP is PTR_VOID, helpers take TADDR
- GetWasmFramePointerFromStackPointer is now 2-arg (sp, controlPC) on main (dotnet#130363),
  pass (PCODE)InterpreterIP
- (typo m_CallerReturnAddress -> m_pCallerReturnAddress fixed during cherry-pick resolve)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
lewing added a commit to lewing/runtime that referenced this pull request Jul 13, 2026
Rebaselines the WASI R2R prototype onto current main (67 commits, now includes
dotnet#130446 param-homing merged upstream 07-12). 4 trivial conflicts resolved in favor
of origin/main (jiteeversionguid.h GUID token; wasi PAL stubs/file/map comment+null-check
polish that landed via dotnet#130051 squash). dotnet#130446 de-duplicated cleanly (our cherry-pick
== main's merged change). Prototype-only delta preserved: dotnet#130384 (inline pinvokes,
still draft upstream), GAP1 (crossgen2 Program.cs +Wasi optimistic-ISA), static-compose
corerun glue + JIT-EE WasmWellKnownGlobalSymbol additions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
lewing added a commit to lewing/runtime that referenced this pull request Jul 13, 2026
…arity

Cherry-pick InitHelpers.cs from AndyAyersMS:next-blocker-spc — InitClass and
InitInstantiatedClass return void* (null) instead of void, so the compiled wasm
call_indirect signature matches the interp's value-returning P_ helper convention.
Fixes the class-init helper arity mismatch (Console.cctor trap) that the rebaselined
corelib-R2R composite hit at func 61854 after Gates 1+2 (dotnet#130384/dotnet#130446).

Prototype-only; for the future WASI R2R PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
lewing added a commit to lewing/runtime that referenced this pull request Jul 13, 2026
…tes #1,#3-#7)

Merges Andy's complete 'get hello world working' set on top of our branch (which
already had gate #2 InitHelpers). Adds:
 #1 CallEntryPoint: assembly.cpp RunMainInternal EnsurePortableEntryPointIsCallableFromR2R
 #3 disable wasm SIMD (compiler.cpp, InstructionSetHelpers.cs, codeman.cpp)
 #4 WasmBase LZC/TZC + PackedSimd NYI (hwintrinsic*.{cpp,h})
 #5 interp IsSupported fold (interpreter/compiler.cpp)
 #6 thread-static base FCall (Thread.CoreCLR.cs, comsynchronizable.*, ecalllist.h)
 #7 String-ctor PEP (prestub.cpp, wasm/helpers.cpp)
One conflict in wasm/helpers.cpp (dotnet#130384 overlap) resolved to Andy's canonical version.
NOTE: gate #3 disables SIMD — prototype exploration only, not a shippable path.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
davidwrighton and others added 3 commits July 20, 2026 14:39
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a4d21b59-7518-4932-99eb-6f229cb57a7b
Copilot AI review requested due to automatic review settings July 20, 2026 23:21

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 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

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

  • m_pCallerReturnAddress is being set to the magic value INLINED_PINVOKE_FROM_R2R (1). Other VM code assumes this field is a real code address (e.g., exception unwinding checks ExecutionManager::IsReadyToRunCode(m_pCallerReturnAddress) to decide whether to unlink the frame). With a sentinel value, unwinds will take the wrong path (or potentially probe an invalid PC on other configurations). Prefer storing the actual virtual IP derived from sp (and optionally the derived frame pointer) instead of a sentinel.
    ::new ((void*)pFrame) InlinedCallFrame();
    pFrame->m_pCallSiteSP          = sp;
    pFrame->m_pCallerReturnAddress = INLINED_PINVOKE_FROM_R2R; // When this is true, UpdateRegDisplay_Impl derives state from m_pCallSiteSP.
    pFrame->m_pCalleeSavedFP       = 0;
    pFrame->m_pThread              = pThread;

Comment thread src/coreclr/vm/wasm/helpers.cpp
Comment thread src/coreclr/vm/wasm/helpers.cpp
@davidwrighton
davidwrighton marked this pull request as ready for review July 21, 2026 17:48
@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.

@davidwrighton
davidwrighton merged commit af76c92 into dotnet:main Jul 21, 2026
127 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants