Skip to content
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

C++ SysV ABI incompatibility wrt. passing non-PODs by value #2702

Closed
kinke opened this issue May 18, 2018 · 3 comments
Closed

C++ SysV ABI incompatibility wrt. passing non-PODs by value #2702

kinke opened this issue May 18, 2018 · 3 comments

Comments

@kinke
Copy link
Member

kinke commented May 18, 2018

While checking assembly and clang-IR wrt. DIP 1014, I stumbled on what looks like a huge ABI incompatibility, at least for the SysV ABI, and probably the 32-bit x86 ABIs too (Win64 should be safe though).

As soon as a C++ struct/class has a copy or move ctor, pass-by-value semantics seem to match ExplicitByvalRewrite (pass a pointer to a caller-allocated copy). LDC and DMD instead pass the aggregate on the stack (i.e., like a big POD struct). More information to follow.

@kinke
Copy link
Member Author

kinke commented May 18, 2018

To play around with C++: https://godbolt.org/g/XV8Pem (try commenting out the copy ctor and see what happens)

@kinke kinke changed the title C++ SysV ABI incompatibility wrt. non-PODs C++ SysV ABI incompatibility wrt. passing non-PODs by value May 18, 2018
@kinke
Copy link
Member Author

kinke commented May 18, 2018

GDC, at least v5.2 as latest version on godbolt, is affected too. See this D snippet.

D additionally doesn't call the C++ copy ctor when passing an lvalue by value, I thought that'd be implemented already. That can be worked around with a D postblit ctor though.

Then there's the different destruction rules; D moves the arg (or arg copy for lvalues) to the callee's memory params stack and lets the callee destruct it, C++ passes a ref to the rvalue (or lvalue copy) to the callee and the calleR destructs it after the call. In frontend terms, a C++ non-POD by-value param is more like an exotic ref, accepting rvalue args and requiring a copy for lvalue args.

Anyway, this explains why clang has no problems calling a move ctor, while LDC would probably have a hard time for DIP1014 with the current ABI (final address of callee param in IR only exposed to callee via implicit byval pointer param; original address of moved-from arg only known by caller).

kinke added a commit to kinke/ldc that referenced this issue Jun 7, 2018
Fixing one aspect of issue ldc-developers#2702; not tackling the different destruction
rules yet.
kinke added a commit to kinke/ldc that referenced this issue Jun 8, 2018
Fixing one aspect of issue ldc-developers#2702; not tackling the different destruction
rules yet.
kinke added a commit to kinke/ldc that referenced this issue Jun 17, 2018
Fixing one aspect of issue ldc-developers#2702; not tackling the different destruction
rules yet.
kinke added a commit that referenced this issue Jun 19, 2018
…2728)

Fixing one aspect of issue #2702; not tackling the different destruction
rules yet.
@kinke
Copy link
Member Author

kinke commented Jun 27, 2021

Non-PODs use the IndirectByvalRewrite now, and the C++ destruction rules are applied now too since v2.096 (https://issues.dlang.org/show_bug.cgi?id=20235).

@kinke kinke closed this as completed Jun 27, 2021
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

No branches or pull requests

1 participant