Commit cd35bcf7 by Jan Hubicka Committed by Jan Hubicka

lto-symtab.c (lto_varpool_replace_node): Remove code handling extra name aliases.

	* lto-symtab.c (lto_varpool_replace_node): Remove code handling
	extra name aliases.
	(lto_symtab_resolve_can_prevail_p): Likewise.
	(lto_symtab_merge_cgraph_nodes): Update alias_of pointers.
	* cgraphbuild.c (record_reference): Remove extra body alias code.
	(mark_load): Likewise.
	(mark_store): Likewise.
	* cgraph.h (varpool_node): Remove extra_name filed;
	add alias_of and extraname_alias.
	(varpool_create_variable_alias, varpool_for_node_and_aliases): Declare.
	(varpool_alias_aliased_node): New inline function.
	(varpool_variable_node): New function.
	* cgraphunit.c (handle_alias_pairs): Handle also variable aliases.
	* ipa-ref.c (ipa_record_reference): Allow aliases on variables.
	* lto-cgraph.c (lto_output_varpool_node): Update streaming.
	(input_varpool_node): Likewise.
	* lto-streamer-out.c (produce_symtab): Remove extra name aliases.
	(varpool_externally_visible_p): Remove extra body alias code.
	(function_and_variable_visibility): Likewise.
	* tree-ssa-structalias.c (associate_varinfo_to_alias_1): New function.
	(ipa_pta_execute): Use it.
	* varpool.c (varpool_remove_node): Remove extra name alias code.
	(varpool_mark_needed_node): Likewise.
	(varpool_analyze_pending_decls): Analyze aliases.
	(assemble_aliases): New functoin.
	(varpool_assemble_decl): Use it.
	(varpool_create_variable_alias): New function.
	(varpool_extra_name_alias): Rewrite.
	(varpool_for_node_and_aliases): New function.

