Many changes
This commit is contained in:
65
libffi/debug.c
Normal file
65
libffi/debug.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
debug.c - Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* General debugging routines */
|
||||
|
||||
void ffi_stop_here(void)
|
||||
{
|
||||
/* This function is only useful for debugging purposes.
|
||||
Place a breakpoint on ffi_stop_here to be notified of
|
||||
significant events. */
|
||||
}
|
||||
|
||||
/* This function should only be called via the FFI_ASSERT() macro */
|
||||
|
||||
int ffi_assert(char *file, int line)
|
||||
{
|
||||
fprintf(stderr, "ASSERTION FAILURE: %s line %d\n", file, line);
|
||||
ffi_stop_here();
|
||||
abort();
|
||||
|
||||
/* This has to return something for the compiler not to complain */
|
||||
/*@notreached@*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform a sanity check on an ffi_type structure */
|
||||
|
||||
bool ffi_type_test(ffi_type *a)
|
||||
{
|
||||
/*@-usedef@*/
|
||||
FFI_ASSERT(a->type <= FFI_TYPE_LAST);
|
||||
FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->size > 0 : 1);
|
||||
FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->alignment > 0 : 1);
|
||||
FFI_ASSERT(a->type == FFI_TYPE_STRUCT ? a->elements != NULL : 1);
|
||||
/*@=usedef@*/
|
||||
|
||||
/* This is a silly thing to return, but it keeps the compiler from
|
||||
issuing warnings about "a" not being used in non-debug builds. */
|
||||
return (a != NULL);
|
||||
}
|
||||
736
libffi/ffitest.c
Normal file
736
libffi/ffitest.c
Normal file
@@ -0,0 +1,736 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
/* This is lame. Long double support is barely there under SunOS 4.x */
|
||||
#if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
|
||||
#define BROKEN_LONG_DOUBLE
|
||||
#endif
|
||||
|
||||
#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
|
||||
|
||||
static int fail(char *file, int line)
|
||||
{
|
||||
fprintf(stderr, "Test failure: %s line %d\n", file, line);
|
||||
exit(EXIT_FAILURE);
|
||||
/*@notreached@*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_ARGS 256
|
||||
|
||||
static size_t my_strlen(char *s)
|
||||
{
|
||||
return (strlen(s));
|
||||
}
|
||||
|
||||
static int promotion(signed char sc, signed short ss,
|
||||
unsigned char uc, unsigned short us)
|
||||
{
|
||||
int r = (int) sc + (int) ss + (int) uc + (int) us;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static signed char return_sc(signed char sc)
|
||||
{
|
||||
return sc;
|
||||
}
|
||||
|
||||
static unsigned char return_uc(unsigned char uc)
|
||||
{
|
||||
return uc;
|
||||
}
|
||||
|
||||
static long long return_ll(long long ll)
|
||||
{
|
||||
return ll;
|
||||
}
|
||||
|
||||
static int floating(int a, float b, double c, long double d, int e)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
/* This is ifdef'd out for now. long double support under SunOS/gcc
|
||||
is pretty much non-existent. You'll get the odd bus error in library
|
||||
routines like printf(). */
|
||||
printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
|
||||
#endif
|
||||
|
||||
i = (int) ((float)a/b + ((float)c/(float)d));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static float 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)
|
||||
{
|
||||
#if 0
|
||||
printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
|
||||
(double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
|
||||
(double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
|
||||
(double) f11, (double) f12, (double) f13);
|
||||
#endif
|
||||
|
||||
return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
|
||||
}
|
||||
|
||||
static double dblit(float f)
|
||||
{
|
||||
return f/3.0;
|
||||
}
|
||||
|
||||
static long double ldblit(float f)
|
||||
{
|
||||
return (long double) (((long double) f)/ (long double) 3.0);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char uc;
|
||||
double d;
|
||||
unsigned int ui;
|
||||
} test_structure_1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double d1;
|
||||
double d2;
|
||||
} test_structure_2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int si;
|
||||
} test_structure_3;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned ui1;
|
||||
unsigned ui2;
|
||||
unsigned ui3;
|
||||
} test_structure_4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char c1;
|
||||
char c2;
|
||||
} test_structure_5;
|
||||
|
||||
static test_structure_1 struct1(test_structure_1 ts)
|
||||
{
|
||||
/*@-type@*/
|
||||
ts.uc++;
|
||||
/*@=type@*/
|
||||
ts.d--;
|
||||
ts.ui++;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_2 struct2(test_structure_2 ts)
|
||||
{
|
||||
ts.d1--;
|
||||
ts.d2--;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_3 struct3(test_structure_3 ts)
|
||||
{
|
||||
ts.si = -(ts.si*2);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_4 struct4(test_structure_4 ts)
|
||||
{
|
||||
ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
|
||||
{
|
||||
ts1.c1 += ts2.c1;
|
||||
ts1.c2 -= ts2.c2;
|
||||
|
||||
return ts1;
|
||||
}
|
||||
|
||||
/* Take an int and a float argument, together with int userdata, and */
|
||||
/* return the sum. */
|
||||
static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
|
||||
{
|
||||
*(int*)resp =
|
||||
*(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type)(int, float);
|
||||
|
||||
int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
char *s;
|
||||
signed char sc;
|
||||
unsigned char uc;
|
||||
signed short ss;
|
||||
unsigned short us;
|
||||
unsigned long ul;
|
||||
long long ll;
|
||||
float f;
|
||||
double d;
|
||||
long double ld;
|
||||
signed int si1;
|
||||
signed int si2;
|
||||
|
||||
#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(__mips__) && (_MIPS_SIM == _ABIN32))
|
||||
long long rint;
|
||||
#else
|
||||
int rint;
|
||||
#endif
|
||||
long long rlonglong;
|
||||
|
||||
ffi_type ts1_type;
|
||||
ffi_type ts2_type;
|
||||
ffi_type ts3_type;
|
||||
ffi_type ts4_type;
|
||||
ffi_type ts5_type;
|
||||
ffi_type *ts1_type_elements[4];
|
||||
ffi_type *ts2_type_elements[3];
|
||||
ffi_type *ts3_type_elements[2];
|
||||
ffi_type *ts4_type_elements[4];
|
||||
ffi_type *ts5_type_elements[3];
|
||||
|
||||
ts1_type.size = 0;
|
||||
ts1_type.alignment = 0;
|
||||
ts1_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts2_type.size = 0;
|
||||
ts2_type.alignment = 0;
|
||||
ts2_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts3_type.size = 0;
|
||||
ts3_type.alignment = 0;
|
||||
ts3_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts4_type.size = 0;
|
||||
ts4_type.alignment = 0;
|
||||
ts4_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts5_type.size = 0;
|
||||
ts5_type.alignment = 0;
|
||||
ts5_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
/*@-immediatetrans@*/
|
||||
ts1_type.elements = ts1_type_elements;
|
||||
ts2_type.elements = ts2_type_elements;
|
||||
ts3_type.elements = ts3_type_elements;
|
||||
ts4_type.elements = ts4_type_elements;
|
||||
ts5_type.elements = ts5_type_elements;
|
||||
/*@=immediatetrans@*/
|
||||
|
||||
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;
|
||||
|
||||
ts2_type_elements[0] = &ffi_type_double;
|
||||
ts2_type_elements[1] = &ffi_type_double;
|
||||
ts2_type_elements[2] = NULL;
|
||||
|
||||
ts3_type_elements[0] = &ffi_type_sint;
|
||||
ts3_type_elements[1] = NULL;
|
||||
|
||||
ts4_type_elements[0] = &ffi_type_uint;
|
||||
ts4_type_elements[1] = &ffi_type_uint;
|
||||
ts4_type_elements[2] = &ffi_type_uint;
|
||||
ts4_type_elements[3] = NULL;
|
||||
|
||||
ts5_type_elements[0] = &ffi_type_schar;
|
||||
ts5_type_elements[1] = &ffi_type_schar;
|
||||
ts5_type_elements[2] = NULL;
|
||||
|
||||
ul = 0;
|
||||
|
||||
/* return value tests */
|
||||
{
|
||||
#if defined(__mips__) /* || defined(ARM) */
|
||||
puts ("long long tests not run. This is a known bug on this architecture.");
|
||||
#else
|
||||
args[0] = &ffi_type_sint64;
|
||||
values[0] = ≪
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_sint64, args) == FFI_OK);
|
||||
|
||||
for (ll = 0LL; ll < 100LL; ll++)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
|
||||
CHECK(rlonglong == ll);
|
||||
}
|
||||
|
||||
for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
|
||||
CHECK(rlonglong == ll);
|
||||
}
|
||||
#endif
|
||||
|
||||
args[0] = &ffi_type_schar;
|
||||
values[0] = ≻
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_schar, args) == FFI_OK);
|
||||
|
||||
for (sc = (signed char) -127;
|
||||
sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_sc), &rint, values);
|
||||
CHECK(rint == (int) sc);
|
||||
}
|
||||
|
||||
args[0] = &ffi_type_uchar;
|
||||
values[0] = &uc;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uchar, args) == FFI_OK);
|
||||
|
||||
for (uc = (unsigned char) '\x00';
|
||||
uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_uc), &rint, values);
|
||||
CHECK(rint == (signed int) uc);
|
||||
}
|
||||
|
||||
printf("%lu return value tests run\n", ul);
|
||||
}
|
||||
|
||||
#ifdef BROKEN_LONG_DOUBLE
|
||||
printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
|
||||
#else
|
||||
/* float arg tests */
|
||||
{
|
||||
args[0] = &ffi_type_float;
|
||||
values[0] = &f;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_longdouble, args) == FFI_OK);
|
||||
|
||||
f = 3.14159;
|
||||
|
||||
#if 0
|
||||
/* This is ifdef'd out for now. long double support under SunOS/gcc
|
||||
is pretty much non-existent. You'll get the odd bus error in library
|
||||
routines like printf(). */
|
||||
printf ("%Lf\n", ldblit(f));
|
||||
#endif
|
||||
ld = 666;
|
||||
ffi_call(&cif, FFI_FN(ldblit), &ld, values);
|
||||
|
||||
#if 0
|
||||
/* This is ifdef'd out for now. long double support under SunOS/gcc
|
||||
is pretty much non-existent. You'll get the odd bus error in library
|
||||
routines like printf(). */
|
||||
printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
|
||||
#endif
|
||||
|
||||
/* These are not always the same!! Check for a reasonable delta */
|
||||
/*@-realcompare@*/
|
||||
if (ld - ldblit(f) < LDBL_EPSILON)
|
||||
/*@=realcompare@*/
|
||||
puts("long double return value tests ok!");
|
||||
else
|
||||
CHECK(0);
|
||||
}
|
||||
|
||||
/* float arg tests */
|
||||
{
|
||||
args[0] = &ffi_type_sint;
|
||||
values[0] = &si1;
|
||||
args[1] = &ffi_type_float;
|
||||
values[1] = &f;
|
||||
args[2] = &ffi_type_double;
|
||||
values[2] = &d;
|
||||
args[3] = &ffi_type_longdouble;
|
||||
values[3] = &ld;
|
||||
args[4] = &ffi_type_sint;
|
||||
values[4] = &si2;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
si1 = 6;
|
||||
f = 3.14159;
|
||||
d = (double)1.0/(double)3.0;
|
||||
ld = 2.71828182846L;
|
||||
si2 = 10;
|
||||
|
||||
floating (si1, f, d, ld, si2);
|
||||
|
||||
ffi_call(&cif, FFI_FN(floating), &rint, values);
|
||||
|
||||
printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
|
||||
|
||||
CHECK(rint == floating(si1, f, d, ld, si2));
|
||||
|
||||
printf("float arg tests ok!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* strlen tests */
|
||||
{
|
||||
args[0] = &ffi_type_pointer;
|
||||
values[0] = (void*) &s;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
s = "a";
|
||||
ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
||||
CHECK(rint == 1);
|
||||
|
||||
s = "1234567";
|
||||
ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
||||
CHECK(rint == 7);
|
||||
|
||||
s = "1234567890123456789012345";
|
||||
ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
||||
CHECK(rint == 25);
|
||||
|
||||
printf("strlen tests passed\n");
|
||||
}
|
||||
|
||||
/* float arg tests */
|
||||
{
|
||||
args[0] = &ffi_type_float;
|
||||
values[0] = &f;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_double, args) == FFI_OK);
|
||||
|
||||
f = 3.14159;
|
||||
|
||||
ffi_call(&cif, FFI_FN(dblit), &d, values);
|
||||
|
||||
/* These are not always the same!! Check for a reasonable delta */
|
||||
/*@-realcompare@*/
|
||||
CHECK(d - dblit(f) < DBL_EPSILON);
|
||||
/*@=realcompare@*/
|
||||
|
||||
printf("double return value tests ok!\n");
|
||||
}
|
||||
|
||||
/* 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_DEFAULT_ABI, 13,
|
||||
&ffi_type_float, args) == FFI_OK);
|
||||
|
||||
/*@-usedef@*/
|
||||
ff = 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(many), &f, values);
|
||||
|
||||
/*@-realcompare@*/
|
||||
if (f - ff < FLT_EPSILON)
|
||||
/*@=realcompare@*/
|
||||
printf("many arg tests ok!\n");
|
||||
else
|
||||
#ifdef POWERPC
|
||||
printf("many arg tests failed! This is a gcc bug.\n");
|
||||
#else
|
||||
CHECK(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* promotion tests */
|
||||
{
|
||||
args[0] = &ffi_type_schar;
|
||||
args[1] = &ffi_type_sshort;
|
||||
args[2] = &ffi_type_uchar;
|
||||
args[3] = &ffi_type_ushort;
|
||||
values[0] = ≻
|
||||
values[1] = &ss;
|
||||
values[2] = &uc;
|
||||
values[3] = &us;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
us = 0;
|
||||
ul = 0;
|
||||
|
||||
for (sc = (signed char) -127;
|
||||
sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
|
||||
for (ss = -30000; ss <= 30000; ss += 10000)
|
||||
for (uc = (unsigned char) 0;
|
||||
uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
|
||||
for (us = 0; us <= 60000; us += 10000)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(promotion), &rint, values);
|
||||
CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
|
||||
}
|
||||
printf("%lu promotion tests run\n", ul);
|
||||
}
|
||||
|
||||
#ifndef X86_WIN32 /* Structures dont work on Win32 */
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
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_DEFAULT_ABI, 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);
|
||||
|
||||
puts ("structure test 1 ok!\n");
|
||||
|
||||
free (ts1_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_2 ts2_arg;
|
||||
|
||||
/* 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_DEFAULT_ABI, 1,
|
||||
&ts2_type, args) == FFI_OK);
|
||||
|
||||
ts2_arg.d1 = 5.55;
|
||||
ts2_arg.d2 = 6.66;
|
||||
|
||||
printf ("%g\n", ts2_result->d1);
|
||||
printf ("%g\n", ts2_result->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);
|
||||
|
||||
printf("structure test 2 ok!\n");
|
||||
|
||||
free (ts2_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
int compare_value;
|
||||
test_structure_3 ts3_arg;
|
||||
test_structure_3 *ts3_result =
|
||||
(test_structure_3 *) malloc (sizeof(test_structure_3));
|
||||
|
||||
args[0] = &ts3_type;
|
||||
values[0] = &ts3_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ts3_type, args) == FFI_OK);
|
||||
|
||||
ts3_arg.si = -123;
|
||||
compare_value = ts3_arg.si;
|
||||
|
||||
ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
|
||||
|
||||
printf ("%d %d\n", ts3_result->si, -(compare_value*2));
|
||||
|
||||
if (ts3_result->si == -(ts3_arg.si*2))
|
||||
puts ("structure test 3 ok!");
|
||||
else
|
||||
{
|
||||
puts ("Structure test 3 found structure passing bug.");
|
||||
puts (" Current versions of GCC are not 100% compliant with the");
|
||||
puts (" n32 ABI. There is a known problem related to passing");
|
||||
puts (" small structures. Send a bug report to the gcc maintainers.");
|
||||
}
|
||||
|
||||
free (ts3_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_4 ts4_arg;
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_4 *ts4_result =
|
||||
(test_structure_4 *) malloc (sizeof(test_structure_4));
|
||||
|
||||
args[0] = &ts4_type;
|
||||
values[0] = &ts4_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ts4_type, args) == FFI_OK);
|
||||
|
||||
ts4_arg.ui1 = 2;
|
||||
ts4_arg.ui2 = 3;
|
||||
ts4_arg.ui3 = 4;
|
||||
|
||||
ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
|
||||
|
||||
if (ts4_result->ui3 == 2U * 3U * 4U)
|
||||
puts ("structure test 4 ok!");
|
||||
else
|
||||
puts ("Structure test 4 found GCC's structure passing bug.");
|
||||
|
||||
free (ts4_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_5 ts5_arg1, ts5_arg2;
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_5 *ts5_result =
|
||||
(test_structure_5 *) malloc (sizeof(test_structure_5));
|
||||
|
||||
args[0] = &ts5_type;
|
||||
args[1] = &ts5_type;
|
||||
values[0] = &ts5_arg1;
|
||||
values[1] = &ts5_arg2;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
||||
&ts5_type, args) == FFI_OK);
|
||||
|
||||
ts5_arg1.c1 = 2;
|
||||
ts5_arg1.c2 = 6;
|
||||
ts5_arg2.c1 = 5;
|
||||
ts5_arg2.c2 = 3;
|
||||
|
||||
ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
|
||||
|
||||
if (ts5_result->c1 == 7
|
||||
&& ts5_result->c2 == 3)
|
||||
puts ("structure test 5 ok!");
|
||||
else
|
||||
puts ("Structure test 5 found GCC's structure passing bug.");
|
||||
|
||||
free (ts5_result);
|
||||
}
|
||||
|
||||
#else
|
||||
printf("Structure passing doesn't work on Win32.\n");
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
# if FFI_CLOSURES
|
||||
/* A simple closure test */
|
||||
{
|
||||
ffi_closure cl;
|
||||
ffi_type * cl_arg_types[3];
|
||||
|
||||
cl_arg_types[0] = &ffi_type_sint;
|
||||
cl_arg_types[1] = &ffi_type_float;
|
||||
cl_arg_types[2] = NULL;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
|
||||
(void *) 3 /* userdata */)
|
||||
== FFI_OK);
|
||||
CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* If we arrived here, all is good */
|
||||
(void) puts("\nLooks good. No surprises.\n");
|
||||
|
||||
/*@-compdestroy@*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
270
libffi/java_raw_api.c
Normal file
270
libffi/java_raw_api.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
java_raw_api.c - Copyright (c) 1999 Cygnus Solutions
|
||||
|
||||
Cloned from raw_api.c
|
||||
|
||||
Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
|
||||
Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This defines a Java- and 64-bit specific variant of the raw API. */
|
||||
/* It assumes that "raw" argument blocks look like Java stacks on a */
|
||||
/* 64-bit machine. Arguments that can be stored in a single stack */
|
||||
/* stack slots (longs, doubles) occupy 128 bits, but only the first */
|
||||
/* 64 bits are actually used. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
|
||||
|
||||
size_t
|
||||
ffi_java_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
switch((*at) -> type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
result += 2 * SIZEOF_ARG;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
default:
|
||||
result += SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_ARG == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void *)raw;
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if SIZEOF_ARG == 8
|
||||
switch((*tp)->type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void*) raw;
|
||||
raw += 2;
|
||||
break;
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
#else /* SIZEOF_ARG != 8 */
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
#endif /* SIZEOF_ARG == 8 */
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_FLOAT:
|
||||
(raw++)->flt = *(FLOAT32*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
raw->uint = *(UINT64*) (*args);
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
#if SIZEOF_ARG == 8
|
||||
FFI_ASSERT(FALSE); /* Should have covered all cases */
|
||||
#else
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_java_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_java_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_java_translate_args,
|
||||
(void*)cl);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
147
libffi/prep_cif.c
Normal file
147
libffi/prep_cif.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Cygnus Solutions
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/* Round up to SIZEOF_ARG. */
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, SIZEOF_ARG)
|
||||
|
||||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(arg != NULL);
|
||||
|
||||
/*@-usedef@*/
|
||||
|
||||
FFI_ASSERT(arg->elements != NULL);
|
||||
FFI_ASSERT(arg->size == 0);
|
||||
FFI_ASSERT(arg->alignment == 0);
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT(ffi_type_test((*ptr)));
|
||||
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
|
||||
/*@=usedef@*/
|
||||
}
|
||||
|
||||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
||||
/*@dependent@*/ ffi_type **atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(cif != NULL);
|
||||
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi < FFI_LAST_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
/*@-usedef@*/
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
/*@=usedef@*/
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT(ffi_type_test(cif->rtype));
|
||||
|
||||
#ifndef M68K
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT(ffi_type_test(*ptr));
|
||||
|
||||
/* Initialize any uninitialized aggregate type definitions */
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_V9))
|
||||
bytes += sizeof(void*);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
241
libffi/raw_api.c
Normal file
241
libffi/raw_api.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
raw_api.c - Copyright (c) 1999 Cygnus Solutions
|
||||
|
||||
Author: Kresten Krab Thorup <krab@gnu.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This file defines generic functions for use with the raw api. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
size_t
|
||||
ffi_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*at)->type == FFI_TYPE_STRUCT)
|
||||
result += ALIGN (sizeof (void*), SIZEOF_ARG);
|
||||
else
|
||||
#endif
|
||||
result += ALIGN ((*at)->size, SIZEOF_ARG);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !FFI_NO_STRUCTS
|
||||
case FFI_TYPE_STRUCT:
|
||||
*args = (raw++)->ptr;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*tp)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*args = (raw++)->ptr;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !FFI_NO_STRUCTS
|
||||
case FFI_TYPE_STRUCT:
|
||||
(raw++)->ptr = *args;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_translate_args,
|
||||
(void*)cl);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
154
libffi/types.c
Normal file
154
libffi/types.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
types.c - Copyright (c) 1996, 1998 Cygnus Solutions
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
|
||||
#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
|
||||
FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
|
||||
FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
|
||||
|
||||
#if defined ALPHA || defined SPARC64
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#elif defined X86_WIN32
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#elif defined ARM
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#elif defined M68K
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined X86_WIN32
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined ARM
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined M68K
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined SPARC
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
|
||||
#ifdef SPARC64
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#endif
|
||||
|
||||
#if SIZEOF_SHORT==1
|
||||
extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint8")));
|
||||
extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint8")));
|
||||
#elif SIZEOF_SHORT==2
|
||||
extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint16")));
|
||||
extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint16")));
|
||||
#elif SIZEOF_SHORT==4
|
||||
extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint32")));
|
||||
extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint32")));
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT==2
|
||||
extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint16")));
|
||||
extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint16")));
|
||||
#elif SIZEOF_INT==4
|
||||
extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint32")));
|
||||
extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint32")));
|
||||
#elif SIZEOF_INT==8
|
||||
extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint64")));
|
||||
extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint64")));
|
||||
#endif
|
||||
|
||||
#if SIZEOF_LONG==4
|
||||
extern ffi_type ffi_type_slong __attribute__((alias("ffi_type_sint32")));
|
||||
extern ffi_type ffi_type_ulong __attribute__((alias("ffi_type_uint32")));
|
||||
#elif SIZEOF_INT==8
|
||||
extern ffi_type ffi_type_slong __attribute__((alias("ffi_type_sint64")));
|
||||
extern ffi_type ffi_type_ulong __attribute__((alias("ffi_type_uint64")));
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user