Skip to content

[Wasm RyuJIT] Insert r2r ind cell at the end of the args list instead of after 'this'#125669

Merged
kg merged 1 commit intodotnet:mainfrom
kg:wasm-callsigs-3
Mar 19, 2026
Merged

[Wasm RyuJIT] Insert r2r ind cell at the end of the args list instead of after 'this'#125669
kg merged 1 commit intodotnet:mainfrom
kg:wasm-callsigs-3

Conversation

@kg
Copy link
Member

@kg kg commented Mar 17, 2026

Without this change, the generated arglist for a ftn call looks like (sp) (indcell) (arg0) (arg1) ... when what we want is (sp) (arg0) (arg1) (indcell).

With this it's possible to evaluate a recursive fibonacci as long as you prime the heap with the right ftn ptr, i.e.

    // note: 3rd method in the assembly, so i use the ftn ptr '2' below
    [MethodImpl(MethodImplOptions.NoInlining)]
    public static int fib (int n) {
        return (n < 2) 
            ? n 
            : fib(n - 1) + fib(n - 2);
    }
> dotnet run wasm-ryujit-runner.cs -- --auto-build --config Debug --checkout Z:\runtime --assembly Z:\wasm-test\bin\Debug\net10.0\wasm-test.dll --js-expr "HEAPU32[0] = 2, exports.wasm_test_Program__fib(stackPointer.value, 31, 0)

...

running 'HEAPU32[0] = 2, exports.wasm_test_Program__fib(stackPointer.value, 31, 0)...
result was 1346269

For this test I have to write the ftn ptr 2 at offset 0 in the heap because morph generates indcells that turn into i32.const 0 for some reason I've yet to identify. We can fix that later.

Copilot AI review requested due to automatic review settings March 17, 2026 18:56
@kg kg added arch-wasm WebAssembly architecture area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Mar 17, 2026
@kg
Copy link
Member Author

kg commented Mar 17, 2026

The LIR for a call in fib looks like this with my fix:

Generating: N007 (  1,  1) [000023] -----+-----                   t23 =    PHYSREG   int    $0
IN0010:             local.get 0
Generating: N008 (  1,  1) [000010] -----+-----                   t10 =    LCL_VAR   int    V01 arg0         u:1 $1 (last use) $81
IN0011:             local.get 1
Generating: N009 (  1,  2) [000011] -----+-----                   t11 =    CNS_INT   int    -2 $44
IN0012:             i32.const -2
                                                                        /--*  t10    int    
                                                                        +--*  t11    int    
Generating: N010 (  3,  4) [000012] -----+-----                   t12 = *  ADD       int    $102
Debug: Closing V01 debug range.
							Live vars after [000010]: {V00 V01} -{V01} => {V00}
IN0013:             i32.add
Generating: N011 (  1, 11) [000022] H----+-----                   t22 =    CNS_INT(h) int    0x420078 ftn $140
IN0014:             i32.const 0
Generating: N001 (  1, 11) [000028] H----------                   t28 =    CNS_INT(h) int    0x420078 ftn
IN0015:             i32.const 0
                                                                        /--*  t28    int    
Generating: N002 (  4, 13) [000029] n---G------                   t29 = *  IND       int   
IN0016:             i32.load 0 0
                                                                        /--*  t23    int    wasm sp $0
                                                                        +--*  t12    int    arg1 $1
                                                                        +--*  t22    int    r2r cell $2
                                                                        +--*  t29    int    control expr
Generating: N012 ( 19, 21) [000013] --CXG+-----                   t13 = *  CALL r2r_ind int    Program:fib(int):int $83
IN0017:             call_indirect 4611686018431713408 0      ;; Program:fib(int):int

@kg
Copy link
Member Author

kg commented Mar 17, 2026

cc @AndyAyersMS @SingleAccretion Not sure this is the right way to go about the fix.

@dotnet-policy-service
Copy link
Contributor

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adjusts CoreCLR JIT call-argument construction for WASM ReadyToRun indirect calls so the R2R indirection cell argument is appended at the end of the argument list (matching the expected LIR evaluation/stack order for the WASM backend).

Changes:

  • For TARGET_WASM, append the WellKnownArg::R2RIndirectionCell argument via PushBack instead of inserting it after this/first arg.
  • Keep existing behavior for non-WASM targets (still uses InsertAfterThisOrFirst).
  • Clarify the FEATURE_READYTORUN #endif comment in this area.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

@SingleAccretion SingleAccretion left a comment

Choose a reason for hiding this comment

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

Approach LGTM.

@kg
Copy link
Member Author

kg commented Mar 17, 2026

The indcell always being 0 is likely due to this:

if (icon->ImmedValNeedsReloc(m_compiler))
{
// WASM-TODO: Generate reloc for this handle
ins = INS_I_const;
bits = 0;

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

Let's take this and work on the broader change separately.

@kg
Copy link
Member Author

kg commented Mar 19, 2026

/ba-g wasm only change, red lanes are known failures with tracking issues

@kg kg merged commit 12cdada into dotnet:main Mar 19, 2026
137 of 141 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants