aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-07-16 11:06:02 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2010-07-16 11:06:02 +0200
commit88ad03c2cbc921c32663562c95f2966e6dc0885b (patch)
tree30e7ceedd3005f1370130fd0eea949d4448e16a5 /gcc
parentba2dc63db7830c104a1325133ee5f286e4ff4dcf (diff)
downloadgcc-88ad03c2cbc921c32663562c95f2966e6dc0885b.zip
gcc-88ad03c2cbc921c32663562c95f2966e6dc0885b.tar.gz
gcc-88ad03c2cbc921c32663562c95f2966e6dc0885b.tar.bz2
re PR target/44942 (Bug in argument passing of long double)
PR target/44942 * config/i386/i386-protos.h (ix86_function_arg_boundary): Change second argument to const_tree. * config/i386/i386.c (function_arg_advance): If padding needs to be inserted before argument, increment cum->words by number of padding words as well. (contains_aligned_value_p): Change argument to const_tree. (ix86_function_arg_boundary): Change second argument to const_tree. * gcc.c-torture/execute/pr44942.c: New test. * gcc.target/i386/pr44942.c: New test. From-SVN: r162255
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/i386/i386-protos.h4
-rw-r--r--gcc/config/i386/i386.c15
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr44942.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/pr44942.c44
6 files changed, 142 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e31ff0..8fac566 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2010-07-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/44942
+ * config/i386/i386-protos.h (ix86_function_arg_boundary): Change second
+ argument to const_tree.
+ * config/i386/i386.c (function_arg_advance): If padding needs to be
+ inserted before argument, increment cum->words by number of padding
+ words as well.
+ (contains_aligned_value_p): Change argument to const_tree.
+ (ix86_function_arg_boundary): Change second argument to const_tree.
+
2010-07-16 Bernd Schmidt <bernds@codesourcery.com>
PR target/42235
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index e7ee948..23938b8 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -140,8 +140,8 @@ extern enum machine_mode ix86_fp_compare_mode (enum rtx_code);
extern rtx ix86_libcall_value (enum machine_mode);
extern bool ix86_function_arg_regno_p (int);
extern void ix86_asm_output_function_label (FILE *, const char *, tree);
-extern int ix86_function_arg_boundary (enum machine_mode, tree);
-extern bool ix86_solaris_return_in_memory (const_tree,const_tree);
+extern int ix86_function_arg_boundary (enum machine_mode, const_tree);
+extern bool ix86_solaris_return_in_memory (const_tree, const_tree);
extern rtx ix86_force_to_memory (enum machine_mode, rtx);
extern void ix86_free_from_memory (enum machine_mode);
extern enum calling_abi ix86_cfun_abi (void);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index beb2634..fdb4787 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6157,9 +6157,8 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (!named && VALID_AVX256_REG_MODE (mode))
return;
- if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
- cum->words += words;
- else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
+ if (examine_argument (mode, type, 0, &int_nregs, &sse_nregs)
+ && sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
{
cum->nregs -= int_nregs;
cum->sse_nregs -= sse_nregs;
@@ -6167,7 +6166,11 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->sse_regno += sse_nregs;
}
else
- cum->words += words;
+ {
+ int align = ix86_function_arg_boundary (mode, type) / BITS_PER_WORD;
+ cum->words = (cum->words + align - 1) & ~(align - 1);
+ cum->words += words;
+ }
}
static void
@@ -6508,7 +6511,7 @@ ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
/* Return true when TYPE should be 128bit aligned for 32bit argument passing
ABI. */
static bool
-contains_aligned_value_p (tree type)
+contains_aligned_value_p (const_tree type)
{
enum machine_mode mode = TYPE_MODE (type);
if (((TARGET_SSE && SSE_REG_MODE_P (mode))
@@ -6558,7 +6561,7 @@ contains_aligned_value_p (tree type)
specified mode and type. */
int
-ix86_function_arg_boundary (enum machine_mode mode, tree type)
+ix86_function_arg_boundary (enum machine_mode mode, const_tree type)
{
int align;
if (type)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b4bb9a6..eb478bf 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-07-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/44942
+ * gcc.c-torture/execute/pr44942.c: New test.
+ * gcc.target/i386/pr44942.c: New test.
+
2010-07-15 Jason Merrill <jason@redhat.com>
PR c++/44909
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr44942.c b/gcc/testsuite/gcc.c-torture/execute/pr44942.c
new file mode 100644
index 0000000..3ef0830
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr44942.c
@@ -0,0 +1,70 @@
+/* PR target/44942 */
+
+#include <stdarg.h>
+
+void
+test1 (int a, int b, int c, int d, int e, int f, int g, long double h, ...)
+{
+ int i;
+ va_list ap;
+
+ va_start (ap, h);
+ i = va_arg (ap, int);
+ if (i != 1234)
+ __builtin_abort ();
+ va_end (ap);
+}
+
+void
+test2 (int a, int b, int c, int d, int e, int f, int g, long double h, int i,
+ long double j, int k, long double l, int m, long double n, ...)
+{
+ int o;
+ va_list ap;
+
+ va_start (ap, n);
+ o = va_arg (ap, int);
+ if (o != 1234)
+ __builtin_abort ();
+ va_end (ap);
+}
+
+void
+test3 (double a, double b, double c, double d, double e, double f,
+ double g, long double h, ...)
+{
+ double i;
+ va_list ap;
+
+ va_start (ap, h);
+ i = va_arg (ap, double);
+ if (i != 1234.0)
+ __builtin_abort ();
+ va_end (ap);
+}
+
+void
+test4 (double a, double b, double c, double d, double e, double f, double g,
+ long double h, double i, long double j, double k, long double l,
+ double m, long double n, ...)
+{
+ double o;
+ va_list ap;
+
+ va_start (ap, n);
+ o = va_arg (ap, double);
+ if (o != 1234.0)
+ __builtin_abort ();
+ va_end (ap);
+}
+
+int
+main ()
+{
+ test1 (0, 0, 0, 0, 0, 0, 0, 0.0L, 1234);
+ test2 (0, 0, 0, 0, 0, 0, 0, 0.0L, 0, 0.0L, 0, 0.0L, 0, 0.0L, 1234);
+ test3 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0L, 1234.0);
+ test4 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0L, 0.0, 0.0L,
+ 0.0, 0.0L, 0.0, 0.0L, 1234.0);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr44942.c b/gcc/testsuite/gcc.target/i386/pr44942.c
new file mode 100644
index 0000000..4664f7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr44942.c
@@ -0,0 +1,44 @@
+/* PR target/44942 */
+/* { dg-do run { target lp64 } } */
+
+#include <stdarg.h>
+#include <emmintrin.h>
+
+void
+test1 (double a, double b, double c, double d, double e, double f,
+ double g, __m128d h, ...)
+{
+ double i;
+ va_list ap;
+
+ va_start (ap, h);
+ i = va_arg (ap, double);
+ if (i != 1234.0)
+ __builtin_abort ();
+ va_end (ap);
+}
+
+void
+test2 (double a, double b, double c, double d, double e, double f, double g,
+ __m128d h, double i, __m128d j, double k, __m128d l,
+ double m, __m128d n, ...)
+{
+ double o;
+ va_list ap;
+
+ va_start (ap, n);
+ o = va_arg (ap, double);
+ if (o != 1234.0)
+ __builtin_abort ();
+ va_end (ap);
+}
+
+int
+main ()
+{
+ __m128d m = _mm_set1_pd (7.0);
+ test1 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, m, 1234.0);
+ test2 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, m, 0.0, m,
+ 0.0, m, 0.0, m, 1234.0);
+ return 0;
+}