From 8c17530ef3d7a0e4db6706df5507ace7714ad56d Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 6 Nov 2003 21:35:10 +0000 Subject: [PATCH] s390-protos.h (s390_function_value): Declare. * config/s390/s390-protos.h (s390_function_value): Declare. * config/s390/s390.c (TARGET_RETURN_IN_MEMORY): Define. (s390_return_in_memory): New function. (s390_function_value): New function. (s390_function_arg_float): Return false for all arguments larger than 8 bytes. (s390_function_arg_pass_by_reference): Likewise. Return true for all vector arguments. (s390_function_arg_integer): New function. (s390_function_arg_advance): Call it. Add sanity checks. (s390_function_arg): Likewise. * config/s390/s390.h (FUNCTION_VALUE): Call s390_function_value. (LIBCALL_VALUE): Likewise. (RET_REG): Remove. (RETURN_IN_MEMORY): Remove. From-SVN: r73314 --- gcc/ChangeLog | 18 +++++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 118 +++++++++++++++++++++++++++++++++++++++--- gcc/config/s390/s390.h | 29 ++--------- 4 files changed, 136 insertions(+), 30 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fbb999c..9279d35 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2003-11-06 Ulrich Weigand + + * config/s390/s390-protos.h (s390_function_value): Declare. + * config/s390/s390.c (TARGET_RETURN_IN_MEMORY): Define. + (s390_return_in_memory): New function. + (s390_function_value): New function. + (s390_function_arg_float): Return false for all arguments larger + than 8 bytes. + (s390_function_arg_pass_by_reference): Likewise. Return true for + all vector arguments. + (s390_function_arg_integer): New function. + (s390_function_arg_advance): Call it. Add sanity checks. + (s390_function_arg): Likewise. + * config/s390/s390.h (FUNCTION_VALUE): Call s390_function_value. + (LIBCALL_VALUE): Likewise. + (RET_REG): Remove. + (RETURN_IN_MEMORY): Remove. + 2003-11-06 Richard Sandiford * config/mips/mips-protos.h (mips_initial_elimination_offset): Change diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index cad75e0..1ab6b093 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -99,6 +99,7 @@ extern void s390_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); #ifdef RTX_CODE extern rtx s390_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); +extern rtx s390_function_value (tree, enum machine_mode); extern void s390_va_start (tree, rtx); extern rtx s390_va_arg (tree, tree); #endif /* RTX_CODE */ diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index ede221e..6d94d3d 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -60,6 +60,7 @@ static void s390_select_rtx_section (enum machine_mode, rtx, static void s390_encode_section_info (tree, rtx, int); static bool s390_cannot_force_const_mem (rtx); static rtx s390_delegitimize_address (rtx); +static bool s390_return_in_memory (tree, tree); static void s390_init_builtins (void); static rtx s390_expand_builtin (tree, rtx, rtx, enum machine_mode, int); static void s390_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, @@ -107,6 +108,9 @@ static tree s390_build_builtin_va_list (void); #undef TARGET_DELEGITIMIZE_ADDRESS #define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address +#undef TARGET_RETURN_IN_MEMORY +#define TARGET_RETURN_IN_MEMORY s390_return_in_memory + #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS s390_init_builtins #undef TARGET_EXPAND_BUILTIN @@ -6009,6 +6013,10 @@ s390_function_arg_size (enum machine_mode mode, tree type) static bool s390_function_arg_float (enum machine_mode mode, tree type) { + int size = s390_function_arg_size (mode, type); + if (size > 8) + return false; + /* Soft-float changes the ABI: no floating-point registers are used. */ if (TARGET_SOFT_FLOAT) return false; @@ -6043,6 +6051,39 @@ s390_function_arg_float (enum machine_mode mode, tree type) return TREE_CODE (type) == REAL_TYPE; } +/* Return true if a function argument of type TYPE and mode MODE + is to be passed in an integer register, or a pair of integer + registers, if available. */ + +static bool +s390_function_arg_integer (enum machine_mode mode, tree type) +{ + int size = s390_function_arg_size (mode, type); + if (size > 8) + return false; + + /* No type info available for some library calls ... */ + if (!type) + return GET_MODE_CLASS (mode) == MODE_INT + || (TARGET_SOFT_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT); + + /* We accept small integral (and similar) types. */ + if (INTEGRAL_TYPE_P (type) + || POINTER_TYPE_P (type) + || TREE_CODE (type) == OFFSET_TYPE + || (TARGET_SOFT_FLOAT && TREE_CODE (type) == REAL_TYPE)) + return true; + + /* We also accept structs of size 1, 2, 4, 8 that are not + passed in floating-point registers. */ + if (AGGREGATE_TYPE_P (type) + && exact_log2 (size) >= 0 + && !s390_function_arg_float (mode, type)) + return true; + + return false; +} + /* Return 1 if a function argument of type TYPE and mode MODE is to be passed by reference. The ABI specifies that only structures of size 1, 2, 4, or 8 bytes are passed by value, @@ -6053,15 +6094,16 @@ int s390_function_arg_pass_by_reference (enum machine_mode mode, tree type) { int size = s390_function_arg_size (mode, type); + if (size > 8) + return true; if (type) { - if (AGGREGATE_TYPE_P (type) && - size != 1 && size != 2 && size != 4 && size != 8 - && !s390_function_arg_float (mode, type)) + if (AGGREGATE_TYPE_P (type) && exact_log2 (size) < 0) return 1; - if (TREE_CODE (type) == COMPLEX_TYPE) + if (TREE_CODE (type) == COMPLEX_TYPE + || TREE_CODE (type) == VECTOR_TYPE) return 1; } @@ -6086,11 +6128,13 @@ s390_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, { cum->fprs += 1; } - else + else if (s390_function_arg_integer (mode, type)) { int size = s390_function_arg_size (mode, type); cum->gprs += ((size + UNITS_PER_WORD-1) / UNITS_PER_WORD); } + else + abort (); } /* Define where to put the arguments to a function. @@ -6126,7 +6170,7 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, else return gen_rtx (REG, mode, cum->fprs + 16); } - else + else if (s390_function_arg_integer (mode, type)) { int size = s390_function_arg_size (mode, type); int n_gprs = (size + UNITS_PER_WORD-1) / UNITS_PER_WORD; @@ -6136,6 +6180,68 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, else return gen_rtx (REG, mode, cum->gprs + 2); } + + /* After the real arguments, expand_call calls us once again + with a void_type_node type. Whatever we return here is + passed as operand 2 to the call expanders. + + We don't need this feature ... */ + else if (type == void_type_node) + return const0_rtx; + + abort (); +} + +/* Return true if return values of type TYPE should be returned + in a memory buffer whose address is passed by the caller as + hidden first argument. */ + +static bool +s390_return_in_memory (tree type, tree fundecl ATTRIBUTE_UNUSED) +{ + /* We accept small integral (and similar) types. */ + if (INTEGRAL_TYPE_P (type) + || POINTER_TYPE_P (type) + || TREE_CODE (type) == OFFSET_TYPE + || TREE_CODE (type) == REAL_TYPE) + return int_size_in_bytes (type) > 8; + + /* Aggregates and similar constructs are always returned + in memory. */ + if (AGGREGATE_TYPE_P (type) + || TREE_CODE (type) == COMPLEX_TYPE + || TREE_CODE (type) == VECTOR_TYPE) + return true; + + /* ??? We get called on all sorts of random stuff from + aggregate_value_p. We can't abort, but it's not clear + what's safe to return. Pretend it's a struct I guess. */ + return true; +} + +/* Define where to return a (scalar) value of type TYPE. + If TYPE is null, define where to return a (scalar) + value of mode MODE from a libcall. */ + +rtx +s390_function_value (tree type, enum machine_mode mode) +{ + if (type) + { + int unsignedp = TREE_UNSIGNED (type); + mode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1); + } + + if (GET_MODE_CLASS (mode) != MODE_INT + && GET_MODE_CLASS (mode) != MODE_FLOAT) + abort (); + if (GET_MODE_SIZE (mode) > 8) + abort (); + + if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) + return gen_rtx_REG (mode, 16); + else + return gen_rtx_REG (mode, 2); } diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 63fd3ee..e3eaf91 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -707,34 +707,15 @@ CUMULATIVE_ARGS; /* Scalar return values. */ -/* We return scalars in general purpose register 2 for integral values, - and floating point register 0 for fp values. */ -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG ((INTEGRAL_TYPE_P (VALTYPE) \ - && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ - || POINTER_TYPE_P (VALTYPE) \ - ? word_mode : TYPE_MODE (VALTYPE), \ - TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT ? 16 : 2) - -/* Define how to find the value returned by a library function assuming - the value has mode MODE. */ -#define RET_REG(MODE) ((GET_MODE_CLASS (MODE) == MODE_INT \ - || TARGET_SOFT_FLOAT ) ? 2 : 16) -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, RET_REG (MODE)) +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + s390_function_value ((VALTYPE), VOIDmode) + +#define LIBCALL_VALUE(MODE) \ + s390_function_value (NULL, (MODE)) /* Only gpr 2 and fpr 0 are ever used as return registers. */ #define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16) - -/* Aggregate return values. */ - -/* The definition of this macro implies that there are cases where - a scalar value cannot be returned in registers. */ -#define RETURN_IN_MEMORY(type) \ - (TYPE_MODE (type) == BLKmode || \ - GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_INT || \ - GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT) - /* Structure value address is passed as invisible first argument (gpr 2). */ #define STRUCT_VALUE 0 -- 2.7.4