aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2003-05-11 20:01:01 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2003-05-11 20:01:01 +0000
commit82b1c974a24d2f8df01f191c0e5cf1fceae0f2d1 (patch)
tree63a6d755047fc981fc49f915dcb37d82d94d5fc6 /gcc/config/s390
parent6d70e6bee0dc6e9d0ad552ee70781ae8472b534a (diff)
downloadgcc-82b1c974a24d2f8df01f191c0e5cf1fceae0f2d1.zip
gcc-82b1c974a24d2f8df01f191c0e5cf1fceae0f2d1.tar.gz
gcc-82b1c974a24d2f8df01f191c0e5cf1fceae0f2d1.tar.bz2
s390.c (s390_function_arg_float): New function.
* config/s390/s390.c (s390_function_arg_float): New function. (s390_function_arg_pass_by_reference): Use it. (s390_function_arg_advance): Likewise. (s390_function_arg): Likewise. (s390_va_arg): Likewise From-SVN: r66696
Diffstat (limited to 'gcc/config/s390')
-rw-r--r--gcc/config/s390/s390.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 2a49381..4c290a4 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -211,6 +211,7 @@ static rtx restore_fpr PARAMS ((rtx, int, int));
static rtx save_gprs PARAMS ((rtx, int, int, int));
static rtx restore_gprs PARAMS ((rtx, int, int, int));
static int s390_function_arg_size PARAMS ((enum machine_mode, tree));
+static bool s390_function_arg_float PARAMS ((enum machine_mode, tree));
static struct machine_function * s390_init_machine_status PARAMS ((void));
/* Return true if SET either doesn't set the CC register, or else
@@ -5699,6 +5700,48 @@ s390_function_arg_size (mode, type)
abort ();
}
+/* Return true if a function argument of type TYPE and mode MODE
+ is to be passed in a floating-point register, if available. */
+
+static bool
+s390_function_arg_float (mode, type)
+ enum machine_mode mode;
+ tree type;
+{
+ /* Soft-float changes the ABI: no floating-point registers are used. */
+ if (TARGET_SOFT_FLOAT)
+ return false;
+
+ /* No type info available for some library calls ... */
+ if (!type)
+ return mode == SFmode || mode == DFmode;
+
+ /* The ABI says that record types with a single member are treated
+ just like that member would be. */
+ while (TREE_CODE (type) == RECORD_TYPE)
+ {
+ tree field, single = NULL_TREE;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ if (single == NULL_TREE)
+ single = TREE_TYPE (field);
+ else
+ return false;
+ }
+
+ if (single == NULL_TREE)
+ return false;
+ else
+ type = single;
+ }
+
+ return TREE_CODE (type) == REAL_TYPE;
+}
+
/* 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,
@@ -5715,14 +5758,15 @@ s390_function_arg_pass_by_reference (mode, type)
if (type)
{
if (AGGREGATE_TYPE_P (type) &&
- size != 1 && size != 2 && size != 4 && size != 8)
+ size != 1 && size != 2 && size != 4 && size != 8
+ && !s390_function_arg_float (mode, type))
return 1;
if (TREE_CODE (type) == COMPLEX_TYPE)
return 1;
}
+
return 0;
-
}
/* Update the data in CUM to advance over an argument of mode MODE and
@@ -5738,13 +5782,13 @@ s390_function_arg_advance (cum, mode, type, named)
tree type;
int named ATTRIBUTE_UNUSED;
{
- if (! TARGET_SOFT_FLOAT && (mode == DFmode || mode == SFmode))
+ if (s390_function_arg_pass_by_reference (mode, type))
{
- cum->fprs++;
+ cum->gprs += 1;
}
- else if (s390_function_arg_pass_by_reference (mode, type))
+ else if (s390_function_arg_float (mode, type))
{
- cum->gprs += 1;
+ cum->fprs += 1;
}
else
{
@@ -5782,7 +5826,7 @@ s390_function_arg (cum, mode, type, named)
if (s390_function_arg_pass_by_reference (mode, type))
return 0;
- if (! TARGET_SOFT_FLOAT && (mode == DFmode || mode == SFmode))
+ if (s390_function_arg_float (mode, type))
{
if (cum->fprs + 1 > (TARGET_64BIT? 4 : 2))
return 0;
@@ -5996,7 +6040,7 @@ s390_va_arg (valist, type)
size = UNITS_PER_WORD;
max_reg = 4;
}
- else if (FLOAT_TYPE_P (type) && ! TARGET_SOFT_FLOAT)
+ else if (s390_function_arg_float (TYPE_MODE (type), type))
{
if (TARGET_DEBUG_ARG)
{