This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
A change to MUST_PASS_IN_STACK
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 10 Jan 2003 19:50:31 +1030
- Subject: A change to MUST_PASS_IN_STACK
I'd like to modify MUST_PASS_IN_STACK to accept another parameter.
Reason: No account is taken of arguments passed partially in registers
and partially on the stack. In that case you can't put anything in
"the wrong part of the register" on big-endian machines.
The attached testcase illustrates what I'm talking about on
powerpc64-linux. With a compiler modified to avoid the bug in
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg00508.html, I get:
(sizeof str1 == 60) (sizeof str1 == 64) (sizeof str1 == 60, fixed)
.main: .main: .main:
mflr 0 mflr 0 mflr 0
li 9,5678 li 9,5678 li 11,5678
std 0,16(1) std 0,16(1) std 0,16(1)
li 5,68 li 0,1234 li 0,1234
li 0,1234 stdu 1,-208(1) stdu 1,-208(1)
stdu 1,-208(1) stw 9,188(1) stw 0,120(1)
addi 4,1,120 stw 0,120(1) li 0,5678
addi 3,1,48 lfd 0,184(1) ld 3,120(1)
stw 0,120(1) ld 3,120(1) ld 4,128(1)
stw 9,184(1) ld 4,128(1) ld 5,136(1)
bl .memcpy ld 5,136(1) ld 6,144(1)
nop ld 6,144(1) ld 7,152(1)
ld 3,48(1) ld 7,152(1) ld 8,160(1)
ld 4,56(1) ld 8,160(1) ld 9,168(1)
ld 5,64(1) ld 9,168(1) ld 10,176(1)
ld 6,72(1) ld 10,176(1) stw 0,184(1)
ld 7,80(1) stfd 0,112(1) stw 11,112(1)
ld 8,88(1) bl .subr bl .subr
ld 9,96(1) nop nop
ld 10,104(1) addi 1,1,208 addi 1,1,208
bl .subr li 3,0 li 3,0
nop ld 0,16(1) ld 0,16(1)
addi 1,1,208 mtlr 0 mtlr 0
li 3,0 blr blr
ld 0,16(1)
mtlr 0
blr
Note how we unnecessarily copy the entire struct in the lefthand
column when MUST_PASS_IN_STACK triggers due to padding, and avoid
writing to fixed parameter area in the middle column when the
struct bitsize is a multiple of PARM_BOUNDARY. The rightmost column
shows what I'd like to get for sizeof str1 == 60 (and in fact what I
do get after modifying MUST_PASS_IN_STACK).
Rather than spam the list with a large patch tweaking all occurences
of the macro, I thought I'd first seek approval in principle. The
changed macro looks like the following.
/* Nonzero if we must pass TYPE on the stack.
We cannot do so in the following cases:
- if the type has variable size
- if the type is marked as addressable (it is required to be constructed
into the stack)
- if the padding and mode of the type is such that a copy into a register
would put it into the wrong part of the register.
Which padding can't be supported depends on the byte endianness.
A value in a register is implicitly padded at the most significant end.
On a big-endian machine, that is the lower end in memory.
So a value padded in memory at the upper end can't go in a register.
For a little-endian machine, the reverse is true.
Padding is irrelevant when big-endian if TYPE will be passed partially
in registers and partially on the stack as indicated by PART. This is
because any padding at the upper end will go on the stack anyway. */
#ifndef MUST_PASS_IN_STACK
#define MUST_PASS_IN_STACK(MODE, TYPE, PART) \
((TYPE) != 0 \
&& (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
|| TREE_ADDRESSABLE (TYPE) \
|| ((MODE) == BLKmode \
&& ((PART) == 0 || !BYTES_BIG_ENDIAN) \
&& (int_size_in_bytes (TYPE) \
% (PARM_BOUNDARY / BITS_PER_UNIT)) != 0 \
&& (FUNCTION_ARG_PADDING (MODE, TYPE) \
== (BYTES_BIG_ENDIAN ? upward : downward)))))
#endif
So, is it worth posting the patch or should I try something different?
--
Alan Modra
IBM OzLabs - Linux Technology Centre