Commit 3b601ca3 by Eric Botcazou Committed by Eric Botcazou

linux-common.h (STACK_CHECK_STATIC_BUILTIN): Define.

	* config/mips/linux-common.h (STACK_CHECK_STATIC_BUILTIN): Define.
	(STACK_CHECK_PROTECT): Likewise.
	* config/mips/mips.h (MIPS_PROLOGUE_TEMP2_REGNUM): Likewise.
	(MIPS_PROLOGUE_TEMP2): Likewise.
	* config/mips/mips-protos.h (mips_output_probe_stack_range): Declare.
	* config/mips/mips.c: Include common/common-target.h.
	(mips_emit_probe_stack_range): New function.
	(mips_output_probe_stack_range): Likewise.
	(mips_expand_prologue): Invoke mips_emit_probe_stack_range if static
	builtin stack checking is enabled.
	* config/mips/mips.md (UNSPEC_PROBE_STACK_RANGE): New constant.
	(probe_stack_range_<P:mode>): New insn.
ada/
	* system-linux-mipsel.ads (Stack_Check_Probes): Set to True.
	* system-linux-mips.ads (Stack_Check_Probes): Likewise.
	* system-linux-mips64el.ads (Stack_Check_Probes): Likewise.

From-SVN: r192713
parent a8dcc458
2012-10-23 Eric Botcazou <ebotcazou@adacore.com>
* config/mips/linux-common.h (STACK_CHECK_STATIC_BUILTIN): Define.
(STACK_CHECK_PROTECT): Likewise.
* config/mips/mips.h (MIPS_PROLOGUE_TEMP2_REGNUM): Likewise.
(MIPS_PROLOGUE_TEMP2): Likewise.
* config/mips/mips-protos.h (mips_output_probe_stack_range): Declare.
* config/mips/mips.c: Include common/common-target.h.
(mips_emit_probe_stack_range): New function.
(mips_output_probe_stack_range): Likewise.
(mips_expand_prologue): Invoke mips_emit_probe_stack_range if static
builtin stack checking is enabled.
* config/mips/mips.md (UNSPEC_PROBE_STACK_RANGE): New constant.
(probe_stack_range_<P:mode>): New insn.
2012-10-23 Marc Glisse <marc.glisse@inria.fr>
* tree-ssa-forwprop.c (forward_propagate_into_cond): Handle vectors.
2012-10-23 Eric Botcazou <ebotcazou@adacore.com>
* system-linux-mipsel.ads (Stack_Check_Probes): Set to True.
* system-linux-mips.ads (Stack_Check_Probes): Likewise.
* system-linux-mips64el.ads (Stack_Check_Probes): Likewise.
2012-10-22 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Force
......
......@@ -7,7 +7,7 @@
-- S p e c --
-- (GNU-Linux/MIPS Version) --
-- --
-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
......@@ -128,7 +128,7 @@ private
Preallocated_Stacks : constant Boolean := False;
Signed_Zeros : constant Boolean := True;
Stack_Check_Default : constant Boolean := False;
Stack_Check_Probes : constant Boolean := False;
Stack_Check_Probes : constant Boolean := True;
Stack_Check_Limits : constant Boolean := False;
Support_64_Bit_Divides : constant Boolean := True;
Support_Aggregates : constant Boolean := True;
......
......@@ -7,7 +7,7 @@
-- S p e c --
-- (GNU-Linux/MIPS64EL Version) --
-- --
-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
......@@ -128,7 +128,7 @@ private
Preallocated_Stacks : constant Boolean := False;
Signed_Zeros : constant Boolean := True;
Stack_Check_Default : constant Boolean := False;
Stack_Check_Probes : constant Boolean := False;
Stack_Check_Probes : constant Boolean := True;
Stack_Check_Limits : constant Boolean := False;
Support_64_Bit_Divides : constant Boolean := True;
Support_Aggregates : constant Boolean := True;
......
......@@ -7,7 +7,7 @@
-- S p e c --
-- (GNU-Linux/MIPSEL Version) --
-- --
-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
......@@ -128,7 +128,7 @@ private
Preallocated_Stacks : constant Boolean := False;
Signed_Zeros : constant Boolean := True;
Stack_Check_Default : constant Boolean := False;
Stack_Check_Probes : constant Boolean := False;
Stack_Check_Probes : constant Boolean := True;
Stack_Check_Limits : constant Boolean := False;
Support_64_Bit_Divides : constant Boolean := True;
Support_Aggregates : constant Boolean := True;
......
......@@ -56,3 +56,9 @@ along with GCC; see the file COPYING3. If not see
GNU_USER_TARGET_ENDFILE_SPEC, \
GNU_USER_TARGET_MATHFILE_SPEC " " \
ANDROID_ENDFILE_SPEC)
/* Define this to be nonzero if static stack checking is supported. */
#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)
......@@ -316,6 +316,7 @@ extern const char *mips_output_sync (void);
extern const char *mips_output_sync_loop (rtx, rtx *);
extern unsigned int mips_sync_loop_insns (rtx, rtx *);
extern const char *mips_output_division (const char *, rtx *);
extern const char *mips_output_probe_stack_range (rtx, rtx);
extern unsigned int mips_hard_regno_nregs (int, enum machine_mode);
extern bool mips_linked_madd_p (rtx, rtx);
extern bool mips_store_data_bypass_p (rtx, rtx);
......
......@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "target.h"
#include "target-def.h"
#include "common/common-target.h"
#include "langhooks.h"
#include "sched-int.h"
#include "gimple.h"
......@@ -10613,6 +10614,144 @@ mips_emit_loadgp (void)
emit_insn (gen_loadgp_blockage ());
}
#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
mips_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
{
if (TARGET_MIPS16)
sorry ("-fstack-check=specific not implemented for MIPS16");
/* 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 (Pmode, stack_pointer_rtx,
-(first + i)));
emit_stack_probe (plus_constant (Pmode, 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 r3 = MIPS_PROLOGUE_TEMP (Pmode);
rtx r12 = MIPS_PROLOGUE_TEMP2 (Pmode);
/* 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, r3,
plus_constant (Pmode, stack_pointer_rtx,
-first)));
/* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
if (rounded_size > 32768)
{
emit_move_insn (r12, GEN_INT (rounded_size));
emit_insn (gen_rtx_SET (VOIDmode, r12,
gen_rtx_MINUS (Pmode, r3, r12)));
}
else
emit_insn (gen_rtx_SET (VOIDmode, r12,
plus_constant (Pmode, r3, -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. */
emit_insn (PMODE_INSN (gen_probe_stack_range, (r3, r3, r12)));
/* 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 (Pmode, r12, rounded_size - size));
}
/* Make sure nothing is scheduled before we are done. */
emit_insn (gen_blockage ());
}
/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
absolute addresses. */
const char *
mips_output_probe_stack_range (rtx reg1, rtx reg2)
{
static int labelno = 0;
char loop_lab[32], end_lab[32], tmp[64];
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;
strcpy (tmp, "%(%<beq\t%0,%1,");
output_asm_insn (strcat (tmp, &end_lab[1]), xops);
/* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
xops[1] = GEN_INT (-PROBE_INTERVAL);
if (TARGET_64BIT && TARGET_LONG64)
output_asm_insn ("daddiu\t%0,%0,%1", xops);
else
output_asm_insn ("addiu\t%0,%0,%1", xops);
/* Probe at TEST_ADDR and branch. */
fprintf (asm_out_file, "\tb\t");
assemble_name_raw (asm_out_file, loop_lab);
fputc ('\n', asm_out_file);
if (TARGET_64BIT)
output_asm_insn ("sd\t$0,0(%0)%)", xops);
else
output_asm_insn ("sw\t$0,0(%0)%)", xops);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, end_lab);
return "";
}
/* A for_each_rtx callback. Stop the search if *X is a kernel register. */
static int
......@@ -10652,6 +10791,9 @@ mips_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
/* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP
bytes beforehand; this is enough to cover the register save area
without going out of range. */
......
......@@ -1743,6 +1743,9 @@ struct mips_cpu_info {
- The prologue can use MIPS_PROLOGUE_TEMP as a general temporary
register. The register must not conflict with MIPS16_PIC_TEMP.
- If we aren't generating MIPS16 code, the prologue can also use
MIPS_PROLOGUE_TEMP2 as a general temporary register.
- The epilogue can use MIPS_EPILOGUE_TEMP as a general temporary
register.
......@@ -1759,6 +1762,10 @@ struct mips_cpu_info {
#define MIPS16_PIC_TEMP_REGNUM (GP_REG_FIRST + 2)
#define MIPS_PROLOGUE_TEMP_REGNUM \
(cfun->machine->interrupt_handler_p ? K0_REG_NUM : GP_REG_FIRST + 3)
#define MIPS_PROLOGUE_TEMP2_REGNUM \
(TARGET_MIPS16 \
? (gcc_unreachable (), INVALID_REGNUM) \
: cfun->machine->interrupt_handler_p ? K1_REG_NUM : GP_REG_FIRST + 12)
#define MIPS_EPILOGUE_TEMP_REGNUM \
(cfun->machine->interrupt_handler_p \
? K0_REG_NUM \
......@@ -1766,6 +1773,8 @@ struct mips_cpu_info {
#define MIPS16_PIC_TEMP gen_rtx_REG (Pmode, MIPS16_PIC_TEMP_REGNUM)
#define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM)
#define MIPS_PROLOGUE_TEMP2(MODE) \
gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP2_REGNUM)
#define MIPS_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_EPILOGUE_TEMP_REGNUM)
/* Define this macro if it is as good or better to call a constant
......
......@@ -137,6 +137,9 @@
;; MIPS16 casesi jump table dispatch.
UNSPEC_CASESI_DISPATCH
;; Stack checking.
UNSPEC_PROBE_STACK_RANGE
])
(define_constants
......@@ -6040,6 +6043,17 @@
[(set_attr "type" "ghost")
(set_attr "mode" "none")])
(define_insn "probe_stack_range_<P:mode>"
[(set (match_operand:P 0 "register_operand" "=d")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
(match_operand:P 2 "register_operand" "d")]
UNSPEC_PROBE_STACK_RANGE))]
""
{ return mips_output_probe_stack_range (operands[0], operands[2]); }
[(set_attr "type" "unknown")
(set_attr "can_delay" "no")
(set_attr "mode" "<MODE>")])
(define_expand "epilogue"
[(const_int 2)]
""
......
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