diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 19 |
2 files changed, 23 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c90a62..8482554 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2002-04-24 David S. Miller <davem@redhat.com> + + PR target/6420 + * config/sparc/sparc.h (FUNCTION_OK_FOR_SIBCALL): Return false if + 32-bit Sparc and current_function_returns_struct is true. + Wed Apr 24 13:48:25 CEST 2002 Jan Hubicka <jh@suse.cz> * loop.c (canonicalize_condition): Use gen_int_mode. diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 4552132..872b1ee 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1902,8 +1902,23 @@ do { \ #define STRICT_ARGUMENT_NAMING TARGET_V9 /* We do not allow sibling calls if -mflat, nor - we do not allow indirect calls to be optimized into sibling calls. */ -#define FUNCTION_OK_FOR_SIBCALL(DECL) (DECL && ! TARGET_FLAT) + we do not allow indirect calls to be optimized into sibling calls. + + Also, on sparc 32-bit we cannot emit a sibling call when the + current function returns a structure. This is because the "unimp + after call" convention would cause the callee to return to the + wrong place. The generic code already disallows cases where the + function being called returns a structure. + + It may seem strange how this last case could occur. Usually there + is code after the call which jumps to epilogue code which dumps the + return value into the struct return area. That ought to invalidate + the sibling call right? Well, in the c++ case we can end up passing + the pointer to the struct return area to a constructor (which returns + void) and then nothing else happens. Such a sibling call would look + valid without the added check here. */ +#define FUNCTION_OK_FOR_SIBCALL(DECL) \ + (! TARGET_FLAT && (TARGET_ARCH64 || ! current_function_returns_struct)) /* Generate RTL to flush the register windows so as to make arbitrary frames available. */ |