From 64cfa6c0dbf18985f4fcf2598cbd2a009c55a6a2 Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Thu, 9 May 2013 17:37:12 +0200
Subject: Jan Hubicka  <jh@suse.cz> 	Richard Biener  <rguenther@suse.de>

	PR lto/54095
	* symtab.c (symtab_make_decl_local): Do not add private names.

	* lto.c (lto_register_var_decl_in_symtab): Don't do renaming.
	(lto_register_var_decl_in_symtab): Likewise.
	(lto_main): Promote statics.
	* lto-partition.c (privatize_symbol_name): New function.
	(promote_symbol): Use it.
	(may_need_named_section_p): New predicate.
	(rename_statics): New functions.
	(lto_promote_cross_file_statics): Simplify; do renaming.
	(lto_promote_statics_nonwpa): New function.
	* lto-partition.h (lto_promote_statics_nonwpa): New function.

Co-Authored-By: Richard Biener <rguenther@suse.de>

From-SVN: r198741
---
 gcc/lto/ChangeLog       |  14 +++++
 gcc/lto/lto-partition.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/lto/lto-partition.h |   1 +
 gcc/lto/lto.c           |  54 +----------------
 4 files changed, 166 insertions(+), 55 deletions(-)

(limited to 'gcc/lto')

diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index e3530da..8732069 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,17 @@
+2013-05-09  Jan Hubicka  <jh@suse.cz>
+	    Richard Biener  <rguenther@suse.de>
+
+	* lto.c (lto_register_var_decl_in_symtab): Don't do renaming.
+	(lto_register_var_decl_in_symtab): Likewise.
+	(lto_main): Promote statics.
+	* lto-partition.c (privatize_symbol_name): New function.
+	(promote_symbol): Use it.
+	(may_need_named_section_p): New predicate.
+	(rename_statics): New functions.
+	(lto_promote_cross_file_statics): Simplify; do renaming.
+	(lto_promote_statics_nonwpa): New function.
+	* lto-partition.h (lto_promote_statics_nonwpa): New function.
+
 2013-02-08  Richard Biener  <rguenther@suse.de>
 
 	PR lto/56231
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 833d926..652272a 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -755,6 +755,56 @@ lto_balanced_map (void)
   free (order);
 }
 
+/* Mangle NODE symbol name into a local name.  
+   This is necessary to do
+   1) if two or more static vars of same assembler name
+      are merged into single ltrans unit.
+   2) if prevoiusly static var was promoted hidden to avoid possible conflict
+      with symbols defined out of the LTO world.
+*/
+
+static void
+privatize_symbol_name (symtab_node node)
+{
+  tree decl = node->symbol.decl;
+  const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  char *label;
+
+  /* Our renaming machinery do not handle more than one change of assembler name.
+     We should not need more than one anyway.  */
+  if (node->symbol.lto_file_data
+      && lto_get_decl_name_mapping (node->symbol.lto_file_data, name) != name)
+    {
+      if (cgraph_dump_file)
+	fprintf (cgraph_dump_file,
+		"Not privatizing symbol name: %s. It privatized already.\n",
+		name);
+      return;
+    }
+  /* Avoid mangling of already mangled clones. 
+     ???  should have a flag whether a symbol has a 'private' name already,
+     since we produce some symbols like that i.e. for global constructors
+     that are not really clones.  */
+  if (node->symbol.unique_name)
+    {
+      if (cgraph_dump_file)
+	fprintf (cgraph_dump_file,
+		"Not privatizing symbol name: %s. Has unique name.\n",
+		name);
+      return;
+    }
+  ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
+  change_decl_assembler_name (decl, clone_function_name (decl, "lto_priv"));
+  if (node->symbol.lto_file_data)
+    lto_record_renamed_decl (node->symbol.lto_file_data, name,
+			     IDENTIFIER_POINTER
+			     (DECL_ASSEMBLER_NAME (decl)));
+  if (cgraph_dump_file)
+    fprintf (cgraph_dump_file,
+	    "Privatizing symbol name: %s -> %s\n",
+	    name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+}
+
 /* Promote variable VNODE to be static.  */
 
 static void
@@ -768,6 +818,9 @@ promote_symbol (symtab_node node)
 
   gcc_checking_assert (!TREE_PUBLIC (node->symbol.decl)
 		       && !DECL_EXTERNAL (node->symbol.decl));
+  /* Be sure that newly public symbol does not conflict with anything already
+     defined by the non-LTO part.  */
+  privatize_symbol_name (node);
   TREE_PUBLIC (node->symbol.decl) = 1;
   DECL_VISIBILITY (node->symbol.decl) = VISIBILITY_HIDDEN;
   DECL_VISIBILITY_SPECIFIED (node->symbol.decl) = true;
@@ -776,6 +829,85 @@ promote_symbol (symtab_node node)
 	    "Promoting as hidden: %s\n", symtab_node_name (node));
 }
 
+/* Return true if NODE needs named section even if it won't land in the partition
+   symbol table.
+   FIXME: we should really not use named sections for inline clones and master clones.  */
+
+static bool
+may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node)
+{
+  struct cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+  if (!cnode)
+    return false;
+  if (symtab_real_symbol_p (node))
+    return false;
+  if (!cnode->global.inlined_to && !cnode->clones)
+    return false;
+  return (!encoder
+	  || (lto_symtab_encoder_lookup (encoder, node) != LCC_NOT_FOUND
+              && lto_symtab_encoder_encode_body_p (encoder,
+				                   cnode)));
+}
+
+/* If NODE represents a static variable.  See if there are other variables
+   of the same name in partition ENCODER (or in whole compilation unit if
+   ENCODER is NULL) and if so, mangle the statics.  Always mangle all
+   conflicting statics, so we reduce changes of silently miscompiling
+   asm statemnets refering to them by symbol name.  */
+
+static void
+rename_statics (lto_symtab_encoder_t encoder, symtab_node node)
+{
+  tree decl = node->symbol.decl;
+  symtab_node s;
+  tree name = DECL_ASSEMBLER_NAME (decl);
+
+  /* See if this is static symbol. */
+  if ((node->symbol.externally_visible
+      /* FIXME: externally_visible is somewhat illogically not set for
+	 external symbols (i.e. those not defined).  Remove this test
+	 once this is fixed.  */
+        || DECL_EXTERNAL (node->symbol.decl)
+        || !symtab_real_symbol_p (node))
+       && !may_need_named_section_p (encoder, node))
+    return;
+
+  /* Now walk symbols sharing the same name and see if there are any conflicts.
+     (all types of symbols counts here, since we can not have static of the
+     same name as external or public symbol.)  */
+  for (s = symtab_node_for_asm (name);
+       s; s = s->symbol.next_sharing_asm_name)
+    if ((symtab_real_symbol_p (s) || may_need_named_section_p (encoder, s))
+	&& s->symbol.decl != node->symbol.decl
+	&& (!encoder
+	    || lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND))
+       break;
+
+  /* OK, no confict, so we have nothing to do.  */
+  if (!s)
+    return;
+
+  if (cgraph_dump_file)
+    fprintf (cgraph_dump_file,
+	    "Renaming statics with asm name: %s\n", symtab_node_name (node));
+
+  /* Assign every symbol in the set that shares the same ASM name an unique
+     mangled name.  */
+  for (s = symtab_node_for_asm (name); s;)
+    if (!s->symbol.externally_visible
+	&& ((symtab_real_symbol_p (s)
+             && !DECL_EXTERNAL (node->symbol.decl)
+	     && !TREE_PUBLIC (node->symbol.decl))
+ 	    || may_need_named_section_p (encoder, s))
+	&& (!encoder
+	    || lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND))
+      {
+        privatize_symbol_name (s);
+	/* Re-start from beggining since we do not know how many symbols changed a name.  */
+	s = symtab_node_for_asm (name);
+      }
+   else s = s->symbol.next_sharing_asm_name;
+}
 
 /* Find out all static decls that need to be promoted to global because
    of cross file sharing.  This function must be run in the WPA mode after
@@ -801,16 +933,17 @@ lto_promote_cross_file_statics (void)
   for (i = 0; i < n_sets; i++)
     {
       lto_symtab_encoder_iterator lsei;
-      lto_symtab_encoder_t encoder;
-      ltrans_partition part
-	= ltrans_partitions[i];
+      lto_symtab_encoder_t encoder = ltrans_partitions[i]->encoder;
 
-      encoder = part->encoder;
       for (lsei = lsei_start (encoder); !lsei_end_p (lsei);
 	   lsei_next (&lsei))
         {
           symtab_node node = lsei_node (lsei);
 
+	  /* If symbol is static, rename it if its assembler name clash with
+	     anything else in this unit.  */
+	  rename_statics (encoder, node);
+
 	  /* No need to promote if symbol already is externally visible ... */
 	  if (node->symbol.externally_visible
  	      /* ... or if it is part of current partition ... */
@@ -824,3 +957,14 @@ lto_promote_cross_file_statics (void)
         }
     }
 }
+
+/* Rename statics in the whole unit in the case that 
+   we do -flto-partition=none.  */
+
+void
+lto_promote_statics_nonwpa (void)
+{
+  symtab_node node;
+  FOR_EACH_SYMBOL (node)
+    rename_statics (NULL, node);
+}
diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
index cf5650f..73c131f 100644
--- a/gcc/lto/lto-partition.h
+++ b/gcc/lto/lto-partition.h
@@ -37,3 +37,4 @@ void lto_max_map (void);
 void lto_balanced_map (void);
 void lto_promote_cross_file_statics (void);
 void free_ltrans_partitions (void);
+void lto_promote_statics_nonwpa (void);
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 52442f9..0943335 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1748,23 +1748,11 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
 {
   tree context;
 
-  /* Variable has file scope, not local. Need to ensure static variables
-     between different files don't clash unexpectedly.  */
+  /* Variable has file scope, not local.  */
   if (!TREE_PUBLIC (decl)
       && !((context = decl_function_context (decl))
 	   && auto_var_in_fn_p (decl, context)))
     {
-      /* ??? We normally pre-mangle names before we serialize them
-	 out.  Here, in lto1, we do not know the language, and
-	 thus cannot do the mangling again. Instead, we just
-	 append a suffix to the mangled name.  The resulting name,
-	 however, is not a properly-formed mangled name, and will
-	 confuse any attempt to unmangle it.  */
-      const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      char *label;
-
-      ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
       rest_of_decl_compilation (decl, 1, 0);
     }
 
@@ -1788,44 +1776,6 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
 static void
 lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl)
 {
-  /* Need to ensure static entities between different files
-     don't clash unexpectedly.  */
-  if (!TREE_PUBLIC (decl))
-    {
-      /* We must not use the DECL_ASSEMBLER_NAME macro here, as it
-	 may set the assembler name where it was previously empty.  */
-      tree old_assembler_name = decl->decl_with_vis.assembler_name;
-
-      /* FIXME lto: We normally pre-mangle names before we serialize
-	 them out.  Here, in lto1, we do not know the language, and
-	 thus cannot do the mangling again. Instead, we just append a
-	 suffix to the mangled name.  The resulting name, however, is
-	 not a properly-formed mangled name, and will confuse any
-	 attempt to unmangle it.  */
-      const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      char *label;
-
-      ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
-
-      /* We may arrive here with the old assembler name not set
-	 if the function body is not needed, e.g., it has been
-	 inlined away and does not appear in the cgraph.  */
-      if (old_assembler_name)
-	{
-	  tree new_assembler_name = DECL_ASSEMBLER_NAME (decl);
-
-	  /* Make the original assembler name available for later use.
-	     We may have used it to indicate the section within its
-	     object file where the function body may be found.
-	     FIXME lto: Find a better way to maintain the function decl
-	     to body section mapping so we don't need this hack.  */
-	  lto_record_renamed_decl (data_in->file_data,
-				   IDENTIFIER_POINTER (old_assembler_name),
-				   IDENTIFIER_POINTER (new_assembler_name));
-	}
-    }
-
   /* If this variable has already been declared, queue the
      declaration for merging.  */
   if (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl))
@@ -3396,6 +3346,8 @@ lto_main (void)
 	  timevar_start (TV_PHASE_OPT_GEN);
 
 	  materialize_cgraph ();
+	  if (!flag_ltrans)
+	    lto_promote_statics_nonwpa ();
 
 	  /* Let the middle end know that we have read and merged all of
 	     the input files.  */ 
-- 
cgit v1.1