re PR target/15783 (ICE with union assignment in 64-bit mode)
authorEric Botcazou <ebotcazou@libertysurf.fr>
Mon, 7 Jun 2004 20:58:33 +0000 (22:58 +0200)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 7 Jun 2004 20:58:33 +0000 (20:58 +0000)
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.

From-SVN: r82722

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/union-1.c [new file with mode: 0644]

index a119116e04b41a859df8143154d90a62ae58bdf6..0be308243f8ae16c05a99829c6994d610994c240 100644 (file)
@@ -1,3 +1,13 @@
+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.
+
+       * config/sparc/sparc.c (sparc_function_epilogue): Properly format.
+
 2004-06-07  Roger Sayle  <roger@eyesopen.com>
 
        * real.c (real_copysign): New function to implement libm's copysign.
index 30fbb878b66a5235568c1b78af7415821677314c..0d19727145688a1f00846ef28d6b59ebeb5e4f2f 100644 (file)
@@ -4514,12 +4514,12 @@ sparc_function_epilogue (FILE *file,
      This insn is used in the 32-bit ABI when calling a function that returns
      a non zero-sized structure. The 64-bit ABI doesn't have it.  Be careful
      to have this test be the same as that used on the call.  */
-  sparc_skip_caller_unimp =
-    ! TARGET_ARCH64
-    && current_function_returns_struct
-    && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
-       == INTEGER_CST)
-    && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)));
+  sparc_skip_caller_unimp
+    ! TARGET_ARCH64
+      && current_function_returns_struct
+      && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
+         == INTEGER_CST)
+      && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)));
 
   if (current_function_epilogue_delay_list == 0)
     {
@@ -5129,7 +5129,7 @@ static void function_arg_record_value_2
 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);
+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.  */
@@ -5471,26 +5471,25 @@ function_arg_record_value (tree type, enum machine_mode mode,
    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, int regno)
+function_arg_union_value (int size, enum machine_mode mode, int regno)
 {
-  enum machine_mode mode;
-  rtx reg;
+  int nwords = ROUND_ADVANCE (size), i;
+  rtx regs;
 
-  if (size <= UNITS_PER_WORD)
-    mode = word_mode;
-  else
-    mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+  /* Unions are passed left-justified.  */
+  regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords));
 
-  reg = gen_rtx_REG (mode, regno);
+  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));
 
-  /* Unions are passed left-justified.  */
-  return gen_rtx_PARALLEL (mode,
-                          gen_rtvec (1, gen_rtx_EXPR_LIST (VOIDmode,
-                                                           reg,
-                                                           const0_rtx)));
+  return regs;
 }
 
 /* Handle the FUNCTION_ARG macro.
@@ -5547,7 +5546,7 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
       if (size > 16)
        abort (); /* shouldn't get here */
 
-      return function_arg_union_value (size, regno);
+      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.
@@ -5872,7 +5871,7 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
          if (size > 32)
            abort (); /* shouldn't get here */
 
-         return function_arg_union_value (size, regbase);
+         return function_arg_union_value (size, mode, regbase);
        }
       else if (AGGREGATE_TYPE_P (type))
        {
index 35bf511e71de9ce222c9791469a6b49d0b6e3126..055cd69bf8ed118396aefc87c5973f809a892606 100644 (file)
@@ -1,3 +1,7 @@
+2004-06-07  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * gcc.dg/union-1.c: New test.
+
 2004-06-07  Roger Sayle  <roger@eyesopen.com>
 
        * gcc.dg/builtins-41.c: New test case.
@@ -22718,3 +22722,4 @@ rlsruhe.de>
        correspond to c-torture 1.11.
 
        * New file.
+
diff --git a/gcc/testsuite/gcc.dg/union-1.c b/gcc/testsuite/gcc.dg/union-1.c
new file mode 100644 (file)
index 0000000..0dd2df9
--- /dev/null
@@ -0,0 +1,22 @@
+/* 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();
+}