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]

fix middle-end/16417


I *believe* this takes care off all the issues found with the last CFT.

Tested on i686-linux, and spot-tested cross compile to the various 
cases pointed out by folk in the cft.  I've gone ahead and committed
this; if we still have failures, please reopen the bug.


r~


        PR middle-end/16417
        * c-decl.c (store_parm_decls): Clarify get_pending_sizes insertion
        comment.
        * c-objc-common.c (c_cannot_inline_tree_fn): Remove pending sizes
        checks.
        * c-tree.h (struct lang_decl): Remove pending_sizes.
        * function.c: Include tree-gimple.h
        (assign_parm_setup_reg): Remove callee-copies code.
        (gimplify_parm_type, gimplify_parameters): New functions.
        (expand_pending_sizes): Remove.
        (expand_function_start): Don't call it.
        * gimplify.c (gimplify_expr): Examine DECL_VALUE_EXPR for PARM_DECL.
        (gimplify_body): Add do_parms argument.  Use gimplify_parameters.
        (gimplify_function_tree): Setup cfun.  Update gimplify_body call.
        * tree-gimple.h (gimplify_body): Update decl.
        * tree-inline.c (initialize_inlined_parameters): Update gimplify_body
        call.
        * tree.h (gimplify_parameters): Declare.
        * Makefile.in (function.o): Depend on TREE_GIMPLE_H.

Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.615
diff -c -p -d -r1.615 c-decl.c
*** c-decl.c	19 Dec 2004 04:07:52 -0000	1.615
--- c-decl.c	19 Dec 2004 04:31:22 -0000
*************** store_parm_decls (void)
*** 6235,6242 ****
    DECL_SAVED_TREE (fndecl) = push_stmt_list ();
  
    /* ??? Insert the contents of the pending sizes list into the function
!      to be evaluated.  This just changes mis-behavior until assign_parms
!      phase ordering problems are resolved.  */
    {
      tree t;
      for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
--- 6235,6245 ----
    DECL_SAVED_TREE (fndecl) = push_stmt_list ();
  
    /* ??? Insert the contents of the pending sizes list into the function
!      to be evaluated.  The only reason left to have this is
! 	void foo(int n, int array[n++])
!      because we throw away the array type in favor of a pointer type, and
!      thus won't naturally see the SAVE_EXPR containing the increment.  All
!      other pending sizes would be handled by gimplify_parameters.  */
    {
      tree t;
      for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
Index: c-objc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.59
diff -c -p -d -r1.59 c-objc-common.c
*** c-objc-common.c	2 Nov 2004 20:29:14 -0000	1.59
--- c-objc-common.c	19 Dec 2004 04:31:22 -0000
*************** int
*** 68,74 ****
  c_cannot_inline_tree_fn (tree *fnp)
  {
    tree fn = *fnp;
-   tree t;
    bool do_warning = (warn_inline
  		     && DECL_INLINE (fn)
  		     && DECL_DECLARED_INLINE_P (fn)
--- 68,73 ----
*************** c_cannot_inline_tree_fn (tree *fnp)
*** 101,135 ****
        goto cannot_inline;
      }
  
-   /* If a function has pending sizes, we must not defer its
-      compilation, and we can't inline it as a tree.  */
-   if (fn == current_function_decl)
-     {
-       t = get_pending_sizes ();
-       put_pending_sizes (t);
- 
-       if (t)
- 	{
- 	  if (do_warning)
- 	    warning ("%Jfunction %qF can never be inlined because it has "
- 		     "pending sizes", fn, fn);
- 	  goto cannot_inline;
- 	}
-     }
- 
-   if (!DECL_FILE_SCOPE_P (fn))
-     {
-       /* If a nested function has pending sizes, we may have already
-          saved them.  */
-       if (DECL_LANG_SPECIFIC (fn)->pending_sizes)
- 	{
- 	  if (do_warning)
- 	    warning ("%Jnested function %qF can never be inlined because it "
- 		     "has possibly saved pending sizes", fn, fn);
- 	  goto cannot_inline;
- 	}
-     }
- 
    return 0;
  
   cannot_inline:
--- 100,105 ----
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.189
diff -c -p -d -r1.189 c-tree.h
*** c-tree.h	7 Dec 2004 23:46:10 -0000	1.189
--- c-tree.h	19 Dec 2004 04:31:22 -0000
*************** Software Foundation, 59 Temple Place - S
*** 41,50 ****
  
  struct lang_decl GTY(())
  {
!   /* The return types and parameter types may have variable size.
!      This is a list of any SAVE_EXPRs that need to be evaluated to
!      compute those sizes.  */
!   tree pending_sizes;
  };
  
  /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
--- 41,47 ----
  
  struct lang_decl GTY(())
  {
!   char dummy;
  };
  
  /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.592
diff -c -p -d -r1.592 function.c
*** function.c	1 Dec 2004 18:13:30 -0000	1.592
--- function.c	19 Dec 2004 04:31:23 -0000
*************** Software Foundation, 59 Temple Place - S
*** 59,64 ****
--- 59,65 ----
  #include "langhooks.h"
  #include "target.h"
  #include "cfglayout.h"
+ #include "tree-gimple.h"
  
  #ifndef LOCAL_ALIGNMENT
  #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
*************** assign_parm_setup_reg (struct assign_par
*** 2804,2853 ****
        data->stack_parm = NULL;
      }
  
-   /* If we are passed an arg by reference and it is our responsibility
-      to make a copy, do it now.
-      PASSED_TYPE and PASSED mode now refer to the pointer, not the
-      original argument, so we must recreate them in the call to
-      FUNCTION_ARG_CALLEE_COPIES.  */
-   /* ??? Later add code to handle the case that if the argument isn't
-      modified, don't do the copy.  */
- 
-   else if (data->passed_pointer)
-     {
-       tree type = TREE_TYPE (data->passed_type);
-     
-       if (reference_callee_copied (&all->args_so_far, TYPE_MODE (type),
- 				   type, data->named_arg))
- 	{
- 	  rtx copy;
- 
- 	  /* This sequence may involve a library call perhaps clobbering
- 	     registers that haven't been copied to pseudos yet.  */
- 
- 	  push_to_sequence (all->conversion_insns);
- 
- 	  if (!COMPLETE_TYPE_P (type)
- 	      || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- 	    {
- 	      /* This is a variable sized object.  */
- 	      copy = allocate_dynamic_stack_space (expr_size (parm), NULL_RTX,
- 						   TYPE_ALIGN (type));
- 	      copy = gen_rtx_MEM (BLKmode, copy);
- 	    }
- 	  else
- 	    copy = assign_stack_temp (TYPE_MODE (type),
- 				      int_size_in_bytes (type), 1);
- 	  set_mem_attributes (copy, parm, 1);
- 
- 	  store_expr (parm, copy, 0);
- 	  emit_move_insn (parmreg, XEXP (copy, 0));
- 	  all->conversion_insns = get_insns ();
- 	  end_sequence ();
- 
- 	  did_conversion = true;
- 	}
-     }
- 
    /* Mark the register as eliminable if we did no conversion and it was
       copied from memory at a fixed offset, and the arg pointer was not
       copied to a pseudo-reg.  If the arg pointer is a pseudo reg or the
--- 2805,2810 ----
*************** assign_parms (tree fndecl)
*** 3202,3207 ****
--- 3159,3273 ----
  	}
      }
  }
+ 
+ /* A subroutine of gimplify_parameters, invoked via walk_tree.
+    For all seen types, gimplify their sizes.  */
+ 
+ static tree
+ gimplify_parm_type (tree *tp, int *walk_subtrees, void *data)
+ {
+   tree t = *tp;
+ 
+   *walk_subtrees = 0;
+   if (TYPE_P (t))
+     {
+       if (POINTER_TYPE_P (t))
+ 	*walk_subtrees = 1;
+       else if (TYPE_SIZE (t) && !TREE_CONSTANT (TYPE_SIZE (t)))
+ 	{
+ 	  gimplify_type_sizes (t, (tree *) data);
+ 	  *walk_subtrees = 1;
+ 	}
+     }
+ 
+   return NULL;
+ }
+ 
+ /* Gimplify the parameter list for current_function_decl.  This involves
+    evaluating SAVE_EXPRs of variable sized parameters and generating code
+    to implement callee-copies reference parameters.  Returns a list of
+    statements to add to the beginning of the function, or NULL if nothing
+    to do.  */
+ 
+ tree
+ gimplify_parameters (void)
+ {
+   struct assign_parm_data_all all;
+   tree fnargs, parm, stmts = NULL;
+ 
+   assign_parms_initialize_all (&all);
+   fnargs = assign_parms_augmented_arg_list (&all);
+ 
+   for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
+     {
+       struct assign_parm_data_one data;
+ 
+       /* Extract the type of PARM; adjust it according to ABI.  */
+       assign_parm_find_data_types (&all, parm, &data);
+ 
+       /* Early out for errors and void parameters.  */
+       if (data.passed_mode == VOIDmode || DECL_SIZE (parm) == NULL)
+ 	continue;
+ 
+       /* Update info on where next arg arrives in registers.  */
+       FUNCTION_ARG_ADVANCE (all.args_so_far, data.promoted_mode,
+ 			    data.passed_type, data.named_arg);
+ 
+       /* ??? Once upon a time variable_size stuffed parameter list
+ 	 SAVE_EXPRs (amongst others) onto a pending sizes list.  This
+ 	 turned out to be less than manageable in the gimple world.
+ 	 Now we have to hunt them down ourselves.  */
+       walk_tree_without_duplicates (&data.passed_type,
+ 				    gimplify_parm_type, &stmts);
+ 
+       if (!TREE_CONSTANT (DECL_SIZE (parm)))
+ 	{
+ 	  gimplify_one_sizepos (&DECL_SIZE (parm), &stmts);
+ 	  gimplify_one_sizepos (&DECL_SIZE_UNIT (parm), &stmts);
+ 	}
+ 
+       if (data.passed_pointer)
+ 	{
+           tree type = TREE_TYPE (data.passed_type);
+ 	  if (reference_callee_copied (&all.args_so_far, TYPE_MODE (type),
+ 				       type, data.named_arg))
+ 	    {
+ 	      tree local, t;
+ 
+ 	      /* For constant sized objects, this is trivial; for
+ 		 variable-sized objects, we have to play games.  */
+ 	      if (TREE_CONSTANT (DECL_SIZE (parm)))
+ 		{
+ 		  local = create_tmp_var (type, get_name (parm));
+ 		  DECL_IGNORED_P (local) = 0;
+ 		}
+ 	      else
+ 		{
+ 		  tree ptr_type, addr, args;
+ 
+ 		  ptr_type = build_pointer_type (type);
+ 		  addr = create_tmp_var (ptr_type, get_name (parm));
+ 		  DECL_IGNORED_P (addr) = 0;
+ 		  local = build_fold_indirect_ref (addr);
+ 
+ 		  args = tree_cons (NULL, DECL_SIZE_UNIT (parm), NULL);
+ 		  t = built_in_decls[BUILT_IN_ALLOCA];
+ 		  t = build_function_call_expr (t, args);
+ 		  t = fold_convert (ptr_type, t);
+ 		  t = build2 (MODIFY_EXPR, void_type_node, addr, t);
+ 		  gimplify_and_add (t, &stmts);
+ 		}
+ 
+ 	      t = build2 (MODIFY_EXPR, void_type_node, local, parm);
+ 	      gimplify_and_add (t, &stmts);
+ 
+ 	      DECL_VALUE_EXPR (parm) = local;
+ 	    }
+ 	}
+     }
+ 
+   return stmts;
+ }
  
  /* Indicate whether REGNO is an incoming argument to the current function
     that was promoted to a wider mode.  If so, return the RTX for the
*************** expand_main_function (void)
*** 3972,3993 ****
  #endif
  }
  
- /* The PENDING_SIZES represent the sizes of variable-sized types.
-    Create RTL for the various sizes now (using temporary variables),
-    so that we can refer to the sizes from the RTL we are generating
-    for the current function.  The PENDING_SIZES are a TREE_LIST.  The
-    TREE_VALUE of each node is a SAVE_EXPR.  */
- 
- static void
- expand_pending_sizes (tree pending_sizes)
- {
-   tree tem;
- 
-   /* Evaluate now the sizes of any types declared among the arguments.  */
-   for (tem = pending_sizes; tem; tem = TREE_CHAIN (tem))
-     expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode, 0);
- }
- 
  /* Start the RTL for a new function, and set variables used for
     emitting RTL.
     SUBR is the FUNCTION_DECL node.
--- 4038,4043 ----
*************** expand_function_start (tree subr)
*** 4152,4160 ****
       since some things (like trampolines) get placed before this.  */
    tail_recursion_reentry = emit_note (NOTE_INSN_DELETED);
  
-   /* Evaluate now the sizes of any types declared among the arguments.  */
-   expand_pending_sizes (nreverse (get_pending_sizes ()));
- 
    /* Make sure there is a line number after the function entry setup code.  */
    force_next_line_note ();
  }
--- 4202,4207 ----
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.92
diff -c -p -d -r2.92 gimplify.c
*** gimplify.c	8 Dec 2004 08:47:47 -0000	2.92
--- gimplify.c	19 Dec 2004 04:31:24 -0000
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 3832,3837 ****
--- 3832,3841 ----
  	      ret = GS_ERROR;
  	      break;
  	    }
+ 	  /* FALLTHRU */
+ 
+ 	case PARM_DECL:
+ 	  tmp = *expr_p;
  
  	  /* If this is a local variable sized decl, it must be accessed
  	     indirectly.  Perform that substitution.  */
*************** check_pointer_types_r (tree *tp, int *wa
*** 4213,4222 ****
     function decl containing BODY.  */
  
  void
! gimplify_body (tree *body_p, tree fndecl)
  {
    location_t saved_location = input_location;
!   tree body;
  
    timevar_push (TV_TREE_GIMPLIFY);
    push_gimplify_context ();
--- 4217,4226 ----
     function decl containing BODY.  */
  
  void
! gimplify_body (tree *body_p, tree fndecl, bool do_parms)
  {
    location_t saved_location = input_location;
!   tree body, parm_stmts;
  
    timevar_push (TV_TREE_GIMPLIFY);
    push_gimplify_context ();
*************** gimplify_body (tree *body_p, tree fndecl
*** 4231,4243 ****
    /* Make sure input_location isn't set to something wierd.  */
    input_location = DECL_SOURCE_LOCATION (fndecl);
  
    /* Gimplify the function's body.  */
    gimplify_stmt (body_p);
    body = *body_p;
  
-   /* Unshare again, in case gimplification was sloppy.  */
-   unshare_all_trees (body);
- 
    if (!body)
      body = alloc_stmt_list ();
    else if (TREE_CODE (body) == STATEMENT_LIST)
--- 4235,4248 ----
    /* Make sure input_location isn't set to something wierd.  */
    input_location = DECL_SOURCE_LOCATION (fndecl);
  
+   /* Resolve callee-copies.  This has to be done before processing
+      the body so that DECL_VALUE_EXPR gets processed correctly.  */
+   parm_stmts = do_parms ? gimplify_parameters () : NULL;
+ 
    /* Gimplify the function's body.  */
    gimplify_stmt (body_p);
    body = *body_p;
  
    if (!body)
      body = alloc_stmt_list ();
    else if (TREE_CODE (body) == STATEMENT_LIST)
*************** gimplify_body (tree *body_p, tree fndecl
*** 4256,4261 ****
--- 4261,4278 ----
        append_to_statement_list_force (body, &BIND_EXPR_BODY (b));
        body = b;
      }
+ 
+   /* If we had callee-copies statements, insert them at the beginning
+      of the function.  */
+   if (parm_stmts)
+     {
+       append_to_statement_list_force (BIND_EXPR_BODY (body), &parm_stmts);
+       BIND_EXPR_BODY (body) = parm_stmts;
+     }
+ 
+   /* Unshare again, in case gimplification was sloppy.  */
+   unshare_all_trees (body);
+ 
    *body_p = body;
  
    pop_gimplify_context (body);
*************** gimplify_function_tree (tree fndecl)
*** 4278,4285 ****
  
    oldfn = current_function_decl;
    current_function_decl = fndecl;
  
!   gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl);
  
    /* If we're instrumenting function entry/exit, then prepend the call to
       the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
--- 4295,4305 ----
  
    oldfn = current_function_decl;
    current_function_decl = fndecl;
+   cfun = DECL_STRUCT_FUNCTION (fndecl);
+   if (cfun == NULL)
+     allocate_struct_function (fndecl);
  
!   gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true);
  
    /* If we're instrumenting function entry/exit, then prepend the call to
       the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
*************** gimplify_function_tree (tree fndecl)
*** 4309,4314 ****
--- 4329,4335 ----
      }
  
    current_function_decl = oldfn;
+   cfun = oldfn ? DECL_STRUCT_FUNCTION (oldfn) : NULL;
  }
  
  
Index: tree-gimple.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.h,v
retrieving revision 2.19
diff -c -p -d -r2.19 tree-gimple.h
*** tree-gimple.h	22 Oct 2004 18:50:34 -0000	2.19
--- tree-gimple.h	19 Dec 2004 04:31:24 -0000
*************** extern void gimplify_type_sizes (tree, t
*** 113,119 ****
  extern void gimplify_one_sizepos (tree *, tree *);
  extern void gimplify_stmt (tree *);
  extern void gimplify_to_stmt_list (tree *);
! extern void gimplify_body (tree *, tree);
  extern void push_gimplify_context (void);
  extern void pop_gimplify_context (tree);
  extern void gimplify_and_add (tree, tree *);
--- 113,119 ----
  extern void gimplify_one_sizepos (tree *, tree *);
  extern void gimplify_stmt (tree *);
  extern void gimplify_to_stmt_list (tree *);
! extern void gimplify_body (tree *, tree, bool);
  extern void push_gimplify_context (void);
  extern void pop_gimplify_context (tree);
  extern void gimplify_and_add (tree, tree *);
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.158
diff -c -p -d -r1.158 tree-inline.c
*** tree-inline.c	15 Dec 2004 19:14:43 -0000	1.158
--- tree-inline.c	19 Dec 2004 04:31:24 -0000
*************** initialize_inlined_parameters (inline_da
*** 819,825 ****
      }
  
    if (gimplify_init_stmts_p)
!     gimplify_body (&init_stmts, current_function_decl);
  
    declare_inline_vars (bind_expr, vars);
    return init_stmts;
--- 819,825 ----
      }
  
    if (gimplify_init_stmts_p)
!     gimplify_body (&init_stmts, current_function_decl, false);
  
    declare_inline_vars (bind_expr, vars);
    return init_stmts;
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.666
diff -c -p -d -r1.666 tree.h
*** tree.h	9 Dec 2004 10:54:38 -0000	1.666
--- tree.h	19 Dec 2004 04:31:25 -0000
*************** extern void push_function_context (void)
*** 3602,3607 ****
--- 3602,3608 ----
  extern void pop_function_context (void);
  extern void push_function_context_to (tree);
  extern void pop_function_context_from (tree);
+ extern tree gimplify_parameters (void);
  
  /* In print-rtl.c */
  #ifdef BUFSIZ
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1434
diff -c -p -d -r1.1434 Makefile.in
*** Makefile.in	18 Dec 2004 19:40:20 -0000	1.1434
--- Makefile.in	19 Dec 2004 04:37:06 -0000
*************** varasm.o : varasm.c $(CONFIG_H) $(SYSTEM
*** 1843,1849 ****
     output.h $(C_PRAGMA_H) toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
     $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
  function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
!    $(TREE_H) $(CFGLAYOUT_H) \
     $(FLAGS_H) function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
     insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
     $(TM_P_H) langhooks.h gt-function.h $(TARGET_H) basic-block.h
--- 1843,1849 ----
     output.h $(C_PRAGMA_H) toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
     $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
  function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
!    $(TREE_H) $(CFGLAYOUT_H) $(TREE_GIMPLE_H) \
     $(FLAGS_H) function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
     insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
     $(TM_P_H) langhooks.h gt-function.h $(TARGET_H) basic-block.h


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