===================================================================
@@ -10653,8 +10653,17 @@
{
rtx rtl = *rtlp;
+ /* Try to delegitimize address before check. */
if (GET_CODE (rtl) == UNSPEC)
{
+ rtx n = targetm.delegitimize_address (rtl);
+
+ if (GET_CODE (n) == SYMBOL_REF)
+ *rtlp = rtl = n;
+ }
+
+ 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
===================================================================
@@ -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
===================================================================
@@ -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;
}
===================================================================
@@ -13227,14 +13227,18 @@
if (TARGET_64BIT)
{
+ if (GET_CODE (x) == UNSPEC
+ && XINT (x, 1) == UNSPEC_PCREL)
+ return XVECEXP (x, 0, 0);
+
if (GET_CODE (x) != CONST
|| 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);