Regarding ref results

John Colvin via Digitalmars-d digitalmars-d at puremagic.com
Wed Apr 30 04:10:01 PDT 2014


On Wednesday, 30 April 2014 at 10:22:45 UTC, bearophile wrote:
> - You need to define the return variable before the function, 
> this is not handy for UFCS chains;
> - You also need to define the type of the result before calling 
> the function. Here I have found such type using 
> ParameterTypeTuple, but this is not so handy, and if the 
> function becomes a template, you also need to instantiate it to 
> find the argument type.

Assuming a static array is considered to be a normal aggregate, 
the System V ABI defines some of this problem away.

int[10] foo()
{
     int[10] a;
     //fill a

     return a;
}

void bar()
{
     foo();
}

becomes assembly equivalent to this, assuming a sensible (not 
necessarily very clever) compiler:

void foo(int* ret)
{
     int[10] a;
     //fill a

     ret[0 .. 10] = a[];
}

void bar()
{
     int[10] a;
     foo(a.ptr);
}

The memory is allocated on stack of caller, and then it passes 
the base address in %edi

Perhaps I'm being naive, but it should be trivial for the 
optimiser to produce something like:

void foo(int* ret)
{
     ret[0 .. 10] = 0; //pessimistic, sometimes elidable.*

     //fill ret as if it was an int[10]
}

void bar()
{
     int[10] a;
     foo(a.ptr);
}

*especially when inlined.


I'm not so familiar with other ABIs, but there are really only 3 
choices: 1) allocate in caller, 2) memcopy or 3) return in 
multiple registers. I doubt anyone uses 2, 1 is what we see above 
and 3 is very cheap (register moves normally cost little).


More information about the Digitalmars-d mailing list