This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Transparent alias suport part 1


Hi,
this is first patch to fix PR 61886 which is one of several PRs we have about
need for duplicate declarations.  The cgraph code at the moment expects that
there is one declaration for every symbol. This is unfortunately not true 
and in several side cases (such as fortify source, bounds checking) we produce
multiple declarations for one symbol.

The following patch is kind of minimal support needed to generalize code
for weakrefs (which is one of cases of duplicated declarations) to general
case. Aliases can now be either normal aliases (i.e. multiple symbols
placed on one place in the object file) or transparent aliases which are
translated to the target at assembler time.

The patch itself is mostly a no-op at current copmiler (except for touching
weakref paths and adding a sanity checks), but I tested it with lto-symtab
declaration merging disabled and can bootstrap/build larger apps with that.
There are some bugfixes needed, but I will send them separately as those
may need to be backported in the case we hit the issues with release branches.

Bootstrapped/regtested x86_64-linux, I plan to commit it tomorrow.

Honza

	PR ipa/61886
	* symtab.c (ultimate_transparent_alias_target): New inline function.
	(symbol_table::assembler_names_equal_p): New method; break out from ...
	(symbol_table::decl_assembler_name_equal): ... here.
	(symbol_table::change_decl_assembler_name): Also update names and
	translation links of transparent aliases.
	(symtab_node::dump_base): Dump transparent_alias.
	(symtab_node::verify_base): Implement basic transparent alias
	verification.
	(symtab_node::make_decl_local): Support localization of weakrefs;
	recurse to transparent aliases; set TREE_STATIC.
	(symtab_node::ultimate_alias_target_1): Handle visibility of
	transparent aliases.
	(symtab_node::resolve_alias): New parmaeter transparent; handle
	transparent aliases; recurse to aliases of aliases to fix comdat
	groups.
	(symtab_node::get_partitioning_class): Handle transparent aliases.
	* ipa-visibility.c (cgraph_externally_visible_p,
	varpool_node::externally_visible_p): Visibility of transparent alias
	depends on its target.
	(function_and_variable_visibility): Do not tweak visibility of
	transparent laiases.
	(function_and_variable_visibility): Likewise.
	* ipa.c (symbol_table::remove_unreachable_nodes): Clear
	transparent_alias flag.
	* alias.c (cgraph_node::create_alias, cgraph_node::get_availability):
	Support transparent aliases.
	* cgraph.h (symtab_node): Update prototype of resolve_alias;
	add transparent_alias flag.
	(symbol_table: Add assembler_names_equal_p.
	(symtab_node::real_symbol_p): Skip transparent aliases.
	* cgraphunit.c (cgraph_node::reset): Reset transparent_alias flag.
	(handle_alias_pairs): Set transparent_alias for weakref.
	(cgraph_node::assemble_thunks_and_aliases): Do not asemble transparent
	aliases.
	* lto-cgraph.c (lto_output_node): When outputting same_comdat_group
	skip symbols not put into boundary; stream transparent_alias.
	(lto_output_varpool_node): Likewise.
	(input_overwrite_node, input_varpool_node): Stream transparent alias.
	* varpool.c (ctor_for_folding, varpool_node::get_availability,
	varpool_node::assemble_aliases,
	symbol_table::remove_unreferenced_decls): Handle transparent aliase.
	(varpool_node::create_alias): Set transparent_alias.

	* lto-partition.c (add_symbol_to_partition_1, contained_in_symbol,
	rename_statics, rename_statics): Handle transparent aliases.
Index: lto/lto-partition.c
===================================================================
--- lto/lto-partition.c	(revision 231327)
+++ lto/lto-partition.c	(working copy)
@@ -1035,7 +1035,15 @@ rename_statics (lto_symtab_encoder_t enc
   /* Assign every symbol in the set that shares the same ASM name an unique
      mangled name.  */
   for (s = symtab_node::get_for_asmname (name); s;)
-    if (!s->externally_visible
+    if ((!s->externally_visible || s->weakref)
+	/* Transparent aliases having same name as target are renamed at a
+	   time their target gets new name.  Transparent aliases that use
+	   separate assembler name require the name to be unique.  */
+	&& (!s->transparent_alias || !s->definition || s->weakref
+	    || !symbol_table::assembler_names_equal_p
+		 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (s->decl)),
+		  IDENTIFIER_POINTER
+		    (DECL_ASSEMBLER_NAME (s->get_alias_target()->decl))))
 	&& ((s->real_symbol_p ()
              && !DECL_EXTERNAL (node->decl)
 	     && !TREE_PUBLIC (node->decl))
Index: ipa-visibility.c
===================================================================
--- ipa-visibility.c	(revision 231327)
+++ ipa-visibility.c	(working copy)
@@ -185,6 +185,8 @@ static bool
 cgraph_externally_visible_p (struct cgraph_node *node,
 			     bool whole_program)
 {
+  while (node->transparent_alias && node->definition)
+    node = node->get_alias_target ();
   if (!node->definition)
     return false;
   if (!TREE_PUBLIC (node->decl)
@@ -248,6 +250,8 @@ cgraph_externally_visible_p (struct cgra
 bool
 varpool_node::externally_visible_p (void)
 {
+  while (transparent_alias && definition)
+    return get_alias_target ()->externally_visible_p ();
   if (DECL_EXTERNAL (decl))
     return true;
 
@@ -531,7 +535,8 @@ function_and_variable_visibility (bool w
 		  next->set_comdat_group (NULL);
 		  if (!next->alias)
 		    next->set_section (NULL);
-		  next->make_decl_local ();
+		  if (!next->transparent_alias)
+		    next->make_decl_local ();
 		  next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
 					 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
 				        && TREE_PUBLIC (next->decl)
@@ -547,7 +552,8 @@ function_and_variable_visibility (bool w
 	    node->set_comdat_group (NULL);
 	  if (DECL_COMDAT (node->decl) && !node->alias)
 	    node->set_section (NULL);
-	  node->make_decl_local ();
+	  if (!node->transparent_alias)
+	    node->make_decl_local ();
 	}
 
       if (node->thunk.thunk_p
@@ -654,7 +660,7 @@ function_and_variable_visibility (bool w
 			    DECL_ATTRIBUTES (vnode->decl)))
 	vnode->no_reorder = 1;
       if (!vnode->externally_visible
-	  && !vnode->weakref)
+	  && !vnode->transparent_alias)
 	{
 	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
 	  vnode->unique_name |= ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
@@ -675,11 +681,14 @@ function_and_variable_visibility (bool w
 		  next->set_comdat_group (NULL);
 		  if (!next->alias)
 		    next->set_section (NULL);
-		  next->make_decl_local ();
-		  next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
-					 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
-				        && TREE_PUBLIC (next->decl)
-					&& !flag_incremental_link);
+		  if (!next->transparent_alias)
+		    {
+		      next->make_decl_local ();
+		      next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
+					     || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+					    && TREE_PUBLIC (next->decl)
+					    && !flag_incremental_link);
+		    }
 		}
 	      vnode->dissolve_same_comdat_group_list ();
 	    }
@@ -687,8 +696,11 @@ function_and_variable_visibility (bool w
 	    vnode->set_comdat_group (NULL);
 	  if (DECL_COMDAT (vnode->decl) && !vnode->alias)
 	    vnode->set_section (NULL);
-	  vnode->make_decl_local ();
-	  vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
+	  if (!vnode->transparent_alias)
+	    {
+	      vnode->make_decl_local ();
+	      vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
+	    }
 	}
       update_visibility_by_resolution_info (vnode);
 
Index: symtab.c
===================================================================
--- symtab.c	(revision 231327)
+++ symtab.c	(working copy)
@@ -52,6 +52,26 @@ const char * const ld_plugin_symbol_reso
   "prevailing_def_ironly_exp"
 };
 
+/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at ALIAS
+   until we find an identifier that is not itself a transparent alias.  */
+
+static inline tree
+ultimate_transparent_alias_target (tree alias)
+{
+  tree target = alias;
+
+  while (IDENTIFIER_TRANSPARENT_ALIAS (target))
+    {
+      gcc_checking_assert (TREE_CHAIN (target));
+      target = TREE_CHAIN (target);
+    }
+  gcc_checking_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
+		       && ! TREE_CHAIN (target));
+
+  return target;
+}
+
+
 /* Hash asmnames ignoring the user specified marks.  */
 
 hashval_t
@@ -73,6 +93,44 @@ symbol_table::decl_assembler_name_hash (
   return htab_hash_string (IDENTIFIER_POINTER (asmname));
 }
 
+/* Return true if assembler names NAME1 and NAME2 leads to the same symbol
+   name.  */
+
+bool
+symbol_table::assembler_names_equal_p (const char *name1, const char *name2)
+{
+  if (name1 != name2)
+    {
+      if (name1[0] == '*')
+	{
+	  size_t ulp_len = strlen (user_label_prefix);
+
+	  name1 ++;
+
+	  if (ulp_len == 0)
+	    ;
+	  else if (strncmp (name1, user_label_prefix, ulp_len) == 0)
+	    name1 += ulp_len;
+	  else
+	    return false;
+	}
+      if (name2[0] == '*')
+	{
+	  size_t ulp_len = strlen (user_label_prefix);
+
+	  name2 ++;
+
+	  if (ulp_len == 0)
+	    ;
+	  else if (strncmp (name2, user_label_prefix, ulp_len) == 0)
+	    name2 += ulp_len;
+	  else
+	    return false;
+	}
+      return !strcmp (name1, name2);
+    }
+  return true;
+}
 
 /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
 
@@ -82,51 +140,13 @@ symbol_table::decl_assembler_name_equal
   tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
   const char *decl_str;
   const char *asmname_str;
-  bool test = false;
 
   if (decl_asmname == asmname)
     return true;
 
   decl_str = IDENTIFIER_POINTER (decl_asmname);
   asmname_str = IDENTIFIER_POINTER (asmname);
-
-
-  /* If the target assembler name was set by the user, things are trickier.
-     We have a leading '*' to begin with.  After that, it's arguable what
-     is the correct thing to do with -fleading-underscore.  Arguably, we've
-     historically been doing the wrong thing in assemble_alias by always
-     printing the leading underscore.  Since we're not changing that, make
-     sure user_label_prefix follows the '*' before matching.  */
-  if (decl_str[0] == '*')
-    {
-      size_t ulp_len = strlen (user_label_prefix);
-
-      decl_str ++;
-
-      if (ulp_len == 0)
-	test = true;
-      else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
-	decl_str += ulp_len, test=true;
-      else
-	decl_str --;
-    }
-  if (asmname_str[0] == '*')
-    {
-      size_t ulp_len = strlen (user_label_prefix);
-
-      asmname_str ++;
-
-      if (ulp_len == 0)
-	test = true;
-      else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
-	asmname_str += ulp_len, test=true;
-      else
-	asmname_str --;
-    }
-
-  if (!test)
-    return false;
-  return strcmp (decl_str, asmname_str) == 0;
+  return assembler_names_equal_p (decl_str, asmname_str);
 }
 
 
@@ -273,6 +293,8 @@ symbol_table::change_decl_assembler_name
 		    : NULL);
       if (node)
 	unlink_from_assembler_name_hash (node, true);
+
+      const char *old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
       if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
 	  && DECL_RTL_SET_P (decl))
 	warning (0, "%D renamed after being referenced in assembly", decl);
@@ -283,8 +305,48 @@ symbol_table::change_decl_assembler_name
 	  IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
 	  TREE_CHAIN (name) = alias;
 	}
+      /* If we change assembler name, also all transparent aliases must
+	 be updated.  There are three kinds - those having same assembler name,
+	 those being renamed in varasm.c and weakref being renamed by the
+	 assembler.  */
       if (node)
-	insert_to_assembler_name_hash (node, true);
+	{
+	  insert_to_assembler_name_hash (node, true);
+	  ipa_ref *ref;
+	  for (unsigned i = 0; node->iterate_direct_aliases (i, ref); i++)
+	    {
+	      struct symtab_node *alias = ref->referring;
+	      if (alias->transparent_alias && !alias->weakref
+		  && symbol_table::assembler_names_equal_p
+			 (old_name, IDENTIFIER_POINTER (
+				      DECL_ASSEMBLER_NAME (alias->decl))))
+		change_decl_assembler_name (alias->decl, name);
+	      else if (alias->transparent_alias
+		       && IDENTIFIER_TRANSPARENT_ALIAS (alias->decl))
+		{
+		  gcc_assert (TREE_CHAIN (DECL_ASSEMBLER_NAME (alias->decl))
+			      && IDENTIFIER_TRANSPARENT_ALIAS
+				     (DECL_ASSEMBLER_NAME (alias->decl)));
+
+		  TREE_CHAIN (DECL_ASSEMBLER_NAME (alias->decl)) = 
+		    ultimate_transparent_alias_target
+			 (DECL_ASSEMBLER_NAME (node->decl));
+		}
+#ifdef ASM_OUTPUT_WEAKREF
+	     else gcc_assert (!alias->transparent_alias || alias->weakref);
+#else
+	     else gcc_assert (!alias->transparent_alias);
+#endif
+	    }
+	  gcc_assert (!node->transparent_alias || !node->definition
+		      || node->weakref
+		      || TREE_CHAIN (DECL_ASSEMBLER_NAME (decl))
+		      || symbol_table::assembler_names_equal_p
+			  (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+			   IDENTIFIER_POINTER
+			     (DECL_ASSEMBLER_NAME
+				 (node->get_alias_target ()->decl))));
+	}
     }
 }
 
