diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-10-05 02:48:47 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-10-05 02:48:47 +0000 |
commit | 1e3b023ca8a1e3c71fbc30d4bb9b84cd1623903d (patch) | |
tree | 8512628500ca03ba513e5684fba6a6a044156017 /gcc/cp/tree.c | |
parent | b632977bd166019a4589082e383c5519b5f31558 (diff) | |
download | gcc-1e3b023ca8a1e3c71fbc30d4bb9b84cd1623903d.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46020 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 271 |
1 files changed, 239 insertions, 32 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 32783adc728..ec51eaa7e41 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "insn-config.h" #include "integrate.h" +#include "tree-inline.h" static tree bot_manip 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 *)); static tree verify_stmt_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)); +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_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *)); @@ -1154,12 +1161,13 @@ bind_template_template_parm (t, newargs) once. */ tree -walk_tree (tp, func, data, htab) +walk_tree (tp, func, data, htab_) tree *tp; walk_tree_fn func; void *data; - htab_t htab; + void *htab_; { + htab_t htab = (htab_t) htab_; enum tree_code code; int walk_subtrees; tree result; @@ -1204,7 +1212,8 @@ walk_tree (tp, func, data, htab) interesting below this point in the tree. */ 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. */ return walk_tree (&TREE_CHAIN (*tp), func, data, htab); else @@ -1268,6 +1277,10 @@ walk_tree (tp, func, data, htab) 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 children. */ switch (code) @@ -1277,47 +1290,29 @@ walk_tree (tp, func, data, htab) case INTEGER_CST: case REAL_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 COMPLEX_TYPE: case VECTOR_TYPE: case VOID_TYPE: case BOOLEAN_TYPE: - case TYPENAME_TYPE: case UNION_TYPE: case ENUMERAL_TYPE: - case TYPEOF_TYPE: case BLOCK: + case RECORD_TYPE: /* None of thse have subtrees other than those already walked above. */ break; - case PTRMEM_CST: - WALK_SUBTREE (TREE_TYPE (*tp)); - break; - case POINTER_TYPE: case REFERENCE_TYPE: WALK_SUBTREE (TREE_TYPE (*tp)); 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)); WALK_SUBTREE (TREE_VALUE (*tp)); WALK_SUBTREE (TREE_CHAIN (*tp)); break; - case OVERLOAD: - WALK_SUBTREE (OVL_FUNCTION (*tp)); - WALK_SUBTREE (OVL_CHAIN (*tp)); - break; - case TREE_VEC: { int len = TREE_VEC_LENGTH (*tp); @@ -1365,13 +1360,8 @@ walk_tree (tp, func, data, htab) WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp)); break; - case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (*tp)) - WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp)); - break; - default: - my_friendly_abort (19990803); + abort (); } /* We didn't find what we were looking for. */ @@ -1539,7 +1529,7 @@ copy_tree_r (tp, walk_subtrees, data) || TREE_CODE_CLASS (code) == 's' || code == TREE_LIST || code == TREE_VEC - || code == OVERLOAD) + || LANG_TREE_CHAIN_MATTERS_P (*tp)) { /* Because the chain gets clobbered when we make a copy, we save it here. */ @@ -1550,7 +1540,8 @@ copy_tree_r (tp, walk_subtrees, data) /* Now, restore the chain, if appropriate. That will cause 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)) TREE_CHAIN (*tp) = chain; @@ -2344,12 +2335,227 @@ make_ptrmem_cst (type, member) 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. */ void init_tree () { 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_statement_code_p = cp_statement_code_p; lang_set_decl_assembler_name = mangle_decl; @@ -2365,12 +2571,13 @@ init_tree () ST. FN is the function into which the copy will be placed. */ void -remap_save_expr (tp, st, fn, walk_subtrees) +remap_save_expr (tp, st_, fn, walk_subtrees) tree *tp; - splay_tree st; + void *st_; tree fn; int *walk_subtrees; { + splay_tree st = (splay_tree) st_; splay_tree_node n; /* See if we already encountered this SAVE_EXPR. */ |