aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2003-08-29 16:21:13 -0700
committerRichard Henderson <rth@gcc.gnu.org>2003-08-29 16:21:13 -0700
commit4985cde3ef44391a43fd95c0972bf72c86e127cb (patch)
treed3ecf1a361ca516453ed6172c096bc2f280d5875
parentfc2b84778bb51750c841f53b1ba30950935cc901 (diff)
downloadgcc-4985cde3ef44391a43fd95c0972bf72c86e127cb.zip
gcc-4985cde3ef44391a43fd95c0972bf72c86e127cb.tar.gz
gcc-4985cde3ef44391a43fd95c0972bf72c86e127cb.tar.bz2
tree-optimize.c: New file.
gcc/ * tree-optimize.c: New file. * Makefile.in (OBJS-archive): Add tree-optimize.o. (tree-optimize.o): New. * c-decl.c (store_parm_decls): Use allocate_struct_function. (finish_function): Don't free_after_parsing or free_after_compilation. (set_save_expr_context): Move to tree-optimize.c. (c_expand_body_1): Use tree_rest_of_compilation. * c-lang.c (LANG_HOOKS_RTL_EXPAND_STMT): New. * objc/objc-lang.c (LANG_HOOKS_RTL_EXPAND_STMT): New. * c-objc-common.c (expand_deferred_fns): Don't emit unused inlines; iterate until closure. * langhooks-def.h (LANG_HOOKS_RTL_EXPAND_START, LANG_HOOKS_RTL_EXPAND_STMT, LANG_HOOKS_RTL_EXPAND_END): New. (LANG_HOOKS_RTL_EXPAND_INITIALIZER): New. * langhooks.h (struct lang_hooks_for_rtl_expansion): New. * toplev.h (tree_rest_of_compilation): Declare it. gcc/cp/ * cp-lang.c (LANG_HOOKS_RTL_EXPAND_START): New. (LANG_HOOKS_RTL_EXPAND_STMT): New. * cp-tree.h (cxx_expand_function_start): Declare. * decl.c (start_function): Use allocate_struct_function. Move stmts_are_full_exprs_p assertion from expand_body. Do not free_after_parsing or free_after_compilation. (cxx_push_function_context): Move code to set struct function data from genrtl_start_function. * optimize.c (optimize_function): Don't inc/dec function_depth. * semantics.c (expand_body): Use tree_rest_of_compilation. (cxx_expand_function_start): Rename from genrtl_start_function, omit bits done by tree_rest_of_compilation. (genrtl_finish_function): Remove. (clear_decl_rtl): Move to ../tree-optimize.c. Co-Authored-By: Jason Merrill <jason@redhat.com> From-SVN: r70933
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/Makefile.in13
-rw-r--r--gcc/c-decl.c139
-rw-r--r--gcc/c-lang.c3
-rw-r--r--gcc/c-objc-common.c39
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/cp-lang.c5
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c40
-rw-r--r--gcc/cp/optimize.c14
-rw-r--r--gcc/cp/semantics.c250
-rw-r--r--gcc/langhooks-def.h13
-rw-r--r--gcc/langhooks.h15
-rw-r--r--gcc/objc/objc-lang.c3
-rw-r--r--gcc/toplev.h1
-rw-r--r--gcc/tree-optimize.c250
16 files changed, 422 insertions, 401 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d573615..fdabb62 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,24 @@
2003-08-29 Richard Henderson <rth@redhat.com>
+ * tree-optimize.c: New file.
+ * Makefile.in (OBJS-archive): Add tree-optimize.o.
+ (tree-optimize.o): New.
+ * c-decl.c (store_parm_decls): Use allocate_struct_function.
+ (finish_function): Don't free_after_parsing or free_after_compilation.
+ (set_save_expr_context): Move to tree-optimize.c.
+ (c_expand_body_1): Use tree_rest_of_compilation.
+ * c-lang.c (LANG_HOOKS_RTL_EXPAND_STMT): New.
+ * objc/objc-lang.c (LANG_HOOKS_RTL_EXPAND_STMT): New.
+ * c-objc-common.c (expand_deferred_fns): Don't emit unused inlines;
+ iterate until closure.
+ * langhooks-def.h (LANG_HOOKS_RTL_EXPAND_START,
+ LANG_HOOKS_RTL_EXPAND_STMT, LANG_HOOKS_RTL_EXPAND_END): New.
+ (LANG_HOOKS_RTL_EXPAND_INITIALIZER): New.
+ * langhooks.h (struct lang_hooks_for_rtl_expansion): New.
+ * toplev.h (tree_rest_of_compilation): Declare it.
+
+2003-08-29 Richard Henderson <rth@redhat.com>
+
* function.h (struct function): Add rtl_inline_init, saved_for_inline.
* integrate.c (save_for_inline): Set saved_for_inline.
* c-semantics.c (genrtl_scope_stmt): Check it.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 94569eb..3ea2c56 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -845,7 +845,7 @@ OBJS-common = \
OBJS-md = $(out_object_file)
OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o \
- cgraph.o cgraphunit.o
+ tree-optimize.o cgraph.o cgraphunit.o
OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
@@ -1466,10 +1466,13 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) flags.h fu
tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) flags.h langhooks.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
$(EXPR_H) $(SPLAY_TREE_H) tree-dump.h
-tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(EXPR_H) flags.h $(PARAMS_H) input.h insn-config.h $(INTEGRATE_H) \
- $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h langhooks.h \
- $(C_COMMON_H) tree-inline.h cgraph.h
+tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(RTL_H) $(EXPR_H) flags.h $(PARAMS_H) input.h insn-config.h \
+ $(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
+ langhooks.h $(C_COMMON_H) tree-inline.h cgraph.h
+tree-optimize.o : tree-optimize.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) toplev.h langhooks.h cgraph.h $(TIMEVAR_H) function.h $(GGC_H)
+
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) langhooks.h real.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 51491d2..eef6e6d 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -6032,7 +6032,7 @@ store_parm_decls (void)
gen_aux_info_record (fndecl, 1, 0, prototype);
/* Initialize the RTL code for the function. */
- init_function_start (fndecl);
+ allocate_struct_function (fndecl);
/* Begin the statement tree for this function. */
begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
@@ -6142,11 +6142,8 @@ finish_function (int nested, int can_defer_p)
&& DECL_INLINE (fndecl))
warning ("no return statement in function returning non-void");
- /* 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);
+ /* We're leaving the context of this function, so zap cfun. It's still in
+ DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */
cfun = NULL;
if (flag_unit_at_a_time && can_defer_p)
@@ -6239,25 +6236,6 @@ c_expand_deferred_function (tree fndecl)
}
}
-/* 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
@@ -6266,78 +6244,14 @@ set_save_expr_context (tree *tp,
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_FILE_SCOPE_P (fndecl))
- 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 ();
+ tree_rest_of_compilation (fndecl);
/* With just -Wextra, complain only if function returns both with
and without a value. */
@@ -6346,46 +6260,6 @@ c_expand_body_1 (tree fndecl, int nested_p)
&& current_function_returns_null)
warning ("this function may return with or without a value");
- /* If requested, warn about function definitions where the function will
- return a value (usually of some struct or union type) which itself will
- take up a lot of stack space. */
-
- if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
- {
- tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
-
- if (ret_type && TYPE_SIZE_UNIT (ret_type)
- && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
- && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
- larger_than_size))
- {
- const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
- unsigned int size_as_int
- = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
-
- if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
- warning ("%Hsize of return value of '%D' is %u bytes",
- locus, fndecl, size_as_int);
- else
- warning ("%Hsize of return value of '%D' is larger than %wd bytes",
- locus, fndecl, larger_than_size);
- }
- }
-
- if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p
- && ! flag_inline_trees)
- {
- /* Stop pointing to the local nodes about to be freed.
- But DECL_INITIAL must remain nonzero so we know this
- was an actual function definition.
- For a nested function, this is done in c_pop_function_context.
- 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;
- }
-
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
if (targetm.have_ctors_dtors)
@@ -6403,11 +6277,6 @@ c_expand_body_1 (tree fndecl, int nested_p)
else
static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
}
-
- if (nested_p)
- /* Return to the enclosing function. */
- pop_function_context ();
- timevar_pop (TV_EXPAND);
}
/* Like c_expand_body_1 but only for unnested functions. */
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index 93437a3..fb1741d 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -90,6 +90,9 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_DECL_UNINIT
#define LANG_HOOKS_DECL_UNINIT c_decl_uninit
+#undef LANG_HOOKS_RTL_EXPAND_STMT
+#define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt
+
/* Attribute hooks. */
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
index b5f263f..16e0cff 100644
--- a/gcc/c-objc-common.c
+++ b/gcc/c-objc-common.c
@@ -289,20 +289,43 @@ static void
expand_deferred_fns (void)
{
unsigned int i;
+ bool reconsider;
- for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_fns); i++)
+ do
{
- tree decl = VARRAY_TREE (deferred_fns, i);
-
- if (! TREE_ASM_WRITTEN (decl))
+ reconsider = false;
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_fns); i++)
{
- /* For static inline functions, delay the decision whether to
- emit them or not until wrapup_global_declarations. */
- if (! TREE_PUBLIC (decl))
- DECL_DEFER_OUTPUT (decl) = 1;
+ tree decl = VARRAY_TREE (deferred_fns, i);
+
+ if (TREE_ASM_WRITTEN (decl))
+ continue;
+
+ /* "extern inline" says the symbol exists externally,
+ which means we should *never* expand it locally
+ unless we're actually inlining it. */
+ /* ??? Why did we queue these in the first place? */
+ if (DECL_DECLARED_INLINE_P (decl) && DECL_EXTERNAL (decl))
+ continue;
+
+ /* With flag_keep_inline_functions, we're emitting everything,
+ so we never need to reconsider. */
+ if (flag_keep_inline_functions)
+ ;
+ /* Must emit all public functions. C doesn't have COMDAT
+ functions, so we don't need to check that, like C++. */
+ else if (TREE_PUBLIC (decl))
+ reconsider = true;
+ /* Must emit if the symbol is referenced. */
+ else if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ reconsider = true;
+ else
+ continue;
+
c_expand_deferred_function (decl);
}
}
+ while (reconsider);
deferred_fns = 0;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 60c81ab..503a3b8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+2003-08-29 Richard Henderson <rth@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_RTL_EXPAND_START): New.
+ (LANG_HOOKS_RTL_EXPAND_STMT): New.
+ * cp-tree.h (cxx_expand_function_start): Declare.
+ * decl.c (start_function): Use allocate_struct_function.
+ Move stmts_are_full_exprs_p assertion from expand_body.
+ Do not free_after_parsing or free_after_compilation.
+ (cxx_push_function_context): Move code to set struct function
+ data from genrtl_start_function.
+ * optimize.c (optimize_function): Don't inc/dec function_depth.
+ * semantics.c (expand_body): Use tree_rest_of_compilation.
+ (cxx_expand_function_start): Rename from genrtl_start_function,
+ omit bits done by tree_rest_of_compilation.
+ (genrtl_finish_function): Remove.
+ (clear_decl_rtl): Move to ../tree-optimize.c.
+
2003-08-29 Gabriel Dos Reis <gdr@integrable-solutions.net>
PR c++/11811
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 8ca9361..4d5ed27 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -115,6 +115,11 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#undef LANG_HOOKS_FUNCTION_FINAL
#define LANG_HOOKS_FUNCTION_FINAL cxx_pop_function_context
+#undef LANG_HOOKS_RTL_EXPAND_START
+#define LANG_HOOKS_RTL_EXPAND_START cxx_expand_function_start
+#undef LANG_HOOKS_RTL_EXPAND_STMT
+#define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt
+
/* Attribute hooks. */
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e1ad9df..1a2f06e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4137,6 +4137,7 @@ extern tree finish_alignof (tree);
extern void finish_decl_cleanup (tree, tree);
extern void finish_eh_cleanup (tree);
extern void expand_body (tree);
+extern void cxx_expand_function_start (void);
extern tree nullify_returns_r (tree *, int *, void *);
extern void do_pushlevel (scope_kind);
extern tree do_poplevel (void);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0f6d090..b4eb019 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13539,7 +13539,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
CFUN set up, and our per-function variables initialized.
FIXME factor out the non-RTL stuff. */
bl = current_binding_level;
- init_function_start (decl1);
+ allocate_struct_function (decl1);
current_binding_level = bl;
/* Even though we're inside a function body, we still don't want to
@@ -14084,6 +14084,10 @@ finish_function (int flags)
}
poplevel (1, 0, 1);
+ /* Statements should always be full-expressions at the outermost set
+ of curly braces for a function. */
+ my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
+
/* Set up the named return value optimization, if we can. Here, we
eliminate the copy from the nrv into the RESULT_DECL and any cleanup
for the nrv. genrtl_start_function and declare_return_variable
@@ -14154,12 +14158,9 @@ finish_function (int flags)
inline function, as we might never be compiled separately. */
&& (DECL_INLINE (fndecl) || processing_template_decl))
warning ("no return statement in function returning non-void");
-
- /* 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);
+
+ /* We're leaving the context of this function, so zap cfun. It's still in
+ DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */
cfun = NULL;
/* If this is an in-class inline definition, we may have to pop the
@@ -14479,6 +14480,31 @@ cxx_push_function_context (struct function * f)
/* Whenever we start a new function, we destroy temporaries in the
usual way. */
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+
+ if (f->decl)
+ {
+ tree fn = f->decl;
+
+ current_function_is_thunk = DECL_THUNK_P (fn);
+
+ if (DECL_SAVED_FUNCTION_DATA (fn))
+ {
+ /* If we already parsed this function, and we're just expanding it
+ now, restore saved state. */
+ *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
+
+ /* If we decided that we didn't want to inline this function,
+ make sure the back-end knows that. */
+ if (!current_function_cannot_inline)
+ current_function_cannot_inline = cp_function_chain->cannot_inline;
+
+ /* We don't need the saved data anymore. Unless this is an inline
+ function; we need the named return value info for
+ cp_copy_res_decl_for_inlining. */
+ if (! DECL_INLINE (fn))
+ DECL_SAVED_FUNCTION_DATA (fn) = NULL;
+ }
+ }
}
/* Free the language-specific parts of F, now that we've finished
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 4cb5c69..8c604e3 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -49,17 +49,6 @@ optimize_function (tree fn)
{
dump_function (TDI_original, fn);
- /* While in this function, we may choose to go off and compile
- another function. For example, we might instantiate a function
- in the hopes of inlining it. Normally, that wouldn't trigger any
- actual RTL code-generation -- but it will if the template is
- actually needed. (For example, if it's address is taken, or if
- some other function already refers to the template.) If
- code-generation occurs, then garbage collection will occur, so we
- must protect ourselves, just as we do while building up the body
- of the function. */
- ++function_depth;
-
if (flag_inline_trees
/* We do not inline thunks, as (a) the backend tries to optimize
the call to the thunkee, (b) tree based inlining breaks that
@@ -72,9 +61,6 @@ optimize_function (tree fn)
dump_function (TDI_inlined, fn);
}
- /* Undo the call to ggc_push_context above. */
- --function_depth;
-
dump_function (TDI_optimized, fn);
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c38bdd3..c9f3675 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -59,9 +59,7 @@ static void genrtl_try_block (tree);
static void genrtl_eh_spec_block (tree);
static void genrtl_handler (tree);
static void cp_expand_stmt (tree);
-static void genrtl_start_function (tree);
-static void genrtl_finish_function (tree);
-static tree clear_decl_rtl (tree *, int *, void *);
+
/* Finish processing the COND, the SUBSTMT condition for STMT. */
@@ -2863,9 +2861,6 @@ expand_body (tree fn)
location_t saved_loc;
tree saved_function;
- if (flag_unit_at_a_time && !cgraph_global_info_ready)
- abort ();
-
/* Compute the appropriate object-file linkage for inline
functions. */
if (DECL_DECLARED_INLINE_P (fn))
@@ -2879,61 +2874,35 @@ expand_body (tree fn)
if (DECL_EXTERNAL (fn))
return;
- /* Save the current file name and line number. When we expand the
- body of the function, we'll set INPUT_LOCATION so that
- error-messages come out in the right places. */
+ /* ??? When is this needed? */
saved_loc = input_location;
saved_function = current_function_decl;
- input_location = DECL_SOURCE_LOCATION (fn);
- current_function_decl = fn;
timevar_push (TV_INTEGRATION);
-
- /* Optimize the body of the function before expanding it. */
optimize_function (fn);
-
timevar_pop (TV_INTEGRATION);
- timevar_push (TV_EXPAND);
-
- genrtl_start_function (fn);
- current_function_is_thunk = DECL_THUNK_P (fn);
-
- /* Expand the body. */
- expand_stmt (DECL_SAVED_TREE (fn));
-
- /* Statements should always be full-expressions at the outermost set
- of curly braces for a function. */
- my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
-
- /* The outermost statement for a function contains the line number
- recorded when we finished processing the function. */
- input_line = STMT_LINENO (DECL_SAVED_TREE (fn));
-
- /* Generate code for the function. */
- genrtl_finish_function (fn);
- /* If possible, obliterate the body of the function so that it can
- be garbage collected. */
- if (dump_enabled_p (TDI_all))
- /* Keep the body; we're going to dump it. */
- ;
- else if (DECL_INLINE (fn) && flag_inline_trees)
- /* We might need the body of this function so that we can expand
- it inline somewhere else. */
- ;
- else
- /* We don't need the body; blow it away. */
- DECL_SAVED_TREE (fn) = NULL_TREE;
+ tree_rest_of_compilation (fn);
- /* And restore the current source position. */
current_function_decl = saved_function;
input_location = saved_loc;
- extract_interface_info ();
- timevar_pop (TV_EXPAND);
+ extract_interface_info ();
/* Emit any thunks that should be emitted at the same time as FN. */
emit_associated_thunks (fn);
+
+ /* If this function is marked with the constructor attribute, add it
+ to the list of functions to be called along with constructors
+ from static duration objects. */
+ if (DECL_STATIC_CONSTRUCTOR (fn))
+ static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
+
+ /* If this function is marked with the destructor attribute, add it
+ to the list of functions to be called along with destructors from
+ static duration objects. */
+ if (DECL_STATIC_DESTRUCTOR (fn))
+ static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
}
/* Generate RTL for FN. */
@@ -3062,197 +3031,16 @@ nullify_returns_r (tree* tp, int* walk_subtrees, void* data)
/* Start generating the RTL for FN. */
-static void
-genrtl_start_function (tree fn)
+void
+cxx_expand_function_start (void)
{
- /* Tell everybody what function we're processing. */
- current_function_decl = fn;
- /* Get the RTL machinery going for this function. */
- init_function_start (fn);
/* Let everybody know that we're expanding this function, not doing
semantic analysis. */
expanding_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;
-
- /* Let the user know we're compiling this function. */
- announce_function (fn);
-
- /* Initialize the per-function data. */
- my_friendly_assert (!DECL_PENDING_INLINE_P (fn), 20000911);
- if (DECL_SAVED_FUNCTION_DATA (fn))
- {
- /* If we already parsed this function, and we're just expanding it
- now, restore saved state. */
- *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
-
- /* This function is being processed in whole-function mode; we
- already did semantic analysis. */
- cfun->x_whole_function_mode_p = 1;
-
- /* If we decided that we didn't want to inline this function,
- make sure the back-end knows that. */
- if (!current_function_cannot_inline)
- current_function_cannot_inline = cp_function_chain->cannot_inline;
-
- /* We don't need the saved data anymore. Unless this is an inline
- function; we need the named return value info for
- cp_copy_res_decl_for_inlining. */
- if (! DECL_INLINE (fn))
- DECL_SAVED_FUNCTION_DATA (fn) = NULL;
- }
-
- /* Keep track of how many functions we're presently expanding. */
- ++function_depth;
-
- /* Create a binding level for the parameters. */
- expand_function_start (fn, /*parms_have_cleanups=*/0);
- /* If this function is `main'. */
- if (DECL_MAIN_P (fn))
- expand_main_function ();
-
/* Give our named return value the same RTL as our RESULT_DECL. */
if (current_function_return_value)
- COPY_DECL_RTL (DECL_RESULT (fn), current_function_return_value);
-}
-
-/* Finish generating the RTL for FN. */
-
-static void
-genrtl_finish_function (tree fn)
-{
- tree t;
-
-#if 0
- if (write_symbols != NO_DEBUG)
- {
- /* Keep this code around in case we later want to control debug info
- based on whether a type is "used". (jason 1999-11-11) */
-
- tree ttype = target_type (fntype);
- tree parmdecl;
-
- if (IS_AGGR_TYPE (ttype))
- /* Let debugger know it should output info for this type. */
- note_debug_info_needed (ttype);
-
- for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
- {
- ttype = target_type (TREE_TYPE (parmdecl));
- if (IS_AGGR_TYPE (ttype))
- /* Let debugger know it should output info for this type. */
- note_debug_info_needed (ttype);
- }
- }
-#endif
-
- /* Clean house because we will need to reorder insns here. */
- do_pending_stack_adjust ();
-
- /* If we have a named return value, we need to force a return so that
- the return register is USEd. */
- if (DECL_NAME (DECL_RESULT (fn)))
- emit_jump (return_label);
-
- /* We hard-wired immediate_size_expand to zero in start_function.
- 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;
-
- /* Generate rtl for function exit. */
- expand_function_end ();
-
- /* If this is a nested function (like a template instantiation that
- we're compiling in the midst of compiling something else), push a
- new GC context. That will keep local variables on the stack from
- being collected while we're doing the compilation of this
- function. */
- if (function_depth > 1)
- ggc_push_context ();
-
- /* There's no need to defer outputting this function any more; we
- know we want to output it. */
- DECL_DEFER_OUTPUT (fn) = 0;
-
- /* Run the optimizers and output the assembler code for this
- function. */
- rest_of_compilation (fn);
-
- /* Undo the call to ggc_push_context above. */
- if (function_depth > 1)
- ggc_pop_context ();
-
-#if 0
- /* Keep this code around in case we later want to control debug info
- based on whether a type is "used". (jason 1999-11-11) */
-
- if (ctype && TREE_ASM_WRITTEN (fn))
- note_debug_info_needed (ctype);
-#endif
-
- /* If this function is marked with the constructor attribute, add it
- to the list of functions to be called along with constructors
- from static duration objects. */
- if (DECL_STATIC_CONSTRUCTOR (fn))
- static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
-
- /* If this function is marked with the destructor attribute, add it
- to the list of functions to be called along with destructors from
- static duration objects. */
- if (DECL_STATIC_DESTRUCTOR (fn))
- static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
-
- --function_depth;
-
- /* In C++, we should never be saving RTL for the function. */
- my_friendly_assert (!DECL_SAVED_INSNS (fn), 20010903);
-
- /* Since we don't need the RTL for this function anymore, stop
- pointing to it. That's especially important for LABEL_DECLs,
- since you can reach all the instructions in the function from the
- CODE_LABEL stored in the DECL_RTL for the LABEL_DECL. Walk the
- BLOCK-tree, clearing DECL_RTL for LABEL_DECLs and non-static
- local variables. */
- walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
- clear_decl_rtl,
- NULL);
-
- /* Clear out the RTL for the arguments. */
- for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
- {
- SET_DECL_RTL (t, NULL_RTX);
- DECL_INCOMING_RTL (t) = NULL_RTX;
- }
-
- if (!(flag_inline_trees && DECL_INLINE (fn)))
- /* DECL_INITIAL must remain nonzero so we know this was an
- actual function definition. */
- DECL_INITIAL (fn) = error_mark_node;
-
- /* Let the error reporting routines know that we're outside a
- function. For a nested function, this value is used in
- pop_cp_function_context and then reset via pop_function_context. */
- current_function_decl = NULL_TREE;
-}
-
-/* Clear out the DECL_RTL for the non-static variables in BLOCK and
- its sub-blocks. */
-
-static tree
-clear_decl_rtl (tree* tp,
- int* walk_subtrees ATTRIBUTE_UNUSED ,
- void* data ATTRIBUTE_UNUSED )
-{
- if (nonstatic_local_decl_p (*tp))
- SET_DECL_RTL (*tp, NULL_RTX);
-
- return NULL_TREE;
+ COPY_DECL_RTL (DECL_RESULT (cfun->decl), current_function_return_value);
}
/* Perform initialization related to this module. */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 56c24c7..ee30749 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -123,6 +123,10 @@ extern void lhd_initialize_diagnostics (struct diagnostic_context *);
#define LANG_HOOKS_FUNCTION_ENTER_NESTED lhd_do_nothing_f
#define LANG_HOOKS_FUNCTION_LEAVE_NESTED lhd_do_nothing_f
+#define LANG_HOOKS_RTL_EXPAND_START lhd_do_nothing
+#define LANG_HOOKS_RTL_EXPAND_STMT (void *) abort
+#define LANG_HOOKS_RTL_EXPAND_END lhd_do_nothing
+
/* Attribute hooks. */
#define LANG_HOOKS_ATTRIBUTE_TABLE NULL
#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE NULL
@@ -186,6 +190,12 @@ extern void lhd_initialize_diagnostics (struct diagnostic_context *);
LANG_HOOKS_FUNCTION_LEAVE_NESTED \
}
+#define LANG_HOOKS_RTL_EXPAND_INITIALIZER { \
+ LANG_HOOKS_RTL_EXPAND_START, \
+ LANG_HOOKS_RTL_EXPAND_STMT, \
+ LANG_HOOKS_RTL_EXPAND_END \
+}
+
/* Tree dump hooks. */
extern bool lhd_tree_dump_dump_tree (void *, tree);
extern int lhd_tree_dump_type_quals (tree);
@@ -289,7 +299,8 @@ extern int lhd_tree_dump_type_quals (tree);
LANG_HOOKS_CALLGRAPH_INITIALIZER, \
LANG_HOOKS_TREE_DUMP_INITIALIZER, \
LANG_HOOKS_DECLS, \
- LANG_HOOKS_FOR_TYPES_INITIALIZER \
+ LANG_HOOKS_FOR_TYPES_INITIALIZER, \
+ LANG_HOOKS_RTL_EXPAND_INITIALIZER \
}
#endif /* GCC_LANG_HOOKS_DEF_H */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 7bcd435..109dfa1 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -77,6 +77,19 @@ struct lang_hooks_for_functions
void (*leave_nested) (struct function *);
};
+/* Lang hooks for rtl code generation. */
+struct lang_hooks_for_rtl_expansion
+{
+ /* Called after expand_function_start, but before expanding the body. */
+ void (*start) (void);
+
+ /* Called to expand each statement. */
+ void (*stmt) (tree);
+
+ /* Called after expanding the body but before expand_function_end. */
+ void (*end) (void);
+};
+
/* The following hooks are used by tree-dump.c. */
struct lang_hooks_for_tree_dump
@@ -387,6 +400,8 @@ struct lang_hooks
struct lang_hooks_for_types types;
+ struct lang_hooks_for_rtl_expansion rtl_expand;
+
/* Whenever you add entries here, make sure you adjust langhooks-def.h
and langhooks.c accordingly. */
};
diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c
index 7a330ce..3f70122 100644
--- a/gcc/objc/objc-lang.c
+++ b/gcc/objc/objc-lang.c
@@ -87,6 +87,9 @@ enum c_language_kind c_language = clk_objc;
#undef LANG_HOOKS_FUNCTION_LEAVE_NESTED
#define LANG_HOOKS_FUNCTION_LEAVE_NESTED c_pop_function_context
+#undef LANG_HOOKS_RTL_EXPAND_STMT
+#define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt
+
/* Attribute hooks. */
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
diff --git a/gcc/toplev.h b/gcc/toplev.h
index 5adab61..3ebd8e4 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -66,6 +66,7 @@ extern void inform (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
extern void rest_of_decl_compilation (tree, const char *, int, int);
extern void rest_of_type_compilation (tree, int);
extern void rest_of_compilation (tree);
+extern void tree_rest_of_compilation (tree);
extern void announce_function (tree);
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
new file mode 100644
index 0000000..e5bea3e
--- /dev/null
+++ b/gcc/tree-optimize.c
@@ -0,0 +1,250 @@
+/* Control and data flow functions for trees.
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+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 version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License 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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "toplev.h"
+#include "tree.h"
+#include "tree-inline.h"
+#include "flags.h"
+#include "langhooks.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "tm.h"
+#include "function.h"
+#include "ggc.h"
+
+
+/* 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;
+}
+
+/* Clear out the DECL_RTL for the non-static local variables in BLOCK and
+ its sub-blocks. DATA is the decl of the function being processed. */
+
+static tree
+clear_decl_rtl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+{
+ bool nonstatic_p, local_p;
+ tree t = *tp;
+
+ switch (TREE_CODE (t))
+ {
+ case VAR_DECL:
+ nonstatic_p = !TREE_STATIC (t) && !DECL_EXTERNAL (t);
+ local_p = DECL_CONTEXT (t) == data;
+ break;
+
+ case PARM_DECL:
+ case LABEL_DECL:
+ nonstatic_p = true;
+ local_p = DECL_CONTEXT (t) == data;
+ break;
+
+ case RESULT_DECL:
+ nonstatic_p = local_p = true;
+ break;
+
+ default:
+ nonstatic_p = local_p = false;
+ break;
+ }
+
+ if (nonstatic_p && local_p)
+ SET_DECL_RTL (t, NULL);
+
+ return NULL;
+}
+
+/* For functions-as-trees languages, this performs all optimization and
+ compilation for FNDECL. */
+
+void
+tree_rest_of_compilation (tree fndecl)
+{
+ static int nesting = -1;
+
+ timevar_push (TV_EXPAND);
+
+ ++nesting;
+
+ if (flag_unit_at_a_time && !cgraph_global_info_ready)
+ abort ();
+
+ if (nesting > 0)
+ /* 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;
+
+ /* 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);
+
+ /* Set up parameters and prepare for return, for the function. */
+ expand_function_start (fndecl, 0);
+
+ /* Allow language dialects to perform special processing. */
+ (*lang_hooks.rtl_expand.start) ();
+
+ /* 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_FILE_SCOPE_P (fndecl))
+ expand_main_function ();
+
+ /* Generate the RTL for this function. */
+ (*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
+ variable to one here, so that after the decrement it will remain
+ zero. */
+ immediate_size_expand = 1;
+
+ /* Allow language dialects to perform special processing. */
+ (*lang_hooks.rtl_expand.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 (nesting > 0)
+ ggc_push_context ();
+
+ /* There's no need to defer outputting this function any more; we
+ know we want to output it. */
+ DECL_DEFER_OUTPUT (fndecl) = 0;
+
+ /* Run the optimizers and output the assembler code for this function. */
+ rest_of_compilation (fndecl);
+
+ /* Undo the GC context switch. */
+ if (nesting > 0)
+ ggc_pop_context ();
+
+ /* If requested, warn about function definitions where the function will
+ return a value (usually of some struct or union type) which itself will
+ take up a lot of stack space. */
+ if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
+ {
+ tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+
+ if (ret_type && TYPE_SIZE_UNIT (ret_type)
+ && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
+ && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
+ larger_than_size))
+ {
+ const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
+ unsigned int size_as_int
+ = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
+
+ if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
+ warning ("%Hsize of return value of '%D' is %u bytes",
+ locus, fndecl, size_as_int);
+ else
+ warning ("%Hsize of return value of '%D' is larger than %wd bytes",
+ locus, fndecl, larger_than_size);
+ }
+ }
+
+ /* ??? Looks like some of this could be combined. */
+
+ /* If possible, obliterate the body of the function so that it can
+ be garbage collected. */
+ if (dump_enabled_p (TDI_all))
+ /* Keep the body; we're going to dump it. */
+ ;
+ else if (DECL_INLINE (fndecl) && flag_inline_trees)
+ /* We might need the body of this function so that we can expand
+ it inline somewhere else. */
+ ;
+ else
+ /* We don't need the body; blow it away. */
+ DECL_SAVED_TREE (fndecl) = NULL;
+
+ /* Since we don't need the RTL for this function anymore, stop pointing to
+ it. That's especially important for LABEL_DECLs, since you can reach all
+ the instructions in the function from the CODE_LABEL stored in the
+ DECL_RTL for the LABEL_DECL. Walk the BLOCK-tree, clearing DECL_RTL for
+ LABEL_DECLs and non-static local variables. Note that we must check the
+ context of the variables, otherwise processing a nested function can kill
+ the rtl of a variable from an outer function. */
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
+ clear_decl_rtl,
+ fndecl);
+
+ if (DECL_SAVED_INSNS (fndecl) == 0 && ! nesting && ! flag_inline_trees)
+ {
+ /* Stop pointing to the local nodes about to be freed.
+ But DECL_INITIAL must remain nonzero so we know this
+ was an actual function definition.
+ For a nested function, this is done in c_pop_function_context.
+ 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;
+ }
+
+ if (nesting > 0)
+ /* Return to the enclosing function. */
+ pop_function_context ();
+
+ --nesting;
+
+ timevar_pop (TV_EXPAND);
+}