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]

[PATCH] PR64979: S/390: Fix setup of overflow area pointer in va_start


Hi,

the attached patch fixes a critical problem in the va_start expansion
code in the S/390 backend. The problem exists since GCC 4.0.

Ok to commit to 4.9 branch and mainline?

Bye,

-Andreas-


2015-02-09  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	PR target/64979
	* config/s390/s390.c (s390_va_start): Make set up of
	__overflow_arg_area unconditional.

2015-02-09  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	PR target/64979
	* gcc.dg/pr64979.c: New testcase.


diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index bc6223e..ed22d35 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -9697,23 +9697,19 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
     }
 
   /* Find the overflow area.  */
-  if (n_gpr + cfun->va_list_gpr_size > GP_ARG_NUM_REG
-      || n_fpr + cfun->va_list_fpr_size > FP_ARG_NUM_REG)
-    {
-      t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
+  t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
 
-      off = INTVAL (crtl->args.arg_offset_rtx);
-      off = off < 0 ? 0 : off;
-      if (TARGET_DEBUG_ARG)
-	fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
-		 (int)n_gpr, (int)n_fpr, off);
+  off = INTVAL (crtl->args.arg_offset_rtx);
+  off = off < 0 ? 0 : off;
+  if (TARGET_DEBUG_ARG)
+    fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
+	     (int)n_gpr, (int)n_fpr, off);
 
-      t = fold_build_pointer_plus_hwi (t, off);
+  t = fold_build_pointer_plus_hwi (t, off);
 
-      t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
-      TREE_SIDE_EFFECTS (t) = 1;
-      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-    }
+  t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+  TREE_SIDE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
   /* Find the register save area.  */
   if ((cfun->va_list_gpr_size && n_gpr < GP_ARG_NUM_REG)
diff --git a/gcc/testsuite/gcc.dg/pr64979.c b/gcc/testsuite/gcc.dg/pr64979.c
new file mode 100644
index 0000000..9c715c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64979.c
@@ -0,0 +1,40 @@
+/* PR target/64979 */
+
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+void __attribute__((noinline))
+bar(int msgno, va_list *args)
+{
+  int i;
+
+  for (i = 0; i < 10; i++)
+    if (i != va_arg(*args, int))
+      abort ();
+}
+
+
+void __attribute__((noinline))
+foo(int msgno, ...)
+{
+  va_list args;
+  int nargs;
+
+  va_start(args, msgno);
+  nargs = va_arg(args, int);
+  bar(msgno, (va_list *)((nargs == 0) ? ((void *)0) : &args));
+}
+
+
+int main(void)
+{
+  foo(100 /* msgno */,
+      1 /* nargs - part of vararg list */,
+      0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+  return 0;
+}


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