diff options
author | Richard Henderson <rth@redhat.com> | 2002-07-21 17:42:54 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2002-07-21 17:42:54 -0700 |
commit | 8943a0b4d855341542bf9b5fe4d29b616078ca9a (patch) | |
tree | 9405da1d51ba2f549696823714d6adf0ba1ea1fd /gcc/expr.c | |
parent | b1aef35bb1ba3ee75c7e9831b3248ab8d1f7b353 (diff) | |
download | gcc-8943a0b4d855341542bf9b5fe4d29b616078ca9a.zip gcc-8943a0b4d855341542bf9b5fe4d29b616078ca9a.tar.gz gcc-8943a0b4d855341542bf9b5fe4d29b616078ca9a.tar.bz2 |
expr.c (expand_expr): Don't use GOTO_SUBROUTINE_EXPR when finally_block can be re-expanded.
* 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.
From-SVN: r55636
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 58 |
1 files changed, 39 insertions, 19 deletions
@@ -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; } |