Skip to content

Win64: Fix extern(C++) ABI wrt. passing non-POD structs by value#2706

Merged
kinke merged 1 commit intoldc-developers:masterfrom
kinke:nonpod_byval
May 25, 2018
Merged

Win64: Fix extern(C++) ABI wrt. passing non-POD structs by value#2706
kinke merged 1 commit intoldc-developers:masterfrom
kinke:nonpod_byval

Conversation

@kinke
Copy link
Member

@kinke kinke commented May 20, 2018

Return types have been checked for POD-ness already, but parameters haven't.

@kinke
Copy link
Member Author

kinke commented May 20, 2018

The dmd-testsuite tests work for Win32 and Win64, so both ABI (LL ref vs. value) and destruction rules (MSVC++ lets the callee destruct the param, just like D) match across D and C++, which is pretty nice. Maybe there's a slight chance that 32-bit POSIX passes the tests too, I haven't checked yet.

There's still at least one remaining special case not covered yet, and that's MSVC++ apparently treating struct S { int a; ~S(); }; as POD (any ctor will make it a non-POD, AFAIK another MSVC special case, but a dtor alone doesn't), while the D frontend doesn't.

@kinke
Copy link
Member Author

kinke commented May 20, 2018

Maybe there's a slight chance that 32-bit POSIX passes the tests too

Nope, 32-bit Linux fails with a segfault; like for x86_64, a ref is passed, and the caller destructs it.

@kinke
Copy link
Member Author

kinke commented May 20, 2018

Erm, turns out this only fixes the case where there's a deleted copy ctor and a move ctor, where 64-bit MSVC++ really passes a ref. With copy ctor, the argument is passed by value in a register, but the return value is still returned via hidden sret (!!), so the existing code and the inconsistent POD-ness check for return/param types is actually correct. A deleted C++ copy ctor apparently enforces by-ref passing though...

@kinke kinke changed the title Win64: Fix ABI wrt. passing non-POD structs by value Win64: Fix extern(C++) ABI wrt. passing non-POD structs by value May 21, 2018
@kinke
Copy link
Member Author

kinke commented May 21, 2018

I reworked this, especially the tests. They don't handle all permutations and corner cases of course, but the resulting fix should make byval-interop with C++ on Windows/MSVC work in most cases now.

Most small non-PODs are passed in registers, but those with a C++ copy
ctor, including an explicitly deleted one, are apparently passed by ref.
@kinke
Copy link
Member Author

kinke commented May 25, 2018

[Slightly reworked once more.]

@kinke kinke merged commit d714cde into ldc-developers:master May 25, 2018
@kinke kinke deleted the nonpod_byval branch May 25, 2018 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants