diff mbox

Handle weakrefs from callgraph

Message ID 20111021110608.GC5543@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Oct. 21, 2011, 11:06 a.m. UTC
Hi,
this patch makes weakref that has no declaration they alias to to go the callgraph
way instead of alias pair way.  This should make practically all sane aliases go
the callgraph way, but we still do not handle aliases from functions to variables
and vice versa.

They are not too hard to represent in callgraph+varpool but they complicate
handling of them.  I would think in favour of making them unsupported, but if neccesary,
I can add support for them.

Bootstrapped/regtested x86_64-linux, comitted.
Honza

	* cgraph.c (dump_cgraph_node): Dump alias flag.
	* cgraphunit.c (handle_alias_pairs): Handle weakrefs with no destination.
	(get_alias_symbol): New function.
	(output_weakrefs): Output also weakrefs with no destinatoin.
	(lto_output_node): Output weakref alias flag when at function boundary.
diff mbox

Patch

Index: cgraph.c
===================================================================
--- cgraph.c	(revision 180181)
+++ cgraph.c	(working copy)
@@ -1838,6 +1838,8 @@  dump_cgraph_node (FILE *f, struct cgraph
     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");
 
   fprintf (f, "\n");
 
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 180181)
+++ cgraphunit.c	(working copy)
@@ -1249,6 +1249,18 @@  handle_alias_pairs (void)
 	  varpool_create_variable_alias (p->decl, target_vnode->decl);
 	  VEC_unordered_remove (alias_pair, alias_pairs, i);
 	}
+      /* Weakrefs with target not defined in current unit are easy to handle; they
+	 behave just as external variables except we need to note the alias flag
+	 to later output the weakref pseudo op into asm file.  */
+      else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL)
+	{
+	  if (TREE_CODE (p->decl) == FUNCTION_DECL)
+	    cgraph_get_create_node (p->decl)->alias = true;
+	  else
+	    varpool_get_node (p->decl)->alias = true;
+	  DECL_EXTERNAL (p->decl) = 1;
+	  VEC_unordered_remove (alias_pair, alias_pairs, i);
+	}
       else
 	{
 	  if (dump_file)
@@ -2064,24 +2078,36 @@  ipa_passes (void)
   bitmap_obstack_release (NULL);
 }
 
+/* Return string alias is alias of.  */
+
+static tree
+get_alias_symbol (tree decl)
+{
+  tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
+  return get_identifier (TREE_STRING_POINTER
+			  (TREE_VALUE (TREE_VALUE (alias))));
+}
+
 /* Weakrefs may be associated to external decls and thus not output
    at expansion time.  Emit all neccesary aliases.  */
 
-void
+static void
 output_weakrefs (void)
 {
   struct cgraph_node *node;
   struct varpool_node *vnode;
   for (node = cgraph_nodes; node; node = node->next)
-    if (node->alias && node->thunk.alias && DECL_EXTERNAL (node->decl)
+    if (node->alias && DECL_EXTERNAL (node->decl)
         && !TREE_ASM_WRITTEN (node->decl))
       assemble_alias (node->decl,
-		      DECL_ASSEMBLER_NAME (node->thunk.alias));
+		      node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
+		      : get_alias_symbol (node->decl));
   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
-    if (vnode->alias && vnode->alias_of && DECL_EXTERNAL (vnode->decl)
+    if (vnode->alias && DECL_EXTERNAL (vnode->decl)
         && !TREE_ASM_WRITTEN (vnode->decl))
       assemble_alias (vnode->decl,
-		      DECL_ASSEMBLER_NAME (vnode->alias_of));
+		      vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
+		      : get_alias_symbol (vnode->decl));
 }
 
 
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 180181)
+++ lto-cgraph.c	(working copy)
@@ -512,7 +512,13 @@  lto_output_node (struct lto_simple_outpu
 		     || referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
   bp_pack_value (&bp, node->lowered, 1);
   bp_pack_value (&bp, in_other_partition, 1);
-  bp_pack_value (&bp, node->alias && !boundary_p, 1);
+  /* Real aliases in a boundary become non-aliases. However we still stream
+     alias info on weakrefs. 
+     TODO: We lose a bit of information here - when we know that variable is
+     defined in other unit, we may use the info on aliases to resolve 
+     symbol1 != symbol2 type tests that we can do only for locally defined objects
+     otherwise.  */
+  bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->decl)), 1);
   bp_pack_value (&bp, node->frequency, 2);
   bp_pack_value (&bp, node->only_called_at_startup, 1);
   bp_pack_value (&bp, node->only_called_at_exit, 1);
@@ -530,7 +536,8 @@  lto_output_node (struct lto_simple_outpu
       streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
       streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
     }
-  if ((node->alias || node->thunk.thunk_p) && !boundary_p)
+  if ((node->alias || node->thunk.thunk_p)
+      && (!boundary_p || (node->alias && DECL_EXTERNAL (node->decl))))
     {
       streamer_write_hwi_in_range (ob->main_stream, 0, 1,
 					node->thunk.alias != NULL);