Commit 25af8512 by Alexandre Oliva Committed by Alexandre Oliva

Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.

* Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
(cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise.
* cp-tree.h (lang_decl): Moved inlined_fns to tree_decl.
(TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h.
(flag_inline_trees): Moved declaration to ../tree-inline.h.
(walk_tree): Moved declaration to ../tree-inline.h.
(walk_tree_without_duplicates, copy_tree_r): Likewise.
(remap_save_expr): Likewise.
* decl.c: Include tree-inline.h.
(lang_mark_tree): Don't mark inlined_fns.
* decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c.
* optimize.c: Include tree-inline.h.
(optimize_inline_calls): Move declaration to ../tree.h, as
non-static.
(remap_decl): Use language-independent constructs and hooks.
(remap_block, copy_body_r, declare_return_variable): Likewise.
(inlinable_function_p): Likewise.  Don't test for
DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is
no longer language-specific.
(optimize_inline_calls): Likewise.  Make it non-static.  Moved
call of dump_function to...
(optimize_function): Here...
(clone_body): New function, extracted from...
(maybe_clone_body): ... here.  Build decl_map locally and pass
it on to clone_body.
* pt.c, semantics.c: Include tree-inline.h.
* tree.c: Likewise.
(cp_walk_subtrees): New language-specific hook for tree inlining.
(cp_cannot_inline_tree_fn, cp_add_pending_fn_decls,
cp_is_overload_p, cp_auto_var_in_fn_p,
cp_copy_res_decl_for_inlining): Likewise.
(walk_tree): Move language-specific constructs into...
(cp_walk_subtrees): this new function.
(copy_tree_r): Use language-independent constructs and hooks.
(init_tree): Initialize tree inlining hooks.
(remap_save_expr): Adjust prototype so that the declaration
does not require the definition of splay_tree.

From-SVN: r46020
parent ffb0e73a
2001-10-04 Alexandre Oliva <aoliva@redhat.com>
* Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
(cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise.
* cp-tree.h (lang_decl): Moved inlined_fns to tree_decl.
(TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h.
(flag_inline_trees): Moved declaration to ../tree-inline.h.
(walk_tree): Moved declaration to ../tree-inline.h.
(walk_tree_without_duplicates, copy_tree_r): Likewise.
(remap_save_expr): Likewise.
* decl.c: Include tree-inline.h.
(lang_mark_tree): Don't mark inlined_fns.
* decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c.
* optimize.c: Include tree-inline.h.
(optimize_inline_calls): Move declaration to ../tree.h, as
non-static.
(remap_decl): Use language-independent constructs and hooks.
(remap_block, copy_body_r, declare_return_variable): Likewise.
(inlinable_function_p): Likewise. Don't test for
DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is
no longer language-specific.
(optimize_inline_calls): Likewise. Make it non-static. Moved
call of dump_function to...
(optimize_function): Here...
(clone_body): New function, extracted from...
(maybe_clone_body): ... here. Build decl_map locally and pass
it on to clone_body.
* pt.c, semantics.c: Include tree-inline.h.
* tree.c: Likewise.
(cp_walk_subtrees): New language-specific hook for tree inlining.
(cp_cannot_inline_tree_fn, cp_add_pending_fn_decls,
cp_is_overload_p, cp_auto_var_in_fn_p,
cp_copy_res_decl_for_inlining): Likewise.
(walk_tree): Move language-specific constructs into...
(cp_walk_subtrees): this new function.
(copy_tree_r): Use language-independent constructs and hooks.
(init_tree): Initialize tree inlining hooks.
(remap_save_expr): Adjust prototype so that the declaration
does not require the definition of splay_tree.
2001-10-03 John David Anglin <dave@hiauly1.hia.nrc.ca> 2001-10-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
* rtti.c (get_tinfo_decl): Call typeinfo_in_lib_p with the type used * rtti.c (get_tinfo_decl): Call typeinfo_in_lib_p with the type used
......
...@@ -243,7 +243,7 @@ cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h c-pragma.h \ ...@@ -243,7 +243,7 @@ cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h c-pragma.h \
$(TM_P_H) $(TM_P_H)
cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \ cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \ output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
cp/operators.def $(TM_P_H) cp/operators.def $(TM_P_H) tree-inline.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \ cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
output.h except.h toplev.h $(GGC_H) $(RTL_H) output.h except.h toplev.h $(GGC_H) $(RTL_H)
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \ cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
...@@ -261,7 +261,7 @@ cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \ ...@@ -261,7 +261,7 @@ cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H) cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \ cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
insn-config.h integrate.h insn-config.h integrate.h tree-inline.h
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H) cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h
cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \ cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \
...@@ -270,14 +270,15 @@ cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \ ...@@ -270,14 +270,15 @@ cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H) except.h $(TM_P_H)
cp/xref.o: cp/xref.c $(CXX_TREE_H) input.h toplev.h cp/xref.o: cp/xref.c $(CXX_TREE_H) input.h toplev.h
cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h cp/parse.h cp/lex.h toplev.h \ cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h cp/parse.h cp/lex.h toplev.h \
$(GGC_H) $(RTL_H) except.h $(GGC_H) $(RTL_H) except.h tree-inline.h
cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h
cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \ cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \
flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) c-dump.h cp/dump.o: cp/dump.c $(CXX_TREE_H) c-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \ cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
input.h $(PARAMS_H) debug.h input.h $(PARAMS_H) debug.h tree-inline.h
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \ cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
......
...@@ -1758,10 +1758,6 @@ struct lang_decl ...@@ -1758,10 +1758,6 @@ struct lang_decl
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */ /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
tree cloned_function; tree cloned_function;
/* In a FUNCTION_DECL, these are function data which is to be kept
as long as FUNCTION_DECL is kept. */
tree inlined_fns;
union union
{ {
tree sorted_fields; tree sorted_fields;
...@@ -1778,10 +1774,6 @@ struct lang_decl ...@@ -1778,10 +1774,6 @@ struct lang_decl
#define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK(NODE)->identifier.id.str) #define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK(NODE)->identifier.id.str)
/* Non-zero if NODE is a _DECL with TREE_READONLY set. */
#define TREE_READONLY_DECL_P(NODE) \
(TREE_READONLY (NODE) && DECL_P (NODE))
/* DECL_NEEDED_P holds of a declaration when we need to emit its /* DECL_NEEDED_P holds of a declaration when we need to emit its
definition. This is true when the back-end tells us that definition. This is true when the back-end tells us that
the symbol has been referenced in the generated code. If, however, the symbol has been referenced in the generated code. If, however,
...@@ -1888,10 +1880,6 @@ struct lang_decl ...@@ -1888,10 +1880,6 @@ struct lang_decl
#define DECL_CLONED_FUNCTION(NODE) \ #define DECL_CLONED_FUNCTION(NODE) \
(DECL_LANG_SPECIFIC (NODE)->cloned_function) (DECL_LANG_SPECIFIC (NODE)->cloned_function)
/* List of FUNCION_DECLs inlined into this function's body. */
#define DECL_INLINED_FNS(NODE) \
(DECL_LANG_SPECIFIC (NODE)->inlined_fns)
/* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */ /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */
#define DECL_DISCRIMINATOR_P(NODE) \ #define DECL_DISCRIMINATOR_P(NODE) \
(TREE_CODE (NODE) == VAR_DECL \ (TREE_CODE (NODE) == VAR_DECL \
...@@ -3262,13 +3250,6 @@ extern int flag_implicit_templates; ...@@ -3262,13 +3250,6 @@ extern int flag_implicit_templates;
extern int flag_weak; extern int flag_weak;
/* 0 if we should not perform inlining.
1 if we should expand functions calls inline at the tree level.
2 if we should consider *all* functions to be inline
candidates. */
extern int flag_inline_trees;
/* Nonzero if we're done parsing and into end-of-file activities. */ /* Nonzero if we're done parsing and into end-of-file activities. */
extern int at_eof; extern int at_eof;
...@@ -4197,18 +4178,9 @@ extern void debug_binfo PARAMS ((tree)); ...@@ -4197,18 +4178,9 @@ extern void debug_binfo PARAMS ((tree));
extern tree build_dummy_object PARAMS ((tree)); extern tree build_dummy_object PARAMS ((tree));
extern tree maybe_dummy_object PARAMS ((tree, tree *)); extern tree maybe_dummy_object PARAMS ((tree, tree *));
extern int is_dummy_object PARAMS ((tree)); extern int is_dummy_object PARAMS ((tree));
extern tree walk_tree PARAMS ((tree *,
walk_tree_fn,
void *,
htab_t));
extern tree walk_tree_without_duplicates PARAMS ((tree *,
walk_tree_fn,
void *));
extern tree copy_tree_r PARAMS ((tree *, int *, void *));
extern const struct attribute_spec cp_attribute_table[]; extern const struct attribute_spec cp_attribute_table[];
extern tree make_ptrmem_cst PARAMS ((tree, tree)); extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int)); extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
extern void remap_save_expr PARAMS ((tree *, splay_tree, tree, int *));
#define cp_build_qualified_type(TYPE, QUALS) \ #define cp_build_qualified_type(TYPE, QUALS) \
cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1) cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1)
extern tree build_shared_int_cst PARAMS ((int)); extern tree build_shared_int_cst PARAMS ((int));
......
...@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "expr.h" #include "expr.h"
#include "flags.h" #include "flags.h"
#include "cp-tree.h" #include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h" #include "decl.h"
#include "lex.h" #include "lex.h"
#include "output.h" #include "output.h"
...@@ -14479,7 +14480,6 @@ lang_mark_tree (t) ...@@ -14479,7 +14480,6 @@ lang_mark_tree (t)
ggc_mark_tree (ld->befriending_classes); ggc_mark_tree (ld->befriending_classes);
ggc_mark_tree (ld->context); ggc_mark_tree (ld->context);
ggc_mark_tree (ld->cloned_function); ggc_mark_tree (ld->cloned_function);
ggc_mark_tree (ld->inlined_fns);
if (TREE_CODE (t) == TYPE_DECL) if (TREE_CODE (t) == TYPE_DECL)
ggc_mark_tree (ld->u.sorted_fields); ggc_mark_tree (ld->u.sorted_fields);
else if (TREE_CODE (t) == FUNCTION_DECL else if (TREE_CODE (t) == FUNCTION_DECL
......
...@@ -378,13 +378,6 @@ int flag_weak = 1; ...@@ -378,13 +378,6 @@ int flag_weak = 1;
int flag_use_cxa_atexit; int flag_use_cxa_atexit;
/* 0 if we should not perform inlining.
1 if we should expand functions calls inline at the tree level.
2 if we should consider *all* functions to be inline
candidates. */
int flag_inline_trees = 0;
/* Maximum template instantiation depth. This limit is rather /* Maximum template instantiation depth. This limit is rather
arbitrary, but it exists to limit the time it takes to notice arbitrary, but it exists to limit the time it takes to notice
infinite template instantiations. */ infinite template instantiations. */
......
...@@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "params.h" #include "params.h"
#include "hashtab.h" #include "hashtab.h"
#include "debug.h" #include "debug.h"
#include "tree-inline.h"
/* To Do: /* To Do:
...@@ -99,7 +100,6 @@ static int inlinable_function_p PARAMS ((tree, inline_data *)); ...@@ -99,7 +100,6 @@ static int inlinable_function_p PARAMS ((tree, inline_data *));
static tree remap_decl PARAMS ((tree, inline_data *)); static tree remap_decl PARAMS ((tree, inline_data *));
static void remap_block PARAMS ((tree, tree, inline_data *)); static void remap_block PARAMS ((tree, tree, inline_data *));
static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *)); static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
static void optimize_inline_calls PARAMS ((tree));
static tree calls_setjmp_r PARAMS ((tree *, int *, void *)); static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
static void update_cloned_parm PARAMS ((tree, tree)); static void update_cloned_parm PARAMS ((tree, tree));
static void dump_function PARAMS ((enum tree_dump_index, tree)); static void dump_function PARAMS ((enum tree_dump_index, tree));
...@@ -121,7 +121,7 @@ remap_decl (decl, id) ...@@ -121,7 +121,7 @@ remap_decl (decl, id)
/* We only remap local variables in the current function. */ /* We only remap local variables in the current function. */
fn = VARRAY_TOP_TREE (id->fns); fn = VARRAY_TOP_TREE (id->fns);
if (!nonstatic_local_decl_p (decl) || DECL_CONTEXT (decl) != fn) if (! LANG_AUTO_VAR_IN_FN_P (decl, fn))
return NULL_TREE; return NULL_TREE;
/* See if we have remapped this declaration. */ /* See if we have remapped this declaration. */
...@@ -151,8 +151,8 @@ remap_decl (decl, id) ...@@ -151,8 +151,8 @@ remap_decl (decl, id)
copy_body_r, id, NULL); copy_body_r, id, NULL);
} }
if (!DECL_NAME (t) && TREE_TYPE (t) if (! DECL_NAME (t) && TREE_TYPE (t)
&& ANON_AGGR_TYPE_P (TREE_TYPE ((t)))) && LANG_ANON_AGGR_TYPE_P (TREE_TYPE (t)))
{ {
/* For a VAR_DECL of anonymous type, we must also copy the /* For a VAR_DECL of anonymous type, we must also copy the
member VAR_DECLS here and rechain the member VAR_DECLS here and rechain the
...@@ -165,7 +165,8 @@ remap_decl (decl, id) ...@@ -165,7 +165,8 @@ remap_decl (decl, id)
{ {
tree member = remap_decl (TREE_VALUE (src), id); tree member = remap_decl (TREE_VALUE (src), id);
my_friendly_assert (!TREE_PURPOSE (src), 20010529); if (TREE_PURPOSE (src))
abort ();
members = tree_cons (NULL, member, members); members = tree_cons (NULL, member, members);
} }
DECL_ANON_UNION_ELEMS (t) = nreverse (members); DECL_ANON_UNION_ELEMS (t) = nreverse (members);
...@@ -277,7 +278,8 @@ remap_block (scope_stmt, decls, id) ...@@ -277,7 +278,8 @@ remap_block (scope_stmt, decls, id)
/* Find this block in the table of remapped things. */ /* Find this block in the table of remapped things. */
n = splay_tree_lookup (id->decl_map, n = splay_tree_lookup (id->decl_map,
(splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt)); (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
my_friendly_assert (n != NULL, 19991203); if (! n)
abort ();
SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value; SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
} }
} }
...@@ -322,12 +324,14 @@ copy_body_r (tp, walk_subtrees, data) ...@@ -322,12 +324,14 @@ copy_body_r (tp, walk_subtrees, data)
id = (inline_data *) data; id = (inline_data *) data;
fn = VARRAY_TOP_TREE (id->fns); fn = VARRAY_TOP_TREE (id->fns);
#if 0
/* All automatic variables should have a DECL_CONTEXT indicating /* All automatic variables should have a DECL_CONTEXT indicating
what function they come from. */ what function they come from. */
if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL) if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL)
&& DECL_NAMESPACE_SCOPE_P (*tp)) && DECL_NAMESPACE_SCOPE_P (*tp))
my_friendly_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp), if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp))
19991113); abort ();
#endif
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
GOTO_STMT with the RET_LABEL as its target. */ GOTO_STMT with the RET_LABEL as its target. */
...@@ -359,26 +363,29 @@ copy_body_r (tp, walk_subtrees, data) ...@@ -359,26 +363,29 @@ copy_body_r (tp, walk_subtrees, data)
variables. We don't want to copy static variables; there's only variables. We don't want to copy static variables; there's only
one of those, no matter how many times we inline the containing one of those, no matter how many times we inline the containing
function. */ function. */
else if (nonstatic_local_decl_p (*tp) && DECL_CONTEXT (*tp) == fn) else if (LANG_AUTO_VAR_IN_FN_P (*tp, fn))
{ {
tree new_decl; tree new_decl;
/* Remap the declaration. */ /* Remap the declaration. */
new_decl = remap_decl (*tp, id); new_decl = remap_decl (*tp, id);
my_friendly_assert (new_decl != NULL_TREE, 19991203); if (! new_decl)
abort ();
/* Replace this variable with the copy. */ /* Replace this variable with the copy. */
STRIP_TYPE_NOPS (new_decl); STRIP_TYPE_NOPS (new_decl);
*tp = new_decl; *tp = new_decl;
} }
#if 0
else if (nonstatic_local_decl_p (*tp) else if (nonstatic_local_decl_p (*tp)
&& DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0)) && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0))
my_friendly_abort (0); abort ();
#endif
else if (TREE_CODE (*tp) == SAVE_EXPR) else if (TREE_CODE (*tp) == SAVE_EXPR)
remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0), remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0),
walk_subtrees); walk_subtrees);
else if (TREE_CODE (*tp) == UNSAVE_EXPR) else if (TREE_CODE (*tp) == UNSAVE_EXPR)
/* UNSAVE_EXPRs should not be generated until expansion time. */ /* UNSAVE_EXPRs should not be generated until expansion time. */
my_friendly_abort (19991113); abort ();
/* For a SCOPE_STMT, we must copy the associated block so that we /* For a SCOPE_STMT, we must copy the associated block so that we
can write out debugging information for the inlined variables. */ can write out debugging information for the inlined variables. */
else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p) else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p)
...@@ -398,8 +405,7 @@ copy_body_r (tp, walk_subtrees, data) ...@@ -398,8 +405,7 @@ copy_body_r (tp, walk_subtrees, data)
} }
else if (TREE_CODE (*tp) == MODIFY_EXPR else if (TREE_CODE (*tp) == MODIFY_EXPR
&& TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
&& nonstatic_local_decl_p (TREE_OPERAND (*tp, 0)) && LANG_AUTO_VAR_IN_FN_P (TREE_OPERAND (*tp, 0), fn))
&& DECL_CONTEXT (TREE_OPERAND (*tp, 0)) == fn)
{ {
/* Some assignments VAR = VAR; don't generate any rtl code /* Some assignments VAR = VAR; don't generate any rtl code
and thus don't count as variable modification. Avoid and thus don't count as variable modification. Avoid
...@@ -561,7 +567,7 @@ declare_return_variable (id, use_stmt) ...@@ -561,7 +567,7 @@ declare_return_variable (id, use_stmt)
tree fn = VARRAY_TOP_TREE (id->fns); tree fn = VARRAY_TOP_TREE (id->fns);
tree result = DECL_RESULT (fn); tree result = DECL_RESULT (fn);
tree var; tree var;
int aggregate_return_p; int need_return_decl = 1;
/* We don't need to do anything for functions that don't return /* We don't need to do anything for functions that don't return
anything. */ anything. */
...@@ -571,29 +577,9 @@ declare_return_variable (id, use_stmt) ...@@ -571,29 +577,9 @@ declare_return_variable (id, use_stmt)
return NULL_TREE; return NULL_TREE;
} }
/* Figure out whether or not FN returns an aggregate. */ var = LANG_COPY_RES_DECL_FOR_INLINING (result, fn, VARRAY_TREE (id->fns, 0),
aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result)); id->decl_map, &need_return_decl,
&id->target_exprs);
/* If FN returns an aggregate then the caller will always create the
temporary (using a TARGET_EXPR) and the call will be the
initializing expression for the TARGET_EXPR. If we were just to
create a new VAR_DECL here, then the result of this function
would be copied (bitwise) into the variable initialized by the
TARGET_EXPR. That's incorrect, so we must transform any
references to the RESULT into references to the target. */
if (aggregate_return_p)
{
my_friendly_assert (VARRAY_ACTIVE_SIZE (id->target_exprs) != 0,
20000430);
var = TREE_OPERAND (VARRAY_TOP_TREE (id->target_exprs), 0);
my_friendly_assert
(same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
TREE_TYPE (result)),
20000430);
}
/* Otherwise, make an appropriate copy. */
else
var = copy_decl_for_inlining (result, fn, VARRAY_TREE (id->fns, 0));
/* Register the VAR_DECL as the equivalent for the RESULT_DECL; that /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
way, when the RESULT_DECL is encountered, it will be way, when the RESULT_DECL is encountered, it will be
...@@ -602,29 +588,12 @@ declare_return_variable (id, use_stmt) ...@@ -602,29 +588,12 @@ declare_return_variable (id, use_stmt)
(splay_tree_key) result, (splay_tree_key) result,
(splay_tree_value) var); (splay_tree_value) var);
if (DECL_SAVED_FUNCTION_DATA (fn))
{
tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
if (nrv)
{
/* We have a named return value; copy the name and source
position so we can get reasonable debugging information, and
register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv);
DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
splay_tree_insert (id->decl_map,
(splay_tree_key) nrv,
(splay_tree_value) var);
}
}
/* Build the USE_STMT. */ /* Build the USE_STMT. */
*use_stmt = build_stmt (EXPR_STMT, var); *use_stmt = build_stmt (EXPR_STMT, var);
/* Build the declaration statement if FN does not return an /* Build the declaration statement if FN does not return an
aggregate. */ aggregate. */
if (!aggregate_return_p) if (need_return_decl)
return build_stmt (DECL_STMT, var); return build_stmt (DECL_STMT, var);
/* If FN does return an aggregate, there's no need to declare the /* If FN does return an aggregate, there's no need to declare the
return variable; we're using a variable in our caller's frame. */ return variable; we're using a variable in our caller's frame. */
...@@ -656,12 +625,11 @@ inlinable_function_p (fn, id) ...@@ -656,12 +625,11 @@ inlinable_function_p (fn, id)
it. */ it. */
else if (!DECL_INLINE (fn)) else if (!DECL_INLINE (fn))
; ;
/* We can't inline varargs functions. */ /* We can't inline functions that are too big. Only allow a single
else if (varargs_function_p (fn)) function to eat up half of our budget. Make special allowance
; for extern inline functions, though. */
/* We can't inline functions that are too big. else if (! LANG_DISREGARD_INLINE_LIMITS (fn)
* Only allow a single function to eat up half of our budget. */ && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
else if (DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
; ;
/* All is well. We can inline this function. Traditionally, GCC /* All is well. We can inline this function. Traditionally, GCC
has refused to inline functions using alloca, or functions whose has refused to inline functions using alloca, or functions whose
...@@ -675,27 +643,26 @@ inlinable_function_p (fn, id) ...@@ -675,27 +643,26 @@ inlinable_function_p (fn, id)
/* Even if this function is not itself too big to inline, it might /* Even if this function is not itself too big to inline, it might
be that we've done so much inlining already that we don't want to be that we've done so much inlining already that we don't want to
risk too much inlining any more and thus halve the acceptable size. */ risk too much inlining any more and thus halve the acceptable
if ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT size. */
> MAX_INLINE_INSNS if (! LANG_DISREGARD_INLINE_LIMITS (fn)
&& ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT
> MAX_INLINE_INSNS)
&& DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4) && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4)
inlinable = 0; inlinable = 0;
/* We can inline a template instantiation only if it's fully if (inlinable && LANG_CANNOT_INLINE_TREE_FN (&fn))
instantiated. */ inlinable = 0;
if (inlinable
&& DECL_TEMPLATE_INFO (fn)
&& TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
{
fn = instantiate_decl (fn, /*defer_ok=*/0);
inlinable = !TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
}
/* If we don't have the function body available, we can't inline /* If we don't have the function body available, we can't inline
it. */ it. */
if (!DECL_SAVED_TREE (fn)) if (!DECL_SAVED_TREE (fn))
inlinable = 0; inlinable = 0;
/* Check again, language hooks may have modified it. */
if (! inlinable || DECL_UNINLINABLE (fn))
return 0;
/* Don't do recursive inlining, either. We don't record this in /* Don't do recursive inlining, either. We don't record this in
DECL_UNINLINABLE; we may be able to inline this function later. */ DECL_UNINLINABLE; we may be able to inline this function later. */
if (inlinable) if (inlinable)
...@@ -706,7 +673,7 @@ inlinable_function_p (fn, id) ...@@ -706,7 +673,7 @@ inlinable_function_p (fn, id)
if (VARRAY_TREE (id->fns, i) == fn) if (VARRAY_TREE (id->fns, i) == fn)
return 0; return 0;
if (inlinable && DECL_LANG_SPECIFIC (fn) && DECL_INLINED_FNS (fn)) if (inlinable && DECL_INLINED_FNS (fn))
{ {
int j; int j;
tree inlined_fns = DECL_INLINED_FNS (fn); tree inlined_fns = DECL_INLINED_FNS (fn);
...@@ -808,7 +775,7 @@ expand_call_inline (tp, walk_subtrees, data) ...@@ -808,7 +775,7 @@ expand_call_inline (tp, walk_subtrees, data)
for the return statements within the function to jump to. The for the return statements within the function to jump to. The
type of the statement expression is the return type of the type of the statement expression is the return type of the
function call. */ function call. */
expr = build_min (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE); expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE);
/* Local declarations will be replaced by their equivalents in this /* Local declarations will be replaced by their equivalents in this
map. */ map. */
...@@ -832,7 +799,7 @@ expand_call_inline (tp, walk_subtrees, data) ...@@ -832,7 +799,7 @@ expand_call_inline (tp, walk_subtrees, data)
/* Record the function we are about to inline if optimize_function /* Record the function we are about to inline if optimize_function
has not been called on it yet and we don't have it in the list. */ has not been called on it yet and we don't have it in the list. */
if (DECL_LANG_SPECIFIC (fn) && !DECL_INLINED_FNS (fn)) if (! DECL_INLINED_FNS (fn))
{ {
int i; int i;
...@@ -878,9 +845,9 @@ expand_call_inline (tp, walk_subtrees, data) ...@@ -878,9 +845,9 @@ expand_call_inline (tp, walk_subtrees, data)
/* Close the block for the parameters. */ /* Close the block for the parameters. */
scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn)); scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
SCOPE_NO_CLEANUPS_P (scope_stmt) = 1; SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
my_friendly_assert (DECL_INITIAL (fn) if (! DECL_INITIAL (fn)
&& TREE_CODE (DECL_INITIAL (fn)) == BLOCK, || TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
19991203); abort ();
remap_block (scope_stmt, NULL_TREE, id); remap_block (scope_stmt, NULL_TREE, id);
STMT_EXPR_STMT (expr) STMT_EXPR_STMT (expr)
= chainon (STMT_EXPR_STMT (expr), scope_stmt); = chainon (STMT_EXPR_STMT (expr), scope_stmt);
...@@ -957,13 +924,12 @@ expand_calls_inline (tp, id) ...@@ -957,13 +924,12 @@ expand_calls_inline (tp, id)
/* Expand calls to inline functions in the body of FN. */ /* Expand calls to inline functions in the body of FN. */
static void void
optimize_inline_calls (fn) optimize_inline_calls (fn)
tree fn; tree fn;
{ {
inline_data id; inline_data id;
tree prev_fn; tree prev_fn;
struct saved_scope *s;
/* Clear out ID. */ /* Clear out ID. */
memset (&id, 0, sizeof (id)); memset (&id, 0, sizeof (id));
...@@ -978,12 +944,8 @@ optimize_inline_calls (fn) ...@@ -978,12 +944,8 @@ optimize_inline_calls (fn)
VARRAY_PUSH_TREE (id.fns, current_function_decl); VARRAY_PUSH_TREE (id.fns, current_function_decl);
prev_fn = current_function_decl; prev_fn = current_function_decl;
} }
for (s = scope_chain; s; s = s->prev)
if (s->function_decl && s->function_decl != prev_fn) prev_fn = LANG_ADD_PENDING_FN_DECLS (&id.fns, prev_fn);
{
VARRAY_PUSH_TREE (id.fns, s->function_decl);
prev_fn = s->function_decl;
}
/* Create the stack of TARGET_EXPRs. */ /* Create the stack of TARGET_EXPRs. */
VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs"); VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
...@@ -1014,8 +976,6 @@ optimize_inline_calls (fn) ...@@ -1014,8 +976,6 @@ optimize_inline_calls (fn)
DECL_INLINED_FNS (fn) = ifn; DECL_INLINED_FNS (fn) = ifn;
} }
VARRAY_FREE (id.inlined_fns); VARRAY_FREE (id.inlined_fns);
dump_function (TDI_inlined, fn);
} }
/* Optimize the body of FN. */ /* Optimize the body of FN. */
...@@ -1043,7 +1003,11 @@ optimize_function (fn) ...@@ -1043,7 +1003,11 @@ optimize_function (fn)
optimization, (c) virtual functions are rarely inlineable, optimization, (c) virtual functions are rarely inlineable,
and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */ and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */
&& !DECL_THUNK_P (fn)) && !DECL_THUNK_P (fn))
optimize_inline_calls (fn); {
optimize_inline_calls (fn);
dump_function (TDI_inlined, fn);
}
/* Undo the call to ggc_push_context above. */ /* Undo the call to ggc_push_context above. */
--function_depth; --function_depth;
...@@ -1106,6 +1070,38 @@ update_cloned_parm (parm, cloned_parm) ...@@ -1106,6 +1070,38 @@ update_cloned_parm (parm, cloned_parm)
DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm); DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm);
} }
/* FN is a function that has a complete body, and CLONE is a function
whose body is to be set to a copy of FN, mapping argument
declarations according to the ARG_MAP splay_tree. */
void
clone_body (clone, fn, arg_map)
tree clone, fn;
void *arg_map;
{
inline_data id;
/* Clone the body, as if we were making an inline call. But, remap
the parameters in the callee to the parameters of caller. If
there's an in-charge parameter, map it to an appropriate
constant. */
memset (&id, 0, sizeof (id));
VARRAY_TREE_INIT (id.fns, 2, "fns");
VARRAY_PUSH_TREE (id.fns, clone);
VARRAY_PUSH_TREE (id.fns, fn);
id.decl_map = (splay_tree)arg_map;
/* Cloning is treated slightly differently from inlining. Set
CLONING_P so that it's clear which operation we're performing. */
id.cloning_p = true;
/* Actually copy the body. */
TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
/* Clean up. */
VARRAY_FREE (id.fns);
}
/* FN is a function that has a complete body. Clone the body as /* FN is a function that has a complete body. Clone the body as
necessary. Returns non-zero if there's no longer any need to necessary. Returns non-zero if there's no longer any need to
process the main body. */ process the main body. */
...@@ -1114,7 +1110,6 @@ int ...@@ -1114,7 +1110,6 @@ int
maybe_clone_body (fn) maybe_clone_body (fn)
tree fn; tree fn;
{ {
inline_data id;
tree clone; tree clone;
int first = 1; int first = 1;
...@@ -1135,6 +1130,7 @@ maybe_clone_body (fn) ...@@ -1135,6 +1130,7 @@ maybe_clone_body (fn)
tree parm; tree parm;
tree clone_parm; tree clone_parm;
int parmno; int parmno;
splay_tree decl_map;
/* Update CLONE's source position information to match FN's. */ /* Update CLONE's source position information to match FN's. */
DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn); DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
...@@ -1178,22 +1174,8 @@ maybe_clone_body (fn) ...@@ -1178,22 +1174,8 @@ maybe_clone_body (fn)
push_to_top_level (); push_to_top_level ();
start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED); start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
/* Just clone the body, as if we were making an inline call.
But, remap the parameters in the callee to the parameters of
caller. If there's an in-charge parameter, map it to an
appropriate constant. */
memset (&id, 0, sizeof (id));
VARRAY_TREE_INIT (id.fns, 2, "fns");
VARRAY_PUSH_TREE (id.fns, clone);
VARRAY_PUSH_TREE (id.fns, fn);
/* Cloning is treated slightly differently from inlining. Set
CLONING_P so that its clear which operation we're performing. */
id.cloning_p = true;
/* Remap the parameters. */ /* Remap the parameters. */
id.decl_map = splay_tree_new (splay_tree_compare_pointers, decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
NULL, NULL);
for (parmno = 0, for (parmno = 0,
parm = DECL_ARGUMENTS (fn), parm = DECL_ARGUMENTS (fn),
clone_parm = DECL_ARGUMENTS (clone); clone_parm = DECL_ARGUMENTS (clone);
...@@ -1206,7 +1188,7 @@ maybe_clone_body (fn) ...@@ -1206,7 +1188,7 @@ maybe_clone_body (fn)
{ {
tree in_charge; tree in_charge;
in_charge = in_charge_arg_for_name (DECL_NAME (clone)); in_charge = in_charge_arg_for_name (DECL_NAME (clone));
splay_tree_insert (id.decl_map, splay_tree_insert (decl_map,
(splay_tree_key) parm, (splay_tree_key) parm,
(splay_tree_value) in_charge); (splay_tree_value) in_charge);
} }
...@@ -1219,7 +1201,7 @@ maybe_clone_body (fn) ...@@ -1219,7 +1201,7 @@ maybe_clone_body (fn)
if (DECL_HAS_VTT_PARM_P (clone)) if (DECL_HAS_VTT_PARM_P (clone))
{ {
DECL_ABSTRACT_ORIGIN (clone_parm) = parm; DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
splay_tree_insert (id.decl_map, splay_tree_insert (decl_map,
(splay_tree_key) parm, (splay_tree_key) parm,
(splay_tree_value) clone_parm); (splay_tree_value) clone_parm);
clone_parm = TREE_CHAIN (clone_parm); clone_parm = TREE_CHAIN (clone_parm);
...@@ -1227,7 +1209,7 @@ maybe_clone_body (fn) ...@@ -1227,7 +1209,7 @@ maybe_clone_body (fn)
/* Otherwise, map the VTT parameter to `NULL'. */ /* Otherwise, map the VTT parameter to `NULL'. */
else else
{ {
splay_tree_insert (id.decl_map, splay_tree_insert (decl_map,
(splay_tree_key) parm, (splay_tree_key) parm,
(splay_tree_value) null_pointer_node); (splay_tree_value) null_pointer_node);
} }
...@@ -1236,23 +1218,22 @@ maybe_clone_body (fn) ...@@ -1236,23 +1218,22 @@ maybe_clone_body (fn)
function. */ function. */
else else
{ {
splay_tree_insert (id.decl_map, splay_tree_insert (decl_map,
(splay_tree_key) parm, (splay_tree_key) parm,
(splay_tree_value) clone_parm); (splay_tree_value) clone_parm);
clone_parm = TREE_CHAIN (clone_parm); clone_parm = TREE_CHAIN (clone_parm);
} }
} }
/* Actually copy the body. */ /* Clone the body. */
TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); clone_body (clone, fn, decl_map);
/* There are as many statements in the clone as in the /* There are as many statements in the clone as in the
original. */ original. */
DECL_NUM_STMTS (clone) = DECL_NUM_STMTS (fn); DECL_NUM_STMTS (clone) = DECL_NUM_STMTS (fn);
/* Clean up. */ /* Clean up. */
splay_tree_delete (id.decl_map); splay_tree_delete (decl_map);
VARRAY_FREE (id.fns);
/* Now, expand this function into RTL, if appropriate. */ /* Now, expand this function into RTL, if appropriate. */
finish_function (0); finish_function (0);
......
...@@ -29,10 +29,10 @@ Boston, MA 02111-1307, USA. */ ...@@ -29,10 +29,10 @@ Boston, MA 02111-1307, USA. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "obstack.h" #include "obstack.h"
#include "tree.h" #include "tree.h"
#include "flags.h" #include "flags.h"
#include "cp-tree.h" #include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h" #include "decl.h"
#include "parse.h" #include "parse.h"
#include "lex.h" #include "lex.h"
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "system.h" #include "system.h"
#include "tree.h" #include "tree.h"
#include "cp-tree.h" #include "cp-tree.h"
#include "tree-inline.h"
#include "except.h" #include "except.h"
#include "lex.h" #include "lex.h"
#include "toplev.h" #include "toplev.h"
......
...@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "ggc.h" #include "ggc.h"
#include "insn-config.h" #include "insn-config.h"
#include "integrate.h" #include "integrate.h"
#include "tree-inline.h"
static tree bot_manip PARAMS ((tree *, int *, void *)); static tree bot_manip PARAMS ((tree *, int *, void *));
static tree bot_replace PARAMS ((tree *, int *, void *)); static tree bot_replace PARAMS ((tree *, int *, void *));
...@@ -49,6 +50,12 @@ static tree count_trees_r PARAMS ((tree *, int *, void *)); ...@@ -49,6 +50,12 @@ static tree count_trees_r PARAMS ((tree *, int *, void *));
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *)); static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
static tree find_tree_r PARAMS ((tree *, int *, void *)); static tree find_tree_r PARAMS ((tree *, int *, void *));
extern int cp_statement_code_p PARAMS ((enum tree_code)); extern int cp_statement_code_p PARAMS ((enum tree_code));
static treeopt_walk_subtrees_type cp_walk_subtrees;
static treeopt_cannot_inline_tree_fn_type cp_cannot_inline_tree_fn;
static treeopt_add_pending_fn_decls_type cp_add_pending_fn_decls;
static treeopt_tree_chain_matters_p_type cp_is_overload_p;
static treeopt_auto_var_in_fn_p_type cp_auto_var_in_fn_p;
static treeopt_copy_res_decl_for_inlining_type cp_copy_res_decl_for_inlining;
static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
...@@ -1154,12 +1161,13 @@ bind_template_template_parm (t, newargs) ...@@ -1154,12 +1161,13 @@ bind_template_template_parm (t, newargs)
once. */ once. */
tree tree
walk_tree (tp, func, data, htab) walk_tree (tp, func, data, htab_)
tree *tp; tree *tp;
walk_tree_fn func; walk_tree_fn func;
void *data; void *data;
htab_t htab; void *htab_;
{ {
htab_t htab = (htab_t) htab_;
enum tree_code code; enum tree_code code;
int walk_subtrees; int walk_subtrees;
tree result; tree result;
...@@ -1204,7 +1212,8 @@ walk_tree (tp, func, data, htab) ...@@ -1204,7 +1212,8 @@ walk_tree (tp, func, data, htab)
interesting below this point in the tree. */ interesting below this point in the tree. */
if (!walk_subtrees) if (!walk_subtrees)
{ {
if (statement_code_p (code) || code == TREE_LIST || code == OVERLOAD) if (statement_code_p (code) || code == TREE_LIST
|| LANG_TREE_CHAIN_MATTERS_P (*tp))
/* But we still need to check our siblings. */ /* But we still need to check our siblings. */
return walk_tree (&TREE_CHAIN (*tp), func, data, htab); return walk_tree (&TREE_CHAIN (*tp), func, data, htab);
else else
...@@ -1268,6 +1277,10 @@ walk_tree (tp, func, data, htab) ...@@ -1268,6 +1277,10 @@ walk_tree (tp, func, data, htab)
return NULL_TREE; return NULL_TREE;
} }
result = LANG_WALK_SUBTREES (tp, &walk_subtrees, func, data, htab);
if (result || ! walk_subtrees)
return result;
/* Not one of the easy cases. We must explicitly go through the /* Not one of the easy cases. We must explicitly go through the
children. */ children. */
switch (code) switch (code)
...@@ -1277,47 +1290,29 @@ walk_tree (tp, func, data, htab) ...@@ -1277,47 +1290,29 @@ walk_tree (tp, func, data, htab)
case INTEGER_CST: case INTEGER_CST:
case REAL_CST: case REAL_CST:
case STRING_CST: case STRING_CST:
case DEFAULT_ARG:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TYPE_PARM:
case REAL_TYPE: case REAL_TYPE:
case COMPLEX_TYPE: case COMPLEX_TYPE:
case VECTOR_TYPE: case VECTOR_TYPE:
case VOID_TYPE: case VOID_TYPE:
case BOOLEAN_TYPE: case BOOLEAN_TYPE:
case TYPENAME_TYPE:
case UNION_TYPE: case UNION_TYPE:
case ENUMERAL_TYPE: case ENUMERAL_TYPE:
case TYPEOF_TYPE:
case BLOCK: case BLOCK:
case RECORD_TYPE:
/* None of thse have subtrees other than those already walked /* None of thse have subtrees other than those already walked
above. */ above. */
break; break;
case PTRMEM_CST:
WALK_SUBTREE (TREE_TYPE (*tp));
break;
case POINTER_TYPE: case POINTER_TYPE:
case REFERENCE_TYPE: case REFERENCE_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp)); WALK_SUBTREE (TREE_TYPE (*tp));
break; break;
case TREE_LIST: case TREE_LIST:
/* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular. */
if (!BASELINK_P (*tp))
WALK_SUBTREE (TREE_PURPOSE (*tp));
WALK_SUBTREE (TREE_VALUE (*tp)); WALK_SUBTREE (TREE_VALUE (*tp));
WALK_SUBTREE (TREE_CHAIN (*tp)); WALK_SUBTREE (TREE_CHAIN (*tp));
break; break;
case OVERLOAD:
WALK_SUBTREE (OVL_FUNCTION (*tp));
WALK_SUBTREE (OVL_CHAIN (*tp));
break;
case TREE_VEC: case TREE_VEC:
{ {
int len = TREE_VEC_LENGTH (*tp); int len = TREE_VEC_LENGTH (*tp);
...@@ -1365,13 +1360,8 @@ walk_tree (tp, func, data, htab) ...@@ -1365,13 +1360,8 @@ walk_tree (tp, func, data, htab)
WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp)); WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp));
break; break;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (*tp))
WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
break;
default: default:
my_friendly_abort (19990803); abort ();
} }
/* We didn't find what we were looking for. */ /* We didn't find what we were looking for. */
...@@ -1539,7 +1529,7 @@ copy_tree_r (tp, walk_subtrees, data) ...@@ -1539,7 +1529,7 @@ copy_tree_r (tp, walk_subtrees, data)
|| TREE_CODE_CLASS (code) == 's' || TREE_CODE_CLASS (code) == 's'
|| code == TREE_LIST || code == TREE_LIST
|| code == TREE_VEC || code == TREE_VEC
|| code == OVERLOAD) || LANG_TREE_CHAIN_MATTERS_P (*tp))
{ {
/* Because the chain gets clobbered when we make a copy, we save it /* Because the chain gets clobbered when we make a copy, we save it
here. */ here. */
...@@ -1550,7 +1540,8 @@ copy_tree_r (tp, walk_subtrees, data) ...@@ -1550,7 +1540,8 @@ copy_tree_r (tp, walk_subtrees, data)
/* Now, restore the chain, if appropriate. That will cause /* Now, restore the chain, if appropriate. That will cause
walk_tree to walk into the chain as well. */ walk_tree to walk into the chain as well. */
if (code == PARM_DECL || code == TREE_LIST || code == OVERLOAD if (code == PARM_DECL || code == TREE_LIST
|| LANG_TREE_CHAIN_MATTERS_P (*tp)
|| statement_code_p (code)) || statement_code_p (code))
TREE_CHAIN (*tp) = chain; TREE_CHAIN (*tp) = chain;
...@@ -2344,12 +2335,227 @@ make_ptrmem_cst (type, member) ...@@ -2344,12 +2335,227 @@ make_ptrmem_cst (type, member)
return ptrmem_cst; return ptrmem_cst;
} }
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
traversal. Called from walk_tree(). */
static tree
cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
tree *tp;
int *walk_subtrees_p;
walk_tree_fn func;
void *data;
void *htab;
{
enum tree_code code = TREE_CODE (*tp);
tree result;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_tree (&(NODE), func, data, htab); \
if (result) \
return result; \
} \
while (0)
/* Not one of the easy cases. We must explicitly go through the
children. */
switch (code)
{
case DEFAULT_ARG:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TYPE_PARM:
case TYPENAME_TYPE:
case TYPEOF_TYPE:
/* None of thse have subtrees other than those already walked
above. */
*walk_subtrees_p = 0;
break;
case PTRMEM_CST:
WALK_SUBTREE (TREE_TYPE (*tp));
*walk_subtrees_p = 0;
break;
case TREE_LIST:
/* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular. */
if (!BASELINK_P (*tp))
WALK_SUBTREE (TREE_PURPOSE (*tp));
break;
case OVERLOAD:
WALK_SUBTREE (OVL_FUNCTION (*tp));
WALK_SUBTREE (OVL_CHAIN (*tp));
*walk_subtrees_p = 0;
break;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (*tp))
WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
break;
default:
break;
}
/* We didn't find what we were looking for. */
return NULL_TREE;
#undef WALK_SUBTREE
}
/* Decide whether there are language-specific reasons to not inline a
function as a tree. */
static int
cp_cannot_inline_tree_fn (fnp)
tree *fnp;
{
tree fn = *fnp;
/* We can inline a template instantiation only if it's fully
instantiated. */
if (DECL_TEMPLATE_INFO (fn)
&& TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
{
fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
return TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
}
if (varargs_function_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
}
if (! function_attribute_inlinable_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
}
return 0;
}
/* Add any pending functions other than the current function (already
handled by the caller), that thus cannot be inlined, to FNS_P, then
return the latest function added to the array, PREV_FN. */
static tree
cp_add_pending_fn_decls (fns_p, prev_fn)
void *fns_p;
tree prev_fn;
{
varray_type *fnsp = (varray_type *)fns_p;
struct saved_scope *s;
for (s = scope_chain; s; s = s->prev)
if (s->function_decl && s->function_decl != prev_fn)
{
VARRAY_PUSH_TREE (*fnsp, s->function_decl);
prev_fn = s->function_decl;
}
return prev_fn;
}
/* Determine whether a tree node is an OVERLOAD node. Used to decide
whether to copy a node or to preserve its chain when inlining a
function. */
static int
cp_is_overload_p (t)
tree t;
{
return TREE_CODE (t) == OVERLOAD;
}
/* Determine whether VAR is a declaration of an automatic variable in
function FN. */
static int
cp_auto_var_in_fn_p (var, fn)
tree var, fn;
{
return (DECL_P (var) && DECL_CONTEXT (var) == fn
&& nonstatic_local_decl_p (var));
}
/* Tell whether a declaration is needed for the RESULT of a function
FN being inlined into CALLER or if the top node of target_exprs is
to be used. */
static tree
cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
need_decl, target_exprs)
tree result, fn, caller;
void *decl_map_;
int *need_decl;
void *target_exprs;
{
splay_tree decl_map = (splay_tree)decl_map_;
varray_type *texps = (varray_type *)target_exprs;
tree var;
int aggregate_return_p;
/* Figure out whether or not FN returns an aggregate. */
aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
*need_decl = ! aggregate_return_p;
/* If FN returns an aggregate then the caller will always create the
temporary (using a TARGET_EXPR) and the call will be the
initializing expression for the TARGET_EXPR. If we were just to
create a new VAR_DECL here, then the result of this function
would be copied (bitwise) into the variable initialized by the
TARGET_EXPR. That's incorrect, so we must transform any
references to the RESULT into references to the target. */
if (aggregate_return_p)
{
if (VARRAY_ACTIVE_SIZE (*texps) == 0)
abort ();
var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
TREE_TYPE (result)))
abort ();
}
/* Otherwise, make an appropriate copy. */
else
var = copy_decl_for_inlining (result, fn, caller);
if (DECL_SAVED_FUNCTION_DATA (fn))
{
tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
if (nrv)
{
/* We have a named return value; copy the name and source
position so we can get reasonable debugging information, and
register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv);
DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
splay_tree_insert (decl_map,
(splay_tree_key) nrv,
(splay_tree_value) var);
}
}
return var;
}
/* Initialize tree.c. */ /* Initialize tree.c. */
void void
init_tree () init_tree ()
{ {
make_lang_type_fn = cp_make_lang_type; make_lang_type_fn = cp_make_lang_type;
lang_walk_subtrees = cp_walk_subtrees;
lang_cannot_inline_tree_fn = cp_cannot_inline_tree_fn;
lang_add_pending_fn_decls = cp_add_pending_fn_decls;
lang_tree_chain_matters_p = cp_is_overload_p;
lang_auto_var_in_fn_p = cp_auto_var_in_fn_p;
lang_copy_res_decl_for_inlining = cp_copy_res_decl_for_inlining;
lang_unsave = cp_unsave; lang_unsave = cp_unsave;
lang_statement_code_p = cp_statement_code_p; lang_statement_code_p = cp_statement_code_p;
lang_set_decl_assembler_name = mangle_decl; lang_set_decl_assembler_name = mangle_decl;
...@@ -2365,12 +2571,13 @@ init_tree () ...@@ -2365,12 +2571,13 @@ init_tree ()
ST. FN is the function into which the copy will be placed. */ ST. FN is the function into which the copy will be placed. */
void void
remap_save_expr (tp, st, fn, walk_subtrees) remap_save_expr (tp, st_, fn, walk_subtrees)
tree *tp; tree *tp;
splay_tree st; void *st_;
tree fn; tree fn;
int *walk_subtrees; int *walk_subtrees;
{ {
splay_tree st = (splay_tree) st_;
splay_tree_node n; splay_tree_node n;
/* See if we already encountered this SAVE_EXPR. */ /* See if we already encountered this SAVE_EXPR. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment