Blob Blame History Raw
Revert:
2015-02-12  H.J. Lu  <hongjiu.lu@intel.com>
	    Richard Henderson  <rth@redhat.com>

	PR rtl/32219
	* cgraphunit.c (cgraph_node::finalize_function): Set definition
	before notice_global_symbol.
	(varpool_node::finalize_decl): Likewise.
	* varasm.c (default_binds_local_p_2): Rename from
	default_binds_local_p_1, add weak_dominate argument.  Use direct
	returns instead of assigning to local variable.  Unify varpool and
	cgraph paths via symtab_node.  Reject undef weak variables before
	testing visibility.  Reorder tests for simplicity.
	(default_binds_local_p): Use default_binds_local_p_2.
	(default_binds_local_p_1): Likewise.
	(decl_binds_to_current_def_p): Unify varpool and cgraph paths
	via symtab_node.
	(default_elf_asm_output_external): Emit visibility when specified.

--- gcc/cgraphunit.c	(revision 220674)
+++ gcc/cgraphunit.c	(revision 220673)
@@ -442,10 +442,8 @@ cgraph_node::finalize_function (tree dec
       node->local.redefined_extern_inline = true;
     }
 
-  /* Set definition first before calling notice_global_symbol so that
-     it is available to notice_global_symbol.  */
-  node->definition = true;
   notice_global_symbol (decl);
+  node->definition = true;
   node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
 
   /* With -fkeep-inline-functions we are keeping all inline functions except
@@ -805,10 +803,8 @@ varpool_node::finalize_decl (tree decl)
 
   if (node->definition)
     return;
-  /* Set definition first before calling notice_global_symbol so that
-     it is available to notice_global_symbol.  */
-  node->definition = true;
   notice_global_symbol (decl);
+  node->definition = true;
   if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
       /* Traditionally we do not eliminate static variables when not
 	 optimizing and when not doing toplevel reoder.  */
--- gcc/varasm.c	(revision 220674)
+++ gcc/varasm.c	(revision 220673)
@@ -6802,96 +6802,97 @@ resolution_local_p (enum ld_plugin_symbo
 	  || resolution == LDPR_RESOLVED_EXEC);
 }
 
-static bool
-default_binds_local_p_2 (const_tree exp, bool shlib, bool weak_dominate)
+/* Assume ELF-ish defaults, since that's pretty much the most liberal
+   wrt cross-module name binding.  */
+
+bool
+default_binds_local_p (const_tree exp)
 {
+  return default_binds_local_p_1 (exp, flag_shlib);
+}
+
+bool
+default_binds_local_p_1 (const_tree exp, int shlib)
+{
+  bool local_p;
+  bool resolved_locally = false;
+  bool resolved_to_local_def = false;
+
+  /* With resolution file in hands, take look into resolutions.
+     We can't just return true for resolved_locally symbols,
+     because dynamic linking might overwrite symbols
+     in shared libraries.  */
+  if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
+      && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
+    {
+      varpool_node *vnode = varpool_node::get (exp);
+      if (vnode && (resolution_local_p (vnode->resolution) || vnode->in_other_partition))
+	resolved_locally = true;
+      if (vnode
+	  && resolution_to_local_definition_p (vnode->resolution))
+	resolved_to_local_def = true;
+    }
+  else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
+    {
+      struct cgraph_node *node = cgraph_node::get (exp);
+      if (node
+	  && (resolution_local_p (node->resolution) || node->in_other_partition))
+	resolved_locally = true;
+      if (node
+	  && resolution_to_local_definition_p (node->resolution))
+	resolved_to_local_def = true;
+    }
+
   /* A non-decl is an entry in the constant pool.  */
   if (!DECL_P (exp))
-    return true;
-
+    local_p = true;
   /* Weakrefs may not bind locally, even though the weakref itself is always
      static and therefore local.  Similarly, the resolver for ifunc functions
      might resolve to a non-local function.
      FIXME: We can resolve the weakref case more curefuly by looking at the
      weakref alias.  */
-  if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
+  else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
 	   || (TREE_CODE (exp) == FUNCTION_DECL
 	       && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
-    return false;
-
+    local_p = false;
   /* Static variables are always local.  */
-  if (! TREE_PUBLIC (exp))
-    return true;
-
-  /* With resolution file in hand, take look into resolutions.
-     We can't just return true for resolved_locally symbols,
-     because dynamic linking might overwrite symbols
-     in shared libraries.  */
-  bool resolved_locally = false;
-  bool defined_locally = false;
-  if (symtab_node *node = symtab_node::get (exp))
-    {
-      if (node->definition || node->in_other_partition)
-	{
-	  defined_locally = true;
-	  resolved_locally = (weak_dominate && !shlib);
-	}
-      if (resolution_to_local_definition_p (node->resolution))
-	defined_locally = resolved_locally = true;
-      else if (resolution_local_p (node->resolution))
-	resolved_locally = true;
-    }
-
-  /* Undefined weak symbols are never defined locally.  */
-  if (DECL_WEAK (exp) && !defined_locally)
-    return false;
-
-  /* A symbol is local if the user has said explicitly that it will be,
-     or if we have a definition for the symbol.  We cannot infer visibility
-     for undefined symbols.  */
-  if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT
-      && (DECL_VISIBILITY_SPECIFIED (exp) || defined_locally))
-    return true;
-
+  else if (! TREE_PUBLIC (exp))
+    local_p = true;
+  /* A variable is local if the user has said explicitly that it will
+     be.  */
+  else if ((DECL_VISIBILITY_SPECIFIED (exp)
+	    || resolved_to_local_def)
+	   && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+    local_p = true;
+  /* Variables defined outside this object might not be local.  */
+  else if (DECL_EXTERNAL (exp) && !resolved_locally)
+    local_p = false;
+  /* If defined in this object and visibility is not default, must be
+     local.  */
+  else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+    local_p = true;
+  /* Default visibility weak data can be overridden by a strong symbol
+     in another module and so are not local.  */
+  else if (DECL_WEAK (exp)
+	   && !resolved_locally)
+    local_p = false;
   /* If PIC, then assume that any global name can be overridden by
      symbols resolved from other modules.  */
-  if (shlib)
-    return false;
-
-  /* Variables defined outside this object might not be local.  */
-  if (DECL_EXTERNAL (exp) && !resolved_locally)
-    return false;
-
-  /* Non-dominant weak symbols are not defined locally.  */
-  if (DECL_WEAK (exp) && !resolved_locally)
-    return false;
-
+  else if (shlib)
+    local_p = false;
   /* Uninitialized COMMON variable may be unified with symbols
      resolved from other modules.  */
-  if (DECL_COMMON (exp)
-      && !resolved_locally
-      && (DECL_INITIAL (exp) == NULL
-	  || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
-    return false;
-
+  else if (DECL_COMMON (exp)
+	   && !resolved_locally
+	   && (DECL_INITIAL (exp) == NULL
+	       || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
+    local_p = false;
   /* Otherwise we're left with initialized (or non-common) global data
      which is of necessity defined locally.  */
-  return true;
-}
-
-/* Assume ELF-ish defaults, since that's pretty much the most liberal
-   wrt cross-module name binding.  */
-
-bool
-default_binds_local_p (const_tree exp)
-{
-  return default_binds_local_p_2 (exp, flag_shlib != 0, true);
-}
+  else
+    local_p = true;
 
-bool
-default_binds_local_p_1 (const_tree exp, int shlib)
-{
-  return default_binds_local_p_2 (exp, shlib != 0, false);
+  return local_p;
 }
 
 /* Return true when references to DECL must bind to current definition in
@@ -6913,14 +6914,22 @@ decl_binds_to_current_def_p (const_tree
     return false;
   if (!TREE_PUBLIC (decl))
     return true;
-
   /* When resolution is available, just use it.  */
-  if (symtab_node *node = symtab_node::get (decl))
+  if (TREE_CODE (decl) == VAR_DECL
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
     {
-      if (node->resolution != LDPR_UNKNOWN)
+      varpool_node *vnode = varpool_node::get (decl);
+      if (vnode
+	  && vnode->resolution != LDPR_UNKNOWN)
+	return resolution_to_local_definition_p (vnode->resolution);
+    }
+  else if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      struct cgraph_node *node = cgraph_node::get (decl);
+      if (node
+	  && node->resolution != LDPR_UNKNOWN)
 	return resolution_to_local_definition_p (node->resolution);
     }
-
   /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks
      binds locally but still can be overwritten), DECL_COMMON (can be merged
      with a non-common definition somewhere in the same module) or
@@ -7440,10 +7449,9 @@ default_elf_asm_output_external (FILE *f
 {
   /* We output the name if and only if TREE_SYMBOL_REFERENCED is
      set in order to avoid putting out names that are never really
-     used.  Always output visibility specified in the source.  */
+     used. */
   if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
-      && (DECL_VISIBILITY_SPECIFIED (decl)
-	  || targetm.binds_local_p (decl)))
+      && targetm.binds_local_p (decl))
     maybe_assemble_visibility (decl);
 }
 
--- gcc/testsuite/gcc.target/i386/pr64317.c	(revision 220674)
+++ gcc/testsuite/gcc.target/i386/pr64317.c	(revision 220673)
@@ -1,7 +1,7 @@
 /* { dg-do compile { target { *-*-linux* && ia32 } } } */
 /* { dg-options "-O2 -fpie" } */
 /* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
-/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOT\[(\]%ebx\[)\]" } } */
 /* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
 long c;