aboutsummaryrefslogtreecommitdiff
path: root/gcc/varpool.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2011-06-18 10:31:03 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2011-06-18 08:31:03 +0000
commitcd35bcf7e8fa8fb1f11e8a45fd1012ca6461e278 (patch)
treed841d5d2b4ed36e1175fc28ca05d5529968c1c38 /gcc/varpool.c
parentd3ff9ee4686ea27a0df76224c790c67284889f57 (diff)
downloadgcc-cd35bcf7e8fa8fb1f11e8a45fd1012ca6461e278.zip
gcc-cd35bcf7e8fa8fb1f11e8a45fd1012ca6461e278.tar.gz
gcc-cd35bcf7e8fa8fb1f11e8a45fd1012ca6461e278.tar.bz2
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
Diffstat (limited to 'gcc/varpool.c')
-rw-r--r--gcc/varpool.c166
1 files changed, 105 insertions, 61 deletions
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 43ee229..d223779 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"