mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 21:41:14 +08:00
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:
parent
1fcfaf375c
commit
eb3c46a17e
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user