Menu

#819 incorrect argument passing for struct{double} on win64

v1.0 (example)
open
nobody
None
5
2019-11-20
2019-11-14
Esme Povirk
No

This is something I noticed in the Mono test suite.

https://github.com/mono/mono/blob/73b50890cc1fd2cb8ea4b7c209c03bfbd491359b/mono/tests/libtest.c#L4562

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.

Related

Bugs: #819

Discussion

  • Doug Semler

    Doug Semler - 2019-11-14

    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...

     
  • Esme Povirk

    Esme Povirk - 2019-11-14

    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.

     
  • Doug Semler

    Doug Semler - 2019-11-14

    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)

    typedef struct
    {
            double a;
    } winx64_doubleStruct;
    
    int
    mono_test_Winx64_doubleStruct(winx64_doubleStruct a)
    {
            if (a.a < 5.5 || a.a > 7.5)
                    return 1;
    
            return 0;
    }
    
    int main(void)
    {
            int a;
            double d = 6;
            asm("movq $0x3FF3333333333333, %%rcx \n\t"
                "movsd %1, %%xmm0 \n\t"
                "call       mono_test_Winx64_doubleStruct"
                : "=r" (a)
                : "m" (d));
            return a;
    }
    
     

    Last edit: Doug Semler 2019-11-15
  • LIU Hao

    LIU Hao - 2019-11-15

    Please file a bug report at https://gcc.gnu.org/bugzilla/.

     
    • Kai Tietz

      Kai Tietz - 2019-11-20

      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:

      Please file a bug report at https://gcc.gnu.org/bugzilla/.


      [bugs:#819] incorrect argument passing for struct{double} on win64

      Status: open
      Group: v1.0 (example)
      Created: Thu Nov 14, 2019 07:23 PM UTC by Vincent Povirk
      Last Updated: Thu Nov 14, 2019 11:25 PM UTC
      Owner: nobody

      This is something I noticed in the Mono test suite.

      https://github.com/mono/mono/blob/73b50890cc1fd2cb8ea4b7c209c03bfbd491359b/mono/tests/libtest.c#L4562

      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.


      Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/mingw-w64/bugs/819/

      To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

       

      Related

      Bugs: #819


Log in to post a comment.