summaryrefslogtreecommitdiff
path: root/gcc/cgraph.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r--gcc/cgraph.c107
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"