/* Callgraph handling code.
- Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
#include "debug.h"
#include "target.h"
#include "output.h"
-#include "tree-gimple.h"
+#include "gimple.h"
#include "tree-flow.h"
/* This file contains basic routines manipulating variable pool.
The queue is maintained via mark_needed_node, linked via node->next_needed
pointer.
- LAST_NNEDED_NODE points to the end of queue, so it can be maintained in forward
- order. QTY is needed to make it friendly to PCH.
+ LAST_NEEDED_NODE points to the end of queue, so it can be
+ maintained in forward order. GTY is needed to make it friendly to
+ PCH.
- During unit-at-a-time compilation we construct the queue of needed variables
+ During compilation we construct the queue of needed variables
twice: first time it is during cgraph construction, second time it is at the
end of compilation in VARPOOL_REMOVE_UNREFERENCED_DECLS so we can avoid
optimized out variables being output.
struct varpool_node *node;
fprintf (f, "variable pool:\n\n");
- for (node = varpool_nodes; node; node = node->next_needed)
+ for (node = varpool_nodes; node; node = node->next)
dump_varpool_node (f, node);
}
+/* Dump the variable pool to stderr. */
+
+void
+debug_varpool (void)
+{
+ dump_varpool (stderr);
+}
+
/* Given an assembler name, lookup node. */
struct varpool_node *
varpool_node_for_asm (tree asmname)
/* Determine if variable DECL is needed. That is, visible to something
either outside this translation unit, something magic in the system
- configury, or (if not doing unit-at-a-time) to something we haven't
- seen yet. */
+ configury */
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)
return true;
- if (!flag_unit_at_a_time
- && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
the name later after finalizing the function and the fact is noticed
/* When not reordering top level variables, we have to assume that
we are going to keep everything. */
- if (flag_unit_at_a_time && flag_toplevel_reorder)
+ if (flag_toplevel_reorder)
return false;
/* We want to emit COMDAT variables only when absolutely necessary. */
if this function has already run. */
if (node->finalized)
{
- if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
+ if (cgraph_global_info_ready)
varpool_assemble_pending_decls ();
return;
}
there. */
else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
varpool_mark_needed_node (node);
- if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
+ if (cgraph_global_info_ready)
varpool_assemble_pending_decls ();
}
&& (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
{
assemble_variable (decl, 0, 1, 0);
- return TREE_ASM_WRITTEN (decl);
+ if (TREE_ASM_WRITTEN (decl))
+ {
+ node->next_needed = varpool_assembled_nodes_queue;
+ varpool_assembled_nodes_queue = node;
+ node->finalized = 1;
+ return true;
+ }
}
return false;
varpool_nodes_queue = varpool_nodes_queue->next_needed;
if (varpool_assemble_decl (node))
- {
- changed = true;
- node->next_needed = varpool_assembled_nodes_queue;
- varpool_assembled_nodes_queue = node;
- node->finalized = 1;
- }
+ changed = true;
else
node->next_needed = NULL;
}
return changed;
}
-/* Output all variables enqueued to be assembled. */
+/* Remove all elements from the queue so we can re-use it for debug output. */
void
-varpool_output_debug_info (void)
+varpool_empty_needed_queue (void)
{
- timevar_push (TV_SYMOUT);
- if (errorcount == 0 && sorrycount == 0)
- while (varpool_assembled_nodes_queue)
- {
- struct varpool_node *node = varpool_assembled_nodes_queue;
-
- /* Local static variables are never seen by check_global_declarations
- so we need to output debug info by hand. */
- if (DECL_CONTEXT (node->decl)
- && (TREE_CODE (DECL_CONTEXT (node->decl)) == BLOCK
- || TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
- && errorcount == 0 && sorrycount == 0)
- (*debug_hooks->global_decl) (node->decl);
- varpool_assembled_nodes_queue = node->next_needed;
- node->next_needed = 0;
- }
- timevar_pop (TV_SYMOUT);
+ /* EH might mark decls as needed during expansion. This should be safe since
+ we don't create references to new function, but it should not be used
+ elsewhere. */
+ varpool_analyze_pending_decls ();
+
+ while (varpool_nodes_queue)
+ {
+ struct varpool_node *node = varpool_nodes_queue;
+ varpool_nodes_queue = varpool_nodes_queue->next_needed;
+ node->next_needed = NULL;
+ }
+ /* varpool_nodes_queue is now empty, clear the pointer to the last element
+ in the queue. */
+ varpool_last_needed_node = NULL;
}
/* Create a new global variable of type TYPE. */