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