mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 18:40:57 +08:00
re PR target/44575 (__builtin_va_arg overwrites into adjacent stack location)
PR target/44575 * config/i386/i386.c (ix86_gimplify_va_arg): When copying va_arg from a set of register save slots into a temporary, if the container is bigger than type size, do the copying using smaller mode or using memcpy. * gcc.c-torture/execute/pr44575.c: New test. From-SVN: r161097
This commit is contained in:
parent
5ec9660956
commit
529e5fc9c0
@ -47,6 +47,12 @@
|
||||
* stmt.c (resolve_asm_operand_names): Fix handling
|
||||
of %%.
|
||||
|
||||
PR target/44575
|
||||
* config/i386/i386.c (ix86_gimplify_va_arg): When copying
|
||||
va_arg from a set of register save slots into a temporary,
|
||||
if the container is bigger than type size, do the copying
|
||||
using smaller mode or using memcpy.
|
||||
|
||||
PR bootstrap/44426
|
||||
* sel-sched-dump.h (sel_prepare_string_for_dot_label): Remove
|
||||
prototype.
|
||||
|
@ -7267,7 +7267,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
|
||||
}
|
||||
if (need_temp)
|
||||
{
|
||||
int i;
|
||||
int i, prev_size = 0;
|
||||
tree temp = create_tmp_var (type, "va_arg_tmp");
|
||||
|
||||
/* addr = &temp; */
|
||||
@ -7279,13 +7279,29 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
|
||||
rtx slot = XVECEXP (container, 0, i);
|
||||
rtx reg = XEXP (slot, 0);
|
||||
enum machine_mode mode = GET_MODE (reg);
|
||||
tree piece_type = lang_hooks.types.type_for_mode (mode, 1);
|
||||
tree addr_type = build_pointer_type (piece_type);
|
||||
tree daddr_type = build_pointer_type_for_mode (piece_type,
|
||||
ptr_mode, true);
|
||||
tree piece_type;
|
||||
tree addr_type;
|
||||
tree daddr_type;
|
||||
tree src_addr, src;
|
||||
int src_offset;
|
||||
tree dest_addr, dest;
|
||||
int cur_size = GET_MODE_SIZE (mode);
|
||||
|
||||
if (prev_size + cur_size > size)
|
||||
{
|
||||
cur_size = size - prev_size;
|
||||
mode = mode_for_size (cur_size * BITS_PER_UNIT, MODE_INT, 1);
|
||||
if (mode == BLKmode)
|
||||
mode = QImode;
|
||||
}
|
||||
piece_type = lang_hooks.types.type_for_mode (mode, 1);
|
||||
if (mode == GET_MODE (reg))
|
||||
addr_type = build_pointer_type (piece_type);
|
||||
else
|
||||
addr_type = build_pointer_type_for_mode (piece_type, ptr_mode,
|
||||
true);
|
||||
daddr_type = build_pointer_type_for_mode (piece_type, ptr_mode,
|
||||
true);
|
||||
|
||||
if (SSE_REGNO_P (REGNO (reg)))
|
||||
{
|
||||
@ -7300,14 +7316,26 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
|
||||
src_addr = fold_convert (addr_type, src_addr);
|
||||
src_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, src_addr,
|
||||
size_int (src_offset));
|
||||
src = build_va_arg_indirect_ref (src_addr);
|
||||
|
||||
dest_addr = fold_convert (daddr_type, addr);
|
||||
dest_addr = fold_build2 (POINTER_PLUS_EXPR, daddr_type, dest_addr,
|
||||
size_int (INTVAL (XEXP (slot, 1))));
|
||||
dest = build_va_arg_indirect_ref (dest_addr);
|
||||
if (cur_size == GET_MODE_SIZE (mode))
|
||||
{
|
||||
src = build_va_arg_indirect_ref (src_addr);
|
||||
dest = build_va_arg_indirect_ref (dest_addr);
|
||||
|
||||
gimplify_assign (dest, src, pre_p);
|
||||
gimplify_assign (dest, src, pre_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree copy
|
||||
= build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
|
||||
3, dest_addr, src_addr,
|
||||
size_int (cur_size));
|
||||
gimplify_and_add (copy, pre_p);
|
||||
}
|
||||
prev_size += cur_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2010-06-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/44575
|
||||
* gcc.c-torture/execute/pr44575.c: New test.
|
||||
|
||||
2010-06-21 Tobias Burnus <burnus@net-b.de>
|
||||
|
||||
PR fortran/40632
|
||||
|
49
gcc/testsuite/gcc.c-torture/execute/pr44575.c
Normal file
49
gcc/testsuite/gcc.c-torture/execute/pr44575.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* PR target/44575 */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int fails = 0;
|
||||
struct S { float a[3]; };
|
||||
struct S a[5];
|
||||
|
||||
void
|
||||
check (int z, ...)
|
||||
{
|
||||
struct S arg, *p;
|
||||
va_list ap;
|
||||
int j = 0, k = 0;
|
||||
int i;
|
||||
va_start (ap, z);
|
||||
for (i = 2; i < 4; ++i)
|
||||
{
|
||||
p = 0;
|
||||
j++;
|
||||
k += 2;
|
||||
switch ((z << 4) | i)
|
||||
{
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
p = &a[2];
|
||||
arg = va_arg (ap, struct S);
|
||||
break;
|
||||
default:
|
||||
++fails;
|
||||
break;
|
||||
}
|
||||
if (p && p->a[2] != arg.a[2])
|
||||
++fails;
|
||||
if (fails)
|
||||
break;
|
||||
}
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
a[2].a[2] = -49026;
|
||||
check (1, a[2], a[2]);
|
||||
if (fails)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user