/* Control and data flow functions for trees.
- Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
tree_rest_of_compilation (tree fndecl, bool nested_p)
{
location_t saved_loc;
+ struct cgraph_node *node, *saved_node = NULL;
timevar_push (TV_EXPAND);
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
+ node = cgraph_node (fndecl);
+
+ /* We might need the body of this function so that we can expand
+ it inline somewhere else. This means not lowering some constructs
+ such as exception handling. */
+ if (cgraph_preserve_function_body_p (fndecl))
+ {
+ if (!flag_unit_at_a_time)
+ {
+ struct cgraph_edge *e;
+
+ saved_node = cgraph_clone_node (node);
+ for (e = saved_node->callees; e; e = e->next_callee)
+ if (!e->inline_failed)
+ cgraph_clone_inlined_nodes (e, true);
+ }
+ cfun->saved_tree = save_body (fndecl, &cfun->saved_args);
+ }
+
+ if (flag_inline_trees)
+ {
+ struct cgraph_edge *e;
+ for (e = node->callees; e; e = e->next_callee)
+ if (!e->inline_failed || warn_inline)
+ break;
+ if (e)
+ {
+ timevar_push (TV_INTEGRATION);
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ }
+ }
+
/* If the function has a variably modified type, there may be
SAVE_EXPRs in the parameter types. Their context must be set to
refer to this function; they cannot be expanded in the containing
expand_function_start (fndecl, 0);
/* Allow language dialects to perform special processing. */
- (*lang_hooks.rtl_expand.start) ();
+ lang_hooks.rtl_expand.start ();
/* If this function is `main', emit a call to `__main'
to run global initializers, etc. */
expand_main_function ();
/* Generate the RTL for this function. */
- (*lang_hooks.rtl_expand.stmt) (DECL_SAVED_TREE (fndecl));
+ lang_hooks.rtl_expand.stmt (DECL_SAVED_TREE (fndecl));
/* We hard-wired immediate_size_expand to zero above.
expand_function_end will decrement this variable. So, we set the
immediate_size_expand = 1;
/* Allow language dialects to perform special processing. */
- (*lang_hooks.rtl_expand.end) ();
+ lang_hooks.rtl_expand.end ();
/* Generate rtl for function exit. */
expand_function_end ();
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
+
/* Undo the GC context switch. */
if (nested_p)
ggc_pop_context ();
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
clear_decl_rtl,
fndecl);
- if (!cgraph_function_possibly_inlined_p (fndecl))
+ /* Restore original body if still needed. */
+ if (cfun->saved_tree)
+ {
+ DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
+ DECL_ARGUMENTS (fndecl) = cfun->saved_args;
+
+ /* When not in unit-at-a-time mode, we must preserve out of line copy
+ representing node before inlining. Restore original outgoing edges
+ using clone we created earlier. */
+ if (!flag_unit_at_a_time)
+ {
+ struct cgraph_edge *e;
+ while (node->callees)
+ cgraph_remove_edge (node->callees);
+ node->callees = saved_node->callees;
+ saved_node->callees = NULL;
+ for (e = saved_node->callees; e; e = e->next_callee)
+ e->caller = node;
+ cgraph_remove_node (saved_node);
+ }
+ }
+ else
{
DECL_SAVED_TREE (fndecl) = NULL;
- if (DECL_SAVED_INSNS (fndecl) == 0
- && !cgraph_node (fndecl)->origin)
+ if (cgraph_node (fndecl)->origin)
{
/* Stop pointing to the local nodes about to be freed.
But DECL_INITIAL must remain nonzero so we know this
If rest_of_compilation set this to 0, leave it 0. */
if (DECL_INITIAL (fndecl) != 0)
DECL_INITIAL (fndecl) = error_mark_node;
-
- DECL_ARGUMENTS (fndecl) = 0;
}
}
+ free_after_compilation (cfun);
+ cfun = 0;
+ DECL_STRUCT_FUNCTION (fndecl) = 0;
input_location = saved_loc;