This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix sjlj eh, and small complex return values
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 17 Sep 2005 14:03:51 -0700
- Subject: fix sjlj eh, and small complex return values
I've had this patch in one of my trees for a comple of weeks and
forgot about it. In the process, I've lost track of where the
original problem was reported.
Anyway, it was reported that sjlj was broken, because we put the
call to _SjLj_Unregister after we've set up the hard return
register, clobbering it.
While I was looking at that -- perhaps with some extra checking -- I
noticed that we generate the bit field inserts for e.g. _Complex char
into hard registers. Which could potentially fail at reload time.
So I fixed that to do the insert into pseudos and then copy the
result to the hard register.
Tested on alpha and i686 linux, and with --enable-sjlj-exceptions.
r~
* expr.c (emit_move_via_integer): Add force argument, pass it on
to emit_move_change_mode. Update callers.
(emit_move_complex): Pass true to new force argument.
* function.c (expand_function_end): Move expand_eh_return call
earlier. Merge sub-word complex values into a pseudo before
copying to the return hard register.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.816
diff -u -p -d -r1.816 expr.c
--- expr.c 9 Sep 2005 01:37:29 -0000 1.816
+++ expr.c 17 Sep 2005 18:27:50 -0000
@@ -2812,7 +2812,7 @@ emit_move_change_mode (enum machine_mode
emitted, or NULL if such a move could not be generated. */
static rtx
-emit_move_via_integer (enum machine_mode mode, rtx x, rtx y)
+emit_move_via_integer (enum machine_mode mode, rtx x, rtx y, bool force)
{
enum machine_mode imode;
enum insn_code code;
@@ -2827,10 +2827,10 @@ emit_move_via_integer (enum machine_mode
if (code == CODE_FOR_nothing)
return NULL_RTX;
- x = emit_move_change_mode (imode, mode, x, false);
+ x = emit_move_change_mode (imode, mode, x, force);
if (x == NULL_RTX)
return NULL_RTX;
- y = emit_move_change_mode (imode, mode, y, false);
+ y = emit_move_change_mode (imode, mode, y, force);
if (y == NULL_RTX)
return NULL_RTX;
return emit_insn (GEN_FCN (code) (x, y));
@@ -2973,7 +2973,7 @@ emit_move_complex (enum machine_mode mod
return get_last_insn ();
}
- ret = emit_move_via_integer (mode, x, y);
+ ret = emit_move_via_integer (mode, x, y, true);
if (ret)
return ret;
}
@@ -3011,7 +3011,7 @@ emit_move_ccmode (enum machine_mode mode
}
/* Otherwise, find the MODE_INT mode of the same width. */
- ret = emit_move_via_integer (mode, x, y);
+ ret = emit_move_via_integer (mode, x, y, false);
gcc_assert (ret != NULL);
return ret;
}
@@ -3119,7 +3119,7 @@ emit_move_insn_1 (rtx x, rtx y)
fits within a HOST_WIDE_INT. */
if (!CONSTANT_P (y) || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{
- rtx ret = emit_move_via_integer (mode, x, y);
+ rtx ret = emit_move_via_integer (mode, x, y, false);
if (ret)
return ret;
}
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.644
diff -u -p -d -r1.644 function.c
--- function.c 7 Sep 2005 07:47:08 -0000 1.644
+++ function.c 17 Sep 2005 18:27:51 -0000
@@ -4403,6 +4403,10 @@ expand_function_end (void)
if (flag_exceptions && USING_SJLJ_EXCEPTIONS)
sjlj_emit_function_exit_after (get_last_insn ());
+ /* If this is an implementation of throw, do what's necessary to
+ communicate between __builtin_eh_return and the epilogue. */
+ expand_eh_return ();
+
/* 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. */
@@ -4464,6 +4468,24 @@ expand_function_end (void)
TREE_TYPE (decl_result),
int_size_in_bytes (TREE_TYPE (decl_result)));
}
+ /* In the case of complex integer modes smaller than a word, we'll
+ need to generate some non-trivial bitfield insertions. Do that
+ on a pseudo and not the hard register. */
+ else if (GET_CODE (decl_rtl) == CONCAT
+ && GET_MODE_CLASS (GET_MODE (decl_rtl)) == MODE_COMPLEX_INT
+ && GET_MODE_BITSIZE (GET_MODE (decl_rtl)) <= BITS_PER_WORD)
+ {
+ int old_generating_concat_p;
+ rtx tmp;
+
+ old_generating_concat_p = generating_concat_p;
+ generating_concat_p = 0;
+ tmp = gen_reg_rtx (GET_MODE (decl_rtl));
+ generating_concat_p = old_generating_concat_p;
+
+ emit_move_insn (tmp, decl_rtl);
+ emit_move_insn (real_decl_rtl, tmp);
+ }
else
emit_move_insn (real_decl_rtl, decl_rtl);
}
@@ -4505,10 +4527,6 @@ expand_function_end (void)
current_function_return_rtx = outgoing;
}
- /* If this is an implementation of throw, do what's necessary to
- communicate between __builtin_eh_return and the epilogue. */
- expand_eh_return ();
-
/* Emit the actual code to clobber return register. */
{
rtx seq;