This is something I noticed in the Mono test suite.
Mono's test dll has a function mono_test_Winx64_doubleStruct which takes a single argument, a struct containing a single double field.
That function is called from managed code here: https://github.com/mono/mono/blob/73b50890cc1fd2cb8ea4b7c209c03bfbd491359b/mono/tests/winx64structs.cs#L264
From what I can tell, the purpose of this test is to verify that the argument is passed in via the RCX register on Win64 (hence the name of the test case). However, when I build libtest.dll using mingw, the resulting function expects its argument in the XMM0 register. This results in test failures sometimes, depending on whether the .NET implementation coincidentally leaves the value in XMM0.
I believe this works as expected, by checking RCX, when compiled with MSVC, but I don't have the build setup to verify that.
Unfortunately, I don't have the ASM knowledge to create a reiable test case for this.
Ayup. However, this is a gcc issue, , the x64 ABI most definitely specifies that aggregates <= 64 bits are passed via RCX, RDX, R8, and R9 (as bit-for-bit copy; eg a movq rcx to xmm1 for the double arithmetic in the function)
However, this is a gcc issue, as it is seemingly emitting bad assembly. Please submit a bug report to the gcc https://gcc.gnu.org/bugs/ specifying the violation of simple aggregates <= 64 bits. This will probably open up a huge can of worms; this would be a breaking change in the ABI of any DLL compiled previously...
I, uh, don't actually care about this bug enough to do that. One flaky test doesn't bother me. I just figured I should tell someone instead of just sitting on it.
If no one else cares either, maybe it's best that we don't open that can of worms.
simple test program. This should return 1, from main, as the rcx register is 1.2, but it instead returns 0, as xmm0 is 6. (wrong answer can be verified by compiling the mono_test_Winx64_doubleStruct into a DLL (EDIT: WITH MSVC) and calling that instead of the local)
Last edit: Doug Semler 2019-11-15
Please file a bug report at https://gcc.gnu.org/bugzilla/.
Hmm, I might miss here something, but x64 ABI is actually pretty clear
about how aggregates should be passed. They (should) passed by
reference. So I don't see that this sample is valid.
Actually the function expects a reference to a struct, and not the
double value in any register.
Am Fr., 15. Nov. 2019 um 15:40 Uhr schrieb LH_Mouse
lhmouse@users.sourceforge.net:
Related
Bugs: #819
MSDN specifies that an aggregate of size 8, 16, 32 or 64 bits (as well as
__m64
) shall be passed via a register or on stack as if it were a scalar value, while the other aggregates are passed by reference.Despite bad wording ('parameter' shall be 'argument') such specification is effective. There is also an example for return values although no example exists for arguments.