Commit a7f875d7 by Richard Kenner

(expand_return): Correctly handle returning BLKmode structures in registers when...

(expand_return): Correctly handle returning BLKmode structures in
registers when the size of the structure is not a multiple of
word_size.

From-SVN: r10052
parent 1b5c5873
...@@ -2722,52 +2722,61 @@ expand_return (retval) ...@@ -2722,52 +2722,61 @@ expand_return (retval)
&& TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
&& GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG) && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG)
{ {
int i; int i, bitpos, xbitpos;
int big_endian_correction = 0; int big_endian_correction = 0;
int bytes = int_size_in_bytes (TREE_TYPE (retval_rhs)); int bytes = int_size_in_bytes (TREE_TYPE (retval_rhs));
int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)),BITS_PER_WORD);
rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs); rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
rtx result_reg; rtx result_reg, src, dst;
rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0); rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
enum machine_mode tmpmode, result_reg_mode; enum machine_mode tmpmode, result_reg_mode;
/* Structures smaller than a word are aligned to the least significant /* Structures whose size is not a multiple of a word are aligned
byte (to the right). On a BYTES_BIG_ENDIAN machine, this means we to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
must skip the empty high order bytes when calculating the bit machine, this means we must skip the empty high order bytes when
offset. */ calculating the bit offset. */
if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD) if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT)); big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
* BITS_PER_UNIT));
for (i = 0; i < n_regs; i++)
{ /* Copy the structure BITSIZE bits at a time. */
rtx reg = gen_reg_rtx (word_mode); for (bitpos = 0, xbitpos = big_endian_correction;
rtx word = operand_subword_force (result_val, i, BLKmode); bitpos < bytes * BITS_PER_UNIT;
int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)),BITS_PER_WORD); bitpos += bitsize, xbitpos += bitsize)
int bitpos; {
/* We need a new destination pseudo each time xbitpos is
result_pseudos[i] = reg; on a word boundary and when xbitpos == big_endian_corrction
(the first time through). */
/* Clobber REG and move each partword into it. Ensure we don't if (xbitpos % BITS_PER_WORD == 0
go past the end of the structure. Note that the loop below || xbitpos == big_endian_correction)
works because we've already verified that padding and {
endianness are compatible. */ /* Generate an appropriate register. */
emit_insn (gen_rtx (CLOBBER, VOIDmode, reg)); dst = gen_reg_rtx (word_mode);
result_pseudos[xbitpos / BITS_PER_WORD] = dst;
for (bitpos = 0;
bitpos < BITS_PER_WORD && bytes > 0; /* Clobber the destination before we move anything into it. */
bitpos += bitsize, bytes -= bitsize / BITS_PER_UNIT) emit_insn (gen_rtx (CLOBBER, VOIDmode, dst));
{ }
int xbitpos = bitpos + big_endian_correction;
/* We need a new source operand each time bitpos is on a word
store_bit_field (reg, bitsize, xbitpos, word_mode, boundary. */
extract_bit_field (word, bitsize, bitpos, 1, if (bitpos % BITS_PER_WORD == 0)
src = operand_subword_force (result_val,
bitpos / BITS_PER_WORD,
BLKmode);
/* Use bitpos for the source extraction (left justified) and
xbitpos for the destination store (right justified). */
store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode,
extract_bit_field (src, bitsize,
bitpos % BITS_PER_WORD, 1,
NULL_RTX, word_mode, NULL_RTX, word_mode,
word_mode, word_mode,
bitsize / BITS_PER_UNIT, bitsize / BITS_PER_UNIT,
BITS_PER_WORD), BITS_PER_WORD),
bitsize / BITS_PER_UNIT, BITS_PER_WORD); bitsize / BITS_PER_UNIT, BITS_PER_WORD);
} }
}
/* Find the smallest integer mode large enough to hold the /* Find the smallest integer mode large enough to hold the
entire structure and use that mode instead of BLKmode entire structure and use that mode instead of BLKmode
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment