-
-
Notifications
You must be signed in to change notification settings - Fork 610
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
Trivial constructors should allow the struct to be passed as POD #2975
Conversation
|
This changes the definition of |
|
@andralex: @ibuclaw: Why would you allow destructors? |
|
Why can't we support throwing constructors? |
|
@yebblies - see point 3 in my initial message. @klickverbot - The point of passing in memory is that you can catch the object in EH. If the dtor is guaranteed not to throw, then we don't need to worry about this. |
|
Forgot to include link to bug report |
|
@ibuclaw I can see it, but I don't think it answers my question. We can't support throwing constructors because we can't tell if they might throw? |
|
@ibuclaw: Could you sketch a situation where throwing constructors would be a problem, and how constructors relate to parameter passing in the first place? It seems to me that we would always be able to construct objects on the stack and then move them to registers. Assignment (copy constructors in C++) is a different story, of course. |
|
@klickverbot when calling the constructor, the 'this' parameter for the would be passed via registers rather than on the stack. @yebblies - change of direction, ignoring nothrow altogether and a basterdised pass over the ctor body to ensure is only made up of simple assignment statements. |
| } | ||
| } | ||
| return true; | ||
| Lret: | ||
| return (ispod & ISPODyes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idpod == ISPODyes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked at it again, and I honestly can't remember what I was thinking using bitwise operators... :o)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must have thought that I was programming in B
|
@klickverbot - https://d.puremagic.com/issues/show_bug.cgi?id=11224 is an example which shows 'this' being passed on the stack. Incidentally this pull will now break that because it now passes the struct through registers in that test. |
Huh? 'this' is a reference. It doesn't matter where it's passed. The difference between POD and non-POD is only for pass-by-value... |
| return false; | ||
| // If we've already determined whether this struct is POD. | ||
| if (ispod != ISPODfwd) | ||
| goto Lret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just return from here, no need for goto.
|
I still don't get it. By definition, constructors are called on an initialized chunk of memory. If the inliner is screwing with that then it's an inliner bug, right? |
|
Because toArgTypes is returning a |
|
How on earth is |
|
[incorrect reply to Daniel removed] @ibuclaw: I fail to see how bug 11224 is related to my question: First of all, I asked for an example where a throwing constructor is a problem, but there are no exceptions in sight. :P Regarding the test case, I don't think it is related to constructors or the low-level ABI at all. First, note that the Second, I'd doubt that the failing test case is fundamentally related to constructors at all – Now, regarding the test case failure: Either, the language guarantees that NRVO happens if possible, regardless of whether it makes any sense, or the test case just makes the flawed assumption that it will always happen, because this actually was the case prior to the patch. Now, given that the entire point of NRVO is to be an optimization, and storing small structs in registers is pretty much always going to beat a memory access, I don't think the former would be a reasonable decision. But if it was the case, then structs would have to be always returned in memory, and this rewrite to a hidden pointer parameter would take place before the ABI comes into play. Thus, I'm heavily leaning towards the second option – just fix that broken test case. |
It seems to use |
|
On Thu, Dec 19, 2013 at 4:20 PM, Iain Buclaw notifications@github.comwrote:
|
@klickverbot comment is still there. ;) As for NRVO, I despise that the testsuite treats it as if the language requires NRVO to happen anyway... :-) |
|
Err, okay, then the GitHub notifications were just behaving erratically... So, if you don't think NRVO is required to happen, then why did you cite that issue/test case in the first place? By the way, I don't know of any part of the spec that would mandate NRVO, but it could have just slipped from my mind... |
|
@klickverbot - it's not in the spec, but phobos code (std.typecons.scoped) requires NRVO in order to implement its own semantic. Which is bad, very bad... |
|
This: https://d.puremagic.com/issues/show_bug.cgi?id=4500 |
|
@ibuclaw: I agree that the unclear semantics of struct return values/NRVO are a problem. But the point I have been trying to make is that this doesn't have anything to do with constructors. |
|
I've spoken some more to @yebblies - and this is taking the wrong angle anyway. isPOD should be more strict, not laxed, and the dmd backend shouldn't be using isPOD to determine whether to pass the struct via invisible reference. |
|
@ibuclaw: Determining whether to keep a struct in registers is the entire point of If you and @yebblies reached a different conclusion, then we are exactly in the situation I predicted back then - without appropriate documentation, apparently the purpose of it isn't even clear to compiler hackers. |
|
The only thing I care about is that we must match the System V ABI for passing structs to extern(C++) functions. |
|
@yebblies it's not just the System V ABI - it's at least the C++ ABI for GCC (not sure about other C++ implementations). All structs that define a user cpctor/postblit/dtor should be candidates for pass by reference. |
|
Doesn't g++ follow the System V ABI? I see the last set of commits still has a ctor marking a struct as non-POD... |
|
The point of POD is so that it can be placed in registers. Since you cannot take the address of a register, a POD struct cannot have operations on it that require taking the address of it to make copies. This is why destructors and copy constructors are not allowed for POD. |
|
@WalterBright The issue here is just with normal constructors. Or at least, the issue in the bug report. I have no idea where this pull is supposed to be going. Do you agree that a (non-copy) constructor should not prevent a struct from being passed in registers? (ie we follow the System V ABI) |
I can't think of a reason why not. But I also can't think of a reason why private fields should influence this. |
I'm with you there. |
|
(I've been away a while, so am just catching up). This started as one thing and ended up something completed different. So I'm closing this and re-opening each individual amendment separately. The original problem with @yebblies is that D compiler and runtime (see argtypes.c) assumes that if a struct is non-POD, then it is passed in memory by reference (via hidden pointer). Which as far as I can tell is not the case in any other ABI except Microsoft's own cdecl (Ugh!). The more common ABI (eg: all other flavours of *NIX) is that only non-trivially copyable structs are passed by reference. This can be determined by the following rules, albeit checked recursively: For linux, trivially copyable structs should be passed in registers. Which is not currently the case. |
|
These might be useful to someone: C++03 POD rules: http://stackoverflow.com/a/4178176/279684 GCC has a simple macro to check if a symbol is a non-pod type via |
|
Funny, on win32/dmc++ having a ctor is enough to make it non-pod. |
|
Probably an oversight by @WalterBright - or there is something funny going on in the implementation detail that makes it non-pod. |
|
It appears to be correct msvc behavior. win32 is just different. |
https://d.puremagic.com/issues/show_bug.cgi?id=11740
Improvements to be done:
isPODdoes not check for assignment operators at all.isPODdoes not cache its return value.Can not infer whether the ctor is nothrow as fbody might not have fully ran its semantic.