re PR target/36834 (structure return ABI for windows targets differs from native MSVC)

2010-12-18  Kai Tietz  <kai.tietz@onevision.com>

	PR target/36834
	* config/i386/i386.c (ix86_keep_aggregate_return_pointer):
	New local function.
	(ix86_return_pops_args): Use ix86_keep_aggregate_return_pointer
	function instead of KEEP_AGGREGATE_RETURN_POINTER.
	(ix86_handle_callee_pop_aggregate_return): New handler.
	(ix86_attribute_table): Add new attribute
	callee_pop_aggregate_return.
	* doc/extend.texi (callee_pop_aggregate_return): Add
	attribute documentation.

2010-12-18  Kai Tietz  <kai.tietz@onevision.com>

	PR target/36834
	* gcc.target/i386/aggregate-ret1.c: New.
	* gcc.target/i386/aggregate-ret2.c: New.

From-SVN: r168019
This commit is contained in:
Kai Tietz 2010-12-18 10:16:13 +00:00 committed by Kai Tietz
parent a6e4343fc4
commit 628c4eee53
6 changed files with 156 additions and 1 deletions

View File

@ -1,3 +1,16 @@
2010-12-18 Kai Tietz <kai.tietz@onevision.com>
PR target/36834
* config/i386/i386.c (ix86_keep_aggregate_return_pointer):
New local function.
(ix86_return_pops_args): Use ix86_keep_aggregate_return_pointer
function instead of KEEP_AGGREGATE_RETURN_POINTER.
(ix86_handle_callee_pop_aggregate_return): New handler.
(ix86_attribute_table): Add new attribute
callee_pop_aggregate_return.
* doc/extend.texi (callee_pop_aggregate_return): Add
attribute documentation.
2010-12-18 Iain Sandoe <iains@gcc.gnu.org>
* config/darwin.h (SUBTARGET_C_COMMON_OVERRIDE_OPTIONS):

View File

@ -5436,6 +5436,19 @@ ix86_eax_live_at_start_p (void)
return REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR), 0);
}
static bool
ix86_keep_aggregate_return_pointer (tree fntype)
{
tree attr;
attr = lookup_attribute ("callee_pop_aggregate_return",
TYPE_ATTRIBUTES (fntype));
if (attr)
return (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))) == 0);
return KEEP_AGGREGATE_RETURN_POINTER != 0;
}
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
FUNDECL is the declaration node of the function (as a tree),
@ -5480,7 +5493,7 @@ ix86_return_pops_args (tree fundecl, tree funtype, int size)
/* Lose any fake structure return argument if it is passed on the stack. */
if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
&& !KEEP_AGGREGATE_RETURN_POINTER)
&& !ix86_keep_aggregate_return_pointer (funtype))
{
int nregs = ix86_function_regparm (funtype, fundecl);
if (nregs == 0)
@ -29060,6 +29073,58 @@ x86_order_regs_for_local_alloc (void)
reg_alloc_order [pos++] = 0;
}
/* Handle a "callee_pop_aggregate_return" attribute; arguments as
in struct attribute_spec handler. */
static tree
ix86_handle_callee_pop_aggregate_return (tree *node, tree name,
tree args,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_TYPE
&& TREE_CODE (*node) != METHOD_TYPE
&& TREE_CODE (*node) != FIELD_DECL
&& TREE_CODE (*node) != TYPE_DECL)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
*no_add_attrs = true;
return NULL_TREE;
}
if (TARGET_64BIT)
{
warning (OPT_Wattributes, "%qE attribute only available for 32-bit",
name);
*no_add_attrs = true;
return NULL_TREE;
}
if (is_attribute_p ("callee_pop_aggregate_return", name))
{
tree cst;
cst = TREE_VALUE (args);
if (TREE_CODE (cst) != INTEGER_CST)
{
warning (OPT_Wattributes,
"%qE attribute requires an integer constant argument",
name);
*no_add_attrs = true;
}
else if (compare_tree_int (cst, 0) != 0
&& compare_tree_int (cst, 1) != 0)
{
warning (OPT_Wattributes,
"argument to %qE attribute is neither zero, nor one",
name);
*no_add_attrs = true;
}
return NULL_TREE;
}
return NULL_TREE;
}
/* Handle a "ms_abi" or "sysv" attribute; arguments as in
struct attribute_spec.handler. */
static tree
@ -32229,6 +32294,8 @@ static const struct attribute_spec ix86_attribute_table[] =
{ "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
{ "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
{ "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute },
{ "callee_pop_aggregate_return", 1, 1, false, true, true,
ix86_handle_callee_pop_aggregate_return },
/* End element. */
{ NULL, 0, 0, false, false, false, NULL }
};

View File

@ -2823,6 +2823,19 @@ when targeting Windows. On all other systems, the default is the AMD ABI.
Note, the @code{ms_abi} attribute for Windows targets currently requires
the @option{-maccumulate-outgoing-args} option.
@item callee_pop_aggregate_return (@var{number})
@cindex @code{callee_pop_aggregate_return} attribute
On 32-bit i?86-*-* targets, you can control by those attribute for
aggregate return in memory, if the caller is responsible to pop the hidden
pointer together with the rest of the arguments - @var{number} equal to
zero -, or if the callee is responsible to pop hidden pointer - @var{number}
equal to one.
For i?86-netware, the caller pops the stack for the hidden arguments pointing
to aggregate return value. This differs from the default i386 ABI which assumes
that the callee pops the stack for hidden pointer.
@item ms_hook_prologue
@cindex @code{ms_hook_prologue} attribute

View File

@ -1,3 +1,9 @@
2010-12-18 Kai Tietz <kai.tietz@onevision.com>
PR target/36834
* gcc.target/i386/aggregate-ret1.c: New.
* gcc.target/i386/aggregate-ret2.c: New.
2010-12-18 Iain Sandoe <iains@gcc.gnu.org>
* gcc.target/powerpc/darwin-split-ld-stret.c: New test.

View File

@ -0,0 +1,28 @@
/* target/36834 */
/* Check that, with keep_aggregate_return_pointer attribute, callee does
not pop the stack for the implicit pointer arg when returning a large
structure in memory. */
/* { dg-do compile { target i?86-*-* } } */
struct foo {
int a;
int b;
int c;
int d;
};
__attribute__ ((callee_pop_aggregate_return(0)))
struct foo
bar (void)
{
struct foo retval;
retval.a = 1;
retval.b = 2;
retval.c = 3;
retval.d = 4;
return retval;
}
/* { dg-final { scan-assembler-not "ret\[ \t\]\\\$4" } } */

View File

@ -0,0 +1,28 @@
/* target/36834 */
/* Check that, with dont_keep_aggregate_return_pointer attribute, callee
pops the stack for the implicit pointer arg when returning a large
structure in memory. */
/* { dg-do compile { target i?86-*-* } } */
struct foo {
int a;
int b;
int c;
int d;
};
__attribute__ ((callee_pop_aggregate_return(1)))
struct foo
bar (void)
{
struct foo retval;
retval.a = 1;
retval.b = 2;
retval.c = 3;
retval.d = 4;
return retval;
}
/* { dg-final { scan-assembler "ret\[ \t\]\\\$4" } } */