aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cgraph.c4
-rw-r--r--gcc/cgraphunit.c37
-rw-r--r--gcc/lto-cgraph.c11
-rw-r--r--gcc/lto/lto.c2
5 files changed, 55 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 61ca0dc5fe5..235016536ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-21 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (dump_cgraph_node): Dump alias flag.
+ * cgraphunit.c (handle_alias_pairs): Handle weakrefs with no destination.
+ (get_alias_symbol): New function.
+ (output_weakrefs): Output also weakrefs with no destinatoin.
+ (lto_output_node): Output weakref alias flag when at function boundary.
+
2011-10-21 Andrew Stubbs <ams@codesourcery.com>
PR target/50809
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 84d6bd5198a..f056d3db58e 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1838,6 +1838,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " only_called_at_startup");
if (node->only_called_at_exit)
fprintf (f, " only_called_at_exit");
+ else if (node->alias)
+ fprintf (f, " alias");
fprintf (f, "\n");
@@ -2567,7 +2569,7 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
for (e = node->callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p
&& (include_overwritable
- || cgraph_function_body_availability (e->caller)))
+ || cgraph_function_body_availability (e->caller) > AVAIL_OVERWRITABLE))
if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
include_overwritable))
return true;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index ef71b5bed7c..25d7561cbdb 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1249,6 +1249,21 @@ handle_alias_pairs (void)
varpool_create_variable_alias (p->decl, target_vnode->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i);
}
+ /* Weakrefs with target not defined in current unit are easy to handle; they
+ behave just as external variables except we need to note the alias flag
+ to later output the weakref pseudo op into asm file. */
+ else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL
+ && (TREE_CODE (p->decl) == FUNCTION_DECL
+ ? (varpool_node_for_asm (p->target) == NULL)
+ : (cgraph_node_for_asm (p->target) == NULL)))
+ {
+ if (TREE_CODE (p->decl) == FUNCTION_DECL)
+ cgraph_get_create_node (p->decl)->alias = true;
+ else
+ varpool_get_node (p->decl)->alias = true;
+ DECL_EXTERNAL (p->decl) = 1;
+ VEC_unordered_remove (alias_pair, alias_pairs, i);
+ }
else
{
if (dump_file)
@@ -2064,6 +2079,18 @@ ipa_passes (void)
bitmap_obstack_release (NULL);
}
+
+/* Return string alias is alias of. */
+
+static tree
+get_alias_symbol (tree decl)
+{
+ tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
+ return get_identifier (TREE_STRING_POINTER
+ (TREE_VALUE (TREE_VALUE (alias))));
+}
+
+
/* Weakrefs may be associated to external decls and thus not output
at expansion time. Emit all neccesary aliases. */
@@ -2073,15 +2100,17 @@ output_weakrefs (void)
struct cgraph_node *node;
struct varpool_node *vnode;
for (node = cgraph_nodes; node; node = node->next)
- if (node->alias && node->thunk.alias && DECL_EXTERNAL (node->decl)
+ if (node->alias && DECL_EXTERNAL (node->decl)
&& !TREE_ASM_WRITTEN (node->decl))
assemble_alias (node->decl,
- DECL_ASSEMBLER_NAME (node->thunk.alias));
+ node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
+ : get_alias_symbol (node->decl));
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
- if (vnode->alias && vnode->alias_of && DECL_EXTERNAL (vnode->decl)
+ if (vnode->alias && DECL_EXTERNAL (vnode->decl)
&& !TREE_ASM_WRITTEN (vnode->decl))
assemble_alias (vnode->decl,
- DECL_ASSEMBLER_NAME (vnode->alias_of));
+ vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
+ : get_alias_symbol (vnode->decl));
}
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 833bf84743b..98ae19b4aab 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -512,7 +512,13 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|| referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
bp_pack_value (&bp, node->lowered, 1);
bp_pack_value (&bp, in_other_partition, 1);
- bp_pack_value (&bp, node->alias && !boundary_p, 1);
+ /* Real aliases in a boundary become non-aliases. However we still stream
+ alias info on weakrefs.
+ TODO: We lose a bit of information here - when we know that variable is
+ defined in other unit, we may use the info on aliases to resolve
+ symbol1 != symbol2 type tests that we can do only for locally defined objects
+ otherwise. */
+ bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->decl)), 1);
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_exit, 1);
@@ -530,7 +536,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
}
- if ((node->alias || node->thunk.thunk_p) && !boundary_p)
+ if ((node->alias || node->thunk.thunk_p)
+ && (!boundary_p || (node->alias && DECL_EXTERNAL (node->decl))))
{
streamer_write_hwi_in_range (ob->main_stream, 0, 1,
node->thunk.alias != NULL);
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 40afc7f1c9b..c50a97ec205 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1481,6 +1481,8 @@ add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode
{
varpool_node_set_iterator vsi;
+ vnode = varpool_variable_node (vnode, NULL);
+
/* If NODE is already there, we have nothing to do. */
vsi = varpool_node_set_find (part->varpool_set, vnode);
if (!vsi_end_p (vsi))