#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
#endif
-
/* Protect cleanup actions with must-not-throw regions, with a call
to the given failure handler. */
-tree (*lang_protect_cleanup_actions) (void);
+gimple (*lang_protect_cleanup_actions) (void);
/* Return true if type A catches type B. */
int (*lang_eh_type_covers) (tree a, tree b);
/* A list of catch blocks, a surrounding try block,
and the label for continuing after a catch. */
struct eh_region_u_try {
- struct eh_region *catch;
+ struct eh_region *eh_catch;
struct eh_region *last_catch;
- } GTY ((tag ("ERT_TRY"))) try;
+ } GTY ((tag ("ERT_TRY"))) eh_try;
/* The list through the catch handlers, the list of type objects
matched, and the list of associated filters. */
struct eh_region *prev_catch;
tree type_list;
tree filter_list;
- } GTY ((tag ("ERT_CATCH"))) catch;
+ } GTY ((tag ("ERT_CATCH"))) eh_catch;
/* A tree_list of allowed types. */
struct eh_region_u_allowed {
for a throw. */
struct eh_region_u_throw {
tree type;
- } GTY ((tag ("ERT_THROW"))) throw;
+ } GTY ((tag ("ERT_THROW"))) eh_throw;
/* Retain the cleanup expression even after expansion so that
we can match up fixup regions. */
/* The same information as an indexable array. */
VEC(eh_region,gc) *region_array;
-
- /* The most recently open region. */
- struct eh_region *cur_region;
-
- /* This is the region for which we are processing catch blocks. */
- struct eh_region *try_region;
-
- rtx filter;
- rtx exc_ptr;
-
- int built_landing_pads;
int last_region_number;
- VEC(tree,gc) *ttype_data;
- varray_type ehspec_data;
- varray_type action_record_data;
-
- htab_t GTY ((param_is (struct ehl_map_entry))) exception_handler_label_map;
-
- struct call_site_record * GTY ((length ("%h.call_site_data_used")))
- call_site_data;
- int call_site_data_used;
- int call_site_data_size;
-
- rtx ehr_stackadj;
- rtx ehr_handler;
- rtx ehr_label;
-
- rtx sjlj_fc;
- rtx sjlj_exit_after;
-
htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table;
};
\f
DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
tmp = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
- tmp = build_array_type (lang_hooks.types.type_for_mode (word_mode, 1),
+ 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);
DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
void
init_eh_for_function (void)
{
- cfun->eh = ggc_alloc_cleared (sizeof (struct eh_status));
+ cfun->eh = GGC_CNEW (struct eh_status);
}
\f
/* Routines to generate the exception tree somewhat directly.
static struct eh_region *
gen_eh_region (enum eh_region_type type, struct eh_region *outer)
{
- struct eh_region *new;
+ struct eh_region *new_eh;
#ifdef ENABLE_CHECKING
gcc_assert (doing_eh (0));
#endif
/* Insert a new blank region as a leaf in the tree. */
- new = ggc_alloc_cleared (sizeof (*new));
- new->type = type;
- new->outer = outer;
+ new_eh = GGC_CNEW (struct eh_region);
+ new_eh->type = type;
+ new_eh->outer = outer;
if (outer)
{
- new->next_peer = outer->inner;
- outer->inner = new;
+ new_eh->next_peer = outer->inner;
+ outer->inner = new_eh;
}
else
{
- new->next_peer = cfun->eh->region_tree;
- cfun->eh->region_tree = new;
+ new_eh->next_peer = cfun->eh->region_tree;
+ cfun->eh->region_tree = new_eh;
}
- new->region_number = ++cfun->eh->last_region_number;
+ new_eh->region_number = ++cfun->eh->last_region_number;
- return new;
+ return new_eh;
}
struct eh_region *
}
c = gen_eh_region (ERT_CATCH, t->outer);
- c->u.catch.type_list = type_list;
- l = t->u.try.last_catch;
- c->u.catch.prev_catch = l;
+ c->u.eh_catch.type_list = type_list;
+ l = t->u.eh_try.last_catch;
+ c->u.eh_catch.prev_catch = l;
if (l)
- l->u.catch.next_catch = c;
+ l->u.eh_catch.next_catch = c;
else
- t->u.try.catch = c;
- t->u.try.last_catch = c;
+ t->u.eh_try.eh_catch = c;
+ t->u.eh_try.last_catch = c;
return c;
}
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));
emit_barrier ();
}
}
}
-void
-note_current_region_may_contain_throw (void)
-{
- note_eh_region_may_contain_throw (cfun->eh->cur_region);
-}
-
/* Return an rtl expression for a pointer to the exception object
within a handler. */
rtx
-get_exception_pointer (struct function *fun)
+get_exception_pointer (void)
{
- rtx exc_ptr = fun->eh->exc_ptr;
- if (fun == cfun && ! exc_ptr)
- {
- exc_ptr = gen_reg_rtx (ptr_mode);
- fun->eh->exc_ptr = exc_ptr;
- }
- return exc_ptr;
+ if (! crtl->eh.exc_ptr)
+ crtl->eh.exc_ptr = gen_reg_rtx (ptr_mode);
+ return crtl->eh.exc_ptr;
}
/* Return an rtl expression for the exception dispatch filter
within a handler. */
rtx
-get_exception_filter (struct function *fun)
+get_exception_filter (void)
{
- rtx filter = fun->eh->filter;
- if (fun == cfun && ! filter)
- {
- filter = gen_reg_rtx (targetm.eh_return_filter_mode ());
- fun->eh->filter = filter;
- }
- return filter;
+ if (! crtl->eh.filter)
+ crtl->eh.filter = gen_reg_rtx (targetm.eh_return_filter_mode ());
+ return crtl->eh.filter;
}
\f
/* This section is for the exception handling specific optimization pass. */
struct eh_region *r;
rtx insn;
- uid_region_num = xcalloc (get_max_uid (), sizeof(int));
- reachable = xcalloc (cfun->eh->last_region_number + 1, sizeof(bool));
+ uid_region_num = XCNEWVEC (int, get_max_uid ());
+ reachable = XCNEWVEC (bool, cfun->eh->last_region_number + 1);
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;
- for (c = r->u.try.catch; c ; c = c->u.catch.next_catch)
+ for (c = r->u.eh_try.eh_catch; c ; c = c->u.eh_catch.next_catch)
if (reachable[c->region_number])
{
kill_it = false;
LABEL_PRESERVE_P (label) = 1;
- entry = ggc_alloc (sizeof (*entry));
+ entry = GGC_NEW (struct ehl_map_entry);
entry->label = label;
entry->region = region;
slot = (struct ehl_map_entry **)
- htab_find_slot (cfun->eh->exception_handler_label_map, entry, INSERT);
+ htab_find_slot (crtl->eh.exception_handler_label_map, entry, INSERT);
/* Before landing pad creation, each exception handler has its own
label. After landing pad creation, the exception handlers may
share landing pads. This is ok, since maybe_remove_eh_handler
only requires the 1-1 mapping before landing pad creation. */
- gcc_assert (!*slot || cfun->eh->built_landing_pads);
+ gcc_assert (!*slot || crtl->eh.built_landing_pads);
*slot = entry;
}
{
int i;
- if (cfun->eh->exception_handler_label_map)
- htab_empty (cfun->eh->exception_handler_label_map);
+ if (crtl->eh.exception_handler_label_map)
+ htab_empty (crtl->eh.exception_handler_label_map);
else
{
/* ??? The expansion factor here (3/2) must be greater than the htab
occupancy factor (4/3) to avoid unnecessary resizing. */
- cfun->eh->exception_handler_label_map
+ crtl->eh.exception_handler_label_map
= htab_create_ggc (cfun->eh->last_region_number * 3 / 2,
ehl_hash, ehl_eq, NULL);
}
region = VEC_index (eh_region, cfun->eh->region_array, i);
if (! region || region->region_number != i)
continue;
- if (cfun->eh->built_landing_pads)
+ if (crtl->eh.built_landing_pads)
lab = region->landing_pad;
else
lab = region->label;
/* For sjlj exceptions, need the return label to remain live until
after landing pad generation. */
- if (USING_SJLJ_EXCEPTIONS && ! cfun->eh->built_landing_pads)
+ if (USING_SJLJ_EXCEPTIONS && ! crtl->eh.built_landing_pads)
add_ehl_entry (return_label, NULL);
}
{
eh_region ret, n;
- ret = n = ggc_alloc (sizeof (struct eh_region));
+ ret = n = GGC_NEW (struct eh_region);
*n = *old;
n->outer = outer;
switch (cur->type)
{
case ERT_TRY:
- if (cur->u.try.catch)
- REMAP (cur->u.try.catch);
- if (cur->u.try.last_catch)
- REMAP (cur->u.try.last_catch);
+ if (cur->u.eh_try.eh_catch)
+ REMAP (cur->u.eh_try.eh_catch);
+ if (cur->u.eh_try.last_catch)
+ REMAP (cur->u.eh_try.last_catch);
break;
case ERT_CATCH:
- if (cur->u.catch.next_catch)
- REMAP (cur->u.catch.next_catch);
- if (cur->u.catch.prev_catch)
- REMAP (cur->u.catch.prev_catch);
+ if (cur->u.eh_catch.next_catch)
+ REMAP (cur->u.eh_catch.next_catch);
+ if (cur->u.eh_catch.prev_catch)
+ REMAP (cur->u.eh_catch.prev_catch);
break;
case ERT_CLEANUP:
return h;
}
-/* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH
+/* Add TYPE (which may be NULL) to crtl->eh.ttype_data, using TYPES_HASH
to speed up the search. Return the filter value to be used. */
static int
n = XNEW (struct ttypes_filter);
n->t = type;
- n->filter = VEC_length (tree, cfun->eh->ttype_data) + 1;
+ n->filter = VEC_length (tree, crtl->eh.ttype_data) + 1;
*slot = n;
- VEC_safe_push (tree, gc, cfun->eh->ttype_data, type);
+ VEC_safe_push (tree, gc, crtl->eh.ttype_data, type);
}
return n->filter;
}
-/* Add LIST to cfun->eh->ehspec_data, using EHSPEC_HASH and TYPES_HASH
+/* Add LIST to crtl->eh.ehspec_data, using EHSPEC_HASH and TYPES_HASH
to speed up the search. Return the filter value to be used. */
static int
n = XNEW (struct ttypes_filter);
n->t = list;
- n->filter = -(VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) + 1);
+ n->filter = -(VARRAY_ACTIVE_SIZE (crtl->eh.ehspec_data) + 1);
*slot = n;
/* Generate a 0 terminated list of filter values. */
for (; list ; list = TREE_CHAIN (list))
{
if (targetm.arm_eabi_unwinder)
- VARRAY_PUSH_TREE (cfun->eh->ehspec_data, TREE_VALUE (list));
+ VARRAY_PUSH_TREE (crtl->eh.ehspec_data, TREE_VALUE (list));
else
{
/* Look up each type in the list and encode its filter
value as a uleb128. */
- push_uleb128 (&cfun->eh->ehspec_data,
+ push_uleb128 (&crtl->eh.ehspec_data,
add_ttypes_entry (ttypes_hash, TREE_VALUE (list)));
}
}
if (targetm.arm_eabi_unwinder)
- VARRAY_PUSH_TREE (cfun->eh->ehspec_data, NULL_TREE);
+ VARRAY_PUSH_TREE (crtl->eh.ehspec_data, NULL_TREE);
else
- VARRAY_PUSH_UCHAR (cfun->eh->ehspec_data, 0);
+ VARRAY_PUSH_UCHAR (crtl->eh.ehspec_data, 0);
}
return n->filter;
int i;
htab_t ttypes, ehspec;
- cfun->eh->ttype_data = VEC_alloc (tree, gc, 16);
+ crtl->eh.ttype_data = VEC_alloc (tree, gc, 16);
if (targetm.arm_eabi_unwinder)
- VARRAY_TREE_INIT (cfun->eh->ehspec_data, 64, "ehspec_data");
+ VARRAY_TREE_INIT (crtl->eh.ehspec_data, 64, "ehspec_data");
else
- VARRAY_UCHAR_INIT (cfun->eh->ehspec_data, 64, "ehspec_data");
+ VARRAY_UCHAR_INIT (crtl->eh.ehspec_data, 64, "ehspec_data");
ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
case ERT_CATCH:
/* Whatever type_list is (NULL or true list), we build a list
of filters for the region. */
- r->u.catch.filter_list = NULL_TREE;
+ r->u.eh_catch.filter_list = NULL_TREE;
- if (r->u.catch.type_list != NULL)
+ if (r->u.eh_catch.type_list != NULL)
{
/* Get a filter value for each of the types caught and store
them in the region's dedicated list. */
- tree tp_node = r->u.catch.type_list;
+ tree tp_node = r->u.eh_catch.type_list;
for (;tp_node; tp_node = TREE_CHAIN (tp_node))
{
int flt = add_ttypes_entry (ttypes, TREE_VALUE (tp_node));
tree flt_node = build_int_cst (NULL_TREE, flt);
- r->u.catch.filter_list
- = tree_cons (NULL_TREE, flt_node, r->u.catch.filter_list);
+ r->u.eh_catch.filter_list
+ = tree_cons (NULL_TREE, flt_node, r->u.eh_catch.filter_list);
}
}
else
int flt = add_ttypes_entry (ttypes, NULL);
tree flt_node = build_int_cst (NULL_TREE, flt);
- r->u.catch.filter_list
- = tree_cons (NULL_TREE, flt_node, r->u.catch.filter_list);
+ r->u.eh_catch.filter_list
+ = tree_cons (NULL_TREE, flt_node, r->u.eh_catch.filter_list);
}
break;
Rapid prototyping sez a sequence of ifs. */
{
struct eh_region *c;
- for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
+ for (c = region->u.eh_try.eh_catch; c ; c = c->u.eh_catch.next_catch)
{
- if (c->u.catch.type_list == NULL)
+ if (c->u.eh_catch.type_list == NULL)
emit_jump (c->label);
else
{
/* Need for one cmp/jump per type caught. Each type
list entry has a matching entry in the filter list
(see assign_filter_values). */
- tree tp_node = c->u.catch.type_list;
- tree flt_node = c->u.catch.filter_list;
+ tree tp_node = c->u.eh_catch.type_list;
+ tree flt_node = c->u.eh_catch.filter_list;
for (; tp_node; )
{
emit_cmp_and_jump_insns
- (cfun->eh->filter,
+ (crtl->eh.filter,
GEN_INT (tree_low_cst (TREE_VALUE (flt_node), 0)),
EQ, NULL_RTX,
targetm.eh_return_filter_mode (), 0, c->label);
seq = get_insns ();
end_sequence ();
- emit_to_new_bb_before (seq, region->u.try.catch->label);
+ emit_to_new_bb_before (seq, region->u.eh_try.eh_catch->label);
break;
emit_label (region->post_landing_pad);
- emit_cmp_and_jump_insns (cfun->eh->filter,
+ emit_cmp_and_jump_insns (crtl->eh.filter,
GEN_INT (region->u.allowed.filter),
EQ, NULL_RTX,
targetm.eh_return_filter_mode (), 0, region->label);
else
{
emit_library_call (unwind_resume_libfunc, LCT_THROW,
- VOIDmode, 1, cfun->eh->exc_ptr, ptr_mode);
+ 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
#endif
{ /* Nothing */ }
- emit_move_insn (cfun->eh->exc_ptr,
+ emit_move_insn (crtl->eh.exc_ptr,
gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
- emit_move_insn (cfun->eh->filter,
+ emit_move_insn (crtl->eh.filter,
gen_rtx_REG (targetm.eh_return_filter_mode (),
EH_RETURN_DATA_REGNO (1)));
type_thrown = NULL_TREE;
if (region->type == ERT_THROW)
{
- type_thrown = region->u.throw.type;
+ type_thrown = region->u.eh_throw.type;
region = region->outer;
}
/* First task: build the action table. */
- VARRAY_UCHAR_INIT (cfun->eh->action_record_data, 64, "action_record_data");
+ VARRAY_UCHAR_INIT (crtl->eh.action_record_data, 64, "action_record_data");
ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
for (i = cfun->eh->last_region_number; i > 0; --i)
r->landing_pad = dispatch_label;
lp_info[i].action_index = collect_one_action_chain (ar_hash, r);
if (lp_info[i].action_index != -1)
- cfun->uses_eh_lsda = 1;
+ crtl->uses_eh_lsda = 1;
}
htab_delete (ar_hash);
before = find_first_parameter_load (insn, NULL_RTX);
start_sequence ();
- mem = adjust_address (cfun->eh->sjlj_fc, TYPE_MODE (integer_type_node),
+ mem = adjust_address (crtl->eh.sjlj_fc, TYPE_MODE (integer_type_node),
sjlj_fc_call_site_ofs);
emit_move_insn (mem, GEN_INT (this_call_site));
p = get_insns ();
rtx fn_begin, fc, mem, seq;
bool fn_begin_outside_block;
- fc = cfun->eh->sjlj_fc;
+ fc = crtl->eh.sjlj_fc;
start_sequence ();
emit_move_insn (mem, eh_personality_libfunc);
mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
- if (cfun->uses_eh_lsda)
+ if (crtl->uses_eh_lsda)
{
char buf[20];
rtx sym;
void
sjlj_emit_function_exit_after (rtx after)
{
- cfun->eh->sjlj_exit_after = after;
+ crtl->eh.sjlj_exit_after = after;
}
static void
start_sequence ();
emit_library_call (unwind_sjlj_unregister_libfunc, LCT_NORMAL, VOIDmode,
- 1, XEXP (cfun->eh->sjlj_fc, 0), Pmode);
+ 1, XEXP (crtl->eh.sjlj_fc, 0), Pmode);
seq = get_insns ();
end_sequence ();
gcc_assert (e->src->next_bb == EXIT_BLOCK_PTR);
for (insn = BB_HEAD (e->src); ; insn = NEXT_INSN (insn))
{
- if (insn == cfun->eh->sjlj_exit_after)
+ if (insn == crtl->eh.sjlj_exit_after)
{
if (LABEL_P (insn))
insn = NEXT_INSN (insn);
static void
sjlj_emit_dispatch_table (rtx dispatch_label, struct sjlj_lp_info *lp_info)
{
+ enum machine_mode unwind_word_mode = targetm.unwind_word_mode ();
+ enum machine_mode filter_mode = targetm.eh_return_filter_mode ();
int i, first_reachable;
rtx mem, dispatch, seq, fc;
rtx before;
basic_block bb;
edge e;
- fc = cfun->eh->sjlj_fc;
+ fc = crtl->eh.sjlj_fc;
start_sequence ();
sjlj_fc_call_site_ofs);
dispatch = copy_to_reg (mem);
- mem = adjust_address (fc, word_mode, sjlj_fc_data_ofs);
- if (word_mode != ptr_mode)
+ mem = adjust_address (fc, unwind_word_mode, sjlj_fc_data_ofs);
+ if (unwind_word_mode != ptr_mode)
{
#ifdef POINTERS_EXTEND_UNSIGNED
mem = convert_memory_address (ptr_mode, mem);
mem = convert_to_mode (ptr_mode, mem, 0);
#endif
}
- emit_move_insn (cfun->eh->exc_ptr, mem);
+ emit_move_insn (crtl->eh.exc_ptr, mem);
- mem = adjust_address (fc, word_mode, sjlj_fc_data_ofs + UNITS_PER_WORD);
- emit_move_insn (cfun->eh->filter, mem);
+ mem = adjust_address (fc, unwind_word_mode,
+ sjlj_fc_data_ofs + GET_MODE_SIZE (unwind_word_mode));
+ if (unwind_word_mode != filter_mode)
+ mem = convert_to_mode (filter_mode, mem, 0);
+ emit_move_insn (crtl->eh.filter, mem);
/* Jump to one of the directly reachable regions. */
/* ??? This really ought to be using a switch statement. */
{
rtx dispatch_label = gen_label_rtx ();
- cfun->eh->sjlj_fc
+ crtl->eh.sjlj_fc
= assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
int_size_in_bytes (sjlj_fc_type_node),
TYPE_ALIGN (sjlj_fc_type_node));
/* These registers are used by the landing pads. Make sure they
have been generated. */
- get_exception_pointer (cfun);
- get_exception_filter (cfun);
+ get_exception_pointer ();
+ get_exception_filter ();
/* Construct the landing pads. */
else
dw2_build_landing_pads ();
- cfun->eh->built_landing_pads = 1;
+ crtl->eh.built_landing_pads = 1;
/* We've totally changed the CFG. Start over. */
find_exception_handler_labels ();
/* If exception_handler_label_map was not built yet,
there is nothing to do. */
- if (cfun->eh->exception_handler_label_map == NULL)
+ if (crtl->eh.exception_handler_label_map == NULL)
return;
tmp.label = label;
slot = (struct ehl_map_entry **)
- htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
+ htab_find_slot (crtl->eh.exception_handler_label_map, &tmp, NO_INSERT);
gcc_assert (slot);
- htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
+ htab_clear_slot (crtl->eh.exception_handler_label_map, (void **) slot);
}
/* Splice REGION from the region tree etc. */
bitmap_set_bit (outer->aka, region->region_number);
}
- if (cfun->eh->built_landing_pads)
+ if (crtl->eh.built_landing_pads)
lab = region->landing_pad;
else
lab = region->label;
if (region->type == ERT_CATCH)
{
- struct eh_region *try, *next, *prev;
+ struct eh_region *eh_try, *next, *prev;
- for (try = region->next_peer;
- try->type == ERT_CATCH;
- try = try->next_peer)
+ for (eh_try = region->next_peer;
+ eh_try->type == ERT_CATCH;
+ eh_try = eh_try->next_peer)
continue;
- gcc_assert (try->type == ERT_TRY);
+ gcc_assert (eh_try->type == ERT_TRY);
- next = region->u.catch.next_catch;
- prev = region->u.catch.prev_catch;
+ next = region->u.eh_catch.next_catch;
+ prev = region->u.eh_catch.prev_catch;
if (next)
- next->u.catch.prev_catch = prev;
+ next->u.eh_catch.prev_catch = prev;
else
- try->u.try.last_catch = prev;
+ eh_try->u.eh_try.last_catch = prev;
if (prev)
- prev->u.catch.next_catch = next;
+ prev->u.eh_catch.next_catch = next;
else
{
- try->u.try.catch = next;
+ eh_try->u.eh_try.eh_catch = next;
if (! next)
- remove_eh_handler (try);
+ remove_eh_handler (eh_try);
}
}
}
if the region data is completely unused. One must examine the
landing pad and the post landing pad, and whether an inner try block
is referencing the catch handlers directly. */
- if (cfun->eh->built_landing_pads)
+ if (crtl->eh.built_landing_pads)
return;
tmp.label = label;
slot = (struct ehl_map_entry **)
- htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
+ htab_find_slot (crtl->eh.exception_handler_label_map, &tmp, NO_INSERT);
if (! slot)
return;
region = (*slot)->region;
are no more contained calls, which we don't see here. */
if (region->type == ERT_MUST_NOT_THROW)
{
- htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
+ htab_clear_slot (crtl->eh.exception_handler_label_map, (void **) slot);
region->label = NULL_RTX;
}
else
void
for_each_eh_label (void (*callback) (rtx))
{
- htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1,
+ htab_traverse (crtl->eh.exception_handler_label_map, for_each_eh_label_1,
(void *) &callback);
}
info->saw_any_handlers = true;
- if (cfun->eh->built_landing_pads)
+ if (crtl->eh.built_landing_pads)
info->callback (lp_region, info->callback_data);
else
info->callback (region, info->callback_data);
struct eh_region *c;
enum reachable_code ret = RNL_NOT_CAUGHT;
- for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
+ for (c = region->u.eh_try.eh_catch; c ; c = c->u.eh_catch.next_catch)
{
/* A catch-all handler ends the search. */
- if (c->u.catch.type_list == NULL)
+ if (c->u.eh_catch.type_list == NULL)
{
add_reachable_handler (info, region, c);
return RNL_CAUGHT;
if (type_thrown)
{
/* If we have at least one type match, end the search. */
- tree tp_node = c->u.catch.type_list;
+ tree tp_node = c->u.eh_catch.type_list;
for (; tp_node; tp_node = TREE_CHAIN (tp_node))
{
ret = RNL_MAYBE_CAUGHT;
else
{
- tree tp_node = c->u.catch.type_list;
+ tree tp_node = c->u.eh_catch.type_list;
bool maybe_reachable = false;
/* Compute the potential reachability of this handler and
}
else if (region->type == ERT_THROW)
{
- type_thrown = region->u.throw.type;
+ type_thrown = region->u.eh_throw.type;
region = region->outer;
}
static void
arh_to_landing_pad (struct eh_region *region, void *data)
{
- rtx *p_handlers = data;
+ rtx *p_handlers = (rtx *) data;
if (! *p_handlers)
*p_handlers = alloc_INSN_LIST (region->landing_pad, NULL_RTX);
}
static void
arh_to_label (struct eh_region *region, void *data)
{
- rtx *p_handlers = data;
+ rtx *p_handlers = (rtx *) data;
*p_handlers = alloc_INSN_LIST (region->label, *p_handlers);
}
}
foreach_reachable_handler (region_number, is_resx,
- (cfun->eh->built_landing_pads
+ (crtl->eh.built_landing_pads
? arh_to_landing_pad
: arh_to_label),
&handlers);
region = region->outer;
else if (region->type == ERT_THROW)
{
- type_thrown = region->u.throw.type;
+ type_thrown = region->u.eh_throw.type;
region = region->outer;
}
region = region->outer;
else if (region->type == ERT_THROW)
{
- type_thrown = region->u.throw.type;
+ type_thrown = region->u.eh_throw.type;
region = region->outer;
}
return can_throw_external_1 (INTVAL (XEXP (note, 0)), false);
}
-/* Set TREE_NOTHROW and cfun->all_throwers_are_sibcalls. */
+/* Set TREE_NOTHROW and crtl->all_throwers_are_sibcalls. */
unsigned int
set_nothrow_function_flags (void)
TREE_NOTHROW (current_function_decl) = 1;
- /* Assume cfun->all_throwers_are_sibcalls until we encounter
+ /* Assume crtl->all_throwers_are_sibcalls until we encounter
something that can throw an exception. We specifically exempt
CALL_INSNs that are SIBLING_CALL_P, as these are really jumps,
and can't throw. Most CALL_INSNs are not SIBLING_CALL_P, so this
is optimistic. */
- cfun->all_throwers_are_sibcalls = 1;
+ crtl->all_throwers_are_sibcalls = 1;
if (! flag_exceptions)
return 0;
if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
{
- cfun->all_throwers_are_sibcalls = 0;
+ crtl->all_throwers_are_sibcalls = 0;
return 0;
}
}
- for (insn = current_function_epilogue_delay_list; insn;
+ for (insn = crtl->epilogue_delay_list; insn;
insn = XEXP (insn, 1))
if (can_throw_external (insn))
{
if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
{
- cfun->all_throwers_are_sibcalls = 0;
+ crtl->all_throwers_are_sibcalls = 0;
return 0;
}
}
return 0;
}
-struct tree_opt_pass pass_set_nothrow_function_flags =
+struct rtl_opt_pass pass_set_nothrow_function_flags =
{
+ {
+ RTL_PASS,
NULL, /* name */
NULL, /* gate */
set_nothrow_function_flags, /* execute */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
- 0 /* letter */
+ }
};
\f
{
/* Set this so all the registers get saved in our frame; we need to be
able to copy the saved values for any registers from frames we unwind. */
- current_function_saves_all_registers = 1;
+ crtl->saves_all_registers = 1;
#ifdef SETUP_FRAME_ADDRESSES
SETUP_FRAME_ADDRESSES ();
rtx tmp;
#ifdef EH_RETURN_STACKADJ_RTX
- tmp = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj,
+ tmp = expand_expr (stackadj_tree, crtl->eh.ehr_stackadj,
VOIDmode, EXPAND_NORMAL);
tmp = convert_memory_address (Pmode, tmp);
- if (!cfun->eh->ehr_stackadj)
- cfun->eh->ehr_stackadj = copy_to_reg (tmp);
- else if (tmp != cfun->eh->ehr_stackadj)
- emit_move_insn (cfun->eh->ehr_stackadj, tmp);
+ if (!crtl->eh.ehr_stackadj)
+ crtl->eh.ehr_stackadj = copy_to_reg (tmp);
+ else if (tmp != crtl->eh.ehr_stackadj)
+ emit_move_insn (crtl->eh.ehr_stackadj, tmp);
#endif
- tmp = expand_expr (handler_tree, cfun->eh->ehr_handler,
+ tmp = expand_expr (handler_tree, crtl->eh.ehr_handler,
VOIDmode, EXPAND_NORMAL);
tmp = convert_memory_address (Pmode, tmp);
- if (!cfun->eh->ehr_handler)
- cfun->eh->ehr_handler = copy_to_reg (tmp);
- else if (tmp != cfun->eh->ehr_handler)
- emit_move_insn (cfun->eh->ehr_handler, tmp);
+ if (!crtl->eh.ehr_handler)
+ crtl->eh.ehr_handler = copy_to_reg (tmp);
+ else if (tmp != crtl->eh.ehr_handler)
+ emit_move_insn (crtl->eh.ehr_handler, tmp);
- if (!cfun->eh->ehr_label)
- cfun->eh->ehr_label = gen_label_rtx ();
- emit_jump (cfun->eh->ehr_label);
+ if (!crtl->eh.ehr_label)
+ crtl->eh.ehr_label = gen_label_rtx ();
+ emit_jump (crtl->eh.ehr_label);
}
void
{
rtx around_label;
- if (! cfun->eh->ehr_label)
+ if (! crtl->eh.ehr_label)
return;
- current_function_calls_eh_return = 1;
+ crtl->calls_eh_return = 1;
#ifdef EH_RETURN_STACKADJ_RTX
emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
around_label = gen_label_rtx ();
emit_jump (around_label);
- emit_label (cfun->eh->ehr_label);
+ emit_label (crtl->eh.ehr_label);
clobber_return_register ();
#ifdef EH_RETURN_STACKADJ_RTX
- emit_move_insn (EH_RETURN_STACKADJ_RTX, cfun->eh->ehr_stackadj);
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, crtl->eh.ehr_stackadj);
#endif
#ifdef HAVE_eh_return
if (HAVE_eh_return)
- emit_insn (gen_eh_return (cfun->eh->ehr_handler));
+ emit_insn (gen_eh_return (crtl->eh.ehr_handler));
else
#endif
{
#ifdef EH_RETURN_HANDLER_RTX
- emit_move_insn (EH_RETURN_HANDLER_RTX, cfun->eh->ehr_handler);
+ emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler);
#else
error ("__builtin_eh_return not supported on this target");
#endif
extend = 1;
#endif
- return convert_modes (word_mode, ptr_mode, addr, extend);
+ return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
}
\f
/* In the following functions, we represent entries in the action table
static int
add_action_record (htab_t ar_hash, int filter, int next)
{
- struct action_record **slot, *new, tmp;
+ struct action_record **slot, *new_ar, tmp;
tmp.filter = filter;
tmp.next = next;
slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
- if ((new = *slot) == NULL)
+ if ((new_ar = *slot) == NULL)
{
- new = xmalloc (sizeof (*new));
- new->offset = VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data) + 1;
- new->filter = filter;
- new->next = next;
- *slot = new;
+ new_ar = XNEW (struct action_record);
+ new_ar->offset = VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data) + 1;
+ new_ar->filter = filter;
+ new_ar->next = next;
+ *slot = new_ar;
/* The filter value goes in untouched. The link to the next
record is a "self-relative" byte offset, or zero to indicate
that there is no next record. So convert the absolute 1 based
indices we've been carrying around into a displacement. */
- push_sleb128 (&cfun->eh->action_record_data, filter);
+ push_sleb128 (&crtl->eh.action_record_data, filter);
if (next)
- next -= VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data) + 1;
- push_sleb128 (&cfun->eh->action_record_data, next);
+ next -= VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data) + 1;
+ push_sleb128 (&crtl->eh.action_record_data, next);
}
- return new->offset;
+ return new_ar->offset;
}
static int
search outer regions. Use a magic -3 value to record
that we haven't done the outer search. */
next = -3;
- for (c = region->u.try.last_catch; c ; c = c->u.catch.prev_catch)
+ for (c = region->u.eh_try.last_catch; c ; c = c->u.eh_catch.prev_catch)
{
- if (c->u.catch.type_list == NULL)
+ if (c->u.eh_catch.type_list == NULL)
{
/* Retrieve the filter from the head of the filter list
where we have stored it (see assign_filter_values). */
int filter
- = TREE_INT_CST_LOW (TREE_VALUE (c->u.catch.filter_list));
+ = TREE_INT_CST_LOW (TREE_VALUE (c->u.eh_catch.filter_list));
next = add_action_record (ar_hash, filter, 0);
}
next = add_action_record (ar_hash, 0, 0);
}
- flt_node = c->u.catch.filter_list;
+ flt_node = c->u.eh_catch.filter_list;
for (; flt_node; flt_node = TREE_CHAIN (flt_node))
{
int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node));
static int
add_call_site (rtx landing_pad, int action)
{
- struct call_site_record *data = cfun->eh->call_site_data;
- int used = cfun->eh->call_site_data_used;
- int size = cfun->eh->call_site_data_size;
-
- if (used >= size)
- {
- size = (size ? size * 2 : 64);
- data = ggc_realloc (data, sizeof (*data) * size);
- cfun->eh->call_site_data = data;
- cfun->eh->call_site_data_size = size;
- }
-
- data[used].landing_pad = landing_pad;
- data[used].action = action;
+ call_site_record record;
+
+ record = GGC_NEW (struct call_site_record);
+ record->landing_pad = landing_pad;
+ record->action = action;
- cfun->eh->call_site_data_used = used + 1;
+ VEC_safe_push (call_site_record, gc, crtl->eh.call_site_record, record);
- return used + call_site_base;
+ return call_site_base + VEC_length (call_site_record, crtl->eh.call_site_record) - 1;
}
/* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
if (USING_SJLJ_EXCEPTIONS || cfun->eh->region_tree == NULL)
return 0;
- VARRAY_UCHAR_INIT (cfun->eh->action_record_data, 64, "action_record_data");
+ VARRAY_UCHAR_INIT (crtl->eh.action_record_data, 64, "action_record_data");
ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
/* Existence of catch handlers, or must-not-throw regions
implies that an lsda is needed (even if empty). */
if (this_action != -1)
- cfun->uses_eh_lsda = 1;
+ crtl->uses_eh_lsda = 1;
/* Delay creation of region notes for no-action regions
until we're sure that an lsda will be required. */
return 0;
}
-struct tree_opt_pass pass_convert_to_eh_region_ranges =
+struct rtl_opt_pass pass_convert_to_eh_region_ranges =
{
+ {
+ RTL_PASS,
"eh-ranges", /* name */
NULL, /* gate */
convert_to_eh_region_ranges, /* execute */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func, /* todo_flags_finish */
- 0 /* letter */
+ }
};
\f
static int
dw2_size_of_call_site_table (void)
{
- int n = cfun->eh->call_site_data_used;
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record);
int size = n * (4 + 4 + 4);
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = &cfun->eh->call_site_data[i];
+ struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
size += size_of_uleb128 (cs->action);
}
static int
sjlj_size_of_call_site_table (void)
{
- int n = cfun->eh->call_site_data_used;
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record);
int size = 0;
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = &cfun->eh->call_site_data[i];
+ struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
size += size_of_uleb128 (INTVAL (cs->landing_pad));
size += size_of_uleb128 (cs->action);
}
static void
dw2_output_call_site_table (void)
{
- int n = cfun->eh->call_site_data_used;
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record);
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = &cfun->eh->call_site_data[i];
+ struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
char reg_start_lab[32];
char reg_end_lab[32];
char landing_pad_lab[32];
static void
sjlj_output_call_site_table (void)
{
- int n = cfun->eh->call_site_data_used;
+ int n = VEC_length (call_site_record, crtl->eh.call_site_record);
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record *cs = &cfun->eh->call_site_data[i];
+ struct call_site_record *cs = VEC_index (call_site_record, crtl->eh.call_site_record, i);
dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
"region %d landing pad", i);
#ifdef HAVE_LD_EH_GC_SECTIONS
if (flag_function_sections)
{
- char *section_name = xmalloc (strlen (fnname) + 32);
+ char *section_name = XNEWVEC (char, strlen (fnname) + 32);
sprintf (section_name, ".gcc_except_table.%s", fnname);
s = get_section (section_name, flags, NULL);
free (section_name);
output_ttype (tree type, int tt_format, int tt_format_size)
{
rtx value;
- bool public = true;
+ bool is_public = true;
if (type == NULL_TREE)
value = const0_rtx;
node = varpool_node (type);
if (node)
varpool_mark_needed_node (node);
- public = TREE_PUBLIC (type);
+ is_public = TREE_PUBLIC (type);
}
}
else
assemble_integer (value, tt_format_size,
tt_format_size * BITS_PER_UNIT, 1);
else
- dw2_asm_output_encoded_addr_rtx (tt_format, value, public, NULL);
+ dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
}
void
int tt_format_size = 0;
/* Not all functions need anything. */
- if (! cfun->uses_eh_lsda)
+ if (! crtl->uses_eh_lsda)
return;
if (eh_personality_libfunc)
/* If the target wants a label to begin the table, emit it here. */
targetm.asm_out.except_table_label (asm_out_file);
- have_tt_data = (VEC_length (tree, cfun->eh->ttype_data) > 0
- || VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) > 0);
+ have_tt_data = (VEC_length (tree, crtl->eh.ttype_data) > 0
+ || VARRAY_ACTIVE_SIZE (crtl->eh.ehspec_data) > 0);
/* Indicate the format of the @TType entries. */
if (! have_tt_data)
before_disp = 1 + 1;
after_disp = (1 + size_of_uleb128 (call_site_len)
+ call_site_len
- + VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data)
- + (VEC_length (tree, cfun->eh->ttype_data)
+ + VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data)
+ + (VEC_length (tree, crtl->eh.ttype_data)
* tt_format_size));
disp = after_disp;
#endif
/* ??? Decode and interpret the data for flag_debug_asm. */
- n = VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data);
+ n = VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data);
for (i = 0; i < n; ++i)
- dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->action_record_data, i),
+ dw2_asm_output_data (1, VARRAY_UCHAR (crtl->eh.action_record_data, i),
(i ? NULL : "Action record table"));
if (have_tt_data)
assemble_align (tt_format_size * BITS_PER_UNIT);
- i = VEC_length (tree, cfun->eh->ttype_data);
+ i = VEC_length (tree, crtl->eh.ttype_data);
while (i-- > 0)
{
- tree type = VEC_index (tree, cfun->eh->ttype_data, i);
+ tree type = VEC_index (tree, crtl->eh.ttype_data, i);
output_ttype (type, tt_format, tt_format_size);
}
#endif
/* ??? Decode and interpret the data for flag_debug_asm. */
- n = VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data);
+ n = VARRAY_ACTIVE_SIZE (crtl->eh.ehspec_data);
for (i = 0; i < n; ++i)
{
if (targetm.arm_eabi_unwinder)
{
- tree type = VARRAY_TREE (cfun->eh->ehspec_data, i);
+ tree type = VARRAY_TREE (crtl->eh.ehspec_data, i);
output_ttype (type, tt_format, tt_format_size);
}
else
- dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i),
+ dw2_asm_output_data (1, VARRAY_UCHAR (crtl->eh.ehspec_data, i),
(i ? NULL : "Exception specification table"));
}
return 0;
}
-struct tree_opt_pass pass_rtl_eh =
+struct rtl_opt_pass pass_rtl_eh =
{
+ {
+ RTL_PASS,
"eh", /* name */
gate_handle_eh, /* gate */
rest_of_handle_eh, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
- 'h' /* letter */
+ TODO_dump_func /* todo_flags_finish */
+ }
};
#include "gt-except.h"