I'm sorry I have to pester you with this again, but I still have some questions regarding POD types and I'd like to fix this in GDC.

So from last discussion:
>> 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.

I compiled some test programs with dmd and dmd _does_ pass non-POD values in registers as I suggested above.
See this example:
https://gist.github.com/jpf91/5064703 (D)
https://gist.github.com/jpf91/5064764 (ASM)

I also don't understand how a copy ctor could break this. I asked on D.learn and there was no answer. Of course in C++ where structs have identity and interior pointers are allowed passing in register could be bad as it changes the address. But in D this is explicitly allowed. So I take it that this is actually allowed?

What is weird then is that dmd passes non-PODs in registers for normal functions, but for varargs functions they're always passed on the stack. I don't think there's a reason to make this difference. I know the SysV ABI specifies that non-PODs are never passed in registers, but that's only true for C++ PODs*, I don't see why D non-PODs (no identity, internal pointers) couldn't be passed in registers for varargs functions as well.


DMD also uses the "invisible reference" trick described in the SysV ABI for all non-PODs. But again, I don't see why returning in a register would be problematic. In pseudo-asm:

What we have now in DMD:
--------
lea -0x4(%ebp),%edi
call <function>

<function>:
mov <returnvalue>, (%edi)
ret
--------

Why would returning in a register be illegal?
Especially considering that we pass parameters in registers, why not do the same for return values?
--------
call <function>
mov %eax, -0x4(%ebp)

<function>:
mov <returnvalue>, %eax
ret
--------


> Whenever you make a copy of a non-POD value, you have to (for example) build an exception handling frame to destruct it if, in > the meantime, an exception is thrown. This is not only expensive, but it doesn't work if the value lives in registers.

But if the copy is only a temporary bitcopy, i.e the copy constructor & postblit wasn't called (and this should be valid as D structs don't have identity/internal pointers) then there's no need to call the destructor? Maybe I should rather talk about "moving" than copying as in C++s move semantics.



* There's actually an explanation in the ABI pdf:
--------
A non-POD object cannot be passed in registers because such objects must have well defined addresses; the address at which an object is constructed (by the caller) and the address at which the object is destroyed (by the callee) must be the same. Similar issues apply when returning a
non-POD object from a function.
--------
However, with the current DMD implementation this is not the case. There is also no documentation stating that D non-PODs are constructed/destructed at the same address. http://dlang.org/struct.html says "A struct is defined to _not have an identity_; that is, the implementation is free to make bit copies of the struct as convenient."

--
Johannes Pfau

_______________________________________________
dmd-internals mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/dmd-internals

Reply via email to