This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix PR target/15783


This is a regression on SPARC 64-bit present on 3.4 branch and mainline.  The 
compiler ICEs on a function returning a 24-byte union (by value), a fallout 
of the ABI fixes that went into the 3.4.0 release.

The problem is as follows: it is valid for the FUNCTION_VALUE macro to return 
a (reg:BLK) rtx because hard_function_value will try to convert it to an 
appropriate integer mode.  That's what the SPARC 64-bit back-end used to do 
for large unions returned by value.

Now the back-end was deviating from the psABI for unions (they were 
right-justified while they must be left-justified) so it has been corrected 
to a return a PARALLEL instead, wrapping up the register.  But in this case 
hard_function_value doesn't do the conversion and the compiler ICEs quickly 
thereafter.

Fixed by enumerating the registers spanned by the union inside the PARALLEL.

Bootstrapped/regtested/compat-regtested on sparc64-sun-solaris2.9 (3.4 
branch), applied to 3.4 branch and mainline (the mainline patch also contains 
a formatting fix).


2004-06-07  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR target/15783
	* config/sparc/sparc.c (function_arg_union_value): Add 'mode'
	parameter.  Enumerate the registers inside the PARALLEL.
	(function_arg): Adjust call to function_arg_union_value.
	(function_value): Likewise.


2004-06-07  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* gcc.dg/union-1.c: New test.


-- 
Eric Botcazou
/* PR target/15783 */
/* Origin: Paul Pluzhnikov <ppluzhnikov@charter.net> */

/* This used to ICE on SPARC 64-bit because the back-end was
   returning an invalid construct for the return value of fu2.  */

/* { dg-do compile } */

union u2 {
    struct
    {
        int u2s_a, u2s_b, u2s_c, u2s_d, u2s_e;
    } u2_s;
    double u2_d;
} u2a;

union u2 fu2();

void unions()
{
    u2a = fu2();
}
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.271.4.14
diff -c -p -r1.271.4.14 sparc.c
*** config/sparc/sparc.c	31 May 2004 21:40:14 -0000	1.271.4.14
--- config/sparc/sparc.c	6 Jun 2004 09:09:21 -0000
*************** static void function_arg_record_value_2
*** 5033,5039 ****
  static void function_arg_record_value_1
   (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
  static rtx function_arg_record_value (tree, enum machine_mode, int, int, int);
! static rtx function_arg_union_value (int, int);
  
  /* A subroutine of function_arg_record_value.  Traverse the structure
     recursively and determine how many registers will be required.  */
--- 5033,5039 ----
  static void function_arg_record_value_1
   (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
  static rtx function_arg_record_value (tree, enum machine_mode, int, int, int);
! static rtx function_arg_union_value (int, enum machine_mode, int);
  
  /* A subroutine of function_arg_record_value.  Traverse the structure
     recursively and determine how many registers will be required.  */
*************** function_arg_record_value (tree type, en
*** 5373,5398 ****
     FUNCTION_ARG and FUNCTION_VALUE.
  
     SIZE is the size in bytes of the union.
     REGNO is the hard register the union will be passed in.  */
  
  static rtx
! function_arg_union_value (int size, int regno)
  {
!   enum machine_mode mode;
!   rtx reg;
  
!   if (size <= UNITS_PER_WORD)
!     mode = word_mode;
!   else
!     mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
  
!   reg = gen_rtx_REG (mode, regno);
  
!   /* Unions are passed left-justified.  */
!   return gen_rtx_PARALLEL (mode,
! 			   gen_rtvec (1, gen_rtx_EXPR_LIST (VOIDmode,
! 							    reg,
! 							    const0_rtx)));
  }
  
  /* Handle the FUNCTION_ARG macro.
--- 5373,5397 ----
     FUNCTION_ARG and FUNCTION_VALUE.
  
     SIZE is the size in bytes of the union.
+    MODE is the argument's machine mode.
     REGNO is the hard register the union will be passed in.  */
  
  static rtx
! function_arg_union_value (int size, enum machine_mode mode, int regno)
  {
!   int nwords = ROUND_ADVANCE (size), i;
!   rtx regs;
  
!   /* Unions are passed left-justified.  */
!   regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords));
  
!   for (i = 0; i < nwords; i++)
!     XVECEXP (regs, 0, i)
!       = gen_rtx_EXPR_LIST (VOIDmode,
! 			   gen_rtx_REG (word_mode, regno + i),
! 			   GEN_INT (UNITS_PER_WORD * i));
  
!   return regs;
  }
  
  /* Handle the FUNCTION_ARG macro.
*************** function_arg (const struct sparc_args *c
*** 5449,5455 ****
        if (size > 16)
  	abort (); /* shouldn't get here */
  
!       return function_arg_union_value (size, regno);
      }
    /* v9 fp args in reg slots beyond the int reg slots get passed in regs
       but also have the slot allocated for them.
--- 5448,5454 ----
        if (size > 16)
  	abort (); /* shouldn't get here */
  
!       return function_arg_union_value (size, mode, regno);
      }
    /* v9 fp args in reg slots beyond the int reg slots get passed in regs
       but also have the slot allocated for them.
*************** function_value (tree type, enum machine_
*** 5729,5735 ****
  	  if (size > 32)
  	    abort (); /* shouldn't get here */
  
! 	  return function_arg_union_value (size, regbase);
  	}
        else if (AGGREGATE_TYPE_P (type))
  	{
--- 5728,5734 ----
  	  if (size > 32)
  	    abort (); /* shouldn't get here */
  
! 	  return function_arg_union_value (size, mode, regbase);
  	}
        else if (AGGREGATE_TYPE_P (type))
  	{

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]