This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]