From mboxrd@z Thu Jan 1 00:00:00 1970 From: Joern Rennecke To: wilson@cygnus.com (Jim Wilson) Cc: egcs@cygnus.com Subject: Re: Applying FUNCTION_ARG_PADDING to register arguments Date: Tue, 28 Oct 1997 12:35:00 -0000 Message-id: <199710281804.SAA18780@phal.cygnus.co.uk> References: <199710240016.RAA27996@cygnus.com> X-SW-Source: 1997-10/msg01196.html > The first problem is that MUST_PASS_IN_STACK macro in expr.h forces BLKmode > arguments to be passed in the stack if the padding is opposite the natural > direction. This is wrong for irix6. In general, MUST_PASS_IN_STACK should > not be overriding FUNCTION_ARG if FUNCTION_ARG says that something is only > passed in registers. This seems to be a relic left over from GCC 1.x. I > suspect that other ports may also be generating incorrect (non ABI compliant) > code because of this. For instance, I noticed that the standard MIPS ABI > support suffers from this bug also. However, at this point, it seems unsafe to > just delete this macro, because that will introduce unexpected and unnecessary > incompatibilites for targets where gcc is the only compiler. Providing a > way for tm.h files to override MUST_PASS_IN_STACK seems the safest way for > now. For now I have just modified expr.h but I don't think this is safe. I have made a patch now that changes MUST_PASS_IN_STACK in expr.h, and sets it back in all egcs ports where it matters, except for the SH, where I know that the old behaviour was reason for a bug. I think this should be safe to install; after that, the individual port maintaines can sort out what they want to do with MUST_PASS_IN_STACK. Tue Oct 28 17:53:05 1997 J"orn Rennecke * expr.h (MUST_PASS_IN_STACK): Don't care about padding. Don't define if already defined. * a29k, arc.h, arm.h, h8300.h, m32r.h (MUST_PASS_IN_STACK): Redefine. * mips.h, pa.h, pyr.h, romp.h, sparc.h (MUST_PASS_IN_STACK): Redefine. Index: expr.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/expr.h,v retrieving revision 1.4 diff -p -r1.4 expr.h *** expr.h 1997/08/29 15:02:03 1.4 --- expr.h 1997/10/28 17:44:58 *************** enum direction {none, upward, downward}; *** 206,231 **** - 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. */ #define MUST_PASS_IN_STACK(MODE,TYPE) \ ((TYPE) != 0 \ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ ! || TREE_ADDRESSABLE (TYPE) \ ! || ((MODE) == BLKmode \ ! && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ ! && 0 == (int_size_in_bytes (TYPE) \ ! % (PARM_BOUNDARY / BITS_PER_UNIT))) \ ! && (FUNCTION_ARG_PADDING (MODE, TYPE) \ ! == (BYTES_BIG_ENDIAN ? upward : downward))))) /* Nonzero if type TYPE should be returned in memory. Most machines can use the following default definition. */ --- 206,234 ---- - if the type has variable size - if the type is marked as addressable (it is required to be constructed into the stack) ! ! There used to be also a padding constraint, but this is no longer ! true: ! - if the padding and mode of the type was such that a copy into a register would put it into the wrong part of the register. ! Which padding couldn't be supported depended 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 couldn't go in a register. ! For a little-endian machine, the reverse was true. ! ! Now, we can store values that come in registers with inconvenient padding ! to memory at the function start. That is important, because some ABIs ! require such register argument passing. */ + #ifndef MUST_PASS_IN_STACK #define MUST_PASS_IN_STACK(MODE,TYPE) \ ((TYPE) != 0 \ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ ! || TREE_ADDRESSABLE (TYPE))) ! #endif /* Nonzero if type TYPE should be returned in memory. Most machines can use the following default definition. */ Index: config/arc/arc.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/arc/arc.h,v retrieving revision 1.1 diff -p -r1.1 arc.h *** arc.h 1997/09/10 07:50:29 1.1 --- arc.h 1997/10/28 17:45:01 *************** enum arc_function_type { *** 1641,1643 **** --- 1641,1659 ---- ((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2) /* Compute the type of a function from its DECL. */ enum arc_function_type arc_compute_function_type (); + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/arm/arm.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/arm/arm.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 arm.h *** arm.h 1997/08/11 15:57:24 1.1.1.1 --- arm.h 1997/10/28 17:45:04 *************** void aof_add_import (/* char * */); *** 2047,2049 **** --- 2047,2065 ---- void aof_delete_import (/* char * */); void aof_dump_imports (/* FILE * */); #endif + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/h8300/h8300.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/h8300/h8300.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 h8300.h *** h8300.h 1997/08/11 15:57:43 1.1.1.1 --- h8300.h 1997/10/28 17:45:07 *************** int h8300_funcvec_function_p (); *** 1397,1399 **** --- 1397,1414 ---- char *output_adds_subs (); char * output_simode_bld (); + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/m32r/m32r.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/m32r/m32r.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 m32r.h *** m32r.h 1997/08/11 15:57:52 1.1.1.1 --- m32r.h 1997/10/28 17:45:10 *************** enum m32r_function_type { *** 1865,1867 **** --- 1865,1883 ---- ((TYPE) == M32R_FUNCTION_INTERRUPT) /* Compute the type of a function from its DECL. */ enum m32r_function_type m32r_compute_function_type (); + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/mips/mips.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/mips/mips.h,v retrieving revision 1.3 diff -p -r1.3 mips.h *** mips.h 1997/09/18 00:31:51 1.3 --- mips.h 1997/10/28 17:45:16 *************** while (0) *** 4046,4048 **** --- 4046,4064 ---- true. */ #define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_ABICALLS && mips_abi != ABI_32) + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/pa/pa.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/pa/pa.h,v retrieving revision 1.4 diff -p -r1.4 pa.h *** pa.h 1997/08/25 15:00:44 1.4 --- pa.h 1997/10/28 17:45:28 *************** do { \ *** 2422,2424 **** --- 2422,2440 ---- /* The number of Pmode words for the setjmp buffer. */ #define JMP_BUF_SIZE 50 + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/pyr/pyr.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/pyr/pyr.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 pyr.h *** pyr.h 1997/08/11 15:57:38 1.1.1.1 --- pyr.h 1997/10/28 17:45:30 *************** extern int swap_operands; *** 1503,1505 **** --- 1503,1521 ---- output_addr_const (FILE, addr); \ } \ } + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/romp/romp.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/romp/romp.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 romp.h *** romp.h 1997/08/11 15:57:21 1.1.1.1 --- romp.h 1997/10/28 17:45:33 *************** extern int romp_debugger_arg_correction( *** 1634,1636 **** --- 1634,1652 ---- extern char *output_in_line_mul (); extern char *output_fpop (); + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/sparc/sparc.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/sparc/sparc.h,v retrieving revision 1.5 diff -p -r1.5 sparc.h *** sparc.h 1997/10/10 22:33:24 1.5 --- sparc.h 1997/10/28 17:45:39 *************** extern char *output_return (); *** 3199,3201 **** --- 3199,3217 ---- /* Defined in flags.h, but insn-emit.c does not include flags.h. */ extern int flag_pic; + + /* This is defined here for strict compatibility with the previous + definition in expr.h. It should probably be checked by someone + who knows what the ABI for this target should exactly be. */ + + #undef MUST_PASS_IN_STACK + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) Index: config/a29k/a29k.h =================================================================== RCS file: /cvs/cvsfiles/egcs/gcc/config/a29k/a29k.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 a29k.h *** a29k.h 1997/08/11 15:57:20 1.1.1.1 --- a29k.h 1997/10/28 17:45:42 *************** extern struct rtx_def *a29k_get_reloaded *** 764,769 **** --- 764,786 ---- #define FUNCTION_ARG_REGNO_P(N) ((N) <= R_LR (17) && (N) >= R_LR (2)) + /* The definition of MUST_PASS_IN_STACK here is solely for the benefit + of the macros in this file itself; since the a29k FUNCTION_ARG will + never return a register when MUST_PASS_IN_STACK is false, there is + no problem with possible double argument passing in registers and + stack. */ + + #define MUST_PASS_IN_STACK(MODE,TYPE) \ + ((TYPE) != 0 \ + && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ + || TREE_ADDRESSABLE (TYPE) \ + || ((MODE) == BLKmode \ + && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && 0 == (int_size_in_bytes (TYPE) \ + % (PARM_BOUNDARY / BITS_PER_UNIT))) \ + && (FUNCTION_ARG_PADDING (MODE, TYPE) \ + == (BYTES_BIG_ENDIAN ? upward : downward))))) + /* Define a data type for recording info about an argument list during the scan of that argument list. This data type should hold all necessary information about the function itself