[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:
parent
ad28cff7c1
commit
c94974caed
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
144
libffi/configure
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ---------- */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
575
libffi/src/x86/ffi64.c
Normal 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__ */
|
@ -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
166
libffi/src/x86/unix64.S
Normal 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__ */
|
Loading…
Reference in New Issue
Block a user