mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-07 11:33:45 +08:00
re PR lto/61886 (LTO breaks fread with _FORTIFY_SOURCE=2)
PR ipa/61886 * symtab.c (ultimate_transparent_alias_target): New inline function. (symbol_table::assembler_names_equal_p): New method; break out from ... (symbol_table::decl_assembler_name_equal): ... here. (symbol_table::change_decl_assembler_name): Also update names and translation links of transparent aliases. (symtab_node::dump_base): Dump transparent_alias. (symtab_node::verify_base): Implement basic transparent alias verification. (symtab_node::make_decl_local): Support localization of weakrefs; recurse to transparent aliases; set TREE_STATIC. (symtab_node::ultimate_alias_target_1): Handle visibility of transparent aliases. (symtab_node::resolve_alias): New parmaeter transparent; handle transparent aliases; recurse to aliases of aliases to fix comdat groups. (symtab_node::get_partitioning_class): Handle transparent aliases. * ipa-visibility.c (cgraph_externally_visible_p, varpool_node::externally_visible_p): Visibility of transparent alias depends on its target. (function_and_variable_visibility): Do not tweak visibility of transparent laiases. (function_and_variable_visibility): Likewise. * ipa.c (symbol_table::remove_unreachable_nodes): Clear transparent_alias flag. * alias.c (cgraph_node::create_alias, cgraph_node::get_availability): Support transparent aliases. * cgraph.h (symtab_node): Update prototype of resolve_alias; add transparent_alias flag. (symbol_table: Add assembler_names_equal_p. (symtab_node::real_symbol_p): Skip transparent aliases. * cgraphunit.c (cgraph_node::reset): Reset transparent_alias flag. (handle_alias_pairs): Set transparent_alias for weakref. (cgraph_node::assemble_thunks_and_aliases): Do not asemble transparent aliases. * lto-cgraph.c (lto_output_node): When outputting same_comdat_group skip symbols not put into boundary; stream transparent_alias. (lto_output_varpool_node): Likewise. (input_overwrite_node, input_varpool_node): Stream transparent alias. * varpool.c (ctor_for_folding, varpool_node::get_availability, varpool_node::assemble_aliases, symbol_table::remove_unreferenced_decls): Handle transparent aliase. (varpool_node::create_alias): Set transparent_alias. * lto-partition.c (add_symbol_to_partition_1, contained_in_symbol, rename_statics, rename_statics): Handle transparent aliases. From-SVN: r231373
This commit is contained in:
parent
058c6384fe
commit
71e546870c
@ -1,3 +1,49 @@
|
|||||||
|
2015-12-07 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
|
PR ipa/61886
|
||||||
|
* symtab.c (ultimate_transparent_alias_target): New inline function.
|
||||||
|
(symbol_table::assembler_names_equal_p): New method; break out from ...
|
||||||
|
(symbol_table::decl_assembler_name_equal): ... here.
|
||||||
|
(symbol_table::change_decl_assembler_name): Also update names and
|
||||||
|
translation links of transparent aliases.
|
||||||
|
(symtab_node::dump_base): Dump transparent_alias.
|
||||||
|
(symtab_node::verify_base): Implement basic transparent alias
|
||||||
|
verification.
|
||||||
|
(symtab_node::make_decl_local): Support localization of weakrefs;
|
||||||
|
recurse to transparent aliases; set TREE_STATIC.
|
||||||
|
(symtab_node::ultimate_alias_target_1): Handle visibility of
|
||||||
|
transparent aliases.
|
||||||
|
(symtab_node::resolve_alias): New parmaeter transparent; handle
|
||||||
|
transparent aliases; recurse to aliases of aliases to fix comdat
|
||||||
|
groups.
|
||||||
|
(symtab_node::get_partitioning_class): Handle transparent aliases.
|
||||||
|
* ipa-visibility.c (cgraph_externally_visible_p,
|
||||||
|
varpool_node::externally_visible_p): Visibility of transparent alias
|
||||||
|
depends on its target.
|
||||||
|
(function_and_variable_visibility): Do not tweak visibility of
|
||||||
|
transparent laiases.
|
||||||
|
(function_and_variable_visibility): Likewise.
|
||||||
|
* ipa.c (symbol_table::remove_unreachable_nodes): Clear
|
||||||
|
transparent_alias flag.
|
||||||
|
* alias.c (cgraph_node::create_alias, cgraph_node::get_availability):
|
||||||
|
Support transparent aliases.
|
||||||
|
* cgraph.h (symtab_node): Update prototype of resolve_alias;
|
||||||
|
add transparent_alias flag.
|
||||||
|
(symbol_table: Add assembler_names_equal_p.
|
||||||
|
(symtab_node::real_symbol_p): Skip transparent aliases.
|
||||||
|
* cgraphunit.c (cgraph_node::reset): Reset transparent_alias flag.
|
||||||
|
(handle_alias_pairs): Set transparent_alias for weakref.
|
||||||
|
(cgraph_node::assemble_thunks_and_aliases): Do not asemble transparent
|
||||||
|
aliases.
|
||||||
|
* lto-cgraph.c (lto_output_node): When outputting same_comdat_group
|
||||||
|
skip symbols not put into boundary; stream transparent_alias.
|
||||||
|
(lto_output_varpool_node): Likewise.
|
||||||
|
(input_overwrite_node, input_varpool_node): Stream transparent alias.
|
||||||
|
* varpool.c (ctor_for_folding, varpool_node::get_availability,
|
||||||
|
varpool_node::assemble_aliases,
|
||||||
|
symbol_table::remove_unreferenced_decls): Handle transparent aliase.
|
||||||
|
(varpool_node::create_alias): Set transparent_alias.
|
||||||
|
|
||||||
2015-12-07 Eric Botcazou <ebotcazou@adacore.com>
|
2015-12-07 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
PR middle-end/68291
|
PR middle-end/68291
|
||||||
|
@ -560,7 +560,7 @@ cgraph_node::create_alias (tree alias, tree target)
|
|||||||
alias_node->definition = true;
|
alias_node->definition = true;
|
||||||
alias_node->alias = true;
|
alias_node->alias = true;
|
||||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
|
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
|
||||||
alias_node->weakref = true;
|
alias_node->transparent_alias = alias_node->weakref = true;
|
||||||
return alias_node;
|
return alias_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2147,7 +2147,7 @@ cgraph_node::get_availability (void)
|
|||||||
avail = AVAIL_NOT_AVAILABLE;
|
avail = AVAIL_NOT_AVAILABLE;
|
||||||
else if (local.local)
|
else if (local.local)
|
||||||
avail = AVAIL_LOCAL;
|
avail = AVAIL_LOCAL;
|
||||||
else if (alias && weakref)
|
else if (transparent_alias)
|
||||||
ultimate_alias_target (&avail);
|
ultimate_alias_target (&avail);
|
||||||
else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
|
else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
|
||||||
avail = AVAIL_INTERPOSABLE;
|
avail = AVAIL_INTERPOSABLE;
|
||||||
|
31
gcc/cgraph.h
31
gcc/cgraph.h
@ -249,9 +249,10 @@ public:
|
|||||||
inline symtab_node *next_defined_symbol (void);
|
inline symtab_node *next_defined_symbol (void);
|
||||||
|
|
||||||
/* Add reference recording that symtab node is alias of TARGET.
|
/* Add reference recording that symtab node is alias of TARGET.
|
||||||
|
If TRANSPARENT is true make the alias to be transparent alias.
|
||||||
The function can fail in the case of aliasing cycles; in this case
|
The function can fail in the case of aliasing cycles; in this case
|
||||||
it returns false. */
|
it returns false. */
|
||||||
bool resolve_alias (symtab_node *target);
|
bool resolve_alias (symtab_node *target, bool transparent = false);
|
||||||
|
|
||||||
/* C++ FE sometimes change linkage flags after producing same
|
/* C++ FE sometimes change linkage flags after producing same
|
||||||
body aliases. */
|
body aliases. */
|
||||||
@ -421,6 +422,28 @@ public:
|
|||||||
/* True when symbol is an alias.
|
/* True when symbol is an alias.
|
||||||
Set by ssemble_alias. */
|
Set by ssemble_alias. */
|
||||||
unsigned alias : 1;
|
unsigned alias : 1;
|
||||||
|
/* When true the alias is translated into its target symbol either by GCC
|
||||||
|
or assembler (it also may just be a duplicate declaration of the same
|
||||||
|
linker name).
|
||||||
|
|
||||||
|
Currently transparent aliases come in three different flavors
|
||||||
|
- aliases having the same assembler name as their target (aka duplicated
|
||||||
|
declarations). In this case the assembler names compare via
|
||||||
|
assembler_names_equal_p and weakref is false
|
||||||
|
- aliases that are renamed at a time being output to final file
|
||||||
|
by varasm.c. For those DECL_ASSEMBLER_NAME have
|
||||||
|
IDENTIFIER_TRANSPARENT_ALIAS set and thus also their assembler
|
||||||
|
name must be unique.
|
||||||
|
Weakrefs belong to this cateogry when we target assembler without
|
||||||
|
.weakref directive.
|
||||||
|
- weakrefs that are renamed by assembler via .weakref directive.
|
||||||
|
In this case the alias may or may not be definition (depending if
|
||||||
|
target declaration was seen by the compiler), weakref is set.
|
||||||
|
Unless we are before renaming statics, assembler names are different.
|
||||||
|
|
||||||
|
Given that we now support duplicate declarations, the second option is
|
||||||
|
redundant and will be removed. */
|
||||||
|
unsigned transparent_alias : 1;
|
||||||
/* True when alias is a weakref. */
|
/* True when alias is a weakref. */
|
||||||
unsigned weakref : 1;
|
unsigned weakref : 1;
|
||||||
/* C++ frontend produce same body aliases and extra name aliases for
|
/* C++ frontend produce same body aliases and extra name aliases for
|
||||||
@ -2098,6 +2121,10 @@ public:
|
|||||||
/* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */
|
/* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */
|
||||||
void change_decl_assembler_name (tree decl, tree name);
|
void change_decl_assembler_name (tree decl, tree name);
|
||||||
|
|
||||||
|
/* Return true if assembler names NAME1 and NAME2 leads to the same symbol
|
||||||
|
name. */
|
||||||
|
static bool assembler_names_equal_p (const char *name1, const char *name2);
|
||||||
|
|
||||||
int cgraph_count;
|
int cgraph_count;
|
||||||
int cgraph_max_uid;
|
int cgraph_max_uid;
|
||||||
int cgraph_max_summary_uid;
|
int cgraph_max_summary_uid;
|
||||||
@ -2251,6 +2278,8 @@ symtab_node::real_symbol_p (void)
|
|||||||
|
|
||||||
if (DECL_ABSTRACT_P (decl))
|
if (DECL_ABSTRACT_P (decl))
|
||||||
return false;
|
return false;
|
||||||
|
if (transparent_alias && definition)
|
||||||
|
return false;
|
||||||
if (!is_a <cgraph_node *> (this))
|
if (!is_a <cgraph_node *> (this))
|
||||||
return true;
|
return true;
|
||||||
cnode = dyn_cast <cgraph_node *> (this);
|
cnode = dyn_cast <cgraph_node *> (this);
|
||||||
|
@ -369,6 +369,7 @@ cgraph_node::reset (void)
|
|||||||
analyzed = false;
|
analyzed = false;
|
||||||
definition = false;
|
definition = false;
|
||||||
alias = false;
|
alias = false;
|
||||||
|
transparent_alias = false;
|
||||||
weakref = false;
|
weakref = false;
|
||||||
cpp_implicit_alias = false;
|
cpp_implicit_alias = false;
|
||||||
|
|
||||||
@ -594,7 +595,7 @@ cgraph_node::analyze (void)
|
|||||||
thunk.alias = NULL;
|
thunk.alias = NULL;
|
||||||
}
|
}
|
||||||
if (alias)
|
if (alias)
|
||||||
resolve_alias (cgraph_node::get (alias_target));
|
resolve_alias (cgraph_node::get (alias_target), transparent_alias);
|
||||||
else if (dispatcher_function)
|
else if (dispatcher_function)
|
||||||
{
|
{
|
||||||
/* Generate the dispatcher body of multi-versioned functions. */
|
/* Generate the dispatcher body of multi-versioned functions. */
|
||||||
@ -1254,6 +1255,7 @@ handle_alias_pairs (void)
|
|||||||
node->alias_target = p->target;
|
node->alias_target = p->target;
|
||||||
node->weakref = true;
|
node->weakref = true;
|
||||||
node->alias = true;
|
node->alias = true;
|
||||||
|
node->transparent_alias = true;
|
||||||
}
|
}
|
||||||
alias_pairs->unordered_remove (i);
|
alias_pairs->unordered_remove (i);
|
||||||
continue;
|
continue;
|
||||||
@ -1908,15 +1910,18 @@ cgraph_node::assemble_thunks_and_aliases (void)
|
|||||||
FOR_EACH_ALIAS (this, ref)
|
FOR_EACH_ALIAS (this, ref)
|
||||||
{
|
{
|
||||||
cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
|
cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
|
||||||
bool saved_written = TREE_ASM_WRITTEN (decl);
|
if (!alias->transparent_alias)
|
||||||
|
{
|
||||||
|
bool saved_written = TREE_ASM_WRITTEN (decl);
|
||||||
|
|
||||||
/* Force assemble_alias to really output the alias this time instead
|
/* Force assemble_alias to really output the alias this time instead
|
||||||
of buffering it in same alias pairs. */
|
of buffering it in same alias pairs. */
|
||||||
TREE_ASM_WRITTEN (decl) = 1;
|
TREE_ASM_WRITTEN (decl) = 1;
|
||||||
do_assemble_alias (alias->decl,
|
do_assemble_alias (alias->decl,
|
||||||
DECL_ASSEMBLER_NAME (decl));
|
DECL_ASSEMBLER_NAME (decl));
|
||||||
alias->assemble_thunks_and_aliases ();
|
alias->assemble_thunks_and_aliases ();
|
||||||
TREE_ASM_WRITTEN (decl) = saved_written;
|
TREE_ASM_WRITTEN (decl) = saved_written;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +185,8 @@ static bool
|
|||||||
cgraph_externally_visible_p (struct cgraph_node *node,
|
cgraph_externally_visible_p (struct cgraph_node *node,
|
||||||
bool whole_program)
|
bool whole_program)
|
||||||
{
|
{
|
||||||
|
while (node->transparent_alias && node->definition)
|
||||||
|
node = node->get_alias_target ();
|
||||||
if (!node->definition)
|
if (!node->definition)
|
||||||
return false;
|
return false;
|
||||||
if (!TREE_PUBLIC (node->decl)
|
if (!TREE_PUBLIC (node->decl)
|
||||||
@ -248,6 +250,8 @@ cgraph_externally_visible_p (struct cgraph_node *node,
|
|||||||
bool
|
bool
|
||||||
varpool_node::externally_visible_p (void)
|
varpool_node::externally_visible_p (void)
|
||||||
{
|
{
|
||||||
|
while (transparent_alias && definition)
|
||||||
|
return get_alias_target ()->externally_visible_p ();
|
||||||
if (DECL_EXTERNAL (decl))
|
if (DECL_EXTERNAL (decl))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -531,7 +535,8 @@ function_and_variable_visibility (bool whole_program)
|
|||||||
next->set_comdat_group (NULL);
|
next->set_comdat_group (NULL);
|
||||||
if (!next->alias)
|
if (!next->alias)
|
||||||
next->set_section (NULL);
|
next->set_section (NULL);
|
||||||
next->make_decl_local ();
|
if (!next->transparent_alias)
|
||||||
|
next->make_decl_local ();
|
||||||
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
||||||
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
||||||
&& TREE_PUBLIC (next->decl)
|
&& TREE_PUBLIC (next->decl)
|
||||||
@ -547,7 +552,8 @@ function_and_variable_visibility (bool whole_program)
|
|||||||
node->set_comdat_group (NULL);
|
node->set_comdat_group (NULL);
|
||||||
if (DECL_COMDAT (node->decl) && !node->alias)
|
if (DECL_COMDAT (node->decl) && !node->alias)
|
||||||
node->set_section (NULL);
|
node->set_section (NULL);
|
||||||
node->make_decl_local ();
|
if (!node->transparent_alias)
|
||||||
|
node->make_decl_local ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->thunk.thunk_p
|
if (node->thunk.thunk_p
|
||||||
@ -654,7 +660,7 @@ function_and_variable_visibility (bool whole_program)
|
|||||||
DECL_ATTRIBUTES (vnode->decl)))
|
DECL_ATTRIBUTES (vnode->decl)))
|
||||||
vnode->no_reorder = 1;
|
vnode->no_reorder = 1;
|
||||||
if (!vnode->externally_visible
|
if (!vnode->externally_visible
|
||||||
&& !vnode->weakref)
|
&& !vnode->transparent_alias)
|
||||||
{
|
{
|
||||||
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
|
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
|
||||||
vnode->unique_name |= ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
|
vnode->unique_name |= ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
|
||||||
@ -675,11 +681,14 @@ function_and_variable_visibility (bool whole_program)
|
|||||||
next->set_comdat_group (NULL);
|
next->set_comdat_group (NULL);
|
||||||
if (!next->alias)
|
if (!next->alias)
|
||||||
next->set_section (NULL);
|
next->set_section (NULL);
|
||||||
next->make_decl_local ();
|
if (!next->transparent_alias)
|
||||||
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
{
|
||||||
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
next->make_decl_local ();
|
||||||
&& TREE_PUBLIC (next->decl)
|
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
||||||
&& !flag_incremental_link);
|
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
||||||
|
&& TREE_PUBLIC (next->decl)
|
||||||
|
&& !flag_incremental_link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vnode->dissolve_same_comdat_group_list ();
|
vnode->dissolve_same_comdat_group_list ();
|
||||||
}
|
}
|
||||||
@ -687,8 +696,11 @@ function_and_variable_visibility (bool whole_program)
|
|||||||
vnode->set_comdat_group (NULL);
|
vnode->set_comdat_group (NULL);
|
||||||
if (DECL_COMDAT (vnode->decl) && !vnode->alias)
|
if (DECL_COMDAT (vnode->decl) && !vnode->alias)
|
||||||
vnode->set_section (NULL);
|
vnode->set_section (NULL);
|
||||||
vnode->make_decl_local ();
|
if (!vnode->transparent_alias)
|
||||||
vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
{
|
||||||
|
vnode->make_decl_local ();
|
||||||
|
vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
update_visibility_by_resolution_info (vnode);
|
update_visibility_by_resolution_info (vnode);
|
||||||
|
|
||||||
|
@ -543,6 +543,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
|
|||||||
node->definition = false;
|
node->definition = false;
|
||||||
node->cpp_implicit_alias = false;
|
node->cpp_implicit_alias = false;
|
||||||
node->alias = false;
|
node->alias = false;
|
||||||
|
node->transparent_alias = false;
|
||||||
node->thunk.thunk_p = false;
|
node->thunk.thunk_p = false;
|
||||||
node->weakref = false;
|
node->weakref = false;
|
||||||
/* After early inlining we drop always_inline attributes on
|
/* After early inlining we drop always_inline attributes on
|
||||||
|
@ -485,11 +485,12 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|
|||||||
|
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
if (node->same_comdat_group && !boundary_p)
|
if (node->same_comdat_group)
|
||||||
{
|
{
|
||||||
ref = lto_symtab_encoder_lookup (encoder,
|
ref = LCC_NOT_FOUND;
|
||||||
node->same_comdat_group);
|
for (struct symtab_node *n = node->same_comdat_group;
|
||||||
gcc_assert (ref != LCC_NOT_FOUND);
|
ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
|
||||||
|
ref = lto_symtab_encoder_lookup (encoder, n);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ref = LCC_NOT_FOUND;
|
ref = LCC_NOT_FOUND;
|
||||||
@ -523,6 +524,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|
|||||||
bp_pack_value (&bp, node->lowered, 1);
|
bp_pack_value (&bp, node->lowered, 1);
|
||||||
bp_pack_value (&bp, in_other_partition, 1);
|
bp_pack_value (&bp, in_other_partition, 1);
|
||||||
bp_pack_value (&bp, node->alias, 1);
|
bp_pack_value (&bp, node->alias, 1);
|
||||||
|
bp_pack_value (&bp, node->transparent_alias, 1);
|
||||||
bp_pack_value (&bp, node->weakref, 1);
|
bp_pack_value (&bp, node->weakref, 1);
|
||||||
bp_pack_value (&bp, node->frequency, 2);
|
bp_pack_value (&bp, node->frequency, 2);
|
||||||
bp_pack_value (&bp, node->only_called_at_startup, 1);
|
bp_pack_value (&bp, node->only_called_at_startup, 1);
|
||||||
@ -599,8 +601,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
|
|||||||
bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
|
bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
|
||||||
1);
|
1);
|
||||||
bp_pack_value (&bp, node->alias, 1);
|
bp_pack_value (&bp, node->alias, 1);
|
||||||
|
bp_pack_value (&bp, node->transparent_alias, 1);
|
||||||
bp_pack_value (&bp, node->weakref, 1);
|
bp_pack_value (&bp, node->weakref, 1);
|
||||||
bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
|
bp_pack_value (&bp, node->analyzed && (!boundary_p || node->alias), 1);
|
||||||
gcc_assert (node->definition || !node->analyzed);
|
gcc_assert (node->definition || !node->analyzed);
|
||||||
/* Constant pool initializers can be de-unified into individual ltrans units.
|
/* Constant pool initializers can be de-unified into individual ltrans units.
|
||||||
FIXME: Alternatively at -Os we may want to avoid generating for them the local
|
FIXME: Alternatively at -Os we may want to avoid generating for them the local
|
||||||
@ -632,11 +635,12 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
|
|||||||
|
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
if (node->same_comdat_group && !boundary_p)
|
if (node->same_comdat_group)
|
||||||
{
|
{
|
||||||
ref = lto_symtab_encoder_lookup (encoder,
|
ref = LCC_NOT_FOUND;
|
||||||
node->same_comdat_group);
|
for (struct symtab_node *n = node->same_comdat_group;
|
||||||
gcc_assert (ref != LCC_NOT_FOUND);
|
ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
|
||||||
|
ref = lto_symtab_encoder_lookup (encoder, n);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ref = LCC_NOT_FOUND;
|
ref = LCC_NOT_FOUND;
|
||||||
@ -1170,6 +1174,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
|
|||||||
TREE_STATIC (node->decl) = 0;
|
TREE_STATIC (node->decl) = 0;
|
||||||
}
|
}
|
||||||
node->alias = bp_unpack_value (bp, 1);
|
node->alias = bp_unpack_value (bp, 1);
|
||||||
|
node->transparent_alias = bp_unpack_value (bp, 1);
|
||||||
node->weakref = bp_unpack_value (bp, 1);
|
node->weakref = bp_unpack_value (bp, 1);
|
||||||
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
|
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
|
||||||
node->only_called_at_startup = bp_unpack_value (bp, 1);
|
node->only_called_at_startup = bp_unpack_value (bp, 1);
|
||||||
@ -1369,6 +1374,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
|
|||||||
node->writeonly = bp_unpack_value (&bp, 1);
|
node->writeonly = bp_unpack_value (&bp, 1);
|
||||||
node->definition = bp_unpack_value (&bp, 1);
|
node->definition = bp_unpack_value (&bp, 1);
|
||||||
node->alias = bp_unpack_value (&bp, 1);
|
node->alias = bp_unpack_value (&bp, 1);
|
||||||
|
node->transparent_alias = bp_unpack_value (&bp, 1);
|
||||||
node->weakref = bp_unpack_value (&bp, 1);
|
node->weakref = bp_unpack_value (&bp, 1);
|
||||||
node->analyzed = bp_unpack_value (&bp, 1);
|
node->analyzed = bp_unpack_value (&bp, 1);
|
||||||
node->used_from_other_partition = bp_unpack_value (&bp, 1);
|
node->used_from_other_partition = bp_unpack_value (&bp, 1);
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2015-12-07 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
|
PR ipa/61886
|
||||||
|
* lto-partition.c (add_symbol_to_partition_1, contained_in_symbol,
|
||||||
|
rename_statics, rename_statics): Handle transparent aliases.
|
||||||
|
|
||||||
2015-12-04 Jan Hubicka <hubicka@ucw.cz>
|
2015-12-04 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
* lto-symtab.c (lto_cgraph_replace_node): Update code computing
|
* lto-symtab.c (lto_cgraph_replace_node): Update code computing
|
||||||
|
@ -1035,7 +1035,15 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node *node)
|
|||||||
/* Assign every symbol in the set that shares the same ASM name an unique
|
/* Assign every symbol in the set that shares the same ASM name an unique
|
||||||
mangled name. */
|
mangled name. */
|
||||||
for (s = symtab_node::get_for_asmname (name); s;)
|
for (s = symtab_node::get_for_asmname (name); s;)
|
||||||
if (!s->externally_visible
|
if ((!s->externally_visible || s->weakref)
|
||||||
|
/* Transparent aliases having same name as target are renamed at a
|
||||||
|
time their target gets new name. Transparent aliases that use
|
||||||
|
separate assembler name require the name to be unique. */
|
||||||
|
&& (!s->transparent_alias || !s->definition || s->weakref
|
||||||
|
|| !symbol_table::assembler_names_equal_p
|
||||||
|
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (s->decl)),
|
||||||
|
IDENTIFIER_POINTER
|
||||||
|
(DECL_ASSEMBLER_NAME (s->get_alias_target()->decl))))
|
||||||
&& ((s->real_symbol_p ()
|
&& ((s->real_symbol_p ()
|
||||||
&& !DECL_EXTERNAL (node->decl)
|
&& !DECL_EXTERNAL (node->decl)
|
||||||
&& !TREE_PUBLIC (node->decl))
|
&& !TREE_PUBLIC (node->decl))
|
||||||
|
266
gcc/symtab.c
266
gcc/symtab.c
@ -52,6 +52,26 @@ const char * const ld_plugin_symbol_resolution_names[]=
|
|||||||
"prevailing_def_ironly_exp"
|
"prevailing_def_ironly_exp"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at ALIAS
|
||||||
|
until we find an identifier that is not itself a transparent alias. */
|
||||||
|
|
||||||
|
static inline tree
|
||||||
|
ultimate_transparent_alias_target (tree alias)
|
||||||
|
{
|
||||||
|
tree target = alias;
|
||||||
|
|
||||||
|
while (IDENTIFIER_TRANSPARENT_ALIAS (target))
|
||||||
|
{
|
||||||
|
gcc_checking_assert (TREE_CHAIN (target));
|
||||||
|
target = TREE_CHAIN (target);
|
||||||
|
}
|
||||||
|
gcc_checking_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
|
||||||
|
&& ! TREE_CHAIN (target));
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Hash asmnames ignoring the user specified marks. */
|
/* Hash asmnames ignoring the user specified marks. */
|
||||||
|
|
||||||
hashval_t
|
hashval_t
|
||||||
@ -73,6 +93,44 @@ symbol_table::decl_assembler_name_hash (const_tree asmname)
|
|||||||
return htab_hash_string (IDENTIFIER_POINTER (asmname));
|
return htab_hash_string (IDENTIFIER_POINTER (asmname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if assembler names NAME1 and NAME2 leads to the same symbol
|
||||||
|
name. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
symbol_table::assembler_names_equal_p (const char *name1, const char *name2)
|
||||||
|
{
|
||||||
|
if (name1 != name2)
|
||||||
|
{
|
||||||
|
if (name1[0] == '*')
|
||||||
|
{
|
||||||
|
size_t ulp_len = strlen (user_label_prefix);
|
||||||
|
|
||||||
|
name1 ++;
|
||||||
|
|
||||||
|
if (ulp_len == 0)
|
||||||
|
;
|
||||||
|
else if (strncmp (name1, user_label_prefix, ulp_len) == 0)
|
||||||
|
name1 += ulp_len;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (name2[0] == '*')
|
||||||
|
{
|
||||||
|
size_t ulp_len = strlen (user_label_prefix);
|
||||||
|
|
||||||
|
name2 ++;
|
||||||
|
|
||||||
|
if (ulp_len == 0)
|
||||||
|
;
|
||||||
|
else if (strncmp (name2, user_label_prefix, ulp_len) == 0)
|
||||||
|
name2 += ulp_len;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !strcmp (name1, name2);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
|
/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
|
||||||
|
|
||||||
@ -82,51 +140,13 @@ symbol_table::decl_assembler_name_equal (tree decl, const_tree asmname)
|
|||||||
tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
|
tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
|
||||||
const char *decl_str;
|
const char *decl_str;
|
||||||
const char *asmname_str;
|
const char *asmname_str;
|
||||||
bool test = false;
|
|
||||||
|
|
||||||
if (decl_asmname == asmname)
|
if (decl_asmname == asmname)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
decl_str = IDENTIFIER_POINTER (decl_asmname);
|
decl_str = IDENTIFIER_POINTER (decl_asmname);
|
||||||
asmname_str = IDENTIFIER_POINTER (asmname);
|
asmname_str = IDENTIFIER_POINTER (asmname);
|
||||||
|
return assembler_names_equal_p (decl_str, asmname_str);
|
||||||
|
|
||||||
/* If the target assembler name was set by the user, things are trickier.
|
|
||||||
We have a leading '*' to begin with. After that, it's arguable what
|
|
||||||
is the correct thing to do with -fleading-underscore. Arguably, we've
|
|
||||||
historically been doing the wrong thing in assemble_alias by always
|
|
||||||
printing the leading underscore. Since we're not changing that, make
|
|
||||||
sure user_label_prefix follows the '*' before matching. */
|
|
||||||
if (decl_str[0] == '*')
|
|
||||||
{
|
|
||||||
size_t ulp_len = strlen (user_label_prefix);
|
|
||||||
|
|
||||||
decl_str ++;
|
|
||||||
|
|
||||||
if (ulp_len == 0)
|
|
||||||
test = true;
|
|
||||||
else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
|
|
||||||
decl_str += ulp_len, test=true;
|
|
||||||
else
|
|
||||||
decl_str --;
|
|
||||||
}
|
|
||||||
if (asmname_str[0] == '*')
|
|
||||||
{
|
|
||||||
size_t ulp_len = strlen (user_label_prefix);
|
|
||||||
|
|
||||||
asmname_str ++;
|
|
||||||
|
|
||||||
if (ulp_len == 0)
|
|
||||||
test = true;
|
|
||||||
else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
|
|
||||||
asmname_str += ulp_len, test=true;
|
|
||||||
else
|
|
||||||
asmname_str --;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!test)
|
|
||||||
return false;
|
|
||||||
return strcmp (decl_str, asmname_str) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -273,6 +293,8 @@ symbol_table::change_decl_assembler_name (tree decl, tree name)
|
|||||||
: NULL);
|
: NULL);
|
||||||
if (node)
|
if (node)
|
||||||
unlink_from_assembler_name_hash (node, true);
|
unlink_from_assembler_name_hash (node, true);
|
||||||
|
|
||||||
|
const char *old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||||
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|
||||||
&& DECL_RTL_SET_P (decl))
|
&& DECL_RTL_SET_P (decl))
|
||||||
warning (0, "%D renamed after being referenced in assembly", decl);
|
warning (0, "%D renamed after being referenced in assembly", decl);
|
||||||
@ -283,8 +305,48 @@ symbol_table::change_decl_assembler_name (tree decl, tree name)
|
|||||||
IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
|
IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
|
||||||
TREE_CHAIN (name) = alias;
|
TREE_CHAIN (name) = alias;
|
||||||
}
|
}
|
||||||
|
/* If we change assembler name, also all transparent aliases must
|
||||||
|
be updated. There are three kinds - those having same assembler name,
|
||||||
|
those being renamed in varasm.c and weakref being renamed by the
|
||||||
|
assembler. */
|
||||||
if (node)
|
if (node)
|
||||||
insert_to_assembler_name_hash (node, true);
|
{
|
||||||
|
insert_to_assembler_name_hash (node, true);
|
||||||
|
ipa_ref *ref;
|
||||||
|
for (unsigned i = 0; node->iterate_direct_aliases (i, ref); i++)
|
||||||
|
{
|
||||||
|
struct symtab_node *alias = ref->referring;
|
||||||
|
if (alias->transparent_alias && !alias->weakref
|
||||||
|
&& symbol_table::assembler_names_equal_p
|
||||||
|
(old_name, IDENTIFIER_POINTER (
|
||||||
|
DECL_ASSEMBLER_NAME (alias->decl))))
|
||||||
|
change_decl_assembler_name (alias->decl, name);
|
||||||
|
else if (alias->transparent_alias
|
||||||
|
&& IDENTIFIER_TRANSPARENT_ALIAS (alias->decl))
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CHAIN (DECL_ASSEMBLER_NAME (alias->decl))
|
||||||
|
&& IDENTIFIER_TRANSPARENT_ALIAS
|
||||||
|
(DECL_ASSEMBLER_NAME (alias->decl)));
|
||||||
|
|
||||||
|
TREE_CHAIN (DECL_ASSEMBLER_NAME (alias->decl)) =
|
||||||
|
ultimate_transparent_alias_target
|
||||||
|
(DECL_ASSEMBLER_NAME (node->decl));
|
||||||
|
}
|
||||||
|
#ifdef ASM_OUTPUT_WEAKREF
|
||||||
|
else gcc_assert (!alias->transparent_alias || alias->weakref);
|
||||||
|
#else
|
||||||
|
else gcc_assert (!alias->transparent_alias);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
gcc_assert (!node->transparent_alias || !node->definition
|
||||||
|
|| node->weakref
|
||||||
|
|| TREE_CHAIN (DECL_ASSEMBLER_NAME (decl))
|
||||||
|
|| symbol_table::assembler_names_equal_p
|
||||||
|
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
|
||||||
|
IDENTIFIER_POINTER
|
||||||
|
(DECL_ASSEMBLER_NAME
|
||||||
|
(node->get_alias_target ()->decl))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -727,6 +789,8 @@ symtab_node::dump_base (FILE *f)
|
|||||||
fprintf (f, " analyzed");
|
fprintf (f, " analyzed");
|
||||||
if (alias)
|
if (alias)
|
||||||
fprintf (f, " alias");
|
fprintf (f, " alias");
|
||||||
|
if (transparent_alias)
|
||||||
|
fprintf (f, " transparent_alias");
|
||||||
if (weakref)
|
if (weakref)
|
||||||
fprintf (f, " weakref");
|
fprintf (f, " weakref");
|
||||||
if (cpp_implicit_alias)
|
if (cpp_implicit_alias)
|
||||||
@ -973,9 +1037,14 @@ symtab_node::verify_base (void)
|
|||||||
error ("node is alias but not definition");
|
error ("node is alias but not definition");
|
||||||
error_found = true;
|
error_found = true;
|
||||||
}
|
}
|
||||||
if (weakref && !alias)
|
if (weakref && !transparent_alias)
|
||||||
{
|
{
|
||||||
error ("node is weakref but not an alias");
|
error ("node is weakref but not an transparent_alias");
|
||||||
|
error_found = true;
|
||||||
|
}
|
||||||
|
if (transparent_alias && !alias)
|
||||||
|
{
|
||||||
|
error ("node is transparent_alias but not an alias");
|
||||||
error_found = true;
|
error_found = true;
|
||||||
}
|
}
|
||||||
if (same_comdat_group)
|
if (same_comdat_group)
|
||||||
@ -1061,6 +1130,29 @@ symtab_node::verify_base (void)
|
|||||||
get_alias_target ()->dump (stderr);
|
get_alias_target ()->dump (stderr);
|
||||||
error_found = true;
|
error_found = true;
|
||||||
}
|
}
|
||||||
|
if (transparent_alias && definition && !weakref)
|
||||||
|
{
|
||||||
|
symtab_node *to = get_alias_target ();
|
||||||
|
const char *name1
|
||||||
|
= IDENTIFIER_POINTER (
|
||||||
|
ultimate_transparent_alias_target (DECL_ASSEMBLER_NAME (decl)));
|
||||||
|
const char *name2
|
||||||
|
= IDENTIFIER_POINTER (
|
||||||
|
ultimate_transparent_alias_target (DECL_ASSEMBLER_NAME (to->decl)));
|
||||||
|
if (!symbol_table::assembler_names_equal_p (name1, name2))
|
||||||
|
{
|
||||||
|
error ("Transparent alias and target's assembler names differs");
|
||||||
|
get_alias_target ()->dump (stderr);
|
||||||
|
error_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (transparent_alias && definition
|
||||||
|
&& get_alias_target()->transparent_alias && get_alias_target()->analyzed)
|
||||||
|
{
|
||||||
|
error ("Chained transparent aliases");
|
||||||
|
get_alias_target ()->dump (stderr);
|
||||||
|
error_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
return error_found;
|
return error_found;
|
||||||
}
|
}
|
||||||
@ -1132,15 +1224,35 @@ symtab_node::make_decl_local (void)
|
|||||||
{
|
{
|
||||||
rtx rtl, symbol;
|
rtx rtl, symbol;
|
||||||
|
|
||||||
|
if (weakref)
|
||||||
|
{
|
||||||
|
weakref = false;
|
||||||
|
IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) = 0;
|
||||||
|
TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) = NULL_TREE;
|
||||||
|
symtab->change_decl_assembler_name
|
||||||
|
(decl, DECL_ASSEMBLER_NAME (get_alias_target ()->decl));
|
||||||
|
DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
|
||||||
|
DECL_ATTRIBUTES (decl));
|
||||||
|
}
|
||||||
/* Avoid clearing comdat_groups on comdat-local decls. */
|
/* Avoid clearing comdat_groups on comdat-local decls. */
|
||||||
if (TREE_PUBLIC (decl) == 0)
|
else if (TREE_PUBLIC (decl) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Localizing a symbol also make all its transparent aliases local. */
|
||||||
|
ipa_ref *ref;
|
||||||
|
for (unsigned i = 0; iterate_direct_aliases (i, ref); i++)
|
||||||
|
{
|
||||||
|
struct symtab_node *alias = ref->referring;
|
||||||
|
if (alias->transparent_alias)
|
||||||
|
alias->make_decl_local ();
|
||||||
|
}
|
||||||
|
|
||||||
if (TREE_CODE (decl) == VAR_DECL)
|
if (TREE_CODE (decl) == VAR_DECL)
|
||||||
{
|
{
|
||||||
DECL_COMMON (decl) = 0;
|
DECL_COMMON (decl) = 0;
|
||||||
/* ADDRESSABLE flag is not defined for public symbols. */
|
/* ADDRESSABLE flag is not defined for public symbols. */
|
||||||
TREE_ADDRESSABLE (decl) = 1;
|
TREE_ADDRESSABLE (decl) = 1;
|
||||||
|
TREE_STATIC (decl) = 1;
|
||||||
}
|
}
|
||||||
else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
|
else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
|
||||||
|
|
||||||
@ -1175,29 +1287,28 @@ symtab_node::make_decl_local (void)
|
|||||||
symtab_node *
|
symtab_node *
|
||||||
symtab_node::ultimate_alias_target_1 (enum availability *availability)
|
symtab_node::ultimate_alias_target_1 (enum availability *availability)
|
||||||
{
|
{
|
||||||
bool weakref_p = false;
|
bool transparent_p = false;
|
||||||
|
|
||||||
/* To determine visibility of the target, we follow ELF semantic of aliases.
|
/* To determine visibility of the target, we follow ELF semantic of aliases.
|
||||||
Here alias is an alternative assembler name of a given definition. Its
|
Here alias is an alternative assembler name of a given definition. Its
|
||||||
availability prevails the availability of its target (i.e. static alias of
|
availability prevails the availability of its target (i.e. static alias of
|
||||||
weak definition is available.
|
weak definition is available.
|
||||||
|
|
||||||
Weakref is a different animal (and not part of ELF per se). It is just
|
Transaparent alias is just alternative anme of a given symbol used within
|
||||||
alternative name of a given symbol used within one complation unit
|
one compilation unit and is translated prior hitting the object file. It
|
||||||
and is translated prior hitting the object file. It inherits the
|
inherits the visibility of its target.
|
||||||
visibility of its target (i.e. weakref of non-overwritable definition
|
Weakref is a different animal (and noweak definition is weak).
|
||||||
is non-overwritable, while weakref of weak definition is weak).
|
|
||||||
|
|
||||||
If we ever get into supporting targets with different semantics, a target
|
If we ever get into supporting targets with different semantics, a target
|
||||||
hook will be needed here. */
|
hook will be needed here. */
|
||||||
|
|
||||||
if (availability)
|
if (availability)
|
||||||
{
|
{
|
||||||
weakref_p = weakref;
|
transparent_p = transparent_alias;
|
||||||
if (!weakref_p)
|
if (!transparent_p)
|
||||||
*availability = get_availability ();
|
*availability = get_availability ();
|
||||||
else
|
else
|
||||||
*availability = AVAIL_LOCAL;
|
*availability = AVAIL_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
symtab_node *node = this;
|
symtab_node *node = this;
|
||||||
@ -1207,27 +1318,19 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability)
|
|||||||
node = node->get_alias_target ();
|
node = node->get_alias_target ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!availability)
|
if (!availability || (!transparent_p && node->analyzed))
|
||||||
;
|
;
|
||||||
else if (node->analyzed)
|
else if (node->analyzed && !node->transparent_alias)
|
||||||
{
|
*availability = node->get_availability ();
|
||||||
if (weakref_p)
|
|
||||||
{
|
|
||||||
enum availability a = node->get_availability ();
|
|
||||||
if (a < *availability)
|
|
||||||
*availability = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
*availability = AVAIL_NOT_AVAILABLE;
|
*availability = AVAIL_NOT_AVAILABLE;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (node && availability && weakref_p)
|
if (node && availability && transparent_p
|
||||||
|
&& node->transparent_alias)
|
||||||
{
|
{
|
||||||
enum availability a = node->get_availability ();
|
*availability = node->get_availability ();
|
||||||
if (a < *availability)
|
transparent_p = false;
|
||||||
*availability = a;
|
|
||||||
weakref_p = node->weakref;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (availability)
|
if (availability)
|
||||||
@ -1442,7 +1545,7 @@ symtab_node::set_implicit_section (symtab_node *n,
|
|||||||
it returns false. */
|
it returns false. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
symtab_node::resolve_alias (symtab_node *target)
|
symtab_node::resolve_alias (symtab_node *target, bool transparent)
|
||||||
{
|
{
|
||||||
symtab_node *n;
|
symtab_node *n;
|
||||||
|
|
||||||
@ -1468,6 +1571,11 @@ symtab_node::resolve_alias (symtab_node *target)
|
|||||||
definition = true;
|
definition = true;
|
||||||
alias = true;
|
alias = true;
|
||||||
analyzed = true;
|
analyzed = true;
|
||||||
|
transparent |= transparent_alias;
|
||||||
|
transparent_alias = transparent;
|
||||||
|
if (transparent)
|
||||||
|
while (target->transparent_alias && target->analyzed)
|
||||||
|
target = target->get_alias_target ();
|
||||||
create_reference (target, IPA_REF_ALIAS, NULL);
|
create_reference (target, IPA_REF_ALIAS, NULL);
|
||||||
|
|
||||||
/* Add alias into the comdat group of its target unless it is already there. */
|
/* Add alias into the comdat group of its target unless it is already there. */
|
||||||
@ -1492,19 +1600,29 @@ symtab_node::resolve_alias (symtab_node *target)
|
|||||||
when renaming symbols. */
|
when renaming symbols. */
|
||||||
alias_target = NULL;
|
alias_target = NULL;
|
||||||
|
|
||||||
if (cpp_implicit_alias && symtab->state >= CONSTRUCTION)
|
if (!transparent && cpp_implicit_alias && symtab->state >= CONSTRUCTION)
|
||||||
fixup_same_cpp_alias_visibility (target);
|
fixup_same_cpp_alias_visibility (target);
|
||||||
|
|
||||||
/* If alias has address taken, so does the target. */
|
/* If alias has address taken, so does the target. */
|
||||||
if (address_taken)
|
if (address_taken)
|
||||||
target->ultimate_alias_target ()->address_taken = true;
|
target->ultimate_alias_target ()->address_taken = true;
|
||||||
|
|
||||||
/* All non-weakref aliases of THIS are now in fact aliases of TARGET. */
|
/* All non-transparent aliases of THIS are now in fact aliases of TARGET.
|
||||||
|
If alias is transparent, also all transparent aliases of THIS are now
|
||||||
|
aliases of TARGET.
|
||||||
|
Also merge same comdat group lists. */
|
||||||
ipa_ref *ref;
|
ipa_ref *ref;
|
||||||
for (unsigned i = 0; iterate_direct_aliases (i, ref);)
|
for (unsigned i = 0; iterate_direct_aliases (i, ref);)
|
||||||
{
|
{
|
||||||
struct symtab_node *alias_alias = ref->referring;
|
struct symtab_node *alias_alias = ref->referring;
|
||||||
if (!alias_alias->weakref)
|
if (alias_alias->get_comdat_group ())
|
||||||
|
{
|
||||||
|
alias_alias->remove_from_same_comdat_group ();
|
||||||
|
alias_alias->set_comdat_group (NULL);
|
||||||
|
if (target->get_comdat_group ())
|
||||||
|
alias_alias->add_to_same_comdat_group (target);
|
||||||
|
}
|
||||||
|
if (!alias_alias->transparent_alias || transparent)
|
||||||
{
|
{
|
||||||
alias_alias->remove_all_references ();
|
alias_alias->remove_all_references ();
|
||||||
alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
|
alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
|
||||||
@ -1648,9 +1766,9 @@ symtab_node::get_partitioning_class (void)
|
|||||||
if (cnode && cnode->global.inlined_to)
|
if (cnode && cnode->global.inlined_to)
|
||||||
return SYMBOL_DUPLICATE;
|
return SYMBOL_DUPLICATE;
|
||||||
|
|
||||||
/* Weakref aliases are always duplicated. */
|
/* Transparent aliases are always duplicated. */
|
||||||
if (weakref)
|
if (transparent_alias)
|
||||||
return SYMBOL_DUPLICATE;
|
return definition ? SYMBOL_DUPLICATE : SYMBOL_EXTERNAL;
|
||||||
|
|
||||||
/* External declarations are external. */
|
/* External declarations are external. */
|
||||||
if (DECL_EXTERNAL (decl))
|
if (DECL_EXTERNAL (decl))
|
||||||
|
57
gcc/tree.c
57
gcc/tree.c
@ -13423,6 +13423,12 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
|
|||||||
{
|
{
|
||||||
tree f1, f2;
|
tree f1, f2;
|
||||||
|
|
||||||
|
/* Don't try to compare variants of an incomplete type, before
|
||||||
|
TYPE_FIELDS has been copied around. */
|
||||||
|
if (!COMPLETE_TYPE_P (t1) && !COMPLETE_TYPE_P (t2))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
if (TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2))
|
if (TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -13709,28 +13715,35 @@ verify_type (const_tree t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (RECORD_OR_UNION_TYPE_P (t))
|
else if (RECORD_OR_UNION_TYPE_P (t))
|
||||||
for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
|
{
|
||||||
{
|
if (TYPE_FIELDS (t) && !COMPLETE_TYPE_P (t) && in_lto_p)
|
||||||
/* TODO: verify properties of decls. */
|
{
|
||||||
if (TREE_CODE (fld) == FIELD_DECL)
|
error ("TYPE_FIELDS defined in incomplete type");
|
||||||
;
|
error_found = true;
|
||||||
else if (TREE_CODE (fld) == TYPE_DECL)
|
}
|
||||||
;
|
for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
|
||||||
else if (TREE_CODE (fld) == CONST_DECL)
|
{
|
||||||
;
|
/* TODO: verify properties of decls. */
|
||||||
else if (TREE_CODE (fld) == VAR_DECL)
|
if (TREE_CODE (fld) == FIELD_DECL)
|
||||||
;
|
;
|
||||||
else if (TREE_CODE (fld) == TEMPLATE_DECL)
|
else if (TREE_CODE (fld) == TYPE_DECL)
|
||||||
;
|
;
|
||||||
else if (TREE_CODE (fld) == USING_DECL)
|
else if (TREE_CODE (fld) == CONST_DECL)
|
||||||
;
|
;
|
||||||
else
|
else if (TREE_CODE (fld) == VAR_DECL)
|
||||||
{
|
;
|
||||||
error ("Wrong tree in TYPE_FIELDS list");
|
else if (TREE_CODE (fld) == TEMPLATE_DECL)
|
||||||
debug_tree (fld);
|
;
|
||||||
error_found = true;
|
else if (TREE_CODE (fld) == USING_DECL)
|
||||||
}
|
;
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
error ("Wrong tree in TYPE_FIELDS list");
|
||||||
|
debug_tree (fld);
|
||||||
|
error_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (TREE_CODE (t) == INTEGER_TYPE
|
else if (TREE_CODE (t) == INTEGER_TYPE
|
||||||
|| TREE_CODE (t) == BOOLEAN_TYPE
|
|| TREE_CODE (t) == BOOLEAN_TYPE
|
||||||
|| TREE_CODE (t) == OFFSET_TYPE
|
|| TREE_CODE (t) == OFFSET_TYPE
|
||||||
|
@ -440,7 +440,7 @@ ctor_for_folding (tree decl)
|
|||||||
gcc_assert (!DECL_INITIAL (decl)
|
gcc_assert (!DECL_INITIAL (decl)
|
||||||
|| (node->alias && node->get_alias_target () == real_node)
|
|| (node->alias && node->get_alias_target () == real_node)
|
||||||
|| DECL_INITIAL (decl) == error_mark_node);
|
|| DECL_INITIAL (decl) == error_mark_node);
|
||||||
if (node->weakref)
|
while (node->transparent_alias && node->analyzed)
|
||||||
{
|
{
|
||||||
node = node->get_alias_target ();
|
node = node->get_alias_target ();
|
||||||
decl = node->decl;
|
decl = node->decl;
|
||||||
@ -490,11 +490,11 @@ varpool_node::get_availability (void)
|
|||||||
if (DECL_IN_CONSTANT_POOL (decl)
|
if (DECL_IN_CONSTANT_POOL (decl)
|
||||||
|| DECL_VIRTUAL_P (decl))
|
|| DECL_VIRTUAL_P (decl))
|
||||||
return AVAIL_AVAILABLE;
|
return AVAIL_AVAILABLE;
|
||||||
if (alias && weakref)
|
if (transparent_alias)
|
||||||
{
|
{
|
||||||
enum availability avail;
|
enum availability avail;
|
||||||
|
|
||||||
ultimate_alias_target (&avail)->get_availability ();
|
ultimate_alias_target (&avail);
|
||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
/* If the variable can be overwritten, return OVERWRITABLE. Takes
|
/* If the variable can be overwritten, return OVERWRITABLE. Takes
|
||||||
@ -536,8 +536,9 @@ varpool_node::assemble_aliases (void)
|
|||||||
FOR_EACH_ALIAS (this, ref)
|
FOR_EACH_ALIAS (this, ref)
|
||||||
{
|
{
|
||||||
varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
|
varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
|
||||||
do_assemble_alias (alias->decl,
|
if (!alias->transparent_alias)
|
||||||
DECL_ASSEMBLER_NAME (decl));
|
do_assemble_alias (alias->decl,
|
||||||
|
DECL_ASSEMBLER_NAME (decl));
|
||||||
alias->assemble_aliases ();
|
alias->assemble_aliases ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -665,7 +666,14 @@ symbol_table::remove_unreferenced_decls (void)
|
|||||||
&& vnode->analyzed)
|
&& vnode->analyzed)
|
||||||
enqueue_node (vnode, &first);
|
enqueue_node (vnode, &first);
|
||||||
else
|
else
|
||||||
referenced.add (node);
|
{
|
||||||
|
referenced.add (node);
|
||||||
|
while (node->alias && node->definition)
|
||||||
|
{
|
||||||
|
node = node->get_alias_target ();
|
||||||
|
referenced.add (node);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
@ -760,7 +768,7 @@ varpool_node::create_alias (tree alias, tree decl)
|
|||||||
alias_node->definition = true;
|
alias_node->definition = true;
|
||||||
alias_node->alias_target = decl;
|
alias_node->alias_target = decl;
|
||||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
|
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
|
||||||
alias_node->weakref = true;
|
alias_node->weakref = alias_node->transparent_alias = true;
|
||||||
return alias_node;
|
return alias_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user