OSDN Git Service

* calls.c (store_one_arg): Pass correct alignment to
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Feb 2007 01:11:18 +0000 (01:11 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Feb 2007 01:11:18 +0000 (01:11 +0000)
emit_push_insn for non-BLKmode values.
* expr.c (emit_push_insn): If STRICT_ALIGNMENT, copy to an
unaligned stack slot via a suitably aligned slot.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121736 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/calls.c
gcc/expr.c

index 59ad7fc..777ca63 100644 (file)
@@ -1,3 +1,10 @@
+2007-02-09  Joseph Myers  <joseph@codesourcery.com>
+
+       * calls.c (store_one_arg): Pass correct alignment to
+       emit_push_insn for non-BLKmode values.
+       * expr.c (emit_push_insn): If STRICT_ALIGNMENT, copy to an
+       unaligned stack slot via a suitably aligned slot.
+
 2007-02-08  DJ Delorie  <dj@redhat.com>
 
        * config/m32c/m32c.c (m32c_unpend_compare): Add default to silence
index 0ca03f8..ab51d17 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert function calls to rtl insns, for GNU C compiler.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -4191,6 +4191,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
   else if (arg->mode != BLKmode)
     {
       int size;
+      unsigned int parm_align;
 
       /* Argument is a scalar, not entirely passed in registers.
         (If part is passed in registers, arg->partial says how much
@@ -4218,10 +4219,22 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
                 / (PARM_BOUNDARY / BITS_PER_UNIT))
                * (PARM_BOUNDARY / BITS_PER_UNIT));
 
+      /* Compute the alignment of the pushed argument.  */
+      parm_align = arg->locate.boundary;
+      if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
+       {
+         int pad = used - size;
+         if (pad)
+           {
+             unsigned int pad_align = (pad & -pad) * BITS_PER_UNIT;
+             parm_align = MIN (parm_align, pad_align);
+           }
+       }
+
       /* This isn't already where we want it on the stack, so put it there.
         This can either be done with push or copy insns.  */
       emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
-                     PARM_BOUNDARY, partial, reg, used - size, argblock,
+                     parm_align, partial, reg, used - size, argblock,
                      ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
                      ARGS_SIZE_RTX (arg->locate.alignment_pad));
 
index b49813a..a04e931 100644 (file)
@@ -3643,7 +3643,8 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
 
   xinner = x;
 
-  if (mode == BLKmode)
+  if (mode == BLKmode
+      || (STRICT_ALIGNMENT && align < GET_MODE_ALIGNMENT (mode)))
     {
       /* Copy a block into the stack, entirely or partially.  */
 
@@ -3655,6 +3656,20 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
       offset = partial % (PARM_BOUNDARY / BITS_PER_UNIT);
       used = partial - offset;
 
+      if (mode != BLKmode)
+       {
+         /* A value is to be stored in an insufficiently aligned
+            stack slot; copy via a suitably aligned slot if
+            necessary.  */
+         size = GEN_INT (GET_MODE_SIZE (mode));
+         if (!MEM_P (xinner))
+           {
+             temp = assign_temp (type, 0, 1, 1);
+             emit_move_insn (temp, xinner);
+             xinner = temp;
+           }
+       }
+
       gcc_assert (size);
 
       /* USED is now the # of bytes we need not copy to the stack