summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/except.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/except.c')
-rw-r--r--contrib/gcc/except.c746
1 files changed, 266 insertions, 480 deletions
diff --git a/contrib/gcc/except.c b/contrib/gcc/except.c
index a258731..b6f851b 100644
--- a/contrib/gcc/except.c
+++ b/contrib/gcc/except.c
@@ -70,15 +70,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
+#include "langhooks.h"
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
-#ifndef EH_RETURN_STACKADJ_RTX
-#define EH_RETURN_STACKADJ_RTX 0
-#endif
-#ifndef EH_RETURN_HANDLER_RTX
-#define EH_RETURN_HANDLER_RTX 0
-#endif
#ifndef EH_RETURN_DATA_REGNO
#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
#endif
@@ -99,20 +94,18 @@ tree (*lang_eh_runtime_type) PARAMS ((tree));
/* A hash table of label to region number. */
-struct ehl_map_entry
+struct ehl_map_entry GTY(())
{
rtx label;
struct eh_region *region;
};
-static htab_t exception_handler_label_map;
-
static int call_site_base;
-static unsigned int sjlj_funcdef_number;
-static htab_t type_to_runtime_map;
+static GTY ((param_is (union tree_node)))
+ htab_t type_to_runtime_map;
/* Describe the SjLj_Function_Context structure. */
-static tree sjlj_fc_type_node;
+static GTY(()) tree sjlj_fc_type_node;
static int sjlj_fc_call_site_ofs;
static int sjlj_fc_data_ofs;
static int sjlj_fc_personality_ofs;
@@ -120,7 +113,7 @@ static int sjlj_fc_lsda_ofs;
static int sjlj_fc_jbuf_ofs;
/* Describes one exception region. */
-struct eh_region
+struct eh_region GTY(())
{
/* The immediately surrounding region. */
struct eh_region *outer;
@@ -150,50 +143,51 @@ struct eh_region
} type;
/* Holds the action to perform based on the preceding type. */
- union {
+ union eh_region_u {
/* A list of catch blocks, a surrounding try block,
and the label for continuing after a catch. */
- struct {
+ struct eh_region_u_try {
struct eh_region *catch;
struct eh_region *last_catch;
struct eh_region *prev_try;
rtx continue_label;
- } try;
+ } GTY ((tag ("ERT_TRY"))) try;
/* The list through the catch handlers, the list of type objects
matched, and the list of associated filters. */
- struct {
+ struct eh_region_u_catch {
struct eh_region *next_catch;
struct eh_region *prev_catch;
tree type_list;
tree filter_list;
- } catch;
+ } GTY ((tag ("ERT_CATCH"))) catch;
/* A tree_list of allowed types. */
- struct {
+ struct eh_region_u_allowed {
tree type_list;
int filter;
- } allowed;
+ } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
/* The type given by a call to "throw foo();", or discovered
for a throw. */
- struct {
+ struct eh_region_u_throw {
tree type;
- } throw;
+ } GTY ((tag ("ERT_THROW"))) throw;
/* Retain the cleanup expression even after expansion so that
we can match up fixup regions. */
- struct {
+ struct eh_region_u_cleanup {
tree exp;
- } cleanup;
+ struct eh_region *prev_try;
+ } GTY ((tag ("ERT_CLEANUP"))) cleanup;
/* The real region (by expression and by pointer) that fixup code
should live in. */
- struct {
+ struct eh_region_u_fixup {
tree cleanup_exp;
struct eh_region *real_region;
- } fixup;
- } u;
+ } GTY ((tag ("ERT_FIXUP"))) fixup;
+ } GTY ((desc ("%0.type"))) u;
/* Entry point for this region's handler before landing pads are built. */
rtx label;
@@ -207,16 +201,25 @@ struct eh_region
/* The RESX insn for handing off control to the next outermost handler,
if appropriate. */
rtx resume;
+
+ /* True if something in this region may throw. */
+ unsigned may_contain_throw : 1;
+};
+
+struct call_site_record GTY(())
+{
+ rtx landing_pad;
+ int action;
};
/* Used to save exception status for each function. */
-struct eh_status
+struct eh_status GTY(())
{
/* The tree of all regions for this function. */
struct eh_region *region_tree;
/* The same information as an indexable array. */
- struct eh_region **region_array;
+ struct eh_region ** GTY ((length ("%h.last_region_number"))) region_array;
/* The most recently open region. */
struct eh_region *cur_region;
@@ -224,12 +227,6 @@ struct eh_status
/* This is the region for which we are processing catch blocks. */
struct eh_region *try_region;
- /* A stack (TREE_LIST) of lists of handlers. The TREE_VALUE of each
- node is itself a TREE_CHAINed list of handlers for regions that
- are not yet closed. The TREE_VALUE of each entry contains the
- handler for the corresponding entry on the ehstack. */
- tree protect_list;
-
rtx filter;
rtx exc_ptr;
@@ -240,11 +237,10 @@ struct eh_status
varray_type ehspec_data;
varray_type action_record_data;
- struct call_site_record
- {
- rtx landing_pad;
- int action;
- } *call_site_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;
@@ -257,17 +253,9 @@ struct eh_status
};
-static void mark_eh_region PARAMS ((struct eh_region *));
-static int mark_ehl_map_entry PARAMS ((PTR *, PTR));
-static void mark_ehl_map PARAMS ((void *));
-
-static void free_region PARAMS ((struct eh_region *));
-
static int t2r_eq PARAMS ((const PTR,
const PTR));
static hashval_t t2r_hash PARAMS ((const PTR));
-static int t2r_mark_1 PARAMS ((PTR *, PTR));
-static void t2r_mark PARAMS ((PTR));
static void add_type_for_runtime PARAMS ((tree));
static tree lookup_type_for_runtime PARAMS ((tree));
@@ -315,7 +303,6 @@ static void sjlj_build_landing_pads PARAMS ((void));
static hashval_t ehl_hash PARAMS ((const PTR));
static int ehl_eq PARAMS ((const PTR,
const PTR));
-static void ehl_free PARAMS ((PTR));
static void add_ehl_entry PARAMS ((rtx,
struct eh_region *));
static void remove_exception_handler_label PARAMS ((rtx));
@@ -364,7 +351,7 @@ static void sjlj_output_call_site_table PARAMS ((void));
/* Routine to see if exception handling is turned on.
- DO_WARN is non-zero if we want to inform the user that exception
+ DO_WARN is nonzero if we want to inform the user that exception
handling is turned off.
This is used to ensure that -fexceptions has been specified if the
@@ -391,13 +378,10 @@ doing_eh (do_warn)
void
init_eh ()
{
- ggc_add_root (&exception_handler_label_map, 1, 1, mark_ehl_map);
-
if (! flag_exceptions)
return;
- type_to_runtime_map = htab_create (31, t2r_hash, t2r_eq, NULL);
- ggc_add_root (&type_to_runtime_map, 1, sizeof (htab_t), t2r_mark);
+ type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL);
/* Create the SjLj_Function_Context structure. This should match
the definition in unwind-sjlj.c. */
@@ -405,8 +389,7 @@ init_eh ()
{
tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp;
- sjlj_fc_type_node = make_lang_type (RECORD_TYPE);
- ggc_add_tree_root (&sjlj_fc_type_node, 1);
+ sjlj_fc_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
f_prev = build_decl (FIELD_DECL, get_identifier ("__prev"),
build_pointer_type (sjlj_fc_type_node));
@@ -417,7 +400,8 @@ init_eh ()
DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
tmp = build_index_type (build_int_2 (4 - 1, 0));
- tmp = build_array_type (type_for_mode (word_mode, 1), tmp);
+ tmp = build_array_type ((*lang_hooks.types.type_for_mode) (word_mode, 1),
+ tmp);
f_data = build_decl (FIELD_DECL, get_identifier ("__data"), tmp);
DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
@@ -488,210 +472,9 @@ init_eh ()
void
init_eh_for_function ()
{
- cfun->eh = (struct eh_status *) xcalloc (1, sizeof (struct eh_status));
+ cfun->eh = (struct eh_status *)
+ ggc_alloc_cleared (sizeof (struct eh_status));
}
-
-/* Mark EH for GC. */
-
-static void
-mark_eh_region (region)
- struct eh_region *region;
-{
- if (! region)
- return;
-
- switch (region->type)
- {
- case ERT_UNKNOWN:
- /* This can happen if a nested function is inside the body of a region
- and we do a GC as part of processing it. */
- break;
- case ERT_CLEANUP:
- ggc_mark_tree (region->u.cleanup.exp);
- break;
- case ERT_TRY:
- ggc_mark_rtx (region->u.try.continue_label);
- break;
- case ERT_CATCH:
- ggc_mark_tree (region->u.catch.type_list);
- ggc_mark_tree (region->u.catch.filter_list);
- break;
- case ERT_ALLOWED_EXCEPTIONS:
- ggc_mark_tree (region->u.allowed.type_list);
- break;
- case ERT_MUST_NOT_THROW:
- break;
- case ERT_THROW:
- ggc_mark_tree (region->u.throw.type);
- break;
- case ERT_FIXUP:
- ggc_mark_tree (region->u.fixup.cleanup_exp);
- break;
- default:
- abort ();
- }
-
- ggc_mark_rtx (region->label);
- ggc_mark_rtx (region->resume);
- ggc_mark_rtx (region->landing_pad);
- ggc_mark_rtx (region->post_landing_pad);
-}
-
-static int
-mark_ehl_map_entry (pentry, data)
- PTR *pentry;
- PTR data ATTRIBUTE_UNUSED;
-{
- struct ehl_map_entry *entry = *(struct ehl_map_entry **) pentry;
- ggc_mark_rtx (entry->label);
- return 1;
-}
-
-static void
-mark_ehl_map (pp)
- void *pp;
-{
- htab_t map = *(htab_t *) pp;
- if (map)
- htab_traverse (map, mark_ehl_map_entry, NULL);
-}
-
-void
-mark_eh_status (eh)
- struct eh_status *eh;
-{
- int i;
-
- if (eh == 0)
- return;
-
- /* If we've called collect_eh_region_array, use it. Otherwise walk
- the tree non-recursively. */
- if (eh->region_array)
- {
- for (i = eh->last_region_number; i > 0; --i)
- {
- struct eh_region *r = eh->region_array[i];
- if (r && r->region_number == i)
- mark_eh_region (r);
- }
- }
- else if (eh->region_tree)
- {
- struct eh_region *r = eh->region_tree;
- while (1)
- {
- mark_eh_region (r);
- if (r->inner)
- r = r->inner;
- else if (r->next_peer)
- r = r->next_peer;
- else
- {
- do {
- r = r->outer;
- if (r == NULL)
- goto tree_done;
- } while (r->next_peer == NULL);
- r = r->next_peer;
- }
- }
- tree_done:;
- }
-
- ggc_mark_tree (eh->protect_list);
- ggc_mark_rtx (eh->filter);
- ggc_mark_rtx (eh->exc_ptr);
- ggc_mark_tree_varray (eh->ttype_data);
-
- if (eh->call_site_data)
- {
- for (i = eh->call_site_data_used - 1; i >= 0; --i)
- ggc_mark_rtx (eh->call_site_data[i].landing_pad);
- }
-
- ggc_mark_rtx (eh->ehr_stackadj);
- ggc_mark_rtx (eh->ehr_handler);
- ggc_mark_rtx (eh->ehr_label);
-
- ggc_mark_rtx (eh->sjlj_fc);
- ggc_mark_rtx (eh->sjlj_exit_after);
-}
-
-static inline void
-free_region (r)
- struct eh_region *r;
-{
- /* Note that the aka bitmap is freed by regset_release_memory. But if
- we ever replace with a non-obstack implementation, this would be
- the place to do it. */
- free (r);
-}
-
-void
-free_eh_status (f)
- struct function *f;
-{
- struct eh_status *eh = f->eh;
-
- if (eh->region_array)
- {
- int i;
- for (i = eh->last_region_number; i > 0; --i)
- {
- struct eh_region *r = eh->region_array[i];
- /* Mind we don't free a region struct more than once. */
- if (r && r->region_number == i)
- free_region (r);
- }
- free (eh->region_array);
- }
- else if (eh->region_tree)
- {
- struct eh_region *next, *r = eh->region_tree;
- while (1)
- {
- if (r->inner)
- r = r->inner;
- else if (r->next_peer)
- {
- next = r->next_peer;
- free_region (r);
- r = next;
- }
- else
- {
- do {
- next = r->outer;
- free_region (r);
- r = next;
- if (r == NULL)
- goto tree_done;
- } while (r->next_peer == NULL);
- next = r->next_peer;
- free_region (r);
- r = next;
- }
- }
- tree_done:;
- }
-
- VARRAY_FREE (eh->ttype_data);
- VARRAY_FREE (eh->ehspec_data);
- VARRAY_FREE (eh->action_record_data);
- if (eh->call_site_data)
- free (eh->call_site_data);
-
- free (eh);
- f->eh = NULL;
-
- if (exception_handler_label_map)
- {
- htab_delete (exception_handler_label_map);
- exception_handler_label_map = NULL;
- }
-}
-
/* Start an exception handling region. All instructions emitted
after this point are considered to be part of the region until
@@ -708,7 +491,7 @@ expand_eh_region_start ()
return;
/* Insert a new blank region as a leaf in the tree. */
- new_region = (struct eh_region *) xcalloc (1, sizeof (*new_region));
+ new_region = (struct eh_region *) ggc_alloc_cleared (sizeof (*new_region));
cur_region = cfun->eh->cur_region;
new_region->outer = cur_region;
if (cur_region)
@@ -766,39 +549,43 @@ expand_eh_region_end_cleanup (handler)
region->type = ERT_CLEANUP;
region->label = gen_label_rtx ();
region->u.cleanup.exp = handler;
+ region->u.cleanup.prev_try = cfun->eh->try_region;
around_label = gen_label_rtx ();
emit_jump (around_label);
emit_label (region->label);
- /* Give the language a chance to specify an action to be taken if an
- exception is thrown that would propagate out of the HANDLER. */
- protect_cleanup_actions
- = (lang_protect_cleanup_actions
- ? (*lang_protect_cleanup_actions) ()
- : NULL_TREE);
+ if (flag_non_call_exceptions || region->may_contain_throw)
+ {
+ /* Give the language a chance to specify an action to be taken if an
+ exception is thrown that would propagate out of the HANDLER. */
+ protect_cleanup_actions
+ = (lang_protect_cleanup_actions
+ ? (*lang_protect_cleanup_actions) ()
+ : NULL_TREE);
- if (protect_cleanup_actions)
- expand_eh_region_start ();
+ if (protect_cleanup_actions)
+ expand_eh_region_start ();
- /* In case this cleanup involves an inline destructor with a try block in
- it, we need to save the EH return data registers around it. */
- data_save[0] = gen_reg_rtx (Pmode);
- emit_move_insn (data_save[0], get_exception_pointer (cfun));
- data_save[1] = gen_reg_rtx (word_mode);
- emit_move_insn (data_save[1], get_exception_filter (cfun));
+ /* In case this cleanup involves an inline destructor with a try block in
+ it, we need to save the EH return data registers around it. */
+ data_save[0] = gen_reg_rtx (ptr_mode);
+ emit_move_insn (data_save[0], get_exception_pointer (cfun));
+ data_save[1] = gen_reg_rtx (word_mode);
+ emit_move_insn (data_save[1], get_exception_filter (cfun));
- expand_expr (handler, const0_rtx, VOIDmode, 0);
+ expand_expr (handler, const0_rtx, VOIDmode, 0);
- emit_move_insn (cfun->eh->exc_ptr, data_save[0]);
- emit_move_insn (cfun->eh->filter, data_save[1]);
+ emit_move_insn (cfun->eh->exc_ptr, data_save[0]);
+ emit_move_insn (cfun->eh->filter, data_save[1]);
- if (protect_cleanup_actions)
- expand_eh_region_end_must_not_throw (protect_cleanup_actions);
+ if (protect_cleanup_actions)
+ expand_eh_region_end_must_not_throw (protect_cleanup_actions);
- /* We need any stack adjustment complete before the around_label. */
- do_pending_stack_adjust ();
+ /* We need any stack adjustment complete before the around_label. */
+ do_pending_stack_adjust ();
+ }
/* We delay the generation of the _Unwind_Resume until we generate
landing pads. We emit a marker here so as to get good control
@@ -856,11 +643,11 @@ expand_start_catch (type_or_list)
tree type_node;
if (TREE_CODE (type_or_list) != TREE_LIST)
- type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
+ type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
type_node = type_list;
for (; type_node; type_node = TREE_CHAIN (type_node))
- add_type_for_runtime (TREE_VALUE (type_node));
+ add_type_for_runtime (TREE_VALUE (type_node));
}
expand_eh_region_start ();
@@ -1034,6 +821,22 @@ expand_eh_region_end_fixup (handler)
fixup->u.fixup.cleanup_exp = handler;
}
+/* Note that the current EH region (if any) may contain a throw, or a
+ call to a function which itself may contain a throw. */
+
+void
+note_eh_region_may_contain_throw ()
+{
+ struct eh_region *region;
+
+ region = cfun->eh->cur_region;
+ while (region && !region->may_contain_throw)
+ {
+ region->may_contain_throw = 1;
+ region = region->outer;
+ }
+}
+
/* Return an rtl expression for a pointer to the exception object
within a handler. */
@@ -1044,7 +847,7 @@ get_exception_pointer (fun)
rtx exc_ptr = fun->eh->exc_ptr;
if (fun == cfun && ! exc_ptr)
{
- exc_ptr = gen_reg_rtx (Pmode);
+ exc_ptr = gen_reg_rtx (ptr_mode);
fun->eh->exc_ptr = exc_ptr;
}
return exc_ptr;
@@ -1066,55 +869,6 @@ get_exception_filter (fun)
return filter;
}
-/* Begin a region that will contain entries created with
- add_partial_entry. */
-
-void
-begin_protect_partials ()
-{
- /* Push room for a new list. */
- cfun->eh->protect_list
- = tree_cons (NULL_TREE, NULL_TREE, cfun->eh->protect_list);
-}
-
-/* Start a new exception region for a region of code that has a
- cleanup action and push the HANDLER for the region onto
- protect_list. All of the regions created with add_partial_entry
- will be ended when end_protect_partials is invoked.
-
- ??? The only difference between this purpose and that of
- expand_decl_cleanup is that in this case, we only want the cleanup to
- run if an exception is thrown. This should also be handled using
- binding levels. */
-
-void
-add_partial_entry (handler)
- tree handler;
-{
- expand_eh_region_start ();
-
- /* Add this entry to the front of the list. */
- TREE_VALUE (cfun->eh->protect_list)
- = tree_cons (NULL_TREE, handler, TREE_VALUE (cfun->eh->protect_list));
-}
-
-/* End all the pending exception regions on protect_list. */
-
-void
-end_protect_partials ()
-{
- tree t;
-
- /* Pop the topmost entry. */
- t = TREE_VALUE (cfun->eh->protect_list);
- cfun->eh->protect_list = TREE_CHAIN (cfun->eh->protect_list);
-
- /* End all the exception regions. */
- for (; t; t = TREE_CHAIN (t))
- expand_eh_region_end_cleanup (TREE_VALUE (t));
-}
-
-
/* This section is for the exception handling specific optimization pass. */
/* Random access the exception region tree. It's just as simple to
@@ -1130,7 +884,8 @@ collect_eh_region_array ()
if (! i)
return;
- array = xcalloc (cfun->eh->last_region_number + 1, sizeof (*array));
+ array = ggc_alloc_cleared ((cfun->eh->last_region_number + 1)
+ * sizeof (*array));
cfun->eh->region_array = array;
while (1)
@@ -1219,7 +974,7 @@ remove_fixup_regions ()
/* Allow GC to maybe free some memory. */
if (fixup->type == ERT_CLEANUP)
- fixup->u.cleanup.exp = NULL_TREE;
+ fixup->u.cleanup.exp = NULL_TREE;
if (fixup->type != ERT_FIXUP)
continue;
@@ -1275,23 +1030,23 @@ remove_unreachable_regions (insns)
continue;
if (r->resume)
- {
+ {
if (uid_region_num[INSN_UID (r->resume)])
abort ();
uid_region_num[INSN_UID (r->resume)] = i;
- }
+ }
if (r->label)
- {
+ {
if (uid_region_num[INSN_UID (r->label)])
abort ();
uid_region_num[INSN_UID (r->label)] = i;
- }
+ }
if (r->type == ERT_TRY && r->u.try.continue_label)
- {
+ {
if (uid_region_num[INSN_UID (r->u.try.continue_label)])
abort ();
uid_region_num[INSN_UID (r->u.try.continue_label)] = i;
- }
+ }
}
for (insn = insns; insn; insn = NEXT_INSN (insn))
@@ -1431,12 +1186,12 @@ add_ehl_entry (label, region)
LABEL_PRESERVE_P (label) = 1;
- entry = (struct ehl_map_entry *) xmalloc (sizeof (*entry));
+ entry = (struct ehl_map_entry *) ggc_alloc (sizeof (*entry));
entry->label = label;
entry->region = region;
slot = (struct ehl_map_entry **)
- htab_find_slot (exception_handler_label_map, entry, INSERT);
+ htab_find_slot (cfun->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
@@ -1448,29 +1203,20 @@ add_ehl_entry (label, region)
*slot = entry;
}
-static void
-ehl_free (pentry)
- PTR pentry;
-{
- struct ehl_map_entry *entry = (struct ehl_map_entry *)pentry;
- LABEL_PRESERVE_P (entry->label) = 0;
- free (entry);
-}
-
void
find_exception_handler_labels ()
{
int i;
- if (exception_handler_label_map)
- htab_empty (exception_handler_label_map);
+ if (cfun->eh->exception_handler_label_map)
+ htab_empty (cfun->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. */
- exception_handler_label_map
- = htab_create (cfun->eh->last_region_number * 3 / 2,
- ehl_hash, ehl_eq, ehl_free);
+ cfun->eh->exception_handler_label_map
+ = htab_create_ggc (cfun->eh->last_region_number * 3 / 2,
+ ehl_hash, ehl_eq, NULL);
}
if (cfun->eh->region_tree == NULL)
@@ -1522,7 +1268,7 @@ duplicate_eh_region_1 (o, map)
struct inline_remap *map;
{
struct eh_region *n
- = (struct eh_region *) xcalloc (1, sizeof (struct eh_region));
+ = (struct eh_region *) ggc_alloc_cleared (sizeof (struct eh_region));
n->region_number = o->region_number + cfun->eh->last_region_number;
n->type = o->type;
@@ -1583,9 +1329,9 @@ duplicate_eh_region_2 (o, n_array)
case ERT_CATCH:
if (o->u.catch.next_catch)
- n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
+ n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
if (o->u.catch.prev_catch)
- n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
+ n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
break;
default:
@@ -1687,23 +1433,6 @@ t2r_hash (pentry)
return TYPE_HASH (TREE_PURPOSE (entry));
}
-static int
-t2r_mark_1 (slot, data)
- PTR *slot;
- PTR data ATTRIBUTE_UNUSED;
-{
- tree contents = (tree) *slot;
- ggc_mark_tree (contents);
- return 1;
-}
-
-static void
-t2r_mark (addr)
- PTR addr;
-{
- htab_traverse (*(htab_t *)addr, t2r_mark_1, NULL);
-}
-
static void
add_type_for_runtime (type)
tree type;
@@ -1735,7 +1464,7 @@ lookup_type_for_runtime (type)
/* Represent an entry in @TTypes for either catch actions
or exception filter actions. */
-struct ttypes_filter
+struct ttypes_filter GTY(())
{
tree t;
int filter;
@@ -1968,7 +1697,6 @@ build_post_landing_pads ()
struct eh_region *c;
for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
{
- /* ??? _Unwind_ForcedUnwind wants no match here. */
if (c->u.catch.type_list == NULL)
emit_jump (c->label);
else
@@ -2003,7 +1731,7 @@ build_post_landing_pads ()
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->u.try.catch->label);
+ emit_insn_before (seq, region->u.try.catch->label);
break;
case ERT_ALLOWED_EXCEPTIONS:
@@ -2027,7 +1755,7 @@ build_post_landing_pads ()
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->label);
+ emit_insn_before (seq, region->label);
break;
case ERT_CLEANUP:
@@ -2080,11 +1808,11 @@ connect_post_landing_pads ()
emit_jump (outer->post_landing_pad);
else
emit_library_call (unwind_resume_libfunc, LCT_THROW,
- VOIDmode, 1, cfun->eh->exc_ptr, Pmode);
+ VOIDmode, 1, cfun->eh->exc_ptr, ptr_mode);
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->resume);
+ emit_insn_before (seq, region->resume);
delete_insn (region->resume);
}
}
@@ -2153,14 +1881,14 @@ dw2_build_landing_pads ()
}
emit_move_insn (cfun->eh->exc_ptr,
- gen_rtx_REG (Pmode, EH_RETURN_DATA_REGNO (0)));
+ gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
emit_move_insn (cfun->eh->filter,
gen_rtx_REG (word_mode, EH_RETURN_DATA_REGNO (1)));
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->post_landing_pad);
+ emit_insn_before (seq, region->post_landing_pad);
}
}
@@ -2335,7 +2063,7 @@ sjlj_mark_call_sites (lp_info)
/* Don't separate a call from it's argument loads. */
before = insn;
if (GET_CODE (insn) == CALL_INSN)
- before = find_first_parameter_load (insn, NULL_RTX);
+ before = find_first_parameter_load (insn, NULL_RTX);
start_sequence ();
mem = adjust_address (cfun->eh->sjlj_fc, TYPE_MODE (integer_type_node),
@@ -2344,7 +2072,7 @@ sjlj_mark_call_sites (lp_info)
p = get_insns ();
end_sequence ();
- emit_insns_before (p, before);
+ emit_insn_before (p, before);
last_call_site = this_call_site;
}
}
@@ -2372,7 +2100,7 @@ sjlj_emit_function_enter (dispatch_label)
if (cfun->uses_eh_lsda)
{
char buf[20];
- ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", sjlj_funcdef_number);
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", current_function_funcdef_no);
emit_move_insn (mem, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)));
}
else
@@ -2411,7 +2139,7 @@ sjlj_emit_function_enter (dispatch_label)
if (GET_CODE (fn_begin) == NOTE
&& NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
break;
- emit_insns_after (seq, fn_begin);
+ emit_insn_after (seq, fn_begin);
}
/* Call back from expand_function_end to know where we should put
@@ -2441,7 +2169,7 @@ sjlj_emit_function_exit ()
post-dominates all can_throw_internal instructions. This is
the last possible moment. */
- emit_insns_after (seq, cfun->eh->sjlj_exit_after);
+ emit_insn_after (seq, cfun->eh->sjlj_exit_after);
}
static void
@@ -2505,8 +2233,8 @@ sjlj_emit_dispatch_table (dispatch_label, lp_info)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, (cfun->eh->region_array[first_reachable]
- ->post_landing_pad));
+ emit_insn_before (seq, (cfun->eh->region_array[first_reachable]
+ ->post_landing_pad));
}
static void
@@ -2553,9 +2281,7 @@ finish_eh_generation ()
connect many of the handlers, and then type information will not
be effective. Still, this is a win over previous implementations. */
- rebuild_jump_labels (get_insns ());
- find_basic_blocks (get_insns (), max_reg_num (), 0);
- cleanup_cfg (CLEANUP_PRE_LOOP);
+ cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
/* These registers are used by the landing pads. Make sure they
have been generated. */
@@ -2578,7 +2304,7 @@ finish_eh_generation ()
find_exception_handler_labels ();
rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0);
- cleanup_cfg (CLEANUP_PRE_LOOP);
+ cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
}
static hashval_t
@@ -2615,16 +2341,16 @@ remove_exception_handler_label (label)
/* If exception_handler_label_map was not built yet,
there is nothing to do. */
- if (exception_handler_label_map == NULL)
+ if (cfun->eh->exception_handler_label_map == NULL)
return;
tmp.label = label;
slot = (struct ehl_map_entry **)
- htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
+ htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
if (! slot)
abort ();
- htab_clear_slot (exception_handler_label_map, (void **) slot);
+ htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
}
/* Splice REGION from the region tree etc. */
@@ -2654,7 +2380,7 @@ remove_eh_handler (region)
if (outer)
{
if (!outer->aka)
- outer->aka = BITMAP_XMALLOC ();
+ outer->aka = BITMAP_GGC_ALLOC ();
if (region->aka)
bitmap_a_or_b (outer->aka, outer->aka, region->aka);
bitmap_set_bit (outer->aka, region->region_number);
@@ -2713,8 +2439,6 @@ remove_eh_handler (region)
remove_eh_handler (try);
}
}
-
- free_region (region);
}
/* LABEL heads a basic block that is about to be deleted. If this
@@ -2737,7 +2461,7 @@ maybe_remove_eh_handler (label)
tmp.label = label;
slot = (struct ehl_map_entry **)
- htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
+ htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
if (! slot)
return;
region = (*slot)->region;
@@ -2750,7 +2474,7 @@ maybe_remove_eh_handler (label)
are no more contained calls, which we don't see here. */
if (region->type == ERT_MUST_NOT_THROW)
{
- htab_clear_slot (exception_handler_label_map, (void **) slot);
+ htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
region->label = NULL_RTX;
}
else
@@ -2764,7 +2488,7 @@ void
for_each_eh_label (callback)
void (*callback) PARAMS ((rtx));
{
- htab_traverse (exception_handler_label_map, for_each_eh_label_1,
+ htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1,
(void *)callback);
}
@@ -2783,7 +2507,7 @@ for_each_eh_label_1 (pentry, data)
/* This section describes CFG exception edges for flow. */
/* For communicating between calls to reachable_next_level. */
-struct reachable_info
+struct reachable_info GTY(())
{
tree types_caught;
tree types_allowed;
@@ -2870,8 +2594,6 @@ reachable_next_level (region, type_thrown, info)
for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
{
/* A catch-all handler ends the search. */
- /* ??? _Unwind_ForcedUnwind will want outer cleanups
- to be run as well. */
if (c->u.catch.type_list == NULL)
{
add_reachable_handler (info, region, c);
@@ -2995,7 +2717,7 @@ reachable_next_level (region, type_thrown, info)
if (info && info->handlers)
{
add_reachable_handler (info, region, region);
- return RNL_CAUGHT;
+ return RNL_CAUGHT;
}
else
return RNL_BLOCKED;
@@ -3053,10 +2775,20 @@ reachable_handlers (insn)
region = region->outer;
}
- for (; region; region = region->outer)
- if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
- break;
-
+ while (region)
+ {
+ if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
+ break;
+ /* If we have processed one cleanup, there is no point in
+ processing any more of them. Each cleanup will have an edge
+ to the next outer cleanup region, so the flow graph will be
+ accurate. */
+ if (region->type == ERT_CLEANUP)
+ region = region->u.cleanup.prev_try;
+ else
+ region = region->outer;
+ }
+
return info.handlers;
}
@@ -3115,7 +2847,7 @@ can_throw_internal (insn)
if (how == RNL_BLOCKED)
return false;
if (how != RNL_NOT_CAUGHT)
- return true;
+ return true;
}
return false;
@@ -3186,25 +2918,50 @@ can_throw_external (insn)
return true;
}
-/* True if nothing in this function can throw outside this function. */
+/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */
-bool
-nothrow_function_p ()
+void
+set_nothrow_function_flags ()
{
rtx insn;
+
+ current_function_nothrow = 1;
- if (! flag_exceptions)
- return true;
+ /* Assume cfun->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;
+
+ if (! flag_exceptions)
+ return;
+
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (can_throw_external (insn))
- return false;
+ {
+ current_function_nothrow = 0;
+
+ if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
+ {
+ cfun->all_throwers_are_sibcalls = 0;
+ return;
+ }
+ }
+
for (insn = current_function_epilogue_delay_list; insn;
insn = XEXP (insn, 1))
if (can_throw_external (insn))
- return false;
+ {
+ current_function_nothrow = 0;
- return true;
+ if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
+ {
+ cfun->all_throwers_are_sibcalls = 0;
+ return;
+ }
+ }
}
@@ -3261,6 +3018,16 @@ expand_builtin_extract_return_addr (addr_tree)
{
rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
+ if (GET_MODE (addr) != Pmode
+ && GET_MODE (addr) != VOIDmode)
+ {
+#ifdef POINTERS_EXTEND_UNSIGNED
+ addr = convert_memory_address (Pmode, addr);
+#else
+ addr = convert_to_mode (Pmode, addr, 0);
+#endif
+ }
+
/* First mask out any unwanted bits. */
#ifdef MASK_RETURN_ADDR
expand_and (Pmode, addr, MASK_RETURN_ADDR, addr);
@@ -3302,77 +3069,73 @@ expand_builtin_frob_return_addr (addr_tree)
void
expand_builtin_eh_return (stackadj_tree, handler_tree)
- tree stackadj_tree, handler_tree;
+ tree stackadj_tree ATTRIBUTE_UNUSED;
+ tree handler_tree;
{
- rtx stackadj, handler;
-
- stackadj = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
- handler = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
+ rtx tmp;
+#ifdef EH_RETURN_STACKADJ_RTX
+ tmp = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (stackadj) != Pmode)
- stackadj = convert_memory_address (Pmode, stackadj);
-
- if (GET_MODE (handler) != Pmode)
- handler = convert_memory_address (Pmode, handler);
+ if (GET_MODE (tmp) != Pmode)
+ tmp = convert_memory_address (Pmode, tmp);
+#endif
+ 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);
#endif
- if (! cfun->eh->ehr_label)
- {
- cfun->eh->ehr_stackadj = copy_to_reg (stackadj);
- cfun->eh->ehr_handler = copy_to_reg (handler);
- cfun->eh->ehr_label = gen_label_rtx ();
- }
- else
- {
- if (stackadj != cfun->eh->ehr_stackadj)
- emit_move_insn (cfun->eh->ehr_stackadj, stackadj);
- if (handler != cfun->eh->ehr_handler)
- emit_move_insn (cfun->eh->ehr_handler, handler);
- }
+ tmp = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (tmp) != Pmode)
+ tmp = convert_memory_address (Pmode, tmp);
+#endif
+ 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 (!cfun->eh->ehr_label)
+ cfun->eh->ehr_label = gen_label_rtx ();
emit_jump (cfun->eh->ehr_label);
}
void
expand_eh_return ()
{
- rtx sa, ra, around_label;
+ rtx around_label;
if (! cfun->eh->ehr_label)
return;
- sa = EH_RETURN_STACKADJ_RTX;
- if (! sa)
- {
- error ("__builtin_eh_return not supported on this target");
- return;
- }
-
current_function_calls_eh_return = 1;
+#ifdef EH_RETURN_STACKADJ_RTX
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
+#endif
+
around_label = gen_label_rtx ();
- emit_move_insn (sa, const0_rtx);
emit_jump (around_label);
emit_label (cfun->eh->ehr_label);
clobber_return_register ();
+#ifdef EH_RETURN_STACKADJ_RTX
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, cfun->eh->ehr_stackadj);
+#endif
+
#ifdef HAVE_eh_return
if (HAVE_eh_return)
- emit_insn (gen_eh_return (cfun->eh->ehr_stackadj, cfun->eh->ehr_handler));
+ emit_insn (gen_eh_return (cfun->eh->ehr_handler));
else
#endif
{
- ra = EH_RETURN_HANDLER_RTX;
- if (! ra)
- {
- error ("__builtin_eh_return not supported on this target");
- ra = gen_reg_rtx (Pmode);
- }
-
- emit_move_insn (sa, cfun->eh->ehr_stackadj);
- emit_move_insn (ra, cfun->eh->ehr_handler);
+#ifdef EH_RETURN_HANDLER_RTX
+ emit_move_insn (EH_RETURN_HANDLER_RTX, cfun->eh->ehr_handler);
+#else
+ error ("__builtin_eh_return not supported on this target");
+#endif
}
emit_label (around_label);
@@ -3563,7 +3326,7 @@ add_call_site (landing_pad, action)
{
size = (size ? size * 2 : 64);
data = (struct call_site_record *)
- xrealloc (data, sizeof (*data) * size);
+ ggc_realloc (data, sizeof (*data) * size);
cfun->eh->call_site_data = data;
cfun->eh->call_site_data_size = size;
}
@@ -3847,6 +3610,33 @@ sjlj_output_call_site_table ()
call_site_base += n;
}
+/* Tell assembler to switch to the section for the exception handling
+ table. */
+
+void
+default_exception_section ()
+{
+ if (targetm.have_named_sections)
+ {
+ int flags;
+#ifdef HAVE_LD_RO_RW_SECTION_MIXING
+ int tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
+
+ flags = (! flag_pic
+ || ((tt_format & 0x70) != DW_EH_PE_absptr
+ && (tt_format & 0x70) != DW_EH_PE_aligned))
+ ? 0 : SECTION_WRITE;
+#else
+ flags = SECTION_WRITE;
+#endif
+ named_section_flags (".gcc_except_table", flags);
+ }
+ else if (flag_pic)
+ data_section ();
+ else
+ readonly_data_section ();
+}
+
void
output_function_exception_table ()
{
@@ -3859,17 +3649,12 @@ output_function_exception_table ()
int call_site_len;
#endif
int have_tt_data;
- int funcdef_number;
int tt_format_size = 0;
/* Not all functions need anything. */
if (! cfun->uses_eh_lsda)
return;
- funcdef_number = (USING_SJLJ_EXCEPTIONS
- ? sjlj_funcdef_number
- : current_funcdef_number);
-
#ifdef IA64_UNWIND_INFO
fputs ("\t.personality\t", asm_out_file);
output_addr_const (asm_out_file, eh_personality_libfunc);
@@ -3890,14 +3675,16 @@ output_function_exception_table ()
{
tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
#ifdef HAVE_AS_LEB128
- ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT", funcdef_number);
+ ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT",
+ current_function_funcdef_no);
#endif
tt_format_size = size_of_encoded_value (tt_format);
assemble_align (tt_format_size * BITS_PER_UNIT);
}
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA", funcdef_number);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA",
+ current_function_funcdef_no);
/* The LSDA header. */
@@ -3929,7 +3716,7 @@ output_function_exception_table ()
#ifdef HAVE_AS_LEB128
char ttype_after_disp_label[32];
ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label, "LLSDATTD",
- funcdef_number);
+ current_function_funcdef_no);
dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
"@TType base offset");
ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
@@ -3975,9 +3762,9 @@ output_function_exception_table ()
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
- funcdef_number);
+ current_function_funcdef_no);
ASM_GENERATE_INTERNAL_LABEL (cs_end_label, "LLSDACSE",
- funcdef_number);
+ current_function_funcdef_no);
dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
"Call-site table length");
ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
@@ -4019,7 +3806,7 @@ output_function_exception_table ()
assemble_integer (value, tt_format_size,
tt_format_size * BITS_PER_UNIT, 1);
else
- dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
+ dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
}
#ifdef HAVE_AS_LEB128
@@ -4034,7 +3821,6 @@ output_function_exception_table ()
(i ? NULL : "Exception specification table"));
function_section (current_function_decl);
-
- if (USING_SJLJ_EXCEPTIONS)
- sjlj_funcdef_number += 1;
}
+
+#include "gt-except.h"
OpenPOWER on IntegriCloud