re PR middle-end/16417 (crappy code (gcc.c-torture/compile/20020210-1.c) in arguments...
authorRichard Henderson <rth@redhat.com>
Sun, 19 Dec 2004 04:42:14 +0000 (20:42 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 19 Dec 2004 04:42:14 +0000 (20:42 -0800)
        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.

From-SVN: r92373

gcc/ChangeLog
gcc/Makefile.in
gcc/c-decl.c
gcc/c-objc-common.c
gcc/c-tree.h
gcc/function.c
gcc/gimplify.c
gcc/tree-gimple.h
gcc/tree-inline.c
gcc/tree.h

index f9a9b5628bc2e349ff49522acd4c6de38ed6c07d..60b90b06b8c01eb0124b7598ac3de5f8363cf4f8 100644 (file)
@@ -1,3 +1,25 @@
+2004-12-18  Richard Henderson  <rth@redhat.com>
+
+       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.
+
 2004-12-18  Richard Henderson  <rth@redhat.com>
 
        * c-decl.c (finish_struct): Add DECL_EXPR for variable sized
index 801e231642b5978a9ff8ee7c860f7b8c5b49c77e..c73562b6c3c9a49ff382d8f9567115e83bbf7073 100644 (file)
@@ -1843,7 +1843,7 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_
    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_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 26caa2c47b3457333d1bd8070350c46f4d1a0346..e6b4cba791294418f96c2b4bc86ebd380a41deb0 100644 (file)
@@ -6235,8 +6235,11 @@ store_parm_decls (void)
   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.  */
+     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 d9e8b93e481e3578ca9f6be4e8c37e8d26057bea..35bcf9e327559430e1b9474c1b8b24acfe12b3b2 100644 (file)
@@ -68,7 +68,6 @@ int
 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)
@@ -101,35 +100,6 @@ c_cannot_inline_tree_fn (tree *fnp)
       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:
index 5415ee079b60b99ec088d081f9f625ff4d688be0..43001ca0aa54d3f81bf5df4ea6dc3faf512293d4 100644 (file)
@@ -41,10 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 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;
+  char dummy;
 };
 
 /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
index 046a4adda6d4fed71a3a7facc49162fc753a3f22..9251071d6f8bad1e55fa62cf49e86f4a94aaf9e4 100644 (file)
@@ -59,6 +59,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "langhooks.h"
 #include "target.h"
 #include "cfglayout.h"
+#include "tree-gimple.h"
 
 #ifndef LOCAL_ALIGNMENT
 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
@@ -2804,50 +2805,6 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
       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
@@ -3202,6 +3159,115 @@ assign_parms (tree fndecl)
        }
     }
 }
+
+/* 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;
+}
 \f
 /* 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
@@ -3972,22 +4038,6 @@ expand_main_function (void)
 #endif
 }
 \f
-/* 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.
@@ -4152,9 +4202,6 @@ expand_function_start (tree subr)
      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 ();
 }
index 0b83d78fd43ef56bdfc87d09c79ffdf8721d09c0..55889ea9dcceb0bc0fa5373bfb027362980c7cba 100644 (file)
@@ -3832,6 +3832,10 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
              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.  */
@@ -4213,10 +4217,10 @@ check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
    function decl containing BODY.  */
 
 void
-gimplify_body (tree *body_p, tree fndecl)
+gimplify_body (tree *body_p, tree fndecl, bool do_parms)
 {
   location_t saved_location = input_location;
-  tree body;
+  tree body, parm_stmts;
 
   timevar_push (TV_TREE_GIMPLIFY);
   push_gimplify_context ();
@@ -4231,13 +4235,14 @@ gimplify_body (tree *body_p, tree fndecl)
   /* 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;
 
-  /* Unshare again, in case gimplification was sloppy.  */
-  unshare_all_trees (body);
-
   if (!body)
     body = alloc_stmt_list ();
   else if (TREE_CODE (body) == STATEMENT_LIST)
@@ -4256,6 +4261,18 @@ gimplify_body (tree *body_p, tree fndecl)
       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);
@@ -4278,8 +4295,11 @@ gimplify_function_tree (tree fndecl)
 
   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);
+  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
@@ -4309,6 +4329,7 @@ gimplify_function_tree (tree fndecl)
     }
 
   current_function_decl = oldfn;
+  cfun = oldfn ? DECL_STRUCT_FUNCTION (oldfn) : NULL;
 }
 
 \f
index 0f05d6a7f55cb327d237ea0cd0ee445187862503..de62d29a5f38b1383a94e7f44d16eb879e1298a0 100644 (file)
@@ -113,7 +113,7 @@ extern void gimplify_type_sizes (tree, tree *);
 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 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 61fe66dbb085683acbc28ce87dedd2eb8f06a848..53a16133a6af9d3a2714722123af3fae0f5f555e 100644 (file)
@@ -819,7 +819,7 @@ initialize_inlined_parameters (inline_data *id, tree args, tree static_chain,
     }
 
   if (gimplify_init_stmts_p)
-    gimplify_body (&init_stmts, current_function_decl);
+    gimplify_body (&init_stmts, current_function_decl, false);
 
   declare_inline_vars (bind_expr, vars);
   return init_stmts;
index 457d72cd12f2c19f038480de0b654fdb1648febe..fa328bedad2ce68fd3ef4fbd3e5ce1310fa730c1 100644 (file)
@@ -3602,6 +3602,7 @@ extern void push_function_context (void);
 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