This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR64979: S/390: Fix setup of overflow area pointer in va_start
- From: Andreas Krebbel <krebbel at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 9 Feb 2015 10:50:34 +0100
- Subject: [PATCH] PR64979: S/390: Fix setup of overflow area pointer in va_start
- Authentication-results: sourceware.org; auth=none
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;
+}