ABI for Decimal32/64/128 is incorrect with regards to native ABI for by value parameter passing
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
The by-value native ABI for `System.Numerics.Decimal32`, `Decimal64`, and `Decimal128` is not yet implemented in the JIT, mirroring the situation for `Int128`/`UInt128` tracked by #74209.
Known issues:
- `Decimal128` is a 16-byte, 16-byte-aligned type and hits the same unimplemented register-pair/stack-alignment paths as `Int128` on Arm64 and Unix x64 (both enregistered and when spilled to the stack).
- `Decimal32`/`Decimal64` are 4/8-byte scalars, but the JIT has no decimal floating-point calling convention. To the JIT they are `struct{uint}`/`struct{ulong}` passed in integer registers, which does not match a platform `_Decimal32`/`_Decimal64` (SSE class on the System V ABI).
Until this is implemented, by-value marshaling of these types (and structs containing them) is blocked, and the field layout for `Decimal128` is given a 16-byte alignment to match the native ABI (the same treatment as `Int128`/`UInt128`).
When this is fixed, re-enable the by-value scenarios in `$(XunitTestBinBase)/Interop/PInvoke/Decimal128/`.
category:correctness
theme:calling-convention
skill-level:expert
> [!NOTE]
> This issue was drafted with the assistance of GitHub Copilot.
Contributor guide
Research direction
Start by comparing the unimplemented Decimal32/64/128 paths with the Int128/UInt128 work tracked by #74209, focusing on Arm64 and Unix x64 register and stack handling. Re-enable the by-value scenarios under $(XunitTestBinBase)/Interop/PInvoke/Decimal128/ and use them to verify native ABI-compatible marshaling and alignment.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100