Skip to content

[Wasm RyuJIT] Wire up GC info encoding/decoding for Wasm#126932

Open
kg wants to merge 16 commits intodotnet:mainfrom
kg:wasm-gcinfo-1
Open

[Wasm RyuJIT] Wire up GC info encoding/decoding for Wasm#126932
kg wants to merge 16 commits intodotnet:mainfrom
kg:wasm-gcinfo-1

Conversation

@kg
Copy link
Copy Markdown
Member

@kg kg commented Apr 15, 2026

This set of changes is sufficient to R2R release S.P.CoreLib like before but with gc info encoding wired up and working. Still figuring out how to clean some of it up, feedback welcome.

@kg kg added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Apr 15, 2026
Copilot AI review requested due to automatic review settings April 15, 2026 03:04
@kg kg added NO-REVIEW Experimental/testing PR, do NOT review it arch-wasm WebAssembly architecture labels Apr 15, 2026
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 15, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

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

Copy link
Copy Markdown
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

This PR enables GC info encoding/decoding support for the CoreCLR WASM RyuJIT backend by turning on GCInfo generation, adding the necessary encoder/decoder sources to the WASM JIT build, and introducing a WASM-specific GC info encoding definition.

Changes:

  • Enable EMIT_GENERATE_GCINFO for WASM and wire up CodeGen::genCreateAndStoreGCInfo to use GcInfoEncoder.
  • Add/adjust conditional compilation to skip register-GC-tracking paths on WASM while still enabling GC info generation.
  • Update CMake wiring to link WASM standalone JITs against the appropriate gcinfo_* library and add a universal wasm gcinfo target.

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/jit/targetwasm.h Enables GC info generation for WASM (but comment needs updating).
src/coreclr/jit/gcinfo.cpp Disables register pointer marking path for WASM.
src/coreclr/jit/gcencode.cpp Disables register-state-change recording for WASM.
src/coreclr/jit/emit.cpp Disables register-GC live update emission for WASM.
src/coreclr/jit/codegenwasm.cpp Implements GCInfo creation/emission via GcInfoEncoder for WASM.
src/coreclr/jit/codegenlinear.cpp Skips GC register update/debug validation paths for WASM.
src/coreclr/jit/codegencommon.cpp Skips register-based GC liveness updates/validation for WASM.
src/coreclr/jit/CMakeLists.txt Ensures standalone JIT links a gcinfo lib and builds gcencode/gcdecode for WASM JIT.
src/coreclr/inc/gcinfotypes.h Adds Wasm32GcInfoEncoding and sets it as the WASM target encoding.
src/coreclr/gcinfo/CMakeLists.txt Adds gcinfo_universal_wasm target (currently under the wrong build condition for the failing scenario).

Comment thread src/coreclr/gcinfo/CMakeLists.txt
Comment thread src/coreclr/jit/targetwasm.h Outdated
@kg
Copy link
Copy Markdown
Member Author

kg commented Apr 16, 2026

Latest problem: with

--singlemethodtypename:"System.AppContext"
--singlemethodname:"OnUnhandledException"
--singlemethodindex:2

We call genEmitUnwindDebugGCandEH multiple times on some methods, and the second call attempts to overwrite existing debug information and (rightly, as far as I can tell) fails. I can't figure out why we're doing this, maybe something to do with funclets?

Copy link
Copy Markdown
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

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

Comment thread src/coreclr/jit/gcencode.cpp Outdated
Comment thread src/coreclr/jit/CMakeLists.txt
@kg
Copy link
Copy Markdown
Member Author

kg commented Apr 17, 2026

Latest problem: with

--singlemethodtypename:"System.AppContext"
--singlemethodname:"OnUnhandledException"
--singlemethodindex:2

We call genEmitUnwindDebugGCandEH multiple times on some methods, and the second call attempts to overwrite existing debug information and (rightly, as far as I can tell) fails. I can't figure out why we're doing this, maybe something to do with funclets?

This was intentional behavior - we were failing the compilation of a method as R2R unsupported late enough in compilation that debug info had already been generated, then hit an assertion the second time we tried to generate debug info (on the retried compilation). I think the asserts are just wrong in this case.

Now failing with block(s) missing a bbEmitCookie in particular methods, i.e.:

