diff --git a/gcc45-pr44942.patch b/gcc45-pr44942.patch new file mode 100644 index 0000000..1fe4b5c --- /dev/null +++ b/gcc45-pr44942.patch @@ -0,0 +1,192 @@ +2010-07-16 Jakub Jelinek + + 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. + +--- gcc/config/i386/i386-protos.h.jj 2010-07-13 15:56:31.000000000 +0200 ++++ gcc/config/i386/i386-protos.h 2010-07-15 12:45:01.000000000 +0200 +@@ -137,8 +137,8 @@ extern enum machine_mode ix86_fp_compare + 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_sol10_return_in_memory (const_tree,const_tree); ++extern int ix86_function_arg_boundary (enum machine_mode, const_tree); ++extern bool ix86_sol10_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); +--- gcc/config/i386/i386.c.jj 2010-07-13 15:56:31.000000000 +0200 ++++ gcc/config/i386/i386.c 2010-07-15 12:44:31.000000000 +0200 +@@ -6157,9 +6157,8 @@ function_arg_advance_64 (CUMULATIVE_ARGS + 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->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 + /* 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) +--- gcc/testsuite/gcc.c-torture/execute/pr44942.c.jj 2010-07-15 13:41:28.000000000 +0200 ++++ gcc/testsuite/gcc.c-torture/execute/pr44942.c 2010-07-15 13:46:40.000000000 +0200 +@@ -0,0 +1,70 @@ ++/* PR target/44942 */ ++ ++#include ++ ++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; ++} +--- gcc/testsuite/gcc.target/i386/pr44942.c.jj 2010-07-15 13:52:37.000000000 +0200 ++++ gcc/testsuite/gcc.target/i386/pr44942.c 2010-07-15 13:53:24.000000000 +0200 +@@ -0,0 +1,44 @@ ++/* PR target/44942 */ ++/* { dg-do run { target lp64 } } */ ++ ++#include ++#include ++ ++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; ++}