From-SVN: r175167
parent d3ff9ee4
2011-06-18 Jan Hubicka <jh@suse.cz>
* lto-symtab.c (lto_varpool_replace_node): Remove code handling
extra name aliases.
(lto_symtab_resolve_can_prevail_p): Likewise.
(lto_symtab_merge_cgraph_nodes): Update alias_of pointers.
* cgraphbuild.c (record_reference): Remove extra body alias code.
(mark_load): Likewise.
(mark_store): Likewise.
* cgraph.h (varpool_node): Remove extra_name filed;
add alias_of and extraname_alias.
(varpool_create_variable_alias, varpool_for_node_and_aliases): Declare.
(varpool_alias_aliased_node): New inline function.
(varpool_variable_node): New function.
* cgraphunit.c (handle_alias_pairs): Handle also variable aliases.
* ipa-ref.c (ipa_record_reference): Allow aliases on variables.
* lto-cgraph.c (lto_output_varpool_node): Update streaming.
(input_varpool_node): Likewise.
* lto-streamer-out.c (produce_symtab): Remove extra name aliases.
(varpool_externally_visible_p): Remove extra body alias code.
(function_and_variable_visibility): Likewise.
* tree-ssa-structalias.c (associate_varinfo_to_alias_1): New function.
(ipa_pta_execute): Use it.
* varpool.c (varpool_remove_node): Remove extra name alias code.
(varpool_mark_needed_node): Likewise.
(varpool_analyze_pending_decls): Analyze aliases.
(assemble_aliases): New functoin.
(varpool_assemble_decl): Use it.
(varpool_create_variable_alias): New function.
(varpool_extra_name_alias): Rewrite.
(varpool_for_node_and_aliases): New function.
2011-06-18 Jakub Jelinek <jakub@redhat.com> 2011-06-18 Jakub Jelinek <jakub@redhat.com>
PR target/49411 PR target/49411
......
...@@ -380,13 +380,12 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap); ...@@ -380,13 +380,12 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
tree decl; tree decl;
/* For aliases points to declaration DECL is alias of. */
tree alias_of;
/* Pointer to the next function in varpool_nodes. */ /* Pointer to the next function in varpool_nodes. */
struct varpool_node *next, *prev; struct varpool_node *next, *prev;
/* Pointer to the next function in varpool_nodes_queue. */ /* Pointer to the next function in varpool_nodes_queue. */
struct varpool_node *next_needed, *prev_needed; struct varpool_node *next_needed, *prev_needed;
/* For normal nodes a pointer to the first extra name alias. For alias
nodes a pointer to the normal node. */
struct varpool_node *extra_name;
/* Circular list of nodes in the same comdat group if non-NULL. */ /* Circular list of nodes in the same comdat group if non-NULL. */
struct varpool_node *same_comdat_group; struct varpool_node *same_comdat_group;
struct ipa_ref_list ref_list; struct ipa_ref_list ref_list;
...@@ -415,6 +414,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { ...@@ -415,6 +414,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
/* Set for aliases once they got through assemble_alias. Also set for /* Set for aliases once they got through assemble_alias. Also set for
extra name aliases in varpool_extra_name_alias. */ extra name aliases in varpool_extra_name_alias. */
unsigned alias : 1; unsigned alias : 1;
unsigned extra_name_alias : 1;
/* Set when variable is used from other LTRANS partition. */ /* Set when variable is used from other LTRANS partition. */
unsigned used_from_other_partition : 1; unsigned used_from_other_partition : 1;
/* Set when variable is available in the other LTRANS partition. /* Set when variable is available in the other LTRANS partition.
...@@ -665,9 +665,13 @@ bool varpool_analyze_pending_decls (void); ...@@ -665,9 +665,13 @@ bool varpool_analyze_pending_decls (void);
void varpool_remove_unreferenced_decls (void); void varpool_remove_unreferenced_decls (void);
void varpool_empty_needed_queue (void); void varpool_empty_needed_queue (void);
struct varpool_node * varpool_extra_name_alias (tree, tree); struct varpool_node * varpool_extra_name_alias (tree, tree);
struct varpool_node * varpool_create_variable_alias (tree, tree);
const char * varpool_node_name (struct varpool_node *node); const char * varpool_node_name (struct varpool_node *node);
void varpool_reset_queue (void); void varpool_reset_queue (void);
bool const_value_known_p (tree); bool const_value_known_p (tree);
bool varpool_for_node_and_aliases (struct varpool_node *,
bool (*) (struct varpool_node *, void *),
void *, bool);
/* Walk all reachable static variables. */ /* Walk all reachable static variables. */
#define FOR_EACH_STATIC_VARIABLE(node) \ #define FOR_EACH_STATIC_VARIABLE(node) \
...@@ -968,6 +972,20 @@ cgraph_alias_aliased_node (struct cgraph_node *n) ...@@ -968,6 +972,20 @@ cgraph_alias_aliased_node (struct cgraph_node *n)
return NULL; return NULL;
} }
/* Return node that alias N is aliasing. */
static inline struct varpool_node *
varpool_alias_aliased_node (struct varpool_node *n)
{
struct ipa_ref *ref;
ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
gcc_checking_assert (ref->use == IPA_REF_ALIAS);
if (ref->refered_type == IPA_REF_CGRAPH)
return ipa_ref_varpool_node (ref);
return NULL;
}
/* Given NODE, walk the alias chain to return the function NODE is alias of. /* Given NODE, walk the alias chain to return the function NODE is alias of.
Walk through thunk, too. Walk through thunk, too.
When AVAILABILITY is non-NULL, get minimal availablity in the chain. */ When AVAILABILITY is non-NULL, get minimal availablity in the chain. */
...@@ -1026,6 +1044,34 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai ...@@ -1026,6 +1044,34 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai
return NULL; return NULL;
} }
/* Given NODE, walk the alias chain to return the function NODE is alias of.
Do not walk through thunks.
When AVAILABILITY is non-NULL, get minimal availablity in the chain. */
static inline struct varpool_node *
varpool_variable_node (struct varpool_node *node, enum availability *availability)
{
if (availability)
*availability = cgraph_variable_initializer_availability (node);
while (node)
{
if (node->alias && node->analyzed)
node = varpool_alias_aliased_node (node);
else
return node;
if (node && availability)
{
enum availability a;
a = cgraph_variable_initializer_availability (node);
if (a < *availability)
*availability = a;
}
}
if (*availability)
*availability = AVAIL_NOT_AVAILABLE;
return NULL;
}
/* Return true when the edge E represents a direct recursion. */ /* Return true when the edge E represents a direct recursion. */
static inline bool static inline bool
cgraph_edge_recursive_p (struct cgraph_edge *e) cgraph_edge_recursive_p (struct cgraph_edge *e)
......
...@@ -87,8 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data) ...@@ -87,8 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference (NULL, ctx->varpool_node, ipa_record_reference (NULL, ctx->varpool_node,
NULL, vnode, NULL, vnode,
IPA_REF_ADDR, NULL); IPA_REF_ADDR, NULL);
...@@ -261,8 +259,6 @@ mark_address (gimple stmt, tree addr, void *data) ...@@ -261,8 +259,6 @@ mark_address (gimple stmt, tree addr, void *data)
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL, ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode, NULL, vnode,
IPA_REF_ADDR, stmt); IPA_REF_ADDR, stmt);
...@@ -296,8 +292,6 @@ mark_load (gimple stmt, tree t, void *data) ...@@ -296,8 +292,6 @@ mark_load (gimple stmt, tree t, void *data)
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL, ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode, NULL, vnode,
IPA_REF_LOAD, stmt); IPA_REF_LOAD, stmt);
...@@ -320,8 +314,6 @@ mark_store (gimple stmt, tree t, void *data) ...@@ -320,8 +314,6 @@ mark_store (gimple stmt, tree t, void *data)
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL, ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode, NULL, vnode,
IPA_REF_STORE, stmt); IPA_REF_STORE, stmt);
......
...@@ -1186,6 +1186,7 @@ handle_alias_pairs (void) ...@@ -1186,6 +1186,7 @@ handle_alias_pairs (void)
unsigned i; unsigned i;
struct cgraph_node *target_node; struct cgraph_node *target_node;
struct cgraph_node *src_node; struct cgraph_node *src_node;
struct varpool_node *target_vnode;
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);) for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
{ {
...@@ -1206,6 +1207,20 @@ handle_alias_pairs (void) ...@@ -1206,6 +1207,20 @@ handle_alias_pairs (void)
cgraph_create_function_alias (p->decl, target_node->decl); cgraph_create_function_alias (p->decl, target_node->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i); VEC_unordered_remove (alias_pair, alias_pairs, i);
} }
else if (TREE_CODE (p->decl) == VAR_DECL
&& !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
&& (target_vnode = varpool_node_for_asm (p->target)) != NULL)
{
/* Normally EXTERNAL flag is used to mark external inlines,
however for aliases it seems to be allowed to use it w/o
any meaning. See gcc.dg/attr-alias-3.c
However for weakref we insist on EXTERNAL flag being set.
See gcc.dg/attr-alias-5.c */
if (DECL_EXTERNAL (p->decl))
DECL_EXTERNAL (p->decl) = 0;
varpool_create_variable_alias (p->decl, target_vnode->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i);
}
else else
{ {
if (dump_file) if (dump_file)
......
...@@ -68,7 +68,7 @@ ipa_record_reference (struct cgraph_node *refering_node, ...@@ -68,7 +68,7 @@ ipa_record_reference (struct cgraph_node *refering_node,
{ {
ref->refering.varpool_node = refering_varpool_node; ref->refering.varpool_node = refering_varpool_node;
ref->refering_type = IPA_REF_VARPOOL; ref->refering_type = IPA_REF_VARPOOL;
gcc_assert (use_type == IPA_REF_ADDR); gcc_assert (use_type == IPA_REF_ADDR || use_type == IPA_REF_ALIAS);
} }
if (refered_node) if (refered_node)
{ {
......
...@@ -544,8 +544,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node ...@@ -544,8 +544,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
{ {
bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed; bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
struct bitpack_d bp; struct bitpack_d bp;
struct varpool_node *alias;
int count = 0;
int ref; int ref;
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl); lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
...@@ -554,7 +552,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node ...@@ -554,7 +552,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
bp_pack_value (&bp, node->force_output, 1); bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->finalized, 1);
bp_pack_value (&bp, node->alias, 1); bp_pack_value (&bp, node->alias, 1);
gcc_assert (!node->alias || !node->extra_name); bp_pack_value (&bp, node->alias_of != NULL, 1);
gcc_assert (node->finalized || !node->analyzed); gcc_assert (node->finalized || !node->analyzed);
gcc_assert (node->needed); gcc_assert (node->needed);
/* Constant pool initializers can be de-unified into individual ltrans units. /* Constant pool initializers can be de-unified into individual ltrans units.
...@@ -573,11 +571,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node ...@@ -573,11 +571,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
set, vset), 1); set, vset), 1);
bp_pack_value (&bp, boundary_p, 1); /* in_other_partition. */ bp_pack_value (&bp, boundary_p, 1); /* in_other_partition. */
} }
/* Also emit any extra name aliases. */
for (alias = node->extra_name; alias; alias = alias->next)
count++;
bp_pack_value (&bp, count != 0, 1);
lto_output_bitpack (&bp); lto_output_bitpack (&bp);
if (node->alias_of)
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of);
if (node->same_comdat_group && !boundary_p) if (node->same_comdat_group && !boundary_p)
{ {
ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group); ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group);
...@@ -588,17 +584,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node ...@@ -588,17 +584,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
lto_output_sleb128_stream (ob->main_stream, ref); lto_output_sleb128_stream (ob->main_stream, ref);
lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution, lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN, node->resolution); LDPR_NUM_KNOWN, node->resolution);
if (count)
{
lto_output_uleb128_stream (ob->main_stream, count);
for (alias = node->extra_name; alias; alias = alias->next)
{
lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl);
lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN, alias->resolution);
}
}
} }
/* Output the varpool NODE to OB. /* Output the varpool NODE to OB.
...@@ -780,7 +765,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state, ...@@ -780,7 +765,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state,
for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
{ {
struct varpool_node *vnode = vsi_node (vsi); struct varpool_node *vnode = vsi_node (vsi);
gcc_assert (!vnode->alias); gcc_assert (!vnode->alias || vnode->alias_of);
lto_varpool_encoder_encode (varpool_encoder, vnode); lto_varpool_encoder_encode (varpool_encoder, vnode);
lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode); lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
add_references (encoder, varpool_encoder, &vnode->ref_list); add_references (encoder, varpool_encoder, &vnode->ref_list);
...@@ -1054,9 +1039,8 @@ input_varpool_node (struct lto_file_decl_data *file_data, ...@@ -1054,9 +1039,8 @@ input_varpool_node (struct lto_file_decl_data *file_data,
tree var_decl; tree var_decl;
struct varpool_node *node; struct varpool_node *node;
struct bitpack_d bp; struct bitpack_d bp;
bool aliases_p;
int count;
int ref = LCC_NOT_FOUND; int ref = LCC_NOT_FOUND;
bool non_null_aliasof;
decl_index = lto_input_uleb128 (ib); decl_index = lto_input_uleb128 (ib);
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index); var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
...@@ -1068,6 +1052,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, ...@@ -1068,6 +1052,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->force_output = bp_unpack_value (&bp, 1); node->force_output = bp_unpack_value (&bp, 1);
node->finalized = bp_unpack_value (&bp, 1); node->finalized = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1);
non_null_aliasof = bp_unpack_value (&bp, 1);
node->analyzed = node->finalized; node->analyzed = node->finalized;
node->used_from_other_partition = bp_unpack_value (&bp, 1); node->used_from_other_partition = bp_unpack_value (&bp, 1);
node->in_other_partition = bp_unpack_value (&bp, 1); node->in_other_partition = bp_unpack_value (&bp, 1);
...@@ -1076,27 +1061,19 @@ input_varpool_node (struct lto_file_decl_data *file_data, ...@@ -1076,27 +1061,19 @@ input_varpool_node (struct lto_file_decl_data *file_data,
DECL_EXTERNAL (node->decl) = 1; DECL_EXTERNAL (node->decl) = 1;
TREE_STATIC (node->decl) = 0; TREE_STATIC (node->decl) = 0;
} }
aliases_p = bp_unpack_value (&bp, 1);
if (node->finalized) if (node->finalized)
varpool_mark_needed_node (node); varpool_mark_needed_node (node);
if (non_null_aliasof)
{
decl_index = lto_input_uleb128 (ib);
node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index);
}
ref = lto_input_sleb128 (ib); ref = lto_input_sleb128 (ib);
/* Store a reference for now, and fix up later to be a pointer. */ /* Store a reference for now, and fix up later to be a pointer. */
node->same_comdat_group = (struct varpool_node *) (intptr_t) ref; node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
node->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution, node->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN); LDPR_NUM_KNOWN);
if (aliases_p)
{
count = lto_input_uleb128 (ib);
for (; count > 0; count --)
{
tree decl = lto_file_decl_data_get_var_decl (file_data,
lto_input_uleb128 (ib));
struct varpool_node *alias;
alias = varpool_extra_name_alias (decl, var_decl);
alias->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN);
}
}
return node; return node;
} }
......
...@@ -2557,7 +2557,7 @@ produce_symtab (struct output_block *ob, ...@@ -2557,7 +2557,7 @@ produce_symtab (struct output_block *ob,
char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL); char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
struct pointer_set_t *seen; struct pointer_set_t *seen;
struct cgraph_node *node; struct cgraph_node *node;
struct varpool_node *vnode, *valias; struct varpool_node *vnode;
struct lto_output_stream stream; struct lto_output_stream stream;
lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
...@@ -2617,11 +2617,9 @@ produce_symtab (struct output_block *ob, ...@@ -2617,11 +2617,9 @@ produce_symtab (struct output_block *ob,
&& vnode->finalized && vnode->finalized
&& DECL_VIRTUAL_P (vnode->decl)) && DECL_VIRTUAL_P (vnode->decl))
continue; continue;
if (vnode->alias) if (vnode->alias && !vnode->alias_of)
continue; continue;
write_symbol (cache, &stream, vnode->decl, seen, false); write_symbol (cache, &stream, vnode->decl, seen, false);
for (valias = vnode->extra_name; valias; valias = valias->next)
write_symbol (cache, &stream, valias->decl, seen, true);
} }
for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
{ {
...@@ -2633,11 +2631,9 @@ produce_symtab (struct output_block *ob, ...@@ -2633,11 +2631,9 @@ produce_symtab (struct output_block *ob,
&& vnode->finalized && vnode->finalized
&& DECL_VIRTUAL_P (vnode->decl)) && DECL_VIRTUAL_P (vnode->decl))
continue; continue;
if (vnode->alias) if (vnode->alias && !vnode->alias_of)
continue; continue;
write_symbol (cache, &stream, vnode->decl, seen, false); write_symbol (cache, &stream, vnode->decl, seen, false);
for (valias = vnode->extra_name; valias; valias = valias->next)
write_symbol (cache, &stream, valias->decl, seen, true);
} }
/* Write all aliases. */ /* Write all aliases. */
......
...@@ -268,32 +268,9 @@ lto_varpool_replace_node (struct varpool_node *vnode, ...@@ -268,32 +268,9 @@ lto_varpool_replace_node (struct varpool_node *vnode,
gcc_assert (!vnode->analyzed || prevailing_node->analyzed); gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
varpool_mark_needed_node (prevailing_node); varpool_mark_needed_node (prevailing_node);
} }
/* Relink aliases. */
if (vnode->extra_name && !vnode->alias)
{
struct varpool_node *alias, *last;
for (alias = vnode->extra_name;
alias; alias = alias->next)
{
last = alias;
alias->extra_name = prevailing_node;
}
if (prevailing_node->extra_name)
{
last->next = prevailing_node->extra_name;
prevailing_node->extra_name->prev = last;
}
prevailing_node->extra_name = vnode->extra_name;
vnode->extra_name = NULL;
}
gcc_assert (!vnode->finalized || prevailing_node->finalized); gcc_assert (!vnode->finalized || prevailing_node->finalized);
gcc_assert (!vnode->analyzed || prevailing_node->analyzed); gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
/* When replacing by an alias, the references goes to the original
variable. */
if (prevailing_node->alias && prevailing_node->extra_name)
prevailing_node = prevailing_node->extra_name;
ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list); ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list);
/* Be sure we can garbage collect the initializer. */ /* Be sure we can garbage collect the initializer. */
...@@ -438,14 +415,11 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e) ...@@ -438,14 +415,11 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
if (TREE_CODE (e->decl) == FUNCTION_DECL) if (TREE_CODE (e->decl) == FUNCTION_DECL)
return (e->node && e->node->analyzed); return (e->node && e->node->analyzed);
/* A variable should have a size. */
else if (TREE_CODE (e->decl) == VAR_DECL) else if (TREE_CODE (e->decl) == VAR_DECL)
{ {
if (!e->vnode) if (!e->vnode)
return false; return false;
if (e->vnode->finalized) return e->vnode->finalized;
return true;
return e->vnode->alias && e->vnode->extra_name->finalized;
} }
gcc_unreachable (); gcc_unreachable ();
...@@ -779,6 +753,7 @@ void ...@@ -779,6 +753,7 @@ void
lto_symtab_merge_cgraph_nodes (void) lto_symtab_merge_cgraph_nodes (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
struct varpool_node *vnode;
lto_symtab_maybe_init_hash_table (); lto_symtab_maybe_init_hash_table ();
htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL); htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
...@@ -786,6 +761,9 @@ lto_symtab_merge_cgraph_nodes (void) ...@@ -786,6 +761,9 @@ lto_symtab_merge_cgraph_nodes (void)
if ((node->thunk.thunk_p || node->alias) if ((node->thunk.thunk_p || node->alias)
&& node->thunk.alias) && node->thunk.alias)
node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias); node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
if (vnode->alias_of)
vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
} }
/* Given the decl DECL, return the prevailing decl with the same name. */ /* Given the decl DECL, return the prevailing decl with the same name. */
......
...@@ -6685,6 +6685,16 @@ associate_varinfo_to_alias (struct cgraph_node *node, void *data) ...@@ -6685,6 +6685,16 @@ associate_varinfo_to_alias (struct cgraph_node *node, void *data)
return false; return false;
} }
/* Associate node with varinfo DATA. Worker for
varpool_for_node_and_aliases. */
static bool
associate_varinfo_to_alias_1 (struct varpool_node *node, void *data)
{
if (node->alias)
insert_vi_for_tree (node->decl, (varinfo_t)data);
return false;
}
/* Execute the driver for IPA PTA. */ /* Execute the driver for IPA PTA. */
static unsigned int static unsigned int
ipa_pta_execute (void) ipa_pta_execute (void)
...@@ -6716,14 +6726,12 @@ ipa_pta_execute (void) ...@@ -6716,14 +6726,12 @@ ipa_pta_execute (void)
/* Create constraints for global variables and their initializers. */ /* Create constraints for global variables and their initializers. */
for (var = varpool_nodes; var; var = var->next) for (var = varpool_nodes; var; var = var->next)
{ {
struct varpool_node *alias;
varinfo_t vi; varinfo_t vi;
if (var->alias)
continue;
vi = get_vi_for_tree (var->decl); vi = get_vi_for_tree (var->decl);
varpool_for_node_and_aliases (var, associate_varinfo_to_alias_1, vi, true);
/* Associate the varinfo node with all aliases. */
for (alias = var->extra_name; alias; alias = alias->next)
insert_vi_for_tree (alias->decl, vi);
} }
if (dump_file) if (dump_file)
......
...@@ -131,7 +131,7 @@ varpool_node (tree decl) ...@@ -131,7 +131,7 @@ varpool_node (tree decl)
struct varpool_node key, *node, **slot; struct varpool_node key, *node, **slot;
gcc_assert (TREE_CODE (decl) == VAR_DECL gcc_assert (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl))); && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p));
if (!varpool_hash) if (!varpool_hash)
varpool_hash = htab_create_ggc (10, hash_varpool_node, varpool_hash = htab_create_ggc (10, hash_varpool_node,
...@@ -162,25 +162,14 @@ varpool_remove_node (struct varpool_node *node) ...@@ -162,25 +162,14 @@ varpool_remove_node (struct varpool_node *node)
gcc_assert (*slot == node); gcc_assert (*slot == node);
htab_clear_slot (varpool_hash, slot); htab_clear_slot (varpool_hash, slot);
gcc_assert (!varpool_assembled_nodes_queue); gcc_assert (!varpool_assembled_nodes_queue);
if (!node->alias)
while (node->extra_name)
varpool_remove_node (node->extra_name);
if (node->next) if (node->next)
node->next->prev = node->prev; node->next->prev = node->prev;
if (node->prev) if (node->prev)
node->prev->next = node->next; node->prev->next = node->next;
else else
{ {
if (node->alias && node->extra_name) gcc_assert (varpool_nodes == node);
{ varpool_nodes = node->next;
gcc_assert (node->extra_name->extra_name == node);
node->extra_name->extra_name = node->next;
}
else
{
gcc_assert (varpool_nodes == node);
varpool_nodes = node->next;
}
} }
if (varpool_first_unanalyzed_node == node) if (varpool_first_unanalyzed_node == node)
varpool_first_unanalyzed_node = node->next_needed; varpool_first_unanalyzed_node = node->next_needed;
...@@ -311,8 +300,6 @@ varpool_enqueue_needed_node (struct varpool_node *node) ...@@ -311,8 +300,6 @@ varpool_enqueue_needed_node (struct varpool_node *node)
void void
varpool_mark_needed_node (struct varpool_node *node) varpool_mark_needed_node (struct varpool_node *node)
{ {
if (node->alias && node->extra_name)
node = node->extra_name;
if (!node->needed && node->finalized if (!node->needed && node->finalized
&& !TREE_ASM_WRITTEN (node->decl)) && !TREE_ASM_WRITTEN (node->decl))
varpool_enqueue_needed_node (node); varpool_enqueue_needed_node (node);
...@@ -473,7 +460,40 @@ varpool_analyze_pending_decls (void) ...@@ -473,7 +460,40 @@ varpool_analyze_pending_decls (void)
already informed about increased alignment. */ already informed about increased alignment. */
align_variable (decl, 0); align_variable (decl, 0);
} }
if (DECL_INITIAL (decl)) if (node->alias && node->alias_of)
{
struct varpool_node *tgt = varpool_node (node->alias_of);
if (!VEC_length (ipa_ref_t, node->ref_list.references))
ipa_record_reference (NULL, node, NULL, tgt, IPA_REF_ALIAS, NULL);
/* C++ FE sometimes change linkage flags after producing same body aliases. */
if (node->extra_name_alias)
{
DECL_WEAK (node->decl) = DECL_WEAK (node->alias_of);
TREE_PUBLIC (node->decl) = TREE_PUBLIC (node->alias_of);
DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (node->alias_of);
if (TREE_PUBLIC (node->decl))
{
DECL_COMDAT (node->decl) = DECL_COMDAT (node->alias_of);
DECL_COMDAT_GROUP (node->decl) = DECL_COMDAT_GROUP (node->alias_of);
if (DECL_ONE_ONLY (node->alias_of) && !node->same_comdat_group)
{
node->same_comdat_group = tgt;
if (!tgt->same_comdat_group)
tgt->same_comdat_group = node;
else
{
struct varpool_node *n;
for (n = tgt->same_comdat_group;
n->same_comdat_group != tgt;
n = n->same_comdat_group)
;
n->same_comdat_group = node;
}
}
}
}
}
else if (DECL_INITIAL (decl))
record_references_in_initializer (decl, analyzed); record_references_in_initializer (decl, analyzed);
if (node->same_comdat_group) if (node->same_comdat_group)
{ {
...@@ -488,6 +508,23 @@ varpool_analyze_pending_decls (void) ...@@ -488,6 +508,23 @@ varpool_analyze_pending_decls (void)
return changed; return changed;
} }
/* Assemble thunks and aliases asociated to NODE. */
static void
assemble_aliases (struct varpool_node *node)
{
int i;
struct ipa_ref *ref;
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct varpool_node *alias = ipa_ref_refering_varpool_node (ref);
assemble_alias (alias->decl,
DECL_ASSEMBLER_NAME (alias->alias_of));
assemble_aliases (alias);
}
}
/* Output one variable, if necessary. Return whether we output it. */ /* Output one variable, if necessary. Return whether we output it. */
bool bool
varpool_assemble_decl (struct varpool_node *node) varpool_assemble_decl (struct varpool_node *node)
...@@ -503,25 +540,13 @@ varpool_assemble_decl (struct varpool_node *node) ...@@ -503,25 +540,13 @@ varpool_assemble_decl (struct varpool_node *node)
assemble_variable (decl, 0, 1, 0); assemble_variable (decl, 0, 1, 0);
if (TREE_ASM_WRITTEN (decl)) if (TREE_ASM_WRITTEN (decl))
{ {
struct varpool_node *alias;
node->next_needed = varpool_assembled_nodes_queue; node->next_needed = varpool_assembled_nodes_queue;
node->prev_needed = NULL; node->prev_needed = NULL;
if (varpool_assembled_nodes_queue) if (varpool_assembled_nodes_queue)
varpool_assembled_nodes_queue->prev_needed = node; varpool_assembled_nodes_queue->prev_needed = node;
varpool_assembled_nodes_queue = node; varpool_assembled_nodes_queue = node;
node->finalized = 1; node->finalized = 1;
assemble_aliases (node);
/* Also emit any extra name aliases. */
for (alias = node->extra_name; alias; alias = alias->next)
{
/* Update linkage fields in case they've changed. */
DECL_WEAK (alias->decl) = DECL_WEAK (decl);
TREE_PUBLIC (alias->decl) = TREE_PUBLIC (decl);
DECL_VISIBILITY (alias->decl) = DECL_VISIBILITY (decl);
assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl));
}
return true; return true;
} }
} }
...@@ -670,38 +695,36 @@ add_new_static_var (tree type) ...@@ -670,38 +695,36 @@ add_new_static_var (tree type)
Extra name aliases are output whenever DECL is output. */ Extra name aliases are output whenever DECL is output. */
struct varpool_node * struct varpool_node *
varpool_extra_name_alias (tree alias, tree decl) varpool_create_variable_alias (tree alias, tree decl)
{ {
struct varpool_node key, *alias_node, *decl_node, **slot; struct varpool_node *alias_node;
#ifndef ASM_OUTPUT_DEF
/* If aliases aren't supported by the assembler, fail. */
return NULL;
#endif
gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_CODE (alias) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL);
/* Make sure the hash table has been created. */ alias_node = varpool_node (alias);
decl_node = varpool_node (decl); alias_node->alias = 1;
alias_node->finalized = 1;
key.decl = alias; alias_node->alias_of = decl;
if (decide_is_variable_needed (alias_node, alias)
|| alias_node->needed)
varpool_mark_needed_node (alias_node);
return alias_node;
}
slot = (struct varpool_node **) htab_find_slot (varpool_hash, &key, INSERT); /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
Extra name aliases are output whenever DECL is output. */
/* If the varpool_node has been already created, fail. */ struct varpool_node *
if (*slot) varpool_extra_name_alias (tree alias, tree decl)
return NULL; {
struct varpool_node *alias_node;
alias_node = ggc_alloc_cleared_varpool_node (); #ifndef ASM_OUTPUT_DEF
alias_node->decl = alias; /* If aliases aren't supported by the assembler, fail. */
alias_node->alias = 1; return NULL;
alias_node->extra_name = decl_node; #endif
alias_node->next = decl_node->extra_name; alias_node = varpool_create_variable_alias (alias, decl);
ipa_empty_ref_list (&alias_node->ref_list); alias_node->extra_name_alias = true;
if (decl_node->extra_name)
decl_node->extra_name->prev = alias_node;
decl_node->extra_name = alias_node;
*slot = alias_node;
return alias_node; return alias_node;
} }
...@@ -711,17 +734,38 @@ varpool_extra_name_alias (tree alias, tree decl) ...@@ -711,17 +734,38 @@ varpool_extra_name_alias (tree alias, tree decl)
bool bool
varpool_used_from_object_file_p (struct varpool_node *node) varpool_used_from_object_file_p (struct varpool_node *node)
{ {
struct varpool_node *alias;
if (!TREE_PUBLIC (node->decl)) if (!TREE_PUBLIC (node->decl))
return false; return false;
if (resolution_used_from_other_file_p (node->resolution)) if (resolution_used_from_other_file_p (node->resolution))
return true; return true;
for (alias = node->extra_name; alias; alias = alias->next)
if (TREE_PUBLIC (alias->decl)
&& resolution_used_from_other_file_p (alias->resolution))
return true;
return false; return false;
} }
/* Call calback on NODE and aliases asociated to NODE.
When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
skipped. */
bool
varpool_for_node_and_aliases (struct varpool_node *node,
bool (*callback) (struct varpool_node *, void *),
void *data,
bool include_overwritable)
{
int i;
struct ipa_ref *ref;
if (callback (node, data))
return true;
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct varpool_node *alias = ipa_ref_refering_varpool_node (ref);
if (include_overwritable
|| cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE)
if (varpool_for_node_and_aliases (alias, callback, data,
include_overwritable))
return true;
}
return false;
}
#include "gt-varpool.h" #include "gt-varpool.h"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment