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
This commit is contained in:
parent
20cbfac4e9
commit
ef6843ed0b
2 changed files with 90 additions and 76 deletions
|
@ -1,3 +1,13 @@
|
|||
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>
|
||||
|
||||
* dwarf2out.c (premark_used_types): Remove problematic prototype.
|
||||
|
|
|
@ -4559,7 +4559,10 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
|
|||
|
||||
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)
|
||||
return -1;
|
||||
|
@ -5073,45 +5076,19 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
|
|||
: SPARC_OUTGOING_INT_ARG_FIRST);
|
||||
int slotno, regno, padding;
|
||||
enum mode_class mclass = GET_MODE_CLASS (mode);
|
||||
rtx reg;
|
||||
|
||||
slotno = function_arg_slotno (cum, mode, type, named, incoming_p,
|
||||
®no, &padding);
|
||||
|
||||
if (slotno == -1)
|
||||
return 0;
|
||||
|
||||
if (TARGET_ARCH32)
|
||||
{
|
||||
reg = gen_rtx_REG (mode, regno);
|
||||
return reg;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return function_arg_record_value (type, mode, slotno, named, regbase);
|
||||
}
|
||||
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. */
|
||||
if (type && TREE_CODE (type) == VECTOR_TYPE)
|
||||
{
|
||||
HOST_WIDE_INT size = int_size_in_bytes (type);
|
||||
|
||||
gcc_assert (size <= 16);
|
||||
|
||||
return function_arg_union_value (size, mode, slotno, regno);
|
||||
}
|
||||
else 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);
|
||||
|
||||
gcc_assert (size <= 16);
|
||||
gcc_assert ((TARGET_ARCH32 && size <= 8)
|
||||
|| (TARGET_ARCH64 && size <= 16));
|
||||
|
||||
if (mode == BLKmode)
|
||||
return function_arg_vector_value (size,
|
||||
|
@ -5121,14 +5098,36 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
|
|||
mclass = MODE_FLOAT;
|
||||
}
|
||||
|
||||
if (TARGET_ARCH32)
|
||||
return gen_rtx_REG (mode, regno);
|
||||
|
||||
/* Structures up to 16 bytes in size are passed in arg slots on the stack
|
||||
and are promoted to registers if possible. */
|
||||
if (type && TREE_CODE (type) == RECORD_TYPE)
|
||||
{
|
||||
HOST_WIDE_INT size = int_size_in_bytes (type);
|
||||
gcc_assert (size <= 16);
|
||||
|
||||
return function_arg_record_value (type, mode, slotno, named, regbase);
|
||||
}
|
||||
|
||||
/* Unions up to 16 bytes in size are passed in integer registers. */
|
||||
else if (type && TREE_CODE (type) == UNION_TYPE)
|
||||
{
|
||||
HOST_WIDE_INT size = int_size_in_bytes (type);
|
||||
gcc_assert (size <= 16);
|
||||
|
||||
return function_arg_union_value (size, mode, slotno, regno);
|
||||
}
|
||||
|
||||
/* v9 fp args in reg slots beyond the int reg slots get passed in regs
|
||||
but also have the slot allocated for them.
|
||||
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. */
|
||||
if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
|
||||
&& SPARC_FP_REG_P (regno))
|
||||
else if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
|
||||
&& 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)
|
||||
{
|
||||
/* "* 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,
|
|||
}
|
||||
}
|
||||
}
|
||||
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. */
|
||||
reg = gen_rtx_REG (mode, regno);
|
||||
HOST_WIDE_INT size = int_size_in_bytes (type);
|
||||
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,
|
||||
|
@ -5271,7 +5275,6 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
|
|||
bool named ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (TARGET_ARCH32)
|
||||
{
|
||||
/* Original SPARC 32-bit ABI says that structures and unions,
|
||||
and quad-precision floats are passed by reference. For Pascal,
|
||||
also pass arrays by reference. All other base types are passed
|
||||
|
@ -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
|
||||
registers up to 8 bytes. Pass all vector floats by reference
|
||||
like structure and unions. */
|
||||
return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
|
||||
|| mode == SCmode
|
||||
/* Catch CDImode, TFmode, DCmode and TCmode. */
|
||||
|| GET_MODE_SIZE (mode) > 8
|
||||
|| (type
|
||||
&& TREE_CODE (type) == VECTOR_TYPE
|
||||
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
|
||||
}
|
||||
return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
|
||||
|| mode == SCmode
|
||||
/* Catch CDImode, TFmode, DCmode and TCmode. */
|
||||
|| GET_MODE_SIZE (mode) > 8
|
||||
|| (type
|
||||
&& TREE_CODE (type) == VECTOR_TYPE
|
||||
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
|
||||
else
|
||||
{
|
||||
/* Original SPARC 64-bit ABI says that structures and unions
|
||||
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
|
||||
complex floats are passed in registers up to 16 bytes. Pass
|
||||
|
@ -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
|
||||
registers (up to 16 bytes). Pass all vector floats like structure
|
||||
and unions. */
|
||||
return ((type && TREE_CODE (type) == ARRAY_TYPE)
|
||||
|| (type
|
||||
&& (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
|
||||
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
|
||||
/* Catch CTImode and TCmode. */
|
||||
|| GET_MODE_SIZE (mode) > 16);
|
||||
}
|
||||
return ((type
|
||||
&& (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
|
||||
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
|
||||
/* Catch CTImode and TCmode. */
|
||||
|| GET_MODE_SIZE (mode) > 16);
|
||||
}
|
||||
|
||||
/* Handle the FUNCTION_ARG_ADVANCE macro.
|
||||
|
@ -5499,13 +5498,11 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
|
|||
enum mode_class mclass = GET_MODE_CLASS (mode);
|
||||
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)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
gcc_assert ((TARGET_ARCH32 && size <= 8)
|
||||
|| (TARGET_ARCH64 && size <= 32));
|
||||
|
||||
|
@ -5516,34 +5513,41 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
|
|||
else
|
||||
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)
|
||||
{
|
||||
/* Structures up to 32 bytes in size are passed in registers,
|
||||
promoted to fp registers where possible. */
|
||||
|
||||
gcc_assert (int_size_in_bytes (type) <= 32);
|
||||
HOST_WIDE_INT size = int_size_in_bytes (type);
|
||||
gcc_assert (size <= 32);
|
||||
|
||||
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)
|
||||
{
|
||||
HOST_WIDE_INT size = int_size_in_bytes (type);
|
||||
|
||||
gcc_assert (size <= 32);
|
||||
|
||||
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))
|
||||
{
|
||||
/* All other aggregate types are passed in an integer register
|
||||
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
|
||||
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)
|
|||
try to be unduly clever, and simply follow the ABI
|
||||
for unions in that case. */
|
||||
if (mode == BLKmode)
|
||||
return function_arg_union_value (bytes, mode, 0, regbase);
|
||||
return function_arg_union_value (size, mode, 0, regbase);
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
|
||||
&& TARGET_FPU)
|
||||
if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && TARGET_FPU)
|
||||
regno = SPARC_FP_ARG_FIRST;
|
||||
else
|
||||
regno = regbase;
|
||||
|
|
Loading…
Add table
Reference in a new issue