Jan Hubicka <jh@suse.cz>
authorJan Hubicka <jh@suse.cz>
Thu, 9 May 2013 15:37:12 +0000 (17:37 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 9 May 2013 15:37:12 +0000 (15:37 +0000)
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/ChangeLog
gcc/lto/ChangeLog
gcc/lto/lto-partition.c
gcc/lto/lto-partition.h
gcc/lto/lto.c
gcc/symtab.c

index 94ed169..d22b31d 100644 (file)
@@ -1,4 +1,10 @@
 2013-05-09  Jan Hubicka  <jh@suse.cz>
+           Richard Biener  <rguenther@suse.de>
+
+       PR lto/54095
+       * symtab.c (symtab_make_decl_local): Do not add private names.
+
+2013-05-09  Jan Hubicka  <jh@suse.cz>
 
        PR lto/54095
        * symtab.c (insert_to_assembler_name_hash): Handle clones.
index e3530da..8732069 100644 (file)
@@ -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
index 833d926..652272a 100644 (file)
@@ -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);
+}
index cf5650f..73c131f 100644 (file)
@@ -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);
index 52442f9..0943335 100644 (file)
@@ -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.  */ 
index a474bfe..56f0de9 100644 (file)
@@ -756,23 +756,6 @@ symtab_make_decl_local (tree decl)
 
   if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl))
     {
-      /* It is possible that we are linking against library defining same COMDAT
-        function.  To avoid conflict we need to rename our local name of the
-        function just in the case WHOPR partitioning decide to make it hidden
-        to avoid cross partition references.  */
-      if (flag_wpa)
-       {
-         const char *old_name;
-          symtab_node node = symtab_get_node (decl);
-         old_name  = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-         change_decl_assembler_name (decl,
-                                     clone_function_name (decl, "local"));
-         if (node->symbol.lto_file_data)
-           lto_record_renamed_decl (node->symbol.lto_file_data,
-                                    old_name,
-                                    IDENTIFIER_POINTER
-                                      (DECL_ASSEMBLER_NAME (decl)));
-       }
       DECL_SECTION_NAME (decl) = 0;
       DECL_COMDAT (decl) = 0;
     }