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:
parent
a6e4343fc4
commit
628c4eee53
|
@ -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>
|
2010-12-18 Iain Sandoe <iains@gcc.gnu.org>
|
||||||
|
|
||||||
* config/darwin.h (SUBTARGET_C_COMMON_OVERRIDE_OPTIONS):
|
* config/darwin.h (SUBTARGET_C_COMMON_OVERRIDE_OPTIONS):
|
||||||
|
|
|
@ -5436,6 +5436,19 @@ ix86_eax_live_at_start_p (void)
|
||||||
return REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR), 0);
|
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
|
/* Value is the number of bytes of arguments automatically
|
||||||
popped when returning from a subroutine call.
|
popped when returning from a subroutine call.
|
||||||
FUNDECL is the declaration node of the function (as a tree),
|
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. */
|
/* Lose any fake structure return argument if it is passed on the stack. */
|
||||||
if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
|
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);
|
int nregs = ix86_function_regparm (funtype, fundecl);
|
||||||
if (nregs == 0)
|
if (nregs == 0)
|
||||||
|
@ -29060,6 +29073,58 @@ x86_order_regs_for_local_alloc (void)
|
||||||
reg_alloc_order [pos++] = 0;
|
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
|
/* Handle a "ms_abi" or "sysv" attribute; arguments as in
|
||||||
struct attribute_spec.handler. */
|
struct attribute_spec.handler. */
|
||||||
static tree
|
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 },
|
{ "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
|
||||||
{ "sysv_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 },
|
{ "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. */
|
/* End element. */
|
||||||
{ NULL, 0, 0, false, false, false, NULL }
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
Note, the @code{ms_abi} attribute for Windows targets currently requires
|
||||||
the @option{-maccumulate-outgoing-args} option.
|
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
|
@item ms_hook_prologue
|
||||||
@cindex @code{ms_hook_prologue} attribute
|
@cindex @code{ms_hook_prologue} attribute
|
||||||
|
|
||||||
|
|
|
@ -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>
|
2010-12-18 Iain Sandoe <iains@gcc.gnu.org>
|
||||||
|
|
||||||
* gcc.target/powerpc/darwin-split-ld-stret.c: New test.
|
* gcc.target/powerpc/darwin-split-ld-stret.c: New test.
|
||||||
|
|
|
@ -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" } } */
|
||||||
|
|
||||||
|
|
|
@ -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" } } */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue