[M3devel] a trouble with passing records by value..

Rodney M. Bates rodney_bates at lcwb.coop
Wed Sep 1 04:24:07 CEST 2010


If the writers of an ABI actually *required* that small structs/records be
passed in registers, then they have made a big blunder.   In C, formal
parameters are l-values, and in Modula-3, they are designators, regardless
of the parameter mode. Thus taking their address must always be possible,
to comply with language semantics, which means they must be in memory.

The only possible resolutions are

1) Declare that language semantics trump ABI requirements and defy the ABI.

2) Pass them in registers at the time of control transfer, but store them
    in memory in the prologue, then access them from memory thereafter.

As for 1), any usable ABI will have to have an alternate, in-memory method of
passing things by value (if for no other reason, because they can be too big
for registers), so it is hard to imagine how just using this mechanism in more
cases could cause any trouble that didn't already exist anyway.

I guess the one case that would preclude doing 1) would be if you wanted
to allow calls and prologues generated by different compilers to work,
and you couldn't rely on getting all compilers to do 1).

As for 2), in some stack runtime models, passing in registers is probably
less efficient than just letting the call-site code store parameters directly
into the being-constructed activation record.

Of course, if the compiler can ascertain that the address is never taken,
then it could avoid storing them, but this doesn't absolve an ABI from
providing an adequate mechanism for those cases when this can't be done.

And of course, making formals be l-values/designators applies to most/all
other types besides structs/records.


Jay K wrote:
> t1 must still be passed in registers. The ABI can't be changed by that.
> 
>  - Jay
> 
> ----------------------------------------
>> From: hosking at cs.purdue.edu
>> Date: Tue, 31 Aug 2010 09:15:32 -0400
>> To: jay.krell at cornell.edu
>> CC: m3devel at elegosoft.com
>> Subject: Re: [M3devel] a trouble with passing records by value..
>>
>> What happens if you take the address of t inside ActionLookup?
>> What happens if you take the address of t1 inside main?
>>
>> On 31 Aug 2010, at 07:25, Jay K wrote:
>>
>>> Given something like this:
>>>
>>> jbook2:p247 jay$ more 1.c
>>> #include 
>>>
>>> typedef struct { long code; long value; } T1;
>>>
>>> void ActionLookup(T1 t, long code, long value);
>>>
>>> void ActionLookup(T1 t, long code, long value)
>>> {
>>> assert(t.code == code);
>>> assert(t.value == value);
>>> }
>>>
>>> int main()
>>> {
>>> T1 t1 = {2,2};
>>> ActionLookup(t1, 2, 2);
>>> return 0;
>>> }
>>> j
>>>
>>>
>>> on some platforms, such as AMD64_DARWIN, T1 is passed in registers. Good.
>>>
>>>
>>> However, one of the unfortunate aspects of our Modula-3 system is that when you reference e.g. t1.value,
>>> the backend isn't told you are accessing the "value" "field" of "t1", and it figures out where that is,
>>> but rather 64bits at offset 64bits into t1. Therefore t1 must have an address. Therefore it can't be in registers.
>>> Darn.
>>>
>>>
>>> If m3cg were higher level this could be better.
>>>
>>>
>>> There should be a viable compromise where the parameter is passed in registers, and only "homed"
>>> to some stack location if its address is used -- e.g. to pass unused parameters in registers.
>>> But given the inefficiency of field accesses, I'm not sure it is worth trying?
>>>
>>>
>>> Maybe we should have M3CG include field references?
>>>
>>>
>>> There is this basic problem that the interface between m3front and m3cc isn't really at the
>>> right level for m3cc. But it is probably for m3front. m3front wants a lower level code generator.
>>>
>>>
>>> - Jay
>>>
>  		 	   		  



More information about the M3devel mailing list