This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]