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