summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/cgraph.h1
-rw-r--r--gcc/cgraphunit.c1
-rw-r--r--gcc/ipa.c18
-rw-r--r--gcc/varpool.c10
5 files changed, 32 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0fe06ac7dfb..d616cb7dc77 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2009-11-12 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.h (varpool_node_name): Declare.
+ * cgraphunit.c (process_function_and_variable_attributes): Set force_output
+ flag on used variables.
+ * ipa.c (function_and_variable_visibility): Dump externally visible and needed
+ variables.
+ * varpool.c (varpool_node_name): Export.
+ (decide_is_variable_needed): Check COMDAT for externally visible vars;
+ ignore needed flag.
+
2009-11-12 Uros Bizjak <ubizjak@gmail.com>
PR middle-end/41930
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 016ce9de14c..46fee67e6e3 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -531,6 +531,7 @@ bool varpool_assemble_decl (struct varpool_node *node);
bool varpool_analyze_pending_decls (void);
void varpool_remove_unreferenced_decls (void);
void varpool_empty_needed_queue (void);
+const char * varpool_node_name (struct varpool_node *node);
/* Walk all reachable static variables. */
#define FOR_EACH_STATIC_VARIABLE(node) \
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 7105e59c5ec..377e4353fdb 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -884,6 +884,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
{
mark_decl_referenced (decl);
+ vnode->force_output = true;
if (vnode->finalized)
varpool_mark_needed_node (vnode);
}
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 4297ea2f46f..bf8faa95fc9 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -292,7 +292,8 @@ function_and_variable_visibility (bool whole_program)
for (node = cgraph_nodes; node; node = node->next)
{
- gcc_assert (!DECL_WEAK (node->decl) || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
+ gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
+ || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
if (cgraph_externally_visible_p (node, whole_program))
{
gcc_assert (!node->global.inlined_to);
@@ -317,7 +318,7 @@ function_and_variable_visibility (bool whole_program)
{
if (!vnode->finalized)
continue;
- gcc_assert ((!DECL_WEAK (vnode->decl) || DECL_COMMON (vnode->decl))
+ gcc_assert ((!DECL_WEAK (vnode->decl) && !DECL_COMMON (vnode->decl) && !DECL_COMDAT (vnode->decl))
|| TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (node->decl));
if (vnode->needed
&& (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
@@ -352,6 +353,11 @@ function_and_variable_visibility (bool whole_program)
if (node->local.externally_visible)
fprintf (dump_file, " %s", cgraph_node_name (node));
fprintf (dump_file, "\n\n");
+ fprintf (dump_file, "\nMarking externally visible variables:");
+ for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+ if (vnode->externally_visible)
+ fprintf (dump_file, " %s", varpool_node_name (vnode));
+ fprintf (dump_file, "\n\n");
}
cgraph_function_flags_ready = true;
return 0;
@@ -410,6 +416,14 @@ whole_program_function_and_variable_visibility (void)
for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
varpool_mark_needed_node (vnode);
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nNeeded variables:");
+ for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+ if (vnode->needed)
+ fprintf (dump_file, " %s", varpool_node_name (vnode));
+ fprintf (dump_file, "\n\n");
+ }
return 0;
}
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 8815efda249..90a9ace0ff9 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -80,7 +80,7 @@ static GTY(()) struct varpool_node *varpool_first_unanalyzed_node;
static GTY(()) struct varpool_node *varpool_assembled_nodes_queue;
/* Return name of the node used in debug output. */
-static const char *
+const char *
varpool_node_name (struct varpool_node *node)
{
return lang_hooks.decl_printable_name (node->decl, 2);
@@ -229,7 +229,8 @@ bool
decide_is_variable_needed (struct varpool_node *node, tree decl)
{
/* If the user told us it is used, then it must be so. */
- if (node->externally_visible || node->force_output)
+ if ((node->externally_visible && !DECL_COMDAT (decl))
+ || node->force_output)
return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
@@ -239,11 +240,6 @@ decide_is_variable_needed (struct varpool_node *node, tree decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
return true;
- /* If we decided it was needed before, but at the time we didn't have
- the definition available, then it's still needed. */
- if (node->needed)
- return true;
-
/* Externally visible variables must be output. The exception is
COMDAT variables that must be output only when they are needed. */
if (TREE_PUBLIC (decl)