Module: wine Branch: master Commit: 84a7a7ea0769d6dd833cd6d1d4f2502996d92690 URL: https://source.winehq.org/git/wine.git/?a=commit;h=84a7a7ea0769d6dd833cd6d1d...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Feb 27 17:11:08 2019 +0100
winebuild: Add support for fastcall entry points.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
tools/winebuild/build.h | 7 ++++--- tools/winebuild/parser.c | 27 ++++++++++++++++++++++++--- tools/winebuild/spec32.c | 8 +++++--- tools/winebuild/winebuild.man.in | 6 ++++++ 4 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 15d22a0..eee98eb 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -173,10 +173,11 @@ struct strarray #define FLAG_PRIVATE 0x20 /* function is private (cannot be imported) */ #define FLAG_ORDINAL 0x40 /* function should be imported by ordinal */ #define FLAG_THISCALL 0x80 /* use thiscall calling convention */ +#define FLAG_FASTCALL 0x100 /* use fastcall calling convention */
-#define FLAG_FORWARD 0x100 /* function is a forwarded name */ -#define FLAG_EXT_LINK 0x200 /* function links to an external symbol */ -#define FLAG_EXPORT32 0x400 /* 32-bit export in 16-bit spec file */ +#define FLAG_FORWARD 0x200 /* function is a forwarded name */ +#define FLAG_EXT_LINK 0x400 /* function links to an external symbol */ +#define FLAG_EXPORT32 0x800 /* 32-bit export in 16-bit spec file */
#define FLAG_CPU(cpu) (0x01000 << (cpu)) #define FLAG_CPU_MASK (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0)) diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 11b05aa..dfb7f6f 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -69,6 +69,7 @@ static const char * const FlagNames[] = "private", /* FLAG_PRIVATE */ "ordinal", /* FLAG_ORDINAL */ "thiscall", /* FLAG_THISCALL */ + "fastcall", /* FLAG_FASTCALL */ NULL };
@@ -300,6 +301,24 @@ static int parse_spec_arguments( ORDDEF *odp, DLLSPEC *spec, int optional ) return 0; } } + if (odp->flags & FLAG_FASTCALL) + { + if (odp->type != TYPE_STDCALL) + { + error( "A fastcall function must use the stdcall convention\n" ); + return 0; + } + if (!i || (odp->u.func.args[0] != ARG_PTR && odp->u.func.args[0] != ARG_LONG)) + { + error( "First argument of a fastcall function must be a pointer or integer\n" ); + return 0; + } + if (i > 1 && odp->u.func.args[1] != ARG_PTR && odp->u.func.args[1] != ARG_LONG) + { + error( "Second argument of a fastcall function must be a pointer or integer\n" ); + return 0; + } + } return 1; }
@@ -331,7 +350,7 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec ) odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */
if (target_cpu != CPU_x86) - odp->flags &= ~FLAG_THISCALL; + odp->flags &= ~(FLAG_THISCALL | FLAG_FASTCALL);
if (!(token = GetToken(1))) { @@ -355,9 +374,10 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec ) odp->flags |= FLAG_FORWARD; } } - if ((odp->flags & FLAG_THISCALL) && !(odp->flags & FLAG_FORWARD)) + if ((odp->flags & (FLAG_THISCALL | FLAG_FASTCALL)) && !(odp->flags & FLAG_FORWARD)) { - char *link_name = strmake( "__thiscall_%s", odp->link_name ); + char *link_name = strmake( "__%s_%s", (odp->flags & FLAG_THISCALL) ? "thiscall" : "fastcall", + odp->link_name ); free( odp->link_name ); odp->link_name = link_name; } @@ -513,6 +533,7 @@ static const char *parse_spec_flags( DLLSPEC *spec, ORDDEF *odp ) break; case FLAG_RET64: case FLAG_THISCALL: + case FLAG_FASTCALL: if (spec->type == SPEC_WIN16) error( "Flag '%s' is not supported in Win16\n", FlagNames[i] ); break; diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 1b4e534..44d1c2c 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -128,7 +128,8 @@ static void get_arg_string( ORDDEF *odp, char str[MAX_ARGUMENTS + 1] ) break; } } - if (odp->flags & FLAG_THISCALL) str[0] = 't'; + if (odp->flags & (FLAG_THISCALL | FLAG_FASTCALL)) str[0] = 't'; + if ((odp->flags & FLAG_FASTCALL) && odp->u.func.nb_args > 1) str[1] = 't';
/* append return value */ if (get_ptr_size() == 4 && (odp->flags & FLAG_RET64)) @@ -224,9 +225,10 @@ static void output_relay_debug( DLLSPEC *spec ) switch (target_cpu) { case CPU_x86: - if (odp->flags & FLAG_THISCALL) /* add the this pointer */ + if (odp->flags & (FLAG_THISCALL | FLAG_FASTCALL)) /* add the register arguments */ { output( "\tpopl %%eax\n" ); + if ((odp->flags & FLAG_FASTCALL) && get_args_size( odp ) > 4) output( "\tpushl %%edx\n" ); output( "\tpushl %%ecx\n" ); output( "\tpushl %%eax\n" ); } @@ -966,7 +968,7 @@ void output_def_file( DLLSPEC *spec, int include_private ) else if (strcmp(name, odp->link_name)) /* try to reduce output */ { output( "=%s", odp->link_name ); - if (!kill_at && target_cpu == CPU_x86 && !(odp->flags & FLAG_THISCALL)) + if (!kill_at && target_cpu == CPU_x86 && !(odp->flags & (FLAG_THISCALL | FLAG_FASTCALL))) output( "@%d", at_param ); } break; diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index 4455e63..8f25052 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -304,6 +304,12 @@ The function uses the .I thiscall calling convention (first parameter in %ecx register on i386). .TP +.B -fastcall +The function uses the +.I fastcall +calling convention (first two parameters in %ecx/%edx registers on +i386). +.TP .RE .BI -arch= cpu\fR[\fB,\fIcpu\fR] The entry point is only available on the specified CPU