struct GTY(()) ehl_map_entry {
rtx label;
- struct eh_region *region;
+ struct eh_region_d *region;
};
static GTY(()) int call_site_base;
static int sjlj_fc_jbuf_ofs;
\f
-struct GTY(()) call_site_record
+struct GTY(()) call_site_record_d
{
rtx landing_pad;
int action;
static void sjlj_emit_dispatch_table (rtx, struct sjlj_lp_info *);
static void sjlj_build_landing_pads (void);
-static void remove_eh_handler (struct eh_region *);
-static void remove_eh_handler_and_replace (struct eh_region *,
- struct eh_region *, bool);
+static void remove_eh_handler (struct eh_region_d *);
+static void remove_eh_handler_and_replace (struct eh_region_d *,
+ struct eh_region_d *, bool);
/* The return value of reachable_next_level. */
enum reachable_code
};
struct reachable_info;
-static enum reachable_code reachable_next_level (struct eh_region *, tree,
+static enum reachable_code reachable_next_level (struct eh_region_d *, tree,
struct reachable_info *, bool);
static int action_record_eq (const void *, const void *);
static hashval_t action_record_hash (const void *);
static int add_action_record (htab_t, int, int);
-static int collect_one_action_chain (htab_t, struct eh_region *);
-static int add_call_site (rtx, int);
+static int collect_one_action_chain (htab_t, struct eh_region_d *);
+static int add_call_site (rtx, int, int);
static void push_uleb128 (varray_type *, unsigned int);
static void push_sleb128 (varray_type *, int);
#ifndef HAVE_AS_LEB128
-static int dw2_size_of_call_site_table (void);
+static int dw2_size_of_call_site_table (int);
static int sjlj_size_of_call_site_table (void);
#endif
-static void dw2_output_call_site_table (void);
+static void dw2_output_call_site_table (int, int);
static void sjlj_output_call_site_table (void);
\f
sjlj_fc_type_node = lang_hooks.types.make_type (RECORD_TYPE);
- f_prev = build_decl (FIELD_DECL, get_identifier ("__prev"),
+ f_prev = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, get_identifier ("__prev"),
build_pointer_type (sjlj_fc_type_node));
DECL_FIELD_CONTEXT (f_prev) = sjlj_fc_type_node;
- f_cs = build_decl (FIELD_DECL, get_identifier ("__call_site"),
+ f_cs = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, get_identifier ("__call_site"),
integer_type_node);
DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
tmp = build_array_type (lang_hooks.types.type_for_mode
(targetm.unwind_word_mode (), 1),
tmp);
- f_data = build_decl (FIELD_DECL, get_identifier ("__data"), tmp);
+ f_data = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, get_identifier ("__data"), tmp);
DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
- f_per = build_decl (FIELD_DECL, get_identifier ("__personality"),
+ f_per = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, get_identifier ("__personality"),
ptr_type_node);
DECL_FIELD_CONTEXT (f_per) = sjlj_fc_type_node;
- f_lsda = build_decl (FIELD_DECL, get_identifier ("__lsda"),
+ f_lsda = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, get_identifier ("__lsda"),
ptr_type_node);
DECL_FIELD_CONTEXT (f_lsda) = sjlj_fc_type_node;
#endif
tmp = build_index_type (tmp);
tmp = build_array_type (ptr_type_node, tmp);
- f_jbuf = build_decl (FIELD_DECL, get_identifier ("__jbuf"), tmp);
+ f_jbuf = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, get_identifier ("__jbuf"), tmp);
#ifdef DONT_USE_BUILTIN_SETJMP
/* We don't know what the alignment requirements of the
runtime's jmp_buf has. Overestimate. */
These are used from tree-eh.c when processing exception related
nodes during tree optimization. */
-static struct eh_region *
-gen_eh_region (enum eh_region_type type, struct eh_region *outer)
+static struct eh_region_d *
+gen_eh_region (enum eh_region_type type, struct eh_region_d *outer)
{
- struct eh_region *new_eh;
+ struct eh_region_d *new_eh;
#ifdef ENABLE_CHECKING
gcc_assert (doing_eh (0));
#endif
/* Insert a new blank region as a leaf in the tree. */
- new_eh = GGC_CNEW (struct eh_region);
+ new_eh = GGC_CNEW (struct eh_region_d);
new_eh->type = type;
new_eh->outer = outer;
if (outer)
return new_eh;
}
-struct eh_region *
-gen_eh_region_cleanup (struct eh_region *outer)
+struct eh_region_d *
+gen_eh_region_cleanup (struct eh_region_d *outer)
{
- struct eh_region *cleanup = gen_eh_region (ERT_CLEANUP, outer);
+ struct eh_region_d *cleanup = gen_eh_region (ERT_CLEANUP, outer);
return cleanup;
}
-struct eh_region *
-gen_eh_region_try (struct eh_region *outer)
+struct eh_region_d *
+gen_eh_region_try (struct eh_region_d *outer)
{
return gen_eh_region (ERT_TRY, outer);
}
-struct eh_region *
-gen_eh_region_catch (struct eh_region *t, tree type_or_list)
+struct eh_region_d *
+gen_eh_region_catch (struct eh_region_d *t, tree type_or_list)
{
- struct eh_region *c, *l;
+ struct eh_region_d *c, *l;
tree type_list, type_node;
/* Ensure to always end up with a type list to normalize further
return c;
}
-struct eh_region *
-gen_eh_region_allowed (struct eh_region *outer, tree allowed)
+struct eh_region_d *
+gen_eh_region_allowed (struct eh_region_d *outer, tree allowed)
{
- struct eh_region *region = gen_eh_region (ERT_ALLOWED_EXCEPTIONS, outer);
+ struct eh_region_d *region = gen_eh_region (ERT_ALLOWED_EXCEPTIONS, outer);
region->u.allowed.type_list = allowed;
for (; allowed ; allowed = TREE_CHAIN (allowed))
return region;
}
-struct eh_region *
-gen_eh_region_must_not_throw (struct eh_region *outer)
+struct eh_region_d *
+gen_eh_region_must_not_throw (struct eh_region_d *outer)
{
return gen_eh_region (ERT_MUST_NOT_THROW, outer);
}
int
-get_eh_region_number (struct eh_region *region)
+get_eh_region_number (struct eh_region_d *region)
{
return region->region_number;
}
bool
-get_eh_region_may_contain_throw (struct eh_region *region)
+get_eh_region_may_contain_throw (struct eh_region_d *region)
{
return region->may_contain_throw;
}
tree
-get_eh_region_tree_label (struct eh_region *region)
+get_eh_region_tree_label (struct eh_region_d *region)
{
return region->tree_label;
}
}
void
-set_eh_region_tree_label (struct eh_region *region, tree lab)
+set_eh_region_tree_label (struct eh_region_d *region, tree lab)
{
region->tree_label = lab;
}
expand_resx_expr (tree exp)
{
int region_nr = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
- struct eh_region *reg = VEC_index (eh_region,
- cfun->eh->region_array, region_nr);
+ rtx insn;
+ struct eh_region_d *reg = VEC_index (eh_region,
+ cfun->eh->region_array, region_nr);
- gcc_assert (!reg->resume);
do_pending_stack_adjust ();
- reg->resume = emit_jump_insn (gen_rtx_RESX (VOIDmode, region_nr));
+ insn = emit_jump_insn (gen_rtx_RESX (VOIDmode, region_nr));
+ if (reg->resume)
+ reg->resume = gen_rtx_INSN_LIST (VOIDmode, insn, reg->resume);
+ else
+ reg->resume = insn;
emit_barrier ();
}
call to a function which itself may contain a throw. */
void
-note_eh_region_may_contain_throw (struct eh_region *region)
+note_eh_region_may_contain_throw (struct eh_region_d *region)
{
while (region && !region->may_contain_throw)
{
void
collect_eh_region_array (void)
{
- struct eh_region *i;
+ struct eh_region_d *i;
i = cfun->eh->region_tree;
if (! i)
a problem. */
static bool
-can_be_reached_by_runtime (sbitmap contains_stmt, struct eh_region *r)
+can_be_reached_by_runtime (sbitmap contains_stmt, struct eh_region_d *r)
{
- struct eh_region *i = r->inner;
+ struct eh_region_d *i = r->inner;
unsigned n;
bitmap_iterator bi;
if (i->type != ERT_MUST_NOT_THROW)
{
bool found = TEST_BIT (contains_stmt, i->region_number);
- if (!found)
+ if (!found && i->aka)
EXECUTE_IF_SET_IN_BITMAP (i->aka, 0, n, bi)
if (TEST_BIT (contains_stmt, n))
{
firest place. */
if (found)
{
- struct eh_region *i1 = i;
+ struct eh_region_d *i1 = i;
tree type_thrown = NULL_TREE;
if (i1->type == ERT_THROW)
/* Bring region R to the root of tree. */
static void
-bring_to_root (struct eh_region *r)
+bring_to_root (struct eh_region_d *r)
{
- struct eh_region **pp;
- struct eh_region *outer = r->outer;
+ struct eh_region_d **pp;
+ struct eh_region_d *outer = r->outer;
if (!r->outer)
return;
for (pp = &outer->inner; *pp != r; pp = &(*pp)->next_peer)
/* Return true if region R2 can be replaced by R1. */
static bool
-eh_region_replaceable_by_p (const struct eh_region *r1,
- const struct eh_region *r2)
+eh_region_replaceable_by_p (const struct eh_region_d *r1,
+ const struct eh_region_d *r2)
{
/* Regions are semantically same if they are of same type,
have same label and type. */
break;
case ERT_TRY:
{
- struct eh_region *c1, *c2;
+ struct eh_region_d *c1, *c2;
for (c1 = r1->u.eh_try.eh_catch,
c2 = r2->u.eh_try.eh_catch;
c1 && c2;
/* Replace region R2 by R1. */
static void
-replace_region (struct eh_region *r1, struct eh_region *r2)
+replace_region (struct eh_region_d *r1, struct eh_region_d *r2)
{
- struct eh_region *next1 = r1->u.eh_try.eh_catch;
- struct eh_region *next2 = r2->u.eh_try.eh_catch;
+ struct eh_region_d *next1 = r1->u.eh_try.eh_catch;
+ struct eh_region_d *next2 = r2->u.eh_try.eh_catch;
bool is_try = r1->type == ERT_TRY;
gcc_assert (r1->type != ERT_CATCH);
static hashval_t
hash_eh_region (const void *r)
{
- const struct eh_region *region = (const struct eh_region *)r;
+ const struct eh_region_d *region = (const struct eh_region_d *) r;
hashval_t val = region->type;
if (region->tree_label)
break;
case ERT_TRY:
{
- struct eh_region *c;
+ struct eh_region_d *c;
for (c = region->u.eh_try.eh_catch;
c; c = c->u.eh_catch.next_catch)
val = iterative_hash_hashval_t (hash_eh_region (c), val);
static int
eh_regions_equal_p (const void *r1, const void *r2)
{
- return eh_region_replaceable_by_p ((const struct eh_region *)r1,
- (const struct eh_region *)r2);
+ return eh_region_replaceable_by_p ((const struct eh_region_d *) r1,
+ (const struct eh_region_d *) r2);
}
/* Walk all peers of REGION and try to merge those regions
recursively too. */
static bool
-merge_peers (struct eh_region *region)
+merge_peers (struct eh_region_d *region)
{
- struct eh_region *r1, *r2, *outer = NULL, *next;
+ struct eh_region_d *r1, *r2, *outer = NULL, *next;
bool merged = false;
int num_regions = 0;
if (region)
if (!*slot)
*slot = r1;
else
- replace_region ((struct eh_region *)*slot, r1);
+ replace_region ((struct eh_region_d *) *slot, r1);
}
htab_delete (hash);
}
remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt)
{
int i;
- struct eh_region *r;
+ struct eh_region_d *r;
VEC(eh_region,heap) *must_not_throws = VEC_alloc (eh_region, heap, 16);
- struct eh_region *local_must_not_throw = NULL;
- struct eh_region *first_must_not_throw = NULL;
+ struct eh_region_d *local_must_not_throw = NULL;
+ struct eh_region_d *first_must_not_throw = NULL;
for (i = cfun->eh->last_region_number; i > 0; --i)
{
{
/* TRY regions are reachable if any of its CATCH regions
are reachable. */
- struct eh_region *c;
+ struct eh_region_d *c;
for (c = r->u.eh_try.eh_catch; c;
c = c->u.eh_catch.next_catch)
if (TEST_BIT (reachable, c->region_number))
cfun->cfg->last_label_uid + 1);
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *r = VEC_index (eh_region, cfun->eh->region_array, i);
+ struct eh_region_d *r = VEC_index (eh_region, cfun->eh->region_array, i);
if (r && r->region_number == i
&& r->tree_label && LABEL_DECL_UID (r->tree_label) >= 0)
{
int
get_next_region_sharing_label (int region)
{
- struct eh_region *r;
+ struct eh_region_d *r;
if (!region)
return 0;
r = VEC_index (eh_region, cfun->eh->region_array, region);
return r->next_region_sharing_label->region_number;
}
+/* Return bitmap of all labels that are handlers of must not throw regions. */
+
+bitmap
+must_not_throw_labels (void)
+{
+ struct eh_region_d *i;
+ bitmap labels = BITMAP_ALLOC (NULL);
+
+ i = cfun->eh->region_tree;
+ if (! i)
+ return labels;
+
+ while (1)
+ {
+ if (i->type == ERT_MUST_NOT_THROW && i->tree_label
+ && LABEL_DECL_UID (i->tree_label) >= 0)
+ bitmap_set_bit (labels, LABEL_DECL_UID (i->tree_label));
+
+ /* If there are sub-regions, process them. */
+ if (i->inner)
+ i = i->inner;
+ /* If there are peers, process them. */
+ else if (i->next_peer)
+ i = i->next_peer;
+ /* Otherwise, step back up the tree to the next peer. */
+ else
+ {
+ do {
+ i = i->outer;
+ if (i == NULL)
+ return labels;
+ } while (i->next_peer == NULL);
+ i = i->next_peer;
+ }
+ }
+}
+
/* Set up EH labels for RTL. */
void
we allocated earlier. */
for (i = 1; i <= n; ++i)
{
- struct eh_region *region;
+ struct eh_region_d *region;
region = VEC_index (eh_region, cfun->eh->region_array, i);
if (region && region->tree_label)
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *region;
+ struct eh_region_d *region;
rtx lab;
region = VEC_index (eh_region, cfun->eh->region_array, i);
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *region;
+ struct eh_region_d *region;
region = VEC_index (eh_region, cfun->eh->region_array, i);
if (region
{
eh_region ret, n;
- ret = n = GGC_NEW (struct eh_region);
+ ret = n = GGC_NEW (struct eh_region_d);
*n = *old;
n->outer = outer;
/* Look for first outer region of R (or R itself) that is
TRY region. Return NULL if none. */
-static struct eh_region *
-find_prev_try (struct eh_region * r)
+static struct eh_region_d *
+find_prev_try (struct eh_region_d * r)
{
for (; r && r->type != ERT_TRY; r = r->outer)
if (r->type == ERT_MUST_NOT_THROW
/* Return new copy of eh region OLD inside region NEW_OUTER.
Do not care about updating the tree otherwise. */
-static struct eh_region *
-copy_eh_region_1 (struct eh_region *old, struct eh_region *new_outer)
+static struct eh_region_d *
+copy_eh_region_1 (struct eh_region_d *old, struct eh_region_d *new_outer)
{
- struct eh_region *new_eh = gen_eh_region (old->type, new_outer);
+ struct eh_region_d *new_eh = gen_eh_region (old->type, new_outer);
new_eh->u = old->u;
new_eh->tree_label = old->tree_label;
new_eh->may_contain_throw = old->may_contain_throw;
Copy whole catch-try chain if neccesary. */
-static struct eh_region *
-copy_eh_region (struct eh_region *old, struct eh_region *new_outer)
+static struct eh_region_d *
+copy_eh_region (struct eh_region_d *old, struct eh_region_d *new_outer)
{
- struct eh_region *r, *n, *old_try, *new_try, *ret = NULL;
+ struct eh_region_d *r, *n, *old_try, *new_try, *ret = NULL;
VEC(eh_region,heap) *catch_list = NULL;
if (old->type != ERT_CATCH)
/* Callback for forach_reachable_handler that push REGION into single VECtor DATA. */
static void
-push_reachable_handler (struct eh_region *region, void *data)
+push_reachable_handler (struct eh_region_d *region, void *data)
{
VEC(eh_region,heap) **trace = (VEC(eh_region,heap) **) data;
VEC_safe_push (eh_region, heap, *trace, region);
IS_RESX, INLINABLE_CALL and REGION_NMUBER match the parameter of
foreach_reachable_handler. */
-struct eh_region *
+struct eh_region_d *
redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx,
bool inlinable_call, int region_number)
{
- struct eh_region *outer;
- struct eh_region *region;
+ struct eh_region_d *outer;
+ struct eh_region_d *region;
VEC (eh_region, heap) * trace = NULL;
int i;
int start_here = -1;
basic_block old_bb = e->dest;
- struct eh_region *old, *r = NULL;
+ struct eh_region_d *old, *r = NULL;
bool update_inplace = true;
edge_iterator ei;
edge e2;
int
eh_region_outermost (struct function *ifun, int region_a, int region_b)
{
- struct eh_region *rp_a, *rp_b;
+ struct eh_region_d *rp_a, *rp_b;
sbitmap b_outer;
gcc_assert (ifun->eh->last_region_number > 0);
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *r;
+ struct eh_region_d *r;
r = VEC_index (eh_region, cfun->eh->region_array, i);
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *region;
+ struct eh_region_d *region;
rtx seq;
region = VEC_index (eh_region, cfun->eh->region_array, i);
switch statement generation code in expand_end_case.
Rapid prototyping sez a sequence of ifs. */
{
- struct eh_region *c;
+ struct eh_region_d *c;
for (c = region->u.eh_try.eh_catch; c ; c = c->u.eh_catch.next_catch)
{
if (c->u.eh_catch.type_list == NULL)
/* We delay the generation of the _Unwind_Resume until we generate
landing pads. We emit a marker here so as to get good control
flow data in the meantime. */
+ gcc_assert (!region->resume);
region->resume
= emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
emit_barrier ();
/* We delay the generation of the _Unwind_Resume until we generate
landing pads. We emit a marker here so as to get good control
flow data in the meantime. */
+ gcc_assert (!region->resume);
region->resume
= emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
emit_barrier ();
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *region;
- struct eh_region *outer;
+ struct eh_region_d *region;
+ struct eh_region_d *outer;
rtx seq;
rtx barrier;
+ rtx resume_list;
region = VEC_index (eh_region, cfun->eh->region_array, i);
/* Mind we don't process a region more than once. */
/* If there is no RESX, or it has been deleted by flow, there's
nothing to fix up. */
- if (! region->resume || INSN_DELETED_P (region->resume))
+ if (! region->resume)
continue;
/* Search for another landing pad in this function. */
if (outer->post_landing_pad)
break;
- start_sequence ();
-
- if (outer)
- {
- edge e;
- basic_block src, dest;
-
- emit_jump (outer->post_landing_pad);
- src = BLOCK_FOR_INSN (region->resume);
- dest = BLOCK_FOR_INSN (outer->post_landing_pad);
- while (EDGE_COUNT (src->succs) > 0)
- remove_edge (EDGE_SUCC (src, 0));
- e = make_edge (src, dest, 0);
- e->probability = REG_BR_PROB_BASE;
- e->count = src->count;
- }
- else
+ for (resume_list = region->resume; resume_list;
+ resume_list = (GET_CODE (resume_list) == INSN_LIST
+ ? XEXP (resume_list, 1) : NULL_RTX))
{
- emit_library_call (unwind_resume_libfunc, LCT_THROW,
- VOIDmode, 1, crtl->eh.exc_ptr, ptr_mode);
-
- /* What we just emitted was a throwing libcall, so it got a
- barrier automatically added after it. If the last insn in
- the libcall sequence isn't the barrier, it's because the
- target emits multiple insns for a call, and there are insns
- after the actual call insn (which are redundant and would be
- optimized away). The barrier is inserted exactly after the
- call insn, so let's go get that and delete the insns after
- it, because below we need the barrier to be the last insn in
- the sequence. */
- delete_insns_since (NEXT_INSN (last_call_insn ()));
- }
+ rtx resume = (GET_CODE (resume_list) == INSN_LIST
+ ? XEXP (resume_list, 0) : resume_list);
+ if (INSN_DELETED_P (resume))
+ continue;
+ start_sequence ();
- seq = get_insns ();
- end_sequence ();
- barrier = emit_insn_before (seq, region->resume);
- /* Avoid duplicate barrier. */
- gcc_assert (BARRIER_P (barrier));
- delete_insn (barrier);
- delete_insn (region->resume);
+ if (outer)
+ {
+ edge e;
+ basic_block src, dest;
+
+ emit_jump (outer->post_landing_pad);
+ src = BLOCK_FOR_INSN (resume);
+ dest = BLOCK_FOR_INSN (outer->post_landing_pad);
+ while (EDGE_COUNT (src->succs) > 0)
+ remove_edge (EDGE_SUCC (src, 0));
+ e = make_edge (src, dest, 0);
+ e->probability = REG_BR_PROB_BASE;
+ e->count = src->count;
+ }
+ else
+ {
+ emit_library_call (unwind_resume_libfunc, LCT_THROW,
+ VOIDmode, 1, crtl->eh.exc_ptr, ptr_mode);
+
+ /* What we just emitted was a throwing libcall, so it got a
+ barrier automatically added after it. If the last insn in
+ the libcall sequence isn't the barrier, it's because the
+ target emits multiple insns for a call, and there are insns
+ after the actual call insn (which are redundant and would be
+ optimized away). The barrier is inserted exactly after the
+ call insn, so let's go get that and delete the insns after
+ it, because below we need the barrier to be the last insn in
+ the sequence. */
+ delete_insns_since (NEXT_INSN (last_call_insn ()));
+ }
+
+ seq = get_insns ();
+ end_sequence ();
+ barrier = emit_insn_before (seq, resume);
+ /* Avoid duplicate barrier. */
+ gcc_assert (BARRIER_P (barrier));
+ delete_insn (barrier);
+ delete_insn (resume);
+ }
/* ??? From tree-ssa we can wind up with catch regions whose
label is not instantiated, but whose resx is present. Now
for (i = cfun->eh->last_region_number; i > 0; --i)
{
- struct eh_region *region;
+ struct eh_region_d *region;
rtx seq;
basic_block bb;
edge e;
for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
{
- struct eh_region *region;
+ struct eh_region_d *region;
enum reachable_code rc;
tree type_thrown;
rtx note;
for (i = cfun->eh->last_region_number; i > 0; --i)
if (lp_info[i].directly_reachable)
{
- struct eh_region *r = VEC_index (eh_region, cfun->eh->region_array, i);
+ struct eh_region_d *r =
+ VEC_index (eh_region, cfun->eh->region_array, i);
r->landing_pad = dispatch_label;
lp_info[i].action_index = collect_one_action_chain (ar_hash, r);
index = -1;
/* Otherwise, look it up in the table. */
else
- index = add_call_site (GEN_INT (lp_info[i].dispatch_index), action);
+ index = add_call_site (GEN_INT (lp_info[i].dispatch_index),
+ action, 0);
lp_info[i].call_site_index = index;
}
for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
{
- struct eh_region *region;
+ struct eh_region_d *region;
int this_call_site;
rtx note, before, p;
emit_cmp_and_jump_insns (dispatch, GEN_INT (lp_info[i].dispatch_index),
EQ, NULL_RTX, TYPE_MODE (integer_type_node), 0,
- ((struct eh_region *)VEC_index (eh_region, cfun->eh->region_array, i))
- ->post_landing_pad);
+ (((struct eh_region_d *)
+ VEC_index (eh_region,
+ cfun->eh->region_array, i))
+ ->post_landing_pad));
}
seq = get_insns ();
end_sequence ();
- before = (((struct eh_region *)VEC_index (eh_region, cfun->eh->region_array, first_reachable))
+ before = (((struct eh_region_d *)
+ VEC_index (eh_region, cfun->eh->region_array, first_reachable))
->post_landing_pad);
bb = emit_to_new_bb_before (seq, before);
region.*/
static void
-remove_eh_handler_and_replace (struct eh_region *region,
- struct eh_region *replace,
+remove_eh_handler_and_replace (struct eh_region_d *region,
+ struct eh_region_d *replace,
bool update_catch_try)
{
- struct eh_region **pp, **pp_start, *p, *outer, *inner;
+ struct eh_region_d **pp, **pp_start, *p, *outer, *inner;
rtx lab;
outer = region->outer;
if (region->type == ERT_CATCH
&& update_catch_try)
{
- struct eh_region *eh_try, *next, *prev;
+ struct eh_region_d *eh_try, *next, *prev;
for (eh_try = region->next_peer;
eh_try->type == ERT_CATCH;
etc. */
static void
-remove_eh_handler (struct eh_region *region)
+remove_eh_handler (struct eh_region_d *region)
{
remove_eh_handler_and_replace (region, region->outer, true);
}
void
remove_eh_region (int r)
{
- struct eh_region *region;
+ struct eh_region_d *region;
region = VEC_index (eh_region, cfun->eh->region_array, r);
remove_eh_handler (region);
void
remove_eh_region_and_replace_by_outer_of (int r, int r2)
{
- struct eh_region *region, *region2;
+ struct eh_region_d *region, *region2;
region = VEC_index (eh_region, cfun->eh->region_array, r);
region2 = VEC_index (eh_region, cfun->eh->region_array, r2);
int i;
for (i = 0; i < cfun->eh->last_region_number; i++)
{
- struct eh_region *r = VEC_index (eh_region, cfun->eh->region_array, i);
+ struct eh_region_d *r = VEC_index (eh_region, cfun->eh->region_array, i);
if (r && r->region_number == i && r->label
- && GET_CODE (r->label) == CODE_LABEL)
+ && LABEL_P (r->label))
(*callback) (r->label);
}
}
/* Invoke CALLBACK for every exception region in the current function. */
void
-for_each_eh_region (void (*callback) (struct eh_region *))
+for_each_eh_region (void (*callback) (struct eh_region_d *))
{
int i, n = cfun->eh->last_region_number;
for (i = 1; i <= n; ++i)
{
- struct eh_region *region;
+ struct eh_region_d *region;
region = VEC_index (eh_region, cfun->eh->region_array, i);
if (region)
{
tree types_caught;
tree types_allowed;
- void (*callback) (struct eh_region *, void *);
+ void (*callback) (struct eh_region_d *, void *);
void *callback_data;
};
static void
add_reachable_handler (struct reachable_info *info,
- struct eh_region *lp_region, struct eh_region *region)
+ struct eh_region_d *lp_region,
+ struct eh_region_d *region)
{
if (! info)
return;
and caught/allowed type information between invocations. */
static enum reachable_code
-reachable_next_level (struct eh_region *region, tree type_thrown,
+reachable_next_level (struct eh_region_d *region, tree type_thrown,
struct reachable_info *info,
bool maybe_resx)
{
case ERT_TRY:
{
- struct eh_region *c;
+ struct eh_region_d *c;
enum reachable_code ret = RNL_NOT_CAUGHT;
for (c = region->u.eh_try.eh_catch; c ; c = c->u.eh_catch.next_catch)
void
foreach_reachable_handler (int region_number, bool is_resx, bool inlinable_call,
- void (*callback) (struct eh_region *, void *),
+ void (*callback) (struct eh_region_d *, void *),
void *callback_data)
{
struct reachable_info info;
- struct eh_region *region;
+ struct eh_region_d *region;
tree type_thrown;
memset (&info, 0, sizeof (info));
reached by a given insn. */
static void
-arh_to_landing_pad (struct eh_region *region, void *data)
+arh_to_landing_pad (struct eh_region_d *region, void *data)
{
rtx *p_handlers = (rtx *) data;
if (! *p_handlers)
}
static void
-arh_to_label (struct eh_region *region, void *data)
+arh_to_label (struct eh_region_d *region, void *data)
{
rtx *p_handlers = (rtx *) data;
*p_handlers = alloc_INSN_LIST (region->label, *p_handlers);
bool
can_throw_internal_1 (int region_number, bool is_resx, bool inlinable_call)
{
- struct eh_region *region;
+ struct eh_region_d *region;
tree type_thrown;
region = VEC_index (eh_region, cfun->eh->region_array, region_number);
bool
can_throw_external_1 (int region_number, bool is_resx, bool inlinable_call)
{
- struct eh_region *region;
+ struct eh_region_d *region;
tree type_thrown;
region = VEC_index (eh_region, cfun->eh->region_array, region_number);
}
static int
-collect_one_action_chain (htab_t ar_hash, struct eh_region *region)
+collect_one_action_chain (htab_t ar_hash, struct eh_region_d *region)
{
- struct eh_region *c;
+ struct eh_region_d *c;
int next;
/* If we've reached the top of the region chain, then we have
}
static int
-add_call_site (rtx landing_pad, int action)
+add_call_site (rtx landing_pad, int action, int section)
{
call_site_record record;
- record = GGC_NEW (struct call_site_record);
+ record = GGC_NEW (struct call_site_record_d);
record->landing_pad = landing_pad;
record->action = action;
- VEC_safe_push (call_site_record, gc, crtl->eh.call_site_record, record);
+ VEC_safe_push (call_site_record, gc,
+ crtl->eh.call_site_record[section], record);
- return call_site_base + VEC_length (call_site_record, crtl->eh.call_site_record) - 1;
+ return call_site_base + VEC_length (call_site_record,
+ crtl->eh.call_site_record[section]) - 1;
}
/* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
rtx last_landing_pad = NULL_RTX;
rtx first_no_action_insn = NULL_RTX;
int call_site = 0;
+ int cur_sec = 0;
+ rtx section_switch_note = NULL_RTX;
+ rtx first_no_action_insn_before_switch = NULL_RTX;
+ rtx last_no_action_insn_before_switch = NULL_RTX;
+ rtx *pad_map = NULL;
+ sbitmap pad_loc = NULL;
+ int min_labelno = 0, max_labelno = 0;
+ int saved_call_site_base = call_site_base;
if (USING_SJLJ_EXCEPTIONS || cfun->eh->region_tree == NULL)
return 0;
for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
if (INSN_P (iter))
{
- struct eh_region *region;
+ struct eh_region_d *region;
int this_action;
rtx this_landing_pad;
landing pads. Collect the landing pad for this region. */
if (this_action >= 0)
{
- struct eh_region *o;
+ struct eh_region_d *o;
for (o = region; ! o->landing_pad ; o = o->outer)
continue;
this_landing_pad = o->landing_pad;
if (last_action >= -1)
{
/* If we delayed the creation of the begin, do it now. */
+ if (first_no_action_insn_before_switch)
+ {
+ call_site = add_call_site (NULL_RTX, 0, 0);
+ note
+ = emit_note_before (NOTE_INSN_EH_REGION_BEG,
+ first_no_action_insn_before_switch);
+ NOTE_EH_HANDLER (note) = call_site;
+ if (first_no_action_insn)
+ {
+ note
+ = emit_note_after (NOTE_INSN_EH_REGION_END,
+ last_no_action_insn_before_switch);
+ NOTE_EH_HANDLER (note) = call_site;
+ }
+ else
+ gcc_assert (last_action_insn
+ == last_no_action_insn_before_switch);
+ }
if (first_no_action_insn)
{
- call_site = add_call_site (NULL_RTX, 0);
+ call_site = add_call_site (NULL_RTX, 0, cur_sec);
note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
first_no_action_insn);
NOTE_EH_HANDLER (note) = call_site;
if (this_action >= -1)
{
call_site = add_call_site (this_landing_pad,
- this_action < 0 ? 0 : this_action);
+ this_action < 0 ? 0 : this_action,
+ cur_sec);
note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter);
NOTE_EH_HANDLER (note) = call_site;
}
}
last_action_insn = iter;
}
+ else if (NOTE_P (iter)
+ && NOTE_KIND (iter) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ {
+ gcc_assert (section_switch_note == NULL_RTX);
+ gcc_assert (flag_reorder_blocks_and_partition);
+ section_switch_note = iter;
+ if (first_no_action_insn)
+ {
+ first_no_action_insn_before_switch = first_no_action_insn;
+ last_no_action_insn_before_switch = last_action_insn;
+ first_no_action_insn = NULL_RTX;
+ gcc_assert (last_action == -1);
+ last_action = -3;
+ }
+ /* Force closing of current EH region before section switch and
+ opening a new one afterwards. */
+ else if (last_action != -3)
+ last_landing_pad = pc_rtx;
+ call_site_base += VEC_length (call_site_record,
+ crtl->eh.call_site_record[cur_sec]);
+ cur_sec++;
+ gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL);
+ crtl->eh.call_site_record[cur_sec]
+ = VEC_alloc (call_site_record, gc, 10);
+ max_labelno = max_label_num ();
+ min_labelno = get_first_label_num ();
+ pad_map = XCNEWVEC (rtx, max_labelno - min_labelno + 1);
+ pad_loc = sbitmap_alloc (max_labelno - min_labelno + 1);
+ }
+ else if (LABEL_P (iter) && pad_map)
+ SET_BIT (pad_loc, CODE_LABEL_NUMBER (iter) - min_labelno);
if (last_action >= -1 && ! first_no_action_insn)
{
NOTE_EH_HANDLER (note) = call_site;
}
+ call_site_base = saved_call_site_base;
+
+ if (pad_map)
+ {
+ /* When doing hot/cold partitioning, ensure landing pads are
+ always in the same section as the EH region, .gcc_except_table
+ can't express it otherwise. */
+ for (cur_sec = 0; cur_sec < 2; cur_sec++)
+ {
+ int i, idx;
+ int n = VEC_length (call_site_record,
+ crtl->eh.call_site_record[cur_sec]);
+ basic_block prev_bb = NULL, padbb;
+
+ for (i = 0; i < n; ++i)
+ {
+ struct call_site_record_d *cs =
+ VEC_index (call_site_record,
+ crtl->eh.call_site_record[cur_sec], i);
+ rtx jump, note;
+
+ if (cs->landing_pad == NULL_RTX)
+ continue;
+ idx = CODE_LABEL_NUMBER (cs->landing_pad) - min_labelno;
+ /* If the landing pad is in the correct section, nothing
+ is needed. */
+ if (TEST_BIT (pad_loc, idx) ^ (cur_sec == 0))
+ continue;
+ /* Otherwise, if we haven't seen this pad yet, we need to
+ add a new label and jump to the correct section. */
+ if (pad_map[idx] == NULL_RTX)
+ {
+ pad_map[idx] = gen_label_rtx ();
+ if (prev_bb == NULL)
+ for (iter = section_switch_note;
+ iter; iter = PREV_INSN (iter))
+ if (NOTE_INSN_BASIC_BLOCK_P (iter))
+ {
+ prev_bb = NOTE_BASIC_BLOCK (iter);
+ break;
+ }
+ if (cur_sec == 0)
+ {
+ note = emit_label_before (pad_map[idx],
+ section_switch_note);
+ jump = emit_jump_insn_before (gen_jump (cs->landing_pad),
+ section_switch_note);
+ }
+ else
+ {
+ jump = emit_jump_insn_after (gen_jump (cs->landing_pad),
+ section_switch_note);
+ note = emit_label_after (pad_map[idx],
+ section_switch_note);
+ }
+ JUMP_LABEL (jump) = cs->landing_pad;
+ add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
+ iter = NEXT_INSN (cs->landing_pad);
+ if (iter && NOTE_INSN_BASIC_BLOCK_P (iter))
+ padbb = NOTE_BASIC_BLOCK (iter);
+ else
+ padbb = NULL;
+ if (padbb && prev_bb
+ && BB_PARTITION (padbb) != BB_UNPARTITIONED)
+ {
+ basic_block bb;
+ int part
+ = BB_PARTITION (padbb) == BB_COLD_PARTITION
+ ? BB_HOT_PARTITION : BB_COLD_PARTITION;
+ edge_iterator ei;
+ edge e;
+
+ bb = create_basic_block (note, jump, prev_bb);
+ make_single_succ_edge (bb, padbb, EDGE_CROSSING);
+ BB_SET_PARTITION (bb, part);
+ for (ei = ei_start (padbb->preds);
+ (e = ei_safe_edge (ei)); )
+ {
+ if ((e->flags & (EDGE_EH|EDGE_CROSSING))
+ == (EDGE_EH|EDGE_CROSSING))
+ {
+ redirect_edge_succ (e, bb);
+ e->flags &= ~EDGE_CROSSING;
+ }
+ else
+ ei_next (&ei);
+ }
+ if (cur_sec == 0)
+ prev_bb = bb;
+ }
+ }
+ cs->landing_pad = pad_map[idx];
+ }
+ }
+
+ sbitmap_free (pad_loc);
+ XDELETEVEC (pad_map);
+ }
+
htab_delete (ar_hash);
return 0;
}
\f
#ifndef HAVE_AS_LEB128
static int
-dw2_size_of_call_site_table (void)
+dw2_size_of_call_site_table (int section)
{
- int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
int size = n * (4 + 4 + 4);
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
+ struct call_site_record_d *cs =
+ VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
size += size_of_uleb128 (cs->action);
}
static int
sjlj_size_of_call_site_table (void)
{
- int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
int size = 0;
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
+ struct call_site_record_d *cs =
+ VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
size += size_of_uleb128 (INTVAL (cs->landing_pad));
size += size_of_uleb128 (cs->action);
}
#endif
static void
-dw2_output_call_site_table (void)
+dw2_output_call_site_table (int cs_format, int section)
{
- int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
int i;
+ const char *begin;
+
+ if (section == 0)
+ begin = current_function_func_begin_label;
+ else if (first_function_block_is_cold)
+ begin = crtl->subsections.hot_section_label;
+ else
+ begin = crtl->subsections.cold_section_label;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
+ struct call_site_record_d *cs =
+ VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
char reg_start_lab[32];
char reg_end_lab[32];
char landing_pad_lab[32];
generic arithmetic. */
/* ??? Perhaps use attr_length to choose data1 or data2 instead of
data4 if the function is small enough. */
-#ifdef HAVE_AS_LEB128
- dw2_asm_output_delta_uleb128 (reg_start_lab,
- current_function_func_begin_label,
- "region %d start", i);
- dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
- "length");
- if (cs->landing_pad)
- dw2_asm_output_delta_uleb128 (landing_pad_lab,
- current_function_func_begin_label,
- "landing pad");
- else
- dw2_asm_output_data_uleb128 (0, "landing pad");
-#else
- dw2_asm_output_delta (4, reg_start_lab,
- current_function_func_begin_label,
- "region %d start", i);
- dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
- if (cs->landing_pad)
- dw2_asm_output_delta (4, landing_pad_lab,
- current_function_func_begin_label,
- "landing pad");
+ if (cs_format == DW_EH_PE_uleb128)
+ {
+ dw2_asm_output_delta_uleb128 (reg_start_lab, begin,
+ "region %d start", i);
+ dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
+ "length");
+ if (cs->landing_pad)
+ dw2_asm_output_delta_uleb128 (landing_pad_lab, begin,
+ "landing pad");
+ else
+ dw2_asm_output_data_uleb128 (0, "landing pad");
+ }
else
- dw2_asm_output_data (4, 0, "landing pad");
-#endif
+ {
+ dw2_asm_output_delta (4, reg_start_lab, begin,
+ "region %d start", i);
+ dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
+ if (cs->landing_pad)
+ dw2_asm_output_delta (4, landing_pad_lab, begin,
+ "landing pad");
+ else
+ dw2_asm_output_data (4, 0, "landing pad");
+ }
dw2_asm_output_data_uleb128 (cs->action, "action");
}
static void
sjlj_output_call_site_table (void)
{
- int n = VEC_length (call_site_record, crtl->eh.call_site_record);
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
+ struct call_site_record_d *cs =
+ VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
"region %d landing pad", i);
dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
}
-void
-output_function_exception_table (const char * ARG_UNUSED (fnname))
+static void
+output_one_function_exception_table (const char * ARG_UNUSED (fnname),
+ int section)
{
int tt_format, cs_format, lp_format, i, n;
#ifdef HAVE_AS_LEB128
int have_tt_data;
int tt_format_size = 0;
- /* Not all functions need anything. */
- if (! crtl->uses_eh_lsda)
- return;
-
- if (eh_personality_libfunc)
- assemble_external_libcall (eh_personality_libfunc);
-
#ifdef TARGET_UNWIND_INFO
/* TODO: Move this into target file. */
fputs ("\t.personality\t", asm_out_file);
{
tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
#ifdef HAVE_AS_LEB128
- ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT",
+ ASM_GENERATE_INTERNAL_LABEL (ttype_label,
+ section ? "LLSDATTC" : "LLSDATT",
current_function_funcdef_no);
#endif
tt_format_size = size_of_encoded_value (tt_format);
assemble_align (tt_format_size * BITS_PER_UNIT);
}
- targetm.asm_out.internal_label (asm_out_file, "LLSDA",
- current_function_funcdef_no);
+ targetm.asm_out.internal_label (asm_out_file, section ? "LLSDAC" : "LLSDA",
+ current_function_funcdef_no);
/* The LSDA header. */
if (USING_SJLJ_EXCEPTIONS)
call_site_len = sjlj_size_of_call_site_table ();
else
- call_site_len = dw2_size_of_call_site_table ();
+ call_site_len = dw2_size_of_call_site_table (section);
#endif
/* A pc-relative 4-byte displacement to the @TType data. */
{
#ifdef HAVE_AS_LEB128
char ttype_after_disp_label[32];
- ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label, "LLSDATTD",
+ ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
+ section ? "LLSDATTDC" : "LLSDATTD",
current_function_funcdef_no);
dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
"@TType base offset");
eh_data_format_name (cs_format));
#ifdef HAVE_AS_LEB128
- ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
+ ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
+ section ? "LLSDACSBC" : "LLSDACSB",
current_function_funcdef_no);
- ASM_GENERATE_INTERNAL_LABEL (cs_end_label, "LLSDACSE",
+ ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
+ section ? "LLSDACSEC" : "LLSDACSE",
current_function_funcdef_no);
dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
"Call-site table length");
if (USING_SJLJ_EXCEPTIONS)
sjlj_output_call_site_table ();
else
- dw2_output_call_site_table ();
+ dw2_output_call_site_table (cs_format, section);
ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
#else
- dw2_asm_output_data_uleb128 (call_site_len,"Call-site table length");
+ dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
if (USING_SJLJ_EXCEPTIONS)
sjlj_output_call_site_table ();
else
- dw2_output_call_site_table ();
+ dw2_output_call_site_table (cs_format, section);
#endif
/* ??? Decode and interpret the data for flag_debug_asm. */
dw2_asm_output_data (1, VARRAY_UCHAR (crtl->eh.ehspec_data, i),
(i ? NULL : "Exception specification table"));
}
+}
+
+void
+output_function_exception_table (const char * ARG_UNUSED (fnname))
+{
+ /* Not all functions need anything. */
+ if (! crtl->uses_eh_lsda)
+ return;
+
+ if (eh_personality_libfunc)
+ assemble_external_libcall (eh_personality_libfunc);
+
+ output_one_function_exception_table (fnname, 0);
+ if (crtl->eh.call_site_record[1] != NULL)
+ output_one_function_exception_table (fnname, 1);
switch_to_section (current_function_section ());
}
void
dump_eh_tree (FILE * out, struct function *fun)
{
- struct eh_region *i;
+ struct eh_region_d *i;
int depth = 0;
static const char *const type_name[] = { "unknown", "cleanup", "try", "catch",
"allowed_exceptions", "must_not_throw",
if (i->landing_pad)
{
fprintf (out, " landing_pad:%i", INSN_UID (i->landing_pad));
- if (GET_CODE (i->landing_pad) == NOTE)
+ if (NOTE_P (i->landing_pad))
fprintf (out, " (deleted)");
}
if (i->post_landing_pad)
{
fprintf (out, " post_landing_pad:%i", INSN_UID (i->post_landing_pad));
- if (GET_CODE (i->post_landing_pad) == NOTE)
+ if (NOTE_P (i->post_landing_pad))
fprintf (out, " (deleted)");
}
if (i->resume)
{
+ rtx resume_list = i->resume;
+ fprintf (out, " resume:");
+ while (GET_CODE (resume_list) == INSN_LIST)
+ {
+ fprintf (out, "%i,", INSN_UID (XEXP (resume_list, 0)));
+ if (NOTE_P (XEXP (resume_list, 0)))
+ fprintf (out, " (deleted)");
+ resume_list = XEXP (resume_list, 1);
+ }
fprintf (out, " resume:%i", INSN_UID (i->resume));
- if (GET_CODE (i->resume) == NOTE)
+ if (NOTE_P (i->resume))
fprintf (out, " (deleted)");
}
if (i->may_contain_throw)
case ERT_TRY:
{
- struct eh_region *c;
+ struct eh_region_d *c;
fprintf (out, " catch regions:");
for (c = i->u.eh_try.eh_catch; c; c = c->u.eh_catch.next_catch)
fprintf (out, " %i", c->region_number);
/* Verify EH region invariants. */
static bool
-verify_eh_region (struct eh_region *region)
+verify_eh_region (struct eh_region_d *region)
{
bool found = false;
if (!region)
{
case ERT_TRY:
{
- struct eh_region *c, *prev = NULL;
+ struct eh_region_d *c, *prev = NULL;
if (region->u.eh_try.eh_catch->u.eh_catch.prev_catch)
{
error ("Try region %i has wrong rh_catch pointer to %i",
void
verify_eh_tree (struct function *fun)
{
- struct eh_region *i, *outer = NULL;
+ struct eh_region_d *i, *outer = NULL;
bool err = false;
int nvisited = 0;
int count = 0;