This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] New -fstack-check implementation


Hi,

Due to popular demand :-), I'm again submitting the new stack checking 
implementation that we have been using at AdaCore for a few years now.

Previous submissions:
  http://gcc.gnu.org/ml/gcc-patches/2006-03/msg01239.html
  http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01846.html

But, contrary to the above submissions, this one contains the full set of 
changes (modulo some adjustments in the Ada runtime and *-unwind.h files for 
non-Linux platforms).

-fstack-check is broken in the 4.x series of compilers in the sense that you 
cannot recover from a stack overflow condition (for example in Ada).  It's a 
regression from the 3.x series although there were bugs in that series too.

Moreover, the original implementation comes with several drawbacks:
- modified allocation strategy for large objects: they will always be
allocated dynamically if their size exceeds a fixed threshold.
- 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.
- inefficiency: because of both the modified allocation strategy and the
generic implementation, the performances of the code are unnecessarily 
hampered.

We are proposing a new implementation that eliminates the aforementioned 
drawbacks.  It is based on partial support code in the architecture 
back-ends, modelled on what the Alpha back-end already has because of the 
requirement of the Tru64 ABI.  We implemented it on Alpha/Tru64, x86/Linux, 
x86/Solaris, x86/FreeBSD, x86/Windows, x86/VxWorks, x86/LynxOS, x86-64/Linux, 
MIPS/IRIX (n32), SPARC/Solaris, SPARC64/Solaris, PA/HP-UX, PowerPC/AIX, 
PowerPC/VxWorks, PowerPC/LynxOS, IA-64/Linux and IA-64/HP-UX in 3.4.x, 4.1.x 
and 4.3.x based compilers.

The new mechanism doesn't eliminate the old one, the option -fold-stack-check 
even makes it possible to select the latter when the former is available.  On 
architectures without specific support code, -fstack-check is equivalent to 
-fold-stack-check.

Tested on i586-suse-linux.  Although the changes are mostly orthogonal to the 
rest of the compiler, suggestions are welcome as to what the best procedure 
for integrating this patch in the compiler would be.


