/* 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.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "debug.h"
#include "target.h"
#include "output.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)
+{
+ /* 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. */
+tree
+add_new_static_var (tree type)
{
- 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);
+ tree new_decl;
+ struct varpool_node *new_node;
+
+ new_decl = create_tmp_var (type, NULL);
+ DECL_NAME (new_decl) = create_tmp_var_name (NULL);
+ TREE_READONLY (new_decl) = 0;
+ TREE_STATIC (new_decl) = 1;
+ TREE_USED (new_decl) = 1;
+ DECL_CONTEXT (new_decl) = NULL_TREE;
+ DECL_ABSTRACT (new_decl) = 0;
+ lang_hooks.dup_lang_specific_decl (new_decl);
+ create_var_ann (new_decl);
+ new_node = varpool_node (new_decl);
+ varpool_mark_needed_node (new_node);
+ add_referenced_var (new_decl);
+ varpool_finalize_decl (new_decl);
+
+ return new_node->decl;
}
#include "gt-varpool.h"