Revert: 2015-02-12 H.J. Lu Richard Henderson 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,97 +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 && !DECL_EXTERNAL (node->decl)) - || 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;