From: jsm28 Date: Fri, 9 Feb 2007 01:11:18 +0000 (+0000) Subject: * calls.c (store_one_arg): Pass correct alignment to X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=851fc2b32b9f3673d73d5d672d9e3ea698fc69ea * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121736 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 59ad7fc3ded..777ca6382c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-02-09 Joseph Myers + + * 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 * config/m32c/m32c.c (m32c_unpend_compare): Add default to silence diff --git a/gcc/calls.c b/gcc/calls.c index 0ca03f8e587..ab51d17a1dd 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 b49813ab2a9..a04e931acd0 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