This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] PATCH to tree-inline.c aggregate return handling
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 19 Aug 2003 23:20:26 -0400
- Subject: [tree-ssa] PATCH to tree-inline.c aggregate return handling
Cases where we were using a variable X from the caller as the return value
slot for an inline function were confusing the inliner: if we also had a
named return value Y in the inline function, we would try to insert X as
the inlined version of Y, screwing up the BIND_EXPR where X really lives.
Fixed by remembering the return value and ignoring it if we encounter it in
a chain of remapped decls.
Tested athlon-pc-linux-gnu, applied to tree-ssa.
2003-08-19 Jason Merrill <jason@redhat.com>
* tree-inline.c (inline_data): Add retvar field.
(declare_return_variable): Set it.
(remap_decls): Use it.
(expand_call_inline): Tweak.
*** ./tree-inline.c.~1~ Tue Aug 19 14:38:35 2003
--- ./tree-inline.c Tue Aug 19 18:30:34 2003
*************** typedef struct inline_data
*** 81,86 ****
--- 81,88 ----
this value is NULL, then return statements will simply be
remapped as return statements, rather than as jumps. */
tree ret_label;
+ /* The VAR_DECL for the return value. */
+ tree retvar;
/* The map from local declarations in the inlined function to
equivalents in the function into which it is being inlined. */
splay_tree decl_map;
*************** remap_decls (tree decls, inline_data *id
*** 229,241 ****
/* Remap the variable. */
new_var = remap_decl (old_var, id);
! /* 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
{
TREE_CHAIN (new_var) = new_decls;
--- 231,245 ----
/* Remap the variable. */
new_var = remap_decl (old_var, id);
! /* If we didn't remap this variable, so we can't mess with its
! TREE_CHAIN. If we remapped this variable to the return slot, it's
! already declared somewhere else, so don't declare it here. */
! if (!new_var || new_var == id->retvar)
;
+ #ifdef ENABLE_CHECKING
+ else if (!DECL_P (new_var))
+ abort ();
+ #endif
else
{
TREE_CHAIN (new_var) = new_decls;
*************** declare_return_variable (inline_data *id
*** 706,714 ****
(splay_tree_key) result,
(splay_tree_value) var);
/* Build the use expr. If the return type of the function was
promoted, convert it back to the expected type. */
! if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
*use_p = var;
else if (TREE_CODE (var) == INDIRECT_REF)
*use_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (fn)),
--- 710,725 ----
(splay_tree_key) result,
(splay_tree_value) var);
+ /* Remember this so we can ignore it in remap_decls. */
+ id->retvar = var;
+
/* Build the use expr. If the return type of the function was
promoted, convert it back to the expected type. */
! if (return_slot_addr)
! /* The function returns through an explicit return slot, not a normal
! return value. */
! *use_p = NULL_TREE;
! else if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
*use_p = var;
else if (TREE_CODE (var) == INDIRECT_REF)
*use_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (fn)),
*************** expand_call_inline (tree *tp, int *walk_
*** 922,928 ****
tree t;
tree expr;
tree stmt;
! tree retvar;
tree decl;
tree fn;
tree arg_inits;
--- 933,939 ----
tree t;
tree expr;
tree stmt;
! tree use_retvar;
tree decl;
tree fn;
tree arg_inits;
*************** expand_call_inline (tree *tp, int *walk_
*** 1087,1094 ****
abort ();
/* Declare the return variable for the function. */
! decl = declare_return_variable (id, return_slot_addr, &retvar);
! if (retvar)
add_var_to_bind_expr (expr, decl);
/* After we've initialized the parameters, we insert the body of the
--- 1098,1105 ----
abort ();
/* Declare the return variable for the function. */
! decl = declare_return_variable (id, return_slot_addr, &use_retvar);
! if (decl)
add_var_to_bind_expr (expr, decl);
/* After we've initialized the parameters, we insert the body of the
*************** expand_call_inline (tree *tp, int *walk_
*** 1110,1119 ****
/* Finally, mention the returned value so that the value of the
statement-expression is the returned value of the function. */
! if (retvar && TREE_TYPE (expr) != void_type_node)
BIND_EXPR_BODY (expr)
= add_stmt_to_compound (BIND_EXPR_BODY (expr),
! TREE_TYPE (retvar), retvar);
/* Clean up. */
splay_tree_delete (id->decl_map);
--- 1121,1130 ----
/* Finally, mention the returned value so that the value of the
statement-expression is the returned value of the function. */
! if (use_retvar)
BIND_EXPR_BODY (expr)
= add_stmt_to_compound (BIND_EXPR_BODY (expr),
! TREE_TYPE (use_retvar), use_retvar);
/* Clean up. */
splay_tree_delete (id->decl_map);