rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.

* config/rs6000/rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.
	(USE_ALTIVEC_FOR_ARG_P): Likewise.
	* config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Move from rs6000.h.
	Take a pointer as the CUM parameter.  Update callers.
	(USE_ALTIVEC_FOR_ARG_P): Likewise.  Also correct for Darwin/AIX
	32-bit ABIs.
	(function_arg_advance): Use USE_ALTIVEC_FOR_ARG_P.  Correct case
	of vector parameters as named arguments of stdarg function.
	(function_arg): Likewise.

	* config/rs6000/darwin.h (ASM_SPEC): Use -force_cpusubtype_ALL when
	-maltivec is specified, not the non-existent -faltivec.

From-SVN: r73317
This commit is contained in:
Geoffrey Keating 2003-11-06 21:52:36 +00:00 committed by Geoffrey Keating
parent 8c17530ef3
commit 2858f73ac1
6 changed files with 152 additions and 43 deletions

View File

@ -1,3 +1,18 @@
2003-11-06 Geoffrey Keating <geoffk@apple.com>
* config/rs6000/rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.
(USE_ALTIVEC_FOR_ARG_P): Likewise.
* config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Move from rs6000.h.
Take a pointer as the CUM parameter. Update callers.
(USE_ALTIVEC_FOR_ARG_P): Likewise. Also correct for Darwin/AIX
32-bit ABIs.
(function_arg_advance): Use USE_ALTIVEC_FOR_ARG_P. Correct case
of vector parameters as named arguments of stdarg function.
(function_arg): Likewise.
* config/rs6000/darwin.h (ASM_SPEC): Use -force_cpusubtype_ALL when
-maltivec is specified, not the non-existent -faltivec.
2003-11-06 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390-protos.h (s390_function_value): Declare.

View File

@ -100,7 +100,7 @@ do { \
#define ASM_SPEC "-arch ppc \
%{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
%{!Zforce_cpusubtype_ALL:%{faltivec:-force_cpusubtype_ALL}}"
%{!Zforce_cpusubtype_ALL:%{maltivec:-force_cpusubtype_ALL}}"
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \

View File

@ -3618,6 +3618,19 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
}
/* Nonzero if we can use a floating-point register to pass this arg. */
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
&& (CUM)->fregno <= FP_ARG_MAX_REG \
&& TARGET_HARD_FLOAT && TARGET_FPRS)
/* Nonzero if we can use an AltiVec register to pass this arg. */
#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
(ALTIVEC_VECTOR_MODE (MODE) \
&& (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
&& TARGET_ALTIVEC_ABI \
&& (DEFAULT_ABI == ABI_V4 || (NAMED)))
/* Return a nonzero value to say to return the function value in
memory, just as large structures are always returned. TYPE will be
the data type of the value, and FNTYPE will be the type of the
@ -3802,23 +3815,35 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
{
if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
cum->vregno++;
else
/* In variable-argument functions, vector arguments get GPRs allocated
even if they are going to be passed in a vector register. */
if (cum->stdarg && DEFAULT_ABI != ABI_V4)
{
int align;
/* Vector parameters must be 16-byte aligned. This places them at
2 mod 4 in terms of words (on both ABIs). */
align = ((6 - (cum->words & 3)) & 3);
/* Vector parameters must be 16-byte aligned. This places
them at 2 mod 4 in terms of words in 32-bit mode, since
the parameter save area starts at offset 24 from the
stack. In 64-bit mode, they just have to start on an
even word, since the parameter save area is 16-byte
aligned. Space for GPRs is reserved even if the argument
will be passed in memory. */
if (TARGET_32BIT)
align = ((6 - (cum->words & 3)) & 3);
else
align = cum->words & 1;
cum->words += align + RS6000_ARG_SIZE (mode, type);
if (TARGET_DEBUG_ARG)
{
fprintf (stderr, "function_adv: words = %2d, align=%d, ",
cum->words, align);
fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n",
cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
cum->nargs_prototype, cum->prototype,
GET_MODE_NAME (mode));
}
}
}
@ -4099,40 +4124,43 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return GEN_INT (cum->call_cookie);
}
if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
return gen_rtx_REG (mode, cum->vregno);
else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
{
if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
return gen_rtx_REG (mode, cum->vregno);
else if (named || abi == ABI_V4)
if (named || abi == ABI_V4)
return NULL_RTX;
else
{
/* Vector parameters to varargs functions under AIX or Darwin
get passed in memory and possibly also in GPRs. */
int align, align_words;
rtx reg;
enum machine_mode part_mode = mode;
/* Vector parameters must be 16-byte aligned. This places them at
2 mod 4 in terms of words. */
align = ((6 - (cum->words & 3)) & 3);
2 mod 4 in terms of words in 32-bit mode, since the parameter
save area starts at offset 24 from the stack. In 64-bit mode,
they just have to start on an even word, since the parameter
save area is 16-byte aligned. */
if (TARGET_32BIT)
align = ((6 - (cum->words & 3)) & 3);
else
align = cum->words & 1;
align_words = cum->words + align;
/* Out of registers? Memory, then. */
if (align_words >= GP_ARG_NUM_REG)
return NULL_RTX;
/* The vector value goes in both memory and GPRs. Varargs
vector regs will always be saved in R5-R8 or R9-R12. */
reg = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
return gen_rtx_PARALLEL (mode,
gen_rtvec (2,
gen_rtx_EXPR_LIST (VOIDmode,
NULL_RTX,
const0_rtx),
gen_rtx_EXPR_LIST (VOIDmode,
reg,
const0_rtx)));
/* The vector value goes in GPRs. Only the part of the
value in GPRs is reported here. */
if (align_words + CLASS_MAX_NREGS (mode, GENERAL_REGS)
> GP_ARG_NUM_REG)
/* Fortunately, there are only two possibilites, the value
is either wholly in GPRs or half in GPRs and half not. */
part_mode = DImode;
return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
}
}
else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
@ -4183,7 +4211,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
&& (mode == DFmode || mode == DImode || mode == BLKmode))
return rs6000_mixed_function_arg (cum, mode, type, align_words);
if (USE_FP_FOR_ARG_P (*cum, mode, type))
if (USE_FP_FOR_ARG_P (cum, mode, type))
{
if (! type
|| ((cum->nargs_prototype > 0)
@ -4228,13 +4256,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
int
function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named ATTRIBUTE_UNUSED)
tree type, int named)
{
if (DEFAULT_ABI == ABI_V4)
return 0;
if (USE_FP_FOR_ARG_P (*cum, mode, type)
|| USE_ALTIVEC_FOR_ARG_P (*cum, mode, type))
if (USE_FP_FOR_ARG_P (cum, mode, type)
|| USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
{
if (cum->nargs_prototype >= 0)
return 0;

View File

@ -1800,18 +1800,6 @@ typedef struct rs6000_args
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
function_arg_advance (&CUM, MODE, TYPE, NAMED)
/* Nonzero if we can use a floating-point register to pass this arg. */
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
&& (CUM).fregno <= FP_ARG_MAX_REG \
&& TARGET_HARD_FLOAT && TARGET_FPRS)
/* Nonzero if we can use an AltiVec register to pass this arg. */
#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE) \
(ALTIVEC_VECTOR_MODE (MODE) \
&& (CUM).vregno <= ALTIVEC_ARG_MAX_REG \
&& TARGET_ALTIVEC_ABI)
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.

View File

@ -1,3 +1,7 @@
2003-11-06 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/altivec-varargs-1.c: New test.
2003-11-05 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.c-torture/compile/20031023-4.c: XFAIL on SPARC64

View File

@ -0,0 +1,74 @@
/* { dg-do run { target powerpc*-*-darwin* powerpc*-*-*altivec* } } */
/* { dg-options "-maltivec" } */
/* This test requires altivec, which means it'll fail on Darwin running
on G3. FIXME. */
#include <stdarg.h>
#define vector __attribute__((mode(V4SI)))
const vector unsigned int v1 = {10,11,12,13};
const vector unsigned int v2 = {20,21,22,23};
const vector unsigned int v3 = {30,31,32,33};
const vector unsigned int v4 = {40,41,42,43};
void foo(vector unsigned int a, ...)
{
va_list args;
vector unsigned int v;
va_start (args, a);
if (memcmp (&a, &v1, sizeof (v)) != 0)
abort ();
v = va_arg (args, vector unsigned int);
if (memcmp (&v, &v2, sizeof (v)) != 0)
abort ();
v = va_arg (args, vector unsigned int);
if (memcmp (&v, &v3, sizeof (v)) != 0)
abort ();
v = va_arg (args, vector unsigned int);
if (memcmp (&v, &v4, sizeof (v)) != 0)
abort ();
va_end (args);
}
void bar(vector unsigned int a, ...)
{
va_list args;
vector unsigned int v;
int b;
va_start (args, a);
if (memcmp (&a, &v1, sizeof (v)) != 0)
abort ();
b = va_arg (args, int);
if (b != 2)
abort ();
v = va_arg (args, vector unsigned int);
if (memcmp (&v, &v2, sizeof (v)) != 0)
abort ();
v = va_arg (args, vector unsigned int);
if (memcmp (&v, &v3, sizeof (v)) != 0)
abort ();
va_end (args);
}
int main(void)
{
/* In this call, in the Darwin ABI, the first argument goes into v2
the second one into r9-r10 and memory,
and the next two in memory. */
foo ((vector unsigned int){10,11,12,13},
(vector unsigned int){20,21,22,23},
(vector unsigned int){30,31,32,33},
(vector unsigned int){40,41,42,43});
/* In this call, in the Darwin ABI, the first argument goes into v2
the second one into r9, then r10 is reserved and
there are two words of padding in memory, and the next two arguments
go after the padding. */
bar ((vector unsigned int){10,11,12,13}, 2,
(vector unsigned int){20,21,22,23},
(vector unsigned int){30,31,32,33});
return 0;
}