-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UInt128 division broken on big-endian platforms #71157
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/area-system-numerics Issue DetailsDescriptionThe software 128-bit division algorithm added in #69204 (@tannergooding @bartonjs) does not work correctly on big-endian platforms, leading to failed assertions when running the test suite on s390x. Reproduction StepsRun the Expected behaviorTest passes. Actual behavior
Regression?Newly added test case now causes the test suite to fail. Known Workaroundsn/a ConfigurationCurrent runtime sources, on linux-s390x. Other informationFrom an initial investigation, it appears the problem is located in
|
Have a PR up (#71162). Sorry for the breakage. |
Thanks for the quick fix, @tannergooding ! The test now passes again (unfortunately another regression came in at the same time so CI still isn't green, but that's unrelated ...) While there seem to be no more int128-related test suite failures, I noticed this comment in the source that is confusing to me:
Not sure why the System V ABI is called out here, but I do not believe this statement to be correct. Is the intent that this data structure is compatible with a native __int128 type, as far as the calling convention (or at least in-memory layout) is concerned? If so, then this isn't true for the 64-bit big-endian platforms I'm aware of, certainly not for s390x (or big-endian ppc64). On s390x, the native __int128 type is fully big-endian, i.e. the first byte in memory is the most significant of all the 16 bytes. This would not be compatible with the memory layout of the C# Int128 struct as defined above. |
System V is the default Unix ABI for most platforms. All of the System V ABI docs I've checked explicitly state:
and
Notably I don't see that in the s390x-abi doc I found here: https://github.com/IBM/s390x-abi/blob/main/lzsabi.tex. It unfortunately makes no comment on the layout of the data...
Yes and we have interop tests that are meant to validate this. I wonder if they are not running on s390x. |
Ah right, they are all disabled on Mono: #69531 |
PR here: #71211 |
Well, those would presumably be ABI documents for little-endian platforms, where this would be correct.
That's the correct document. The pdf version may be easier to read: https://github.com/IBM/s390x-abi/releases/download/v1.6/lzsabi_s390x.pdf Figure 1.4 (on page 10) of that document shows the layout of the 128-bit (quadword) type. For PowerPC64, both little- and big-endian versions of the ABI are defined by the same document, which can be downloaded from here: https://openpowerfoundation.org/specifications/64bitelfabi/ The layout of the big-endian version of __int128 on PowerPC64 is defined in Table 2.10 there, and it is likewise fully big-endian (MSB is byte 0). I'll open another issue shortly. |
I see its inverse in 2.5 (little-endian bit and byte numbering in quadwords) and so expectations look to be "little-endian in little-endian" and "big-endian in big-endian" so that keeps this simple. 👍
Thanks! |
Description
The software 128-bit division algorithm added in #69204 (@tannergooding @bartonjs) does not work correctly on big-endian platforms, leading to failed assertions when running the test suite on s390x.
Reproduction Steps
Run the
System.Tests.Int128Tests_GenericMath.op_DivisionTest
test on linux-s390x.Expected behavior
Test passes.
Actual behavior
Regression?
Newly added test case now causes the test suite to fail.
Known Workarounds
n/a
Configuration
Current runtime sources, on linux-s390x.
Other information
From an initial investigation, it appears the problem is located in
DivideSlow
(insrc/libraries/System.Private.CoreLib/src/System/UInt128.cs:1038
:WriteLittleEndianUnsafe
writes out the 128-bit integer as a little-endian byte sequence. That sequence of bytes is then re-interpreted as an array ofuint
. This is only correct on systems whereuint
is little-endian.The text was updated successfully, but these errors were encountered: