aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-07-21 17:42:54 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-07-21 17:42:54 -0700
commit8943a0b4d855341542bf9b5fe4d29b616078ca9a (patch)
tree9405da1d51ba2f549696823714d6adf0ba1ea1fd /gcc/expr.c
parentb1aef35bb1ba3ee75c7e9831b3248ab8d1f7b353 (diff)
downloadgcc-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.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 7b5810c..e70bf90 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;
}