winebuild: Use a proper enum for function arguments instead of storing them in a string.
This commit is contained in:
parent
2a5b375580
commit
e0188c8340
|
@ -58,6 +58,22 @@ typedef enum
|
|||
SPEC_WIN32
|
||||
} SPEC_TYPE;
|
||||
|
||||
enum arg_type
|
||||
{
|
||||
ARG_WORD, /* 16-bit word */
|
||||
ARG_SWORD, /* 16-bit signed word */
|
||||
ARG_SEGPTR, /* segmented pointer */
|
||||
ARG_SEGSTR, /* segmented pointer to Ansi string */
|
||||
ARG_LONG, /* long */
|
||||
ARG_PTR, /* pointer */
|
||||
ARG_STR, /* pointer to Ansi string */
|
||||
ARG_WSTR, /* pointer to Unicode string */
|
||||
ARG_DOUBLE, /* floating point double */
|
||||
ARG_MAXARG = ARG_DOUBLE
|
||||
};
|
||||
|
||||
#define MAX_ARGUMENTS 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int n_values;
|
||||
|
@ -66,7 +82,8 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
char arg_types[21];
|
||||
unsigned int nb_args;
|
||||
enum arg_type args[MAX_ARGUMENTS];
|
||||
} ORD_FUNCTION;
|
||||
|
||||
typedef struct
|
||||
|
@ -244,6 +261,7 @@ extern enum target_cpu get_cpu_from_name( const char *name );
|
|||
extern unsigned int get_alignment(unsigned int align);
|
||||
extern unsigned int get_page_size(void);
|
||||
extern unsigned int get_ptr_size(void);
|
||||
extern unsigned int get_args_size( const ORDDEF *odp );
|
||||
extern const char *asm_name( const char *func );
|
||||
extern const char *func_declaration( const char *func );
|
||||
extern const char *asm_globl( const char *func );
|
||||
|
|
|
@ -72,6 +72,19 @@ static const char * const FlagNames[] =
|
|||
NULL
|
||||
};
|
||||
|
||||
static const char * const ArgNames[ARG_MAXARG + 1] =
|
||||
{
|
||||
"word", /* ARG_WORD */
|
||||
"s_word", /* ARG_SWORD */
|
||||
"segptr", /* ARG_SEGPTR */
|
||||
"segstr", /* ARG_SEGSTR */
|
||||
"long", /* ARG_LONG */
|
||||
"ptr", /* ARG_PTR */
|
||||
"str", /* ARG_STR */
|
||||
"wstr", /* ARG_WSTR */
|
||||
"double" /* ARG_DOUBLE */
|
||||
};
|
||||
|
||||
static int IsNumberString(const char *s)
|
||||
{
|
||||
while (*s) if (!isdigit(*s++)) return 0;
|
||||
|
@ -228,7 +241,7 @@ static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
|
|||
static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
unsigned int i;
|
||||
unsigned int i, arg;
|
||||
int is_win32 = (spec->type == SPEC_WIN32) || (odp->flags & FLAG_EXPORT32);
|
||||
|
||||
if (!is_win32 && odp->type == TYPE_STDCALL)
|
||||
|
@ -254,61 +267,42 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(odp->u.func.arg_types); i++)
|
||||
odp->u.func.nb_args = 0;
|
||||
for (i = 0; i < MAX_ARGUMENTS; i++)
|
||||
{
|
||||
if (!(token = GetToken(0))) return 0;
|
||||
if (*token == ')')
|
||||
break;
|
||||
|
||||
if (!strcmp(token, "word"))
|
||||
odp->u.func.arg_types[i] = 'w';
|
||||
else if (!strcmp(token, "s_word"))
|
||||
odp->u.func.arg_types[i] = 's';
|
||||
else if (!strcmp(token, "long") || !strcmp(token, "segptr"))
|
||||
odp->u.func.arg_types[i] = 'l';
|
||||
else if (!strcmp(token, "ptr"))
|
||||
odp->u.func.arg_types[i] = 'p';
|
||||
else if (!strcmp(token, "str"))
|
||||
odp->u.func.arg_types[i] = 't';
|
||||
else if (!strcmp(token, "wstr"))
|
||||
odp->u.func.arg_types[i] = 'W';
|
||||
else if (!strcmp(token, "segstr"))
|
||||
odp->u.func.arg_types[i] = 'T';
|
||||
else if (!strcmp(token, "double"))
|
||||
{
|
||||
odp->u.func.arg_types[i++] = 'l';
|
||||
if (get_ptr_size() == 4 && i < sizeof(odp->u.func.arg_types))
|
||||
odp->u.func.arg_types[i] = 'l';
|
||||
}
|
||||
else
|
||||
for (arg = 0; arg <= ARG_MAXARG; arg++)
|
||||
if (!strcmp( ArgNames[arg], token )) break;
|
||||
|
||||
if (arg > ARG_MAXARG)
|
||||
{
|
||||
error( "Unknown argument type '%s'\n", token );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_win32)
|
||||
if (is_win32) switch (arg)
|
||||
{
|
||||
if (strcmp(token, "long") &&
|
||||
strcmp(token, "ptr") &&
|
||||
strcmp(token, "str") &&
|
||||
strcmp(token, "wstr") &&
|
||||
strcmp(token, "double"))
|
||||
{
|
||||
error( "Type '%s' not supported for Win32 function\n", token );
|
||||
return 0;
|
||||
}
|
||||
case ARG_WORD:
|
||||
case ARG_SWORD:
|
||||
case ARG_SEGPTR:
|
||||
case ARG_SEGSTR:
|
||||
error( "Argument type '%s' only allowed for Win16\n", token );
|
||||
return 0;
|
||||
}
|
||||
odp->u.func.args[i] = arg;
|
||||
}
|
||||
if ((*token != ')') || (i >= sizeof(odp->u.func.arg_types)))
|
||||
if (*token != ')')
|
||||
{
|
||||
error( "Too many arguments\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
odp->u.func.arg_types[i] = '\0';
|
||||
odp->u.func.nb_args = i;
|
||||
if (odp->type == TYPE_VARARGS)
|
||||
odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */
|
||||
if (odp->type == TYPE_THISCALL && odp->u.func.arg_types[0] != 'p')
|
||||
if (odp->type == TYPE_THISCALL && (!i || odp->u.func.args[0] != ARG_PTR))
|
||||
{
|
||||
error( "First argument of a thiscall function must be a pointer\n" );
|
||||
return 0;
|
||||
|
@ -386,7 +380,7 @@ static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
|
|||
*/
|
||||
static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
odp->u.func.arg_types[0] = '\0';
|
||||
odp->u.func.nb_args = 0;
|
||||
odp->link_name = xstrdup("");
|
||||
odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64); /* don't bother generating stubs for Winelib */
|
||||
return 1;
|
||||
|
@ -806,7 +800,8 @@ void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 )
|
|||
odp->lineno = odp16->lineno;
|
||||
odp->ordinal = -1;
|
||||
odp->link_name = xstrdup( odp16->link_name );
|
||||
strcpy( odp->u.func.arg_types, odp16->u.func.arg_types );
|
||||
odp->u.func.nb_args = odp16->u.func.nb_args;
|
||||
memcpy( odp->u.func.args, odp16->u.func.args, odp->u.func.nb_args * sizeof(odp->u.func.args[0]) );
|
||||
}
|
||||
|
||||
assign_names( spec32 );
|
||||
|
@ -936,18 +931,23 @@ static int parse_def_export( char *name, DLLSPEC *spec )
|
|||
odp->ordinal = -1;
|
||||
odp->name = name;
|
||||
args = remove_stdcall_decoration( odp->name );
|
||||
if (args == -1) odp->type = TYPE_CDECL;
|
||||
if (args == -1)
|
||||
{
|
||||
odp->type = TYPE_CDECL;
|
||||
args = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
odp->type = TYPE_STDCALL;
|
||||
args /= get_ptr_size();
|
||||
if (args >= sizeof(odp->u.func.arg_types))
|
||||
if (args >= MAX_ARGUMENTS)
|
||||
{
|
||||
error( "Too many arguments in stdcall function '%s'\n", odp->name );
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < args; i++) odp->u.func.arg_types[i] = 'l';
|
||||
for (i = 0; i < args; i++) odp->u.func.args[i] = ARG_LONG;
|
||||
}
|
||||
odp->u.func.nb_args = args;
|
||||
|
||||
/* check for optional internal name */
|
||||
|
||||
|
|
|
@ -36,14 +36,14 @@
|
|||
/* argument type flags for relay debugging */
|
||||
enum arg_types
|
||||
{
|
||||
ARG_NONE = 0, /* indicates end of arg list */
|
||||
ARG_WORD, /* unsigned word */
|
||||
ARG_SWORD, /* signed word */
|
||||
ARG_LONG, /* long or segmented pointer */
|
||||
ARG_PTR, /* linear pointer */
|
||||
ARG_STR, /* linear pointer to null-terminated string */
|
||||
ARG_SEGSTR, /* segmented pointer to null-terminated string */
|
||||
ARG_VARARG /* start of varargs */
|
||||
ARG16_NONE = 0, /* indicates end of arg list */
|
||||
ARG16_WORD, /* unsigned word */
|
||||
ARG16_SWORD, /* signed word */
|
||||
ARG16_LONG, /* long or segmented pointer */
|
||||
ARG16_PTR, /* linear pointer */
|
||||
ARG16_STR, /* linear pointer to null-terminated string */
|
||||
ARG16_SEGSTR, /* segmented pointer to null-terminated string */
|
||||
ARG16_VARARG /* start of varargs */
|
||||
};
|
||||
|
||||
/* sequences of nops to fill a certain number of words */
|
||||
|
@ -64,6 +64,30 @@ static inline int is_function( const ORDDEF *odp )
|
|||
odp->type == TYPE_STUB);
|
||||
}
|
||||
|
||||
static const char *get_args_str( const ORDDEF *odp )
|
||||
{
|
||||
static char buffer[MAX_ARGUMENTS*2+1];
|
||||
unsigned int i;
|
||||
|
||||
buffer[0] = 0;
|
||||
for (i = 0; i < odp->u.func.nb_args; i++)
|
||||
{
|
||||
switch (odp->u.func.args[i])
|
||||
{
|
||||
case ARG_WORD: strcat( buffer, "w" ); break;
|
||||
case ARG_SWORD: strcat( buffer, "s" ); break;
|
||||
case ARG_SEGSTR: strcat( buffer, "T" ); break;
|
||||
case ARG_STR: strcat( buffer, "t" ); break;
|
||||
case ARG_DOUBLE: strcat( buffer, "ll" ); break;
|
||||
case ARG_LONG:
|
||||
case ARG_SEGPTR: strcat( buffer, "l" ); break;
|
||||
case ARG_PTR:
|
||||
case ARG_WSTR: strcat( buffer, "p" ); break;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* output_entries
|
||||
*
|
||||
|
@ -203,7 +227,7 @@ static const char *get_callfrom16_name( const ORDDEF *odp )
|
|||
(odp->type == TYPE_VARARGS) ? "v" : "c",
|
||||
(odp->flags & FLAG_REGISTER) ? "regs" :
|
||||
(odp->flags & FLAG_RET16) ? "word" : "long",
|
||||
odp->u.func.arg_types );
|
||||
get_args_str(odp) );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -231,7 +255,7 @@ static const char *get_relay_name( const ORDDEF *odp )
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
strcat( buffer, odp->u.func.arg_types );
|
||||
strcat( buffer, get_args_str(odp) );
|
||||
for (p = buffer + 2; *p; p++)
|
||||
{
|
||||
/* map string types to the corresponding plain pointer type */
|
||||
|
@ -248,25 +272,27 @@ static const char *get_relay_name( const ORDDEF *odp )
|
|||
*/
|
||||
static int get_function_argsize( const ORDDEF *odp )
|
||||
{
|
||||
const char *args;
|
||||
int argsize = 0;
|
||||
unsigned int i, argsize = 0;
|
||||
|
||||
for (args = odp->u.func.arg_types; *args; args++)
|
||||
for (i = 0; i < odp->u.func.nb_args; i++)
|
||||
{
|
||||
switch (*args)
|
||||
switch (odp->u.func.args[i])
|
||||
{
|
||||
case 'w': /* word */
|
||||
case 's': /* s_word */
|
||||
case ARG_WORD:
|
||||
case ARG_SWORD:
|
||||
argsize += 2;
|
||||
break;
|
||||
case 'l': /* long or segmented pointer */
|
||||
case 'T': /* segmented pointer to null-terminated string */
|
||||
case 'p': /* linear pointer */
|
||||
case 't': /* linear pointer to null-terminated string */
|
||||
case ARG_SEGPTR:
|
||||
case ARG_SEGSTR:
|
||||
case ARG_LONG:
|
||||
case ARG_PTR:
|
||||
case ARG_STR:
|
||||
case ARG_WSTR:
|
||||
argsize += 4;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
case ARG_DOUBLE:
|
||||
argsize += 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return argsize;
|
||||
|
@ -304,9 +330,8 @@ static void output_call16_function( ORDDEF *odp )
|
|||
{
|
||||
char *name;
|
||||
int i, pos, stack_words;
|
||||
const char *args = odp->u.func.arg_types;
|
||||
int argsize = get_function_argsize( odp );
|
||||
int needs_ldt = strchr( args, 'p' ) || strchr( args, 't' );
|
||||
int needs_ldt = (strpbrk( get_args_str( odp ), "pt" ) != NULL);
|
||||
|
||||
name = strmake( ".L__wine_spec_call16_%s", get_relay_name(odp) );
|
||||
|
||||
|
@ -335,11 +360,13 @@ static void output_call16_function( ORDDEF *odp )
|
|||
}
|
||||
|
||||
/* preserve 16-byte stack alignment */
|
||||
stack_words += strlen(args);
|
||||
stack_words += odp->u.func.nb_args;
|
||||
for (i = 0; i < odp->u.func.nb_args; i++)
|
||||
if (odp->u.func.args[i] == ARG_DOUBLE) stack_words++;
|
||||
if ((odp->flags & FLAG_REGISTER) || (odp->type == TYPE_VARARGS)) stack_words++;
|
||||
if (stack_words % 4) output( "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) );
|
||||
|
||||
if (args[0] || odp->type == TYPE_VARARGS)
|
||||
if (odp->u.func.nb_args || odp->type == TYPE_VARARGS)
|
||||
output( "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
|
||||
|
||||
if (odp->flags & FLAG_REGISTER)
|
||||
|
@ -353,33 +380,40 @@ static void output_call16_function( ORDDEF *odp )
|
|||
}
|
||||
|
||||
pos = (odp->type == TYPE_PASCAL) ? 0 : argsize;
|
||||
for (i = strlen(args) - 1; i >= 0; i--)
|
||||
for (i = odp->u.func.nb_args - 1; i >= 0; i--)
|
||||
{
|
||||
switch (args[i])
|
||||
switch (odp->u.func.args[i])
|
||||
{
|
||||
case 'w': /* word */
|
||||
case ARG_WORD:
|
||||
if (odp->type != TYPE_PASCAL) pos -= 2;
|
||||
output( "\tmovzwl %d(%%ecx),%%eax\n", pos );
|
||||
output( "\tpushl %%eax\n" );
|
||||
if (odp->type == TYPE_PASCAL) pos += 2;
|
||||
break;
|
||||
|
||||
case 's': /* s_word */
|
||||
case ARG_SWORD:
|
||||
if (odp->type != TYPE_PASCAL) pos -= 2;
|
||||
output( "\tmovswl %d(%%ecx),%%eax\n", pos );
|
||||
output( "\tpushl %%eax\n" );
|
||||
if (odp->type == TYPE_PASCAL) pos += 2;
|
||||
break;
|
||||
|
||||
case 'l': /* long or segmented pointer */
|
||||
case 'T': /* segmented pointer to null-terminated string */
|
||||
case ARG_DOUBLE:
|
||||
if (odp->type != TYPE_PASCAL) pos -= 4;
|
||||
output( "\tpushl %d(%%ecx)\n", pos );
|
||||
if (odp->type == TYPE_PASCAL) pos += 4;
|
||||
/* fall through */
|
||||
case ARG_LONG:
|
||||
case ARG_SEGPTR:
|
||||
case ARG_SEGSTR:
|
||||
if (odp->type != TYPE_PASCAL) pos -= 4;
|
||||
output( "\tpushl %d(%%ecx)\n", pos );
|
||||
if (odp->type == TYPE_PASCAL) pos += 4;
|
||||
break;
|
||||
|
||||
case 'p': /* linear pointer */
|
||||
case 't': /* linear pointer to null-terminated string */
|
||||
case ARG_PTR:
|
||||
case ARG_STR:
|
||||
case ARG_WSTR:
|
||||
if (odp->type != TYPE_PASCAL) pos -= 4;
|
||||
output( "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
|
||||
output( "\tshr $3,%%edx\n" );
|
||||
|
@ -388,9 +422,6 @@ static void output_call16_function( ORDDEF *odp )
|
|||
output( "\tpushl %%eax\n" );
|
||||
if (odp->type == TYPE_PASCAL) pos += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,6 +454,7 @@ static int callfrom16_type_compare( const void *e1, const void *e2 )
|
|||
int retval;
|
||||
int type1 = odp1->type;
|
||||
int type2 = odp2->type;
|
||||
char args1[80];
|
||||
|
||||
if (type1 == TYPE_STUB) type1 = TYPE_CDECL;
|
||||
if (type2 == TYPE_STUB) type2 = TYPE_CDECL;
|
||||
|
@ -434,7 +466,8 @@ static int callfrom16_type_compare( const void *e1, const void *e2 )
|
|||
|
||||
if ((retval = type1 - type2) != 0) return retval;
|
||||
|
||||
return strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
|
||||
strcpy( args1, get_args_str( odp1 ));
|
||||
return strcmp( args1, get_args_str( odp2 ));
|
||||
}
|
||||
|
||||
|
||||
|
@ -504,7 +537,7 @@ static void output_module16( DLLSPEC *spec )
|
|||
entry_point->name = NULL;
|
||||
entry_point->link_name = xstrdup( spec->init_func );
|
||||
entry_point->export_name = NULL;
|
||||
entry_point->u.func.arg_types[0] = 0;
|
||||
entry_point->u.func.nb_args = 0;
|
||||
assert( !spec->ordinals[0] );
|
||||
spec->ordinals[0] = entry_point;
|
||||
}
|
||||
|
@ -654,28 +687,36 @@ static void output_module16( DLLSPEC *spec )
|
|||
for ( i = 0; i < nb_funcs; i++ )
|
||||
{
|
||||
unsigned int arg_types[2];
|
||||
int nop_words, argsize = 0;
|
||||
int nop_words, pos, argsize = 0;
|
||||
|
||||
if ( typelist[i]->type == TYPE_PASCAL )
|
||||
argsize = get_function_argsize( typelist[i] );
|
||||
|
||||
/* build the arg types bit fields */
|
||||
arg_types[0] = arg_types[1] = 0;
|
||||
for (j = 0; typelist[i]->u.func.arg_types[j]; j++)
|
||||
for (j = pos = 0; j < typelist[i]->u.func.nb_args && pos < 20; j++, pos++)
|
||||
{
|
||||
int type = 0;
|
||||
switch(typelist[i]->u.func.arg_types[j])
|
||||
switch (typelist[i]->u.func.args[j])
|
||||
{
|
||||
case 'w': type = ARG_WORD; break;
|
||||
case 's': type = ARG_SWORD; break;
|
||||
case 'l': type = ARG_LONG; break;
|
||||
case 'p': type = ARG_PTR; break;
|
||||
case 't': type = ARG_STR; break;
|
||||
case 'T': type = ARG_SEGSTR; break;
|
||||
case ARG_WORD: type = ARG16_WORD; break;
|
||||
case ARG_SWORD: type = ARG16_SWORD; break;
|
||||
case ARG_SEGPTR: type = ARG16_LONG; break;
|
||||
case ARG_SEGSTR: type = ARG16_SEGSTR; break;
|
||||
case ARG_LONG: type = ARG16_LONG; break;
|
||||
case ARG_PTR: type = ARG16_PTR; break;
|
||||
case ARG_STR: type = ARG16_STR; break;
|
||||
case ARG_WSTR: type = ARG16_PTR; break;
|
||||
case ARG_DOUBLE:
|
||||
type = ARG16_LONG;
|
||||
arg_types[pos / 10] |= type << (3 * (pos % 10));
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
arg_types[j / 10] |= type << (3 * (j % 10));
|
||||
if (pos < 20) arg_types[pos / 10] |= type << (3 * (pos % 10));
|
||||
}
|
||||
if (typelist[i]->type == TYPE_VARARGS) arg_types[j / 10] |= ARG_VARARG << (3 * (j % 10));
|
||||
if (typelist[i]->type == TYPE_VARARGS && pos < 20)
|
||||
arg_types[pos / 10] |= ARG16_VARARG << (3 * (pos % 10));
|
||||
|
||||
output( ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
|
||||
output( "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );
|
||||
|
|
|
@ -81,7 +81,7 @@ int has_relays( DLLSPEC *spec )
|
|||
static void output_relay_debug( DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
unsigned int j, args, flags;
|
||||
unsigned int j, pos, args, flags;
|
||||
|
||||
/* first the table of entry point offsets */
|
||||
|
||||
|
@ -111,10 +111,15 @@ static void output_relay_debug( DLLSPEC *spec )
|
|||
|
||||
if (needs_relay( odp ))
|
||||
{
|
||||
for (j = 0; j < 16 && odp->u.func.arg_types[j]; j++)
|
||||
for (j = pos = 0; pos < 16 && j < odp->u.func.nb_args; j++)
|
||||
{
|
||||
if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
|
||||
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
|
||||
switch (odp->u.func.args[j])
|
||||
{
|
||||
case ARG_STR: mask |= 1 << (2 * pos++); break;
|
||||
case ARG_WSTR: mask |= 2 << (2 * pos++); break;
|
||||
case ARG_DOUBLE: pos += 8 / get_ptr_size(); break;
|
||||
default: pos++; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
output( "\t.long 0x%08x\n", mask );
|
||||
|
@ -135,7 +140,7 @@ static void output_relay_debug( DLLSPEC *spec )
|
|||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( ".L__wine_spec_relay_entry_point_%d:\n", i );
|
||||
|
||||
args = strlen(odp->u.func.arg_types);
|
||||
args = get_args_size(odp) / get_ptr_size();
|
||||
flags = 0;
|
||||
|
||||
switch (target_cpu)
|
||||
|
@ -831,7 +836,7 @@ void output_def_file( DLLSPEC *spec, int include_private )
|
|||
break;
|
||||
case TYPE_STDCALL:
|
||||
{
|
||||
int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
|
||||
int at_param = get_args_size( odp );
|
||||
if (!kill_at && target_cpu == CPU_x86) output( "@%d", at_param );
|
||||
if (odp->flags & FLAG_FORWARD)
|
||||
{
|
||||
|
|
|
@ -890,6 +890,26 @@ unsigned int get_ptr_size(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* return the total size in bytes of the arguments on the stack */
|
||||
unsigned int get_args_size( const ORDDEF *odp )
|
||||
{
|
||||
unsigned int i, size;
|
||||
|
||||
for (i = size = 0; i < odp->u.func.nb_args; i++)
|
||||
{
|
||||
switch (odp->u.func.args[i])
|
||||
{
|
||||
case ARG_DOUBLE:
|
||||
size += 8;
|
||||
break;
|
||||
default:
|
||||
size += get_ptr_size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* return the assembly name for a C symbol */
|
||||
const char *asm_name( const char *sym )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue