Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints - #126901

Merged
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints
Apr 18, 2026
Merged

Adjust PortableEntryPoint logic to actually handle having Wasm R2R native entrypoints#126901
davidwrighton merged 18 commits into
dotnet:mainfrom
davidwrighton:fix_PortableEntryPoint_for_R2R_entrypoints

Conversation

@davidwrighton

@davidwrightondavidwrighton commented Apr 14, 2026

Copy link
Copy Markdown
Member
  • This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
  • Adjust PortableEntryPoint calling convention to match the WASM version
  • Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
  • Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
  • Update all of the FCDECL/FCIMPL macros to capture the stack correctly
  • Adjust the various FCalls which should capture a TransitionBlock to capture one from the callersStackPointer parameter to FCalls.
  • Implement correct signature mapping for PortableEntryPoints which are FCalls
  • Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
  • Put the callers frame pointer into the TransitionBlock. To do so, I've added a new m_StackPointer field to the TransitionBlock
  • Make the ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
  • Add m_StackPointer to TransitionBlock, and put the callers stack pointer in there.
  • Update helper calls in interpexec to setup the stack pointer argument correctly

Fixes#123437

…entrypoints
- This includes some initial work where there is a predefined set of new thunks generated into the coreclr codebase. I expect that we'll build some sort of hardcoded list here for invokes to/from R2R code, and then have R2R supplement the list with extra cases.
- Adjust PortableEntryPoint calling convention to match the WASM version
- Update PortableEntryPoint::HasNativeEntryPoint to indicate that the NativeEntryPoint is the intentional target
- Update the calls from R2R into interpreter to capture the stack argument into the TransitionBlock
- Implement correct signature mapping for PortableEntryPoints which are FCalls
- Update interp to managed helpers to pass a stack pointer which informs the stack walker to stop walking
- Put the callers frame pointer into the TransitionBlock. The current implementation drops it into the m_ReturnAddress field which is a bit dodgy, but we can fix this later when we actually work on the stack walker
- Make the ExecuteInterpretedMehtodWtihArgs_PortableEntryPoint_Complex function into functionally being the Prestub when called from R2R.
…inter in there.
- Update helper calls in interpexec to setup the stack pointer argument correctly
@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.

CopilotAI 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 CoreCLR’s WASM PortableEntryPoint and interpreter interop to support scenarios where R2R code calls through PortableEntryPoints that may ultimately target native entrypoints, including new thunk/signature handling and stack-walk termination plumbing.

Changes:

  • Extend signature generation and thunk tables to distinguish PortableEntryPoint calls (via a 'p' suffix) and to include InternalCall/FCall shapes.
  • Add/adjust WASM-side thunk implementations and runtime lookup/caching for R2R→interpreter and interpreter→native dispatch.
  • Update PortableEntryPoint state tracking (preferring interpreter vs native) and propagate a stack-walk termination/stack pointer through TransitionBlock and helper call paths.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pregenerated signatures; writes cache as UTF-8.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct _PE call thunks for signatures ending in 'p' (PortableEntryPoint context).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans for MethodImplAttributes.InternalCall and emits 'p'-suffixed signatures.
src/coreclr/vm/wasm/helpers.cppAdds hardcoded R2R→interpreter thunks, PortableEntryPoint thunk cache, and signature key support for 'p' suffix.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated interpreter→native thunk implementations for PortableEntryPoint calls (*_PE) and signature table entries.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint-aware interpreted execution path that can run prestub work and dispatch to compiled code.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag and accessors.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint/SetActualCode semantics around “prefer interpreter” state.
src/coreclr/vm/method.cppInitializes PortableEntryPoints with an optional R2R→interpreter thunk and marks them as preferring interpreter initially.
src/coreclr/vm/jithelpers.cppUpdates WASM helper wrappers to pass stack-walk termination/TransitionBlock info into _Impl variants.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod prototype for PortableEntryPoint prestub dispatch use.
src/coreclr/vm/interpexec.cppAdds macros/typedefs to pass PortableEntryPoint stack/context args through helper calls; adjusts PortableEntryPoint native-entrypoint gating.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use GC flags instead of a bool.
src/coreclr/vm/frames.hChanges GCFrame API from BOOL maybeInterior to UINT gcFlags and updates protection macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame behavior using gcFlags and asserts flag expectations.
src/coreclr/vm/fcall.hAdjusts WASM FCALL/HCALL signatures to include hidden stack/context parameters.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock for WASM exception context.
src/coreclr/vm/eetwain.cppEnsures WASM TransitionBlock has stack pointer set for funclet calls.
src/coreclr/vm/callingconvention.hAdds m_StackPointer overlay in WASM TransitionBlock.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates an internal FCALL-to-FCALL call site to pass the new WASM hidden parameters explicitly.

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/coreclr/vm/interpexec.cpp Outdated
…ng the address of an aligned local.
- Fix the stack arg passed to R2R functions to always be 16 byte aligned
- Fix missing Call_System_Private_CoreLib_System_Environment_CallEntryPoint_I32_I32_I32_I32_I32_RetVoid thunk
CopilotAI review requested due to automatic review settings April 14, 2026 23:32

CopilotAI 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 PortableEntryPoint calling convention and thunk/signature infrastructure to support ReadyToRun (R2R) native entrypoints while preserving correct interpreter dispatch and stack-walking behavior.

Changes:

  • Extends WASM signature generation to account for PortableEntryPoint context ('p') and InternalCall/FCall signature shapes.
  • Adds R2R-to-interpreter thunk support, including capturing the caller stack pointer into TransitionBlock and using it to terminate/limit stack walking.
  • Adjusts PortableEntryPoint state management and prestub-like behavior to correctly resolve interpreter vs native (R2R) targets.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this to signature mapping for instance methods.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csReplaces icall table generation with InternalCall signature collection and adds pregenerated signature shapes.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct call thunks for PortableEntryPoint calls (extra hidden params + stack-walk termination).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew scanner to collect InternalCall signatures for thunk generation.
src/coreclr/vm/wasm/helpers.cppAdds R2R→interpreter thunk table/cache and updates managed calli invocation to carry PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates reverse-thunk exports and signature naming adjustments.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk table to include PE-aware signatures and call patterns.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves like prestub when invoked from R2R.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag/accessors and updates PortableEntryPoint API surface.
src/coreclr/vm/precode_portable.cppUpdates native-entrypoint detection and allows “upgrade” from interpreter-preferred to actual code.
src/coreclr/vm/method.cppInitializes PortableEntryPoint with an R2R→interpreter thunk when available and sets interpreter-preferred state.
src/coreclr/vm/jithelpers.cppWASM FCALL wrappers now pass stack pointer / transition info to exception helpers.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod for prestub/R2R dispatch paths.
src/coreclr/vm/interpexec.cppAdjusts helper calling patterns and PortableEntryPoint selection logic; threads stack-pointer through transition blocks.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later in IL stub creation sequence.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to new ctor parameterization (gcFlags).
src/coreclr/vm/frames.hChanges GCFrame API from maybeInterior to gcFlags and updates GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame gcFlags handling and enforces interior-flag expectations.
src/coreclr/vm/fcall.hUpdates FCALL/HCALL macro signatures for WASM to include hidden stack/context args.
src/coreclr/vm/excep.cppPlumbs interpreter stack pointer from TransitionBlock into exception frame context.
src/coreclr/vm/eetwain.cppEnsures WASM transition blocks set stack pointer consistently for funclet calls.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock to carry m_StackPointer.
src/coreclr/vm/callhelpers.hAdds TERMINATE_R2R_STACK_WALK sentinel for WASM stack-walk termination.
src/coreclr/runtime/portable/AllocFast.cppUpdates a FCALL wrapper to supply explicit hidden args under new WASM calling convention.

Comment threadsrc/coreclr/vm/precode_portable.hpp Outdated
Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/method.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 14, 2026 23:41

CopilotAI 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 CoreCLR WASM PortableEntryPoint plumbing to support ReadyToRun (R2R) native entrypoints and correct calling conventions/signature handling across interpreter ↔ native transitions (including FCalls), with additional stack-walk/TransitionBlock support.

Changes:

  • Extend signature generation/mapping to support PortableEntryPoint context (p) and InternalCall (FCall) signatures; update thunk generation accordingly.
  • Add initial hardcoded R2R→interpreter PortableEntryPoint thunk set and associated lookup/caching paths; adjust prestub-style dispatch for PortableEntryPoint calls.
  • Update runtime structures/paths for WASM stack-walk termination and TransitionBlock stack pointer propagation; refactor GCFrame to use GC flag bitmasks.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdds optional inclusion of this in computed signatures.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection; adds pregenerated signature list.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates distinct PE thunks (extra hidden params + stack-walk sentinel) and maps ...p signatures.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector for InternalCall method signatures (for PE thunk generation).
src/coreclr/vm/wasm/helpers.cppAdds PE thunk table + lookup; appends p to default-callconv signature keys; updates managed calli cookie invocation shape; adds thunk lookup for R2R→interp.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppUpdates generated thunk implementations + table entries for ...p (PortableEntryPoint) signatures.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates generated reverse thunks and some signatures/entry mappings.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path that behaves prestub-like and can dispatch to R2R via InvokeManagedMethod.
src/coreclr/vm/precode_portable.hppAdds PrefersInterpreterEntryPoint flag API to PortableEntryPoint.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and SetActualCode behavior with PrefersInterpreterEntryPoint.
src/coreclr/vm/method.cppUses R2R→interp thunk when available and sets PrefersInterpreterEntryPoint on new PortableEntryPoints.
src/coreclr/vm/jithelpers.cppUpdates WASM IL_Throw/IL_Rethrow/IL_ThrowExact wrappers to incorporate TransitionBlock/stack pointer logic.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration for new prestub path usage.
src/coreclr/vm/interpexec.cppAdds helper-call wrappers for WASM portable-entrypoint calling convention; updates PortableEntryPoint/native-entrypoint selection logic.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock storage with a unioned stack pointer field.
src/coreclr/vm/callhelpers.hIntroduces TERMINATE_R2R_STACK_WALK sentinel for WASM stack walking.
src/coreclr/vm/frames.hUpdates GCFrame ctor signature (bool → flags) and adjusts GCPROTECT macros.
src/coreclr/vm/frames.cppImplements GCFrame flag-based scanning behavior.
src/coreclr/vm/gccover.cppUpdates GCFrame usage to pass GC flags.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint call later in IL stub creation.
src/coreclr/vm/fcall.hAdjusts FCALL/HCALL signature macros for TARGET_WASM to include hidden params.
src/coreclr/vm/excep.cppPlumbs TransitionBlock stack pointer into SoftwareExceptionFrame context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer for WASM funclet path.
src/coreclr/runtime/portable/AllocFast.cppUpdates RhpNewPtrArrayFast to match new WASM FCALL signature shape.

Comment threadsrc/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.cs Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/frames.cpp
Comment threadsrc/coreclr/vm/precode_portable.cpp Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/vm/callhelpers.h Outdated
Comment threadsrc/coreclr/vm/jithelpers.cpp Outdated
Comment threadsrc/coreclr/runtime/portable/AllocFast.cpp Outdated
…al signature and then its filled in later
- Add a comment about the work we need to do to handle R2R modules adding new thunks at runtime.
- Add contracts to Wasm thunk import
- Adjust initialization of the wasm thunks so that we don't need to have that logic be legal to run when in a NOTHROW region
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Outdated
CopilotAI review requested due to automatic review settings April 17, 2026 13:15

CopilotAI 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 CoreCLR WASM PortableEntryPoint / FCALL calling-convention plumbing to support scenarios where ReadyToRun (R2R) code has native entrypoints, including new/updated WASM thunk generation and TransitionBlock stack-pointer propagation.

Changes:

  • Extend managed→native thunk signature generation to support PortableEntryPoint (“…p”) signatures and collect InternalCall shapes from System.Private.CoreLib.
  • Add WASM-side thunk caches and interpreter dispatch paths to correctly pass PortableEntryPoint context and a stack-walk termination sentinel via TransitionBlock.
  • Update FCALL/HCALL/GCFrame/PortableEntryPoint infrastructure to carry stack pointer state and prefer interpreter entrypoints until native code is available.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAdd optional inclusion of this in signature encoding.
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitch to InternalCall signature collection; add pregenerated PE signatures; UTF-8 cache write.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerate distinct PE thunk entrypoints and signatures with PE suffix handling.
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew: scan CoreLib for InternalCall methods and emit PE thunk signatures.
src/coreclr/vm/wasm/helpers.hppNew: startup init hook for wasm thunk caches.
src/coreclr/vm/wasm/helpers.cppAdd PE thunk tables/caches; update calli cookie calling convention; init caches at startup.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdate reverse thunks/signatures to match new calling convention expectations.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdd “_PE” call thunks that pass PE context + stack-walk sentinel.
src/coreclr/vm/tailcallhelp.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/stubhelpers.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/runtimehandles.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/reflectioninvocation.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/prestub.cppAdd PortableEntryPoint “complex” interpreter entry path behaving like prestub for R2R.
src/coreclr/vm/precode_portable.hppAdd “prefers interpreter entrypoint” flag + APIs.
src/coreclr/vm/precode_portable.cppAdjust HasNativeEntryPoint logic; clear prefer-interpreter flag on upgrade.
src/coreclr/vm/portable/AllocSlow.cppConvert selected alloc helpers to FCIMPL + TransitionBlock-aware calling convention.
src/coreclr/vm/method.hppAdd MethodDesc helper to initialize PE initial state.
src/coreclr/vm/method.cppInitialize/reset PE based on available PE→interp thunk; default to prefer-interpreter.
src/coreclr/vm/marshalnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/managedmdimport.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/jithelpers.cppWASM: build TransitionBlock for throw helpers using callersStackPointer sentinel logic.
src/coreclr/vm/interpexec.hExpose InvokeManagedMethod for PortableEntryPoint prestub-like flow.
src/coreclr/vm/interpexec.cppUpdate helper-call sites to new calling convention; integrate prefer-interpreter logic.
src/coreclr/vm/ilstubcache.cppMove temporary entrypoint assignment after signature/flags setup.
src/coreclr/vm/gccover.cppUpdate GCFrame ctor usage to new gcFlags model.
src/coreclr/vm/frames.hReplace maybeInterior bool with gcFlags.
src/coreclr/vm/frames.cppImplement gcFlags-based scanning behavior for GCFrame.
src/coreclr/vm/fcall.hWASM: introduce wrapper/impl calling convention capture for callersStackPointer + PE context.
src/coreclr/vm/excep.cppUpdate TransitionBlock-derived interpreter context capture in exception frame.
src/coreclr/vm/eetwain.cppEnsure TransitionBlock stack pointer is initialized for WASM funclet calls.
src/coreclr/vm/ecall.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/dynamicmethod.cppAdjust contract mode + Reset ordering relative to signature/flags.
src/coreclr/vm/comutilnative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comsynchronizable.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/commodule.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdependenthandle.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/comdelegate.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/ceemain.cppWASM: initialize thunk caches during EEStartup.
src/coreclr/vm/callingconvention.hWASM: add m_StackPointer union member in TransitionBlock.
src/coreclr/vm/callhelpers.hWASM: add TERMINATE_R2R_STACK_WALK sentinel definition.
src/coreclr/vm/assemblynative.hppUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/vm/arraynative.hUpdate FCDECL macro usage style to accommodate new signatures.
src/coreclr/runtime/portable/WriteBarriers.cppConvert write barrier stubs to FCIMPL for new WASM convention.
src/coreclr/runtime/portable/AllocFast.cppAdd TransitionBlock-aware calling convention + helper macros; convert to FCIMPL.
src/coreclr/runtime/MiscNativeHelpers.hAdd PREPARE_TRANSITION_ARG helper for WASM/non-NativeAOT.

Comment threadsrc/coreclr/vm/fcall.h
Comment threadsrc/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
Comment threadsrc/coreclr/vm/callingconvention.h
Comment threadsrc/coreclr/vm/frames.h
Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/vm/wasm/helpers.cpp Outdated
@radekdoulik

Copy link
Copy Markdown
Member

I tried to run priority1 runtime tests and I see few failures. I will need to rerun it on main too, to see if it is introduced here or whether we regressed on main meanwhile. Doesn't need to block this PR though, we can fix it in a follow up PR. Just want to let you know.

Note for me: I should enable priority1 tests in the outer loop.

@radekdoulikradekdoulik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

CopilotAI review requested due to automatic review settings April 18, 2026 14:15
@davidwrighton
davidwrighton enabled auto-merge (squash) April 18, 2026 14:16

CopilotAI 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 CoreCLR WASM portable entry point and FCall calling convention plumbing to support R2R/native entrypoints, including stack-pointer capture/propagation needed for correct transition handling and future stack walking on WASM. It also extends the WASM app builder codegen to generate (and pre-seed) additional thunk signatures, including InternalCall-driven portable entry point thunks.

Changes:

  • Extend WASM thunk/signature generation to include InternalCall portable-entry-point shapes and pre-generated common signatures.
  • Add WASM runtime support for portable-entry-point → interpreter thunks, thunk caches, and updated calli cookie invocation.
  • Update portable entry point state/flags and transition block handling to carry a stack pointer, plus broad FCDECL/FCIMPL macro/call-site adjustments for the WASM ABI.

Reviewed changes

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

