The attached patch fixes a problem noted in the libffi testsuite.  This is a 
particular problem
on 32-bit hppa*-hpux*.

We pass homogeneous SFmode and DFmode aggregates in the general registers 
instead of the floating
point registers that are used to pass SFmode and DFmode values.  
ASM_DECLARE_FUNCTION_NAME did not
correctly indicate that the general registers were being used.  The HP linker 
adjusts the call and
return values to compensate for the registers being used.  Since the indication 
was wrong, this
resulted in passed and return values being clobbered.

I also adjusted the value size check in pa_function_value as it could accept 
arguments with a size
other than word or double word.

Tested on hppa2.0w-hp-hpux11.11 and hppa-unknown-linux-gnu.  Committed to 
trunk, gcc-9 and gcc-8.

Dave

2020-02-21  John David Anglin  <dang...@gcc.gnu.org>

        * gcc/config/pa/pa.c (pa_function_value): Fix check for word and
        double-word size when handling aggregate return values.
        * gcc/config/pa/som.h (ASM_DECLARE_FUNCTION_NAME): Fix to indicate
        that homogeneous SFmode and DFmode aggregates are passed and returned
        in general registers.

diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 24b88304637..a662de96ac9 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -9335,7 +9335,7 @@ pa_function_value (const_tree valtype,
       HOST_WIDE_INT valsize = int_size_in_bytes (valtype);

       /* Handle aggregates that fit exactly in a word or double word.  */
-      if ((valsize & (UNITS_PER_WORD - 1)) == 0)
+      if (valsize == UNITS_PER_WORD || valsize == 2 * UNITS_PER_WORD)
        return gen_rtx_REG (TYPE_MODE (valtype), 28);

       if (TARGET_64BIT)
diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
index 95c3bd238fe..505fdd65d79 100644
--- a/gcc/config/pa/som.h
+++ b/gcc/config/pa/som.h
@@ -98,8 +98,8 @@ do {                                                          
\

 
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
-    do { tree fntype = TREE_TYPE (TREE_TYPE (DECL));                   \
-        tree tree_type = TREE_TYPE (DECL);                             \
+    do { tree tree_type = TREE_TYPE (DECL);                            \
+        tree fntype = TREE_TYPE (tree_type);                           \
         tree parm;                                                     \
         int i;                                                         \
         if (TREE_PUBLIC (DECL) || TARGET_GAS)                          \
@@ -121,9 +121,11 @@ do {                                                       
        \
               {                                                        \
                 tree type = DECL_ARG_TYPE (parm);                      \
                 machine_mode mode = TYPE_MODE (type);                  \
-                if (mode == SFmode && ! TARGET_SOFT_FLOAT)             \
+                if (!AGGREGATE_TYPE_P (type)                           \
+                    && mode == SFmode && ! TARGET_SOFT_FLOAT)          \
                   fprintf (FILE, ",ARGW%d=FR", i++);                   \
-                else if (mode == DFmode && ! TARGET_SOFT_FLOAT)        \
+                else if (!AGGREGATE_TYPE_P (type)                      \
+                         && mode == DFmode && ! TARGET_SOFT_FLOAT)     \
                   {                                                    \
                     if (i <= 2)                                        \
                       {                                                \
@@ -158,9 +160,13 @@ do {                                                       
        \
                 for (; i < 4; i++)                                     \
                   fprintf (FILE, ",ARGW%d=GR", i);                     \
               }                                                        \
-            if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT)   \
+            if (!AGGREGATE_TYPE_P (fntype)                             \
+                && TYPE_MODE (fntype) == DFmode                        \
+                && ! TARGET_SOFT_FLOAT)                                \
               fputs (DFMODE_RETURN_STRING, FILE);                      \
-            else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \
+            else if (!AGGREGATE_TYPE_P (fntype)                        \
+                     && TYPE_MODE (fntype) == SFmode                   \
+                     && ! TARGET_SOFT_FLOAT)                           \
               fputs (SFMODE_RETURN_STRING, FILE);                      \
             else if (fntype != void_type_node)                         \
               fputs (",RTNVAL=GR", FILE);                              \

Reply via email to