/* Callgraph based interprocedural optimizations.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Jan Hubicka
case CGRAPH_STATE_EXPANSION:
/* Functions created during expansion shall be compiled
directly. */
- node->output = 0;
+ node->process = 0;
cgraph_expand_function (node);
break;
static void
cgraph_reset_node (struct cgraph_node *node)
{
- /* If node->output is set, then we have already begun whole-unit analysis.
+ /* If node->process is set, then we have already begun whole-unit analysis.
This is *not* testing for whether we've already emitted the function.
That case can be sort-of legitimately seen with real function redefinition
errors. I would argue that the front end should never present us with
such a case, but don't enforce that for now. */
- gcc_assert (!node->output);
+ gcc_assert (!node->process);
/* Reset our data structures so we can analyze the function again. */
memset (&node->local, 0, sizeof (node->local));
if (!edge->callee->reachable)
cgraph_mark_reachable_node (edge->callee);
+ /* If decl is a clone of an abstract function, mark that abstract
+ function so that we don't release its body. The DECL_INITIAL() of that
+ abstract function declaration will be later needed to output debug info. */
+ if (DECL_ABSTRACT_ORIGIN (decl))
+ {
+ struct cgraph_node *origin_node = cgraph_node (DECL_ABSTRACT_ORIGIN (decl));
+ origin_node->abstract_and_needed = true;
+ }
+
/* We finalize local static variables during constructing callgraph
edges. Process their attributes too. */
process_function_and_variable_attributes (first_processed,
tree decl = node->decl;
struct cgraph_edge *e;
- gcc_assert (!node->output);
+ gcc_assert (!node->process);
for (e = node->callers; e; e = e->next_caller)
if (e->inline_failed)
|| (e && node->reachable))
&& !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl))
- node->output = 1;
+ node->process = 1;
else
{
/* We should've reclaimed all functions that are not needed. */
gcc_assert (!node->global.inlined_to);
announce_function (decl);
+ node->process = 0;
gcc_assert (node->lowered);
/* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
bool
-cgraph_inline_p (struct cgraph_edge *e, const char **reason)
+cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason)
{
*reason = e->inline_failed;
return !e->inline_failed;
/* Garbage collector may remove inline clones we eliminate during
optimization. So we must be sure to not reference them. */
for (i = 0; i < order_pos; i++)
- if (order[i]->output)
+ if (order[i]->process)
order[new_order_pos++] = order[i];
for (i = new_order_pos - 1; i >= 0; i--)
{
node = order[i];
- if (node->output)
+ if (node->process)
{
gcc_assert (node->reachable);
- node->output = 0;
+ node->process = 0;
cgraph_expand_function (node);
}
}
for (pf = cgraph_nodes; pf; pf = pf->next)
{
- if (pf->output)
+ if (pf->process)
{
i = pf->order;
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
switch (nodes[i].kind)
{
case ORDER_FUNCTION:
- nodes[i].u.f->output = 0;
+ nodes[i].u.f->process = 0;
cgraph_expand_function (nodes[i].u.f);
break;
varpool_assemble_pending_decls ();
}
- varpool_output_debug_info ();
cgraph_process_new_functions ();
cgraph_state = CGRAPH_STATE_FINISHED;
/* Update the call expr on the edges to call the new version. */
for (e = new_version->callers; e; e = e->next_caller)
- gimple_call_set_fndecl (e->call_stmt, new_version->decl);
+ {
+ struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->decl);
+ gimple_call_set_fndecl (e->call_stmt, new_version->decl);
+ /* Update EH information too, just in case. */
+ if (!stmt_could_throw_p (e->call_stmt)
+ && lookup_stmt_eh_region_fn (inner_function, e->call_stmt))
+ remove_stmt_from_eh_region_fn (inner_function, e->call_stmt);
+ }
}
/* Copy the OLD_VERSION_NODE function tree to the new version. */
tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip);
- /* Update the call_expr on the edges to call the new version node. */
- update_call_expr (new_version_node);
/* Update the new version's properties.
- Make The new version visible only within this translation unit.
+ Make The new version visible only within this translation unit. Make sure
+ that is not weak also.
??? We cannot use COMDAT linkage because there is no
ABI support for this. */
DECL_EXTERNAL (new_version_node->decl) = 0;
DECL_ONE_ONLY (new_version_node->decl) = 0;
TREE_PUBLIC (new_version_node->decl) = 0;
DECL_COMDAT (new_version_node->decl) = 0;
+ DECL_WEAK (new_version_node->decl) = 0;
+ DECL_VIRTUAL_P (new_version_node->decl) = 0;
new_version_node->local.externally_visible = 0;
new_version_node->local.local = 1;
new_version_node->lowered = true;
+
+ /* Update the call_expr on the edges to call the new version node. */
+ update_call_expr (new_version_node);
+
cgraph_call_function_insertion_hooks (new_version_node);
return new_version_node;
}