- /* Clear out memory we no longer need. */
- free_after_parsing (cfun);
- /* Since we never call rest_of_compilation, we never clear
- CFUN. Do so explicitly. */
- free_after_compilation (cfun);
- cfun = NULL;
-
- if (flag_unit_at_a_time && can_defer_p)
- {
- cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
- current_function_decl = NULL;
- return;
- }
-
- if (! nested)
- {
- /* Function is parsed.
- Generate RTL for the body of this function or defer
- it for later expansion. */
- int uninlinable = 1;
-
- /* There's no reason to do any of the work here if we're only doing
- semantic analysis; this code just generates RTL. */
- if (flag_syntax_only)
- {
- current_function_decl = NULL;
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
- return;
- }
-
- if (flag_inline_trees)
- {
- /* First, cache whether the current function is inlinable. Some
- predicates depend on cfun and current_function_decl to
- function completely. */
- timevar_push (TV_INTEGRATION);
- uninlinable = ! tree_inlinable_function_p (fndecl, 0);
-
- if (can_defer_p
- /* We defer functions marked inline *even if* the function
- itself is not inlinable. This is because we don't yet
- know if the function will actually be used; we may be
- able to avoid emitting it entirely. */
- && (! uninlinable || DECL_DECLARED_INLINE_P (fndecl))
- /* Save function tree for inlining. Should return 0 if the
- language does not support function deferring or the
- function could not be deferred. */
- && defer_fn (fndecl))
- {
- /* Let the back-end know that this function exists. */
- (*debug_hooks->deferred_inline_function) (fndecl);
- timevar_pop (TV_INTEGRATION);
- current_function_decl = NULL;
- return;
- }
-
- /* Then, inline any functions called in it. */
- optimize_inline_calls (fndecl);
- timevar_pop (TV_INTEGRATION);
- }
-
- c_expand_body (fndecl);
-
- /* Keep the function body if it's needed for inlining or dumping. */
- if (uninlinable && !dump_enabled_p (TDI_all))
- {
- /* Allow the body of the function to be garbage collected. */
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
- }
-
- /* Let the error reporting routines know that we're outside a
- function. For a nested function, this value is used in
- c_pop_function_context and then reset via pop_function_context. */
- current_function_decl = NULL;
- }
-}
-
-/* Generate the RTL for a deferred function FNDECL. */
-
-void
-c_expand_deferred_function (tree fndecl)
-{
- /* DECL_INLINE or DECL_RESULT might got cleared after the inline
- function was deferred, e.g. in duplicate_decls. */
- if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
- {
- if (flag_inline_trees)
- {
- timevar_push (TV_INTEGRATION);
- optimize_inline_calls (fndecl);
- timevar_pop (TV_INTEGRATION);
- }
- c_expand_body (fndecl);
- current_function_decl = NULL;
- }
-}
-
-/* Called to move the SAVE_EXPRs for parameter declarations in a
- nested function into the nested function. DATA is really the
- nested FUNCTION_DECL. */
-
-static tree
-set_save_expr_context (tree *tp,
- int *walk_subtrees,
- void *data)
-{
- if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
- SAVE_EXPR_CONTEXT (*tp) = (tree) data;
- /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
- circularity. */
- else if (DECL_P (*tp))
- *walk_subtrees = 0;
-
- return NULL_TREE;
-}
-
-/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero,
- then we are already in the process of generating RTL for another
- function. If can_defer_p is zero, we won't attempt to defer the
- generation of RTL. */
-
-static void
-c_expand_body_1 (tree fndecl, int nested_p)
-{
- timevar_push (TV_EXPAND);
-
- if (nested_p)
- {
- /* Make sure that we will evaluate variable-sized types involved
- in our function's type. */
- expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
- /* Squirrel away our current state. */
- push_function_context ();
- }
-
- /* Initialize the RTL code for the function. */
- current_function_decl = fndecl;
- input_location = DECL_SOURCE_LOCATION (fndecl);
- init_function_start (fndecl);
-
- /* This function is being processed in whole-function mode. */
- cfun->x_whole_function_mode_p = 1;
-
- /* Even though we're inside a function body, we still don't want to
- call expand_expr to calculate the size of a variable-sized array.
- We haven't necessarily assigned RTL to all variables yet, so it's
- not safe to try to expand expressions involving them. */
- immediate_size_expand = 0;
- cfun->x_dont_save_pending_sizes_p = 1;
-
- /* Set up parameters and prepare for return, for the function. */
- expand_function_start (fndecl, 0);
-
- /* 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
- function. */
- if (decl_function_context (fndecl)
- && variably_modified_type_p (TREE_TYPE (fndecl)))
- walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
- NULL);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && MAIN_NAME_P (DECL_NAME (fndecl))
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- expand_main_function ();
-
- /* Generate the RTL for this function. */
- 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
- variable to one here, so that after the decrement it will remain
- zero. */
- immediate_size_expand = 1;
-
- /* Allow language dialects to perform special processing. */
- if (lang_expand_function_end)
- (*lang_expand_function_end) ();
-
- /* Generate rtl for function exit. */
- expand_function_end ();
-
- /* If this is a nested function, protect the local variables in the stack
- above us from being collected while we're compiling this function. */
- if (nested_p)
- ggc_push_context ();
-
- /* 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 ();
-