diff options
| author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-22 00:42:54 +0000 | 
|---|---|---|
| committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-22 00:42:54 +0000 | 
| commit | 6fc8784048bd1a34f08bf37fde4e7d7e6811b96f (patch) | |
| tree | 9405da1d51ba2f549696823714d6adf0ba1ea1fd /gcc/expr.c | |
| parent | 098fb0512245a9c2eddbfa38529995b1ec9186aa (diff) | |
| download | ppe42-gcc-6fc8784048bd1a34f08bf37fde4e7d7e6811b96f.tar.gz ppe42-gcc-6fc8784048bd1a34f08bf37fde4e7d7e6811b96f.zip | |
        * expr.c (expand_expr) [TRY_FINALLY_EXPR]: Don't use
        GOTO_SUBROUTINE_EXPR when finally_block can be re-expanded.
        * lang.c (java_unsafe_for_reeval): New.
        (LANG_HOOKS_UNSAFE_FOR_REEVAL): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55636 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
| -rw-r--r-- | gcc/expr.c | 58 | 
1 files changed, 39 insertions, 19 deletions
| diff --git a/gcc/expr.c b/gcc/expr.c index 7b5810c617c..e70bf905b20 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8965,29 +8965,49 @@ expand_expr (exp, target, tmode, modifier)        {  	tree try_block = TREE_OPERAND (exp, 0);  	tree finally_block = TREE_OPERAND (exp, 1); -	rtx finally_label = gen_label_rtx (); -	rtx done_label = gen_label_rtx (); -	rtx return_link = gen_reg_rtx (Pmode); -	tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node, -			      (tree) finally_label, (tree) return_link); -	TREE_SIDE_EFFECTS (cleanup) = 1; -	/* Start a new binding layer that will keep track of all cleanup -	   actions to be performed.  */ -	expand_start_bindings (2); +        if (unsafe_for_reeval (finally_block) > 1) +	  { +	    /* In this case, wrapping FINALLY_BLOCK in an UNSAVE_EXPR +	       is not sufficient, so we cannot expand the block twice. +	       So we play games with GOTO_SUBROUTINE_EXPR to let us +	       expand the thing only once.  */ + +	    rtx finally_label = gen_label_rtx (); +	    rtx done_label = gen_label_rtx (); +	    rtx return_link = gen_reg_rtx (Pmode); +	    tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node, +			          (tree) finally_label, (tree) return_link); +	    TREE_SIDE_EFFECTS (cleanup) = 1; + +	    /* Start a new binding layer that will keep track of all cleanup +	       actions to be performed.  */ +	    expand_start_bindings (2); +	    target_temp_slot_level = temp_slot_level; + +	    expand_decl_cleanup (NULL_TREE, cleanup); +	    op0 = expand_expr (try_block, target, tmode, modifier); + +	    preserve_temp_slots (op0); +	    expand_end_bindings (NULL_TREE, 0, 0); +	    emit_jump (done_label); +	    emit_label (finally_label); +	    expand_expr (finally_block, const0_rtx, VOIDmode, 0); +	    emit_indirect_jump (return_link); +	    emit_label (done_label); +	  } +	else +	  { +	    expand_start_bindings (2); +	    target_temp_slot_level = temp_slot_level; -	target_temp_slot_level = temp_slot_level; +	    expand_decl_cleanup (NULL_TREE, finally_block); +	    op0 = expand_expr (try_block, target, tmode, modifier); -	expand_decl_cleanup (NULL_TREE, cleanup); -	op0 = expand_expr (try_block, target, tmode, modifier); +	    preserve_temp_slots (op0); +	    expand_end_bindings (NULL_TREE, 0, 0); +	  } -	preserve_temp_slots (op0); -	expand_end_bindings (NULL_TREE, 0, 0); -	emit_jump (done_label); -	emit_label (finally_label); -	expand_expr (finally_block, const0_rtx, VOIDmode, 0); -	emit_indirect_jump (return_link); -	emit_label (done_label);  	return op0;        } | 

