diff options
author | Joseph Myers <joseph@codesourcery.com> | 2007-02-09 01:11:18 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2007-02-09 01:11:18 +0000 |
commit | 46bd2beed4c78dcb32fcde4913815527c14e5e17 (patch) | |
tree | 0c7d195e64cf1a546187b71d49c8c44bdca1041f | |
parent | 687e00ee8a88d034fb91a9eecb611b5927c5f677 (diff) | |
download | gcc-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
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/calls.c | 17 | ||||
-rw-r--r-- | gcc/expr.c | 17 |
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)); @@ -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 |