Implement TentativeMethodNode for WASM - #132814
Conversation
|
Azure Pipelines: 16 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR implements WebAssembly (Wasm) codegen support for TentativeMethodNode in the NativeAOT compiler pipeline, enabling emission of tentative method stubs and ensuring the Wasm object writer can register the correct function signatures and relocations.
Changes:
- Add Wasm instruction support for
unreachable,call, andreturn_call, plus helpers to emit them with function-index relocations. - Enable Wasm emission in
WasmEmitteroutside#if READYTORUN, and implement Wasm stub emission forTentativeMethodNode. - Update
TentativeMethodNodeto provide a type signature to the Wasm object writer, and add a unit test that validates emitted bytes + relocation behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs | Adds Wasm expr kinds and helpers to emit unreachable, call, and return_call with function-index relocations. |
| src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs | Removes #if READYTORUN gating so Wasm function bodies/relocs can be emitted in this compilation path. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeMethodNode.cs | Makes TentativeMethodNode provide a type signature (via IMethodCodeNodeWithTypeSignature) for Wasm signature registration. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmTentativeMethodNode.cs | Implements Wasm stub emission: forward args to real body (return_call) or call throw-helper then unreachable. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs | Implements WasmTypeNode(MethodDesc) using WasmLowering.GetSignature(...).FuncType so Wasm signatures can be registered. |
| src/coreclr/tools/aot/ILCompiler.Compiler.Tests/DependencyGraphTests.cs | Adds a focused unit test asserting Wasm encoding + relocation for tentative stubs. |
| { | ||
| #if READYTORUN | ||
| public WasmFunctionBody FunctionBody = null; | ||
| #endif | ||
|
|
There was a problem hiding this comment.
Updated FunctionBody to initialize with null! in ae1d521.
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
| if (ReferenceEquals(target, RealBody)) | ||
| { | ||
| // No throw helper is available, so forward all parameters and tail-call the real body. | ||
| int parameterCount = signature.Params.Types.Length; | ||
| expressions = new WasmExpr[parameterCount + 1]; | ||
| for (int i = 0; i < parameterCount; i++) | ||
| { | ||
| expressions[i] = Local.Get(i); | ||
| } | ||
| expressions[parameterCount] = ControlFlow.ReturnCall(target); | ||
| } |
There was a problem hiding this comment.
Whatever is generated in this codepath is never actually written into the output object file (we're generating a reloc to RealBody; doing that marks it and makes object emission of this node skipped):
I think it would be completely fine to always do the else branch, the WASM doesn't need to be valid here.
There was a problem hiding this comment.
Simplified WASM emission to always generate the minimal call relocation path in ae1d521.
| [Theory] | ||
| [InlineData(false)] | ||
| [InlineData(true)] | ||
| public void TentativeMethodNodeEmitsWasmCall(bool useRealBody) |
There was a problem hiding this comment.
This test is quite some slop forcing invariants that are not useful, I'd delete it.
There was a problem hiding this comment.
Deleted this test and its supporting test-only node in ae1d521.
| else | ||
| { | ||
| // The real body was removed, so call the throw helper with the shadow stack pointer. | ||
| Debug.Assert(!Method.IsUnmanagedCallersOnly); |
There was a problem hiding this comment.
If we really want to assert this, it should be done in the constructor so we get a useful stack pointing to the blame place. But I don't find it likely we could accidentally use this with UnmanagedCallersOnly methods, I don't see a world where they could be tentative (i.e. reloc to them is reachable, but they could be effectively unexecutable).
There was a problem hiding this comment.
Removed the unmanaged-caller assertion in ae1d521.
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
| End = 0x0B, | ||
| Call = 0x10, | ||
| CallIndirect = 0x11, | ||
| ReturnCall = 0x12, |
There was a problem hiding this comment.
This is dead code now. LGTM otherwise.
NativeAOT’s WASM backend could not emit tentative method stubs.
callplusunreachablefor throw helpers.return_callwhen forwarding to the real body.