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
This commit is contained in:
Eric Botcazou 2012-10-23 14:40:07 +00:00 committed by Eric Botcazou
parent a8dcc45889
commit 3b601ca3eb
10 changed files with 199 additions and 6 deletions

View File

@ -1,3 +1,18 @@
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.

View File

@ -1,3 +1,9 @@
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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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. */

View File

@ -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

View File

@ -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)]
""