On 05/13/2015 04:45 AM, Eric Botcazou wrote:
Hi,

the SJLJ EH schemes manipulate a buffer that contains a few pointers and, in
particular, the stack pointer.  Therefore, when dynamic stack allocation is
also used, you need to update its value in the buffer, otherwise Bad Things
will happen if you resume execution where the stack is shifted.

GNAT uses a manual SJLJ EH scheme that is piggybacked on the __builtin_setjmp
__builtin_longjmp machinery and has this block in gcc-interface/decl.c:

        /* If we are defining an object with variable size or an object with
           fixed size that will be dynamically allocated, and we are using the
           setjmp/longjmp exception mechanism, update the setjmp buffer.  */
        if (definition
            && Exception_Mechanism == Setjmp_Longjmp
            && get_block_jmpbuf_decl ()
            && DECL_SIZE_UNIT (gnu_decl)
            && (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_n_expr
                              (update_setjmp_buf_decl, 1,
                               build_unary_op (ADDR_EXPR, NULL_TREE,
                                               get_block_jmpbuf_decl ())),
                              gnat_entity);

It is necessary if you want to pass the ACATS testsuite.

But the regular SJLJ scheme (--enable-sjlj-exceptions) doesn't do this update
and, therefore, doesn't play nice with dynamic stack allocation.  It's a long-
standing issue and you can find messages about it in the archives.  On the
other hand, this update has always been done for non-local gotos (they also
use a buffer, the non-local goto save area).

The attached patch implements this update for the regular SJLJ scheme and
yields a clean ACATS testsuite.  Tested on x86_64-suse-linux with --enable-
sjlj-exceptions, OK for the mainline?


2015-05-13  Eric Botcazou  <ebotca...@adacore.com>
             Tristan Gingold  <ging...@adacore.com>

        * insn-notes.def (UPDATE_SJLJ_CONTEXT): New note.
        * builtins.c (expand_builtin_update_setjmp_buf): Make global.
        (expand_stack_restore): Call record_new_stack_level.
        (expand_stack_save): Do not call do_pending_stack_adjust.
        * builtins.h (expand_builtin_update_setjmp_buf): Declare.
        * calls.c (expand_call): Call record_new_stack_level for alloca.
        * except.c (sjlj_mark_call_sites): Expand builtin_update_setjmp_buf
        wherever a NOTE_INSN_UPDATE_SJLJ_CONTEXT note is present.
        (update_sjlj_context): New global function.
        * except.h (update_sjlj_context): Declare.
        * explow.c (record_new_stack_level): New global function.
        (allocate_dynamic_stack_space): Call record_new_stack_level.
        * explow.h (record_new_stack_level): Declare.
        * final.c (final_scan_insn): Deal with NOTE_INSN_UPDATE_SJLJ_CONTEXT.
        * cfgrtl.c (duplicate_insn_chain): Likewise.
OK.  Thanks for tackling this.

jeff

Reply via email to