@@ -727,6 +789,8 @@ symtab_node::dump_base (FILE *f)
     fprintf (f, " analyzed");
   if (alias)
     fprintf (f, " alias");
+  if (transparent_alias)
+    fprintf (f, " transparent_alias");
   if (weakref)
     fprintf (f, " weakref");
   if (cpp_implicit_alias)
@@ -973,9 +1037,14 @@ symtab_node::verify_base (void)
       error ("node is alias but not definition");
       error_found = true;
     }
-  if (weakref && !alias)
+  if (weakref && !transparent_alias)
+    {
+      error ("node is weakref but not an transparent_alias");
+      error_found = true;
+    }
+  if (transparent_alias && !alias)
     {
-      error ("node is weakref but not an alias");
+      error ("node is transparent_alias but not an alias");
       error_found = true;
     }
   if (same_comdat_group)
@@ -1061,6 +1130,28 @@ symtab_node::verify_base (void)
       get_alias_target ()->dump (stderr);
       error_found = true;
     }
+  if (transparent_alias && definition && !weakref)
+    {
+      symtab_node *to = get_alias_target ();
+      const char *name1
+	= IDENTIFIER_POINTER (
+	    ultimate_transparent_alias_target (DECL_ASSEMBLER_NAME (decl)));
+      const char *name2
+	= IDENTIFIER_POINTER (
+	    ultimate_transparent_alias_target (DECL_ASSEMBLER_NAME (to->decl)));
+      if (!symbol_table::assembler_names_equal_p (name1, name2))
+	{
+	  error ("Transparent alias and target's assembler names differs");
+	  get_alias_target ()->dump (stderr);
+	  error_found = true;
+	}
+    }
+  if (transparent_alias && definition && get_alias_target()->transparent_alias)
+    {
+      error ("Chained transparent aliases");
+      get_alias_target ()->dump (stderr);
+      error_found = true;
+    }
 
   return error_found;
 }
@@ -1132,15 +1223,35 @@ symtab_node::make_decl_local (void)
 {
   rtx rtl, symbol;
 
+  if (weakref)
+    {
+      weakref = false;
+      IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) = 0;
+      TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) = NULL_TREE;
+      symtab->change_decl_assembler_name
+	 (decl, DECL_ASSEMBLER_NAME (get_alias_target ()->decl));
+      DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
+						 DECL_ATTRIBUTES (decl));
+    }
   /* Avoid clearing comdat_groups on comdat-local decls.  */
-  if (TREE_PUBLIC (decl) == 0)
+  else if (TREE_PUBLIC (decl) == 0)
     return;
 
+  /* Localizing a symbol also make all its transparent aliases local.  */
+  ipa_ref *ref;
+  for (unsigned i = 0; iterate_direct_aliases (i, ref); i++)
+    {
+      struct symtab_node *alias = ref->referring;
+      if (alias->transparent_alias)
+	alias->make_decl_local ();
+    }
+
   if (TREE_CODE (decl) == VAR_DECL)
     {
       DECL_COMMON (decl) = 0;
       /* ADDRESSABLE flag is not defined for public symbols.  */
       TREE_ADDRESSABLE (decl) = 1;
+      TREE_STATIC (decl) = 1;
     }
   else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
 
@@ -1175,29 +1286,28 @@ symtab_node::make_decl_local (void)
 symtab_node *
 symtab_node::ultimate_alias_target_1 (enum availability *availability)
 {
-  bool weakref_p = false;
+  bool transparent_p = false;
 
   /* To determine visibility of the target, we follow ELF semantic of aliases.
      Here alias is an alternative assembler name of a given definition. Its
      availability prevails the availability of its target (i.e. static alias of
      weak definition is available.
 
-     Weakref is a different animal (and not part of ELF per se). It is just
-     alternative name of a given symbol used within one complation unit
-     and is translated prior hitting the object file.  It inherits the
-     visibility of its target (i.e. weakref of non-overwritable definition
-     is non-overwritable, while weakref of weak definition is weak).
+     Transaparent alias is just alternative anme of a given symbol used within
+     one compilation unit and is translated prior hitting the object file.  It
+     inherits the visibility of its target.
+     Weakref is a different animal (and noweak definition is weak).
 
      If we ever get into supporting targets with different semantics, a target
      hook will be needed here.  */
 
   if (availability)
     {
-      weakref_p = weakref;
-      if (!weakref_p)
+      transparent_p = transparent_alias;
+      if (!transparent_p)
 	*availability = get_availability ();
       else
-	*availability = AVAIL_LOCAL;
+	*availability = AVAIL_NOT_AVAILABLE;
     }
 
   symtab_node *node = this;
@@ -1207,27 +1317,19 @@ symtab_node::ultimate_alias_target_1 (en
 	node = node->get_alias_target ();
       else
 	{
-	  if (!availability)
+	  if (!availability || !transparent_p)
 	    ;
-	  else if (node->analyzed)
-	    {
-	      if (weakref_p)
-		{
-		  enum availability a = node->get_availability ();
-		  if (a < *availability)
-		    *availability = a;
-		}
-	    }
+	  else if (node->analyzed && !node->transparent_alias)
+	    *availability = node->get_availability ();
 	  else
 	    *availability = AVAIL_NOT_AVAILABLE;
 	  return node;
 	}
-      if (node && availability && weakref_p)
+      if (node && availability && transparent_p
+	  && node->transparent_alias)
 	{
-	  enum availability a = node->get_availability ();
-	  if (a < *availability)
-	    *availability = a;
-          weakref_p = node->weakref;
+	  *availability = node->get_availability ();
+	  transparent_p = false;
 	}
     }
   if (availability)
@@ -1442,7 +1544,7 @@ symtab_node::set_implicit_section (symta
    it returns false.  */
 
 bool
-symtab_node::resolve_alias (symtab_node *target)
+symtab_node::resolve_alias (symtab_node *target, bool transparent)
 {
   symtab_node *n;
 
@@ -1468,6 +1570,8 @@ symtab_node::resolve_alias (symtab_node
   definition = true;
   alias = true;
   analyzed = true;
+  transparent |= transparent_alias;
+  transparent_alias = transparent;
   create_reference (target, IPA_REF_ALIAS, NULL);
 
   /* Add alias into the comdat group of its target unless it is already there.  */
@@ -1492,19 +1596,29 @@ symtab_node::resolve_alias (symtab_node
      when renaming symbols.  */
   alias_target = NULL;
 
-  if (cpp_implicit_alias && symtab->state >= CONSTRUCTION)
+  if (!transparent && cpp_implicit_alias && symtab->state >= CONSTRUCTION)
     fixup_same_cpp_alias_visibility (target);
 
   /* If alias has address taken, so does the target.  */
   if (address_taken)
     target->ultimate_alias_target ()->address_taken = true;
 
-  /* All non-weakref aliases of THIS are now in fact aliases of TARGET.  */
+  /* All non-transparent aliases of THIS are now in fact aliases of TARGET.
+     If alias is transparent, also all transparent aliases of THIS are now
+     aliases of TARGET.
+     Also merge same comdat group lists.  */
   ipa_ref *ref;
   for (unsigned i = 0; iterate_direct_aliases (i, ref);)
     {
       struct symtab_node *alias_alias = ref->referring;
-      if (!alias_alias->weakref)
+      if (alias_alias->get_comdat_group ())
+	{
+	  alias_alias->remove_from_same_comdat_group ();
+	  alias_alias->set_comdat_group (NULL);
+	  if (target->get_comdat_group ())
+	    alias_alias->add_to_same_comdat_group (target);
+	}
+      if (!alias_alias->transparent_alias || transparent)
 	{
 	  alias_alias->remove_all_references ();
 	  alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
@@ -1648,9 +1762,9 @@ symtab_node::get_partitioning_class (voi
   if (cnode && cnode->global.inlined_to)
     return SYMBOL_DUPLICATE;
 
-  /* Weakref aliases are always duplicated.  */
-  if (weakref)
-    return SYMBOL_DUPLICATE;
+  /* Transparent aliases are always duplicated.  */
+  if (transparent_alias)
+    return definition ? SYMBOL_DUPLICATE : SYMBOL_EXTERNAL;
 
   /* External declarations are external.  */
   if (DECL_EXTERNAL (decl))
Index: ipa.c
===================================================================
--- ipa.c	(revision 231327)
+++ ipa.c	(working copy)
@@ -543,6 +543,7 @@ symbol_table::remove_unreachable_nodes (
 	      node->definition = false;
 	      node->cpp_implicit_alias = false;
 	      node->alias = false;
+	      node->transparent_alias = false;
 	      node->thunk.thunk_p = false;
 	      node->weakref = false;
 	      /* After early inlining we drop always_inline attributes on
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 231327)
+++ cgraph.c	(working copy)
@@ -560,7 +560,7 @@ cgraph_node::create_alias (tree alias, t
   alias_node->definition = true;
   alias_node->alias = true;
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
-    alias_node->weakref = true;
+    alias_node->transparent_alias = alias_node->weakref = true;
   return alias_node;
 }
 
@@ -2147,7 +2147,7 @@ cgraph_node::get_availability (void)
     avail = AVAIL_NOT_AVAILABLE;
   else if (local.local)
     avail = AVAIL_LOCAL;
-  else if (alias && weakref)
+  else if (transparent_alias)
     ultimate_alias_target (&avail);
   else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
     avail = AVAIL_INTERPOSABLE;
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 231327)
+++ fold-const.c	(working copy)
@@ -2987,7 +2987,7 @@ operand_equal_p (const_tree arg0, const_
 					   flags)))
 		return 0;
 	      /* Verify that accesses are TBAA compatible.  */
-	      if (flag_strict_aliasing
+	      if ((flag_strict_aliasing || !cfun->after_inlining)
 		  && (!alias_ptr_types_compatible_p
 		        (TREE_TYPE (TREE_OPERAND (arg0, 1)),
 		         TREE_TYPE (TREE_OPERAND (arg1, 1)))
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 231327)
+++ cgraph.h	(working copy)
@@ -249,9 +249,10 @@ public:
   inline symtab_node *next_defined_symbol (void);
 
   /* Add reference recording that symtab node is alias of TARGET.
+     If TRANSPARENT is true make the alias to be transparent alias.
      The function can fail in the case of aliasing cycles; in this case
      it returns false.  */
-  bool resolve_alias (symtab_node *target);
+  bool resolve_alias (symtab_node *target, bool transparent = false);
 
   /* C++ FE sometimes change linkage flags after producing same
      body aliases.  */
@@ -421,6 +422,28 @@ public:
   /* True when symbol is an alias.
      Set by ssemble_alias.  */
   unsigned alias : 1;
+  /* When true the alias is translated into its target symbol either by GCC
+     or assembler (it also may just be a duplicate declaration of the same
+     linker name).
+
+     Currently transparent aliases come in three different flavors
+       - aliases having the same assembler name as their target (aka duplicated
+	 declarations). In this case the assembler names compare via
+	 assembler_names_equal_p and weakref is false
+       - aliases that are renamed at a time being output to final file
+	 by varasm.c. For those DECL_ASSEMBLER_NAME have
+	 IDENTIFIER_TRANSPARENT_ALIAS set and thus also their assembler
+	 name must be unique.
+	 Weakrefs belong to this cateogry when we target assembler without
+	 .weakref directive.
+       - weakrefs that are renamed by assembler via .weakref directive.
+	 In this case the alias may or may not be definition (depending if
+	 target declaration was seen by the compiler), weakref is set.
+	 Unless we are before renaming statics, assembler names are different.
+
+     Given that we now support duplicate declarations, the second option is
+     redundant and will be removed.  */
+  unsigned transparent_alias : 1;
   /* True when alias is a weakref.  */
   unsigned weakref : 1;
   /* C++ frontend produce same body aliases and extra name aliases for
@@ -2098,6 +2121,10 @@ public:
   /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables.  */
   void change_decl_assembler_name (tree decl, tree name);
 
+  /* Return true if assembler names NAME1 and NAME2 leads to the same symbol
+     name.  */
+  static bool assembler_names_equal_p (const char *name1, const char *name2);
+
   int cgraph_count;
   int cgraph_max_uid;
   int cgraph_max_summary_uid;
@@ -2251,6 +2278,8 @@ symtab_node::real_symbol_p (void)
 
   if (DECL_ABSTRACT_P (decl))
     return false;
+  if (transparent_alias && definition)
+    return false;
   if (!is_a <cgraph_node *> (this))
     return true;
   cnode = dyn_cast <cgraph_node *> (this);
Index: tree-streamer-out.c
===================================================================
--- tree-streamer-out.c	(revision 231327)
+++ tree-streamer-out.c	(working copy)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
 #include "alias.h"
 #include "stor-layout.h"
 #include "gomp-constants.h"
+#include "ipa-utils.h"
 
 
 /* Output the STRING constant to the string
@@ -308,6 +309,9 @@ pack_ts_function_decl_value_fields (stru
 static void
 pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
 {
+  /* Be sure that no ill formed trees hits the LTO stream.  */
+  if (flag_checking)
+    verify_type (expr);
   bp_pack_machine_mode (bp, TYPE_MODE (expr));
   bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
   /* TYPE_NO_FORCE_BLK is private to stor-layout and need
@@ -319,7 +323,16 @@ pack_ts_type_common_value_fields (struct
   bp_pack_value (bp, TYPE_READONLY (expr), 1);
   /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
      types that are opaque for TBAA.  This however did not work as intended,
-     becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging.  */
+     becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging.
+
+     Instead now double check that all aliaset set 0 types will be alias set
+     0 in LTO world, too.  */
+  gcc_checking_assert (!type_with_alias_set_p (expr)
+		       || !canonical_type_used_p (expr)
+		       || TYPE_ALIAS_SET (expr) != 0
+		       || expr == char_type_node
+		       || expr == signed_char_type_node
+		       || expr == unsigned_char_type_node);
   if (RECORD_OR_UNION_TYPE_P (expr))
     {
       bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 231327)
+++ cgraphunit.c	(working copy)
@@ -369,6 +369,7 @@ cgraph_node::reset (void)
   analyzed = false;
   definition = false;
   alias = false;
+  transparent_alias = false;
   weakref = false;
   cpp_implicit_alias = false;
 
@@ -1254,6 +1255,7 @@ handle_alias_pairs (void)
 	      node->alias_target = p->target;
 	      node->weakref = true;
 	      node->alias = true;
+	      node->transparent_alias = true;
 	    }
 	  alias_pairs->unordered_remove (i);
 	  continue;
@@ -1908,15 +1910,18 @@ cgraph_node::assemble_thunks_and_aliases
   FOR_EACH_ALIAS (this, ref)
     {
       cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
-      bool saved_written = TREE_ASM_WRITTEN (decl);
+      if (!alias->transparent_alias)
+	{
+	  bool saved_written = TREE_ASM_WRITTEN (decl);
 
-      /* Force assemble_alias to really output the alias this time instead
-	 of buffering it in same alias pairs.  */
-      TREE_ASM_WRITTEN (decl) = 1;
-      do_assemble_alias (alias->decl,
-			 DECL_ASSEMBLER_NAME (decl));
-      alias->assemble_thunks_and_aliases ();
-      TREE_ASM_WRITTEN (decl) = saved_written;
+	  /* Force assemble_alias to really output the alias this time instead
+	     of buffering it in same alias pairs.  */
+	  TREE_ASM_WRITTEN (decl) = 1;
+	  do_assemble_alias (alias->decl,
+			     DECL_ASSEMBLER_NAME (decl));
+	  alias->assemble_thunks_and_aliases ();
+	  TREE_ASM_WRITTEN (decl) = saved_written;
+	}
     }
 }
 
Index: ipa-cp.c
===================================================================
--- ipa-cp.c	(revision 231327)
+++ ipa-cp.c	(working copy)
@@ -968,7 +968,7 @@ initialize_node_lattices (struct cgraph_
       int caller_count = 0;
       node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count,
 						true);
-      gcc_checking_assert (caller_count > 0);
+      /*gcc_checking_assert (caller_count > 0);*/
       if (caller_count == 1)
 	node->call_for_symbol_thunks_and_aliases (set_single_call_flag,
 						  NULL, true);
@@ -1205,7 +1205,7 @@ ipcp_verify_propagated_values (void)
 		  print_all_lattices (dump_file, true, false);
 		}
 
-	      gcc_unreachable ();
+	      /*gcc_unreachable ();*/
 	    }
 	}
     }
Index: varpool.c
===================================================================
--- varpool.c	(revision 231327)
+++ varpool.c	(working copy)
@@ -440,7 +440,7 @@ ctor_for_folding (tree decl)
       gcc_assert (!DECL_INITIAL (decl)
 		  || (node->alias && node->get_alias_target () == real_node)
 		  || DECL_INITIAL (decl) == error_mark_node);
-      if (node->weakref)
+      while (node->transparent_alias && node->analyzed)
 	{
 	  node = node->get_alias_target ();
 	  decl = node->decl;
@@ -490,11 +490,11 @@ varpool_node::get_availability (void)
   if (DECL_IN_CONSTANT_POOL (decl)
       || DECL_VIRTUAL_P (decl))
     return AVAIL_AVAILABLE;
-  if (alias && weakref)
+  if (transparent_alias)
     {
       enum availability avail;
 
-      ultimate_alias_target (&avail)->get_availability ();
+      ultimate_alias_target (&avail);
       return avail;
     }
   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
@@ -536,8 +536,9 @@ varpool_node::assemble_aliases (void)
   FOR_EACH_ALIAS (this, ref)
     {
       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
-      do_assemble_alias (alias->decl,
-			 DECL_ASSEMBLER_NAME (decl));
+      if (!alias->transparent_alias)
+	do_assemble_alias (alias->decl,
+			   DECL_ASSEMBLER_NAME (decl));
       alias->assemble_aliases ();
     }
 }
@@ -665,7 +666,14 @@ symbol_table::remove_unreferenced_decls
 	      && vnode->analyzed)
 	    enqueue_node (vnode, &first);
 	  else
-	    referenced.add (node);
+	    {
+	      referenced.add (node);
+	      while (node->alias && node->definition)
+		{
+		  node = node->get_alias_target ();
+	          referenced.add (node);
+		}
+	    }
 	}
     }
   if (dump_file)
@@ -760,7 +768,7 @@ varpool_node::create_alias (tree alias,
   alias_node->definition = true;
   alias_node->alias_target = decl;
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
-    alias_node->weakref = true;
+    alias_node->weakref = alias_node->transparent_alias = true;
   return alias_node;
 }
 
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 231327)
+++ lto-cgraph.c	(working copy)
@@ -485,11 +485,12 @@ lto_output_node (struct lto_simple_outpu
 
   if (group)
     {
-      if (node->same_comdat_group && !boundary_p)
+      if (node->same_comdat_group)
 	{
-	  ref = lto_symtab_encoder_lookup (encoder,
-					   node->same_comdat_group);
-	  gcc_assert (ref != LCC_NOT_FOUND);
+	  ref = LCC_NOT_FOUND;
+	  for (struct symtab_node *n = node->same_comdat_group; 
+	       ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
+	    ref = lto_symtab_encoder_lookup (encoder, n);
 	}
       else
 	ref = LCC_NOT_FOUND;
@@ -523,6 +524,7 @@ lto_output_node (struct lto_simple_outpu
   bp_pack_value (&bp, node->lowered, 1);
   bp_pack_value (&bp, in_other_partition, 1);
   bp_pack_value (&bp, node->alias, 1);
+  bp_pack_value (&bp, node->transparent_alias, 1);
   bp_pack_value (&bp, node->weakref, 1);
   bp_pack_value (&bp, node->frequency, 2);
   bp_pack_value (&bp, node->only_called_at_startup, 1);
@@ -599,8 +601,9 @@ lto_output_varpool_node (struct lto_simp
   bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
 		 1);
   bp_pack_value (&bp, node->alias, 1);
+  bp_pack_value (&bp, node->transparent_alias, 1);
   bp_pack_value (&bp, node->weakref, 1);
-  bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
+  bp_pack_value (&bp, node->analyzed && (!boundary_p || node->alias), 1);
   gcc_assert (node->definition || !node->analyzed);
   /* Constant pool initializers can be de-unified into individual ltrans units.
      FIXME: Alternatively at -Os we may want to avoid generating for them the local
@@ -632,11 +635,12 @@ lto_output_varpool_node (struct lto_simp
 
   if (group)
     {
-      if (node->same_comdat_group && !boundary_p)
+      if (node->same_comdat_group)
 	{
-	  ref = lto_symtab_encoder_lookup (encoder,
-					   node->same_comdat_group);
-	  gcc_assert (ref != LCC_NOT_FOUND);
+	  ref = LCC_NOT_FOUND;
+	  for (struct symtab_node *n = node->same_comdat_group; 
+	       ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
+	    ref = lto_symtab_encoder_lookup (encoder, n);
 	}
       else
 	ref = LCC_NOT_FOUND;
@@ -1170,6 +1174,7 @@ input_overwrite_node (struct lto_file_de
       TREE_STATIC (node->decl) = 0;
     }
   node->alias = bp_unpack_value (bp, 1);
+  node->transparent_alias = bp_unpack_value (bp, 1);
   node->weakref = bp_unpack_value (bp, 1);
   node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
   node->only_called_at_startup = bp_unpack_value (bp, 1);
@@ -1369,6 +1374,7 @@ input_varpool_node (struct lto_file_decl
   node->writeonly = bp_unpack_value (&bp, 1);
   node->definition = bp_unpack_value (&bp, 1);
   node->alias = bp_unpack_value (&bp, 1);
+  node->transparent_alias = bp_unpack_value (&bp, 1);
   node->weakref = bp_unpack_value (&bp, 1);
   node->analyzed = bp_unpack_value (&bp, 1);
   node->used_from_other_partition = bp_unpack_value (&bp, 1);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]