[multiple changes]

2002-07-16  Bo Thorsen  <bo@suse.de>

	* src/x86/ffi64.c: New file that adds x86-64 support.
	* src/x86/unix64.S: New file that handles argument setup for
	x86-64.
	* src/x86/sysv.S: Don't use this on x86-64.
	* src/x86/ffi.c: Don't use this on x86-64.
	Remove unused vars.
	* src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation
	for x86-64.
	* src/ffitest.c (struct6): New test that tests a special case in
	the x86-64 ABI.
	(struct7): Likewise.
	(struct8): Likewise.
	(struct9): Likewise.
	(closure_test_fn): Silence warning about this when it's not used.
	(main): Add the new tests.
	(main): Fix a couple of wrong casts and silence some compiler warnings.
	* include/ffi.h.in: Add x86-64 ABI definition.
	* fficonfig.h.in: Regenerate.
	* Makefile.am: Add x86-64 support.
	* configure.in: Likewise.
	* Makefile.in: Regenerate.
	* configure: Likewise.

2002-06-24  Bo Thorsen  <bo@suse.de>

	* src/types.c: Merge settings for similar architectures.
	Add x86-64 sizes and alignments.

2002-06-23  Bo Thorsen  <bo@suse.de>

	* src/arm/ffi.c (ffi_prep_args): Remove unused vars.
	* src/sparc/ffi.c (ffi_prep_args_v8): Likewise.
	* src/mips/ffi.c (ffi_prep_args): Likewise.
	* src/m68k/ffi.c (ffi_prep_args): Likewise.

From-SVN: r55571
This commit is contained in:
Bo Thorsen 2002-07-18 23:08:31 +00:00 committed by Bo Thorsen
parent ad28cff7c1
commit c94974caed
17 changed files with 1174 additions and 160 deletions

View File

@ -1,3 +1,40 @@
2002-07-16 Bo Thorsen <bo@suse.de>
* src/x86/ffi64.c: New file that adds x86-64 support.
* src/x86/unix64.S: New file that handles argument setup for
x86-64.
* src/x86/sysv.S: Don't use this on x86-64.
* src/x86/ffi.c: Don't use this on x86-64.
Remove unused vars.
* src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation
for x86-64.
* src/ffitest.c (struct6): New test that tests a special case in
the x86-64 ABI.
(struct7): Likewise.
(struct8): Likewise.
(struct9): Likewise.
(closure_test_fn): Silence warning about this when it's not used.
(main): Add the new tests.
(main): Fix a couple of wrong casts and silence some compiler warnings.
* include/ffi.h.in: Add x86-64 ABI definition.
* fficonfig.h.in: Regenerate.
* Makefile.am: Add x86-64 support.
* configure.in: Likewise.
* Makefile.in: Regenerate.
* configure: Likewise.
2002-06-24 Bo Thorsen <bo@suse.de>
* src/types.c: Merge settings for similar architectures.
Add x86-64 sizes and alignments.
2002-06-23 Bo Thorsen <bo@suse.de>
* src/arm/ffi.c (ffi_prep_args): Remove unused vars.
* src/sparc/ffi.c (ffi_prep_args_v8): Likewise.
* src/mips/ffi.c (ffi_prep_args): Likewise.
* src/m68k/ffi.c (ffi_prep_args): Likewise.
2002-07-18 H.J. Lu (hjl@gnu.org)
* Makefile.am (TARGET_SRC_MIPS_LINUX): New.
@ -15,11 +52,6 @@
* src/s390/sysv.S: Save/restore %r6. Add DWARF-2 unwind info.
2002-05-28 Bo Thorsen <bo@suse.de>
* src/x86/ffi.c (ffi_prep_incoming_args_SYSV): Remove
the same unused avn var from this one too.
2002-05-27 Roger Sayle <roger@eyesopen.com>
* src/x86/ffi.c (ffi_prep_args): Remove reference to avn.

View File

@ -8,6 +8,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
src/mips/n32.s src/mips/o32.S src/mips/o32.s \
src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
src/x86/ffi.c src/x86/sysv.S src/x86/win32.S \
src/x86/ffi64.c src/x86/unix64.S \
src/alpha/ffi.c src/alpha/osf.S \
src/m68k/ffi.c src/m68k/sysv.S \
src/powerpc/ffi.c src/powerpc/sysv.S \
@ -106,6 +107,7 @@ TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/
TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c
TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@)
## Work around automake deficiency
@ -167,6 +169,10 @@ if S390
libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
endif
if X86_64
libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
endif
AM_CFLAGS = -fexceptions

View File

@ -89,6 +89,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
src/mips/n32.s src/mips/o32.S src/mips/o32.s \
src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
src/x86/ffi.c src/x86/sysv.S src/x86/win32.S \
src/x86/ffi64.c src/x86/unix64.S \
src/alpha/ffi.c src/alpha/osf.S \
src/m68k/ffi.c src/m68k/sysv.S \
src/powerpc/ffi.c src/powerpc/sysv.S \
@ -177,6 +178,7 @@ TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/
TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c
TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
src/raw_api.c src/java_raw_api.c
@ -195,6 +197,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
@POWERPC_DARWIN_TRUE@libffi_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN)
@ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
@S390_TRUE@libffi_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
@X86_64_TRUE@libffi_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
@MIPS_GCC_TRUE@libffi_convenience_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
@MIPS_LINUX_TRUE@libffi_convenience_la_SOURCES = @MIPS_LINUX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_LINUX)
@MIPS_SGI_TRUE@libffi_convenience_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI)
@ -209,6 +212,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
@POWERPC_DARWIN_TRUE@libffi_convenience_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN)
@ARM_TRUE@libffi_convenience_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
@S390_TRUE@libffi_convenience_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
@X86_64_TRUE@libffi_convenience_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
AM_CFLAGS = -fexceptions
@ -304,6 +308,9 @@ libffi_la_LIBADD =
@S390_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \
@S390_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
@S390_TRUE@src/s390/sysv.lo src/s390/ffi.lo
@X86_64_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \
@X86_64_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
@X86_64_TRUE@src/x86/ffi.lo src/x86/sysv.lo src/x86/unix64.lo src/x86/ffi64.lo
@X86_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \
@X86_TRUE@src/raw_api.lo src/java_raw_api.lo src/x86/ffi.lo \
@X86_TRUE@src/x86/sysv.lo
@ -323,6 +330,9 @@ libffi_la_LIBADD =
@M68K_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \
@M68K_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
@M68K_TRUE@src/m68k/ffi.lo src/m68k/sysv.lo
@X86_64_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \
@X86_64_TRUE@src/raw_api.lo src/java_raw_api.lo src/x86/ffi.lo \
@X86_64_TRUE@src/x86/sysv.lo src/x86/unix64.lo src/x86/ffi64.lo
noinst_PROGRAMS = ffitest$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)

