From a3acf46d445fffc0d691bf1acb80d9a70dbd082c Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 18 Apr 2002 21:10:11 +0200 Subject: [PATCH] re PR c/6358 (GCC 3.1 ICE on statement expressions) PR c/6358 * function.c (assign_parms): Assign hard current_function_return_rtx register here... (expand_function_end): ...not here. * gcc.c-torture/compile/20020418-1.c: New test. From-SVN: r52485 --- gcc/ChangeLog | 7 +++ gcc/function.c | 47 +++++++++++++------ gcc/testsuite/ChangeLog | 4 ++ .../gcc.c-torture/compile/20020418-1.c | 18 +++++++ 4 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/20020418-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 091231ed8a2..2676cb0036b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2002-04-18 Jakub Jelinek + + PR c/6358 + * function.c (assign_parms): Assign hard current_function_return_rtx + register here... + (expand_function_end): ...not here. + 2002-04-18 Neil Booth * c-lang.c (LANG_HOOKS_INCOMPLETE_TYPE_ERROR): Redefine. diff --git a/gcc/function.c b/gcc/function.c index 86a87ab6068..4562376ce49 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -5145,6 +5145,35 @@ assign_parms (fndecl) current_function_return_rtx = (DECL_RTL_SET_P (DECL_RESULT (fndecl)) ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX); + + /* If scalar return value was computed in a pseudo-reg, or was a named + return value that got dumped to the stack, copy that to the hard + return register. */ + if (DECL_RTL_SET_P (DECL_RESULT (fndecl))) + { + tree decl_result = DECL_RESULT (fndecl); + rtx decl_rtl = DECL_RTL (decl_result); + + if (REG_P (decl_rtl) + ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER + : DECL_REGISTER (decl_result)) + { + rtx real_decl_rtl; + +#ifdef FUNCTION_OUTGOING_VALUE + real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result), + fndecl); +#else + real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result), + fndecl); +#endif + REG_FUNCTION_VALUE_P (real_decl_rtl) = 1; + /* The delay slot scheduler assumes that current_function_return_rtx + holds the hard register containing the return value, not a + temporary pseudo. */ + current_function_return_rtx = real_decl_rtl; + } + } } /* Indicate whether REGNO is an incoming argument to the current function @@ -6958,16 +6987,11 @@ expand_function_end (filename, line, end_bindings) ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER : DECL_REGISTER (decl_result)) { - rtx real_decl_rtl; + rtx real_decl_rtl = current_function_return_rtx; -#ifdef FUNCTION_OUTGOING_VALUE - real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result), - current_function_decl); -#else - real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result), - current_function_decl); -#endif - REG_FUNCTION_VALUE_P (real_decl_rtl) = 1; + /* This should be set in assign_parms. */ + if (! REG_FUNCTION_VALUE_P (real_decl_rtl)) + abort (); /* If this is a BLKmode structure being returned in registers, then use the mode computed in expand_return. Note that if @@ -6995,11 +7019,6 @@ expand_function_end (filename, line, end_bindings) int_size_in_bytes (TREE_TYPE (decl_result))); else emit_move_insn (real_decl_rtl, decl_rtl); - - /* The delay slot scheduler assumes that current_function_return_rtx - holds the hard register containing the return value, not a - temporary pseudo. */ - current_function_return_rtx = real_decl_rtl; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8798cc1eb69..9c6bd869be3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-04-18 Jakub Jelinek + + * gcc.c-torture/compile/20020418-1.c: New test. + 2002-04-18 Roger Sayle * gcc.c-torture/compile/20020415-1.c: New. diff --git a/gcc/testsuite/gcc.c-torture/compile/20020418-1.c b/gcc/testsuite/gcc.c-torture/compile/20020418-1.c new file mode 100644 index 00000000000..df01e6847e3 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20020418-1.c @@ -0,0 +1,18 @@ +/* PR c/6358 + This testcase ICEd on IA-32 in foo, because current_function_return_rtx + was assigned a hard register only after expand_null_return was called, + thus return pseudo was clobbered twice and the hard register not at + all. */ + +void baz (void); + +double foo (void) +{ + baz (); + return; +} + +double bar (void) +{ + baz (); +} -- 2.30.2