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]

Re: [PATCH] Stack protector ppc/ppc64 support


On Mon, Jun 27, 2005 at 10:36:03AM -0400, David Edelsohn wrote:
> 	I guess we cannot simplify it easily at the moment.  If mode macro
> "P" could be used, then the body becomes
> 
> {
>   emit_insn (gen_stack_protect_set<mode> (operands[0], operands[1]));
>   DONE;
> }

This can't be used in the expander, since the expander itself is not
<mode> pattern, there is just one expander for both 32-bit and 64-bit
target, called gen_stack_protect_set.

> On current POWER processors, "xor." internally is split into "xor" and
> "cmp", and the "li" provide some ILP.  It would be nice to include the
> non-cr0 versions.

So, do you prefer following patch instead of the one I sent before?
Or another variant, which would always use the 5 insn sequence
for stack_protect_test<mode>, unless optimize_size?

BTW, the patch depends on
http://gcc.gnu.org/ml/gcc-patches/2005-06/msg01871.html,
so can you please review that patch as well?  Thanks.

2005-06-28  Jakub Jelinek  <jakub@redhat.com>

	* function.c (stack_protect_epilogue): Pass label to
	stack_protect_test, assume it emitted also the conditional
	branch.
	* doc/md.texi (stack_protect_test): Adjust documentation.
	* config/i386/i386.md (stack_protect_test): Add third argument,
	emit beq with operands[2].
	* config/rs6000/rs6000.h (FRAME_GROWS_DOWNWARD): Define to
	flag_stack_protect != 0.
	* config/rs6000/rs6000.md (UNSPEC_SP_SET, UNSPEC_SP_TEST): New
	constants.
	(stack_protect_set, stack_protect_test): New expanders.
	(stack_protect_setsi, stack_protect_setdi, stack_protect_testsi,
	stack_protect_testdi): New insns.
	* config/rs6000/rs6000.c (rs6000_stack_protect_fail): New function.
	(TARGET_STACK_PROTECT_FAIL): Define.
	(rs6000_generate_compare): Handle UNSPEC_SP_TEST.

--- gcc/config/rs6000/rs6000.h.jj	2005-06-22 15:11:20.000000000 +0200
+++ gcc/config/rs6000/rs6000.h	2005-06-23 11:33:33.000000000 +0200
@@ -1226,7 +1226,7 @@ extern enum rs6000_abi rs6000_current_ab
 
    On the RS/6000, we grow upwards, from the area after the outgoing
    arguments.  */
-#define FRAME_GROWS_DOWNWARD 0
+#define FRAME_GROWS_DOWNWARD (flag_stack_protect != 0)
 
 /* Size of the outgoing register save area */
 #define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX			\
--- gcc/config/rs6000/rs6000.md.jj	2005-06-17 17:09:36.000000000 +0200
+++ gcc/config/rs6000/rs6000.md	2005-06-28 18:10:44.000000000 +0200
@@ -59,6 +59,8 @@
    (UNSPEC_ISYNC		37)
    (UNSPEC_POPCNTB		38)
    (UNSPEC_FRES			39)
+   (UNSPEC_SP_SET		40)
+   (UNSPEC_SP_TEST		41)
   ])
 
 ;;
@@ -14383,6 +14385,71 @@
   ""
   ".long 0x7c2004ac")
 
+(define_expand "stack_protect_set"
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "memory_operand" "")]
+  ""
+{
+  if (TARGET_64BIT)
+    emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+  else
+    emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+  DONE;
+})
+
+(define_insn "stack_protect_set<mode>"
+  [(set (match_operand:P 0 "memory_operand" "=m")
+	(unspec:P [(match_operand:P 1 "memory_operand" "m")] UNSPEC_SP_SET))
+   (set (match_scratch:P 2 "=&r") (const_int 0))]
+  ""
+{
+  if (TARGET_64BIT)
+    return "ld%U1%X1 %2,%1\;std%U0%X0 %2,%0\;{lil|li} %2,0";
+  else
+    return "{l%U1%X1|lwz%U1%X1} %2,%1\;{st%U0%X0|stw%U0%X0} %2,%0\;{lil|li} %2,0";
+}
+  [(set_attr "type" "three")
+   (set_attr "length" "12")])
+
+(define_expand "stack_protect_test"
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "memory_operand" "")
+   (match_operand 2 "" "")]
+  ""
+{
+  rs6000_compare_op0 = operands[0];
+  rs6000_compare_op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]),
+				       UNSPEC_SP_TEST);
+  rs6000_compare_fp_p = 0;
+  emit_jump_insn (gen_beq (operands[2]));
+  DONE;
+})
+
+(define_insn "stack_protect_test<mode>"
+  [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,=?y")
+        (unspec:CCEQ [(match_operand:P 1 "memory_operand" "m,m")
+		      (match_operand:P 2 "memory_operand" "m,m")]
+		     UNSPEC_SP_TEST))
+   (clobber (match_scratch:P 3 "=r,r"))
+   (set (match_scratch:P 4 "=&r,&r") (const_int 0))]
+  ""
+{
+  if (which_alternative == 1)
+    {
+      if (TARGET_64BIT)
+	return "ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;cmpld %0,%3,%4\;{lil|li} %3,0\;{lil|li} %4,0";
+      else
+	return "{l%U1%X1|lwz%U1%X1} %3,%1\;{l%U2%X2|lwz%U2%X2} %4,%2\;{cmpl|cmplw} %0,%3,%4\;\;{lil|li} %3,0\;{lil|li} %4,0";
+    }
+  else
+    {
+      if (TARGET_64BIT)
+	return "ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0";
+      else
+	return "{l%U1%X1|lwz%U1%X1} %3,%1\;{l%U2%X2|lwz%U2%X2} %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0";
+    }
+}
+  [(set_attr "length" "16,20")])
 
 
 (include "altivec.md")
--- gcc/config/rs6000/rs6000.c.jj	2005-06-22 16:44:07.000000000 +0200
+++ gcc/config/rs6000/rs6000.c	2005-06-24 21:58:29.000000000 +0200
@@ -728,7 +728,7 @@ static rtx rs6000_emit_vector_compare (e
 				       enum machine_mode);
 static int get_vsel_insn (enum machine_mode);
 static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
-
+static tree rs6000_stack_protect_fail (void);
 
 const int INSN_NOT_AVAILABLE = -1;
 static enum machine_mode rs6000_eh_return_filter_mode (void);
@@ -973,6 +973,9 @@ static const char alt_reg_names[][8] =
 #define TARGET_DEFAULT_TARGET_FLAGS \
   (TARGET_DEFAULT | MASK_SCHED_PROLOG)
 
+#undef TARGET_STACK_PROTECT_FAIL
+#define TARGET_STACK_PROTECT_FAIL rs6000_stack_protect_fail
+
 /* MPC604EUM 3.5.2 Weak Consistency between Multiple Processors
    The PowerPC architecture requires only weak consistency among
    processors--that is, memory accesses between processors need not be
@@ -10585,6 +10588,19 @@ rs6000_generate_compare (enum rtx_code c
 		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
 		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
 		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)))));
+      else if (GET_CODE (rs6000_compare_op1) == UNSPEC
+	       && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST)
+	{
+	  rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0);
+	  comp_mode = CCEQmode;
+	  compare_result = gen_reg_rtx (CCEQmode);
+	  if (TARGET_64BIT)
+	    emit_insn (gen_stack_protect_testdi (compare_result,
+						 rs6000_compare_op0, op1));
+	  else
+	    emit_insn (gen_stack_protect_testsi (compare_result,
+						 rs6000_compare_op0, op1));
+	}
       else
 	emit_insn (gen_rtx_SET (VOIDmode, compare_result,
 				gen_rtx_COMPARE (comp_mode,
@@ -18367,4 +18383,17 @@ invalid_arg_for_unprototyped_fn (tree ty
 	  : NULL;
 }
 
+/* For TARGET_SECURE_PLT 32-bit PIC code we can save PIC register
+   setup by using __stack_chk_fail_local hidden function instead of
+   calling __stack_chk_fail directly.  Otherwise it is better to call
+   __stack_chk_fail directly.  */
+
+static tree
+rs6000_stack_protect_fail (void)
+{
+  return (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
+	 ? default_hidden_stack_protect_fail ()
+	 : default_external_stack_protect_fail ();
+}
+
 #include "gt-rs6000.h"
--- gcc/config/i386/i386.md.jj	2005-06-24 21:51:55.000000000 +0200
+++ gcc/config/i386/i386.md	2005-06-24 21:53:13.000000000 +0200
@@ -19630,7 +19630,8 @@
 
 (define_expand "stack_protect_test"
   [(match_operand 0 "memory_operand" "")
-   (match_operand 1 "memory_operand" "")]
+   (match_operand 1 "memory_operand" "")
+   (match_operand 2 "" "")]
   ""
 {
   rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
@@ -19642,6 +19643,7 @@
     emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
   else
     emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
+  emit_jump_insn (gen_beq (operands[2]));
   DONE;
 })
 
--- gcc/function.c.jj	2005-06-22 19:06:11.000000000 +0200
+++ gcc/function.c	2005-06-24 21:49:51.000000000 +0200
@@ -3995,11 +3995,10 @@ stack_protect_epilogue (void)
   switch (HAVE_stack_protect_test != 0)
     {
     case 1:
-      tmp = gen_stack_protect_test (x, y);
+      tmp = gen_stack_protect_test (x, y, label);
       if (tmp)
 	{
 	  emit_insn (tmp);
-	  emit_jump_insn (bcc_gen_fctn[EQ] (label));
 	  break;
 	}
       /* FALLTHRU */
--- gcc/doc/md.texi.jj	2005-06-22 19:06:11.000000000 +0200
+++ gcc/doc/md.texi	2005-06-24 23:14:08.000000000 +0200
@@ -4110,13 +4110,11 @@ If this pattern is not defined, then a p
 
 This pattern, if defined, compares a @code{Pmode} value from the
 memory in operand 1 with the memory in operand 0 without leaving the
-value in a register afterward.  Further, it initializes the data
-structures in the target as if the normal @code{cmp@var{mode}} 
-pattern had been emitted.  If the pattern does not @code{FAIL}, then
-the rtl expanders will be invoking either the @code{beq} or @code{bne}
-pattern to make use of the comparison.
+value in a register afterward and branches to operand 2 if the values
+weren't equal.
 
-If this pattern is not defined, then a plain compare pattern is used.
+If this pattern is not defined, then a plain compare pattern and
+conditional branch pattern is used.
 
 @end table
 


	Jakub


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