144
libffi/configure vendored
View File

@ -2395,6 +2395,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
esac
if test $TARGETDIR = unknown; then
@ -2528,12 +2529,21 @@ else
S390_FALSE=
fi
if test x$TARGET = xX86_64; then
X86_64_TRUE=
X86_64_FALSE='#'
else
X86_64_TRUE='#'
X86_64_FALSE=
fi
if test x$TARGET = xMIPS_LINUX; then
TARGET=MIPS
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:2537: checking how to run the C preprocessor" >&5
echo "configure:2547: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@ -2548,13 +2558,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 2552 "configure"
#line 2562 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2558: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2568: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -2565,13 +2575,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 2569 "configure"
#line 2579 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2575: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -2582,13 +2592,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
#line 2586 "configure"
#line 2596 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2592: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2602: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -2613,12 +2623,12 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:2617: checking for ANSI C header files" >&5
echo "configure:2627: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2622 "configure"
#line 2632 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@ -2626,7 +2636,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2630: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2640: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@ -2643,7 +2653,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 2647 "configure"
#line 2657 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@ -2661,7 +2671,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 2665 "configure"
#line 2675 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@ -2682,7 +2692,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 2686 "configure"
#line 2696 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@ -2693,7 +2703,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
if { (eval echo configure:2697: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:2707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@ -2719,12 +2729,12 @@ fi
for ac_func in memcpy
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:2723: checking for $ac_func" >&5
echo "configure:2733: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2728 "configure"
#line 2738 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -2747,7 +2757,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:2751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -2774,19 +2784,19 @@ done
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
echo "configure:2778: checking for working alloca.h" >&5
echo "configure:2788: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2783 "configure"
#line 2793 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
if { (eval echo configure:2790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@ -2807,12 +2817,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
echo "configure:2811: checking for alloca" >&5
echo "configure:2821: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2816 "configure"
#line 2826 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@ -2840,7 +2850,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
if { (eval echo configure:2844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@ -2872,12 +2882,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
echo "configure:2876: checking whether alloca needs Cray hooks" >&5
echo "configure:2886: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2881 "configure"
#line 2891 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@ -2902,12 +2912,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:2906: checking for $ac_func" >&5
echo "configure:2916: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2911 "configure"
#line 2921 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -2930,7 +2940,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:2934: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -2957,7 +2967,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
echo "configure:2961: checking stack direction for C alloca" >&5
echo "configure:2971: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2965,7 +2975,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
#line 2969 "configure"
#line 2979 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@ -2984,7 +2994,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
if { (eval echo configure:2988: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:2998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@ -3007,13 +3017,13 @@ fi
echo $ac_n "checking size of short""... $ac_c" 1>&6
echo "configure:3011: checking size of short" >&5
echo "configure:3021: checking size of short" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3017 "configure"
#line 3027 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3023,7 +3033,7 @@ int main() {
switch (0) case 0: case (sizeof (short) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3027: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3037: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_short=$ac_size
else
@ -3046,13 +3056,13 @@ EOF
echo $ac_n "checking size of int""... $ac_c" 1>&6
echo "configure:3050: checking size of int" >&5
echo "configure:3060: checking size of int" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3056 "configure"
#line 3066 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3062,7 +3072,7 @@ int main() {
switch (0) case 0: case (sizeof (int) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3066: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3076: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_int=$ac_size
else
@ -3085,13 +3095,13 @@ EOF
echo $ac_n "checking size of long""... $ac_c" 1>&6
echo "configure:3089: checking size of long" >&5
echo "configure:3099: checking size of long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3095 "configure"
#line 3105 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3101,7 +3111,7 @@ int main() {
switch (0) case 0: case (sizeof (long) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3105: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3115: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long=$ac_size
else
@ -3124,13 +3134,13 @@ EOF
echo $ac_n "checking size of long long""... $ac_c" 1>&6
echo "configure:3128: checking size of long long" >&5
echo "configure:3138: checking size of long long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3134 "configure"
#line 3144 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3140,7 +3150,7 @@ int main() {
switch (0) case 0: case (sizeof (long long) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3144: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3154: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long_long=$ac_size
else
@ -3163,13 +3173,13 @@ EOF
echo $ac_n "checking size of float""... $ac_c" 1>&6
echo "configure:3167: checking size of float" >&5
echo "configure:3177: checking size of float" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3173 "configure"
#line 3183 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3179,7 +3189,7 @@ int main() {
switch (0) case 0: case (sizeof (float) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3183: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_float=$ac_size
else
@ -3202,13 +3212,13 @@ EOF
echo $ac_n "checking size of double""... $ac_c" 1>&6
echo "configure:3206: checking size of double" >&5
echo "configure:3216: checking size of double" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3212 "configure"
#line 3222 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3218,7 +3228,7 @@ int main() {
switch (0) case 0: case (sizeof (double) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3222: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3232: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_double=$ac_size
else
@ -3241,13 +3251,13 @@ EOF
echo $ac_n "checking size of long double""... $ac_c" 1>&6
echo "configure:3245: checking size of long double" >&5
echo "configure:3255: checking size of long double" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3251 "configure"
#line 3261 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3257,7 +3267,7 @@ int main() {
switch (0) case 0: case (sizeof (long double) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3261: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3271: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long_double=$ac_size
else
@ -3281,13 +3291,13 @@ EOF
echo $ac_n "checking size of void *""... $ac_c" 1>&6
echo "configure:3285: checking size of void *" >&5
echo "configure:3295: checking size of void *" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3291 "configure"
#line 3301 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@ -3297,7 +3307,7 @@ int main() {
switch (0) case 0: case (sizeof (void *) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3301: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_void_p=$ac_size
else
@ -3320,14 +3330,14 @@ EOF
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
echo "configure:3324: checking whether byte ordering is bigendian" >&5
echo "configure:3334: checking whether byte ordering is bigendian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
#line 3331 "configure"
#line 3341 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@ -3338,11 +3348,11 @@ int main() {
#endif
; return 0; }
EOF
if { (eval echo configure:3342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
#line 3346 "configure"
#line 3356 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@ -3353,7 +3363,7 @@ int main() {
#endif
; return 0; }
EOF
if { (eval echo configure:3357: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
@ -3373,7 +3383,7 @@ if test "$cross_compiling" = yes; then
echo $ac_n "cross-compiling... " 2>&6
else
cat > conftest.$ac_ext <<EOF
#line 3377 "configure"
#line 3387 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
@ -3386,7 +3396,7 @@ main () {
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
if { (eval echo configure:3390: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:3400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
@ -3404,7 +3414,7 @@ fi
echo "$ac_t""$ac_cv_c_bigendian" 1>&6
if test $ac_cv_c_bigendian = unknown; then
echo $ac_n "checking to probe for byte ordering""... $ac_c" 1>&6
echo "configure:3408: checking to probe for byte ordering" >&5
echo "configure:3418: checking to probe for byte ordering" >&5
cat >conftest.c <<EOF
short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
@ -3454,7 +3464,7 @@ fi
if test x$TARGET = xSPARC; then
echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6
echo "configure:3458: checking assembler and linker support unaligned pc related relocs" >&5
echo "configure:3468: checking assembler and linker support unaligned pc related relocs" >&5
if eval "test \"`echo '$''{'libffi_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3464,14 +3474,14 @@ else
CFLAGS="$CFLAGS -fpic"
LDFLAGS="$LDFLAGS -shared"
cat > conftest.$ac_ext <<EOF
#line 3468 "configure"
#line 3478 "configure"
#include "confdefs.h"
asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");
int main() {
; return 0; }
EOF
if { (eval echo configure:3475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
libffi_cv_as_sparc_ua_pcrel=yes
else
@ -3756,6 +3766,8 @@ s%@ARM_TRUE@%$ARM_TRUE%g
s%@ARM_FALSE@%$ARM_FALSE%g
s%@S390_TRUE@%$S390_TRUE%g
s%@S390_FALSE@%$S390_FALSE%g
s%@X86_64_TRUE@%$X86_64_TRUE%g
s%@X86_64_FALSE@%$X86_64_FALSE%g
s%@CPP@%$CPP%g
s%@ALLOCA@%$ALLOCA%g
s%@TARGET@%$TARGET%g

View File

@ -70,6 +70,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
esac
if test $TARGETDIR = unknown; then
@ -90,6 +91,7 @@ AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
AM_CONDITIONAL(S390, test x$TARGET = xS390)
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
if test x$TARGET = xMIPS_LINUX; then
TARGET=MIPS

View File

@ -189,10 +189,15 @@ typedef enum ffi_abi {
#endif
#endif
/* ---- Intel x86 ---------------- */
#ifdef X86
/* ---- Intel x86 and AMD x86-64 - */
#if defined(X86) || defined(X86_64)
FFI_SYSV,
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
#ifdef X86
FFI_DEFAULT_ABI = FFI_SYSV,
#else
FFI_DEFAULT_ABI = FFI_UNIX64,
#endif
#endif
/* ---- Intel x86 Win32 ---------- */

View File

@ -36,13 +36,10 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
register unsigned int i;
register int tmp;
register unsigned int avn;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
tmp = 0;
argp = stack;
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
@ -50,11 +47,10 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
argp += 4;
}
avn = ecif->cif->nargs;
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0) && (avn != 0);
(i != 0);
i--, p_arg++)
{
size_t z;
@ -64,9 +60,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
}
if (avn != 0)
{
avn--;
z = (*p_arg)->size;
if (z < sizeof(int))
{
@ -107,7 +100,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
}
p_argv++;
argp += z;
}
}
return;

View File

@ -153,6 +153,33 @@ typedef struct
char c2;
} test_structure_5;
typedef struct
{
float f;
double d;
} test_structure_6;
typedef struct
{
float f1;
float f2;
double d;
} test_structure_7;
typedef struct
{
float f1;
float f2;
float f3;
float f4;
} test_structure_8;
typedef struct
{
float f;
int i;
} test_structure_9;
static test_structure_1 struct1(test_structure_1 ts)
{
/*@-type@*/
@ -194,15 +221,52 @@ static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
return ts1;
}
static test_structure_6 struct6 (test_structure_6 ts)
{
ts.f += 1;
ts.d += 1;
return ts;
}
static test_structure_7 struct7 (test_structure_7 ts)
{
ts.f1 += 1;
ts.f2 += 1;
ts.d += 1;
return ts;
}
static test_structure_8 struct8 (test_structure_8 ts)
{
ts.f1 += 1;
ts.f2 += 1;
ts.f3 += 1;
ts.f4 += 1;
return ts;
}
static test_structure_9 struct9 (test_structure_9 ts)
{
ts.f += 1;
ts.i += 1;
return ts;
}
/* 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)
#if FFI_CLOSURES
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;
*(int*)resp = *(int*)args[0] + (int)(*(float*)args[1]) + (int)(long)userdata;
}
typedef int (*closure_test_type)(int, float);
#endif
int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
{
@ -230,11 +294,19 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
ffi_type ts3_type;
ffi_type ts4_type;
ffi_type ts5_type;
ffi_type ts6_type;
ffi_type ts7_type;
ffi_type ts8_type;
ffi_type ts9_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];
ffi_type *ts6_type_elements[3];
ffi_type *ts7_type_elements[4];
ffi_type *ts8_type_elements[5];
ffi_type *ts9_type_elements[3];
ts1_type.size = 0;
ts1_type.alignment = 0;
@ -256,12 +328,32 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
ts5_type.alignment = 0;
ts5_type.type = FFI_TYPE_STRUCT;
ts6_type.size = 0;
ts6_type.alignment = 0;
ts6_type.type = FFI_TYPE_STRUCT;
ts7_type.size = 0;
ts7_type.alignment = 0;
ts7_type.type = FFI_TYPE_STRUCT;
ts8_type.size = 0;
ts8_type.alignment = 0;
ts8_type.type = FFI_TYPE_STRUCT;
ts9_type.size = 0;
ts9_type.alignment = 0;
ts9_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;
ts6_type.elements = ts6_type_elements;
ts7_type.elements = ts7_type_elements;
ts8_type.elements = ts8_type_elements;
ts9_type.elements = ts9_type_elements;
/*@=immediatetrans@*/
ts1_type_elements[0] = &ffi_type_uchar;
@ -285,6 +377,25 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
ts5_type_elements[1] = &ffi_type_schar;
ts5_type_elements[2] = NULL;
ts6_type_elements[0] = &ffi_type_float;
ts6_type_elements[1] = &ffi_type_double;
ts6_type_elements[2] = NULL;
ts7_type_elements[0] = &ffi_type_float;
ts7_type_elements[1] = &ffi_type_float;
ts7_type_elements[2] = &ffi_type_double;
ts7_type_elements[3] = NULL;
ts8_type_elements[0] = &ffi_type_float;
ts8_type_elements[1] = &ffi_type_float;
ts8_type_elements[2] = &ffi_type_float;
ts8_type_elements[3] = &ffi_type_float;
ts8_type_elements[4] = NULL;
ts9_type_elements[0] = &ffi_type_float;
ts9_type_elements[1] = &ffi_type_sint;
ts9_type_elements[2] = NULL;
ul = 0;
/* return value tests */
@ -326,7 +437,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
{
ul++;
ffi_call(&cif, FFI_FN(return_sc), &rint, values);
CHECK(rint == (int) sc);
CHECK(rint == (ffi_arg) sc);
}
args[0] = &ffi_type_uchar;
@ -413,7 +524,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
ffi_call(&cif, FFI_FN(floating), &rint, values);
printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld, si2));
CHECK(rint == floating(si1, f, d, ld, si2));
@ -483,7 +594,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
&ffi_type_float, args) == FFI_OK);
/*@-usedef@*/
ff = many(fa[0], fa[1],
ff = many (fa[0], fa[1],
fa[2], fa[3],
fa[4], fa[5],
fa[6], fa[7],
@ -532,7 +643,8 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
{
ul++;
ffi_call(&cif, FFI_FN(promotion), &rint, values);
CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
CHECK((int)rint == (signed char) sc + (signed short) ss +
(unsigned char) uc + (unsigned short) us);
}
printf("%lu promotion tests run\n", ul);
}
@ -579,8 +691,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
values[0] = &ts2_arg;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ts2_type, args) == FFI_OK);
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
ts2_arg.d1 = 5.55;
ts2_arg.d2 = 6.66;
@ -647,8 +758,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
values[0] = &ts4_arg;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ts4_type, args) == FFI_OK);
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
ts4_arg.ui1 = 2;
ts4_arg.ui2 = 3;
@ -678,8 +788,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
values[1] = &ts5_arg2;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
&ts5_type, args) == FFI_OK);
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
ts5_arg1.c1 = 2;
ts5_arg1.c2 = 6;
@ -697,6 +806,150 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
free (ts5_result);
}
/* struct tests */
{
test_structure_6 ts6_arg;
/* This is a hack to get a properly aligned result buffer */
test_structure_6 *ts6_result =
(test_structure_6 *) malloc (sizeof(test_structure_6));
args[0] = &ts6_type;
values[0] = &ts6_arg;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
ts6_arg.f = 5.55f;
ts6_arg.d = 6.66;
printf ("%g\n", ts6_arg.f);
printf ("%g\n", ts6_arg.d);
ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
printf ("%g\n", ts6_result->f);
printf ("%g\n", ts6_result->d);
CHECK(ts6_result->f == 5.55f + 1);
CHECK(ts6_result->d == 6.66 + 1);
printf("structure test 6 ok!\n");
free (ts6_result);
}
/* struct tests */
{
test_structure_7 ts7_arg;
/* This is a hack to get a properly aligned result buffer */
test_structure_7 *ts7_result =
(test_structure_7 *) malloc (sizeof(test_structure_7));
args[0] = &ts7_type;
values[0] = &ts7_arg;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
ts7_arg.f1 = 5.55f;
ts7_arg.f2 = 55.5f;
ts7_arg.d = 6.66;
printf ("%g\n", ts7_arg.f1);
printf ("%g\n", ts7_arg.f2);
printf ("%g\n", ts7_arg.d);
ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
printf ("%g\n", ts7_result->f1);
printf ("%g\n", ts7_result->f2);
printf ("%g\n", ts7_result->d);
CHECK(ts7_result->f1 == 5.55f + 1);
CHECK(ts7_result->f2 == 55.5f + 1);
CHECK(ts7_result->d == 6.66 + 1);
printf("structure test 7 ok!\n");
free (ts7_result);
}
/* struct tests */
{
test_structure_8 ts8_arg;
/* This is a hack to get a properly aligned result buffer */
test_structure_8 *ts8_result =
(test_structure_8 *) malloc (sizeof(test_structure_8));
args[0] = &ts8_type;
values[0] = &ts8_arg;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
ts8_arg.f1 = 5.55f;
ts8_arg.f2 = 55.5f;
ts8_arg.f3 = -5.55f;
ts8_arg.f4 = -55.5f;
printf ("%g\n", ts8_arg.f1);
printf ("%g\n", ts8_arg.f2);
printf ("%g\n", ts8_arg.f3);
printf ("%g\n", ts8_arg.f4);
ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
printf ("%g\n", ts8_result->f1);
printf ("%g\n", ts8_result->f2);
printf ("%g\n", ts8_result->f3);
printf ("%g\n", ts8_result->f4);
CHECK(ts8_result->f1 == 5.55f + 1);
CHECK(ts8_result->f2 == 55.5f + 1);
CHECK(ts8_result->f3 == -5.55f + 1);
CHECK(ts8_result->f4 == -55.5f + 1);
printf("structure test 8 ok!\n");
free (ts8_result);
}
/* struct tests */
{
test_structure_9 ts9_arg;
/* This is a hack to get a properly aligned result buffer */
test_structure_9 *ts9_result =
(test_structure_9 *) malloc (sizeof(test_structure_9));
args[0] = &ts9_type;
values[0] = &ts9_arg;
/* Initialize the cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
ts9_arg.f = 5.55f;
ts9_arg.i = 5;
printf ("%g\n", ts9_arg.f);
printf ("%d\n", ts9_arg.i);
ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
printf ("%g\n", ts9_result->f);
printf ("%d\n", ts9_result->i);
CHECK(ts9_result->f == 5.55f + 1);
CHECK(ts9_result->i == 5 + 1);
printf("structure test 9 ok!\n");
free (ts9_result);
}
#else
printf("Structure passing doesn't work on Win32.\n");
#endif /* X86_WIN32 */

View File

@ -16,14 +16,11 @@ static void *
ffi_prep_args (void *stack, extended_cif *ecif)
{
unsigned int i;
int tmp;
unsigned int avn;
void **p_argv;
char *argp;
ffi_type **p_arg;
void *struct_value_ptr;
tmp = 0;
argp = stack;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
@ -32,11 +29,10 @@ ffi_prep_args (void *stack, extended_cif *ecif)
else
struct_value_ptr = NULL;
avn = ecif->cif->nargs;
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
i != 0 && avn != 0;
i != 0;
i--, p_arg++)
{
size_t z;
@ -45,9 +41,6 @@ ffi_prep_args (void *stack, extended_cif *ecif)
if (((*p_arg)->alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, (*p_arg)->alignment);
if (avn != 0)
{
avn--;
z = (*p_arg)->size;
if (z < sizeof (int))
{
@ -82,7 +75,6 @@ ffi_prep_args (void *stack, extended_cif *ecif)
memcpy (argp, *p_argv, z);
p_argv++;
argp += z;
}
}
return struct_value_ptr;

View File

@ -51,7 +51,6 @@ static void ffi_prep_args(char *stack,
int flags)
{
register int i;
register int avn;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
@ -81,12 +80,9 @@ static void ffi_prep_args(char *stack,
FIX_ARGP;
}
avn = ecif->cif->nargs;
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
i && avn;
i--, p_arg++)
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
{
size_t z;
@ -102,9 +98,6 @@ static void ffi_prep_args(char *stack,
#define OFFSET sizeof(int)
#endif
if (avn)
{
avn--;
z = (*p_arg)->size;
if (z < sizeof(SLOT_TYPE_UNSIGNED))
{
@ -180,7 +173,6 @@ static void ffi_prep_args(char *stack,
p_argv++;
argp += z;
FIX_ARGP;
}
}
return;

View File

@ -103,7 +103,9 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
/* Perform a sanity check on the return type */
FFI_ASSERT(ffi_type_test(cif->rtype));
#ifndef M68K
/* x86-64 and s390 stack space allocation is handled in prep_machdep.
TODO: Disable this for s390 too? */
#if !defined M68K && !defined __x86_64__
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
@ -122,6 +124,8 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* TODO: Disable this calculation for s390 too? */
#ifndef __x86_64__
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
@ -137,6 +141,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
cif->bytes = bytes;

View File

@ -34,14 +34,10 @@
void ffi_prep_args_v8(char *stack, extended_cif *ecif)
{
int i;
int tmp;
int avn;
void **p_argv;
char *argp;
ffi_type **p_arg;
tmp = 0;
/* Skip 16 words for the window save area */
argp = stack + 16*sizeof(int);
@ -66,18 +62,12 @@ void ffi_prep_args_v8(char *stack, extended_cif *ecif)
((int*)argp)[5] = 0;
#endif
avn = ecif->cif->nargs;
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
i && avn;
i--, p_arg++)
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
{
size_t z;
if (avn)
{
avn--;
if ((*p_arg)->type == FFI_TYPE_STRUCT
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE
@ -122,7 +112,6 @@ void ffi_prep_args_v8(char *stack, extended_cif *ecif)
}
p_argv++;
argp += z;
}
}
return;

View File

@ -42,7 +42,7 @@ 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
#if defined ALPHA || defined SPARC64 || defined X86_64
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
@ -52,22 +52,7 @@ FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
#endif
#ifdef X86
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
#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
@ -80,12 +65,7 @@ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
#endif
#ifdef X86
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
#elif defined X86_WIN32
#if defined X86 || defined X86_WIN32 || defined M68K
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
@ -95,25 +75,20 @@ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
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
#elif defined X86_64
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
#else
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);

View File

@ -23,6 +23,8 @@
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef __x86_64__
#include <ffi.h>
#include <ffi_common.h>
@ -491,3 +493,5 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
}
#endif
#endif /* __x86_64__ */

575
libffi/src/x86/ffi64.c Normal file
View File

@ -0,0 +1,575 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
x86-64 Foreign Function Interface
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 CYGNUS SOLUTIONS 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>
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
#ifdef __x86_64__
#define MAX_GPR_REGS 6
#define MAX_SSE_REGS 8
typedef struct
{
/* Registers for argument passing. */
long gpr[MAX_GPR_REGS];
__int128_t sse[MAX_SSE_REGS];
/* Stack space for arguments. */
char argspace[0];
} stackLayout;
/* All reference to register classes here is identical to the code in
gcc/config/i386/i386.c. Do *not* change one without the other. */
/* Register class used for passing given 64bit part of the argument.
These represent classes as documented by the PS ABI, with the exception
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
use SF or DFmode move instead of DImode to avoid reformating penalties.
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
whenever possible (upper half does contain padding).
*/
enum x86_64_reg_class
{
X86_64_NO_CLASS,
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS,
X86_64_SSE_CLASS,
X86_64_SSESF_CLASS,
X86_64_SSEDF_CLASS,
X86_64_SSEUP_CLASS,
X86_64_X87_CLASS,
X86_64_X87UP_CLASS,
X86_64_MEMORY_CLASS
};
#define MAX_CLASSES 4
/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
of this code is to classify each 8bytes of incoming argument by the register
class and assign registers accordingly. */
/* Return the union class of CLASS1 and CLASS2.
See the x86-64 PS ABI for details. */
static enum x86_64_reg_class
merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
{
/* Rule #1: If both classes are equal, this is the resulting class. */
if (class1 == class2)
return class1;
/* Rule #2: If one of the classes is NO_CLASS, the resulting class is
the other class. */
if (class1 == X86_64_NO_CLASS)
return class2;
if (class2 == X86_64_NO_CLASS)
return class1;
/* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
return X86_64_MEMORY_CLASS;
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
|| (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
return X86_64_INTEGERSI_CLASS;
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
return X86_64_INTEGER_CLASS;
/* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */
if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
|| class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
return X86_64_MEMORY_CLASS;
/* Rule #6: Otherwise class SSE is used. */
return X86_64_SSE_CLASS;
}
/* Classify the argument of type TYPE and mode MODE.
CLASSES will be filled by the register class used to pass each word
of the operand. The number of words is returned. In case the parameter
should be passed in memory, 0 is returned. As a special case for zero
sized containers, classes[0] will be NO_CLASS and 1 is returned.
See the x86-64 PS ABI for details.
*/
static int
classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
int *byte_offset)
{
/* First, align to the right place. */
*byte_offset = ALIGN(*byte_offset, type->alignment);
switch (type->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
if (((*byte_offset) % 8 + type->size) <= 4)
classes[0] = X86_64_INTEGERSI_CLASS;
else
classes[0] = X86_64_INTEGER_CLASS;
return 1;
case FFI_TYPE_FLOAT:
if (((*byte_offset) % 8) == 0)
classes[0] = X86_64_SSESF_CLASS;
else
classes[0] = X86_64_SSE_CLASS;
return 1;
case FFI_TYPE_DOUBLE:
classes[0] = X86_64_SSEDF_CLASS;
return 1;
case FFI_TYPE_LONGDOUBLE:
classes[0] = X86_64_X87_CLASS;
classes[1] = X86_64_X87UP_CLASS;
return 2;
case FFI_TYPE_STRUCT:
{
const int UNITS_PER_WORD = 8;
int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
ffi_type **ptr;
int i;
enum x86_64_reg_class subclasses[MAX_CLASSES];
/* If the struct is larger than 16 bytes, pass it on the stack. */
if (type->size > 16)
return 0;
for (i = 0; i < words; i++)
classes[i] = X86_64_NO_CLASS;
/* Merge the fields of structure. */
for (ptr=type->elements; (*ptr)!=NULL; ptr++)
{
int num;
num = classify_argument (*ptr, subclasses, byte_offset);
if (num == 0)
return 0;
for (i = 0; i < num; i++)
{
int pos = *byte_offset / 8;
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
}
if ((*ptr)->type != FFI_TYPE_STRUCT)
*byte_offset += (*ptr)->size;
}
/* Final merger cleanup. */
for (i = 0; i < words; i++)
{
/* If one class is MEMORY, everything should be passed in
memory. */
if (classes[i] == X86_64_MEMORY_CLASS)
return 0;
/* The X86_64_SSEUP_CLASS should be always preceded by
X86_64_SSE_CLASS. */
if (classes[i] == X86_64_SSEUP_CLASS
&& (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
classes[i] = X86_64_SSE_CLASS;
/* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
if (classes[i] == X86_64_X87UP_CLASS
&& (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
classes[i] = X86_64_SSE_CLASS;
}
return words;
}
default:
FFI_ASSERT(0);
}
return 0; /* Never reached. */
}
/* Examine the argument and return set number of register required in each
class. Return 0 iff parameter should be passed in memory. */
static int
examine_argument (ffi_type *type, int in_return, int *int_nregs,int *sse_nregs)
{
enum x86_64_reg_class class[MAX_CLASSES];
int offset = 0;
int n;
n = classify_argument (type, class, &offset);
if (n == 0)
return 0;
*int_nregs = 0;
*sse_nregs = 0;
for (n--; n>=0; n--)
switch (class[n])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
(*int_nregs)++;
break;
case X86_64_SSE_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
(*sse_nregs)++;
break;
case X86_64_NO_CLASS:
case X86_64_SSEUP_CLASS:
break;
case X86_64_X87_CLASS:
case X86_64_X87UP_CLASS:
if (!in_return)
return 0;
break;
default:
abort ();
}
return 1;
}
/* Functions to load floats and double to an SSE register placeholder. */
extern void float2sse (float, __int128_t *);
extern void double2sse (double, __int128_t *);
extern void floatfloat2sse (void *, __int128_t *);
/* Functions to put the floats and doubles back. */
extern float sse2float (__int128_t *);
extern double sse2double (__int128_t *);
extern void sse2floatfloat(__int128_t *, void *);
/*@-exportheader@*/
void
ffi_prep_args (stackLayout *stack, extended_cif *ecif)
/*@=exportheader@*/
{
int gprcount, ssecount, i, g, s;
void **p_argv;
void *argp = &stack->argspace;
ffi_type **p_arg;
/* First check if the return value should be passed in memory. If so,
pass the pointer as the first argument. */
gprcount = ssecount = 0;
if (examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
(void *)stack->gpr[gprcount++] = ecif->rvalue;
for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
i!=0; i--, p_arg++, p_argv++)
{
int in_register = 0;
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
if (gprcount < MAX_GPR_REGS)
{
stack->gpr[gprcount] = 0;
stack->gpr[gprcount++] = *(long long *)(*p_argv);
in_register = 1;
}
break;
case FFI_TYPE_FLOAT:
if (ssecount < MAX_SSE_REGS)
{
float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
in_register = 1;
}
break;
case FFI_TYPE_DOUBLE:
if (ssecount < MAX_SSE_REGS)
{
double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
in_register = 1;
}
break;
}
if (in_register)
continue;
/* Either all places in registers where filled, or this is a
type that potentially goes into a memory slot. */
if (examine_argument (*p_arg, 0, &g, &s) == 0
|| gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
{
/* Pass this argument in memory. */
argp = (void *)ALIGN(argp, (*p_arg)->alignment);
memcpy (argp, *p_argv, (*p_arg)->size);
argp += (*p_arg)->size;
}
else
{
/* All easy cases are eliminated. Now fire the big guns. */
enum x86_64_reg_class classes[MAX_CLASSES];
int offset = 0, j, num;
void *a;
num = classify_argument (*p_arg, classes, &offset);
for (j=0, a=*p_argv; j<num; j++, a+=8)
{
switch (classes[j])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
stack->gpr[gprcount++] = *(long long *)a;
break;
case X86_64_SSE_CLASS:
floatfloat2sse (a, &stack->sse[ssecount++]);
break;
case X86_64_SSESF_CLASS:
float2sse (*(float *)a, &stack->sse[ssecount++]);
break;
case X86_64_SSEDF_CLASS:
double2sse (*(double *)a, &stack->sse[ssecount++]);
break;
default:
abort();
}
}
}
}
}
/* Perform machine dependent cif processing. */
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
int gprcount, ssecount, i, g, s;
gprcount = ssecount = 0;
/* Reset the byte count. We handle this size estimation here. */
cif->bytes = 0;
/* If the return value should be passed in memory, pass the pointer
as the first argument. The actual memory isn't allocated here. */
if (examine_argument (cif->rtype, 1, &g, &s) == 0)
gprcount = 1;
/* Go over all arguments and determine the way they should be passed.
If it's in a register and there is space for it, let that be so. If
not, add it's size to the stack byte count. */
for (i=0; i<cif->nargs; i++)
{
if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
|| gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
{
/* This is passed in memory. First align to the basic type. */
cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
/* Stack arguments are *always* at least 8 byte aligned. */
cif->bytes = ALIGN(cif->bytes, 8);
/* Now add the size of this argument. */
cif->bytes += cif->arg_types[i]->size;
}
else
{
gprcount += g;
ssecount += s;
}
}
/* Set the flag for the closures return. */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
case FFI_TYPE_STRUCT:
case FFI_TYPE_SINT64:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
cif->flags = (unsigned) cif->rtype->type;
break;
case FFI_TYPE_UINT64:
cif->flags = FFI_TYPE_SINT64;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
}
puts ("prep_machdep\n");
return FFI_OK;
}
typedef struct
{
long gpr[2];
__int128_t sse[2];
long double st0;
} return_value;
void
ffi_fill_return_value (return_value *rv, extended_cif *ecif)
{
enum x86_64_reg_class classes[MAX_CLASSES];
int i = 0, num;
long *gpr = rv->gpr;
__int128_t *sse = rv->sse;
signed char sc;
signed short ss;
/* This is needed because of the way x86-64 handles signed short
integers. */
switch (ecif->cif->rtype->type)
{
case FFI_TYPE_SINT8:
sc = *(signed char *)gpr;
*(long long *)ecif->rvalue = (long long)sc;
return;
case FFI_TYPE_SINT16:
ss = *(signed short *)gpr;
*(long long *)ecif->rvalue = (long long)ss;
return;
default:
/* Just continue. */
;
}
num = classify_argument (ecif->cif->rtype, classes, &i);
if (num == 0)
/* Return in memory. */
ecif->rvalue = (void *) rv->gpr[0];
else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
classes[1] == X86_64_X87UP_CLASS)
/* This is a long double (this is easiest to handle this way instead
of an eightbyte at a time as in the loop below. */
*((long double *)ecif->rvalue) = rv->st0;
else
{
void *a;
for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
{
switch (classes[i])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
*(long long *)a = *gpr;
gpr++;
break;
case X86_64_SSE_CLASS:
sse2floatfloat (sse++, a);
break;
case X86_64_SSESF_CLASS:
*(float *)a = sse2float (sse++);
break;
case X86_64_SSEDF_CLASS:
*(double *)a = sse2double (sse++);
break;
default:
abort();
}
}
}
}
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
void (*) (return_value *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, /*@out@*/ unsigned *, void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
int dummy;
ecif.cif = cif;
ecif.avalue = avalue;
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
if ((rvalue == NULL) &&
(examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
/* Stack must always be 16byte aligned. Make it so. */
cif->bytes = ALIGN(cif->bytes, 16);
switch (cif->abi)
{
case FFI_SYSV:
/* Calling 32bit code from 64bit is not possible */
FFI_ASSERT(0);
break;
case FFI_UNIX64:
/*@-usedef@*/
ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
cif->bytes, ecif.rvalue, fn);
/*@=usedef@*/
break;
default:
FFI_ASSERT(0);
break;
}
}
#endif /* ifndef __x86_64__ */

View File

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 1996, 1998, 2001 Cygnus Solutions
sysv.S - Copyright (c) 1996, 1998, 2001, 2002 Cygnus Solutions
X86 Foreign Function Interface
@ -23,6 +23,8 @@
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef __x86_64__
#define LIBFFI_ASM
#include <ffi.h>
@ -163,3 +165,5 @@ __FRAME_BEGIN__:
.align 4
.LEFDE1:
.set .LLFDE1,.LEFDE1-.LSFDE1
#endif /* ifndef __x86_64__ */

166
libffi/src/x86/unix64.S Normal file
View File

@ -0,0 +1,166 @@
/* -----------------------------------------------------------------------
unix64.S - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
x86-64 Foreign Function Interface
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 CYGNUS SOLUTIONS 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.
----------------------------------------------------------------------- */
#ifdef __x86_64__
#define LIBFFI_ASM
#include <ffi.h>
.section .rodata
.LC0:
.string "asm in progress %lld\n"
.LC1:
.string "asm in progress\n"
.text
.align 2
.globl ffi_call_UNIX64
.type ffi_call_UNIX64,@function
ffi_call_UNIX64:
.LFB1:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
/* Save all arguments */
subq $48, %rsp
.LCFI2:
movq %rdi, -8(%rbp) /* ffi_prep_args */
movq %rsi, -16(%rbp) /* ffi_fill_return_value */
movq %rdx, -24(%rbp) /* ecif */
movq %rcx, -32(%rbp) /* cif->bytes */
movq %r8, -40(%rbp) /* ecif.rvalue */
movq %r9, -48(%rbp) /* fn */
/* Make room for all of the new args and the register args */
addl $176, %ecx
.LCFI3:
subq %rcx, %rsp
.LCFI4:
/* Setup the call to ffi_prep_args. */
movq %rdi, %rax /* &ffi_prep_args */
movq %rsp, %rdi /* stackLayout */
movq %rdx, %rsi /* ecif */
call *%rax /* ffi_prep_args(stackLayout, ecif);*/
/* ffi_prep_args have put all the register contents into the */
/* stackLayout struct. Now put the register values in place. */
movq (%rsp), %rdi
movq 8(%rsp), %rsi
movq 16(%rsp), %rdx
movq 24(%rsp), %rcx
movq 32(%rsp), %r8
movq 40(%rsp), %r9
movaps 48(%rsp), %xmm0
movaps 64(%rsp), %xmm1
movaps 80(%rsp), %xmm2
movaps 96(%rsp), %xmm3
movaps 112(%rsp), %xmm4
movaps 128(%rsp), %xmm5
movaps 144(%rsp), %xmm6
movaps 160(%rsp), %xmm7
/* Remove space for stackLayout so stack arguments are placed
correctly for the call. */
.LCFI5:
addq $176, %rsp
.LCFI6:
/* Call the user function. */
call *-48(%rbp)
/* Make stack space for the return_value struct. */
subq $64, %rsp
/* Fill in all potential return values to this struct. */
movq %rax, (%rsp)
movq %rdx, 8(%rsp)
movaps %xmm0, 16(%rsp)
movaps %xmm1, 32(%rsp)
fstpt 48(%rsp)
/* Now call ffi_fill_return_value. */
movq %rsp, %rdi /* struct return_value */
movq -24(%rbp), %rsi /* ecif */
movq -16(%rbp), %rax /* &ffi_fill_return_value */
call *%rax /* call it */
/* And the work is done. */
leave
ret
.LFE1:
.ffi_call_UNIX64_end:
.size ffi_call_UNIX64,.ffi_call_UNIX64_end-ffi_call_UNIX64
.text
.align 2
.globl float2sse
.type float2sse,@function
float2sse:
/* Save the contents of this sse-float in a pointer. */
movaps %xmm0, (%rdi)
ret
.align 2
.globl floatfloat2sse
.type floatfloat2sse,@function
floatfloat2sse:
/* Save the contents of these two sse-floats in a pointer. */
movq (%rdi), %xmm0
movaps %xmm0, (%rsi)
ret
.align 2
.globl double2sse
.type double2sse,@function
double2sse:
/* Save the contents of this sse-double in a pointer. */
movaps %xmm0, (%rdi)
ret
.align 2
.globl sse2float
.type sse2float,@function
sse2float:
/* Save the contents of this sse-float in a pointer. */
movaps (%rdi), %xmm0
ret
.align 2
.globl sse2double
.type sse2double,@function
sse2double:
/* Save the contents of this pointer in a sse-double. */
movaps (%rdi), %xmm0
ret
.align 2
.globl sse2floatfloat
.type sse2floatfloat,@function
sse2floatfloat:
/* Save the contents of this pointer in two sse-floats. */
movaps (%rdi), %xmm0
movq %xmm0, (%rsi)
ret
#endif /* __x86_64__ */