winebuild: Make thiscall an entry point flag instead of a function type.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Alexandre Julliard 2019-02-27 17:09:51 +01:00
parent d88f129507
commit 28debd82fc
5 changed files with 39 additions and 28 deletions

View File

@ -47,7 +47,6 @@ typedef enum
TYPE_STDCALL, /* stdcall function (Win32) */
TYPE_CDECL, /* cdecl function (Win32) */
TYPE_VARARGS, /* varargs function (Win32) */
TYPE_THISCALL, /* thiscall function (Win32 on i386) */
TYPE_EXTERN, /* external symbol (Win32) */
TYPE_NBTYPES
} ORD_TYPE;
@ -173,6 +172,7 @@ struct strarray
#define FLAG_REGISTER 0x10 /* use register calling convention */
#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_FORWARD 0x100 /* function is a forwarded name */
#define FLAG_EXT_LINK 0x200 /* function links to an external symbol */

View File

@ -466,7 +466,6 @@ static void check_undefined_exports( DLLSPEC *spec )
case TYPE_STDCALL:
case TYPE_CDECL:
case TYPE_VARARGS:
case TYPE_THISCALL:
if (link_ext_symbols)
{
odp->flags |= FLAG_EXT_LINK;
@ -1444,7 +1443,6 @@ static void build_unix_import_lib( DLLSPEC *spec )
case TYPE_VARARGS:
case TYPE_CDECL:
case TYPE_STDCALL:
case TYPE_THISCALL:
prefix = (!odp->name || (odp->flags & FLAG_ORDINAL)) ? import_ord_prefix : import_func_prefix;
new_output_as_file( spec->file_name );
output( "\t.text\n" );

View File

@ -56,7 +56,6 @@ static const char * const TypeNames[TYPE_NBTYPES] =
"stdcall", /* TYPE_STDCALL */
"cdecl", /* TYPE_CDECL */
"varargs", /* TYPE_VARARGS */
"thiscall", /* TYPE_THISCALL */
"extern" /* TYPE_EXTERN */
};
@ -69,6 +68,7 @@ static const char * const FlagNames[] =
"register", /* FLAG_REGISTER */
"private", /* FLAG_PRIVATE */
"ordinal", /* FLAG_ORDINAL */
"thiscall", /* FLAG_THISCALL */
NULL
};
@ -287,10 +287,18 @@ static int parse_spec_arguments( ORDDEF *odp, DLLSPEC *spec, int optional )
}
odp->u.func.nb_args = i;
if (odp->type == TYPE_THISCALL && (!i || odp->u.func.args[0] != ARG_PTR))
if (odp->flags & FLAG_THISCALL)
{
error( "First argument of a thiscall function must be a pointer\n" );
return 0;
if (odp->type != TYPE_STDCALL)
{
error( "A thiscall function must use the stdcall convention\n" );
return 0;
}
if (!i || odp->u.func.args[0] != ARG_PTR)
{
error( "First argument of a thiscall function must be a pointer\n" );
return 0;
}
}
return 1;
}
@ -311,11 +319,6 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
error( "'stdcall' not supported for Win16\n" );
return 0;
}
if (!is_win32 && odp->type == TYPE_THISCALL)
{
error( "'thiscall' not supported for Win16\n" );
return 0;
}
if (is_win32 && odp->type == TYPE_PASCAL)
{
error( "'pascal' not supported for Win32\n" );
@ -327,6 +330,9 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
if (odp->type == TYPE_VARARGS)
odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */
if (target_cpu != CPU_x86)
odp->flags &= ~FLAG_THISCALL;
if (!(token = GetToken(1)))
{
if (!strcmp( odp->name, "@" ))
@ -349,7 +355,7 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
odp->flags |= FLAG_FORWARD;
}
}
if (target_cpu == CPU_x86 && odp->type == TYPE_THISCALL && !(odp->flags & FLAG_FORWARD))
if ((odp->flags & FLAG_THISCALL) && !(odp->flags & FLAG_FORWARD))
{
char *link_name = strmake( "__thiscall_%s", odp->link_name );
free( odp->link_name );
@ -506,6 +512,7 @@ static const char *parse_spec_flags( DLLSPEC *spec, ORDDEF *odp )
error( "Flag '%s' is not supported in Win32\n", FlagNames[i] );
break;
case FLAG_RET64:
case FLAG_THISCALL:
if (spec->type == SPEC_WIN16)
error( "Flag '%s' is not supported in Win16\n", FlagNames[i] );
break;
@ -538,8 +545,16 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
if (odp->type >= TYPE_NBTYPES)
{
error( "Expected type after ordinal, found '%s' instead\n", token );
goto error;
if (!strcmp( token, "thiscall" )) /* for backwards compatibility */
{
odp->type = TYPE_STDCALL;
odp->flags |= FLAG_THISCALL;
}
else
{
error( "Expected type after ordinal, found '%s' instead\n", token );
goto error;
}
}
if (!(token = GetToken(0))) goto error;
@ -571,7 +586,6 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
case TYPE_THISCALL:
if (!parse_spec_export( odp, spec )) goto error;
break;
case TYPE_ABS:

View File

@ -58,7 +58,6 @@ static inline int needs_relay( const ORDDEF *odp )
{
case TYPE_STDCALL:
case TYPE_CDECL:
case TYPE_THISCALL:
break;
case TYPE_STUB:
if (odp->u.func.nb_args != -1) break;
@ -129,7 +128,7 @@ static void get_arg_string( ORDDEF *odp, char str[MAX_ARGUMENTS + 1] )
break;
}
}
if (target_cpu == CPU_x86 && odp->type == TYPE_THISCALL) str[0] = 't';
if (odp->flags & FLAG_THISCALL) str[0] = 't';
/* append return value */
if (get_ptr_size() == 4 && (odp->flags & FLAG_RET64))
@ -225,7 +224,7 @@ static void output_relay_debug( DLLSPEC *spec )
switch (target_cpu)
{
case CPU_x86:
if (odp->type == TYPE_THISCALL) /* add the this pointer */
if (odp->flags & FLAG_THISCALL) /* add the this pointer */
{
output( "\tpopl %%eax\n" );
output( "\tpushl %%ecx\n" );
@ -246,7 +245,7 @@ static void output_relay_debug( DLLSPEC *spec )
output( "\tcall *4(%%eax)\n" );
output_cfi( ".cfi_adjust_cfa_offset -8" );
if (odp->type == TYPE_STDCALL || odp->type == TYPE_THISCALL)
if (odp->type == TYPE_STDCALL)
output( "\tret $%u\n", get_args_size( odp ));
else
output( "\tret\n" );
@ -392,7 +391,6 @@ void output_exports( DLLSPEC *spec )
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
case TYPE_THISCALL:
if (odp->flags & FLAG_FORWARD)
{
output( "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
@ -953,7 +951,6 @@ void output_def_file( DLLSPEC *spec, int include_private )
/* fall through */
case TYPE_VARARGS:
case TYPE_CDECL:
case TYPE_THISCALL:
/* try to reduce output */
if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
output( "=%s", odp->link_name );
@ -969,7 +966,8 @@ 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) output( "@%d", at_param );
if (!kill_at && target_cpu == CPU_x86 && !(odp->flags & FLAG_THISCALL))
output( "@%d", at_param );
}
break;
}

View File

@ -299,6 +299,12 @@ accessed through GetProcAddress.
The entry point will be imported by ordinal instead of by name. The
name is still exported.
.TP
.B -thiscall
The function uses the
.I thiscall
calling convention (first parameter in %ecx register on i386).
.TP
.RE
.BI -arch= cpu\fR[\fB,\fIcpu\fR]
The entry point is only available on the specified CPU
architecture(s). The names \fBwin32\fR and \fBwin64\fR match all
@ -335,11 +341,6 @@ for a Win16 or Win32 function using the C calling convention
.B varargs
for a Win16 or Win32 function using the C calling convention with a
variable number of arguments
.TP
.B thiscall
for a Win32 function using the
.I thiscall
calling convention (first parameter in %ecx register on i386)
.RE
.PP
.I args