diff options
author | Jakub Jelinek <jakub@redhat.com> | 2010-07-16 11:06:02 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2010-07-16 11:06:02 +0200 |
commit | 88ad03c2cbc921c32663562c95f2966e6dc0885b (patch) | |
tree | 30e7ceedd3005f1370130fd0eea949d4448e16a5 /gcc | |
parent | ba2dc63db7830c104a1325133ee5f286e4ff4dcf (diff) | |
download | gcc-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/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr44942.c | 70 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr44942.c | 44 |
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; +} |