From amylaar Tue Jul 11 22:41:46 1995 Return-Path: <amylaar> Message-Id: <m0sVm7k-000D39C@meolyon> Date: Tue, 11 Jul 95 22:41 MET DST From: amylaar (Joern Rennecke) To: bug-gcc@prep.ai.mit.edu Subject: returning 8 byte structs on sparc Bcc: amylaar Status: RO gcc is supposed to return structs of 8 bytes in registers when -freg-struct-return is in effect. Alas, this does not work right when compiling for sparc ( I tried under SunOs 4.x, SunOS 5.x , and cross-compiling on Linux for SunOs 4.x , all with the same effect). As an example, take struct ii_struct { int i,j; }; struct ii_struct z() {struct ii_struct i; i.i = 0; i.j = 1; return i; } With the following patch, gcc 2.7.0 can be coerced to return the struct in memory: diff -c --recursive gcc-2.7.0/config/sparc/sparc.h gcc-2.7.0-x/config/sparc/sparc.h *** gcc-2.7.0/config/sparc/sparc.h Sat Jul 8 01:55:32 1995 --- gcc-2.7.0-x/config/sparc/sparc.h Tue Jul 11 15:52:33 1995 *************** *** 763,769 **** in memory. For v9, all aggregates are returned in memory. */ #define RETURN_IN_MEMORY(TYPE) \ ! (TYPE_MODE (TYPE) == BLKmode \ || (! TARGET_V9 && (TYPE_MODE (TYPE) == TFmode \ || TYPE_MODE (TYPE) == TCmode))) --- 763,769 ---- in memory. For v9, all aggregates are returned in memory. */ #define RETURN_IN_MEMORY(TYPE) \ ! (TYPE_MODE (TYPE) == BLKmode && !TYPE_NO_FORCE_BLK (TYPE) \ || (! TARGET_V9 && (TYPE_MODE (TYPE) == TFmode \ || TYPE_MODE (TYPE) == TCmode))) ------ end of patch ----- Alas, the generated code is still pretty bad, because the struct is only returned in registers, but first placed in memory on the stack. .align 4 .global _z .proc 010 _z: !#PROLOGUE# 0 add %sp,-112,%sp !#PROLOGUE# 1 st %g0,[%sp+96] mov 1,%g2 st %g2,[%sp+100] mov 0,%o0 mov 1,%o1 retl sub %sp,-112,%sp This can be alleviated by a patch to stor-layout.c : *** gcc-2.7.0/stor-layout.c Sat Jul 8 01:57:01 1995 --- gcc-2.7.0-x/stor-layout.c Tue Jul 11 21:24:06 1995 *************** layout_decl (decl, known_align) *** 235,241 **** else if (DECL_ALIGN (decl) == 0 || (! DECL_PACKED (decl) && TYPE_ALIGN (type) > DECL_ALIGN (decl))) DECL_ALIGN (decl) = TYPE_ALIGN (type); ! /* See if we can use an ordinary integer mode for a bit-field. */ /* Conditions are: a fixed size that is correct for another mode and occupying a complete byte or bytes on proper boundary. */ --- 235,247 ---- else if (DECL_ALIGN (decl) == 0 || (! DECL_PACKED (decl) && TYPE_ALIGN (type) > DECL_ALIGN (decl))) DECL_ALIGN (decl) = TYPE_ALIGN (type); ! /* allow to put 8 byte structs without type-forced alignment in registers */ ! if (code == VAR_DECL ! && TYPE_MODE (type) == BLKmode && TYPE_NO_FORCE_BLK (type) ) ! { ! DECL_MODE (decl) = mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)), ! MODE_INT, 1); ! } /* See if we can use an ordinary integer mode for a bit-field. */ /* Conditions are: a fixed size that is correct for another mode and occupying a complete byte or bytes on proper boundary. */ But this causes problems when assigning structs or wnen returning them with -fpcc-struct-return. All works fine when the struct is enclosed in a union of desired alignment: union ii_union { struct ii_struct i; double d; }; union ii_union zu() {union ii_union i; i.i.i = 0; i.i.j = 1; return i; } Alas, this necessiates an extra union member selector, thus enlarging and obscuring the C code. Moreover, on other targets, the mentioning of a double union member might cause more inefficient or even wrong code. You might say that I should use #ifdef __GNUC__ #define ALIGN8 __attribute__ ((aligned(8))) #else #define ALIGN8 #endif struct ii_struct { int i,j; } ALIGN8; Alas, all I get from this is: gcc: Internal compiler error: program cc1 got fatal signal 11 Joern Rennecke