2008-03-29  Eric Botcazou  <ebotcazou@adacore.com>
            Tristan Gingold  <gingold@adacore.com>
	    Olivier Hainque  <hainque@adacore.com>
            Jose Ruiz  <ruiz@adacore.com>

	PR ada/20548
	New stack checking implementation
	* common.opt (-fstack-check): Do not declare the variable here.
	(-fold-stack-check): New option.
	* doc/invoke.texi (Code Gen Options): Document it.
	* expr.h (STACK_CHECK_PROBE_INTERVAL): Delete.
	(STACK_CHECK_PROBE_INTERVAL_EXP): New macro.
	(STACK_CHECK_MAX_FRAME_SIZE): Adjust for above change.
	(STACK_OLD_CHECK_PROTECT): Likewise.
	(STACK_CHECK_PROTECT): Bump to 3 pages if DWARF-2 EH is used.
	(STACK_CHECK_STATIC_BUILTIN): New macro.
	(STACK_CHECK_PROBE_IOR): Likewise.
	(STACK_CHECK_MOVING_SP): Likewise.
	* system.h (STACK_CHECK_PROBE_INTERVAL): Poison it.
	* doc/tm.texi (Stack Checking): Delete STACK_CHECK_PROBE_INTERVAL.
	Document STACK_CHECK_PROBE_INTERVAL_EXP, STACK_CHECK_STATIC_BUILTIN,
	STACK_CHECK_PROBE_IOR and STACK_CHECK_MOVING_SP.
	* opts.c: Include expr.h.
	(common_handle_option) <OPT_fold_stack_check>: New case.
	<OPT_fstack_check>: Likewise.
	* calls.c (emit_library_call_value_1): Clear the ECF_NOTHROW flag if
	the libcall is LCT_MAY_THROW.
	(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.
	(anti_adjust_stack_and_probe): New function.
	(allocate_dynamic_stack_space): Do not take into account
	STACK_CHECK_MAX_FRAME_SIZE for static builtin stack checking.
	Do not directly allocate space if STACK_CHECK_MOVING_SP, instead
	invoke above function.
	(set_stack_check_libfunc): Delete.
	(stack_check_libfunc): Make public.
	(stack_check_symbol): New public variable.
	(emit_stack_probe): Deal with STACK_CHECK_PROBE_IOR.
	(PROBE_INTERVAL): New macro.
	(STACK_GROW_OPTAB): Likewise.
	(STACK_HIGH, STACK_LOW): Likewise.
	(probe_stack_range): Cope with SPARC_STACK_BIAS.  Pass LCT_MAY_THROW
	to emit_library_call for the checking routine.  Remove support code
	for dedicated pattern.  Add support for stack limits provided by the
	stack_check_symbol variable.  Fix loop condition in the small constant
	case.  Rewrite in the general case to be immune to wrap-around.
	Make sure the address of probes is valid.  Try to use [base + disp]
	addressing mode as much as possible.
	Do not include gt-explow.h.
	* 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.
	(init_elim_table): Set frame_pointer_needed if stack checking is
	enabled and STACK_CHECK_MOVING_SP.
	* rtlanal.c: Include expr.h.
	(may_trap_p_1) <MEM>: If STACK_CHECK_MOVING_SP, return 1 for
	volatile references to the stack pointer.
	* stmt.c (expand_decl): Assert that all automatic variables have
	fixed size at this point and remove dead code.
	* rtl.h (set_stack_check_libfunc): Delete.
	(stack_check_libfunc): Declare.
	(stack_check_symbol): Likewise.
	(libcall_type enum): Add LCT_MAY_THROW.
	* flags.h (stack_check_type): New enumeration type.
	(flag_stack_check): Change type to above.
	* toplev.c (flag_stack_check): Likewise.
	* tree.c (build_common_builtin_nodes): Do not set ECF_NOTHROW on
	__builtin_alloca if stack checking is enabled.
	* Makefile.in (rtlanal.o): Add dependency on EXPR_H.
	(explow.o): Remove gt-explow.h.
	* config/alpha/alpha.c (alpha_expand_prologue): If stack checking
	is enabled, probe up to frame_size + STACK_CHECK_PROTECT bytes.
	* config/i386/cygming.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/i386/freebsd.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	* config/i386/linux.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	(STACK_CHECK_MOVING_SP): Likewise.
	* config/i386/linux64.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	(STACK_CHECK_MOVING_SP): Likewise.
	* config/i386/lynx.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	* config/i386/sol2.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	* config/i386/vxworks.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	(STACK_CHECK_PROTECT): 8K is reserved in the stack to propagate
	exceptions reliably in case of stack overflow.
	* config/i386/vxworksae.h (STACK_CHECK_PROTECT): Redefine to 4K
	which is enough for executing a possible last chance handler.
	* config/i386/i386.h (STACK_CHECK_PROBE_IOR): Define to 1.
	* config/i386/i386.c (ix86_target_stack_probe): New function.
	(ix86_compute_frame_layout): Force use of push instructions to
	save registers if stack checking with probes is enabled.
	(ix86_eax_maybe_live_in_or_out): New function.
	(ix86_edx_maybe_live_in_or_out: Likewise.
	(ix86_ecx_maybe_live_in_or_out): Likewise.
	(get_scratch_register_on_entry): Likewise.
	(release_scratch_register_on_entry): Likewise.
	(output_probe_op): Likewise.
	(output_adjust_stack_and_probe_op): Likewise.
	(output_adjust_stack_and_probe): Likewise.
	(ix86_gen_adjust_stack_and_probe): Likewise.
	(ix86_adjust_stack_and_probe): Likewise.
	(output_cond_trap): Likewise.
	(output_probe_stack_range_op): Likewise.
	(ix86_gen_probe_stack_range): Likewise.
	(ix86_emit_probe_stack_range): Likewise.
	(ix86_expand_prologue): Emit stack checking code if static builtin
	stack checking is enabled.
	Test ix86_target_stack_probe instead of TARGET_STACK_PROBE.
	* config/i386/i386-protos.h (ix86_target_stack_probe): Declare.
	(output_adjust_stack_and_probe): Likewise.
	(output_cond_trap): Likewise.
	(output_probe_stack_range): Likewise.
	* config/i386/i386.md (UNSPECV_STACK_PROBE_INLINE): New constant.
	(allocate_stack_worker_32): Test ix86_target_stack_probe instead of
	TARGET_STACK_PROBE.
	(allocate_stack_worker_64): Likewise.
	(allocate_stack): Likewise.
	(adjust_stack_and_probe): New insn.
	(probe_stack_range): Likewise.
	(logical operation peepholes): Do not split stack checking probes.
	(cond_trap): New insn.
	* config/ia64/hpux.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	(STACK_CHECK_PROTECT): Define.
	* config/ia64/linux.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/ia64/ia64.c (ia64_emit_probe_stack_range): New function.
	(output_probe_stack_range): Likewise.
	(ia64_expand_prologue): Invoke ia64_emit_probe_stack_range if static
	builtin stack checking is enabled.
	(rtx_needs_barrier): Return 1 for inline stack probes.
	(asm_insn_p): New predicate.
	(ia64_dfa_sched_reorder): Use it.
	(ia64_dfa_new_cycle): Likewise.
	(issue_nops_and_insn): Likewise.
	(bundling): Likewise.
	(final_emit_insn_group_barriers): Likewise.
	* config/ia64/ia64-protos.h (output_probe_stack_range): Declare.
	* config/ia64/ia64.md (UNSPECV_STACK_PROBE_INLINE): New constant.
	(probe_stack_range): New insn.
	* config/mips/iris6.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/mips/mips.c: Include except.h.
	(mips_emit_probe_stack_range): New function.
	(mips_output_probe_stack_range): Likewise.
	(mips_expand_prologue): Invoke mips_emit_probe_stack_range if static
	builtin stack checking is enabled.
	* config/mips/mips-protos.h (mips_output_probe_stack_range): Declare.
	* config/mips/mips.md (UNSPECV_STACK_PROBE_INLINE): New constant.
	(probe_stack_range): New insn.
	* config/pa/pa-hpux.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/pa/pa.c (pa_emit_probe_stack_range): New function.
	(output_probe_stack_range): Likewise.
	(hppa_expand_prologue): Invoke pa_emit_probe_stack_range if static
	builtin stack checking is enabled.
	* config/pa/pa-protos.h (output_probe_stack_range): Declare.
	* config/pa/pa.md (probe_stack_range): New insn.
	* config/rs6000/aix.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/rs6000/lynx.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	* config/rs6000/vxworks.h (STACK_CHECK_STATIC_BUILTIN): Likewise.
	(STACK_CHECK_PROTECT): 8K is reserved in the stack to propagate
	exceptions reliably in case of stack overflow.
	* config/rs6000/vxworksae.h  (STACK_CHECK_PROTECT): Redefine to 4K
	which is enough for executing a possible last chance handler.
	* config/rs6000/rs6000.c (rs6000_emit_probe_stack_range): New function.
	(output_probe_stack_range): Likewise.
	(rs6000_emit_prologue): Invoke rs6000_emit_probe_stack_range if static
	builtin stack checking is enabled.
	* config/rs6000/rs6000-protos.h (output_probe_stack_range): Declare.
	* config/rs6000/rs6000.md (UNSPECV_STACK_PROBE_INLINE): New constant.
	(probe_stack_range): New insn.
	* config/sparc/sol2.h (STACK_CHECK_STATIC_BUILTIN): Define to 1.
	* config/sparc/sparc.c: Include except.h.
	(sparc_emit_probe_stack_range): New function.
	(build_big_number): Likewise.
	(output_probe_stack_range): Likewise.
	(sparc_expand_prologue): Invoke sparc_emit_probe_stack_range if static
	builtin stack checking is enabled.
	* config/sparc/sparc-protos.h (output_probe_stack_range): Declare.
	* config/sparc/sparc.md (UNSPECV_STACK_PROBE_INLINE): New constant.
	(probe_stack_range): New insn.

ada/
        * decl.c (gnat_to_gnu_entity): Use DECL_SIZE_UNIT consistently in the
        setjmp test.  Adjust for new behaviour of flag_stack_check.
        * trans.c (gigi): Set stack_check_symbol to __gnat_stack_limit on
	selected platforms.
        * utils2.c (build_call_alloc_dealloc): Remove redundant test of
        flag_stack_check.  Adjust for new behaviour of flag_stack_check.

	* init.c (HP-UX section): Use an alternate signal stack.
	(Linux section): Likewise on x86 and x86-64.
	* system-linux-x86_64.ads (Stack_Check_Probes): Set to true.
	* system-linux-x86.ads (Stack_Check_Probes): Set to true.

testsuite/
        * ada/acats/norun.lst: Remove c52103x, c52104x, c52104y, cb1010a,
        cb1010c and cb1010d.

-- 
Eric Botcazou

Attachment: gcc-44_stack-check.diff.gz
Description: GNU Zip compressed data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]