{
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;
}
static int process_option_with_no PARAMS ((const char *,
const struct string_option *,
int));
+static int java_unsafe_for_reeval PARAMS ((tree));
#ifndef TARGET_OBJECT_SUFFIX
# define TARGET_OBJECT_SUFFIX ".o"
#define LANG_HOOKS_POST_OPTIONS java_post_options
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE java_parse_file
+#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
+#define LANG_HOOKS_UNSAFE_FOR_REEVAL java_unsafe_for_reeval
#undef LANG_HOOKS_MARK_ADDRESSABLE
#define LANG_HOOKS_MARK_ADDRESSABLE java_mark_addressable
#undef LANG_HOOKS_EXPAND_EXPR
return false;
}
+/* Called from unsafe_for_reeval. */
+static int
+java_unsafe_for_reeval (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case BLOCK:
+ /* Our expander tries to expand the variables twice. Boom. */
+ if (BLOCK_EXPR_DECLS (t) != NULL)
+ return 2;
+ return unsafe_for_reeval (BLOCK_EXPR_BODY (t));
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
#include "gt-java-lang.h"