You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The experimental WASM JIT (clrjit_universal_wasm) cannot codegen GT_ASYNC_CONTINUATION. Every runtime-async method that retrieves a call''s continuation falls through to the codegen default case and asserts.
NYIRAW: ASYNC_CONTINUATION
default case in genCodeForTreeNode (codegenwasm.cpp)
Root cause
On register-based targets, GT_ASYNC_CONTINUATION reads the continuation object that a runtime-async call returns in a dedicated second return register, alongside the method''s normal result:
// codegencommon.cpp — compiled out for wasm via #if !TARGET_WASMvoidCodeGen::genCodeForAsyncContinuation(GenTree* tree)
{
inst_Mov(targetType, targetReg, REG_ASYNC_CONTINUATION_RET, /* canSkip */true);
genTransferRegGCState(targetReg, REG_ASYNC_CONTINUATION_RET);
genProduceReg(tree);
}
On WASM REG_ASYNC_CONTINUATION_RET == REG_NA (targetwasm.h:220) and genCodeForAsyncContinuation is excluded from the build, so codegenwasm.cpp has no handler and the node hits the default NYIRAW case.
Why this needs a design decision
The dedicated-register mechanism has no WASM analogue. Making GT_ASYNC_CONTINUATION work requires modeling how a runtime-async call surfaces both its normal result and the continuation object on WASM — most naturally a WASM multi-value return, but that is a runtime-async / WASM calling-convention design decision, not a mechanical codegen addition.
Impact
In an SPMI replay of the WASM altjit over libraries_tests_no_tiered_compilation + coreclr_tests, this accounts for ~2,005 asserting contexts (~1,870 libraries, ~135 coreclr) — the dominant oper reaching the codegen default case. Tracking for the WASM interop / runtime-async owners.
Note
This issue was authored with the assistance of GitHub Copilot.
Summary
The experimental WASM JIT (
clrjit_universal_wasm) cannot codegenGT_ASYNC_CONTINUATION. Every runtime-async method that retrieves a call''s continuation falls through to the codegen default case and asserts.Root cause
On register-based targets,
GT_ASYNC_CONTINUATIONreads the continuation object that a runtime-async call returns in a dedicated second return register, alongside the method''s normal result:On WASM
REG_ASYNC_CONTINUATION_RET == REG_NA(targetwasm.h:220) andgenCodeForAsyncContinuationis excluded from the build, socodegenwasm.cpphas no handler and the node hits the defaultNYIRAWcase.Why this needs a design decision
The dedicated-register mechanism has no WASM analogue. Making
GT_ASYNC_CONTINUATIONwork requires modeling how a runtime-async call surfaces both its normal result and the continuation object on WASM — most naturally a WASM multi-value return, but that is a runtime-async / WASM calling-convention design decision, not a mechanical codegen addition.Impact
In an SPMI replay of the WASM altjit over
libraries_tests_no_tiered_compilation+coreclr_tests, this accounts for ~2,005 asserting contexts (~1,870 libraries, ~135 coreclr) — the dominant oper reaching the codegen default case. Tracking for the WASM interop / runtime-async owners.Note
This issue was authored with the assistance of GitHub Copilot.