/* 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, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
Contributed by Mike Stump <mrs@cygnus.com>.
This file is part of GCC.
#include "tm.h"
#include "rtl.h"
#include "tree.h"
+#include "stringpool.h"
+#include "stor-layout.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
#include "insn-config.h"
#include "except.h"
#include "hard-reg-set.h"
-#include "basic-block.h"
#include "output.h"
#include "dwarf2asm.h"
#include "dwarf2out.h"
#include "dwarf2.h"
#include "toplev.h"
-#include "hashtab.h"
+#include "hash-table.h"
#include "intl.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "common/common-target.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "tree-pass.h"
-#include "tree-flow.h"
#include "cfgloop.h"
+#include "builtins.h"
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
rtx landing_pad;
int action;
};
+
+/* In the following structure and associated functions,
+ we represent entries in the action table as 1-based indices.
+ Special cases are:
+
+ 0: null action record, non-null landing pad; implies cleanups
+ -1: null action record, null landing pad; implies no action
+ -2: no call-site entry; implies must_not_throw
+ -3: we have yet to process outer regions
+
+ Further, no special cases apply to the "next" field of the record.
+ For next, 0 means end of list. */
+
+struct action_record
+{
+ int offset;
+ int filter;
+ int next;
+};
+
+/* Hashtable helpers. */
+
+struct action_record_hasher : typed_free_remove <action_record>
+{
+ typedef action_record value_type;
+ typedef action_record compare_type;
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+action_record_hasher::hash (const value_type *entry)
+{
+ return entry->next * 1009 + entry->filter;
+}
+
+inline bool
+action_record_hasher::equal (const value_type *entry, const compare_type *data)
+{
+ return entry->filter == data->filter && entry->next == data->next;
+}
+
+typedef hash_table<action_record_hasher> action_hash_type;
\f
static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
eh_landing_pad *);
static int t2r_eq (const void *, const void *);
static hashval_t t2r_hash (const void *);
-static int ttypes_filter_eq (const void *, const void *);
-static hashval_t ttypes_filter_hash (const void *);
-static int ehspec_filter_eq (const void *, const void *);
-static hashval_t ehspec_filter_hash (const void *);
-static int add_ttypes_entry (htab_t, tree);
-static int add_ehspec_entry (htab_t, htab_t, tree);
static void dw2_build_landing_pads (void);
-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, eh_region);
+static int collect_one_action_chain (action_hash_type *, 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);
tmp = size_int (FIRST_PSEUDO_REGISTER + 2 - 1);
#endif
#else
- /* builtin_setjmp takes a pointer to 5 words. */
- tmp = size_int (5 * BITS_PER_WORD / POINTER_SIZE - 1);
+ /* Compute a minimally sized jump buffer. We need room to store at
+ least 3 pointers - stack pointer, frame pointer and return address.
+ Plus for some targets we need room for an extra pointer - in the
+ case of MIPS this is the global pointer. This makes a total of four
+ pointers, but to be safe we actually allocate room for 5.
+
+ If pointers are smaller than words then we allocate enough room for
+ 5 words, just in case the backend needs this much room. For more
+ discussion on this issue see:
+ http://gcc.gnu.org/ml/gcc-patches/2014-05/msg00313.html. */
+ if (POINTER_SIZE > BITS_PER_WORD)
+ tmp = size_int (5 - 1);
+ else
+ tmp = size_int ((5 * BITS_PER_WORD / POINTER_SIZE) - 1);
#endif
+
tmp = build_index_type (tmp);
tmp = build_array_type (ptr_type_node, tmp);
f_jbuf = build_decl (BUILTINS_LOCATION,
/* Cache the interesting field offsets so that we have
easy access from rtl. */
sjlj_fc_call_site_ofs
- = (tree_low_cst (DECL_FIELD_OFFSET (f_cs), 1)
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_cs), 1) / BITS_PER_UNIT);
+ = (tree_to_uhwi (DECL_FIELD_OFFSET (f_cs))
+ + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_cs)) / BITS_PER_UNIT);
sjlj_fc_data_ofs
- = (tree_low_cst (DECL_FIELD_OFFSET (f_data), 1)
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_data), 1) / BITS_PER_UNIT);
+ = (tree_to_uhwi (DECL_FIELD_OFFSET (f_data))
+ + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_data)) / BITS_PER_UNIT);
sjlj_fc_personality_ofs
- = (tree_low_cst (DECL_FIELD_OFFSET (f_per), 1)
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_per), 1) / BITS_PER_UNIT);
+ = (tree_to_uhwi (DECL_FIELD_OFFSET (f_per))
+ + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_per)) / BITS_PER_UNIT);
sjlj_fc_lsda_ofs
- = (tree_low_cst (DECL_FIELD_OFFSET (f_lsda), 1)
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_lsda), 1) / BITS_PER_UNIT);
+ = (tree_to_uhwi (DECL_FIELD_OFFSET (f_lsda))
+ + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_lsda)) / BITS_PER_UNIT);
sjlj_fc_jbuf_ofs
- = (tree_low_cst (DECL_FIELD_OFFSET (f_jbuf), 1)
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_jbuf), 1) / BITS_PER_UNIT);
+ = (tree_to_uhwi (DECL_FIELD_OFFSET (f_jbuf))
+ + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_jbuf)) / BITS_PER_UNIT);
}
}
void
init_eh_for_function (void)
{
- cfun->eh = ggc_alloc_cleared_eh_status ();
+ cfun->eh = ggc_cleared_alloc<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.
eh_region new_eh;
/* Insert a new blank region as a leaf in the tree. */
- new_eh = ggc_alloc_cleared_eh_region_d ();
+ new_eh = ggc_cleared_alloc<eh_region_d> ();
new_eh->type = type;
new_eh->outer = outer;
if (outer)
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)
add_type_for_runtime (TREE_VALUE (type_node));
}
- c = ggc_alloc_cleared_eh_catch_d ();
+ c = ggc_cleared_alloc<eh_catch_d> ();
c->type_list = type_list;
l = t->u.eh_try.last_catch;
c->prev_catch = l;
eh_landing_pad
gen_eh_landing_pad (eh_region region)
{
- eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d ();
+ eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
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;
}
}
{
duplicate_eh_regions_map label_map;
void *label_map_data;
- struct pointer_map_t *eh_map;
+ hash_map<void *, void *> *eh_map;
};
static void
{
eh_landing_pad old_lp, new_lp;
eh_region new_r;
- void **slot;
new_r = gen_eh_region (old_r->type, outer);
- slot = pointer_map_insert (data->eh_map, (void *)old_r);
- gcc_assert (*slot == NULL);
- *slot = (void *)new_r;
+ gcc_assert (!data->eh_map->put (old_r, new_r));
switch (old_r->type)
{
continue;
new_lp = gen_eh_landing_pad (new_r);
- slot = pointer_map_insert (data->eh_map, (void *)old_lp);
- gcc_assert (*slot == NULL);
- *slot = (void *)new_lp;
+ gcc_assert (!data->eh_map->put (old_lp, new_lp));
new_lp->post_landing_pad
= data->label_map (old_lp->post_landing_pad, data->label_map_data);
that allows the caller to remap uses of both EH regions and
EH landing pads. */
-struct pointer_map_t *
+hash_map<void *, void *> *
duplicate_eh_regions (struct function *ifun,
eh_region copy_region, int outer_lp,
duplicate_eh_regions_map map, void *map_data)
data.label_map = map;
data.label_map_data = map_data;
- data.eh_map = pointer_map_create ();
+ data.eh_map = new hash_map<void *, void *>;
outer_region = get_eh_region_from_lp_number (outer_lp);
gcc_assert (ifun->eh->region_array);
gcc_assert (ifun->eh->region_tree);
- b_outer = sbitmap_alloc (VEC_length (eh_region, ifun->eh->region_array));
+ b_outer = sbitmap_alloc (ifun->eh->region_array->length ());
bitmap_clear (b_outer);
do
int filter;
};
+/* Helper for ttypes_filter hashing. */
+
+struct ttypes_filter_hasher : typed_free_remove <ttypes_filter>
+{
+ typedef ttypes_filter value_type;
+ typedef tree_node compare_type;
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+};
+
/* Compare ENTRY (a ttypes_filter entry in the hash table) with DATA
(a tree) for a @TTypes type node we are thinking about adding. */
-static int
-ttypes_filter_eq (const void *pentry, const void *pdata)
+inline bool
+ttypes_filter_hasher::equal (const value_type *entry, const compare_type *data)
{
- const struct ttypes_filter *const entry
- = (const struct ttypes_filter *) pentry;
- const_tree const data = (const_tree) pdata;
-
return entry->t == data;
}
-static hashval_t
-ttypes_filter_hash (const void *pentry)
+inline hashval_t
+ttypes_filter_hasher::hash (const value_type *entry)
{
- const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
return TREE_HASH (entry->t);
}
+typedef hash_table<ttypes_filter_hasher> ttypes_hash_type;
+
+
+/* Helper for ehspec hashing. */
+
+struct ehspec_hasher : typed_free_remove <ttypes_filter>
+{
+ typedef ttypes_filter value_type;
+ typedef ttypes_filter compare_type;
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+};
+
/* Compare ENTRY with DATA (both struct ttypes_filter) for a @TTypes
exception specification list we are thinking about adding. */
/* ??? Currently we use the type lists in the order given. Someone
should put these in some canonical order. */
-static int
-ehspec_filter_eq (const void *pentry, const void *pdata)
+inline bool
+ehspec_hasher::equal (const value_type *entry, const compare_type *data)
{
- const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
- const struct ttypes_filter *data = (const struct ttypes_filter *) pdata;
-
return type_list_equal (entry->t, data->t);
}
/* Hash function for exception specification lists. */
-static hashval_t
-ehspec_filter_hash (const void *pentry)
+inline hashval_t
+ehspec_hasher::hash (const value_type *entry)
{
- const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
hashval_t h = 0;
tree list;
return h;
}
+typedef hash_table<ehspec_hasher> ehspec_hash_type;
+
+
/* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH
to speed up the search. Return the filter value to be used. */
static int
-add_ttypes_entry (htab_t ttypes_hash, tree type)
+add_ttypes_entry (ttypes_hash_type *ttypes_hash, tree type)
{
struct ttypes_filter **slot, *n;
- slot = (struct ttypes_filter **)
- htab_find_slot_with_hash (ttypes_hash, type, TREE_HASH (type), INSERT);
+ slot = ttypes_hash->find_slot_with_hash (type, (hashval_t) TREE_HASH (type),
+ INSERT);
if ((n = *slot) == NULL)
{
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;
to speed up the search. Return the filter value to be used. */
static int
-add_ehspec_entry (htab_t ehspec_hash, htab_t ttypes_hash, tree list)
+add_ehspec_entry (ehspec_hash_type *ehspec_hash, ttypes_hash_type *ttypes_hash,
+ tree list)
{
struct ttypes_filter **slot, *n;
struct ttypes_filter dummy;
dummy.t = list;
- slot = (struct ttypes_filter **)
- htab_find_slot (ehspec_hash, &dummy, INSERT);
+ slot = ehspec_hash->find_slot (&dummy, INSERT);
if ((n = *slot) == NULL)
{
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;
assign_filter_values (void)
{
int i;
- htab_t ttypes, ehspec;
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);
+ ehspec_hash_type ehspec (31);
+ ttypes_hash_type ttypes (31);
- 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;
for ( ; tp_node; tp_node = TREE_CHAIN (tp_node))
{
- int flt = add_ttypes_entry (ttypes, TREE_VALUE (tp_node));
+ int flt
+ = add_ttypes_entry (&ttypes, TREE_VALUE (tp_node));
tree flt_node = build_int_cst (integer_type_node, flt);
c->filter_list
{
/* Get a filter value for the NULL list also since it
will need an action record anyway. */
- int flt = add_ttypes_entry (ttypes, NULL);
+ int flt = add_ttypes_entry (&ttypes, NULL);
tree flt_node = build_int_cst (integer_type_node, flt);
c->filter_list
case ERT_ALLOWED_EXCEPTIONS:
r->u.allowed.filter
- = add_ehspec_entry (ehspec, ttypes, r->u.allowed.type_list);
+ = add_ehspec_entry (&ehspec, &ttypes, r->u.allowed.type_list);
break;
default:
break;
}
}
-
- htab_delete (ttypes);
- htab_delete (ehspec);
}
/* Emit SEQ into basic block just before INSN (that is assumed to be
first instruction of some existing BB and return the newly
produced block. */
static basic_block
-emit_to_new_bb_before (rtx seq, rtx insn)
+emit_to_new_bb_before (rtx_insn *seq, rtx insn)
{
- rtx last;
- basic_block bb, prev_bb;
+ rtx_insn *last;
+ basic_block bb;
edge e;
edge_iterator ei;
last = emit_insn_before (seq, insn);
if (BARRIER_P (last))
last = PREV_INSN (last);
- prev_bb = BLOCK_FOR_INSN (insn)->prev_bb;
- bb = create_basic_block (seq, last, prev_bb);
+ bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->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;
+ rtx_insn *seq;
edge e;
if (lp == NULL || lp->post_landing_pad == NULL)
}
\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. */
static int
sjlj_assign_call_site_values (void)
{
- htab_t ar_hash;
+ action_hash_type ar_hash (31);
int i, disp_index;
eh_landing_pad lp;
- crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
- ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
+ vec_alloc (crtl->eh.action_record_data, 64);
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;
/* First: build the action table. */
- action = collect_one_action_chain (ar_hash, lp->region);
+ action = collect_one_action_chain (&ar_hash, lp->region);
/* Next: assign call-site values. If dwarf2 terms, this would be
the region number assigned by convert_to_eh_region_ranges, but
/* 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++;
}
- htab_delete (ar_hash);
-
return disp_index;
}
sjlj_mark_call_sites (void)
{
int last_call_site = -2;
- rtx insn, mem;
+ rtx_insn *insn;
+ rtx mem;
for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
{
eh_region r;
bool nothrow;
int this_call_site;
- rtx before, p;
+ rtx_insn *before, *p;
/* Reset value tracking at extended basic block boundaries. */
if (LABEL_P (insn))
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
start_sequence ();
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));
+ emit_move_insn (mem, gen_int_mode (this_call_site, GET_MODE (mem)));
p = get_insns ();
end_sequence ();
/* Construct the SjLj_Function_Context. */
static void
-sjlj_emit_function_enter (rtx dispatch_label)
+sjlj_emit_function_enter (rtx_code_label *dispatch_label)
{
- rtx fn_begin, fc, mem, seq;
+ rtx_insn *fn_begin, *seq;
+ rtx fc, mem;
bool fn_begin_outside_block;
rtx personality = get_personality_function (current_function_decl);
}
if (fn_begin_outside_block)
- insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
+ insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
else
emit_insn_after (seq, fn_begin);
}
the call to unwind_sjlj_unregister_libfunc if needed. */
void
-sjlj_emit_function_exit_after (rtx after)
+sjlj_emit_function_exit_after (rtx_insn *after)
{
crtl->eh.sjlj_exit_after = after;
}
static void
sjlj_emit_function_exit (void)
{
- rtx seq, insn;
+ rtx_insn *seq, *insn;
start_sequence ();
}
static void
-sjlj_emit_dispatch_table (rtx dispatch_label, int num_dispatch)
+sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch)
{
enum machine_mode unwind_word_mode = targetm.unwind_word_mode ();
enum machine_mode filter_mode = targetm.eh_return_filter_mode ();
eh_landing_pad lp;
- rtx mem, seq, fc, before, exc_ptr_reg, filter_reg;
+ rtx mem, fc, before, exc_ptr_reg, filter_reg;
+ rtx_insn *seq;
rtx first_reachable_label;
basic_block bb;
eh_region r;
edge e;
int i, disp_index;
- VEC(tree, heap) *dispatch_labels = NULL;
+ vec<tree> dispatch_labels = vNULL;
fc = crtl->eh.sjlj_fc;
CFG edges more exactly, we can use the forced_labels list instead. */
LABEL_PRESERVE_P (dispatch_label) = 1;
forced_labels
- = gen_rtx_EXPR_LIST (VOIDmode, dispatch_label, forced_labels);
+ = gen_rtx_INSN_LIST (VOIDmode, dispatch_label, forced_labels);
#endif
/* Load up exc_ptr and filter values from the function context. */
/* If there's exactly one call site in the function, don't bother
generating a switch statement. */
if (num_dispatch > 1)
- dispatch_labels = VEC_alloc (tree, heap, num_dispatch);
+ dispatch_labels.create (num_dispatch);
- 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;
+ rtx_insn *seq2;
+ rtx label;
start_sequence ();
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);
- VEC_quick_push (tree, dispatch_labels, case_elt);
+ dispatch_labels.quick_push (case_elt);
label = label_rtx (t_label);
}
else
{
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)
{
- rtx dispatch_label = gen_label_rtx ();
+ rtx_code_label *dispatch_label = gen_label_rtx ();
int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
TYPE_MODE (sjlj_fc_type_node),
TYPE_ALIGN (sjlj_fc_type_node));
align);
sjlj_mark_call_sites ();
- sjlj_emit_function_enter (NULL_RTX);
+ sjlj_emit_function_enter (NULL);
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
if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
/* Kludge for Alpha (see alpha_gp_save_rtx). */
- || single_succ_edge (ENTRY_BLOCK_PTR)->insns.r)
+ || single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->insns.r)
commit_edge_insertions ();
/* Redirect all EH edges from the post_landing_pad to the landing pad. */
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
{
eh_landing_pad lp;
edge_iterator ei;
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)
{
to look for a note, or the note itself. */
void
-copy_reg_eh_region_note_forward (rtx note_or_insn, rtx first, rtx last)
+copy_reg_eh_region_note_forward (rtx note_or_insn, rtx_insn *first, rtx last)
{
- rtx insn, note = note_or_insn;
+ rtx_insn *insn;
+ rtx note = note_or_insn;
if (INSN_P (note_or_insn))
{
/* Likewise, but iterate backward. */
void
-copy_reg_eh_region_note_backward (rtx note_or_insn, rtx last, rtx first)
+copy_reg_eh_region_note_backward (rtx note_or_insn, rtx_insn *last, rtx first)
{
- rtx insn, note = note_or_insn;
+ rtx_insn *insn;
+ rtx note = note_or_insn;
if (INSN_P (note_or_insn))
{
}
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;
}
if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
{
- rtx seq = PATTERN (insn);
- int i, n = XVECLEN (seq, 0);
+ rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
+ int i, n = seq->len ();
for (i = 0; i < n; i++)
- if (can_throw_external (XVECEXP (seq, 0, i)))
+ if (can_throw_external (seq->element (i)))
return true;
return false;
if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
{
- rtx seq = PATTERN (insn);
- int i, n = XVECLEN (seq, 0);
+ rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
+ int i, n = seq->len ();
for (i = 0; i < n; i++)
- if (!insn_nothrow_p (XVECEXP (seq, 0, i)))
+ if (!insn_nothrow_p (seq->element (i)))
return false;
return true;
static unsigned int
set_nothrow_function_flags (void)
{
- rtx insn;
+ rtx_insn *insn;
crtl->nothrow = 1;
}
}
- 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))
+ && (cgraph_node::get (current_function_decl)->get_availability ()
>= AVAIL_AVAILABLE))
{
- struct cgraph_node *node = cgraph_get_node (current_function_decl);
+ struct cgraph_node *node = cgraph_node::get (current_function_decl);
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
e->can_throw_external = false;
- cgraph_set_nothrow_flag (node, true);
+ node->set_nothrow_flag (true);
if (dump_file)
fprintf (dump_file, "Marking function nothrow: %s\n\n",
return 0;
}
-struct rtl_opt_pass pass_set_nothrow_function_flags =
-{
- {
- RTL_PASS,
- "nothrow", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- NULL, /* gate */
- set_nothrow_function_flags, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- }
+namespace {
+
+const pass_data pass_data_set_nothrow_function_flags =
+{
+ RTL_PASS, /* type */
+ "nothrow", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
};
+class pass_set_nothrow_function_flags : public rtl_opt_pass
+{
+public:
+ pass_set_nothrow_function_flags (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_set_nothrow_function_flags, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *)
+ {
+ return set_nothrow_function_flags ();
+ }
+
+}; // class pass_set_nothrow_function_flags
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_set_nothrow_function_flags (gcc::context *ctxt)
+{
+ return new pass_set_nothrow_function_flags (ctxt);
+}
+
\f
/* Various hooks for unwind library. */
HOST_WIDE_INT region_nr;
eh_region region;
- gcc_assert (host_integerp (region_nr_t, 0));
- region_nr = tree_low_cst (region_nr_t, 0);
+ gcc_assert (tree_fits_shwi_p (region_nr_t));
+ region_nr = tree_to_shwi (region_nr_t);
- 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. */
return constm1_rtx;
}
- iwhich = tree_low_cst (which, 1);
+ iwhich = tree_to_uhwi (which);
iwhich = EH_RETURN_DATA_REGNO (iwhich);
if (iwhich == INVALID_REGNUM)
return constm1_rtx;
void
expand_eh_return (void)
{
- rtx around_label;
+ rtx_code_label *around_label;
if (! crtl->eh.ehr_label)
return;
return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
}
\f
-/* In the following functions, we represent entries in the action table
- as 1-based indices. Special cases are:
-
- 0: null action record, non-null landing pad; implies cleanups
- -1: null action record, null landing pad; implies no action
- -2: no call-site entry; implies must_not_throw
- -3: we have yet to process outer regions
-
- Further, no special cases apply to the "next" field of the record.
- For next, 0 means end of list. */
-
-struct action_record
-{
- int offset;
- int filter;
- int next;
-};
-
static int
-action_record_eq (const void *pentry, const void *pdata)
-{
- const struct action_record *entry = (const struct action_record *) pentry;
- const struct action_record *data = (const struct action_record *) pdata;
- return entry->filter == data->filter && entry->next == data->next;
-}
-
-static hashval_t
-action_record_hash (const void *pentry)
-{
- const struct action_record *entry = (const struct action_record *) pentry;
- return entry->next * 1009 + entry->filter;
-}
-
-static int
-add_action_record (htab_t ar_hash, int filter, int next)
+add_action_record (action_hash_type *ar_hash, int filter, int next)
{
struct action_record **slot, *new_ar, tmp;
tmp.filter = filter;
tmp.next = next;
- slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
+ slot = ar_hash->find_slot (&tmp, INSERT);
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);
}
}
static int
-collect_one_action_chain (htab_t ar_hash, eh_region region)
+collect_one_action_chain (action_hash_type *ar_hash, eh_region region)
{
int next;
{
call_site_record record;
- record = ggc_alloc_call_site_record_d ();
+ record = ggc_alloc<call_site_record_d> ();
record->landing_pad = landing_pad;
record->action = action;
- VEC_safe_push (call_site_record, gc,
- crtl->eh.call_site_record_v[section], record);
+ vec_safe_push (crtl->eh.call_site_record_v[section], record);
+
+ return call_site_base + crtl->eh.call_site_record_v[section]->length () - 1;
+}
+
+static rtx_note *
+emit_note_eh_region_end (rtx insn)
+{
+ rtx_insn *next = NEXT_INSN (insn);
+
+ /* Make sure we do not split a call and its corresponding
+ CALL_ARG_LOCATION note. */
+ if (next && NOTE_P (next)
+ && NOTE_KIND (next) == NOTE_INSN_CALL_ARG_LOCATION)
+ insn = next;
- return call_site_base + VEC_length (call_site_record,
- crtl->eh.call_site_record_v[section]) - 1;
+ return emit_note_after (NOTE_INSN_EH_REGION_END, insn);
}
/* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
static unsigned int
convert_to_eh_region_ranges (void)
{
- rtx insn, iter, note;
- htab_t ar_hash;
+ rtx insn;
+ rtx_insn *iter;
+ rtx_note *note;
+ action_hash_type ar_hash (31);
int last_action = -3;
- rtx last_action_insn = NULL_RTX;
+ rtx_insn *last_action_insn = NULL;
rtx last_landing_pad = NULL_RTX;
- rtx first_no_action_insn = NULL_RTX;
+ rtx_insn *first_no_action_insn = NULL;
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_insn *first_no_action_insn_before_switch = NULL;
+ rtx_insn *last_no_action_insn_before_switch = NULL;
int saved_call_site_base = call_site_base;
- crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
-
- ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
+ vec_alloc (crtl->eh.action_record_data, 64);
for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
if (INSN_P (iter))
if (nothrow)
continue;
if (region)
- this_action = collect_one_action_chain (ar_hash, region);
+ this_action = collect_one_action_chain (&ar_hash, region);
else
this_action = -1;
note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
first_no_action_insn_before_switch);
NOTE_EH_HANDLER (note) = call_site;
- note = emit_note_after (NOTE_INSN_EH_REGION_END,
- last_no_action_insn_before_switch);
+ note
+ = emit_note_eh_region_end (last_no_action_insn_before_switch);
NOTE_EH_HANDLER (note) = call_site;
gcc_assert (last_action != -3
|| (last_action_insn
== last_no_action_insn_before_switch));
- first_no_action_insn_before_switch = NULL_RTX;
- last_no_action_insn_before_switch = NULL_RTX;
+ first_no_action_insn_before_switch = NULL;
+ last_no_action_insn_before_switch = NULL;
call_site_base++;
}
/* If we'd not seen a previous action (-3) or the previous
note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
first_no_action_insn);
NOTE_EH_HANDLER (note) = call_site;
- first_no_action_insn = NULL_RTX;
+ first_no_action_insn = NULL;
}
- note = emit_note_after (NOTE_INSN_EH_REGION_END,
- last_action_insn);
+ note = emit_note_eh_region_end (last_action_insn);
NOTE_EH_HANDLER (note) = call_site;
}
{
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;
+ first_no_action_insn = NULL;
gcc_assert (last_action == -1);
last_action = -3;
}
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_v[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_v[cur_sec] == NULL);
- crtl->eh.call_site_record_v[cur_sec]
- = VEC_alloc (call_site_record, gc, 10);
+ vec_alloc (crtl->eh.call_site_record_v[cur_sec], 10);
}
if (last_action >= -1 && ! first_no_action_insn)
{
- note = emit_note_after (NOTE_INSN_EH_REGION_END, last_action_insn);
+ note = emit_note_eh_region_end (last_action_insn);
NOTE_EH_HANDLER (note) = call_site;
}
call_site_base = saved_call_site_base;
- htab_delete (ar_hash);
return 0;
}
-static bool
-gate_convert_to_eh_region_ranges (void)
+namespace {
+
+const pass_data pass_data_convert_to_eh_region_ranges =
+{
+ RTL_PASS, /* type */
+ "eh_ranges", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_convert_to_eh_region_ranges : public rtl_opt_pass
+{
+public:
+ pass_convert_to_eh_region_ranges (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_convert_to_eh_region_ranges, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *);
+ virtual unsigned int execute (function *)
+ {
+ return convert_to_eh_region_ranges ();
+ }
+
+}; // class pass_convert_to_eh_region_ranges
+
+bool
+pass_convert_to_eh_region_ranges::gate (function *)
{
/* Nothing to do for SJLJ exceptions or if no regions created. */
if (cfun->eh->region_tree == NULL)
return true;
}
-struct rtl_opt_pass pass_convert_to_eh_region_ranges =
-{
- {
- RTL_PASS,
- "eh_ranges", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_convert_to_eh_region_ranges, /* gate */
- convert_to_eh_region_ranges, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- }
-};
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_convert_to_eh_region_ranges (gcc::context *ctxt)
+{
+ return new pass_convert_to_eh_region_ranges (ctxt);
+}
\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_v[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_v[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_v[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_v[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_v[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_v[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_v[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_v[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);
#ifdef HAVE_LD_EH_GC_SECTIONS
if (flag_function_sections
- || (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP))
+ || (DECL_COMDAT_GROUP (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)
+ if (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP)
flags |= SECTION_LINKONCE;
sprintf (section_name, ".gcc_except_table.%s", fnname);
s = get_section (section_name, flags, current_function_decl);
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_v[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;