aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2007-02-09 01:11:18 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2007-02-09 01:11:18 +0000
commit46bd2beed4c78dcb32fcde4913815527c14e5e17 (patch)
tree0c7d195e64cf1a546187b71d49c8c44bdca1041f /gcc
parent687e00ee8a88d034fb91a9eecb611b5927c5f677 (diff)
downloadgcc-46bd2beed4c78dcb32fcde4913815527c14e5e17.zip
gcc-46bd2beed4c78dcb32fcde4913815527c14e5e17.tar.gz
gcc-46bd2beed4c78dcb32fcde4913815527c14e5e17.tar.bz2
calls.c (store_one_arg): Pass correct alignment to emit_push_insn for non-BLKmode values.
* 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. From-SVN: r121736
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/calls.c17
-rw-r--r--gcc/expr.c17
3 files changed, 38 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 59ad7fc..777ca63 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/calls.c b/gcc/calls.c
index 0ca03f8..ab51d17 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -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));
diff --git a/gcc/expr.c b/gcc/expr.c
index b49813a..a04e931 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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