Show a summary per file
FileDescription
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.csAllows optional inclusion of this in generated signatures (used for InternalCall scanning).
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.csSwitches from icall table generation to InternalCall signature collection + pre-generated PE signatures.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.csGenerates separate thunk entrypoints for portable entry point calls (extra hidden context + frame-pointer arg).
src/tasks/WasmAppBuilder/coreclr/InternalCallSignatureCollector.csNew collector that scans System.Private.CoreLib InternalCalls and emits PE signatures.
src/coreclr/vm/wasm/helpers.hppDeclares InitializeWasmThunkCaches for explicit EEStartup initialization.
src/coreclr/vm/wasm/helpers.cppAdds PE→interpreter thunk table/caches, updates thunk lookup/init, and adjusts calli invocation to pass PE context.
src/coreclr/vm/wasm/callhelpers-reverse.cppUpdates/renames some reverse thunks and signatures to align with updated calling convention shapes.
src/coreclr/vm/wasm/callhelpers-interp-to-managed.cppAdds PE-specific thunk entrypoints (extra frame-pointer + PE context) and updates thunk map keys.
src/coreclr/vm/tailcallhelp.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/stubhelpers.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/runtimehandles.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/reflectioninvocation.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/prestub.cppAdds PortableEntryPoint “complex” path to act like prestub for R2R vs interpreter dispatch on WASM.
src/coreclr/vm/precode_portable.hppAdds “prefers interpreter entry point” flag and API surface.
src/coreclr/vm/precode_portable.cppUpdates HasNativeEntryPoint semantics and clears the “prefer interpreter” flag on code upgrade.
src/coreclr/vm/portable/AllocSlow.cppUpdates allocator FCALLs to capture/pass a transition block under the new WASM calling convention.
src/coreclr/vm/method.hppAdds helper to initialize portable entry point state based on method characteristics.
src/coreclr/vm/method.cppInitializes portable entry points with optional PE→interp thunk and sets initial “prefer interpreter” state.
src/coreclr/vm/marshalnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/managedmdimport.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/jithelpers.cppAdjusts WASM FCALL wrappers to provide TransitionBlock context based on callers’ stack pointer sentinel.
src/coreclr/vm/interpexec.hExposes InvokeManagedMethod declaration needed by new prestub-like PE path.
src/coreclr/vm/interpexec.cppUpdates helper call patterns for PE ABI (frame-pointer + hidden args) and PE/native-entrypoint preference logic.
src/coreclr/vm/ilstubcache.cppMoves SetTemporaryEntryPoint later to ensure dynamic method state is initialized first.
src/coreclr/vm/gccover.cppUpdates GCFrame construction to use flag-based interior tracking.
src/coreclr/vm/frames.hChanges GCFrame ctor signature (flags instead of bool) and updates GCPROTECT macros accordingly.
src/coreclr/vm/frames.cppImplements GCFrame flag storage/scanning semantics and asserts correct interior-flag usage.
src/coreclr/vm/fcall.hAdds WASM FCALL ABI support (hidden callersStackPointer + PE context) and wrapper generation macros.
src/coreclr/vm/excep.cppRecords interpreter stack pointer from TransitionBlock into exception context on WASM.
src/coreclr/vm/eetwain.cppInitializes TransitionBlock stack pointer in WASM funclet path.
src/coreclr/vm/ecall.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/dynamicmethod.cppAdjusts contract mode and reorders Reset() to occur after signature/flags are set (WASM needs signature inspection).
src/coreclr/vm/comutilnative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comsynchronizable.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/commodule.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdependenthandle.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/comdelegate.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/ceemain.cppCalls InitializeWasmThunkCaches() during EE startup on WASM.
src/coreclr/vm/callingconvention.hExtends WASM TransitionBlock layout to carry a stack pointer (union overlay).
src/coreclr/vm/callhelpers.hAdds WASM sentinel TERMINATE_R2R_STACK_WALK for stack-walk termination.
src/coreclr/vm/assemblynative.hppConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/vm/arraynative.hConverts FCDECL usage to new macro placement pattern for static members.
src/coreclr/runtime/portable/WriteBarriers.cppWraps portable write barrier stubs in FCIMPL for updated FCALL handling.
src/coreclr/runtime/portable/AllocFast.cppUpdates fast alloc helpers to prepare/pass transition args (TransitionBlock) under the WASM ABI.
src/coreclr/runtime/MiscNativeHelpers.hAdds WASM helper macros for preparing/passing TransitionBlock based on callersStackPointer sentinel.

Comment threadsrc/coreclr/runtime/MiscNativeHelpers.h
@davidwrighton
davidwrighton merged commit 3bcab26 into dotnet:mainApr 18, 2026
131 of 134 checks passed
@pavelsavara

pavelsavara commented Apr 20, 2026

Copy link
Copy Markdown
Member

This breaks CI ☹️ (it's in-tree coreCLR)

Log

D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:22:5: error: unknown type name 'NOINLINE'
22 | NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:24:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:29:5: error: unknown type name 'NOINLINE'
29 | NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:31:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
31 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:36:5: error: unknown type name 'NOINLINE'
36 | NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext)
| ^
D:\a\_work\1\s\artifacts\obj\mono\Wasm.BrowserLogProfile.Sample\browser.wasm.Release\wasm\for-build\wasm_m2n_invoke.g.cpp:38:40: error: use of undeclared identifier 'TERMINATE_R2R_STACK_WALK'
38 | alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
| ^

@radekdoulik

Copy link
Copy Markdown
Member

Indeed, it was masked by known build issue

#127177 should fix it

radekdoulik added a commit that referenced this pull request Apr 21, 2026
This should fix CI build and relinking, introduced in
#126901 and masked by
#90458 in build analysis
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 21, 2026
@pavelsavarapavelsavara added the arch-wasm WebAssembly architecture label Jun 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][coreclr] Make fcalls follow the new calling convention

5 participants

@davidwrighton@radekdoulik@pavelsavara@jkotas