www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What can be done with copy constructors / post blits

reply Johannes Pfau <nospam example.com> writes:
When trying to implement non-POD types for gdc some time ago I asked on
the dmd mailing list what the backend is actually supposed to do for
non-POD types. Walter answered that they should never be passed in
registers:

--------------------------
 Wouldn't it be legal to still pass non-PODs in registers when calling
 functions and only copying them back to the stack if the address is
 needed? As we pass structs by value anyway, how could this be
 problematic?
No, not allowed. Consider why there are copy constructors, and what they do. -------------------------- Now that's probably because of my weak C++ background, but what can you do with copy constructors that would break if the compiler passed the non-POD type in a register to a function? Note: If I interpret this assembly properly dmd does do exactly what I proposed and what's illegal according to Walter: D: https://gist.github.com/jpf91/5064703 ASM: https://gist.github.com/jpf91/5064764
Mar 01 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 1 March 2013 at 13:59:08 UTC, Johannes Pfau wrote:
 When trying to implement non-POD types for gdc some time ago I 
 asked on
 the dmd mailing list what the backend is actually supposed to 
 do for
 non-POD types. Walter answered that they should never be passed 
 in
 registers:

 --------------------------
 Wouldn't it be legal to still pass non-PODs in registers when 
 calling
 functions and only copying them back to the stack if the 
 address is
 needed? As we pass structs by value anyway, how could this be
 problematic?
No, not allowed. Consider why there are copy constructors, and what they do. -------------------------- Now that's probably because of my weak C++ background, but what can you do with copy constructors that would break if the compiler passed the non-POD type in a register to a function? Note: If I interpret this assembly properly dmd does do exactly what I proposed and what's illegal according to Walter: D: https://gist.github.com/jpf91/5064703 ASM: https://gist.github.com/jpf91/5064764
Unsure what "pass in register" means. As in storing the data before calling the function in a register, as opposed to the stack? In C++, if you ever copy or move anything, then a CC must be called. Because of this, I'd say you can't place a non POD in a register, because that would imply CC'ing the thing just to place it in said register. In D, it is a little different, because you are allowed to move stuff in-memory without ever calling the CC. This is "D move semantics", and it works because D bans internal pointers. Because of this, I'd say you can pass by register. Maybe Walter gave you his "reflex" C++ reply, and didn't realize that D relaxed semantics changed the rules?
Mar 01 2013
parent Johannes Pfau <nospam example.com> writes:
Am Fri, 01 Mar 2013 15:09:11 +0100
schrieb "monarch_dodra" <monarchdodra gmail.com>:

 On Friday, 1 March 2013 at 13:59:08 UTC, Johannes Pfau wrote:
 When trying to implement non-POD types for gdc some time ago I 
 asked on
 the dmd mailing list what the backend is actually supposed to 
 do for
 non-POD types. Walter answered that they should never be passed 
 in
 registers:

 --------------------------
 Wouldn't it be legal to still pass non-PODs in registers when 
 calling
 functions and only copying them back to the stack if the 
 address is
 needed? As we pass structs by value anyway, how could this be
 problematic?
No, not allowed. Consider why there are copy constructors, and what they do. -------------------------- Now that's probably because of my weak C++ background, but what can you do with copy constructors that would break if the compiler passed the non-POD type in a register to a function? Note: If I interpret this assembly properly dmd does do exactly what I proposed and what's illegal according to Walter: D: https://gist.github.com/jpf91/5064703 ASM: https://gist.github.com/jpf91/5064764
Unsure what "pass in register" means. As in storing the data before calling the function in a register, as opposed to the stack? In C++, if you ever copy or move anything, then a CC must be called. Because of this, I'd say you can't place a non POD in a register, because that would imply CC'ing the thing just to place it in said register.
Because of that the GCC backend complains a lot when trying to fit D Non-PODS into that C++ model: The backend refuses to create any temporaries, move anything etc. I'll probably have to ask on the GCC mailing list what to do about this, it seems there's no good solution right now. (Maybe C++11 move semantics can help)
 
 In D, it is a little different, because you are allowed to move 
 stuff in-memory without ever calling the CC. This is "D move 
 semantics", and it works because D bans internal pointers. 
 Because of this, I'd say you can pass by register.
The rules in DMD are a little weird though: * For normal functions the value is passed in registers, but for varargs functions it's passed on the stack! Any idea what could be different here? (This is actually a bug in gdc right now cause gdc passes those in registers even to varargs functions) * DMD never returns a value in a register. It uses the hidden reference trick described in the SysV ABI: func(A* storage) { *storage = result_value; } instead of simply returning A by value. Any idea why this is necessary?
 
 Maybe Walter gave you his "reflex" C++ reply, and didn't realize 
 that D relaxed semantics changed the rules?
Yep, internal pointers was the only thing which I though could break, but isn't allowed in D anyway. That's what I thought, maybe I'll have to ask again. Pass in register in this case means putting the value into a specific register before calling the function, not on the stack (memory). The details are described in the SYSv x86_64 ABI. The important difference here is that a value passed on the stack has an address, a value passed in a register not. GCC has a notion of an ADRESSABLE type which is then probably not useful for gdc as it's too strict, it always prevents passing these types in registers (and produces many errors ;-).
Mar 01 2013