winebuild: Add support for fastcall entry points.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-02-27 17:11:08 +01:00
parent 28debd82fc
commit 84a7a7ea07
4 changed files with 39 additions and 9 deletions

View File

@ -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))

View File

@ -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;

View File

@ -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;

View File

@ -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