--singlemethodtypename:"System.GC"
--singlemethodname:"RunFinalizers"
--singlemethodindex:1
*************** In genSetScopeInfo()
VarLocInfo count is 7
; Variable debug info: 7 live ranges, 4 vars for method System.GC:RunFinalizers():uint
(V00 SP) : From 00000000h to 0000000Ah, in $1
(V01 arg0) : From 0000006Ah to 00000152h, in '[0] (1 slot)
(V01 arg0) : From 00000178h to 000001ECh, in '[0] (1 slot)
(V02 loc1) : From 00000074h to 0000014Ah, in '[56] (1 slot)
(V02 loc1) : From 00000150h to 00000159h, in '[56] (1 slot)
(V02 loc1) : From 00000178h to 000001ECh, in '[56] (1 slot)
(V04 loc3) : From 000000DEh to 000000F2h, in $2
*************** In gcInfoBlockHdrSave()
Set code length to 493.
Set stack base register to NA.
Stack slot id for offset 52 (0x34) (frame) (untracked) = 0.
Z:\runtime\src\coreclr\jit\jiteh.cpp:1120
Assertion failed 'cookie != nullptr' in 'System.GC:RunFinalizers():uint' during 'Emit GC+EH tables' (IL size 81; hash 0x81ce67df; FullOpts)

Copilot AI review requested due to automatic review settings April 17, 2026 01:21
Copy link
Copy Markdown
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

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

Comment thread src/coreclr/jit/codegenlinear.cpp Outdated
@kg kg removed NO-REVIEW Experimental/testing PR, do NOT review it NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) labels Apr 17, 2026
Copilot AI review requested due to automatic review settings April 17, 2026 01:51
@kg kg force-pushed the wasm-gcinfo-1 branch from 5ba8436 to 02ce8d6 Compare April 17, 2026 01:56
Copy link
Copy Markdown
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

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

Comment thread src/coreclr/jit/gcencode.cpp
Copilot AI review requested due to automatic review settings April 20, 2026 23:01
Copy link
Copy Markdown
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

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

Comments suppressed due to low confidence (1)

src/coreclr/jit/codegencommon.cpp:1081

  • This TARGET_WASM guard skips all handling of locals going live in registers. If GC-tracked locals can be assigned to Wasm locals (lvIsInReg()==true), they will bypass both the register path and the stack path here, so their liveness may never be reflected in GC info. Either ensure GC refs are never enregistered for Wasm, or add a Wasm-specific strategy to report/enforce where GC refs live at safe points (stack home or encoded register slots).
        if (varDsc->lvIsInReg())
        {
#ifndef TARGET_WASM
            // If this variable is going live in a register, it is no longer live on the stack,
            // unless it is an EH/"spill at single-def" var, which always remains live on the stack.
            if (!varDsc->IsAlwaysAliveInMemory())
            {

Comment thread src/coreclr/inc/gcinfotypes.h
Comment thread src/coreclr/jit/codegencommon.cpp
@AndyAyersMS
Copy link
Copy Markdown
Member

What was happening is we'd flag this (V01) as not enregisterable, even though it's coming in as a register, and then stuff would break down the road.

If that should work somehow I'll keep looking into it

If we don't enregister a GC param then we need to add code to the prolog (or just aftert it) to spill the param to the proper stack slot. That should happen in genHomeRegisterParamsOutsideProlog, which looks like it already knows some params need to be spilled.

@kg kg marked this pull request as draft May 1, 2026 03:10
Copilot AI review requested due to automatic review settings May 1, 2026 04:22
@kg
Copy link
Copy Markdown
Member Author

kg commented May 1, 2026

What was happening is we'd flag this (V01) as not enregisterable, even though it's coming in as a register, and then stuff would break down the road.
If that should work somehow I'll keep looking into it

If we don't enregister a GC param then we need to add code to the prolog (or just aftert it) to spill the param to the proper stack slot. That should happen in genHomeRegisterParamsOutsideProlog, which looks like it already knows some params need to be spilled.

OK, I managed to fix this so that we can disable enregistration for all GC values including parameters and temps. I had to collect references for orphan GT_NULLCHECKs left behind by dead block stores, because the block store was turning the address into a multiply-used temp and nothing was left to collect it.

Next I need to generate the spills in the right places around calls. Do you have thoughts on where/how I should do that? Do I want to do it in lowering?

Copy link
Copy Markdown
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

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

@kg
Copy link
Copy Markdown
Member Author

kg commented May 1, 2026

After discussion with Andy we won't do spilling of temps in this PR because it's too complex, we'll do that in a follow-up PR.

@kg kg marked this pull request as ready for review May 1, 2026 18:45
Copilot AI review requested due to automatic review settings May 1, 2026 18:45
Copy link
Copy Markdown
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

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

Comment thread src/coreclr/jit/codegencommon.cpp Outdated
Comment thread src/coreclr/jit/compiler.cpp
Copy link
Copy Markdown
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.

LGTM

kg added 16 commits May 2, 2026 05:30
Checkpoint

Checkpoint

Comment out some overly sensitive asserts that can be hit when things are working as designed

Funclet start blocks need labels on Wasm for some reason.

Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Cleanup

jit-format

Compile the gc info decoder too, since we'll need it

Add comment
…lready enregistered implicitly due to being params; add todo comment
…K nodes with multiply-used operands we need to collect
@kg kg force-pushed the wasm-gcinfo-1 branch from 9744410 to d8f5f9f Compare May 2, 2026 12:30
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.

4 participants