Multiple return values...

Robert Jacques sandford at jhu.edu
Sun Mar 11 14:57:01 PDT 2012


On Sun, 11 Mar 2012 15:38:21 -0500, Timon Gehr <timon.gehr at gmx.ch> wrote:

> On 03/11/2012 09:30 PM, Robert Jacques wrote:
>> On Sun, 11 Mar 2012 12:39:56 -0500, Manu <turkeyman at gmail.com> wrote:
>>> On 11 March 2012 18:50, Robert Jacques <sandford at jhu.edu> wrote:
>>>> On Sun, 11 Mar 2012 05:57:05 -0500, Manu <turkeyman at gmail.com> wrote:
>>>> On 11 March 2012 04:35, Sean Cavanaugh <WorksOnMyMachine at gmail.com>
>>>>> wrote:
>>>>> On 3/10/2012 8:08 PM, Mantis wrote:
>>
>> [snip]
>>
>>>> And Walter has talked about using the XMM registers to return floating
>>>> point data for exactly this reason. But those optimization apply to all
>>>> structs and all data types. There's nothing special about MRV. It has to
>>>> return a set of data in a structured manner; this is identical to the
>>>> case
>>>> of returning a struct.
>>>>
>>>
>>> Well you can't build these sorts of tightly packed structs in XMM
>>> registers... and even for the GPR's, it's very inefficient to do so. I
>>> haven't done tests, but I suspect this feature is probably a
>>> de-optimisation in all cases other than an int-pair struct (ranges,
>>> delegates? I suspect that's why this was invented). Structure
>>> packing/unpacking code will likely be slower than a store/load.
>>>
>>> We just need proper multiple return values, then this can go away. And
>>> the
>>> earlier any ABI breaking changes are implemented, the better, while there
>>> are still few(/none?) closed source, binary distributed D libraries.
>>
>> Manu, why are you assuming that the struct is returned in any sort of
>> fixed memory layout?
>
> Because that is what the ABI says.
>
> * 1, 2 and 4 byte structs are returned in EAX.
> * 8 byte structs are returned in EDX,EAX, where EDX gets the most
> significant half.
> * For other struct sizes, the return value is stored through a hidden
> pointer passed as an argument to the function.

You made my point. Manu is arguing that structs small enough to be worth passing in registers must maintain some sort of fixed memory layout; i.e. they can't broken up across a desperate set of registers.

>> You can _not_ take the memory address, etc of a
>> register so maintaining the layout of a struct is a) impossible and b)
>> not necessary, if you're returning it via registers. The compiler is
>> free to use XMM registers for floats/doubles and GPRs for pointers/ints.
>> And there's no need for the caller to place those struct register values
>> on the stack if they're never used. Furthermore, even on the stack, the
>> struct's memory layout is only ever valid immediately before (and
>> forever after due to pointer escapes) a non-inlined function call or
>> address taking. At a low level, MRV is a structured set of value, ergo
>> it's a struct.
>
> Multiple function arguments are a structured set of values too.

And the call structure for multiple arguments is virtually identical for structs and multiple arguments. In fact, I've used this duality on various cross-language calls, defining arguments in one language and a struct in the other.


More information about the Digitalmars-d mailing list