diff options
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 107 |
1 files changed, 69 insertions, 38 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 2a2973bc6e4..7bcff203379 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -129,7 +129,7 @@ static GTY(()) struct cgraph_node *free_nodes; static GTY(()) struct cgraph_edge *free_edges; /* Did procss_same_body_aliases run? */ -bool same_body_aliases_done; +bool cpp_implicit_aliases_done; /* Map a cgraph_node to cgraph_function_version_info using this htab. The cgraph_function_version_info has a THIS_NODE field that is the @@ -556,17 +556,18 @@ cgraph_get_create_node (tree decl) the function body is associated with (not necessarily cgraph_node (DECL). */ struct cgraph_node * -cgraph_create_function_alias (tree alias, tree decl) +cgraph_create_function_alias (tree alias, tree target) { struct cgraph_node *alias_node; - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + gcc_assert (TREE_CODE (target) == FUNCTION_DECL + || TREE_CODE (target) == IDENTIFIER_NODE); gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); alias_node = cgraph_get_create_node (alias); - gcc_assert (!alias_node->local.finalized); - alias_node->thunk.alias = decl; - alias_node->local.finalized = true; - alias_node->alias = 1; + gcc_assert (!alias_node->symbol.definition); + alias_node->symbol.alias_target = target; + alias_node->symbol.definition = true; + alias_node->symbol.alias = true; return alias_node; } @@ -589,10 +590,10 @@ cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree ali return NULL; n = cgraph_create_function_alias (alias, decl); - n->same_body_alias = true; - if (same_body_aliases_done) - ipa_record_reference ((symtab_node)n, (symtab_node)cgraph_get_node (decl), - IPA_REF_ALIAS, NULL); + n->symbol.cpp_implicit_alias = true; + if (cpp_implicit_aliases_done) + symtab_resolve_alias ((symtab_node)n, + (symtab_node)cgraph_get_node (decl)); return n; } @@ -613,8 +614,8 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, node = cgraph_get_node (alias); if (node) { - gcc_assert (node->local.finalized); - gcc_assert (!node->alias); + gcc_assert (node->symbol.definition); + gcc_assert (!node->symbol.alias); gcc_assert (!node->thunk.thunk_p); cgraph_remove_node (node); } @@ -629,7 +630,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, node->thunk.virtual_offset_p = virtual_offset != NULL; node->thunk.alias = real_alias; node->thunk.thunk_p = true; - node->local.finalized = true; + node->symbol.definition = true; return node; } @@ -1325,6 +1326,7 @@ cgraph_remove_node (struct cgraph_node *node) /* Incremental inlining access removed nodes stored in the postorder list. */ node->symbol.force_output = false; + node->symbol.forced_by_abi = false; for (n = node->nested; n; n = n->next_nested) n->origin = NULL; node->nested = NULL; @@ -1384,7 +1386,7 @@ cgraph_remove_node (struct cgraph_node *node) && (cgraph_global_info_ready && (TREE_ASM_WRITTEN (n->symbol.decl) || DECL_EXTERNAL (n->symbol.decl) - || !n->analyzed + || !n->symbol.analyzed || n->symbol.in_other_partition)))) cgraph_release_function_body (node); @@ -1521,8 +1523,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) cgraph_availability_names [cgraph_function_body_availability (node)]); fprintf (f, " Function flags:"); - if (node->analyzed) - fprintf (f, " analyzed"); if (node->count) fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x", (HOST_WIDEST_INT)node->count); @@ -1534,16 +1534,12 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) fprintf (f, " process"); if (node->local.local) fprintf (f, " local"); - if (node->local.finalized) - fprintf (f, " finalized"); if (node->local.redefined_extern_inline) fprintf (f, " redefined_extern_inline"); if (node->only_called_at_startup) fprintf (f, " only_called_at_startup"); if (node->only_called_at_exit) fprintf (f, " only_called_at_exit"); - else if (node->alias) - fprintf (f, " alias"); if (node->tm_clone) fprintf (f, " tm_clone"); @@ -1551,15 +1547,19 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) if (node->thunk.thunk_p) { - fprintf (f, " Thunk of %s (asm: %s) fixed offset %i virtual value %i has " + fprintf (f, " Thunk"); + if (node->thunk.alias) + fprintf (f, " of %s (asm: %s)", + lang_hooks.decl_printable_name (node->thunk.alias, 2), + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias))); + fprintf (f, " fixed offset %i virtual value %i has " "virtual offset %i)\n", - lang_hooks.decl_printable_name (node->thunk.alias, 2), - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias)), (int)node->thunk.fixed_offset, (int)node->thunk.virtual_value, (int)node->thunk.virtual_offset_p); } - if (node->alias && node->thunk.alias && DECL_P (node->thunk.alias)) + if (node->symbol.alias && node->thunk.alias + && DECL_P (node->thunk.alias)) { fprintf (f, " Alias of %s", lang_hooks.decl_printable_name (node->thunk.alias, 2)); @@ -1676,7 +1676,7 @@ cgraph_function_body_availability (struct cgraph_node *node) { enum availability avail; gcc_assert (cgraph_function_flags_ready); - if (!node->analyzed) + if (!node->symbol.analyzed) avail = AVAIL_NOT_AVAILABLE; else if (node->local.local) avail = AVAIL_LOCAL; @@ -1713,6 +1713,8 @@ cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node, { return !(!node->symbol.force_output && ((DECL_COMDAT (node->symbol.decl) + && !node->symbol.forced_by_abi + && !symtab_used_from_object_file_p ((symtab_node) node) && !node->symbol.same_comdat_group) || !node->symbol.externally_visible)); } @@ -1805,6 +1807,7 @@ cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) symtab_make_decl_local (node->symbol.decl); node->symbol.externally_visible = false; + node->symbol.forced_by_abi = false; node->local.local = true; node->symbol.unique_name = (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); @@ -1983,7 +1986,7 @@ cgraph_propagate_frequency (struct cgraph_node *node) if (!node->local.local) return false; - gcc_assert (node->analyzed); + gcc_assert (node->symbol.analyzed); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node)); @@ -2086,6 +2089,7 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) /* Only COMDAT functions can be removed if externally visible. */ if (node->symbol.externally_visible && (!DECL_COMDAT (node->symbol.decl) + || node->symbol.forced_by_abi || symtab_used_from_object_file_p ((symtab_node) node))) return false; return true; @@ -2293,17 +2297,11 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl) return false; node = cgraph_function_or_thunk_node (node, NULL); - if ((e->callee->former_clone_of != node->symbol.decl - && (!node->same_body_alias - || e->callee->former_clone_of != node->thunk.alias)) + if (e->callee->former_clone_of != node->symbol.decl /* IPA-CP sometimes redirect edge to clone and then back to the former function. This ping-pong has to go, eventually. */ && (node != cgraph_function_or_thunk_node (e->callee, NULL)) - && !clone_of_p (node, e->callee) - /* If decl is a same body alias of some other decl, allow e->callee to be - a clone of a clone of that other decl too. */ - && (!node->same_body_alias - || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee))) + && !clone_of_p (cgraph_function_or_thunk_node (node, NULL), e->callee)) return true; else return false; @@ -2342,6 +2340,11 @@ verify_cgraph_node (struct cgraph_node *node) error ("inline clone in same comdat group list"); error_found = true; } + if (!node->symbol.definition && node->local.local) + { + error ("local symbols must be defined"); + error_found = true; + } if (node->global.inlined_to && node->symbol.externally_visible) { error ("externally visible inline clone"); @@ -2455,7 +2458,7 @@ verify_cgraph_node (struct cgraph_node *node) error_found = true; } - if (node->analyzed && node->alias) + if (node->symbol.analyzed && node->symbol.alias) { bool ref_found = false; int i; @@ -2486,7 +2489,7 @@ verify_cgraph_node (struct cgraph_node *node) error_found = true; } } - if (node->analyzed && node->thunk.thunk_p) + if (node->symbol.analyzed && node->thunk.thunk_p) { if (!node->callees) { @@ -2504,7 +2507,7 @@ verify_cgraph_node (struct cgraph_node *node) error_found = true; } } - else if (node->analyzed && gimple_has_body_p (node->symbol.decl) + else if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl) && !TREE_ASM_WRITTEN (node->symbol.decl) && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to) && !flag_wpa) @@ -2653,4 +2656,32 @@ cgraph_get_create_real_symbol_node (tree decl) node->symbol.order); return node; } + + +/* Given NODE, walk the alias chain to return the function NODE is alias of. + Walk through thunk, too. + When AVAILABILITY is non-NULL, get minimal availability in the chain. */ + +struct cgraph_node * +cgraph_function_node (struct cgraph_node *node, enum availability *availability) +{ + do + { + node = cgraph_function_or_thunk_node (node, availability); + if (node->thunk.thunk_p) + { + node = node->callees->callee; + if (availability) + { + enum availability a; + a = cgraph_function_body_availability (node); + if (a < *availability) + *availability = a; + } + node = cgraph_function_or_thunk_node (node, availability); + } + } while (node && node->thunk.thunk_p); + return node; +} + #include "gt-cgraph.h" |