Commit eb3c46a1 by Ranjit Mathew Committed by Anthony Green

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
parent 1fcfaf37
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> 2002-11-27 Ulrich Weigand <uweigand@de.ibm.com>
* src/s390/sysv.S (.eh_frame section): Make section read-only. * src/s390/sysv.S (.eh_frame section): Make section read-only.
......
...@@ -198,6 +198,8 @@ typedef enum ffi_abi { ...@@ -198,6 +198,8 @@ typedef enum ffi_abi {
/* ---- Intel x86 Win32 ---------- */ /* ---- Intel x86 Win32 ---------- */
#ifdef X86_WIN32 #ifdef X86_WIN32
FFI_SYSV, FFI_SYSV,
FFI_STDCALL,
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV,
#endif #endif
...@@ -287,7 +289,7 @@ typedef struct _ffi_type ...@@ -287,7 +289,7 @@ typedef struct _ffi_type
/*@null@*/ struct _ffi_type **elements; /*@null@*/ struct _ffi_type **elements;
} ffi_type; } 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_void;
extern ffi_type ffi_type_uint8; extern ffi_type ffi_type_uint8;
extern ffi_type ffi_type_sint8; extern ffi_type ffi_type_sint8;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
...@@ -49,6 +49,13 @@ static size_t my_strlen(char *s) ...@@ -49,6 +49,13 @@ static size_t my_strlen(char *s)
return (strlen(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, static int promotion(signed char sc, signed short ss,
unsigned char uc, unsigned short us) unsigned char uc, unsigned short us)
{ {
...@@ -112,6 +119,25 @@ static float many(float f1, ...@@ -112,6 +119,25 @@ static float many(float f1,
return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13); 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) static double dblit(float f)
{ {
return f/3.0; return f/3.0;
...@@ -954,6 +980,67 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[]) ...@@ -954,6 +980,67 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
printf("Structure passing doesn't work on Win32.\n"); printf("Structure passing doesn't work on Win32.\n");
#endif /* X86_WIN32 */ #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 # if FFI_CLOSURES
/* A simple closure test */ /* A simple closure test */
{ {
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 x86 Foreign Function Interface
...@@ -148,6 +151,18 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *), ...@@ -148,6 +151,18 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@=declundef@*/ /*@=declundef@*/
/*@=exportheader@*/ /*@=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 ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(), void (*fn)(),
/*@out@*/ void *rvalue, /*@out@*/ void *rvalue,
...@@ -180,6 +195,14 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, ...@@ -180,6 +195,14 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
cif->flags, ecif.rvalue, fn); cif->flags, ecif.rvalue, fn);
/*@=usedef@*/ /*@=usedef@*/
break; 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: default:
FFI_ASSERT(0); FFI_ASSERT(0);
break; break;
...@@ -448,6 +471,15 @@ ffi_call_SYSV(void (*)(char *, extended_cif *), ...@@ -448,6 +471,15 @@ ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ unsigned *, /*@out@*/ unsigned *,
void (*fn)()); 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 void
ffi_raw_call(/*@dependent@*/ ffi_cif *cif, ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(), void (*fn)(),
...@@ -482,6 +514,14 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif, ...@@ -482,6 +514,14 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
cif->flags, ecif.rvalue, fn); cif->flags, ecif.rvalue, fn);
/*@=usedef@*/ /*@=usedef@*/
break; 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: default:
FFI_ASSERT(0); FFI_ASSERT(0);
break; break;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 X86 Foreign Function Interface
...@@ -52,7 +55,10 @@ _ffi_call_SYSV: ...@@ -52,7 +55,10 @@ _ffi_call_SYSV:
# Return stack to previous state and call the function # Return stack to previous state and call the function
addl $8,%esp 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 # Remove the space we pushed for the args
movl 16(%ebp),%ecx movl 16(%ebp),%ecx
...@@ -123,3 +129,98 @@ epilogue: ...@@ -123,3 +129,98 @@ epilogue:
ret ret
.ffi_call_SYSV_end: .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:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment