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
This commit is contained in:
Jakub Jelinek 2010-07-16 11:06:02 +02:00 committed by Jakub Jelinek
parent ba2dc63db7
commit 88ad03c2cb
6 changed files with 142 additions and 8 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}