winebuild: Use a proper enum for function arguments instead of storing them in a string.

This commit is contained in:
Alexandre Julliard 2010-08-30 12:06:19 +02:00
parent 2a5b375580
commit e0188c8340
5 changed files with 183 additions and 99 deletions

View File

@ -58,6 +58,22 @@ typedef enum
SPEC_WIN32 SPEC_WIN32
} SPEC_TYPE; } 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 typedef struct
{ {
int n_values; int n_values;
@ -66,7 +82,8 @@ typedef struct
typedef struct typedef struct
{ {
char arg_types[21]; unsigned int nb_args;
enum arg_type args[MAX_ARGUMENTS];
} ORD_FUNCTION; } ORD_FUNCTION;
typedef struct 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_alignment(unsigned int align);
extern unsigned int get_page_size(void); extern unsigned int get_page_size(void);
extern unsigned int get_ptr_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 *asm_name( const char *func );
extern const char *func_declaration( const char *func ); extern const char *func_declaration( const char *func );
extern const char *asm_globl( const char *func ); extern const char *asm_globl( const char *func );

View File

@ -72,6 +72,19 @@ static const char * const FlagNames[] =
NULL 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) static int IsNumberString(const char *s)
{ {
while (*s) if (!isdigit(*s++)) return 0; 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 ) static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
{ {
const char *token; const char *token;
unsigned int i; unsigned int i, arg;
int is_win32 = (spec->type == SPEC_WIN32) || (odp->flags & FLAG_EXPORT32); int is_win32 = (spec->type == SPEC_WIN32) || (odp->flags & FLAG_EXPORT32);
if (!is_win32 && odp->type == TYPE_STDCALL) if (!is_win32 && odp->type == TYPE_STDCALL)
@ -254,61 +267,42 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
return 0; 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 = GetToken(0))) return 0;
if (*token == ')') if (*token == ')')
break; break;
if (!strcmp(token, "word")) for (arg = 0; arg <= ARG_MAXARG; arg++)
odp->u.func.arg_types[i] = 'w'; if (!strcmp( ArgNames[arg], token )) break;
else if (!strcmp(token, "s_word"))
odp->u.func.arg_types[i] = 's'; if (arg > ARG_MAXARG)
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
{ {
error( "Unknown argument type '%s'\n", token ); error( "Unknown argument type '%s'\n", token );
return 0; return 0;
} }
if (is_win32) switch (arg)
if (is_win32)
{ {
if (strcmp(token, "long") && case ARG_WORD:
strcmp(token, "ptr") && case ARG_SWORD:
strcmp(token, "str") && case ARG_SEGPTR:
strcmp(token, "wstr") && case ARG_SEGSTR:
strcmp(token, "double")) error( "Argument type '%s' only allowed for Win16\n", token );
{ return 0;
error( "Type '%s' not supported for Win32 function\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" ); error( "Too many arguments\n" );
return 0; return 0;
} }
odp->u.func.arg_types[i] = '\0'; odp->u.func.nb_args = i;
if (odp->type == TYPE_VARARGS) if (odp->type == TYPE_VARARGS)
odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */ 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" ); error( "First argument of a thiscall function must be a pointer\n" );
return 0; return 0;
@ -386,7 +380,7 @@ static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
*/ */
static int parse_spec_stub( 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->link_name = xstrdup("");
odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64); /* don't bother generating stubs for Winelib */ odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64); /* don't bother generating stubs for Winelib */
return 1; return 1;
@ -806,7 +800,8 @@ void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 )
odp->lineno = odp16->lineno; odp->lineno = odp16->lineno;
odp->ordinal = -1; odp->ordinal = -1;
odp->link_name = xstrdup( odp16->link_name ); 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 ); assign_names( spec32 );
@ -936,18 +931,23 @@ static int parse_def_export( char *name, DLLSPEC *spec )
odp->ordinal = -1; odp->ordinal = -1;
odp->name = name; odp->name = name;
args = remove_stdcall_decoration( odp->name ); args = remove_stdcall_decoration( odp->name );
if (args == -1) odp->type = TYPE_CDECL; if (args == -1)
{
odp->type = TYPE_CDECL;
args = 0;
}
else else
{ {
odp->type = TYPE_STDCALL; odp->type = TYPE_STDCALL;
args /= get_ptr_size(); 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 ); error( "Too many arguments in stdcall function '%s'\n", odp->name );
return 0; 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 */ /* check for optional internal name */

View File

@ -36,14 +36,14 @@
/* argument type flags for relay debugging */ /* argument type flags for relay debugging */
enum arg_types enum arg_types
{ {
ARG_NONE = 0, /* indicates end of arg list */ ARG16_NONE = 0, /* indicates end of arg list */
ARG_WORD, /* unsigned word */ ARG16_WORD, /* unsigned word */
ARG_SWORD, /* signed word */ ARG16_SWORD, /* signed word */
ARG_LONG, /* long or segmented pointer */ ARG16_LONG, /* long or segmented pointer */
ARG_PTR, /* linear pointer */ ARG16_PTR, /* linear pointer */
ARG_STR, /* linear pointer to null-terminated string */ ARG16_STR, /* linear pointer to null-terminated string */
ARG_SEGSTR, /* segmented pointer to null-terminated string */ ARG16_SEGSTR, /* segmented pointer to null-terminated string */
ARG_VARARG /* start of varargs */ ARG16_VARARG /* start of varargs */
}; };
/* sequences of nops to fill a certain number of words */ /* 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); 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 * output_entries
* *
@ -203,7 +227,7 @@ static const char *get_callfrom16_name( const ORDDEF *odp )
(odp->type == TYPE_VARARGS) ? "v" : "c", (odp->type == TYPE_VARARGS) ? "v" : "c",
(odp->flags & FLAG_REGISTER) ? "regs" : (odp->flags & FLAG_REGISTER) ? "regs" :
(odp->flags & FLAG_RET16) ? "word" : "long", (odp->flags & FLAG_RET16) ? "word" : "long",
odp->u.func.arg_types ); get_args_str(odp) );
return buffer; return buffer;
} }
@ -231,7 +255,7 @@ static const char *get_relay_name( const ORDDEF *odp )
default: default:
assert(0); assert(0);
} }
strcat( buffer, odp->u.func.arg_types ); strcat( buffer, get_args_str(odp) );
for (p = buffer + 2; *p; p++) for (p = buffer + 2; *p; p++)
{ {
/* map string types to the corresponding plain pointer type */ /* 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 ) static int get_function_argsize( const ORDDEF *odp )
{ {
const char *args; unsigned int i, argsize = 0;
int 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 ARG_WORD:
case 's': /* s_word */ case ARG_SWORD:
argsize += 2; argsize += 2;
break; break;
case 'l': /* long or segmented pointer */ case ARG_SEGPTR:
case 'T': /* segmented pointer to null-terminated string */ case ARG_SEGSTR:
case 'p': /* linear pointer */ case ARG_LONG:
case 't': /* linear pointer to null-terminated string */ case ARG_PTR:
case ARG_STR:
case ARG_WSTR:
argsize += 4; argsize += 4;
break; break;
default: case ARG_DOUBLE:
assert(0); argsize += 8;
break;
} }
} }
return argsize; return argsize;
@ -304,9 +330,8 @@ static void output_call16_function( ORDDEF *odp )
{ {
char *name; char *name;
int i, pos, stack_words; int i, pos, stack_words;
const char *args = odp->u.func.arg_types;
int argsize = get_function_argsize( odp ); 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) ); 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 */ /* 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 ((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 (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 */ output( "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
if (odp->flags & FLAG_REGISTER) if (odp->flags & FLAG_REGISTER)
@ -353,33 +380,40 @@ static void output_call16_function( ORDDEF *odp )
} }
pos = (odp->type == TYPE_PASCAL) ? 0 : argsize; 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; if (odp->type != TYPE_PASCAL) pos -= 2;
output( "\tmovzwl %d(%%ecx),%%eax\n", pos ); output( "\tmovzwl %d(%%ecx),%%eax\n", pos );
output( "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 2; if (odp->type == TYPE_PASCAL) pos += 2;
break; break;
case 's': /* s_word */ case ARG_SWORD:
if (odp->type != TYPE_PASCAL) pos -= 2; if (odp->type != TYPE_PASCAL) pos -= 2;
output( "\tmovswl %d(%%ecx),%%eax\n", pos ); output( "\tmovswl %d(%%ecx),%%eax\n", pos );
output( "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 2; if (odp->type == TYPE_PASCAL) pos += 2;
break; break;
case 'l': /* long or segmented pointer */ case ARG_DOUBLE:
case 'T': /* segmented pointer to null-terminated string */ 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; if (odp->type != TYPE_PASCAL) pos -= 4;
output( "\tpushl %d(%%ecx)\n", pos ); output( "\tpushl %d(%%ecx)\n", pos );
if (odp->type == TYPE_PASCAL) pos += 4; if (odp->type == TYPE_PASCAL) pos += 4;
break; break;
case 'p': /* linear pointer */ case ARG_PTR:
case 't': /* linear pointer to null-terminated string */ case ARG_STR:
case ARG_WSTR:
if (odp->type != TYPE_PASCAL) pos -= 4; if (odp->type != TYPE_PASCAL) pos -= 4;
output( "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */ output( "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
output( "\tshr $3,%%edx\n" ); output( "\tshr $3,%%edx\n" );
@ -388,9 +422,6 @@ static void output_call16_function( ORDDEF *odp )
output( "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 4; if (odp->type == TYPE_PASCAL) pos += 4;
break; break;
default:
assert(0);
} }
} }
@ -423,6 +454,7 @@ static int callfrom16_type_compare( const void *e1, const void *e2 )
int retval; int retval;
int type1 = odp1->type; int type1 = odp1->type;
int type2 = odp2->type; int type2 = odp2->type;
char args1[80];
if (type1 == TYPE_STUB) type1 = TYPE_CDECL; if (type1 == TYPE_STUB) type1 = TYPE_CDECL;
if (type2 == TYPE_STUB) type2 = 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; 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->name = NULL;
entry_point->link_name = xstrdup( spec->init_func ); entry_point->link_name = xstrdup( spec->init_func );
entry_point->export_name = NULL; entry_point->export_name = NULL;
entry_point->u.func.arg_types[0] = 0; entry_point->u.func.nb_args = 0;
assert( !spec->ordinals[0] ); assert( !spec->ordinals[0] );
spec->ordinals[0] = entry_point; spec->ordinals[0] = entry_point;
} }
@ -654,28 +687,36 @@ static void output_module16( DLLSPEC *spec )
for ( i = 0; i < nb_funcs; i++ ) for ( i = 0; i < nb_funcs; i++ )
{ {
unsigned int arg_types[2]; unsigned int arg_types[2];
int nop_words, argsize = 0; int nop_words, pos, argsize = 0;
if ( typelist[i]->type == TYPE_PASCAL ) if ( typelist[i]->type == TYPE_PASCAL )
argsize = get_function_argsize( typelist[i] ); argsize = get_function_argsize( typelist[i] );
/* build the arg types bit fields */ /* build the arg types bit fields */
arg_types[0] = arg_types[1] = 0; 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; 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 ARG_WORD: type = ARG16_WORD; break;
case 's': type = ARG_SWORD; break; case ARG_SWORD: type = ARG16_SWORD; break;
case 'l': type = ARG_LONG; break; case ARG_SEGPTR: type = ARG16_LONG; break;
case 'p': type = ARG_PTR; break; case ARG_SEGSTR: type = ARG16_SEGSTR; break;
case 't': type = ARG_STR; break; case ARG_LONG: type = ARG16_LONG; break;
case 'T': type = ARG_SEGSTR; 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( ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
output( "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) ); output( "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );

View File

@ -81,7 +81,7 @@ int has_relays( DLLSPEC *spec )
static void output_relay_debug( DLLSPEC *spec ) static void output_relay_debug( DLLSPEC *spec )
{ {
int i; int i;
unsigned int j, args, flags; unsigned int j, pos, args, flags;
/* first the table of entry point offsets */ /* first the table of entry point offsets */
@ -111,10 +111,15 @@ static void output_relay_debug( DLLSPEC *spec )
if (needs_relay( odp )) 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); switch (odp->u.func.args[j])
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2); {
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 ); 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( "\t.align %d\n", get_alignment(4) );
output( ".L__wine_spec_relay_entry_point_%d:\n", i ); 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; flags = 0;
switch (target_cpu) switch (target_cpu)
@ -831,7 +836,7 @@ void output_def_file( DLLSPEC *spec, int include_private )
break; break;
case TYPE_STDCALL: 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 (!kill_at && target_cpu == CPU_x86) output( "@%d", at_param );
if (odp->flags & FLAG_FORWARD) if (odp->flags & FLAG_FORWARD)
{ {

View File

@ -890,6 +890,26 @@ unsigned int get_ptr_size(void)
return 0; 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 */ /* return the assembly name for a C symbol */
const char *asm_name( const char *sym ) const char *asm_name( const char *sym )
{ {