ffi.h.in: Added FFI_STDCALL ffi_type enumeration for X86_WIN32.

2002-11-10  Ranjit Mathew <rmathew@hotmail.com>

	* include/ffi.h.in: Added FFI_STDCALL ffi_type
	  enumeration for X86_WIN32.
	* src/x86/win32.S: Added ffi_call_STDCALL function
	  definition.
	* src/x86/ffi.c (ffi_call/ffi_raw_call): Added
	  switch cases for recognising FFI_STDCALL and
	  calling ffi_call_STDCALL if target is X86_WIN32.
	* src/ffitest.c (my_stdcall_strlen/stdcall_many):
	  stdcall versions of the "my_strlen" and "many"
	  test functions (for X86_WIN32).
	  Added test cases to test stdcall invocation using
	  these functions.

From-SVN: r59878
This commit is contained in:
Ranjit Mathew 2002-12-06 01:16:45 +00:00 committed by Anthony Green
parent 1fcfaf375c
commit eb3c46a17e
5 changed files with 250 additions and 5 deletions

View File

@ -1,3 +1,18 @@
2002-11-10 Ranjit Mathew <rmathew@hotmail.com>
* include/ffi.h.in: Added FFI_STDCALL ffi_type
enumeration for X86_WIN32.
* src/x86/win32.S: Added ffi_call_STDCALL function
definition.
* src/x86/ffi.c (ffi_call/ffi_raw_call): Added
switch cases for recognising FFI_STDCALL and
calling ffi_call_STDCALL if target is X86_WIN32.
* src/ffitest.c (my_stdcall_strlen/stdcall_many):
stdcall versions of the "my_strlen" and "many"
test functions (for X86_WIN32).
Added test cases to test stdcall invocation using
these functions.
2002-11-27 Ulrich Weigand <uweigand@de.ibm.com>
* src/s390/sysv.S (.eh_frame section): Make section read-only.

View File

@ -198,6 +198,8 @@ typedef enum ffi_abi {
/* ---- Intel x86 Win32 ---------- */
#ifdef X86_WIN32
FFI_SYSV,
FFI_STDCALL,
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
@ -287,7 +289,7 @@ typedef struct _ffi_type
/*@null@*/ struct _ffi_type **elements;
} ffi_type;
/* These are defined in ffi.c */
/* These are defined in types.c */
extern ffi_type ffi_type_void;
extern ffi_type ffi_type_uint8;
extern ffi_type ffi_type_sint8;

