diff options
author | Geoff Keating <geoffk@cygnus.com> | 1999-12-04 03:00:04 +0000 |
---|---|---|
committer | Geoffrey Keating <geoffk@gcc.gnu.org> | 1999-12-04 03:00:04 +0000 |
commit | a157febd0ca69d5b4570fc714c141fd5da555a7a (patch) | |
tree | 9c9c8b5fa8e01f95d849e7b0f24402c7081b73d4 /gcc/config | |
parent | 3c12fcc27809a223032e1b0ad2beba1f6844a5c6 (diff) | |
download | gcc-a157febd0ca69d5b4570fc714c141fd5da555a7a.zip gcc-a157febd0ca69d5b4570fc714c141fd5da555a7a.tar.gz gcc-a157febd0ca69d5b4570fc714c141fd5da555a7a.tar.bz2 |
c-common.c (enum attrs): Add A_NO_LIMIT_STACK.
* c-common.c (enum attrs): Add A_NO_LIMIT_STACK.
(init_attributes): Add A_NO_LIMIT_STACK.
(decl_attributes): Handle A_NO_LIMIT_STACK.
* c-decl.c (duplicate_decls): Handle DECL_NO_LIMIT_STACK.
* explow.c (allocate_dynamic_stack_space) [!HAVE_allocate_stack]:
Handle stack bounds checking.
* flags.h (flag_stack_check): Use the word 'probe' rather than
'check', because the flag doesn't actually cause any checking to
be done.
* function.c (expand_function_start): Set
current_function_limit_stack.
* function.h (struct function): Add limit_stack.
(current_function_limit_stack): Define.
* invoke.texi (Code Gen Options): Document new options.
* rtl.h: Declare stack_limit_rtx.
* toplev.c (stack_limit_rtx): New variable.
(decode_f_option): Handle new options -fstack-limit-register=REG,
-fstack-limit-symbol=IDENT, -fno-stack-limit.
(main): Add stack_limit_rtx as GC root.
* tree.h (DECL_NO_LIMIT_STACK): New macro.
(struct tree_decl): New member no_limit_stack.
* config/rs6000/rs6000.c (rs6000_allocate_stack_space): Handle
stack_limit_rtx.
* config/rs6000/rs6000.md (allocate_stack): Handle stack_limit_rtx.
(conditional_trap+1): Get new mnemonic correct.
(conditional_trap+2): New pattern for DImode traps.
* config/m68k/m68k.c (output_function_prologue): Handle
stack_limit_rtx.
* config/m68k/m68k.md (trap): New insn.
(conditional_trap): New insn.
* md.texi (Standard Names): Document `trap' and
`conditional_trap'.
* optabs.c (gen_cond_trap): Use start_sequence()/end_sequence()
so a cc0 setter doesn't get emitted at some random place in the
function.
* config/i960/i960.md (trap): New insn.
(conditional_trap): New expander.
(conditional_trap+1, conditional_trap+2): New insns for signed
and unsigned cases.
* config/i960/i960.c (i960_function_prologue): Use
STARTING_FRAME_OFFSET. Handle stack_limit_rtx.
Co-Authored-By: Greg McGary <gkm@gnu.org>
From-SVN: r30771
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i960/i960.c | 31 | ||||
-rw-r--r-- | gcc/config/i960/i960.md | 33 | ||||
-rw-r--r-- | gcc/config/m68k/m68k.c | 31 | ||||
-rw-r--r-- | gcc/config/m68k/m68k.md | 28 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 47 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 20 |
6 files changed, 188 insertions, 2 deletions
diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c index c7dc008..0c9ae30 100644 --- a/gcc/config/i960/i960.c +++ b/gcc/config/i960/i960.c @@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */ #include "except.h" #include "function.h" #include "recog.h" +#include "toplev.h" #include <math.h> /* Save the operands last given to a compare for use when we @@ -1431,6 +1432,34 @@ i960_function_prologue (file, size) actual_fsize = (actual_fsize + 15) & ~0xF; #endif + /* Check stack limit if necessary. */ + if (current_function_limit_stack) + { + rtx min_stack = stack_limit_rtx; + if (actual_fsize != 0) + min_stack = plus_constant (stack_limit_rtx, -actual_fsize); + + /* Now, emulate a little bit of reload. We want to turn 'min_stack' + into an arith_operand. Use register 20 as the temporary. */ + if (legitimate_address_p (Pmode, min_stack, 1) + && !arith_operand (min_stack, Pmode)) + { + rtx tmp = gen_rtx_MEM (Pmode, min_stack); + fputs ("\tlda\t", file); + i960_print_operand (file, tmp, 0); + fputs (",r4\n", file); + min_stack = gen_rtx_REG (Pmode, 20); + } + if (arith_operand (min_stack, Pmode)) + { + fputs ("\tcmpo\tsp,", file); + i960_print_operand (file, min_stack, 0); + fputs ("\n\tfaultge.f\n", file); + } + else + warning ("stack limit expression is not supported"); + } + /* Allocate space for register save and locals. */ if (actual_fsize > 0) { @@ -1443,7 +1472,7 @@ i960_function_prologue (file, size) /* Take hardware register save area created by the call instruction into account, but store them before the argument block area. */ lvar_size = actual_fsize - compute_frame_size (0) - n_saved_regs * 4; - offset = 64 + lvar_size; + offset = STARTING_FRAME_OFFSET + lvar_size; /* Save registers on stack if needed. */ /* ??? Is it worth to use the same algorithm as one for saving global registers in local registers? */ diff --git a/gcc/config/i960/i960.md b/gcc/config/i960/i960.md index 1e5c112..38c14ba 100644 --- a/gcc/config/i960/i960.md +++ b/gcc/config/i960/i960.md @@ -540,6 +540,39 @@ "cmp%S0%B0%X0 %2,%1,%l3" [(set_attr "type" "branch")]) +;; Now the trap instructions. The i960 appears to only have conditional +;; traps... + +(define_insn ("trap") + [(trap_if (const_int 1) (const_int 0))] + "" + "cmpo g0,g0 ; faulteq.t") + +(define_expand "conditional_trap" + [(trap_if (match_operator 0 "comparison_operator" + [(match_dup 2) (const_int 0)]) + (match_operand 1 "const_int_operand" "i"))] + "" + " +{ + operands[2] = gen_compare_reg (GET_CODE (operands[0]), + i960_compare_op0, i960_compare_op1); +}") + +(define_insn "" + [(trap_if (match_operator 0 "comparison_operator" + [(reg:CC 36) (const_int 0)]) + (match_operand 1 "const_int_operand" "i"))] + "" + "fault%C0.f") + +(define_insn "" + [(trap_if (match_operator 0 "comparison_operator" + [(reg:CC_UNS 36) (const_int 0)]) + (match_operand 1 "const_int_operand" "i"))] + "" + "fault%C0.f") + ;; Normal move instructions. ;; This code is based on the sparc machine description. diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index f718ccd..8a798b7 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -151,6 +151,19 @@ output_function_prologue (stream, size) int fsize = (size + 3) & -4; int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset; + /* If the stack limit is a symbol, we can check it here, + before actually allocating the space. */ + if (current_function_limit_stack + && GET_CODE (stack_limit_rtx) == SYMBOL_REF) + { +#if defined (MOTOROLA) + asm_fprintf (stream, "\tcmp.l %0I%s+%d,%Rsp\n\ttrapcs\n", + XSTR (stack_limit_rtx, 0), fsize + 4); +#else + asm_fprintf (stream, "\tcmpl %0I%s+%d,%Rsp\n\ttrapcs\n", + XSTR (stack_limit_rtx, 0), fsize + 4); +#endif + } if (frame_pointer_needed) { @@ -374,6 +387,24 @@ output_function_prologue (stream, size) #endif #endif + /* If the stack limit is not a symbol, check it here. + This has the disadvantage that it may be too late... */ + if (current_function_limit_stack) + { + if (REG_P (stack_limit_rtx)) + { +#if defined (MOTOROLA) + asm_fprintf (stream, "\tcmp.l %s,%Rsp\n\ttrapcs\n", + reg_names[REGNO (stack_limit_rtx)]); +#else + asm_fprintf (stream, "\tcmpl %s,%Rsp\n\ttrapcs\n", + reg_names[REGNO (stack_limit_rtx)]); +#endif + } + else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF) + warning ("stack limit expression is not supported"); + } + if (num_saved_regs <= 2) { /* Store each separately in the same order moveml uses. diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 8a95259..6217719 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -7897,3 +7897,31 @@ (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))] "TARGET_68881 && flag_fast_math" "fcos%.x %1,%0") + +(define_insn "trap" + [(trap_if (const_int -1) (const_int 7))] + "" + "trap %#7") + +(define_insn "conditional_trap" + [(trap_if (match_operator 0 "valid_dbcc_comparison_p" + [(cc0) (const_int 0)]) + (match_operand:SI 1 "const_int_operand" "I"))] + "TARGET_68020 && ! flags_in_68881 ()" + "* +{ + switch (GET_CODE (operands[0])) + { + case EQ: return \"trapeq\"; + case NE: return \"trapne\"; + case GT: return \"trapgt\"; + case GTU: return \"traphi\"; + case LT: return \"traplt\"; + case LTU: return \"trapcs\"; + case GE: return \"trapge\"; + case GEU: return \"trapcc\"; + case LE: return \"traple\"; + case LEU: return \"trapls\"; + default: abort(); + } +}") diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 250c8cd..a8db6d0 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4176,6 +4176,53 @@ rs6000_allocate_stack_space (file, size, copy_r12) int copy_r12; { int neg_size = -size; + + if (current_function_limit_stack) + { + if (REG_P (stack_limit_rtx) + && REGNO (stack_limit_rtx) > 1 + && REGNO (stack_limit_rtx) <= 31) + { + if (size <= 32767) + asm_fprintf (file, "\t{cal %s,%d(%s)|addi %s,%s,%d}\n", + reg_names[0], reg_names[REGNO (stack_limit_rtx)], + size); + else + { + asm_fprintf (file, "\t{cau|addis} %s,%s,0x%x\n", + reg_names[0], reg_names[REGNO (stack_limit_rtx)], + ((size + 0x8000) >> 16) & 0xffff); + asm_fprintf (file, "\t{ai|addic} %s,%s,%d\n", + reg_names[0], reg_names[0], + (size & 0x7fff) | -(size & 0x8000)); + } + if (TARGET_32BIT) + asm_fprintf (file, "\t{t|tw}llt %s,%s\n", + reg_names[1], reg_names[0]); + else + asm_fprintf (file, "\ttdllt %s,%s\n", reg_names[1], reg_names[0]); + } + else if (GET_CODE (stack_limit_rtx) == SYMBOL_REF + && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)) + { + char * l_name = XSTR (stack_limit_rtx, 0); + const char * stripped_name; + + STRIP_NAME_ENCODING (stripped_name, l_name); + asm_fprintf (file, "\t{liu|lis} %s,%s@ha+%d\n", + reg_names[0], stripped_name, size); + asm_fprintf (file, "\t{ai|addic} %s,%s,%s@l+%d\n", + reg_names[0], reg_names[0], stripped_name, size); + if (TARGET_32BIT) + asm_fprintf (file, "\t{t|tw}llt %s,%s\n", + reg_names[1], reg_names[0]); + else + asm_fprintf (file, "\ttdllt %s,%s\n", reg_names[1], reg_names[0]); + } + else + warning ("stack limit expression is not supported"); + } + if (TARGET_UPDATE) { if (size < 32767) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 8d6e85c..bde6369 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -7882,6 +7882,16 @@ emit_move_insn (chain, stack_bot); + /* Check stack bounds if necessary. */ + if (current_function_limit_stack) + { + rtx available; + available = expand_binop (Pmode, sub_optab, + stack_pointer_rtx, stack_limit_rtx, + NULL_RTX, 1, OPTAB_WIDEN); + emit_insn (gen_cond_trap (LTU, available, operands[1], const0_rtx)); + } + /* Under Windows NT, we need to add stack probes for large/variable allocations, so do it via a call to the external function alloca instead of doing it inline. */ @@ -11151,4 +11161,12 @@ (match_operand:SI 2 "reg_or_short_operand" "rI")]) (const_int 0))] "" - "t%V0%I2 %1,%2") + "{t|tw}%V0%I2 %1,%2") + +(define_insn "" + [(trap_if (match_operator 0 "trap_comparison_operator" + [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "reg_or_short_operand" "rI")]) + (const_int 0))] + "TARGET_POWERPC64" + "td%V0%I2 %1,%2") |