Commit 39acb18f by Eric Botcazou Committed by Eric Botcazou

aix.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.

	* config/rs6000/aix.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/rs6000/linux.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	* config/rs6000/linux64.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	(STACK_CHECK_PROTECT): Define.
	* config/rs6000/rs6000.c (rs6000_emit_probe_stack_range): New function.
	(output_probe_stack_range): Likewise.
	(rs6000_emit_prologue): Invoke rs6000_emit_probe_stack_range if static
	builtin stack checking is enabled.
	* config/rs6000/rs6000-protos.h (output_probe_stack_range): Declare.
	* config/rs6000/rs6000.md (UNSPECV_PROBE_STACK_RANGE): New constant.
	(probe_stack_range): New insn.

From-SVN: r163424
parent 410841c6
2010-08-20 Eric Botcazou <ebotcazou@adacore.com>
* config/rs6000/aix.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
* config/rs6000/linux.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
* config/rs6000/linux64.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
(STACK_CHECK_PROTECT): Define.
* config/rs6000/rs6000.c (rs6000_emit_probe_stack_range): New function.
(output_probe_stack_range): Likewise.
(rs6000_emit_prologue): Invoke rs6000_emit_probe_stack_range if static
builtin stack checking is enabled.
* config/rs6000/rs6000-protos.h (output_probe_stack_range): Declare.
* config/rs6000/rs6000.md (UNSPECV_PROBE_STACK_RANGE): New constant.
(probe_stack_range): New insn.
2010-08-20 H.J. Lu <hongjiu.lu@intel.com> 2010-08-20 H.J. Lu <hongjiu.lu@intel.com>
PR target/45336 PR target/45336
......
...@@ -260,3 +260,6 @@ ...@@ -260,3 +260,6 @@
/* WINT_TYPE */ /* WINT_TYPE */
#define WINT_TYPE "int" #define WINT_TYPE "int"
/* Static stack checking is supported by means of probes. */
#define STACK_CHECK_STATIC_BUILTIN 1
...@@ -130,3 +130,6 @@ ...@@ -130,3 +130,6 @@
#ifdef TARGET_DEFAULT_LONG_DOUBLE_128 #ifdef TARGET_DEFAULT_LONG_DOUBLE_128
#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
#endif #endif
/* Static stack checking is supported by means of probes. */
#define STACK_CHECK_STATIC_BUILTIN 1
...@@ -573,3 +573,9 @@ extern enum rs6000_cmodel cmodel; ...@@ -573,3 +573,9 @@ extern enum rs6000_cmodel cmodel;
#ifdef TARGET_DEFAULT_LONG_DOUBLE_128 #ifdef TARGET_DEFAULT_LONG_DOUBLE_128
#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
#endif #endif
/* Static stack checking is supported by means of probes. */
#define STACK_CHECK_STATIC_BUILTIN 1
/* The default value isn't sufficient in 64-bit mode. */
#define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024)
...@@ -95,6 +95,7 @@ extern void rs6000_emit_sCOND (enum machine_mode, rtx[]); ...@@ -95,6 +95,7 @@ extern void rs6000_emit_sCOND (enum machine_mode, rtx[]);
extern void rs6000_emit_cbranch (enum machine_mode, rtx[]); extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
extern char * output_cbranch (rtx, const char *, int, rtx); extern char * output_cbranch (rtx, const char *, int, rtx);
extern char * output_e500_flip_gt_bit (rtx, rtx); extern char * output_e500_flip_gt_bit (rtx, rtx);
extern const char * output_probe_stack_range (rtx, rtx);
extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx); extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
......
...@@ -18788,6 +18788,137 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg) ...@@ -18788,6 +18788,137 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg)
GEN_INT (-size)))); GEN_INT (-size))));
} }
#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
#if PROBE_INTERVAL > 32768
#error Cannot use indexed addressing mode for stack probing
#endif
/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
inclusive. These are offsets from the current stack pointer. */
static void
rs6000_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
{
/* See if we have a constant small number of probes to generate. If so,
that's the easy case. */
if (first + size <= 32768)
{
HOST_WIDE_INT i;
/* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
it exceeds SIZE. If only one probe is needed, this will not
generate any code. Then probe at FIRST + SIZE. */
for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
emit_stack_probe (plus_constant (stack_pointer_rtx, -(first + i)));
emit_stack_probe (plus_constant (stack_pointer_rtx, -(first + size)));
}
/* Otherwise, do the same as above, but in a loop. Note that we must be
extra careful with variables wrapping around because we might be at
the very top (or the very bottom) of the address space and we have
to be able to handle this case properly; in particular, we use an
equality test for the loop condition. */
else
{
HOST_WIDE_INT rounded_size;
rtx r12 = gen_rtx_REG (Pmode, 12);
rtx r0 = gen_rtx_REG (Pmode, 0);
/* Sanity check for the addressing mode we're going to use. */
gcc_assert (first <= 32768);
/* Step 1: round SIZE to the previous multiple of the interval. */
rounded_size = size & -PROBE_INTERVAL;
/* Step 2: compute initial and final value of the loop counter. */
/* TEST_ADDR = SP + FIRST. */
emit_insn (gen_rtx_SET (VOIDmode, r12,
plus_constant (stack_pointer_rtx, -first)));
/* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
if (rounded_size > 32768)
{
emit_move_insn (r0, GEN_INT (-rounded_size));
emit_insn (gen_rtx_SET (VOIDmode, r0,
gen_rtx_PLUS (Pmode, r12, r0)));
}
else
emit_insn (gen_rtx_SET (VOIDmode, r0,
plus_constant (r12, -rounded_size)));
/* Step 3: the loop
while (TEST_ADDR != LAST_ADDR)
{
TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
probe at TEST_ADDR
}
probes at FIRST + N * PROBE_INTERVAL for values of N from 1
until it is equal to ROUNDED_SIZE. */
if (TARGET_64BIT)
emit_insn (gen_probe_stack_rangedi (r12, r12, r0));
else
emit_insn (gen_probe_stack_rangesi (r12, r12, r0));
/* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
that SIZE is equal to ROUNDED_SIZE. */
if (size != rounded_size)
emit_stack_probe (plus_constant (r12, rounded_size - size));
}
}
/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
absolute addresses. */
const char *
output_probe_stack_range (rtx reg1, rtx reg2)
{
static int labelno = 0;
char loop_lab[32], end_lab[32];
rtx xops[2];
ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno);
ASM_GENERATE_INTERNAL_LABEL (end_lab, "LPSRE", labelno++);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
/* Jump to END_LAB if TEST_ADDR == LAST_ADDR. */
xops[0] = reg1;
xops[1] = reg2;
if (TARGET_64BIT)
output_asm_insn ("{cmp|cmpd} 0,%0,%1", xops);
else
output_asm_insn ("{cmp|cmpw} 0,%0,%1", xops);
fputs ("\tbeq 0,", asm_out_file);
assemble_name_raw (asm_out_file, end_lab);
fputc ('\n', asm_out_file);
/* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
xops[1] = GEN_INT (-PROBE_INTERVAL);
output_asm_insn ("{cal %0,%1(%0)|addi %0,%0,%1}", xops);
/* Probe at TEST_ADDR and branch. */
output_asm_insn ("{st|stw} 0,0(%0)", xops);
fprintf (asm_out_file, "\tb ");
assemble_name_raw (asm_out_file, loop_lab);
fputc ('\n', asm_out_file);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, end_lab);
return "";
}
/* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced /* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced
with (plus:P (reg 1) VAL), and with REG2 replaced with RREG if REG2 with (plus:P (reg 1) VAL), and with REG2 replaced with RREG if REG2
is not NULL. It would be nice if dwarf2out_frame_debug_expr could is not NULL. It would be nice if dwarf2out_frame_debug_expr could
...@@ -19400,6 +19531,9 @@ rs6000_emit_prologue (void) ...@@ -19400,6 +19531,9 @@ rs6000_emit_prologue (void)
&& call_used_regs[STATIC_CHAIN_REGNUM]); && call_used_regs[STATIC_CHAIN_REGNUM]);
HOST_WIDE_INT sp_offset = 0; HOST_WIDE_INT sp_offset = 0;
if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && info->total_size)
rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT, info->total_size);
if (TARGET_FIX_AND_CONTINUE) if (TARGET_FIX_AND_CONTINUE)
{ {
/* gdb on darwin arranges to forward a function from the old /* gdb on darwin arranges to forward a function from the old
......
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
[(UNSPECV_BLOCK 0) [(UNSPECV_BLOCK 0)
(UNSPECV_LL 1) ; load-locked (UNSPECV_LL 1) ; load-locked
(UNSPECV_SC 2) ; store-conditional (UNSPECV_SC 2) ; store-conditional
(UNSPECV_PROBE_STACK_RANGE 3) ; probe range of stack addresses
(UNSPECV_EH_RR 9) ; eh_reg_restore (UNSPECV_EH_RR 9) ; eh_reg_restore
]) ])
...@@ -12663,6 +12664,15 @@ ...@@ -12663,6 +12664,15 @@
"{st%U0%X0|stw%U0%X0} 0,%0" "{st%U0%X0|stw%U0%X0} 0,%0"
[(set_attr "type" "store") [(set_attr "type" "store")
(set_attr "length" "4")]) (set_attr "length" "4")])
(define_insn "probe_stack_range<P:mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
(match_operand:P 2 "register_operand" "r")]
UNSPECV_PROBE_STACK_RANGE))]
""
"* return output_probe_stack_range (operands[0], operands[2]);"
[(set_attr "type" "three")])
;; Compare insns are next. Note that the RS/6000 has two types of compares, ;; Compare insns are next. Note that the RS/6000 has two types of compares,
;; signed & unsigned, and one type of branch. ;; signed & unsigned, and one type of branch.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment