From 3e6bf5fe04413ffdcf981bf74684309cb7cf6800 Mon Sep 17 00:00:00 2001 From: ktietz Date: Sun, 29 Jan 2012 13:29:53 +0000 Subject: * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new argument to prototype for specify calling-convention. (ffi_call): Add support for stdcall/thiscall convention. (ffi_prep_args): Likewise. (ffi_raw_call): Likewise. * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and FFI_FASTCALL. * src/x86/win32.S (_ffi_call_win32): Add support for fastcall/thiscall calling-convention calls. * testsuite/libffi.call/fastthis1_win32.c: New test. * testsuite/libffi.call/fastthis2_win32.c: New test. * testsuite/libffi.call/fastthis3_win32.c: New test. * testsuite/libffi.call/strlen2_win32.c: New test. * testsuite/libffi.call/many2_win32.c: New test. * testsuite/libffi.call/struct1_win32.c: New test. * testsuite/libffi.call/struct2_win32.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183676 138bc75d-0d04-0410-961f-82ee72b054a4 --- libffi/testsuite/libffi.call/fastthis1_win32.c | 50 +++++++++++++++++++ libffi/testsuite/libffi.call/fastthis2_win32.c | 50 +++++++++++++++++++ libffi/testsuite/libffi.call/fastthis3_win32.c | 56 +++++++++++++++++++++ libffi/testsuite/libffi.call/many2_win32.c | 63 ++++++++++++++++++++++++ libffi/testsuite/libffi.call/strlen2_win32.c | 45 +++++++++++++++++ libffi/testsuite/libffi.call/struct1_win32.c | 65 +++++++++++++++++++++++++ libffi/testsuite/libffi.call/struct2_win32.c | 67 ++++++++++++++++++++++++++ 7 files changed, 396 insertions(+) create mode 100644 libffi/testsuite/libffi.call/fastthis1_win32.c create mode 100644 libffi/testsuite/libffi.call/fastthis2_win32.c create mode 100644 libffi/testsuite/libffi.call/fastthis3_win32.c create mode 100644 libffi/testsuite/libffi.call/many2_win32.c create mode 100644 libffi/testsuite/libffi.call/strlen2_win32.c create mode 100644 libffi/testsuite/libffi.call/struct1_win32.c create mode 100644 libffi/testsuite/libffi.call/struct2_win32.c (limited to 'libffi/testsuite') diff --git a/libffi/testsuite/libffi.call/fastthis1_win32.c b/libffi/testsuite/libffi.call/fastthis1_win32.c new file mode 100644 index 000000000000..b3c4c733b627 --- /dev/null +++ b/libffi/testsuite/libffi.call/fastthis1_win32.c @@ -0,0 +1,50 @@ +/* Area: ffi_call + Purpose: Check fastcall fct call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_f(char *s, float a) +{ + return (size_t) ((int) strlen(s) + (int) a); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + float v2; + args[0] = &ffi_type_pointer; + args[1] = &ffi_type_float; + values[0] = (void*) &s; + values[1] = (void*) &v2; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + v2 = 0.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 1); + + s = "1234567"; + v2 = -1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 6); + + s = "1234567890123456789012345"; + v2 = 1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 26); + + printf("fastcall fct1 tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/fastthis2_win32.c b/libffi/testsuite/libffi.call/fastthis2_win32.c new file mode 100644 index 000000000000..f148a12fa66b --- /dev/null +++ b/libffi/testsuite/libffi.call/fastthis2_win32.c @@ -0,0 +1,50 @@ +/* Area: ffi_call + Purpose: Check fastcall fct call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_f(float a, char *s) +{ + return (size_t) ((int) strlen(s) + (int) a); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + float v2; + args[1] = &ffi_type_pointer; + args[0] = &ffi_type_float; + values[1] = (void*) &s; + values[0] = (void*) &v2; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + v2 = 0.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 1); + + s = "1234567"; + v2 = -1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 6); + + s = "1234567890123456789012345"; + v2 = 1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 26); + + printf("fastcall fct2 tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/fastthis3_win32.c b/libffi/testsuite/libffi.call/fastthis3_win32.c new file mode 100644 index 000000000000..5cf82bbfa99d --- /dev/null +++ b/libffi/testsuite/libffi.call/fastthis3_win32.c @@ -0,0 +1,56 @@ +/* Area: ffi_call + Purpose: Check fastcall f call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_f(float a, char *s, int i) +{ + return (size_t) ((int) strlen(s) + (int) a + i); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + int v1; + float v2; + args[2] = &ffi_type_sint; + args[1] = &ffi_type_pointer; + args[0] = &ffi_type_float; + values[2] = (void*) &v1; + values[1] = (void*) &s; + values[0] = (void*) &v2; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 3, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + v1 = 1; + v2 = 0.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 2); + + s = "1234567"; + v2 = -1.0; + v1 = -2; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 4); + + s = "1234567890123456789012345"; + v2 = 1.0; + v1 = 2; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 28); + + printf("fastcall fct3 tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/many2_win32.c b/libffi/testsuite/libffi.call/many2_win32.c new file mode 100644 index 000000000000..4adbe4d705f8 --- /dev/null +++ b/libffi/testsuite/libffi.call/many2_win32.c @@ -0,0 +1,63 @@ +/* Area: ffi_call + Purpose: Check stdcall many call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" +#include + +static float __attribute__((fastcall)) fastcall_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); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[13]; + void *values[13]; + float fa[13]; + float f, ff; + unsigned long ul; + + 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_FASTCALL, 13, + &ffi_type_float, args) == FFI_OK); + + ff = fastcall_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]); + + ffi_call(&cif, FFI_FN(fastcall_many), &f, values); + + if (f - ff < FLT_EPSILON) + printf("fastcall many arg tests ok!\n"); + else + CHECK(0); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/strlen2_win32.c b/libffi/testsuite/libffi.call/strlen2_win32.c new file mode 100644 index 000000000000..b348e4340979 --- /dev/null +++ b/libffi/testsuite/libffi.call/strlen2_win32.c @@ -0,0 +1,45 @@ +/* Area: ffi_call + Purpose: Check fastcall strlen call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_strlen(char *s) +{ + return (strlen(s)); +} + +int d +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + args[0] = &ffi_type_pointer; + values[0] = (void*) &s; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values); + CHECK(rint == 1); + + s = "1234567"; + ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values); + CHECK(rint == 7); + + s = "1234567890123456789012345"; + ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values); + CHECK(rint == 25); + + printf("fastcall strlen tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/struct1_win32.c b/libffi/testsuite/libffi.call/struct1_win32.c new file mode 100644 index 000000000000..4a7eb9444bd4 --- /dev/null +++ b/libffi/testsuite/libffi.call/struct1_win32.c @@ -0,0 +1,65 @@ +/* Area: ffi_call + Purpose: Check structures with fastcall/thiscall convention. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ +#include "ffitest.h" + +typedef struct +{ + unsigned char uc; + double d; + unsigned int ui; +} test_structure_1; + +static __attribute__ ((fastcall)) test_structure_1 struct1(test_structure_1 ts) +{ + ts.uc++; + ts.d--; + ts.ui++; + + return ts; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_type ts1_type; + ffi_type *ts1_type_elements[4]; + ts1_type.size = 0; + ts1_type.alignment = 0; + ts1_type.type = FFI_TYPE_STRUCT; + ts1_type.elements = ts1_type_elements; + ts1_type_elements[0] = &ffi_type_uchar; + ts1_type_elements[1] = &ffi_type_double; + ts1_type_elements[2] = &ffi_type_uint; + ts1_type_elements[3] = NULL; + + test_structure_1 ts1_arg; + /* This is a hack to get a properly aligned result buffer */ + test_structure_1 *ts1_result = + (test_structure_1 *) malloc (sizeof(test_structure_1)); + + args[0] = &ts1_type; + values[0] = &ts1_arg; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, + &ts1_type, args) == FFI_OK); + + ts1_arg.uc = '\x01'; + ts1_arg.d = 3.14159; + ts1_arg.ui = 555; + + ffi_call(&cif, FFI_FN(struct1), ts1_result, values); + + CHECK(ts1_result->ui == 556); + CHECK(ts1_result->d == 3.14159 - 1); + + free (ts1_result); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/struct2_win32.c b/libffi/testsuite/libffi.call/struct2_win32.c new file mode 100644 index 000000000000..2bfbdc5ff81c --- /dev/null +++ b/libffi/testsuite/libffi.call/struct2_win32.c @@ -0,0 +1,67 @@ +/* Area: ffi_call + Purpose: Check structures in fastcall/stdcall function + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ +#include "ffitest.h" + +typedef struct +{ + double d1; + double d2; +} test_structure_2; + +static test_structure_2 __attribute__ ((fastcall)) struct2(test_structure_2 ts) +{ + ts.d1--; + ts.d2--; + + return ts; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + test_structure_2 ts2_arg; + ffi_type ts2_type; + ffi_type *ts2_type_elements[3]; + ts2_type.size = 0; + ts2_type.alignment = 0; + ts2_type.type = FFI_TYPE_STRUCT; + ts2_type.elements = ts2_type_elements; + ts2_type_elements[0] = &ffi_type_double; + ts2_type_elements[1] = &ffi_type_double; + ts2_type_elements[2] = NULL; + + + /* This is a hack to get a properly aligned result buffer */ + test_structure_2 *ts2_result = + (test_structure_2 *) malloc (sizeof(test_structure_2)); + + args[0] = &ts2_type; + values[0] = &ts2_arg; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, &ts2_type, args) == FFI_OK); + + ts2_arg.d1 = 5.55; + ts2_arg.d2 = 6.66; + + printf ("%g\n", ts2_arg.d1); + printf ("%g\n", ts2_arg.d2); + + ffi_call(&cif, FFI_FN(struct2), ts2_result, values); + + printf ("%g\n", ts2_result->d1); + printf ("%g\n", ts2_result->d2); + + CHECK(ts2_result->d1 == 5.55 - 1); + CHECK(ts2_result->d2 == 6.66 - 1); + + free (ts2_result); + exit(0); +} -- cgit v1.2.3