OSDN Git Service

* lto-symtab.c (lto_cgraph_replace_node): Handle aliases.
[pf3gnuchains/gcc-fork.git] / gcc / lto-symtab.c
index e94bc20..9985745 100644 (file)
@@ -206,6 +206,24 @@ lto_cgraph_replace_node (struct cgraph_node *node,
                         struct cgraph_node *prevailing_node)
 {
   struct cgraph_edge *e, *next;
+  bool no_aliases_please = false;
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i"
+              " for symbol %s\n",
+              cgraph_node_name (node), node->uid,
+              cgraph_node_name (prevailing_node),
+              prevailing_node->uid,
+              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
+    }
+
+  if (prevailing_node->same_body_alias)
+    {
+      if (prevailing_node->thunk.thunk_p)
+       no_aliases_please = true;
+      prevailing_node = prevailing_node->same_body;
+    }
 
   /* Merge node flags.  */
   if (node->needed)
@@ -227,27 +245,37 @@ lto_cgraph_replace_node (struct cgraph_node *node,
   /* Redirect incomming references.  */
   ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
 
-  if (node->same_body)
+  /* If we have aliases, redirect them to the prevailing node.  */
+  if (!node->same_body_alias && node->same_body)
     {
-      struct cgraph_node *alias;
+      struct cgraph_node *alias, *last;
+      /* We prevail aliases/tunks by a thunk.  This is doable but
+         would need thunk combination.  Hopefully no ABI changes will
+         every be crazy enough.  */
+      gcc_assert (!no_aliases_please);
 
       for (alias = node->same_body; alias; alias = alias->next)
-       if (DECL_ASSEMBLER_NAME_SET_P (alias->decl))
-         {
-           lto_symtab_entry_t se
-             = lto_symtab_get (DECL_ASSEMBLER_NAME (alias->decl));
-
-           for (; se; se = se->next)
-             if (se->node == node)
-               {
-                 se->node = NULL;
-                 break;
-               }
-         }
+       {
+         last = alias;
+         gcc_assert (alias->same_body_alias);
+         alias->same_body = prevailing_node;
+         alias->thunk.alias = prevailing_node->decl;
+       }
+      last->next = prevailing_node->same_body;
+      /* Node with aliases is prevailed by alias.
+        We could handle this, but combining thunks together will be tricky.
+        Hopefully this does not happen.  */
+      if (prevailing_node->same_body)
+       prevailing_node->same_body->previous = last;
+      prevailing_node->same_body = node->same_body;
+      node->same_body = NULL;
     }
 
   /* Finally remove the replaced node.  */
-  cgraph_remove_node (node);
+  if (node->same_body_alias)
+    cgraph_remove_same_body_alias (node);
+  else
+    cgraph_remove_node (node);
 }
 
 /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
@@ -433,7 +461,9 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
 
   /* For functions we need a non-discarded body.  */
   if (TREE_CODE (e->decl) == FUNCTION_DECL)
-    return (e->node && e->node->analyzed);
+    return (e->node
+           && (e->node->analyzed
+               || (e->node->same_body_alias && e->node->same_body->analyzed)));
 
   /* A variable should have a size.  */
   else if (TREE_CODE (e->decl) == VAR_DECL)
@@ -461,7 +491,7 @@ lto_symtab_resolve_symbols (void **slot)
   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
     {
       if (TREE_CODE (e->decl) == FUNCTION_DECL)
-       e->node = cgraph_get_node (e->decl);
+       e->node = cgraph_get_node_or_alias (e->decl);
       else if (TREE_CODE (e->decl) == VAR_DECL)
        {
          e->vnode = varpool_get_node (e->decl);
@@ -751,22 +781,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
   for (e = prevailing->next; e; e = e->next)
     {
       if (e->node != NULL)
-       {
-         if (e->node->decl != e->decl && e->node->same_body)
-           {
-             struct cgraph_node *alias;
-
-             for (alias = e->node->same_body; alias; alias = alias->next)
-               if (alias->decl == e->decl)
-                 break;
-             if (alias)
-               {
-                 cgraph_remove_same_body_alias (alias);
-                 continue;
-               }
-           }
-         lto_cgraph_replace_node (e->node, prevailing->node);
-       }
+       lto_cgraph_replace_node (e->node, prevailing->node);
       if (e->vnode != NULL)
        lto_varpool_replace_node (e->vnode, prevailing->vnode);
     }