diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d0cd8be1d7..0cf5ae0d1e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2006-04-11 Eric Botcazou + + * config/sparc/sparc.c (function_arg_slotno) : 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 * dwarf2out.c (premark_used_types): Remove problematic prototype. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index e880226412e..578f91668b1 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,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;