OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 7 Feb 2012 19:15:10 +0000 (19:15 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 7 Feb 2012 19:15:10 +0000 (19:15 +0000)
PR middle-end/24306
* config/mips/mips.c (mips_std_gimplify_va_arg_expr): New function.
(mips_gimplify_va_arg_expr): Call it instead of
std_gimplify_va_arg_expr.

gcc/testsuite/
PR middle-end/24306
PR target/52154
* lib/target-supports.exp (check_effective_target_mips_eabi): New.
* gcc.target/mips/va-arg-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183977 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/va-arg-1.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index da4ceb7..8ea5882 100644 (file)
@@ -1,3 +1,10 @@
+2012-02-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       PR middle-end/24306
+       * config/mips/mips.c (mips_std_gimplify_va_arg_expr): New function.
+       (mips_gimplify_va_arg_expr): Call it instead of
+       std_gimplify_va_arg_expr.
+
 2012-02-07  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        * config/rs6000/rs6000.c (rs6000_trampoline_init): Fix error
index e4231a5..56863fa 100644 (file)
@@ -5576,6 +5576,95 @@ mips_va_start (tree valist, rtx nextarg)
     }
 }
 
+/* Like std_gimplify_va_arg_expr, but apply alignment to zero-sized
+   types as well.  */
+
+static tree
+mips_std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+                              gimple_seq *post_p)
+{
+  tree addr, t, type_size, rounded_size, valist_tmp;
+  unsigned HOST_WIDE_INT align, boundary;
+  bool indirect;
+
+  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  if (indirect)
+    type = build_pointer_type (type);
+
+  align = PARM_BOUNDARY / BITS_PER_UNIT;
+  boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+
+  /* When we align parameter on stack for caller, if the parameter
+     alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
+     aligned at MAX_SUPPORTED_STACK_ALIGNMENT.  We will match callee
+     here with caller.  */
+  if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
+    boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+
+  boundary /= BITS_PER_UNIT;
+
+  /* Hoist the valist value into a temporary for the moment.  */
+  valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
+
+  /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
+     requires greater alignment, we must perform dynamic alignment.  */
+  if (boundary > align)
+    {
+      t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+                 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+      gimplify_and_add (t, pre_p);
+
+      t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+                 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
+                              valist_tmp,
+                              build_int_cst (TREE_TYPE (valist), -boundary)));
+      gimplify_and_add (t, pre_p);
+    }
+  else
+    boundary = align;
+
+  /* If the actual alignment is less than the alignment of the type,
+     adjust the type accordingly so that we don't assume strict alignment
+     when dereferencing the pointer.  */
+  boundary *= BITS_PER_UNIT;
+  if (boundary < TYPE_ALIGN (type))
+    {
+      type = build_variant_type_copy (type);
+      TYPE_ALIGN (type) = boundary;
+    }
+
+  /* Compute the rounded size of the type.  */
+  type_size = size_in_bytes (type);
+  rounded_size = round_up (type_size, align);
+
+  /* Reduce rounded_size so it's sharable with the postqueue.  */
+  gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+
+  /* Get AP.  */
+  addr = valist_tmp;
+  if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
+    {
+      /* Small args are padded downward.  */
+      t = fold_build2_loc (input_location, GT_EXPR, sizetype,
+                      rounded_size, size_int (align));
+      t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+                      size_binop (MINUS_EXPR, rounded_size, type_size));
+      addr = fold_build_pointer_plus (addr, t);
+    }
+
+  /* Compute new value for AP.  */
+  t = fold_build_pointer_plus (valist_tmp, rounded_size);
+  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+  gimplify_and_add (t, pre_p);
+
+  addr = fold_convert (build_pointer_type (type), addr);
+
+  if (indirect)
+    addr = build_va_arg_indirect_ref (addr);
+
+  return build_va_arg_indirect_ref (addr);
+}
+
 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR.  */
 
 static tree
@@ -5590,7 +5679,7 @@ mips_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
     type = build_pointer_type (type);
 
   if (!EABI_FLOAT_VARARGS_P)
-    addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
+    addr = mips_std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
   else
     {
       tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
index 47509f0..76daf3d 100644 (file)
@@ -1,3 +1,10 @@
+2012-02-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       PR middle-end/24306
+       PR target/52154
+       * lib/target-supports.exp (check_effective_target_mips_eabi): New.
+       * gcc.target/mips/va-arg-1.c: New test.
+
 2012-02-07  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        * gcc.target/powerpc/no-r11-3.c (outer_func): Fix error message
diff --git a/gcc/testsuite/gcc.target/mips/va-arg-1.c b/gcc/testsuite/gcc.target/mips/va-arg-1.c
new file mode 100644 (file)
index 0000000..87c95f5
--- /dev/null
@@ -0,0 +1,48 @@
+/* See PR 52154 for the xfail.  */
+/* { dg-do run { xfail { mips_eabi && { hard_float && ilp32 } } } } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+struct __attribute__((aligned(16))) empty {};
+
+static void __attribute__((noinline))
+check_args (int count, ...)
+{
+  va_list va;
+  int i;
+
+  va_start (va, count);
+  for (i = 0; i < count; i++)
+    if (va_arg (va, int) != 1000 + i)
+      abort ();
+
+  va_arg (va, struct empty);
+  if (va_arg (va, int) != 2000 + count)
+    abort ();
+
+  va_end (va);
+}
+
+int
+main (void)
+{
+  struct empty e;
+
+  check_args (1, 1000, e, 2001);
+  check_args (2, 1000, 1001, e, 2002);
+  check_args (3, 1000, 1001, 1002, e, 2003);
+  check_args (4, 1000, 1001, 1002, 1003, e, 2004);
+  check_args (5, 1000, 1001, 1002, 1003, 1004, e, 2005);
+  check_args (6, 1000, 1001, 1002, 1003, 1004, 1005, e, 2006);
+  check_args (7, 1000, 1001, 1002, 1003, 1004, 1005, 1006, e, 2007);
+  check_args (8, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, e, 2008);
+  check_args (9, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+             1008, e, 2009);
+  check_args (10, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+             1008, 1009, e, 2010);
+  check_args (11, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+             1008, 1009, 1010, e, 2011);
+  return 0;
+}
index 518d654..02490d9 100644 (file)
@@ -924,6 +924,19 @@ proc check_effective_target_mips_rel { } {
     }]
 }
 
+# Return true if the target is a MIPS target that uses the EABI.
+
+proc check_effective_target_mips_eabi { } {
+    if { ![istarget mips*-*-*] } {
+       return 0
+    }
+    return [check_no_compiler_messages mips_eabi object {
+       #ifndef __mips_eabi
+       #error FOO
+       #endif
+    }]
+}
+
 # Return 1 if the current multilib does not generate PIC by default.
 
 proc check_effective_target_nonpic { } {