Commit 529e5fc9 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 5ec96609
......@@ -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;
}
}
......
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
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment