From owner-freebsd-ppc Sat Aug 17 13:29:53 2002 Delivered-To: freebsd-ppc@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 60BAF37B400 for ; Sat, 17 Aug 2002 13:29:49 -0700 (PDT) Received: from bothawui.bothan.net (bothawui.bothan.net [66.92.184.160]) by mx1.FreeBSD.org (Postfix) with SMTP id 0D3ED43E6A for ; Sat, 17 Aug 2002 13:29:49 -0700 (PDT) (envelope-from jtl-freebsd@bothan.net) Received: (qmail 18132 invoked from network); 17 Aug 2002 20:29:48 -0000 Received: from unknown (HELO localhost.localdomain) (127.0.0.1) by localhost with SMTP; 17 Aug 2002 20:29:48 -0000 Subject: freebsd-ppc: gcc's SysV ABI and parameter passing From: Joshua LeVasseur To: freebsd-ppc@freebsd.org Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Mailer: Ximian Evolution 1.0.7 Date: 17 Aug 2002 22:29:44 +0200 Message-Id: <1029616185.9422.427.camel@i30pc32> Mime-Version: 1.0 Sender: owner-freebsd-ppc@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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