This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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