winebuild: Add support for fastcall entry points.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
28debd82fc
commit
84a7a7ea07
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue