+2004-08-18 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * config/s390/s390.md (s390_warn_framesize_string)
+ (s390_warn_dynamic_string, s390_stack_size_string)
+ (s390_stack_guard_string): New global string variables.
+ (s390_warn_framesize, s390_warn_dynamicstack_p, s390_stack_size)
+ (s390_stack_guard): New global variables.
+ (override_options): Added checks for the new options.
+ (s390_emit_prologue): Emit stack check and trap code and perform
+ compile time stack size checking.
+
+ * config/s390/s390.h (TARGET_OPTIONS): Added new options
+ "warn-framesize", "warn-dynamicstack", "stack-size" and
+ "stack-guard".
+
+ * doc/invoke.texi: Added documentation for the new options.
+
2004-08-19 Ulrich Weigand <uweigand@de.ibm.com>
* unwind-dw2-fde.c (get_cie_encoding): Cast argument to strlen
const char *s390_backchain_string = ""; /* "" no-backchain ,"1" backchain,
"2" kernel-backchain */
+const char *s390_warn_framesize_string;
+const char *s390_warn_dynamicstack_string;
+const char *s390_stack_size_string;
+const char *s390_stack_guard_string;
+
+HOST_WIDE_INT s390_warn_framesize = 0;
+bool s390_warn_dynamicstack_p = 0;
+HOST_WIDE_INT s390_stack_size = 0;
+HOST_WIDE_INT s390_stack_guard = 0;
+
/* The following structure is embedded in the machine
specific part of struct function. */
error ("z/Architecture mode not supported on %s.", s390_arch_string);
if (TARGET_64BIT && !TARGET_ZARCH)
error ("64-bit ABI not supported in ESA/390 mode.");
+
+ if (s390_warn_framesize_string)
+ {
+ if (sscanf (s390_warn_framesize_string, HOST_WIDE_INT_PRINT_DEC,
+ &s390_warn_framesize) != 1)
+ error ("invalid value for -mwarn-framesize");
+ }
+
+ if (s390_warn_dynamicstack_string)
+ s390_warn_dynamicstack_p = 1;
+
+ if (s390_stack_size_string)
+ {
+ if (sscanf (s390_stack_size_string, HOST_WIDE_INT_PRINT_DEC,
+ &s390_stack_size) != 1)
+ error ("invalid value for -mstack-size");
+
+ if (exact_log2 (s390_stack_size) == -1)
+ error ("stack size must be an exact power of 2");
+
+ if (s390_stack_guard_string)
+ {
+ if (sscanf (s390_stack_guard_string, HOST_WIDE_INT_PRINT_DEC,
+ &s390_stack_guard) != 1)
+ error ("invalid value for -mstack-guard");
+
+ if (s390_stack_guard >= s390_stack_size)
+ error ("stack size must be greater than the stack guard value");
+
+ if (exact_log2 (s390_stack_guard) == -1)
+ error ("stack guard value must be an exact power of 2");
+ }
+ else
+ error ("-mstack-size implies use of -mstack-guard");
+ }
+
+ if (s390_stack_guard_string && !s390_stack_size_string)
+ error ("-mstack-guard implies use of -mstack-size");
}
/* Map for smallest class containing reg regno. */
{
rtx frame_off = GEN_INT (-cfun_frame_layout.frame_size);
+ if (s390_stack_size)
+ {
+ HOST_WIDE_INT stack_check_mask = ((s390_stack_size - 1)
+ & ~(s390_stack_guard - 1));
+ rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx,
+ GEN_INT (stack_check_mask));
+
+ if (TARGET_64BIT)
+ gen_cmpdi (t, const0_rtx);
+ else
+ gen_cmpsi (t, const0_rtx);
+
+ emit_insn (gen_conditional_trap (gen_rtx_EQ (CCmode,
+ gen_rtx_REG (CCmode,
+ CC_REGNUM),
+ const0_rtx),
+ const0_rtx));
+ }
+
+ if (s390_warn_framesize > 0
+ && cfun_frame_layout.frame_size >= s390_warn_framesize)
+ warning ("frame size of `%s' is " HOST_WIDE_INT_PRINT_DEC " bytes",
+ current_function_name (), cfun_frame_layout.frame_size);
+
+ if (s390_warn_dynamicstack_p && cfun->calls_alloca)
+ warning ("`%s' uses dynamic stack allocation", current_function_name ());
+
/* Save incoming stack pointer into temp reg. */
if (cfun_frame_layout.save_backchain_p || next_fpr)
insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
extern const char *s390_backchain_string;
+extern const char *s390_warn_framesize_string;
+extern const char *s390_warn_dynamicstack_string;
+extern const char *s390_stack_size_string;
+extern const char *s390_stack_guard_string;
+
#define TARGET_CPU_IEEE_FLOAT \
(s390_arch_flags & PF_IEEE_FLOAT)
#define TARGET_CPU_ZARCH \
{ "fused-madd", -256, N_("enable fused multiply/add instructions")}, \
{ "", TARGET_DEFAULT, 0 } }
-#define TARGET_OPTIONS \
-{ { "tune=", &s390_tune_string, \
- N_("Schedule code for given CPU"), 0}, \
- { "arch=", &s390_arch_string, \
- N_("Generate code for given CPU"), 0}, \
- { "backchain", &s390_backchain_string, \
- N_("Set backchain"), "1"}, \
- { "no-backchain", &s390_backchain_string, \
- N_("Do not set backchain"), ""}, \
- { "kernel-backchain", &s390_backchain_string, \
- N_("Set backchain appropriate for the linux kernel"), "2"}, \
+#define TARGET_OPTIONS \
+{ { "tune=", &s390_tune_string, \
+ N_("Schedule code for given CPU"), 0}, \
+ { "arch=", &s390_arch_string, \
+ N_("Generate code for given CPU"), 0}, \
+ { "backchain", &s390_backchain_string, \
+ N_("Set backchain"), "1"}, \
+ { "no-backchain", &s390_backchain_string, \
+ N_("Do not set backchain"), ""}, \
+ { "kernel-backchain", &s390_backchain_string, \
+ N_("Set backchain appropriate for the linux kernel"), "2"}, \
+ { "warn-framesize=", &s390_warn_framesize_string, \
+ N_("Warn if a single function's framesize exceeds the given framesize"), \
+ 0}, \
+ { "warn-dynamicstack", &s390_warn_dynamicstack_string, \
+ N_("Warn if a function uses alloca or creates an array with dynamic size"),\
+ 0}, \
+ { "stack-size=", &s390_stack_size_string, \
+ N_("Emit extra code in the function prologue in order to trap if the stack"\
+ "size exceeds the given limit"), 0}, \
+ { "stack-guard=", &s390_stack_guard_string, \
+ N_("Set the max. number of bytes which has to be left to stack size " \
+ "before a trap instruction is triggered"), 0}, \
}
/* Support for configure-time defaults. */
-mhard-float -msoft-float -mbackchain -mno-backchain -mkernel-backchain @gol
-msmall-exec -mno-small-exec -mmvcle -mno-mvcle @gol
-m64 -m31 -mdebug -mno-debug -mesa -mzarch @gol
--mtpf-trace -mno-tpf-trace -mfused-madd -mno-fused-madd}
+-mtpf-trace -mno-tpf-trace -mfused-madd -mno-fused-madd @gol
+-mwarn-framesize -mwarn-dynamicstack -mstack-size -mstack-guard}
@emph{SH Options}
@gccoptlist{-m1 -m2 -m2e -m3 -m3e @gol
Generate code that uses (does not use) the floating point multiply and
accumulate instructions. These instructions are generated by default if
hardware floating point is used.
+
+@item -mwarn-framesize=@var{framesize}
+@opindex mwarn-framesize
+Emit a warning if the current function exceeds the given frame size. Because
+this is a compile time check it doesn't need to be a real problem when the program
+runs. It is intended to identify functions which most probably cause
+a stack overflow. It is useful to be used in an environment with limited stack
+size e.g. the linux kernel.
+
+@item -mwarn-dynamicstack
+@opindex mwarn-dynamicstack
+Emit a warning if the function calls alloca or uses dynamically
+sized arrays. This is generally a bad idea with a limited stack size.
+
+@item -mstack-guard=@var{stack-guard}
+@item -mstack-size=@var{stack-size}
+@opindex mstack-guard
+@opindex mstack-size
+These arguments always have to be used in conjunction. If they are present the s390
+back end emits additional instructions in the function prologue which trigger a trap
+if the stack size is @var{stack-guard} bytes above the @var{stack-size}
+(remember that the stack on s390 grows downward). These options are intended to
+be used to help debugging stack overflow problems. The additionally emitted code
+cause only little overhead and hence can also be used in production like systems
+without greater performance degradation. The given values have to be exact
+powers of 2 and @var{stack-size} has to be greater than @var{stack-guard}.
+In order to be efficient the extra code makes the assumption that the stack starts
+at an address aligned to the value given by @var{stack-size}.
@end table
@node SH Options