aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2011-06-18 08:31:03 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2011-06-18 08:31:03 +0000
commite0eaac8049ca6b188697d265c857df02a34722ee (patch)
treed841d5d2b4ed36e1175fc28ca05d5529968c1c38 /gcc
parent6e5d2d21c82843720cb1d3f02146da2fc71dc4cf (diff)
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175167 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog32
-rw-r--r--gcc/cgraph.h52
-rw-r--r--gcc/cgraphbuild.c8
-rw-r--r--gcc/cgraphunit.c15
-rw-r--r--gcc/ipa-ref.c2
-rw-r--r--gcc/lto-cgraph.c47
-rw-r--r--gcc/lto-streamer-out.c10
-rw-r--r--gcc/lto-symtab.c32
-rw-r--r--gcc/tree-ssa-structalias.c18
-rw-r--r--gcc/varpool.c166
10 files changed, 235 insertions, 147 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 80431630bf5..4fe0b105bf0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,35 @@
+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>
PR target/49411
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index feb742d387e..dd08febaf12 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -380,13 +380,12 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
tree decl;
+ /* For aliases points to declaration DECL is alias of. */
+ tree alias_of;
/* Pointer to the next function in varpool_nodes. */
struct varpool_node *next, *prev;
/* Pointer to the next function in varpool_nodes_queue. */
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. */
struct varpool_node *same_comdat_group;
struct ipa_ref_list ref_list;
@@ -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
extra name aliases in varpool_extra_name_alias. */
unsigned alias : 1;
+ unsigned extra_name_alias : 1;
/* Set when variable is used from other LTRANS partition. */
unsigned used_from_other_partition : 1;
/* Set when variable is available in the other LTRANS partition.
@@ -665,9 +665,13 @@ bool varpool_analyze_pending_decls (void);
void varpool_remove_unreferenced_decls (void);
void varpool_empty_needed_queue (void);
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);
void varpool_reset_queue (void);
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. */
#define FOR_EACH_STATIC_VARIABLE(node) \
@@ -968,6 +972,20 @@ cgraph_alias_aliased_node (struct cgraph_node *n)
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.
Walk through thunk, too.
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
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. */
static inline bool
cgraph_edge_recursive_p (struct cgraph_edge *e)
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 961804b415e..8bf88300593 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -87,8 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
varpool_mark_needed_node (vnode);
- if (vnode->alias && vnode->extra_name)
- vnode = vnode->extra_name;
ipa_record_reference (NULL, ctx->varpool_node,
NULL, vnode,
IPA_REF_ADDR, NULL);
@@ -261,8 +259,6 @@ mark_address (gimple stmt, tree addr, void *data)
if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
varpool_mark_needed_node (vnode);
- if (vnode->alias && vnode->extra_name)
- vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
IPA_REF_ADDR, stmt);
@@ -296,8 +292,6 @@ mark_load (gimple stmt, tree t, void *data)
if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
varpool_mark_needed_node (vnode);
- if (vnode->alias && vnode->extra_name)
- vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
IPA_REF_LOAD, stmt);
@@ -320,8 +314,6 @@ mark_store (gimple stmt, tree t, void *data)
if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
varpool_mark_needed_node (vnode);
- if (vnode->alias && vnode->extra_name)
- vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
IPA_REF_STORE, stmt);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 88d0face010..6683d2a5df3 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1186,6 +1186,7 @@ handle_alias_pairs (void)
unsigned i;
struct cgraph_node *target_node;
struct cgraph_node *src_node;
+ struct varpool_node *target_vnode;
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
{
@@ -1206,6 +1207,20 @@ handle_alias_pairs (void)
cgraph_create_function_alias (p->decl, target_node->decl);
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
{
if (dump_file)
diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c
index f5fd03f67fb..8520bca33ac 100644
--- a/gcc/ipa-ref.c
+++ b/gcc/ipa-ref.c
@@ -68,7 +68,7 @@ ipa_record_reference (struct cgraph_node *refering_node,
{
ref->refering.varpool_node = refering_varpool_node;
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)
{
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 169de382dbe..9d9cb4366a0 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -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;
struct bitpack_d bp;
- struct varpool_node *alias;
- int count = 0;
int ref;
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
bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->finalized, 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->needed);
/* 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
set, vset), 1);
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);
+ 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)
{
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
lto_output_sleb128_stream (ob->main_stream, ref);
lto_output_enum (ob->main_stream, ld_plugin_symbol_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.
@@ -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))
{
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_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
add_references (encoder, varpool_encoder, &vnode->ref_list);
@@ -1054,9 +1039,8 @@ input_varpool_node (struct lto_file_decl_data *file_data,
tree var_decl;
struct varpool_node *node;
struct bitpack_d bp;
- bool aliases_p;
- int count;
int ref = LCC_NOT_FOUND;
+ bool non_null_aliasof;
decl_index = lto_input_uleb128 (ib);
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,
node->force_output = bp_unpack_value (&bp, 1);
node->finalized = 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->used_from_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,
DECL_EXTERNAL (node->decl) = 1;
TREE_STATIC (node->decl) = 0;
}
- aliases_p = bp_unpack_value (&bp, 1);
if (node->finalized)
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);
/* Store a reference for now, and fix up later to be a pointer. */
node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
node->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution,
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;
}
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index a28e857617d..19b0ae8bb1e 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2557,7 +2557,7 @@ produce_symtab (struct output_block *ob,
char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
struct pointer_set_t *seen;
struct cgraph_node *node;
- struct varpool_node *vnode, *valias;
+ struct varpool_node *vnode;
struct lto_output_stream stream;
lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
@@ -2617,11 +2617,9 @@ produce_symtab (struct output_block *ob,
&& vnode->finalized
&& DECL_VIRTUAL_P (vnode->decl))
continue;
- if (vnode->alias)
+ if (vnode->alias && !vnode->alias_of)
continue;
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++)
{
@@ -2633,11 +2631,9 @@ produce_symtab (struct output_block *ob,
&& vnode->finalized
&& DECL_VIRTUAL_P (vnode->decl))
continue;
- if (vnode->alias)
+ if (vnode->alias && !vnode->alias_of)
continue;
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. */
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c
index d58da8df2db..2bbf064ee7d 100644
--- a/gcc/lto-symtab.c
+++ b/gcc/lto-symtab.c
@@ -268,32 +268,9 @@ lto_varpool_replace_node (struct varpool_node *vnode,
gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
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->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);
/* Be sure we can garbage collect the initializer. */
@@ -438,14 +415,11 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
if (TREE_CODE (e->decl) == FUNCTION_DECL)
return (e->node && e->node->analyzed);
- /* A variable should have a size. */
else if (TREE_CODE (e->decl) == VAR_DECL)
{
if (!e->vnode)
return false;
- if (e->vnode->finalized)
- return true;
- return e->vnode->alias && e->vnode->extra_name->finalized;
+ return e->vnode->finalized;
}
gcc_unreachable ();
@@ -779,6 +753,7 @@ void
lto_symtab_merge_cgraph_nodes (void)
{
struct cgraph_node *node;
+ struct varpool_node *vnode;
lto_symtab_maybe_init_hash_table ();
htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
@@ -786,6 +761,9 @@ lto_symtab_merge_cgraph_nodes (void)
if ((node->thunk.thunk_p || node->alias)
&& 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. */
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index d5516e673fa..6f076dcd3e7 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -6685,6 +6685,16 @@ associate_varinfo_to_alias (struct cgraph_node *node, void *data)
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. */
static unsigned int
ipa_pta_execute (void)
@@ -6716,14 +6726,12 @@ ipa_pta_execute (void)
/* Create constraints for global variables and their initializers. */
for (var = varpool_nodes; var; var = var->next)
{
- struct varpool_node *alias;
varinfo_t vi;
+ if (var->alias)
+ continue;
vi = get_vi_for_tree (var->decl);
-
- /* Associate the varinfo node with all aliases. */
- for (alias = var->extra_name; alias; alias = alias->next)
- insert_vi_for_tree (alias->decl, vi);
+ varpool_for_node_and_aliases (var, associate_varinfo_to_alias_1, vi, true);
}
if (dump_file)
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 43ee2290389..d223779a5c1 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -131,7 +131,7 @@ varpool_node (tree decl)
struct varpool_node key, *node, **slot;
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)
varpool_hash = htab_create_ggc (10, hash_varpool_node,
@@ -162,25 +162,14 @@ varpool_remove_node (struct varpool_node *node)
gcc_assert (*slot == node);
htab_clear_slot (varpool_hash, slot);
gcc_assert (!varpool_assembled_nodes_queue);
- if (!node->alias)
- while (node->extra_name)
- varpool_remove_node (node->extra_name);
if (node->next)
node->next->prev = node->prev;
if (node->prev)
node->prev->next = node->next;
else
{
- if (node->alias && node->extra_name)
- {
- 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;
- }
+ gcc_assert (varpool_nodes == node);
+ varpool_nodes = node->next;
}
if (varpool_first_unanalyzed_node == node)
varpool_first_unanalyzed_node = node->next_needed;
@@ -311,8 +300,6 @@ varpool_enqueue_needed_node (struct varpool_node *node)
void
varpool_mark_needed_node (struct varpool_node *node)
{
- if (node->alias && node->extra_name)
- node = node->extra_name;
if (!node->needed && node->finalized
&& !TREE_ASM_WRITTEN (node->decl))
varpool_enqueue_needed_node (node);
@@ -473,7 +460,40 @@ varpool_analyze_pending_decls (void)
already informed about increased alignment. */
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);
if (node->same_comdat_group)
{
@@ -488,6 +508,23 @@ varpool_analyze_pending_decls (void)
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. */
bool
varpool_assemble_decl (struct varpool_node *node)
@@ -503,25 +540,13 @@ varpool_assemble_decl (struct varpool_node *node)
assemble_variable (decl, 0, 1, 0);
if (TREE_ASM_WRITTEN (decl))
{
- struct varpool_node *alias;
-
node->next_needed = varpool_assembled_nodes_queue;
node->prev_needed = NULL;
if (varpool_assembled_nodes_queue)
varpool_assembled_nodes_queue->prev_needed = node;
varpool_assembled_nodes_queue = node;
node->finalized = 1;
-
- /* 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));
- }
-
+ assemble_aliases (node);
return true;
}
}
@@ -670,38 +695,36 @@ add_new_static_var (tree type)
Extra name aliases are output whenever DECL is output. */
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;
-
-#ifndef ASM_OUTPUT_DEF
- /* If aliases aren't supported by the assembler, fail. */
- return NULL;
-#endif
+ struct varpool_node *alias_node;
gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_CODE (alias) == VAR_DECL);
- /* Make sure the hash table has been created. */
- decl_node = varpool_node (decl);
-
- key.decl = alias;
+ alias_node = varpool_node (alias);
+ alias_node->alias = 1;
+ alias_node->finalized = 1;
+ 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. */
- if (*slot)
- return NULL;
+struct varpool_node *
+varpool_extra_name_alias (tree alias, tree decl)
+{
+ struct varpool_node *alias_node;
- alias_node = ggc_alloc_cleared_varpool_node ();
- alias_node->decl = alias;
- alias_node->alias = 1;
- alias_node->extra_name = decl_node;
- alias_node->next = decl_node->extra_name;
- ipa_empty_ref_list (&alias_node->ref_list);
- if (decl_node->extra_name)
- decl_node->extra_name->prev = alias_node;
- decl_node->extra_name = alias_node;
- *slot = alias_node;
+#ifndef ASM_OUTPUT_DEF
+ /* If aliases aren't supported by the assembler, fail. */
+ return NULL;
+#endif
+ alias_node = varpool_create_variable_alias (alias, decl);
+ alias_node->extra_name_alias = true;
return alias_node;
}
@@ -711,17 +734,38 @@ varpool_extra_name_alias (tree alias, tree decl)
bool
varpool_used_from_object_file_p (struct varpool_node *node)
{
- struct varpool_node *alias;
-
if (!TREE_PUBLIC (node->decl))
return false;
if (resolution_used_from_other_file_p (node->resolution))
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;
}
+/* 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"