Skip site navigation (1)Skip section navigation (2)
Date:      17 Aug 2002 22:29:44 +0200
From:      Joshua LeVasseur <jtl-freebsd@bothan.net>
To:        freebsd-ppc@freebsd.org
Subject:   freebsd-ppc: gcc's SysV ABI and parameter passing
Message-ID:  <1029616185.9422.427.camel@i30pc32>

next in thread | raw e-mail | index | archive | help

While analyzing the code generated by gcc, I noticed that gcc implements
quite a literal interpretation of the System V ABI for parameter
passing.

From the spec:
"A struct, union, or long double, any of which shall be treated as a
pointer to the object, or to a copy of the object where necessary to
enforce call-by-value semantics.  Only if the caller can ascertain that
the object is "constant" can it pass a pointer to the object itself."

Some example code, which declares a union for representing a 32-bit
bit-field (common for kernel code).

-----------------------
class simple_t {
public:
    union {
	unsigned raw;
	struct {
	    unsigned yoda : 16;
	    unsigned vader : 16;
	} x;
    };
};

int add( simple_t a, simple_t b )
{
    return a.raw + b.raw;
}

int main( void )
{
    simple_t a, b;

    a.raw = 1;
    b.raw = 2;
    return add( a, b );
}
----------------------

gcc, using the SysV ABI, will generate the following code:

add:
        lwz r0,0(r3)
        lwz r3,0(r4)
        add r3,r0,r3
        blr

main:
        li r0,1
        li r9,2
        stw r0,8(r1)
        stw r9,12(r1)
        addi r3,r1,8
        addi r4,r1,12
        bl add


Notice how gcc writes the values to the stack before calling add(), and
then loads them off the stack in the add() function.  Rather than
passing them as 32-bit parameters.

Now inspect the code generated by an alternative ABI (I use a modified
eabi to generate tight code).  This code is also generated by Apple's
MachO ABI, and the AIX ABI (although I lack access to an AIX box).

add:
        add r3,r3,r4
        blr

main:
        li r3,1
        li r4,2
        b  add


Darwin, via the MachO ABI, uses the nice version (a good thing too,
since they use lots of C++, where data is abstracted in classes).  Linux
uses the standard SysV ABI, and generates the stack-happy code.  Which
is unfortunate, since the Linux kernel abstracts many data types in
structures (such as the pte data type).  But it would be hard for Linux
to change the ABI, now that people already use it for glibc, although it
could be changed in the kernel.

And FreeBSD suffers from the same stack-happy ABI problems.  But it
isn't too late to modify the ABI before freebsd-ppc is widely deployed. 
Or at least for the kernel.

I think that this aspect of the SysV calling convention is really bad. 
If a data-type is 32-bits (whether or not it is expressed as a structure
in the high level language), it should be passed by register when passed
by value.

Modifying gcc to fix this problem is really simple.  The function of
concern is function_arg_pass_by_reference() in
gcc/gcc/config/rs6000/rs6000.c.

Josh




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ppc" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1029616185.9422.427.camel>