re PR middle-end/20548 (ACATS c52103x c52104x c52104y segfault)
PR ada/20548 * common.opt (-fstack-check): Do not declare the variable here. (-fstack-check=): New option variant. * doc/invoke.texi (Code Gen Options): Document it. * expr.h (STACK_OLD_CHECK_PROTECT): New macro. (STACK_CHECK_PROTECT): Bump to 3 pages if DWARF-2 EH is used. (STACK_CHECK_STATIC_BUILTIN): New macro. * doc/tm.texi (Stack Checking): Document STACK_CHECK_STATIC_BUILTIN. * opts.c: Include expr.h. (common_handle_option) <OPT_fold_stack_check_>: New case. <OPT_fstack_check>: Likewise. * calls.c (initialize_argument_information): Use TYPE_SIZE_UNIT consistently in the test for variable-sized types. Adjust for new behaviour of flag_stack_check. * explow.c: Include except.h. (allocate_dynamic_stack_space): Do not take into account STACK_CHECK_MAX_FRAME_SIZE for static builtin stack checking. * function.c (gimplify_parameters): Use DECL_SIZE_UNIT in the test for variable-sized parameters. Treat all parameters whose size is greater than STACK_CHECK_MAX_VAR_SIZE as variable-sized if generic stack checking is enabled. * gimplify.c (gimplify_decl_expr): Treat non-static objects whose size is greater than STACK_CHECK_MAX_VAR_SIZE as variable-sized if generic stack checking is enabled. (expand_function_end): Adjust for new behaviour of flag_stack_check. * reload1.c (reload): Likewise. * stmt.c (expand_decl): Assert that all automatic variables have fixed size at this point and remove dead code. * flags.h (stack_check_type): New enumeration type. (flag_stack_check): Declare. * toplev.c (flag_stack_check): New global variable. * Makefile.in (opts.o): Add dependency on EXPR_H. (explow.o): Add dependency on except.h. ada/ * gcc-interface/decl.c (gnat_to_gnu_entity): Use DECL_SIZE_UNIT in the setjmp test consistently. Adjust for new behaviour of flag_stack_check. * gcc-interface/utils2.c (build_call_alloc_dealloc): Remove redundant test of flag_stack_check. Adjust for new behaviour of flag_stack_check. From-SVN: r139159
This commit is contained in:
parent
6c397102b2
commit
b38f3813f7
18 changed files with 233 additions and 95 deletions
|
@ -1,3 +1,39 @@
|
|||
2008-08-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR ada/20548
|
||||
* common.opt (-fstack-check): Do not declare the variable here.
|
||||
(-fstack-check=): New option variant.
|
||||
* doc/invoke.texi (Code Gen Options): Document it.
|
||||
* expr.h (STACK_OLD_CHECK_PROTECT): New macro.
|
||||
(STACK_CHECK_PROTECT): Bump to 3 pages if DWARF-2 EH is used.
|
||||
(STACK_CHECK_STATIC_BUILTIN): New macro.
|
||||
* doc/tm.texi (Stack Checking): Document STACK_CHECK_STATIC_BUILTIN.
|
||||
* opts.c: Include expr.h.
|
||||
(common_handle_option) <OPT_fold_stack_check_>: New case.
|
||||
<OPT_fstack_check>: Likewise.
|
||||
* calls.c (initialize_argument_information): Use TYPE_SIZE_UNIT
|
||||
consistently in the test for variable-sized types. Adjust for
|
||||
new behaviour of flag_stack_check.
|
||||
* explow.c: Include except.h.
|
||||
(allocate_dynamic_stack_space): Do not take into account
|
||||
STACK_CHECK_MAX_FRAME_SIZE for static builtin stack checking.
|
||||
* function.c (gimplify_parameters): Use DECL_SIZE_UNIT in the test
|
||||
for variable-sized parameters. Treat all parameters whose size is
|
||||
greater than STACK_CHECK_MAX_VAR_SIZE as variable-sized if generic
|
||||
stack checking is enabled.
|
||||
* gimplify.c (gimplify_decl_expr): Treat non-static objects whose
|
||||
size is greater than STACK_CHECK_MAX_VAR_SIZE as variable-sized
|
||||
if generic stack checking is enabled.
|
||||
(expand_function_end): Adjust for new behaviour of flag_stack_check.
|
||||
* reload1.c (reload): Likewise.
|
||||
* stmt.c (expand_decl): Assert that all automatic variables have
|
||||
fixed size at this point and remove dead code.
|
||||
* flags.h (stack_check_type): New enumeration type.
|
||||
(flag_stack_check): Declare.
|
||||
* toplev.c (flag_stack_check): New global variable.
|
||||
* Makefile.in (opts.o): Add dependency on EXPR_H.
|
||||
(explow.o): Add dependency on except.h.
|
||||
|
||||
2008-08-16 Andy Hutchinson <hutchinsonandy@aim.com>
|
||||
|
||||
* config/avr/avr.c (avr_override_options): Reduce value of
|
||||
|
|
|
@ -2392,7 +2392,7 @@ diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
|||
$(TREE_H) version.h $(TM_P_H) $(FLAGS_H) $(INPUT_H) $(TOPLEV_H) intl.h \
|
||||
$(DIAGNOSTIC_H) langhooks.h $(LANGHOOKS_DEF_H) diagnostic.def opts.h
|
||||
opts.o : opts.c opts.h options.h $(TOPLEV_H) $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \
|
||||
coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(EXPR_H) $(RTL_H) \
|
||||
output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
|
||||
$(FLAGS_H) $(PARAMS_H) tree-pass.h $(DBGCNT_H) debug.h varray.h
|
||||
opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
|
||||
|
@ -2495,7 +2495,7 @@ expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_
|
|||
$(TOPLEV_H) $(TM_P_H) langhooks.h $(DF_H) $(TARGET_H)
|
||||
explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
|
||||
$(FLAGS_H) hard-reg-set.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
|
||||
$(TOPLEV_H) $(FUNCTION_H) $(GGC_H) $(TM_P_H) langhooks.h gt-explow.h \
|
||||
$(TOPLEV_H) except.h $(FUNCTION_H) $(GGC_H) $(TM_P_H) langhooks.h gt-explow.h \
|
||||
$(TARGET_H) output.h
|
||||
optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TREE_H) $(FLAGS_H) insn-config.h $(EXPR_H) $(OPTABS_H) libfuncs.h \
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2008-08-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR ada/20548
|
||||
* gcc-interface/decl.c (gnat_to_gnu_entity): Use DECL_SIZE_UNIT in the
|
||||
setjmp test consistently. Adjust for new behaviour of flag_stack_check.
|
||||
* gcc-interface/utils2.c (build_call_alloc_dealloc): Remove redundant
|
||||
test of flag_stack_check. Adjust for new behaviour of flag_stack_check.
|
||||
|
||||
2008-08-13 Samuel Tardieu <sam@rfc1149.net>
|
||||
|
||||
PR ada/36777
|
||||
|
|
|
@ -1303,12 +1303,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|
|||
}
|
||||
}
|
||||
|
||||
if (definition && DECL_SIZE (gnu_decl)
|
||||
if (definition && DECL_SIZE_UNIT (gnu_decl)
|
||||
&& get_block_jmpbuf_decl ()
|
||||
&& (TREE_CODE (DECL_SIZE (gnu_decl)) != INTEGER_CST
|
||||
|| (flag_stack_check && !STACK_CHECK_BUILTIN
|
||||
&& 0 < compare_tree_int (DECL_SIZE_UNIT (gnu_decl),
|
||||
STACK_CHECK_MAX_VAR_SIZE))))
|
||||
&& (TREE_CODE (DECL_SIZE_UNIT (gnu_decl)) != INTEGER_CST
|
||||
|| (flag_stack_check == GENERIC_STACK_CHECK
|
||||
&& compare_tree_int (DECL_SIZE_UNIT (gnu_decl),
|
||||
STACK_CHECK_MAX_VAR_SIZE) > 0)))
|
||||
add_stmt_with_node (build_call_1_expr
|
||||
(update_setjmp_buf_decl,
|
||||
build_unary_op (ADDR_EXPR, NULL_TREE,
|
||||
|
|
|
@ -1920,11 +1920,11 @@ build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, unsigned align,
|
|||
/* ??? For now, disable variable-sized allocators in the stack since
|
||||
we can't yet gimplify an ALLOCATE_EXPR. */
|
||||
else if (gnat_pool == -1
|
||||
&& TREE_CODE (gnu_size) == INTEGER_CST && !flag_stack_check)
|
||||
&& TREE_CODE (gnu_size) == INTEGER_CST
|
||||
&& flag_stack_check != GENERIC_STACK_CHECK)
|
||||
{
|
||||
/* If the size is a constant, we can put it in the fixed portion of
|
||||
the stack frame to avoid the need to adjust the stack pointer. */
|
||||
if (TREE_CODE (gnu_size) == INTEGER_CST && !flag_stack_check)
|
||||
{
|
||||
tree gnu_range
|
||||
= build_range_type (NULL_TREE, size_one_node, gnu_size);
|
||||
|
@ -1937,9 +1937,8 @@ build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, unsigned align,
|
|||
return convert (ptr_void_type_node,
|
||||
build_unary_op (ADDR_EXPR, NULL_TREE, gnu_decl));
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
#if 0
|
||||
else
|
||||
return build2 (ALLOCATE_EXPR, ptr_void_type_node, gnu_size, gnu_align);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1069,10 +1069,10 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
|
|||
rtx copy;
|
||||
|
||||
if (!COMPLETE_TYPE_P (type)
|
||||
|| TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
|
||||
|| (flag_stack_check && ! STACK_CHECK_BUILTIN
|
||||
&& (0 < compare_tree_int (TYPE_SIZE_UNIT (type),
|
||||
STACK_CHECK_MAX_VAR_SIZE))))
|
||||
|| TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
|
||||
|| (flag_stack_check == GENERIC_STACK_CHECK
|
||||
&& compare_tree_int (TYPE_SIZE_UNIT (type),
|
||||
STACK_CHECK_MAX_VAR_SIZE) > 0))
|
||||
{
|
||||
/* This is a variable-sized object. Make space on the stack
|
||||
for it. */
|
||||
|
|
|
@ -992,11 +992,13 @@ fvariable-expansion-in-unroller
|
|||
Common Report Var(flag_variable_expansion_in_unroller) Optimization
|
||||
Apply variable expansion when loops are unrolled
|
||||
|
||||
; Emit code to probe the stack, to help detect stack overflow; also
|
||||
; may cause large objects to be allocated dynamically.
|
||||
fstack-check=
|
||||
Common Report RejectNegative Joined
|
||||
-fstack-check=[no|generic|specific] Insert stack checking code into the program
|
||||
|
||||
fstack-check
|
||||
Common Report Var(flag_stack_check)
|
||||
Insert stack checking code into the program
|
||||
Common Report
|
||||
Insert stack checking code into the program. Same as -fstack-check=specific
|
||||
|
||||
fstack-limit
|
||||
Common
|
||||
|
|
|
@ -15207,8 +15207,34 @@ 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.
|
||||
operating system or the language runtime must do that. The switch causes
|
||||
generation of code to ensure that they see the stack being extended.
|
||||
|
||||
You can additionally specify a string parameter: @code{no} means no
|
||||
checking, @code{generic} means force the use of old-style checking,
|
||||
@code{specific} means use the best checking method and is equivalent
|
||||
to bare @option{-fstack-check}.
|
||||
|
||||
Old-style checking is a generic mechanism that requires no specific
|
||||
target support in the compiler but comes with the following drawbacks:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
Modified allocation strategy for large objects: they will always be
|
||||
allocated dynamically if their size exceeds a fixed threshold.
|
||||
|
||||
@item
|
||||
Fixed limit on the size of the static frame of functions: when it is
|
||||
topped by a particular function, stack checking is not reliable and
|
||||
a warning is issued by the compiler.
|
||||
|
||||
@item
|
||||
Inefficiency: because of both the modified allocation strategy and the
|
||||
generic implementation, the performances of the code are hampered.
|
||||
@end enumerate
|
||||
|
||||
Note that old-style stack checking is also the fallback method for
|
||||
@code{specific} if no target support has been added in the compiler.
|
||||
|
||||
@item -fstack-limit-register=@var{reg}
|
||||
@itemx -fstack-limit-symbol=@var{sym}
|
||||
|
|
|
@ -3376,38 +3376,49 @@ linkage is necessary. The default is @code{0}.
|
|||
@node Stack Checking
|
||||
@subsection Specifying How Stack Checking is Done
|
||||
|
||||
GCC will check that stack references are within the boundaries of
|
||||
the stack, if the @option{-fstack-check} is specified, in one of three ways:
|
||||
GCC will check that stack references are within the boundaries of the
|
||||
stack, if the option @option{-fstack-check} is specified, in one of
|
||||
three ways:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
If the value of the @code{STACK_CHECK_BUILTIN} macro is nonzero, GCC
|
||||
will assume that you have arranged for stack checking to be done at
|
||||
appropriate places in the configuration files, e.g., in
|
||||
@code{TARGET_ASM_FUNCTION_PROLOGUE}. GCC will do not other special
|
||||
processing.
|
||||
will assume that you have arranged for full stack checking to be done
|
||||
at appropriate places in the configuration files. GCC will not do
|
||||
other special processing.
|
||||
|
||||
@item
|
||||
If @code{STACK_CHECK_BUILTIN} is zero and you defined a named pattern
|
||||
called @code{check_stack} in your @file{md} file, GCC will call that
|
||||
pattern with one argument which is the address to compare the stack
|
||||
value against. You must arrange for this pattern to report an error if
|
||||
the stack pointer is out of range.
|
||||
If @code{STACK_CHECK_BUILTIN} is zero and the value of the
|
||||
@code{STACK_CHECK_STATIC_BUILTIN} macro is nonzero, GCC will assume
|
||||
that you have arranged for static stack checking (checking of the
|
||||
static stack frame of functions) to be done at appropriate places
|
||||
in the configuration files. GCC will only emit code to do dynamic
|
||||
stack checking (checking on dynamic stack allocations) using the third
|
||||
approach below.
|
||||
|
||||
@item
|
||||
If neither of the above are true, GCC will generate code to periodically
|
||||
``probe'' the stack pointer using the values of the macros defined below.
|
||||
@end enumerate
|
||||
|
||||
Normally, you will use the default values of these macros, so GCC
|
||||
will use the third approach.
|
||||
If neither STACK_CHECK_BUILTIN nor STACK_CHECK_STATIC_BUILTIN is defined,
|
||||
GCC will change its allocation strategy for large objects if the option
|
||||
@option{-fstack-check} is specified: they will always be allocated
|
||||
dynamically if their size exceeds @code{STACK_CHECK_MAX_VAR_SIZE} bytes.
|
||||
|
||||
@defmac STACK_CHECK_BUILTIN
|
||||
A nonzero value if stack checking is done by the configuration files in a
|
||||
machine-dependent manner. You should define this macro if stack checking
|
||||
is require by the ABI of your machine or if you would like to have to stack
|
||||
checking in some more efficient way than GCC's portable approach.
|
||||
The default value of this macro is zero.
|
||||
is require by the ABI of your machine or if you would like to do stack
|
||||
checking in some more efficient way than the generic approach. The default
|
||||
value of this macro is zero.
|
||||
@end defmac
|
||||
|
||||
@defmac STACK_CHECK_STATIC_BUILTIN
|
||||
A nonzero value if static stack checking is done by the configuration files
|
||||
in a machine-dependent manner. You should define this macro if you would
|
||||
like to do static stack checking in some more efficient way than the generic
|
||||
approach. The default value of this macro is zero.
|
||||
@end defmac
|
||||
|
||||
@defmac STACK_CHECK_PROBE_INTERVAL
|
||||
|
@ -3418,7 +3429,7 @@ default value of 4096 is suitable for most systems.
|
|||
@end defmac
|
||||
|
||||
@defmac STACK_CHECK_PROBE_LOAD
|
||||
A integer which is nonzero if GCC should perform the stack probe
|
||||
An integer which is nonzero if GCC should perform the stack probe
|
||||
as a load instruction and zero if GCC should use a store instruction.
|
||||
The default is zero, which is the most efficient choice on most systems.
|
||||
@end defmac
|
||||
|
@ -3429,6 +3440,10 @@ for languages where such a recovery is supported. The default value of
|
|||
75 words should be adequate for most machines.
|
||||
@end defmac
|
||||
|
||||
The following macros are relevant only if neither STACK_CHECK_BUILTIN
|
||||
nor STACK_CHECK_STATIC_BUILTIN is defined; you can omit them altogether
|
||||
in the opposite case.
|
||||
|
||||
@defmac STACK_CHECK_MAX_FRAME_SIZE
|
||||
The maximum size of a stack frame, in bytes. GCC will generate probe
|
||||
instructions in non-leaf functions to ensure at least this many bytes of
|
||||
|
|
12
gcc/explow.c
12
gcc/explow.c
|
@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tree.h"
|
||||
#include "tm_p.h"
|
||||
#include "flags.h"
|
||||
#include "except.h"
|
||||
#include "function.h"
|
||||
#include "expr.h"
|
||||
#include "optabs.h"
|
||||
|
@ -1190,10 +1191,13 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
|
|||
gcc_assert (!(stack_pointer_delta
|
||||
% (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)));
|
||||
|
||||
/* If needed, check that we have the required amount of stack. Take into
|
||||
account what has already been checked. */
|
||||
if (flag_stack_check && ! STACK_CHECK_BUILTIN)
|
||||
probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
|
||||
/* If needed, check that we have the required amount of stack.
|
||||
Take into account what has already been checked. */
|
||||
if (flag_stack_check == GENERIC_STACK_CHECK)
|
||||
probe_stack_range (STACK_OLD_CHECK_PROTECT + STACK_CHECK_MAX_FRAME_SIZE,
|
||||
size);
|
||||
else if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
|
||||
probe_stack_range (STACK_CHECK_PROTECT, size);
|
||||
|
||||
/* Don't use a TARGET that isn't a pseudo or is the wrong mode. */
|
||||
if (target == 0 || !REG_P (target)
|
||||
|
|
25
gcc/expr.h
25
gcc/expr.h
|
@ -208,10 +208,16 @@ do { \
|
|||
|
||||
/* Provide default values for the macros controlling stack checking. */
|
||||
|
||||
/* The default is neither full builtin stack checking... */
|
||||
#ifndef STACK_CHECK_BUILTIN
|
||||
#define STACK_CHECK_BUILTIN 0
|
||||
#endif
|
||||
|
||||
/* ...nor static builtin stack checking. */
|
||||
#ifndef STACK_CHECK_STATIC_BUILTIN
|
||||
#define STACK_CHECK_STATIC_BUILTIN 0
|
||||
#endif
|
||||
|
||||
/* The default interval is one page. */
|
||||
#ifndef STACK_CHECK_PROBE_INTERVAL
|
||||
#define STACK_CHECK_PROBE_INTERVAL 4096
|
||||
|
@ -222,9 +228,24 @@ do { \
|
|||
#define STACK_CHECK_PROBE_LOAD 0
|
||||
#endif
|
||||
|
||||
/* This value is arbitrary, but should be sufficient for most machines. */
|
||||
/* This is a kludge to try to capture the discrepancy between the old
|
||||
mechanism (generic stack checking) and the new mechanism (static
|
||||
builtin stack checking). STACK_CHECK_PROTECT needs to be bumped
|
||||
for the latter because part of the protection area is effectively
|
||||
included in STACK_CHECK_MAX_FRAME_SIZE for the former. */
|
||||
#ifdef STACK_CHECK_PROTECT
|
||||
#define STACK_OLD_CHECK_PROTECT STACK_CHECK_PROTECT
|
||||
#else
|
||||
#define STACK_OLD_CHECK_PROTECT \
|
||||
(USING_SJLJ_EXCEPTIONS ? 75 * UNITS_PER_WORD : 8 * 1024)
|
||||
#endif
|
||||
|
||||
/* Minimum amount of stack required to recover from an anticipated stack
|
||||
overflow detection. The default value conveys an estimate of the amount
|
||||
of stack required to propagate an exception. */
|
||||
#ifndef STACK_CHECK_PROTECT
|
||||
#define STACK_CHECK_PROTECT (75 * UNITS_PER_WORD)
|
||||
#define STACK_CHECK_PROTECT \
|
||||
(USING_SJLJ_EXCEPTIONS ? 75 * UNITS_PER_WORD : 12 * 1024)
|
||||
#endif
|
||||
|
||||
/* Make the maximum frame size be the largest we can and still only need
|
||||
|
|
21
gcc/flags.h
21
gcc/flags.h
|
@ -254,6 +254,27 @@ extern int flag_var_tracking;
|
|||
warning message in case flag was set by -fprofile-{generate,use}. */
|
||||
extern bool flag_speculative_prefetching_set;
|
||||
|
||||
/* Type of stack check. */
|
||||
enum stack_check_type
|
||||
{
|
||||
/* Do not check the stack. */
|
||||
NO_STACK_CHECK = 0,
|
||||
|
||||
/* Check the stack generically, i.e. assume no specific support
|
||||
from the target configuration files. */
|
||||
GENERIC_STACK_CHECK,
|
||||
|
||||
/* Check the stack and rely on the target configuration files to
|
||||
check the static frame of functions, i.e. use the generic
|
||||
mechanism only for dynamic stack allocations. */
|
||||
STATIC_BUILTIN_STACK_CHECK,
|
||||
|
||||
/* Check the stack and entirely rely on the target configuration
|
||||
files, i.e. do not use the generic mechanism at all. */
|
||||
FULL_BUILTIN_STACK_CHECK
|
||||
};
|
||||
extern enum stack_check_type flag_stack_check;
|
||||
|
||||
/* Returns TRUE if generated code should match ABI version N or
|
||||
greater is in use. */
|
||||
|
||||
|
|
|
@ -3236,7 +3236,7 @@ gimplify_parameters (void)
|
|||
walk_tree_without_duplicates (&data.passed_type,
|
||||
gimplify_parm_type, &stmts);
|
||||
|
||||
if (!TREE_CONSTANT (DECL_SIZE (parm)))
|
||||
if (TREE_CODE (DECL_SIZE_UNIT (parm)) != INTEGER_CST)
|
||||
{
|
||||
gimplify_one_sizepos (&DECL_SIZE (parm), &stmts);
|
||||
gimplify_one_sizepos (&DECL_SIZE_UNIT (parm), &stmts);
|
||||
|
@ -3250,9 +3250,12 @@ gimplify_parameters (void)
|
|||
{
|
||||
tree local, t;
|
||||
|
||||
/* For constant sized objects, this is trivial; for
|
||||
/* For constant-sized objects, this is trivial; for
|
||||
variable-sized objects, we have to play games. */
|
||||
if (TREE_CONSTANT (DECL_SIZE (parm)))
|
||||
if (TREE_CODE (DECL_SIZE_UNIT (parm)) == INTEGER_CST
|
||||
&& !(flag_stack_check == GENERIC_STACK_CHECK
|
||||
&& compare_tree_int (DECL_SIZE_UNIT (parm),
|
||||
STACK_CHECK_MAX_VAR_SIZE) > 0))
|
||||
{
|
||||
local = create_tmp_var (type, get_name (parm));
|
||||
DECL_IGNORED_P (local) = 0;
|
||||
|
@ -4480,10 +4483,10 @@ expand_function_end (void)
|
|||
if (arg_pointer_save_area && ! crtl->arg_pointer_save_area_init)
|
||||
get_arg_pointer_save_area ();
|
||||
|
||||
/* If we are doing stack checking and this function makes calls,
|
||||
/* If we are doing generic stack checking and this function makes calls,
|
||||
do a stack probe at the start of the function to ensure we have enough
|
||||
space for another stack frame. */
|
||||
if (flag_stack_check && ! STACK_CHECK_BUILTIN)
|
||||
if (flag_stack_check == GENERIC_STACK_CHECK)
|
||||
{
|
||||
rtx insn, seq;
|
||||
|
||||
|
@ -4491,7 +4494,7 @@ expand_function_end (void)
|
|||
if (CALL_P (insn))
|
||||
{
|
||||
start_sequence ();
|
||||
probe_stack_range (STACK_CHECK_PROTECT,
|
||||
probe_stack_range (STACK_OLD_CHECK_PROTECT,
|
||||
GEN_INT (STACK_CHECK_MAX_FRAME_SIZE));
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
|
|
|
@ -1447,7 +1447,11 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
|
|||
{
|
||||
tree init = DECL_INITIAL (decl);
|
||||
|
||||
if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
|
||||
if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
|
||||
|| (!TREE_STATIC (decl)
|
||||
&& flag_stack_check == GENERIC_STACK_CHECK
|
||||
&& compare_tree_int (DECL_SIZE_UNIT (decl),
|
||||
STACK_CHECK_MAX_VAR_SIZE) > 0))
|
||||
gimplify_vla_decl (decl, seq_p);
|
||||
|
||||
if (init && init != error_mark_node)
|
||||
|
|
32
gcc/opts.c
32
gcc/opts.c
|
@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "rtl.h"
|
||||
#include "expr.h"
|
||||
#include "ggc.h"
|
||||
#include "output.h"
|
||||
#include "langhooks.h"
|
||||
|
@ -1900,6 +1901,37 @@ common_handle_option (size_t scode, const char *arg, int value,
|
|||
flag_sched_stalled_insns_dep = value;
|
||||
break;
|
||||
|
||||
case OPT_fstack_check_:
|
||||
if (!strcmp (arg, "no"))
|
||||
flag_stack_check = NO_STACK_CHECK;
|
||||
else if (!strcmp (arg, "generic"))
|
||||
/* This is the old stack checking method. */
|
||||
flag_stack_check = STACK_CHECK_BUILTIN
|
||||
? FULL_BUILTIN_STACK_CHECK
|
||||
: GENERIC_STACK_CHECK;
|
||||
else if (!strcmp (arg, "specific"))
|
||||
/* This is the new stack checking method. */
|
||||
flag_stack_check = STACK_CHECK_BUILTIN
|
||||
? FULL_BUILTIN_STACK_CHECK
|
||||
: STACK_CHECK_STATIC_BUILTIN
|
||||
? STATIC_BUILTIN_STACK_CHECK
|
||||
: GENERIC_STACK_CHECK;
|
||||
else
|
||||
warning (0, "unknown stack check parameter \"%s\"", arg);
|
||||
break;
|
||||
|
||||
case OPT_fstack_check:
|
||||
/* This is the same as the "specific" mode above. */
|
||||
if (value)
|
||||
flag_stack_check = STACK_CHECK_BUILTIN
|
||||
? FULL_BUILTIN_STACK_CHECK
|
||||
: STACK_CHECK_STATIC_BUILTIN
|
||||
? STATIC_BUILTIN_STACK_CHECK
|
||||
: GENERIC_STACK_CHECK;
|
||||
else
|
||||
flag_stack_check = NO_STACK_CHECK;
|
||||
break;
|
||||
|
||||
case OPT_fstack_limit:
|
||||
/* The real switch is -fno-stack-limit. */
|
||||
if (value)
|
||||
|
|
|
@ -1301,9 +1301,9 @@ reload (rtx first, int global)
|
|||
}
|
||||
}
|
||||
|
||||
/* If we are doing stack checking, give a warning if this function's
|
||||
frame size is larger than we expect. */
|
||||
if (flag_stack_check && ! STACK_CHECK_BUILTIN)
|
||||
/* If we are doing generic stack checking, give a warning if this
|
||||
function's frame size is larger than we expect. */
|
||||
if (flag_stack_check == GENERIC_STACK_CHECK)
|
||||
{
|
||||
HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
|
||||
static int verbose_warned = 0;
|
||||
|
|
46
gcc/stmt.c
46
gcc/stmt.c
|
@ -1867,8 +1867,8 @@ expand_decl (tree decl)
|
|||
SET_DECL_RTL (decl, gen_rtx_MEM (BLKmode, const0_rtx));
|
||||
|
||||
else if (DECL_SIZE (decl) == 0)
|
||||
/* Variable with incomplete type. */
|
||||
{
|
||||
/* Variable with incomplete type. */
|
||||
rtx x;
|
||||
if (DECL_INITIAL (decl) == 0)
|
||||
/* Error message was already done; now avoid a crash. */
|
||||
|
@ -1899,16 +1899,15 @@ expand_decl (tree decl)
|
|||
TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
|
||||
}
|
||||
|
||||
else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
|
||||
&& ! (flag_stack_check && ! STACK_CHECK_BUILTIN
|
||||
&& 0 < compare_tree_int (DECL_SIZE_UNIT (decl),
|
||||
STACK_CHECK_MAX_VAR_SIZE)))
|
||||
else
|
||||
{
|
||||
/* Variable of fixed size that goes on the stack. */
|
||||
rtx oldaddr = 0;
|
||||
rtx addr;
|
||||
rtx x;
|
||||
|
||||
/* Variable-sized decls are dealt with in the gimplifier. */
|
||||
gcc_assert (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST);
|
||||
|
||||
/* If we previously made RTL for this decl, it must be an array
|
||||
whose size was determined by the initializer.
|
||||
The old address was a register; set that register now
|
||||
|
@ -1936,41 +1935,6 @@ expand_decl (tree decl)
|
|||
emit_move_insn (oldaddr, addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Dynamic-size object: must push space on the stack. */
|
||||
{
|
||||
rtx address, size, x;
|
||||
|
||||
/* Record the stack pointer on entry to block, if have
|
||||
not already done so. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
/* Compute the variable's size, in bytes. This will expand any
|
||||
needed SAVE_EXPRs for the first time. */
|
||||
size = expand_normal (DECL_SIZE_UNIT (decl));
|
||||
free_temp_slots ();
|
||||
|
||||
/* Allocate space on the stack for the variable. Note that
|
||||
DECL_ALIGN says how the variable is to be aligned and we
|
||||
cannot use it to conclude anything about the alignment of
|
||||
the size. */
|
||||
address = allocate_dynamic_stack_space (size, NULL_RTX,
|
||||
TYPE_ALIGN (TREE_TYPE (decl)));
|
||||
|
||||
/* Reference the variable indirect through that rtx. */
|
||||
x = gen_rtx_MEM (DECL_MODE (decl), address);
|
||||
set_mem_attributes (x, decl, 1);
|
||||
SET_DECL_RTL (decl, x);
|
||||
|
||||
|
||||
/* Indicate the alignment we actually gave this variable. */
|
||||
#ifdef STACK_BOUNDARY
|
||||
DECL_ALIGN (decl) = STACK_BOUNDARY;
|
||||
#else
|
||||
DECL_ALIGN (decl) = BIGGEST_ALIGNMENT;
|
||||
#endif
|
||||
DECL_USER_ALIGN (decl) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit code to save the current value of stack. */
|
||||
|
|
|
@ -306,6 +306,9 @@ rtx stack_limit_rtx;
|
|||
to optimize, debug_info_level and debug_hooks in process_options (). */
|
||||
int flag_var_tracking = AUTODETECT_VALUE;
|
||||
|
||||
/* Type of stack check. */
|
||||
enum stack_check_type flag_stack_check = NO_STACK_CHECK;
|
||||
|
||||
/* True if the user has tagged the function with the 'section'
|
||||
attribute. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue