This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] New -fstack-check implementation (1/n)
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 May 2008 20:43:30 +0200
- Subject: [PATCH] New -fstack-check implementation (1/n)
Hi,
This is the first patch in a series that stems from the split of
http://gcc.gnu.org/ml/gcc-patches/2008-03/msg01853.html
It's mostly infrastructure work but it does contain a few fixes to restore
proper functioning of stack checking and remove a block of dead code.
As per Mark's suggestion, I've removed the new option -fold-stack-check and
instead added -fstack-check=[no|generic|specific] (better names welcome!).
Tested on i586-suse-linux by verifying that this doesn't break anything.
I cannot really do more since stack checking is still non-functional on the
popular targets (most notably x86/Linux and x86-64/Linux) but this patch
works fine in our 4.1 and 4.3 compilers. OK for mainline?
2008-05-30 Eric Botcazou <ebotcazou@adacore.com>
PR ada/20548
New stack checking implementation
* 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/
* decl.c (gnat_to_gnu_entity): Use DECL_SIZE_UNIT consistently in the
setjmp test. Adjust for new behaviour of flag_stack_check.
* utils2.c (build_call_alloc_dealloc): Remove redundant test of
flag_stack_check. Adjust for new behaviour of flag_stack_check.
--
Eric Botcazou
Index: doc/tm.texi
===================================================================
--- doc/tm.texi (revision 136136)
+++ doc/tm.texi (working copy)
@@ -3434,38 +3434,49 @@ linkage is necessary. The default is @c
@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
@@ -3476,7 +3487,7 @@ default value of 4096 is suitable for mo
@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
@@ -3487,6 +3498,10 @@ for languages where such a recovery is s
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
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi (revision 136136)
+++ doc/invoke.texi (working copy)
@@ -15199,8 +15199,34 @@ a single-threaded environment since stac
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}
Index: flags.h
===================================================================
--- flags.h (revision 136136)
+++ flags.h (working copy)
@@ -269,6 +269,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. */
Index: toplev.c
===================================================================
--- toplev.c (revision 136136)
+++ toplev.c (working copy)
@@ -315,6 +315,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. */
Index: expr.h
===================================================================
--- expr.h (revision 136136)
+++ expr.h (working copy)
@@ -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
Index: opts.c
===================================================================
--- opts.c (revision 136136)
+++ opts.c (working copy)
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.
#include "tm.h"
#include "tree.h"
#include "rtl.h"
+#include "expr.h"
#include "ggc.h"
#include "output.h"
#include "langhooks.h"
@@ -1808,6 +1809,37 @@ common_handle_option (size_t scode, cons
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)
Index: ada/decl.c
===================================================================
--- ada/decl.c (revision 136136)
+++ ada/decl.c (working copy)
@@ -1266,12 +1266,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
}
}
- 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,
Index: ada/utils2.c
===================================================================
--- ada/utils2.c (revision 136136)
+++ ada/utils2.c (working copy)
@@ -1908,11 +1908,11 @@ build_call_alloc_dealloc (tree gnu_obj,
/* ??? 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);
@@ -1925,9 +1925,8 @@ build_call_alloc_dealloc (tree gnu_obj,
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
}
Index: function.c
===================================================================
--- function.c (revision 136136)
+++ function.c (working copy)
@@ -3159,7 +3159,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);
@@ -3173,9 +3173,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;
@@ -4371,10 +4374,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;
@@ -4382,7 +4385,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 ();
Index: gimplify.c
===================================================================
--- gimplify.c (revision 136136)
+++ gimplify.c (working copy)
@@ -1279,7 +1279,11 @@ gimplify_decl_expr (tree *stmt_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, stmt_p);
if (init && init != error_mark_node)
Index: calls.c
===================================================================
--- calls.c (revision 136136)
+++ calls.c (working copy)
@@ -1048,10 +1048,10 @@ initialize_argument_information (int num
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. */
Index: explow.c
===================================================================
--- explow.c (revision 136136)
+++ explow.c (working copy)
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.
#include "tree.h"
#include "tm_p.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
#include "expr.h"
#include "optabs.h"
@@ -1193,10 +1194,13 @@ allocate_dynamic_stack_space (rtx size,
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)
Index: common.opt
===================================================================
--- common.opt (revision 136136)
+++ common.opt (working copy)
@@ -980,11 +980,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
Index: Makefile.in
===================================================================
--- Makefile.in (revision 136136)
+++ Makefile.in (working copy)
@@ -2337,7 +2337,7 @@ diagnostic.o : diagnostic.c $(CONFIG_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) $(RTL_H) $(EXPR_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
opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
@@ -2440,7 +2440,7 @@ expmed.o : expmed.c $(CONFIG_H) $(SYSTEM
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 \
Index: stmt.c
===================================================================
--- stmt.c (revision 136136)
+++ stmt.c (working copy)
@@ -1873,8 +1873,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. */
@@ -1905,16 +1905,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
@@ -1942,41 +1941,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. */
Index: reload1.c
===================================================================
--- reload1.c (revision 136136)
+++ reload1.c (working copy)
@@ -1304,9 +1304,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;