Merge libffi to upstream commit c82cc159426d8d4402375fa1ae3f045b9cf82e16

From-SVN: r219477
This commit is contained in:
Richard Henderson 2015-01-12 08:19:59 -08:00 committed by Richard Henderson
parent 62e22fcb79
commit b1760f7f91
221 changed files with 23053 additions and 15964 deletions

View file

@ -1,3 +1,7 @@
2015-01-12 Richard Henderson <rth@redhat.com>
Merge to upstream commit c82cc159426d8d4402375fa1ae3f045b9cf82e16.
2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
PR bootstrap/63784

View file

@ -1,4 +1,4 @@
libffi - Copyright (c) 1996-2012 Anthony Green, Red Hat, Inc and others.
libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others.
See source files for details.
Permission is hereby granted, free of charge, to any person obtaining

View file

@ -1,46 +1,19 @@
## Process this with automake to create Makefile.in
AUTOMAKE_OPTIONS = foreign subdir-objects
ACLOCAL_AMFLAGS = -I .. -I ../config
SUBDIRS = include testsuite man
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \
src/aarch64/ffi.c src/aarch64/ffitarget.h \
src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h \
src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h \
src/ia64/unix.S src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S \
src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S \
src/m68k/ffitarget.h \
src/powerpc/ffi.c src/powerpc/ffi_powerpc.h \
src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \
src/powerpc/sysv.S src/powerpc/linux64.S \
src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \
src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S \
src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c \
src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S \
src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c \
src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S \
src/x86/win32.S src/x86/darwin.S src/x86/win64.S \
src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S \
src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c \
src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c \
src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S \
src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c \
src/tile/ffitarget.h src/tile/tile.S libtool-version \
ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4 \
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
ChangeLog.libffi ChangeLog.libffi-3.1 \
m4/libtool.m4 m4/lt~obsolete.m4 \
m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \
m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh \
generate-ios-source-and-headers.py \
generate-osx-source-and-headers.py \
libffi.xcodeproj/project.pbxproj src/arm/trampoline.S
m4/ltversion.m4 src/debug.c msvcc.sh \
generate-darwin-source-and-headers.py \
libffi.xcodeproj/project.pbxproj \
libtool-ldflags
# Automake Documentation:
# If your package has Texinfo files in many directories, you can use the
@ -79,7 +52,6 @@ stamp-build-info: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)/doc -o doc/libffi.info $(srcdir)/doc/libffi.texi
@touch $@
CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) doc/libffi.info
MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
@ -93,153 +65,147 @@ MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
# values defined in terms of make variables, as is the case for CC and
# friends when we are called from the top level Makefile.
AM_MAKEFLAGS = \
"AR_FLAGS=$(AR_FLAGS)" \
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
"CFLAGS=$(CFLAGS)" \
"CXXFLAGS=$(CXXFLAGS)" \
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
"JC1FLAGS=$(JC1FLAGS)" \
"LDFLAGS=$(LDFLAGS)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
"PICFLAG=$(PICFLAG)" \
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
"SHELL=$(SHELL)" \
"exec_prefix=$(exec_prefix)" \
"infodir=$(infodir)" \
"libdir=$(libdir)" \
"mandir=$(mandir)" \
"prefix=$(prefix)" \
"AR=$(AR)" \
"AS=$(AS)" \
"CC=$(CC)" \
"CXX=$(CXX)" \
"LD=$(LD)" \
"NM=$(NM)" \
"RANLIB=$(RANLIB)" \
"DESTDIR=$(DESTDIR)"
'AR_FLAGS=$(AR_FLAGS)' \
'CC_FOR_BUILD=$(CC_FOR_BUILD)' \
'CFLAGS=$(CFLAGS)' \
'CXXFLAGS=$(CXXFLAGS)' \
'CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)' \
'CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)' \
'INSTALL=$(INSTALL)' \
'INSTALL_DATA=$(INSTALL_DATA)' \
'INSTALL_PROGRAM=$(INSTALL_PROGRAM)' \
'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \
'JC1FLAGS=$(JC1FLAGS)' \
'LDFLAGS=$(LDFLAGS)' \
'LIBCFLAGS=$(LIBCFLAGS)' \
'LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)' \
'MAKE=$(MAKE)' \
'MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)' \
'PICFLAG=$(PICFLAG)' \
'PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)' \
'RUNTESTFLAGS=$(RUNTESTFLAGS)' \
'SHELL=$(SHELL)' \
'exec_prefix=$(exec_prefix)' \
'infodir=$(infodir)' \
'libdir=$(libdir)' \
'mandir=$(mandir)' \
'prefix=$(prefix)' \
'AR=$(AR)' \
'AS=$(AS)' \
'CC=$(CC)' \
'CXX=$(CXX)' \
'LD=$(LD)' \
'NM=$(NM)' \
'RANLIB=$(RANLIB)' \
'DESTDIR=$(DESTDIR)'
# Subdir rules rely on $(FLAGS_TO_PASS)
FLAGS_TO_PASS = $(AM_MAKEFLAGS)
MAKEOVERRIDES=
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libffi.pc
toolexeclib_LTLIBRARIES = libffi.la
noinst_LTLIBRARIES = libffi_convenience.la
libffi_la_SOURCES = src/prep_cif.c src/types.c \
src/raw_api.c src/java_raw_api.c src/closures.c
nodist_libffi_la_SOURCES =
if FFI_DEBUG
nodist_libffi_la_SOURCES += src/debug.c
libffi_la_SOURCES += src/debug.c
endif
if MIPS
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
endif
if BFIN
nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S
endif
if X86
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
endif
if X86_FREEBSD
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S
endif
if X86_WIN32
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
endif
if X86_WIN64
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win64.S
endif
if X86_DARWIN
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
endif
if SPARC
nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
endif
if ALPHA
nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
endif
if IA64
nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
endif
if M32R
nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
endif
if M68K
nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
endif
if POWERPC
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
endif
if POWERPC_AIX
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
endif
if POWERPC_DARWIN
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
endif
if POWERPC_FREEBSD
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
endif
if AARCH64
nodist_libffi_la_SOURCES += src/aarch64/sysv.S src/aarch64/ffi.c
endif
if ARM
nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
if FFI_EXEC_TRAMPOLINE_TABLE
nodist_libffi_la_SOURCES += src/arm/trampoline.S
endif
endif
if AVR32
nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c
endif
if LIBFFI_CRIS
nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
endif
if FRV
nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
endif
if S390
nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
endif
if X86_64
nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
endif
if SH
nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
endif
if SH64
nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
endif
if PA_LINUX
nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
endif
if PA_HPUX
nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
endif
if TILE
nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/ffi.c
endif
noinst_HEADERS = \
src/aarch64/ffitarget.h src/aarch64/internal.h \
src/alpha/ffitarget.h src/alpha/internal.h \
src/arc/ffitarget.h \
src/arm/ffitarget.h src/arm/internal.h \
src/avr32/ffitarget.h \
src/bfin/ffitarget.h \
src/cris/ffitarget.h \
src/frv/ffitarget.h \
src/ia64/ffitarget.h src/ia64/ia64_flags.h \
src/m32r/ffitarget.h \
src/m68k/ffitarget.h \
src/m88k/ffitarget.h \
src/metag/ffitarget.h \
src/microblaze/ffitarget.h \
src/mips/ffitarget.h \
src/moxie/ffitarget.h \
src/nios2/ffitarget.h \
src/or1k/ffitarget.h \
src/pa/ffitarget.h \
src/powerpc/ffitarget.h src/powerpc/asm.h src/powerpc/ffi_powerpc.h \
src/s390/ffitarget.h \
src/sh/ffitarget.h \
src/sh64/ffitarget.h \
src/sparc/ffitarget.h src/sparc/internal.h \
src/tile/ffitarget.h \
src/vax/ffitarget.h \
src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h \
src/xtensa/ffitarget.h \
src/dlmalloc.c
EXTRA_libffi_la_SOURCES = \
src/aarch64/ffi.c src/aarch64/sysv.S \
src/alpha/ffi.c src/alpha/osf.S \
src/arc/ffi.c src/arc/arcompact.S \
src/arm/ffi.c src/arm/sysv.S \
src/avr32/ffi.c src/avr32/sysv.S \
src/bfin/ffi.c src/bfin/sysv.S \
src/cris/ffi.c src/cris/sysv.S \
src/frv/ffi.c src/frv/eabi.S \
src/ia64/ffi.c src/ia64/unix.S \
src/m32r/ffi.c src/m32r/sysv.S \
src/m68k/ffi.c src/m68k/sysv.S \
src/m88k/ffi.c src/m88k/obsd.S \
src/metag/ffi.c src/metag/sysv.S \
src/microblaze/ffi.c src/microblaze/sysv.S \
src/mips/ffi.c src/mips/o32.S src/mips/n32.S \
src/moxie/ffi.c src/moxie/eabi.S \
src/nios2/ffi.c src/nios2/sysv.S \
src/or1k/ffi.c src/or1k/sysv.S \
src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \
src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \
src/powerpc/sysv.S src/powerpc/linux64.S \
src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \
src/powerpc/aix.S src/powerpc/darwin.S src/powerpc/aix_closure.S \
src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \
src/s390/ffi.c src/s390/sysv.S \
src/sh/ffi.c src/sh/sysv.S \
src/sh64/ffi.c src/sh64/sysv.S \
src/sparc/ffi.c src/sparc/ffi64.c src/sparc/v8.S src/sparc/v9.S \
src/tile/ffi.c src/tile/tile.S \
src/vax/ffi.c src/vax/elfbsd.S \
src/x86/ffi.c src/x86/sysv.S \
src/x86/ffiw64.c src/x86/win64.S \
src/x86/ffi64.c src/x86/unix64.S \
src/x86/darwin64.S src/x86/darwin.S \
src/x86/darwin64_c.c src/x86/darwin_c.c \
src/xtensa/ffi.c src/xtensa/sysv.S
TARGET_OBJ = @TARGET_OBJ@
libffi_la_LIBADD = $(TARGET_OBJ)
libffi_la_DEPENDENCIES = $(TARGET_OBJ)
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
EXTRA_libffi_convenience_la_SOURCES = $(EXTRA_libffi_la_SOURCES)
libffi_convenience_la_LIBADD = $(libffi_la_LIBADD)
libffi_convenience_la_DEPENDENCIES = $(libffi_la_DEPENDENCIES)
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
AM_CFLAGS = -Wall -g -fexceptions
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
AM_CFLAGS = -Wall -g -fexceptions
if FFI_DEBUG
# Build debug. Define FFI_DEBUG on the commandline so that, when building with
# MSVC, it can link against the debug CRT.
AM_CFLAGS += -DFFI_DEBUG
endif
libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
AM_CCASFLAGS = $(AM_CPPFLAGS)

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
Status
======
libffi-3.0.12 was released on XXXXXXX. Check the libffi web page for
updates: <URL:http://sourceware.org/libffi/>.
libffi-4?? was released on TBD. Check the libffi web
page for updates: <URL:http://sourceware.org/libffi/>.
What is libffi?
@ -43,57 +43,78 @@ Libffi has been ported to many different platforms.
For specific configuration details and testing status, please
refer to the wiki page here:
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.2
At the time of release, the following basic configurations have been
tested:
|-----------------+------------------|
| Architecture | Operating System |
|-----------------+------------------|
| AArch64 | Linux |
| Alpha | Linux |
| Alpha | Tru64 |
| ARM | Linux |
| ARM | iOS |
| AVR32 | Linux |
| Blackfin | uClinux |
| HPPA | HPUX |
| IA-64 | Linux |
| M68K | FreeMiNT |
| M68K | RTEMS |
| MIPS | IRIX |
| MIPS | Linux |
| MIPS | RTEMS |
| MIPS64 | Linux |
| PowerPC | AMIGA |
| PowerPC | Linux |
| PowerPC | Mac OSX |
| PowerPC | FreeBSD |
| PowerPC64 | Linux |
| S390 | Linux |
| S390X | Linux |
| SPARC | Linux |
| SPARC | Solaris |
| SPARC64 | Linux |
| SPARC64 | FreeBSD |
| TILE-Gx/TILEPro | Linux |
| X86 | FreeBSD |
| X86 | Interix |
| X86 | kFreeBSD |
| X86 | Linux |
| X86 | Mac OSX |
| X86 | OpenBSD |
| X86 | OS/2 |
| X86 | Solaris |
| X86 | Windows/Cygwin |
| X86 | Windows/MingW |
| X86-64 | FreeBSD |
| X86-64 | Linux |
| X86-64 | Linux/x32 |
| X86-64 | OpenBSD |
| X86-64 | Windows/MingW |
|-----------------+------------------|
|-----------------+------------------+-------------------------|
| Architecture | Operating System | Compiler |
|-----------------+------------------+-------------------------|
| AArch64 (ARM64) | iOS | Clang |
| AArch64 | Linux | GCC |
| Alpha | Linux | GCC |
| Alpha | Tru64 | GCC |
| ARC | Linux | GCC |
| ARM | Linux | GCC |
| ARM | iOS | GCC |
| AVR32 | Linux | GCC |
| Blackfin | uClinux | GCC |
| HPPA | HPUX | GCC |
| IA-64 | Linux | GCC |
| M68K | FreeMiNT | GCC |
| M68K | Linux | GCC |
| M68K | RTEMS | GCC |
| M88K | OpenBSD/mvme88k | GCC |
| Meta | Linux | GCC |
| MicroBlaze | Linux | GCC |
| MIPS | IRIX | GCC |
| MIPS | Linux | GCC |
| MIPS | RTEMS | GCC |
| MIPS64 | Linux | GCC |
| Moxie | Bare metal | GCC |
| Nios II | Linux | GCC |
| OpenRISC | Linux | GCC |
| PowerPC 32-bit | AIX | IBM XL C |
| PowerPC 64-bit | AIX | IBM XL C |
| PowerPC | AMIGA | GCC |
| PowerPC | Linux | GCC |
| PowerPC | Mac OSX | GCC |
| PowerPC | FreeBSD | GCC |
| PowerPC 64-bit | FreeBSD | GCC |
| PowerPC 64-bit | Linux ELFv1 | GCC |
| PowerPC 64-bit | Linux ELFv2 | GCC |
| S390 | Linux | GCC |
| S390X | Linux | GCC |
| SPARC | Linux | GCC |
| SPARC | Solaris | GCC |
| SPARC | Solaris | Oracle Solaris Studio C |
| SPARC64 | Linux | GCC |
| SPARC64 | FreeBSD | GCC |
| SPARC64 | Solaris | Oracle Solaris Studio C |
| TILE-Gx/TILEPro | Linux | GCC |
| VAX | OpenBSD/vax | GCC |
| X86 | FreeBSD | GCC |
| X86 | GNU HURD | GCC |
| X86 | Interix | GCC |
| X86 | kFreeBSD | GCC |
| X86 | Linux | GCC |
| X86 | Mac OSX | GCC |
| X86 | OpenBSD | GCC |
| X86 | OS/2 | GCC |
| X86 | Solaris | GCC |
| X86 | Solaris | Oracle Solaris Studio C |
| X86 | Windows/Cygwin | GCC |
| X86 | Windows/MingW | GCC |
| X86-64 | FreeBSD | GCC |
| X86-64 | Linux | GCC |
| X86-64 | Linux/x32 | GCC |
| X86-64 | OpenBSD | GCC |
| X86-64 | Solaris | Oracle Solaris Studio C |
| X86-64 | Windows/Cygwin | GCC |
| X86-64 | Windows/MingW | GCC |
| Xtensa | Linux | GCC |
|-----------------+------------------+-------------------------|
Please send additional platform test results to
libffi-discuss@sourceware.org and feel free to update the wiki page
@ -107,6 +128,9 @@ system. Go to the directory you wish to build libffi in and run the
"configure" program found in the root directory of the libffi source
distribution.
If you're building libffi directly from version control, configure won't
exist yet; run ./autogen.sh first.
You may want to tell configure where to install the libffi library and
header files. To do that, use the --prefix configure switch. Libffi
will install under /usr/local by default.
@ -124,20 +148,28 @@ It's also possible to build libffi on Windows platforms with
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
wrapper script during configuration like so:
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP"
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
You may also need to specify --build appropriately. When building with MSVC
under a MingW environment, you may need to remove the line in configure
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
present in MingW, and is not required when using MingW-style paths.)
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64" and
CXX="path/to/msvcc.sh -m64". You may also need to specify --build
appropriately.
It is also possible to build libffi on Windows platforms with the LLVM
project's clang-cl compiler, like below:
path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
When building with MSVC under a MingW environment, you may need to
remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath'
command. ('cygpath' is not present in MingW, and is not required when
using MingW-style paths.)
For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
Configure has many other options. Use "configure --help" to see them all.
Once configure has finished, type "make". Note that you must be using
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make .
To ensure that libffi is working as advertised, type "make check".
This will require that you have DejaGNU installed.
@ -148,17 +180,59 @@ To install the library and header files, type "make install".
History
=======
See the ChangeLog files for details.
See the git log for details at http://github.com/atgreen/libffi.
3.0.12 XXX-XX-XX
4.0 TBD
New API in support of GO closures.
3.2.1 Nov-12-14
Build fix for non-iOS AArch64 targets.
3.2 Nov-11-14
Add C99 Complex Type support (currently only supported on
s390).
Add support for PASCAL and REGISTER calling conventions on x86
Windows/Linux.
Add OpenRISC and Cygwin-64 support.
Bug fixes.
3.1 May-19-14
Add AArch64 (ARM64) iOS support.
Add Nios II support.
Add m88k and DEC VAX support.
Add support for stdcall, thiscall, and fastcall on non-Windows
32-bit x86 targets such as Linux.
Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi
fixes.
Make the testsuite more robust: eliminate several spurious
failures, and respect the $CC and $CXX environment variables.
Archive off the manually maintained ChangeLog in favor of git
log.
3.0.13 Mar-17-13
Add Meta support.
Add missing Moxie bits.
Fix stack alignment bug on 32-bit x86.
Build fix for m68000 targets.
Build fix for soft-float Power targets.
Fix the install dir location for some platforms when building
with GCC (OS X, Solaris).
Fix Cygwin regression.
3.0.12 Feb-11-13
Add Moxie support.
Add AArch64 support.
Add Blackfin support.
Add TILE-Gx/TILEPro support.
Add AArch64 support.
Add MicroBlaze support.
Add Xtensa support.
Add support for PaX enabled kernels with MPROTECT.
Add support for native vendor compilers on
Solaris and AIX.
Work around LLVM/GCC interoperability issue on x86_64.
3.0.11 Apr-11-12
Lots of build fixes.
Add Amiga newer MacOS support.
Add support for variadic functions (ffi_prep_cif_var).
Add Linux/x32 support.
Add thiscall, fastcall and MSVC cdecl support on Windows.
@ -167,7 +241,6 @@ See the ChangeLog files for details.
Integration with iOS' xcode build tools.
Fix Octeon and MC68881 support.
Fix code pessimizations.
Lots of build fixes.
3.0.10 Aug-23-11
Add support for Apple's iOS.
@ -311,7 +384,7 @@ See the ChangeLog files for details.
Authors & Credits
=================
libffi was originally written by Anthony Green <green@redhat.com>.
libffi was originally written by Anthony Green <green@moxielogic.com>.
The developers of the GNU Compiler Collection project have made
innumerable valuable contributions. See the ChangeLog file for
@ -335,8 +408,13 @@ frv Anthony Green
ia64 Hans Boehm
m32r Kazuhiro Inaoka
m68k Andreas Schwab
m88k Miod Vallat
microblaze Nathan Rossi
mips Anthony Green, Casey Marshall
mips64 David Daney
moxie Anthony Green
nios ii Sandra Loosemore
openrisc Sebastian Macke
pa Randolph Chung, Dave Anglin, Andreas Tobler
powerpc Geoffrey Keating, Andreas Tobler,
David Edelsohn, John Hornkvist
@ -346,8 +424,10 @@ sh Kaz Kojima
sh64 Kaz Kojima
sparc Anthony Green, Gordon Irlam
tile-gx/tilepro Walter Lee
vax Miod Vallat
x86 Anthony Green, Jon Beniston
x86-64 Bo Thorsen
xtensa Chris Zankel
Jesper Skov and Andrew Haley both did more than their fair share of
stepping through the code and tracking down bugs.

View file

@ -1,67 +0,0 @@
#!/bin/sh
PLATFORM_IOS=/Developer/Platforms/iPhoneOS.platform/
PLATFORM_IOS_SIM=/Developer/Platforms/iPhoneSimulator.platform/
SDK_IOS_VERSION="4.2"
MIN_IOS_VERSION="3.0"
OUTPUT_DIR="universal-ios"
build_target () {
local platform=$1
local sdk=$2
local arch=$3
local triple=$4
local builddir=$5
mkdir -p "${builddir}"
pushd "${builddir}"
export CC="${platform}"/Developer/usr/bin/gcc-4.2
export CFLAGS="-arch ${arch} -isysroot ${sdk} -miphoneos-version-min=${MIN_IOS_VERSION}"
../configure --host=${triple} && make
popd
}
# Build all targets
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv6 arm-apple-darwin10 armv6-ios
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv7 arm-apple-darwin10 armv7-ios
build_target "${PLATFORM_IOS_SIM}" "${PLATFORM_IOS_SIM}/Developer/SDKs/iPhoneSimulator${SDK_IOS_VERSION}.sdk/" i386 i386-apple-darwin10 i386-ios-sim
# Create universal output directories
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}/include"
mkdir -p "${OUTPUT_DIR}/include/armv6"
mkdir -p "${OUTPUT_DIR}/include/armv7"
mkdir -p "${OUTPUT_DIR}/include/i386"
# Create the universal binary
lipo -create armv6-ios/.libs/libffi.a armv7-ios/.libs/libffi.a i386-ios-sim/.libs/libffi.a -output "${OUTPUT_DIR}/libffi.a"
# Copy in the headers
copy_headers () {
local src=$1
local dest=$2
# Fix non-relative header reference
sed 's/<ffitarget.h>/"ffitarget.h"/' < "${src}/include/ffi.h" > "${dest}/ffi.h"
cp "${src}/include/ffitarget.h" "${dest}"
}
copy_headers armv6-ios "${OUTPUT_DIR}/include/armv6"
copy_headers armv7-ios "${OUTPUT_DIR}/include/armv7"
copy_headers i386-ios-sim "${OUTPUT_DIR}/include/i386"
# Create top-level header
(
cat << EOF
#ifdef __arm__
#include <arm/arch.h>
#ifdef _ARM_ARCH_6
#include "include/armv6/ffi.h"
#elif _ARM_ARCH_7
#include "include/armv7/ffi.h"
#endif
#elif defined(__i386__)
#include "include/i386/ffi.h"
#endif
EOF
) > "${OUTPUT_DIR}/ffi.h"

4790
libffi/configure vendored

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.64)
AC_INIT([libffi], [3.0.11], [http://gcc.gnu.org/bugs.html])
AC_INIT([libffi], [3.99999], [http://github.com/atgreen/libffi/issues])
AC_CONFIG_HEADERS([fficonfig.h])
AM_ENABLE_MULTILIB(, ..)
@ -10,8 +10,6 @@ AM_ENABLE_MULTILIB(, ..)
AC_CANONICAL_SYSTEM
target_alias=${target_alias-$host_alias}
. ${srcdir}/configure.host
AM_INIT_AUTOMAKE([no-dist])
# See if makeinfo has been installed and is modern enough
@ -43,10 +41,16 @@ AM_CONDITIONAL(GENINSRC, test "$enable_generated_files_in_srcdir" = yes)
# We must force CC to /not/ be precious variables; otherwise
# the wrong, non-multilib-adjusted value will be used in multilibs.
# As a side effect, we have to subst CFLAGS ourselves.
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
# defaults of its own if none are provided.
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
m4_define([_AC_ARG_VAR_PRECIOUS],[])
save_CFLAGS=$CFLAGS
AC_PROG_CC
AC_PROG_CXX
CFLAGS=$save_CFLAGS
m4_undefine([_AC_ARG_VAR_PRECIOUS])
m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
AC_SUBST(CFLAGS)
@ -55,10 +59,13 @@ AM_PROG_AS
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
# Test for 64-bit build.
AC_CHECK_SIZEOF([size_t])
AM_MAINTAINER_MODE
AC_CHECK_HEADERS(sys/mman.h)
AC_CHECK_FUNCS(mmap)
AC_CHECK_FUNCS([mmap mkostemp])
AC_FUNC_MMAP_BLACKLIST
dnl The -no-testsuite modules omit the test subdir.
@ -66,205 +73,15 @@ AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
TARGETDIR="unknown"
HAVE_LONG_DOUBLE_VARIANT=0
case "$host" in
aarch64*-*-*)
TARGET=AARCH64; TARGETDIR=aarch64
;;
alpha*-*-*)
TARGET=ALPHA; TARGETDIR=alpha;
# Support 128-bit long double, changeable via command-line switch.
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
;;
. ${srcdir}/configure.host
arm*-*-*)
TARGET=ARM; TARGETDIR=arm
;;
amd64-*-freebsd* | amd64-*-openbsd*)
TARGET=X86_64; TARGETDIR=x86
;;
amd64-*-freebsd*)
TARGET=X86_64; TARGETDIR=x86
;;
avr32*-*-*)
TARGET=AVR32; TARGETDIR=avr32
;;
bfin*)
TARGET=BFIN; TARGETDIR=bfin
;;
cris-*-*)
TARGET=LIBFFI_CRIS; TARGETDIR=cris
;;
frv-*-*)
TARGET=FRV; TARGETDIR=frv
;;
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
TARGET=PA_LINUX; TARGETDIR=pa
;;
hppa*64-*-hpux*)
TARGET=PA64_HPUX; TARGETDIR=pa
;;
hppa*-*-hpux*)
TARGET=PA_HPUX; TARGETDIR=pa
;;
i?86-*-freebsd* | i?86-*-openbsd*)
TARGET=X86_FREEBSD; TARGETDIR=x86
;;
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
TARGET=X86_WIN32; TARGETDIR=x86
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
# We must also check with_cross_host to decide if this is a native
# or cross-build and select where to install dlls appropriately.
if test -n "$with_cross_host" &&
test x"$with_cross_host" != x"no"; then
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
else
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
fi
;;
i?86-*-darwin*)
TARGET=X86_DARWIN; TARGETDIR=x86
;;
i?86-*-solaris2.1[[0-9]]*)
TARGET=X86_64; TARGETDIR=x86
;;
i?86-*-*)
TARGET=X86_64; TARGETDIR=x86
;;
ia64*-*-*)
TARGET=IA64; TARGETDIR=ia64
;;
m32r*-*-*)
TARGET=M32R; TARGETDIR=m32r
;;
m68k-*-*)
TARGET=M68K; TARGETDIR=m68k
;;
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
TARGET=MIPS; TARGETDIR=mips
;;
mips*-*-linux* | mips*-*-openbsd*)
# Support 128-bit long double for NewABI.
HAVE_LONG_DOUBLE='defined(__mips64)'
TARGET=MIPS; TARGETDIR=mips
;;
powerpc*-*-linux* | powerpc-*-sysv*)
TARGET=POWERPC; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc-*-amigaos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-beos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-darwin* | powerpc64-*-darwin*)
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
;;
powerpc-*-aix* | rs6000-*-aix*)
TARGET=POWERPC_AIX; TARGETDIR=powerpc
;;
powerpc-*-freebsd* | powerpc-*-openbsd*)
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc64-*-freebsd*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc*-*-rtems*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
s390-*-* | s390x-*-*)
TARGET=S390; TARGETDIR=s390
;;
sh-*-* | sh[[34]]*-*-*)
TARGET=SH; TARGETDIR=sh
;;
sh64-*-* | sh5*-*-*)
TARGET=SH64; TARGETDIR=sh64
;;
sparc*-*-*)
TARGET=SPARC; TARGETDIR=sparc
;;
tile*-*)
TARGET=TILE; TARGETDIR=tile
;;
x86_64-*-darwin*)
TARGET=X86_DARWIN; TARGETDIR=x86
;;
x86_64-*-cygwin* | x86_64-*-mingw*)
TARGET=X86_WIN64; TARGETDIR=x86
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
# We must also check with_cross_host to decide if this is a native
# or cross-build and select where to install dlls appropriately.
if test -n "$with_cross_host" &&
test x"$with_cross_host" != x"no"; then
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
else
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
fi
;;
x86_64-*-*)
TARGET=X86_64; TARGETDIR=x86
;;
esac
AC_SUBST(AM_RUNTESTFLAGS)
AC_SUBST(AM_LTLDFLAGS)
if test $TARGETDIR = unknown; then
if test -n "${UNSUPPORTED}"; then
AC_MSG_ERROR(["libffi has not been ported to $host."])
fi
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
AM_CONDITIONAL(X86, test x$TARGET = xX86)
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
AM_CONDITIONAL(AARCH64, test x$TARGET = xAARCH64)
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
AM_CONDITIONAL(S390, test x$TARGET = xS390)
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
AM_CONDITIONAL(SH, test x$TARGET = xSH)
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
AC_SUBST(AM_RUNTESTFLAGS)
AC_SUBST(AM_LTLDFLAGS)
AC_HEADER_STDC
AC_CHECK_FUNCS(memcpy)
@ -295,15 +112,6 @@ AC_C_BIGENDIAN
GCC_AS_CFI_PSEUDO_OP
AC_CACHE_CHECK([if compiler supports -Qunused-arguments],
[libffi_cv_c_unused_arguments],
[CFLAGS_hold=$CFLAGS
CFLAGS="$CFLAGS -Qunused-arguments"
AC_COMPILE_IFELSE([[int i;]],
[libffi_cv_c_unused_arguments=yes],
[libffi_cv_c_unused_arguments=no])
CFLAGS=$CFLAGS_hold])
if test x$TARGET = xSPARC; then
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
libffi_cv_as_sparc_ua_pcrel, [
@ -325,7 +133,7 @@ if test x$TARGET = xSPARC; then
libffi_cv_as_register_pseudo_op, [
libffi_cv_as_register_pseudo_op=unknown
# Check if we have .register
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
AC_TRY_COMPILE(,[asm (".register %g2, #scratch");],
[libffi_cv_as_register_pseudo_op=yes],
[libffi_cv_as_register_pseudo_op=no])
])
@ -338,16 +146,11 @@ fi
if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
AC_CACHE_CHECK([assembler supports pc related relocs],
libffi_cv_as_x86_pcrel, [
libffi_cv_as_x86_pcrel=yes
libffi_cv_as_x86_pcrel=no
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
CFLAGS_hold=$CFLAGS
if test "$libffi_cv_c_unused_arguments" = yes; then
CFLAGS="$CFLAGS -Qunused-arguments"
if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
libffi_cv_as_x86_pcrel=yes
fi
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
libffi_cv_as_x86_pcrel=no
fi
CFLAGS=$CFLAGS_hold
])
if test "x$libffi_cv_as_x86_pcrel" = xyes; then
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
@ -358,7 +161,7 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
libffi_cv_as_ascii_pseudo_op, [
libffi_cv_as_ascii_pseudo_op=unknown
# Check if we have .ascii
AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
AC_TRY_COMPILE(,[asm (".ascii \\"string\\"");],
[libffi_cv_as_ascii_pseudo_op=yes],
[libffi_cv_as_ascii_pseudo_op=no])
])
@ -371,7 +174,7 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
libffi_cv_as_string_pseudo_op, [
libffi_cv_as_string_pseudo_op=unknown
# Check if we have .string
AC_TRY_COMPILE([asm (".string \\"string\\"");],,
AC_TRY_COMPILE(,[asm (".string \\"string\\"");],
[libffi_cv_as_string_pseudo_op=yes],
[libffi_cv_as_string_pseudo_op=no])
])
@ -381,6 +184,23 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
fi
fi
if test x$TARGET = xS390; then
AC_CACHE_CHECK([compiler uses zarch features],
libffi_cv_as_s390_zarch, [
libffi_cv_as_s390_zarch=no
echo 'void foo(void) { bar(); bar(); }' > conftest.c
if $CC $CFLAGS -S conftest.c > /dev/null 2>&1; then
if grep -q brasl conftest.s; then
libffi_cv_as_s390_zarch=yes
fi
fi
])
if test "x$libffi_cv_as_s390_zarch" = xyes; then
AC_DEFINE(HAVE_AS_S390_ZARCH, 1,
[Define if the compiler uses zarch features.])
fi
fi
# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
AC_ARG_ENABLE(pax_emutramp,
[ --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC],
@ -407,18 +227,29 @@ AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
if test x$TARGET = xX86_64; then
AC_CACHE_CHECK([assembler supports unwind section type],
AC_CACHE_CHECK([toolchain supports unwind section type],
libffi_cv_as_x86_64_unwind_section_type, [
libffi_cv_as_x86_64_unwind_section_type=yes
echo '.section .eh_frame,"a",@unwind' > conftest.s
CFLAGS_hold=$CFLAGS
if test "$libffi_cv_c_unused_arguments" = yes; then
CFLAGS="$CFLAGS -Qunused-arguments"
cat > conftest1.s << EOF
.text
.globl foo
foo:
jmp bar
.section .eh_frame,"a",@unwind
bar:
EOF
cat > conftest2.c << EOF
extern void foo();
int main(){foo();}
EOF
libffi_cv_as_x86_64_unwind_section_type=no
# we ensure that we can compile _and_ link an assembly file containing an @unwind section
# since the compiler can support it and not the linker (ie old binutils)
if $CC -Wa,--fatal-warnings $CFLAGS -c conftest1.s > /dev/null 2>&1 && \
$CC conftest2.c conftest1.o > /dev/null 2>&1 ; then
libffi_cv_as_x86_64_unwind_section_type=yes
fi
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
libffi_cv_as_x86_64_unwind_section_type=no
fi
CFLAGS=$CFLAGS_hold
])
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
@ -431,13 +262,16 @@ if test "x$GCC" = "xyes"; then
libffi_cv_ro_eh_frame, [
libffi_cv_ro_eh_frame=no
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
libffi_cv_ro_eh_frame=yes
elif grep '.section.*eh_frame.*#alloc' conftest.c \
| grep -v '#write' > /dev/null; then
libffi_cv_ro_eh_frame=yes
fi
if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then
objdump -h conftest.o > conftest.dump 2>&1
libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1`
if test "x$libffi_eh_frame_line" != "x"; then
libffi_test_line=`expr $libffi_eh_frame_line + 1`p
sed -n $libffi_test_line conftest.dump > conftest.line
if grep READONLY conftest.line > /dev/null; then
libffi_cv_ro_eh_frame=yes
fi
fi
fi
rm -f conftest.*
])
@ -487,6 +321,14 @@ AH_BOTTOM([
AC_SUBST(TARGET)
AC_SUBST(TARGETDIR)
changequote(<,>)
TARGET_OBJ=
for i in $SOURCES; do
TARGET_OBJ="${TARGET_OBJ} src/${TARGETDIR}/"`echo $i | sed 's/[cS]$/lo/'`
done
changequote([,])
AC_SUBST(TARGET_OBJ)
AC_SUBST(SHELL)
AC_ARG_ENABLE(debug,
@ -499,13 +341,14 @@ AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
AC_ARG_ENABLE(structs,
[ --disable-structs omit code for struct support],
if test "$enable_structs" = "no"; then
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this if you do not want support for aggregate types.])
fi)
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
AC_ARG_ENABLE(raw-api,
[ --disable-raw-api make the raw api unavailable],
if test "$enable_raw_api" = "no"; then
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this if you do not want support for the raw API.])
fi)
AC_ARG_ENABLE(purify-safety,
@ -544,6 +387,6 @@ test -d src/$TARGETDIR || mkdir src/$TARGETDIR
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile)
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
AC_OUTPUT

View file

@ -1,11 +1,265 @@
# configure.host
#
# This shell script handles all host based configuration for libffi.
#
#
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
# Most of the time we can define all the variables all at once...
case "${host}" in
frv*-elf)
LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
;;
aarch64*-*-*)
TARGET=AARCH64; TARGETDIR=aarch64
SOURCES="ffi.c sysv.S"
;;
alpha*-*-*)
TARGET=ALPHA; TARGETDIR=alpha;
# Support 128-bit long double, changeable via command-line switch.
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
SOURCES="ffi.c osf.S"
;;
arc*-*-*)
TARGET=ARC; TARGETDIR=arc
SOURCES="ffi.c arcompact.S"
;;
arm*-*-*)
TARGET=ARM; TARGETDIR=arm
SOURCES="ffi.c sysv.S"
;;
avr32*-*-*)
TARGET=AVR32; TARGETDIR=avr32
SOURCES="ffi.c sysv.S"
;;
bfin*)
TARGET=BFIN; TARGETDIR=bfin
SOURCES="ffi.c sysv.S"
;;
cris-*-*)
TARGET=LIBFFI_CRIS; TARGETDIR=cris
SOURCES="ffi.c sysv.S"
;;
frv-*-*)
TARGET=FRV; TARGETDIR=frv
SOURCES="ffi.c eabi.S"
;;
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
TARGET=PA_LINUX; TARGETDIR=pa
SOURCES="ffi.c linux.S"
;;
hppa*64-*-hpux*)
TARGET=PA64_HPUX; TARGETDIR=pa
;;
hppa*-*-hpux*)
TARGET=PA_HPUX; TARGETDIR=pa
SOURCES="ffi.c hpux32.S"
;;
i?86-*-freebsd* | i?86-*-openbsd*)
TARGET=X86_FREEBSD; TARGETDIR=x86
;;
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix* \
| x86_64-*-cygwin* | x86_64-*-mingw*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
TARGET=X86_WIN32
else
TARGET=X86_WIN64
fi
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
# We must also check with_cross_host to decide if this is a native
# or cross-build and select where to install dlls appropriately.
if test -n "$with_cross_host" &&
test x"$with_cross_host" != x"no"; then
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
else
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
fi
;;
i?86-*-darwin* | x86_64-*-darwin*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
TARGET=X86_DARWIN
else
TARGET=X86_64_DARWIN
fi
;;
i?86-*-* | x86_64-*-* | amd64-*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
case "$host" in
*-gnux32)
TARGET=X86_64
;;
*)
TARGET=X86
;;
esac
else
TARGET=X86_64;
fi
;;
ia64*-*-*)
TARGET=IA64; TARGETDIR=ia64
SOURCES="ffi.c unix.S"
;;
m32r*-*-*)
TARGET=M32R; TARGETDIR=m32r
SOURCES="ffi.c sysv.S"
;;
m68k-*-*)
TARGET=M68K; TARGETDIR=m68k
SOURCES="ffi.c sysv.S"
;;
m88k-*-*)
TARGET=M88K; TARGETDIR=m88k
SOURCES="ffi.c obsd.S"
;;
microblaze*-*-*)
TARGET=MICROBLAZE; TARGETDIR=microblaze
SOURCES="ffi.c sysv.S"
;;
moxie-*-*)
TARGET=MOXIE; TARGETDIR=moxie
SOURCES="ffi.c eabi.S"
;;
metag-*-*)
TARGET=METAG; TARGETDIR=metag
SOURCES="ffi.c sysv.S"
;;
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
TARGET=MIPS; TARGETDIR=mips
;;
mips*-*linux* | mips*-*-openbsd*)
# Support 128-bit long double for NewABI.
HAVE_LONG_DOUBLE='defined(__mips64)'
TARGET=MIPS; TARGETDIR=mips
;;
nios2*-linux*)
TARGET=NIOS2; TARGETDIR=nios2
SOURCES="ffi.c sysv.S"
;;
or1k*-linux*)
TARGET=OR1K; TARGETDIR=or1k
SOURCES="ffi.c sysv.S"
;;
powerpc*-*-linux* | powerpc-*-sysv*)
TARGET=POWERPC; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc-*-amigaos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-beos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-darwin* | powerpc64-*-darwin*)
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
;;
powerpc-*-aix* | rs6000-*-aix*)
TARGET=POWERPC_AIX; TARGETDIR=powerpc
;;
powerpc-*-freebsd* | powerpc-*-openbsd*)
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc64-*-freebsd*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc*-*-rtems*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
s390-*-* | s390x-*-*)
TARGET=S390; TARGETDIR=s390
SOURCES="ffi.c sysv.S"
;;
sh-*-* | sh[[34]]*-*-*)
TARGET=SH; TARGETDIR=sh
SOURCES="ffi.c sysv.S"
;;
sh64-*-* | sh5*-*-*)
TARGET=SH64; TARGETDIR=sh64
SOURCES="ffi.c sysv.S"
;;
sparc*-*-*)
TARGET=SPARC; TARGETDIR=sparc
SOURCES="ffi.c ffi64.c v8.S v9.S"
;;
tile*-*)
TARGET=TILE; TARGETDIR=tile
SOURCES="ffi.c tile.S"
;;
vax-*-*)
TARGET=VAX; TARGETDIR=vax
SOURCES="ffi.c elfbsd.S"
;;
xtensa*-*)
TARGET=XTENSA; TARGETDIR=xtensa
SOURCES="ffi.c sysv.S"
;;
esac
# ... but some of the cases above share configury.
case "${TARGET}" in
MIPS)
SOURCES="ffi.c o32.S n32.S"
;;
POWERPC)
SOURCES="ffi.c ffi_sysv.c ffi_linux64.c sysv.S ppc_closure.S"
SOURCES="${SOURCES} linux64.S linux64_closure.S"
;;
POWERPC_AIX)
SOURCES="ffi_darwin.c aix.S aix_closure.S"
;;
POWERPC_DARWIN)
SOURCES="ffi_darwin.c darwin.S darwin_closure.S"
;;
POWERPC_FREEBSD)
SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S"
;;
X86 | X86_FREEBSD | X86_WIN32)
SOURCES="ffi.c sysv.S"
;;
X86_64)
SOURCES="ffi64.c unix64.S"
;;
X86_WIN64)
SOURCES="ffiw64.c win64.S"
;;
X86_DARWIN)
SOURCES="darwin_c.c darwin.S"
;;
X86_64_DARWIN)
SOURCES="darwin64_c.c darwin64.S"
;;
esac
# If we failed to configure SOURCES, we can't do anything.
if test -z "${SOURCES}"; then
UNSUPPORTED=1
fi

View file

@ -63,14 +63,14 @@ section entitled ``GNU General Public License''.
@node Introduction
@chapter What is libffi?
Compilers for high-level languages generate code that follow certain
Compilers for high level languages generate code that follow certain
conventions. These conventions are necessary, in part, for separate
compilation to work. One such convention is the @dfn{calling
convention}. The calling convention is a set of assumptions made by
the compiler about where function arguments will be found on entry to
a function. A calling convention also specifies where the return
value for a function is found. The calling convention is part of
what is called the @dfn{ABI} or @dfn{Application Binary Interface}.
value for a function is found. The calling convention is also
sometimes called the @dfn{ABI} or @dfn{Application Binary Interface}.
@cindex calling convention
@cindex ABI
@cindex Application Binary Interface
@ -247,6 +247,8 @@ int main()
* Primitive Types:: Built-in types.
* Structures:: Structure types.
* Type Example:: Structure type example.
* Complex:: Complex types.
* Complex Type Example:: Complex type example.
@end menu
@node Primitive Types
@ -345,6 +347,20 @@ On other platforms, it is not.
@tindex ffi_type_pointer
A generic @code{void *} pointer. You should use this for all
pointers, regardless of their real type.
@item ffi_type_complex_float
@tindex ffi_type_complex_float
The C @code{_Complex float} type.
@item ffi_type_complex_double
@tindex ffi_type_complex_double
The C @code{_Complex double} type.
@item ffi_type_complex_longdouble
@tindex ffi_type_complex_longdouble
The C @code{_Complex long double} type.
On platforms that have a C @code{long double} type, this is defined.
On other platforms, it is not.
@end table
Each of these is of type @code{ffi_type}, so you must take the address
@ -429,6 +445,135 @@ Here is the corresponding code to describe this struct to
@}
@end example
@node Complex
@subsection Complex Types
@samp{libffi} supports the complex types defined by the C99
standard (@code{_Complex float}, @code{_Complex double} and
@code{_Complex long double} with the built-in type descriptors
@code{ffi_type_complex_float}, @code{ffi_type_complex_double} and
@code{ffi_type_complex_longdouble}.
Custom complex types like @code{_Complex int} can also be used.
An @code{ffi_type} object has to be defined to describe the
complex type to @samp{libffi}.
@tindex ffi_type
@deftp {Data type} ffi_type
@table @code
@item size_t size
This must be manually set to the size of the complex type.
@item unsigned short alignment
This must be manually set to the alignment of the complex type.
@item unsigned short type
For a complex type, this must be set to @code{FFI_TYPE_COMPLEX}.
@item ffi_type **elements
This is a @samp{NULL}-terminated array of pointers to
@code{ffi_type} objects. The first element is set to the
@code{ffi_type} of the complex's base type. The second element
must be set to @code{NULL}.
@end table
@end deftp
The section @ref{Complex Type Example} shows a way to determine
the @code{size} and @code{alignment} members in a platform
independent way.
For platforms that have no complex support in @code{libffi} yet,
the functions @code{ffi_prep_cif} and @code{ffi_prep_args} abort
the program if they encounter a complex type.
@node Complex Type Example
@subsection Complex Type Example
This example demonstrates how to use complex types:
@example
#include <stdio.h>
#include <ffi.h>
#include <complex.h>
void complex_fn(_Complex float cf,
_Complex double cd,
_Complex long double cld)
@{
printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n",
(float)creal (cf), (float)cimag (cf),
(float)creal (cd), (float)cimag (cd),
(float)creal (cld), (float)cimag (cld));
@}
int main()
@{
ffi_cif cif;
ffi_type *args[3];
void *values[3];
_Complex float cf;
_Complex double cd;
_Complex long double cld;
/* Initialize the argument info vectors */
args[0] = &ffi_type_complex_float;
args[1] = &ffi_type_complex_double;
args[2] = &ffi_type_complex_longdouble;
values[0] = &cf;
values[1] = &cd;
values[2] = &cld;
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
&ffi_type_void, args) == FFI_OK)
@{
cf = 1.0 + 20.0 * I;
cd = 300.0 + 4000.0 * I;
cld = 50000.0 + 600000.0 * I;
/* Call the function */
ffi_call(&cif, (void (*)(void))complex_fn, 0, values);
@}
return 0;
@}
@end example
This is an example for defining a custom complex type descriptor
for compilers that support them:
@example
/*
* This macro can be used to define new complex type descriptors
* in a platform independent way.
*
* name: Name of the new descriptor is ffi_type_complex_<name>.
* type: The C base type of the complex type.
*/
#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \
static ffi_type *ffi_elements_complex_##name [2] = @{ \
(ffi_type *)(&ffitype), NULL \
@}; \
struct struct_align_complex_##name @{ \
char c; \
_Complex type x; \
@}; \
ffi_type ffi_type_complex_##name = @{ \
sizeof(_Complex type), \
offsetof(struct struct_align_complex_##name, x), \
FFI_TYPE_COMPLEX, \
(ffi_type **)ffi_elements_complex_##name \
@}
/* Define new complex type descriptors using the macro: */
/* ffi_type_complex_sint */
FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
/* ffi_type_complex_uchar */
FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
@end example
The new type descriptors can then be used like one of the built-in
type descriptors in the previous example.
@node Multiple ABIs
@section Multiple ABIs
@ -534,7 +679,7 @@ writable and executable addresses.
@section Closure Example
A trivial example that creates a new @code{puts} by binding
@code{fputs} with @code{stdin}.
@code{fputs} with @code{stdout}.
@example
#include <stdio.h>

View file

@ -1,4 +0,0 @@
@set UPDATED 6 March 2012
@set UPDATED-MONTH March 2012
@set EDITION 3.0.11
@set VERSION 3.0.11

View file

@ -1,4 +1,4 @@
@set UPDATED 6 March 2012
@set UPDATED-MONTH March 2012
@set EDITION 3.0.11
@set VERSION 3.0.11
@set UPDATED 8 November 2014
@set UPDATED-MONTH November 2014
@set EDITION 3.2.1
@set VERSION 3.2.1

View file

@ -26,10 +26,10 @@
/* Cannot use malloc on this target, so, we revert to alternative means */
#undef FFI_MMAP_EXEC_WRIT
/* Define this is you do not want support for the raw API. */
/* Define this if you do not want support for the raw API. */
#undef FFI_NO_RAW_API
/* Define this is you do not want support for aggregate types. */
/* Define this if you do not want support for aggregate types. */
#undef FFI_NO_STRUCTS
/* Define to 1 if you have `alloca', as a function or macro. */
@ -48,6 +48,9 @@
/* Define if your assembler supports .register. */
#undef HAVE_AS_REGISTER_PSEUDO_OP
/* Define if the compiler uses zarch features. */
#undef HAVE_AS_S390_ZARCH
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
#undef HAVE_AS_SPARC_UA_PCREL
@ -82,6 +85,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkostemp' function. */
#undef HAVE_MKOSTEMP
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
@ -155,6 +161,9 @@
/* The size of `long double', as computed by sizeof. */
#undef SIZEOF_LONG_DOUBLE
/* The size of `size_t', as computed by sizeof. */
#undef SIZEOF_SIZE_T
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.

View file

@ -0,0 +1,209 @@
#!/usr/bin/env python
import subprocess
import os
import errno
import collections
import glob
import argparse
class Platform(object):
pass
class simulator_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphonesimulator'
arch = 'i386'
triple = 'i386-apple-darwin11'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __i386__\n\n"
suffix = "\n\n#endif"
src_dir = 'x86'
src_files = ['darwin.S', 'win32.S', 'ffi.c']
class simulator64_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphonesimulator'
arch = 'x86_64'
triple = 'x86_64-apple-darwin13'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __x86_64__\n\n"
suffix = "\n\n#endif"
src_dir = 'x86'
src_files = ['darwin64.S', 'ffi64.c']
class device_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphoneos'
arch = 'armv7'
triple = 'arm-apple-darwin11'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __arm__\n\n"
suffix = "\n\n#endif"
src_dir = 'arm'
src_files = ['sysv.S', 'trampoline.S', 'ffi.c']
class device64_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphoneos'
arch = 'arm64'
triple = 'aarch64-apple-darwin13'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __arm64__\n\n"
suffix = "\n\n#endif"
src_dir = 'aarch64'
src_files = ['sysv.S', 'ffi.c']
class desktop32_platform(Platform):
directory = 'darwin_osx'
sdk = 'macosx'
arch = 'i386'
triple = 'i386-apple-darwin10'
version_min = '-mmacosx-version-min=10.6'
src_dir = 'x86'
src_files = ['darwin.S', 'win32.S', 'ffi.c']
prefix = "#ifdef __i386__\n\n"
suffix = "\n\n#endif"
class desktop64_platform(Platform):
directory = 'darwin_osx'
sdk = 'macosx'
arch = 'x86_64'
triple = 'x86_64-apple-darwin10'
version_min = '-mmacosx-version-min=10.6'
prefix = "#ifdef __x86_64__\n\n"
suffix = "\n\n#endif"
src_dir = 'x86'
src_files = ['darwin64.S', 'ffi64.c']
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST:
pass
else:
raise
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
mkdir_p(dst_dir)
out_filename = filename
if file_suffix:
split_name = os.path.splitext(filename)
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
with open(os.path.join(src_dir, filename)) as in_file:
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
if prefix:
out_file.write(prefix)
out_file.write(in_file.read())
if suffix:
out_file.write(suffix)
def list_files(src_dir, pattern=None, filelist=None):
if pattern: filelist = glob.iglob(os.path.join(src_dir, pattern))
for file in filelist:
yield os.path.basename(file)
def copy_files(src_dir, dst_dir, pattern=None, filelist=None, file_suffix=None, prefix=None, suffix=None):
for filename in list_files(src_dir, pattern=pattern, filelist=filelist):
move_file(src_dir, dst_dir, filename, file_suffix=file_suffix, prefix=prefix, suffix=suffix)
def copy_src_platform_files(platform):
src_dir = os.path.join('src', platform.src_dir)
dst_dir = os.path.join(platform.directory, 'src', platform.src_dir)
copy_files(src_dir, dst_dir, filelist=platform.src_files, file_suffix=platform.arch, prefix=platform.prefix, suffix=platform.suffix)
def build_target(platform, platform_headers):
def xcrun_cmd(cmd):
return 'xcrun -sdk %s %s -arch %s' % (platform.sdk, cmd, platform.arch)
tag='%s-%s' % (platform.sdk, platform.arch)
build_dir = 'build_%s' % tag
mkdir_p(build_dir)
env = dict(CC=xcrun_cmd('clang'),
LD=xcrun_cmd('ld'),
CFLAGS='%s' % (platform.version_min))
working_dir = os.getcwd()
try:
os.chdir(build_dir)
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
finally:
os.chdir(working_dir)
for src_dir in [build_dir, os.path.join(build_dir, 'include')]:
copy_files(src_dir,
os.path.join(platform.directory, 'include'),
pattern='*.h',
file_suffix=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
for filename in list_files(src_dir, pattern='*.h'):
platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix))
def make_tramp():
with open('src/arm/trampoline.S', 'w') as tramp_out:
p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)
p.wait()
def generate_source_and_headers(generate_osx=True, generate_ios=True):
copy_files('src', 'darwin_common/src', pattern='*.c')
copy_files('include', 'darwin_common/include', pattern='*.h')
if generate_ios:
make_tramp()
copy_src_platform_files(simulator_platform)
copy_src_platform_files(simulator64_platform)
copy_src_platform_files(device_platform)
copy_src_platform_files(device64_platform)
if generate_osx:
copy_src_platform_files(desktop32_platform)
copy_src_platform_files(desktop64_platform)
platform_headers = collections.defaultdict(set)
if generate_ios:
build_target(simulator_platform, platform_headers)
build_target(simulator64_platform, platform_headers)
build_target(device_platform, platform_headers)
build_target(device64_platform, platform_headers)
if generate_osx:
build_target(desktop32_platform, platform_headers)
build_target(desktop64_platform, platform_headers)
mkdir_p('darwin_common/include')
for header_name, tag_tuples in platform_headers.iteritems():
basename, suffix = os.path.splitext(header_name)
with open(os.path.join('darwin_common/include', header_name), 'w') as header:
for tag_tuple in tag_tuples:
header.write('%s#include <%s_%s%s>\n%s\n' % (tag_tuple[0], basename, tag_tuple[1], suffix, tag_tuple[2]))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--only-ios', action='store_true', default=False)
parser.add_argument('--only-osx', action='store_true', default=False)
args = parser.parse_args()
generate_source_and_headers(generate_osx=not args.only_ios, generate_ios=not args.only_osx)

View file

@ -1,160 +0,0 @@
#!/usr/bin/env python
import subprocess
import re
import os
import errno
import collections
import sys
class Platform(object):
pass
sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
def sdkinfo(sdkname):
ret = {}
for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
kv = line.strip().split(': ', 1)
if len(kv) == 2:
k,v = kv
ret[k] = v
return ret
sim_sdk_info = sdkinfo('iphonesimulator')
device_sdk_info = sdkinfo('iphoneos')
def latest_sdks():
latest_sim = None
latest_device = None
for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
match = sdk_re.match(line)
if match:
if 'Simulator' in line:
latest_sim = match.group(1)
elif 'iOS' in line:
latest_device = match.group(1)
return latest_sim, latest_device
sim_sdk, device_sdk = latest_sdks()
class simulator_platform(Platform):
sdk='iphonesimulator'
arch = 'i386'
name = 'simulator'
triple = 'i386-apple-darwin10'
sdkroot = sim_sdk_info['Path']
prefix = "#if !defined(__arm__) && defined(__i386__)\n\n"
suffix = "\n\n#endif"
class device_platform(Platform):
sdk='iphoneos'
name = 'ios'
arch = 'armv7'
triple = 'arm-apple-darwin10'
sdkroot = device_sdk_info['Path']
prefix = "#ifdef __arm__\n\n"
suffix = "\n\n#endif"
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
out_filename = filename
if file_suffix:
split_name = os.path.splitext(filename)
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
with open(os.path.join(src_dir, filename)) as in_file:
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
if prefix:
out_file.write(prefix)
out_file.write(in_file.read())
if suffix:
out_file.write(suffix)
headers_seen = collections.defaultdict(set)
def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
for root, dirs, files in os.walk(src_dir, followlinks=True):
relroot = os.path.relpath(root,src_dir)
def move_dir(arch, prefix='', suffix='', files=[]):
for file in files:
file_suffix = None
if file.endswith('.h'):
if dest_include_dir:
file_suffix = arch
if arch:
headers_seen[file].add(arch)
move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
elif dest_dir:
outroot = os.path.join(dest_dir, relroot)
move_file(root, outroot, file, prefix=prefix, suffix=suffix)
if relroot == '.':
move_dir(arch=arch,
files=files,
prefix=prefix,
suffix=suffix)
elif relroot == 'arm':
move_dir(arch='arm',
prefix="#ifdef __arm__\n\n",
suffix="\n\n#endif",
files=files)
elif relroot == 'x86':
move_dir(arch='i386',
prefix="#if !defined(__arm__) && defined(__i386__)\n\n",
suffix="\n\n#endif",
files=files)
def build_target(platform):
def xcrun_cmd(cmd):
return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
build_dir = 'build_' + platform.name
if not os.path.exists(build_dir):
os.makedirs(build_dir)
env = dict(CC=xcrun_cmd('clang'),
LD=xcrun_cmd('ld'),
CFLAGS='-arch %s -isysroot %s -miphoneos-version-min=4.0' % (platform.arch, platform.sdkroot))
working_dir=os.getcwd()
try:
os.chdir(build_dir)
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
move_source_tree('.', None, '../ios/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
move_source_tree('./include', None, '../ios/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
finally:
os.chdir(working_dir)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
def main():
move_source_tree('src', 'ios/src', 'ios/include')
move_source_tree('include', None, 'ios/include')
build_target(simulator_platform)
build_target(device_platform)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
with open(os.path.join('ios/include', header_name), 'w') as header:
for arch in archs:
header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
if __name__ == '__main__':
main()

View file

@ -1,153 +0,0 @@
#!/usr/bin/env python
import subprocess
import re
import os
import errno
import collections
import sys
class Platform(object):
pass
sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
def sdkinfo(sdkname):
ret = {}
for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
kv = line.strip().split(': ', 1)
if len(kv) == 2:
k,v = kv
ret[k] = v
return ret
desktop_sdk_info = sdkinfo('macosx')
def latest_sdks():
latest_desktop = None
for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
match = sdk_re.match(line)
if match:
if 'OS X' in line:
latest_desktop = match.group(1)
return latest_desktop
desktop_sdk = latest_sdks()
class desktop_platform_32(Platform):
sdk='macosx'
arch = 'i386'
name = 'mac32'
triple = 'i386-apple-darwin10'
sdkroot = desktop_sdk_info['Path']
prefix = "#if defined(__i386__) && !defined(__x86_64__)\n\n"
suffix = "\n\n#endif"
class desktop_platform_64(Platform):
sdk='macosx'
arch = 'x86_64'
name = 'mac'
triple = 'x86_64-apple-darwin10'
sdkroot = desktop_sdk_info['Path']
prefix = "#if !defined(__i386__) && defined(__x86_64__)\n\n"
suffix = "\n\n#endif"
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
out_filename = filename
if file_suffix:
split_name = os.path.splitext(filename)
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
with open(os.path.join(src_dir, filename)) as in_file:
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
if prefix:
out_file.write(prefix)
out_file.write(in_file.read())
if suffix:
out_file.write(suffix)
headers_seen = collections.defaultdict(set)
def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
for root, dirs, files in os.walk(src_dir, followlinks=True):
relroot = os.path.relpath(root,src_dir)
def move_dir(arch, prefix='', suffix='', files=[]):
for file in files:
file_suffix = None
if file.endswith('.h'):
if dest_include_dir:
file_suffix = arch
if arch:
headers_seen[file].add(arch)
move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
elif dest_dir:
outroot = os.path.join(dest_dir, relroot)
move_file(root, outroot, file, prefix=prefix, suffix=suffix)
if relroot == '.':
move_dir(arch=arch,
files=files,
prefix=prefix,
suffix=suffix)
elif relroot == 'x86':
move_dir(arch='i386',
prefix="#if defined(__i386__) && !defined(__x86_64__)\n\n",
suffix="\n\n#endif",
files=files)
move_dir(arch='x86_64',
prefix="#if !defined(__i386__) && defined(__x86_64__)\n\n",
suffix="\n\n#endif",
files=files)
def build_target(platform):
def xcrun_cmd(cmd):
return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
build_dir = 'build_' + platform.name
if not os.path.exists(build_dir):
os.makedirs(build_dir)
env = dict(CC=xcrun_cmd('clang'),
LD=xcrun_cmd('ld'),
CFLAGS='-arch %s -isysroot %s -mmacosx-version-min=10.6' % (platform.arch, platform.sdkroot))
working_dir=os.getcwd()
try:
os.chdir(build_dir)
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
move_source_tree('.', None, '../osx/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
move_source_tree('./include', None, '../osx/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
finally:
os.chdir(working_dir)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
def main():
move_source_tree('src', 'osx/src', 'osx/include')
move_source_tree('include', None, 'osx/include')
build_target(desktop_platform_32)
build_target(desktop_platform_64)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
with open(os.path.join('osx/include', header_name), 'w') as header:
for arch in archs:
header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
if __name__ == '__main__':
main()

View file

@ -3,7 +3,8 @@
AUTOMAKE_OPTIONS=foreign
DISTCLEANFILES=ffitarget.h
EXTRA_DIST=ffi.h.in ffi_common.h
noinst_HEADERS=ffi_common.h ffi_cfi.h
EXTRA_DIST=ffi.h.in
# Where generated headers like ffitarget.h get installed.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)

View file

@ -37,7 +37,7 @@ host_triplet = @host@
target_triplet = @target@
subdir = include
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/ffi.h.in $(toollibffi_HEADERS)
$(srcdir)/ffi.h.in $(noinst_HEADERS) $(toollibffi_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/asmcfi.m4 \
@ -78,7 +78,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(toollibffidir)"
HEADERS = $(toollibffi_HEADERS)
HEADERS = $(noinst_HEADERS) $(toollibffi_HEADERS)
ETAGS = etags
CTAGS = ctags
ACLOCAL = @ACLOCAL@
@ -99,6 +99,10 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -151,12 +155,14 @@ SHELL = @SHELL@
STRIP = @STRIP@
TARGET = @TARGET@
TARGETDIR = @TARGETDIR@
TARGET_OBJ = @TARGET_OBJ@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
@ -212,7 +218,8 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign
DISTCLEANFILES = ffitarget.h
EXTRA_DIST = ffi.h.in ffi_common.h
noinst_HEADERS = ffi_common.h ffi_cfi.h
EXTRA_DIST = ffi.h.in
# Where generated headers like ffitarget.h get installed.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)

View file

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------*-C-*-
libffi @VERSION@ - Copyright (c) 2011 Anthony Green
libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person
@ -68,7 +68,7 @@ extern "C" {
#ifndef LIBFFI_ASM
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
@ -166,25 +166,49 @@ typedef struct _ffi_type
#error "long size not supported"
#endif
/* Need minimal decorations for DLLs to works on Windows. */
/* GCC has autoimport and autoexport. Rely on Libtool to */
/* help MSVC export from a DLL, but always declare data */
/* to be imported for MSVC clients. This costs an extra */
/* indirection for MSVC clients using the static version */
/* of the library, but don't worry about that. Besides, */
/* as a workaround, they can define FFI_BUILDING if they */
/* *know* they are going to link with the static library. */
#if defined _MSC_VER && !defined FFI_BUILDING
#define FFI_EXTERN extern __declspec(dllimport)
#else
#define FFI_EXTERN extern
#endif
/* These are defined in types.c */
extern ffi_type ffi_type_void;
extern ffi_type ffi_type_uint8;
extern ffi_type ffi_type_sint8;
extern ffi_type ffi_type_uint16;
extern ffi_type ffi_type_sint16;
extern ffi_type ffi_type_uint32;
extern ffi_type ffi_type_sint32;
extern ffi_type ffi_type_uint64;
extern ffi_type ffi_type_sint64;
extern ffi_type ffi_type_float;
extern ffi_type ffi_type_double;
extern ffi_type ffi_type_pointer;
FFI_EXTERN ffi_type ffi_type_void;
FFI_EXTERN ffi_type ffi_type_uint8;
FFI_EXTERN ffi_type ffi_type_sint8;
FFI_EXTERN ffi_type ffi_type_uint16;
FFI_EXTERN ffi_type ffi_type_sint16;
FFI_EXTERN ffi_type ffi_type_uint32;
FFI_EXTERN ffi_type ffi_type_sint32;
FFI_EXTERN ffi_type ffi_type_uint64;
FFI_EXTERN ffi_type ffi_type_sint64;
FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if @HAVE_LONG_DOUBLE@
extern ffi_type ffi_type_longdouble;
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_EXTERN ffi_type ffi_type_complex_float;
FFI_EXTERN ffi_type ffi_type_complex_double;
#if @HAVE_LONG_DOUBLE@
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
#else
#define ffi_type_complex_longdouble ffi_type_complex_double
#endif
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
@ -207,10 +231,10 @@ typedef struct {
#endif
} ffi_cif;
#if HAVE_LONG_DOUBLE_VARIANT
#if @HAVE_LONG_DOUBLE_VARIANT@
/* Used to adjust size/alignment of ffi types. */
void ffi_prep_types (ffi_abi abi);
# endif
#endif
/* Used internally, but overridden by some architectures */
ffi_status ffi_prep_cif_core(ffi_cif *cif,
@ -288,7 +312,12 @@ size_t ffi_java_raw_size (ffi_cif *cif);
__declspec(align(8))
#endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
@ -321,8 +350,12 @@ ffi_prep_closure_loc (ffi_closure*,
# pragma pack 8
#endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
@ -342,7 +375,12 @@ typedef struct {
} ffi_raw_closure;
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
@ -390,6 +428,22 @@ ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
#endif /* FFI_CLOSURES */
#if FFI_GO_CLOSURES
typedef struct {
void *tramp;
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
} ffi_go_closure;
ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*));
void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure);
#endif /* FFI_GO_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
ffi_status ffi_prep_cif(ffi_cif *cif,
@ -437,9 +491,10 @@ void ffi_call(ffi_cif *cif,
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
#define FFI_TYPE_COMPLEX 15
/* This should always refer to the last type code (for sanity checks) */
#define FFI_TYPE_LAST FFI_TYPE_POINTER
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}

55
libffi/include/ffi_cfi.h Normal file
View file

@ -0,0 +1,55 @@
/* -----------------------------------------------------------------------
ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc.
Conditionally assemble cfi directives. Only necessary for building libffi.
----------------------------------------------------------------------- */
#ifndef FFI_CFI_H
#define FFI_CFI_H
#ifdef HAVE_AS_CFI_PSEUDO_OP
# define cfi_startproc .cfi_startproc
# define cfi_endproc .cfi_endproc
# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
# define cfi_offset(reg, off) .cfi_offset reg, off
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
# define cfi_register(r1, r2) .cfi_register r1, r2
# define cfi_return_column(reg) .cfi_return_column reg
# define cfi_restore(reg) .cfi_restore reg
# define cfi_same_value(reg) .cfi_same_value reg
# define cfi_undefined(reg) .cfi_undefined reg
# define cfi_remember_state .cfi_remember_state
# define cfi_restore_state .cfi_restore_state
# define cfi_window_save .cfi_window_save
# define cfi_personality(enc, exp) .cfi_personality enc, exp
# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
# define cfi_escape(...) .cfi_escape __VA_ARGS__
#else
# define cfi_startproc
# define cfi_endproc
# define cfi_def_cfa(reg, off)
# define cfi_def_cfa_register(reg)
# define cfi_def_cfa_offset(off)
# define cfi_adjust_cfa_offset(off)
# define cfi_offset(reg, off)
# define cfi_rel_offset(reg, off)
# define cfi_register(r1, r2)
# define cfi_return_column(reg)
# define cfi_restore(reg)
# define cfi_same_value(reg)
# define cfi_undefined(reg)
# define cfi_remember_state
# define cfi_restore_state
# define cfi_window_save
# define cfi_personality(enc, exp)
# define cfi_lsda(enc, exp)
# define cfi_escape(...)
#endif /* HAVE_AS_CFI_PSEUDO_OP */
#endif /* FFI_CFI_H */

View file

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (C) 2011, 2012 Anthony Green
ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc
Copyright (c) 1996 Red Hat, Inc.
@ -19,10 +19,14 @@ extern "C" {
/* Do not move this. Some versions of AIX are very picky about where
this is positioned. */
#ifdef __GNUC__
/* mingw64 defines this already in malloc.h. */
#ifndef alloca
# define alloca __builtin_alloca
#endif
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
/* mingw64 defines this already in malloc.h. */
# ifndef alloca
# define alloca __builtin_alloca
# endif
# endif
# define MAYBE_UNUSED __attribute__((__unused__))
#else
# define MAYBE_UNUSED
@ -30,17 +34,17 @@ extern "C" {
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
# ifdef _MSC_VER
# define alloca _alloca
# else
char *alloca ();
# endif
# endif
# endif
# endif
# endif
#endif
/* Check for the existence of memcpy. */
@ -87,7 +91,7 @@ typedef struct
} extended_cif;
/* Terse sized type definitions. */
#if defined(_MSC_VER) || defined(__sgi)
#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
typedef unsigned char UINT8;
typedef signed char SINT8;
typedef unsigned short UINT16;

11
libffi/libffi.pc.in Normal file
View file

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
toolexeclibdir=@toolexeclibdir@
includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
Name: @PACKAGE_NAME@
Description: Library supporting Foreign Function Interfaces
Version: @PACKAGE_VERSION@
Libs: -L${toolexeclibdir} -lffi
Cflags: -I${includedir}

View file

@ -7,473 +7,448 @@
objects = {
/* Begin PBXBuildFile section */
6C43CBDC1534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBD1534F76F00162364 /* ffi.c */; };
6C43CBDD1534F76F00162364 /* sysv.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBF1534F76F00162364 /* sysv.S */; };
6C43CBDE1534F76F00162364 /* trampoline.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC01534F76F00162364 /* trampoline.S */; };
6C43CBE61534F76F00162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC91534F76F00162364 /* darwin.S */; };
6C43CBE81534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBCB1534F76F00162364 /* ffi.c */; };
6C43CC1F1534F77800162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC051534F77800162364 /* darwin.S */; };
6C43CC201534F77800162364 /* darwin64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC061534F77800162364 /* darwin64.S */; };
6C43CC211534F77800162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC071534F77800162364 /* ffi.c */; };
6C43CC221534F77800162364 /* ffi64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC081534F77800162364 /* ffi64.c */; };
6C43CC2F1534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
6C43CC301534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
6C43CC371534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
6C43CC381534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
6C43CC391534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
6C43CC3B1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
6C43CC3C1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
6C43CC971535032600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8D1535032600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CC981535032600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8E1535032600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CC991535032600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8F1535032600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC901535032600162364 /* ffi_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CC9B1535032600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC911535032600162364 /* fficonfig.h */; };
6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC921535032600162364 /* fficonfig_i386.h */; };
6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC931535032600162364 /* fficonfig_x86_64.h */; };
6C43CC9E1535032600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC941535032600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC951535032600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC961535032600162364 /* ffitarget_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCAD1535039600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA21535039600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA31535039600162364 /* ffi_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCAF1535039600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA41535039600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCB01535039600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA51535039600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCB11535039600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA61535039600162364 /* fficonfig.h */; };
6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA71535039600162364 /* fficonfig_armv7.h */; };
6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA81535039600162364 /* fficonfig_i386.h */; };
6C43CCB41535039600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA91535039600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAA1535039600162364 /* ffitarget_arm.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAB1535039600162364 /* ffitarget_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAC1535039600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; };
DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; };
DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; };
DBFA714E187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
DBFA714F187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
DBFA7158187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
DBFA7159187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
DBFA715A187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
DBFA715B187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716C187F1D9B00A76262 /* ffi_arm64.c */; };
DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; };
DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; };
DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; };
DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */; };
DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */; };
DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7174187F1D9B00A76262 /* darwin_i386.S */; };
DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; };
DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7176187F1D9B00A76262 /* ffi_i386.c */; };
DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7182187F1DA100A76262 /* ffi_i386.h */; };
DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; };
DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7184187F1DA100A76262 /* fficonfig_i386.h */; };
DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */; };
DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7186187F1DA100A76262 /* ffitarget_i386.h */; };
DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; };
DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */; };
DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* darwin_i386.S */; };
DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; };
DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
DB13B1641849DF1E0010F42D /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
6C43CB3D1534E9D100162364 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
6C43CBBD1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
6C43CBBF1534F76F00162364 /* sysv.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv.S; sourceTree = "<group>"; };
6C43CBC01534F76F00162364 /* trampoline.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline.S; sourceTree = "<group>"; };
6C43CBC91534F76F00162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
6C43CBCB1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
6C43CC051534F77800162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
6C43CC061534F77800162364 /* darwin64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64.S; sourceTree = "<group>"; };
6C43CC071534F77800162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
6C43CC081534F77800162364 /* ffi64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64.c; sourceTree = "<group>"; };
6C43CC281534F7BE00162364 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = closures.c; path = src/closures.c; sourceTree = SOURCE_ROOT; };
6C43CC2B1534F7BE00162364 /* java_raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = java_raw_api.c; path = src/java_raw_api.c; sourceTree = SOURCE_ROOT; };
6C43CC2C1534F7BE00162364 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prep_cif.c; path = src/prep_cif.c; sourceTree = SOURCE_ROOT; };
6C43CC2D1534F7BE00162364 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = raw_api.c; path = src/raw_api.c; sourceTree = SOURCE_ROOT; };
6C43CC2E1534F7BE00162364 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = types.c; path = src/types.c; sourceTree = SOURCE_ROOT; };
6C43CC8D1535032600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
6C43CC8E1535032600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
6C43CC8F1535032600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
6C43CC901535032600162364 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
6C43CC911535032600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
6C43CC921535032600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
6C43CC931535032600162364 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
6C43CC941535032600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
6C43CC951535032600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
6C43CC961535032600162364 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
6C43CCA21535039600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
6C43CCA31535039600162364 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
6C43CCA41535039600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
6C43CCA51535039600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
6C43CCA61535039600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
6C43CCA71535039600162364 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
6C43CCA81535039600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
6C43CCA91535039600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
6C43CCAA1535039600162364 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = "<group>"; };
6C43CCAB1535039600162364 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
6C43CCAC1535039600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
F6F980BA147386130008F121 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
DBFA713F187F1D8600A76262 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
DBFA7140187F1D8600A76262 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
DBFA7141187F1D8600A76262 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
DBFA7143187F1D8600A76262 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = closures.c; sourceTree = "<group>"; };
DBFA7145187F1D8600A76262 /* dlmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dlmalloc.c; sourceTree = "<group>"; };
DBFA7147187F1D8600A76262 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prep_cif.c; sourceTree = "<group>"; };
DBFA7148187F1D8600A76262 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_api.c; sourceTree = "<group>"; };
DBFA7149187F1D8600A76262 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = "<group>"; };
DBFA715E187F1D9B00A76262 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = "<group>"; };
DBFA715F187F1D9B00A76262 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
DBFA7160187F1D9B00A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = "<group>"; };
DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = "<group>"; };
DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = "<group>"; };
DBFA716D187F1D9B00A76262 /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = "<group>"; };
DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = "<group>"; };
DBFA7170187F1D9B00A76262 /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = "<group>"; };
DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline_armv7.S; sourceTree = "<group>"; };
DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; };
DBFA7174187F1D9B00A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; };
DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; };
DBFA7176187F1D9B00A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; };
DBFA7182187F1DA100A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
DBFA7183187F1DA100A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
DBFA7184187F1DA100A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
DBFA7186187F1DA100A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; };
DBFA718B187F1DA100A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; };
DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; };
DBFA718D187F1DA100A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6C43CB3A1534E9D100162364 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
F6F980B7147386130008F121 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
6C43CBAF1534F76F00162364 /* iOS */ = {
DB13B15B1849DEB70010F42D = {
isa = PBXGroup;
children = (
6C43CCA11535039600162364 /* include */,
6C43CBBB1534F76F00162364 /* src */,
DBFA713C187F1D8600A76262 /* darwin_common */,
DBFA715C187F1D9B00A76262 /* darwin_ios */,
DBFA7180187F1DA100A76262 /* darwin_osx */,
DB13B1671849DF1E0010F42D /* Products */,
);
name = iOS;
path = ios;
sourceTree = "<group>";
};
6C43CBBB1534F76F00162364 /* src */ = {
DB13B1671849DF1E0010F42D /* Products */ = {
isa = PBXGroup;
children = (
6C43CBC81534F76F00162364 /* x86 */,
6C43CBBC1534F76F00162364 /* arm */,
DB13B1661849DF1E0010F42D /* libffi.a */,
DB13B1911849DF510010F42D /* ffi.dylib */,
);
name = Products;
sourceTree = "<group>";
};
DBFA713C187F1D8600A76262 /* darwin_common */ = {
isa = PBXGroup;
children = (
DBFA713D187F1D8600A76262 /* include */,
DBFA7142187F1D8600A76262 /* src */,
);
path = "darwin_common";
sourceTree = "<group>";
};
DBFA713D187F1D8600A76262 /* include */ = {
isa = PBXGroup;
children = (
DBFA713E187F1D8600A76262 /* ffi.h */,
DBFA713F187F1D8600A76262 /* ffi_common.h */,
DBFA7140187F1D8600A76262 /* fficonfig.h */,
DBFA7141187F1D8600A76262 /* ffitarget.h */,
);
path = include;
sourceTree = "<group>";
};
DBFA7142187F1D8600A76262 /* src */ = {
isa = PBXGroup;
children = (
DBFA7143187F1D8600A76262 /* closures.c */,
DBFA7145187F1D8600A76262 /* dlmalloc.c */,
DBFA7147187F1D8600A76262 /* prep_cif.c */,
DBFA7148187F1D8600A76262 /* raw_api.c */,
DBFA7149187F1D8600A76262 /* types.c */,
);
path = src;
sourceTree = "<group>";
};
6C43CBBC1534F76F00162364 /* arm */ = {
DBFA715C187F1D9B00A76262 /* darwin_ios */ = {
isa = PBXGroup;
children = (
6C43CBBD1534F76F00162364 /* ffi.c */,
6C43CBBF1534F76F00162364 /* sysv.S */,
6C43CBC01534F76F00162364 /* trampoline.S */,
DBFA715D187F1D9B00A76262 /* include */,
DBFA716A187F1D9B00A76262 /* src */,
);
path = "darwin_ios";
sourceTree = "<group>";
};
DBFA715D187F1D9B00A76262 /* include */ = {
isa = PBXGroup;
children = (
DBFA715E187F1D9B00A76262 /* ffi_arm64.h */,
DBFA715F187F1D9B00A76262 /* ffi_armv7.h */,
DBFA7160187F1D9B00A76262 /* ffi_i386.h */,
DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */,
DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */,
DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */,
DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */,
DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */,
DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */,
DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */,
DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */,
DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */,
);
path = include;
sourceTree = "<group>";
};
DBFA716A187F1D9B00A76262 /* src */ = {
isa = PBXGroup;
children = (
DBFA716B187F1D9B00A76262 /* aarch64 */,
DBFA716E187F1D9B00A76262 /* arm */,
DBFA7172187F1D9B00A76262 /* x86 */,
);
path = src;
sourceTree = "<group>";
};
DBFA716B187F1D9B00A76262 /* aarch64 */ = {
isa = PBXGroup;
children = (
DBFA716C187F1D9B00A76262 /* ffi_arm64.c */,
DBFA716D187F1D9B00A76262 /* sysv_arm64.S */,
);
path = aarch64;
sourceTree = "<group>";
};
DBFA716E187F1D9B00A76262 /* arm */ = {
isa = PBXGroup;
children = (
DBFA716F187F1D9B00A76262 /* ffi_armv7.c */,
DBFA7170187F1D9B00A76262 /* sysv_armv7.S */,
DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */,
);
path = arm;
sourceTree = "<group>";
};
6C43CBC81534F76F00162364 /* x86 */ = {
DBFA7172187F1D9B00A76262 /* x86 */ = {
isa = PBXGroup;
children = (
6C43CBC91534F76F00162364 /* darwin.S */,
6C43CBCB1534F76F00162364 /* ffi.c */,
DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */,
DBFA7174187F1D9B00A76262 /* darwin_i386.S */,
DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */,
DBFA7176187F1D9B00A76262 /* ffi_i386.c */,
);
path = x86;
sourceTree = "<group>";
};
6C43CBF01534F77800162364 /* OS X */ = {
DBFA7180187F1DA100A76262 /* darwin_osx */ = {
isa = PBXGroup;
children = (
6C43CC8C1535032600162364 /* include */,
6C43CBFC1534F77800162364 /* src */,
DBFA7181187F1DA100A76262 /* include */,
DBFA7188187F1DA100A76262 /* src */,
);
name = "OS X";
path = osx;
path = "darwin_osx";
sourceTree = "<group>";
};
6C43CBFC1534F77800162364 /* src */ = {
DBFA7181187F1DA100A76262 /* include */ = {
isa = PBXGroup;
children = (
6C43CC041534F77800162364 /* x86 */,
DBFA7182187F1DA100A76262 /* ffi_i386.h */,
DBFA7183187F1DA100A76262 /* ffi_x86_64.h */,
DBFA7184187F1DA100A76262 /* fficonfig_i386.h */,
DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */,
DBFA7186187F1DA100A76262 /* ffitarget_i386.h */,
DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */,
);
path = include;
sourceTree = "<group>";
};
DBFA7188187F1DA100A76262 /* src */ = {
isa = PBXGroup;
children = (
DBFA7189187F1DA100A76262 /* x86 */,
);
path = src;
sourceTree = "<group>";
};
6C43CC041534F77800162364 /* x86 */ = {
DBFA7189187F1DA100A76262 /* x86 */ = {
isa = PBXGroup;
children = (
6C43CC051534F77800162364 /* darwin.S */,
6C43CC061534F77800162364 /* darwin64.S */,
6C43CC071534F77800162364 /* ffi.c */,
6C43CC081534F77800162364 /* ffi64.c */,
DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */,
DBFA718B187F1DA100A76262 /* darwin_i386.S */,
DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */,
DBFA718D187F1DA100A76262 /* ffi_i386.c */,
);
path = x86;
sourceTree = "<group>";
};
6C43CC3D1534F7C400162364 /* src */ = {
isa = PBXGroup;
children = (
6C43CC281534F7BE00162364 /* closures.c */,
6C43CC2B1534F7BE00162364 /* java_raw_api.c */,
6C43CC2C1534F7BE00162364 /* prep_cif.c */,
6C43CC2D1534F7BE00162364 /* raw_api.c */,
6C43CC2E1534F7BE00162364 /* types.c */,
);
name = src;
path = ios;
sourceTree = "<group>";
};
6C43CC8C1535032600162364 /* include */ = {
isa = PBXGroup;
children = (
6C43CC8D1535032600162364 /* ffi.h */,
6C43CC8E1535032600162364 /* ffi_common.h */,
6C43CC8F1535032600162364 /* ffi_i386.h */,
6C43CC901535032600162364 /* ffi_x86_64.h */,
6C43CC911535032600162364 /* fficonfig.h */,
6C43CC921535032600162364 /* fficonfig_i386.h */,
6C43CC931535032600162364 /* fficonfig_x86_64.h */,
6C43CC941535032600162364 /* ffitarget.h */,
6C43CC951535032600162364 /* ffitarget_i386.h */,
6C43CC961535032600162364 /* ffitarget_x86_64.h */,
);
path = include;
sourceTree = "<group>";
};
6C43CCA11535039600162364 /* include */ = {
isa = PBXGroup;
children = (
6C43CCA21535039600162364 /* ffi.h */,
6C43CCA31535039600162364 /* ffi_armv7.h */,
6C43CCA41535039600162364 /* ffi_common.h */,
6C43CCA51535039600162364 /* ffi_i386.h */,
6C43CCA61535039600162364 /* fficonfig.h */,
6C43CCA71535039600162364 /* fficonfig_armv7.h */,
6C43CCA81535039600162364 /* fficonfig_i386.h */,
6C43CCA91535039600162364 /* ffitarget.h */,
6C43CCAA1535039600162364 /* ffitarget_arm.h */,
6C43CCAB1535039600162364 /* ffitarget_armv7.h */,
6C43CCAC1535039600162364 /* ffitarget_i386.h */,
);
path = include;
sourceTree = "<group>";
};
F6B0839514721EE50031D8A1 = {
isa = PBXGroup;
children = (
6C43CC3D1534F7C400162364 /* src */,
6C43CBAF1534F76F00162364 /* iOS */,
6C43CBF01534F77800162364 /* OS X */,
F6F980C6147386260008F121 /* Products */,
);
sourceTree = "<group>";
};
F6F980C6147386260008F121 /* Products */ = {
isa = PBXGroup;
children = (
F6F980BA147386130008F121 /* libffi.a */,
6C43CB3D1534E9D100162364 /* libffi.a */,
);
name = Products;
path = ../..;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
6C43CB3B1534E9D100162364 /* Headers */ = {
DB13B18F1849DF510010F42D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
6C43CC971535032600162364 /* ffi.h in Headers */,
6C43CC981535032600162364 /* ffi_common.h in Headers */,
6C43CC991535032600162364 /* ffi_i386.h in Headers */,
6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */,
6C43CC9E1535032600162364 /* ffitarget.h in Headers */,
6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */,
6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */,
6C43CC9B1535032600162364 /* fficonfig.h in Headers */,
6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */,
6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6F980B8147386130008F121 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
6C43CCAD1535039600162364 /* ffi.h in Headers */,
6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */,
6C43CCAF1535039600162364 /* ffi_common.h in Headers */,
6C43CCB01535039600162364 /* ffi_i386.h in Headers */,
6C43CCB41535039600162364 /* ffitarget.h in Headers */,
6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */,
6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */,
6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */,
6C43CCB11535039600162364 /* fficonfig.h in Headers */,
6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */,
6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */,
DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */,
DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */,
DBFA714A187F1D8600A76262 /* ffi.h in Headers */,
DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */,
DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */,
DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */,
DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */,
DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */,
DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */,
DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
6C43CB3C1534E9D100162364 /* libffi OS X */ = {
DB13B1651849DF1E0010F42D /* libffi-iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */;
buildConfigurationList = DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */;
buildPhases = (
6C43CC401534FF3B00162364 /* Generate Source and Headers */,
6C43CB391534E9D100162364 /* Sources */,
6C43CB3A1534E9D100162364 /* Frameworks */,
6C43CB3B1534E9D100162364 /* Headers */,
DB13B3051849E01C0010F42D /* ShellScript */,
DB13B1621849DF1E0010F42D /* Sources */,
DB13B1641849DF1E0010F42D /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = "libffi OS X";
productName = "ffi OS X";
productReference = 6C43CB3D1534E9D100162364 /* libffi.a */;
name = "libffi-iOS";
productName = ffi;
productReference = DB13B1661849DF1E0010F42D /* libffi.a */;
productType = "com.apple.product-type.library.static";
};
F6F980B9147386130008F121 /* libffi iOS */ = {
DB13B1901849DF510010F42D /* libffi-Mac */ = {
isa = PBXNativeTarget;
buildConfigurationList = F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */;
buildConfigurationList = DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */;
buildPhases = (
6C43CC3E1534F8E200162364 /* Generate Trampoline */,
6C43CC3F1534FF1B00162364 /* Generate Source and Headers */,
F6F980B6147386130008F121 /* Sources */,
F6F980B7147386130008F121 /* Frameworks */,
F6F980B8147386130008F121 /* Headers */,
DB13B3061849E0490010F42D /* ShellScript */,
DB13B18D1849DF510010F42D /* Sources */,
DB13B18F1849DF510010F42D /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = "libffi iOS";
name = "libffi-Mac";
productName = ffi;
productReference = F6F980BA147386130008F121 /* libffi.a */;
productType = "com.apple.product-type.library.static";
productReference = DB13B1911849DF510010F42D /* ffi.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
F6B0839714721EE50031D8A1 /* Project object */ = {
DB13B15C1849DEB70010F42D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0430;
LastUpgradeCheck = 0510;
};
buildConfigurationList = F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */;
buildConfigurationList = DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = F6B0839514721EE50031D8A1;
productRefGroup = F6B0839514721EE50031D8A1;
mainGroup = DB13B15B1849DEB70010F42D;
productRefGroup = DB13B1671849DF1E0010F42D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
F6F980B9147386130008F121 /* libffi iOS */,
6C43CB3C1534E9D100162364 /* libffi OS X */,
DB13B1651849DF1E0010F42D /* libffi-iOS */,
DB13B1901849DF510010F42D /* libffi-Mac */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
6C43CC3E1534F8E200162364 /* Generate Trampoline */ = {
DB13B3051849E01C0010F42D /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Generate Trampoline";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /usr/bin/python;
shellScript = "import subprocess\nimport re\nimport os\nimport errno\nimport sys\n\ndef main():\n with open('src/arm/trampoline.S', 'w') as tramp_out:\n p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)\n p.wait()\n\nif __name__ == '__main__':\n main()";
};
6C43CC3F1534FF1B00162364 /* Generate Source and Headers */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Generate Source and Headers";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/bin/python generate-ios-source-and-headers.py";
shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-ios";
};
6C43CC401534FF3B00162364 /* Generate Source and Headers */ = {
DB13B3061849E0490010F42D /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Generate Source and Headers";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/bin/python generate-osx-source-and-headers.py";
shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-osx";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
6C43CB391534E9D100162364 /* Sources */ = {
DB13B1621849DF1E0010F42D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6C43CC1F1534F77800162364 /* darwin.S in Sources */,
6C43CC201534F77800162364 /* darwin64.S in Sources */,
6C43CC211534F77800162364 /* ffi.c in Sources */,
6C43CC221534F77800162364 /* ffi64.c in Sources */,
6C43CC301534F7BE00162364 /* closures.c in Sources */,
6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */,
6C43CC381534F7BE00162364 /* prep_cif.c in Sources */,
6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */,
6C43CC3C1534F7BE00162364 /* types.c in Sources */,
DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */,
DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */,
DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */,
DBFA714E187F1D8600A76262 /* closures.c in Sources */,
DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */,
DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */,
DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */,
DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */,
DBFA7158187F1D8600A76262 /* raw_api.c in Sources */,
DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */,
DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */,
DBFA715A187F1D8600A76262 /* types.c in Sources */,
DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6F980B6147386130008F121 /* Sources */ = {
DB13B18D1849DF510010F42D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6C43CBDC1534F76F00162364 /* ffi.c in Sources */,
6C43CBDD1534F76F00162364 /* sysv.S in Sources */,
6C43CBDE1534F76F00162364 /* trampoline.S in Sources */,
6C43CBE61534F76F00162364 /* darwin.S in Sources */,
6C43CBE81534F76F00162364 /* ffi.c in Sources */,
6C43CC2F1534F7BE00162364 /* closures.c in Sources */,
6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */,
6C43CC371534F7BE00162364 /* prep_cif.c in Sources */,
6C43CC391534F7BE00162364 /* raw_api.c in Sources */,
6C43CC3B1534F7BE00162364 /* types.c in Sources */,
DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */,
DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */,
DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */,
DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */,
DBFA715B187F1D8600A76262 /* types.c in Sources */,
DBFA7159187F1D8600A76262 /* raw_api.c in Sources */,
DBFA714F187F1D8600A76262 /* closures.c in Sources */,
DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
6C43CB4B1534E9D100162364 /* Debug */ = {
DB13B1601849DEB70010F42D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
DSTROOT = /tmp/ffi.dst;
FRAMEWORK_SEARCH_PATHS = (
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
"darwin_common/include",
);
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = ffi;
SDKROOT = macosx;
};
name = Debug;
};
6C43CB4C1534E9D100162364 /* Release */ = {
DB13B1611849DEB70010F42D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DSTROOT = /tmp/ffi.dst;
FRAMEWORK_SEARCH_PATHS = (
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
"darwin_common/include",
);
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
PRODUCT_NAME = ffi;
SDKROOT = macosx;
};
name = Release;
};
F6B083AB14721EE50031D8A1 /* Debug */ = {
DB13B1871849DF1E0010F42D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DSTROOT = /tmp/ffi.dst;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@ -482,98 +457,181 @@
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VALUE = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ios/include;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"darwin_ios/include",
);
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = ffi;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
};
name = Debug;
};
F6B083AC14721EE50031D8A1 /* Release */ = {
DB13B1881849DF1E0010F42D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DSTROOT = /tmp/ffi.dst;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VALUE = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ios/include;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"darwin_ios/include",
);
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = ffi;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
F6F980C2147386130008F121 /* Debug */ = {
DB13B1B11849DF520010F42D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
armv6,
armv7,
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
DSTROOT = /tmp/ffi.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_THUMB_SUPPORT = NO;
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
OTHER_LDFLAGS = "-ObjC";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"darwin_osx/include",
);
MACOSX_DEPLOYMENT_TARGET = 10.6;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
PRODUCT_NAME = ffi;
SKIP_INSTALL = YES;
SDKROOT = macosx;
};
name = Debug;
};
F6F980C3147386130008F121 /* Release */ = {
DB13B1B21849DF520010F42D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
armv6,
armv7,
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"darwin_osx/include",
);
DSTROOT = /tmp/ffi.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_THUMB_SUPPORT = NO;
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
OTHER_LDFLAGS = "-ObjC";
MACOSX_DEPLOYMENT_TARGET = 10.6;
OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
PRODUCT_NAME = ffi;
SKIP_INSTALL = YES;
SDKROOT = macosx;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */ = {
DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6C43CB4B1534E9D100162364 /* Debug */,
6C43CB4C1534E9D100162364 /* Release */,
DB13B1601849DEB70010F42D /* Debug */,
DB13B1611849DEB70010F42D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */ = {
DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F6B083AB14721EE50031D8A1 /* Debug */,
F6B083AC14721EE50031D8A1 /* Release */,
DB13B1871849DF1E0010F42D /* Debug */,
DB13B1881849DF1E0010F42D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */ = {
DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F6F980C2147386130008F121 /* Debug */,
F6F980C3147386130008F121 /* Release */,
DB13B1B11849DF520010F42D /* Debug */,
DB13B1B21849DF520010F42D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = F6B0839714721EE50031D8A1 /* Project object */;
rootObject = DB13B15C1849DEB70010F42D /* Project object */;
}

View file

@ -97,6 +97,10 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -149,12 +153,14 @@ SHELL = @SHELL@
STRIP = @STRIP@
TARGET = @TARGET@
TARGETDIR = @TARGETDIR@
TARGET_OBJ = @TARGET_OBJ@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@

View file

@ -61,10 +61,8 @@ does not refer to a valid ABI,
.Nm FFI_BAD_ABI
will be returned. Available ABIs are
defined in
.Nm <ffitarget.h>
.
.Nm <ffitarget.h> .
.Sh SEE ALSO
.Xr ffi 3 ,
.Xr ffi_call 3 ,
.Xr ffi_prep_cif_var 3

View file

@ -42,8 +42,10 @@
# format and translated into something sensible for cl or ml.
#
args_orig=$@
args="-nologo -W3"
md=-MD
static_crt=
debug_crt=
cl="cl"
ml="ml"
safeseh="-safeseh"
@ -62,31 +64,65 @@ do
shift 1
;;
-m64)
cl="cl" # "$MSVC/x86_amd64/cl"
ml="ml64" # "$MSVC/x86_amd64/ml64"
safeseh=
shift 1
;;
-clang-cl)
cl="clang-cl"
safeseh=
shift 1
;;
-O0)
args="$args -Od"
shift 1
;;
-O*)
# If we're optimizing, make sure we explicitly turn on some optimizations
# that are implicitly disabled by debug symbols (-Zi).
args="$args $1 -OPT:REF -OPT:ICF -INCREMENTAL:NO"
# Runtime error checks (enabled by setting -RTC1 in the -DFFI_DEBUG
# case below) are not compatible with optimization flags and will
# cause the build to fail. Therefore, drop the optimization flag if
# -DFFI_DEBUG is also set.
case $args_orig in
*-DFFI_DEBUG*)
args="$args"
;;
*)
# The ax_cc_maxopt.m4 macro from the upstream autoconf-archive
# project doesn't support MSVC and therefore ends up trying to
# use -O3. Use the equivalent "max optimization" flag for MSVC
# instead of erroring out.
case $1 in
-O3)
args="$args -O2"
;;
*)
args="$args $1"
;;
esac
opt="true"
;;
esac
shift 1
;;
-g)
# Enable debug symbol generation.
args="$args -Zi -DEBUG"
args="$args -Zi"
shift 1
;;
-DFFI_DEBUG)
# Link against debug CRT and enable runtime error checks.
# Enable runtime error checks.
args="$args -RTC1"
defines="$defines $1"
md=-MDd
shift 1
;;
-DUSE_STATIC_RTL)
# Link against static CRT.
static_crt=1
shift 1
;;
-DUSE_DEBUG_RTL)
# Link against debug CRT.
debug_crt=1
shift 1
;;
-c)
@ -126,6 +162,10 @@ do
# to do here.
shift 1
;;
-pedantic)
# libffi tests -pedantic with -Wall, so drop it also.
shift 1
;;
-Werror)
args="$args -WX"
shift 1
@ -170,6 +210,23 @@ do
esac
done
# If -Zi is specified, certain optimizations are implicitly disabled
# by MSVC. Add back those optimizations if this is an optimized build.
# NOTE: These arguments must come after all others.
if [ -n "$opt" ]; then
args="$args -link -OPT:REF -OPT:ICF -INCREMENTAL:NO"
fi
if [ -n "$static_crt" ]; then
md=-MT
else
md=-MD
fi
if [ -n "$debug_crt" ]; then
md="${md}d"
fi
if [ -n "$assembly" ]; then
if [ -z "$outdir" ]; then
outdir="."
@ -189,7 +246,10 @@ if [ -n "$assembly" ]; then
else
args="$md $args"
echo "$cl $args"
eval "\"$cl\" $args"
# Return an error code of 1 if an invalid command line parameter is passed
# instead of just ignoring it.
eval "(\"$cl\" $args 2>&1 1>&3 | \
awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1"
result=$?
fi

File diff suppressed because it is too large Load diff

View file

@ -42,18 +42,20 @@ typedef enum ffi_abi
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 36
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0
/* ---- Internal ---- */
#if defined (__APPLE__)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
#else
/* iOS reserves x18 for the system. Disable Go closures until
a new static chain is chosen. */
#define FFI_GO_CLOSURES 1
#endif
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
#define AARCH64_FFI_WITH_V_BIT 0
#define AARCH64_N_XREG 32
#define AARCH64_N_VREG 32
#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif

View file

@ -0,0 +1,67 @@
/*
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 THE AUTHORS OR COPYRIGHT HOLDERS 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. */
#define AARCH64_RET_VOID 0
#define AARCH64_RET_INT64 1
#define AARCH64_RET_INT128 2
#define AARCH64_RET_UNUSED3 3
#define AARCH64_RET_UNUSED4 4
#define AARCH64_RET_UNUSED5 5
#define AARCH64_RET_UNUSED6 6
#define AARCH64_RET_UNUSED7 7
/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4,
so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */
#define AARCH64_RET_S4 8
#define AARCH64_RET_S3 9
#define AARCH64_RET_S2 10
#define AARCH64_RET_S1 11
#define AARCH64_RET_D4 12
#define AARCH64_RET_D3 13
#define AARCH64_RET_D2 14
#define AARCH64_RET_D1 15
#define AARCH64_RET_Q4 16
#define AARCH64_RET_Q3 17
#define AARCH64_RET_Q2 18
#define AARCH64_RET_Q1 19
/* Note that each of the sub-64-bit integers gets two entries. */
#define AARCH64_RET_UINT8 20
#define AARCH64_RET_UINT16 22
#define AARCH64_RET_UINT32 24
#define AARCH64_RET_SINT8 26
#define AARCH64_RET_SINT16 28
#define AARCH64_RET_SINT32 30
#define AARCH64_RET_MASK 31
#define AARCH64_RET_IN_MEM (1 << 5)
#define AARCH64_RET_NEED_COPY (1 << 6)
#define AARCH64_FLAG_ARG_V_BIT 7
#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT)
#define N_X_ARG_REG 8
#define N_V_ARG_REG 8
#define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8)

View file

@ -22,286 +22,382 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include "internal.h"
#define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#define cfi_restore(reg) .cfi_restore reg
#define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#else
#ifdef __USER_LABEL_PREFIX__
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
.text
.globl ffi_call_SYSV
.type ffi_call_SYSV, #function
/* Use the right prefix for global labels. */
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#else
#define CNAME(x) x
#endif
#endif
/* ffi_call_SYSV()
#ifdef __AARCH64EB__
# define BE(X) X
#else
# define BE(X) 0
#endif
Create a stack frame, setup an argument context, call the callee
and extract the result.
.text
.align 4
The maximum required argument stack size is provided,
ffi_call_SYSV() allocates that stack space then calls the
prepare_fn to populate register context and stack. The
argument passing registers are loaded from the register
context and the callee called, on return the register passing
register are saved back to the context. Our caller will
extract the return value from the final state of the saved
register context.
Prototype:
extern unsigned
ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
extended_cif *),
struct call_context *context,
extended_cif *,
unsigned required_stack_size,
void (*fn)(void));
/* ffi_call_SYSV
extern void ffi_call_SYSV (void *stack, void *frame,
void (*fn)(void), void *rvalue,
int flags, void *closure);
Therefore on entry we have:
x0 prepare_fn
x1 &context
x2 &ecif
x3 bytes
x4 fn
x0 stack
x1 frame
x2 fn
x3 rvalue
x4 flags
x5 closure
*/
This function uses the following stack frame layout:
cfi_startproc
CNAME(ffi_call_SYSV):
/* Use a stack frame allocated by our caller. */
cfi_def_cfa(x1, 32);
stp x29, x30, [x1]
mov x29, x1
mov sp, x0
cfi_def_cfa_register(x29)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
==
saved x30(lr)
x29(fp)-> saved x29(fp)
saved x24
saved x23
saved x22
sp' -> saved x21
...
sp -> (constructed callee stack arguments)
==
mov x9, x2 /* save fn */
mov x8, x3 /* install structure return */
#ifdef FFI_GO_CLOSURES
mov x18, x5 /* install static chain */
#endif
stp x3, x4, [x29, #16] /* save rvalue and flags */
Voila! */
#define ffi_call_SYSV_FS (8 * 4)
.cfi_startproc
ffi_call_SYSV:
stp x29, x30, [sp, #-16]!
cfi_adjust_cfa_offset (16)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
mov x29, sp
cfi_def_cfa_register (x29)
sub sp, sp, #ffi_call_SYSV_FS
stp x21, x22, [sp, 0]
cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS)
cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS)
stp x23, x24, [sp, 16]
cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS)
cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS)
mov x21, x1
mov x22, x2
mov x24, x4
/* Allocate the stack space for the actual arguments, many
arguments will be passed in registers, but we assume
worst case and allocate sufficient stack for ALL of
the arguments. */
sub sp, sp, x3
/* unsigned (*prepare_fn) (struct call_context *context,
unsigned char *stack, extended_cif *ecif);
*/
mov x23, x0
mov x0, x1
mov x1, sp
/* x2 already in place */
blr x23
/* Preserve the flags returned. */
mov x23, x0
/* Figure out if we should touch the vector registers. */
tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f
/* Load the vector argument passing registers. */
ldp q0, q1, [x21, #8*32 + 0]
ldp q2, q3, [x21, #8*32 + 32]
ldp q4, q5, [x21, #8*32 + 64]
ldp q6, q7, [x21, #8*32 + 96]
/* Load the vector argument passing registers, if necessary. */
tbz w4, #AARCH64_FLAG_ARG_V_BIT, 1f
ldp q0, q1, [sp, #0]
ldp q2, q3, [sp, #32]
ldp q4, q5, [sp, #64]
ldp q6, q7, [sp, #96]
1:
/* Load the core argument passing registers. */
ldp x0, x1, [x21, #0]
ldp x2, x3, [x21, #16]
ldp x4, x5, [x21, #32]
ldp x6, x7, [x21, #48]
/* Load the core argument passing registers, including
the structure return pointer. */
ldp x0, x1, [sp, #16*N_V_ARG_REG + 0]
ldp x2, x3, [sp, #16*N_V_ARG_REG + 16]
ldp x4, x5, [sp, #16*N_V_ARG_REG + 32]
ldp x6, x7, [sp, #16*N_V_ARG_REG + 48]
/* Don't forget x8 which may be holding the address of a return buffer.
*/
ldr x8, [x21, #8*8]
/* Deallocate the context, leaving the stacked arguments. */
add sp, sp, #CALL_CONTEXT_SIZE
blr x24
blr x9 /* call fn */
/* Save the core argument passing registers. */
stp x0, x1, [x21, #0]
stp x2, x3, [x21, #16]
stp x4, x5, [x21, #32]
stp x6, x7, [x21, #48]
ldp x3, x4, [x29, #16] /* reload rvalue and flags */
/* Note nothing useful ever comes back in x8! */
/* Figure out if we should touch the vector registers. */
tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f
/* Save the vector argument passing registers. */
stp q0, q1, [x21, #8*32 + 0]
stp q2, q3, [x21, #8*32 + 32]
stp q4, q5, [x21, #8*32 + 64]
stp q6, q7, [x21, #8*32 + 96]
1:
/* All done, unwind our stack frame. */
ldp x21, x22, [x29, # - ffi_call_SYSV_FS]
cfi_restore (x21)
cfi_restore (x22)
ldp x23, x24, [x29, # - ffi_call_SYSV_FS + 16]
cfi_restore (x23)
cfi_restore (x24)
mov sp, x29
/* Partially deconstruct the stack frame. */
mov sp, x29
cfi_def_cfa_register (sp)
ldp x29, x30, [x29]
ldp x29, x30, [sp], #16
cfi_adjust_cfa_offset (-16)
cfi_restore (x29)
cfi_restore (x30)
/* Save the return value as directed. */
adr x5, 0f
and w4, w4, #AARCH64_RET_MASK
add x5, x5, x4, lsl #3
br x5
ret
/* Note that each table entry is 2 insns, and thus 8 bytes.
For integer data, note that we're storing into ffi_arg
and therefore we want to extend to 64 bits; these types
have two consecutive entries allocated for them. */
.align 4
0: ret /* VOID */
nop
1: str x0, [x3] /* INT64 */
ret
2: stp x0, x1, [x3] /* INT128 */
ret
3: brk #1000 /* UNUSED */
ret
4: brk #1000 /* UNUSED */
ret
5: brk #1000 /* UNUSED */
ret
6: brk #1000 /* UNUSED */
ret
7: brk #1000 /* UNUSED */
ret
8: st4 { v0.s-v3.s }[0], [x3] /* S4 */
ret
9: st3 { v0.s-v2.s }[0], [x3] /* S3 */
ret
10: stp s0, s1, [x3] /* S2 */
ret
11: str s0, [x3] /* S1 */
ret
12: st4 { v0.d-v3.d }[0], [x3] /* D4 */
ret
13: st3 { v0.d-v2.d }[0], [x3] /* D3 */
ret
14: stp d0, d1, [x3] /* D2 */
ret
15: str d0, [x3] /* D1 */
ret
16: str q3, [x3, #48] /* Q4 */
nop
17: str q2, [x3, #32] /* Q3 */
nop
18: stp q0, q1, [x3] /* Q2 */
ret
19: str q0, [x3] /* Q1 */
ret
20: uxtb w0, w0 /* UINT8 */
str x0, [x3]
21: ret /* reserved */
nop
22: uxth w0, w0 /* UINT16 */
str x0, [x3]
23: ret /* reserved */
nop
24: mov w0, w0 /* UINT32 */
str x0, [x3]
25: ret /* reserved */
nop
26: sxtb x0, w0 /* SINT8 */
str x0, [x3]
27: ret /* reserved */
nop
28: sxth x0, w0 /* SINT16 */
str x0, [x3]
29: ret /* reserved */
nop
30: sxtw x0, w0 /* SINT32 */
str x0, [x3]
31: ret /* reserved */
nop
.cfi_endproc
.size ffi_call_SYSV, .-ffi_call_SYSV
cfi_endproc
#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
.globl CNAME(ffi_call_SYSV)
#ifdef __ELF__
.type CNAME(ffi_call_SYSV), #function
.hidden CNAME(ffi_call_SYSV)
.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
#endif
/* ffi_closure_SYSV
Closure invocation glue. This is the low level code invoked directly by
the closure trampoline to setup and call a closure.
On entry x17 points to a struct trampoline_data, x16 has been clobbered
On entry x17 points to a struct ffi_closure, x16 has been clobbered
all other registers are preserved.
We allocate a call context and save the argument passing registers,
then invoked the generic C ffi_closure_SYSV_inner() function to do all
the real work, on return we load the result passing registers back from
the call context.
*/
On entry
#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64)
extern void
ffi_closure_SYSV (struct trampoline_data *);
.align 4
CNAME(ffi_closure_SYSV_V):
cfi_startproc
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
struct trampoline_data
{
UINT64 *ffi_closure;
UINT64 flags;
};
/* Save the argument passing vector registers. */
stp q0, q1, [sp, #16 + 0]
stp q2, q3, [sp, #16 + 32]
stp q4, q5, [sp, #16 + 64]
stp q6, q7, [sp, #16 + 96]
b 0f
cfi_endproc
This function uses the following stack frame layout:
.globl CNAME(ffi_closure_SYSV_V)
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV_V), #function
.hidden CNAME(ffi_closure_SYSV_V)
.size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
#endif
==
saved x30(lr)
x29(fp)-> saved x29(fp)
saved x22
saved x21
...
sp -> call_context
==
.align 4
cfi_startproc
CNAME(ffi_closure_SYSV):
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
0:
mov x29, sp
Voila! */
/* Save the argument passing core registers. */
stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
.text
.globl ffi_closure_SYSV
.cfi_startproc
ffi_closure_SYSV:
stp x29, x30, [sp, #-16]!
cfi_adjust_cfa_offset (16)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
/* Load ffi_closure_inner arguments. */
ldp x0, x1, [x17, #FFI_TRAMPOLINE_SIZE] /* load cif, fn */
ldr x2, [x17, #FFI_TRAMPOLINE_SIZE+16] /* load user_data */
.Ldo_closure:
add x3, sp, #16 /* load context */
add x4, sp, #ffi_closure_SYSV_FS /* load stack */
add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
mov x6, x8 /* load struct_rval */
bl CNAME(ffi_closure_SYSV_inner)
mov x29, sp
cfi_def_cfa_register (x29)
/* Load the return value as directed. */
adr x1, 0f
and w0, w0, #AARCH64_RET_MASK
add x1, x1, x0, lsl #3
add x3, sp, #16+CALL_CONTEXT_SIZE
br x1
sub sp, sp, #ffi_closure_SYSV_FS
/* Note that each table entry is 2 insns, and thus 8 bytes. */
.align 4
0: b 99f /* VOID */
nop
1: ldr x0, [x3] /* INT64 */
b 99f
2: ldp x0, x1, [x3] /* INT128 */
b 99f
3: brk #1000 /* UNUSED */
nop
4: brk #1000 /* UNUSED */
nop
5: brk #1000 /* UNUSED */
nop
6: brk #1000 /* UNUSED */
nop
7: brk #1000 /* UNUSED */
nop
8: ldr s3, [x3, #12] /* S4 */
nop
9: ldr s2, [x2, #8] /* S3 */
nop
10: ldp s0, s1, [x3] /* S2 */
b 99f
11: ldr s0, [x3] /* S1 */
b 99f
12: ldr d3, [x3, #24] /* D4 */
nop
13: ldr d2, [x3, #16] /* D3 */
nop
14: ldp d0, d1, [x3] /* D2 */
b 99f
15: ldr d0, [x3] /* D1 */
b 99f
16: ldr q3, [x3, #48] /* Q4 */
nop
17: ldr q2, [x3, #32] /* Q3 */
nop
18: ldp q0, q1, [x3] /* Q2 */
b 99f
19: ldr q0, [x3] /* Q1 */
b 99f
20: ldrb w0, [x3, #BE(7)] /* UINT8 */
b 99f
21: brk #1000 /* reserved */
nop
22: ldrh w0, [x3, #BE(6)] /* UINT16 */
b 99f
23: brk #1000 /* reserved */
nop
24: ldr w0, [x3, #BE(4)] /* UINT32 */
b 99f
25: brk #1000 /* reserved */
nop
26: ldrsb x0, [x3, #BE(7)] /* SINT8 */
b 99f
27: brk #1000 /* reserved */
nop
28: ldrsh x0, [x3, #BE(6)] /* SINT16 */
b 99f
29: brk #1000 /* reserved */
nop
30: ldrsw x0, [x3, #BE(4)] /* SINT32 */
nop
31: /* reserved */
99: ldp x29, x30, [sp], #ffi_closure_SYSV_FS
cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
cfi_restore (x29)
cfi_restore (x30)
ret
cfi_endproc
stp x21, x22, [x29, #-16]
cfi_rel_offset (x21, -16)
cfi_rel_offset (x22, -8)
.globl CNAME(ffi_closure_SYSV)
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV), #function
.hidden CNAME(ffi_closure_SYSV)
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
#endif
/* Load x21 with &call_context. */
mov x21, sp
/* Preserve our struct trampoline_data * */
mov x22, x17
#ifdef FFI_GO_CLOSURES
.align 4
CNAME(ffi_go_closure_SYSV_V):
cfi_startproc
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
/* Save the rest of the argument passing registers. */
stp x0, x1, [x21, #0]
stp x2, x3, [x21, #16]
stp x4, x5, [x21, #32]
stp x6, x7, [x21, #48]
/* Don't forget we may have been given a result scratch pad address.
*/
str x8, [x21, #64]
/* Save the argument passing vector registers. */
stp q0, q1, [sp, #16 + 0]
stp q2, q3, [sp, #16 + 32]
stp q4, q5, [sp, #16 + 64]
stp q6, q7, [sp, #16 + 96]
b 0f
cfi_endproc
/* Figure out if we should touch the vector registers. */
ldr x0, [x22, #8]
tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f
.globl CNAME(ffi_go_closure_SYSV_V)
#ifdef __ELF__
.type CNAME(ffi_go_closure_SYSV_V), #function
.hidden CNAME(ffi_go_closure_SYSV_V)
.size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
#endif
/* Save the argument passing vector registers. */
stp q0, q1, [x21, #8*32 + 0]
stp q2, q3, [x21, #8*32 + 32]
stp q4, q5, [x21, #8*32 + 64]
stp q6, q7, [x21, #8*32 + 96]
1:
/* Load &ffi_closure.. */
ldr x0, [x22, #0]
mov x1, x21
/* Compute the location of the stack at the point that the
trampoline was called. */
add x2, x29, #16
.align 4
cfi_startproc
CNAME(ffi_go_closure_SYSV):
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
0:
mov x29, sp
bl ffi_closure_SYSV_inner
/* Save the argument passing core registers. */
stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
/* Figure out if we should touch the vector registers. */
ldr x0, [x22, #8]
tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f
/* Load ffi_closure_inner arguments. */
ldp x0, x1, [x18, #8] /* load cif, fn */
mov x2, x18 /* load user_data */
b .Ldo_closure
cfi_endproc
/* Load the result passing vector registers. */
ldp q0, q1, [x21, #8*32 + 0]
ldp q2, q3, [x21, #8*32 + 32]
ldp q4, q5, [x21, #8*32 + 64]
ldp q6, q7, [x21, #8*32 + 96]
1:
/* Load the result passing core registers. */
ldp x0, x1, [x21, #0]
ldp x2, x3, [x21, #16]
ldp x4, x5, [x21, #32]
ldp x6, x7, [x21, #48]
/* Note nothing usefull is returned in x8. */
.globl CNAME(ffi_go_closure_SYSV)
#ifdef __ELF__
.type CNAME(ffi_go_closure_SYSV), #function
.hidden CNAME(ffi_go_closure_SYSV)
.size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
#endif
#endif /* FFI_GO_CLOSURES */
/* We are done, unwind our frame. */
ldp x21, x22, [x29, #-16]
cfi_restore (x21)
cfi_restore (x22)
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits
#endif
mov sp, x29
cfi_def_cfa_register (sp)
ldp x29, x30, [sp], #16
cfi_adjust_cfa_offset (-16)
cfi_restore (x29)
cfi_restore (x30)
ret
.cfi_endproc
.size ffi_closure_SYSV, .-ffi_closure_SYSV

View file

@ -1,8 +1,8 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2012 Anthony Green
Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
Alpha Foreign Function Interface
Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
Alpha Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -27,6 +27,8 @@
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include "internal.h"
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
all further uses in this file will refer to the 128-bit type. */
@ -39,135 +41,286 @@
# define FFI_TYPE_LONGDOUBLE 4
#endif
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
FFI_HIDDEN;
extern void ffi_call_osf(void *stack, void *frame, unsigned flags,
void *raddr, void (*fn)(void), void *closure)
FFI_HIDDEN;
extern void ffi_closure_osf(void) FFI_HIDDEN;
extern void ffi_go_closure_osf(void) FFI_HIDDEN;
/* Promote a float value to its in-register double representation.
Unlike actually casting to double, this does not trap on NaN. */
static inline UINT64 lds(void *ptr)
{
UINT64 ret;
asm("lds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr));
return ret;
}
ffi_status
/* And the reverse. */
static inline void sts(void *ptr, UINT64 val)
{
asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val));
}
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif *cif)
{
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
register argument loading area. */
if (cif->bytes < 6*FFI_SIZEOF_ARG)
cif->bytes = 6*FFI_SIZEOF_ARG;
size_t bytes = 0;
int flags, i, avn;
ffi_type *rtype, *itype;
if (cif->abi != FFI_OSF)
return FFI_BAD_ABI;
/* Compute the size of the argument area. */
for (i = 0, avn = cif->nargs; i < avn; i++)
{
itype = cif->arg_types[i];
switch (itype->type)
{
case FFI_TYPE_INT:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
/* All take one 8 byte slot. */
bytes += 8;
break;
case FFI_TYPE_VOID:
case FFI_TYPE_STRUCT:
/* Passed by value in N slots. */
bytes += ALIGN(itype->size, FFI_SIZEOF_ARG);
break;
case FFI_TYPE_COMPLEX:
/* _Complex long double passed by reference; others in 2 slots. */
if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
bytes += 8;
else
bytes += 16;
break;
default:
abort();
}
}
/* Set the return type flag */
switch (cif->rtype->type)
rtype = cif->rtype;
switch (rtype->type)
{
case FFI_TYPE_STRUCT:
case FFI_TYPE_VOID:
flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID);
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT32);
break;
case FFI_TYPE_FLOAT:
flags = ALPHA_FLAGS(ALPHA_ST_FLOAT, ALPHA_LD_FLOAT);
break;
case FFI_TYPE_DOUBLE:
cif->flags = cif->rtype->type;
flags = ALPHA_FLAGS(ALPHA_ST_DOUBLE, ALPHA_LD_DOUBLE);
break;
case FFI_TYPE_UINT8:
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT8);
break;
case FFI_TYPE_SINT8:
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT8);
break;
case FFI_TYPE_UINT16:
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT16);
break;
case FFI_TYPE_SINT16:
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT16);
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
break;
case FFI_TYPE_LONGDOUBLE:
/* 128-bit long double is returned in memory, like a struct. */
cif->flags = FFI_TYPE_STRUCT;
case FFI_TYPE_STRUCT:
/* Passed in memory, with a hidden pointer. */
flags = ALPHA_RET_IN_MEM;
break;
case FFI_TYPE_COMPLEX:
itype = rtype->elements[0];
switch (itype->type)
{
case FFI_TYPE_FLOAT:
flags = ALPHA_FLAGS(ALPHA_ST_CPLXF, ALPHA_LD_CPLXF);
break;
case FFI_TYPE_DOUBLE:
flags = ALPHA_FLAGS(ALPHA_ST_CPLXD, ALPHA_LD_CPLXD);
break;
default:
if (rtype->size <= 8)
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
else
flags = ALPHA_RET_IN_MEM;
break;
}
break;
default:
cif->flags = FFI_TYPE_INT;
break;
abort();
}
cif->flags = flags;
/* Include the hidden structure pointer in args requirement. */
if (flags == ALPHA_RET_IN_MEM)
bytes += 8;
/* Minimum size is 6 slots, so that ffi_call_osf can pop them. */
if (bytes < 6*8)
bytes = 6*8;
cif->bytes = bytes;
return FFI_OK;
}
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
static unsigned long
extend_basic_type(void *valp, int type, int argn)
{
unsigned long *stack, *argp;
long i, avn;
switch (type)
{
case FFI_TYPE_SINT8:
return *(SINT8 *)valp;
case FFI_TYPE_UINT8:
return *(UINT8 *)valp;
case FFI_TYPE_SINT16:
return *(SINT16 *)valp;
case FFI_TYPE_UINT16:
return *(UINT16 *)valp;
case FFI_TYPE_FLOAT:
if (argn < 6)
return lds(valp);
/* FALLTHRU */
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
/* Note that unsigned 32-bit quantities are sign extended. */
return *(SINT32 *)valp;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
case FFI_TYPE_DOUBLE:
return *(UINT64 *)valp;
default:
abort();
}
}
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
unsigned long *argp;
long i, avn, argn, flags = cif->flags;
ffi_type **arg_types;
void *frame;
/* 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 && cif->flags == FFI_TYPE_STRUCT)
if (rvalue == NULL && flags == ALPHA_RET_IN_MEM)
rvalue = alloca(cif->rtype->size);
/* Allocate the space for the arguments, plus 4 words of temp
space for ffi_call_osf. */
argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
frame += cif->bytes;
if (cif->flags == FFI_TYPE_STRUCT)
*(void **) argp++ = rvalue;
argn = 0;
if (flags == ALPHA_RET_IN_MEM)
argp[argn++] = (unsigned long)rvalue;
i = 0;
avn = cif->nargs;
arg_types = cif->arg_types;
while (i < avn)
for (i = 0, avn = cif->nargs; i < avn; i++)
{
size_t size = (*arg_types)->size;
ffi_type *ty = arg_types[i];
void *valp = avalue[i];
int type = ty->type;
size_t size;
switch ((*arg_types)->type)
switch (type)
{
case FFI_TYPE_INT:
case FFI_TYPE_SINT8:
*(SINT64 *) argp = *(SINT8 *)(* avalue);
break;
case FFI_TYPE_UINT8:
*(SINT64 *) argp = *(UINT8 *)(* avalue);
break;
case FFI_TYPE_SINT16:
*(SINT64 *) argp = *(SINT16 *)(* avalue);
break;
case FFI_TYPE_UINT16:
*(SINT64 *) argp = *(UINT16 *)(* avalue);
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
/* Note that unsigned 32-bit quantities are sign extended. */
*(SINT64 *) argp = *(SINT32 *)(* avalue);
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
*(UINT64 *) argp = *(UINT64 *)(* avalue);
break;
case FFI_TYPE_FLOAT:
if (argp - stack < 6)
{
/* Note the conversion -- all the fp regs are loaded as
doubles. The in-register format is the same. */
*(double *) argp = *(float *)(* avalue);
}
else
*(float *) argp = *(float *)(* avalue);
break;
case FFI_TYPE_DOUBLE:
*(double *) argp = *(double *)(* avalue);
argp[argn] = extend_basic_type(valp, type, argn);
argn++;
break;
case FFI_TYPE_LONGDOUBLE:
/* 128-bit long double is passed by reference. */
*(long double **) argp = (long double *)(* avalue);
size = sizeof (long double *);
by_reference:
/* Note that 128-bit long double is passed by reference. */
argp[argn++] = (unsigned long)valp;
break;
case FFI_TYPE_VOID:
case FFI_TYPE_STRUCT:
memcpy(argp, *avalue, (*arg_types)->size);
size = ty->size;
memcpy(argp + argn, valp, size);
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
break;
case FFI_TYPE_COMPLEX:
type = ty->elements[0]->type;
if (type == FFI_TYPE_LONGDOUBLE)
goto by_reference;
/* Most complex types passed as two separate arguments. */
size = ty->elements[0]->size;
argp[argn] = extend_basic_type(valp, type, argn);
argp[argn + 1] = extend_basic_type(valp + size, type, argn + 1);
argn += 2;
break;
default:
FFI_ASSERT(0);
abort();
}
argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
i++, arg_types++, avalue++;
}
ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
ffi_call_osf(argp, frame, flags, rvalue, fn, closure);
}
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_call_int(cif, fn, rvalue, avalue, NULL);
}
void
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int(cif, fn, rvalue, avalue, closure);
}
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
@ -203,39 +356,56 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK;
}
ffi_status
ffi_prep_go_closure (ffi_go_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*))
{
if (cif->abi != FFI_OSF)
return FFI_BAD_ABI;
closure->tramp = (void *)ffi_go_closure_osf;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}
long FFI_HIDDEN
ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
ffi_closure_osf_inner (ffi_cif *cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data,
void *rvalue, unsigned long *argp)
{
ffi_cif *cif;
void **avalue;
ffi_type **arg_types;
long i, avn, argn;
long i, avn, argn, flags;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
flags = cif->flags;
argn = 0;
/* Copy the caller's structure return address to that the closure
returns the data directly to the caller. */
if (cif->flags == FFI_TYPE_STRUCT)
if (flags == ALPHA_RET_IN_MEM)
{
rvalue = (void *) argp[0];
argn = 1;
}
i = 0;
avn = cif->nargs;
arg_types = cif->arg_types;
/* Grab the addresses of the arguments from the stack frame. */
while (i < avn)
{
size_t size = arg_types[i]->size;
switch (arg_types[i]->type)
/* Grab the addresses of the arguments from the stack frame. */
for (i = 0, avn = cif->nargs; i < avn; i++)
{
ffi_type *ty = arg_types[i];
int type = ty->type;
void *valp = &argp[argn];
size_t size;
switch (type)
{
case FFI_TYPE_INT:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT16:
@ -245,43 +415,107 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
argn += 1;
break;
case FFI_TYPE_VOID:
case FFI_TYPE_STRUCT:
avalue[i] = &argp[argn];
size = ty->size;
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
break;
case FFI_TYPE_FLOAT:
/* Floats coming from registers need conversion from double
back to float format. */
if (argn < 6)
{
/* Floats coming from registers need conversion from double
back to float format. */
*(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
avalue[i] = &argp[argn - 6];
valp = &argp[argn - 6];
sts(valp, argp[argn - 6]);
}
else
avalue[i] = &argp[argn];
argn += 1;
break;
case FFI_TYPE_DOUBLE:
avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
if (argn < 6)
valp = &argp[argn - 6];
argn += 1;
break;
case FFI_TYPE_LONGDOUBLE:
by_reference:
/* 128-bit long double is passed by reference. */
avalue[i] = (long double *) argp[argn];
size = sizeof (long double *);
valp = (void *)argp[argn];
argn += 1;
break;
case FFI_TYPE_COMPLEX:
type = ty->elements[0]->type;
switch (type)
{
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
/* Passed as separate arguments, but they wind up sequential. */
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
/* Passed as separate arguments. Disjoint, but there's room
enough in one slot to hold the pair. */
size = ty->elements[0]->size;
memcpy(valp + size, valp + 8, size);
break;
case FFI_TYPE_FLOAT:
/* Passed as separate arguments. Disjoint, and each piece
may need conversion back to float. */
if (argn < 6)
{
valp = &argp[argn - 6];
sts(valp, argp[argn - 6]);
}
if (argn + 1 < 6)
sts(valp + 4, argp[argn + 1 - 6]);
else
*(UINT32 *)(valp + 4) = argp[argn + 1];
break;
case FFI_TYPE_DOUBLE:
/* Passed as separate arguments. Only disjoint if one part
is in fp regs and the other is on the stack. */
if (argn < 5)
valp = &argp[argn - 6];
else if (argn == 5)
{
valp = alloca(16);
((UINT64 *)valp)[0] = argp[5 - 6];
((UINT64 *)valp)[1] = argp[6];
}
break;
case FFI_TYPE_LONGDOUBLE:
goto by_reference;
default:
abort();
}
argn += 2;
break;
default:
FFI_ASSERT (0);
abort ();
}
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
i++;
avalue[i] = valp;
}
/* Invoke the closure. */
closure->fun (cif, rvalue, avalue, closure->user_data);
fun (cif, rvalue, avalue, user_data);
/* Tell ffi_closure_osf how to perform return type promotions. */
return cif->rtype->type;
return (flags >> ALPHA_LD_SHIFT) & 0xff;
}

View file

@ -44,9 +44,13 @@ typedef enum ffi_abi {
} ffi_abi;
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0

View file

@ -0,0 +1,23 @@
#define ALPHA_ST_VOID 0
#define ALPHA_ST_INT 1
#define ALPHA_ST_FLOAT 2
#define ALPHA_ST_DOUBLE 3
#define ALPHA_ST_CPLXF 4
#define ALPHA_ST_CPLXD 5
#define ALPHA_LD_VOID 0
#define ALPHA_LD_INT64 1
#define ALPHA_LD_INT32 2
#define ALPHA_LD_UINT16 3
#define ALPHA_LD_SINT16 4
#define ALPHA_LD_UINT8 5
#define ALPHA_LD_SINT8 6
#define ALPHA_LD_FLOAT 7
#define ALPHA_LD_DOUBLE 8
#define ALPHA_LD_CPLXF 9
#define ALPHA_LD_CPLXD 10
#define ALPHA_ST_SHIFT 0
#define ALPHA_LD_SHIFT 8
#define ALPHA_RET_IN_MEM 0x10000
#define ALPHA_FLAGS(S, L) (((L) << ALPHA_LD_SHIFT) | (S))

View file

@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
Alpha/OSF Foreign Function Interface
osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
Alpha/OSF Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -24,40 +24,49 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include "internal.h"
.arch ev6
.text
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
void *raddr, void (*fnaddr)(void));
/* Aid in building a direct addressed jump table, 4 insns per entry. */
.macro E index
.align 4
.org 99b + \index * 16
.endm
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
/* ffi_call_osf (void *stack, void *frame, unsigned flags,
void *raddr, void (*fnaddr)(void), void *closure)
Bit o trickiness here -- FRAME is the base of the stack frame
for this function. This has been allocated by ffi_call. We also
deallocate some of the stack that has been alloca'd. */
.align 3
.align 4
.globl ffi_call_osf
.ent ffi_call_osf
FFI_HIDDEN(ffi_call_osf)
ffi_call_osf:
.frame $15, 32, $26, 0
.mask 0x4008000, -32
$LFB1:
addq $16,$17,$1
cfi_startproc
cfi_def_cfa($17, 32)
mov $16, $30
stq $26, 0($1)
stq $15, 8($1)
stq $18, 16($1)
mov $1, $15
$LCFI1:
stq $26, 0($17)
stq $15, 8($17)
mov $17, $15
.prologue 0
cfi_def_cfa_register($15)
cfi_rel_offset($26, 0)
cfi_rel_offset($15, 8)
stq $19, 24($1)
mov $20, $27
stq $18, 16($17) # save flags into frame
stq $19, 24($17) # save rvalue into frame
mov $20, $27 # fn into place for call
mov $21, $1 # closure into static chain
# Load up all of the (potential) argument registers.
ldq $16, 0($30)
@ -77,310 +86,196 @@ $LCFI1:
lda $30, 48($30)
jsr $26, ($27), 0
ldgp $29, 0($26)
# If the return value pointer is NULL, assume no return value.
ldq $19, 24($15)
ldq $18, 16($15)
0:
ldah $29, 0($26) !gpdisp!1
ldq $2, 24($15) # reload rvalue
lda $29, 0($29) !gpdisp!1
ldq $3, 16($15) # reload flags
lda $1, 99f-0b($26)
ldq $26, 0($15)
$LCFI2:
beq $19, $noretval
# Store the return value out in the proper type.
cmpeq $18, FFI_TYPE_INT, $1
bne $1, $retint
cmpeq $18, FFI_TYPE_FLOAT, $2
bne $2, $retfloat
cmpeq $18, FFI_TYPE_DOUBLE, $3
bne $3, $retdouble
.align 3
$noretval:
ldq $15, 8($15)
ret
cfi_restore($26)
cfi_restore($15)
cfi_def_cfa($sp, 0)
cmoveq $2, ALPHA_ST_VOID, $3 # mash null rvalue to void
addq $3, $3, $3
s8addq $3, $1, $1 # 99f + stcode * 16
jmp $31, ($1), $st_int
.align 4
$retint:
stq $0, 0($19)
nop
ldq $15, 8($15)
99:
E ALPHA_ST_VOID
ret
E ALPHA_ST_INT
$st_int:
stq $0, 0($2)
ret
E ALPHA_ST_FLOAT
sts $f0, 0($2)
ret
E ALPHA_ST_DOUBLE
stt $f0, 0($2)
ret
E ALPHA_ST_CPLXF
sts $f0, 0($2)
sts $f1, 4($2)
ret
E ALPHA_ST_CPLXD
stt $f0, 0($2)
stt $f1, 8($2)
ret
.align 4
$retfloat:
sts $f0, 0($19)
nop
ldq $15, 8($15)
ret
.align 4
$retdouble:
stt $f0, 0($19)
nop
ldq $15, 8($15)
ret
$LFE1:
cfi_endproc
.end ffi_call_osf
/* ffi_closure_osf(...)
Receives the closure argument in $1. */
.align 3
#define CLOSURE_FS (16*8)
.align 4
.globl ffi_go_closure_osf
.ent ffi_go_closure_osf
FFI_HIDDEN(ffi_go_closure_osf)
ffi_go_closure_osf:
cfi_startproc
ldgp $29, 0($27)
subq $30, CLOSURE_FS, $30
cfi_adjust_cfa_offset(CLOSURE_FS)
stq $26, 0($30)
.prologue 1
cfi_rel_offset($26, 0)
stq $16, 10*8($30)
stq $17, 11*8($30)
stq $18, 12*8($30)
ldq $16, 8($1) # load cif
ldq $17, 16($1) # load fun
mov $1, $18 # closure is user_data
br $do_closure
cfi_endproc
.end ffi_go_closure_osf
.align 4
.globl ffi_closure_osf
.ent ffi_closure_osf
FFI_HIDDEN(ffi_closure_osf)
ffi_closure_osf:
.frame $30, 16*8, $26, 0
.mask 0x4000000, -16*8
$LFB2:
cfi_startproc
ldgp $29, 0($27)
subq $30, 16*8, $30
$LCFI5:
subq $30, CLOSURE_FS, $30
cfi_adjust_cfa_offset(CLOSURE_FS)
stq $26, 0($30)
$LCFI6:
.prologue 1
cfi_rel_offset($26, 0)
# Store all of the potential argument registers in va_list format.
stq $16, 10*8($30)
stq $17, 11*8($30)
stq $18, 12*8($30)
ldq $16, 24($1) # load cif
ldq $17, 32($1) # load fun
ldq $18, 40($1) # load user_data
$do_closure:
stq $19, 13*8($30)
stq $20, 14*8($30)
stq $21, 15*8($30)
stt $f16, 4*8($30)
stt $f17, 5*8($30)
stt $f18, 6*8($30)
stt $f19, 7*8($30)
stt $f20, 8*8($30)
stt $f21, 9*8($30)
stq $16, 10*8($30)
stq $17, 11*8($30)
stq $18, 12*8($30)
stq $19, 13*8($30)
stq $20, 14*8($30)
stq $21, 15*8($30)
# Call ffi_closure_osf_inner to do the bulk of the work.
mov $1, $16
lda $17, 2*8($30)
lda $18, 10*8($30)
lda $19, 2*8($30)
lda $20, 10*8($30)
jsr $26, ffi_closure_osf_inner
ldgp $29, 0($26)
0:
ldah $29, 0($26) !gpdisp!2
lda $2, 99f-0b($26)
s4addq $0, 0, $1 # ldcode * 4
ldq $0, 16($30) # preload return value
s4addq $1, $2, $1 # 99f + ldcode * 16
lda $29, 0($29) !gpdisp!2
ldq $26, 0($30)
# Load up the return value in the proper type.
lda $1, $load_table
s4addq $0, $1, $1
ldl $1, 0($1)
addq $1, $29, $1
cfi_restore($26)
jmp $31, ($1), $load_32
.align 4
$load_none:
addq $30, 16*8, $30
.macro epilogue
addq $30, CLOSURE_FS, $30
cfi_adjust_cfa_offset(-CLOSURE_FS)
ret
.align 4
cfi_adjust_cfa_offset(CLOSURE_FS)
.endm
.align 4
$load_float:
lds $f0, 16($30)
nop
addq $30, 16*8, $30
ret
99:
E ALPHA_LD_VOID
epilogue
.align 4
$load_double:
ldt $f0, 16($30)
nop
addq $30, 16*8, $30
ret
E ALPHA_LD_INT64
epilogue
.align 4
$load_u8:
#ifdef __alpha_bwx__
ldbu $0, 16($30)
nop
#else
ldq $0, 16($30)
and $0, 255, $0
#endif
addq $30, 16*8, $30
ret
E ALPHA_LD_INT32
$load_32:
sextl $0, $0
epilogue
.align 4
$load_s8:
#ifdef __alpha_bwx__
ldbu $0, 16($30)
sextb $0, $0
#else
ldq $0, 16($30)
sll $0, 56, $0
sra $0, 56, $0
#endif
addq $30, 16*8, $30
ret
.align 4
$load_u16:
#ifdef __alpha_bwx__
ldwu $0, 16($30)
nop
#else
ldq $0, 16($30)
E ALPHA_LD_UINT16
zapnot $0, 3, $0
#endif
addq $30, 16*8, $30
ret
epilogue
.align 4
$load_s16:
E ALPHA_LD_SINT16
#ifdef __alpha_bwx__
ldwu $0, 16($30)
sextw $0, $0
#else
ldq $0, 16($30)
sll $0, 48, $0
sra $0, 48, $0
#endif
addq $30, 16*8, $30
ret
epilogue
.align 4
$load_32:
ldl $0, 16($30)
nop
addq $30, 16*8, $30
ret
E ALPHA_LD_UINT8
and $0, 0xff, $0
epilogue
.align 4
$load_64:
ldq $0, 16($30)
nop
addq $30, 16*8, $30
ret
$LFE2:
.end ffi_closure_osf
#ifdef __ELF__
.section .rodata
E ALPHA_LD_SINT8
#ifdef __alpha_bwx__
sextb $0, $0
#else
.rdata
sll $0, 56, $0
sra $0, 56, $0
#endif
$load_table:
.gprel32 $load_none # FFI_TYPE_VOID
.gprel32 $load_32 # FFI_TYPE_INT
.gprel32 $load_float # FFI_TYPE_FLOAT
.gprel32 $load_double # FFI_TYPE_DOUBLE
.gprel32 $load_none # FFI_TYPE_LONGDOUBLE
.gprel32 $load_u8 # FFI_TYPE_UINT8
.gprel32 $load_s8 # FFI_TYPE_SINT8
.gprel32 $load_u16 # FFI_TYPE_UINT16
.gprel32 $load_s16 # FFI_TYPE_SINT16
.gprel32 $load_32 # FFI_TYPE_UINT32
.gprel32 $load_32 # FFI_TYPE_SINT32
.gprel32 $load_64 # FFI_TYPE_UINT64
.gprel32 $load_64 # FFI_TYPE_SINT64
.gprel32 $load_none # FFI_TYPE_STRUCT
.gprel32 $load_64 # FFI_TYPE_POINTER
epilogue
/* Assert that the table above is in sync with ffi.h. */
E ALPHA_LD_FLOAT
lds $f0, 16($sp)
epilogue
#if FFI_TYPE_FLOAT != 2 \
|| FFI_TYPE_DOUBLE != 3 \
|| FFI_TYPE_UINT8 != 5 \
|| FFI_TYPE_SINT8 != 6 \
|| FFI_TYPE_UINT16 != 7 \
|| FFI_TYPE_SINT16 != 8 \
|| FFI_TYPE_UINT32 != 9 \
|| FFI_TYPE_SINT32 != 10 \
|| FFI_TYPE_UINT64 != 11 \
|| FFI_TYPE_SINT64 != 12 \
|| FFI_TYPE_STRUCT != 13 \
|| FFI_TYPE_POINTER != 14 \
|| FFI_TYPE_LAST != 14
#error "osf.S out of sync with ffi.h"
#endif
E ALPHA_LD_DOUBLE
ldt $f0, 16($sp)
epilogue
#ifdef __ELF__
# define UA_SI .4byte
# define FDE_ENCODING 0x1b /* pcrel sdata4 */
# define FDE_ENCODE(X) .4byte X-.
# define FDE_ARANGE(X) .4byte X
#elif defined __osf__
# define UA_SI .align 0; .long
# define FDE_ENCODING 0x50 /* aligned absolute */
# define FDE_ENCODE(X) .align 3; .quad X
# define FDE_ARANGE(X) .align 0; .quad X
#endif
E ALPHA_LD_CPLXF
lds $f0, 16($sp)
lds $f1, 20($sp)
epilogue
#ifdef __ELF__
.section .eh_frame,EH_FRAME_FLAGS,@progbits
#elif defined __osf__
.data
.align 3
.globl _GLOBAL__F_ffi_call_osf
_GLOBAL__F_ffi_call_osf:
#endif
__FRAME_BEGIN__:
UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry
$LSCIE1:
UA_SI 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
.byte 26 # CIE RA Column
.byte 0x1 # uleb128 0x1; Augmentation size
.byte FDE_ENCODING # FDE Encoding
.byte 0xc # DW_CFA_def_cfa
.byte 30 # uleb128 column 30
.byte 0 # uleb128 offset 0
.align 3
$LECIE1:
$LSFDE1:
UA_SI $LEFDE1-$LASFDE1 # FDE Length
$LASFDE1:
UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
FDE_ENCODE($LFB1) # FDE initial location
FDE_ARANGE($LFE1-$LFB1) # FDE address range
.byte 0x0 # uleb128 0x0; Augmentation size
E ALPHA_LD_CPLXD
ldt $f0, 16($sp)
ldt $f1, 24($sp)
epilogue
.byte 0x4 # DW_CFA_advance_loc4
UA_SI $LCFI1-$LFB1
.byte 0x9a # DW_CFA_offset, column 26
.byte 4 # uleb128 4*-8
.byte 0x8f # DW_CFA_offset, column 15
.byte 0x3 # uleb128 3*-8
.byte 0xc # DW_CFA_def_cfa
.byte 15 # uleb128 column 15
.byte 32 # uleb128 offset 32
.byte 0x4 # DW_CFA_advance_loc4
UA_SI $LCFI2-$LCFI1
.byte 0xda # DW_CFA_restore, column 26
.align 3
$LEFDE1:
$LSFDE3:
UA_SI $LEFDE3-$LASFDE3 # FDE Length
$LASFDE3:
UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
FDE_ENCODE($LFB2) # FDE initial location
FDE_ARANGE($LFE2-$LFB2) # FDE address range
.byte 0x0 # uleb128 0x0; Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
UA_SI $LCFI5-$LFB2
.byte 0xe # DW_CFA_def_cfa_offset
.byte 0x80,0x1 # uleb128 128
.byte 0x4 # DW_CFA_advance_loc4
UA_SI $LCFI6-$LCFI5
.byte 0x9a # DW_CFA_offset, column 26
.byte 16 # uleb128 offset 16*-8
.align 3
$LEFDE3:
#if defined __osf__
.align 0
.long 0 # End of Table
#endif
cfi_endproc
.end ffi_closure_osf
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits

135
libffi/src/arc/arcompact.S Normal file
View file

@ -0,0 +1,135 @@
/* -----------------------------------------------------------------------
arcompact.S - Copyright (c) 2013 Synposys, Inc. (www.synopsys.com)
ARCompact 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 RENESAS TECHNOLOGY 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.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#else
#define CNAME(x) x
#define ENTRY(x) .globl CNAME(x)` .type CNAME(x),%function` CNAME(x):
#endif
.text
/* R0: ffi_prep_args */
/* R1: &ecif */
/* R2: cif->bytes */
/* R3: fig->flags */
/* R4: ecif.rvalue */
/* R5: fn */
ENTRY(ffi_call_ARCompact)
/* Save registers. */
st.a fp, [sp, -4] /* fp + 20, fp */
push_s blink /* fp + 16, blink */
st.a r4, [sp, -4] /* fp + 12, ecif.rvalue */
push_s r3 /* fp + 8, fig->flags */
st.a r5, [sp, -4] /* fp + 4, fn */
push_s r2 /* fp + 0, cif->bytes */
mov fp, sp
/* Make room for all of the new args. */
sub sp, sp, r2
/* Place all of the ffi_prep_args in position. */
/* ffi_prep_args(char *stack, extended_cif *ecif) */
/* R1 already set. */
/* And call. */
jl_s.d [r0]
mov_s r0, sp
ld.ab r12, [fp, 4] /* cif->bytes */
ld.ab r11, [fp, 4] /* fn */
/* Move first 8 parameters in registers... */
ld_s r0, [sp]
ld_s r1, [sp, 4]
ld_s r2, [sp, 8]
ld_s r3, [sp, 12]
ld r4, [sp, 16]
ld r5, [sp, 20]
ld r6, [sp, 24]
ld r7, [sp, 28]
/* ...and adjust the stack. */
min r12, r12, 32
/* Call the function. */
jl.d [r11]
add sp, sp, r12
mov sp, fp
pop_s r3 /* fig->flags, return type */
pop_s r2 /* ecif.rvalue, pointer for return value */
/* If the return value pointer is NULL, assume no return value. */
breq.d r2, 0, epilogue
pop_s blink
/* Return INT. */
brne r3, FFI_TYPE_INT, return_double
b.d epilogue
st_s r0, [r2]
return_double:
brne r3, FFI_TYPE_DOUBLE, epilogue
st_s r0, [r2]
st_s r1, [r2,4]
epilogue:
j_s.d [blink]
ld.ab fp, [sp, 4]
ENTRY(ffi_closure_ARCompact)
st.a r0, [sp, -32]
st_s r1, [sp, 4]
st_s r2, [sp, 8]
st_s r3, [sp, 12]
st r4, [sp, 16]
st r5, [sp, 20]
st r6, [sp, 24]
st r7, [sp, 28]
/* pointer to arguments */
mov_s r2, sp
/* return value goes here */
sub sp, sp, 8
mov_s r1, sp
push_s blink
bl.d ffi_closure_inner_ARCompact
mov_s r0, r8 /* codeloc, set by trampoline */
pop_s blink
/* set return value to r1:r0 */
pop_s r0
pop_s r1
j_s.d [blink]
add_s sp, sp, 32

268
libffi/src/arc/ffi.c Normal file
View file

@ -0,0 +1,268 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
ARC 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 RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/cachectl.h>
/* for little endian ARC, the code is in fact stored as mixed endian for
performance reasons */
#if __BIG_ENDIAN__
#define CODE_ENDIAN(x) (x)
#else
#define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
#endif
/* ffi_prep_args is called by the assembly routine once stack
space has been allocated for the function's arguments. */
void
ffi_prep_args (char *stack, extended_cif * ecif)
{
unsigned int i;
int tmp;
void **p_argv;
char *argp;
ffi_type **p_arg;
tmp = 0;
argp = stack;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
{
*(void **) argp = ecif->rvalue;
argp += 4;
}
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0); i--, p_arg++)
{
size_t z;
int alignment;
/* align alignment to 4 */
alignment = (((*p_arg)->alignment - 1) | 3) + 1;
/* Align if necessary. */
if ((alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, alignment);
z = (*p_arg)->size;
if (z < sizeof (int))
{
z = sizeof (int);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
break;
case FFI_TYPE_STRUCT:
memcpy (argp, *p_argv, (*p_arg)->size);
break;
default:
FFI_ASSERT (0);
}
}
else if (z == sizeof (int))
{
*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
}
else
{
if ((*p_arg)->type == FFI_TYPE_STRUCT)
{
memcpy (argp, *p_argv, z);
}
else
{
/* Double or long long 64bit. */
memcpy (argp, *p_argv, z);
}
}
p_argv++;
argp += z;
}
return;
}
/* Perform machine dependent cif processing. */
ffi_status
ffi_prep_cif_machdep (ffi_cif * cif)
{
/* Set the return type flag. */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
cif->flags = (unsigned) cif->rtype->type;
break;
case FFI_TYPE_STRUCT:
cif->flags = (unsigned) cif->rtype->type;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_DOUBLE:
cif->flags = FFI_TYPE_DOUBLE;
break;
case FFI_TYPE_FLOAT:
default:
cif->flags = FFI_TYPE_INT;
break;
}
return FFI_OK;
}
extern void ffi_call_ARCompact (void (*)(char *, extended_cif *),
extended_cif *, unsigned, unsigned,
unsigned *, void (*fn) (void));
void
ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
{
extended_cif ecif;
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) && (cif->rtype->type == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca (cif->rtype->size);
}
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_ARCOMPACT:
ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
default:
FFI_ASSERT (0);
break;
}
}
int
ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
ffi_arg * args)
{
void **arg_area, **p_argv;
ffi_cif *cif = closure->cif;
char *argp = (char *) args;
ffi_type **p_argt;
int i;
arg_area = (void **) alloca (cif->nargs * sizeof (void *));
/* handle hidden argument */
if (cif->flags == FFI_TYPE_STRUCT)
{
rvalue = *(void **) argp;
argp += 4;
}
p_argv = arg_area;
for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
i++, p_argt++, p_argv++)
{
size_t z;
int alignment;
/* align alignment to 4 */
alignment = (((*p_argt)->alignment - 1) | 3) + 1;
/* Align if necessary. */
if ((alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, alignment);
z = (*p_argt)->size;
*p_argv = (void *) argp;
argp += z;
}
(closure->fun) (cif, rvalue, arg_area, closure->user_data);
return cif->flags;
}
extern void ffi_closure_ARCompact (void);
ffi_status
ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data, void *codeloc)
{
uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
switch (cif->abi)
{
case FFI_ARCOMPACT:
FFI_ASSERT (tramp == codeloc);
tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */
tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */
tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
break;
default:
return FFI_BAD_ABI;
}
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
return FFI_OK;
}

View file

@ -0,0 +1,53 @@
/* -----------------------------------------------------------------------
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
Target configuration macros for ARC.
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 RENESAS TECHNOLOGY 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.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi
{
FFI_FIRST_ABI = 0,
FFI_ARCOMPACT,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_ARCOMPACT
} ffi_abi;
#endif
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_NATIVE_RAW_API 0
#endif

File diff suppressed because it is too large Load diff

View file

@ -53,19 +53,17 @@ typedef enum ffi_abi {
#define FFI_EXTRA_CIF_FIELDS \
int vfp_used; \
short vfp_reg_free, vfp_nargs; \
unsigned short vfp_reg_free, vfp_nargs; \
signed char vfp_args[16] \
/* Internally used. */
#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 20
#define FFI_GO_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_NATIVE_RAW_API 0
#endif

View file

@ -1,118 +0,0 @@
#!/bin/sh
# -----------------------------------------------------------------------
# gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
#
# ARM Trampoline Page Generator
#
# 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 THE AUTHORS OR COPYRIGHT
# HOLDERS 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.
# -----------------------------------------------------------------------
PROGNAME=$0
# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
# the entire arm trampoline implementation must be updated to match, too.
# Size of an individual trampoline, in bytes
TRAMPOLINE_SIZE=12
# Page size, in bytes
PAGE_SIZE=4096
# Compute the size of the reachable config page; The first 16 bytes of the config page
# are unreachable due to our maximum pc-relative ldr offset.
PAGE_AVAIL=`expr $PAGE_SIZE - 16`
# Compute the number of of available trampolines.
TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
header () {
echo "# GENERATED CODE - DO NOT EDIT"
echo "# This file was generated by $PROGNAME"
echo ""
# Write out the license header
cat << EOF
# Copyright (c) 2010, Plausible Labs Cooperative, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# ``Software''), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS 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.
# -----------------------------------------------------------------------
EOF
# Write out the trampoline table, aligned to the page boundary
echo ".text"
echo ".align 12"
echo ".globl _ffi_closure_trampoline_table_page"
echo "_ffi_closure_trampoline_table_page:"
}
# WARNING - Don't modify the trampoline code size without also updating the relevent libffi code
trampoline () {
cat << END
// trampoline
// Save to stack
stmfd sp!, {r0-r3}
// Load the context argument from the config page.
// This places the first usable config value at _ffi_closure_trampoline_table-4080
// This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
ldr r0, [pc, #-4092]
// Load the jump address from the config page.
ldr pc, [pc, #-4092]
END
}
main () {
# Write out the header
header
# Write out the trampolines
local i=0
while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
trampoline
local i=`expr $i + 1`
done
}
main

View file

@ -0,0 +1,7 @@
#define ARM_TYPE_VFP_S 0
#define ARM_TYPE_VFP_D 1
#define ARM_TYPE_VFP_N 2
#define ARM_TYPE_INT64 3
#define ARM_TYPE_INT 4
#define ARM_TYPE_VOID 5
#define ARM_TYPE_STRUCT 6

View file

@ -1,8 +1,8 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
ARM Foreign Function Interface
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -28,477 +28,307 @@
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#else
#ifdef __USER_LABEL_PREFIX__
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
#include <ffi_cfi.h>
#include "internal.h"
/* Use the right prefix for global labels. */
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#else
#define CNAME(x) x
#endif
#ifdef __APPLE__
#define ENTRY(x) .globl _##x; _##x:
#else
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
#endif /* __APPLE__ */
#endif
#ifdef __ELF__
#define LSYM(x) .x
#else
#define LSYM(x) x
#endif
/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
Function Call Guide */
#ifdef __APPLE__
#define __SOFTFP__
#endif
/* We need a better way of testing for this, but for now, this is all
we can do. */
@ This selects the minimum architecture level required.
#define __ARM_ARCH__ 3
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
# undef __ARM_ARCH__
# define __ARM_ARCH__ 4
#endif
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|| defined(__ARM_ARCH_5TEJ__)
# undef __ARM_ARCH__
# define __ARM_ARCH__ 5
#endif
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */
#ifndef __ARM_ARCH
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__)
# define __ARM_ARCH 7
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|| defined(__ARM_ARCH_6M__)
# undef __ARM_ARCH__
# define __ARM_ARCH__ 6
#endif
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__)
# undef __ARM_ARCH__
# define __ARM_ARCH__ 7
#endif
#if __ARM_ARCH__ >= 5
# define call_reg(x) blx x
#elif defined (__ARM_ARCH_4T__)
# define call_reg(x) mov lr, pc ; bx x
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
# define __INTERWORKING__
# define __ARM_ARCH 6
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|| defined(__ARM_ARCH_5TEJ__)
# define __ARM_ARCH 5
# else
# define __ARM_ARCH 4
# endif
#else
# define call_reg(x) mov lr, pc ; mov pc, x
#endif
/* Conditionally compile unwinder directives. */
.macro UNWIND text:vararg
#ifdef __ARM_EABI__
#define UNWIND
#else
#define UNWIND @
\text
#endif
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
.macro ARM_FUNC_START name
.text
.align 0
.thumb
.thumb_func
#ifdef __APPLE__
ENTRY($0)
#else
ENTRY(\name)
#endif
bx pc
nop
.arm
UNWIND .fnstart
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
directly from other local arm routines. */
#ifdef __APPLE__
_L__$0:
#else
_L__\name:
#endif
.endm
#else
.macro ARM_FUNC_START name
.text
.align 0
.arm
#ifdef __APPLE__
ENTRY($0)
#else
ENTRY(\name)
#endif
UNWIND .fnstart
.endm
#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
.cfi_sections .debug_frame
#endif
.macro RETLDM regs=, cond=, dirn=ia
#if defined (__INTERWORKING__)
.ifc "\regs",""
ldr\cond lr, [sp], #4
.else
ldm\cond\dirn sp!, {\regs, lr}
#define CONCAT(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
#ifdef __USER_LABEL_PREFIX__
# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X)
#else
# define CNAME(X) X
#endif
#ifdef __ELF__
# define SIZE(X) .size CNAME(X), . - CNAME(X)
# define TYPE(X, Y) .type CNAME(X), Y
#else
# define SIZE(X)
# define TYPE(X, Y)
#endif
#define ARM_FUNC_START(name, gl) \
.align 3; \
.ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \
TYPE(name, %function); \
CNAME(name):
#define ARM_FUNC_END(name) \
SIZE(name)
/* Aid in defining a jump table with 8 bytes between entries. */
.macro E index
.if . - 0b - 8*\index
.error "type table out of sync"
.endif
bx\cond lr
#else
.ifc "\regs",""
ldr\cond pc, [sp], #4
.else
ldm\cond\dirn sp!, {\regs, pc}
.endif
#endif
.endm
@ r0: ffi_prep_args
@ r1: &ecif
@ r2: cif->bytes
@ r3: fig->flags
@ sp+0: ecif.rvalue
.text
.syntax unified
.arm
@ This assumes we are using gas.
ARM_FUNC_START ffi_call_SYSV
@ Save registers
stmfd sp!, {r0-r3, fp, lr}
UNWIND .save {r0-r3, fp, lr}
mov fp, sp
/* We require interworking on LDM, which implies ARMv5T,
which implies the existance of BLX. */
.arch armv5t
UNWIND .setfp fp, sp
/* Note that we use STC and LDC to encode VFP instructions,
so that we do not need ".fpu vfp", nor get that added to
the object file attributes. These will not be executed
unless the FFI_VFP abi is used. */
@ Make room for all of the new args.
sub sp, fp, r2
@ r0: stack
@ r1: frame
@ r2: fn
@ r3: vfp_used
@ Place all of the ffi_prep_args in position
mov r0, sp
@ r1 already set
ARM_FUNC_START(ffi_call_VFP, 1)
UNWIND .fnstart
cfi_startproc
@ Call ffi_prep_args(stack, &ecif)
bl CNAME(ffi_prep_args)
cmp r3, #3 @ load only d0 if possible
ldcle p11, cr0, [r0] @ vldrle d0, [sp]
ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
add r0, r0, #64 @ discard the vfp register args
/* FALLTHRU */
ARM_FUNC_END(ffi_call_VFP)
@ move first 4 parameters in registers
ldmia sp, {r0-r3}
ARM_FUNC_START(ffi_call_SYSV, 1)
stm r1, {fp, lr}
mov fp, r1
@ and adjust stack
sub lr, fp, sp @ cif->bytes == fp - sp
ldr ip, [fp] @ load fn() in advance
cmp lr, #16
movhs lr, #16
add sp, sp, lr
@ This is a bit of a lie wrt the origin of the unwind info, but
@ now we've got the usual frame pointer and two saved registers.
UNWIND .save {fp,lr}
UNWIND .setfp fp, sp
cfi_def_cfa(fp, 8)
cfi_rel_offset(fp, 0)
cfi_rel_offset(lr, 4)
@ call (fn) (...)
call_reg(ip)
@ Remove the space we pushed for the args
mov sp, fp
mov sp, r0 @ install the stack pointer
mov lr, r2 @ move the fn pointer out of the way
ldr ip, [fp, #16] @ install the static chain
ldmia sp!, {r0-r3} @ move first 4 parameters in registers.
blx lr @ call fn
@ Load r2 with the pointer to storage for the return value
ldr r2, [sp, #24]
@ Load r3 with the return type code
ldr r2, [fp, #8]
ldr r3, [fp, #12]
@ Load r3 with the return type code
ldr r3, [sp, #12]
@ Deallocate the stack with the arguments.
mov sp, fp
cfi_def_cfa_register(sp)
@ If the return value pointer is NULL, assume no return value.
cmp r2, #0
beq LSYM(Lepilogue)
@ Store values stored in registers.
.align 3
add pc, pc, r3, lsl #3
nop
0:
E ARM_TYPE_VFP_S
stc p10, cr0, [r2] @ vstr s0, [r2]
pop {fp,pc}
E ARM_TYPE_VFP_D
stc p11, cr0, [r2] @ vstr d0, [r2]
pop {fp,pc}
E ARM_TYPE_VFP_N
stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3}
pop {fp,pc}
E ARM_TYPE_INT64
str r1, [r2, #4]
nop
E ARM_TYPE_INT
str r0, [r2]
pop {fp,pc}
E ARM_TYPE_VOID
pop {fp,pc}
nop
E ARM_TYPE_STRUCT
pop {fp,pc}
@ return INT
cmp r3, #FFI_TYPE_INT
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
cmpne r3, #FFI_TYPE_FLOAT
#endif
streq r0, [r2]
beq LSYM(Lepilogue)
@ return INT64
cmp r3, #FFI_TYPE_SINT64
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
cmpne r3, #FFI_TYPE_DOUBLE
#endif
stmeqia r2, {r0, r1}
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
beq LSYM(Lepilogue)
@ return FLOAT
cmp r3, #FFI_TYPE_FLOAT
stfeqs f0, [r2]
beq LSYM(Lepilogue)
@ return DOUBLE or LONGDOUBLE
cmp r3, #FFI_TYPE_DOUBLE
stfeqd f0, [r2]
#endif
LSYM(Lepilogue):
#if defined (__INTERWORKING__)
ldmia sp!, {r0-r3,fp, lr}
bx lr
#else
ldmia sp!, {r0-r3,fp, pc}
#endif
.ffi_call_SYSV_end:
UNWIND .fnend
#ifdef __ELF__
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
#endif
cfi_endproc
UNWIND .fnend
ARM_FUNC_END(ffi_call_SYSV)
/*
unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (closure, respp, args)
ffi_closure *closure;
void **respp;
void *args;
int ffi_closure_inner_* (cif, fun, user_data, frame)
*/
ARM_FUNC_START ffi_closure_SYSV
UNWIND .pad #16
ARM_FUNC_START(ffi_go_closure_SYSV, 1)
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
ldr r0, [ip, #4] @ load cif
ldr r1, [ip, #8] @ load fun
mov r2, ip @ load user_data
b 0f
cfi_endproc
ARM_FUNC_END(ffi_go_closure_SYSV)
ARM_FUNC_START(ffi_closure_SYSV, 1)
UNWIND .fnstart
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
0:
add ip, sp, #16 @ compute entry sp
sub sp, sp, #64+32 @ allocate frame
cfi_adjust_cfa_offset(64+32)
stmdb sp!, {ip,lr}
/* Remember that EABI unwind info only applies at call sites.
We need do nothing except note the save of the stack pointer
and the link registers. */
UNWIND .save {sp,lr}
cfi_adjust_cfa_offset(8)
cfi_rel_offset(lr, 4)
add r3, sp, #8 @ load frame
bl CNAME(ffi_closure_inner_SYSV)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
add pc, r3, r0, lsl #3
cfi_endproc
UNWIND .fnend
ARM_FUNC_END(ffi_closure_SYSV)
ARM_FUNC_START(ffi_go_closure_VFP, 1)
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
ldr r0, [ip, #4] @ load cif
ldr r1, [ip, #8] @ load fun
mov r2, ip @ load user_data
b 0f
cfi_endproc
ARM_FUNC_END(ffi_go_closure_VFP)
ARM_FUNC_START(ffi_closure_VFP, 1)
UNWIND .fnstart
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
0:
add ip, sp, #16
stmfd sp!, {ip, lr}
UNWIND .save {r0, lr}
add r2, sp, #8
UNWIND .pad #16
sub sp, sp, #16
str sp, [sp, #8]
add r1, sp, #8
bl CNAME(ffi_closure_SYSV_inner)
cmp r0, #FFI_TYPE_INT
beq .Lretint
sub sp, sp, #64+32 @ allocate frame
cfi_adjust_cfa_offset(64+32)
stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7}
stmdb sp!, {ip,lr}
/* See above. */
UNWIND .save {sp,lr}
cfi_adjust_cfa_offset(8)
cfi_rel_offset(lr, 4)
add r3, sp, #8 @ load frame
bl CNAME(ffi_closure_inner_VFP)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
add pc, r3, r0, lsl #3
cfi_endproc
UNWIND .fnend
ARM_FUNC_END(ffi_closure_VFP)
/* Load values returned in registers for both closure entry points.
Note that we use LDM with SP in the register set. This is deprecated
by ARM, but not yet unpredictable. */
ARM_FUNC_START(ffi_closure_ret, 0)
cfi_startproc
cfi_rel_offset(sp, 0)
cfi_rel_offset(lr, 4)
0:
E ARM_TYPE_VFP_S
ldc p10, cr0, [r2] @ vldr s0, [r2]
ldm sp, {sp,pc}
E ARM_TYPE_VFP_D
ldc p11, cr0, [r2] @ vldr d0, [r2]
ldm sp, {sp,pc}
E ARM_TYPE_VFP_N
ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
ldm sp, {sp,pc}
E ARM_TYPE_INT64
ldr r1, [r2, #4]
nop
E ARM_TYPE_INT
ldr r0, [r2]
ldm sp, {sp,pc}
E ARM_TYPE_VOID
ldm sp, {sp,pc}
nop
E ARM_TYPE_STRUCT
ldm sp, {sp,pc}
cfi_endproc
ARM_FUNC_END(ffi_closure_ret)
#if FFI_EXEC_TRAMPOLINE_TABLE
/* ??? The iOS support should be updated. The first insn used to
be STMFD, but that's been moved into ffi_closure_SYSV. If the
writable page is put after this one we can make use of the
pc+8 feature of the architecture. We can also reduce the size
of the thunk to 8 and pack more of these into the page.
In the meantime, simply replace the STMFD with a NOP so as to
keep all the magic numbers the same within ffi.c. */
.align 12
ARM_FUNC_START(ffi_closure_trampoline_table_page)
.rept 4096 / 12
nop
ldr ip, [pc, #-4092]
ldr pc, [pc, #-4092]
.endr
cmp r0, #FFI_TYPE_FLOAT
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
beq .Lretint
#else
beq .Lretfloat
#endif
cmp r0, #FFI_TYPE_DOUBLE
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
beq .Lretlonglong
#else
beq .Lretdouble
#endif
ARM_FUNC_START(ffi_arm_trampoline, 1)
0: adr ip, 0b
ldr pc, 1f
1: .long 0
ARM_FUNC_END(ffi_arm_trampoline)
cmp r0, #FFI_TYPE_LONGDOUBLE
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
beq .Lretlonglong
#else
beq .Lretlongdouble
#endif
cmp r0, #FFI_TYPE_SINT64
beq .Lretlonglong
.Lclosure_epilogue:
add sp, sp, #16
ldmfd sp, {sp, pc}
.Lretint:
ldr r0, [sp]
b .Lclosure_epilogue
.Lretlonglong:
ldr r0, [sp]
ldr r1, [sp, #4]
b .Lclosure_epilogue
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
.Lretfloat:
ldfs f0, [sp]
b .Lclosure_epilogue
.Lretdouble:
ldfd f0, [sp]
b .Lclosure_epilogue
.Lretlongdouble:
ldfd f0, [sp]
b .Lclosure_epilogue
#endif
.ffi_closure_SYSV_end:
UNWIND .fnend
#ifdef __ELF__
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
#endif
/* Below are VFP hard-float ABI call and closure implementations.
Add VFP FPU directive here. This is only compiled into the library
under EABI. */
#ifdef __ARM_EABI__
.fpu vfp
@ r0: fn
@ r1: &ecif
@ r2: cif->bytes
@ r3: fig->flags
@ sp+0: ecif.rvalue
ARM_FUNC_START ffi_call_VFP
@ Save registers
stmfd sp!, {r0-r3, fp, lr}
UNWIND .save {r0-r3, fp, lr}
mov fp, sp
UNWIND .setfp fp, sp
@ Make room for all of the new args.
sub sp, sp, r2
@ Make room for loading VFP args
sub sp, sp, #64
@ Place all of the ffi_prep_args in position
mov r0, sp
@ r1 already set
sub r2, fp, #64 @ VFP scratch space
@ Call ffi_prep_args(stack, &ecif, vfp_space)
bl CNAME(ffi_prep_args)
@ Load VFP register args if needed
cmp r0, #0
beq LSYM(Lbase_args)
@ Load only d0 if possible
cmp r0, #3
sub ip, fp, #64
flddle d0, [ip]
fldmiadgt ip, {d0-d7}
LSYM(Lbase_args):
@ move first 4 parameters in registers
ldmia sp, {r0-r3}
@ and adjust stack
sub lr, ip, sp @ cif->bytes == (fp - 64) - sp
ldr ip, [fp] @ load fn() in advance
cmp lr, #16
movhs lr, #16
add sp, sp, lr
@ call (fn) (...)
call_reg(ip)
@ Remove the space we pushed for the args
mov sp, fp
@ Load r2 with the pointer to storage for
@ the return value
ldr r2, [sp, #24]
@ Load r3 with the return type code
ldr r3, [sp, #12]
@ If the return value pointer is NULL,
@ assume no return value.
cmp r2, #0
beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_INT
streq r0, [r2]
beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_SINT64
stmeqia r2, {r0, r1}
beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_FLOAT
fstseq s0, [r2]
beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_DOUBLE
fstdeq d0, [r2]
beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT
cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
fstmiadeq r2, {d0-d3}
LSYM(Lepilogue_vfp):
RETLDM "r0-r3,fp"
.ffi_call_VFP_end:
UNWIND .fnend
.size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
ARM_FUNC_START ffi_closure_VFP
fstmfdd sp!, {d0-d7}
@ r0-r3, then d0-d7
UNWIND .pad #80
add ip, sp, #80
stmfd sp!, {ip, lr}
UNWIND .save {r0, lr}
add r2, sp, #72
add r3, sp, #8
UNWIND .pad #72
sub sp, sp, #72
str sp, [sp, #64]
add r1, sp, #64
bl CNAME(ffi_closure_SYSV_inner)
cmp r0, #FFI_TYPE_INT
beq .Lretint_vfp
cmp r0, #FFI_TYPE_FLOAT
beq .Lretfloat_vfp
cmp r0, #FFI_TYPE_DOUBLE
cmpne r0, #FFI_TYPE_LONGDOUBLE
beq .Lretdouble_vfp
cmp r0, #FFI_TYPE_SINT64
beq .Lretlonglong_vfp
cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT
beq .Lretfloat_struct_vfp
cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
beq .Lretdouble_struct_vfp
.Lclosure_epilogue_vfp:
add sp, sp, #72
ldmfd sp, {sp, pc}
.Lretfloat_vfp:
flds s0, [sp]
b .Lclosure_epilogue_vfp
.Lretdouble_vfp:
fldd d0, [sp]
b .Lclosure_epilogue_vfp
.Lretint_vfp:
ldr r0, [sp]
b .Lclosure_epilogue_vfp
.Lretlonglong_vfp:
ldmia sp, {r0, r1}
b .Lclosure_epilogue_vfp
.Lretfloat_struct_vfp:
fldmiad sp, {d0-d1}
b .Lclosure_epilogue_vfp
.Lretdouble_struct_vfp:
fldmiad sp, {d0-d3}
b .Lclosure_epilogue_vfp
.ffi_closure_VFP_end:
UNWIND .fnend
.size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
#endif
ENTRY(ffi_arm_trampoline)
stmfd sp!, {r0-r3}
ldr r0, [pc]
ldr pc, [pc]
#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
Paulo Pizarro <paulo.pizarro@gmail.com>
Blackfin Foreign Function Interface

View file

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
Paulo Pizarro <paulo.pizarro@gmail.com>
Blackfin Foreign Function Interface
@ -32,7 +33,7 @@
.align 4
/*
There is a "feature" in the bfin toolchain that it puts a _ before funcion names
There is a "feature" in the bfin toolchain that it puts a _ before function names
that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV
*/
.global _ffi_call_SYSV;
@ -40,25 +41,26 @@
.func ffi_call_SYSV
/*
cif->bytes = R0 (fp+8)
&ecif = R1 (fp+12)
ffi_prep_args = R2 (fp+16)
ret_type = stack (fp+20)
ecif.rvalue = stack (fp+24)
fn = stack (fp+28)
got (fp+32)
There is room for improvement here (we can use temporary registers
instead of saving the values in the memory)
REGS:
P5 => Stack pointer (function arguments)
R5 => cif->bytes
R4 => ret->type
cif->bytes = R0 (fp+8)
&ecif = R1 (fp+12)
ffi_prep_args = R2 (fp+16)
ret_type = stack (fp+20)
ecif.rvalue = stack (fp+24)
fn = stack (fp+28)
got (fp+32)
FP-20 = P3
FP-16 = SP (parameters area)
FP-12 = SP (temp)
FP-08 = function return part 1 [R0]
FP-04 = function return part 2 [R1]
There is room for improvement here (we can use temporary registers
instead of saving the values in the memory)
REGS:
P5 => Stack pointer (function arguments)
R5 => cif->bytes
R4 => ret->type
FP-20 = P3
FP-16 = SP (parameters area)
FP-12 = SP (temp)
FP-08 = function return part 1 [R0]
FP-04 = function return part 2 [R1]
*/
_ffi_call_SYSV:

View file

@ -34,7 +34,7 @@
#include <ffi_common.h>
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
# if __gnu_linux__
# if __gnu_linux__ && !defined(__ANDROID__)
/* This macro indicates it may be forbidden to map anonymous memory
with both write and execute permission. Code compiled when this
option is defined will attempt to map such pages once, but if it
@ -181,10 +181,26 @@ static int emutramp_enabled = -1;
static int
emutramp_enabled_check (void)
{
if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL)
return 1;
else
char *buf = NULL;
size_t len = 0;
FILE *f;
int ret;
f = fopen ("/proc/self/status", "r");
if (f == NULL)
return 0;
ret = 0;
while (getline (&buf, &len, f) != -1)
if (!strncmp (buf, "PaX:", 4))
{
char emutramp;
if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
ret = (emutramp == 'E');
break;
}
free (buf);
fclose (f);
return ret;
}
#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
@ -249,9 +265,15 @@ static size_t execsize = 0;
/* Open a temporary file name, and immediately unlink it. */
static int
open_temp_exec_file_name (char *name)
open_temp_exec_file_name (char *name, int flags)
{
int fd = mkstemp (name);
int fd;
#ifdef HAVE_MKOSTEMP
fd = mkostemp (name, flags);
#else
fd = mkstemp (name);
#endif
if (fd != -1)
unlink (name);
@ -264,8 +286,30 @@ static int
open_temp_exec_file_dir (const char *dir)
{
static const char suffix[] = "/ffiXXXXXX";
int lendir = strlen (dir);
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
int lendir, flags;
char *tempname;
#ifdef O_TMPFILE
int fd;
#endif
#ifdef O_CLOEXEC
flags = O_CLOEXEC;
#else
flags = 0;
#endif
#ifdef O_TMPFILE
fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
/* If the running system does not support the O_TMPFILE flag then retry without it. */
if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
return fd;
} else {
errno = 0;
}
#endif
lendir = strlen (dir);
tempname = __builtin_alloca (lendir + sizeof (suffix));
if (!tempname)
return -1;
@ -273,7 +317,7 @@ open_temp_exec_file_dir (const char *dir)
memcpy (tempname, dir, lendir);
memcpy (tempname + lendir, suffix, sizeof (suffix));
return open_temp_exec_file_name (tempname);
return open_temp_exec_file_name (tempname, flags);
}
/* Open a temporary file in the directory in the named environment
@ -382,7 +426,7 @@ open_temp_exec_file_opts_next (void)
}
/* Return a file descriptor of a temporary zero-sized file in a
writable and exexutable filesystem. */
writable and executable filesystem. */
static int
open_temp_exec_file (void)
{

View file

@ -54,6 +54,11 @@ void ffi_type_test(ffi_type *a, char *file, int line)
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
|| a->elements != NULL, file, line);
FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
|| (a->elements != NULL
&& a->elements[0] != NULL && a->elements[1] == NULL),
file, line);
}

View file

@ -1255,7 +1255,7 @@ extern void* sbrk(ptrdiff_t);
#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
/* Some constants coerced to size_t */
/* Annoying but necessary to avoid errors on some plaftorms */
/* Annoying but necessary to avoid errors on some platforms */
#define SIZE_T_ZERO ((size_t)0)
#define SIZE_T_ONE ((size_t)1)
#define SIZE_T_TWO ((size_t)2)
@ -1409,7 +1409,7 @@ static int win32munmap(void* ptr, size_t size) {
#define CALL_MORECORE(S) MFAIL
#endif /* HAVE_MORECORE */
/* mstate bit set if continguous morecore disabled or failed */
/* mstate bit set if contiguous morecore disabled or failed */
#define USE_NONCONTIGUOUS_BIT (4U)
/* segment bit set in create_mspace_with_base */
@ -1661,7 +1661,7 @@ struct malloc_chunk {
typedef struct malloc_chunk mchunk;
typedef struct malloc_chunk* mchunkptr;
typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
typedef unsigned int bindex_t; /* Described below */
typedef size_t bindex_t; /* Described below */
typedef unsigned int binmap_t; /* Described below */
typedef unsigned int flag_t; /* The type of various bit flag sets */
@ -2291,7 +2291,7 @@ static size_t traverse_and_check(mstate m);
#define treebin_at(M,i) (&((M)->treebins[i]))
/* assign tree index for size S to variable I */
#if defined(__GNUC__) && defined(i386)
#if defined(__GNUC__) && defined(__i386__)
#define compute_tree_index(S, I)\
{\
size_t X = S >> TREEBIN_SHIFT;\
@ -2356,7 +2356,7 @@ static size_t traverse_and_check(mstate m);
/* index corresponding to given bit */
#if defined(__GNUC__) && defined(i386)
#if defined(__GNUC__) && defined(__i386__)
#define compute_bit2idx(X, I)\
{\
unsigned int J;\
@ -3090,8 +3090,8 @@ static void internal_malloc_stats(mstate m) {
and choose its bk node as its replacement.
2. If x was the last node of its size, but not a leaf node, it must
be replaced with a leaf node (not merely one with an open left or
right), to make sure that lefts and rights of descendents
correspond properly to bit masks. We use the rightmost descendent
right), to make sure that lefts and rights of descendants
correspond properly to bit masks. We use the rightmost descendant
of x. We could use any other leaf, but this is easy to locate and
tends to counteract removal of leftmosts elsewhere, and so keeps
paths shorter than minimally guaranteed. This doesn't loop much
@ -3388,7 +3388,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
*ss = m->seg; /* Push current record */
m->seg.base = tbase;
m->seg.size = tsize;
set_segment_flags(&m->seg, mmapped);
(void)set_segment_flags(&m->seg, mmapped);
m->seg.next = ss;
/* Insert trailing fenceposts */
@ -3548,7 +3548,7 @@ static void* sys_alloc(mstate m, size_t nb) {
if (!is_initialized(m)) { /* first-time initialization */
m->seg.base = m->least_addr = tbase;
m->seg.size = tsize;
set_segment_flags(&m->seg, mmap_flag);
(void)set_segment_flags(&m->seg, mmap_flag);
m->magic = mparams.magic;
init_bins(m);
if (is_global(m))
@ -5091,10 +5091,10 @@ History:
Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Use last_remainder in more cases.
* Pack bins using idea from colin@nyx10.cs.du.edu
* Use ordered bins instead of best-fit threshhold
* Use ordered bins instead of best-fit threshold
* Eliminate block-local decls to simplify tracing and debugging.
* Support another case of realloc via move into top
* Fix error occuring when initial sbrk_base not word-aligned.
* Fix error occurring when initial sbrk_base not word-aligned.
* Rely on page size for units instead of SBRK_UNIT to
avoid surprises about sbrk alignment conventions.
* Add mallinfo, mallopt. Thanks to Raymond Nijssen

View file

@ -401,7 +401,7 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
the closure (in the "trampoline" area), but we replace the gp
pointer with a pointer to the closure itself. We also add the real
gp pointer to the closure. This allows the function entry code to
both retrieve the user data, and to restire the correct gp pointer. */
both retrieve the user data, and to restore the correct gp pointer. */
extern void ffi_closure_unix ();

View file

@ -60,6 +60,9 @@ ffi_java_raw_size (ffi_cif *cif)
case FFI_TYPE_STRUCT:
/* No structure parameters in Java. */
abort();
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
result += FFI_SIZEOF_JAVA_RAW;
}
@ -104,6 +107,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
*args = (void*) &(raw++)->ptr;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
*args = raw;
raw +=
@ -126,6 +133,9 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
*args = (void*) raw;
raw += 2;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
*args = (void*) raw++;
}
@ -254,6 +264,10 @@ ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
*(SINT64 *)rvalue <<= 32;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
break;
}
@ -279,6 +293,10 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
*(SINT64 *)rvalue >>= 32;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
break;
}

View file

@ -123,6 +123,8 @@ ffi_prep_args (void *stack, extended_cif *ecif)
#define CIF_FLAGS_POINTER 32
#define CIF_FLAGS_STRUCT1 64
#define CIF_FLAGS_STRUCT2 128
#define CIF_FLAGS_SINT8 256
#define CIF_FLAGS_SINT16 512
/* Perform machine dependent cif processing */
ffi_status
@ -200,6 +202,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
cif->flags = CIF_FLAGS_DINT;
break;
case FFI_TYPE_SINT16:
cif->flags = CIF_FLAGS_SINT16;
break;
case FFI_TYPE_SINT8:
cif->flags = CIF_FLAGS_SINT8;
break;
default:
cif->flags = CIF_FLAGS_INT;
break;

View file

@ -2,9 +2,10 @@
sysv.S - Copyright (c) 2012 Alan Hourihane
Copyright (c) 1998, 2012 Andreas Schwab
Copyright (c) 2008 Red Hat, Inc.
m68k Foreign Function Interface
Copyright (c) 2008 Red Hat, Inc.
Copyright (c) 2012 Thorsten Glaser
m68k Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -168,8 +169,28 @@ retstruct1:
retstruct2:
btst #7,%d2
jbeq noretval
jbeq retsint8
move.w %d0,(%a1)
jbra epilogue
retsint8:
btst #8,%d2
jbeq retsint16
| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
ext.w %d0
ext.l %d0
#else
extb.l %d0
#endif
move.l %d0,(%a1)
jbra epilogue
retsint16:
btst #9,%d2
jbeq noretval
ext.l %d0
move.l %d0,(%a1)
noretval:
epilogue:
@ -201,8 +222,10 @@ CALLFUNC(ffi_closure_SYSV):
lsr.l #1,%d0
jne 1f
jcc .Lcls_epilogue
| CIF_FLAGS_INT
move.l -12(%fp),%d0
.Lcls_epilogue:
| no CIF_FLAGS_*
unlk %fp
rts
1:
@ -210,6 +233,7 @@ CALLFUNC(ffi_closure_SYSV):
lsr.l #2,%d0
jne 1f
jcs .Lcls_ret_float
| CIF_FLAGS_DINT
move.l (%a0)+,%d0
move.l (%a0),%d1
jra .Lcls_epilogue
@ -224,6 +248,7 @@ CALLFUNC(ffi_closure_SYSV):
lsr.l #2,%d0
jne 1f
jcs .Lcls_ret_ldouble
| CIF_FLAGS_DOUBLE
#if defined(__MC68881__) || defined(__HAVE_68881__)
fmove.d (%a0),%fp0
#else
@ -242,17 +267,37 @@ CALLFUNC(ffi_closure_SYSV):
jra .Lcls_epilogue
1:
lsr.l #2,%d0
jne .Lcls_ret_struct2
jne 1f
jcs .Lcls_ret_struct1
| CIF_FLAGS_POINTER
move.l (%a0),%a0
move.l %a0,%d0
jra .Lcls_epilogue
.Lcls_ret_struct1:
move.b (%a0),%d0
jra .Lcls_epilogue
.Lcls_ret_struct2:
1:
lsr.l #2,%d0
jne 1f
jcs .Lcls_ret_sint8
| CIF_FLAGS_STRUCT2
move.w (%a0),%d0
jra .Lcls_epilogue
.Lcls_ret_sint8:
move.l (%a0),%d0
| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
ext.w %d0
ext.l %d0
#else
extb.l %d0
#endif
jra .Lcls_epilogue
1:
| CIF_FLAGS_SINT16
move.l (%a0),%d0
ext.l %d0
jra .Lcls_epilogue
CFI_ENDPROC()
.size CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)

400
libffi/src/m88k/ffi.c Normal file
View file

@ -0,0 +1,400 @@
/*
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* ``Software''), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/*
* m88k Foreign Function Interface
*
* This file attempts to provide all the FFI entry points which can reliably
* be implemented in C.
*
* Only OpenBSD/m88k is currently supported; other platforms (such as
* Motorola's SysV/m88k) could be supported with the following tweaks:
*
* - non-OpenBSD systems use an `outgoing parameter area' as part of the
* 88BCS calling convention, which is not supported under OpenBSD from
* release 3.6 onwards. Supporting it should be as easy as taking it
* into account when adjusting the stack, in the assembly code.
*
* - the logic deciding whether a function argument gets passed through
* registers, or on the stack, has changed several times in OpenBSD in
* edge cases (especially for structs larger than 32 bytes being passed
* by value). The code below attemps to match the logic used by the
* system compiler of OpenBSD 5.3, i.e. gcc 3.3.6 with many m88k backend
* fixes.
*/
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <unistd.h>
void ffi_call_OBSD (unsigned int, extended_cif *, unsigned int, void *,
void (*fn) ());
void *ffi_prep_args (void *, extended_cif *);
void ffi_closure_OBSD (ffi_closure *);
void ffi_closure_struct_OBSD (ffi_closure *);
unsigned int ffi_closure_OBSD_inner (ffi_closure *, void *, unsigned int *,
char *);
void ffi_cacheflush_OBSD (unsigned int, unsigned int);
#define CIF_FLAGS_INT (1 << 0)
#define CIF_FLAGS_DINT (1 << 1)
/*
* Foreign Function Interface API
*/
/* ffi_prep_args is called by the assembly routine once stack space has
been allocated for the function's arguments. */
void *
ffi_prep_args (void *stack, extended_cif *ecif)
{
unsigned int i;
void **p_argv;
char *argp, *stackp;
unsigned int *regp;
unsigned int regused;
ffi_type **p_arg;
void *struct_value_ptr;
regp = (unsigned int *)stack;
stackp = (char *)(regp + 8);
regused = 0;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
&& !ecif->cif->flags)
struct_value_ptr = ecif->rvalue;
else
struct_value_ptr = NULL;
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i != 0; i--, p_arg++)
{
size_t z;
unsigned short t, a;
z = (*p_arg)->size;
t = (*p_arg)->type;
a = (*p_arg)->alignment;
/*
* Figure out whether the argument can be passed through registers
* or on the stack.
* The rule is that registers can only receive simple types not larger
* than 64 bits, or structs the exact size of a register and aligned to
* the size of a register.
*/
if (t == FFI_TYPE_STRUCT)
{
if (z == sizeof (int) && a == sizeof (int) && regused < 8)
argp = (char *)regp;
else
argp = stackp;
}
else
{
if (z > sizeof (int) && regused < 8 - 1)
{
/* align to an even register pair */
if (regused & 1)
{
regp++;
regused++;
}
}
if (regused < 8)
argp = (char *)regp;
else
argp = stackp;
}
/* Enforce proper stack alignment of 64-bit types */
if (argp == stackp && a > sizeof (int))
{
stackp = (char *) ALIGN(stackp, a);
argp = stackp;
}
switch (t)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
break;
case FFI_TYPE_INT:
case FFI_TYPE_FLOAT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
*(unsigned int *) argp = *(unsigned int *) *p_argv;
break;
case FFI_TYPE_DOUBLE:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_STRUCT:
memcpy (argp, *p_argv, z);
break;
default:
FFI_ASSERT (0);
}
/* Align if necessary. */
if ((sizeof (int) - 1) & z)
z = ALIGN(z, sizeof (int));
p_argv++;
/* Be careful, once all registers are filled, and about to continue
on stack, regp == stackp. Therefore the check for regused as well. */
if (argp == (char *)regp && regused < 8)
{
regp += z / sizeof (int);
regused += z / sizeof (int);
}
else
stackp += z;
}
return struct_value_ptr;
}
/* Perform machine dependent cif processing */
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
cif->flags = 0;
break;
case FFI_TYPE_STRUCT:
if (cif->rtype->size == sizeof (int) &&
cif->rtype->alignment == sizeof (int))
cif->flags = CIF_FLAGS_INT;
else
cif->flags = 0;
break;
case FFI_TYPE_DOUBLE:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = CIF_FLAGS_DINT;
break;
default:
cif->flags = CIF_FLAGS_INT;
break;
}
return FFI_OK;
}
void
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
{
extended_cif ecif;
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
&& cif->rtype->type == FFI_TYPE_STRUCT
&& (cif->rtype->size != sizeof (int)
|| cif->rtype->alignment != sizeof (int)))
ecif.rvalue = alloca (cif->rtype->size);
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_OBSD:
ffi_call_OBSD (cif->bytes, &ecif, cif->flags, ecif.rvalue, fn);
break;
default:
FFI_ASSERT (0);
break;
}
}
/*
* Closure API
*/
static void
ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp,
char *stackp)
{
unsigned int i;
void **p_argv;
char *argp;
unsigned int regused;
ffi_type **p_arg;
regused = 0;
p_argv = avalue;
for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
{
size_t z;
unsigned short t, a;
z = (*p_arg)->size;
t = (*p_arg)->type;
a = (*p_arg)->alignment;
/*
* Figure out whether the argument has been passed through registers
* or on the stack.
* The rule is that registers can only receive simple types not larger
* than 64 bits, or structs the exact size of a register and aligned to
* the size of a register.
*/
if (t == FFI_TYPE_STRUCT)
{
if (z == sizeof (int) && a == sizeof (int) && regused < 8)
argp = (char *)regp;
else
argp = stackp;
}
else
{
if (z > sizeof (int) && regused < 8 - 1)
{
/* align to an even register pair */
if (regused & 1)
{
regp++;
regused++;
}
}
if (regused < 8)
argp = (char *)regp;
else
argp = stackp;
}
/* Enforce proper stack alignment of 64-bit types */
if (argp == stackp && a > sizeof (int))
{
stackp = (char *) ALIGN(stackp, a);
argp = stackp;
}
if (z < sizeof (int) && t != FFI_TYPE_STRUCT)
*p_argv = (void *) (argp + sizeof (int) - z);
else
*p_argv = (void *) argp;
/* Align if necessary */
if ((sizeof (int) - 1) & z)
z = ALIGN(z, sizeof (int));
p_argv++;
/* Be careful, once all registers are exhausted, and about to fetch from
stack, regp == stackp. Therefore the check for regused as well. */
if (argp == (char *)regp && regused < 8)
{
regp += z / sizeof (int);
regused += z / sizeof (int);
}
else
stackp += z;
}
}
unsigned int
ffi_closure_OBSD_inner (ffi_closure *closure, void *resp, unsigned int *regp,
char *stackp)
{
ffi_cif *cif;
void **arg_area;
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void *));
ffi_prep_closure_args_OBSD(cif, arg_area, regp, stackp);
(closure->fun) (cif, resp, arg_area, closure->user_data);
return cif->flags;
}
ffi_status
ffi_prep_closure_loc (ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data, void *codeloc)
{
unsigned int *tramp = (unsigned int *) codeloc;
void *fn;
FFI_ASSERT (cif->abi == FFI_OBSD);
if (cif->rtype->type == FFI_TYPE_STRUCT && !cif->flags)
fn = &ffi_closure_struct_OBSD;
else
fn = &ffi_closure_OBSD;
/* or.u %r10, %r0, %hi16(fn) */
tramp[0] = 0x5d400000 | (((unsigned int)fn) >> 16);
/* or.u %r13, %r0, %hi16(closure) */
tramp[1] = 0x5da00000 | ((unsigned int)closure >> 16);
/* or %r10, %r10, %lo16(fn) */
tramp[2] = 0x594a0000 | (((unsigned int)fn) & 0xffff);
/* jmp.n %r10 */
tramp[3] = 0xf400c40a;
/* or %r13, %r13, %lo16(closure) */
tramp[4] = 0x59ad0000 | ((unsigned int)closure & 0xffff);
ffi_cacheflush_OBSD((unsigned int)codeloc, FFI_TRAMPOLINE_SIZE);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* ``Software''), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/*
* m88k Foreign Function Interface
*/
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_OBSD,
FFI_DEFAULT_ABI = FFI_OBSD,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 0x14
#define FFI_NATIVE_RAW_API 0
#endif

209
libffi/src/m88k/obsd.S Normal file
View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* ``Software''), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/*
* m88k Foreign Function Interface
*/
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
.text
/*
* ffi_cacheflush_OBSD(unsigned int addr, %r2
* unsigned int size); %r3
*/
.align 4
.globl ffi_cacheflush_OBSD
.type ffi_cacheflush_OBSD,@function
ffi_cacheflush_OBSD:
tb0 0, %r0, 451
or %r0, %r0, %r0
jmp %r1
.size ffi_cacheflush_OBSD, . - ffi_cacheflush_OBSD
/*
* ffi_call_OBSD(unsigned bytes, %r2
* extended_cif *ecif, %r3
* unsigned flags, %r4
* void *rvalue, %r5
* void (*fn)()); %r6
*/
.align 4
.globl ffi_call_OBSD
.type ffi_call_OBSD,@function
ffi_call_OBSD:
subu %r31, %r31, 32
st %r30, %r31, 4
st %r1, %r31, 0
addu %r30, %r31, 32
| Save the few arguments we'll need after ffi_prep_args()
st.d %r4, %r31, 8
st %r6, %r31, 16
| Allocate room for the image of r2-r9, and the stack space for
| the args (rounded to a 16-byte boundary)
addu %r2, %r2, (8 * 4) + 15
clr %r2, %r2, 4<0>
subu %r31, %r31, %r2
| Fill register and stack image
or %r2, %r31, %r0
#ifdef PIC
bsr ffi_prep_args#plt
#else
bsr ffi_prep_args
#endif
| Save pointer to return struct address, if any
or %r12, %r2, %r0
| Get function pointer
subu %r4, %r30, 32
ld %r1, %r4, 16
| Fetch the register arguments
ld.d %r2, %r31, (0 * 4)
ld.d %r4, %r31, (2 * 4)
ld.d %r6, %r31, (4 * 4)
ld.d %r8, %r31, (6 * 4)
addu %r31, %r31, (8 * 4)
| Invoke the function
jsr %r1
| Restore stack now that we don't need the args anymore
subu %r31, %r30, 32
| Figure out what to return as the function's return value
ld %r5, %r31, 12 | rvalue
ld %r4, %r31, 8 | flags
bcnd eq0, %r5, 9f
bb0 0, %r4, 1f | CIF_FLAGS_INT
st %r2, %r5, 0
br 9f
1:
bb0 1, %r4, 1f | CIF_FLAGS_DINT
st.d %r2, %r5, 0
br 9f
1:
9:
ld %r1, %r31, 0
ld %r30, %r31, 4
jmp.n %r1
addu %r31, %r31, 32
.size ffi_call_OBSD, . - ffi_call_OBSD
/*
* ffi_closure_OBSD(ffi_closure *closure); %r13
*/
.align 4
.globl ffi_closure_OBSD
.type ffi_closure_OBSD, @function
ffi_closure_OBSD:
subu %r31, %r31, 16
st %r30, %r31, 4
st %r1, %r31, 0
addu %r30, %r31, 16
| Make room on the stack for saved register arguments and return
| value
subu %r31, %r31, (8 * 4) + (2 * 4)
st.d %r2, %r31, (0 * 4)
st.d %r4, %r31, (2 * 4)
st.d %r6, %r31, (4 * 4)
st.d %r8, %r31, (6 * 4)
| Invoke the closure function
or %r5, %r30, 0 | calling stack
addu %r4, %r31, 0 | saved registers
addu %r3, %r31, (8 * 4) | return value
or %r2, %r13, %r0 | closure
#ifdef PIC
bsr ffi_closure_OBSD_inner#plt
#else
bsr ffi_closure_OBSD_inner
#endif
| Figure out what to return as the function's return value
bb0 0, %r2, 1f | CIF_FLAGS_INT
ld %r2, %r31, (8 * 4)
br 9f
1:
bb0 1, %r2, 1f | CIF_FLAGS_DINT
ld.d %r2, %r31, (8 * 4)
br 9f
1:
9:
subu %r31, %r30, 16
ld %r1, %r31, 0
ld %r30, %r31, 4
jmp.n %r1
addu %r31, %r31, 16
.size ffi_closure_OBSD,.-ffi_closure_OBSD
/*
* ffi_closure_struct_OBSD(ffi_closure *closure); %r13
*/
.align 4
.globl ffi_closure_struct_OBSD
.type ffi_closure_struct_OBSD, @function
ffi_closure_struct_OBSD:
subu %r31, %r31, 16
st %r30, %r31, 4
st %r1, %r31, 0
addu %r30, %r31, 16
| Make room on the stack for saved register arguments
subu %r31, %r31, (8 * 4)
st.d %r2, %r31, (0 * 4)
st.d %r4, %r31, (2 * 4)
st.d %r6, %r31, (4 * 4)
st.d %r8, %r31, (6 * 4)
| Invoke the closure function
or %r5, %r30, 0 | calling stack
addu %r4, %r31, 0 | saved registers
or %r3, %r12, 0 | return value
or %r2, %r13, %r0 | closure
#ifdef PIC
bsr ffi_closure_OBSD_inner#plt
#else
bsr ffi_closure_OBSD_inner
#endif
subu %r31, %r30, 16
ld %r1, %r31, 0
ld %r30, %r31, 4
jmp.n %r1
addu %r31, %r31, 16
.size ffi_closure_struct_OBSD,.-ffi_closure_struct_OBSD

330
libffi/src/metag/ffi.c Normal file
View file

@ -0,0 +1,330 @@
/* ----------------------------------------------------------------------
ffi.c - Copyright (c) 2013 Imagination Technologies
Meta 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 SIMON POSNJAK 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>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
/*
* ffi_prep_args is called by the assembly routine once stack space has been
* allocated for the function's arguments
*/
unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
/* Store return value */
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
argp -= 4;
*(void **) argp = ecif->rvalue;
}
p_argv = ecif->avalue;
/* point to next location */
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++)
{
size_t z;
/* Move argp to address of argument */
z = (*p_arg)->size;
argp -= z;
/* Align if necessary */
argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
if (z < sizeof(int)) {
z = sizeof(int);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
case FFI_TYPE_STRUCT:
memcpy(argp, *p_argv, (*p_arg)->size);
break;
default:
FFI_ASSERT(0);
}
} else if ( z == sizeof(int)) {
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
} else {
memcpy(argp, *p_argv, z);
}
}
/* return the size of the arguments to be passed in registers,
padded to an 8 byte boundary to preserve stack alignment */
return ALIGN(MIN(stack - argp, 6*4), 8);
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
ffi_type **ptr;
unsigned i, bytes = 0;
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) {
if ((*ptr)->size == 0)
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes += ALIGN((*ptr)->size, 4);
}
/* Ensure arg space is aligned to an 8-byte boundary */
bytes = ALIGN(bytes, 8);
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT) {
bytes += sizeof(void*);
/* Ensure stack is aligned to an 8-byte boundary */
bytes = ALIGN(bytes, 8);
}
cif->bytes = bytes;
/* Set the return type flag */
switch (cif->rtype->type) {
case FFI_TYPE_VOID:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
cif->flags = (unsigned) cif->rtype->type;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = (unsigned) FFI_TYPE_SINT64;
break;
case FFI_TYPE_STRUCT:
/* Meta can store return values which are <= 64 bits */
if (cif->rtype->size <= 4)
/* Returned to D0Re0 as 32-bit value */
cif->flags = (unsigned)FFI_TYPE_INT;
else if ((cif->rtype->size > 4) && (cif->rtype->size <= 8))
/* Returned valued is stored to D1Re0|R0Re0 */
cif->flags = (unsigned)FFI_TYPE_DOUBLE;
else
/* value stored in memory */
cif->flags = (unsigned)FFI_TYPE_STRUCT;
break;
default:
cif->flags = (unsigned)FFI_TYPE_INT;
break;
}
return FFI_OK;
}
extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned, double *);
/*
* Exported in API. Entry point
* cif -> ffi_cif object
* fn -> function pointer
* rvalue -> pointer to return value
* avalue -> vector of void * pointers pointing to memory locations holding the
* arguments
*/
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
int small_struct = (((cif->flags == FFI_TYPE_INT) || (cif->flags == FFI_TYPE_DOUBLE)) && (cif->rtype->type == FFI_TYPE_STRUCT));
ecif.cif = cif;
ecif.avalue = avalue;
double temp;
/*
* 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 ) && (cif->flags == FFI_TYPE_STRUCT))
ecif.rvalue = alloca(cif->rtype->size);
else if (small_struct)
ecif.rvalue = &temp;
else
ecif.rvalue = rvalue;
switch (cif->abi) {
case FFI_SYSV:
ffi_call_SYSV(fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
break;
default:
FFI_ASSERT(0);
break;
}
if (small_struct)
memcpy (rvalue, &temp, cif->rtype->size);
}
/* private members */
static void ffi_prep_incoming_args_SYSV (char *, void **, void **,
ffi_cif*, float *);
void ffi_closure_SYSV (ffi_closure *);
/* Do NOT change that without changing the FFI_TRAMPOLINE_SIZE */
extern unsigned int ffi_metag_trampoline[10]; /* 10 instructions */
/* end of private members */
/*
* __tramp: trampoline memory location
* __fun: assembly routine
* __ctx: memory location for wrapper
*
* At this point, tramp[0] == __ctx !
*/
void ffi_init_trampoline(unsigned char *__tramp, unsigned int __fun, unsigned int __ctx) {
memcpy (__tramp, ffi_metag_trampoline, sizeof(ffi_metag_trampoline));
*(unsigned int*) &__tramp[40] = __ctx;
*(unsigned int*) &__tramp[44] = __fun;
/* This will flush the instruction cache */
__builtin_meta2_cachewd(&__tramp[0], 1);
__builtin_meta2_cachewd(&__tramp[47], 1);
}
/* the cif must already be prepared */
ffi_status
ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
void (*closure_func)(ffi_closure*) = NULL;
if (cif->abi == FFI_SYSV)
closure_func = &ffi_closure_SYSV;
else
return FFI_BAD_ABI;
ffi_init_trampoline(
(unsigned char*)&closure->tramp[0],
(unsigned int)closure_func,
(unsigned int)codeloc);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
/* This function is jumped to by the trampoline */
unsigned int ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
ffi_closure *closure;
void **respp;
void *args;
void *vfp_args;
{
ffi_cif *cif;
void **arg_area;
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
/*
* This call will initialize ARG_AREA, such that each
* element in that array points to the corresponding
* value on the stack; and if the function returns
* a structure, it will re-set RESP to point to the
* structure return address.
*/
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
(closure->fun) ( cif, *respp, arg_area, closure->user_data);
return cif->flags;
}
static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif,
float *vfp_stack)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
/* stack points to original arguments */
argp = stack;
/* Store return value */
if ( cif->flags == FFI_TYPE_STRUCT ) {
argp -= 4;
*rvalue = *(void **) argp;
}
p_argv = avalue;
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) {
size_t z;
size_t alignment;
alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
if ((alignment - 1) & (unsigned)argp)
argp = (char *) ALIGN(argp, alignment);
z = (*p_arg)->size;
*p_argv = (void*) argp;
p_argv++;
argp -= z;
}
return;
}

View file

@ -0,0 +1,53 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2013 Imagination Technologies Ltd.
Target configuration macros for Meta
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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1,
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 48
#define FFI_NATIVE_RAW_API 0
#endif

311
libffi/src/metag/sysv.S Normal file
View file

@ -0,0 +1,311 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2013 Imagination Technologies Ltd.
Meta 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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#else
#ifdef __USER_LABEL_PREFIX__
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#else
#define CNAME(x) x
#endif
#define ENTRY(x) .globl CNAME(x); .type CNAME(x), %function; CNAME(x):
#endif
#ifdef __ELF__
#define LSYM(x) .x
#else
#define LSYM(x) x
#endif
.macro call_reg x=
.text
.balign 4
mov D1RtP, \x
swap D1RtP, PC
.endm
! Save register arguments
.macro SAVE_ARGS
.text
.balign 4
setl [A0StP++], D0Ar6, D1Ar5
setl [A0StP++], D0Ar4, D1Ar3
setl [A0StP++], D0Ar2, D1Ar1
.endm
! Save retrun, frame pointer and other regs
.macro SAVE_REGS regs=
.text
.balign 4
setl [A0StP++], D0FrT, D1RtP
! Needs to be a pair of regs
.ifnc "\regs",""
setl [A0StP++], \regs
.endif
.endm
! Declare a global function
.macro METAG_FUNC_START name
.text
.balign 4
ENTRY(\name)
.endm
! Return registers from the stack. Reverse SAVE_REGS operation
.macro RET_REGS regs=, cond=
.ifnc "\regs", ""
getl \regs, [--A0StP]
.endif
getl D0FrT, D1RtP, [--A0StP]
.endm
! Return arguments
.macro RET_ARGS
getl D0Ar2, D1Ar1, [--A0StP]
getl D0Ar4, D1Ar3, [--A0StP]
getl D0Ar6, D1Ar5, [--A0StP]
.endm
! D1Ar1: fn
! D0Ar2: &ecif
! D1Ar3: cif->bytes
! D0Ar4: fig->flags
! D1Ar5: ecif.rvalue
! This assumes we are using GNU as
METAG_FUNC_START ffi_call_SYSV
! Save argument registers
SAVE_ARGS
! new frame
mov D0FrT, A0FrP
add A0FrP, A0StP, #0
! Preserve the old frame pointer
SAVE_REGS "D1.5, D0.5"
! Make room for new args. cifs->bytes is the total space for input
! and return arguments
add A0StP, A0StP, D1Ar3
! Preserve cifs->bytes & fn
mov D0.5, D1Ar3
mov D1.5, D1Ar1
! Place all of the ffi_prep_args in position
mov D1Ar1, A0StP
! Call ffi_prep_args(stack, &ecif)
#ifdef __PIC__
callr D1RtP, CNAME(ffi_prep_args@PLT)
#else
callr D1RtP, CNAME(ffi_prep_args)
#endif
! Restore fn pointer
! The foreign stack should look like this
! XXXXX XXXXXX <--- stack pointer
! FnArgN rvalue
! FnArgN+2 FnArgN+1
! FnArgN+4 FnArgN+3
! ....
!
! A0StP now points to the first (or return) argument + 4
! Preserve cif->bytes
getl D0Ar2, D1Ar1, [--A0StP]
getl D0Ar4, D1Ar3, [--A0StP]
getl D0Ar6, D1Ar5, [--A0StP]
! Place A0StP to the first argument again
add A0StP, A0StP, #24 ! That's because we loaded 6 regs x 4 byte each
! A0FrP points to the initial stack without the reserved space for the
! cifs->bytes, whilst A0StP points to the stack after the space allocation
! fn was the first argument of ffi_call_SYSV.
! The stack at this point looks like this:
!
! A0StP(on entry to _SYSV) -> Arg6 Arg5 | low
! Arg4 Arg3 |
! Arg2 Arg1 |
! A0FrP ----> D0FrtP D1RtP |
! D1.5 D0.5 |
! A0StP(bf prep_args) -> FnArgn FnArgn-1 |
! FnArgn-2FnArgn-3 |
! ................ | <= cifs->bytes
! FnArg4 FnArg3 |
! A0StP (prv_A0StP+cifs->bytes) FnArg2 FnArg1 | high
!
! fn was in Arg1 so it's located in in A0FrP+#-0xC
!
! D0Re0 contains the size of arguments stored in registers
sub A0StP, A0StP, D0Re0
! Arg1 is the function pointer for the foreign call. This has been
! preserved in D1.5
! Time to call (fn). Arguments should be like this:
! Arg1-Arg6 are loaded to regs
! The rest of the arguments are stored in stack pointed by A0StP
call_reg D1.5
! Reset stack.
mov A0StP, A0FrP
! Load Arg1 with the pointer to storage for the return type
! This was stored in Arg5
getd D1Ar1, [A0FrP+#-20]
! Load D0Ar2 with the return type code. This was stored in Arg4 (flags)
getd D0Ar2, [A0FrP+#-16]
! We are ready to start processing the return value
! D0Re0 (and D1Re0) hold the return value
! If the return value is NULL, assume no return value
cmp D1Ar1, #0
beq LSYM(Lepilogue)
! return INT
cmp D0Ar2, #FFI_TYPE_INT
! Sadly, there is no setd{cc} instruction so we need to workaround that
bne .INT64
setd [D1Ar1], D0Re0
b LSYM(Lepilogue)
! return INT64
.INT64:
cmp D0Ar2, #FFI_TYPE_SINT64
setleq [D1Ar1], D0Re0, D1Re0
! return DOUBLE
cmp D0Ar2, #FFI_TYPE_DOUBLE
setl [D1AR1++], D0Re0, D1Re0
LSYM(Lepilogue):
! At this point, the stack pointer points right after the argument
! saved area. We need to restore 4 regs, therefore we need to move
! 16 bytes ahead.
add A0StP, A0StP, #16
RET_REGS "D1.5, D0.5"
RET_ARGS
getd D0Re0, [A0StP]
mov A0FrP, D0FrT
swap D1RtP, PC
.ffi_call_SYSV_end:
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
/*
(called by ffi_metag_trampoline)
void ffi_closure_SYSV (ffi_closure*)
(called by ffi_closure_SYSV)
unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (closure,respp, args)
ffi_closure *closure;
void **respp;
void *args;
*/
METAG_FUNC_START ffi_closure_SYSV
! We assume that D1Ar1 holds the address of the
! ffi_closure struct. We will use that to fetch the
! arguments. The stack pointer points to an empty space
! and it is ready to store more data.
! D1Ar1 is ready
! Allocate stack space for return value
add A0StP, A0StP, #8
! Store it to D0Ar2
sub D0Ar2, A0StP, #8
sub D1Ar3, A0FrP, #4
! D1Ar3 contains the address of the original D1Ar1 argument
! We need to subtract #4 later on
! Preverve D0Ar2
mov D0.5, D0Ar2
#ifdef __PIC__
callr D1RtP, CNAME(ffi_closure_SYSV_inner@PLT)
#else
callr D1RtP, CNAME(ffi_closure_SYSV_inner)
#endif
! Check the return value and store it to D0.5
cmp D0Re0, #FFI_TYPE_INT
beq .Lretint
cmp D0Re0, #FFI_TYPE_DOUBLE
beq .Lretdouble
.Lclosure_epilogue:
sub A0StP, A0StP, #8
RET_REGS "D1.5, D0.5"
RET_ARGS
swap D1RtP, PC
.Lretint:
setd [D0.5], D0Re0
b .Lclosure_epilogue
.Lretdouble:
setl [D0.5++], D0Re0, D1Re0
b .Lclosure_epilogue
.ffi_closure_SYSV_end:
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
ENTRY(ffi_metag_trampoline)
SAVE_ARGS
! New frame
mov A0FrP, A0StP
SAVE_REGS "D1.5, D0.5"
mov D0.5, PC
! Load D1Ar1 the value of ffi_metag_trampoline
getd D1Ar1, [D0.5 + #8]
! Jump to ffi_closure_SYSV
getd PC, [D0.5 + #12]

321
libffi/src/microblaze/ffi.c Normal file
View file

@ -0,0 +1,321 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc
MicroBlaze 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 THE AUTHORS OR COPYRIGHT
HOLDERS 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>
extern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*,
unsigned int, unsigned int, unsigned int*, void (*fn)(void),
unsigned int, unsigned int);
extern void ffi_closure_SYSV(void);
#define WORD_SIZE sizeof(unsigned int)
#define ARGS_REGISTER_SIZE (WORD_SIZE * 6)
#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE)
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
void ffi_prep_args(void* stack, extended_cif* ecif)
{
unsigned int i;
ffi_type** p_arg;
void** p_argv;
void* stack_args_p = stack;
p_argv = ecif->avalue;
if (ecif == NULL || ecif->cif == NULL) {
return; /* no description to prepare */
}
if ((ecif->cif->rtype != NULL) &&
(ecif->cif->rtype->type == FFI_TYPE_STRUCT))
{
/* if return type is a struct which is referenced on the stack/reg5,
* by a pointer. Stored the return value pointer in r5.
*/
char* addr = stack_args_p;
memcpy(addr, &(ecif->rvalue), WORD_SIZE);
stack_args_p += WORD_SIZE;
}
if (ecif->avalue == NULL) {
return; /* no arguments to prepare */
}
for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
i++, p_arg++)
{
size_t size = (*p_arg)->size;
int type = (*p_arg)->type;
void* value = p_argv[i];
char* addr = stack_args_p;
int aligned_size = WORD_ALIGN(size);
/* force word alignment on the stack */
stack_args_p += aligned_size;
switch (type)
{
case FFI_TYPE_UINT8:
*(unsigned int *)addr = (unsigned int)*(UINT8*)(value);
break;
case FFI_TYPE_SINT8:
*(signed int *)addr = (signed int)*(SINT8*)(value);
break;
case FFI_TYPE_UINT16:
*(unsigned int *)addr = (unsigned int)*(UINT16*)(value);
break;
case FFI_TYPE_SINT16:
*(signed int *)addr = (signed int)*(SINT16*)(value);
break;
case FFI_TYPE_STRUCT:
#if __BIG_ENDIAN__
/*
* MicroBlaze toolchain appears to emit:
* bsrli r5, r5, 8 (caller)
* ...
* <branch to callee>
* ...
* bslli r5, r5, 8 (callee)
*
* For structs like "struct a { uint8_t a[3]; };", when passed
* by value.
*
* Structs like "struct b { uint16_t a; };" are also expected
* to be packed strangely in registers.
*
* This appears to be because the microblaze toolchain expects
* "struct b == uint16_t", which is only any issue for big
* endian.
*
* The following is a work around for big-endian only, for the
* above mentioned case, it will re-align the contents of a
* <= 3-byte struct value.
*/
if (size < WORD_SIZE)
{
memcpy (addr + (WORD_SIZE - size), value, size);
break;
}
#endif
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_DOUBLE:
default:
memcpy(addr, value, aligned_size);
}
}
}
ffi_status ffi_prep_cif_machdep(ffi_cif* cif)
{
/* check ABI */
switch (cif->abi)
{
case FFI_SYSV:
break;
default:
return FFI_BAD_ABI;
}
return FFI_OK;
}
void ffi_call(ffi_cif* cif, void (*fn)(void), void* rvalue, void** avalue)
{
extended_cif ecif;
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) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
ecif.rvalue = alloca(cif->rtype->size);
} else {
ecif.rvalue = rvalue;
}
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn, cif->rtype->type, cif->rtype->size);
break;
default:
FFI_ASSERT(0);
break;
}
}
void ffi_closure_call_SYSV(void* register_args, void* stack_args,
ffi_closure* closure, void* rvalue,
unsigned int* rtype, unsigned int* rsize)
{
/* prepare arguments for closure call */
ffi_cif* cif = closure->cif;
ffi_type** arg_types = cif->arg_types;
/* re-allocate data for the args. This needs to be done in order to keep
* multi-word objects (e.g. structs) in contiguous memory. Callers are not
* required to store the value of args in the lower 6 words in the stack
* (although they are allocated in the stack).
*/
char* stackclone = alloca(cif->bytes);
void** avalue = alloca(cif->nargs * sizeof(void*));
void* struct_rvalue = NULL;
char* ptr = stackclone;
int i;
/* copy registers into stack clone */
int registers_used = cif->bytes;
if (registers_used > ARGS_REGISTER_SIZE) {
registers_used = ARGS_REGISTER_SIZE;
}
memcpy(stackclone, register_args, registers_used);
/* copy stack allocated args into stack clone */
if (cif->bytes > ARGS_REGISTER_SIZE) {
int stack_used = cif->bytes - ARGS_REGISTER_SIZE;
memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used);
}
/* preserve struct type return pointer passing */
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
struct_rvalue = *((void**)ptr);
ptr += WORD_SIZE;
}
/* populate arg pointer list */
for (i = 0; i < cif->nargs; i++)
{
switch (arg_types[i]->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
#ifdef __BIG_ENDIAN__
avalue[i] = ptr + 3;
#else
avalue[i] = ptr;
#endif
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
#ifdef __BIG_ENDIAN__
avalue[i] = ptr + 2;
#else
avalue[i] = ptr;
#endif
break;
case FFI_TYPE_STRUCT:
#if __BIG_ENDIAN__
/*
* Work around strange ABI behaviour.
* (see info in ffi_prep_args)
*/
if (arg_types[i]->size < WORD_SIZE)
{
memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size);
}
#endif
avalue[i] = (void*)ptr;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
avalue[i] = ptr;
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
default:
/* default 4-byte argument */
avalue[i] = ptr;
break;
}
ptr += WORD_ALIGN(arg_types[i]->size);
}
/* set the return type info passed back to the wrapper */
*rsize = cif->rtype->size;
*rtype = cif->rtype->type;
if (struct_rvalue != NULL) {
closure->fun(cif, struct_rvalue, avalue, closure->user_data);
/* copy struct return pointer value into function return value */
*((void**)rvalue) = struct_rvalue;
} else {
closure->fun(cif, rvalue, avalue, closure->user_data);
}
}
ffi_status ffi_prep_closure_loc(
ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void* user_data, void* codeloc)
{
unsigned long* tramp = (unsigned long*)&(closure->tramp[0]);
unsigned long cls = (unsigned long)codeloc;
unsigned long fn = 0;
unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV;
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
switch (cif->abi)
{
case FFI_SYSV:
fn = (unsigned long)ffi_closure_SYSV;
/* load r11 (temp) with fn */
/* imm fn(upper) */
tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff);
/* addik r11, r0, fn(lower) */
tramp[1] = 0x31600000 | (fn & 0xffff);
/* load r12 (temp) with cls */
/* imm cls(upper) */
tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff);
/* addik r12, r0, cls(lower) */
tramp[3] = 0x31800000 | (cls & 0xffff);
/* load r3 (temp) with ffi_closure_call_SYSV */
/* imm fn_closure_call_sysv(upper) */
tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff);
/* addik r3, r0, fn_closure_call_sysv(lower) */
tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff);
/* branch/jump to address stored in r11 (fn) */
tramp[6] = 0x98085800; /* bra r11 */
break;
default:
return FFI_BAD_ABI;
}
return FFI_OK;
}

View file

@ -0,0 +1,53 @@
/* -----------------------------------------------------------------------
ffitarget.h - Copyright (c) 2012, 2013 Xilinx, Inc
Target configuration macros for MicroBlaze.
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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
/* Definitions for closures */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#define FFI_TRAMPOLINE_SIZE (4*8)
#endif

View file

@ -0,0 +1,302 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc
MicroBlaze 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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
/*
* arg[0] (r5) = ffi_prep_args,
* arg[1] (r6) = &ecif,
* arg[2] (r7) = cif->bytes,
* arg[3] (r8) = cif->flags,
* arg[4] (r9) = ecif.rvalue,
* arg[5] (r10) = fn
* arg[6] (sp[0]) = cif->rtype->type
* arg[7] (sp[4]) = cif->rtype->size
*/
.text
.globl ffi_call_SYSV
.type ffi_call_SYSV, @function
ffi_call_SYSV:
/* push callee saves */
addik r1, r1, -20
swi r19, r1, 0 /* Frame Pointer */
swi r20, r1, 4 /* PIC register */
swi r21, r1, 8 /* PIC register */
swi r22, r1, 12 /* save for locals */
swi r23, r1, 16 /* save for locals */
/* save the r5-r10 registers in the stack */
addik r1, r1, -24 /* increment sp to store 6x 32-bit words */
swi r5, r1, 0
swi r6, r1, 4
swi r7, r1, 8
swi r8, r1, 12
swi r9, r1, 16
swi r10, r1, 20
/* save function pointer */
addik r3, r5, 0 /* copy ffi_prep_args into r3 */
addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */
addik r23, r10, 0 /* save function address into r23 (callee-saved) */
/* prepare stack with allocation for n (bytes = r7) args */
rsub r1, r7, r1 /* subtract bytes from sp */
/* prep args for ffi_prep_args call */
addik r5, r1, 0 /* store stack pointer into arg[0] */
/* r6 still holds ecif for arg[1] */
/* Call ffi_prep_args(stack, &ecif). */
addik r1, r1, -4
swi r15, r1, 0 /* store the link register in the frame */
brald r15, r3
nop /* branch has delay slot */
lwi r15, r1, 0
addik r1, r1, 4 /* restore the link register from the frame */
/* returns calling stack pointer location */
/* prepare args for fn call, prep_args populates them onto the stack */
lwi r5, r1, 0 /* arg[0] */
lwi r6, r1, 4 /* arg[1] */
lwi r7, r1, 8 /* arg[2] */
lwi r8, r1, 12 /* arg[3] */
lwi r9, r1, 16 /* arg[4] */
lwi r10, r1, 20 /* arg[5] */
/* call (fn) (...). */
addik r1, r1, -4
swi r15, r1, 0 /* store the link register in the frame */
brald r15, r23
nop /* branch has delay slot */
lwi r15, r1, 0
addik r1, r1, 4 /* restore the link register from the frame */
/* Remove the space we pushed for the args. */
addik r1, r22, 0 /* restore old SP */
/* restore this functions parameters */
lwi r5, r1, 0 /* arg[0] */
lwi r6, r1, 4 /* arg[1] */
lwi r7, r1, 8 /* arg[2] */
lwi r8, r1, 12 /* arg[3] */
lwi r9, r1, 16 /* arg[4] */
lwi r10, r1, 20 /* arg[5] */
addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */
/* If the return value pointer is NULL, assume no return value. */
beqi r9, ffi_call_SYSV_end
lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */
lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7]) */
/* Check if return type is actually a struct, do nothing */
rsubi r11, r22, FFI_TYPE_STRUCT
beqi r11, ffi_call_SYSV_end
/* Return 8bit */
rsubi r11, r23, 1
beqi r11, ffi_call_SYSV_store8
/* Return 16bit */
rsubi r11, r23, 2
beqi r11, ffi_call_SYSV_store16
/* Return 32bit */
rsubi r11, r23, 4
beqi r11, ffi_call_SYSV_store32
/* Return 64bit */
rsubi r11, r23, 8
beqi r11, ffi_call_SYSV_store64
/* Didn't match anything */
bri ffi_call_SYSV_end
ffi_call_SYSV_store64:
swi r3, r9, 0 /* store word r3 into return value */
swi r4, r9, 4 /* store word r4 into return value */
bri ffi_call_SYSV_end
ffi_call_SYSV_store32:
swi r3, r9, 0 /* store word r3 into return value */
bri ffi_call_SYSV_end
ffi_call_SYSV_store16:
#ifdef __BIG_ENDIAN__
shi r3, r9, 2 /* store half-word r3 into return value */
#else
shi r3, r9, 0 /* store half-word r3 into return value */
#endif
bri ffi_call_SYSV_end
ffi_call_SYSV_store8:
#ifdef __BIG_ENDIAN__
sbi r3, r9, 3 /* store byte r3 into return value */
#else
sbi r3, r9, 0 /* store byte r3 into return value */
#endif
bri ffi_call_SYSV_end
ffi_call_SYSV_end:
/* callee restores */
lwi r19, r1, 0 /* frame pointer */
lwi r20, r1, 4 /* PIC register */
lwi r21, r1, 8 /* PIC register */
lwi r22, r1, 12
lwi r23, r1, 16
addik r1, r1, 20
/* return from sub-routine (with delay slot) */
rtsd r15, 8
nop
.size ffi_call_SYSV, . - ffi_call_SYSV
/* ------------------------------------------------------------------------- */
/*
* args passed into this function, are passed down to the callee.
* this function is the target of the closure trampoline, as such r12 is
* a pointer to the closure object.
*/
.text
.globl ffi_closure_SYSV
.type ffi_closure_SYSV, @function
ffi_closure_SYSV:
/* push callee saves */
addik r11, r1, 28 /* save stack args start location (excluding regs/link) */
addik r1, r1, -12
swi r19, r1, 0 /* Frame Pointer */
swi r20, r1, 4 /* PIC register */
swi r21, r1, 8 /* PIC register */
/* store register args on stack */
addik r1, r1, -24
swi r5, r1, 0
swi r6, r1, 4
swi r7, r1, 8
swi r8, r1, 12
swi r9, r1, 16
swi r10, r1, 20
/* setup args */
addik r5, r1, 0 /* register_args */
addik r6, r11, 0 /* stack_args */
addik r7, r12, 0 /* closure object */
addik r1, r1, -8 /* allocate return value */
addik r8, r1, 0 /* void* rvalue */
addik r1, r1, -8 /* allocate for return type/size values */
addik r9, r1, 0 /* void* rtype */
addik r10, r1, 4 /* void* rsize */
/* call the wrap_call function */
addik r1, r1, -28 /* allocate args + link reg */
swi r15, r1, 0 /* store the link register in the frame */
brald r15, r3
nop /* branch has delay slot */
lwi r15, r1, 0
addik r1, r1, 28 /* restore the link register from the frame */
ffi_closure_SYSV_prepare_return:
lwi r9, r1, 0 /* rtype */
lwi r10, r1, 4 /* rsize */
addik r1, r1, 8 /* de-allocate return info values */
/* Check if return type is actually a struct, store 4 bytes */
rsubi r11, r9, FFI_TYPE_STRUCT
beqi r11, ffi_closure_SYSV_store32
/* Return 8bit */
rsubi r11, r10, 1
beqi r11, ffi_closure_SYSV_store8
/* Return 16bit */
rsubi r11, r10, 2
beqi r11, ffi_closure_SYSV_store16
/* Return 32bit */
rsubi r11, r10, 4
beqi r11, ffi_closure_SYSV_store32
/* Return 64bit */
rsubi r11, r10, 8
beqi r11, ffi_closure_SYSV_store64
/* Didn't match anything */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store64:
lwi r3, r1, 0 /* store word r3 into return value */
lwi r4, r1, 4 /* store word r4 into return value */
/* 64 bits == 2 words, no sign extend occurs */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store32:
lwi r3, r1, 0 /* store word r3 into return value */
/* 32 bits == 1 word, no sign extend occurs */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store16:
#ifdef __BIG_ENDIAN__
lhui r3, r1, 2 /* store half-word r3 into return value */
#else
lhui r3, r1, 0 /* store half-word r3 into return value */
#endif
rsubi r11, r9, FFI_TYPE_SINT16
bnei r11, ffi_closure_SYSV_end
sext16 r3, r3 /* fix sign extend of sint8 */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store8:
#ifdef __BIG_ENDIAN__
lbui r3, r1, 3 /* store byte r3 into return value */
#else
lbui r3, r1, 0 /* store byte r3 into return value */
#endif
rsubi r11, r9, FFI_TYPE_SINT8
bnei r11, ffi_closure_SYSV_end
sext8 r3, r3 /* fix sign extend of sint8 */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_end:
addik r1, r1, 8 /* de-allocate return value */
/* de-allocate stored args */
addik r1, r1, 24
/* callee restores */
lwi r19, r1, 0 /* frame pointer */
lwi r20, r1, 4 /* PIC register */
lwi r21, r1, 8 /* PIC register */
addik r1, r1, 12
/* return from sub-routine (with delay slot) */
rtsd r15, 8
nop
.size ffi_closure_SYSV, . - ffi_closure_SYSV

View file

@ -170,7 +170,14 @@ static void ffi_prep_args(char *stack,
break;
case FFI_TYPE_UINT32:
#ifdef FFI_MIPS_N32
/* The N32 ABI requires that 32-bit integers
be sign-extended to 64-bits, regardless of
whether they are signed or unsigned. */
*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
#else
*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
#endif
break;
/* This can only happen with 64bit slots. */

View file

@ -108,10 +108,8 @@ loadregs:
REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
and t4, t6, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg1_floatp
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
b arg1_next
arg1_floatp:
beqz t4, arg1_next
bne t4, FFI_TYPE_FLOAT, arg1_doublep
l.s $f12, 0*FFI_SIZEOF_ARG(t9)
b arg1_next
@ -121,10 +119,8 @@ arg1_next:
SRL t4, t6, 1*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg2_floatp
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
b arg2_next
arg2_floatp:
beqz t4, arg2_next
bne t4, FFI_TYPE_FLOAT, arg2_doublep
l.s $f13, 1*FFI_SIZEOF_ARG(t9)
b arg2_next
@ -134,10 +130,8 @@ arg2_next:
SRL t4, t6, 2*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg3_floatp
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
b arg3_next
arg3_floatp:
beqz t4, arg3_next
bne t4, FFI_TYPE_FLOAT, arg3_doublep
l.s $f14, 2*FFI_SIZEOF_ARG(t9)
b arg3_next
@ -147,10 +141,8 @@ arg3_next:
SRL t4, t6, 3*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg4_floatp
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
b arg4_next
arg4_floatp:
beqz t4, arg4_next
bne t4, FFI_TYPE_FLOAT, arg4_doublep
l.s $f15, 3*FFI_SIZEOF_ARG(t9)
b arg4_next
@ -160,10 +152,8 @@ arg4_next:
SRL t4, t6, 4*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg5_floatp
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
b arg5_next
arg5_floatp:
beqz t4, arg5_next
bne t4, FFI_TYPE_FLOAT, arg5_doublep
l.s $f16, 4*FFI_SIZEOF_ARG(t9)
b arg5_next
@ -173,10 +163,8 @@ arg5_next:
SRL t4, t6, 5*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg6_floatp
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
b arg6_next
arg6_floatp:
beqz t4, arg6_next
bne t4, FFI_TYPE_FLOAT, arg6_doublep
l.s $f17, 5*FFI_SIZEOF_ARG(t9)
b arg6_next
@ -186,10 +174,8 @@ arg6_next:
SRL t4, t6, 6*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg7_floatp
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
b arg7_next
arg7_floatp:
beqz t4, arg7_next
bne t4, FFI_TYPE_FLOAT, arg7_doublep
l.s $f18, 6*FFI_SIZEOF_ARG(t9)
b arg7_next
@ -199,10 +185,8 @@ arg7_next:
SRL t4, t6, 7*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
bnez t4, arg8_floatp
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
b arg8_next
arg8_floatp:
beqz t4, arg8_next
bne t4, FFI_TYPE_FLOAT, arg8_doublep
l.s $f19, 7*FFI_SIZEOF_ARG(t9)
b arg8_next

101
libffi/src/moxie/eabi.S Normal file
View file

@ -0,0 +1,101 @@
/* -----------------------------------------------------------------------
eabi.S - Copyright (c) 2012, 2013 Anthony Green
Moxie Assembly glue.
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 THE AUTHOR 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.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
.globl ffi_prep_args_EABI
.text
.p2align 4
.globl ffi_call_EABI
.type ffi_call_EABI, @function
# $r0 : ffi_prep_args
# $r1 : &ecif
# $r2 : cif->bytes
# $r3 : fig->flags
# $r4 : ecif.rvalue
# $r5 : fn
ffi_call_EABI:
push $sp, $r6
push $sp, $r7
push $sp, $r8
dec $sp, 24
/* Store incoming args on stack. */
sto.l 0($sp), $r0 /* ffi_prep_args */
sto.l 4($sp), $r1 /* ecif */
sto.l 8($sp), $r2 /* bytes */
sto.l 12($sp), $r3 /* flags */
sto.l 16($sp), $r4 /* &rvalue */
sto.l 20($sp), $r5 /* fn */
/* Call ffi_prep_args. */
mov $r6, $r4 /* Save result buffer */
mov $r7, $r5 /* Save the target fn */
mov $r8, $r3 /* Save the flags */
sub.l $sp, $r2 /* Allocate stack space */
mov $r0, $sp /* We can stomp over $r0 */
/* $r1 is already set up */
jsra ffi_prep_args
/* Load register arguments. */
ldo.l $r0, 0($sp)
ldo.l $r1, 4($sp)
ldo.l $r2, 8($sp)
ldo.l $r3, 12($sp)
ldo.l $r4, 16($sp)
ldo.l $r5, 20($sp)
/* Call the target function. */
jsr $r7
ldi.l $r7, 0xffffffff
cmp $r8, $r7
beq retstruct
ldi.l $r7, 4
cmp $r8, $r7
bgt ret2reg
st.l ($r6), $r0
jmpa retdone
ret2reg:
st.l ($r6), $r0
sto.l 4($r6), $r1
retstruct:
retdone:
/* Return. */
ldo.l $r6, -4($fp)
ldo.l $r7, -8($fp)
ldo.l $r8, -12($fp)
ret
.size ffi_call_EABI, .-ffi_call_EABI

272
libffi/src/moxie/ffi.c Normal file
View file

@ -0,0 +1,272 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (C) 2012, 2013 Anthony Green
Moxie 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 THE AUTHORS OR COPYRIGHT
HOLDERS 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 */
void *ffi_prep_args(char *stack, extended_cif *ecif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
register int count = 0;
p_argv = ecif->avalue;
argp = stack;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
{
*(void **) argp = ecif->rvalue;
argp += 4;
}
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0);
i--, p_arg++)
{
size_t z;
z = (*p_arg)->size;
if ((*p_arg)->type == FFI_TYPE_STRUCT)
{
z = sizeof(void*);
*(void **) argp = *p_argv;
}
else if (z < sizeof(int))
{
z = sizeof(int);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
break;
default:
FFI_ASSERT(0);
}
}
else if (z == sizeof(int))
{
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
}
else
{
memcpy(argp, *p_argv, z);
}
p_argv++;
argp += z;
count += z;
}
return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
if (cif->rtype->type == FFI_TYPE_STRUCT)
cif->flags = -1;
else
cif->flags = cif->rtype->size;
cif->bytes = ALIGN (cif->bytes, 8);
return FFI_OK;
}
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
extended_cif *,
unsigned, unsigned,
unsigned *,
void (*fn)(void));
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue)
{
extended_cif ecif;
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) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
}
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_EABI:
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
default:
FFI_ASSERT(0);
break;
}
}
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
unsigned arg4, unsigned arg5, unsigned arg6)
{
/* This function is called by a trampoline. The trampoline stows a
pointer to the ffi_closure object in $r7. We must save this
pointer in a place that will persist while we do our work. */
register ffi_closure *creg __asm__ ("$r12");
ffi_closure *closure = creg;
/* Arguments that don't fit in registers are found on the stack
at a fixed offset above the current frame pointer. */
register char *frame_pointer __asm__ ("$fp");
/* Pointer to a struct return value. */
void *struct_rvalue = (void *) arg1;
/* 6 words reserved for register args + 3 words from jsr */
char *stack_args = frame_pointer + 9*4;
/* Lay the register arguments down in a continuous chunk of memory. */
unsigned register_args[6] =
{ arg1, arg2, arg3, arg4, arg5, arg6 };
char *register_args_ptr = (char *) register_args;
ffi_cif *cif = closure->cif;
ffi_type **arg_types = cif->arg_types;
void **avalue = alloca (cif->nargs * sizeof(void *));
char *ptr = (char *) register_args;
int i;
/* preserve struct type return pointer passing */
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
ptr += 4;
register_args_ptr = (char *)&register_args[1];
}
/* Find the address of each argument. */
for (i = 0; i < cif->nargs; i++)
{
switch (arg_types[i]->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
avalue[i] = ptr + 3;
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
avalue[i] = ptr + 2;
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
case FFI_TYPE_POINTER:
avalue[i] = ptr;
break;
case FFI_TYPE_STRUCT:
avalue[i] = *(void**)ptr;
break;
default:
/* This is an 8-byte value. */
avalue[i] = ptr;
ptr += 4;
break;
}
ptr += 4;
/* If we've handled more arguments than fit in registers,
start looking at the those passed on the stack. */
if (ptr == &register_args[6])
ptr = stack_args;
}
/* Invoke the closure. */
if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
{
(closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
}
else
{
/* Allocate space for the return value and call the function. */
long long rvalue;
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue));
}
}
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data,
void *codeloc)
{
unsigned short *tramp = (unsigned short *) &closure->tramp[0];
unsigned long fn = (long) ffi_closure_eabi;
unsigned long cls = (long) codeloc;
if (cif->abi != FFI_EABI)
return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_eabi;
tramp[0] = 0x01e0; /* ldi.l $r7, .... */
tramp[1] = cls >> 16;
tramp[2] = cls & 0xffff;
tramp[3] = 0x1a00; /* jmpa .... */
tramp[4] = fn >> 16;
tramp[5] = fn & 0xffff;
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}

View file

@ -0,0 +1,52 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2012, 2013 Anthony Green
Target configuration macros for Moxie
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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
/* ---- System specific configurations ----------------------------------- */
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_EABI,
FFI_DEFAULT_ABI = FFI_EABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
/* Trampolines are 12-bytes long. See ffi_prep_closure_loc. */
#define FFI_TRAMPOLINE_SIZE (12)
#endif

304
libffi/src/nios2/ffi.c Normal file
View file

@ -0,0 +1,304 @@
/* libffi support for Altera Nios II.
Copyright (c) 2013 Mentor Graphics.
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 THE AUTHORS OR COPYRIGHT HOLDERS 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>
/* The Nios II Processor Reference Handbook defines the procedure call
ABI as follows.
Arguments are passed as if a structure containing the types of
the arguments were constructed. The first 16 bytes are passed in r4
through r7, the remainder on the stack. The first 16 bytes of a function
taking variable arguments are passed in r4-r7 in the same way.
Return values of types up to 8 bytes are returned in r2 and r3. For
return values greater than 8 bytes, the caller must allocate memory for
the result and pass the address as if it were argument 0.
While this isn't specified explicitly in the ABI documentation, GCC
promotes integral arguments smaller than int size to 32 bits.
Also of note, the ABI specifies that all structure objects are
aligned to 32 bits even if all their fields have a smaller natural
alignment. See FFI_AGGREGATE_ALIGNMENT. */
/* Declare the assembly language hooks. */
extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
extended_cif *,
unsigned,
void (*fn) (void));
extern void ffi_closure_sysv (void);
/* Perform machine-dependent cif processing. */
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
{
/* We always want at least 16 bytes in the parameter block since it
simplifies the low-level call function. Also round the parameter
block size up to a multiple of 4 bytes to preserve
32-bit alignment of the stack pointer. */
if (cif->bytes < 16)
cif->bytes = 16;
else
cif->bytes = (cif->bytes + 3) & ~3;
return FFI_OK;
}
/* ffi_prep_args is called by the assembly routine to transfer arguments
to the stack using the pointers in the ecif array.
Note that the stack buffer is big enough to fit all the arguments,
but the first 16 bytes will be copied to registers for the actual
call. */
void ffi_prep_args (char *stack, extended_cif *ecif)
{
char *argp = stack;
unsigned int i;
/* The implicit return value pointer is passed as if it were a hidden
first argument. */
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
&& ecif->cif->rtype->size > 8)
{
(*(void **) argp) = ecif->rvalue;
argp += 4;
}
for (i = 0; i < ecif->cif->nargs; i++)
{
void *avalue = ecif->avalue[i];
ffi_type *atype = ecif->cif->arg_types[i];
size_t size = atype->size;
size_t alignment = atype->alignment;
/* Align argp as appropriate for the argument type. */
if ((alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, alignment);
/* Copy the argument, promoting integral types smaller than a
word to word size. */
if (size < sizeof (int))
{
size = sizeof (int);
switch (atype->type)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int) *(SINT8 *) avalue;
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int) *(SINT16 *) avalue;
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
break;
case FFI_TYPE_STRUCT:
memcpy (argp, avalue, atype->size);
break;
default:
FFI_ASSERT(0);
}
}
else if (size == sizeof (int))
*(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
else
memcpy (argp, avalue, size);
argp += size;
}
}
/* Call FN using the prepared CIF. RVALUE points to space allocated by
the caller for the return value, and AVALUE is an array of argument
pointers. */
void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
{
extended_cif ecif;
UINT64 result;
/* If bigret is true, this is the case where a return value of larger
than 8 bytes is handled by being passed by reference as an implicit
argument. */
int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
&& cif->rtype->size > 8);
ecif.cif = cif;
ecif.avalue = avalue;
/* Allocate space for return value if this is the pass-by-reference case
and the caller did not provide a buffer. */
if (rvalue == NULL && bigret)
ecif.rvalue = alloca (cif->rtype->size);
else
ecif.rvalue = rvalue;
result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
/* Now result contains the 64 bit contents returned from fn in
r2 and r3. Copy the value of the appropriate size to the user-provided
rvalue buffer. */
if (rvalue && !bigret)
switch (cif->rtype->size)
{
case 1:
*(UINT8 *)rvalue = (UINT8) result;
break;
case 2:
*(UINT16 *)rvalue = (UINT16) result;
break;
case 4:
*(UINT32 *)rvalue = (UINT32) result;
break;
case 8:
*(UINT64 *)rvalue = (UINT64) result;
break;
default:
memcpy (rvalue, (void *)&result, cif->rtype->size);
break;
}
}
/* This function is invoked from the closure trampoline to invoke
CLOSURE with argument block ARGS. Parse ARGS according to
CLOSURE->cfi and invoke CLOSURE->fun. */
static UINT64
ffi_closure_helper (unsigned char *args,
ffi_closure *closure)
{
ffi_cif *cif = closure->cif;
unsigned char *argp = args;
void **parsed_args = alloca (cif->nargs * sizeof (void *));
UINT64 result;
void *retptr;
unsigned int i;
/* First figure out what to do about the return type. If this is the
big-structure-return case, the first arg is the hidden return buffer
allocated by the caller. */
if (cif->rtype->type == FFI_TYPE_STRUCT
&& cif->rtype->size > 8)
{
retptr = *((void **) argp);
argp += 4;
}
else
retptr = (void *) &result;
/* Fill in the array of argument pointers. */
for (i = 0; i < cif->nargs; i++)
{
size_t size = cif->arg_types[i]->size;
size_t alignment = cif->arg_types[i]->alignment;
/* Align argp as appropriate for the argument type. */
if ((alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, alignment);
/* Arguments smaller than an int are promoted to int. */
if (size < sizeof (int))
size = sizeof (int);
/* Store the pointer. */
parsed_args[i] = argp;
argp += size;
}
/* Call the user-supplied function. */
(closure->fun) (cif, retptr, parsed_args, closure->user_data);
return result;
}
/* Initialize CLOSURE with a trampoline to call FUN with
CIF and USER_DATA. */
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun) (ffi_cif*, void*, void**, void*),
void *user_data,
void *codeloc)
{
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
int i;
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
/* The trampoline looks like:
movhi r8, %hi(ffi_closure_sysv)
ori r8, r8, %lo(ffi_closure_sysv)
movhi r9, %hi(ffi_closure_helper)
ori r0, r9, %lo(ffi_closure_helper)
movhi r10, %hi(closure)
ori r10, r10, %lo(closure)
jmp r8
and then ffi_closure_sysv retrieves the closure pointer out of r10
in addition to the arguments passed in the normal way for the call,
and invokes ffi_closure_helper. We encode the pointer to
ffi_closure_helper in the trampoline because making a PIC call
to it in ffi_closure_sysv would be messy (it would have to indirect
through the GOT). */
#define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
#define LO(x) (((unsigned int) (x)) & 0xffff)
tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
#undef HI
#undef LO
/* Flush the caches.
See Example 9-4 in the Nios II Software Developer's Handbook. */
for (i = 0; i < 7; i++)
asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
asm volatile ("flushp" ::: "memory");
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}

View file

@ -0,0 +1,52 @@
/* libffi target includes for Altera Nios II.
Copyright (c) 2013 Mentor Graphics.
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 THE AUTHORS OR COPYRIGHT HOLDERS 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. */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
/* Structures have a 4-byte alignment even if all the fields have lesser
alignment requirements. */
#define FFI_AGGREGATE_ALIGNMENT 4
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 28 /* 7 instructions */
#define FFI_NATIVE_RAW_API 0
#endif

136
libffi/src/nios2/sysv.S Normal file
View file

@ -0,0 +1,136 @@
/* Low-level libffi support for Altera Nios II.
Copyright (c) 2013 Mentor Graphics.
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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/* This function is declared on the C side as
extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *),
extended_cif *ecif,
unsigned nbytes,
void (*fn) (void));
On input, the arguments appear as
r4 = arghook
r5 = ecif
r6 = nbytes
r7 = fn
*/
.section .text
.align 2
.global ffi_call_sysv
.type ffi_call_sysv, @function
ffi_call_sysv:
.cfi_startproc
/* Create the stack frame, saving r16 so we can use it locally. */
addi sp, sp, -12
.cfi_def_cfa_offset 12
stw ra, 8(sp)
stw fp, 4(sp)
stw r16, 0(sp)
.cfi_offset 31, -4
.cfi_offset 28, -8
.cfi_offset 16, -12
mov fp, sp
.cfi_def_cfa_register 28
mov r16, r7
/* Adjust the stack pointer to create the argument buffer
nbytes long. */
sub sp, sp, r6
/* Call the arghook function. */
mov r2, r4 /* fn */
mov r4, sp /* argbuffer */
callr r2 /* r5 already contains ecif */
/* Pop off the first 16 bytes of the argument buffer on the stack,
transferring the contents to the argument registers. */
ldw r4, 0(sp)
ldw r5, 4(sp)
ldw r6, 8(sp)
ldw r7, 12(sp)
addi sp, sp, 16
/* Call the user function, which leaves its result in r2 and r3. */
callr r16
/* Pop off the stack frame. */
mov sp, fp
ldw ra, 8(sp)
ldw fp, 4(sp)
ldw r16, 0(sp)
addi sp, sp, 12
ret
.cfi_endproc
.size ffi_call_sysv, .-ffi_call_sysv
/* Closure trampolines jump here after putting the C helper address
in r9 and the closure pointer in r10. The user-supplied arguments
to the closure are in the normal places, in r4-r7 and on the
stack. Push the register arguments on the stack too and then call the
C helper function to deal with them. */
.section .text
.align 2
.global ffi_closure_sysv
.type ffi_closure_sysv, @function
ffi_closure_sysv:
.cfi_startproc
/* Create the stack frame, pushing the register args on the stack
just below the stack args. This is the same trick illustrated
in Figure 7-3 in the Nios II Processor Reference Handbook, used
for variable arguments and structures passed by value. */
addi sp, sp, -20
.cfi_def_cfa_offset 20
stw ra, 0(sp)
.cfi_offset 31, -20
stw r4, 4(sp)
.cfi_offset 4, -16
stw r5, 8(sp)
.cfi_offset 5, -12
stw r6, 12(sp)
.cfi_offset 6, -8
stw r7, 16(sp)
.cfi_offset 7, -4
/* Call the helper.
r4 = pointer to arguments on stack
r5 = closure pointer (loaded in r10 by the trampoline)
r9 = address of helper function (loaded by trampoline) */
addi r4, sp, 4
mov r5, r10
callr r9
/* Pop the stack and return. */
ldw ra, 0(sp)
addi sp, sp, 20
.cfi_def_cfa_offset -20
ret
.cfi_endproc
.size ffi_closure_sysv, .-ffi_closure_sysv

328
libffi/src/or1k/ffi.c Normal file
View file

@ -0,0 +1,328 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
OpenRISC 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 THE AUTHORS OR COPYRIGHT
HOLDERS 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"
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
void* ffi_prep_args(char *stack, extended_cif *ecif)
{
char *stacktemp = stack;
int i, s;
ffi_type **arg;
int count = 0;
int nfixedargs;
nfixedargs = ecif->cif->nfixedargs;
arg = ecif->cif->arg_types;
void **argv = ecif->avalue;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
{
*(void **) stack = ecif->rvalue;
stack += 4;
count = 4;
}
for(i=0; i<ecif->cif->nargs; i++)
{
/* variadic args are saved on stack */
if ((nfixedargs == 0) && (count < 24))
{
count = 24;
stack = stacktemp + 24;
}
nfixedargs--;
s = 4;
switch((*arg)->type)
{
case FFI_TYPE_STRUCT:
*(void **)stack = *argv;
break;
case FFI_TYPE_SINT8:
*(signed int *) stack = (signed int)*(SINT8 *)(* argv);
break;
case FFI_TYPE_UINT8:
*(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv);
break;
case FFI_TYPE_SINT16:
*(signed int *) stack = (signed int)*(SINT16 *)(* argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv);
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
case FFI_TYPE_POINTER:
*(int *)stack = *(int*)(*argv);
break;
default: /* 8 byte types */
if (count == 20) /* never split arguments */
{
stack += 4;
count += 4;
}
s = (*arg)->size;
memcpy(stack, *argv, s);
break;
}
stack += s;
count += s;
argv++;
arg++;
}
return stacktemp + ((count>24)?24:0);
}
extern void ffi_call_SYSV(unsigned,
extended_cif *,
void *(*)(int *, extended_cif *),
unsigned *,
void (*fn)(void),
unsigned);
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
int i;
int size;
ffi_type **arg;
/* Calculate size to allocate on stack */
for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++)
{
if ((*arg)->type == FFI_TYPE_STRUCT)
size += 4;
else
if ((*arg)->size <= 4)
size += 4;
else
size += 8;
}
/* for variadic functions more space is needed on the stack */
if (cif->nargs != cif->nfixedargs)
size += 24;
if (cif->rtype->type == FFI_TYPE_STRUCT)
size += 4;
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags);
break;
default:
FFI_ASSERT(0);
break;
}
}
void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8)
{
register int *sp __asm__ ("r17");
register int *r13 __asm__ ("r13");
ffi_closure* closure = (ffi_closure*) r13;
char *stack_args = sp;
/* Lay the register arguments down in a continuous chunk of memory. */
unsigned register_args[6] =
{ r3, r4, r5, r6, r7, r8 };
/* Pointer to a struct return value. */
void *struct_rvalue = (void *) r3;
ffi_cif *cif = closure->cif;
ffi_type **arg_types = cif->arg_types;
void **avalue = alloca (cif->nargs * sizeof(void *));
char *ptr = (char *) register_args;
int count = 0;
int nfixedargs = cif->nfixedargs;
int i;
/* preserve struct type return pointer passing */
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
{
ptr += 4;
count = 4;
}
/* Find the address of each argument. */
for (i = 0; i < cif->nargs; i++)
{
/* variadic args are saved on stack */
if ((nfixedargs == 0) && (count < 24))
{
ptr = stack_args;
count = 24;
}
nfixedargs--;
switch (arg_types[i]->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
avalue[i] = ptr + 3;
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
avalue[i] = ptr + 2;
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
case FFI_TYPE_POINTER:
avalue[i] = ptr;
break;
case FFI_TYPE_STRUCT:
avalue[i] = *(void**)ptr;
break;
default:
/* 8-byte values */
/* arguments are never splitted */
if (ptr == &register_args[5])
ptr = stack_args;
avalue[i] = ptr;
ptr += 4;
count += 4;
break;
}
ptr += 4;
count += 4;
/* If we've handled more arguments than fit in registers,
start looking at the those passed on the stack. */
if (count == 24)
ptr = stack_args;
}
if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
{
(closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
} else
{
long long rvalue;
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
if (cif->rtype)
asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue));
}
}
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
unsigned short *tramp = (unsigned short *) closure->tramp;
unsigned long fn = (unsigned long) ffi_closure_SYSV;
unsigned long cls = (unsigned long) codeloc;
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
/* write pointers to temporary registers */
tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */
tramp[1] = cls >> 16;
tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */
tramp[3] = cls & 0xFFFF;
tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */
tramp[5] = fn >> 16;
tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */
tramp[7] = fn & 0xFFFF;
tramp[8] = (0x11 << 10); /* l.jr r15 */
tramp[9] = 15 << 11;
tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */
tramp[11] = 0x0;
return FFI_OK;
}
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
{
cif->flags = 0;
/* structures are returned as pointers */
if (cif->rtype->type == FFI_TYPE_STRUCT)
cif->flags = FFI_TYPE_STRUCT;
else
if (cif->rtype->size > 4)
cif->flags = FFI_TYPE_UINT64;
cif->nfixedargs = cif->nargs;
return FFI_OK;
}
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs, unsigned int ntotalargs)
{
ffi_status status;
status = ffi_prep_cif_machdep (cif);
cif->nfixedargs = nfixedargs;
return status;
}

View file

@ -0,0 +1,58 @@
/* -----------------------------------------------------------------------
ffitarget.h - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
OpenRISC Target configuration macros
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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
/* ---- System specific configurations ----------------------------------- */
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#define FFI_TRAMPOLINE_SIZE (24)
#define FFI_TARGET_SPECIFIC_VARIADIC 1
#define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs;
#endif

107
libffi/src/or1k/sysv.S Normal file
View file

@ -0,0 +1,107 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
OpenRISC 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 THE AUTHORS OR COPYRIGHT
HOLDERS 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.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
.text
.globl ffi_call_SYSV
.type ffi_call_SYSV, @function
/*
r3: size to allocate on stack
r4: extended cif structure
r5: function pointer ffi_prep_args
r6: ret address
r7: function to call
r8: flag for return type
*/
ffi_call_SYSV:
/* Store registers used on stack */
l.sw -4(r1), r9 /* return address */
l.sw -8(r1), r1 /* stack address */
l.sw -12(r1), r14 /* callee saved registers */
l.sw -16(r1), r16
l.sw -20(r1), r18
l.sw -24(r1), r20
l.ori r14, r1, 0x0 /* save stack pointer */
l.addi r1, r1, -24
l.ori r16, r7, 0x0 /* save function address */
l.ori r18, r6, 0x0 /* save ret address */
l.ori r20, r8, 0x0 /* save flag */
l.sub r1, r1, r3 /* reserve space on stack */
/* Call ffi_prep_args */
l.ori r3, r1, 0x0 /* first argument stack address, second already ecif */
l.jalr r5
l.nop
/* Load register arguments and call*/
l.lwz r3, 0(r1)
l.lwz r4, 4(r1)
l.lwz r5, 8(r1)
l.lwz r6, 12(r1)
l.lwz r7, 16(r1)
l.lwz r8, 20(r1)
l.ori r1, r11, 0x0 /* new stack pointer */
l.jalr r16
l.nop
/* handle return values */
l.sfeqi r20, FFI_TYPE_STRUCT
l.bf ret /* structs don't return an rvalue */
l.nop
/* copy ret address */
l.sfeqi r20, FFI_TYPE_UINT64
l.bnf four_byte_ret /* 8 byte value is returned */
l.nop
l.sw 4(r18), r12
four_byte_ret:
l.sw 0(r18), r11
ret:
/* return */
l.ori r1, r14, 0x0 /* reset stack pointer */
l.lwz r9, -4(r1)
l.lwz r1, -8(r1)
l.lwz r14, -12(r1)
l.lwz r16, -16(r1)
l.lwz r18, -20(r1)
l.lwz r20, -24(r1)
l.jr r9
l.nop
.size ffi_call_SYSV, .-ffi_call_SYSV

View file

@ -62,6 +62,8 @@ typedef enum ffi_abi {
} ffi_abi;
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1

View file

@ -137,7 +137,7 @@ ffi_call_AIX:
mtcrf 0x40, r31
mtctr r0
/* Load all those argument registers. */
// We have set up a nice stack frame, just load it into registers.
/* We have set up a nice stack frame, just load it into registers. */
ld r3, 40+(1*8)(r1)
ld r4, 40+(2*8)(r1)
ld r5, 40+(3*8)(r1)
@ -150,7 +150,7 @@ ffi_call_AIX:
L1:
/* Load all the FP registers. */
bf 6,L2 // 2f + 0x18
bf 6,L2 /* 2f + 0x18 */
lfd f1,-32-(13*8)(r28)
lfd f2,-32-(12*8)(r28)
lfd f3,-32-(11*8)(r28)
@ -239,7 +239,7 @@ L(float_return_value):
mtcrf 0x40, r31
mtctr r0
/* Load all those argument registers. */
// We have set up a nice stack frame, just load it into registers.
/* We have set up a nice stack frame, just load it into registers. */
lwz r3, 20+(1*4)(r1)
lwz r4, 20+(2*4)(r1)
lwz r5, 20+(3*4)(r1)
@ -252,7 +252,7 @@ L(float_return_value):
L1:
/* Load all the FP registers. */
bf 6,L2 // 2f + 0x18
bf 6,L2 /* 2f + 0x18 */
lfd f1,-16-(13*8)(r28)
lfd f2,-16-(12*8)(r28)
lfd f3,-16-(11*8)(r28)
@ -307,7 +307,7 @@ L(float_return_value):
#endif
.long 0
.byte 0,0,0,1,128,4,0,0
//END(ffi_call_AIX)
/* END(ffi_call_AIX) */
.csect .text[PR]
.align 2
@ -325,4 +325,4 @@ ffi_call_DARWIN:
blr
.long 0
.byte 0,0,0,0,0,0,0,0
//END(ffi_call_DARWIN)
/* END(ffi_call_DARWIN) */

View file

@ -318,11 +318,6 @@ _ffi_call_AIX:
#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
.static_data
.align LOG2_GPR_BYTES
LLFB0$non_lazy_ptr:
.g_long Lstartcode
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
@ -335,7 +330,7 @@ LSCIE1:
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x10 ; FDE Encoding (indirect pcrel)
.byte 0x10 ; FDE Encoding (pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
@ -349,7 +344,7 @@ LSFDE1:
.long L$set$1 ; FDE Length
LASFDE1:
.long LASFDE1-EH_frame1 ; FDE CIE offset
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
.g_long Lstartcode-. ; FDE initial location
.set L$set$3,LFE1-Lstartcode
.g_long L$set$3 ; FDE address range
.byte 0x0 ; uleb128 0x0; Augmentation size

View file

@ -192,7 +192,7 @@ LCFI1:
lg r0,0(r3) ; size => r0
lhz r3,FFI_TYPE_TYPE(r3) ; type => r3
/* The helper will have intercepted struture returns and inserted
/* The helper will have intercepted structure returns and inserted
the caller`s destination address for structs returned by ref. */
/* r3 contains the return type so use it to look up in a table
@ -467,11 +467,6 @@ Lendcode:
#define EH_FRAME_OFFSETA MODE_CHOICE(176,0x90)
#define EH_FRAME_OFFSETB MODE_CHOICE(1,3)
.static_data
.align LOG2_GPR_BYTES
LLFB1$non_lazy_ptr:
.g_long Lstartcode
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
@ -484,7 +479,7 @@ LSCIE1:
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x10 ; FDE Encoding (indirect pcrel)
.byte 0x10 ; FDE Encoding (pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
@ -498,7 +493,7 @@ LSFDE1:
LASFDE1:
.long LASFDE1-EH_frame1 ; FDE CIE offset
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
.g_long Lstartcode-. ; FDE initial location
.set L$set$3,LFE1-Lstartcode
.g_long L$set$3 ; FDE address range
.byte 0x0 ; uleb128 0x0; Augmentation size
@ -523,12 +518,12 @@ LEFDE1:
L_ffi_closure_helper_DARWIN$stub:
.indirect_symbol _ffi_closure_helper_DARWIN
mflr r0
bcl 20,31,"L00000000001$spb"
"L00000000001$spb":
bcl 20,31,"L1$spb"
"L1$spb":
mflr r11
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")
mtlr r0
lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")(r11)
lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")(r11)
mtctr r12
bctr
.lazy_symbol_pointer
@ -542,12 +537,12 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
L_darwin64_struct_ret_by_value_p$stub:
.indirect_symbol _darwin64_struct_ret_by_value_p
mflr r0
bcl 20,31,"L00000000002$spb"
"L00000000002$spb":
bcl 20,31,"L2$spb"
"L2$spb":
mflr r11
addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")
addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")
mtlr r0
lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")(r11)
lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")(r11)
mtctr r12
bctr
.lazy_symbol_pointer
@ -560,12 +555,12 @@ L_darwin64_struct_ret_by_value_p$lazy_ptr:
L_darwin64_pass_struct_floats$stub:
.indirect_symbol _darwin64_pass_struct_floats
mflr r0
bcl 20,31,"L00000000003$spb"
"L00000000003$spb":
bcl 20,31,"L3$spb"
"L3$spb":
mflr r11
addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")
addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")
mtlr r0
lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")(r11)
lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")(r11)
mtctr r12
bctr
.lazy_symbol_pointer

View file

@ -70,8 +70,12 @@ ffi_prep_cif_machdep_var (ffi_cif *cif,
#endif
}
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
static void
ffi_call_int (ffi_cif *cif,
void (*fn) (void),
void *rvalue,
void **avalue,
void *closure)
{
/* The final SYSV ABI says that structures smaller or equal 8 bytes
are returned in r3/r4. A draft ABI used by linux instead returns
@ -97,9 +101,10 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ecif.rvalue = alloca (cif->rtype->size);
#ifdef POWERPC64
ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
ffi_call_LINUX64 (&ecif, fn, ecif.rvalue, cif->flags, closure,
-(long) cif->bytes);
#else
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
ffi_call_SYSV (&ecif, fn, ecif.rvalue, cif->flags, closure, -cif->bytes);
#endif
/* Check for a bounce-buffered return value */
@ -125,6 +130,18 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
}
}
void
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
{
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
ffi_status
ffi_prep_closure_loc (ffi_closure *closure,
@ -139,3 +156,18 @@ ffi_prep_closure_loc (ffi_closure *closure,
return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc);
#endif
}
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure,
ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *))
{
#ifdef POWERPC64
closure->tramp = ffi_go_closure_linux64;
#else
closure->tramp = ffi_go_closure_sysv;
#endif
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}

View file

@ -302,10 +302,10 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
}
/* Check that we didn't overrun the stack... */
//FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
//FFI_ASSERT((unsigned *)fpr_base
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
/* FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
FFI_ASSERT((unsigned *)fpr_base
<= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); */
}
#if defined(POWERPC_DARWIN64)
@ -593,7 +593,7 @@ darwin_adjust_aggregate_sizes (ffi_type *s)
/* Natural alignment for all items. */
align = p->alignment;
#else
/* Natrual alignment for the first item... */
/* Natural alignment for the first item... */
if (i == 0)
align = p->alignment;
else if (p->alignment == 16 || p->alignment < 4)

View file

@ -667,7 +667,8 @@ flush_icache (char *wraddr, char *xaddr, int size)
}
#endif
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_closure_loc_linux64 (ffi_closure *closure,
ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
@ -688,16 +689,17 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure,
/* 2: .quad context */
*(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
*(void **) &tramp[6] = codeloc;
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
flush_icache ((char *) tramp, (char *) codeloc, 4 * 4);
#else
void **tramp = (void **) &closure->tramp[0];
if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
return FFI_BAD_ABI;
/* Copy function address and TOC from ffi_closure_LINUX64. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
tramp[2] = codeloc;
/* Copy function address and TOC from ffi_closure_LINUX64 OPD. */
memcpy (&tramp[0], (void **) ffi_closure_LINUX64, sizeof (void *));
tramp[1] = codeloc;
memcpy (&tramp[2], (void **) ffi_closure_LINUX64 + 1, sizeof (void *));
#endif
closure->cif = cif;
@ -709,8 +711,12 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure,
int FFI_HIDDEN
ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
unsigned long *pst, ffi_dblfl *pfr)
ffi_closure_helper_LINUX64 (ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
void *rvalue,
unsigned long *pst,
ffi_dblfl *pfr)
{
/* rvalue is the pointer to space for return value in closure assembly */
/* pst is the pointer to parameter save area
@ -720,11 +726,9 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
void **avalue;
ffi_type **arg_types;
unsigned long i, avn, nfixedargs;
ffi_cif *cif;
ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
unsigned long align;
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
/* Copy the caller's structure return value address so that the
@ -924,8 +928,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
i++;
}
(closure->fun) (cif, rvalue, avalue, closure->user_data);
(*fun) (cif, rvalue, avalue, user_data);
/* Tell ffi_closure_LINUX64 how to perform return type promotions. */
if ((cif->flags & FLAG_RETURNS_SMST) != 0)

View file

@ -56,22 +56,39 @@ typedef union
} ffi_dblfl;
void FFI_HIDDEN ffi_closure_SYSV (void);
void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
void (*)(void));
void FFI_HIDDEN ffi_go_closure_sysv (void);
void FFI_HIDDEN ffi_call_SYSV(extended_cif *, void (*)(void), void *,
unsigned, void *, int);
void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi);
ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *);
int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv (ffi_closure *,
ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *);
int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *, unsigned long *,
ffi_dblfl *, unsigned long *);
void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long,
unsigned long *, void (*)(void));
void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, void (*) (void), void *,
unsigned long, void *, long);
void FFI_HIDDEN ffi_closure_LINUX64 (void);
void FFI_HIDDEN ffi_go_closure_linux64 (void);
void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi);
ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *);
ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int,
unsigned int);
void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const);
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
ffi_status FFI_HIDDEN ffi_prep_closure_loc_linux64 (ffi_closure *, ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *);
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *,
unsigned long *, ffi_dblfl *);

View file

@ -36,7 +36,7 @@
/* About the SYSV ABI. */
#define ASM_NEEDS_REGISTERS 4
#define ASM_NEEDS_REGISTERS 6
#define NUM_GPR_ARG_REGISTERS 8
#define NUM_FPR_ARG_REGISTERS 8
@ -654,18 +654,18 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
tramp[4] = 0x7d6802a6; /* mflr r11 */
tramp[5] = 0x7c0803a6; /* mtlr r0 */
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
tramp[8] = 0x7c0903a6; /* mtctr r0 */
tramp[9] = 0x4e800420; /* bctr */
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
*(void **) &tramp[3] = codeloc; /* context */
tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
tramp[2] = 0x7d6802a6; /* mflr r11 */
tramp[3] = 0x7c0803a6; /* mtlr r0 */
tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
tramp[6] = 0x7c0903a6; /* mtctr r0 */
tramp[7] = 0x4e800420; /* bctr */
*(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
*(void **) &tramp[9] = codeloc; /* context */
/* Flush the icache. */
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
closure->cif = cif;
closure->fun = fun;
@ -682,8 +682,12 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
following helper function to do most of the work. */
int
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
unsigned long *pgr, ffi_dblfl *pfr,
ffi_closure_helper_SYSV (ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
void *rvalue,
unsigned long *pgr,
ffi_dblfl *pfr,
unsigned long *pst)
{
/* rvalue is the pointer to space for return value in closure assembly */
@ -699,7 +703,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
#endif
long ng = 0; /* number of general registers already used */
ffi_cif *cif = closure->cif;
unsigned size = cif->rtype->size;
unsigned short rtypenum = cif->rtype->type;
@ -915,7 +918,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
i++;
}
(closure->fun) (cif, rvalue, avalue, closure->user_data);
(*fun) (cif, rvalue, avalue, user_data);
/* Tell ffi_closure_SYSV how to perform return type promotions.
Because the FFI_SYSV ABI returns the structures <= 8 bytes in

View file

@ -138,23 +138,35 @@ typedef enum ffi_abi {
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#if defined (POWERPC) || defined (POWERPC_FREEBSD)
# define FFI_GO_CLOSURES 1
# define FFI_TARGET_SPECIFIC_VARIADIC 1
# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
#endif
/* For additional types like the below, take care about the order in
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
/* ppc_closure.S and linux64_closure.S expect this. */
#define FFI_PPC_TYPE_LAST FFI_TYPE_POINTER
/* We define additional types below. If generic types are added that
must be supported by powerpc libffi then it is likely that
FFI_PPC_TYPE_LAST needs increasing *and* the jump tables in
ppc_closure.S and linux64_closure.S be extended. */
#if !(FFI_TYPE_LAST == FFI_PPC_TYPE_LAST \
|| (FFI_TYPE_LAST == FFI_TYPE_COMPLEX \
&& !defined FFI_TARGET_HAS_COMPLEX_TYPE))
# error "You likely have a broken powerpc libffi"
#endif
/* Needed for soft-float long-double-128 support. */
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
#define FFI_TYPE_UINT128 (FFI_PPC_TYPE_LAST + 1)
/* Needed for FFI_SYSV small structure returns. */
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 2)
/* Used by ELFv2 for homogenous structure returns. */
#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_TYPE_LAST + 1)
#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_TYPE_LAST + 2)
#define FFI_V2_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 3)
#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_PPC_TYPE_LAST + 1)
#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_PPC_TYPE_LAST + 2)
#define FFI_V2_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 3)
#if _CALL_ELF == 2
# define FFI_TRAMPOLINE_SIZE 32

View file

@ -32,8 +32,9 @@
#ifdef POWERPC64
.hidden ffi_call_LINUX64
.globl ffi_call_LINUX64
# if _CALL_ELF == 2
.text
.cfi_startproc
# if _CALL_ELF == 2
ffi_call_LINUX64:
addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_call_LINUX64@l
@ -57,20 +58,26 @@ ffi_call_LINUX64:
.ffi_call_LINUX64:
# endif
# endif
.LFB1:
mflr %r0
std %r28, -32(%r1)
std %r29, -24(%r1)
std %r30, -16(%r1)
std %r31, -8(%r1)
std %r7, 8(%r1) /* closure, saved in cr field. */
std %r0, 16(%r1)
mr %r28, %r1 /* our AP. */
.LCFI0:
stdux %r1, %r1, %r4
mr %r31, %r5 /* flags, */
mr %r30, %r6 /* rvalue, */
mr %r29, %r7 /* function address. */
.cfi_def_cfa_register 28
.cfi_offset 65, 16
.cfi_offset 31, -8
.cfi_offset 30, -16
.cfi_offset 29, -24
.cfi_offset 28, -32
stdux %r1, %r1, %r8
mr %r31, %r6 /* flags, */
mr %r30, %r5 /* rvalue, */
mr %r29, %r4 /* function address. */
/* Save toc pointer, not for the ffi_prep_args64 call, but for the later
bctrl function call. */
# if _CALL_ELF == 2
@ -92,7 +99,6 @@ ffi_call_LINUX64:
# else
ld %r12, 0(%r29)
ld %r2, 8(%r29)
ld %r11, 16(%r29)
# endif
/* Now do the call. */
/* Set up cr1 with bits 4-7 of the flags. */
@ -130,6 +136,7 @@ ffi_call_LINUX64:
2:
/* Make the call. */
ld %r11, 8(%r28)
bctrl
/* This must follow the call immediately, the unwinder
@ -151,6 +158,7 @@ ffi_call_LINUX64:
.Ldone_return_value:
/* Restore the registers we used and return. */
mr %r1, %r28
.cfi_def_cfa_register 1
ld %r0, 16(%r28)
ld %r28, -32(%r28)
mtlr %r0
@ -160,6 +168,7 @@ ffi_call_LINUX64:
blr
.Lfp_return_value:
.cfi_def_cfa_register 28
bf 28, .Lfloat_return_value
stfd %f1, 0(%r30)
mtcrf 0x02, %r31 /* cr6 */
@ -199,61 +208,19 @@ ffi_call_LINUX64:
std %r4, 8(%r30)
b .Ldone_return_value
.LFE1:
.long 0
.byte 0,12,0,1,128,4,0,0
.cfi_endproc
# if _CALL_ELF == 2
.size ffi_call_LINUX64,.-ffi_call_LINUX64
# else
# ifdef _CALL_LINUX
.size ffi_call_LINUX64,.-.L.ffi_call_LINUX64
# else
.long 0
.byte 0,12,0,1,128,4,0,0
.size .ffi_call_LINUX64,.-.ffi_call_LINUX64
# endif
# endif
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0x41 # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x14 # FDE Encoding (pcrel udata8)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1
.uleb128 0x0
.align 3
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.8byte .LFB1-. # FDE initial location
.8byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x2 # DW_CFA_advance_loc1
.byte .LCFI0-.LFB1
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0x1c
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -2
.byte 0x9f # DW_CFA_offset, column 0x1f
.uleb128 0x1
.byte 0x9e # DW_CFA_offset, column 0x1e
.uleb128 0x2
.byte 0x9d # DW_CFA_offset, column 0x1d
.uleb128 0x3
.byte 0x9c # DW_CFA_offset, column 0x1c
.uleb128 0x4
.align 3
.LEFDE1:
#endif
#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2

View file

@ -33,8 +33,9 @@
#ifdef POWERPC64
FFI_HIDDEN (ffi_closure_LINUX64)
.globl ffi_closure_LINUX64
# if _CALL_ELF == 2
.text
.cfi_startproc
# if _CALL_ELF == 2
ffi_closure_LINUX64:
addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
@ -73,20 +74,18 @@ ffi_closure_LINUX64:
# define RETVAL PARMSAVE+64
# endif
.LFB1:
# if _CALL_ELF == 2
ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
mflr %r0
lwz %r12, 28(%r12) # cif->flags
mtcrf 0x40, %r12
addi %r12, %r1, PARMSAVE
bt 7, .Lparmsave
bt 7, 0f
# Our caller has not allocated a parameter save area.
# We need to allocate one here and use it to pass gprs to
# ffi_closure_helper_LINUX64.
addi %r12, %r1, -STACKFRAME+PARMSAVE
.Lparmsave:
std %r0, 16(%r1)
0:
# Save general regs into parm save area
std %r3, 0(%r12)
std %r4, 8(%r12)
@ -98,8 +97,12 @@ ffi_closure_LINUX64:
std %r10, 56(%r12)
# load up the pointer to the parm save area
mr %r5, %r12
mr %r7, %r12
# else
# copy r2 to r11 and load TOC into r2
mr %r11, %r2
ld %r2, 16(%r2)
mflr %r0
# Save general regs into parm save area
# This is the parameter save area set up by our caller.
@ -112,12 +115,19 @@ ffi_closure_LINUX64:
std %r9, PARMSAVE+48(%r1)
std %r10, PARMSAVE+56(%r1)
# load up the pointer to the parm save area
addi %r7, %r1, PARMSAVE
# endif
std %r0, 16(%r1)
# load up the pointer to the parm save area
addi %r5, %r1, PARMSAVE
# endif
# closure->cif
ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
# closure->fun
ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
# closure->user_data
ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
.Ldoclosure:
# next save fpr 1 to fpr 13
stfd %f1, -104+(0*8)(%r1)
stfd %f2, -104+(1*8)(%r1)
@ -134,16 +144,14 @@ ffi_closure_LINUX64:
stfd %f13, -104+(12*8)(%r1)
# load up the pointer to the saved fpr registers */
addi %r6, %r1, -104
addi %r8, %r1, -104
# load up the pointer to the result storage
addi %r4, %r1, -STACKFRAME+RETVAL
addi %r6, %r1, -STACKFRAME+RETVAL
stdu %r1, -STACKFRAME(%r1)
.LCFI0:
# get the context pointer from the trampoline
mr %r3, %r11
.cfi_def_cfa_offset STACKFRAME
.cfi_offset 65, 16
# make the call
# if defined _CALL_LINUX || _CALL_ELF == 2
@ -178,7 +186,9 @@ ffi_closure_LINUX64:
# case FFI_TYPE_VOID
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
nop
# case FFI_TYPE_INT
# ifdef __LITTLE_ENDIAN__
@ -188,17 +198,23 @@ ffi_closure_LINUX64:
# endif
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_FLOAT
lfs %f1, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_DOUBLE
lfd %f1, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_LONGDOUBLE
lfd %f1, RETVAL+0(%r1)
mtlr %r0
@ -212,7 +228,9 @@ ffi_closure_LINUX64:
# endif
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT8
# ifdef __LITTLE_ENDIAN__
lbz %r3, RETVAL+0(%r1)
@ -231,7 +249,9 @@ ffi_closure_LINUX64:
mtlr %r0
.Lfinish:
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT16
# ifdef __LITTLE_ENDIAN__
lha %r3, RETVAL+0(%r1)
@ -240,7 +260,9 @@ ffi_closure_LINUX64:
# endif
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_UINT32
# ifdef __LITTLE_ENDIAN__
lwz %r3, RETVAL+0(%r1)
@ -249,7 +271,9 @@ ffi_closure_LINUX64:
# endif
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT32
# ifdef __LITTLE_ENDIAN__
lwa %r3, RETVAL+0(%r1)
@ -258,27 +282,37 @@ ffi_closure_LINUX64:
# endif
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_UINT64
ld %r3, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT64
ld %r3, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_STRUCT
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
nop
# case FFI_TYPE_POINTER
ld %r3, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_V2_TYPE_FLOAT_HOMOG
lfs %f1, RETVAL+0(%r1)
lfs %f2, RETVAL+4(%r1)
@ -295,7 +329,9 @@ ffi_closure_LINUX64:
lfd %f7, RETVAL+48(%r1)
lfd %f8, RETVAL+56(%r1)
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
.Lmorefloat:
lfs %f4, RETVAL+12(%r1)
mtlr %r0
@ -304,13 +340,16 @@ ffi_closure_LINUX64:
lfs %f7, RETVAL+24(%r1)
lfs %f8, RETVAL+28(%r1)
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
.Lsmall:
# ifdef __LITTLE_ENDIAN__
ld %r3,RETVAL+0(%r1)
mtlr %r0
ld %r4,RETVAL+8(%r1)
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
# else
# A struct smaller than a dword is returned in the low bits of r3
@ -324,63 +363,124 @@ ffi_closure_LINUX64:
mtlr %r0
ld %r4,RETVAL+8(%r1)
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset STACKFRAME
.Lsmalldown:
addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
mtlr %r0
sldi %r5, %r5, 3
addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
srd %r3, %r3, %r5
blr
# endif
.LFE1:
.long 0
.byte 0,12,0,1,128,0,0,0
.cfi_endproc
# if _CALL_ELF == 2
.size ffi_closure_LINUX64,.-ffi_closure_LINUX64
# else
# ifdef _CALL_LINUX
.size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
# else
.long 0
.byte 0,12,0,1,128,0,0,0
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
# endif
# endif
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0x41 # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x14 # FDE Encoding (pcrel udata8)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1
.uleb128 0x0
.align 3
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.8byte .LFB1-. # FDE initial location
.8byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x2 # DW_CFA_advance_loc1
.byte .LCFI0-.LFB1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 STACKFRAME
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -2
.align 3
.LEFDE1:
FFI_HIDDEN (ffi_go_closure_linux64)
.globl ffi_go_closure_linux64
.text
.cfi_startproc
# if _CALL_ELF == 2
ffi_go_closure_linux64:
addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
.localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
# else
.section ".opd","aw"
.align 3
ffi_go_closure_linux64:
# ifdef _CALL_LINUX
.quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
.type ffi_go_closure_linux64,@function
.text
.L.ffi_go_closure_linux64:
# else
FFI_HIDDEN (.ffi_go_closure_linux64)
.globl .ffi_go_closure_linux64
.quad .ffi_go_closure_linux64,.TOC.@tocbase,0
.size ffi_go_closure_linux64,24
.type .ffi_go_closure_linux64,@function
.text
.ffi_go_closure_linux64:
# endif
# endif
# if _CALL_ELF == 2
ld %r12, 8(%r11) # closure->cif
mflr %r0
lwz %r12, 28(%r12) # cif->flags
mtcrf 0x40, %r12
addi %r12, %r1, PARMSAVE
bt 7, 0f
# Our caller has not allocated a parameter save area.
# We need to allocate one here and use it to pass gprs to
# ffi_closure_helper_LINUX64.
addi %r12, %r1, -STACKFRAME+PARMSAVE
0:
# Save general regs into parm save area
std %r3, 0(%r12)
std %r4, 8(%r12)
std %r5, 16(%r12)
std %r6, 24(%r12)
std %r7, 32(%r12)
std %r8, 40(%r12)
std %r9, 48(%r12)
std %r10, 56(%r12)
# load up the pointer to the parm save area
mr %r7, %r12
# else
mflr %r0
# Save general regs into parm save area
# This is the parameter save area set up by our caller.
std %r3, PARMSAVE+0(%r1)
std %r4, PARMSAVE+8(%r1)
std %r5, PARMSAVE+16(%r1)
std %r6, PARMSAVE+24(%r1)
std %r7, PARMSAVE+32(%r1)
std %r8, PARMSAVE+40(%r1)
std %r9, PARMSAVE+48(%r1)
std %r10, PARMSAVE+56(%r1)
# load up the pointer to the parm save area
addi %r7, %r1, PARMSAVE
# endif
std %r0, 16(%r1)
# closure->cif
ld %r3, 8(%r11)
# closure->fun
ld %r4, 16(%r11)
# user_data
mr %r5, %r11
b .Ldoclosure
.cfi_endproc
# if _CALL_ELF == 2
.size ffi_go_closure_linux64,.-ffi_go_closure_linux64
# else
# ifdef _CALL_LINUX
.size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
# else
.long 0
.byte 0,12,0,1,128,0,0,0
.size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
# endif
# endif
#endif
#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2

View file

@ -33,13 +33,14 @@
#ifndef POWERPC64
FFI_HIDDEN(ffi_closure_SYSV)
ENTRY(ffi_closure_SYSV)
.LFB1:
.cfi_startproc
stwu %r1,-144(%r1)
.LCFI0:
.cfi_def_cfa_offset 144
mflr %r0
.LCFI1:
stw %r0,148(%r1)
.cfi_offset 65, 4
# we want to build up an areas for the parameters passed
# in registers (both floating point and integer)
@ -48,6 +49,17 @@ ENTRY(ffi_closure_SYSV)
stw %r3, 16(%r1)
stw %r4, 20(%r1)
stw %r5, 24(%r1)
# set up registers for the routine that does the work
# closure->cif
lwz %r3,FFI_TRAMPOLINE_SIZE(%r11)
# closure->fun
lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11)
# closure->user_data
lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11)
.Ldoclosure:
stw %r6, 28(%r1)
stw %r7, 32(%r1)
stw %r8, 36(%r1)
@ -66,23 +78,18 @@ ENTRY(ffi_closure_SYSV)
stfd %f8, 104(%r1)
#endif
# set up registers for the routine that actually does the work
# get the context pointer from the trampoline
mr %r3,%r11
# pointer to the result storage
addi %r6,%r1,112
# now load up the pointer to the result storage
addi %r4,%r1,112
# pointer to the saved gpr registers
addi %r7,%r1,16
# now load up the pointer to the saved gpr registers
addi %r5,%r1,16
# pointer to the saved fpr registers
addi %r8,%r1,48
# now load up the pointer to the saved fpr registers */
addi %r6,%r1,48
# now load up the pointer to the outgoing parameter
# stack in the previous frame
# pointer to the outgoing parameter save area in the previous frame
# i.e. the previous frame pointer + 8
addi %r7,%r1,152
addi %r9,%r1,152
# make the call
bl ffi_closure_helper_SYSV@local
@ -101,7 +108,6 @@ ENTRY(ffi_closure_SYSV)
add %r3,%r3,%r4 # add contents of table to table address
mtctr %r3
bctr # jump to it
.LFE1:
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
@ -111,7 +117,9 @@ ENTRY(ffi_closure_SYSV)
.Lret_type0:
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
nop
# case FFI_TYPE_INT
@ -119,31 +127,33 @@ ENTRY(ffi_closure_SYSV)
mtlr %r0
.Lfinish:
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_FLOAT
#ifndef __NO_FPRS__
lfs %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
#else
nop
nop
nop
#endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_DOUBLE
#ifndef __NO_FPRS__
lfd %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
#else
nop
nop
nop
#endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_LONGDOUBLE
#ifndef __NO_FPRS__
@ -152,10 +162,12 @@ ENTRY(ffi_closure_SYSV)
mtlr %r0
b .Lfinish
#else
nop
nop
nop
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
nop
#endif
# case FFI_TYPE_UINT8
@ -166,7 +178,9 @@ ENTRY(ffi_closure_SYSV)
#endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_SINT8
#ifdef __LITTLE_ENDIAN__
@ -186,7 +200,9 @@ ENTRY(ffi_closure_SYSV)
#endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_SINT16
#ifdef __LITTLE_ENDIAN__
@ -196,19 +212,25 @@ ENTRY(ffi_closure_SYSV)
#endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_UINT32
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_SINT32
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_UINT64
lwz %r3,112+0(%r1)
@ -225,14 +247,18 @@ ENTRY(ffi_closure_SYSV)
# case FFI_TYPE_STRUCT
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
nop
# case FFI_TYPE_POINTER
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_UINT128
lwz %r3,112+0(%r1)
@ -245,20 +271,26 @@ ENTRY(ffi_closure_SYSV)
lbz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
lhz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
lwz %r3,112+0(%r1)
#ifdef __LITTLE_ENDIAN__
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
#else
srwi %r3,%r3,8
mtlr %r0
@ -269,7 +301,9 @@ ENTRY(ffi_closure_SYSV)
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
lwz %r3,112+0(%r1)
@ -319,64 +353,43 @@ ENTRY(ffi_closure_SYSV)
or %r4,%r6,%r4
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_def_cfa_offset 144
#endif
.Luint128:
lwz %r6,112+12(%r1)
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr
.cfi_endproc
END(ffi_closure_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
#if defined _RELOCATABLE || defined __PIC__
.ascii "zR\0" # CIE Augmentation
#else
.ascii "\0" # CIE Augmentation
#endif
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -4 # CIE Data Alignment Factor
.byte 0x41 # CIE RA Column
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x1 # Augmentation size
.byte 0x1b # FDE Encoding (pcrel sdata4)
#endif
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1
.uleb128 0x0
.align 2
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
#if defined _RELOCATABLE || defined __PIC__
.4byte .LFB1-. # FDE initial location
#else
.4byte .LFB1 # FDE initial location
#endif
.4byte .LFE1-.LFB1 # FDE address range
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x0 # Augmentation size
#endif
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 144
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -1
.align 2
.LEFDE1:
FFI_HIDDEN(ffi_go_closure_sysv)
ENTRY(ffi_go_closure_sysv)
.cfi_startproc
stwu %r1,-144(%r1)
.cfi_def_cfa_offset 144
mflr %r0
stw %r0,148(%r1)
.cfi_offset 65, 4
stw %r3, 16(%r1)
stw %r4, 20(%r1)
stw %r5, 24(%r1)
# closure->cif
lwz %r3,4(%r11)
# closure->fun
lwz %r4,8(%r11)
# user_data
mr %r5,%r11
b .Ldoclosure
.cfi_endproc
END(ffi_go_closure_sysv)
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits

View file

@ -31,34 +31,35 @@
#include <powerpc/asm.h>
#ifndef POWERPC64
.globl ffi_prep_args_SYSV
FFI_HIDDEN(ffi_call_SYSV)
ENTRY(ffi_call_SYSV)
.LFB1:
.cfi_startproc
/* Save the old stack pointer as AP. */
mr %r8,%r1
mr %r10,%r1
.cfi_def_cfa_register 10
.LCFI0:
/* Allocate the stack space we need. */
stwux %r1,%r1,%r4
stwux %r1,%r1,%r8
/* Save registers we use. */
mflr %r9
stw %r28,-16(%r8)
.LCFI1:
stw %r29,-12(%r8)
.LCFI2:
stw %r30, -8(%r8)
.LCFI3:
stw %r31, -4(%r8)
.LCFI4:
stw %r9, 4(%r8)
.LCFI5:
stw %r28,-16(%r10)
stw %r29,-12(%r10)
stw %r30, -8(%r10)
stw %r31, -4(%r10)
stw %r9, 4(%r10)
.cfi_offset 65, 4
.cfi_offset 31, -4
.cfi_offset 30, -8
.cfi_offset 29, -12
.cfi_offset 28, -16
/* Save arguments over call... */
mr %r31,%r5 /* flags, */
mr %r30,%r6 /* rvalue, */
mr %r29,%r7 /* function address, */
mr %r28,%r8 /* our AP. */
.LCFI6:
stw %r7, -20(%r10) /* closure, */
mr %r31,%r6 /* flags, */
mr %r30,%r5 /* rvalue, */
mr %r29,%r4 /* function address, */
mr %r28,%r10 /* our AP. */
.cfi_def_cfa_register 28
/* Call ffi_prep_args_SYSV. */
mr %r4,%r1
@ -70,35 +71,36 @@ ENTRY(ffi_call_SYSV)
/* Get the address to call into CTR. */
mtctr %r29
/* Load all those argument registers. */
lwz %r3,-16-(8*4)(%r28)
lwz %r4,-16-(7*4)(%r28)
lwz %r5,-16-(6*4)(%r28)
lwz %r6,-16-(5*4)(%r28)
lwz %r3,-24-(8*4)(%r28)
lwz %r4,-24-(7*4)(%r28)
lwz %r5,-24-(6*4)(%r28)
lwz %r6,-24-(5*4)(%r28)
bf- 5,1f
nop
lwz %r7,-16-(4*4)(%r28)
lwz %r8,-16-(3*4)(%r28)
lwz %r9,-16-(2*4)(%r28)
lwz %r10,-16-(1*4)(%r28)
lwz %r7,-24-(4*4)(%r28)
lwz %r8,-24-(3*4)(%r28)
lwz %r9,-24-(2*4)(%r28)
lwz %r10,-24-(1*4)(%r28)
nop
1:
#ifndef __NO_FPRS__
/* Load all the FP registers. */
bf- 6,2f
lfd %f1,-16-(8*4)-(8*8)(%r28)
lfd %f2,-16-(8*4)-(7*8)(%r28)
lfd %f3,-16-(8*4)-(6*8)(%r28)
lfd %f4,-16-(8*4)-(5*8)(%r28)
lfd %f1,-24-(8*4)-(8*8)(%r28)
lfd %f2,-24-(8*4)-(7*8)(%r28)
lfd %f3,-24-(8*4)-(6*8)(%r28)
lfd %f4,-24-(8*4)-(5*8)(%r28)
nop
lfd %f5,-16-(8*4)-(4*8)(%r28)
lfd %f6,-16-(8*4)-(3*8)(%r28)
lfd %f7,-16-(8*4)-(2*8)(%r28)
lfd %f8,-16-(8*4)-(1*8)(%r28)
lfd %f5,-24-(8*4)-(4*8)(%r28)
lfd %f6,-24-(8*4)-(3*8)(%r28)
lfd %f7,-24-(8*4)-(2*8)(%r28)
lfd %f8,-24-(8*4)-(1*8)(%r28)
#endif
2:
/* Make the call. */
lwz %r11, -20(%r28)
bctrl
/* Now, deal with the return value. */
@ -125,11 +127,24 @@ L(done_return_value):
lwz %r30, -8(%r28)
lwz %r29,-12(%r28)
lwz %r28,-16(%r28)
.cfi_remember_state
/* At this point we don't have a cfa register. Say all our
saved regs have been restored. */
.cfi_same_value 65
.cfi_same_value 31
.cfi_same_value 30
.cfi_same_value 29
.cfi_same_value 28
/* Hopefully this works.. */
.cfi_def_cfa_register 1
.cfi_offset 1, 0
lwz %r1,0(%r1)
.cfi_same_value 1
blr
#ifndef __NO_FPRS__
L(fp_return_value):
.cfi_restore_state
bf 28,L(float_return_value)
stfd %f1,0(%r30)
mtcrf 0x02,%r31 /* cr6 */
@ -150,70 +165,10 @@ L(small_struct_return_value):
stw %r3, 0(%r30)
stw %r4, 4(%r30)
b L(done_return_value)
.cfi_endproc
.LFE1:
END(ffi_call_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
.LSCIE1:
.4byte 0x0 /* CIE Identifier Tag */
.byte 0x1 /* CIE Version */
#if defined _RELOCATABLE || defined __PIC__
.ascii "zR\0" /* CIE Augmentation */
#else
.ascii "\0" /* CIE Augmentation */
#endif
.uleb128 0x1 /* CIE Code Alignment Factor */
.sleb128 -4 /* CIE Data Alignment Factor */
.byte 0x41 /* CIE RA Column */
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x1 /* Augmentation size */
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
#endif
.byte 0xc /* DW_CFA_def_cfa */
.uleb128 0x1
.uleb128 0x0
.align 2
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
.LASFDE1:
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
#if defined _RELOCATABLE || defined __PIC__
.4byte .LFB1-. /* FDE initial location */
#else
.4byte .LFB1 /* FDE initial location */
#endif
.4byte .LFE1-.LFB1 /* FDE address range */
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x0 /* Augmentation size */
#endif
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFI0-.LFB1
.byte 0xd /* DW_CFA_def_cfa_register */
.uleb128 0x08
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFI5-.LCFI0
.byte 0x11 /* DW_CFA_offset_extended_sf */
.uleb128 0x41
.sleb128 -1
.byte 0x9f /* DW_CFA_offset, column 0x1f */
.uleb128 0x1
.byte 0x9e /* DW_CFA_offset, column 0x1e */
.uleb128 0x2
.byte 0x9d /* DW_CFA_offset, column 0x1d */
.uleb128 0x3
.byte 0x9c /* DW_CFA_offset, column 0x1c */
.uleb128 0x4
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFI6-.LCFI5
.byte 0xd /* DW_CFA_def_cfa_register */
.uleb128 0x1c
.align 2
.LEFDE1:
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits
#endif

View file

@ -76,6 +76,13 @@ static ffi_status initialize_aggregate(ffi_type *arg)
total size of 3*sizeof(long). */
arg->size = ALIGN (arg->size, arg->alignment);
/* On some targets, the ABI defines that structures have an additional
alignment beyond the "natural" one based on their elements. */
#ifdef FFI_AGGREGATE_ALIGNMENT
if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
arg->alignment = FFI_AGGREGATE_ALIGNMENT;
#endif
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
else
@ -111,13 +118,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
FFI_ASSERT(nfixedargs <= ntotalargs);
#ifndef X86_WIN32
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
return FFI_BAD_ABI;
#else
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
return FFI_BAD_ABI;
#endif
cif->abi = abi;
cif->arg_types = atypes;
@ -134,18 +136,25 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
if (rtype->type == FFI_TYPE_COMPLEX)
abort();
#endif
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
#ifdef TILE
&& (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
#endif
#ifdef XTENSA
&& (cif->rtype->size > 16)
#endif
#ifdef NIOS2
&& (cif->rtype->size > 8)
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
@ -158,23 +167,19 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
if ((*ptr)->type == FFI_TYPE_COMPLEX)
abort();
#endif
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if !defined X86_ANY && !defined S390 && !defined PA
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_V9))
bytes += sizeof(void*);
else
#endif
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
{
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment);
#ifdef TILE
if (bytes < 10 * FFI_SIZEOF_ARG &&
@ -185,6 +190,10 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
bytes = 10 * FFI_SIZEOF_ARG;
}
#endif
#ifdef XTENSA
if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
bytes = 6*4;
#endif
bytes += STACK_ARG_SIZE((*ptr)->size);
}

View file

@ -88,6 +88,10 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
break;
#endif
case FFI_TYPE_COMPLEX:
*args = (raw++)->ptr;
break;
case FFI_TYPE_POINTER:
*args = (void*) &(raw++)->ptr;
break;
@ -112,6 +116,11 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
}
else
#endif
if ((*tp)->type == FFI_TYPE_COMPLEX)
{
*args = (raw++)->ptr;
}
else
{
*args = (void*) raw;
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
@ -167,6 +176,10 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
break;
#endif
case FFI_TYPE_COMPLEX:
(raw++)->ptr = *args;
break;
case FFI_TYPE_POINTER:
(raw++)->ptr = **(void***) args;
break;

View file

@ -1,9 +1,9 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2000, 2007 Software AG
Copyright (c) 2008 Red Hat, Inc
S390 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
@ -11,10 +11,10 @@
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.
@ -27,24 +27,23 @@
/* Includes */
/* -------- */
/*====================================================================*/
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "internal.h"
/*====================== End of Includes =============================*/
/*====================================================================*/
/* Defines */
/* ------- */
/*====================================================================*/
/* Maximum number of GPRs available for argument passing. */
/* Maximum number of GPRs available for argument passing. */
#define MAX_GPRARGS 5
/* Maximum number of FPRs available for argument passing. */
/* Maximum number of FPRs available for argument passing. */
#ifdef __s390x__
#define MAX_FPRARGS 4
#else
@ -54,47 +53,30 @@
/* Round to multiple of 16. */
#define ROUND_SIZE(size) (((size) + 15) & ~15)
/* If these values change, sysv.S must be adapted! */
#define FFI390_RET_VOID 0
#define FFI390_RET_STRUCT 1
#define FFI390_RET_FLOAT 2
#define FFI390_RET_DOUBLE 3
#define FFI390_RET_INT32 4
#define FFI390_RET_INT64 5
/*===================== End of Defines ===============================*/
/*====================================================================*/
/* Prototypes */
/* ---------- */
/*====================================================================*/
static void ffi_prep_args (unsigned char *, extended_cif *);
void
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
__attribute__ ((visibility ("hidden")))
#endif
ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
unsigned long long *, unsigned long *);
/*====================== End of Prototypes ===========================*/
/*====================================================================*/
/* Externals */
/* --------- */
/*====================================================================*/
extern void ffi_call_SYSV(unsigned,
extended_cif *,
void (*)(unsigned char *, extended_cif *),
unsigned,
void *,
void (*fn)(void));
struct call_frame
{
void *back_chain;
void *eos;
unsigned long gpr_args[5];
unsigned long gpr_save[9];
unsigned long long fpr_args[4];
};
extern void FFI_HIDDEN ffi_call_SYSV(struct call_frame *, unsigned, void *,
void (*fn)(void), void *);
extern void ffi_closure_SYSV(void);
extern void ffi_go_closure_SYSV(void);
/*====================== End of Externals ============================*/
/*====================================================================*/
/* */
/* Name - ffi_check_struct_type. */
@ -103,7 +85,7 @@ extern void ffi_closure_SYSV(void);
/* general purpose or floating point register. */
/* */
/*====================================================================*/
static int
ffi_check_struct_type (ffi_type *arg)
{
@ -111,7 +93,7 @@ ffi_check_struct_type (ffi_type *arg)
/* If the struct has just one element, look at that element
to find out whether to consider the struct as floating point. */
while (arg->type == FFI_TYPE_STRUCT
while (arg->type == FFI_TYPE_STRUCT
&& arg->elements[0] && !arg->elements[1])
arg = arg->elements[0];
@ -144,190 +126,9 @@ ffi_check_struct_type (ffi_type *arg)
/* Other structs are passed via a pointer to the data. */
return FFI_TYPE_POINTER;
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_prep_args. */
/* */
/* Function - Prepare parameters for call to function. */
/* */
/* ffi_prep_args is called by the assembly routine once stack space */
/* has been allocated for the function's arguments. */
/* */
/*====================================================================*/
static void
ffi_prep_args (unsigned char *stack, extended_cif *ecif)
{
/* The stack space will be filled with those areas:
FPR argument register save area (highest addresses)
GPR argument register save area
temporary struct copies
overflow argument area (lowest addresses)
We set up the following pointers:
p_fpr: bottom of the FPR area (growing upwards)
p_gpr: bottom of the GPR area (growing upwards)
p_ov: bottom of the overflow area (growing upwards)
p_struct: top of the struct copy area (growing downwards)
All areas are kept aligned to twice the word size. */
int gpr_off = ecif->cif->bytes;
int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
unsigned char *p_struct = (unsigned char *)p_gpr;
unsigned long *p_ov = (unsigned long *)stack;
int n_fpr = 0;
int n_gpr = 0;
int n_ov = 0;
ffi_type **ptr;
void **p_argv = ecif->avalue;
int i;
/* If we returning a structure then we set the first parameter register
to the address of where we are returning this structure. */
if (ecif->cif->flags == FFI390_RET_STRUCT)
p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
/* Now for the arguments. */
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
i > 0;
i--, ptr++, p_argv++)
{
void *arg = *p_argv;
int type = (*ptr)->type;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
/* 16-byte long double is passed like a struct. */
if (type == FFI_TYPE_LONGDOUBLE)
type = FFI_TYPE_STRUCT;
#endif
/* Check how a structure type is passed. */
if (type == FFI_TYPE_STRUCT)
{
type = ffi_check_struct_type (*ptr);
/* If we pass the struct via pointer, copy the data. */
if (type == FFI_TYPE_POINTER)
{
p_struct -= ROUND_SIZE ((*ptr)->size);
memcpy (p_struct, (char *)arg, (*ptr)->size);
arg = &p_struct;
}
}
/* Now handle all primitive int/pointer/float data types. */
switch (type)
{
case FFI_TYPE_DOUBLE:
if (n_fpr < MAX_FPRARGS)
p_fpr[n_fpr++] = *(unsigned long long *) arg;
else
#ifdef __s390x__
p_ov[n_ov++] = *(unsigned long *) arg;
#else
p_ov[n_ov++] = ((unsigned long *) arg)[0],
p_ov[n_ov++] = ((unsigned long *) arg)[1];
#endif
break;
case FFI_TYPE_FLOAT:
if (n_fpr < MAX_FPRARGS)
p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
else
p_ov[n_ov++] = *(unsigned int *) arg;
break;
case FFI_TYPE_POINTER:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
else
p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
#ifdef __s390x__
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned long *) arg;
else
p_ov[n_ov++] = *(unsigned long *) arg;
#else
if (n_gpr == MAX_GPRARGS-1)
n_gpr = MAX_GPRARGS;
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
else
p_ov[n_ov++] = ((unsigned long *) arg)[0],
p_ov[n_ov++] = ((unsigned long *) arg)[1];
#endif
break;
case FFI_TYPE_UINT32:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned int *) arg;
else
p_ov[n_ov++] = *(unsigned int *) arg;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(signed int *) arg;
else
p_ov[n_ov++] = *(signed int *) arg;
break;
case FFI_TYPE_UINT16:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned short *) arg;
else
p_ov[n_ov++] = *(unsigned short *) arg;
break;
case FFI_TYPE_SINT16:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(signed short *) arg;
else
p_ov[n_ov++] = *(signed short *) arg;
break;
case FFI_TYPE_UINT8:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned char *) arg;
else
p_ov[n_ov++] = *(unsigned char *) arg;
break;
case FFI_TYPE_SINT8:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(signed char *) arg;
else
p_ov[n_ov++] = *(signed char *) arg;
break;
default:
FFI_ASSERT (0);
break;
}
}
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_prep_cif_machdep. */
@ -335,8 +136,8 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif)
/* Function - Perform machine dependent CIF processing. */
/* */
/*====================================================================*/
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif *cif)
{
size_t struct_size = 0;
@ -347,7 +148,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
ffi_type **ptr;
int i;
/* Determine return value handling. */
/* Determine return value handling. */
switch (cif->rtype->type)
{
@ -356,11 +157,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = FFI390_RET_VOID;
break;
/* Structures are returned via a hidden pointer. */
/* Structures and complex are returned via a hidden pointer. */
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
cif->flags = FFI390_RET_STRUCT;
n_gpr++; /* We need one GPR to pass the pointer. */
break;
break;
/* Floating point values are returned in fpr 0. */
case FFI_TYPE_FLOAT:
@ -399,14 +201,14 @@ ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = FFI390_RET_INT32;
#endif
break;
default:
FFI_ASSERT (0);
break;
}
/* Now for the arguments. */
for (ptr = cif->arg_types, i = cif->nargs;
i > 0;
i--, ptr++)
@ -420,9 +222,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
#endif
/* Check how a structure type is passed. */
if (type == FFI_TYPE_STRUCT)
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
{
type = ffi_check_struct_type (*ptr);
if (type == FFI_TYPE_COMPLEX)
type = FFI_TYPE_POINTER;
else
type = ffi_check_struct_type (*ptr);
/* If we pass the struct via pointer, we must reserve space
to copy its data for proper call-by-value semantics. */
@ -431,7 +236,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
}
/* Now handle all primitive int/float data types. */
switch (type)
switch (type)
{
/* The first MAX_FPRARGS floating point arguments
go in FPRs, the rest overflow to the stack. */
@ -442,7 +247,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
else
n_ov += sizeof (double) / sizeof (long);
break;
case FFI_TYPE_FLOAT:
if (n_fpr < MAX_FPRARGS)
n_fpr++;
@ -452,9 +257,9 @@ ffi_prep_cif_machdep(ffi_cif *cif)
/* On 31-bit machines, 64-bit integers are passed in GPR pairs,
if one is still available, or else on the stack. If only one
register is free, skip the register (it won't be used for any
register is free, skip the register (it won't be used for any
subsequent argument either). */
#ifndef __s390x__
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
@ -470,7 +275,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
/* Everything else is passed in GPRs (until MAX_GPRARGS
have been used) or overflows to the stack. */
default:
default:
if (n_gpr < MAX_GPRARGS)
n_gpr++;
else
@ -483,12 +288,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
and temporary structure copies. */
cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
return FFI_OK;
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_call. */
@ -496,42 +301,195 @@ ffi_prep_cif_machdep(ffi_cif *cif)
/* Function - Call the FFI routine. */
/* */
/*====================================================================*/
void
ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue)
static void
ffi_call_int(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue,
void *closure)
{
int ret_type = cif->flags;
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
ecif.rvalue = rvalue;
size_t rsize = 0, bytes = cif->bytes;
unsigned char *stack, *p_struct;
struct call_frame *frame;
unsigned long *p_ov, *p_gpr;
unsigned long long *p_fpr;
int n_fpr, n_gpr, n_ov, i, n;
ffi_type **arg_types;
FFI_ASSERT (cif->abi == FFI_SYSV);
/* If we don't have a return value, we need to fake one. */
if (rvalue == NULL)
{
if (ret_type == FFI390_RET_STRUCT)
ecif.rvalue = alloca (cif->rtype->size);
if (ret_type & FFI390_RET_IN_MEM)
rsize = cif->rtype->size;
else
ret_type = FFI390_RET_VOID;
}
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
ret_type, ecif.rvalue, fn);
break;
default:
FFI_ASSERT (0);
break;
}
/* The stack space will be filled with those areas:
dummy structure return (highest addresses)
FPR argument register save area
GPR argument register save area
stack frame for ffi_call_SYSV
temporary struct copies
overflow argument area (lowest addresses)
We set up the following pointers:
p_fpr: bottom of the FPR area (growing upwards)
p_gpr: bottom of the GPR area (growing upwards)
p_ov: bottom of the overflow area (growing upwards)
p_struct: top of the struct copy area (growing downwards)
All areas are kept aligned to twice the word size.
Note that we're going to create the stack frame for both
ffi_call_SYSV _and_ the target function right here. This
works because we don't make any function calls with more
than 5 arguments (indeed only memcpy and ffi_call_SYSV),
and thus we don't have any stacked outgoing parameters. */
stack = alloca (bytes + sizeof(struct call_frame) + rsize);
frame = (struct call_frame *)(stack + bytes);
if (rsize)
rvalue = frame + 1;
/* Link the new frame back to the one from this function. */
frame->back_chain = __builtin_frame_address (0);
/* Fill in all of the argument stuff. */
p_ov = (unsigned long *)stack;
p_struct = (unsigned char *)frame;
p_gpr = frame->gpr_args;
p_fpr = frame->fpr_args;
n_fpr = n_gpr = n_ov = 0;
/* If we returning a structure then we set the first parameter register
to the address of where we are returning this structure. */
if (cif->flags & FFI390_RET_IN_MEM)
p_gpr[n_gpr++] = (uintptr_t) rvalue;
/* Now for the arguments. */
arg_types = cif->arg_types;
for (i = 0, n = cif->nargs; i < n; ++i)
{
ffi_type *ty = arg_types[i];
void *arg = avalue[i];
int type = ty->type;
ffi_arg val;
restart:
switch (type)
{
case FFI_TYPE_SINT8:
val = *(SINT8 *)arg;
goto do_int;
case FFI_TYPE_UINT8:
val = *(UINT8 *)arg;
goto do_int;
case FFI_TYPE_SINT16:
val = *(SINT16 *)arg;
goto do_int;
case FFI_TYPE_UINT16:
val = *(UINT16 *)arg;
goto do_int;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
val = *(SINT32 *)arg;
goto do_int;
case FFI_TYPE_UINT32:
val = *(UINT32 *)arg;
goto do_int;
case FFI_TYPE_POINTER:
val = *(uintptr_t *)arg;
do_int:
*(n_gpr < MAX_GPRARGS ? p_gpr + n_gpr++ : p_ov + n_ov++) = val;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
#ifdef __s390x__
val = *(UINT64 *)arg;
goto do_int;
#else
if (n_gpr == MAX_GPRARGS-1)
n_gpr = MAX_GPRARGS;
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = ((UINT32 *) arg)[0],
p_gpr[n_gpr++] = ((UINT32 *) arg)[1];
else
p_ov[n_ov++] = ((UINT32 *) arg)[0],
p_ov[n_ov++] = ((UINT32 *) arg)[1];
#endif
break;
case FFI_TYPE_DOUBLE:
if (n_fpr < MAX_FPRARGS)
p_fpr[n_fpr++] = *(UINT64 *) arg;
else
{
#ifdef __s390x__
p_ov[n_ov++] = *(UINT64 *) arg;
#else
p_ov[n_ov++] = ((UINT32 *) arg)[0],
p_ov[n_ov++] = ((UINT32 *) arg)[1];
#endif
}
break;
case FFI_TYPE_FLOAT:
val = *(UINT32 *)arg;
if (n_fpr < MAX_FPRARGS)
p_fpr[n_fpr++] = (UINT64)val << 32;
else
p_ov[n_ov++] = val;
break;
case FFI_TYPE_STRUCT:
/* Check how a structure type is passed. */
type = ffi_check_struct_type (ty);
/* Some structures are passed via a type they contain. */
if (type != FFI_TYPE_POINTER)
goto restart;
/* ... otherwise, passed by reference. fallthru. */
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
/* 16-byte long double is passed via reference. */
#endif
case FFI_TYPE_COMPLEX:
/* Complex types are passed via reference. */
p_struct -= ROUND_SIZE (ty->size);
memcpy (p_struct, arg, ty->size);
val = (uintptr_t)p_struct;
goto do_int;
default:
FFI_ASSERT (0);
break;
}
}
ffi_call_SYSV (frame, ret_type & FFI360_RET_MASK, rvalue, fn, closure);
}
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_call_int(cif, fn, rvalue, avalue, NULL);
}
void
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int(cif, fn, rvalue, avalue, closure);
}
/*======================== End of Routine ============================*/
/*====================================================================*/
@ -541,9 +499,11 @@ ffi_call(ffi_cif *cif,
/* Function - Call a FFI closure target function. */
/* */
/*====================================================================*/
void
ffi_closure_helper_SYSV (ffi_closure *closure,
void FFI_HIDDEN
ffi_closure_helper_SYSV (ffi_cif *cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
unsigned long *p_gpr,
unsigned long long *p_fpr,
unsigned long *p_ov)
@ -562,21 +522,16 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
int i;
/* Allocate buffer for argument list pointers. */
p_arg = avalue = alloca (cif->nargs * sizeof (void *));
p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
/* If we returning a structure, pass the structure address
directly to the target function. Otherwise, have the target
/* If we returning a structure, pass the structure address
directly to the target function. Otherwise, have the target
function store the return value to the GPR save area. */
if (closure->cif->flags == FFI390_RET_STRUCT)
if (cif->flags & FFI390_RET_IN_MEM)
rvalue = (void *) p_gpr[n_gpr++];
/* Now for the arguments. */
for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
i > 0;
i--, p_arg++, ptr++)
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++)
{
int deref_struct_pointer = 0;
int type = (*ptr)->type;
@ -588,11 +543,14 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
#endif
/* Check how a structure type is passed. */
if (type == FFI_TYPE_STRUCT)
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
{
type = ffi_check_struct_type (*ptr);
if (type == FFI_TYPE_COMPLEX)
type = FFI_TYPE_POINTER;
else
type = ffi_check_struct_type (*ptr);
/* If we pass the struct via pointer, remember to
/* If we pass the struct via pointer, remember to
retrieve the pointer later. */
if (type == FFI_TYPE_POINTER)
deref_struct_pointer = 1;
@ -600,30 +558,32 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
/* Pointers are passed like UINTs of the same size. */
if (type == FFI_TYPE_POINTER)
{
#ifdef __s390x__
type = FFI_TYPE_UINT64;
type = FFI_TYPE_UINT64;
#else
type = FFI_TYPE_UINT32;
type = FFI_TYPE_UINT32;
#endif
}
/* Now handle all primitive int/float data types. */
switch (type)
switch (type)
{
case FFI_TYPE_DOUBLE:
if (n_fpr < MAX_FPRARGS)
*p_arg = &p_fpr[n_fpr++];
else
*p_arg = &p_ov[n_ov],
*p_arg = &p_ov[n_ov],
n_ov += sizeof (double) / sizeof (long);
break;
case FFI_TYPE_FLOAT:
if (n_fpr < MAX_FPRARGS)
*p_arg = &p_fpr[n_fpr++];
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
#ifdef __s390x__
@ -640,7 +600,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
*p_arg = &p_ov[n_ov], n_ov += 2;
#endif
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
@ -649,7 +609,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
if (n_gpr < MAX_GPRARGS)
@ -665,7 +625,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
break;
default:
FFI_ASSERT (0);
break;
@ -679,14 +639,15 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
/* Call the target function. */
(closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
(fun) (cif, rvalue, avalue, user_data);
/* Convert the return value. */
switch (closure->cif->rtype->type)
switch (cif->rtype->type)
{
/* Void is easy, and so is struct. */
case FFI_TYPE_VOID:
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
#endif
@ -732,7 +693,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
break;
}
}
/*======================== End of Routine ============================*/
/*====================================================================*/
@ -742,7 +703,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
/* Function - Prepare a FFI closure. */
/* */
/*====================================================================*/
ffi_status
ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif *cif,
@ -750,32 +711,46 @@ ffi_prep_closure_loc (ffi_closure *closure,
void *user_data,
void *codeloc)
{
static unsigned short const template[] = {
0x0d10, /* basr %r1,0 */
#ifndef __s390x__
0x9801, 0x1006, /* lm %r0,%r1,6(%r1) */
#else
0xeb01, 0x100e, 0x0004, /* lmg %r0,%r1,14(%r1) */
#endif
0x07f1 /* br %r1 */
};
unsigned long *tramp = (unsigned long *)&closure->tramp;
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
#ifndef __s390x__
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
*(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
*(short *)&closure->tramp [4] = 0x1006;
*(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
*(long *)&closure->tramp [8] = (long)codeloc;
*(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
#else
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
*(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
*(short *)&closure->tramp [4] = 0x100e;
*(short *)&closure->tramp [6] = 0x0004;
*(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
*(long *)&closure->tramp[16] = (long)codeloc;
*(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
#endif
memcpy (tramp, template, sizeof(template));
tramp[2] = (unsigned long)codeloc;
tramp[3] = (unsigned long)&ffi_closure_SYSV;
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}
/*======================== End of Routine ============================*/
/* Build a Go language closure. */
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
void (*fun)(ffi_cif*,void*,void**,void*))
{
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
closure->tramp = ffi_go_closure_SYSV;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}

View file

@ -52,10 +52,13 @@ typedef enum ffi_abi {
} ffi_abi;
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#ifdef S390X
#define FFI_TRAMPOLINE_SIZE 32
#else

View file

@ -0,0 +1,11 @@
/* If these values change, sysv.S must be adapted! */
#define FFI390_RET_DOUBLE 0
#define FFI390_RET_FLOAT 1
#define FFI390_RET_INT64 2
#define FFI390_RET_INT32 3
#define FFI390_RET_VOID 4
#define FFI360_RET_MASK 7
#define FFI390_RET_IN_MEM 8
#define FFI390_RET_STRUCT (FFI390_RET_VOID | FFI390_RET_IN_MEM)

View file

@ -1,9 +1,9 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2000 Software AG
Copyright (c) 2008 Red Hat, Inc.
S390 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
@ -11,10 +11,10 @@
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
@ -29,405 +29,296 @@
#include <fficonfig.h>
#include <ffi.h>
#ifndef __s390x__
.text
.text
#ifndef __s390x__
# r2: frame
# r3: ret_type
# r4: ret_addr
# r5: fun
# r6: closure
# r2: cif->bytes
# r3: &ecif
# r4: ffi_prep_args
# r5: ret_type
# r6: ecif.rvalue
# ov: fn
# This assumes we are using gas.
.balign 8
.globl ffi_call_SYSV
FFI_HIDDEN(ffi_call_SYSV)
.type ffi_call_SYSV,%function
ffi_call_SYSV:
.LFB1:
stm %r6,%r15,24(%r15) # Save registers
.LCFI0:
basr %r13,0 # Set up base register
.Lbase:
lr %r11,%r15 # Set up frame pointer
.LCFI1:
sr %r15,%r2
ahi %r15,-96-48 # Allocate stack
lr %r8,%r6 # Save ecif.rvalue
sr %r9,%r9
ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
l %r7,96(%r11) # Load function address
st %r11,0(%r15) # Set up back chain
ahi %r11,-48 # Register save area
.LCFI2:
.cfi_startproc
st %r6,44(%r2) # Save registers
stm %r12,%r14,48(%r2)
lr %r13,%r2 # Install frame pointer
.cfi_rel_offset r6, 44
.cfi_rel_offset r12, 48
.cfi_rel_offset r13, 52
.cfi_rel_offset r14, 56
.cfi_def_cfa_register r13
st %r2,0(%r15) # Set up back chain
sla %r3,3 # ret_type *= 8
lr %r12,%r4 # Save ret_addr
lr %r1,%r5 # Save fun
lr %r0,%r6 # Install static chain
la %r2,96(%r15) # Save area
# r3 already holds &ecif
basr %r14,%r4 # Call ffi_prep_args
# Set return address, so that there is only one indirect jump.
#ifdef HAVE_AS_S390_ZARCH
larl %r14,.Ltable
ar %r14,%r3
#else
basr %r14,0
0: la %r14,.Ltable-0b(%r14,%r3)
#endif
lm %r2,%r6,0(%r11) # Load arguments
ld %f0,32(%r11)
ld %f2,40(%r11)
la %r14,0(%r13,%r9) # Set return address
br %r7 # ... and call function
lm %r2,%r6,8(%r13) # Load arguments
ld %f0,64(%r13)
ld %f2,72(%r13)
br %r1 # ... and call function
.LretNone: # Return void
l %r4,48+56(%r11)
lm %r6,%r15,48+24(%r11)
br %r4
.LretFloat:
l %r4,48+56(%r11)
ste %f0,0(%r8) # Return float
lm %r6,%r15,48+24(%r11)
br %r4
.LretDouble:
l %r4,48+56(%r11)
std %f0,0(%r8) # Return double
lm %r6,%r15,48+24(%r11)
br %r4
.LretInt32:
l %r4,48+56(%r11)
st %r2,0(%r8) # Return int
lm %r6,%r15,48+24(%r11)
br %r4
.LretInt64:
l %r4,48+56(%r11)
stm %r2,%r3,0(%r8) # Return long long
lm %r6,%r15,48+24(%r11)
br %r4
.balign 8
.Ltable:
.byte .LretNone-.Lbase # FFI390_RET_VOID
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
.byte .LretInt32-.Lbase # FFI390_RET_INT32
.byte .LretInt64-.Lbase # FFI390_RET_INT64
# FFI390_RET_DOUBLE
std %f0,0(%r12)
j .Ldone
.LFE1:
.ffi_call_SYSV_end:
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
.balign 8
# FFI390_RET_FLOAT
ste %f0,0(%r12)
j .Ldone
.balign 8
# FFI390_RET_INT64
st %r3,4(%r12)
nop
# fallthru
.balign 8
# FFI390_RET_INT32
st %r2,0(%r12)
nop
# fallthru
.balign 8
# FFI390_RET_VOID
.Ldone:
l %r14,56(%r13)
l %r12,48(%r13)
l %r6,44(%r13)
l %r13,52(%r13)
.cfi_restore 14
.cfi_restore 13
.cfi_restore 12
.cfi_restore 6
.cfi_def_cfa r15, 96
br %r14
.cfi_endproc
.size ffi_call_SYSV,.-ffi_call_SYSV
.balign 8
.globl ffi_go_closure_SYSV
FFI_HIDDEN(ffi_go_closure_SYSV)
.type ffi_go_closure_SYSV,%function
ffi_go_closure_SYSV:
.cfi_startproc
stm %r2,%r6,8(%r15) # Save arguments
lr %r4,%r0 # Load closure -> user_data
l %r2,4(%r4) # ->cif
l %r3,8(%r4) # ->fun
j .Ldoclosure
.cfi_endproc
.balign 8
.globl ffi_closure_SYSV
FFI_HIDDEN(ffi_closure_SYSV)
.type ffi_closure_SYSV,%function
ffi_closure_SYSV:
.LFB2:
.cfi_startproc
stm %r2,%r6,8(%r15) # Save arguments
lr %r4,%r0 # Closure
l %r2,16(%r4) # ->cif
l %r3,20(%r4) # ->fun
l %r4,24(%r4) # ->user_data
.Ldoclosure:
stm %r12,%r15,48(%r15) # Save registers
.LCFI10:
lr %r12,%r15
.cfi_def_cfa_register r12
.cfi_rel_offset r6, 24
.cfi_rel_offset r12, 48
.cfi_rel_offset r13, 52
.cfi_rel_offset r14, 56
.cfi_rel_offset r15, 60
#ifndef HAVE_AS_S390_ZARCH
basr %r13,0 # Set up base register
.Lcbase:
stm %r2,%r6,8(%r15) # Save arguments
std %f0,64(%r15)
std %f2,72(%r15)
lr %r1,%r15 # Set up stack frame
ahi %r15,-96
.LCFI11:
l %r12,.Lchelper-.Lcbase(%r13) # Get helper function
lr %r2,%r0 # Closure
la %r3,8(%r1) # GPRs
la %r4,64(%r1) # FPRs
la %r5,96(%r1) # Overflow
st %r1,0(%r15) # Set up back chain
l %r1,.Lchelper-.Lcbase(%r13) # Get helper function
#endif
ahi %r15,-96-8 # Set up stack frame
st %r12,0(%r15) # Set up back chain
bas %r14,0(%r12,%r13) # Call helper
std %f0,64(%r12) # Save fp arguments
std %f2,72(%r12)
l %r4,96+56(%r15)
ld %f0,96+64(%r15) # Load return registers
lm %r2,%r3,96+8(%r15)
lm %r12,%r15,96+48(%r15)
br %r4
la %r5,96(%r12) # Overflow
st %r5,96(%r15)
la %r6,64(%r12) # FPRs
la %r5,8(%r12) # GPRs
#ifdef HAVE_AS_S390_ZARCH
brasl %r14,ffi_closure_helper_SYSV
#else
bas %r14,0(%r1,%r13) # Call helper
#endif
lr %r15,%r12
.cfi_def_cfa_register r15
lm %r12,%r14,48(%r12) # Restore saved registers
l %r6,24(%r15)
ld %f0,64(%r15) # Load return registers
lm %r2,%r3,8(%r15)
br %r14
.cfi_endproc
#ifndef HAVE_AS_S390_ZARCH
.align 4
.Lchelper:
.long ffi_closure_helper_SYSV-.Lcbase
#endif
.LFE2:
.ffi_closure_SYSV_end:
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -4 # CIE Data Alignment Factor
.byte 0xe # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x1b # FDE Encoding (pcrel sdata4)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0xf
.uleb128 0x60
.align 4
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.4byte .LFB1-. # FDE initial location
.4byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x9
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0xa
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0xb
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0xc
.byte 0x8b # DW_CFA_offset, column 0xb
.uleb128 0xd
.byte 0x8a # DW_CFA_offset, column 0xa
.uleb128 0xe
.byte 0x89 # DW_CFA_offset, column 0x9
.uleb128 0xf
.byte 0x88 # DW_CFA_offset, column 0x8
.uleb128 0x10
.byte 0x87 # DW_CFA_offset, column 0x7
.uleb128 0x11
.byte 0x86 # DW_CFA_offset, column 0x6
.uleb128 0x12
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0xb
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI2-.LCFI1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0x90
.align 4
.LEFDE1:
.LSFDE2:
.4byte .LEFDE2-.LASFDE2 # FDE Length
.LASFDE2:
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
.4byte .LFB2-. # FDE initial location
.4byte .LFE2-.LFB2 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI10-.LFB2
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x9
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0xa
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0xb
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0xc
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI11-.LCFI10
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xc0
.align 4
.LEFDE2:
.size ffi_closure_SYSV,.-ffi_closure_SYSV
#else
.text
# r2: cif->bytes
# r3: &ecif
# r4: ffi_prep_args
# r5: ret_type
# r6: ecif.rvalue
# ov: fn
# r2: frame
# r3: ret_type
# r4: ret_addr
# r5: fun
# r6: closure
# This assumes we are using gas.
.balign 8
.globl ffi_call_SYSV
FFI_HIDDEN(ffi_call_SYSV)
.type ffi_call_SYSV,%function
ffi_call_SYSV:
.LFB1:
stmg %r6,%r15,48(%r15) # Save registers
.LCFI0:
larl %r13,.Lbase # Set up base register
lgr %r11,%r15 # Set up frame pointer
.LCFI1:
sgr %r15,%r2
aghi %r15,-160-80 # Allocate stack
lgr %r8,%r6 # Save ecif.rvalue
llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
lg %r7,160(%r11) # Load function address
stg %r11,0(%r15) # Set up back chain
aghi %r11,-80 # Register save area
.LCFI2:
.cfi_startproc
stg %r6,88(%r2) # Save registers
stmg %r12,%r14,96(%r2)
lgr %r13,%r2 # Install frame pointer
.cfi_rel_offset r6, 88
.cfi_rel_offset r12, 96
.cfi_rel_offset r13, 104
.cfi_rel_offset r14, 112
.cfi_def_cfa_register r13
stg %r2,0(%r15) # Set up back chain
larl %r14,.Ltable # Set up return address
slag %r3,%r3,3 # ret_type *= 8
lgr %r12,%r4 # Save ret_addr
lgr %r1,%r5 # Save fun
lgr %r0,%r6 # Install static chain
agr %r14,%r3
lmg %r2,%r6,16(%r13) # Load arguments
ld %f0,128(%r13)
ld %f2,136(%r13)
ld %f4,144(%r13)
ld %f6,152(%r13)
br %r1 # ... and call function
la %r2,160(%r15) # Save area
# r3 already holds &ecif
basr %r14,%r4 # Call ffi_prep_args
lmg %r2,%r6,0(%r11) # Load arguments
ld %f0,48(%r11)
ld %f2,56(%r11)
ld %f4,64(%r11)
ld %f6,72(%r11)
la %r14,0(%r13,%r9) # Set return address
br %r7 # ... and call function
.Lbase:
.LretNone: # Return void
lg %r4,80+112(%r11)
lmg %r6,%r15,80+48(%r11)
br %r4
.LretFloat:
lg %r4,80+112(%r11)
ste %f0,0(%r8) # Return float
lmg %r6,%r15,80+48(%r11)
br %r4
.LretDouble:
lg %r4,80+112(%r11)
std %f0,0(%r8) # Return double
lmg %r6,%r15,80+48(%r11)
br %r4
.LretInt32:
lg %r4,80+112(%r11)
st %r2,0(%r8) # Return int
lmg %r6,%r15,80+48(%r11)
br %r4
.LretInt64:
lg %r4,80+112(%r11)
stg %r2,0(%r8) # Return long
lmg %r6,%r15,80+48(%r11)
br %r4
.balign 8
.Ltable:
.byte .LretNone-.Lbase # FFI390_RET_VOID
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
.byte .LretInt32-.Lbase # FFI390_RET_INT32
.byte .LretInt64-.Lbase # FFI390_RET_INT64
# FFI390_RET_DOUBLE
std %f0,0(%r12)
j .Ldone
.LFE1:
.ffi_call_SYSV_end:
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
.balign 8
# FFI390_RET_DOUBLE
ste %f0,0(%r12)
j .Ldone
.balign 8
# FFI390_RET_INT64
stg %r2,0(%r12)
.balign 8
# FFI390_RET_INT32
# Never used, as we always store type ffi_arg.
# But the stg above is 6 bytes and we cannot
# jump around this case, so fall through.
nop
nop
.balign 8
# FFI390_RET_VOID
.Ldone:
lg %r14,112(%r13)
lg %r12,96(%r13)
lg %r6,88(%r13)
lg %r13,104(%r13)
.cfi_restore r14
.cfi_restore r13
.cfi_restore r12
.cfi_restore r6
.cfi_def_cfa r15, 160
br %r14
.cfi_endproc
.size ffi_call_SYSV,.-ffi_call_SYSV
.balign 8
.globl ffi_go_closure_SYSV
FFI_HIDDEN(ffi_go_closure_SYSV)
.type ffi_go_closure_SYSV,%function
ffi_go_closure_SYSV:
.cfi_startproc
stmg %r2,%r6,16(%r15) # Save arguments
lgr %r4,%r0 # Load closure -> user_data
lg %r2,8(%r4) # ->cif
lg %r3,16(%r4) # ->fun
j .Ldoclosure
.cfi_endproc
.size ffi_go_closure_SYSV,.-ffi_go_closure_SYSV
.balign 8
.globl ffi_closure_SYSV
FFI_HIDDEN(ffi_closure_SYSV)
.type ffi_closure_SYSV,%function
ffi_closure_SYSV:
.LFB2:
stmg %r14,%r15,112(%r15) # Save registers
.LCFI10:
.cfi_startproc
stmg %r2,%r6,16(%r15) # Save arguments
std %f0,128(%r15)
std %f2,136(%r15)
std %f4,144(%r15)
std %f6,152(%r15)
lgr %r1,%r15 # Set up stack frame
aghi %r15,-160
.LCFI11:
lgr %r2,%r0 # Closure
la %r3,16(%r1) # GPRs
la %r4,128(%r1) # FPRs
la %r5,160(%r1) # Overflow
stg %r1,0(%r15) # Set up back chain
lgr %r4,%r0 # Load closure
lg %r2,32(%r4) # ->cif
lg %r3,40(%r4) # ->fun
lg %r4,48(%r4) # ->user_data
.Ldoclosure:
stmg %r13,%r15,104(%r15) # Save registers
lgr %r13,%r15
.cfi_def_cfa_register r13
.cfi_rel_offset r6, 48
.cfi_rel_offset r13, 104
.cfi_rel_offset r14, 112
.cfi_rel_offset r15, 120
aghi %r15,-160-16 # Set up stack frame
stg %r13,0(%r15) # Set up back chain
std %f0,128(%r13) # Save fp arguments
std %f2,136(%r13)
std %f4,144(%r13)
std %f6,152(%r13)
la %r5,160(%r13) # Overflow
stg %r5,160(%r15)
la %r6,128(%r13) # FPRs
la %r5,16(%r13) # GPRs
brasl %r14,ffi_closure_helper_SYSV # Call helper
lg %r14,160+112(%r15)
ld %f0,160+128(%r15) # Load return registers
lg %r2,160+16(%r15)
la %r15,160(%r15)
lgr %r15,%r13
.cfi_def_cfa_register r15
lmg %r13,%r14,104(%r13) # Restore saved registers
lg %r6,48(%r15)
ld %f0,128(%r15) # Load return registers
lg %r2,16(%r15)
br %r14
.LFE2:
.ffi_closure_SYSV_end:
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0xe # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x1b # FDE Encoding (pcrel sdata4)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0xf
.uleb128 0xa0
.align 8
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.4byte .LFB1-. # FDE initial location
.4byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x5
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0x6
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0x7
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0x8
.byte 0x8b # DW_CFA_offset, column 0xb
.uleb128 0x9
.byte 0x8a # DW_CFA_offset, column 0xa
.uleb128 0xa
.byte 0x89 # DW_CFA_offset, column 0x9
.uleb128 0xb
.byte 0x88 # DW_CFA_offset, column 0x8
.uleb128 0xc
.byte 0x87 # DW_CFA_offset, column 0x7
.uleb128 0xd
.byte 0x86 # DW_CFA_offset, column 0x6
.uleb128 0xe
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0xb
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI2-.LCFI1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xf0
.align 8
.LEFDE1:
.LSFDE2:
.4byte .LEFDE2-.LASFDE2 # FDE Length
.LASFDE2:
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
.4byte .LFB2-. # FDE initial location
.4byte .LFE2-.LFB2 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI10-.LFB2
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x5
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0x6
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI11-.LCFI10
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0x140
.align 8
.LEFDE2:
#endif
.cfi_endproc
.size ffi_closure_SYSV,.-ffi_closure_SYSV
#endif /* !s390x */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits

View file

@ -41,7 +41,7 @@
#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
#endif
/* If the structure has essentialy an unique element, return its type. */
/* If the structure has essentially an unique element, return its type. */
static int
simple_type (ffi_type *arg)
{

File diff suppressed because it is too large Load diff

608
libffi/src/sparc/ffi64.c Normal file
View file

@ -0,0 +1,608 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2011, 2013 Anthony Green
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
SPARC 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 THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include "internal.h"
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
all further uses in this file will refer to the 128-bit type. */
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
# if FFI_TYPE_LONGDOUBLE != 4
# error FFI_TYPE_LONGDOUBLE out of date
# endif
#else
# undef FFI_TYPE_LONGDOUBLE
# define FFI_TYPE_LONGDOUBLE 4
#endif
#ifdef SPARC64
/* Flatten the contents of a structure to the parts that are passed in
floating point registers. The return is a bit mask wherein bit N
set means bytes [4*n, 4*n+3] are passed in %fN.
We encode both the (running) size (maximum 32) and mask (maxumum 255)
into one integer. The size is placed in the low byte, so that align
and addition work correctly. The mask is placed in the second byte. */
static int
ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
{
ffi_type **elts;
ffi_type *t;
if (outer_type->type == FFI_TYPE_COMPLEX)
{
int m = 0, tt = outer_type->elements[0]->type;
size_t z = outer_type->size;
if (tt == FFI_TYPE_FLOAT
|| tt == FFI_TYPE_DOUBLE
|| tt == FFI_TYPE_LONGDOUBLE)
m = (1 << (z / 4)) - 1;
return (m << 8) | z;
}
FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
{
size_t z = t->size;
int o, m, tt;
size_mask = ALIGN(size_mask, t->alignment);
switch (t->type)
{
case FFI_TYPE_STRUCT:
size_mask = ffi_struct_float_mask (t, size_mask);
continue;
case FFI_TYPE_COMPLEX:
tt = t->elements[0]->type;
if (tt != FFI_TYPE_FLOAT
&& tt != FFI_TYPE_DOUBLE
&& tt != FFI_TYPE_LONGDOUBLE)
break;
/* FALLTHRU */
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
m = (1 << (z / 4)) - 1; /* compute mask for type */
o = (size_mask >> 2) & 0x3f; /* extract word offset */
size_mask |= m << (o + 8); /* insert mask into place */
break;
}
size_mask += z;
}
size_mask = ALIGN(size_mask, outer_type->alignment);
FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
return size_mask;
}
/* Merge floating point data into integer data. If the structure is
entirely floating point, simply return a pointer to the fp data. */
static void *
ffi_struct_float_merge (int size_mask, void *vi, void *vf)
{
int size = size_mask & 0xff;
int mask = size_mask >> 8;
int n = size >> 2;
if (mask == 0)
return vi;
else if (mask == (1 << n) - 1)
return vf;
else
{
unsigned int *wi = vi, *wf = vf;
int i;
for (i = 0; i < n; ++i)
if ((mask >> i) & 1)
wi[i] = wf[i];
return vi;
}
}
/* Similar, but place the data into VD in the end. */
void FFI_HIDDEN
ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf)
{
int size = size_mask & 0xff;
int mask = size_mask >> 8;
int n = size >> 2;
if (mask == 0)
;
else if (mask == (1 << n) - 1)
vi = vf;
else
{
unsigned int *wd = vd, *wi = vi, *wf = vf;
int i;
for (i = 0; i < n; ++i)
wd[i] = ((mask >> i) & 1 ? wf : wi)[i];
return;
}
memcpy (vd, vi, size);
}
/* Perform machine dependent cif processing */
static ffi_status
ffi_prep_cif_machdep_core(ffi_cif *cif)
{
ffi_type *rtype = cif->rtype;
int rtt = rtype->type;
size_t bytes = 0;
int i, n, flags;
/* Set the return type flag */
switch (rtt)
{
case FFI_TYPE_VOID:
flags = SPARC_RET_VOID;
break;
case FFI_TYPE_FLOAT:
flags = SPARC_RET_F_1;
break;
case FFI_TYPE_DOUBLE:
flags = SPARC_RET_F_2;
break;
case FFI_TYPE_LONGDOUBLE:
flags = SPARC_RET_F_4;
break;
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
if (rtype->size > 32)
{
flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM;
bytes = 8;
}
else
{
int size_mask = ffi_struct_float_mask (rtype, 0);
int word_size = (size_mask >> 2) & 0x3f;
int all_mask = (1 << word_size) - 1;
int fp_mask = size_mask >> 8;
flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT;
/* For special cases of all-int or all-fp, we can return
the value directly without popping through a struct copy. */
if (fp_mask == 0)
{
if (rtype->alignment >= 8)
{
if (rtype->size == 8)
flags = SPARC_RET_INT64;
else if (rtype->size == 16)
flags = SPARC_RET_INT128;
}
}
else if (fp_mask == all_mask)
switch (word_size)
{
case 1: flags = SPARC_RET_F_1; break;
case 2: flags = SPARC_RET_F_2; break;
case 3: flags = SP_V9_RET_F_3; break;
case 4: flags = SPARC_RET_F_4; break;
/* 5 word structures skipped; handled via RET_STRUCT. */
case 6: flags = SPARC_RET_F_6; break;
/* 7 word structures skipped; handled via RET_STRUCT. */
case 8: flags = SPARC_RET_F_8; break;
}
}
break;
case FFI_TYPE_SINT8:
flags = SPARC_RET_SINT8;
break;
case FFI_TYPE_UINT8:
flags = SPARC_RET_UINT8;
break;
case FFI_TYPE_SINT16:
flags = SPARC_RET_SINT16;
break;
case FFI_TYPE_UINT16:
flags = SPARC_RET_UINT16;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
flags = SP_V9_RET_SINT32;
break;
case FFI_TYPE_UINT32:
flags = SPARC_RET_UINT32;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
flags = SPARC_RET_INT64;
break;
default:
abort();
}
bytes = 0;
for (i = 0, n = cif->nargs; i < n; ++i)
{
ffi_type *ty = cif->arg_types[i];
size_t z = ty->size;
size_t a = ty->alignment;
switch (ty->type)
{
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
/* Large structs passed by reference. */
if (z > 16)
{
a = z = 8;
break;
}
/* Small structs may be passed in integer or fp regs or both. */
if (bytes >= 16*8)
break;
if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
break;
/* FALLTHRU */
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
flags |= SPARC_FLAG_FP_ARGS;
break;
}
bytes = ALIGN(bytes, a);
bytes += ALIGN(z, 8);
}
/* Sparc call frames require that space is allocated for 6 args,
even if they aren't used. Make that space if necessary. */
if (bytes < 6 * 8)
bytes = 6 * 8;
/* The stack must be 2 word aligned, so round bytes up appropriately. */
bytes = ALIGN(bytes, 16);
/* Include the call frame to prep_args. */
bytes += 8*16 + 8*8;
cif->bytes = bytes;
cif->flags = flags;
return FFI_OK;
}
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif *cif)
{
cif->nfixedargs = cif->nargs;
return ffi_prep_cif_machdep_core(cif);
}
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
{
cif->nfixedargs = nfixedargs;
return ffi_prep_cif_machdep_core(cif);
}
extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
int FFI_HIDDEN
ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
{
ffi_type **p_arg;
int flags = cif->flags;
int i, nargs;
if (rvalue == NULL)
{
if (flags & SPARC_FLAG_RET_IN_MEM)
{
/* Since we pass the pointer to the callee, we need a value.
We allowed for this space in ffi_call, before ffi_call_v8
alloca'd the space. */
rvalue = (char *)argp + cif->bytes;
}
else
{
/* Otherwise, we can ignore the return value. */
flags = SPARC_RET_VOID;
}
}
#ifdef USING_PURIFY
/* Purify will probably complain in our assembly routine,
unless we zero out this memory. */
memset(argp, 0, 6*8);
#endif
if (flags & SPARC_FLAG_RET_IN_MEM)
*argp++ = (unsigned long)rvalue;
p_arg = cif->arg_types;
for (i = 0, nargs = cif->nargs; i < nargs; i++)
{
ffi_type *ty = p_arg[i];
void *a = avalue[i];
size_t z;
switch (ty->type)
{
case FFI_TYPE_SINT8:
*argp++ = *(SINT8 *)a;
break;
case FFI_TYPE_UINT8:
*argp++ = *(UINT8 *)a;
break;
case FFI_TYPE_SINT16:
*argp++ = *(SINT16 *)a;
break;
case FFI_TYPE_UINT16:
*argp++ = *(UINT16 *)a;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
*argp++ = *(SINT32 *)a;
break;
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
*argp++ = *(UINT32 *)a;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER:
case FFI_TYPE_DOUBLE:
*argp++ = *(UINT64 *)a;
break;
case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
z = ty->size;
if (z > 16)
{
/* For structures larger than 16 bytes we pass reference. */
*argp++ = (unsigned long)a;
break;
}
if (((unsigned long)argp & 15) && ty->alignment > 8)
argp++;
memcpy(argp, a, z);
argp += ALIGN(z, 8) / 8;
break;
default:
abort();
}
}
return flags;
}
static void
ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
size_t bytes = cif->bytes;
FFI_ASSERT (cif->abi == FFI_V9);
if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
bytes += ALIGN (cif->rtype->size, 16);
ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
}
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_call_int(cif, fn, rvalue, avalue, NULL);
}
void
ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int(cif, fn, rvalue, avalue, closure);
}
#ifdef __GNUC__
static inline void
ffi_flush_icache (void *p)
{
asm volatile ("flush %0; flush %0+8" : : "r" (p) : "memory");
}
#else
extern void ffi_flush_icache (void *) FFI_HIDDEN;
#endif
extern void ffi_closure_v9(void) FFI_HIDDEN;
extern void ffi_go_closure_v9(void) FFI_HIDDEN;
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data,
void *codeloc)
{
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
unsigned long fn;
if (cif->abi != FFI_V9)
return FFI_BAD_ABI;
/* Trampoline address is equal to the closure address. We take advantage
of that to reduce the trampoline size by 8 bytes. */
fn = (unsigned long) ffi_closure_v9;
tramp[0] = 0x83414000; /* rd %pc, %g1 */
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
tramp[2] = 0x81c14000; /* jmp %g5 */
tramp[3] = 0x01000000; /* nop */
*((unsigned long *) &tramp[4]) = fn;
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
ffi_flush_icache (closure);
return FFI_OK;
}
ffi_status
ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*))
{
if (cif->abi != FFI_V9)
return FFI_BAD_ABI;
closure->tramp = ffi_go_closure_v9;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}
int FFI_HIDDEN
ffi_closure_sparc_inner_v9(ffi_cif *cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data, void *rvalue,
unsigned long *gpr, unsigned long *fpr)
{
ffi_type **arg_types;
void **avalue;
int i, argn, argx, nargs, flags, nfixedargs;
arg_types = cif->arg_types;
nargs = cif->nargs;
flags = cif->flags;
nfixedargs = cif->nfixedargs;
avalue = alloca(nargs * sizeof(void *));
/* Copy the caller's structure return address so that the closure
returns the data directly to the caller. */
if (flags & SPARC_FLAG_RET_IN_MEM)
{
rvalue = (void *) gpr[0];
/* Skip the structure return address. */
argn = 1;
}
else
argn = 0;
/* Grab the addresses of the arguments from the stack frame. */
for (i = 0; i < nargs; i++, argn = argx)
{
int named = i < nfixedargs;
ffi_type *ty = arg_types[i];
void *a = &gpr[argn];
size_t z;
argx = argn + 1;
switch (ty->type)
{
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
z = ty->size;
if (z > 16)
a = *(void **)a;
else
{
argx = argn + ALIGN (z, 8) / 8;
if (named && argn < 16)
{
int size_mask = ffi_struct_float_mask (ty, 0);
int argn_mask = (0xffff00 >> argn) & 0xff00;
/* Eliminate fp registers off the end. */
size_mask = (size_mask & 0xff) | (size_mask & argn_mask);
a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn);
}
}
break;
case FFI_TYPE_LONGDOUBLE:
argn = ALIGN (argn, 2);
a = (named && argn < 16 ? fpr : gpr) + argn;
argx = argn + 2;
break;
case FFI_TYPE_DOUBLE:
if (named && argn < 16)
a = fpr + argn;
break;
case FFI_TYPE_FLOAT:
if (named && argn < 16)
a = fpr + argn;
a += 4;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
a += 4;
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
a += 6;
break;
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
a += 7;
break;
default:
abort();
}
avalue[i] = a;
}
/* Invoke the closure. */
fun (cif, rvalue, avalue, user_data);
/* Tell ffi_closure_sparc how to perform return type promotions. */
return flags;
}
#endif /* SPARC64 */

View file

@ -46,42 +46,36 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_V8,
FFI_V8PLUS,
/* See below for the COMPAT_V9 rationale. */
FFI_COMPAT_V9,
FFI_V9,
FFI_LAST_ABI,
#ifdef SPARC64
FFI_DEFAULT_ABI = FFI_V9
FFI_V9,
FFI_DEFAULT_ABI = FFI_V9,
#else
FFI_DEFAULT_ABI = FFI_V8
FFI_V8,
FFI_DEFAULT_ABI = FFI_V8,
#endif
FFI_LAST_ABI
} ffi_abi;
#endif
#define V8_ABI_P(abi) ((abi) == FFI_V8 || (abi) == FFI_V8PLUS)
#define V9_ABI_P(abi) ((abi) == FFI_COMPAT_V9 || (abi) == FFI_V9)
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION 1
#define FFI_TARGET_HAS_COMPLEX_TYPE 1
#define FFI_TARGET_SPECIFIC_VARIADIC 1
/* The support of variadic functions was broken in the original implementation
of the FFI_V9 ABI. This has been fixed by adding one extra field to the
CIF structure (nfixedargs field), which means that the ABI of libffi itself
has changed. In order to support applications using the original ABI, we
have renamed FFI_V9 into FFI_COMPAT_V9 and defined a new FFI_V9 value. */
#ifdef SPARC64
#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
# define FFI_TARGET_SPECIFIC_VARIADIC 1
# define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#ifdef SPARC64
#define FFI_TRAMPOLINE_SIZE 24
#else
#define FFI_TRAMPOLINE_SIZE 16
#endif
#define FFI_NATIVE_RAW_API 0
#endif

View file

@ -0,0 +1,26 @@
#define SPARC_RET_VOID 0
#define SPARC_RET_STRUCT 1
#define SPARC_RET_UINT8 2
#define SPARC_RET_SINT8 3
#define SPARC_RET_UINT16 4
#define SPARC_RET_SINT16 5
#define SPARC_RET_UINT32 6
#define SP_V9_RET_SINT32 7 /* v9 only */
#define SP_V8_RET_CPLX16 7 /* v8 only */
#define SPARC_RET_INT64 8
#define SPARC_RET_INT128 9
/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT. */
#define SPARC_RET_F_8 10
#define SPARC_RET_F_6 11
#define SPARC_RET_F_4 12
#define SPARC_RET_F_2 13
#define SP_V9_RET_F_3 14 /* v9 only */
#define SP_V8_RET_CPLX8 14 /* v8 only */
#define SPARC_RET_F_1 15
#define SPARC_FLAG_RET_MASK 15
#define SPARC_FLAG_RET_IN_MEM 32
#define SPARC_FLAG_FP_ARGS 64
#define SPARC_SIZEMASK_SHIFT 8

View file

@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
v8.S - Copyright (c) 2013 The Written Word, Inc.
Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
SPARC Foreign Function Interface
SPARC Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -24,153 +25,243 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include "internal.h"
#ifndef SPARC64
#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
#define ARGS (64+4) /* Offset of register area in frame */
#define C2(X, Y) X ## Y
#define C1(X, Y) C2(X, Y)
.text
#ifdef __USER_LABEL_PREFIX__
# define C(Y) C1(__USER_LABEL_PREFIX__, Y)
#else
# define C(Y) Y
#endif
#define L(Y) C1(.L, Y)
.text
#ifndef __GNUC__
.align 8
.globl ffi_call_v8
.globl _ffi_call_v8
.globl C(ffi_flush_icache)
.type C(ffi_flush_icache),@function
FFI_HIDDEN(C(ffi_flush_icache))
ffi_call_v8:
_ffi_call_v8:
.LLFB1:
save %sp, -STACKFRAME, %sp
.LLCFI0:
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
add %sp, STACKFRAME, %l0 ! %l0 has start of
! frame to set up
mov %l0, %o0 ! call routine to set up frame
call %i0
mov %i1, %o1 ! (delay)
ld [%l0+ARGS], %o0 ! call foreign function
ld [%l0+ARGS+4], %o1
ld [%l0+ARGS+8], %o2
ld [%l0+ARGS+12], %o3
ld [%l0+ARGS+16], %o4
ld [%l0+ARGS+20], %o5
call %i5
mov %l0, %sp ! (delay) switch to frame
nop ! STRUCT returning functions skip 12 instead of 8 bytes
! If the return value pointer is NULL, assume no return value.
tst %i4
bz done
C(ffi_flush_icache):
cfi_startproc
1: iflush %o0
iflush %o+8
nop
nop
nop
nop
nop
retl
nop
cfi_endproc
.size C(ffi_flush_icache), . - C(ffi_flush_icache)
#endif
cmp %i3, FFI_TYPE_INT
be,a done
st %o0, [%i4] ! (delay)
.macro E index
.align 16
.org 2b + \index * 16
.endm
cmp %i3, FFI_TYPE_FLOAT
be,a done
st %f0, [%i4+0] ! (delay)
.align 8
.globl C(ffi_call_v8)
.type C(ffi_call_v8),@function
FFI_HIDDEN(C(ffi_call_v8))
cmp %i3, FFI_TYPE_DOUBLE
be,a double
st %f0, [%i4+0] ! (delay)
C(ffi_call_v8):
cfi_startproc
! Allocate a stack frame sized by ffi_call.
save %sp, %o4, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cmp %i3, FFI_TYPE_SINT8
be,a sint8
sll %o0, 24, %o0 ! (delay)
mov %i0, %o0 ! copy cif
add %sp, 64+32, %o1 ! load args area
mov %i2, %o2 ! copy rvalue
call C(ffi_prep_args_v8)
mov %i3, %o3 ! copy avalue
cmp %i3, FFI_TYPE_UINT8
be,a uint8
sll %o0, 24, %o0 ! (delay)
add %sp, 32, %sp ! deallocate prep frame
and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type
srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size
ld [%sp+64+4], %o0 ! load all argument registers
ld [%sp+64+8], %o1
ld [%sp+64+12], %o2
ld [%sp+64+16], %o3
cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4
ld [%sp+64+20], %o4
be 8f
ld [%sp+64+24], %o5
cmp %i3, FFI_TYPE_SINT16
be,a sint16
sll %o0, 16, %o0 ! (delay)
! Call foreign function
call %i1
mov %i5, %g2 ! load static chain
cmp %i3, FFI_TYPE_UINT16
be,a uint16
sll %o0, 16, %o0 ! (delay)
0: call 1f ! load pc in %o7
sll %l0, 4, %l0
1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16
jmp %o7+(2f-0b)
nop
cmp %i3, FFI_TYPE_SINT64
be,a longlong
st %o0, [%i4+0] ! (delay)
done:
! Note that each entry is 4 insns, enforced by the E macro.
.align 16
2:
E SPARC_RET_VOID
ret
restore
double:
st %f1, [%i4+4]
restore
E SPARC_RET_STRUCT
unimp
E SPARC_RET_UINT8
and %o0, 0xff, %o0
st %o0, [%i2]
ret
restore
sint8:
sra %o0, 24, %o0
st %o0, [%i4+0]
restore
E SPARC_RET_SINT8
sll %o0, 24, %o0
b 7f
sra %o0, 24, %o0
E SPARC_RET_UINT16
sll %o0, 16, %o0
b 7f
srl %o0, 16, %o0
E SPARC_RET_SINT16
sll %o0, 16, %o0
b 7f
sra %o0, 16, %o0
E SPARC_RET_UINT32
7: st %o0, [%i2]
ret
restore
uint8:
srl %o0, 24, %o0
st %o0, [%i4+0]
restore
E SP_V8_RET_CPLX16
sth %o0, [%i2+2]
b 9f
srl %o0, 16, %o0
E SPARC_RET_INT64
st %o0, [%i2]
st %o1, [%i2+4]
ret
restore
sint16:
sra %o0, 16, %o0
st %o0, [%i4+0]
restore
E SPARC_RET_INT128
std %o0, [%i2]
std %o2, [%i2+8]
ret
restore
uint16:
srl %o0, 16, %o0
st %o0, [%i4+0]
restore
E SPARC_RET_F_8
st %f7, [%i2+7*4]
nop
st %f6, [%i2+6*4]
nop
E SPARC_RET_F_6
st %f5, [%i2+5*4]
nop
st %f4, [%i2+4*4]
nop
E SPARC_RET_F_4
st %f3, [%i2+3*4]
nop
st %f2, [%i2+2*4]
nop
E SPARC_RET_F_2
st %f1, [%i2+4]
st %f0, [%i2]
ret
restore
longlong:
st %o1, [%i4+4]
restore
E SP_V8_RET_CPLX8
stb %o0, [%i2+1]
b 10f
srl %o0, 8, %o0
E SPARC_RET_F_1
st %f0, [%i2]
ret
restore
.LLFE1:
restore
.ffi_call_v8_end:
.size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
.align 8
9: sth %o0, [%i2]
ret
restore
.align 8
10: stb %o0, [%i2]
ret
restore
! Struct returning functions expect and skip the unimp here.
! To make it worse, conforming callees examine the unimp and
! make sure the low 12 bits of the unimp match the size of
! the struct being returned.
.align 8
8: call 1f ! load pc in %o7
sll %l1, 2, %l0 ! size * 4
1: sll %l1, 4, %l1 ! size * 16
add %l0, %l1, %l0 ! size * 20
add %o7, %l0, %o7 ! o7 = 0b + size*20
jmp %o7+(2f-8b)
mov %i5, %g2 ! load static chain
2:
.rept 0x1000
call %i1
nop
unimp (. - 2b) / 20
ret
restore
.endr
cfi_endproc
.size C(ffi_call_v8),. - C(ffi_call_v8)
#undef STACKFRAME
#define STACKFRAME 104 /* 16*4 register window +
1*4 struct return +
6*4 args backing store +
3*4 locals */
/* 16*4 register window + 1*4 struct return + 6*4 args backing store
+ 8*4 return storage + 1*4 alignment. */
#define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
/* ffi_closure_v8(...)
Receives the closure argument in %g2. */
.text
.align 8
.globl ffi_closure_v8
ffi_closure_v8:
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
.register %g2, #scratch
.register %g2, #scratch
#endif
.LLFB2:
! Reserve frame space for all arguments in case
! we need to align them on a 8-byte boundary.
ld [%g2+FFI_TRAMPOLINE_SIZE], %g1
ld [%g1+4], %g1
sll %g1, 3, %g1
add %g1, STACKFRAME, %g1
! %g1 == STACKFRAME + 8*nargs
neg %g1
save %sp, %g1, %sp
.LLCFI1:
.align 8
.globl C(ffi_go_closure_v8)
.type C(ffi_go_closure_v8),@function
FFI_HIDDEN(C(ffi_go_closure_v8))
C(ffi_go_closure_v8):
cfi_startproc
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
ld [%g2+4], %o0 ! load cif
ld [%g2+8], %o1 ! load fun
b 0f
mov %g2, %o2 ! load user_data
cfi_endproc
.size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
.align 8
.globl C(ffi_closure_v8)
.type C(ffi_closure_v8),@function
FFI_HIDDEN(C(ffi_closure_v8))
C(ffi_closure_v8):
cfi_startproc
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data
0:
! Store all of the potential argument registers in va_list format.
st %i0, [%fp+68+0]
st %i1, [%fp+68+4]
@ -180,137 +271,91 @@ ffi_closure_v8:
st %i5, [%fp+68+20]
! Call ffi_closure_sparc_inner to do the bulk of the work.
mov %g2, %o0
add %fp, -8, %o1
add %fp, 64, %o2
add %fp, -8*4, %o3
call ffi_closure_sparc_inner_v8
add %fp, -16, %o3
add %fp, 64, %o4
! Load up the return value in the proper type.
! See ffi_prep_cif_machdep for the list of cases.
cmp %o0, FFI_TYPE_VOID
be done1
cmp %o0, FFI_TYPE_INT
be done1
ld [%fp-8], %i0
cmp %o0, FFI_TYPE_FLOAT
be,a done1
ld [%fp-8], %f0
cmp %o0, FFI_TYPE_DOUBLE
be,a done1
ldd [%fp-8], %f0
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
cmp %o0, FFI_TYPE_LONGDOUBLE
be done2
#endif
cmp %o0, FFI_TYPE_STRUCT
be done2
cmp %o0, FFI_TYPE_SINT64
be,a done1
ldd [%fp-8], %i0
ld [%fp-8], %i0
done1:
jmp %i7+8
0: call 1f
and %o0, SPARC_FLAG_RET_MASK, %o0
1: sll %o0, 4, %o0 ! o0 = o0 * 16
add %o7, %o0, %o7 ! o7 = 0b + o0*16
jmp %o7+(2f-0b)
add %fp, -8*4, %i2
! Note that each entry is 4 insns, enforced by the E macro.
.align 16
2:
E SPARC_RET_VOID
ret
restore
done2:
! Skip 'unimp'.
E SPARC_RET_STRUCT
ld [%i2], %i0
jmp %i7+12
restore
.LLFE2:
.ffi_closure_v8_end:
.size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
#ifdef SPARC64
#define WS 8
#define nword xword
#define uanword uaxword
#else
#define WS 4
#define nword long
#define uanword uaword
#endif
#ifdef HAVE_RO_EH_FRAME
.section ".eh_frame",#alloc
#else
.section ".eh_frame",#alloc,#write
#endif
.LLframe1:
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
.LLSCIE1:
.uaword 0x0 ! CIE Identifier Tag
.byte 0x1 ! CIE Version
.ascii "zR\0" ! CIE Augmentation
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
.byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor
.byte 0xf ! CIE RA Column
.byte 0x1 ! uleb128 0x1; Augmentation size
#ifdef HAVE_AS_SPARC_UA_PCREL
.byte 0x1b ! FDE Encoding (pcrel sdata4)
#else
.byte 0x50 ! FDE Encoding (aligned absolute)
#endif
.byte 0xc ! DW_CFA_def_cfa
.byte 0xe ! uleb128 0xe
.byte 0x0 ! uleb128 0x0
.align WS
.LLECIE1:
.LLSFDE1:
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
.LLASFDE1:
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
#ifdef HAVE_AS_SPARC_UA_PCREL
.uaword %r_disp32(.LLFB1)
.uaword .LLFE1-.LLFB1 ! FDE address range
#else
.align WS
.nword .LLFB1
.uanword .LLFE1-.LLFB1 ! FDE address range
#endif
.byte 0x0 ! uleb128 0x0; Augmentation size
.byte 0x4 ! DW_CFA_advance_loc4
.uaword .LLCFI0-.LLFB1
.byte 0xd ! DW_CFA_def_cfa_register
.byte 0x1e ! uleb128 0x1e
.byte 0x2d ! DW_CFA_GNU_window_save
.byte 0x9 ! DW_CFA_register
.byte 0xf ! uleb128 0xf
.byte 0x1f ! uleb128 0x1f
.align WS
.LLEFDE1:
.LLSFDE2:
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
.LLASFDE2:
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
#ifdef HAVE_AS_SPARC_UA_PCREL
.uaword %r_disp32(.LLFB2)
.uaword .LLFE2-.LLFB2 ! FDE address range
#else
.align WS
.nword .LLFB2
.uanword .LLFE2-.LLFB2 ! FDE address range
#endif
.byte 0x0 ! uleb128 0x0; Augmentation size
.byte 0x4 ! DW_CFA_advance_loc4
.uaword .LLCFI1-.LLFB2
.byte 0xd ! DW_CFA_def_cfa_register
.byte 0x1e ! uleb128 0x1e
.byte 0x2d ! DW_CFA_GNU_window_save
.byte 0x9 ! DW_CFA_register
.byte 0xf ! uleb128 0xf
.byte 0x1f ! uleb128 0x1f
.align WS
.LLEFDE2:
#endif
E SPARC_RET_UINT8
ldub [%i2+3], %i0
ret
restore
E SPARC_RET_SINT8
ldsb [%i2+3], %i0
ret
restore
E SPARC_RET_UINT16
lduh [%i2+2], %i0
ret
restore
E SPARC_RET_SINT16
ldsh [%i2+2], %i0
ret
restore
E SPARC_RET_UINT32
ld [%i2], %i0
ret
restore
E SP_V8_RET_CPLX16
ld [%i2], %i0
ret
restore
E SPARC_RET_INT64
ldd [%i2], %i0
ret
restore
E SPARC_RET_INT128
ldd [%i2], %i0
ldd [%i2+8], %i2
ret
restore
E SPARC_RET_F_8
ld [%i2+7*4], %f7
nop
ld [%i2+6*4], %f6
nop
E SPARC_RET_F_6
ld [%i2+5*4], %f5
nop
ld [%i2+4*4], %f4
nop
E SPARC_RET_F_4
ld [%i2+3*4], %f3
nop
ld [%i2+2*4], %f2
nop
E SPARC_RET_F_2
ldd [%i2], %f0
ret
restore
E SP_V8_RET_CPLX8
lduh [%i2], %i0
ret
restore
E SPARC_RET_F_1
ld [%i2], %f0
ret
restore
cfi_endproc
.size C(ffi_closure_v8), . - C(ffi_closure_v8)
#endif /* !SPARC64 */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits
#endif

View file

@ -1,6 +1,6 @@
/* -----------------------------------------------------------------------
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
SPARC 64-bit Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@ -27,103 +27,178 @@
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include "internal.h"
#ifdef SPARC64
#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
#define C2(X, Y) X ## Y
#define C1(X, Y) C2(X, Y)
#ifdef __USER_LABEL_PREFIX__
# define C(Y) C1(__USER_LABEL_PREFIX__, Y)
#else
# define C(Y) Y
#endif
#define L(Y) C1(.L, Y)
.macro E index
.align 16
.org 2b + \index * 16
.endm
#define STACK_BIAS 2047
#define ARGS (128) /* Offset of register area in frame */
.text
.text
.align 8
.globl ffi_call_v9
.globl _ffi_call_v9
.globl C(ffi_call_v9)
.type C(ffi_call_v9),@function
FFI_HIDDEN(C(ffi_call_v9))
ffi_call_v9:
_ffi_call_v9:
.LLFB1:
save %sp, -STACKFRAME, %sp
.LLCFI0:
C(ffi_call_v9):
cfi_startproc
save %sp, %o4, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
! frame to set up
mov %i0, %o0 ! copy cif
add %sp, STACK_BIAS+128+48, %o1 ! load args area
mov %i2, %o2 ! copy rvalue
call C(ffi_prep_args_v9)
mov %i3, %o3 ! copy avalue
mov %l0, %o0 ! call routine to set up frame
call %i0
mov %i1, %o1 ! (delay)
brz,pt %o0, 1f
ldx [%l0+ARGS], %o0 ! call foreign function
andcc %o0, SPARC_FLAG_FP_ARGS, %g0 ! need fp regs?
add %sp, 48, %sp ! deallocate prep frame
be,pt %xcc, 1f
mov %o0, %l0 ! save flags
ldd [%l0+ARGS], %f0
ldd [%l0+ARGS+8], %f2
ldd [%l0+ARGS+16], %f4
ldd [%l0+ARGS+24], %f6
ldd [%l0+ARGS+32], %f8
ldd [%l0+ARGS+40], %f10
ldd [%l0+ARGS+48], %f12
ldd [%l0+ARGS+56], %f14
ldd [%l0+ARGS+64], %f16
ldd [%l0+ARGS+72], %f18
ldd [%l0+ARGS+80], %f20
ldd [%l0+ARGS+88], %f22
ldd [%l0+ARGS+96], %f24
ldd [%l0+ARGS+104], %f26
ldd [%l0+ARGS+112], %f28
ldd [%l0+ARGS+120], %f30
ldd [%sp+STACK_BIAS+128], %f0 ! load all fp arg regs
ldd [%sp+STACK_BIAS+128+8], %f2
ldd [%sp+STACK_BIAS+128+16], %f4
ldd [%sp+STACK_BIAS+128+24], %f6
ldd [%sp+STACK_BIAS+128+32], %f8
ldd [%sp+STACK_BIAS+128+40], %f10
ldd [%sp+STACK_BIAS+128+48], %f12
ldd [%sp+STACK_BIAS+128+56], %f14
ldd [%sp+STACK_BIAS+128+64], %f16
ldd [%sp+STACK_BIAS+128+72], %f18
ldd [%sp+STACK_BIAS+128+80], %f20
ldd [%sp+STACK_BIAS+128+88], %f22
ldd [%sp+STACK_BIAS+128+96], %f24
ldd [%sp+STACK_BIAS+128+104], %f26
ldd [%sp+STACK_BIAS+128+112], %f28
ldd [%sp+STACK_BIAS+128+120], %f30
1: ldx [%l0+ARGS+8], %o1
ldx [%l0+ARGS+16], %o2
ldx [%l0+ARGS+24], %o3
ldx [%l0+ARGS+32], %o4
ldx [%l0+ARGS+40], %o5
call %i5
sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
1: ldx [%sp+STACK_BIAS+128], %o0 ! load all int arg regs
ldx [%sp+STACK_BIAS+128+8], %o1
ldx [%sp+STACK_BIAS+128+16], %o2
ldx [%sp+STACK_BIAS+128+24], %o3
ldx [%sp+STACK_BIAS+128+32], %o4
ldx [%sp+STACK_BIAS+128+40], %o5
call %i1
mov %i5, %g5 ! load static chain
! If the return value pointer is NULL, assume no return value.
brz,pn %i4, done
0: call 1f ! load pc in %o7
and %l0, SPARC_FLAG_RET_MASK, %l1
1: sll %l1, 4, %l1
add %o7, %l1, %o7 ! o7 = 0b + ret_type*16
jmp %o7+(2f-0b)
nop
cmp %i3, FFI_TYPE_INT
be,a,pt %icc, done
stx %o0, [%i4+0] ! (delay)
cmp %i3, FFI_TYPE_FLOAT
be,a,pn %icc, done
st %f0, [%i4+0] ! (delay)
cmp %i3, FFI_TYPE_DOUBLE
be,a,pn %icc, done
std %f0, [%i4+0] ! (delay)
cmp %i3, FFI_TYPE_STRUCT
be,pn %icc, dostruct
cmp %i3, FFI_TYPE_LONGDOUBLE
bne,pt %icc, done
.align 16
2:
E SPARC_RET_VOID
return %i7+8
nop
std %f0, [%i4+0]
std %f2, [%i4+8]
E SPARC_RET_STRUCT
add %sp, STACK_BIAS-64+128+48, %l2
sub %sp, 64, %sp
b 8f
stx %o0, [%l2]
E SPARC_RET_UINT8
and %o0, 0xff, %i0
return %i7+8
stx %o0, [%o2]
E SPARC_RET_SINT8
sll %o0, 24, %o0
sra %o0, 24, %i0
return %i7+8
stx %o0, [%o2]
E SPARC_RET_UINT16
sll %o0, 16, %o0
srl %o0, 16, %i0
return %i7+8
stx %o0, [%o2]
E SPARC_RET_SINT16
sll %o0, 16, %o0
sra %o0, 16, %i0
return %i7+8
stx %o0, [%o2]
E SPARC_RET_UINT32
srl %o0, 0, %i0
return %i7+8
stx %o0, [%o2]
E SP_V9_RET_SINT32
sra %o0, 0, %i0
return %i7+8
stx %o0, [%o2]
E SPARC_RET_INT64
stx %o0, [%i2]
return %i7+8
nop
E SPARC_RET_INT128
stx %o0, [%i2]
stx %o1, [%i2+8]
return %i7+8
nop
E SPARC_RET_F_8
st %f7, [%i2+7*4]
nop
st %f6, [%i2+6*4]
nop
E SPARC_RET_F_6
st %f5, [%i2+5*4]
nop
st %f4, [%i2+4*4]
nop
E SPARC_RET_F_4
std %f2, [%i2+2*4]
return %i7+8
std %f0, [%o2]
E SPARC_RET_F_2
return %i7+8
std %f0, [%o2]
E SP_V9_RET_F_3
st %f2, [%i2+2*4]
nop
st %f1, [%i2+1*4]
nop
E SPARC_RET_F_1
return %i7+8
st %f0, [%o2]
done: ret
restore
! Finish the SPARC_RET_STRUCT sequence.
.align 8
8: stx %o1, [%l2+8]
stx %o2, [%l2+16]
stx %o3, [%l2+24]
std %f0, [%l2+32]
std %f2, [%l2+40]
std %f4, [%l2+48]
std %f6, [%l2+56]
dostruct:
/* This will not work correctly for unions. */
stx %o0, [%i4+0]
stx %o1, [%i4+8]
stx %o2, [%i4+16]
stx %o3, [%i4+24]
std %f0, [%i4+32]
std %f2, [%i4+40]
std %f4, [%i4+48]
std %f6, [%i4+56]
ret
restore
.LLFE1:
! Copy the structure into place.
srl %l0, SPARC_SIZEMASK_SHIFT, %o0 ! load size_mask
mov %i2, %o1 ! load dst
mov %l2, %o2 ! load src_gp
call C(ffi_struct_float_copy)
add %l2, 32, %o3 ! load src_fp
.ffi_call_v9_end:
.size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
return %i7+8
nop
cfi_endproc
.size C(ffi_call_v9), . - C(ffi_call_v9)
#undef STACKFRAME
@ -136,15 +211,40 @@ dostruct:
Receives the closure argument in %g1. */
.text
.align 8
.globl ffi_closure_v9
.globl C(ffi_go_closure_v9)
.type C(ffi_go_closure_v9),@function
FFI_HIDDEN(C(ffi_go_closure_v9))
ffi_closure_v9:
.LLFB2:
C(ffi_go_closure_v9):
cfi_startproc
save %sp, -STACKFRAME, %sp
.LLCFI1:
cfi_def_cfa_register(%fp)
cfi_window_save
ldx [%g5+8], %o0
ldx [%g5+16], %o1
b 0f
mov %g5, %o2
cfi_endproc
.size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9)
.align 8
.globl C(ffi_closure_v9)
.type C(ffi_closure_v9),@function
FFI_HIDDEN(C(ffi_closure_v9))
C(ffi_closure_v9):
cfi_startproc
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0
ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1
ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2
0:
! Store all of the potential argument registers in va_list format.
stx %i0, [FP+128+0]
stx %i1, [FP+128+8]
@ -172,134 +272,106 @@ ffi_closure_v9:
std %f30, [FP-8]
! Call ffi_closure_sparc_inner to do the bulk of the work.
mov %g1, %o0
add %fp, STACK_BIAS-160, %o1
add %fp, STACK_BIAS+128, %o2
call ffi_closure_sparc_inner_v9
add %fp, STACK_BIAS-128, %o3
add %fp, STACK_BIAS-160, %o3
add %fp, STACK_BIAS+128, %o4
call C(ffi_closure_sparc_inner_v9)
add %fp, STACK_BIAS-128, %o5
! Load up the return value in the proper type.
! See ffi_prep_cif_machdep for the list of cases.
cmp %o0, FFI_TYPE_VOID
be,pn %icc, done1
0: call 1f ! load pc in %o7
and %o0, SPARC_FLAG_RET_MASK, %o0
1: sll %o0, 4, %o0 ! o2 = i2 * 16
add %o7, %o0, %o7 ! o7 = 0b + i2*16
jmp %o7+(2f-0b)
nop
cmp %o0, FFI_TYPE_INT
be,pn %icc, integer
cmp %o0, FFI_TYPE_FLOAT
be,a,pn %icc, done1
ld [FP-160], %f0
cmp %o0, FFI_TYPE_DOUBLE
be,a,pn %icc, done1
ldd [FP-160], %f0
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
cmp %o0, FFI_TYPE_LONGDOUBLE
be,a,pn %icc, longdouble1
ldd [FP-160], %f0
#endif
! FFI_TYPE_STRUCT
ldx [FP-152], %i1
ldx [FP-144], %i2
ldx [FP-136], %i3
ldd [FP-160], %f0
ldd [FP-152], %f2
ldd [FP-144], %f4
ldd [FP-136], %f6
integer:
! Note that we cannot load the data in the delay slot of
! the return insn because the data is in the stack frame
! that is deallocated by the return.
.align 16
2:
E SPARC_RET_VOID
return %i7+8
nop
E SPARC_RET_STRUCT
ldx [FP-160], %i0
ldd [FP-160], %f0
b 8f
ldx [FP-152], %i1
E SPARC_RET_UINT8
ldub [FP-160+7], %i0
return %i7+8
nop
E SPARC_RET_SINT8
ldsb [FP-160+7], %i0
return %i7+8
nop
E SPARC_RET_UINT16
lduh [FP-160+6], %i0
return %i7+8
nop
E SPARC_RET_SINT16
ldsh [FP-160+6], %i0
return %i7+8
nop
E SPARC_RET_UINT32
lduw [FP-160+4], %i0
return %i7+8
nop
E SP_V9_RET_SINT32
ldsw [FP-160+4], %i0
return %i7+8
nop
E SPARC_RET_INT64
ldx [FP-160], %i0
return %i7+8
nop
E SPARC_RET_INT128
ldx [FP-160], %i0
ldx [FP-160+8], %i1
return %i7+8
nop
E SPARC_RET_F_8
ld [FP-160+7*4], %f7
nop
ld [FP-160+6*4], %f6
nop
E SPARC_RET_F_6
ld [FP-160+5*4], %f5
nop
ld [FP-160+4*4], %f4
nop
E SPARC_RET_F_4
ldd [FP-160], %f0
ldd [FP-160+8], %f2
return %i7+8
nop
E SPARC_RET_F_2
ldd [FP-160], %f0
return %i7+8
nop
E SP_V9_RET_F_3
ld [FP-160+2*4], %f2
nop
ld [FP-160+1*4], %f1
nop
E SPARC_RET_F_1
ld [FP-160], %f0
return %i7+8
nop
done1:
ret
restore
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
longdouble1:
ldd [FP-152], %f2
ret
restore
#endif
.LLFE2:
.ffi_closure_v9_end:
.size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
#ifdef HAVE_RO_EH_FRAME
.section ".eh_frame",#alloc
#else
.section ".eh_frame",#alloc,#write
#endif
.LLframe1:
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
.LLSCIE1:
.uaword 0x0 ! CIE Identifier Tag
.byte 0x1 ! CIE Version
.ascii "zR\0" ! CIE Augmentation
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
.byte 0x78 ! sleb128 -8; CIE Data Alignment Factor
.byte 0xf ! CIE RA Column
.byte 0x1 ! uleb128 0x1; Augmentation size
#ifdef HAVE_AS_SPARC_UA_PCREL
.byte 0x1b ! FDE Encoding (pcrel sdata4)
#else
.byte 0x50 ! FDE Encoding (aligned absolute)
#endif
.byte 0xc ! DW_CFA_def_cfa
.byte 0xe ! uleb128 0xe
.byte 0xff,0xf ! uleb128 0x7ff
.align 8
.LLECIE1:
.LLSFDE1:
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
.LLASFDE1:
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
#ifdef HAVE_AS_SPARC_UA_PCREL
.uaword %r_disp32(.LLFB1)
.uaword .LLFE1-.LLFB1 ! FDE address range
#else
.align 8
.xword .LLFB1
.uaxword .LLFE1-.LLFB1 ! FDE address range
#endif
.byte 0x0 ! uleb128 0x0; Augmentation size
.byte 0x4 ! DW_CFA_advance_loc4
.uaword .LLCFI0-.LLFB1
.byte 0xd ! DW_CFA_def_cfa_register
.byte 0x1e ! uleb128 0x1e
.byte 0x2d ! DW_CFA_GNU_window_save
.byte 0x9 ! DW_CFA_register
.byte 0xf ! uleb128 0xf
.byte 0x1f ! uleb128 0x1f
.align 8
.LLEFDE1:
.LLSFDE2:
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
.LLASFDE2:
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
#ifdef HAVE_AS_SPARC_UA_PCREL
.uaword %r_disp32(.LLFB2)
.uaword .LLFE2-.LLFB2 ! FDE address range
#else
.align 8
.xword .LLFB2
.uaxword .LLFE2-.LLFB2 ! FDE address range
#endif
.byte 0x0 ! uleb128 0x0; Augmentation size
.byte 0x4 ! DW_CFA_advance_loc4
.uaword .LLCFI1-.LLFB2
.byte 0xd ! DW_CFA_def_cfa_register
.byte 0x1e ! uleb128 0x1e
.byte 0x2d ! DW_CFA_GNU_window_save
.byte 0x9 ! DW_CFA_register
.byte 0xf ! uleb128 0xf
.byte 0x1f ! uleb128 0x1f
.align 8
.LLEFDE2:
#endif
! Finish the SPARC_RET_STRUCT sequence.
.align 8
8: ldd [FP-152], %f2
ldx [FP-144], %i2
ldd [FP-144], %f4
ldx [FP-136], %i3
ldd [FP-136], %f6
return %i7+8
nop
cfi_endproc
.size C(ffi_closure_v9), . - C(ffi_closure_v9)
#endif /* SPARC64 */
#ifdef __linux__
.section .note.GNU-stack,"",@progbits
#endif

View file

@ -60,7 +60,7 @@
void (*fnaddr)(void));
On entry, REG_ARGS contain the outgoing register values,
and STACK_ARGS containts STACK_ARG_BYTES of additional values
and STACK_ARGS contains STACK_ARG_BYTES of additional values
to be passed on the stack. If STACK_ARG_BYTES is zero, then
STACK_ARGS is ignored.

Some files were not shown because too many files have changed in this diff Show more