diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2012-10-23 14:40:07 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-10-23 14:40:07 +0000 |
commit | 3b601ca3eb1cb588cc0383c9480eb6fcb986ea2d (patch) | |
tree | 24d37e2d6914736c1bee09bde10d8ad7b3d8a934 | |
parent | a8dcc458896307fb03bb3b8c56c33a1b860837c4 (diff) | |
download | gcc-3b601ca3eb1cb588cc0383c9480eb6fcb986ea2d.zip gcc-3b601ca3eb1cb588cc0383c9480eb6fcb986ea2d.tar.gz gcc-3b601ca3eb1cb588cc0383c9480eb6fcb986ea2d.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/ada/system-linux-mips.ads | 4 | ||||
-rw-r--r-- | gcc/ada/system-linux-mips64el.ads | 4 | ||||
-rw-r--r-- | gcc/ada/system-linux-mipsel.ads | 4 | ||||
-rw-r--r-- | gcc/config/mips/linux-common.h | 6 | ||||
-rw-r--r-- | gcc/config/mips/mips-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 142 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 9 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 14 |
10 files changed, 199 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 24839c4..8b53079 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cd31f01..001a8d9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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 diff --git a/gcc/ada/system-linux-mips.ads b/gcc/ada/system-linux-mips.ads index 885995c..18f4495 100644 --- a/gcc/ada/system-linux-mips.ads +++ b/gcc/ada/system-linux-mips.ads @@ -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; diff --git a/gcc/ada/system-linux-mips64el.ads b/gcc/ada/system-linux-mips64el.ads index de3215b..85a0f41 100644 --- a/gcc/ada/system-linux-mips64el.ads +++ b/gcc/ada/system-linux-mips64el.ads @@ -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; diff --git a/gcc/ada/system-linux-mipsel.ads b/gcc/ada/system-linux-mipsel.ads index a25642a..c700048 100644 --- a/gcc/ada/system-linux-mipsel.ads +++ b/gcc/ada/system-linux-mipsel.ads @@ -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; diff --git a/gcc/config/mips/linux-common.h b/gcc/config/mips/linux-common.h index b811b46..5135905 100644 --- a/gcc/config/mips/linux-common.h +++ b/gcc/config/mips/linux-common.h @@ -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) diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index f2c5c0d..3aaf5f3 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -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); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index bbd0fc4..b867592 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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. */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index e04f099..308b59b 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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 diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index c7dd875..f6a1312 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -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)] "" |