backport: re PR target/44942 (Bug in argument passing of long double)

Backport from mainline
	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.

	* gcc.c-torture/execute/pr44942.c: New test.
	* gcc.target/i386/pr44942.c: New test.

From-SVN: r162399
This commit is contained in:
Jakub Jelinek 2010-07-22 08:46:28 +02:00 committed by Jakub Jelinek
parent fb1057d23a
commit 6031417ef7
6 changed files with 148 additions and 8 deletions

View File

@ -1,3 +1,17 @@
2010-07-22 Jakub Jelinek <jakub@redhat.com>
Backport from mainline
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-21 Steve Ellcey <sje@cup.hp.com>
Backport from mainline:

View File

@ -136,8 +136,8 @@ extern enum machine_mode ix86_fp_compare_mode (enum rtx_code);
extern rtx ix86_libcall_value (enum machine_mode);
extern bool ix86_function_value_regno_p (int);
extern bool ix86_function_arg_regno_p (int);
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 int ix86_cfun_abi (void);

View File

@ -5657,9 +5657,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;
@ -5667,7 +5666,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
@ -5996,7 +5999,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))
@ -6046,7 +6049,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,12 @@
2010-07-22 Jakub Jelinek <jakub@redhat.com>
Backport from mainline
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-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Backport from mainline:

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