[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11
, '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

[Wasm RyuJit] Control flow codegen - #121973

Merged
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics
Dec 4, 2025
Merged

[Wasm RyuJit] Control flow codegen#121973
AndyAyersMS merged 16 commits into
dotnet:mainfrom
AndyAyersMS:WasmEmitControlFlowBasics

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

Emit plausible Wasm control flow for blocks during genCodeForBBList.

Also add a bit of support for relop codegen, so blocks ending in branches have something to use.

Contributes to #121178.

Emit plausible Wasm control flow for blocks during `genCodeForBBList`.
Also add a bit of support for relop codegen, so blocks ending in
branches have something to use.
Contributes to dotnet#121178.
CopilotAI review requested due to automatic review settings November 25, 2025 23:45
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 25, 2025

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 implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.

Key changes include:

  • Addition of Wasm control flow and relational operation instructions to the instruction table
  • Movement of WasmInterval class from fgwasm.cpp to fgwasm.h for use during code generation
  • Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
  • Implementation of control flow instruction emission in genCodeForBBlist, including block/loop/end nesting and branch depth calculation
  • Basic GT_GT (greater than) relational operator codegen support

Reviewed changes

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

Show a summary per file
FileDescription
instrswasm.hAdds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types)
fgwasm.hMoves WasmInterval class definition from .cpp to header for codegen access
fgwasm.cppMoves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code
jitconfigvalues.hRemoves JitWasmControlFlow debug config option (now enabled for TARGET_WASM)
compiler.hAdds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen
compiler.cppMoves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline
lowerwasm.cppImplements LowerJTrue to defer branch handling to codegen instead of using NYI
emitwasm.hAdds code_t typedef for instruction opcodes
emitwasm.cppImplements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics
emitjmps.hDefines Wasm jump kinds: br, br_if, br_table
codegenwasm.cppImplements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching
codegen.hAdds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter
codegenlinear.cppAdds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation
CMakeLists.txtMoves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources

Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/fgwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @dotnet/jit-contrib @SingleAccretion

This won't get much testing in CI... locally it lets us get a simple method like

intFoo(inta,intb){if(a>b)returnb;returna;}

through more of codegen. Prolog gen stubbed out for now.

