summaryrefslogtreecommitdiff
path: root/gcc/stmt.c
diff options
context:
space:
mode:
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>1995-04-25 22:25:28 +0000
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>1995-04-25 22:25:28 +0000
commit6a31fbc7854fae07e030532362ebbe085517ebd5 (patch)
tree40ccb96c146fbf08810df9759941b59007f620c1 /gcc/stmt.c
parent6bee037a201b77ae687eb3bf9b48612328cd4d01 (diff)
downloadgcc-6a31fbc7854fae07e030532362ebbe085517ebd5.tar.gz
(expand_return): When returning BLKmode structure in
registers, copy it to a psuedo-reg instead of to hard registers. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@9452 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r--gcc/stmt.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 3af00be436d..ac8683b8c85 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -2680,7 +2680,8 @@ expand_return (retval)
copying a BLKmode value into registers. We could put this code in a
more general area (for use by everyone instead of just function
call/return), but until this feature is generally usable it is kept here
- (and in expand_call). */
+ (and in expand_call). The value must go into a pseudo in case there
+ are cleanups that will clobber the real return register. */
if (retval_rhs != 0
&& TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
@@ -2691,7 +2692,7 @@ expand_return (retval)
int bytes = int_size_in_bytes (TREE_TYPE (retval_rhs));
int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
- rtx result_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+ rtx result_reg;
rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
enum machine_mode tmpmode;
@@ -2733,13 +2734,6 @@ expand_return (retval)
}
}
- /* Now that the value is in pseudos, copy it to the result reg(s). */
- emit_queue ();
- free_temp_slots ();
- for (i = 0; i < n_regs; i++)
- emit_move_insn (gen_rtx (REG, word_mode, REGNO (result_reg) + i),
- result_pseudos[i]);
-
/* Find the smallest integer mode large enough to hold the
entire structure and use that mode instead of BLKmode
on the USE insn for the return register. */
@@ -2747,17 +2741,25 @@ expand_return (retval)
for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
tmpmode != MAX_MACHINE_MODE;
tmpmode = GET_MODE_WIDER_MODE (tmpmode))
- {
- /* Have we found a large enough mode? */
- if (GET_MODE_SIZE (tmpmode) >= bytes)
- break;
- }
+ {
+ /* Have we found a large enough mode? */
+ if (GET_MODE_SIZE (tmpmode) >= bytes)
+ break;
+ }
/* No suitable mode found. */
if (tmpmode == MAX_MACHINE_MODE)
- abort ();
+ abort ();
+
+ result_reg = gen_reg_rtx (tmpmode);
+ PUT_MODE (DECL_RTL (DECL_RESULT (current_function_decl)), tmpmode);
- PUT_MODE (result_reg, tmpmode);
+ /* Now that the value is in pseudos, copy it to the result reg(s). */
+ emit_queue ();
+ free_temp_slots ();
+ for (i = 0; i < n_regs; i++)
+ emit_move_insn (gen_rtx (REG, word_mode, REGNO (result_reg) + i),
+ result_pseudos[i]);
expand_value_return (result_reg);
}