Skip to content

[wasm] Decide Vector256/Vector512 field alignment on wasm before layout is locked in #135483

Open

Description

@lewing

On wasm, both the VM (MethodTableBuilder::CheckForSystemTypes) and crossgen2 (VectorFieldLayoutAlgorithm) give Vector256<T> and Vector512<T> an alignment of 32 and 64. Neither has a wasm branch, so both fall through to the generic else, which corresponds to x86's __m256/__m512. Since #135481, auto-layout structs that contain these types inherit the same alignment, consistently in the VM and crossgen2.

The VM and crossgen2 agree, so there is no correctness bug today. However, 32/64 is questionable for wasm, and changing it later breaks layout and ReadyToRun compatibility. It should be decided before wasm CoreCLR ships.

Evidence

  • The Wasm Basic C ABI defines nothing wider than v128.

  • clang 22 targeting wasm32-unknown-unknown and wasm32-unknown-emscripten:

    type _Alignof
    __int128, v128 (vector_size(16)) 16
    struct { v128 lo, hi; } 16
    vector_size(32) / vector_size(64) 32 / 64
    __BIGGEST_ALIGNMENT__ 16

    The data layout's stack alignment is S128, i.e. 16 bytes. Only clang's generic vector-extension types get 32/64, and those are not part of the ABI; wasm lowers them to multiple v128s.

  • In [wasm] Use ordinary struct alignment for Int128/UInt128 on wasm #131421, the expected model was that Vector256<T> is struct { Vector128 lower, upper; } and Vector512<T> is struct { Vector256 lower, upper; }, treated like equivalent user-defined structs (as on Arm64). On wasm that gives an alignment of 16.

  • The GC heap on wasm only guarantees 8-byte object alignment (FEATURE_64BIT_ALIGNMENT). Any field alignment above 8 therefore only affects offsets relative to the start of the object, so 32/64 adds padding without giving real alignment.

  • [wasm] Use ordinary struct alignment for Int128/UInt128 on wasm #131421 also found that wide vectors were passed through alignment-blind S<N> signature keys. [wasm] Pass Int128, Decimal128 and wide vectors by value #131492 changed wasm argument passing for these types; that side should be re-checked as part of this decision.

Ask

  • Decide between 16 (the 2×/4× V128 model) and the current 32/64 for wasm.
  • Change the VM (CheckForSystemTypes) and crossgen2 (VectorFieldLayoutAlgorithm) together.
  • Add Wasm32 rows for the vector types to ArchitectureSpecificFieldLayoutTests. Wasm32 coverage for Int128/UInt128/Decimal128 was added in [wasm] Keep larger field alignment for Align8 auto-layout structs #135481.

Note

This issue was drafted with GitHub Copilot.

Activity

  1. added this to the 12.0.0 milestone on Oct 9, 2026
  2. dotnet-policy-service commented on Oct 9, 2026

    @dotnet-policy-service
    Contributor

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

  3. dotnet-policy-service commented on Oct 9, 2026

    @dotnet-policy-service
    Contributor

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

  4. lewing commented on Oct 9, 2026

    @lewing
    MemberAuthor
  5. tannergooding commented on Oct 12, 2026

    @tannergooding
    Member

    I'd say defaulting to 16 for them, like Arm64 does, is reasonable.

    If WASM does get dedicated support for V256 or similar in the future, we can (and may need to) take a R2R/ABI break then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status
      No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions