@@ -803,8 +803,10 @@ varpool_node::finalize_decl (tree decl)
if (node->definition)
return;
- notice_global_symbol (decl);
+ /* Set definition first before calling notice_global_symbol so that
+ it is available to notice_global_symbol. */
node->definition = true;
+ notice_global_symbol (decl);
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. */
@@ -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@GOT\[(\]%ebx\[)\]" } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
long c;
@@ -3859,6 +3859,17 @@ mark_reachable_handlers (sbitmap *r_reachablep, sbitmap *lp_reachablep)
gimple_eh_dispatch_region (
as_a <geh_dispatch *> (stmt)));
break;
+ case GIMPLE_CALL:
+ if (gimple_call_builtin_p (stmt, BUILT_IN_EH_COPY_VALUES))
+ for (int i = 0; i < 2; ++i)
+ {
+ tree rt = gimple_call_arg (stmt, i);
+ HOST_WIDE_INT ri = tree_to_shwi (rt);
+
+ gcc_assert (ri = (int)ri);
+ bitmap_set_bit (r_reachable, ri);
+ }
+ break;
default:
break;
}
@@ -6776,123 +6776,98 @@ default_use_anchors_for_symbol_p (const_rtx symbol)
return true;
}
-/* Return true when RESOLUTION indicate that symbol will be bound to the
- definition provided by current .o file. */
-
static bool
-resolution_to_local_definition_p (enum ld_plugin_symbol_resolution resolution)
+default_binds_local_p_2 (const_tree exp, bool shlib, bool weak_dominate)
{
- return (resolution == LDPR_PREVAILING_DEF
- || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || resolution == LDPR_PREVAILING_DEF_IRONLY);
-}
-
-/* Return true when RESOLUTION indicate that symbol will be bound locally
- within current executable or DSO. */
-
-static bool
-resolution_local_p (enum ld_plugin_symbol_resolution resolution)
-{
- return (resolution == LDPR_PREVAILING_DEF
- || resolution == LDPR_PREVAILING_DEF_IRONLY
- || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || resolution == LDPR_PREEMPTED_REG
- || resolution == LDPR_PREEMPTED_IR
- || resolution == LDPR_RESOLVED_IR
- || resolution == LDPR_RESOLVED_EXEC);
-}
-
-/* Assume ELF-ish defaults, since that's pretty much the most liberal
- wrt cross-module name binding. */
+ /* A non-decl is an entry in the constant pool. */
+ if (!DECL_P (exp))
+ return true;
-bool
-default_binds_local_p (const_tree exp)
-{
- return default_binds_local_p_1 (exp, flag_shlib);
-}
+ /* 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))
+ || (TREE_CODE (exp) == FUNCTION_DECL
+ && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
+ return false;
-bool
-default_binds_local_p_1 (const_tree exp, int shlib)
-{
- bool local_p;
- bool resolved_locally = false;
- bool resolved_to_local_def = false;
+ /* Static variables are always local. */
+ if (! TREE_PUBLIC (exp))
+ return true;
/* 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. */
+ symtab_node *node = NULL;
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;
- }
+ node = varpool_node::get (exp);
else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
+ node = cgraph_node::get (exp);
+
+ bool resolved_locally = false;
+ if (node)
{
- struct cgraph_node *node = cgraph_node::get (exp);
- if (node
- && (resolution_local_p (node->resolution) || node->in_other_partition))
+ /* When not building shared library and weak_dominate is true:
+ weak, common or initialized symbols are resolved locally. */
+ if ((weak_dominate && !shlib && node->definition)
+ || node->in_other_partition
+ || 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 = 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;
- /* 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))
- || (TREE_CODE (exp) == FUNCTION_DECL
- && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
- local_p = 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;
+ /* Undefined (or non-dominant) weak symbols are not defined locally. */
+ if (DECL_WEAK (exp) && !resolved_locally)
+ return false;
+
+ /* If a strong or defined weak symbol has non-default visibility,
+ it must be defined locally. */
+ if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+ return 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. */
- else if (shlib)
- local_p = 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_EXTERNAL (exp) && !resolved_locally)
+ return false;
+
+ /* When compiling for a shared library, then assume that any global name
+ can be overridden by symbols resolved from other modules. */
+ if (shlib)
+ return false;
+
+ /* Uninitialized COMMON variable may be unified with symbols. */
+ 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. */
- return local_p;
+bool
+default_binds_local_p (const_tree exp)
+{
+ return default_binds_local_p_2 (exp, flag_shlib != 0, true);
+}
+
+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
@@ -7445,9 +7420,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);
}