sima/autoconf/
sima/hosts/i386/
sima/mudlib/
sima/mudlib/kernel/
sima/mudlib/obj/
sima/mudlib/sys/
sima/synhash/mips/
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