(splay_tree_value) value);
}
-/* Remap DECL during the copying of the BLOCK tree for the function.
+/* Remap DECL during the copying of the BLOCK tree for the function.
We are only called to remap local variables in the current function. */
static tree
insert_decl_map (id, type, type);
return type;
}
-
+
/* We do need a copy. build and register it now. If this is a pointer or
reference type, remap the designated type and make a new pointer or
reference type. */
if (t && TREE_CODE (t) != INTEGER_CST)
walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL);
return new;
-
+
case FUNCTION_TYPE:
TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
walk_tree (&TYPE_ARG_TYPES (new), copy_body_r, id, NULL);
copy_statement_list (tp);
else if (TREE_CODE (*tp) == SAVE_EXPR)
remap_save_expr (tp, id->decl_map, walk_subtrees);
- else if (TREE_CODE (*tp) == UNSAVE_EXPR)
- /* UNSAVE_EXPRs should not be generated until expansion time. */
- abort ();
else if (TREE_CODE (*tp) == BIND_EXPR)
copy_bind_expr (tp, walk_subtrees, id);
else if (TREE_CODE (*tp) == LABELED_BLOCK_EXPR)
}
}
}
- else if (TREE_CODE (*tp) == ADDR_EXPR
- && (lang_hooks.tree_inlining.auto_var_in_fn_p
- (TREE_OPERAND (*tp, 0), fn)))
- {
- /* Get rid of &* from inline substitutions. It can occur when
- someone takes the address of a parm or return slot passed by
- invisible reference. */
- tree decl = TREE_OPERAND (*tp, 0), value;
- splay_tree_node n;
-
- n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
- if (n)
- {
- value = (tree) n->value;
- if (TREE_CODE (value) == INDIRECT_REF)
- {
- if (!lang_hooks.types_compatible_p
- (TREE_TYPE (*tp), TREE_TYPE (TREE_OPERAND (value, 0))))
- *tp = fold_convert (TREE_TYPE (*tp),
- TREE_OPERAND (value, 0));
- else
- *tp = TREE_OPERAND (value, 0);
-
- return copy_body_r (tp, walk_subtrees, data);
- }
- }
- }
else if (TREE_CODE (*tp) == INDIRECT_REF)
{
/* Get rid of *& from inline substitutions that can happen when a
{
tree init_stmt;
tree var;
- tree var_sub;
/* If the parameter is never assigned to, we may not need to
create a new variable here at all. Instead, we may be able
function. */
var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
- /* See if the frontend wants to pass this by invisible reference. If
- so, our new VAR_DECL will have REFERENCE_TYPE, and we need to
- replace uses of the PARM_DECL with dereferences. */
- if (TREE_TYPE (var) != TREE_TYPE (p)
- && POINTER_TYPE_P (TREE_TYPE (var))
- && TREE_TYPE (TREE_TYPE (var)) == TREE_TYPE (p))
- {
- insert_decl_map (id, var, var);
- var_sub = build1 (INDIRECT_REF, TREE_TYPE (p), var);
- }
- else
- var_sub = var;
-
/* Register the VAR_DECL as the equivalent for the PARM_DECL;
that way, when the PARM_DECL is encountered, it will be
automatically replaced by the VAR_DECL. */
- insert_decl_map (id, p, var_sub);
+ insert_decl_map (id, p, var);
/* Declare this new variable. */
TREE_CHAIN (var) = *vars;
return NULL_TREE;
}
- /* If there was a return slot, then the return value the the
+ /* If there was a return slot, then the return value is the
dereferenced address of that object. */
if (return_slot_addr)
{
a modify expression. */
if (modify_dest)
abort ();
- var = build_fold_indirect_ref (return_slot_addr);
+ if (DECL_BY_REFERENCE (result))
+ var = return_slot_addr;
+ else
+ var = build_fold_indirect_ref (return_slot_addr);
use = NULL;
goto done;
}
return NULL;
switch (TREE_CODE (x))
- {
+ {
/* Containers have no cost. */
case TREE_LIST:
case TREE_VEC:
case NOP_EXPR:
case VIEW_CONVERT_EXPR:
case SAVE_EXPR:
- case UNSAVE_EXPR:
case ADDR_EXPR:
case COMPLEX_EXPR:
case EXIT_BLOCK_EXPR:
case STATEMENT_LIST:
case ERROR_MARK:
case NON_LVALUE_EXPR:
- case ENTRY_VALUE_EXPR:
case FDESC_EXPR:
case VA_ARG_EXPR:
case TRY_CATCH_EXPR:
case EXIT_EXPR:
case LOOP_EXPR:
case PHI_NODE:
+ case WITH_SIZE_EXPR:
break;
/* We don't account constants for now. Assume that the cost is amortized
case ASM_EXPR:
case RESX_EXPR:
- *count++;
+ *count += 1;
break;
/* Few special cases of expensive operations. This is useful
Note we need to save and restore the saved tree statement iterator
to avoid having it clobbered by expand_calls_inline. */
tree_stmt_iterator save_tsi;
-
+
save_tsi = id->tsi;
expand_calls_inline (&arg_inits, id);
id->tsi = save_tsi;
expand_calls_inline (tree *stmt_p, inline_data *id)
{
tree stmt = *stmt_p;
- enum tree_code code = TREE_CODE (stmt);
+ enum tree_code code = TREE_CODE (stmt);
int dummy;
switch (code)
case MODIFY_EXPR:
stmt_p = &TREE_OPERAND (stmt, 1);
stmt = *stmt_p;
+ if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
+ {
+ stmt_p = &TREE_OPERAND (stmt, 0);
+ stmt = *stmt_p;
+ }
if (TREE_CODE (stmt) != CALL_EXPR)
break;
append_to_statement_list_force (copy_body (&id), &DECL_SAVED_TREE (clone));
}
-/* Save duplicate of body in FN. MAP is used to pass around splay tree
- used to update arguments in restore_body. */
+/* Make and return duplicate of body in FN. Put copies of DECL_ARGUMENTS
+ in *arg_copy and of the static chain, if any, in *sc_copy. */
+
tree
-save_body (tree fn, tree *arg_copy)
+save_body (tree fn, tree *arg_copy, tree *sc_copy)
{
inline_data id;
tree body, *parg;
*parg = new;
}
+ *sc_copy = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
+ if (*sc_copy)
+ {
+ tree new = copy_node (*sc_copy);
+
+ lang_hooks.dup_lang_specific_decl (new);
+ DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*sc_copy);
+ insert_decl_map (&id, *sc_copy, new);
+ TREE_CHAIN (new) = TREE_CHAIN (*sc_copy);
+ *sc_copy = new;
+ }
+
insert_decl_map (&id, DECL_RESULT (fn), DECL_RESULT (fn));
/* Actually copy the body. */
if (TREE_CODE (*tp) == BIND_EXPR)
BIND_EXPR_BLOCK (*tp) = NULL_TREE;
}
-
+
else if (TREE_CODE_CLASS (code) == 't')
*walk_subtrees = 0;
else if (TREE_CODE_CLASS (code) == 'd')
/* Copy the decl and remember the copy. */
insert_decl_map (id, decl,
- copy_decl_for_inlining (decl, DECL_CONTEXT (decl),
+ copy_decl_for_inlining (decl, DECL_CONTEXT (decl),
DECL_CONTEXT (decl)));
}
{
/* Lookup the declaration. */
n = splay_tree_lookup (st, (splay_tree_key) *tp);
-
+
/* If it's there, remap it. */
if (n)
*tp = (tree) n->value;