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
This commit is contained in:
parent
7cb5ce1a2d
commit
4566de104d
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
48
gcc/testsuite/gcc.target/mips/va-arg-1.c
Normal file
48
gcc/testsuite/gcc.target/mips/va-arg-1.c
Normal file
@ -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;
|
||||
}
|
@ -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 { } {
|
||||
|
Loading…
Reference in New Issue
Block a user