-
-
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
Fix the uncontrolled blitting which defeats the copy contructor #10510
Conversation
|
What's the frontend representational dump of this? By and large the code gen just does what it is told, and only creates temporaries when a side effect needs to be evaluated multiple times. |
|
Here is an example which illustrates the need to call the copy constructor in the codegen. Container[] darr;
darr ~= v;hits the following lines Lines 3315 to 3326 in 37a0434
The codegen evaluates v into a temporary first then moves it into the array. It should call the copy constructor or ideally the move constructor when it moves from the temporary into the array.
|
|
@ibuclaw That's true, the copying is the problem, it doesn't call the copy constructor when it happens. |
| union | ||
| { | ||
| Symbol* Edtor; // OPctor: destructor | ||
| Symbol* Edecl2; // VarDeclaration being constructed |
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.
When is Edecl2 valid?
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.
Edecl2 holds the temporary symbol being constructed. It's just used to find which this nodes correspond to which ctor node without assuming much about the tree. Nodes which share the same Edecl2 symbol are related together.
Needs to be in the comment message and the subject, or the bot won't work. |
src/dmd/backend/cod1.d
Outdated
| version (MARS) | ||
| { | ||
| case OPstrctor: | ||
| { |
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.
What is this block of code doing?
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.
The same thing it does for DMC, see line 4172.
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.
This does the work for the Win32 ABI. It fills OPstrthis nodes with the offset of the stack arguments, we need this to be able to call the copy constructor directly on the area where arguments are pushed. DMC does this with non-POD C++ arguments and it works.
|
Note this is quite a bit more complex than the ldc solution: ldc-developers/ldc#3204 Which one is better? |
|
Some observations:
|
|
Regarding the other failures (from the bug report)
Arrays fail because again of the __copytmps, it would be better if the frontend recognized and passed the address of all indexes to the cpctor instead. i.e: Structs with non-POD members are again failing because of __copytmp, frontend should recognize and pass address of each relevant field to the cpctor. i.e: |
It can be solved for LDC, pretty easily as Walter noted, by
|
|
@WalterBright LDC doesn't solve Win32 ABI yet, this solves if for DMD. For the rest it's similar in concept to how LDC does it, LDC has this function https://github.com/ldc-developers/ldc/blob/baaef17472bdeae90f80fb5c4f3b0212971db7a5/gen/toir.cpp#L2767 which is called a number of times. This is a DMD variant using |
|
@ibuclaw if you don't have the copy constructor try with the postblit it's the same. |
|
@ibuclaw In summary you're proposing to move much of the work done in the glue layer into the semantic phase. I'm not sure that would end the story though unless a no copying rule is imposed on the glue and the codegen. |
|
I'm uncomfortable with changing the back end like this. For one thing, it's effect on the optimizer is unknown. By doing it in the glue layer, these concerns would vanish. I'm wondering if the code added to cgelem.d could be done in e2ir.d. |
|
@WalterBright it was literally doing the exact same thing in |
d612b21 to
1f8be0e
Compare
|
@SSoulaimane, of course if dmd is creating extra temporaries under the hood, then those need addressing independently too. From my end, having an unambiguous way of representing copy constructor assignments is all that's required. I know what the correct codegen to fix in gdc looks like - just generate the same trees as g++, and gcc backend will take care of the rest. |
|
It still has to use a temporary variable and you have to replace it, or does it need to be some other special AST node instead of a variable? |
|
Only in the case of return statements though? Correct me if I remember wrong, in any step here. In the most simplistic case, assignments can be expressed in the following AST. Therefore one can express This also works fine if In the case of return expressions If there's a way to mark temporary var decls as being the value of a return statement Leaving the complex case for last, objects with cpctor/postblit fields. There's already recognition of: Which sets Going from there to the following: Is not that big a step, albeit the difference is in the above you must expand the constructor to individual direct assignments. If you are going this far, then might as well have this expansion in the frontend. All that I mention above though goes on the assumption that the frontend won't insert magical __tmp vars, which only serves to over complicate the matter. |
|
The selling point of the current way
Everywhere you find Your solution simply sets a function to be called and lets the glue do the logic. In this case you don't really need a new expression AST node, you only need to know the function to be called which can be set on each aggregate type during type semantic, the correct overload of the copy constructor will be picked and the glue decides when and if to call it. |
|
@ibuclaw semaphore failure is caused by this GDC bug https://issues.dlang.org/show_bug.cgi?id=20342. |
|
The codegen is still better placed to know when a temporary value is needed or not. The current behaviour of the frontend generating ast that creates a temporary only for the codegen to say actually you didn't mean that and then proceed to disentangle the mess that it has consumed is not a desirable solution. As far as I can tell, the only reason that the frontend creates the whole |
|
@ibuclaw This approach works. But in general I can see the benefit of moving things to the fronted or to a pre glue phase which is shared between compilers. This would allow GDC and LDC to catchup much quicker with DMD and focus more on the specificities of each backend rather than the repetitive stuff. |
8c418a1 to
b81057c
Compare
…copy constructor or the postblit
This applies to test case `test7516b()` from `test/runnable/sdtor.d`.
non POD struct arguments are passed by ref, static arrays of the same should receive the same treatment since the postblit applies to them too.
This issue affects this work too. non POD structs have to be passed by ref for function arguments.
e564a39 to
d9c9f41
Compare
Happens on 32 bits platforms.
|
This seems to have been abandoned. The issue is referencing this PR, therefore anyone that picks it up, feel free to reopen. |
Issue 20321.
LDC and GDC are also affected.
I chose this way of fixing it which keeps the initialization at the semantic phase then just adapts it in the codegen, but I realized that the backend creates a lot of temporaries and copies into them. There has to be some means to do elaborate copy in the backend, I'm afraid there is no workaround.
CC: @WalterBright
CC: @kinke @ibuclaw are you going to solve this for LDC and GDC? How?