Jump to page: 1 2
Thread overview
[Issue 18928] extern(C++) bad codegen, wrong calling convention
May 31, 2018
Manu
May 31, 2018
Manu
Jun 01, 2018
Walter Bright
Jun 01, 2018
Manu
Jun 01, 2018
Manu
Jun 01, 2018
kinke@gmx.net
Jun 01, 2018
Manu
Jun 01, 2018
kinke@gmx.net
Jun 01, 2018
Manu
Jun 02, 2018
kinke@gmx.net
Jun 04, 2018
Manu
Jun 04, 2018
Rainer Schuetze
May 31, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

Manu <turkeyman@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |C++, industry

--
May 31, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #1 from Manu <turkeyman@gmail.com> ---
I'm suspecting an issue with RVO.
I think the MSC ABI has changed to guarantee RVO at some point in the last few
years... but I'm not sure why the static call and virtual call appear to be
called using different calling convention.

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #2 from Walter Bright <bugzilla@digitalmars.com> ---
Can you please post an example that doesn't require the IDDE? Just show the disassembly where the code is wrong, please.

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #3 from Manu <turkeyman@gmail.com> ---
You'll have to relate these 2 lines to the .cpp file (attached) in main()

Calling code in main():

// static call...
    auto x = addUser(test, "test");
00007FF74843C587  lea         rdx,[string "test" (07FF748448D44h)]
00007FF74843C58E  mov         rcx,qword ptr [test]
00007FF74843C592  call        addUser (07FF74840C735h)
00007FF74843C597  mov         dword ptr [rbp+104h],eax
00007FF74843C59D  mov         eax,dword ptr [rbp+104h]
00007FF74843C5A3  mov         dword ptr [x],eax

// virtual call...
        x = test->addUser("test");
00007FF74843C5A6  mov         rax,qword ptr [test]
00007FF74843C5AA  mov         rax,qword ptr [rax]
00007FF74843C5AD  lea         r8,[string "test" (07FF748448D44h)]
00007FF74843C5B4  lea         rdx,[rbp+124h]  // what is? RVO return address?
00007FF74843C5BB  mov         rcx,qword ptr [test]
00007FF74843C5BF  call        qword ptr [rax]
00007FF74843C5C1  mov         eax,dword ptr [rax]
00007FF74843C5C3  mov         dword ptr [x],eax

This is the C++ code calling into D; it appears C++ makes a static call differently to a virtual call? I suspect RDX in the virtual call is the RVO return address? I wonder why the static-call doesn't follow the same call convention?


I can attach the DMD disassembly? But it's probably easier to build that yourself.


This might reveal that the VC ABI has RVO rules that we don't understand?

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #4 from Manu <turkeyman@gmail.com> ---
If you look at the disassembly of userdatabase.d, you'll see that the virtual function is not expecting the string in R8 where VC is putting it. It also doesn't appear to return via the RVO pointer(?) in RDX.

The static call matches D's expectations.

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

kinke@gmx.net changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kinke@gmx.net

--- Comment #5 from kinke@gmx.net ---
(In reply to Manu from comment #3)
> This might reveal that the VC ABI has RVO rules that we don't understand?

Or rather that their C++ ABI apparently enforces sret/RVO for methods returning structs, even such trivial 32-bit PODs, but doesn't for normal functions. Interesting findings; I'll verify them.

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #6 from Manu <turkeyman@gmail.com> ---
I recall a few years ago reading some article about MSVC breaking their ABI to
guarantee RVO, because C++11 and move semantics and all that.
I guess it needed to be efficient and therefore justified guaranteeing RVO
where previously it was an optimisation.

It's probably the case that extern(C++) was implemented before C++11 made it to
MSVC.

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #7 from kinke@gmx.net ---
Well it doesn't make too much sense, and even less so to do it for methods only; I rather think this is some legacy COM compatibility stuff. I did a few tests, and it really seems to be specific to methods (instance member functions), which return every struct via sret/RVO, not just non-PODs as regular functions, incl. class member functions.

So this is essentially a duplicate of https://issues.dlang.org/show_bug.cgi?id=16987; I thought it was COM-specific back then.

I tried fixing it for LDC, but that's sadly not trivial, as the ABI stuff doesn't operate on FuncDeclaration but on TypeFunction, which contains the calling convention but not whether it's a method.

--
June 01, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #8 from Manu <turkeyman@gmail.com> ---
So, probability of a prompt fix? Is this just a matter of not having correct information up front, or is the fix complicated by some issue?

We have an evaluation here that's kinda been shattered by this, but a fast fix would really help recover the situation if it's possible.

--
June 02, 2018
https://issues.dlang.org/show_bug.cgi?id=18928

--- Comment #9 from kinke@gmx.net ---
Well I gave it a shot and came up with an ugly hack which might just work, the first test results are promising: https://github.com/ldc-developers/ldc/pull/2720

--
« First   ‹ Prev
1 2