diff options
author | Mark Mitchell <mark@codesourcery.com> | 2000-04-11 20:16:36 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2000-04-11 20:16:36 +0000 |
commit | db9b217498015006694d428ada8d8aed292a432f (patch) | |
tree | 00bde8ebf754ce1bd6c1c550c95312c0647e115f /gcc/cp/optimize.c | |
parent | c23c855f38f4287ce82018ca40892379bcdbf715 (diff) | |
download | gcc-db9b217498015006694d428ada8d8aed292a432f.zip gcc-db9b217498015006694d428ada8d8aed292a432f.tar.gz gcc-db9b217498015006694d428ada8d8aed292a432f.tar.bz2 |
cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
* cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
(complete_dtor_identifier): New macro.
(CLASSTYPE_FIRST_CONVERSION): Remove.
(CLASSTYPE_CONSTRUCTOR_SLOT): New macro.
(CLASSTYPE_DESTRUCTOR_SLOT): Likewise.
(CLASSTYPE_FIRST_CONVERSION_SLOT): Likewise.
(CLASSTYPE_CONSTRUCTORS): Likewise.
(CLASSTYPE_DESTRUCTORS): Likewise.
(lang_decl): Add cloned_function.
(DECL_COMPLETE_CONSTRUCTOR_P): New macro.
(DECL_BASE_CONSTRUCTOR_P): Likewise.
(DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P): Likewise.
(DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P): Likewise.
(DECL_CLONED_FUNCTION_P): Likewise.
(DECL_CLONED_FUNCTION): Likewise.
(clone_function_decl): Declare.
(maybe_clone_body): Likewise.
* call.c (build_user_type_conversion_1): Call complete object
constructors in the new ABI.
(build_new_method_call): Don't add in-charge parameters under the
new ABI.
* class.c (add_method): Use DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P,
DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P, CLASSTYPE_CONSTRUCTOR_SLOT, and
CLASSTYPE_DESTRUCTOR_SLOT.
(build_clone): New function.
(clone_function_decl): Likewise.
(clone_constructors_and_destructors): Likewise.
(check_bases_and_members): Use it.
* decl.c (iniitialize_predefined_identifiers): Initialize
complete_dtor_identifier.
(finish_function): Don't add extra code to a clone.
(lang_mark_tree): Mark cloned_function.
* decl2.c (mark_used): Don't bother trying to instantiate things
we synthesized.
* dump.c (dequeue_and_dump): Don't dump CP_DECL_CONTEXT twice.
* method.c (set_mangled_name_for_decl): Don't treat clones as
constructors.
(synthesize_method): Sythesize cloned functions, not the clones.
* optimize.c (inline_data): Update comment on ret_label.
(remap_block): Don't assume DECL_INITIAL exists.
(copy_body_r): Allow ret_label to be NULL.
(maybe_clone_body): Define.
* pt.c (tsubst_decl): Handle clones.
(instantiate_clone): New function.
(instantiate_template): Use it.
(set_mangled_name_for_template_decl): Don't treat clones as
constructors.
* search.c (lookup_fnfields_1): Use CLASSTYPE_CONSTRUCTOR_SLOT,
CLASSTYPE_DESTRUCTOR_SLOT, and CLASSTYPE_FIRST_CONVERSION_SLOT.
* semantics.c (expand_body): Clone function bodies as necessary.
From-SVN: r33084
Diffstat (limited to 'gcc/cp/optimize.c')
-rw-r--r-- | gcc/cp/optimize.c | 127 |
1 files changed, 120 insertions, 7 deletions
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index b12a2ff..9f2fe35 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -50,7 +50,9 @@ typedef struct inline_data inlining the body of `h', the stack will contain, `h', followed by `g', followed by `f'. */ varray_type fns; - /* The label to jump to when a return statement is encountered. */ + /* The label to jump to when a return statement is encountered. If + this value is NULL, then return statements will simply be + remapped as return statements, rather than as jumps. */ tree ret_label; /* The map from local declarations in the inlined function to equivalents in the function into which it is being inlined. */ @@ -157,6 +159,7 @@ remap_block (scope_stmt, decls, id) tree old_block; tree new_block; tree old_var; + tree *first_block; tree fn; /* Make the new block. */ @@ -175,9 +178,12 @@ remap_block (scope_stmt, decls, id) /* Remap the variable. */ new_var = remap_decl (old_var, id); - if (!new_var) - /* We didn't remap this variable, so we can't mess with - its TREE_CHAIN. */ + /* If we didn't remap this variable, so we can't mess with + its TREE_CHAIN. If we remapped this variable to + something other than a declaration (say, if we mapped it + to a constant), then we must similarly omit any mention + of it here. */ + if (!new_var || !DECL_P (new_var)) ; else { @@ -191,8 +197,12 @@ remap_block (scope_stmt, decls, id) function into which this block is being inlined. In rest_of_compilation we will straighten out the BLOCK tree. */ fn = VARRAY_TREE (id->fns, 0); - BLOCK_CHAIN (new_block) = BLOCK_CHAIN (DECL_INITIAL (fn)); - BLOCK_CHAIN (DECL_INITIAL (fn)) = new_block; + if (DECL_INITIAL (fn)) + first_block = &BLOCK_CHAIN (DECL_INITIAL (fn)); + else + first_block = &DECL_INITIAL (fn); + BLOCK_CHAIN (new_block) = *first_block; + *first_block = new_block; /* Remember the remapped block. */ splay_tree_insert (id->decl_map, (splay_tree_key) old_block, @@ -261,7 +271,7 @@ copy_body_r (tp, walk_subtrees, data) /* If this is a RETURN_STMT, change it into an EXPR_STMT and a GOTO_STMT with the RET_LABEL as its target. */ - if (TREE_CODE (*tp) == RETURN_STMT) + if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label) { tree return_stmt = *tp; tree goto_stmt; @@ -774,3 +784,106 @@ calls_setjmp_p (fn) != NULL_TREE); } +/* 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 + process the main body. */ + +int +maybe_clone_body (fn) + tree fn; +{ + inline_data id; + tree clone; + + /* We don't clone constructors and destructors under the old ABI. */ + if (!flag_new_abi) + return 0; + + /* We only clone constructors and destructors. */ + if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) + && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) + return 0; + + /* We don't yet handle destructors. */ + if (DECL_DESTRUCTOR_P (fn)) + return 0; + + /* We know that any clones immediately follow FN in the TYPE_METHODS + list. */ + for (clone = TREE_CHAIN (fn); + clone && DECL_CLONED_FUNCTION_P (clone); + clone = TREE_CHAIN (clone)) + { + tree parm; + tree clone_parm; + int parmno; + + /* Update CLONE's source position information to match FN's. */ + DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn); + DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn); + + /* Start processing the function. */ + push_to_top_level (); + start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED); + store_parm_decls (); + + /* 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); + + /* Remap the parameters. */ + id.decl_map = splay_tree_new (splay_tree_compare_pointers, + NULL, NULL); + for (parmno = 0, + parm = DECL_ARGUMENTS (fn), + clone_parm = DECL_ARGUMENTS (clone); + parm; + ++parmno, + parm = TREE_CHAIN (parm)) + { + /* Map the in-charge parameter to an appropriate constant. */ + if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) + { + tree in_charge; + + if (DECL_COMPLETE_CONSTRUCTOR_P (clone)) + in_charge = integer_one_node; + else + in_charge = integer_zero_node; + + splay_tree_insert (id.decl_map, + (splay_tree_key) parm, + (splay_tree_key) in_charge); + } + /* Map other parameters to their equivalents in the cloned + function. */ + else + { + splay_tree_insert (id.decl_map, + (splay_tree_key) parm, + (splay_tree_value) clone_parm); + clone_parm = TREE_CHAIN (clone_parm); + } + } + + /* Actually copy the body. */ + TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); + + /* Clean up. */ + splay_tree_delete (id.decl_map); + VARRAY_FREE (id.fns); + + /* Now, expand this function into RTL, if appropriate. */ + current_function_name_declared = 1; + expand_body (finish_function (0)); + pop_from_top_level (); + } + + /* We don't need to process the original function any further. */ + return 1; +} |