Applying FUNCTION_ARG_PADDING to register arguments
Joern Rennecke
amylaar@cygnus.co.uk
Thu Oct 23 12:49:00 GMT 1997
While tracking down a varargs bug, I found that calls.c doesn't respect
FUNCTION_ARG_PADDING for register arguments. I think that is a bug.
I have appended a fix. One loop needed rewriting to support
FUNCTION_ARG_PADDING properly, therefore I have left the old test in
#if 0 so that you can more easily see what the actual change is and
what is just necessery code to implement it.
Thu Oct 23 18:11:33 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
* calls.c (expand_call): Use FUNCTION_ARG_PADDING also for
register parameters.
Index: calls.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/calls.c,v
retrieving revision 1.2
diff -p -r1.2 calls.c
*** calls.c 1997/08/11 20:07:08 1.2
--- calls.c 1997/10/23 17:21:04
*************** expand_call (exp, target, ignore)
*** 1773,1778 ****
--- 1773,1781 ----
{
int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
int big_endian_correction = 0;
+ int bitsize = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
+ rtx reg, word;
+ int k, bitpos, xbitpos;
args[i].n_aligned_regs
= args[i].partial ? args[i].partial
*************** expand_call (exp, target, ignore)
*** 1781,1829 ****
args[i].aligned_regs = (rtx *) alloca (sizeof (rtx)
* args[i].n_aligned_regs);
/* Structures smaller than a word are aligned to the least
significant byte (to the right). On a BYTES_BIG_ENDIAN machine,
this means we must skip the empty high order bytes when
calculating the bit offset. */
if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
!
! for (j = 0; j < args[i].n_aligned_regs; j++)
{
! rtx reg = gen_reg_rtx (word_mode);
! rtx word = operand_subword_force (args[i].value, j, BLKmode);
! int bitsize = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
! int bitpos;
!
! args[i].aligned_regs[j] = reg;
!
! /* Clobber REG and move each partword into it. Ensure we don't
! go past the end of the structure. Note that the loop below
! works because we've already verified that padding
! and endianness are compatible.
!
! We use to emit a clobber here but that doesn't let later
! passes optimize the instructions we emit. By storing 0 into
! the register later passes know the first AND to zero out the
! bitfield being set in the register is unnecessary. The store
! of 0 will be deleted as will at least the first AND. */
!
! emit_move_insn (reg, const0_rtx);
!
! for (bitpos = 0;
! bitpos < BITS_PER_WORD && bytes > 0;
! bitpos += bitsize, bytes -= bitsize / BITS_PER_UNIT)
{
! int xbitpos = bitpos + big_endian_correction;
!
! store_bit_field (reg, bitsize, xbitpos, word_mode,
! extract_bit_field (word, bitsize, bitpos, 1,
! NULL_RTX, word_mode,
! word_mode,
! bitsize / BITS_PER_UNIT,
! BITS_PER_WORD),
! bitsize / BITS_PER_UNIT, BITS_PER_WORD);
}
}
}
--- 1784,1841 ----
args[i].aligned_regs = (rtx *) alloca (sizeof (rtx)
* args[i].n_aligned_regs);
+ #if 0
/* Structures smaller than a word are aligned to the least
significant byte (to the right). On a BYTES_BIG_ENDIAN machine,
this means we must skip the empty high order bytes when
calculating the bit offset. */
if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
! #else
! /* Do alignment padding according to FUNCTION_ARG_PADDING. */
! if (FUNCTION_ARG_PADDING (args[i].mode,
! TREE_TYPE (args[i].tree_value))
! == downward)
! big_endian_correction
! = - (unsigned) (bytes * BITS_PER_UNIT) % PARM_BOUNDARY;
! #endif
!
! /* Clobber each REG and move each partword into it. Ensure we
! don't go past the end of the structure.
!
! We used to emit a clobber for each REG here but that doesn't
! let later passes optimize the instructions we emit. By storing
! 0 into the register later passes know the first AND to zero out
! the bitfield being set in the register is unnecessary. The
! store of 0 will be deleted as will at least the first AND. */
!
! for (j = 0, k = 0, bitpos = BITS_PER_WORD,
! xbitpos = BITS_PER_WORD + big_endian_correction;
! bytes > 0;
! bitpos += bitsize, xbitpos += bitsize,
! bytes -= bitsize / BITS_PER_UNIT)
{
! if (bitpos >= BITS_PER_WORD)
{
! word = operand_subword_force (args[i].value, k++, BLKmode);
! bitpos = 0;
! }
! if (xbitpos >= BITS_PER_WORD)
! {
! if (j >= args[i].n_aligned_regs)
! break;
! reg = gen_reg_rtx (word_mode);
! args[i].aligned_regs[j++] = reg;
! emit_move_insn (reg, const0_rtx);
! xbitpos -= BITS_PER_WORD;
}
+ store_bit_field (reg, bitsize, xbitpos, word_mode,
+ extract_bit_field (word, bitsize, bitpos, 1,
+ NULL_RTX, word_mode,
+ word_mode,
+ bitsize / BITS_PER_UNIT,
+ BITS_PER_WORD),
+ bitsize / BITS_PER_UNIT, BITS_PER_WORD);
}
}
More information about the Gcc
mailing list