2005-06-24 Jakub Jelinek * 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-24 22:01:37.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,72 @@ "" ".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_setsi" + [(set (match_operand:SI 0 "memory_operand" "=m") + (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) + (set (match_scratch:SI 2 "=&r") (const_int 0))] + "TARGET_32BIT" + "{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_insn "stack_protect_setdi" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET)) + (set (match_scratch:DI 2 "=&r") (const_int 0))] + "TARGET_64BIT" + "ld%U1%X1 %2,%1\;std%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_testsi" + [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x") + (unspec:CCEQ [(match_operand:SI 1 "memory_operand" "m") + (match_operand:SI 2 "memory_operand" "m")] + UNSPEC_SP_TEST)) + (clobber (match_scratch:SI 3 "=r")) + (set (match_scratch:SI 4 "=&r") (const_int 0))] + "TARGET_32BIT" + "{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")]) + +(define_insn "stack_protect_testdi" + [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x") + (unspec:CCEQ [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "memory_operand" "m")] + UNSPEC_SP_TEST)) + (clobber (match_scratch:DI 3 "=r")) + (set (match_scratch:DI 4 "=&r") (const_int 0))] + "TARGET_64BIT" + "ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0" + [(set_attr "length" "16")]) + (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