View File

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
ffitest.c - Copyright (c) 1996, 1997, 1998, 2002 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -49,6 +49,13 @@ static size_t my_strlen(char *s)
return (strlen(s));
}
#ifdef X86_WIN32
static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
{
return (strlen(s));
}
#endif /* X86_WIN32 */
static int promotion(signed char sc, signed short ss,
unsigned char uc, unsigned short us)
{
@ -112,6 +119,25 @@ static float many(float f1,
return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
}
#ifdef X86_WIN32
static float __attribute__((stdcall)) stdcall_many(float f1,
float f2,
float f3,
float f4,
float f5,
float f6,
float f7,
float f8,
float f9,
float f10,
float f11,
float f12,
float f13)
{
return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
}
#endif /* X86_WIN32 */
static double dblit(float f)
{
return f/3.0;
@ -954,6 +980,67 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
printf("Structure passing doesn't work on Win32.\n");
#endif /* X86_WIN32 */
#ifdef X86_WIN32
/* stdcall strlen tests */
{
args[0] = &ffi_type_pointer;
values[0] = (void*) &s;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
&ffi_type_sint, args) == FFI_OK);
s = "a";
ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
CHECK(rint == 1);
s = "1234567";
ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
CHECK(rint == 7);
s = "1234567890123456789012345";
ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
CHECK(rint == 25);
printf("stdcall strlen tests passed\n");
}
/* stdcall many arg tests */
{
float ff;
float fa[13];
for (ul = 0; ul < 13; ul++)
{
args[ul] = &ffi_type_float;
values[ul] = &fa[ul];
fa[ul] = (float) ul;
}
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
&ffi_type_float, args) == FFI_OK);
/*@-usedef@*/
ff = stdcall_many(fa[0], fa[1],
fa[2], fa[3],
fa[4], fa[5],
fa[6], fa[7],
fa[8], fa[9],
fa[10],fa[11],fa[12]);
/*@=usedef@*/
ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
/*@-realcompare@*/
if (f - ff < FLT_EPSILON)
/*@=realcompare@*/
printf("stdcall many arg tests ok!\n");
else
CHECK(0);
}
#endif /* X86_WIN32 */
# if FFI_CLOSURES
/* A simple closure test */
{

View File

@ -1,5 +1,8 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 1998, 1999 Cygnus Solutions
ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
Copyright (c) 2002 Ranjit Mathew
Copyright (c) 2002 Bo Thorsen
Copyright (c) 2002 Roger Sayle
x86 Foreign Function Interface
@ -148,6 +151,18 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@=declundef@*/
/*@=exportheader@*/
#ifdef X86_WIN32
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
#endif /* X86_WIN32 */
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
@ -180,6 +195,14 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#ifdef X86_WIN32
case FFI_STDCALL:
/*@-usedef@*/
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#endif /* X86_WIN32 */
default:
FFI_ASSERT(0);
break;
@ -448,6 +471,15 @@ ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ unsigned *,
void (*fn)());
#ifdef X86_WIN32
extern void
ffi_call_STDCALL(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
#endif /* X86_WIN32 */
void
ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
@ -482,6 +514,14 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#ifdef X86_WIN32
case FFI_STDCALL:
/*@-usedef@*/
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#endif /* X86_WIN32 */
default:
FFI_ASSERT(0);
break;

View File

@ -1,5 +1,8 @@
/* -----------------------------------------------------------------------
win32.S - Copyright (c) 1996, 1998, 2001 Cygnus Solutions
win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
Copyright (c) 2001 John Beniton
Copyright (c) 2002 Ranjit Mathew
X86 Foreign Function Interface
@ -52,7 +55,10 @@ _ffi_call_SYSV:
# Return stack to previous state and call the function
addl $8,%esp
call *28(%ebp)
# FIXME: Align the stack to a 128-bit boundary to avoid
# potential performance hits.
call *28(%ebp)
# Remove the space we pushed for the args
movl 16(%ebp),%ecx
@ -123,3 +129,98 @@ epilogue:
ret
.ffi_call_SYSV_end:
# This assumes we are using gas.
.balign 16
.globl _ffi_call_STDCALL
_ffi_call_STDCALL:
pushl %ebp
movl %esp,%ebp
# Make room for all of the new args.
movl 16(%ebp),%ecx
subl %ecx,%esp
movl %esp,%eax
# Place all of the ffi_prep_args in position
pushl 12(%ebp)
pushl %eax
call *8(%ebp)
# Return stack to previous state and call the function
addl $8,%esp
# FIXME: Align the stack to a 128-bit boundary to avoid
# potential performance hits.
call *28(%ebp)
# stdcall functions pop arguments off the stack themselves
# Load %ecx with the return type code
movl 20(%ebp),%ecx
# If the return value pointer is NULL, assume no return value.
cmpl $0,24(%ebp)
jne sc_retint
# Even if there is no space for the return value, we are
# obliged to handle floating-point values.
cmpl $FFI_TYPE_FLOAT,%ecx
jne sc_noretval
fstp %st(0)
jmp sc_epilogue
sc_retint:
cmpl $FFI_TYPE_INT,%ecx
jne sc_retfloat
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
jmp sc_epilogue
sc_retfloat:
cmpl $FFI_TYPE_FLOAT,%ecx
jne sc_retdouble
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
fstps (%ecx)
jmp sc_epilogue
sc_retdouble:
cmpl $FFI_TYPE_DOUBLE,%ecx
jne sc_retlongdouble
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
fstpl (%ecx)
jmp sc_epilogue
sc_retlongdouble:
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
jne sc_retint64
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
fstpt (%ecx)
jmp sc_epilogue
sc_retint64:
cmpl $FFI_TYPE_SINT64,%ecx
jne sc_retstruct
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
movl %edx,4(%ecx)
sc_retstruct:
# Nothing to do!
sc_noretval:
sc_epilogue:
movl %ebp,%esp
popl %ebp
ret
.ffi_call_STDCALL_end: