[wasm] R2R: 32-byte struct passed by value is corrupted (fields shifted by one word)
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
On `browser-wasm` (CoreCLR) with `PublishReadyToRun`, a 32-byte struct (four 8-byte fields) passed by value to a method is corrupted: the callee reads it shifted up by one 8-byte word, so each field takes the value of the next and the following argument bleeds in. 16- and 24-byte structs pass correctly.
### Repro
```csharp
using System;
struct S32 { public long A, B, C, D; }
class Program
{
static string E32(int x, S32 s, int y) => $"{x}|{s.A},{s.B},{s.C},{s.D}|{y}";
static void Main()
{
Console.WriteLine(E32(1, new S32 { A = 31, B = 32, C = 33, D = 34 }, 2));
}
}
```
`E32` must be ReadyToRun-compiled. Interpreted execution is correct.
### Expected
`1|31,32,33,34|2`
### Actual
`1|32,33,34,2|0`
`s.A` reads the input `B`, `s.B` reads `C`, `s.C` reads `D`, `s.D` reads the trailing `int y` (2), and `y` reads garbage (0) — i.e. the struct argument is read one 8-byte word too high.
### Notes
- 16-byte (`{ long, long }`) and 24-byte (`{ long, long, long }`) structs pass correctly; only the 32-byte (four-word) struct is affected.
- Reproduces with a direct call; reflection-invoking the same method corrupts it further.
### Configuration
- `-os browser -a wasm`, CoreCLR, `PublishReadyToRun` (crossgen2, `--obj-format:wasm`)
- Reproduces in Node and in the browser.
> [!NOTE]
> This issue was written with the assistance of GitHub Copilot.
Contributor guide
Assessment
This issue has not been assessed yet.