Skip to content

[wasm] Encode struct alignment in thunk signatures - #132248

Merged
davidwrighton merged 4 commits into
dotnet:mainfrom
davidwrighton:fix-wasm-struct-alignment
Aug 15, 2026
Merged

[wasm] Encode struct alignment in thunk signatures#132248
davidwrighton merged 4 commits into
dotnet:mainfrom
davidwrighton:fix-wasm-struct-alignment

Conversation

@davidwrighton

@davidwrighton davidwrighton commented Aug 12, 2026

Copy link
Copy Markdown
Member

Supports structs passed by value with 16 byte alignment on Wasm

  • Consolidate on using the alignment calculation in the jit interface to determine the alignment requirement for parameters in function calls
  • Detect the difference between structures aligned to 8 byte boundaries and 16 byte boundaries in transition thunks
  • Add a new encoding for pass by value structures with 16 byte alignment (A instead of S)
  • Add tests to validate this. Not just on the crossgen side but also a targeted Wasm R2R test.

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

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

Copilot-Session: b1af492e-7431-46af-b519-dcc504b62300
Copilot AI lite review requested due to automatic review settings August 12, 2026 23:24
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI 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

Updates the Wasm thunk signature-string encoding to preserve by-reference struct alignment requirements (notably 16-byte alignment) so that signature raising and transition-block layout remain correct when two same-sized structs differ in alignment.

Changes:

  • Extends struct tokens from S<N> to optionally include alignment for parameters: S!<N>:<A> (while keeping struct returns as S<N>).
  • Threads alignment through signature generation/parsing paths (runtime, WasmAppBuilder thunk generator, and crossgen2 tooling) and updates caching to disambiguate same-sized structs by (size, alignment) when needed.
  • Adds ReadyToRun tests and updates design documentation for the extended encoding.

Reviewed changes

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

Show a summary per file
File Description
src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs Adds parsing/formatting support for alignment-qualified struct tokens and exposes helpers to extract size/alignment.
src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs Aligns interpreter-stack slot offsets for indirect struct args when token alignment exceeds 8, and normalizes struct-return typedef naming.
src/coreclr/vm/wasm/helpers.cpp Encodes parameter struct alignment into thunk signature keys while forcing return structs to remain size-only.
src/coreclr/vm/jitinterface.cpp Adjusts Wasm alignment requirement computation to account for explicit layout and elevated field alignment in auto-layout structs.
src/coreclr/tools/Common/JitInterface/WasmLowering.cs Implements parsing/emission for S!<N>:<A>, raises signatures using cached structs keyed by layout, and emits alignment only for parameters.
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs Mirrors Wasm alignment requirement logic in the tool-side JIT interface implementation.
src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Wasm.cs Changes struct caching to key by (size, alignment) when alignment is part of the signature encoding.
src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/WasmArgumentLayoutTests.cs Adds/updates tests ensuring signatures and computed offsets remain correct for same-sized structs with different alignment.
docs/design/coreclr/botr/readytorun-format.md Documents S!<N>:<A> encoding rules and clarifies slot sizing for struct tokens.

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

Copilot-Session: b1af492e-7431-46af-b519-dcc504b62300
Copilot AI review requested due to automatic review settings August 13, 2026 00:25

Copilot AI 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

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

Suppressed comments (1)

src/coreclr/vm/jitinterface.cpp:1964

  • The comment mentions "beyond the pointer size", but the logic only adjusts the alignment when fieldAlignment > 8. On Wasm32 the pointer size is 4, so this is misleading and makes it harder to reason about why the threshold is 8.
        // Auto-layout structs can contain fields aligned beyond the pointer size on Wasm.

Use the effective JIT-EE alignment consistently when laying out Wasm transition slots, and cover mixed R2R/interpreter calls for auto and explicit layout structs.

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

Copilot-Session: 80340b10-4014-428f-bbba-55b7ad95c668
Copilot AI review requested due to automatic review settings August 13, 2026 21:45

Copilot AI 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

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

Suppressed comments (1)

src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs:73

  • The generated C++ header comment still states that each argument is aligned to INTERP_STACK_SLOT_SIZE, but with the new 'A' struct token you now intentionally align some arguments to a 16-byte boundary (see the new slot rounding in ArgsWithSlotOffsets). Please update the emitted comment so it matches the new behavior and avoids misleading future maintainers.
        {
            var toks = SignatureMapper.ParseSignatureTokens(sig);
            if (toks[0][0] == 'S' && toks[0].Length > 1)
                structReturnSizes.Add(SignatureMapper.GetStructSize(toks[0]));
        }

@davidwrighton
davidwrighton marked this pull request as ready for review August 13, 2026 21:57
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI review requested due to automatic review settings August 14, 2026 21:57

Copilot AI 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

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

Suppressed comments (2)

src/tests/JIT/Regression/JitBlue/WasmR2RStructAlignment/WasmR2RStructAlignment.cs:17

  • This test redefines System.Runtime.BypassReadyToRunAttribute locally, but unlike other tests (e.g., Methodical) it doesn’t explain why this duplicate definition is needed. Adding a short rationale comment helps future maintainers understand that the attribute is matched by name and is intentionally duplicated in the test assembly.
namespace System.Runtime
{
    [AttributeUsage(AttributeTargets.Method)]
    internal sealed class BypassReadyToRunAttribute : Attribute
    {

src/coreclr/tools/Common/JitInterface/WasmLowering.cs:735

  • The new 'A' encoding is introduced here, but the updated test suite in this PR doesn’t appear to validate that any signature actually produces an 'A' token (e.g., WasmArgumentLayoutTests has no expected signatures containing 'A'). Without a regression test that round-trips an 'A' struct (and verifies the 16-byte transition-block padding/offsets), this change can silently break without detection.
                        Debug.Assert(paramType is DefType);
                        int paramAlignment = CorInfoImpl.GetClassAlignmentRequirementStatic((DefType)paramType);
                        bool requiresAlignedSlot = paramAlignment > 8;
                        sigBuilder.Append(requiresAlignedSlot ? 'A' : 'S');
                        sigBuilder.Append(paramSize);
                        ((CompilerTypeSystemContext)paramType.Context).CacheStruct(paramType, requiresAlignedSlot);
                        result.Add(pointerType);

@davidwrighton

Copy link
Copy Markdown
Member Author

/ba-g unrelated failures

@davidwrighton
davidwrighton merged commit d20b851 into dotnet:main Aug 15, 2026
120 of 125 checks passed
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants