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); \