pass a struct by value/ref and size of the struct

ZombineDev via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Apr 2 02:47:24 PDT 2016


On Saturday, 2 April 2016 at 09:28:58 UTC, ZombineDev wrote:
> On Wednesday, 23 March 2016 at 19:39:49 UTC, kinke wrote:
>> On Tuesday, 22 March 2016 at 07:35:49 UTC, ZombineDev wrote:
>>> If the object is larger than the size of a register on the 
>>> target machine, it is implicitly passed by ref
>>
>> That's incorrect. As Johan pointed out, this is somewhat true 
>> for the Win64 ABI (but it firstly copies the argument before 
>> passing a pointer to it!), but it's not for the 32-bit x86 and 
>> x86_64 System V (used on all non-Windows platforms) ABIs. 
>> System V is especially elaborate and may pass structs up to 
>> twice the size of a register in 2 registers. Bigger structs 
>> passed by value are blitted into the function arguments stack 
>> in memory. They are then accessed by the callee via a stack 
>> offset, that's correct, but I wouldn't call that 
>> implicit-by-ref-passing, as copying does take place, unless 
>> the optimizer decides it's unnecessary.
>>
>> So passing structs > 64-bit by value on Win64 never pays off 
>> (there's always an indirection); using `const ref(T)` where 
>> possible makes sure you at least elide the copy. But then 
>> again, you'll very soon find out that it's not really an 
>> option as rvalues cannot be passed byref in D, something a lot 
>> of people [including myself if not already obvious :)] hate 
>> about D.
>
> Thank you and Johan for the detailed explanation. You're 
> efforts on improving LDC are much appreciated.
> My intentions were to say that taking structs by value 
> shouldn't be as expensive as in C++, because of the way D 
> handles copy construction, especially if there is no 
> user-defined postblit (which is quite common), and also because 
> separate compilation is used more rarely.
> But probably I shouldn't have said that about the size of 
> registers as it depends very much on the ABI and it's not true 
> in general (as you pointed out).
>
> BTW, how does LDC handle the `auto ref` and `in` parameter 
> attributes for templated functions (that obviously have their 
> source code available)? Can they be used to prevent indirection 
> when the structure can be passed in registers and to prevent 
> copying when passing by registers is not possible?

I find that (at least from a usability standpoint) auto ref works 
quite well:

// UniqueRef has disabled this(this)
UniqueRef!Resource r;

void use()(auto ref UniqueRef!Resource r);

// borrows
use(r);

// passes ownership of rvalues
use(UniqueRef!Resource())

// transfers ownership
use(move(r));
// r == UniqueRef.init here

//=============

auto ref add(V)(auto ref V v1, auto ref V v2);

// default this(this)
Vec3f vec1;

// accepts both lvalues and rvalues
auto res = add(vec1, Vec3f(1, 2, 3.14));



More information about the Digitalmars-d-learn mailing list