/* Implements exception handling.
- Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2013 Free Software Foundation, Inc.
Contributed by Mike Stump <mrs@cygnus.com>.
This file is part of GCC.
gimple to eh_region mapping that had been recorded in the
THROW_STMT_TABLE.
- During pass_rtl_eh (except.c), we generate the real landing pads
+ Then, via finish_eh_generation, we generate the real landing pads
to which the runtime will actually transfer control. These new
landing pads perform whatever bookkeeping is needed by the target
backend in order to resume execution within the current function.
#include "libfuncs.h"
#include "insn-config.h"
#include "except.h"
-#include "integrate.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "tree-pass.h"
-#include "timevar.h"
#include "tree-flow.h"
+#include "cfgloop.h"
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
static int collect_one_action_chain (htab_t, eh_region);
static int add_call_site (rtx, int, int);
-static void push_uleb128 (VEC (uchar, gc) **, unsigned int);
-static void push_sleb128 (VEC (uchar, gc) **, int);
+static void push_uleb128 (vec<uchar, va_gc> **, unsigned int);
+static void push_sleb128 (vec<uchar, va_gc> **, int);
#ifndef HAVE_AS_LEB128
static int dw2_size_of_call_site_table (int);
static int sjlj_size_of_call_site_table (void);
cfun->eh = ggc_alloc_cleared_eh_status ();
/* Make sure zero'th entries are used. */
- VEC_safe_push (eh_region, gc, cfun->eh->region_array, NULL);
- VEC_safe_push (eh_landing_pad, gc, cfun->eh->lp_array, NULL);
+ vec_safe_push (cfun->eh->region_array, (eh_region)0);
+ vec_safe_push (cfun->eh->lp_array, (eh_landing_pad)0);
}
\f
/* Routines to generate the exception tree somewhat directly.
cfun->eh->region_tree = new_eh;
}
- new_eh->index = VEC_length (eh_region, cfun->eh->region_array);
- VEC_safe_push (eh_region, gc, cfun->eh->region_array, new_eh);
+ new_eh->index = vec_safe_length (cfun->eh->region_array);
+ vec_safe_push (cfun->eh->region_array, new_eh);
/* Copy the language's notion of whether to use __cxa_end_cleanup. */
if (targetm.arm_eabi_unwinder && lang_hooks.eh_use_cxa_end_cleanup)
lp->next_lp = region->landing_pads;
lp->region = region;
- lp->index = VEC_length (eh_landing_pad, cfun->eh->lp_array);
+ lp->index = vec_safe_length (cfun->eh->lp_array);
region->landing_pads = lp;
- VEC_safe_push (eh_landing_pad, gc, cfun->eh->lp_array, lp);
+ vec_safe_push (cfun->eh->lp_array, lp);
return lp;
}
eh_region
get_eh_region_from_number_fn (struct function *ifun, int i)
{
- return VEC_index (eh_region, ifun->eh->region_array, i);
+ return (*ifun->eh->region_array)[i];
}
eh_region
eh_landing_pad
get_eh_landing_pad_from_number_fn (struct function *ifun, int i)
{
- return VEC_index (eh_landing_pad, ifun->eh->lp_array, i);
+ return (*ifun->eh->lp_array)[i];
}
eh_landing_pad
get_eh_region_from_lp_number_fn (struct function *ifun, int i)
{
if (i < 0)
- return VEC_index (eh_region, ifun->eh->region_array, -i);
+ return (*ifun->eh->region_array)[-i];
else if (i == 0)
return NULL;
else
{
eh_landing_pad lp;
- lp = VEC_index (eh_landing_pad, ifun->eh->lp_array, i);
+ lp = (*ifun->eh->lp_array)[i];
return lp->region;
}
}
break;
case ERT_MUST_NOT_THROW:
- new_r->u.must_not_throw = old_r->u.must_not_throw;
+ new_r->u.must_not_throw.failure_loc =
+ LOCATION_LOCUS (old_r->u.must_not_throw.failure_loc);
+ new_r->u.must_not_throw.failure_decl =
+ old_r->u.must_not_throw.failure_decl;
break;
}
gcc_assert (ifun->eh->region_array);
gcc_assert (ifun->eh->region_tree);
- b_outer = sbitmap_alloc (VEC_length (eh_region, ifun->eh->region_array));
- sbitmap_zero (b_outer);
+ b_outer = sbitmap_alloc (ifun->eh->region_array->length());
+ bitmap_clear (b_outer);
do
{
- SET_BIT (b_outer, region_b->index);
+ bitmap_set_bit (b_outer, region_b->index);
region_b = region_b->outer;
}
while (region_b);
do
{
- if (TEST_BIT (b_outer, region_a->index))
+ if (bitmap_bit_p (b_outer, region_a->index))
break;
region_a = region_a->outer;
}
n = XNEW (struct ttypes_filter);
n->t = type;
- n->filter = VEC_length (tree, cfun->eh->ttype_data) + 1;
+ n->filter = vec_safe_length (cfun->eh->ttype_data) + 1;
*slot = n;
- VEC_safe_push (tree, gc, cfun->eh->ttype_data, type);
+ vec_safe_push (cfun->eh->ttype_data, type);
}
return n->filter;
int len;
if (targetm.arm_eabi_unwinder)
- len = VEC_length (tree, cfun->eh->ehspec_data.arm_eabi);
+ len = vec_safe_length (cfun->eh->ehspec_data.arm_eabi);
else
- len = VEC_length (uchar, cfun->eh->ehspec_data.other);
+ len = vec_safe_length (cfun->eh->ehspec_data.other);
/* Filter value is a -1 based byte index into a uleb128 buffer. */
for (; list ; list = TREE_CHAIN (list))
{
if (targetm.arm_eabi_unwinder)
- VEC_safe_push (tree, gc, cfun->eh->ehspec_data.arm_eabi,
- TREE_VALUE (list));
+ vec_safe_push (cfun->eh->ehspec_data.arm_eabi, TREE_VALUE (list));
else
{
/* Look up each type in the list and encode its filter
}
}
if (targetm.arm_eabi_unwinder)
- VEC_safe_push (tree, gc, cfun->eh->ehspec_data.arm_eabi, NULL_TREE);
+ vec_safe_push (cfun->eh->ehspec_data.arm_eabi, NULL_TREE);
else
- VEC_safe_push (uchar, gc, cfun->eh->ehspec_data.other, 0);
+ vec_safe_push (cfun->eh->ehspec_data.other, (uchar)0);
}
return n->filter;
eh_region r;
eh_catch c;
- cfun->eh->ttype_data = VEC_alloc (tree, gc, 16);
+ vec_alloc (cfun->eh->ttype_data, 16);
if (targetm.arm_eabi_unwinder)
- cfun->eh->ehspec_data.arm_eabi = VEC_alloc (tree, gc, 64);
+ vec_alloc (cfun->eh->ehspec_data.arm_eabi, 64);
else
- cfun->eh->ehspec_data.other = VEC_alloc (uchar, gc, 64);
+ vec_alloc (cfun->eh->ehspec_data.other, 64);
ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
- for (i = 1; VEC_iterate (eh_region, cfun->eh->region_array, i, r); ++i)
+ for (i = 1; vec_safe_iterate (cfun->eh->region_array, i, &r); ++i)
{
if (r == NULL)
continue;
emit_to_new_bb_before (rtx seq, rtx insn)
{
rtx last;
- basic_block bb;
+ basic_block bb, prev_bb;
edge e;
edge_iterator ei;
last = emit_insn_before (seq, insn);
if (BARRIER_P (last))
last = PREV_INSN (last);
- bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
+ prev_bb = BLOCK_FOR_INSN (insn)->prev_bb;
+ bb = create_basic_block (seq, last, prev_bb);
update_bb_for_insn (bb);
bb->flags |= BB_SUPERBLOCK;
return bb;
if (flag_reorder_blocks_and_partition)
e_flags |= EDGE_PRESERVE;
- for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
+ for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
{
basic_block bb;
rtx seq;
e = make_edge (bb, bb->next_bb, e_flags);
e->count = bb->count;
e->probability = REG_BR_PROB_BASE;
+ if (current_loops)
+ {
+ struct loop *loop = bb->next_bb->loop_father;
+ /* If we created a pre-header block, add the new block to the
+ outer loop, otherwise to the loop itself. */
+ if (bb->next_bb == loop->header)
+ add_bb_to_loop (bb, loop_outer (loop));
+ else
+ add_bb_to_loop (bb, loop);
+ }
}
}
\f
-static VEC (int, heap) *sjlj_lp_call_site_index;
+static vec<int> sjlj_lp_call_site_index;
/* Process all active landing pads. Assign each one a compact dispatch
index, and a call-site index. */
int i, disp_index;
eh_landing_pad lp;
- crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
+ vec_alloc (crtl->eh.action_record_data, 64);
ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
disp_index = 0;
call_site_base = 1;
- for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
+ for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
if (lp && lp->post_landing_pad)
{
int action, call_site;
/* Otherwise, look it up in the table. */
else
call_site = add_call_site (GEN_INT (disp_index), action, 0);
- VEC_replace (int, sjlj_lp_call_site_index, i, call_site);
+ sjlj_lp_call_site_index[i] = call_site;
disp_index++;
}
if (nothrow)
continue;
if (lp)
- this_call_site = VEC_index (int, sjlj_lp_call_site_index, lp->index);
+ this_call_site = sjlj_lp_call_site_index[lp->index];
else if (r == NULL)
{
/* Calls (and trapping insns) without notes are outside any
if (dispatch_label)
{
#ifdef DONT_USE_BUILTIN_SETJMP
- rtx x, last;
+ rtx x;
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
TYPE_MODE (integer_type_node), 1,
- plus_constant (XEXP (fc, 0),
+ plus_constant (Pmode, XEXP (fc, 0),
sjlj_fc_jbuf_ofs), Pmode);
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0,
- dispatch_label);
- last = get_last_insn ();
- if (JUMP_P (last) && any_condjump_p (last))
- {
- gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
- add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
- }
+ dispatch_label, REG_BR_PROB_BASE / 100);
#else
- expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0),
+ expand_builtin_setjmp_setup (plus_constant (Pmode, XEXP (fc, 0),
sjlj_fc_jbuf_ofs),
dispatch_label);
#endif
eh_region r;
edge e;
int i, disp_index;
- gimple switch_stmt;
+ vec<tree> dispatch_labels = vNULL;
fc = crtl->eh.sjlj_fc;
/* If there's exactly one call site in the function, don't bother
generating a switch statement. */
- switch_stmt = NULL;
if (num_dispatch > 1)
- {
- tree disp;
+ dispatch_labels.create (num_dispatch);
- mem = adjust_address (fc, TYPE_MODE (integer_type_node),
- sjlj_fc_call_site_ofs);
- disp = make_tree (integer_type_node, mem);
-
- switch_stmt = gimple_build_switch_nlabels (num_dispatch, disp, NULL);
- }
-
- for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
+ for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
if (lp && lp->post_landing_pad)
{
rtx seq2, label;
t_label = create_artificial_label (UNKNOWN_LOCATION);
t = build_int_cst (integer_type_node, disp_index);
case_elt = build_case_label (t, NULL, t_label);
- gimple_switch_set_label (switch_stmt, disp_index, case_elt);
-
+ dispatch_labels.quick_push (case_elt);
label = label_rtx (t_label);
}
else
e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
e->count = bb->count;
e->probability = REG_BR_PROB_BASE;
+ if (current_loops)
+ {
+ struct loop *loop = bb->next_bb->loop_father;
+ /* If we created a pre-header block, add the new block to the
+ outer loop, otherwise to the loop itself. */
+ if (bb->next_bb == loop->header)
+ add_bb_to_loop (bb, loop_outer (loop));
+ else
+ add_bb_to_loop (bb, loop);
+ /* ??? For multiple dispatches we will end up with edges
+ from the loop tree root into this loop, making it a
+ multiple-entry loop. Discard all affected loops. */
+ if (num_dispatch > 1)
+ {
+ for (loop = bb->loop_father;
+ loop_outer (loop); loop = loop_outer (loop))
+ {
+ loop->header = NULL;
+ loop->latch = NULL;
+ }
+ }
+ }
disp_index++;
}
if (num_dispatch > 1)
{
- expand_case (switch_stmt);
- expand_builtin_trap ();
+ rtx disp = adjust_address (fc, TYPE_MODE (integer_type_node),
+ sjlj_fc_call_site_ofs);
+ expand_sjlj_dispatch_table (disp, dispatch_labels);
}
seq = get_insns ();
e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
e->count = bb->count;
e->probability = REG_BR_PROB_BASE;
+ if (current_loops)
+ {
+ struct loop *loop = bb->next_bb->loop_father;
+ /* If we created a pre-header block, add the new block to the
+ outer loop, otherwise to the loop itself. */
+ if (bb->next_bb == loop->header)
+ add_bb_to_loop (bb, loop_outer (loop));
+ else
+ add_bb_to_loop (bb, loop);
+ }
+ }
+ else
+ {
+ /* We are not wiring up edges here, but as the dispatcher call
+ is at function begin simply associate the block with the
+ outermost (non-)loop. */
+ if (current_loops)
+ add_bb_to_loop (bb, current_loops->tree_root);
}
}
{
int num_dispatch;
- num_dispatch = VEC_length (eh_landing_pad, cfun->eh->lp_array);
+ num_dispatch = vec_safe_length (cfun->eh->lp_array);
if (num_dispatch == 0)
return;
- VEC_safe_grow (int, heap, sjlj_lp_call_site_index, num_dispatch);
+ sjlj_lp_call_site_index.safe_grow_cleared (num_dispatch);
num_dispatch = sjlj_assign_call_site_values ();
if (num_dispatch > 0)
sjlj_emit_function_exit ();
}
- VEC_free (int, heap, sjlj_lp_call_site_index);
+ sjlj_lp_call_site_index.release ();
}
/* After initial rtl generation, call back to finish generating
exception support code. */
-static void
+void
finish_eh_generation (void)
{
basic_block bb;
break_superblocks ();
if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
- /* Kludge for Alpha/Tru64 (see alpha_gp_save_rtx). */
+ /* Kludge for Alpha (see alpha_gp_save_rtx). */
|| single_succ_edge (ENTRY_BLOCK_PTR)->insns.r)
commit_edge_insertions ();
}
}
}
-
-static bool
-gate_handle_eh (void)
-{
- /* Nothing to do if no regions created. */
- return cfun->eh->region_tree != NULL;
-}
-
-/* Complete generation of exception handling code. */
-static unsigned int
-rest_of_handle_eh (void)
-{
- finish_eh_generation ();
- cleanup_cfg (CLEANUP_NO_INSN_DEL);
- return 0;
-}
-
-struct rtl_opt_pass pass_rtl_eh =
-{
- {
- RTL_PASS,
- "rtl_eh", /* name */
- gate_handle_eh, /* gate */
- rest_of_handle_eh, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_JUMP, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- }
-};
\f
/* This section handles removing dead code for flow. */
if (lp->post_landing_pad)
EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
- VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL);
+ (*cfun->eh->lp_array)[lp->index] = NULL;
}
-/* Splice REGION from the region tree. */
+/* Splice the EH region at PP from the region tree. */
-void
-remove_eh_handler (eh_region region)
+static void
+remove_eh_handler_splicer (eh_region *pp)
{
- eh_region *pp, *pp_start, p, outer;
+ eh_region region = *pp;
eh_landing_pad lp;
for (lp = region->landing_pads; lp ; lp = lp->next_lp)
{
if (lp->post_landing_pad)
EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
- VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL);
+ (*cfun->eh->lp_array)[lp->index] = NULL;
}
- outer = region->outer;
- if (outer)
- pp_start = &outer->inner;
- else
- pp_start = &cfun->eh->region_tree;
- for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp)
- continue;
if (region->inner)
{
+ eh_region p, outer;
+ outer = region->outer;
+
*pp = p = region->inner;
do
{
}
*pp = region->next_peer;
- VEC_replace (eh_region, cfun->eh->region_array, region->index, NULL);
+ (*cfun->eh->region_array)[region->index] = NULL;
+}
+
+/* Splice a single EH region REGION from the region tree.
+
+ To unlink REGION, we need to find the pointer to it with a relatively
+ expensive search in REGION's outer region. If you are going to
+ remove a number of handlers, using remove_unreachable_eh_regions may
+ be a better option. */
+
+void
+remove_eh_handler (eh_region region)
+{
+ eh_region *pp, *pp_start, p, outer;
+
+ outer = region->outer;
+ if (outer)
+ pp_start = &outer->inner;
+ else
+ pp_start = &cfun->eh->region_tree;
+ for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp)
+ continue;
+
+ remove_eh_handler_splicer (pp);
+}
+
+/* Worker for remove_unreachable_eh_regions.
+ PP is a pointer to the region to start a region tree depth-first
+ search from. R_REACHABLE is the set of regions that have to be
+ preserved. */
+
+static void
+remove_unreachable_eh_regions_worker (eh_region *pp, sbitmap r_reachable)
+{
+ while (*pp)
+ {
+ eh_region region = *pp;
+ remove_unreachable_eh_regions_worker (®ion->inner, r_reachable);
+ if (!bitmap_bit_p (r_reachable, region->index))
+ remove_eh_handler_splicer (pp);
+ else
+ pp = ®ion->next_peer;
+ }
+}
+
+/* Splice all EH regions *not* marked in R_REACHABLE from the region tree.
+ Do this by traversing the EH tree top-down and splice out regions that
+ are not marked. By removing regions from the leaves, we avoid costly
+ searches in the region tree. */
+
+void
+remove_unreachable_eh_regions (sbitmap r_reachable)
+{
+ remove_unreachable_eh_regions_worker (&cfun->eh->region_tree, r_reachable);
}
/* Invokes CALLBACK for every exception handler landing pad label.
eh_landing_pad lp;
int i;
- for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
+ for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
{
if (lp)
{
}
if (lp_nr < 0)
- r = VEC_index (eh_region, cfun->eh->region_array, -lp_nr);
+ r = (*cfun->eh->region_array)[-lp_nr];
else
{
- lp = VEC_index (eh_landing_pad, cfun->eh->lp_array, lp_nr);
+ lp = (*cfun->eh->lp_array)[lp_nr];
r = lp->region;
}
}
}
- for (insn = crtl->epilogue_delay_list; insn;
- insn = XEXP (insn, 1))
- if (can_throw_external (insn))
- {
- crtl->nothrow = 0;
-
- if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
- {
- crtl->all_throwers_are_sibcalls = 0;
- return 0;
- }
- }
if (crtl->nothrow
&& (cgraph_function_body_availability (cgraph_get_node
(current_function_decl))
{
RTL_PASS,
"nothrow", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
NULL, /* gate */
set_nothrow_function_flags, /* execute */
NULL, /* sub */
gcc_assert (host_integerp (region_nr_t, 0));
region_nr = tree_low_cst (region_nr_t, 0);
- region = VEC_index (eh_region, cfun->eh->region_array, region_nr);
+ region = (*cfun->eh->region_array)[region_nr];
/* ??? We shouldn't have been able to delete a eh region without
deleting all the code that depended on it. */
/* Then adjust to find the real return address. */
#if defined (RETURN_ADDR_OFFSET)
- addr = plus_constant (addr, RETURN_ADDR_OFFSET);
+ addr = plus_constant (Pmode, addr, RETURN_ADDR_OFFSET);
#endif
return addr;
#ifdef RETURN_ADDR_OFFSET
addr = force_reg (Pmode, addr);
- addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
+ addr = plus_constant (Pmode, addr, -RETURN_ADDR_OFFSET);
#endif
return addr;
if ((new_ar = *slot) == NULL)
{
new_ar = XNEW (struct action_record);
- new_ar->offset = VEC_length (uchar, crtl->eh.action_record_data) + 1;
+ new_ar->offset = crtl->eh.action_record_data->length () + 1;
new_ar->filter = filter;
new_ar->next = next;
*slot = new_ar;
push_sleb128 (&crtl->eh.action_record_data, filter);
if (next)
- next -= VEC_length (uchar, crtl->eh.action_record_data) + 1;
+ next -= crtl->eh.action_record_data->length () + 1;
push_sleb128 (&crtl->eh.action_record_data, next);
}
record->landing_pad = landing_pad;
record->action = action;
- VEC_safe_push (call_site_record, gc,
- crtl->eh.call_site_record[section], record);
+ vec_safe_push (crtl->eh.call_site_record_v[section], record);
- return call_site_base + VEC_length (call_site_record,
- crtl->eh.call_site_record[section]) - 1;
+ return call_site_base + crtl->eh.call_site_record_v[section]->length () - 1;
}
/* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
rtx last_no_action_insn_before_switch = NULL_RTX;
int saved_call_site_base = call_site_base;
- crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
+ vec_alloc (crtl->eh.action_record_data, 64);
ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
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]);
+ if (crtl->eh.call_site_record_v[cur_sec])
+ call_site_base += crtl->eh.call_site_record_v[cur_sec]->length ();
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);
+ gcc_assert (crtl->eh.call_site_record_v[cur_sec] == NULL);
+ vec_alloc (crtl->eh.call_site_record_v[cur_sec], 10);
}
if (last_action >= -1 && ! first_no_action_insn)
{
RTL_PASS,
"eh_ranges", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_convert_to_eh_region_ranges, /* gate */
convert_to_eh_region_ranges, /* execute */
NULL, /* sub */
};
\f
static void
-push_uleb128 (VEC (uchar, gc) **data_area, unsigned int value)
+push_uleb128 (vec<uchar, va_gc> **data_area, unsigned int value)
{
do
{
value >>= 7;
if (value)
byte |= 0x80;
- VEC_safe_push (uchar, gc, *data_area, byte);
+ vec_safe_push (*data_area, byte);
}
while (value);
}
static void
-push_sleb128 (VEC (uchar, gc) **data_area, int value)
+push_sleb128 (vec<uchar, va_gc> **data_area, int value)
{
unsigned char byte;
int more;
|| (value == -1 && (byte & 0x40) != 0));
if (more)
byte |= 0x80;
- VEC_safe_push (uchar, gc, *data_area, byte);
+ vec_safe_push (*data_area, byte);
}
while (more);
}
static int
dw2_size_of_call_site_table (int section)
{
- int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
+ int n = vec_safe_length (crtl->eh.call_site_record_v[section]);
int size = n * (4 + 4 + 4);
int i;
for (i = 0; i < n; ++i)
{
struct call_site_record_d *cs =
- VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
+ (*crtl->eh.call_site_record_v[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[0]);
+ int n = vec_safe_length (crtl->eh.call_site_record_v[0]);
int size = 0;
int i;
for (i = 0; i < n; ++i)
{
struct call_site_record_d *cs =
- VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
+ (*crtl->eh.call_site_record_v[0])[i];
size += size_of_uleb128 (INTVAL (cs->landing_pad));
size += size_of_uleb128 (cs->action);
}
static void
dw2_output_call_site_table (int cs_format, int section)
{
- int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
+ int n = vec_safe_length (crtl->eh.call_site_record_v[section]);
int i;
const char *begin;
for (i = 0; i < n; ++i)
{
- struct call_site_record_d *cs =
- VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
+ struct call_site_record_d *cs = (*crtl->eh.call_site_record_v[section])[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 = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
+ int n = vec_safe_length (crtl->eh.call_site_record_v[0]);
int i;
for (i = 0; i < n; ++i)
{
- struct call_site_record_d *cs =
- VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
+ struct call_site_record_d *cs = (*crtl->eh.call_site_record_v[0])[i];
dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
"region %d landing pad", i);
flags = SECTION_WRITE;
#ifdef HAVE_LD_EH_GC_SECTIONS
- if (flag_function_sections)
+ if (flag_function_sections
+ || (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP))
{
char *section_name = XNEWVEC (char, strlen (fnname) + 32);
+ /* The EH table must match the code section, so only mark
+ it linkonce if we have COMDAT groups to tie them together. */
+ if (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP)
+ flags |= SECTION_LINKONCE;
sprintf (section_name, ".gcc_except_table.%s", fnname);
- s = get_section (section_name, flags, NULL);
+ s = get_section (section_name, flags, current_function_decl);
free (section_name);
}
else
value = const0_rtx;
else
{
- struct varpool_node *node;
-
/* FIXME lto. pass_ipa_free_lang_data changes all types to
runtime types so TYPE should already be a runtime type
reference. When pass_ipa_free_lang data is made a default
{
type = TREE_OPERAND (type, 0);
if (TREE_CODE (type) == VAR_DECL)
- {
- node = varpool_node (type);
- if (node)
- varpool_mark_needed_node (node);
- is_public = TREE_PUBLIC (type);
- }
+ is_public = TREE_PUBLIC (type);
}
else
gcc_assert (TREE_CODE (type) == INTEGER_CST);
int have_tt_data;
int tt_format_size = 0;
- have_tt_data = (VEC_length (tree, cfun->eh->ttype_data)
+ have_tt_data = (vec_safe_length (cfun->eh->ttype_data)
|| (targetm.arm_eabi_unwinder
- ? VEC_length (tree, cfun->eh->ehspec_data.arm_eabi)
- : VEC_length (uchar, cfun->eh->ehspec_data.other)));
+ ? vec_safe_length (cfun->eh->ehspec_data.arm_eabi)
+ : vec_safe_length (cfun->eh->ehspec_data.other)));
/* 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
- + VEC_length (uchar, crtl->eh.action_record_data)
- + (VEC_length (tree, cfun->eh->ttype_data)
+ + vec_safe_length (crtl->eh.action_record_data)
+ + (vec_safe_length (cfun->eh->ttype_data)
* tt_format_size));
disp = after_disp;
/* ??? Decode and interpret the data for flag_debug_asm. */
{
uchar uc;
- FOR_EACH_VEC_ELT (uchar, crtl->eh.action_record_data, i, uc)
+ FOR_EACH_VEC_ELT (*crtl->eh.action_record_data, i, uc)
dw2_asm_output_data (1, uc, 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_safe_length (cfun->eh->ttype_data);
while (i-- > 0)
{
- tree type = VEC_index (tree, cfun->eh->ttype_data, i);
+ tree type = (*cfun->eh->ttype_data)[i];
output_ttype (type, tt_format, tt_format_size);
}
{
tree type;
for (i = 0;
- VEC_iterate (tree, cfun->eh->ehspec_data.arm_eabi, i, type); ++i)
+ vec_safe_iterate (cfun->eh->ehspec_data.arm_eabi, i, &type); ++i)
output_ttype (type, tt_format, tt_format_size);
}
else
{
uchar uc;
for (i = 0;
- VEC_iterate (uchar, cfun->eh->ehspec_data.other, i, uc); ++i)
+ vec_safe_iterate (cfun->eh->ehspec_data.other, i, &uc); ++i)
dw2_asm_output_data (1, uc,
i ? NULL : "Exception specification table");
}
targetm.asm_out.emit_except_table_label (asm_out_file);
output_one_function_exception_table (0);
- if (crtl->eh.call_site_record[1] != NULL)
+ if (crtl->eh.call_site_record_v[1])
output_one_function_exception_table (1);
switch_to_section (current_function_section ());
return;
count_r = 0;
- for (i = 1; VEC_iterate (eh_region, fun->eh->region_array, i, r); ++i)
+ for (i = 1; vec_safe_iterate (fun->eh->region_array, i, &r); ++i)
if (r)
{
if (r->index == i)
}
count_lp = 0;
- for (i = 1; VEC_iterate (eh_landing_pad, fun->eh->lp_array, i, lp); ++i)
+ for (i = 1; vec_safe_iterate (fun->eh->lp_array, i, &lp); ++i)
if (lp)
{
if (lp->index == i)
r = fun->eh->region_tree;
while (1)
{
- if (VEC_index (eh_region, fun->eh->region_array, r->index) != r)
+ if ((*fun->eh->region_array)[r->index] != r)
{
error ("region_array is corrupted for region %i", r->index);
err = true;
for (lp = r->landing_pads; lp ; lp = lp->next_lp)
{
- if (VEC_index (eh_landing_pad, fun->eh->lp_array, lp->index) != lp)
+ if ((*fun->eh->lp_array)[lp->index] != lp)
{
error ("lp_array is corrupted for lp %i", lp->index);
err = true;