=============== Generating BB01 [0000] [000..004) -> BB02(0.5),BB03(0.5) (cond), preds={} succs={BB03,BB02} flags=0x00000000.00000011: i LIR
BB01 IN (2)={V00 V01}
OUT(2)={V00 V01}
Change life 0000000000000000 {} -> 0000000000000003 {V00 V01}
Debug: New V00 debug range: first
Debug: New V01 debug range: first
L_M10749_BB01:
Mapped BB01 to G_M10749_IG02
IN0001: block
Scope info: begin block BB01, IL range [000..004)
Added IP mapping: 0x0000 STACK_EMPTY (G_M10749_IG02,ins#1,ofs#1) label
Generating: [000008] ----------- IL_OFFSET void INLRT @ 0x000[E--]
Generating: N001 ( 1, 1) [000000] -----+----- t0 = LCL_VAR int V00 arg0 u:1 $80
IN0002: i32.load 1 4
Generating: N002 ( 1, 1) [000001] -----+----- t1 = LCL_VAR int V01 arg1 u:1 $81
IN0003: i32.load 1 0
/--* t0 int +--* t1 int Generating: N003 ( 3, 3) [000002] J----+-N--- t2 = * GT int IN0004: i32.gt_s
/--* t2 int Generating: N004 ( 5, 5) [000003] -----+----- * JTRUE void $VN.Void
IN0005: br_if 0
...

Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc.

@am11am11 added the arch-wasm WebAssembly architecture label Nov 26, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

With the latest commit, we can alt-jit methods that just return. Lots of stuff still incomplete, but we have a lot we can fill in now.

image

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.h Outdated
Comment threadsrc/coreclr/jit/instrswasm.h
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
Comment threadsrc/coreclr/jit/lowerwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog.

Please take another look.

@SingleAccretionSingleAccretion 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.

Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.

Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegen.h Outdated
Comment threadsrc/coreclr/jit/codegenlinear.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
Comment threadsrc/coreclr/jit/instrswasm.h Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@SingleAccretion thanks again, pushed another update

@SingleAccretionSingleAccretion 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.

LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.

Comment threadsrc/coreclr/jit/emitwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@dotnet/jit-contrib ping

Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/lowerwasm.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenlinear.cpp
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
Comment threadsrc/coreclr/jit/codegenwasm.cpp Outdated
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch now using a common genEmitEndBlock.
@adamperlin any other notes you want to add?

Comment threadsrc/coreclr/jit/codegen.h Outdated

@jakobbotschjakobbotsch 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.

Looks great to me now.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Not easy to get Roslyn to emit an actual switch, but here's an example of one making it to codegen (requires some fixes/workarounds not in this PR)

image

@adamperlinadamperlin 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.

This looks good to me! I don't have any notes I wanted to add at the moment!

@AndyAyersMS
AndyAyersMS merged commit 75eb218 into dotnet:mainDec 4, 2025
117 of 123 checks passed
@AndyAyersMSAndyAyersMS mentioned this pull request Dec 4, 2025
12 tasks
agocke added a commit that referenced this pull request Dec 5, 2025
#122171)
HostActivation tests are hitting the 5-minute hang dump timeout on OSX
CI despite making steady progress. Tests complete in ~2 minutes locally
but CI environments run 2x slower.
**Changes:**
- Increased `--hangdump-timeout` from `5m` to `8m` in
`src/installer/tests/Directory.Build.props`
This provides adequate headroom for slower CI machines while still
catching actual hangs.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
> > ----
> > *This section details on the original issue you should resolve*
> > <issue_title>Host Activation test failures on OSX</issue_title>
> <issue_description>## Build Information
> Build:
https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628
> Build error leg or test failing:
HostActivation.Tests.WorkItemExecution
> Pull request: #121973
> <!-- Error message template -->
> ## Error Message
> > Fill the error message using [step by step known issues
guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
> > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern
for regex matches (single line/no backtracking). Set BuildRetry to
`true` to retry builds with this error. Set ExcludeConsoleLog to `true`
to skip helix logs analysis. -->
> > ```json
> {
> "ErrorMessage": "Hang dump timeout of '00:05:00' expired",
> "ErrorPattern": "",
> "BuildRetry": false,
> "ExcludeConsoleLog": false
> }
> ```
> > > <!-- Known issue validation start -->
> ### Known issue validation
> **Build: :mag_right:**
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628
> **Error message validated:** `[Hang dump timeout of '00:05:00'
expired`]
> **Result validation:** :white_check_mark: Known issue matched with the
provided build.
> **Validation performed at:** 12/4/2025 3:07:33 AM UTC
> <!-- Known issue validation end -->
> <!--Known issue error report start -->
> > ### Report
> > |Build|Definition|Test|Pull Request|
> |---|---|---|---|
>
|[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136|
>
|[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148|
>
|[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125|
>
|[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168|
>
|[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163|
>
|[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973|
> #### Summary
> |24-Hour Hit Count|7-Day Hit Count|1-Month Count|
> |---|---|---|
> |6|6|6|
> <!--Known issue error report end --></issue_description>
> > ## Comments on the Issue (you are @copilot in this section)
> > <comments>
> <comment_new><author>@agocke</author><body>
> My PR almost certainly broke this, but I'm not sure how
yet</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Actually, I'm not sure I "broke" this in a real sense -- right now the
hang dump timeout is kicking in at the 5m mark. But the log shows a
steady stream of tests passing all the way up to the 5m mark.
> > I wonder if this is just that the tests are taking longer than 5m to
finish and the hang dump timeout is measuring from the start of the test
run.</body></comment_new>
> <comment_new><author>@agocke</author><body>
> Yeah my uncontended M2 Mac takes 2 min to run the tests, I could
easily believe CI is twice as slow. I think we should bump this to ten
minutes.</body></comment_new>
> </comments>
> </details>
- Fixes#122169
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
adamperlin added a commit that referenced this pull request Dec 8, 2025
This is the first prototype of a Wasm object writer for crossgen that
*only* writes out method bodies. It builds the minimum module structure
which is needed to declare and export the module bodies so that the
resulting module can be loaded and method bodies can be called by an
external loader. I have tested the output with a simple JavaScript
loader that instantiates the module and calls one of the exports.
# What IS handled
Emitting simple method bodies from an assembly that have no relocations
or external dependencies of any kind.
# What is NOT handled
## Relocations and any metadata attached to compiled methods.
## R2R format envelope (the plan is to embed this in the data section in
a future PR)
R2R metadata is currently unused.
## Signature generation to meet ABI requirements
Right now, there is a single `i32 -> i32` signature which is used as a
placeholder for any method. Later work will need to build support for
generating and storing wasm-level type signatures for JIT compiled
methods.
## JIT Integration
Currently, the JIT is not called (I believe it will hit asserts on the
Wasm target until #121973 is in). Instead, a simple `(i32.const 0)
(return)` stub is emitted for any JIT calls.
---------
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR 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.

7 participants

@AndyAyersMS@kg@jakobbotsch@adamperlin@SingleAccretion@am11