aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2012-02-07 19:15:10 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2012-02-07 19:15:10 +0000
commit4566de104dd67c8ee3d14a14bc5019f6c32b5c92 (patch)
tree7ba9ccd153582b4f310e1a46c83d99819f72d9b0 /gcc
parent7cb5ce1a2d4e2452ecdbe3306a8d3f74c6c4790b (diff)
downloadgcc-4566de104dd67c8ee3d14a14bc5019f6c32b5c92.zip
gcc-4566de104dd67c8ee3d14a14bc5019f6c32b5c92.tar.gz
gcc-4566de104dd67c8ee3d14a14bc5019f6c32b5c92.tar.bz2
re PR middle-end/24306 (va_arg gets confused when skipping over certain zero-sized types with -msse)
gcc/ PR middle-end/24306 * config/mips/mips.c (mips_std_gimplify_va_arg_expr): New function. (mips_gimplify_va_arg_expr): Call it instead of std_gimplify_va_arg_expr. gcc/testsuite/ PR middle-end/24306 PR target/52154 * lib/target-supports.exp (check_effective_target_mips_eabi): New. * gcc.target/mips/va-arg-1.c: New test. From-SVN: r183977
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/mips/mips.c91
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.target/mips/va-arg-1.c48
-rw-r--r--gcc/testsuite/lib/target-supports.exp13
5 files changed, 165 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index da4ceb7..8ea5882 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2012-02-07 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR middle-end/24306
+ * config/mips/mips.c (mips_std_gimplify_va_arg_expr): New function.
+ (mips_gimplify_va_arg_expr): Call it instead of
+ std_gimplify_va_arg_expr.
+
2012-02-07 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_trampoline_init): Fix error
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index e4231a5..56863fa 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -5576,6 +5576,95 @@ mips_va_start (tree valist, rtx nextarg)
}
}
+/* Like std_gimplify_va_arg_expr, but apply alignment to zero-sized
+ types as well. */
+
+static tree
+mips_std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+ gimple_seq *post_p)
+{
+ tree addr, t, type_size, rounded_size, valist_tmp;
+ unsigned HOST_WIDE_INT align, boundary;
+ bool indirect;
+
+ indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+ if (indirect)
+ type = build_pointer_type (type);
+
+ align = PARM_BOUNDARY / BITS_PER_UNIT;
+ boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+
+ /* When we align parameter on stack for caller, if the parameter
+ alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
+ aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
+ here with caller. */
+ if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
+ boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+
+ boundary /= BITS_PER_UNIT;
+
+ /* Hoist the valist value into a temporary for the moment. */
+ valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
+
+ /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
+ requires greater alignment, we must perform dynamic alignment. */
+ if (boundary > align)
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+ gimplify_and_add (t, pre_p);
+
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
+ valist_tmp,
+ build_int_cst (TREE_TYPE (valist), -boundary)));
+ gimplify_and_add (t, pre_p);
+ }
+ else
+ boundary = align;
+
+ /* If the actual alignment is less than the alignment of the type,
+ adjust the type accordingly so that we don't assume strict alignment
+ when dereferencing the pointer. */
+ boundary *= BITS_PER_UNIT;
+ if (boundary < TYPE_ALIGN (type))
+ {
+ type = build_variant_type_copy (type);
+ TYPE_ALIGN (type) = boundary;
+ }
+
+ /* Compute the rounded size of the type. */
+ type_size = size_in_bytes (type);
+ rounded_size = round_up (type_size, align);
+
+ /* Reduce rounded_size so it's sharable with the postqueue. */
+ gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+
+ /* Get AP. */
+ addr = valist_tmp;
+ if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
+ {
+ /* Small args are padded downward. */
+ t = fold_build2_loc (input_location, GT_EXPR, sizetype,
+ rounded_size, size_int (align));
+ t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+ size_binop (MINUS_EXPR, rounded_size, type_size));
+ addr = fold_build_pointer_plus (addr, t);
+ }
+
+ /* Compute new value for AP. */
+ t = fold_build_pointer_plus (valist_tmp, rounded_size);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+ gimplify_and_add (t, pre_p);
+
+ addr = fold_convert (build_pointer_type (type), addr);
+
+ if (indirect)
+ addr = build_va_arg_indirect_ref (addr);
+
+ return build_va_arg_indirect_ref (addr);
+}
+
/* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. */
static tree
@@ -5590,7 +5679,7 @@ mips_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
type = build_pointer_type (type);
if (!EABI_FLOAT_VARARGS_P)
- addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
+ addr = mips_std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
else
{
tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 47509f0..76daf3d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2012-02-07 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR middle-end/24306
+ PR target/52154
+ * lib/target-supports.exp (check_effective_target_mips_eabi): New.
+ * gcc.target/mips/va-arg-1.c: New test.
+
2012-02-07 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/no-r11-3.c (outer_func): Fix error message
diff --git a/gcc/testsuite/gcc.target/mips/va-arg-1.c b/gcc/testsuite/gcc.target/mips/va-arg-1.c
new file mode 100644
index 0000000..87c95f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/va-arg-1.c
@@ -0,0 +1,48 @@
+/* See PR 52154 for the xfail. */
+/* { dg-do run { xfail { mips_eabi && { hard_float && ilp32 } } } } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+struct __attribute__((aligned(16))) empty {};
+
+static void __attribute__((noinline))
+check_args (int count, ...)
+{
+ va_list va;
+ int i;
+
+ va_start (va, count);
+ for (i = 0; i < count; i++)
+ if (va_arg (va, int) != 1000 + i)
+ abort ();
+
+ va_arg (va, struct empty);
+ if (va_arg (va, int) != 2000 + count)
+ abort ();
+
+ va_end (va);
+}
+
+int
+main (void)
+{
+ struct empty e;
+
+ check_args (1, 1000, e, 2001);
+ check_args (2, 1000, 1001, e, 2002);
+ check_args (3, 1000, 1001, 1002, e, 2003);
+ check_args (4, 1000, 1001, 1002, 1003, e, 2004);
+ check_args (5, 1000, 1001, 1002, 1003, 1004, e, 2005);
+ check_args (6, 1000, 1001, 1002, 1003, 1004, 1005, e, 2006);
+ check_args (7, 1000, 1001, 1002, 1003, 1004, 1005, 1006, e, 2007);
+ check_args (8, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, e, 2008);
+ check_args (9, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+ 1008, e, 2009);
+ check_args (10, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+ 1008, 1009, e, 2010);
+ check_args (11, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+ 1008, 1009, 1010, e, 2011);
+ return 0;
+}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 518d654..02490d9 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -924,6 +924,19 @@ proc check_effective_target_mips_rel { } {
}]
}
+# Return true if the target is a MIPS target that uses the EABI.
+
+proc check_effective_target_mips_eabi { } {
+ if { ![istarget mips*-*-*] } {
+ return 0
+ }
+ return [check_no_compiler_messages mips_eabi object {
+ #ifndef __mips_eabi
+ #error FOO
+ #endif
+ }]
+}
+
# Return 1 if the current multilib does not generate PIC by default.
proc check_effective_target_nonpic { } {