Commit ef6843ed by Eric Botcazou Committed by Eric Botcazou

sparc.c (function_arg_slotno): Handle aggregate types other than record and union types.

	* config/sparc/sparc.c (function_arg_slotno) <BLKmode>: Handle
	aggregate types other than record and union types.
	(function_arg): Likewise.
	(function_arg_pass_by_reference): In 64-bit mode, return 0 for
	small arrays.
	(function_value): In 64-bit mode, return objects that require it
	in FP registers.

From-SVN: r112859
parent 20cbfac4
2006-04-11 Eric Botcazou <ebotcazou@libertysurf.fr>
* config/sparc/sparc.c (function_arg_slotno) <BLKmode>: Handle
aggregate types other than record and union types.
(function_arg): Likewise.
(function_arg_pass_by_reference): In 64-bit mode, return 0 for
small arrays.
(function_value): In 64-bit mode, return objects that require it
in FP registers.
2006-04-11 Roger Sayle <roger@eyesopen.com> 2006-04-11 Roger Sayle <roger@eyesopen.com>
* dwarf2out.c (premark_used_types): Remove problematic prototype. * dwarf2out.c (premark_used_types): Remove problematic prototype.
......
...@@ -4559,7 +4559,10 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode, ...@@ -4559,7 +4559,10 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
gcc_assert (mode == BLKmode); gcc_assert (mode == BLKmode);
if (TARGET_ARCH32 || !type || (TREE_CODE (type) == UNION_TYPE)) if (TARGET_ARCH32
|| !type
|| (TREE_CODE (type) != VECTOR_TYPE
&& TREE_CODE (type) != RECORD_TYPE))
{ {
if (slotno >= SPARC_INT_ARG_MAX) if (slotno >= SPARC_INT_ARG_MAX)
return -1; return -1;
...@@ -5073,62 +5076,58 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode, ...@@ -5073,62 +5076,58 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
: SPARC_OUTGOING_INT_ARG_FIRST); : SPARC_OUTGOING_INT_ARG_FIRST);
int slotno, regno, padding; int slotno, regno, padding;
enum mode_class mclass = GET_MODE_CLASS (mode); enum mode_class mclass = GET_MODE_CLASS (mode);
rtx reg;
slotno = function_arg_slotno (cum, mode, type, named, incoming_p, slotno = function_arg_slotno (cum, mode, type, named, incoming_p,
&regno, &padding); &regno, &padding);
if (slotno == -1) if (slotno == -1)
return 0; return 0;
if (TARGET_ARCH32) /* Vector types deserve special treatment because they are polymorphic wrt
their mode, depending upon whether VIS instructions are enabled. */
if (type && TREE_CODE (type) == VECTOR_TYPE)
{ {
reg = gen_rtx_REG (mode, regno); HOST_WIDE_INT size = int_size_in_bytes (type);
return reg; gcc_assert ((TARGET_ARCH32 && size <= 8)
|| (TARGET_ARCH64 && size <= 16));
if (mode == BLKmode)
return function_arg_vector_value (size,
TYPE_MODE (TREE_TYPE (type)),
SPARC_FP_ARG_FIRST + 2*slotno);
else
mclass = MODE_FLOAT;
} }
if (type && TREE_CODE (type) == RECORD_TYPE)
{
/* Structures up to 16 bytes in size are passed in arg slots on the
stack and are promoted to registers where possible. */
gcc_assert (int_size_in_bytes (type) <= 16); if (TARGET_ARCH32)
return gen_rtx_REG (mode, regno);
return function_arg_record_value (type, mode, slotno, named, regbase); /* Structures up to 16 bytes in size are passed in arg slots on the stack
} and are promoted to registers if possible. */
else if (type && TREE_CODE (type) == UNION_TYPE) if (type && TREE_CODE (type) == RECORD_TYPE)
{ {
HOST_WIDE_INT size = int_size_in_bytes (type); HOST_WIDE_INT size = int_size_in_bytes (type);
gcc_assert (size <= 16); gcc_assert (size <= 16);
return function_arg_union_value (size, mode, slotno, regno); return function_arg_record_value (type, mode, slotno, named, regbase);
} }
else if (type && TREE_CODE (type) == VECTOR_TYPE)
/* Unions up to 16 bytes in size are passed in integer registers. */
else if (type && TREE_CODE (type) == UNION_TYPE)
{ {
/* Vector types deserve special treatment because they are
polymorphic wrt their mode, depending upon whether VIS
instructions are enabled. */
HOST_WIDE_INT size = int_size_in_bytes (type); HOST_WIDE_INT size = int_size_in_bytes (type);
gcc_assert (size <= 16); gcc_assert (size <= 16);
if (mode == BLKmode) return function_arg_union_value (size, mode, slotno, regno);
return function_arg_vector_value (size,
TYPE_MODE (TREE_TYPE (type)),
SPARC_FP_ARG_FIRST + 2*slotno);
else
mclass = MODE_FLOAT;
} }
/* v9 fp args in reg slots beyond the int reg slots get passed in regs /* v9 fp args in reg slots beyond the int reg slots get passed in regs
but also have the slot allocated for them. but also have the slot allocated for them.
If no prototype is in scope fp values in register slots get passed If no prototype is in scope fp values in register slots get passed
in two places, either fp regs and int regs or fp regs and memory. */ in two places, either fp regs and int regs or fp regs and memory. */
if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) else if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
&& SPARC_FP_REG_P (regno)) && SPARC_FP_REG_P (regno))
{ {
reg = gen_rtx_REG (mode, regno); rtx reg = gen_rtx_REG (mode, regno);
if (cum->prototype_p || cum->libcall_p) if (cum->prototype_p || cum->libcall_p)
{ {
/* "* 2" because fp reg numbers are recorded in 4 byte /* "* 2" because fp reg numbers are recorded in 4 byte
...@@ -5189,13 +5188,18 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode, ...@@ -5189,13 +5188,18 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
} }
} }
} }
else
/* All other aggregate types are passed in an integer register in a mode
corresponding to the size of the type. */
else if (type && AGGREGATE_TYPE_P (type))
{ {
/* Scalar or complex int. */ HOST_WIDE_INT size = int_size_in_bytes (type);
reg = gen_rtx_REG (mode, regno); gcc_assert (size <= 16);
mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
} }
return reg; return gen_rtx_REG (mode, regno);
} }
/* For an arg passed partly in registers and partly in memory, /* For an arg passed partly in registers and partly in memory,
...@@ -5271,7 +5275,6 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, ...@@ -5271,7 +5275,6 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED) bool named ATTRIBUTE_UNUSED)
{ {
if (TARGET_ARCH32) if (TARGET_ARCH32)
{
/* Original SPARC 32-bit ABI says that structures and unions, /* Original SPARC 32-bit ABI says that structures and unions,
and quad-precision floats are passed by reference. For Pascal, and quad-precision floats are passed by reference. For Pascal,
also pass arrays by reference. All other base types are passed also pass arrays by reference. All other base types are passed
...@@ -5286,19 +5289,17 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, ...@@ -5286,19 +5289,17 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
integers are passed like floats of the same size, that is in integers are passed like floats of the same size, that is in
registers up to 8 bytes. Pass all vector floats by reference registers up to 8 bytes. Pass all vector floats by reference
like structure and unions. */ like structure and unions. */
return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type))) return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
|| mode == SCmode || mode == SCmode
/* Catch CDImode, TFmode, DCmode and TCmode. */ /* Catch CDImode, TFmode, DCmode and TCmode. */
|| GET_MODE_SIZE (mode) > 8 || GET_MODE_SIZE (mode) > 8
|| (type || (type
&& TREE_CODE (type) == VECTOR_TYPE && TREE_CODE (type) == VECTOR_TYPE
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8)); && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
}
else else
{
/* Original SPARC 64-bit ABI says that structures and unions /* Original SPARC 64-bit ABI says that structures and unions
smaller than 16 bytes are passed in registers, as well as smaller than 16 bytes are passed in registers, as well as
all other base types. For Pascal, pass arrays by reference. all other base types.
Extended ABI (as implemented by the Sun compiler) says that Extended ABI (as implemented by the Sun compiler) says that
complex floats are passed in registers up to 16 bytes. Pass complex floats are passed in registers up to 16 bytes. Pass
...@@ -5309,13 +5310,11 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, ...@@ -5309,13 +5310,11 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
integers are passed like floats of the same size, that is in integers are passed like floats of the same size, that is in
registers (up to 16 bytes). Pass all vector floats like structure registers (up to 16 bytes). Pass all vector floats like structure
and unions. */ and unions. */
return ((type && TREE_CODE (type) == ARRAY_TYPE) return ((type
|| (type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
&& (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE) && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16) /* Catch CTImode and TCmode. */
/* Catch CTImode and TCmode. */ || GET_MODE_SIZE (mode) > 16);
|| GET_MODE_SIZE (mode) > 16);
}
} }
/* Handle the FUNCTION_ARG_ADVANCE macro. /* Handle the FUNCTION_ARG_ADVANCE macro.
...@@ -5499,13 +5498,11 @@ function_value (tree type, enum machine_mode mode, int incoming_p) ...@@ -5499,13 +5498,11 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
enum mode_class mclass = GET_MODE_CLASS (mode); enum mode_class mclass = GET_MODE_CLASS (mode);
int regno; int regno;
/* Vector types deserve special treatment because they are polymorphic wrt
their mode, depending upon whether VIS instructions are enabled. */
if (type && TREE_CODE (type) == VECTOR_TYPE) if (type && TREE_CODE (type) == VECTOR_TYPE)
{ {
/* Vector types deserve special treatment because they are
polymorphic wrt their mode, depending upon whether VIS
instructions are enabled. */
HOST_WIDE_INT size = int_size_in_bytes (type); HOST_WIDE_INT size = int_size_in_bytes (type);
gcc_assert ((TARGET_ARCH32 && size <= 8) gcc_assert ((TARGET_ARCH32 && size <= 8)
|| (TARGET_ARCH64 && size <= 32)); || (TARGET_ARCH64 && size <= 32));
...@@ -5516,34 +5513,41 @@ function_value (tree type, enum machine_mode mode, int incoming_p) ...@@ -5516,34 +5513,41 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
else else
mclass = MODE_FLOAT; mclass = MODE_FLOAT;
} }
else if (type && TARGET_ARCH64)
if (TARGET_ARCH64 && type)
{ {
/* Structures up to 32 bytes in size are returned in registers. */
if (TREE_CODE (type) == RECORD_TYPE) if (TREE_CODE (type) == RECORD_TYPE)
{ {
/* Structures up to 32 bytes in size are passed in registers, HOST_WIDE_INT size = int_size_in_bytes (type);
promoted to fp registers where possible. */ gcc_assert (size <= 32);
gcc_assert (int_size_in_bytes (type) <= 32);
return function_arg_record_value (type, mode, 0, 1, regbase); return function_arg_record_value (type, mode, 0, 1, regbase);
} }
/* Unions up to 32 bytes in size are returned in integer registers. */
else if (TREE_CODE (type) == UNION_TYPE) else if (TREE_CODE (type) == UNION_TYPE)
{ {
HOST_WIDE_INT size = int_size_in_bytes (type); HOST_WIDE_INT size = int_size_in_bytes (type);
gcc_assert (size <= 32); gcc_assert (size <= 32);
return function_arg_union_value (size, mode, 0, regbase); return function_arg_union_value (size, mode, 0, regbase);
} }
/* Objects that require it are returned in FP registers. */
else if (mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
;
/* All other aggregate types are returned in an integer register in a
mode corresponding to the size of the type. */
else if (AGGREGATE_TYPE_P (type)) else if (AGGREGATE_TYPE_P (type))
{ {
/* All other aggregate types are passed in an integer register /* All other aggregate types are passed in an integer register
in a mode corresponding to the size of the type. */ in a mode corresponding to the size of the type. */
HOST_WIDE_INT bytes = int_size_in_bytes (type); HOST_WIDE_INT size = int_size_in_bytes (type);
gcc_assert (size <= 32);
gcc_assert (bytes <= 32);
mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0); mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
/* ??? We probably should have made the same ABI change in /* ??? We probably should have made the same ABI change in
3.4.0 as the one we made for unions. The latter was 3.4.0 as the one we made for unions. The latter was
...@@ -5555,17 +5559,17 @@ function_value (tree type, enum machine_mode mode, int incoming_p) ...@@ -5555,17 +5559,17 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
try to be unduly clever, and simply follow the ABI try to be unduly clever, and simply follow the ABI
for unions in that case. */ for unions in that case. */
if (mode == BLKmode) if (mode == BLKmode)
return function_arg_union_value (bytes, mode, 0, regbase); return function_arg_union_value (size, mode, 0, regbase);
else else
mclass = MODE_INT; mclass = MODE_INT;
} }
else if (mclass == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD) /* This must match PROMOTE_FUNCTION_MODE. */
else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
mode = word_mode; mode = word_mode;
} }
if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && TARGET_FPU)
&& TARGET_FPU)
regno = SPARC_FP_ARG_FIRST; regno = SPARC_FP_ARG_FIRST;
else else
regno = regbase; regno = regbase;
......
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