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).
  • Regarding ref results bearophile via Digitalmars-d
    • Re: Regarding ref results John Colvin via Digitalmars-d

Reply via email to