aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2006-04-11 18:25:46 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2006-04-11 16:25:46 +0000
commitef6843ed0b1a7caf04be629d1dac079e48aa048e (patch)
tree473c6698ddb98834e8855bb71655e69829762bc1
parent20cbfac4e95d090a361db413209a1545ca058342 (diff)
downloadgcc-ef6843ed0b1a7caf04be629d1dac079e48aa048e.zip
gcc-ef6843ed0b1a7caf04be629d1dac079e48aa048e.tar.gz
gcc-ef6843ed0b1a7caf04be629d1dac079e48aa048e.tar.bz2
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/sparc/sparc.c148
2 files changed, 86 insertions, 72 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d0cd8b..0cf5ae0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e880226..578f916 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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,62 +5076,58 @@ 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,
&regno, &padding);
-
if (slotno == -1)
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);
- return reg;
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ 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);
- }
- else if (type && TREE_CODE (type) == UNION_TYPE)
+ /* 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_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);
-
gcc_assert (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;
+ 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);
-
- gcc_assert (bytes <= 32);
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert (size <= 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;