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
This commit is contained in:
Geoff Keating 1999-12-04 03:00:04 +00:00 committed by Geoffrey Keating
parent 3c12fcc278
commit a157febd0c
21 changed files with 401 additions and 7 deletions

View File

@ -1,3 +1,51 @@
1999-12-04 Geoffrey Keating <geoffk@cygnus.com>
Greg McGary <gkm@gnu.org>
* 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.
Thu Dec 2 21:22:45 1999 Greg McGary <gkm@gnu.org>
Geoffrey Keating <geoffk@cygnus.com>

View File

@ -140,7 +140,8 @@ int skip_evaluation;
enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_MALLOC};
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_MALLOC,
A_NO_LIMIT_STACK};
enum format_type { printf_format_type, scanf_format_type,
strftime_format_type };
@ -482,6 +483,7 @@ init_attributes ()
add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
add_attribute (A_MALLOC, "malloc", 0, 0, 1);
add_attribute (A_NO_LIMIT_STACK, "no_stack_limit", 0, 0, 1);
}
/* Default implementation of valid_lang_attribute, below. By default, there
@ -1038,6 +1040,23 @@ decl_attributes (node, attributes, prefix_attributes)
else
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
break;
case A_NO_LIMIT_STACK:
if (TREE_CODE (decl) != FUNCTION_DECL)
{
error_with_decl (decl,
"`%s' attribute applies only to functions",
IDENTIFIER_POINTER (name));
}
else if (DECL_INITIAL (decl))
{
error_with_decl (decl,
"can't set `%s' attribute after definition",
IDENTIFIER_POINTER (name));
}
else
DECL_NO_LIMIT_STACK (decl) = 1;
break;
}
}
}

View File

@ -1884,6 +1884,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_CHECK_MEMORY_USAGE (newdecl)
|= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
DECL_NO_LIMIT_STACK (newdecl)
|= DECL_NO_LIMIT_STACK (olddecl);
}
pop_obstacks ();

View File

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

View File

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

View File

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

View File

@ -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();
}
}")

View File

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

View File

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

View File

@ -1,3 +1,10 @@
1999-11-24 Geoffrey Keating <geoffk@cygnus.com>
Greg McGary <gkm@gnu.org>
* decl.c (duplicate_decls): Merge
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT,
DECL_NO_CHECK_MEMORY_USAGE, DECL_NO_LIMIT_STACK.
1999-12-02 Mike Stump <mrs@wrs.com>
* init.c (perform_member_init): Handle parse errors better.

View File

@ -3364,6 +3364,16 @@ duplicate_decls (newdecl, olddecl)
/* Keep the old rtl since we can safely use it. */
DECL_RTL (newdecl) = DECL_RTL (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_CHECK_MEMORY_USAGE (newdecl)
|= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
DECL_NO_LIMIT_STACK (newdecl)
|= DECL_NO_LIMIT_STACK (olddecl);
}
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */

View File

@ -1333,6 +1333,33 @@ allocate_dynamic_stack_space (size, target, known_align)
emit_move_insn (target, virtual_stack_dynamic_rtx);
#endif
size = convert_modes (Pmode, ptr_mode, size, 1);
/* Check stack bounds if necessary. */
if (current_function_limit_stack)
{
rtx available;
rtx space_available = gen_label_rtx ();
#ifdef STACK_GROWS_DOWNWARD
available = expand_binop (Pmode, sub_optab,
stack_pointer_rtx, stack_limit_rtx,
NULL_RTX, 1, OPTAB_WIDEN);
#else
available = expand_binop (Pmode, sub_optab,
stack_limit_rtx, stack_pointer_rtx,
NULL_RTX, 1, OPTAB_WIDEN);
#endif
emit_cmp_and_jump_insns (available, size, GEU, NULL_RTX, Pmode, 1,
0, space_available);
#ifdef HAVE_trap
if (HAVE_trap)
emit_insn (gen_trap ());
else
#endif
error ("stack limits not supported on this target");
emit_barrier ();
emit_label (space_available);
}
anti_adjust_stack (size);
#ifdef SETJMP_VIA_SAVE_AREA
if (setjmpless_size != NULL_RTX)

View File

