aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2015-02-13 04:52:45 +0000
committerRichard Henderson <rth@gcc.gnu.org>2015-02-12 20:52:45 -0800
commit6a1e352e1efbdf33a3df892dadd725f0b09c70c9 (patch)
tree0b7c95151ce5d3baedf0ed3fc3544b11a92ae3a7 /gcc/varasm.c
parentfa47895fe650bc724adbdb3d5fd24348fd315277 (diff)
downloadgcc-6a1e352e1efbdf33a3df892dadd725f0b09c70c9.zip
gcc-6a1e352e1efbdf33a3df892dadd725f0b09c70c9.tar.gz
gcc-6a1e352e1efbdf33a3df892dadd725f0b09c70c9.tar.bz2
re PR rtl-optimization/32219 (optimizer causes wrong code in pic/hidden/weak symbol checking.)
PR rtl/32219 gcc/ * 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/testsuite/ * gcc.dg/visibility-22.c: New test. * gcc.dg/visibility-23.c: New test. * gcc.target/i386/pr32219-1.c: New test. * gcc.target/i386/pr32219-2.c: New test. * gcc.target/i386/pr32219-3.c: New test. * gcc.target/i386/pr32219-4.c: New test. * gcc.target/i386/pr32219-5.c: New test. * gcc.target/i386/pr32219-6.c: New test. * gcc.target/i386/pr32219-7.c: New test. * gcc.target/i386/pr32219-8.c: New test. * gcc.target/i386/pr64317.c: Expect GOTOFF, not GOT. Co-Authored-By: Richard Henderson <rth@redhat.com> From-SVN: r220674
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c166
1 files changed, 79 insertions, 87 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 3f62fca..0211306 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6802,97 +6802,96 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution)
|| resolution == LDPR_RESOLVED_EXEC);
}
-/* 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)
+static bool
+default_binds_local_p_2 (const_tree exp, bool shlib, bool weak_dominate)
{
- 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))
- local_p = true;
+ return 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. */
- else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
+ if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
|| (TREE_CODE (exp) == FUNCTION_DECL
&& lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
- local_p = false;
+ return false;
+
/* Static variables are always local. */
- 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 (! 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;
+
/* If PIC, then assume that any global name can be overridden by
symbols resolved from other modules. */
- else if (shlib)
- local_p = false;
+ 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;
+
/* Uninitialized COMMON variable may be unified with symbols
resolved from other modules. */
- else if (DECL_COMMON (exp)
- && !resolved_locally
- && (DECL_INITIAL (exp) == NULL
- || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
- local_p = false;
+ if (DECL_COMMON (exp)
+ && !resolved_locally
+ && (DECL_INITIAL (exp) == NULL
+ || (!in_lto_p && 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. */
- else
- local_p = true;
+ 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);
+}
- return local_p;
+bool
+default_binds_local_p_1 (const_tree exp, int shlib)
+{
+ return default_binds_local_p_2 (exp, shlib != 0, false);
}
/* Return true when references to DECL must bind to current definition in
@@ -6914,22 +6913,14 @@ decl_binds_to_current_def_p (const_tree decl)
return false;
if (!TREE_PUBLIC (decl))
return true;
+
/* When resolution is available, just use it. */
- if (TREE_CODE (decl) == VAR_DECL
- && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ if (symtab_node *node = symtab_node::get (decl))
{
- 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)
+ if (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
@@ -7449,9 +7440,10 @@ default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
{
/* 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. */
+ used. Always output visibility specified in the source. */
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
- && targetm.binds_local_p (decl))
+ && (DECL_VISIBILITY_SPECIFIED (decl)
+ || targetm.binds_local_p (decl)))
maybe_assemble_visibility (decl);
}