aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/except.c58
-rw-r--r--gcc/except.h9
-rw-r--r--gcc/stmt.c42
-rw-r--r--gcc/tree.h3
4 files changed, 58 insertions, 54 deletions
diff --git a/gcc/except.c b/gcc/except.c
index f52fc13..71925a5 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -911,7 +911,8 @@ start_dynamic_handler ()
of a using an exception region. */
int
-expand_eh_region_start_tree (cleanup)
+expand_eh_region_start_tree (decl, cleanup)
+ tree decl;
tree cleanup;
{
rtx note;
@@ -952,52 +953,25 @@ expand_eh_region_start_tree (cleanup)
{
/* Arrange for returns and gotos to pop the entry we make on the
dynamic cleanup stack. */
- expand_dcc_cleanup ();
+ expand_dcc_cleanup (decl);
start_dynamic_cleanup (func, arg);
return 1;
}
}
- if (exceptions_via_longjmp)
- {
- /* We need a new block to record the start and end of the
- dynamic handler chain. We could always do this, but we
- really want to permit jumping into such a block, and we want
- to avoid any errors or performance impact in the SJ EH code
- for now. */
- expand_start_bindings (0);
-
- /* But we don't need or want a new temporary level. */
- pop_temp_slots ();
-
- /* Mark this block as created by expand_eh_region_start. This
- is so that we can pop the block with expand_end_bindings
- automatically. */
- mark_block_as_eh_region ();
-
- /* Arrange for returns and gotos to pop the entry we make on the
- dynamic handler stack. */
- expand_dhc_cleanup ();
- }
-
- if (exceptions_via_longjmp == 0)
- note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_BEG);
- emit_label (push_eh_entry (&ehstack));
- if (exceptions_via_longjmp == 0)
- NOTE_BLOCK_NUMBER (note)
- = CODE_LABEL_NUMBER (ehstack.top->entry->exception_handler_label);
- if (exceptions_via_longjmp)
- start_dynamic_handler ();
+ expand_eh_region_start_for_decl (decl);
return 0;
}
-/* Start an exception handling region. All instructions emitted after
- this point are considered to be part of the region until
- expand_eh_region_end is invoked. */
+/* Just like expand_eh_region_start, except if a cleanup action is
+ entered on the cleanup chain, the TREE_PURPOSE of the element put
+ on the chain is DECL. DECL should be the associated VAR_DECL, if
+ any, otherwise it should be NULL_TREE. */
void
-expand_eh_region_start ()
+expand_eh_region_start_for_decl (decl)
+ tree decl;
{
rtx note;
@@ -1024,7 +998,7 @@ expand_eh_region_start ()
/* Arrange for returns and gotos to pop the entry we make on the
dynamic handler stack. */
- expand_dhc_cleanup ();
+ expand_dhc_cleanup (decl);
}
if (exceptions_via_longjmp == 0)
@@ -1037,6 +1011,16 @@ expand_eh_region_start ()
start_dynamic_handler ();
}
+/* Start an exception handling region. All instructions emitted after
+ this point are considered to be part of the region until
+ expand_eh_region_end is invoked. */
+
+void
+expand_eh_region_start ()
+{
+ expand_eh_region_start_for_decl (NULL_TREE);
+}
+
/* End an exception handling region. The information about the region
is found on the top of ehstack.
diff --git a/gcc/except.h b/gcc/except.h
index e939afa8..8d4c5a6 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -88,6 +88,13 @@ struct eh_queue {
extern void expand_eh_region_start PROTO((void));
+/* Just like expand_eh_region_start, except if a cleanup action is
+ entered on the cleanup chain, the TREE_PURPOSE of the element put
+ on the chain is DECL. DECL should be the associated VAR_DECL, if
+ any, otherwise it should be NULL_TREE. */
+
+extern void expand_eh_region_start_for_decl PROTO((tree));
+
/* Start an exception handling region for the given cleanup action.
All instructions emitted after this point are considered to be part
of the region until expand_eh_region_end () is invoked. CLEANUP is
@@ -100,7 +107,7 @@ extern void expand_eh_region_start PROTO((void));
generation, and optimizes it so as to not need the exception
region. */
-extern int expand_eh_region_start_tree PROTO((tree));
+extern int expand_eh_region_start_tree PROTO((tree, tree));
/* End an exception handling region. The information about the region
is found on the top of ehstack.
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 945d98c..6d78234 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -3950,7 +3950,7 @@ expand_decl_cleanup (decl, cleanup)
/* If this was optimized so that there is no exception region for the
cleanup, then mark the TREE_LIST node, so that we can later tell
if we need to call expand_eh_region_end. */
- if (expand_eh_region_start_tree (cleanup))
+ if (expand_eh_region_start_tree (decl, cleanup))
TREE_ADDRESSABLE (t) = 1;
if (cond_context)
@@ -3972,11 +3972,12 @@ expand_decl_cleanup (decl, cleanup)
}
/* Arrange for the top element of the dynamic cleanup chain to be
- popped if we exit the current binding contour. If the current
- contour is left via an exception, then __sjthrow will pop the top
- element off the dynamic cleanup chain. The code that avoids doing
- the action we push into the cleanup chain in the exceptional case
- is contained in expand_cleanups.
+ popped if we exit the current binding contour. DECL is the
+ associated declaration, if any, otherwise NULL_TREE. If the
+ current contour is left via an exception, then __sjthrow will pop
+ the top element off the dynamic cleanup chain. The code that
+ avoids doing the action we push into the cleanup chain in the
+ exceptional case is contained in expand_cleanups.
This routine is only used by expand_eh_region_start, and that is
the only way in which an exception region should be started. This
@@ -3984,7 +3985,8 @@ expand_decl_cleanup (decl, cleanup)
for exception handling. */
int
-expand_dcc_cleanup ()
+expand_dcc_cleanup (decl)
+ tree decl;
{
struct nesting *thisblock = block_stack;
tree cleanup;
@@ -4003,7 +4005,7 @@ expand_dcc_cleanup ()
/* Add the cleanup in a manner similar to expand_decl_cleanup. */
thisblock->data.block.cleanups
- = temp_tree_cons (NULL_TREE, cleanup, thisblock->data.block.cleanups);
+ = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
/* If this block has a cleanup, it belongs in stack_block_stack. */
stack_block_stack = thisblock;
@@ -4011,11 +4013,12 @@ expand_dcc_cleanup ()
}
/* Arrange for the top element of the dynamic handler chain to be
- popped if we exit the current binding contour. If the current
- contour is left via an exception, then __sjthrow will pop the
- top element off the dynamic handler chain. The code that avoids
- doing the action we push into the handler chain in the exceptional
- case is contained in expand_cleanups.
+ popped if we exit the current binding contour. DECL is the
+ assciated declaration, if any, otherwise NULL_TREE. If the current
+ contour is left via an exception, then __sjthrow will pop the top
+ element off the dynamic handler chain. The code that avoids doing
+ the action we push into the handler chain in the exceptional case
+ is contained in expand_cleanups.
This routine is only used by expand_eh_region_start, and that is
the only way in which an exception region should be started. This
@@ -4023,7 +4026,8 @@ expand_dcc_cleanup ()
for exception handling. */
int
-expand_dhc_cleanup ()
+expand_dhc_cleanup (decl)
+ tree decl;
{
struct nesting *thisblock = block_stack;
tree cleanup;
@@ -4042,7 +4046,7 @@ expand_dhc_cleanup ()
/* Add the cleanup in a manner similar to expand_decl_cleanup. */
thisblock->data.block.cleanups
- = temp_tree_cons (NULL_TREE, cleanup, thisblock->data.block.cleanups);
+ = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
/* If this block has a cleanup, it belongs in stack_block_stack. */
stack_block_stack = thisblock;
@@ -4303,6 +4307,8 @@ expand_start_case (exit_flag, expr, type, printname)
emit_note (NULL_PTR, NOTE_INSN_DELETED);
thiscase->data.case_stmt.start = get_last_insn ();
+
+ start_cleanup_deferal ();
}
@@ -4355,6 +4361,7 @@ expand_start_case_dummy ()
thiscase->data.case_stmt.num_ranges = 0;
case_stack = thiscase;
nesting_stack = thiscase;
+ start_cleanup_deferal ();
}
/* End a dummy case statement. */
@@ -4362,6 +4369,7 @@ expand_start_case_dummy ()
void
expand_end_case_dummy ()
{
+ end_cleanup_deferal ();
POPSTACK (case_stack);
}
@@ -5355,6 +5363,8 @@ expand_end_case (orig_index)
if (count != 0)
range = fold (build (MINUS_EXPR, index_type, maxval, minval));
+ end_cleanup_deferal ();
+
if (count == 0)
{
expand_expr (index_expr, const0_rtx, VOIDmode, 0);
@@ -5622,6 +5632,8 @@ expand_end_case (orig_index)
reorder_insns (before_case, get_last_insn (),
thiscase->data.case_stmt.start);
}
+ else
+ end_cleanup_deferal ();
if (thiscase->exit_label)
emit_label (thiscase->exit_label);
diff --git a/gcc/tree.h b/gcc/tree.h
index e0ae9c9..ff73de4 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1697,7 +1697,8 @@ extern void mark_block_as_not_eh_region PROTO((void));
extern int is_eh_region PROTO((void));
extern int conditional_context PROTO((void));
extern tree last_cleanup_this_contour PROTO((void));
-extern int expand_dhc_cleanup PROTO((void));
+extern int expand_dhc_cleanup PROTO((tree));
+extern int expand_dcc_cleanup PROTO((tree));
extern void expand_start_case PROTO((int, tree, tree,
char *));
extern void expand_end_case PROTO((tree));