@ -476,8 +476,8 @@ extern int flag_argument_noalias;
if alias analysis (in general) is enabled. */
extern int flag_strict_aliasing;
/* Emit code to check for stack overflow; also may cause large objects
to be allocated dynamically. */
/* Emit code to probe the stack, to help detect stack overflow; also
may cause large objects to be allocated dynamically. */
extern int flag_stack_check;
/* Do the full regmove optimization pass. */

View File

@ -5946,6 +5946,9 @@ expand_function_start (subr, parms_have_cleanups)
= (flag_instrument_function_entry_exit
&& ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
current_function_limit_stack
= (stack_limit_rtx != NULL_RTX && ! DECL_NO_LIMIT_STACK (subr));
/* If function gets a static chain arg, store it in the stack frame.
Do this first, so it gets the first stack slot offset. */
if (current_function_needs_context)

View File

@ -290,6 +290,10 @@ struct function
/* Nonzero if memory access checking be enabled in the current function. */
int check_memory_usage;
/* Nonzero if stack limit checking should be enabled in the current
function. */
int limit_stack;
/* Number of function calls seen so far in current function. */
int x_function_call_count;
@ -490,6 +494,7 @@ extern struct function *all_functions;
#define current_function_return_rtx (current_function->return_rtx)
#define current_function_instrument_entry_exit (current_function->instrument_entry_exit)
#define current_function_check_memory_usage (current_function->check_memory_usage)
#define current_function_limit_stack (current_function->limit_stack)
#define current_function_uses_pic_offset_table (current_function->uses_pic_offset_table)
#define current_function_uses_const_pool (current_function->uses_const_pool)
#define current_function_cannot_inline (current_function->cannot_inline)

View File

@ -439,6 +439,7 @@ in the following sections.
-freg-struct-return -fshared-data -fshort-enums
-fshort-double -fvolatile -fvolatile-global -fvolatile-static
-fverbose-asm -fpack-struct -fstack-check
-fstack-limit-register=@var{reg} -fstack-limit-symbol=@var{sym}
-fargument-alias -fargument-noalias
-fargument-noalias-global
-fleading-underscore
@ -7085,6 +7086,25 @@ environment with multiple threads, but only rarely need to specify it in
a single-threaded environment since stack overflow is automatically
detected on nearly all systems if there is only one stack.
Note that this switch does not actually cause checking to be done; the
operating system must do that. The switch causes generation of code
to ensure that the operating system sees the stack being extended.
@item -fstack-limit-register=@var{reg}
@itemx -fstack-limit-symbol=@var{sym}
@itemx -fno-stack-limit
Generate code to ensure that the stack does not grow beyond a certain value,
either the value of a register or the address of a symbol. If the stack
would grow beyond the value, a signal is raised. For most targets,
the signal is raised before the stack overruns the boundary, so
it is possible to catch the signal without taking special precautions.
For instance, if the stack starts at address @samp{0x80000000} and grows
downwards you can use the flags
@samp{-fstack-limit-symbol=__stack_limit}
@samp{-Wl,--defsym,__stack_limit=0x7ffe0000} which will enforce a stack
limit of 128K.
@cindex aliasing of parameters
@cindex parameters, aliased
@item -fargument-alias

View File

@ -2549,6 +2549,29 @@ sibling call (aka tail call) sites.
The @code{sibcall_epilogue} pattern must not clobber any arguments used for
parameter passing or any stack slots for arguments passed to the current
function.
@cindex @code{trap} instruction pattern
@item @samp{trap}
This pattern, if defined, signals an error, typically by causing some
kind of signal to be raised. Among other places, it is used by the Java
frontend to signal `invalid array index' exceptions.
@cindex @code{conditional_trap} instruction pattern
@item @samp{conditional_trap}
Conditional trap instruction. Operand 0 is a piece of RTL which
performs a comparison. Operand 1 is the trap code, an integer.
A typical @code{conditional_trap} pattern looks like
@smallexample
(define_insn "conditional_trap"
[(trap_if (match_operator 0 "trap_operator"
[(cc0) (const_int 0)])
(match_operand 1 "const_int_operand" "i"))]
""
"@dots{}")
@end smallexample
@end table
@node Pattern Ordering

View File

@ -4806,11 +4806,17 @@ gen_cond_trap (code, op1, op2, tcode)
&& cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
rtx insn;
start_sequence();
emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
PUT_CODE (trap_rtx, code);
insn = gen_conditional_trap (trap_rtx, tcode);
if (insn)
return insn;
{
emit_insn (insn);
insn = gen_sequence ();
}
end_sequence();
return insn;
}
#endif

View File

@ -1576,6 +1576,8 @@ extern void reg_scan PROTO ((rtx, int, int));
extern void reg_scan_update PROTO ((rtx, rtx, int));
extern void fix_register PROTO ((const char *, int, int));
extern void delete_null_pointer_checks PROTO ((rtx));
/* In regmove.c */
#ifdef BUFSIZ
extern void regmove_optimize PROTO ((rtx, int, FILE *));
@ -1703,6 +1705,8 @@ extern rtx addr_side_effect_eval PROTO ((rtx, int, int));
extern int stack_regs_mentioned PROTO((rtx insn));
#endif
/* In toplev.c */
extern rtx stack_limit_rtx;
extern void delete_null_pointer_checks PROTO ((rtx));
#endif /* _RTL_H */

View File

@ -720,6 +720,15 @@ int flag_pack_struct = 0;
to be allocated dynamically. */
int flag_stack_check;
/* When non-NULL, indicates that whenever space is allocated on the
stack, the resulting stack pointer must not pass this
address---that is, for stacks that grow downward, the stack pointer
must always be greater than or equal to this address; for stacks
that grow upward, the stack pointer must be less than this address.
At present, the rtx may be either a REG or a SYMBOL_REF, although
the support provided depends on the backend. */
rtx stack_limit_rtx;
/* -fcheck-memory-usage causes extra code to be generated in order to check
memory accesses. This is used by a detector of bad memory accesses such
as Checker. */
@ -4889,6 +4898,25 @@ decode_f_option (arg)
align_jumps = read_integral_parameter (arg + 12, arg - 2, align_jumps);
else if (!strncmp (arg, "align-labels=", 13))
align_labels = read_integral_parameter (arg + 13, arg - 2, align_labels);
else if (!strncmp (arg, "stack-limit-register=", 21))
{
int reg = decode_reg_name (arg + 21);
if (reg < 0)
error ("unrecognized register name `%s'", arg + 21);
else
stack_limit_rtx = gen_rtx_REG (Pmode, reg);
}
else if (!strncmp (arg, "stack-limit-symbol=", 19))
{
char *nm;
if (ggc_p)
nm = ggc_alloc_string (arg + 19, strlen (arg + 19));
else
nm = xstrdup (arg + 19);
stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm);
}
else if (!strcmp (arg, "no-stack-limit"))
stack_limit_rtx = NULL_RTX;
else if (!strcmp (arg, "preprocessed"))
/* Recognise this switch but do nothing. This prevents warnings
about an unrecognised switch if cpplib has not been linked in. */
@ -5323,6 +5351,7 @@ main (argc, argv)
init_ggc ();
ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
&mark_file_stack);
ggc_add_rtx_root (&stack_limit_rtx, 1);
/* Perform language-specific options intialization. */
lang_init_options ();

View File

@ -1307,6 +1307,10 @@ struct tree_type
disabled in this function. */
#define DECL_NO_CHECK_MEMORY_USAGE(NODE) ((NODE)->decl.no_check_memory_usage)
/* Used in FUNCTION_DECLs to indicate that limit-stack-* should be
disabled in this function. */
#define DECL_NO_LIMIT_STACK(NODE) ((NODE)->decl.no_limit_stack)
/* Additional flags for language-specific uses. */
#define DECL_LANG_FLAG_0(NODE) (DECL_CHECK (NODE)->decl.lang_flag_0)
#define DECL_LANG_FLAG_1(NODE) (DECL_CHECK (NODE)->decl.lang_flag_1)
@ -1376,6 +1380,7 @@ struct tree_decl
unsigned no_check_memory_usage : 1;
unsigned comdat_flag : 1;
unsigned malloc_flag : 1;
unsigned no_limit_stack : 1;
/* For a FUNCTION_DECL, if inline, this is the size of frame needed.
If built-in, this is the code for which built-in function.