From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17102 invoked by alias); 13 May 2015 10:47:12 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 17086 invoked by uid 89); 13 May 2015 10:47:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=AWL,BAYES_00,KAM_ASCII_DIVIDERS,KAM_LAZY_DOMAIN_SECURITY,RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 13 May 2015 10:47:10 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 87BFC2851500 for ; Wed, 13 May 2015 12:47:06 +0200 (CEST) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id wwJc4-FwvIUs for ; Wed, 13 May 2015 12:47:06 +0200 (CEST) Received: from polaris.localnet (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id 52CEB2851418 for ; Wed, 13 May 2015 12:47:06 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [patch] Update SJLJ buffer after dynamic stack allocation Date: Wed, 13 May 2015 10:54:00 -0000 Message-ID: <1931342.tuu8H0PoOE@polaris> User-Agent: KMail/4.7.2 (Linux/3.1.10-1.29-desktop; KDE/4.7.2; x86_64; ; ) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart5406614.ayYRRvnLmS" Content-Transfer-Encoding: 7Bit X-SW-Source: 2015-05/txt/msg01202.txt.bz2 --nextPart5406614.ayYRRvnLmS Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Content-length: 2768 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 Tristan Gingold * 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. -- Eric Botcazou --nextPart5406614.ayYRRvnLmS Content-Disposition: attachment; filename="sjlj_compiler.diff" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="utf-8"; name="sjlj_compiler.diff" Content-length: 8038 Index: builtins.c =================================================================== --- builtins.c (revision 222673) +++ builtins.c (working copy) @@ -120,7 +120,6 @@ static int apply_result_size (void); #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return) static rtx result_vector (int, rtx); #endif -static void expand_builtin_update_setjmp_buf (rtx); static void expand_builtin_prefetch (tree); static rtx expand_builtin_apply_args (void); static rtx expand_builtin_apply_args_1 (void); @@ -1213,10 +1212,10 @@ expand_builtin_nonlocal_goto (tree exp) /* __builtin_update_setjmp_buf is passed a pointer to an array of five words (not all will be used on all machines) that was passed to __builtin_setjmp. - It updates the stack pointer in that block to correspond to the current - stack pointer. */ + It updates the stack pointer in that block to the current value. This is + also called directly by the SJLJ exception handling code. */ -static void +void expand_builtin_update_setjmp_buf (rtx buf_addr) { machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); @@ -5891,10 +5890,12 @@ expand_stack_restore (tree var) prev = get_last_insn (); emit_stack_restore (SAVE_BLOCK, sa); + + record_new_stack_level (); + fixup_args_size_notes (prev, get_last_insn (), 0); } - /* Emit code to save the current value of stack. */ static rtx @@ -5902,7 +5903,6 @@ expand_stack_save (void) { rtx ret = NULL_RTX; - do_pending_stack_adjust (); emit_stack_save (SAVE_BLOCK, &ret); return ret; } Index: final.c =================================================================== --- final.c (revision 222673) +++ final.c (working copy) @@ -2215,6 +2215,7 @@ final_scan_insn (rtx_insn *insn, FILE *f switch (NOTE_KIND (insn)) { case NOTE_INSN_DELETED: + case NOTE_INSN_UPDATE_SJLJ_CONTEXT: break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: Index: builtins.h =================================================================== --- builtins.h (revision 222673) +++ builtins.h (working copy) @@ -59,6 +59,7 @@ extern unsigned int get_pointer_alignmen extern tree c_strlen (tree, int); extern void expand_builtin_setjmp_setup (rtx, rtx); extern void expand_builtin_setjmp_receiver (rtx); +extern void expand_builtin_update_setjmp_buf (rtx); extern tree mathfn_built_in (tree, enum built_in_function fn); extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, machine_mode); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, machine_mode); Index: insn-notes.def =================================================================== --- insn-notes.def (revision 222673) +++ insn-notes.def (working copy) @@ -87,4 +87,8 @@ INSN_NOTE (CFI) label that should be emitted. */ INSN_NOTE (CFI_LABEL) +/* This note indicates that the function context must be updated if + the Setjmp/Longjmp exception mechanism is used. */ +INSN_NOTE (UPDATE_SJLJ_CONTEXT) + #undef INSN_NOTE Index: calls.c =================================================================== --- calls.c (revision 222673) +++ calls.c (working copy) @@ -3632,12 +3632,9 @@ expand_call (tree exp, rtx target, int i stack_usage_map = initial_stack_usage_map; } - /* If this was alloca, record the new stack level for nonlocal gotos. - Check for the handler slots since we might not have a save area - for non-local gotos. */ - - if ((flags & ECF_MAY_BE_ALLOCA) && cfun->nonlocal_goto_save_area != 0) - update_nonlocal_goto_save_area (); + /* If this was alloca, record the new stack level. */ + if (flags & ECF_MAY_BE_ALLOCA) + record_new_stack_level (); /* Free up storage we no longer need. */ for (i = 0; i < num_actuals; ++i) Index: except.c =================================================================== --- except.c (revision 222673) +++ except.c (working copy) @@ -1126,6 +1126,21 @@ sjlj_mark_call_sites (void) if (LABEL_P (insn)) last_call_site = -2; + /* If the function allocates dynamic stack space, the context must + be updated after every allocation/deallocation accordingly. */ + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_UPDATE_SJLJ_CONTEXT) + { + rtx buf_addr; + + start_sequence (); + buf_addr = plus_constant (Pmode, XEXP (crtl->eh.sjlj_fc, 0), + sjlj_fc_jbuf_ofs); + expand_builtin_update_setjmp_buf (buf_addr); + p = get_insns (); + end_sequence (); + emit_insn_before (p, insn); + } + if (! INSN_P (insn)) continue; @@ -1495,6 +1510,18 @@ sjlj_build_landing_pads (void) sjlj_lp_call_site_index.release (); } +/* Update the sjlj function context. This function should be called + whenever we allocate or deallocate dynamic stack space. */ + +void +update_sjlj_context (void) +{ + if (!flag_exceptions) + return; + + emit_note (NOTE_INSN_UPDATE_SJLJ_CONTEXT); +} + /* After initial rtl generation, call back to finish generating exception support code. */ Index: except.h =================================================================== --- except.h (revision 222673) +++ except.h (working copy) @@ -252,6 +252,7 @@ extern hash_map *duplica (struct function *, eh_region, int, duplicate_eh_regions_map, void *); extern void sjlj_emit_function_exit_after (rtx_insn *); +extern void update_sjlj_context (void); extern eh_region gen_eh_region_cleanup (eh_region); extern eh_region gen_eh_region_try (eh_region); Index: explow.c =================================================================== --- explow.c (revision 222673) +++ explow.c (working copy) @@ -1096,8 +1096,8 @@ emit_stack_restore (enum save_level save } /* Invoke emit_stack_save on the nonlocal_goto_save_area for the current - function. This function should be called whenever we allocate or - deallocate dynamic stack space. */ + function. This should be called whenever we allocate or deallocate + dynamic stack space. */ void update_nonlocal_goto_save_area (void) @@ -1117,6 +1117,21 @@ update_nonlocal_goto_save_area (void) emit_stack_save (SAVE_NONLOCAL, &r_save); } + +/* Record a new stack level for the current function. This should be called + whenever we allocate or deallocate dynamic stack space. */ + +void +record_new_stack_level (void) +{ + /* Record the new stack level for nonlocal gotos. */ + if (cfun->nonlocal_goto_save_area) + update_nonlocal_goto_save_area (); + + /* Record the new stack level for SJLJ exceptions. */ + if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) + update_sjlj_context (); +} /* Return an rtx representing the address of an area of memory dynamically pushed on the stack. @@ -1479,9 +1494,8 @@ allocate_dynamic_stack_space (rtx size, /* Now that we've committed to a return value, mark its alignment. */ mark_reg_pointer (target, required_align); - /* Record the new stack level for nonlocal gotos. */ - if (cfun->nonlocal_goto_save_area != 0) - update_nonlocal_goto_save_area (); + /* Record the new stack level. */ + record_new_stack_level (); return target; } Index: explow.h =================================================================== --- explow.h (revision 222673) +++ explow.h (working copy) @@ -78,6 +78,9 @@ extern void emit_stack_restore (enum sav /* Invoke emit_stack_save for the nonlocal_goto_save_area. */ extern void update_nonlocal_goto_save_area (void); +/* Record a new stack level. */ +extern void record_new_stack_level (void); + /* Allocate some space on the stack dynamically and return its address. */ extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned, bool); Index: cfgrtl.c =================================================================== --- cfgrtl.c (revision 222673) +++ cfgrtl.c (working copy) @@ -4209,6 +4209,7 @@ duplicate_insn_chain (rtx_insn *from, rt break; case NOTE_INSN_EPILOGUE_BEG: + case NOTE_INSN_UPDATE_SJLJ_CONTEXT: emit_note_copy (as_a (insn)); break; --nextPart5406614.ayYRRvnLmS--