cygming.h (TARGET_OS_CPP_BUILTINS): Add __thiscall and _thiscall as predefined macros.
2010-04-09 Kai Tietz <kai.tietz@onevision.com> * config/i386/cygming.h (TARGET_OS_CPP_BUILTINS): Add __thiscall and _thiscall as predefined macros. * config/i386/i386.c (ix86_handle_cconv_attribute): Add thiscall attribute handling. (ix86_comp_type_attributes): Likewise. (ix86_function_regparm): Likewise. (ix86_return_pops_args): Likewise. (init_cumulative_args): Likewise. (find_drap_reg): Likewise. (ix86_static_chain): Likewise. (x86_this_parameter): Likewise. (x86_output_mi_thunk): Likewise. (ix86_attribute_table): Add description for thiscall attribute. * config/i386/i386.h (ix86_args): Adjust comment for member fastcall. * doc/extend.texi: Add documentation for thiscall. From-SVN: r158155
This commit is contained in:
parent
c688a8b0d7
commit
3e65f25191
|
@ -1,3 +1,22 @@
|
|||
2010-04-09 Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
* config/i386/cygming.h (TARGET_OS_CPP_BUILTINS): Add
|
||||
__thiscall and _thiscall as predefined macros.
|
||||
* config/i386/i386.c (ix86_handle_cconv_attribute): Add
|
||||
thiscall attribute handling.
|
||||
(ix86_comp_type_attributes): Likewise.
|
||||
(ix86_function_regparm): Likewise.
|
||||
(ix86_return_pops_args): Likewise.
|
||||
(init_cumulative_args): Likewise.
|
||||
(find_drap_reg): Likewise.
|
||||
(ix86_static_chain): Likewise.
|
||||
(x86_this_parameter): Likewise.
|
||||
(x86_output_mi_thunk): Likewise.
|
||||
(ix86_attribute_table): Add description for thiscall attribute.
|
||||
* config/i386/i386.h (ix86_args): Adjust comment for member
|
||||
fastcall.
|
||||
* doc/extend.texi: Add documentation for thiscall.
|
||||
|
||||
2010-04-09 Manuel López-Ibáñez <manu@gcc.gnu.org>
|
||||
|
||||
PR c++/28584
|
||||
|
|
|
@ -79,11 +79,13 @@ along with GCC; see the file COPYING3. If not see
|
|||
builtin_assert ("system=winnt"); \
|
||||
builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
|
||||
builtin_define ("__fastcall=__attribute__((__fastcall__))"); \
|
||||
builtin_define ("__thiscall=__attribute__((__thiscall__))"); \
|
||||
builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
|
||||
if (!flag_iso) \
|
||||
{ \
|
||||
builtin_define ("_stdcall=__attribute__((__stdcall__))"); \
|
||||
builtin_define ("_fastcall=__attribute__((__fastcall__))"); \
|
||||
builtin_define ("_thiscall=__attribute__((__thiscall__))"); \
|
||||
builtin_define ("_cdecl=__attribute__((__cdecl__))"); \
|
||||
} \
|
||||
/* Even though linkonce works with static libs, this is needed \
|
||||
|
|
|
@ -4395,8 +4395,8 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Handle "cdecl", "stdcall", "fastcall", "regparm" and "sseregparm"
|
||||
calling convention attributes;
|
||||
/* Handle "cdecl", "stdcall", "fastcall", "regparm", "thiscall",
|
||||
and "sseregparm" calling convention attributes;
|
||||
arguments as in struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
|
@ -4426,6 +4426,11 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
|||
error ("fastcall and regparm attributes are not compatible");
|
||||
}
|
||||
|
||||
if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("regparam and thiscall attributes are not compatible");
|
||||
}
|
||||
|
||||
cst = TREE_VALUE (args);
|
||||
if (TREE_CODE (cst) != INTEGER_CST)
|
||||
{
|
||||
|
@ -4471,6 +4476,10 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
|||
{
|
||||
error ("fastcall and regparm attributes are not compatible");
|
||||
}
|
||||
if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("fastcall and thiscall attributes are not compatible");
|
||||
}
|
||||
}
|
||||
|
||||
/* Can combine stdcall with fastcall (redundant), regparm and
|
||||
|
@ -4485,6 +4494,10 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
|||
{
|
||||
error ("stdcall and fastcall attributes are not compatible");
|
||||
}
|
||||
if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("stdcall and thiscall attributes are not compatible");
|
||||
}
|
||||
}
|
||||
|
||||
/* Can combine cdecl with regparm and sseregparm. */
|
||||
|
@ -4498,6 +4511,28 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
|||
{
|
||||
error ("fastcall and cdecl attributes are not compatible");
|
||||
}
|
||||
if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("cdecl and thiscall attributes are not compatible");
|
||||
}
|
||||
}
|
||||
else if (is_attribute_p ("thiscall", name))
|
||||
{
|
||||
if (TREE_CODE (*node) != METHOD_TYPE && pedantic)
|
||||
warning (OPT_Wattributes, "%qE attribute is used for none class-method",
|
||||
name);
|
||||
if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("stdcall and thiscall attributes are not compatible");
|
||||
}
|
||||
if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("fastcall and thiscall attributes are not compatible");
|
||||
}
|
||||
if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
|
||||
{
|
||||
error ("cdecl and thiscall attributes are not compatible");
|
||||
}
|
||||
}
|
||||
|
||||
/* Can combine sseregparm with all attributes. */
|
||||
|
@ -4531,6 +4566,11 @@ ix86_comp_type_attributes (const_tree type1, const_tree type2)
|
|||
!= !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
|
||||
return 0;
|
||||
|
||||
/* Check for mismatched thiscall types. */
|
||||
if (!lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type1))
|
||||
!= !lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type2)))
|
||||
return 0;
|
||||
|
||||
/* Check for mismatched return types (cdecl vs stdcall). */
|
||||
if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
|
||||
!= !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
|
||||
|
@ -4564,6 +4604,9 @@ ix86_function_regparm (const_tree type, const_tree decl)
|
|||
if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
|
||||
return 2;
|
||||
|
||||
if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)))
|
||||
return 1;
|
||||
|
||||
/* Use register calling convention for local functions when possible. */
|
||||
if (decl
|
||||
&& TREE_CODE (decl) == FUNCTION_DECL
|
||||
|
@ -4701,7 +4744,8 @@ ix86_return_pops_args (tree fundecl, tree funtype, int size)
|
|||
/* Stdcall and fastcall functions will pop the stack if not
|
||||
variable args. */
|
||||
if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
|
||||
|| lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
|
||||
|| lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype))
|
||||
|| lookup_attribute ("thiscall", TYPE_ATTRIBUTES (funtype)))
|
||||
rtd = 1;
|
||||
|
||||
if (rtd && ! stdarg_p (funtype))
|
||||
|
@ -4964,7 +5008,12 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
|
|||
else look for regparm information. */
|
||||
if (fntype)
|
||||
{
|
||||
if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
|
||||
if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)))
|
||||
{
|
||||
cum->nregs = 1;
|
||||
cum->fastcall = 1; /* Same first register as in fastcall. */
|
||||
}
|
||||
else if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
|
||||
{
|
||||
cum->nregs = 2;
|
||||
cum->fastcall = 1;
|
||||
|
@ -8303,6 +8352,8 @@ find_drap_reg (void)
|
|||
passing. */
|
||||
if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2
|
||||
&& !lookup_attribute ("fastcall",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (decl)))
|
||||
&& !lookup_attribute ("thiscall",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (decl))))
|
||||
return CX_REG;
|
||||
else
|
||||
|
@ -20157,6 +20208,12 @@ ix86_static_chain (const_tree fndecl, bool incoming_p)
|
|||
us with EAX for the static chain. */
|
||||
regno = AX_REG;
|
||||
}
|
||||
else if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)))
|
||||
{
|
||||
/* Thiscall functions use ecx for arguments, which leaves
|
||||
us with EAX for the static chain. */
|
||||
regno = AX_REG;
|
||||
}
|
||||
else if (ix86_function_regparm (fntype, fndecl) == 3)
|
||||
{
|
||||
/* For regparm 3, we have no free call-clobbered registers in
|
||||
|
@ -26124,6 +26181,11 @@ x86_this_parameter (tree function)
|
|||
|
||||
if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
|
||||
regno = aggr ? DX_REG : CX_REG;
|
||||
/* ???: To be verified. It is not absolutely clear how aggregates
|
||||
have to be treated for thiscall. We assume that they are
|
||||
identical to fastcall. */
|
||||
else if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)))
|
||||
regno = aggr ? DX_REG : CX_REG;
|
||||
else
|
||||
{
|
||||
regno = AX_REG;
|
||||
|
@ -26235,7 +26297,9 @@ x86_output_mi_thunk (FILE *file,
|
|||
{
|
||||
int tmp_regno = CX_REG;
|
||||
if (lookup_attribute ("fastcall",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (function))))
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (function)))
|
||||
|| lookup_attribute ("thiscall",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (function))))
|
||||
tmp_regno = AX_REG;
|
||||
tmp = gen_rtx_REG (SImode, tmp_regno);
|
||||
}
|
||||
|
@ -28975,6 +29039,9 @@ static const struct attribute_spec ix86_attribute_table[] =
|
|||
/* Fastcall attribute says callee is responsible for popping arguments
|
||||
if they are not variable. */
|
||||
{ "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute },
|
||||
/* Thiscall attribute says callee is responsible for popping arguments
|
||||
if they are not variable. */
|
||||
{ "thiscall", 0, 0, false, true, true, ix86_handle_cconv_attribute },
|
||||
/* Cdecl attribute says the callee is a normal C declaration */
|
||||
{ "cdecl", 0, 0, false, true, true, ix86_handle_cconv_attribute },
|
||||
/* Regparm attribute specifies how many integer arguments are to be
|
||||
|
|
|
@ -1580,7 +1580,8 @@ typedef struct ix86_args {
|
|||
int words; /* # words passed so far */
|
||||
int nregs; /* # registers available for passing */
|
||||
int regno; /* next available register number */
|
||||
int fastcall; /* fastcall calling convention is used */
|
||||
int fastcall; /* fastcall or thiscall calling convention
|
||||
is used */
|
||||
int sse_words; /* # sse words passed so far */
|
||||
int sse_nregs; /* # sse registers available for passing */
|
||||
int warn_avx; /* True when we want to warn about AVX ABI. */
|
||||
|
|
|
@ -2323,6 +2323,18 @@ and other typed arguments are passed on the stack. The called function will
|
|||
pop the arguments off the stack. If the number of arguments is variable all
|
||||
arguments are pushed on the stack.
|
||||
|
||||
@item thiscall
|
||||
@cindex functions that pop the argument stack on the 386
|
||||
On the Intel 386, the @code{thiscall} attribute causes the compiler to
|
||||
pass the first argument (if of integral type) in the register ECX.
|
||||
Subsequent and other typed arguments are passed on the stack. The called
|
||||
function will pop the arguments off the stack.
|
||||
If the number of arguments is variable all arguments are pushed on the
|
||||
stack.
|
||||
The @code{thiscall} attribute is intended for C++ non-static member functions.
|
||||
As gcc extension this calling convention can be used for C-functions
|
||||
and for static member methods.
|
||||
|
||||
@item format (@var{archetype}, @var{string-index}, @var{first-to-check})
|
||||
@cindex @code{format} function attribute
|
||||
@opindex Wformat
|
||||
|
|
Loading…
Reference in New Issue