diff mbox

[PR,51900] : Fix PE's delegitimize_address functions

Message ID CAEwic4Yd4vawPqPi_wrkikSBUuwoen3uS30prRQNUeMGv36CVg@mail.gmail.com
State New
Headers show

Commit Message

Kai Tietz Jan. 22, 2012, 7:05 p.m. UTC
Hello,

this patch fixes reported issue in PR about common-symbols and fix
behavior about -fcommon/-fno-common.  Additionally it adds proper
support for weakref, local-variant of weaks, and tries to handle
resolution-file information for PE-COFF.

I did regression tests of all standard-languages for
x86_64-w64-mingw32 and i686-w64-mingw32.  Dave would you mind to test
it for cygwin, too?  I assume it will fit for cygwin, but just to make
sure.  Also I did a regression test for x86_64-unknown-linux-gnu.

Patch ok for apply?

Regards,
Kai

PS: Sorry missed first time subject-line
ChangeLog

2012-01-22  Kai Tietz  <ktietz@redhat.com>

	PR target/51900
	* dwarf2out.c (const_ok_for_output_1): Try to delegitimize
	address before checking for UNSPEC.
	* config/i386/predicates.md (symbolic_operand): Allow
	UNSPEC_PCREL as PIC expression for lea.
	* config/i386/winnt.c (i386_pe_binds_local_p): Reworked.
	* config/i386/i386.c (ix86_delegitimize_address): Handle
	UNSPEC_PCREL for none-MEM, too.
ChangeLog

2012-01-22  Kai Tietz  <ktietz@redhat.com>

	PR target/51900
	* dwarf2out.c (const_ok_for_output_1): Try to delegitimize
	address before checking for UNSPEC.
	* config/i386/predicates.md (symbolic_operand): Allow
	UNSPEC_PCREL as PIC expression for lea.
	* config/i386/winnt.c (i386_pe_binds_local_p): Reworked.
	* config/i386/i386.c (ix86_delegitimize_address): Handle
	UNSPEC_PCREL for none-MEM, too.

Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 183389)
+++ dwarf2out.c	(working copy)
@@ -10653,8 +10653,18 @@
 {
   rtx rtl = *rtlp;
 
+  /* Try to delegitimize address by adding a CONST in front.
+     This is required due pattern checked in delegitimize_address.  */
   if (GET_CODE (rtl) == UNSPEC)
     {
+      rtx newrtl = gen_rtx_CONST (Pmode, rtl);
+      newrtl = targetm.delegitimize_address (newrtl);
+      if (GET_CODE (newrtl) == SYMBOL_REF)
+        *rtlp = rtl = newrtl;
+    }
+
+  if (GET_CODE (rtl) == UNSPEC)
+    {
       /* If delegitimize_address couldn't do anything with the UNSPEC, assume
 	 we can't express it in the debug info.  */
 #ifdef ENABLE_CHECKING
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 183389)
+++ config/i386/predicates.md	(working copy)
@@ -410,6 +410,7 @@
 	  || (GET_CODE (op) == UNSPEC
 	      && (XINT (op, 1) == UNSPEC_GOT
 		  || XINT (op, 1) == UNSPEC_GOTOFF
+		  || XINT (op, 1) == UNSPEC_PCREL
 		  || XINT (op, 1) == UNSPEC_GOTPCREL)))
 	return true;
       if (GET_CODE (op) != PLUS
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 183389)
+++ config/i386/winnt.c	(working copy)
@@ -350,20 +350,101 @@
   SYMBOL_REF_FLAGS (symbol) = flags;
 }
 
+
 bool
 i386_pe_binds_local_p (const_tree exp)
 {
-  /* PE does not do dynamic binding.  Indeed, the only kind of
-     non-local reference comes from a dllimport'd symbol.  */
-  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
-      && DECL_DLLIMPORT_P (exp))
-    return false;
+  bool is_dllimported = false;
+  bool resolved_to_local_def = false;
+  bool resolved_locally = false;
 
-  /* Or a weak one, now that they are supported.  */
-  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
-      && DECL_WEAK (exp))
+  if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
+    is_dllimported = DECL_DLLIMPORT_P (exp);
+
+  if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
+      && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
+    {
+      struct varpool_node *vnode = varpool_get_node (exp);
+      if (vnode)
+        {
+	  if (vnode->resolution == LDPR_PREVAILING_DEF
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || vnode->resolution == LDPR_PREEMPTED_REG
+	      || vnode->resolution == LDPR_PREEMPTED_IR
+	      || vnode->resolution == LDPR_RESOLVED_IR
+	      || vnode->resolution == LDPR_RESOLVED_EXEC)
+	    resolved_locally = !is_dllimported;
+	  if (vnode->resolution == LDPR_PREVAILING_DEF
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
+	    resolved_to_local_def = true;
+	}
+    }
+  else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
+    {
+      struct cgraph_node *node = cgraph_get_node (exp);
+      if (node)
+        {
+	  if (node->resolution == LDPR_PREVAILING_DEF
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || node->resolution == LDPR_PREEMPTED_REG
+	      || node->resolution == LDPR_PREEMPTED_IR
+	      || node->resolution == LDPR_RESOLVED_IR
+	      || node->resolution == LDPR_RESOLVED_EXEC)
+	    resolved_locally = !is_dllimported;
+	  if (node->resolution == LDPR_PREVAILING_DEF
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY)
+	    resolved_to_local_def = true;
+	}
+    }
+
+  if (resolved_locally && is_dllimported)
+    resolved_locally = false;
+
+  if (!DECL_P (exp))
+    return true;
+  /* Weakrefs may not bind locally, even though the weakref itself is always
+     static and therefore local.
+     FIXME: We can resolve the weakref case more curefuly by looking at the
+     weakref alias.  */
+  else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)))
     return false;
-
+  /* Static variables are always local.  */
+  else if (! TREE_PUBLIC (exp))
+    return true;
+  /* A variable is local if the user has said explicitly that it will
+     be.  */
+  else if (!is_dllimported
+           && (DECL_VISIBILITY_SPECIFIED (exp)
+	       || resolved_to_local_def)
+	   && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+    return true;
+  /* Variables defined outside this object might not be local.  */
+  else if (DECL_EXTERNAL (exp) && !resolved_locally && is_dllimported)
+    return false;
+  /* If defined in this object and visibility is not default, must be
+     local.  */
+  else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+    return true;
+  /* Default visibility weak data can be overridden by a strong symbol
+     in another module and so are not local.  */
+  else if (is_dllimported)
+    return false;
+  else if (DECL_WEAK (exp)
+	   && (!resolved_locally || is_dllimported))
+    return false;
+  /* Uninitialized COMMON variable may be unified with symbols
+     resolved from other modules.  */
+  else if (DECL_COMMON (exp)
+	   && !resolved_locally
+	   && (DECL_INITIAL (exp) == NULL
+	       || DECL_INITIAL (exp) == error_mark_node))
+    return false;
+  /* Otherwise we're left with initialized (or non-common) global data
+     which is of necessity defined locally.  */
   return true;
 }
 
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 183389)
+++ config/i386/i386.c	(working copy)
@@ -13231,10 +13231,10 @@
 	  || GET_CODE (XEXP (x, 0)) != UNSPEC
 	  || (XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
 	      && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL)
-	  || !MEM_P (orig_x))
+	  || (!MEM_P (orig_x) && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL))
 	return ix86_delegitimize_tls_address (orig_x);
       x = XVECEXP (XEXP (x, 0), 0, 0);
