diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 43bb8376d5b..5e7c6de39fb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2010-05-10 Jan Hubicka + + * Makefile.in (cgraphbuild.o): Add dependency on except.h. + * cgraphbuild.c: Include except.h + (record_type_list, record_eh_tables): New function. + (build_cgraph_edges, rebuild_cgraph_edges): Use it. + 2010-05-10 Jan Hubicka * crtstuff.c (force_to_data, __do_global_dtors_aux_fini_array_entry, diff --git a/gcc/Makefile.in b/gcc/Makefile.in index f19def73519..d919261f59a 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2892,7 +2892,7 @@ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ gt-cgraphunit.h tree-iterator.h $(COVERAGE_H) $(TREE_DUMP_H) cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \ - $(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) + $(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_H) $(HASHTAB_H) \ $(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \ diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index ec190c7211c..246be20df2e 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "tree-pass.h" #include "ipa-utils.h" +#include "except.h" /* Context of record_reference. */ struct record_reference_ctx @@ -105,6 +106,86 @@ record_reference (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } +/* Record references to typeinfos in the type list LIST. */ + +static void +record_type_list (struct cgraph_node *node, tree list) +{ + for (; list; list = TREE_CHAIN (list)) + { + tree type = TREE_VALUE (list); + + if (TYPE_P (type)) + type = lookup_type_for_runtime (type); + STRIP_NOPS (type); + if (TREE_CODE (type) == ADDR_EXPR) + { + type = TREE_OPERAND (type, 0); + if (TREE_CODE (type) == VAR_DECL) + { + struct varpool_node *vnode = varpool_node (type); + varpool_mark_needed_node (vnode); + ipa_record_reference (node, NULL, + NULL, vnode, + IPA_REF_ADDR, NULL); + } + } + } +} + +/* Record all references we will introduce by producing EH tables + for NODE. */ + +static void +record_eh_tables (struct cgraph_node *node, struct function *fun) +{ + eh_region i; + + i = fun->eh->region_tree; + if (!i) + return; + + while (1) + { + switch (i->type) + { + case ERT_CLEANUP: + case ERT_MUST_NOT_THROW: + break; + + case ERT_TRY: + { + eh_catch c; + for (c = i->u.eh_try.first_catch; c; c = c->next_catch) + record_type_list (node, c->type_list); + } + break; + + case ERT_ALLOWED_EXCEPTIONS: + record_type_list (node, i->u.allowed.type_list); + break; + } + /* If there are sub-regions, process them. */ + if (i->inner) + i = i->inner; + /* If there are peers, process them. */ + else if (i->next_peer) + i = i->next_peer; + /* Otherwise, step back up the tree to the next peer. */ + else + { + do + { + i = i->outer; + if (i == NULL) + return; + } + while (i->next_peer == NULL); + i = i->next_peer; + } + } +} + /* Reset inlining information of all incoming call edges of NODE. */ void @@ -297,6 +378,7 @@ build_cgraph_edges (void) && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))) varpool_finalize_decl (decl); } + record_eh_tables (node, cfun); pointer_set_destroy (visited_nodes); return 0; @@ -375,6 +457,7 @@ rebuild_cgraph_edges (void) walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node, mark_load, mark_store, mark_address); } + record_eh_tables (node, cfun); gcc_assert (!node->global.inlined_to); return 0;