Alexandre Julliard : winebuild: Add support for fastcall entry points.
Alexandre Julliard
julliard at winehq.org
Thu Feb 28 16:09:42 CST 2019
Module: wine
Branch: master
Commit: 84a7a7ea0769d6dd833cd6d1d4f2502996d92690
URL: https://source.winehq.org/git/wine.git/?a=commit;h=84a7a7ea0769d6dd833cd6d1d4f2502996d92690
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Feb 27 17:11:08 2019 +0100
winebuild: Add support for fastcall entry points.
Signed-off-by: Alexandre Julliard <julliard at 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
More information about the wine-cvs
mailing list