-      if (GET_MODE (orig_x) != GET_MODE (x))
+      if (GET_MODE (orig_x) != GET_MODE (x) && MEM_P (orig_x))
 	{
 	  x = simplify_gen_subreg (GET_MODE (orig_x), x,
 				   GET_MODE (x), 0);

Comments

Jakub Jelinek Jan. 22, 2012, 7:35 p.m. UTC | #1
On Sun, Jan 22, 2012 at 08:05:12PM +0100, Kai Tietz wrote:
> this patch fixes reported issue in PR about common-symbols and fix
> behavior about -fcommon/-fno-common.  Additionally it adds proper
> support for weakref, local-variant of weaks, and tries to handle
> resolution-file information for PE-COFF.

The dwarf2out.c change looks wrong to me, either it is necessary
for it to be CONST to be delegitimized, then it should be really CONST in
the IL too, or it is not needed, then delegitimize_address those targets
should handle it even without CONST.

	Jakub
Kai Tietz Jan. 22, 2012, 7:40 p.m. UTC | #2
2012/1/22 Jakub Jelinek <jakub@redhat.com>:
> On Sun, Jan 22, 2012 at 08:05:12PM +0100, Kai Tietz wrote:
>> this patch fixes reported issue in PR about common-symbols and fix
>> behavior about -fcommon/-fno-common.  Additionally it adds proper
>> support for weakref, local-variant of weaks, and tries to handle
>> resolution-file information for PE-COFF.
>
> The dwarf2out.c change looks wrong to me, either it is necessary
> for it to be CONST to be delegitimized, then it should be really CONST in
> the IL too, or it is not needed, then delegitimize_address those targets
> should handle it even without CONST.

Well, it is CONST in IL, but CONST {  list-of-addresses }.
Ok, I will rework target's delegitimize_address and don't post-fix rtx
by CONST at call for in dwarf2out.  Would that be ok for you?

Kai
Richard Biener Jan. 23, 2012, 11:02 a.m. UTC | #3
On Sun, Jan 22, 2012 at 8:05 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
> Hello,
>
> this patch fixes reported issue in PR about common-symbols and fix
> behavior about -fcommon/-fno-common.  Additionally it adds proper
> support for weakref, local-variant of weaks, and tries to handle
> resolution-file information for PE-COFF.
>
> I did regression tests of all standard-languages for
> x86_64-w64-mingw32 and i686-w64-mingw32.  Dave would you mind to test
> it for cygwin, too?  I assume it will fit for cygwin, but just to make
> sure.  Also I did a regression test for x86_64-unknown-linux-gnu.
>
> Patch ok for apply?

As said in the PR your binds_local_p target hook should end with calling
default_binds_local_p[_1].  No need to duplicate all code in your hook
(it will quickly get out-of-date).

Richard.

> Regards,
> Kai
>
> PS: Sorry missed first time subject-line
> ChangeLog
>
> 2012-01-22  Kai Tietz  <ktietz@redhat.com>
>
>        PR target/51900
>        * dwarf2out.c (const_ok_for_output_1): Try to delegitimize
>        address before checking for UNSPEC.
>        * config/i386/predicates.md (symbolic_operand): Allow
>        UNSPEC_PCREL as PIC expression for lea.
>        * config/i386/winnt.c (i386_pe_binds_local_p): Reworked.
>        * config/i386/i386.c (ix86_delegitimize_address): Handle
>        UNSPEC_PCREL for none-MEM, too.
>
> Index: dwarf2out.c
> ===================================================================
> --- dwarf2out.c (revision 183389)
> +++ dwarf2out.c (working copy)
> @@ -10653,8 +10653,18 @@
>  {
>   rtx rtl = *rtlp;
>
> +  /* Try to delegitimize address by adding a CONST in front.
> +     This is required due pattern checked in delegitimize_address.  */
>   if (GET_CODE (rtl) == UNSPEC)
>     {
> +      rtx newrtl = gen_rtx_CONST (Pmode, rtl);
> +      newrtl = targetm.delegitimize_address (newrtl);
> +      if (GET_CODE (newrtl) == SYMBOL_REF)
> +        *rtlp = rtl = newrtl;
> +    }
> +
> +  if (GET_CODE (rtl) == UNSPEC)
> +    {
>       /* If delegitimize_address couldn't do anything with the UNSPEC, assume
>         we can't express it in the debug info.  */
>  #ifdef ENABLE_CHECKING
> Index: config/i386/predicates.md
> ===================================================================
> --- config/i386/predicates.md   (revision 183389)
> +++ config/i386/predicates.md   (working copy)
> @@ -410,6 +410,7 @@
>          || (GET_CODE (op) == UNSPEC
>              && (XINT (op, 1) == UNSPEC_GOT
>                  || XINT (op, 1) == UNSPEC_GOTOFF
> +                 || XINT (op, 1) == UNSPEC_PCREL
>                  || XINT (op, 1) == UNSPEC_GOTPCREL)))
>        return true;
>       if (GET_CODE (op) != PLUS
> Index: config/i386/winnt.c
> ===================================================================
> --- config/i386/winnt.c (revision 183389)
> +++ config/i386/winnt.c (working copy)
> @@ -350,20 +350,101 @@
>   SYMBOL_REF_FLAGS (symbol) = flags;
>  }
>
> +
>  bool
>  i386_pe_binds_local_p (const_tree exp)
>  {
> -  /* PE does not do dynamic binding.  Indeed, the only kind of
> -     non-local reference comes from a dllimport'd symbol.  */
> -  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
> -      && DECL_DLLIMPORT_P (exp))
> -    return false;
> +  bool is_dllimported = false;
> +  bool resolved_to_local_def = false;
> +  bool resolved_locally = false;
>
> -  /* Or a weak one, now that they are supported.  */
> -  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
> -      && DECL_WEAK (exp))
> +  if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
> +    is_dllimported = DECL_DLLIMPORT_P (exp);
> +
> +  if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
> +      && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
> +    {
> +      struct varpool_node *vnode = varpool_get_node (exp);
> +      if (vnode)
> +        {
> +         if (vnode->resolution == LDPR_PREVAILING_DEF
> +             || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
> +             || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> +             || vnode->resolution == LDPR_PREEMPTED_REG
> +             || vnode->resolution == LDPR_PREEMPTED_IR
> +             || vnode->resolution == LDPR_RESOLVED_IR
> +             || vnode->resolution == LDPR_RESOLVED_EXEC)
> +           resolved_locally = !is_dllimported;
> +         if (vnode->resolution == LDPR_PREVAILING_DEF
> +             || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> +             || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
> +           resolved_to_local_def = true;
> +       }
> +    }
> +  else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
> +    {
> +      struct cgraph_node *node = cgraph_get_node (exp);
> +      if (node)
> +        {
> +         if (node->resolution == LDPR_PREVAILING_DEF
> +             || node->resolution == LDPR_PREVAILING_DEF_IRONLY
> +             || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> +             || node->resolution == LDPR_PREEMPTED_REG
> +             || node->resolution == LDPR_PREEMPTED_IR
> +             || node->resolution == LDPR_RESOLVED_IR
> +             || node->resolution == LDPR_RESOLVED_EXEC)
> +           resolved_locally = !is_dllimported;
> +         if (node->resolution == LDPR_PREVAILING_DEF
> +             || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> +             || node->resolution == LDPR_PREVAILING_DEF_IRONLY)
> +           resolved_to_local_def = true;
> +       }
> +    }
> +
> +  if (resolved_locally && is_dllimported)
> +    resolved_locally = false;
> +
> +  if (!DECL_P (exp))
> +    return true;
> +  /* Weakrefs may not bind locally, even though the weakref itself is always
> +     static and therefore local.
> +     FIXME: We can resolve the weakref case more curefuly by looking at the
> +     weakref alias.  */
> +  else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)))
>     return false;
> -
> +  /* Static variables are always local.  */
> +  else if (! TREE_PUBLIC (exp))
> +    return true;
> +  /* A variable is local if the user has said explicitly that it will
> +     be.  */
> +  else if (!is_dllimported
> +           && (DECL_VISIBILITY_SPECIFIED (exp)
> +              || resolved_to_local_def)
> +          && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
> +    return true;
> +  /* Variables defined outside this object might not be local.  */
> +  else if (DECL_EXTERNAL (exp) && !resolved_locally && is_dllimported)
> +    return false;
> +  /* If defined in this object and visibility is not default, must be
> +     local.  */
> +  else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
> +    return true;
> +  /* Default visibility weak data can be overridden by a strong symbol
> +     in another module and so are not local.  */
> +  else if (is_dllimported)
> +    return false;
> +  else if (DECL_WEAK (exp)
> +          && (!resolved_locally || is_dllimported))
> +    return false;
> +  /* Uninitialized COMMON variable may be unified with symbols
> +     resolved from other modules.  */
> +  else if (DECL_COMMON (exp)
> +          && !resolved_locally
> +          && (DECL_INITIAL (exp) == NULL
> +              || DECL_INITIAL (exp) == error_mark_node))
> +    return false;
> +  /* Otherwise we're left with initialized (or non-common) global data
> +     which is of necessity defined locally.  */
>   return true;
>  }
>
> Index: config/i386/i386.c
> ===================================================================
> --- config/i386/i386.c  (revision 183389)
> +++ config/i386/i386.c  (working copy)
> @@ -13231,10 +13231,10 @@
>          || GET_CODE (XEXP (x, 0)) != UNSPEC
>          || (XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
>              && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL)
> -         || !MEM_P (orig_x))
> +         || (!MEM_P (orig_x) && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL))
>        return ix86_delegitimize_tls_address (orig_x);
>       x = XVECEXP (XEXP (x, 0), 0, 0);
> -      if (GET_MODE (orig_x) != GET_MODE (x))
> +      if (GET_MODE (orig_x) != GET_MODE (x) && MEM_P (orig_x))
>        {
>          x = simplify_gen_subreg (GET_MODE (orig_x), x,
>                                   GET_MODE (x), 0);
Kai Tietz Jan. 23, 2012, 11:19 a.m. UTC | #4
2012/1/23 Richard Guenther <richard.guenther@gmail.com>:
> On Sun, Jan 22, 2012 at 8:05 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>> Hello,
>>
>> this patch fixes reported issue in PR about common-symbols and fix
>> behavior about -fcommon/-fno-common.  Additionally it adds proper
>> support for weakref, local-variant of weaks, and tries to handle
>> resolution-file information for PE-COFF.
>>
>> I did regression tests of all standard-languages for
>> x86_64-w64-mingw32 and i686-w64-mingw32.  Dave would you mind to test
>> it for cygwin, too?  I assume it will fit for cygwin, but just to make
>> sure.  Also I did a regression test for x86_64-unknown-linux-gnu.
>>
>> Patch ok for apply?
>
> As said in the PR your binds_local_p target hook should end with calling
> default_binds_local_p[_1].  No need to duplicate all code in your hook
> (it will quickly get out-of-date).
>
> Richard.

Well, issue here is the following block in default_binds_local_p_1:

...
  /* Variables defined outside this object might not be local.  */
  else if (DECL_EXTERNAL (exp) && !resolved_locally)
    local_p = false;
...

This condition is only true for PE-coff, if dllimport attribute was specified.

I will try to adjust patch for this, but some redudant checkings are
necessary here for sure.

Kai
Richard Biener Jan. 23, 2012, 11:27 a.m. UTC | #5
On Mon, Jan 23, 2012 at 12:19 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
> 2012/1/23 Richard Guenther <richard.guenther@gmail.com>:
>> On Sun, Jan 22, 2012 at 8:05 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>>> Hello,
>>>
>>> this patch fixes reported issue in PR about common-symbols and fix
>>> behavior about -fcommon/-fno-common.  Additionally it adds proper
>>> support for weakref, local-variant of weaks, and tries to handle
>>> resolution-file information for PE-COFF.
>>>
>>> I did regression tests of all standard-languages for
>>> x86_64-w64-mingw32 and i686-w64-mingw32.  Dave would you mind to test
>>> it for cygwin, too?  I assume it will fit for cygwin, but just to make
>>> sure.  Also I did a regression test for x86_64-unknown-linux-gnu.
>>>
>>> Patch ok for apply?
>>
>> As said in the PR your binds_local_p target hook should end with calling
>> default_binds_local_p[_1].  No need to duplicate all code in your hook
>> (it will quickly get out-of-date).
>>
>> Richard.
>
> Well, issue here is the following block in default_binds_local_p_1:
>
> ...
>  /* Variables defined outside this object might not be local.  */
>  else if (DECL_EXTERNAL (exp) && !resolved_locally)
>    local_p = false;
> ...
>
> This condition is only true for PE-coff, if dllimport attribute was specified.

That would be a missed-optimization fix, please just fix the wrong-code
regression at this stage.

Richard.

> I will try to adjust patch for this, but some redudant checkings are
> necessary here for sure.

Thta

> Kai
Kai Tietz Jan. 23, 2012, 11:32 a.m. UTC | #6
2012/1/23 Richard Guenther <richard.guenther@gmail.com>:
> On Mon, Jan 23, 2012 at 12:19 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>> 2012/1/23 Richard Guenther <richard.guenther@gmail.com>:
>>> On Sun, Jan 22, 2012 at 8:05 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>>>> Hello,
>>>>
>>>> this patch fixes reported issue in PR about common-symbols and fix
>>>> behavior about -fcommon/-fno-common.  Additionally it adds proper
>>>> support for weakref, local-variant of weaks, and tries to handle
>>>> resolution-file information for PE-COFF.
>>>>
>>>> I did regression tests of all standard-languages for
>>>> x86_64-w64-mingw32 and i686-w64-mingw32.  Dave would you mind to test
>>>> it for cygwin, too?  I assume it will fit for cygwin, but just to make
>>>> sure.  Also I did a regression test for x86_64-unknown-linux-gnu.
>>>>
>>>> Patch ok for apply?
>>>
>>> As said in the PR your binds_local_p target hook should end with calling
>>> default_binds_local_p[_1].  No need to duplicate all code in your hook
>>> (it will quickly get out-of-date).
>>>
>>> Richard.
>>
>> Well, issue here is the following block in default_binds_local_p_1:
>>
>> ...
>>  /* Variables defined outside this object might not be local.  */
>>  else if (DECL_EXTERNAL (exp) && !resolved_locally)
>>    local_p = false;
>> ...
>>
>> This condition is only true for PE-coff, if dllimport attribute was specified.
>
> That would be a missed-optimization fix, please just fix the wrong-code
> regression at this stage.
>
> Richard.

Hmm, 'missed-optimization'?  If I would call current variant directly
without checking for externals, I would introduce wrong code
generation, as it would introduce via the back-door use of GOT-tables
for x86_64 PE+, which aren't present.

>> I will try to adjust patch for this, but some redudant checkings are
>> necessary here for sure.
>
> Thta
>
>> Kai
diff mbox

Patch

Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 183389)
+++ dwarf2out.c	(working copy)
@@ -10653,8 +10653,18 @@ 
 {
   rtx rtl = *rtlp;

+  /* Try to delegitimize address by adding a CONST in front.
+     This is required due pattern checked in delegitimize_address.  */
   if (GET_CODE (rtl) == UNSPEC)
     {
+      rtx newrtl = gen_rtx_CONST (Pmode, rtl);
+      newrtl = targetm.delegitimize_address (newrtl);
+      if (GET_CODE (newrtl) == SYMBOL_REF)
+        *rtlp = rtl = newrtl;
+    }
+
+  if (GET_CODE (rtl) == UNSPEC)
+    {
       /* If delegitimize_address couldn't do anything with the UNSPEC, assume
 	 we can't express it in the debug info.  */
 #ifdef ENABLE_CHECKING
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 183389)
+++ config/i386/predicates.md	(working copy)
@@ -410,6 +410,7 @@ 
 	  || (GET_CODE (op) == UNSPEC
 	      && (XINT (op, 1) == UNSPEC_GOT
 		  || XINT (op, 1) == UNSPEC_GOTOFF
+		  || XINT (op, 1) == UNSPEC_PCREL
 		  || XINT (op, 1) == UNSPEC_GOTPCREL)))
 	return true;
       if (GET_CODE (op) != PLUS
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 183389)
+++ config/i386/winnt.c	(working copy)
@@ -350,20 +350,101 @@ 
   SYMBOL_REF_FLAGS (symbol) = flags;
 }

+
 bool
 i386_pe_binds_local_p (const_tree exp)
 {
-  /* PE does not do dynamic binding.  Indeed, the only kind of
-     non-local reference comes from a dllimport'd symbol.  */
-  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
-      && DECL_DLLIMPORT_P (exp))
-    return false;
+  bool is_dllimported = false;
+  bool resolved_to_local_def = false;
+  bool resolved_locally = false;

-  /* Or a weak one, now that they are supported.  */
-  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
-      && DECL_WEAK (exp))
+  if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
+    is_dllimported = DECL_DLLIMPORT_P (exp);
+
+  if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
+      && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
+    {
+      struct varpool_node *vnode = varpool_get_node (exp);
+      if (vnode)
+        {
+	  if (vnode->resolution == LDPR_PREVAILING_DEF
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || vnode->resolution == LDPR_PREEMPTED_REG
+	      || vnode->resolution == LDPR_PREEMPTED_IR
+	      || vnode->resolution == LDPR_RESOLVED_IR
+	      || vnode->resolution == LDPR_RESOLVED_EXEC)
+	    resolved_locally = !is_dllimported;
+	  if (vnode->resolution == LDPR_PREVAILING_DEF
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
+	    resolved_to_local_def = true;
+	}
+    }
+  else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
+    {
+      struct cgraph_node *node = cgraph_get_node (exp);
+      if (node)
+        {
+	  if (node->resolution == LDPR_PREVAILING_DEF
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || node->resolution == LDPR_PREEMPTED_REG
+	      || node->resolution == LDPR_PREEMPTED_IR
+	      || node->resolution == LDPR_RESOLVED_IR
+	      || node->resolution == LDPR_RESOLVED_EXEC)
+	    resolved_locally = !is_dllimported;
+	  if (node->resolution == LDPR_PREVAILING_DEF
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+	      || node->resolution == LDPR_PREVAILING_DEF_IRONLY)
+	    resolved_to_local_def = true;
+	}
+    }
+
+  if (resolved_locally && is_dllimported)
+    resolved_locally = false;
+
+  if (!DECL_P (exp))
+    return true;
+  /* Weakrefs may not bind locally, even though the weakref itself is always
+     static and therefore local.
+     FIXME: We can resolve the weakref case more curefuly by looking at the
+     weakref alias.  */
+  else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)))
     return false;
-
+  /* Static variables are always local.  */
+  else if (! TREE_PUBLIC (exp))
+    return true;
+  /* A variable is local if the user has said explicitly that it will
+     be.  */
+  else if (!is_dllimported
+           && (DECL_VISIBILITY_SPECIFIED (exp)
+	       || resolved_to_local_def)
+	   && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+    return true;
+  /* Variables defined outside this object might not be local.  */
+  else if (DECL_EXTERNAL (exp) && !resolved_locally && is_dllimported)
+    return false;
+  /* If defined in this object and visibility is not default, must be
+     local.  */
+  else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+    return true;
+  /* Default visibility weak data can be overridden by a strong symbol
+     in another module and so are not local.  */
+  else if (is_dllimported)
+    return false;
+  else if (DECL_WEAK (exp)
+	   && (!resolved_locally || is_dllimported))
+    return false;
+  /* Uninitialized COMMON variable may be unified with symbols
+     resolved from other modules.  */
+  else if (DECL_COMMON (exp)
+	   && !resolved_locally
+	   && (DECL_INITIAL (exp) == NULL
+	       || DECL_INITIAL (exp) == error_mark_node))
+    return false;
+  /* Otherwise we're left with initialized (or non-common) global data
+     which is of necessity defined locally.  */
   return true;
 }

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 183389)
+++ config/i386/i386.c	(working copy)
@@ -13231,10 +13231,10 @@ 
 	  || GET_CODE (XEXP (x, 0)) != UNSPEC
 	  || (XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
 	      && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL)
-	  || !MEM_P (orig_x))
+	  || (!MEM_P (orig_x) && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL))
 	return ix86_delegitimize_tls_address (orig_x);
       x = XVECEXP (XEXP (x, 0), 0, 0);
-      if (GET_MODE (orig_x) != GET_MODE (x))
+      if (GET_MODE (orig_x) != GET_MODE (x) && MEM_P (orig_x))
 	{
 	  x = simplify_gen_subreg (GET_MODE (orig_x), x,
 				   GET_MODE (x), 0);