merge upstream 3.4.4

This commit is contained in:
zhouganqing 2023-01-09 14:32:49 +08:00
parent 3489710a4d
commit f9ba9b10fe
236 changed files with 21879 additions and 9444 deletions

3285
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
libffi - Copyright (c) 1996-2019 Anthony Green, Red Hat, Inc and others.
libffi - Copyright (c) 1996-2022 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

@ -20,8 +20,9 @@ EXTRA_DIST = LICENSE ChangeLog.old \
m4/ltversion.m4 src/debug.c msvcc.sh \
generate-darwin-source-and-headers.py \
libffi.xcodeproj/project.pbxproj \
src/powerpc/t-aix \
libtool-ldflags libtool-version configure.host README.md \
libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl
libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl
# local.exp is generated by configure
DISTCLEANFILES = local.exp
@ -38,71 +39,63 @@ 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
src/raw_api.c src/java_raw_api.c src/closures.c \
src/tramp.c
if FFI_DEBUG
libffi_la_SOURCES += src/debug.c
endif
noinst_HEADERS = \
src/aarch64/ffitarget.h src/aarch64/internal.h \
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/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \
src/avr32/ffitarget.h src/bfin/ffitarget.h \
src/cris/ffitarget.h src/csky/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/riscv/ffitarget.h \
src/s390/ffitarget.h src/s390/internal.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/x86/asmnames.h \
src/xtensa/ffitarget.h \
src/dlmalloc.c
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/riscv/ffitarget.h \
src/s390/ffitarget.h src/s390/internal.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/x86/asmnames.h src/xtensa/ffitarget.h src/dlmalloc.c \
src/kvx/ffitarget.h src/kvx/asm.h \
src/loongarch64/ffitarget.h
EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \
src/aarch64/win64_armasm.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/arm/ffi.c src/arm/sysv_msvc_arm32.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/riscv/ffi.c src/riscv/sysv.S 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/sysv_intel.S src/x86/win64_intel.S \
src/xtensa/ffi.c src/xtensa/sysv.S
EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \
src/aarch64/win64_armasm.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/arm/ffi.c src/arm/sysv_msvc_arm32.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/csky/ffi.c src/csky/sysv.S 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/riscv/ffi.c src/riscv/sysv.S 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/sysv_intel.S src/x86/win64_intel.S \
src/xtensa/ffi.c src/xtensa/sysv.S src/kvx/ffi.c \
src/kvx/sysv.S src/loongarch64/ffi.c src/loongarch64/sysv.S
TARGET_OBJ = @TARGET_OBJ@
libffi_la_LIBADD = $(TARGET_OBJ)
@ -144,7 +137,8 @@ endif
libffi_version_info = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
libffi.map: $(top_srcdir)/libffi.map.in
$(COMPILE) -D$(TARGET) -E -x assembler-with-cpp -o $@ $<
$(COMPILE) -D$(TARGET) -DGENERATE_LIBFFI_MAP \
-E -x assembler-with-cpp -o $@ $(top_srcdir)/libffi.map.in
libffi_la_LDFLAGS = -no-undefined $(libffi_version_info) $(libffi_version_script) $(LTLDFLAGS) $(AM_LTLDFLAGS)
libffi_la_DEPENDENCIES = $(libffi_la_LIBADD) $(libffi_version_dep)
@ -157,3 +151,5 @@ dist-hook:
if [ -d $(top_srcdir)/.git ] ; then (cd $(top_srcdir); git log --no-decorate) ; else echo 'See git log for history.' ; fi > $(distdir)/ChangeLog
s=`awk '/was released on/{ print NR; exit}' $(top_srcdir)/README.md`; tail -n +$$(($$s-1)) $(top_srcdir)/README.md > $(distdir)/README.md
# target overrides
-include $(tmake_file)

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -99,7 +99,6 @@ target_triplet = @target@
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_append_flag.m4 \
$(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
@ -108,6 +107,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_prepend_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
@ -155,11 +155,12 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
am__libffi_la_SOURCES_DIST = src/prep_cif.c src/types.c src/raw_api.c \
src/java_raw_api.c src/closures.c src/debug.c
src/java_raw_api.c src/closures.c src/tramp.c src/debug.c
am__dirstamp = $(am__leading_dot)dirstamp
@FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo
am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
src/java_raw_api.lo src/closures.lo $(am__objects_1)
src/java_raw_api.lo src/closures.lo src/tramp.lo \
$(am__objects_1)
libffi_la_OBJECTS = $(am_libffi_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -170,9 +171,11 @@ libffi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
am__libffi_convenience_la_SOURCES_DIST = src/prep_cif.c src/types.c \
src/raw_api.c src/java_raw_api.c src/closures.c src/debug.c
src/raw_api.c src/java_raw_api.c src/closures.c src/tramp.c \
src/debug.c
am__objects_2 = src/prep_cif.lo src/types.lo src/raw_api.lo \
src/java_raw_api.lo src/closures.lo $(am__objects_1)
src/java_raw_api.lo src/closures.lo src/tramp.lo \
$(am__objects_1)
am_libffi_convenience_la_OBJECTS = $(am__objects_2)
nodist_libffi_convenience_la_OBJECTS =
libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
@ -195,8 +198,8 @@ am__maybe_remake_depfiles = depfiles
am__depfiles_remade = src/$(DEPDIR)/closures.Plo \
src/$(DEPDIR)/debug.Plo src/$(DEPDIR)/java_raw_api.Plo \
src/$(DEPDIR)/prep_cif.Plo src/$(DEPDIR)/raw_api.Plo \
src/$(DEPDIR)/types.Plo src/aarch64/$(DEPDIR)/ffi.Plo \
src/aarch64/$(DEPDIR)/sysv.Plo \
src/$(DEPDIR)/tramp.Plo src/$(DEPDIR)/types.Plo \
src/aarch64/$(DEPDIR)/ffi.Plo src/aarch64/$(DEPDIR)/sysv.Plo \
src/aarch64/$(DEPDIR)/win64_armasm.Plo \
src/alpha/$(DEPDIR)/ffi.Plo src/alpha/$(DEPDIR)/osf.Plo \
src/arc/$(DEPDIR)/arcompact.Plo src/arc/$(DEPDIR)/ffi.Plo \
@ -205,13 +208,16 @@ am__depfiles_remade = src/$(DEPDIR)/closures.Plo \
src/avr32/$(DEPDIR)/ffi.Plo src/avr32/$(DEPDIR)/sysv.Plo \
src/bfin/$(DEPDIR)/ffi.Plo src/bfin/$(DEPDIR)/sysv.Plo \
src/cris/$(DEPDIR)/ffi.Plo src/cris/$(DEPDIR)/sysv.Plo \
src/csky/$(DEPDIR)/ffi.Plo src/csky/$(DEPDIR)/sysv.Plo \
src/frv/$(DEPDIR)/eabi.Plo src/frv/$(DEPDIR)/ffi.Plo \
src/ia64/$(DEPDIR)/ffi.Plo src/ia64/$(DEPDIR)/unix.Plo \
src/m32r/$(DEPDIR)/ffi.Plo src/m32r/$(DEPDIR)/sysv.Plo \
src/m68k/$(DEPDIR)/ffi.Plo src/m68k/$(DEPDIR)/sysv.Plo \
src/m88k/$(DEPDIR)/ffi.Plo src/m88k/$(DEPDIR)/obsd.Plo \
src/metag/$(DEPDIR)/ffi.Plo src/metag/$(DEPDIR)/sysv.Plo \
src/microblaze/$(DEPDIR)/ffi.Plo \
src/kvx/$(DEPDIR)/ffi.Plo src/kvx/$(DEPDIR)/sysv.Plo \
src/loongarch64/$(DEPDIR)/ffi.Plo \
src/loongarch64/$(DEPDIR)/sysv.Plo src/m32r/$(DEPDIR)/ffi.Plo \
src/m32r/$(DEPDIR)/sysv.Plo src/m68k/$(DEPDIR)/ffi.Plo \
src/m68k/$(DEPDIR)/sysv.Plo src/m88k/$(DEPDIR)/ffi.Plo \
src/m88k/$(DEPDIR)/obsd.Plo src/metag/$(DEPDIR)/ffi.Plo \
src/metag/$(DEPDIR)/sysv.Plo src/microblaze/$(DEPDIR)/ffi.Plo \
src/microblaze/$(DEPDIR)/sysv.Plo src/mips/$(DEPDIR)/ffi.Plo \
src/mips/$(DEPDIR)/n32.Plo src/mips/$(DEPDIR)/o32.Plo \
src/moxie/$(DEPDIR)/eabi.Plo src/moxie/$(DEPDIR)/ffi.Plo \
@ -303,8 +309,8 @@ am__recursive_targets = \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
cscope distdir distdir-am dist dist-all distcheck
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
$(LISP)fficonfig.h.in
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
fficonfig.h.in
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
@ -321,13 +327,10 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = include testsuite man doc
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/fficonfig.h.in \
$(srcdir)/libffi.pc.in compile config.guess config.sub depcomp \
install-sh ltmain.sh missing
$(srcdir)/libffi.pc.in README.md compile config.guess \
config.sub depcomp install-sh ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@ -366,6 +369,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -387,8 +392,9 @@ CCASDEPMODE = @CCASDEPMODE@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
@ -403,9 +409,11 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
FGREP = @FGREP@
FILECMD = @FILECMD@
GREP = @GREP@
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
@ -444,6 +452,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
READELF = @READELF@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
SED = @SED@
SET_MAKE = @SET_MAKE@
@ -499,6 +508,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -509,6 +519,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
tmake_file = @tmake_file@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
top_build_prefix = @top_build_prefix@
@ -523,8 +534,9 @@ EXTRA_DIST = LICENSE ChangeLog.old \
m4/ltversion.m4 src/debug.c msvcc.sh \
generate-darwin-source-and-headers.py \
libffi.xcodeproj/project.pbxproj \
src/powerpc/t-aix \
libtool-ldflags libtool-version configure.host README.md \
libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl
libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl
# local.exp is generated by configure
@ -538,66 +550,57 @@ 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 $(am__append_2)
noinst_HEADERS = \
src/aarch64/ffitarget.h src/aarch64/internal.h \
src/java_raw_api.c src/closures.c src/tramp.c $(am__append_2)
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/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \
src/avr32/ffitarget.h src/bfin/ffitarget.h \
src/cris/ffitarget.h src/csky/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/riscv/ffitarget.h \
src/s390/ffitarget.h src/s390/internal.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/x86/asmnames.h \
src/xtensa/ffitarget.h \
src/dlmalloc.c
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/riscv/ffitarget.h \
src/s390/ffitarget.h src/s390/internal.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/x86/asmnames.h src/xtensa/ffitarget.h src/dlmalloc.c \
src/kvx/ffitarget.h src/kvx/asm.h \
src/loongarch64/ffitarget.h
EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \
src/aarch64/win64_armasm.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/arm/ffi.c src/arm/sysv_msvc_arm32.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/riscv/ffi.c src/riscv/sysv.S 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/sysv_intel.S src/x86/win64_intel.S \
src/xtensa/ffi.c src/xtensa/sysv.S
EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \
src/aarch64/win64_armasm.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/arm/ffi.c src/arm/sysv_msvc_arm32.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/csky/ffi.c src/csky/sysv.S 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/riscv/ffi.c src/riscv/sysv.S 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/sysv_intel.S src/x86/win64_intel.S \
src/xtensa/ffi.c src/xtensa/sysv.S src/kvx/ffi.c \
src/kvx/sysv.S src/loongarch64/ffi.c src/loongarch64/sysv.S
libffi_la_LIBADD = $(TARGET_OBJ)
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
@ -730,6 +733,7 @@ src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/tramp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/aarch64/$(am__dirstamp):
@$(MKDIR_P) src/aarch64
@ -813,6 +817,16 @@ src/frv/$(DEPDIR)/$(am__dirstamp):
@: > src/frv/$(DEPDIR)/$(am__dirstamp)
src/frv/ffi.lo: src/frv/$(am__dirstamp) \
src/frv/$(DEPDIR)/$(am__dirstamp)
src/csky/$(am__dirstamp):
@$(MKDIR_P) src/csky
@: > src/csky/$(am__dirstamp)
src/csky/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) src/csky/$(DEPDIR)
@: > src/csky/$(DEPDIR)/$(am__dirstamp)
src/csky/ffi.lo: src/csky/$(am__dirstamp) \
src/csky/$(DEPDIR)/$(am__dirstamp)
src/csky/sysv.lo: src/csky/$(am__dirstamp) \
src/csky/$(DEPDIR)/$(am__dirstamp)
src/frv/eabi.lo: src/frv/$(am__dirstamp) \
src/frv/$(DEPDIR)/$(am__dirstamp)
src/ia64/$(am__dirstamp):
@ -1063,6 +1077,26 @@ src/xtensa/ffi.lo: src/xtensa/$(am__dirstamp) \
src/xtensa/$(DEPDIR)/$(am__dirstamp)
src/xtensa/sysv.lo: src/xtensa/$(am__dirstamp) \
src/xtensa/$(DEPDIR)/$(am__dirstamp)
src/kvx/$(am__dirstamp):
@$(MKDIR_P) src/kvx
@: > src/kvx/$(am__dirstamp)
src/kvx/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) src/kvx/$(DEPDIR)
@: > src/kvx/$(DEPDIR)/$(am__dirstamp)
src/kvx/ffi.lo: src/kvx/$(am__dirstamp) \
src/kvx/$(DEPDIR)/$(am__dirstamp)
src/kvx/sysv.lo: src/kvx/$(am__dirstamp) \
src/kvx/$(DEPDIR)/$(am__dirstamp)
src/loongarch64/$(am__dirstamp):
@$(MKDIR_P) src/loongarch64
@: > src/loongarch64/$(am__dirstamp)
src/loongarch64/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) src/loongarch64/$(DEPDIR)
@: > src/loongarch64/$(DEPDIR)/$(am__dirstamp)
src/loongarch64/ffi.lo: src/loongarch64/$(am__dirstamp) \
src/loongarch64/$(DEPDIR)/$(am__dirstamp)
src/loongarch64/sysv.lo: src/loongarch64/$(am__dirstamp) \
src/loongarch64/$(DEPDIR)/$(am__dirstamp)
libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) $(EXTRA_libffi_la_DEPENDENCIES)
$(AM_V_CCLD)$(libffi_la_LINK) -rpath $(toolexeclibdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
@ -1088,10 +1122,16 @@ mostlyclean-compile:
-rm -f src/bfin/*.lo
-rm -f src/cris/*.$(OBJEXT)
-rm -f src/cris/*.lo
-rm -f src/csky/*.$(OBJEXT)
-rm -f src/csky/*.lo
-rm -f src/frv/*.$(OBJEXT)
-rm -f src/frv/*.lo
-rm -f src/ia64/*.$(OBJEXT)
-rm -f src/ia64/*.lo
-rm -f src/kvx/*.$(OBJEXT)
-rm -f src/kvx/*.lo
-rm -f src/loongarch64/*.$(OBJEXT)
-rm -f src/loongarch64/*.lo
-rm -f src/m32r/*.$(OBJEXT)
-rm -f src/m32r/*.lo
-rm -f src/m68k/*.$(OBJEXT)
@ -1141,6 +1181,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/raw_api.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tramp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/types.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@ -1158,10 +1199,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/csky/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/csky/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/eabi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/unix.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/kvx/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/kvx/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/loongarch64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/loongarch64/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
@ -1290,8 +1337,11 @@ clean-libtool:
-rm -rf src/avr32/.libs src/avr32/_libs
-rm -rf src/bfin/.libs src/bfin/_libs
-rm -rf src/cris/.libs src/cris/_libs
-rm -rf src/csky/.libs src/csky/_libs
-rm -rf src/frv/.libs src/frv/_libs
-rm -rf src/ia64/.libs src/ia64/_libs
-rm -rf src/kvx/.libs src/kvx/_libs
-rm -rf src/loongarch64/.libs src/loongarch64/_libs
-rm -rf src/m32r/.libs src/m32r/_libs
-rm -rf src/m68k/.libs src/m68k/_libs
-rm -rf src/m88k/.libs src/m88k/_libs
@ -1442,7 +1492,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@ -1529,6 +1578,10 @@ dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-zstd: distdir
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@ -1571,6 +1624,8 @@ distcheck: dist
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
*.tar.zst*) \
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
@ -1586,7 +1641,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
@ -1687,10 +1742,16 @@ distclean-generic:
-rm -f src/bfin/$(am__dirstamp)
-rm -f src/cris/$(DEPDIR)/$(am__dirstamp)
-rm -f src/cris/$(am__dirstamp)
-rm -f src/csky/$(DEPDIR)/$(am__dirstamp)
-rm -f src/csky/$(am__dirstamp)
-rm -f src/frv/$(DEPDIR)/$(am__dirstamp)
-rm -f src/frv/$(am__dirstamp)
-rm -f src/ia64/$(DEPDIR)/$(am__dirstamp)
-rm -f src/ia64/$(am__dirstamp)
-rm -f src/kvx/$(DEPDIR)/$(am__dirstamp)
-rm -f src/kvx/$(am__dirstamp)
-rm -f src/loongarch64/$(DEPDIR)/$(am__dirstamp)
-rm -f src/loongarch64/$(am__dirstamp)
-rm -f src/m32r/$(DEPDIR)/$(am__dirstamp)
-rm -f src/m32r/$(am__dirstamp)
-rm -f src/m68k/$(DEPDIR)/$(am__dirstamp)
@ -1748,6 +1809,7 @@ distclean: distclean-recursive
-rm -f src/$(DEPDIR)/java_raw_api.Plo
-rm -f src/$(DEPDIR)/prep_cif.Plo
-rm -f src/$(DEPDIR)/raw_api.Plo
-rm -f src/$(DEPDIR)/tramp.Plo
-rm -f src/$(DEPDIR)/types.Plo
-rm -f src/aarch64/$(DEPDIR)/ffi.Plo
-rm -f src/aarch64/$(DEPDIR)/sysv.Plo
@ -1765,10 +1827,16 @@ distclean: distclean-recursive
-rm -f src/bfin/$(DEPDIR)/sysv.Plo
-rm -f src/cris/$(DEPDIR)/ffi.Plo
-rm -f src/cris/$(DEPDIR)/sysv.Plo
-rm -f src/csky/$(DEPDIR)/ffi.Plo
-rm -f src/csky/$(DEPDIR)/sysv.Plo
-rm -f src/frv/$(DEPDIR)/eabi.Plo
-rm -f src/frv/$(DEPDIR)/ffi.Plo
-rm -f src/ia64/$(DEPDIR)/ffi.Plo
-rm -f src/ia64/$(DEPDIR)/unix.Plo
-rm -f src/kvx/$(DEPDIR)/ffi.Plo
-rm -f src/kvx/$(DEPDIR)/sysv.Plo
-rm -f src/loongarch64/$(DEPDIR)/ffi.Plo
-rm -f src/loongarch64/$(DEPDIR)/sysv.Plo
-rm -f src/m32r/$(DEPDIR)/ffi.Plo
-rm -f src/m32r/$(DEPDIR)/sysv.Plo
-rm -f src/m68k/$(DEPDIR)/ffi.Plo
@ -1881,6 +1949,7 @@ maintainer-clean: maintainer-clean-recursive
-rm -f src/$(DEPDIR)/java_raw_api.Plo
-rm -f src/$(DEPDIR)/prep_cif.Plo
-rm -f src/$(DEPDIR)/raw_api.Plo
-rm -f src/$(DEPDIR)/tramp.Plo
-rm -f src/$(DEPDIR)/types.Plo
-rm -f src/aarch64/$(DEPDIR)/ffi.Plo
-rm -f src/aarch64/$(DEPDIR)/sysv.Plo
@ -1898,10 +1967,16 @@ maintainer-clean: maintainer-clean-recursive
-rm -f src/bfin/$(DEPDIR)/sysv.Plo
-rm -f src/cris/$(DEPDIR)/ffi.Plo
-rm -f src/cris/$(DEPDIR)/sysv.Plo
-rm -f src/csky/$(DEPDIR)/ffi.Plo
-rm -f src/csky/$(DEPDIR)/sysv.Plo
-rm -f src/frv/$(DEPDIR)/eabi.Plo
-rm -f src/frv/$(DEPDIR)/ffi.Plo
-rm -f src/ia64/$(DEPDIR)/ffi.Plo
-rm -f src/ia64/$(DEPDIR)/unix.Plo
-rm -f src/kvx/$(DEPDIR)/ffi.Plo
-rm -f src/kvx/$(DEPDIR)/sysv.Plo
-rm -f src/loongarch64/$(DEPDIR)/ffi.Plo
-rm -f src/loongarch64/$(DEPDIR)/sysv.Plo
-rm -f src/m32r/$(DEPDIR)/ffi.Plo
-rm -f src/m32r/$(DEPDIR)/sysv.Plo
-rm -f src/m68k/$(DEPDIR)/ffi.Plo
@ -1987,20 +2062,21 @@ uninstall-am: uninstall-pkgconfigDATA uninstall-toolexeclibLTLIBRARIES
clean-generic clean-libtool clean-noinstLTLIBRARIES \
clean-toolexeclibLTLIBRARIES cscope cscopelist-am ctags \
ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \
dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \
distclean distclean-compile distclean-generic distclean-hdr \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-pkgconfigDATA install-ps \
install-ps-am install-strip install-toolexeclibLTLIBRARIES \
installcheck installcheck-am installdirs installdirs-am \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
uninstall-pkgconfigDATA uninstall-toolexeclibLTLIBRARIES
dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \
distcheck distclean distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am html html-am info \
info-am install install-am install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-pdf install-pdf-am install-pkgconfigDATA \
install-ps install-ps-am install-strip \
install-toolexeclibLTLIBRARIES installcheck installcheck-am \
installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-pkgconfigDATA \
uninstall-toolexeclibLTLIBRARIES
.PRECIOUS: Makefile
@ -2012,13 +2088,17 @@ uninstall-am: uninstall-pkgconfigDATA uninstall-toolexeclibLTLIBRARIES
@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@ > $@ || (rm -f $@ ; exit 1)
libffi.map: $(top_srcdir)/libffi.map.in
$(COMPILE) -D$(TARGET) -E -x assembler-with-cpp -o $@ $<
$(COMPILE) -D$(TARGET) -DGENERATE_LIBFFI_MAP \
-E -x assembler-with-cpp -o $@ $(top_srcdir)/libffi.map.in
dist-hook:
d=`(cd $(distdir); pwd)`; (cd doc; make pdf; cp *.pdf $$d/doc)
if [ -d $(top_srcdir)/.git ] ; then (cd $(top_srcdir); git log --no-decorate) ; else echo 'See git log for history.' ; fi > $(distdir)/ChangeLog
s=`awk '/was released on/{ print NR; exit}' $(top_srcdir)/README.md`; tail -n +$$(($$s-1)) $(top_srcdir)/README.md > $(distdir)/README.md
# target overrides
-include $(tmake_file)
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

230
README.md
View File

@ -1,5 +1,5 @@
libffi-3.3 was released on November 23, 2019. Check the libffi web
libffi-3.4.4 was released on October 23, 2022. Check the libffi web
page for updates: <URL:http://sourceware.org/libffi/>.
@ -23,7 +23,7 @@ bridge from the interpreter program to compiled code.
The libffi library provides a portable, high level programming
interface to various calling conventions. This allows a programmer to
call any function specified by a call interface description at run
time.
time.
FFI stands for Foreign Function Interface. A foreign function
interface is the popular name for the interface that allows code
@ -55,8 +55,11 @@ tested:
| ARM | Windows | MSVC |
| AVR32 | Linux | GCC |
| Blackfin | uClinux | GCC |
| CSKY | Linux | GCC |
| HPPA | HPUX | GCC |
| KVX | Linux | GCC |
| IA-64 | Linux | GCC |
| LoongArch64 | Linux | GCC |
| M68K | FreeMiNT | GCC |
| M68K | Linux | GCC |
| M68K | RTEMS | GCC |
@ -70,6 +73,7 @@ tested:
| Moxie | Bare metal | GCC |
| Nios II | Linux | GCC |
| OpenRISC | Linux | GCC |
| PowerPC 32-bit | AIX | GCC |
| PowerPC 32-bit | AIX | IBM XL C |
| PowerPC 64-bit | AIX | IBM XL C |
| PowerPC | AMIGA | GCC |
@ -96,7 +100,6 @@ tested:
| X86 | Interix | GCC |
| X86 | kFreeBSD | GCC |
| X86 | Linux | GCC |
| X86 | Mac OSX | GCC |
| X86 | OpenBSD | GCC |
| X86 | OS/2 | GCC |
| X86 | Solaris | GCC |
@ -131,15 +134,15 @@ install autoconf, automake and libtool.
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.
will install under /usr/local by default.
If you want to enable extra run-time debugging checks use the the
``--enable-debug`` configure switch. This is useful when your program dies
mysteriously while using libffi.
mysteriously while using libffi.
Another useful configure switch is ``--enable-purify-safety``. Using this
will add some extra code which will suppress certain warnings when you
are using Purify with libffi. Only use this switch when using
are using Purify with libffi. Only use this switch when using
Purify, as it will slow down the library.
If you don't want to build documentation, use the ``--disable-docs``
@ -158,7 +161,7 @@ For 64-bit Windows builds, use ``CC="path/to/msvcc.sh -m64"`` and
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"
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'
@ -192,7 +195,35 @@ History
See the git log for details at http://github.com/libffi/libffi.
3.3 Nov-23-19
3.4.4 Oct-23-2022
Important aarch64 fixes, including support for linux builds
with Link Time Optimization (-flto).
Fix x86 stdcall stack alignment.
Fix x86 Windows msvc assembler compatibility.
Fix moxie and or1k small structure args.
3.4.3 Sep-19-2022
All struct args are passed by value, regardless of size, as per ABIs.
Enable static trampolines for Cygwin.
Add support for Loongson's LoongArch64 architecture.
Fix x32 static trampolines.
Fix 32-bit x86 stdcall stack corruption.
Fix ILP32 aarch64 support.
3.4.2 Jun-28-2021
Add static trampoline support for Linux on x86_64 and ARM64.
Add support for Alibaba's CSKY architecture.
Add support for Kalray's KVX architecture.
Add support for Intel Control-flow Enforcement Technology (CET).
Add support for ARM Pointer Authentication (PA).
Fix 32-bit PPC regression.
Fix MIPS soft-float problem.
Enable tmpdir override with the $LIBFFI_TMPDIR environment variable.
Enable compatibility with MSVC runtime stack checking.
Reject float and small integer argument in ffi_prep_cif_var().
Callers must promote these types themselves.
3.3 Nov-23-2019
Add RISC-V support.
New API in support of GO closures.
Add IEEE754 binary128 long double support for 64-bit Power
@ -201,21 +232,21 @@ See the git log for details at http://github.com/libffi/libffi.
Add Windows on ARM64 (WOA) support.
Add Windows 32-bit ARM support.
Raw java (gcj) API deprecated.
Add pre-built PDF documentation to source distribution.
Many new tests cases and bug fixes.
3.2.1 Nov-12-14
Add pre-built PDF documentation to source distribution.
Many new test cases and bug fixes.
3.2.1 Nov-12-2014
Build fix for non-iOS AArch64 targets.
3.2 Nov-11-14
3.2 Nov-11-2014
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
3.1 May-19-2014
Add AArch64 (ARM64) iOS support.
Add Nios II support.
Add m88k and DEC VAX support.
@ -227,8 +258,8 @@ See the git log for details at http://github.com/libffi/libffi.
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
3.0.13 Mar-17-2013
Add Meta support.
Add missing Moxie bits.
Fix stack alignment bug on 32-bit x86.
@ -237,8 +268,8 @@ See the git log for details at http://github.com/libffi/libffi.
Fix the install dir location for some platforms when building
with GCC (OS X, Solaris).
Fix Cygwin regression.
3.0.12 Feb-11-13
3.0.12 Feb-11-2013
Add Moxie support.
Add AArch64 support.
Add Blackfin support.
@ -249,8 +280,8 @@ See the git log for details at http://github.com/libffi/libffi.
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
3.0.11 Apr-11-2012
Lots of build fixes.
Add support for variadic functions (ffi_prep_cif_var).
Add Linux/x32 support.
@ -260,8 +291,8 @@ See the git log for details at http://github.com/libffi/libffi.
Integration with iOS' xcode build tools.
Fix Octeon and MC68881 support.
Fix code pessimizations.
3.0.10 Aug-23-11
3.0.10 Aug-23-2011
Add support for Apple's iOS.
Add support for ARM VFP ABI.
Add RTEMS support for MIPS and M68K.
@ -274,129 +305,129 @@ See the git log for details at http://github.com/libffi/libffi.
Solaris compiler.
Testsuite fixes for Tru64 Unix.
Additional platform support.
3.0.9 Dec-31-09
3.0.9 Dec-31-2009
Add AVR32 and win64 ports. Add ARM softfp support.
Many fixes for AIX, Solaris, HP-UX, *BSD.
Several PowerPC and x86-64 bug fixes.
Build DLL for windows.
3.0.8 Dec-19-08
3.0.8 Dec-19-2008
Add *BSD, BeOS, and PA-Linux support.
3.0.7 Nov-11-08
3.0.7 Nov-11-2008
Fix for ppc FreeBSD.
(thanks to Andreas Tobler)
3.0.6 Jul-17-08
3.0.6 Jul-17-2008
Fix for closures on sh.
Mark the sh/sh64 stack as non-executable.
(both thanks to Kaz Kojima)
3.0.5 Apr-3-08
3.0.5 Apr-3-2008
Fix libffi.pc file.
Fix #define ARM for IcedTea users.
Fix x86 closure bug.
3.0.4 Feb-24-08
3.0.4 Feb-24-2008
Fix x86 OpenBSD configury.
3.0.3 Feb-22-08
3.0.3 Feb-22-2008
Enable x86 OpenBSD thanks to Thomas Heller, and
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
Clean up test instruction in README.
3.0.2 Feb-21-08
3.0.2 Feb-21-2008
Improved x86 FreeBSD support.
Thanks to Björn König.
3.0.1 Feb-15-08
3.0.1 Feb-15-2008
Fix instruction cache flushing bug on MIPS.
Thanks to David Daney.
3.0.0 Feb-15-08
3.0.0 Feb-15-2008
Many changes, mostly thanks to the GCC project.
Cygnus Solutions is now Red Hat.
[10 years go by...]
1.20 Oct-5-98
1.20 Oct-5-1998
Raffaele Sena produces ARM port.
1.19 Oct-5-98
1.19 Oct-5-1998
Fixed x86 long double and long long return support.
m68k bug fixes from Andreas Schwab.
Patch for DU assembler compatibility for the Alpha from Richard
Henderson.
1.18 Apr-17-98
1.18 Apr-17-1998
Bug fixes and MIPS configuration changes.
1.17 Feb-24-98
1.17 Feb-24-1998
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
1.16 Feb-11-98
1.16 Feb-11-1998
Richard Henderson produces Alpha port.
1.15 Dec-4-97
1.15 Dec-4-1997
Fixed an n32 ABI bug. New libtool, auto* support.
1.14 May-13-97
libtool is now used to generate shared and static libraries.
Fixed a minor portability problem reported by Russ McManus
<mcmanr@eq.gs.com>.
1.13 Dec-2-96
1.13 Dec-2-1996
Added --enable-purify-safety to keep Purify from complaining
about certain low level code.
Sparc fix for calling functions with < 6 args.
Linux x86 a.out fix.
1.12 Nov-22-96
Added missing ffi_type_void, needed for supporting void return
types. Fixed test case for non MIPS machines. Cygnus Support
is now Cygnus Solutions.
1.11 Oct-30-96
1.12 Nov-22-1996
Added missing ffi_type_void, needed for supporting void return
types. Fixed test case for non MIPS machines. Cygnus Support
is now Cygnus Solutions.
1.11 Oct-30-1996
Added notes about GNU make.
1.10 Oct-29-96
1.10 Oct-29-1996
Added configuration fix for non GNU compilers.
1.09 Oct-29-96
Added --enable-debug configure switch. Clean-ups based on LCLint
feedback. ffi_mips.h is always installed. Many configuration
1.09 Oct-29-1996
Added --enable-debug configure switch. Clean-ups based on LCLint
feedback. ffi_mips.h is always installed. Many configuration
fixes. Fixed ffitest.c for sparc builds.
1.08 Oct-15-96
1.08 Oct-15-1996
Fixed n32 problem. Many clean-ups.
1.07 Oct-14-96
1.07 Oct-14-1996
Gordon Irlam rewrites v8.S again. Bug fixes.
1.06 Oct-14-96
Gordon Irlam improved the sparc port.
1.05 Oct-14-96
1.06 Oct-14-1996
Gordon Irlam improved the sparc port.
1.05 Oct-14-1996
Interface changes based on feedback.
1.04 Oct-11-96
1.04 Oct-11-1996
Sparc port complete (modulo struct passing bug).
1.03 Oct-10-96
1.03 Oct-10-1996
Passing struct args, and returning struct values works for
all architectures/calling conventions. Expanded tests.
1.02 Oct-9-96
1.02 Oct-9-1996
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
Added "make test".
1.01 Oct-8-96
1.01 Oct-8-1996
Fixed float passing bug in mips version. Restructured some
of the code. Builds cleanly with SGI tools.
1.00 Oct-7-96
1.00 Oct-7-1996
First release. No public announcement.
Authors & Credits
@ -424,8 +455,12 @@ developers:
avr32 Bradley Smith
blackfin Alexandre Keunecke I. de Mendonca
cris Simon Posnjak, Hans-Peter Nilsson
csky Ma Jun, Zhang Wenmeng
frv Anthony Green
ia64 Hans Boehm
kvx Yann Sionneau
loongarch64 Cheng Lulu, Xi Ruoyao, Xu Hao,
Zhang Wenlong, Pan Xuefeng
m32r Kazuhiro Inaoka
m68k Andreas Schwab
m88k Miod Vallat
@ -467,6 +502,11 @@ Alex Oliva solved the executable page problem for SElinux.
The list above is almost certainly incomplete and inaccurate. I'm
happy to make corrections or additions upon request.
If you have a problem, or have found a bug, please send a note to the
author at green@moxielogic.com, or the project mailing list at
libffi-discuss@sourceware.org.
If you have a problem, or have found a bug, please file an issue on
our issue tracker at https://github.com/libffi/libffi/issues.
The author can be reached at green@moxielogic.com.
To subscribe/unsubscribe to our mailing lists, visit:
https://sourceware.org/mailman/listinfo/libffi-announce
https://sourceware.org/mailman/listinfo/libffi-discuss

View File

@ -45,16 +45,16 @@ else
# Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon,
[AC_TRY_COMPILE(
[#include <sys/types.h>
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
],
[int n = MAP_ANONYMOUS;],
]],
[[int n = MAP_ANONYMOUS;]])],
ac_cv_decl_map_anon=yes,
ac_cv_decl_map_anon=no)])
@ -104,7 +104,7 @@ dnl See docs/html/17_intro/configury.html#enable for documentation.
dnl
m4_define([LIBFFI_ENABLE],[dnl
m4_define([_g_switch],[--enable-$1])dnl
m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl
m4_define([_g_help],[AS_HELP_STRING([_g_switch$3],[$4 @<:@default=$2@:>@])])dnl
AC_ARG_ENABLE($1,_g_help,
m4_bmatch([$5],
[^permit ],
@ -152,109 +152,7 @@ AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [
# by now (in libtool), but require it now just to be safe...
test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS=''
test -z "$OPT_LDFLAGS" && OPT_LDFLAGS=''
AC_REQUIRE([AC_PROG_LD])
AC_REQUIRE([AC_PROG_AWK])
# The name set by libtool depends on the version of libtool. Shame on us
# for depending on an impl detail, but c'est la vie. Older versions used
# ac_cv_prog_gnu_ld, but now it's lt_cv_prog_gnu_ld, and is copied back on
# top of with_gnu_ld (which is also set by --with-gnu-ld, so that actually
# makes sense). We'll test with_gnu_ld everywhere else, so if that isn't
# set (hence we're using an older libtool), then set it.
if test x${with_gnu_ld+set} != xset; then
if test x${ac_cv_prog_gnu_ld+set} != xset; then
# We got through "ac_require(ac_prog_ld)" and still not set? Huh?
with_gnu_ld=no
else
with_gnu_ld=$ac_cv_prog_gnu_ld
fi
fi
# Start by getting the version number. I think the libtool test already
# does some of this, but throws away the result.
libat_ld_is_gold=no
if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then
libat_ld_is_gold=yes
fi
changequote(,)
ldver=`$LD --version 2>/dev/null |
sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'`
changequote([,])
libat_gnu_ld_version=`echo $ldver | \
$AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'`
# Set --gc-sections.
if test "$with_gnu_ld" = "notbroken"; then
# GNU ld it is! Joy and bunny rabbits!
# All these tests are for C++; save the language and the compiler flags.
# Need to do this so that g++ won't try to link in libstdc++
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS='-x c++ -Wl,--gc-sections'
# Check for -Wl,--gc-sections
# XXX This test is broken at the moment, as symbols required for linking
# are now in libsupc++ (not built yet). In addition, this test has
# cored on solaris in the past. In addition, --gc-sections doesn't
# really work at the moment (keeps on discarding used sections, first
# .eh_frame and now some of the glibc sections for iconv).
# Bzzzzt. Thanks for playing, maybe next time.
AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections])
AC_TRY_RUN([
int main(void)
{
try { throw 1; }
catch (...) { };
return 0;
}
], [ac_sectionLDflags=yes],[ac_sectionLDflags=no], [ac_sectionLDflags=yes])
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
else
# this is the suspicious part
CFLAGS=''
fi
if test "$ac_sectionLDflags" = "yes"; then
SECTION_LDFLAGS="-Wl,--gc-sections $SECTION_LDFLAGS"
fi
AC_MSG_RESULT($ac_sectionLDflags)
fi
# Set linker optimization flags.
if test x"$with_gnu_ld" = x"yes"; then
OPT_LDFLAGS="-Wl,-O1 $OPT_LDFLAGS"
fi
AC_SUBST(SECTION_LDFLAGS)
AC_SUBST(OPT_LDFLAGS)
])
dnl
dnl If GNU ld is in use, check to see if tricky linker opts can be used. If
dnl the native linker is in use, all variables will be defined to something
dnl safe (like an empty string).
dnl
dnl Defines:
dnl SECTION_LDFLAGS='-Wl,--gc-sections' if possible
dnl OPT_LDFLAGS='-Wl,-O1' if possible
dnl LD (as a side effect of testing)
dnl Sets:
dnl with_gnu_ld
dnl libat_ld_is_gold (possibly)
dnl libat_gnu_ld_version (possibly)
dnl
dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will
dnl set libat_gnu_ld_version to 12345. Zeros cause problems.
dnl
AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [
# If we're not using GNU ld, then there's no point in even trying these
# tests. Check for that first. We should have already tested for gld
# by now (in libtool), but require it now just to be safe...
test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS=''
test -z "$OPT_LDFLAGS" && OPT_LDFLAGS=''
AC_REQUIRE([AC_PROG_LD])
AC_REQUIRE([LT_PATH_LD])
AC_REQUIRE([AC_PROG_AWK])
# The name set by libtool depends on the version of libtool. Shame on us
@ -307,14 +205,14 @@ AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [
# .eh_frame and now some of the glibc sections for iconv).
# Bzzzzt. Thanks for playing, maybe next time.
AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections])
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
int main(void)
{
try { throw 1; }
catch (...) { };
return 0;
}
], [ac_sectionLDflags=yes],[ac_sectionLDflags=no], [ac_sectionLDflags=yes])
]])],[ac_sectionLDflags=yes],[ac_sectionLDflags=no],[ac_sectionLDflags=yes])
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
else
@ -401,7 +299,7 @@ if test $enable_symvers != no; then
AC_MSG_CHECKING([for shared libgcc])
ac_save_CFLAGS="$CFLAGS"
CFLAGS=' -lgcc_s'
AC_TRY_LINK(, [return 0;], libat_shared_libgcc=yes, libat_shared_libgcc=no)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[libat_shared_libgcc=yes],[libat_shared_libgcc=no])
CFLAGS="$ac_save_CFLAGS"
if test $libat_shared_libgcc = no; then
cat > conftest.c <<EOF
@ -416,7 +314,7 @@ changequote([,])dnl
rm -f conftest.c conftest.so
if test x${libat_libgcc_s_suffix+set} = xset; then
CFLAGS=" -lgcc_s$libat_libgcc_s_suffix"
AC_TRY_LINK(, [return 0;], libat_shared_libgcc=yes)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[libat_shared_libgcc=yes],[])
CFLAGS="$ac_save_CFLAGS"
fi
fi

94
aclocal.m4 vendored
View File

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -14,22 +14,23 @@
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
[m4_warning([this file was generated for autoconf 2.71.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*-
#
# Copyright (C) 1999-2008, 2011-2015 Free Software Foundation, Inc.
# Copyright (C) 1999-2008, 2011-2019, 2021-2022 Free Software
# Foundation, Inc.
# Written by Thomas Tanner, 1999
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 20 LTDL_INIT
# serial 21 LTDL_INIT
# LT_CONFIG_LTDL_DIR(DIRECTORY, [LTDL-MODE])
# ------------------------------------------
@ -357,7 +358,7 @@ AC_CONFIG_COMMANDS_PRE([
if test -n "$_LT_LIBOBJS"; then
# Remove the extension.
_lt_sed_drop_objext='s/\.o$//;s/\.obj$//'
for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do
for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | $SED "$_lt_sed_drop_objext" | sort -u`; do
_ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext"
_ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo"
done
@ -495,7 +496,7 @@ AC_CACHE_CHECK([whether deplibs are loaded by dlopen],
# If you are looking for one http://www.opendarwin.org/projects/dlcompat
lt_cv_sys_dlopen_deplibs=yes
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
lt_cv_sys_dlopen_deplibs=yes
;;
gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu)
@ -930,7 +931,7 @@ AU_ALIAS([AC_LTDL_DLSYM_USCORE], [LT_FUNC_DLSYM_USCORE])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LTDL_DLSYM_USCORE], [])
# Copyright (C) 2002-2018 Free Software Foundation, Inc.
# Copyright (C) 2002-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -945,7 +946,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.1], [],
m4_if([$1], [1.16.5], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@ -961,14 +962,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.1])dnl
[AM_AUTOMAKE_VERSION([1.16.5])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# Figure out how to run the assembler. -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -988,7 +989,7 @@ _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1040,7 +1041,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1071,7 +1072,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1262,7 +1263,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1301,7 +1302,9 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. Try re-running configure with the
for automatic dependency tracking. If GNU make was not used, consider
re-running the configure script with MAKE="gmake" (or whatever is
necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
@ -1328,7 +1331,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1356,6 +1359,10 @@ m4_defn([AC_PROG_CC])
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.65])dnl
m4_ifdef([_$0_ALREADY_INIT],
[m4_fatal([$0 expanded multiple times
]m4_defn([_$0_ALREADY_INIT]))],
[m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@ -1392,7 +1399,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
@ -1444,6 +1451,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
# Variables for tags utilities; see am/tags.am
if test -z "$CTAGS"; then
CTAGS=ctags
fi
AC_SUBST([CTAGS])
if test -z "$ETAGS"; then
ETAGS=etags
fi
AC_SUBST([ETAGS])
if test -z "$CSCOPE"; then
CSCOPE=cscope
fi
AC_SUBST([CSCOPE])
AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
@ -1525,7 +1546,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1546,7 +1567,7 @@ if test x"${install_sh+set}" != xset; then
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2018 Free Software Foundation, Inc.
# Copyright (C) 2003-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1568,7 +1589,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1603,7 +1624,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1646,7 +1667,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1667,12 +1688,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
@ -1685,7 +1701,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1714,7 +1730,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1761,7 +1777,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1780,7 +1796,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1861,7 +1877,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
# Copyright (C) 2009-2018 Free Software Foundation, Inc.
# Copyright (C) 2009-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1921,7 +1937,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1949,7 +1965,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2018 Free Software Foundation, Inc.
# Copyright (C) 2006-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1968,7 +1984,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2018 Free Software Foundation, Inc.
# Copyright (C) 2004-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -2100,7 +2116,6 @@ AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([m4/asmcfi.m4])
m4_include([m4/ax_append_flag.m4])
m4_include([m4/ax_cc_maxopt.m4])
m4_include([m4/ax_cflags_warn_all.m4])
m4_include([m4/ax_check_compile_flag.m4])
@ -2109,6 +2124,7 @@ m4_include([m4/ax_configure_args.m4])
m4_include([m4/ax_enable_builddir.m4])
m4_include([m4/ax_gcc_archflag.m4])
m4_include([m4/ax_gcc_x86_cpuid.m4])
m4_include([m4/ax_prepend_flag.m4])
m4_include([m4/ax_require_defined.m4])
m4_include([m4/libtool.m4])
m4_include([m4/ltoptions.m4])

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@ -53,7 +53,7 @@ func_file_conv ()
MINGW*)
file_conv=mingw
;;
CYGWIN*)
CYGWIN* | MSYS*)
file_conv=cygwin
;;
*)
@ -67,7 +67,7 @@ func_file_conv ()
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
cygwin/* | msys/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)

1610
config.guess vendored

File diff suppressed because it is too large Load Diff

2990
config.sub vendored

File diff suppressed because it is too large Load Diff

8319
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
dnl Process this with autoconf to create configure
AC_PREREQ(2.68)
AC_PREREQ([2.71])
AC_INIT([libffi], [3.3], [http://github.com/libffi/libffi/issues])
AC_INIT([libffi],[3.4.4],[http://github.com/libffi/libffi/issues])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM
AC_CANONICAL_TARGET
target_alias=${target_alias-$host_alias}
case "${host}" in
@ -38,9 +38,12 @@ AC_SUBST(CFLAGS)
AM_PROG_AS
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
AC_PROG_EGREP
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
AC_CHECK_TOOL(READELF, readelf)
# Test for 64-bit build.
AC_CHECK_SIZEOF([size_t])
@ -59,12 +62,16 @@ fi
cat > local.exp <<EOF
set CC_FOR_TARGET "$CC"
set CXX_FOR_TARGET "$CXX"
set compiler_vendor "$ax_cv_c_compiler_vendor"
EOF
AM_MAINTAINER_MODE
AC_CHECK_HEADERS(sys/memfd.h)
AC_CHECK_FUNCS([memfd_create])
AC_CHECK_HEADERS(sys/mman.h)
AC_CHECK_FUNCS([mmap mkostemp])
AC_CHECK_FUNCS([mmap mkostemp mkstemp])
AC_FUNC_MMAP_BLACKLIST
dnl The -no-testsuite modules omit the test subdir.
@ -82,7 +89,15 @@ fi
AC_SUBST(AM_RUNTESTFLAGS)
AC_SUBST(AM_LTLDFLAGS)
AC_HEADER_STDC
m4_warn([obsolete],
[The preprocessor macro `STDC_HEADERS' is obsolete.
Except in unusual embedded environments, you can safely include all
ISO C90 headers unconditionally.])dnl
# Autoupdate added the next two lines to ensure that your configure
# script's behavior did not change. They are probably safe to remove.
AC_CHECK_INCLUDES_DEFAULT
AC_PROG_EGREP
AC_CHECK_FUNCS(memcpy)
AC_FUNC_ALLOCA
@ -119,9 +134,7 @@ case "$TARGET" in
save_LDFLAGS="$LDFLAGS"
CFLAGS="$CFLAGS -fpic"
LDFLAGS="$LDFLAGS -shared"
AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
[libffi_cv_as_sparc_ua_pcrel=yes],
[libffi_cv_as_sparc_ua_pcrel=no])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");]], [[]])],[libffi_cv_as_sparc_ua_pcrel=yes],[libffi_cv_as_sparc_ua_pcrel=no])
CFLAGS="$save_CFLAGS"
LDFLAGS="$save_LDFLAGS"])
if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
@ -133,9 +146,7 @@ case "$TARGET" in
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");],
[libffi_cv_as_register_pseudo_op=yes],
[libffi_cv_as_register_pseudo_op=no])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[asm (".register %g2, #scratch");]])],[libffi_cv_as_register_pseudo_op=yes],[libffi_cv_as_register_pseudo_op=no])
])
if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
@ -176,12 +187,37 @@ case "$TARGET" in
;;
esac
# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
AC_CACHE_CHECK([whether compiler supports pointer authentication],
libffi_cv_as_ptrauth, [
libffi_cv_as_ptrauth=unknown
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
#ifdef __clang__
# if __has_feature(ptrauth_calls)
# define HAVE_PTRAUTH 1
# endif
#endif
#ifndef HAVE_PTRAUTH
# error Pointer authentication not supported
#endif
]])],[libffi_cv_as_ptrauth=yes],[libffi_cv_as_ptrauth=no])
])
if test "x$libffi_cv_as_ptrauth" = xyes; then
AC_DEFINE(HAVE_PTRAUTH, 1,
[Define if your compiler supports pointer authentication.])
fi
# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC;
# if EMUTRAMP is active too ffi could try mapping without PROT_EXEC,
# but the kernel needs to recognize the trampoline generated by ffi.
# Otherwise fallback to double mmap trick.
AC_ARG_ENABLE(pax_emutramp,
[ --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC],
[ --enable-pax_emutramp enable pax emulated trampolines (experimental)],
if test "$enable_pax_emutramp" = "yes"; then
AC_MSG_WARN([EMUTRAMP is experimental only. Use --enable-pax_emutramp=experimental to enforce.])
elif test "$enable_pax_emutramp" = "experimental"; then
AC_DEFINE(FFI_MMAP_EXEC_EMUTRAMP_PAX, 1,
[Define this if you want to enable pax emulated trampolines])
[Define this if you want to enable pax emulated trampolines (experimental)])
fi)
LT_SYS_SYMBOL_USCORE
@ -238,19 +274,15 @@ EOF
fi
if test "x$GCC" = "xyes"; then
AX_CHECK_COMPILE_FLAG(-fno-lto, libffi_cv_no_lto=-fno-lto)
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
libffi_cv_ro_eh_frame, [
libffi_cv_ro_eh_frame=no
libffi_cv_ro_eh_frame=yes
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
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
if $CC $CFLAGS -c -fpic -fexceptions $libffi_cv_no_lto -o conftest.o conftest.c > /dev/null 2>&1; then
if $READELF -WS conftest.o 2>/dev/null | grep -q -n 'eh_frame .* WA'; then
libffi_cv_ro_eh_frame=no
fi
fi
rm -f conftest.*
@ -270,7 +302,7 @@ if test "x$GCC" = "xyes"; then
echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c
libffi_cv_hidden_visibility_attribute=no
if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
if egrep '(\.hidden|\.private_extern).*foo' conftest.s >/dev/null; then
if $EGREP '(\.hidden|\.private_extern).*foo' conftest.s >/dev/null; then
libffi_cv_hidden_visibility_attribute=yes
fi
fi
@ -283,8 +315,7 @@ if test "x$GCC" = "xyes"; then
fi
AC_ARG_ENABLE(docs,
AC_HELP_STRING([--disable-docs],
[Disable building of docs (default: no)]),
AS_HELP_STRING([--disable-docs],[Disable building of docs (default: no)]),
[enable_docs=no],
[enable_docs=yes])
AM_CONDITIONAL(BUILD_DOCS, [test x$enable_docs = xyes])
@ -342,6 +373,26 @@ AC_ARG_ENABLE(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(exec-static-tramp,
[ --disable-exec-static-tramp disable use of static exec trampolines (enabled by default)])
if test "$enable_exec_static_tramp" != no; then
case "$target" in
*-cygwin* | *-msys*)
# Only define static trampolines if we are using the cygwin runtime.
# Will this need to be changed for mingw?
if test "x$GCC" = "xyes"; then
AC_DEFINE(FFI_EXEC_STATIC_TRAMP, 1,
[Define this if you want statically defined trampolines])
fi
;;
*arm*-*-linux-* | aarch64*-*-linux-* | i*86-*-linux-* | x86_64-*-linux-* | loongarch*-*-linux-*)
AC_DEFINE(FFI_EXEC_STATIC_TRAMP, 1,
[Define this if you want statically defined trampolines])
;;
esac
fi
AC_ARG_ENABLE(purify-safety,
[ --enable-purify-safety purify-safe mode],
if test "$enable_purify_safety" = "yes"; then
@ -351,7 +402,7 @@ AC_ARG_ENABLE(purify-safety,
AC_ARG_ENABLE(multi-os-directory,
[ --disable-multi-os-directory
disable use of gcc --print-multi-os-directory to change the library installation directory])
# These variables are only ever used when we cross-build to X86_WIN32.
# And we only support this with GCC, so...
if test "x$GCC" = "xyes"; then
@ -376,6 +427,16 @@ else
fi
AC_SUBST(toolexeclibdir)
# Conditionalize the makefile for this target machine.
tmake_file_=
for f in ${tmake_file}; do
if test -f ${srcdir}/src/$TARGETDIR/$f; then
tmake_file_="${tmake_file_} \$(srcdir)/src/$TARGETDIR/$f"
fi
done
tmake_file="${tmake_file_}"
AC_SUBST(tmake_file)
# Check linker support.
LIBFFI_ENABLE_SYMVERS

View File

@ -6,9 +6,11 @@
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
# Most of the time we can define all the variables all at once...
case "${host}" in
aarch64*-*-cygwin* | aarch64*-*-mingw* | aarch64*-*-win* )
aarch64*-*-cygwin* | aarch64*-*-msys* | aarch64*-*-mingw* | aarch64*-*-win* )
TARGET=ARM_WIN64; TARGETDIR=aarch64
MSVC=1
if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then
MSVC=1
fi
;;
aarch64*-*-*)
@ -28,9 +30,11 @@ case "${host}" in
SOURCES="ffi.c arcompact.S"
;;
arm*-*-cygwin* | arm*-*-mingw* | arm*-*-win* )
arm*-*-cygwin* | arm*-*-msys* | arm*-*-mingw* | arm*-*-win* )
TARGET=ARM_WIN32; TARGETDIR=arm
MSVC=1
if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then
MSVC=1
fi
;;
arm*-*-*)
@ -53,6 +57,11 @@ case "${host}" in
SOURCES="ffi.c sysv.S"
;;
csky-*-*)
TARGET=CSKY; TARGETDIR=csky
SOURCES="ffi.c sysv.S"
;;
frv-*-*)
TARGET=FRV; TARGETDIR=frv
SOURCES="ffi.c eabi.S"
@ -74,8 +83,8 @@ case "${host}" in
TARGET=X86_FREEBSD; TARGETDIR=x86
;;
i?86-*-cygwin* | i?86-*-mingw* | i?86-*-win* | i?86-*-os2* | i?86-*-interix* \
| x86_64-*-cygwin* | x86_64-*-mingw* | x86_64-*-win* )
i?86-*-cygwin* | i?86-*-msys* | i?86-*-mingw* | i?86-*-win* | i?86-*-os2* | i?86-*-interix* \
| x86_64-*-cygwin* | x86_64-*-msys* | x86_64-*-mingw* | x86_64-*-win* )
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
TARGET=X86_WIN32
@ -108,22 +117,14 @@ case "${host}" in
i?86-*-* | x86_64-*-* | amd64-*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
case "$host" in
x86_64-*x32|x86_64-x32-*)
TARGET_X32=yes
TARGET=X86_64
;;
*)
echo 'int foo (void) { return __x86_64__; }' > conftest.c
if $CC $CFLAGS -Werror -S conftest.c -o conftest.s > /dev/null 2>&1; then
TARGET_X32=yes
TARGET=X86_64
else
TARGET=X86;
fi
rm -f conftest.*
;;
esac
echo 'int foo (void) { return __x86_64__; }' > conftest.c
if $CC $CFLAGS -Werror -S conftest.c -o conftest.s > /dev/null 2>&1; then
TARGET_X32=yes
TARGET=X86_64
else
TARGET=X86;
fi
rm -f conftest.*
else
TARGET=X86_64;
fi
@ -134,6 +135,16 @@ case "${host}" in
SOURCES="ffi.c unix.S"
;;
kvx-*-*)
TARGET=KVX; TARGETDIR=kvx
SOURCES="ffi.c sysv.S"
;;
loongarch64-*-*)
TARGET=LOONGARCH64; TARGETDIR=loongarch64
SOURCES="ffi.c sysv.S"
;;
m32r*-*-*)
TARGET=M32R; TARGETDIR=m32r
SOURCES="ffi.c sysv.S"
@ -167,7 +178,7 @@ case "${host}" in
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
TARGET=MIPS; TARGETDIR=mips
;;
mips*-*linux* | mips*-*-openbsd*)
mips*-*linux* | mips*-*-openbsd* | mips*-*-freebsd*)
# Support 128-bit long double for NewABI.
HAVE_LONG_DOUBLE='defined(__mips64)'
TARGET=MIPS; TARGETDIR=mips
@ -190,6 +201,9 @@ case "${host}" in
powerpc-*-amigaos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-eabi*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-beos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
@ -198,12 +212,18 @@ case "${host}" in
;;
powerpc-*-aix* | rs6000-*-aix*)
TARGET=POWERPC_AIX; TARGETDIR=powerpc
# Create AIX-style "FAT" libraries.
tmake_file="t-aix"
;;
powerpc-*-freebsd* | powerpc-*-openbsd* | powerpc-*-netbsd*)
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc64-*-freebsd*)
powerpcspe-*-freebsd*)
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
CFLAGS="$CFLAGS -D__NO_FPRS__"
;;
powerpc64-*-freebsd* | powerpc64le-*-freebsd*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc*-*-rtems*)
@ -253,10 +273,18 @@ esac
# ... but some of the cases above share configury.
case "${TARGET}" in
ARM_WIN32)
SOURCES="ffi.c sysv_msvc_arm32.S"
if test "$MSVC" = 1; then
SOURCES="ffi.c sysv_msvc_arm32.S"
else
SOURCES="ffi.c sysv.S"
fi
;;
ARM_WIN64)
SOURCES="ffi.c win64_armasm.S"
if test "$MSVC" = 1; then
SOURCES="ffi.c win64_armasm.S"
else
SOURCES="ffi.c sysv.S"
fi
;;
MIPS)
SOURCES="ffi.c o32.S n32.S"

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
libffi (3.4.4-ok1) yangtze; urgency=medium
* New upstream version 3.4.4
-- zhouganqing <zhouganqing@kylinos.cn> Mon, 09 Jan 2023 14:29:07 +0800
libffi (3.3-ok1) yangtze; urgency=medium
* Build for openKylin.

25
debian/patches/no-toolexeclibdir.diff vendored Normal file
View File

@ -0,0 +1,25 @@
From: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Date: Sat, 14 May 2022 00:48:30 +0800
Subject: no-toolexeclibdir
---
libffi.pc.in | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libffi.pc.in b/libffi.pc.in
index 6fad83b..9bd7704 100644
--- a/libffi.pc.in
+++ b/libffi.pc.in
@@ -1,11 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
-toolexeclibdir=@toolexeclibdir@
includedir=@includedir@
Name: @PACKAGE_NAME@
Description: Library supporting Foreign Function Interfaces
Version: @PACKAGE_VERSION@
-Libs: -L${toolexeclibdir} -lffi
+Libs: -lffi
Cflags: -I${includedir}

50
debian/patches/powerpc-fix-2.diff vendored Normal file
View File

@ -0,0 +1,50 @@
From: Samuel Holland <samuel@sholland.org>
Date: Fri, 21 Feb 2020 21:06:15 -0600
Subject: [PATCH] Update powerpc sysv assembly for ffi_powerpc.h changes
(#541)
Some of the flag bits were moved when adding powerpc64 vector support.
Fixes #536
---
src/powerpc/sysv.S | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/powerpc/sysv.S b/src/powerpc/sysv.S
index 1474ce7..df97734 100644
--- a/src/powerpc/sysv.S
+++ b/src/powerpc/sysv.S
@@ -104,17 +104,16 @@ ENTRY(ffi_call_SYSV)
bctrl
/* Now, deal with the return value. */
- mtcrf 0x01,%r31 /* cr7 */
+ mtcrf 0x03,%r31 /* cr6-cr7 */
bt- 31,L(small_struct_return_value)
bt- 30,L(done_return_value)
#ifndef __NO_FPRS__
bt- 29,L(fp_return_value)
#endif
stw %r3,0(%r30)
- bf+ 28,L(done_return_value)
+ bf+ 27,L(done_return_value)
stw %r4,4(%r30)
- mtcrf 0x02,%r31 /* cr6 */
- bf 27,L(done_return_value)
+ bf 26,L(done_return_value)
stw %r5,8(%r30)
stw %r6,12(%r30)
/* Fall through... */
@@ -145,10 +144,9 @@ L(done_return_value):
#ifndef __NO_FPRS__
L(fp_return_value):
.cfi_restore_state
- bf 28,L(float_return_value)
+ bf 27,L(float_return_value)
stfd %f1,0(%r30)
- mtcrf 0x02,%r31 /* cr6 */
- bf 27,L(done_return_value)
+ bf 26,L(done_return_value)
stfd %f2,8(%r30)
b L(done_return_value)
L(float_return_value):

21
debian/patches/powerpc-fix.diff vendored Normal file
View File

@ -0,0 +1,21 @@
From: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Date: Sat, 14 May 2022 00:48:30 +0800
Subject: powerpc-fix
---
src/powerpc/ffi_powerpc.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/powerpc/ffi_powerpc.h b/src/powerpc/ffi_powerpc.h
index 5ee2a70..8e2f2f0 100644
--- a/src/powerpc/ffi_powerpc.h
+++ b/src/powerpc/ffi_powerpc.h
@@ -62,7 +62,7 @@ typedef _Float128 float128;
#elif defined(__FLOAT128__)
typedef __float128 float128;
#else
-typedef __int128 float128;
+typedef char float128[16] __attribute__((aligned(16)));
#endif
void FFI_HIDDEN ffi_closure_SYSV (void);

36
debian/patches/powerpc64-fix-2.diff vendored Normal file
View File

@ -0,0 +1,36 @@
From: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Date: Sat, 14 May 2022 00:48:30 +0800
Subject: powerpc64-fix-2
---
src/powerpc/ffi_linux64.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/powerpc/ffi_linux64.c b/src/powerpc/ffi_linux64.c
index 7364770..4d50878 100644
--- a/src/powerpc/ffi_linux64.c
+++ b/src/powerpc/ffi_linux64.c
@@ -680,9 +680,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
{
if (vecarg_count < NUM_VEC_ARG_REGISTERS64
&& i < nfixedargs)
- *vec_base.f128++ = *arg.f128++;
+ memcpy (vec_base.f128++, arg.f128, sizeof (float128));
else
- *next_arg.f128 = *arg.f128++;
+ memcpy (next_arg.f128, arg.f128++, sizeof (float128));
if (++next_arg.f128 == gpr_end.f128)
next_arg.f128 = rest.f128;
vecarg_count++;
@@ -986,9 +986,9 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
do
{
if (pvec < end_pvec && i < nfixedargs)
- *to.f128 = *pvec++;
+ memcpy (to.f128, pvec++, sizeof (float128));
else
- *to.f128 = *from.f128;
+ memcpy (to.f128, from.f128, sizeof (float128));
to.f128++;
from.f128++;
}

24
debian/patches/powerpc64-fix.diff vendored Normal file
View File

@ -0,0 +1,24 @@
From: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Date: Sat, 14 May 2022 00:48:30 +0800
Subject: powerpc64-fix
---
src/powerpc/ffi_linux64.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/powerpc/ffi_linux64.c b/src/powerpc/ffi_linux64.c
index de0d033..7364770 100644
--- a/src/powerpc/ffi_linux64.c
+++ b/src/powerpc/ffi_linux64.c
@@ -547,9 +547,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
if (next_arg.ul == gpr_end.ul)
next_arg.ul = rest.ul;
if (vecarg_count < NUM_VEC_ARG_REGISTERS64 && i < nfixedargs)
- *vec_base.f128++ = **p_argv.f128;
+ memcpy (vec_base.f128++, *p_argv.f128, sizeof (float128));
else
- *next_arg.f128 = **p_argv.f128;
+ memcpy (next_arg.f128, *p_argv.f128, sizeof (float128));
if (++next_arg.f128 == gpr_end.f128)
next_arg.f128 = rest.f128;
vecarg_count++;

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -91,7 +91,6 @@ target_triplet = @target@
subdir = doc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_append_flag.m4 \
$(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
@ -100,6 +99,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_prepend_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
@ -220,8 +220,9 @@ CCASDEPMODE = @CCASDEPMODE@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
@ -236,9 +237,11 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
FGREP = @FGREP@
FILECMD = @FILECMD@
GREP = @GREP@
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
@ -277,6 +280,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
READELF = @READELF@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
SED = @SED@
SET_MAKE = @SET_MAKE@
@ -332,6 +336,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -342,6 +347,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
tmake_file = @tmake_file@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
top_build_prefix = @top_build_prefix@
@ -554,7 +560,6 @@ ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -1,9 +1,9 @@
This is libffi.info, produced by makeinfo version 6.6 from libffi.texi.
This is libffi.info, produced by makeinfo version 6.8 from libffi.texi.
This manual is for libffi, a portable foreign function interface
library.
Copyright (C) 2008-2019 Anthony Green and Red Hat, Inc.
Copyright (C) 2008-2019, 2021, 2022 Anthony Green and Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -38,7 +38,7 @@ libffi
This manual is for libffi, a portable foreign function interface
library.
Copyright (C) 2008-2019 Anthony Green and Red Hat, Inc.
Copyright (C) 2008-2019, 2021, 2022 Anthony Green and Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -63,6 +63,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Introduction:: What is libffi?
* Using libffi:: How to use libffi.
* Memory Usage:: Where memory for closures comes from.
* Missing Features:: Things libffi can't do.
* Index:: Index.
@ -84,7 +85,7 @@ is found. The calling convention is also sometimes called the "ABI" or
Some programs may not know at the time of compilation what arguments
are to be passed to a function. For instance, an interpreter may be
told at run-time about the number and types of arguments used to call a
given function. 'Libffi' can be used in such programs to provide a
given function. 'libffi' can be used in such programs to provide a
bridge from the interpreter program to compiled code.
The 'libffi' library provides a portable, high level programming
@ -100,7 +101,7 @@ fully featured foreign function interface. A layer must exist above
languages.

File: libffi.info, Node: Using libffi, Next: Missing Features, Prev: Introduction, Up: Top
File: libffi.info, Node: Using libffi, Next: Memory Usage, Prev: Introduction, Up: Top
2 Using libffi
**************
@ -121,7 +122,7 @@ File: libffi.info, Node: The Basics, Next: Simple Example, Up: Using libffi
2.1 The Basics
==============
'Libffi' assumes that you have a pointer to the function you wish to
'libffi' assumes that you have a pointer to the function you wish to
call and that you know the number and types of arguments to pass it, as
well as the return type of the function.
@ -167,6 +168,11 @@ prepare a call interface object, use the function 'ffi_prep_cif'.
NTOTALARGS the total number of arguments, including variadic and
fixed arguments. ARGTYPES must have this many elements.
'ffi_prep_cif_var' will return 'FFI_BAD_ARGTYPE' if any of the
variable argument types are 'ffi_type_float' (promote to
'ffi_type_double' first), or any integer type small than an int
(promote to an int-sized type first).
Note that, different cif's must be prepped for calls to the same
function when different numbers of arguments are passed.
@ -207,9 +213,7 @@ function:
AVALUES is a vector of 'void *' pointers that point to the memory
locations holding the argument values for a call. If CIF declares
that the function has no arguments (i.e., NARGS was 0), then
AVALUES is ignored. Note that argument values may be modified by
the callee (for instance, structs passed by value); the burden of
copying pass-by-value arguments is placed on the caller.
AVALUES is ignored.
Note that while the return value must be register-sized, arguments
should exactly match their declared type. For example, if an
@ -910,9 +914,46 @@ program.
affected type is 'long double'.

File: libffi.info, Node: Missing Features, Next: Index, Prev: Using libffi, Up: Top
File: libffi.info, Node: Memory Usage, Next: Missing Features, Prev: Using libffi, Up: Top
3 Missing Features
3 Memory Usage
**************
Note that memory allocated by 'ffi_closure_alloc' and freed by
'ffi_closure_free' does not come from the same general pool of memory
that 'malloc' and 'free' use. To accomodate security settings, 'libffi'
may aquire memory, for example, by mapping temporary files into multiple
places in the address space (once to write out the closure, a second to
execute it). The search follows this list, using the first that works:
* A anonymous mapping (i.e. not file-backed)
* 'memfd_create()', if the kernel supports it.
* A file created in the directory referenced by the environment
variable 'LIBFFI_TMPDIR'.
* Likewise for the environment variable 'TMPDIR'.
* A file created in '/tmp'.
* A file created in '/var/tmp'.
* A file created in '/dev/shm'.
* A file created in the user's home directory ('$HOME').
* A file created in any directory listed in '/etc/mtab'.
* A file created in any directory listed in '/proc/mounts'.
If security settings prohibit using any of these for closures,
'ffi_closure_alloc' will fail.

File: libffi.info, Node: Missing Features, Next: Index, Prev: Memory Usage, Up: Top
4 Missing Features
******************
'libffi' is missing a few features. We welcome patches to add support
@ -926,9 +967,6 @@ for these.
* The Go API is undocumented.
Note that variadic support is very new and tested on a relatively
small number of platforms.

File: libffi.info, Node: Index, Prev: Missing Features, Up: Top
@ -945,7 +983,7 @@ Index
* closure API: The Closure API. (line 13)
* closures: The Closure API. (line 13)
* FFI: Introduction. (line 31)
* ffi_call: The Basics. (line 67)
* ffi_call: The Basics. (line 72)
* FFI_CLOSURES: The Closure API. (line 13)
* ffi_closure_alloc: The Closure API. (line 19)
* ffi_closure_free: The Closure API. (line 26)
@ -986,31 +1024,37 @@ Index
* ffi_type_ushort: Primitive Types. (line 53)
* ffi_type_void: Primitive Types. (line 10)
* Foreign Function Interface: Introduction. (line 31)
* void: The Basics. (line 67)
* void: The Basics. (line 72)
* void <1>: The Closure API. (line 19)
* void <2>: The Closure API. (line 26)

Tag Table:
Node: Top1388
Node: Introduction2841
Node: Using libffi4473
Node: The Basics5006
Node: Simple Example9870
Node: Types10901
Node: Primitive Types11412
Node: Structures13533
Node: Size and Alignment14572
Node: Arrays Unions Enums16769
Node: Type Example19698
Node: Complex20989
Node: Complex Type Example22407
Node: Multiple ABIs25459
Node: The Closure API25830
Node: Closure Example29656
Node: Thread Safety31288
Node: Missing Features32089
Node: Index32551
Node: Top1400
Node: Introduction2935
Node: Using libffi4567
Node: The Basics5096
Node: Simple Example10024
Node: Types11055
Node: Primitive Types11566
Node: Structures13687
Node: Size and Alignment14726
Node: Arrays Unions Enums16923
Node: Type Example19852
Node: Complex21143
Node: Complex Type Example22561
Node: Multiple ABIs25613
Node: The Closure API25984
Node: Closure Example29810
Node: Thread Safety31442
Node: Memory Usage32243
Node: Missing Features33438
Node: Index33803

End Tag Table

Local Variables:
coding: utf-8
End:

Binary file not shown.

View File

@ -18,7 +18,7 @@
This manual is for libffi, a portable foreign function interface
library.
Copyright @copyright{} 2008--2019 Anthony Green and Red Hat, Inc.
Copyright @copyright{} 2008--2019, 2021, 2022 Anthony Green and Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -65,6 +65,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@menu
* Introduction:: What is libffi?
* Using libffi:: How to use libffi.
* Memory Usage:: Where memory for closures comes from.
* Missing Features:: Things libffi can't do.
* Index:: Index.
@end menu
@ -90,10 +91,10 @@ sometimes called the @dfn{ABI} or @dfn{Application Binary Interface}.
Some programs may not know at the time of compilation what arguments
are to be passed to a function. For instance, an interpreter may be
told at run-time about the number and types of arguments used to call
a given function. @samp{Libffi} can be used in such programs to
a given function. @code{libffi} can be used in such programs to
provide a bridge from the interpreter program to compiled code.
The @samp{libffi} library provides a portable, high level programming
The @code{libffi} library provides a portable, high level programming
interface to various calling conventions. This allows a programmer to
call any function specified by a call interface description at run
time.
@ -101,9 +102,9 @@ time.
@acronym{FFI} stands for Foreign Function Interface. A foreign
function interface is the popular name for the interface that allows
code written in one language to call code written in another language.
The @samp{libffi} library really only provides the lowest, machine
The @code{libffi} library really only provides the lowest, machine
dependent layer of a fully featured foreign function interface. A
layer must exist above @samp{libffi} that handles type conversions for
layer must exist above @code{libffi} that handles type conversions for
values passed between the two languages.
@cindex FFI
@cindex Foreign Function Interface
@ -126,7 +127,7 @@ values passed between the two languages.
@node The Basics
@section The Basics
@samp{Libffi} assumes that you have a pointer to the function you wish
@code{libffi} assumes that you have a pointer to the function you wish
to call and that you know the number and types of arguments to pass
it, as well as the return type of the function.
@ -176,6 +177,11 @@ variadic arguments. It must be greater than zero.
@var{ntotalargs} the total number of arguments, including variadic
and fixed arguments. @var{argtypes} must have this many elements.
@code{ffi_prep_cif_var} will return @code{FFI_BAD_ARGTYPE} if any of
the variable argument types are @code{ffi_type_float} (promote to
@code{ffi_type_double} first), or any integer type small than an int
(promote to an int-sized type first).
Note that, different cif's must be prepped for calls to the same
function when different numbers of arguments are passed.
@ -207,22 +213,20 @@ to ensure this. If @var{cif} declares that the function returns
@code{void} (using @code{ffi_type_void}), then @var{rvalue} is
ignored.
In most situations, @samp{libffi} will handle promotion according to
In most situations, @code{libffi} will handle promotion according to
the ABI. However, for historical reasons, there is a special case
with return values that must be handled by your code. In particular,
for integral (not @code{struct}) types that are narrower than the
system register size, the return value will be widened by
@samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that
@code{libffi}. @code{libffi} provides a type, @code{ffi_arg}, that
can be used as the return type. For example, if the CIF was defined
with a return type of @code{char}, @samp{libffi} will try to store a
with a return type of @code{char}, @code{libffi} will try to store a
full @code{ffi_arg} into the return value.
@var{avalues} is a vector of @code{void *} pointers that point to the
memory locations holding the argument values for a call. If @var{cif}
declares that the function has no arguments (i.e., @var{nargs} was 0),
then @var{avalues} is ignored. Note that argument values may be
modified by the callee (for instance, structs passed by value); the
burden of copying pass-by-value arguments is placed on the caller.
then @var{avalues} is ignored.
Note that while the return value must be register-sized, arguments
should exactly match their declared type. For example, if an argument
@ -249,26 +253,26 @@ int main()
void *values[1];
char *s;
ffi_arg rc;
/* Initialize the argument info vectors */
/* Initialize the argument info vectors */
args[0] = &ffi_type_pointer;
values[0] = &s;
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_sint, args) == FFI_OK)
@{
s = "Hello World!";
ffi_call(&cif, puts, &rc, values);
/* rc now holds the result of the call to puts */
/* values holds a pointer to the function's arg, so to
call puts() again all we need to do is change the
/* values holds a pointer to the function's arg, so to
call puts() again all we need to do is change the
value of s */
s = "This is cool!";
ffi_call(&cif, puts, &rc, values);
@}
return 0;
@}
@end example
@ -406,8 +410,8 @@ when passing to @code{ffi_prep_cif}.
@node Structures
@subsection Structures
@samp{libffi} is perfectly happy passing structures back and forth.
You must first describe the structure to @samp{libffi} by creating a
@code{libffi} is perfectly happy passing structures back and forth.
You must first describe the structure to @code{libffi} by creating a
new @code{ffi_type} object for it.
@tindex ffi_type
@ -427,7 +431,7 @@ For a structure, this should be set to @code{FFI_TYPE_STRUCT}.
This is a @samp{NULL}-terminated array of pointers to @code{ffi_type}
objects. There is one element per field of the struct.
Note that @samp{libffi} has no special support for bit-fields. You
Note that @code{libffi} has no special support for bit-fields. You
must manage these manually.
@end table
@end deftp
@ -504,7 +508,7 @@ valid here.
@subsubsection Arrays
@samp{libffi} does not have direct support for arrays or unions.
@code{libffi} does not have direct support for arrays or unions.
However, they can be emulated using structures.
To emulate an array, simply create an @code{ffi_type} using
@ -531,7 +535,7 @@ structure types created like this should only be used to refer to
members of real @code{FFI_TYPE_STRUCT} objects.
However, a phony array type like this will not cause any errors from
@samp{libffi} if you use it as an argument or return type. This may
@code{libffi} if you use it as an argument or return type. This may
be confusing.
@subsubsection Unions
@ -624,7 +628,7 @@ Here is the corresponding code to describe this struct to
tm_type.size = tm_type.alignment = 0;
tm_type.type = FFI_TYPE_STRUCT;
tm_type.elements = &tm_type_elements;
for (i = 0; i < 9; i++)
tm_type_elements[i] = &ffi_type_sint;
@ -640,7 +644,7 @@ Here is the corresponding code to describe this struct to
@node Complex
@subsection Complex Types
@samp{libffi} supports the complex types defined by the C99
@code{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
@ -648,7 +652,7 @@ standard (@code{_Complex float}, @code{_Complex double} and
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}.
complex type to @code{libffi}.
@tindex ffi_type
@deftp {Data type} ffi_type
@ -815,7 +819,6 @@ Free memory allocated using @code{ffi_closure_alloc}. The argument is
the writable address that was returned.
@end defun
Once you have allocated the memory for a closure, you must construct a
@code{ffi_cif} describing the function call. Finally you can prepare
the closure function:
@ -887,7 +890,7 @@ writable and executable addresses.
@node Closure Example
@section Closure Example
A trivial example that creates a new @code{puts} by binding
A trivial example that creates a new @code{puts} by binding
@code{fputs} with @code{stdout}.
@example
@ -965,6 +968,55 @@ Currently the only affected platform is PowerPC and the only affected
type is @code{long double}.
@end itemize
@node Memory Usage
@chapter Memory Usage
Note that memory allocated by @code{ffi_closure_alloc} and freed by
@code{ffi_closure_free} does not come from the same general pool of
memory that @code{malloc} and @code{free} use. To accomodate security
settings, @code{libffi} may aquire memory, for example, by mapping
temporary files into multiple places in the address space (once to
write out the closure, a second to execute it). The search follows
this list, using the first that works:
@itemize @bullet
@item
A anonymous mapping (i.e. not file-backed)
@item
@code{memfd_create()}, if the kernel supports it.
@item
A file created in the directory referenced by the environment variable
@code{LIBFFI_TMPDIR}.
@item
Likewise for the environment variable @code{TMPDIR}.
@item
A file created in @code{/tmp}.
@item
A file created in @code{/var/tmp}.
@item
A file created in @code{/dev/shm}.
@item
A file created in the user's home directory (@code{$HOME}).
@item
A file created in any directory listed in @code{/etc/mtab}.
@item
A file created in any directory listed in @code{/proc/mounts}.
@end itemize
If security settings prohibit using any of these for closures,
@code{ffi_closure_alloc} will fail.
@node Missing Features
@chapter Missing Features
@ -986,9 +1038,6 @@ The ``raw'' API is undocumented.
The Go API is undocumented.
@end itemize
Note that variadic support is very new and tested on a relatively
small number of platforms.
@node Index
@unnumbered Index

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1995-2018 Free Software Foundation, Inc.
# Copyright (C) 1995-2021 Free Software Foundation, Inc.
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
#
# This program is free software; you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
@set UPDATED 22 November 2019
@set UPDATED-MONTH November 2019
@set EDITION 3.3
@set VERSION 3.3
@set UPDATED 23 October 2022
@set UPDATED-MONTH October 2022
@set EDITION 3.4.4
@set VERSION 3.4.4

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
@set UPDATED 22 November 2019
@set UPDATED-MONTH November 2019
@set EDITION 3.3
@set VERSION 3.3
@set UPDATED 23 October 2022
@set UPDATED-MONTH October 2022
@set EDITION 3.4.4
@set VERSION 3.4.4

View File

@ -3,12 +3,7 @@
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
/* Define to 1 if using 'alloca.c'. */
#undef C_ALLOCA
/* Define to the flags needed for the .section .eh_frame directive. */
@ -17,10 +12,14 @@
/* Define this if you want extra debugging. */
#undef FFI_DEBUG
/* Define this if you want statically defined trampolines */
#undef FFI_EXEC_STATIC_TRAMP
/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
#undef FFI_EXEC_TRAMPOLINE_TABLE
/* Define this if you want to enable pax emulated trampolines */
/* Define this if you want to enable pax emulated trampolines (experimental)
*/
#undef FFI_MMAP_EXEC_EMUTRAMP_PAX
/* Cannot use malloc on this target, so, we revert to alternative means */
@ -32,11 +31,10 @@
/* 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. */
/* Define to 1 if you have 'alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
/* Define to 1 if <alloca.h> works. */
#undef HAVE_ALLOCA_H
/* Define if your assembler supports .cfi_* directives. */
@ -76,12 +74,15 @@
/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memfd_create' function. */
#undef HAVE_MEMFD_CREATE
/* Define to 1 if you have the `mkostemp' function. */
#undef HAVE_MKOSTEMP
/* Define to 1 if you have the `mkstemp' function. */
#undef HAVE_MKSTEMP
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
@ -94,12 +95,18 @@
/* Define if read-only mmap of a plain file works. */
#undef HAVE_MMAP_FILE
/* Define if your compiler supports pointer authentication. */
#undef HAVE_PTRAUTH
/* Define if .eh_frame sections should be read-only. */
#undef HAVE_RO_EH_FRAME
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@ -109,6 +116,9 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/memfd.h> header file. */
#undef HAVE_SYS_MEMFD_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
@ -165,7 +175,9 @@
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Define if symbols are underscored. */

View File

@ -6,15 +6,13 @@ import collections
import glob
import argparse
class Platform(object):
pass
class simulator_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphonesimulator'
class i386_platform(Platform):
arch = 'i386'
triple = 'i386-apple-darwin11'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __i386__\n\n"
suffix = "\n\n#endif"
@ -22,12 +20,8 @@ class simulator_platform(Platform):
src_files = ['sysv.S', 'ffi.c', 'internal.h']
class simulator64_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphonesimulator'
class x86_64_platform(Platform):
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"
@ -35,25 +29,8 @@ class simulator64_platform(Platform):
src_files = ['unix64.S', 'ffi64.c', 'ffiw64.c', 'win64.S', 'internal64.h', 'asmnames.h']
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', 'ffi.c', 'internal.h']
class device64_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphoneos'
class arm64_platform(Platform):
arch = 'arm64'
triple = 'aarch64-apple-darwin13'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __arm64__\n\n"
suffix = "\n\n#endif"
@ -61,30 +38,135 @@ class device64_platform(Platform):
src_files = ['sysv.S', 'ffi.c', 'internal.h']
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'
class armv7_platform(Platform):
arch = 'armv7'
prefix = "#ifdef __arm__\n\n"
suffix = "\n\n#endif"
src_dir = 'arm'
src_files = ['sysv.S', 'ffi.c', 'internal.h']
prefix = "#ifdef __i386__\n\n"
suffix = "\n\n#endif"
class ios_simulator_i386_platform(i386_platform):
triple = 'i386-apple-darwin11'
target = 'i386-apple-ios-simulator'
directory = 'darwin_ios'
sdk = 'iphonesimulator'
version_min = '-miphoneos-version-min=7.0'
class desktop64_platform(Platform):
class ios_simulator_x86_64_platform(x86_64_platform):
triple = 'x86_64-apple-darwin13'
target = 'x86_64-apple-ios-simulator'
directory = 'darwin_ios'
sdk = 'iphonesimulator'
version_min = '-miphoneos-version-min=7.0'
class ios_simulator_arm64_platform(arm64_platform):
triple = 'aarch64-apple-darwin20'
target = 'arm64-apple-ios-simulator'
directory = 'darwin_ios'
sdk = 'iphonesimulator'
version_min = '-miphoneos-version-min=7.0'
class ios_device_armv7_platform(armv7_platform):
triple = 'arm-apple-darwin11'
target = 'armv7-apple-ios'
directory = 'darwin_ios'
sdk = 'iphoneos'
version_min = '-miphoneos-version-min=7.0'
class ios_device_arm64_platform(arm64_platform):
triple = 'aarch64-apple-darwin13'
target = 'arm64-apple-ios'
directory = 'darwin_ios'
sdk = 'iphoneos'
version_min = '-miphoneos-version-min=7.0'
class desktop_x86_64_platform(x86_64_platform):
triple = 'x86_64-apple-darwin10'
target = 'x86_64-apple-macos'
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 = ['unix64.S', 'ffi64.c', 'ffiw64.c', 'win64.S', 'internal64.h', 'asmnames.h']
class desktop_arm64_platform(arm64_platform):
triple = 'aarch64-apple-darwin20'
target = 'arm64-apple-macos'
directory = 'darwin_osx'
sdk = 'macosx'
version_min = '-mmacosx-version-min=11.0'
class tvos_simulator_x86_64_platform(x86_64_platform):
triple = 'x86_64-apple-darwin13'
target = 'x86_64-apple-tvos-simulator'
directory = 'darwin_tvos'
sdk = 'appletvsimulator'
version_min = '-mtvos-version-min=9.0'
class tvos_simulator_arm64_platform(arm64_platform):
triple = 'aarch64-apple-darwin20'
target = 'arm64-apple-tvos-simulator'
directory = 'darwin_tvos'
sdk = 'appletvsimulator'
version_min = '-mtvos-version-min=9.0'
class tvos_device_arm64_platform(arm64_platform):
triple = 'aarch64-apple-darwin13'
target = 'arm64-apple-tvos'
directory = 'darwin_tvos'
sdk = 'appletvos'
version_min = '-mtvos-version-min=9.0'
class watchos_simulator_i386_platform(i386_platform):
triple = 'i386-apple-darwin11'
target = 'i386-apple-watchos-simulator'
directory = 'darwin_watchos'
sdk = 'watchsimulator'
version_min = '-mwatchos-version-min=4.0'
class watchos_simulator_x86_64_platform(x86_64_platform):
triple = 'x86_64-apple-darwin13'
target = 'x86_64-apple-watchos-simulator'
directory = 'darwin_watchos'
sdk = 'watchsimulator'
version_min = '-mwatchos-version-min=4.0'
class watchos_simulator_arm64_platform(arm64_platform):
triple = 'aarch64-apple-darwin20'
target = 'arm64-apple-watchos-simulator'
directory = 'darwin_watchos'
sdk = 'watchsimulator'
version_min = '-mwatchos-version-min=4.0'
class watchos_device_armv7k_platform(armv7_platform):
triple = 'arm-apple-darwin11'
target = 'armv7k-apple-watchos'
directory = 'darwin_watchos'
sdk = 'watchos'
arch = 'armv7k'
version_min = '-mwatchos-version-min=4.0'
class watchos_device_arm64_32_platform(arm64_platform):
triple = 'aarch64-apple-darwin13'
target = 'arm64_32-apple-watchos'
directory = 'darwin_watchos'
sdk = 'watchos'
arch = 'arm64_32'
version_min = '-mwatchos-version-min=4.0'
def mkdir_p(path):
@ -136,14 +218,14 @@ def copy_src_platform_files(platform):
def build_target(platform, platform_headers):
def xcrun_cmd(cmd):
return 'xcrun -sdk %s %s -arch %s' % (platform.sdk, cmd, platform.arch)
return 'xcrun -sdk %s %s -target %s' % (platform.sdk, cmd, platform.target)
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))
CFLAGS='%s -fembed-bitcode' % (platform.version_min))
working_dir = os.getcwd()
try:
os.chdir(build_dir)
@ -163,32 +245,59 @@ def build_target(platform, platform_headers):
platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix))
def generate_source_and_headers(generate_osx=True, generate_ios=True):
def generate_source_and_headers(
generate_osx=True,
generate_ios=True,
generate_tvos=True,
generate_watchos=True,
):
copy_files('src', 'darwin_common/src', pattern='*.c')
copy_files('include', 'darwin_common/include', pattern='*.h')
if generate_ios:
copy_src_platform_files(simulator_platform)
copy_src_platform_files(simulator64_platform)
copy_src_platform_files(device_platform)
copy_src_platform_files(device64_platform)
copy_src_platform_files(ios_simulator_i386_platform)
copy_src_platform_files(ios_simulator_x86_64_platform)
copy_src_platform_files(ios_simulator_arm64_platform)
copy_src_platform_files(ios_device_armv7_platform)
copy_src_platform_files(ios_device_arm64_platform)
if generate_osx:
copy_src_platform_files(desktop32_platform)
copy_src_platform_files(desktop64_platform)
copy_src_platform_files(desktop_x86_64_platform)
copy_src_platform_files(desktop_arm64_platform)
if generate_tvos:
copy_src_platform_files(tvos_simulator_x86_64_platform)
copy_src_platform_files(tvos_simulator_arm64_platform)
copy_src_platform_files(tvos_device_arm64_platform)
if generate_watchos:
copy_src_platform_files(watchos_simulator_i386_platform)
copy_src_platform_files(watchos_simulator_x86_64_platform)
copy_src_platform_files(watchos_simulator_arm64_platform)
copy_src_platform_files(watchos_device_armv7k_platform)
copy_src_platform_files(watchos_device_arm64_32_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)
build_target(ios_simulator_i386_platform, platform_headers)
build_target(ios_simulator_x86_64_platform, platform_headers)
build_target(ios_simulator_arm64_platform, platform_headers)
build_target(ios_device_armv7_platform, platform_headers)
build_target(ios_device_arm64_platform, platform_headers)
if generate_osx:
build_target(desktop32_platform, platform_headers)
build_target(desktop64_platform, platform_headers)
build_target(desktop_x86_64_platform, platform_headers)
build_target(desktop_arm64_platform, platform_headers)
if generate_tvos:
build_target(tvos_simulator_x86_64_platform, platform_headers)
build_target(tvos_simulator_arm64_platform, platform_headers)
build_target(tvos_device_arm64_platform, platform_headers)
if generate_watchos:
build_target(watchos_simulator_i386_platform, platform_headers)
build_target(watchos_simulator_x86_64_platform, platform_headers)
build_target(watchos_simulator_arm64_platform, platform_headers)
build_target(watchos_device_armv7k_platform, platform_headers)
build_target(watchos_device_arm64_32_platform, platform_headers)
mkdir_p('darwin_common/include')
for header_name, tag_tuples in platform_headers.iteritems():
for header_name, tag_tuples in platform_headers.items():
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:
@ -198,6 +307,13 @@ 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)
parser.add_argument('--only-tvos', action='store_true', default=False)
parser.add_argument('--only-watchos', 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)
generate_source_and_headers(
generate_osx=not args.only_ios and not args.only_tvos and not args.only_watchos,
generate_ios=not args.only_osx and not args.only_tvos and not args.only_watchos,
generate_tvos=not args.only_ios and not args.only_osx and not args.only_watchos,
generate_watchos=not args.only_ios and not args.only_osx and not args.only_tvos,
)

View File

@ -3,7 +3,7 @@
AUTOMAKE_OPTIONS=foreign
DISTCLEANFILES=ffitarget.h
noinst_HEADERS=ffi_common.h ffi_cfi.h
noinst_HEADERS=ffi_common.h ffi_cfi.h tramp.h
EXTRA_DIST=ffi.h.in
nodist_include_HEADERS = ffi.h ffitarget.h

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -92,7 +92,6 @@ target_triplet = @target@
subdir = include
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_append_flag.m4 \
$(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
@ -101,6 +100,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_prepend_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
@ -179,8 +179,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/ffi.h.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
@ -200,8 +198,9 @@ CCASDEPMODE = @CCASDEPMODE@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
@ -216,9 +215,11 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
FGREP = @FGREP@
FILECMD = @FILECMD@
GREP = @GREP@
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
@ -257,6 +258,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
READELF = @READELF@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
SED = @SED@
SET_MAKE = @SET_MAKE@
@ -312,6 +314,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -322,6 +325,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
tmake_file = @tmake_file@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
top_build_prefix = @top_build_prefix@
@ -329,7 +333,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign
DISTCLEANFILES = ffitarget.h
noinst_HEADERS = ffi_common.h ffi_cfi.h
noinst_HEADERS = ffi_common.h ffi_cfi.h tramp.h
EXTRA_DIST = ffi.h.in
nodist_include_HEADERS = ffi.h ffitarget.h
all: all-am
@ -445,7 +449,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
libffi @VERSION@ - Copyright (c) 2011, 2014, 2019 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
libffi @VERSION@
- Copyright (c) 2011, 2014, 2019, 2021, 2022 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@ -55,6 +56,31 @@ extern "C" {
/* ---- System configuration information --------------------------------- */
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if @HAVE_LONG_DOUBLE@
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#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_COMPLEX
#include <ffitarget.h>
#ifndef LIBFFI_ASM
@ -217,7 +243,8 @@ FFI_EXTERN ffi_type ffi_type_complex_longdouble;
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
FFI_BAD_ABI,
FFI_BAD_ARGTYPE
} ffi_status;
typedef struct {
@ -269,7 +296,7 @@ typedef ffi_raw ffi_java_raw;
#endif
FFI_API
FFI_API
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
@ -310,11 +337,17 @@ typedef struct {
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
union {
char tramp[FFI_TRAMPOLINE_SIZE];
void *ftramp;
};
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
#if defined(_MSC_VER) && defined(_M_IX86)
void *padding;
#endif
} ffi_closure
#ifdef __GNUC__
__attribute__((aligned (8)))
@ -330,6 +363,14 @@ typedef struct {
FFI_API void *ffi_closure_alloc (size_t size, void **code);
FFI_API void ffi_closure_free (void *);
#if defined(PA_LINUX) || defined(PA_HPUX)
#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2))
#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3))
#else
#define FFI_CLOSURE_PTR(X) (X)
#define FFI_RESTORE_PTR(X) (X)
#endif
FFI_API ffi_status
ffi_prep_closure (ffi_closure*,
ffi_cif *,
@ -347,7 +388,7 @@ ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
void *codeloc);
#ifdef __sgi
# pragma pack 8
@ -363,9 +404,9 @@ typedef struct {
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
@ -389,8 +430,8 @@ typedef struct {
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
@ -451,7 +492,7 @@ FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
/* ---- Public interface definition -------------------------------------- */
FFI_API
FFI_API
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
@ -483,31 +524,6 @@ ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
#endif
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if @HAVE_LONG_DOUBLE@
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#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_COMPLEX
#ifdef __cplusplus
}
#endif

View File

@ -2,6 +2,27 @@
ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc.
Conditionally assemble cfi directives. Only necessary for building libffi.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the ``Software''), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL 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 FFI_CFI_H

View File

@ -5,6 +5,27 @@
Common internal definitions and macros. Only necessary for building
libffi.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the ``Software''), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL 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 FFI_COMMON_H
@ -103,6 +124,10 @@ ffi_status ffi_prep_cif_core(ffi_cif *cif,
some targets. */
void *ffi_data_to_code_pointer (void *data) FFI_HIDDEN;
/* The arch code calls this to determine if a given closure has a
static trampoline. */
int ffi_tramp_is_present (void *closure) FFI_HIDDEN;
/* Extended cif, used in callback from assembly routine */
typedef struct
{

45
include/tramp.h Normal file
View File

@ -0,0 +1,45 @@
/* -----------------------------------------------------------------------
ffi_tramp.h - Copyright (C) 2021 Microsoft, Inc.
Static trampoline definitions.
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 FFI_TRAMP_H
#define FFI_TRAMP_H
#ifdef __cplusplus
extern "C" {
#endif
int ffi_tramp_is_supported(void);
void *ffi_tramp_alloc (int flags);
void ffi_tramp_set_parms (void *tramp, void *data, void *code);
void *ffi_tramp_get_addr (void *tramp);
void ffi_tramp_free (void *tramp);
#ifdef __cplusplus
}
#endif
#endif /* FFI_TRAMP_H */

View File

@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC
scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@ -69,6 +69,11 @@ posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
@ -99,18 +104,28 @@ Options:
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
"
while test $# -ne 0; do
@ -137,8 +152,13 @@ while test $# -ne 0; do
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
@ -255,6 +275,10 @@ do
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
@ -301,22 +325,6 @@ do
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
@ -326,52 +334,49 @@ do
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# Note that $RANDOM variable is not portable (e.g. dash); Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p' feature.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac
if
@ -382,7 +387,7 @@ do
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
@ -411,7 +416,7 @@ do
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
@ -451,7 +456,18 @@ do
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
@ -477,6 +493,13 @@ do
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
@ -491,9 +514,9 @@ do
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1

View File

@ -6,7 +6,7 @@
/* These version numbers correspond to the libtool-version abi numbers,
not to the libffi release numbers. */
LIBFFI_BASE_7.0 {
LIBFFI_BASE_8.0 {
global:
/* Exported data variables. */
ffi_type_void;
@ -38,27 +38,23 @@ LIBFFI_BASE_7.0 {
ffi_java_raw_to_ptrarray;
ffi_java_raw_size;
ffi_get_struct_offsets;
local:
*;
};
LIBFFI_BASE_7.1 {
global:
ffi_get_struct_offsets;
} LIBFFI_BASE_7.0;
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
LIBFFI_COMPLEX_7.0 {
LIBFFI_COMPLEX_8.0 {
global:
/* Exported data variables. */
ffi_type_complex_float;
ffi_type_complex_double;
ffi_type_complex_longdouble;
} LIBFFI_BASE_7.0;
} LIBFFI_BASE_8.0;
#endif
#if FFI_CLOSURES
LIBFFI_CLOSURE_7.0 {
LIBFFI_CLOSURE_8.0 {
global:
ffi_closure_alloc;
ffi_closure_free;
@ -68,13 +64,13 @@ LIBFFI_CLOSURE_7.0 {
ffi_prep_raw_closure_loc;
ffi_prep_java_raw_closure;
ffi_prep_java_raw_closure_loc;
} LIBFFI_BASE_7.0;
} LIBFFI_BASE_8.0;
#endif
#if FFI_GO_CLOSURES
LIBFFI_GO_CLOSURE_7.0 {
LIBFFI_GO_CLOSURE_8.0 {
global:
ffi_call_go;
ffi_prep_go_closure;
} LIBFFI_CLOSURE_7.0;
} LIBFFI_CLOSURE_8.0;
#endif

View File

@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; };
43B5D3FA1D3547CE00D1E1FD /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */; };
43E9A5C71D352C1500926A8F /* sysv_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C51D352C1500926A8F /* sysv_i386.S */; };
43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; };
DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; };
@ -28,26 +27,18 @@
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 */; };
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 /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* unix64_x86_64.S */; };
DBFA7195187F1DA100A76262 /* sysv_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* sysv_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 */; };
FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; };
FDB52FB41F6144FA00AA92E6 /* sysv_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C51D352C1500926A8F /* sysv_i386.S */; };
FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; };
FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; };
FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; };
FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; };
FDB52FBA1F6144FA00AA92E6 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
FDB52FBB1F6144FA00AA92E6 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7176187F1D9B00A76262 /* ffi_i386.c */; };
FDB52FBC1F6144FA00AA92E6 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
FDB52FBD1F6144FA00AA92E6 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; };
FDB52FBE1F6144FA00AA92E6 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
@ -56,7 +47,6 @@
FDB52FD01F614A8B00AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
FDB52FD11F614AA700AA92E6 /* ffi_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715E187F1D9B00A76262 /* ffi_arm64.h */; };
FDB52FD21F614AAB00AA92E6 /* ffi_armv7.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715F187F1D9B00A76262 /* ffi_armv7.h */; };
FDB52FD31F614AB000AA92E6 /* ffi_i386.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7160187F1D9B00A76262 /* ffi_i386.h */; };
FDB52FD41F614AB500AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */; };
FDB52FD51F614AE200AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
FDB52FD61F614AEA00AA92E6 /* ffi_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715E187F1D9B00A76262 /* ffi_arm64.h */; };
@ -64,7 +54,6 @@
FDB52FD81F614B8700AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; };
FDB52FD91F614B8E00AA92E6 /* ffitarget_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */; };
FDB52FDA1F614B9300AA92E6 /* ffitarget_armv7.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */; };
FDB52FDB1F614B9700AA92E6 /* ffitarget_i386.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */; };
FDB52FDD1F614BA900AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */; };
FDB52FDE1F6155E300AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; };
FDB52FDF1F6155EA00AA92E6 /* ffitarget_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */; };
@ -76,9 +65,7 @@
FDDB2F411F5D66E200EF414E /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */; };
FDDB2F461F5D691E00EF414E /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F441F5D68C900EF414E /* win64_x86_64.S */; };
FDDB2F4A1F5D846400EF414E /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; };
FDDB2F4B1F5D846400EF414E /* sysv_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* sysv_i386.S */; };
FDDB2F4C1F5D846400EF414E /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
FDDB2F4D1F5D846400EF414E /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; };
FDDB2F4E1F5D846400EF414E /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */; };
FDDB2F4F1F5D846400EF414E /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
FDDB2F501F5D846400EF414E /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
@ -97,12 +84,10 @@
FDB52FD01F614A8B00AA92E6 /* ffi.h in CopyFiles */,
FDB52FD11F614AA700AA92E6 /* ffi_arm64.h in CopyFiles */,
FDB52FD21F614AAB00AA92E6 /* ffi_armv7.h in CopyFiles */,
FDB52FD31F614AB000AA92E6 /* ffi_i386.h in CopyFiles */,
FDB52FD41F614AB500AA92E6 /* ffi_x86_64.h in CopyFiles */,
FDB52FD81F614B8700AA92E6 /* ffitarget.h in CopyFiles */,
FDB52FD91F614B8E00AA92E6 /* ffitarget_arm64.h in CopyFiles */,
FDB52FDA1F614B9300AA92E6 /* ffitarget_armv7.h in CopyFiles */,
FDB52FDB1F614B9700AA92E6 /* ffitarget_i386.h in CopyFiles */,
FDB52FDD1F614BA900AA92E6 /* ffitarget_x86_64.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -140,7 +125,6 @@
/* Begin PBXFileReference section */
43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffiw64_x86_64.c; sourceTree = "<group>"; };
43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = win64_x86_64.S; sourceTree = "<group>"; };
43E9A5C51D352C1500926A8F /* sysv_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_i386.S; sourceTree = "<group>"; };
43E9A5C61D352C1500926A8F /* unix64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unix64_x86_64.S; sourceTree = "<group>"; };
43E9A5DA1D35373600926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; };
43E9A5DB1D35374400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; };
@ -159,32 +143,23 @@
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; indentWidth = 2; 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; indentWidth = 2; 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>"; };
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 /* unix64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unix64_x86_64.S; sourceTree = "<group>"; };
DBFA718B187F1DA100A76262 /* sysv_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_i386.S; sourceTree = "<group>"; };
DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; 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>"; };
FDB52FC51F6144FA00AA92E6 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
FDDB2F3E1F5D61BC00EF414E /* asmnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asmnames.h; sourceTree = "<group>"; };
FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffiw64_x86_64.c; sourceTree = "<group>"; };
@ -262,15 +237,12 @@
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;
@ -313,8 +285,6 @@
43E9A5DD1D35375400926A8F /* internal64.h */,
DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */,
43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */,
DBFA7176187F1D9B00A76262 /* ffi_i386.c */,
43E9A5C51D352C1500926A8F /* sysv_i386.S */,
43E9A5C61D352C1500926A8F /* unix64_x86_64.S */,
43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */,
);
@ -333,11 +303,8 @@
DBFA7181187F1DA100A76262 /* include */ = {
isa = PBXGroup;
children = (
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;
@ -359,8 +326,6 @@
FDDB2F3E1F5D61BC00EF414E /* asmnames.h */,
DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */,
FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */,
DBFA718D187F1DA100A76262 /* ffi_i386.c */,
DBFA718B187F1DA100A76262 /* sysv_i386.S */,
DBFA718A187F1DA100A76262 /* unix64_x86_64.S */,
FDDB2F441F5D68C900EF414E /* win64_x86_64.S */,
);
@ -379,11 +344,8 @@
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;
};
@ -549,14 +511,12 @@
buildActionMask = 2147483647;
files = (
43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */,
43E9A5C71D352C1500926A8F /* sysv_i386.S in Sources */,
DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */,
DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */,
DBFA714E187F1D8600A76262 /* closures.c in Sources */,
DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */,
43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c 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 */,
DBFA715A187F1D8600A76262 /* types.c in Sources */,
@ -570,9 +530,7 @@
buildActionMask = 2147483647;
files = (
DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */,
DBFA7195187F1DA100A76262 /* sysv_i386.S in Sources */,
DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */,
DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */,
FDDB2F411F5D66E200EF414E /* ffiw64_x86_64.c in Sources */,
DBFA715B187F1D8600A76262 /* types.c in Sources */,
DBFA7159187F1D8600A76262 /* raw_api.c in Sources */,
@ -587,14 +545,12 @@
buildActionMask = 2147483647;
files = (
FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */,
FDB52FB41F6144FA00AA92E6 /* sysv_i386.S in Sources */,
FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */,
FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */,
FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */,
FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */,
FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */,
FDB52FBA1F6144FA00AA92E6 /* prep_cif.c in Sources */,
FDB52FBB1F6144FA00AA92E6 /* ffi_i386.c in Sources */,
FDB52FBC1F6144FA00AA92E6 /* raw_api.c in Sources */,
FDB52FBD1F6144FA00AA92E6 /* sysv_arm64.S in Sources */,
FDB52FBE1F6144FA00AA92E6 /* types.c in Sources */,
@ -608,9 +564,7 @@
buildActionMask = 2147483647;
files = (
FDDB2F4A1F5D846400EF414E /* ffi64_x86_64.c in Sources */,
FDDB2F4B1F5D846400EF414E /* sysv_i386.S in Sources */,
FDDB2F4C1F5D846400EF414E /* prep_cif.c in Sources */,
FDDB2F4D1F5D846400EF414E /* ffi_i386.c in Sources */,
FDDB2F4E1F5D846400EF414E /* ffiw64_x86_64.c in Sources */,
FDDB2F4F1F5D846400EF414E /* types.c in Sources */,
FDDB2F501F5D846400EF414E /* raw_api.c in Sources */,
@ -712,7 +666,7 @@
PRODUCT_NAME = ffi;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
VALID_ARCHS = "arm64 armv7 armv7s i386 x86_64";
VALID_ARCHS = "arm64 armv7 armv7s x86_64";
};
name = Debug;
};
@ -746,7 +700,7 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
VALIDATE_PRODUCT = YES;
VALID_ARCHS = "arm64 armv7 armv7s i386 x86_64";
VALID_ARCHS = "arm64 armv7 armv7s x86_64";
};
name = Release;
};

View File

@ -5,7 +5,7 @@
#
# Here are a set of rules to help you update your library version
# information:
#
#
# 1. Start with version information of `0:0:0' for each libtool library.
#
# 2. Update the version information only immediately before a public
@ -26,4 +26,4 @@
# release, then set age to 0.
#
# CURRENT:REVISION:AGE
8:0:1
9:2:1

870
ltmain.sh

File diff suppressed because it is too large Load Diff

View File

@ -55,7 +55,7 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 17
#serial 22
AC_DEFUN([AX_CC_MAXOPT],
[
@ -67,20 +67,19 @@ AC_ARG_ENABLE(portable-binary, [AS_HELP_STRING([--enable-portable-binary], [disa
acx_maxopt_portable=$enableval, acx_maxopt_portable=no)
# Try to determine "good" native compiler flags if none specified via CFLAGS
if test "$ac_test_CFLAGS" != "set"; then
CFLAGS=""
if test "x$ac_test_CFLAGS" = "x"; then
case $ax_cv_c_compiler_vendor in
dec) CFLAGS="-newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host"
dec) CFLAGS="$CFLAGS -newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host"
if test "x$acx_maxopt_portable" = xno; then
CFLAGS="$CFLAGS -arch host"
fi;;
sun) CFLAGS="-native -fast -xO5 -dalign"
sun) CFLAGS="$CFLAGS -native -fast -xO5 -dalign"
if test "x$acx_maxopt_portable" = xyes; then
CFLAGS="$CFLAGS -xarch=generic"
fi;;
hp) CFLAGS="+Oall +Optrs_ansi +DSnative"
hp) CFLAGS="$CFLAGS +Oall +Optrs_ansi +DSnative"
if test "x$acx_maxopt_portable" = xyes; then
CFLAGS="$CFLAGS +DAportable"
fi;;
@ -91,8 +90,8 @@ if test "$ac_test_CFLAGS" != "set"; then
xlc_opt="-qtune=auto"
fi
AX_CHECK_COMPILE_FLAG($xlc_opt,
CFLAGS="-O3 -qansialias -w $xlc_opt",
[CFLAGS="-O3 -qansialias -w"
CFLAGS="$CFLAGS -O3 -qansialias -w $xlc_opt",
[CFLAGS="$CFLAGS -O3 -qansialias -w"
echo "******************************************************"
echo "* You seem to have the IBM C compiler. It is *"
echo "* recommended for best performance that you use: *"
@ -105,7 +104,7 @@ if test "$ac_test_CFLAGS" != "set"; then
echo "******************************************************"])
;;
intel) CFLAGS="-O3 -ansi_alias"
intel) CFLAGS="$CFLAGS -O3 -ansi_alias"
if test "x$acx_maxopt_portable" = xno; then
icc_archflag=unknown
icc_flags=""
@ -144,12 +143,18 @@ if test "$ac_test_CFLAGS" != "set"; then
fi
;;
nvhpc)
# default optimization flags for nvhpc
CFLAGS="$CFLAGS -O3"
;;
gnu)
# default optimization flags for gcc on all systems
CFLAGS="-O3 -fomit-frame-pointer"
CFLAGS="$CFLAGS -O3 -fomit-frame-pointer"
# -malign-double for x86 systems
# libffi local change -- don't align double, as it changes the ABI
# LIBFFI_LOCAL: don't do this.
# The testsuite doesn't use these flags and we'll get test failures.
# AX_CHECK_COMPILE_FLAG(-malign-double, CFLAGS="$CFLAGS -malign-double")
# -fstrict-aliasing for gcc-2.95+
@ -164,7 +169,7 @@ if test "$ac_test_CFLAGS" != "set"; then
microsoft)
# default optimization flags for MSVC opt builds
CFLAGS="-O2"
CFLAGS="$CFLAGS -O2"
;;
esac
@ -176,7 +181,7 @@ if test "$ac_test_CFLAGS" != "set"; then
echo "* (otherwise, a default of CFLAGS=-O3 will be used) *"
echo "********************************************************"
echo ""
CFLAGS="-O3"
CFLAGS="$CFLAGS -O3"
fi
AX_CHECK_COMPILE_FLAG($CFLAGS, [], [
@ -187,7 +192,6 @@ if test "$ac_test_CFLAGS" != "set"; then
echo "* Use ./configure CFLAGS=... to specify your own flags *"
echo "********************************************************"
echo ""
CFLAGS=""
])
fi

View File

@ -4,33 +4,54 @@
#
# SYNOPSIS
#
# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_CFLAGS_WARN_ALL [(shellvar[, default[, action-if-found[, action-if-not-found]]])]
# AX_CXXFLAGS_WARN_ALL [(shellvar[, default[, action-if-found[, action-if-not-found]]])]
# AX_FCFLAGS_WARN_ALL [(shellvar[, default[, action-if-found[, action-if-not-found]]])]
#
# DESCRIPTION
#
# Try to find a compiler option that enables most reasonable warnings.
# Specify compiler options that enable most reasonable warnings. For the
# GNU Compiler Collection (GCC), for example, it will be "-Wall". The
# result is added to shellvar, one of CFLAGS, CXXFLAGS or FCFLAGS if the
# first parameter is not specified.
#
# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result
# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default.
# Each of these macros accepts the following optional arguments:
#
# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX,
# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and
# Intel compilers. For a given compiler, the Fortran flags are much more
# experimental than their C equivalents.
# - $1 - shellvar
# shell variable to use (CFLAGS, CXXFLAGS or FCFLAGS if not
# specified, depending on macro)
#
# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS
# - $2 add-value-if-not-found : nothing
# - $3 action-if-found : add value to shellvariable
# - $4 action-if-not-found : nothing
# - $2 - default
# value to use for flags if compiler vendor cannot be determined (by
# default, "")
#
# NOTE: These macros depend on AX_APPEND_FLAG.
# - $3 - action-if-found
# action to take if the compiler vendor has been successfully
# determined (by default, add the appropriate compiler flags to
# shellvar)
#
# - $4 - action-if-not-found
# action to take if the compiler vendor has not been determined or
# is unknown (by default, add the default flags, or "" if not
# specified, to shellvar)
#
# These macros use AX_COMPILER_VENDOR to determine which flags should be
# returned for a given compiler. Not all compilers currently have flags
# defined for them; patches are welcome. If need be, compiler flags may
# be made language-dependent: use a construct like the following:
#
# [vendor_name], [m4_if(_AC_LANG_PREFIX,[C], VAR="--relevant-c-flags",dnl
# m4_if(_AC_LANG_PREFIX,[CXX], VAR="--relevant-c++-flags",dnl
# m4_if(_AC_LANG_PREFIX,[FC], VAR="--relevant-fortran-flags",dnl
# VAR="$2"; FOUND="no")))],
#
# Note: These macros also depend on AX_PREPEND_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2010 Rhys Ulerich <rhys.ulerich@gmail.com>
# Copyright (c) 2018 John Zaitseff <J.Zaitseff@zap.org.au>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@ -58,65 +79,80 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 16
#serial 25
AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl
AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
VAR,[VAR="no, unknown"
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-warn all % -warn all" dnl Intel
"-pedantic % -Wall" dnl GCC
"-xstrconst % -v" dnl Solaris C
"-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
"-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
"-ansi -ansiE % -fullwarn" dnl IRIX
"+ESlit % +w1" dnl HP-UX C
"-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
"-h conform % -h msglevel 2" dnl Cray C (Unicos)
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
])
AS_VAR_POPDEF([FLAGS])dnl
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;;
*) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AC_DEFUN([AX_FLAGS_WARN_ALL], [
AX_REQUIRE_DEFINED([AX_PREPEND_FLAG])dnl
AC_REQUIRE([AX_COMPILER_VENDOR])dnl
AS_VAR_PUSHDEF([FLAGS], [m4_default($1,_AC_LANG_PREFIX[]FLAGS)])dnl
AS_VAR_PUSHDEF([VAR], [ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
AS_VAR_PUSHDEF([FOUND], [ac_save_[]_AC_LANG_ABBREV[]flags_warn_all_found])dnl
AC_CACHE_CHECK([FLAGS for most reasonable warnings], VAR, [
VAR=""
FOUND="yes"
dnl Cases are listed in the order found in ax_compiler_vendor.m4
AS_CASE("$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor",
[intel], [VAR="-w2"],
[ibm], [VAR="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd"],
[pathscale], [],
[clang], [VAR="-Wall"],
[cray], [VAR="-h msglevel 2"],
[fujitsu], [],
[sdcc], [],
[sx], [VAR="-pvctl[,]fullmsg"],
[portland], [],
[gnu], [VAR="-Wall"],
[sun], [VAR="-v"],
[hp], [VAR="+w1"],
[dec], [VAR="-verbose -w0 -warnprotos"],
[borland], [],
[comeau], [],
[kai], [],
[lcc], [],
[sgi], [VAR="-fullwarn"],
[microsoft], [],
[metrowerks], [],
[watcom], [],
[tcc], [],
[unknown], [
VAR="$2"
FOUND="no"
],
[
AC_MSG_WARN([Unknown compiler vendor returned by [AX_COMPILER_VENDOR]])
VAR="$2"
FOUND="no"
]
)
AS_IF([test "x$FOUND" = "xyes"], [dnl
m4_default($3, [AS_IF([test "x$VAR" != "x"], [AX_PREPEND_FLAG([$VAR], [FLAGS])])])
], [dnl
m4_default($4, [m4_ifval($2, [AX_PREPEND_FLAG([$VAR], [FLAGS])], [true])])
])dnl
])dnl
AS_VAR_POPDEF([FOUND])dnl
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])dnl AX_FLAGS_WARN_ALL
dnl implementation tactics:
dnl the for-argument contains a list of options. The first part of
dnl these does only exist to detect the compiler - usually it is
dnl a global option to enable -ansi or -extrawarnings. All other
dnl compilers will fail about it. That was needed since a lot of
dnl compilers will give false positives for some option-syntax
dnl like -Woption or -Xoption as they think of it is a pass-through
dnl to later compile stages or something. The "%" is used as a
dnl delimiter. A non-option comment can be given after "%%" marks
dnl which will be shown but not added to the respective C/CXXFLAGS.
AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([C])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C])
])
AC_DEFUN([AX_CFLAGS_WARN_ALL], [dnl
AC_LANG_PUSH([C])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C])
])dnl
AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([C++])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C++])
])
AC_DEFUN([AX_CXXFLAGS_WARN_ALL], [dnl
AC_LANG_PUSH([C++])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C++])
])dnl
AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([Fortran])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([Fortran])
])
AC_DEFUN([AX_FCFLAGS_WARN_ALL], [dnl
AC_LANG_PUSH([Fortran])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([Fortran])
])dnl

View File

@ -8,15 +8,30 @@
#
# DESCRIPTION
#
# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
# watcom, etc. The vendor is returned in the cache variable
# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
# Determine the vendor of the C, C++ or Fortran compiler. The vendor is
# returned in the cache variable $ax_cv_c_compiler_vendor for C,
# $ax_cv_cxx_compiler_vendor for C++ or $ax_cv_fc_compiler_vendor for
# (modern) Fortran. The value is one of "intel", "ibm", "pathscale",
# "clang" (LLVM), "cray", "fujitsu", "sdcc", "sx", "nvhpc" (NVIDIA HPC
# Compiler), "portland" (PGI), "gnu" (GCC), "sun" (Oracle Developer
# Studio), "hp", "dec", "borland", "comeau", "kai", "lcc", "sgi",
# "microsoft", "metrowerks", "watcom", "tcc" (Tiny CC) or "unknown" (if
# the compiler cannot be determined).
#
# To check for a Fortran compiler, you must first call AC_FC_PP_SRCEXT
# with an appropriate preprocessor-enabled extension. For example:
#
# AC_LANG_PUSH([Fortran])
# AC_PROG_FC
# AC_FC_PP_SRCEXT([F])
# AX_COMPILER_VENDOR
# AC_LANG_POP([Fortran])
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2008 Matteo Frigo
# Copyright (c) 2018-19 John Zaitseff <J.Zaitseff@zap.org.au>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@ -44,45 +59,61 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 17
#serial 32
AC_DEFUN([AX_COMPILER_VENDOR],
[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
dnl Please add if possible support to ax_compiler_version.m4
[# note: don't check for gcc first since some other compilers define __GNUC__
vendors="intel: __ICC,__ECC,__INTEL_COMPILER
ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__
pathscale: __PATHCC__,__PATHSCALE__
clang: __clang__
cray: _CRAYC
fujitsu: __FUJITSU
sdcc: SDCC, __SDCC
gnu: __GNUC__
sun: __SUNPRO_C,__SUNPRO_CC
hp: __HP_cc,__HP_aCC
dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
borland: __BORLANDC__,__CODEGEARC__,__TURBOC__
comeau: __COMO__
kai: __KCC
lcc: __LCC__
sgi: __sgi,sgi
microsoft: _MSC_VER
metrowerks: __MWERKS__
watcom: __WATCOMC__
portland: __PGI
tcc: __TINYC__
unknown: UNKNOWN"
for ventest in $vendors; do
case $ventest in
*:) vendor=$ventest; continue ;;
*) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
esac
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
#if !($vencpp)
thisisanerror;
#endif
])], [break])
done
ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
])
])
AC_DEFUN([AX_COMPILER_VENDOR], [dnl
AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [dnl
dnl If you modify this list of vendors, please add similar support
dnl to ax_compiler_version.m4 if at all possible.
dnl
dnl Note: Do NOT check for GCC first since some other compilers
dnl define __GNUC__ to remain compatible with it. Compilers that
dnl are very slow to start (such as Intel) are listed first.
vendors="
intel: __ICC,__ECC,__INTEL_COMPILER
ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__,__ibmxl__
pathscale: __PATHCC__,__PATHSCALE__
clang: __clang__
cray: _CRAYC
fujitsu: __FUJITSU
sdcc: SDCC,__SDCC
sx: _SX
nvhpc: __NVCOMPILER
portland: __PGI
gnu: __GNUC__
sun: __SUNPRO_C,__SUNPRO_CC,__SUNPRO_F90,__SUNPRO_F95
hp: __HP_cc,__HP_aCC
dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
borland: __BORLANDC__,__CODEGEARC__,__TURBOC__
comeau: __COMO__
kai: __KCC
lcc: __LCC__
sgi: __sgi,sgi
microsoft: _MSC_VER
metrowerks: __MWERKS__
watcom: __WATCOMC__
tcc: __TINYC__
unknown: UNKNOWN
"
for ventest in $vendors; do
case $ventest in
*:)
vendor=$ventest
continue
;;
*)
vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")"
;;
esac
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
#if !($vencpp)
thisisanerror;
#endif
]])], [break])
done
ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
])
])dnl

View File

@ -1,36 +1,37 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
# https://www.gnu.org/software/autoconf-archive/ax_prepend_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
# AX_PREPEND_FLAG(FLAG, [FLAGS-VARIABLE])
#
# DESCRIPTION
#
# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
# added in between.
# FLAG is added to the front of the FLAGS-VARIABLE shell variable, with a
# space added in between.
#
# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
# FLAG.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
# NOTE: Implementation based on AX_APPEND_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
# Copyright (c) 2018 John Zaitseff <J.Zaitseff@zap.org.au>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 8
#serial 2
AC_DEFUN([AX_APPEND_FLAG],
AC_DEFUN([AX_PREPEND_FLAG],
[dnl
AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
@ -38,7 +39,7 @@ AS_VAR_SET_IF(FLAGS,[
AS_CASE([" AS_VAR_GET(FLAGS) "],
[*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
[
AS_VAR_APPEND(FLAGS,[" $1"])
FLAGS="$1 $FLAGS"
AC_RUN_LOG([: FLAGS="$FLAGS"])
])
],
@ -47,4 +48,4 @@ AS_VAR_SET_IF(FLAGS,[
AC_RUN_LOG([: FLAGS="$FLAGS"])
])
AS_VAR_POPDEF([FLAGS])dnl
])dnl AX_APPEND_FLAG
])dnl AX_PREPEND_FLAG

227
m4/libtool.m4 vendored
View File

@ -1,6 +1,7 @@
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
# Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
# Foundation, Inc.
# Written by Gordon Matzigkeit, 1996
#
# This file is free software; the Free Software Foundation gives
@ -31,7 +32,7 @@ m4_define([_LT_COPYING], [dnl
# along with this program. If not, see <http://www.gnu.org/licenses/>.
])
# serial 58 LT_INIT
# serial 59 LT_INIT
# LT_PREREQ(VERSION)
@ -181,6 +182,7 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
m4_require([_LT_CMD_RELOAD])dnl
m4_require([_LT_DECL_FILECMD])dnl
m4_require([_LT_CHECK_MAGIC_METHOD])dnl
m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
m4_require([_LT_CMD_OLD_ARCHIVE])dnl
@ -219,8 +221,8 @@ esac
ofile=libtool
can_build_shared=yes
# All known linkers require a '.a' archive for static linking (except MSVC,
# which needs '.lib').
# All known linkers require a '.a' archive for static linking (except MSVC and
# ICC, which need '.lib').
libext=a
with_gnu_ld=$lt_cv_prog_gnu_ld
@ -778,7 +780,7 @@ _LT_EOF
# if finds mixed CR/LF and LF-only lines. Since sed operates in
# text mode, it properly converts lines to CR/LF. This bash problem
# is reportedly fixed, but why not run on old versions too?
sed '$q' "$ltmain" >> "$cfgfile" \
$SED '$q' "$ltmain" >> "$cfgfile" \
|| (rm -f "$cfgfile"; exit 1)
mv -f "$cfgfile" "$ofile" ||
@ -1042,8 +1044,8 @@ int forced_loaded() { return 2;}
_LT_EOF
echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
$RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
cat > conftest.c << _LT_EOF
@ -1067,17 +1069,12 @@ _LT_EOF
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
darwin*) # darwin 5.x on
# if running on 10.5 or later, the deployment target defaults
# to the OS version, if on x86, and 10.4, the deployment
# target defaults to 10.4. Don't you love it?
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
10.[[012]][[,.]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
10.*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
darwin*)
case $MACOSX_DEPLOYMENT_TARGET,$host in
10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
esac
;;
esac
@ -1126,12 +1123,12 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES],
output_verbose_link_cmd=func_echo_all
_LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
_LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
m4_if([$1], [CXX],
[ if test yes != "$lt_cv_apple_cc_single_mod"; then
_LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
fi
],[])
else
@ -1245,7 +1242,8 @@ _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
# _LT_WITH_SYSROOT
# ----------------
AC_DEFUN([_LT_WITH_SYSROOT],
[AC_MSG_CHECKING([for sysroot])
[m4_require([_LT_DECL_SED])dnl
AC_MSG_CHECKING([for sysroot])
AC_ARG_WITH([sysroot],
[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
[Search for dependent libraries within DIR (or the compiler's sysroot
@ -1262,7 +1260,7 @@ case $with_sysroot in #(
fi
;; #(
/*)
lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
;; #(
no|'')
;; #(
@ -1292,7 +1290,7 @@ ia64-*-hpux*)
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*ELF-32*)
HPUX_IA64_MODE=32
;;
@ -1309,7 +1307,7 @@ ia64-*-hpux*)
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
if test yes = "$lt_cv_prog_gnu_ld"; then
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -melf32bsmip"
;;
@ -1321,7 +1319,7 @@ ia64-*-hpux*)
;;
esac
else
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -32"
;;
@ -1343,7 +1341,7 @@ mips64*-*linux*)
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
emul=elf
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
emul="${emul}32"
;;
@ -1351,7 +1349,7 @@ mips64*-*linux*)
emul="${emul}64"
;;
esac
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*MSB*)
emul="${emul}btsmip"
;;
@ -1359,7 +1357,7 @@ mips64*-*linux*)
emul="${emul}ltsmip"
;;
esac
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*N32*)
emul="${emul}n32"
;;
@ -1379,14 +1377,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# not appear in the list.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.o` in
case `$FILECMD conftest.o` in
*32-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
case `/usr/bin/file conftest.o` in
case `$FILECMD conftest.o` in
*x86-64*)
LD="${LD-ld} -m elf32_x86_64"
;;
@ -1454,7 +1452,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.o` in
case `$FILECMD conftest.o` in
*64-bit*)
case $lt_cv_prog_gnu_ld in
yes*)
@ -1493,9 +1491,22 @@ need_locks=$enable_libtool_lock
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
: ${AR_FLAGS=cru}
_LT_DECL([], [AR], [1], [The archiver])
_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
# Use ARFLAGS variable as AR's operation code to sync the variable naming with
# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
# higher priority because thats what people were doing historically (setting
# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
# variable obsoleted/removed.
test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
lt_ar_flags=$AR_FLAGS
_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
[Flags to create an archive])
AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
[lt_cv_ar_at_file=no
@ -1714,7 +1725,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
lt_cv_sys_max_cmd_len=8192;
;;
bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
# This has been around since 386BSD, at least. Likely further.
if test -x /sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
@ -1757,7 +1768,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
sysv5* | sco5v6* | sysv4.2uw2*)
kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
if test -n "$kargmax"; then
lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'`
else
lt_cv_sys_max_cmd_len=32768
fi
@ -2207,26 +2218,35 @@ m4_defun([_LT_CMD_STRIPLIB],
striplib=
old_striplib=
AC_MSG_CHECKING([whether stripping libraries is possible])
if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
test -z "$striplib" && striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
if test -z "$STRIP"; then
AC_MSG_RESULT([no])
else
# FIXME - insert some real tests, host_os isn't really good enough
case $host_os in
darwin*)
if test -n "$STRIP"; then
if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
case $host_os in
darwin*)
# FIXME - insert some real tests, host_os isn't really good enough
striplib="$STRIP -x"
old_striplib="$STRIP -S"
AC_MSG_RESULT([yes])
else
;;
freebsd*)
if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
;;
esac
;;
esac
fi
fi
_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
_LT_DECL([], [striplib], [1])
@ -2549,7 +2569,7 @@ cygwin* | mingw* | pw32* | cegcc*)
case $host_os in
cygwin*)
# Cygwin DLLs use 'cyg' prefix rather than 'lib'
soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
m4_if([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
;;
@ -2559,14 +2579,14 @@ m4_if([$1], [],[
;;
pw32*)
# pw32 DLLs use 'pw' prefix rather than 'lib'
library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
;;
esac
dynamic_linker='Win32 ld.exe'
;;
*,cl*)
# Native MSVC
*,cl* | *,icl*)
# Native MSVC or ICC
libname_spec='$name'
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='$libname.dll.lib'
@ -2585,7 +2605,7 @@ m4_if([$1], [],[
done
IFS=$lt_save_ifs
# Convert to MSYS style.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
;;
cygwin*)
# Convert to unix form, then to dos form, then back to unix form
@ -2622,7 +2642,7 @@ m4_if([$1], [],[
;;
*)
# Assume MSVC wrapper
# Assume MSVC and ICC wrapper
library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
dynamic_linker='Win32 ld.exe'
;;
@ -2655,7 +2675,7 @@ dgux*)
shlibpath_var=LD_LIBRARY_PATH
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
# DragonFly does not have aout. When/if they implement a new
# versioning mechanism, adjust this.
if test -x /usr/bin/objformat; then
@ -3457,7 +3477,7 @@ beos*)
bsdi[[45]]*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
lt_cv_file_magic_cmd='/usr/bin/file -L'
lt_cv_file_magic_cmd='$FILECMD -L'
lt_cv_file_magic_test_file=/shlib/libc.so
;;
@ -3491,14 +3511,14 @@ darwin* | rhapsody*)
lt_cv_deplibs_check_method=pass_all
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
case $host_cpu in
i*86 )
# Not sure whether the presence of OpenBSD here was a mistake.
# Let's accept both of them until this is cleared up.
lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
;;
esac
@ -3512,7 +3532,7 @@ haiku*)
;;
hpux10.20* | hpux11*)
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_cmd=$FILECMD
case $host_cpu in
ia64*)
lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
@ -3559,7 +3579,7 @@ netbsd*)
newos6*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=/usr/lib/libnls.so
;;
@ -3686,13 +3706,13 @@ else
mingw*) lt_bad_file=conftest.nm/nofile ;;
*) lt_bad_file=/dev/null ;;
esac
case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
*$lt_bad_file* | *'Invalid file or object type'*)
lt_cv_path_NM="$tmp_nm -B"
break 2
;;
*)
case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
*/dev/null*)
lt_cv_path_NM="$tmp_nm -p"
break 2
@ -3718,7 +3738,7 @@ else
# Let the user override the test.
else
AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
*COFF*)
DUMPBIN="$DUMPBIN -symbols -headers"
;;
@ -3958,7 +3978,7 @@ esac
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Gets list of data symbols to import.
lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
# Adjust the below global symbol transforms to fixup imported variables.
lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
@ -3976,20 +3996,20 @@ fi
# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="sed -n"\
lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
$lt_cdecl_hook\
" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
@ -4013,7 +4033,7 @@ for ac_symprfx in "" "_"; do
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Fake it for dumpbin and say T for any non-static function,
# D for any global variable and I for any imported variable.
# Also find C++ and __fastcall symbols from MSVC++,
# Also find C++ and __fastcall symbols from MSVC++ or ICC,
# which start with @ or ?.
lt_cv_sys_global_symbol_pipe="$AWK ['"\
" {last_section=section; section=\$ 3};"\
@ -4031,9 +4051,9 @@ for ac_symprfx in "" "_"; do
" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
" ' prfx=^$ac_symprfx]"
else
lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
fi
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
# Check to see that the pipe works correctly.
pipe_works=no
@ -4320,7 +4340,7 @@ m4_if([$1], [CXX], [
;;
esac
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
# FreeBSD uses GNU C++
;;
hpux9* | hpux10* | hpux11*)
@ -4403,7 +4423,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@ -4739,7 +4759,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
# Sun Fortran 8.3 passes all unrecognized flags to the linker
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@ -4922,7 +4942,7 @@ m4_if([$1], [CXX], [
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
;;
pw32*)
@ -4930,7 +4950,7 @@ m4_if([$1], [CXX], [
;;
cygwin* | mingw* | cegcc*)
case $cc_basename in
cl*)
cl* | icl*)
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
;;
*)
@ -4987,15 +5007,15 @@ dnl Note also adjust exclude_expsyms for C++ above.
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
# FIXME: the MSVC++ port hasn't been tested in a loooong time
# FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# Microsoft Visual C++ or Intel C++ Compiler.
if test yes != "$GCC"; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++)
# we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes
;;
openbsd* | bitrig*)
@ -5047,7 +5067,7 @@ dnl Note also adjust exclude_expsyms for C++ above.
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
supports_anon_versioning=no
case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
*GNU\ gold*) supports_anon_versioning=yes ;;
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
*\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
@ -5159,6 +5179,7 @@ _LT_EOF
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
interix[[3-9]]*)
@ -5173,7 +5194,7 @@ _LT_EOF
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
@ -5216,7 +5237,7 @@ _LT_EOF
_LT_TAGVAR(compiler_needs_object, $1)=yes
;;
esac
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*) # Sun C 5.9
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
@ -5228,7 +5249,7 @@ _LT_EOF
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
@ -5244,7 +5265,7 @@ _LT_EOF
_LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
fi
@ -5376,7 +5397,7 @@ _LT_EOF
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
aix_use_runtimelinking=no
@ -5559,12 +5580,12 @@ _LT_EOF
cygwin* | mingw* | pw32* | cegcc*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# Microsoft Visual C++ or Intel C++ Compiler.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
case $cc_basename in
cl*)
# Native MSVC
cl* | icl*)
# Native MSVC or ICC
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
@ -5605,7 +5626,7 @@ _LT_EOF
fi'
;;
*)
# Assume MSVC wrapper
# Assume MSVC and ICC wrapper
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Tell ltmain to make .lib files, not .a files.
@ -5653,7 +5674,7 @@ _LT_EOF
;;
# FreeBSD 3 and greater uses gcc -shared to do shared libraries.
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
@ -5864,6 +5885,7 @@ _LT_EOF
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
osf3*)
@ -6634,8 +6656,8 @@ if test yes != "$_lt_caught_CXX_error"; then
cygwin* | mingw* | pw32* | cegcc*)
case $GXX,$cc_basename in
,cl* | no,cl*)
# Native MSVC
,cl* | no,cl* | ,icl* | no,icl*)
# Native MSVC or ICC
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
@ -6733,6 +6755,7 @@ if test yes != "$_lt_caught_CXX_error"; then
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
dgux*)
@ -6763,7 +6786,7 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
# FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
# conventions
_LT_TAGVAR(ld_shlibs, $1)=yes
@ -6900,7 +6923,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
irix5* | irix6*)
case $cc_basename in
@ -7040,13 +7063,13 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
;;
*)
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
@ -8192,6 +8215,14 @@ _LT_DECL([], [DLLTOOL], [1], [DLL creation program])
AC_SUBST([DLLTOOL])
])
# _LT_DECL_FILECMD
# ----------------
# Check for a file(cmd) program that can be used to detect file type and magic
m4_defun([_LT_DECL_FILECMD],
[AC_CHECK_TOOL([FILECMD], [file], [:])
_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
])# _LD_DECL_FILECMD
# _LT_DECL_SED
# ------------
# Check for a fully-functional sed program, that truncates

4
m4/ltoptions.m4 vendored
View File

@ -1,7 +1,7 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
# Foundation, Inc.
# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
# Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives

2
m4/ltsugar.m4 vendored
View File

@ -1,6 +1,6 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#

13
m4/ltversion.m4 vendored
View File

@ -1,6 +1,7 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
# Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
@ -9,15 +10,15 @@
# @configure_input@
# serial 4179 ltversion.m4
# serial 4245 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])
m4_define([LT_PACKAGE_VERSION], [2.4.7])
m4_define([LT_PACKAGE_REVISION], [2.4.7])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
[macro_version='2.4.7'
macro_revision='2.4.7'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

4
m4/lt~obsolete.m4 vendored
View File

@ -1,7 +1,7 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
# Foundation, Inc.
# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
# Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -91,7 +91,6 @@ target_triplet = @target@
subdir = man
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_append_flag.m4 \
$(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
@ -100,6 +99,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_prepend_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
@ -182,8 +182,9 @@ CCASDEPMODE = @CCASDEPMODE@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
@ -198,9 +199,11 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
FGREP = @FGREP@
FILECMD = @FILECMD@
GREP = @GREP@
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@
@ -239,6 +242,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
READELF = @READELF@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
SED = @SED@
SET_MAKE = @SET_MAKE@
@ -294,6 +298,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -304,6 +309,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
tmake_file = @tmake_file@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
top_build_prefix = @top_build_prefix@
@ -399,7 +405,6 @@ ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify

View File

@ -363,7 +363,7 @@ typedef struct {
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;

View File

@ -52,7 +52,7 @@ ml="ml"
safeseh="-safeseh"
output=
libpaths=
libversion=7
libversion=8
verbose=
while [ $# -gt 0 ]
@ -165,24 +165,24 @@ do
shift 1
;;
-I)
p=$(cygpath -m $2)
args="$args -I$p"
includes="$includes -I$p"
p=$(cygpath -ma "$2")
args="$args -I\"$p\""
includes="$includes -I\"$p\""
shift 2
;;
-I*)
p=$(cygpath -m ${1#-I})
args="$args -I$p"
includes="$includes -I$p"
p=$(cygpath -ma "${1#-I}")
args="$args -I\"$p\""
includes="$includes -I\"$p\""
shift 1
;;
-L)
p=$(cygpath -m $2)
p=$(cygpath -ma $2)
linkargs="$linkargs -LIBPATH:$p"
shift 2
;;
-L*)
p=$(cygpath -m ${1#-L})
p=$(cygpath -ma ${1#-L})
linkargs="$linkargs -LIBPATH:$p"
shift 1
;;
@ -256,12 +256,12 @@ do
shift 2
;;
*.S)
src=$1
src="$(cygpath -ma $1)"
assembly="true"
shift 1
;;
*.c)
args="$args $1"
args="$args $(cygpath -ma $1)"
shift 1
;;
*)
@ -312,7 +312,7 @@ if [ -n "$assembly" ]; then
echo "$cl -nologo -EP $includes $defines $src > $ppsrc"
fi
"$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $?
eval "\"$cl\" -nologo -EP $includes $defines $src" > $ppsrc || exit $?
output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')"
if [ $ml = "armasm" ]; then
args="-nologo -g -oldit $armasm_output $ppsrc -errorReport:prompt"

View File

@ -27,9 +27,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <ffi.h>
#include <ffi_common.h>
#include "internal.h"
#ifdef _M_ARM64
#ifdef _WIN32
#include <windows.h> /* FlushInstructionCache */
#endif
#include <tramp.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. */
@ -62,6 +63,9 @@ struct call_context
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#ifdef HAVE_PTRAUTH
#include <ptrauth.h>
#endif
#include <mach/vm_param.h>
#endif
@ -78,7 +82,7 @@ ffi_clear_cache (void *start, void *end)
sys_icache_invalidate (start, (char *)end - (char *)start);
#elif defined (__GNUC__)
__builtin___clear_cache (start, end);
#elif defined (_M_ARM64)
#elif defined (_WIN32)
FlushInstructionCache(GetCurrentProcess(), start, (char*)end - (char*)start);
#else
#error "Missing builtin to flush instruction cache"
@ -244,13 +248,18 @@ is_vfp_type (const ffi_type *ty)
state.
The terse state variable names match the names used in the AARCH64
PCS. */
PCS.
The struct area is allocated downwards from the top of the argument
area. It is used to hold copies of structures passed by value that are
bigger than 16 bytes. */
struct arg_state
{
unsigned ngrn; /* Next general-purpose register number. */
unsigned nsrn; /* Next vector register number. */
size_t nsaa; /* Next stack offset. */
size_t next_struct_area; /* Place to allocate big structs. */
#if defined (__APPLE__)
unsigned allocating_variadic;
@ -259,11 +268,12 @@ struct arg_state
/* Initialize a procedure call argument marshalling state. */
static void
arg_init (struct arg_state *state)
arg_init (struct arg_state *state, size_t size)
{
state->ngrn = 0;
state->nsrn = 0;
state->nsaa = 0;
state->next_struct_area = size;
#if defined (__APPLE__)
state->allocating_variadic = 0;
#endif
@ -285,37 +295,83 @@ allocate_to_stack (struct arg_state *state, void *stack,
if (alignment < 8)
alignment = 8;
#endif
nsaa = FFI_ALIGN (nsaa, alignment);
state->nsaa = nsaa + size;
return (char *)stack + nsaa;
}
/* Allocate and copy a structure that is passed by value on the stack and
return a pointer to it. */
static void *
allocate_and_copy_struct_to_stack (struct arg_state *state, void *stack,
size_t alignment, size_t size, void *value)
{
size_t dest = state->next_struct_area - size;
/* Round down to the natural alignment of the value. */
dest = FFI_ALIGN_DOWN (dest, alignment);
state->next_struct_area = dest;
return memcpy ((char *) stack + dest, value, size);
}
static ffi_arg
extend_integer_type (void *source, int type)
{
switch (type)
{
case FFI_TYPE_UINT8:
return *(UINT8 *) source;
{
UINT8 u8;
memcpy (&u8, source, sizeof (u8));
return u8;
}
case FFI_TYPE_SINT8:
return *(SINT8 *) source;
{
SINT8 s8;
memcpy (&s8, source, sizeof (s8));
return s8;
}
case FFI_TYPE_UINT16:
return *(UINT16 *) source;
{
UINT16 u16;
memcpy (&u16, source, sizeof (u16));
return u16;
}
case FFI_TYPE_SINT16:
return *(SINT16 *) source;
{
SINT16 s16;
memcpy (&s16, source, sizeof (s16));
return s16;
}
case FFI_TYPE_UINT32:
return *(UINT32 *) source;
{
UINT32 u32;
memcpy (&u32, source, sizeof (u32));
return u32;
}
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
return *(SINT32 *) source;
{
SINT32 s32;
memcpy (&s32, source, sizeof (s32));
return s32;
}
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
return *(UINT64 *) source;
break;
{
UINT64 u64;
memcpy (&u64, source, sizeof (u64));
return u64;
}
case FFI_TYPE_POINTER:
return *(uintptr_t *) source;
{
uintptr_t uptr;
memcpy (&uptr, source, sizeof (uptr));
return uptr;
}
default:
abort();
}
@ -561,6 +617,14 @@ ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
cif->aarch64_nfixedargs = nfixedargs;
return status;
}
#else
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs)
{
ffi_status status = ffi_prep_cif_machdep (cif);
cif->flags |= AARCH64_FLAG_VARARG;
return status;
}
#endif /* __APPLE__ */
extern void ffi_call_SYSV (struct call_context *context, void *frame,
@ -577,7 +641,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
void *stack, *frame, *rvalue;
struct arg_state state;
size_t stack_bytes, rtype_size, rsize;
int i, nargs, flags;
int i, nargs, flags, isvariadic = 0;
ffi_type *rtype;
flags = cif->flags;
@ -585,6 +649,12 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
rtype_size = rtype->size;
stack_bytes = cif->bytes;
if (flags & AARCH64_FLAG_VARARG)
{
isvariadic = 1;
flags &= ~AARCH64_FLAG_VARARG;
}
/* If the target function returns a structure via hidden pointer,
then we cannot allow a null rvalue. Otherwise, mash a null
rvalue to void return type. */
@ -599,19 +669,21 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
else if (flags & AARCH64_RET_NEED_COPY)
rsize = 16;
/* Allocate consectutive stack for everything we'll need. */
context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize);
/* Allocate consectutive stack for everything we'll need.
The frame uses 40 bytes for: lr, fp, rvalue, flags, sp */
context = alloca (sizeof(struct call_context) + stack_bytes + 40 + rsize);
stack = context + 1;
frame = (void*)((uintptr_t)stack + (uintptr_t)stack_bytes);
rvalue = (rsize ? (void*)((uintptr_t)frame + 32) : orig_rvalue);
rvalue = (rsize ? (void*)((uintptr_t)frame + 40) : orig_rvalue);
arg_init (&state);
arg_init (&state, stack_bytes);
for (i = 0, nargs = cif->nargs; i < nargs; i++)
{
ffi_type *ty = cif->arg_types[i];
size_t s = ty->size;
void *a = avalue[i];
int h, t;
void *dest;
t = ty->type;
switch (t)
@ -659,47 +731,44 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
{
void *dest;
h = is_vfp_type (ty);
if (h)
{
int elems = 4 - (h & 3);
#ifdef _M_ARM64 /* for handling armasm calling convention */
if (cif->is_variadic)
{
if (state.ngrn + elems <= N_X_ARG_REG)
{
dest = &context->x[state.ngrn];
state.ngrn += elems;
extend_hfa_type(dest, a, h);
break;
}
state.nsrn = N_X_ARG_REG;
dest = allocate_to_stack(&state, stack, ty->alignment, s);
}
else
{
#endif /* for handling armasm calling convention */
if (state.nsrn + elems <= N_V_ARG_REG)
{
dest = &context->v[state.nsrn];
state.nsrn += elems;
extend_hfa_type (dest, a, h);
break;
}
state.nsrn = N_V_ARG_REG;
dest = allocate_to_stack (&state, stack, ty->alignment, s);
#ifdef _M_ARM64 /* for handling armasm calling convention */
}
#endif /* for handling armasm calling convention */
int elems = 4 - (h & 3);
if (cif->abi == FFI_WIN64 && isvariadic)
{
if (state.ngrn + elems <= N_X_ARG_REG)
{
dest = &context->x[state.ngrn];
state.ngrn += elems;
extend_hfa_type(dest, a, h);
break;
}
state.nsrn = N_X_ARG_REG;
dest = allocate_to_stack(&state, stack, ty->alignment, s);
}
else
{
if (state.nsrn + elems <= N_V_ARG_REG)
{
dest = &context->v[state.nsrn];
state.nsrn += elems;
extend_hfa_type (dest, a, h);
break;
}
state.nsrn = N_V_ARG_REG;
dest = allocate_to_stack (&state, stack, ty->alignment, s);
}
}
else if (s > 16)
{
/* If the argument is a composite type that is larger than 16
bytes, then the argument has been copied to memory, and
bytes, then the argument is copied to memory, and
the argument is replaced by a pointer to the copy. */
a = &avalue[i];
dest = allocate_and_copy_struct_to_stack (&state, stack,
ty->alignment, s,
avalue[i]);
a = &dest;
t = FFI_TYPE_POINTER;
s = sizeof (void *);
goto do_pointer;
@ -756,6 +825,8 @@ ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
#if FFI_CLOSURES
#ifdef FFI_GO_CLOSURES
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
@ -769,6 +840,10 @@ ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
extern void ffi_closure_SYSV (void) FFI_HIDDEN;
extern void ffi_closure_SYSV_V (void) FFI_HIDDEN;
#if defined(FFI_EXEC_STATIC_TRAMP)
extern void ffi_closure_SYSV_alt (void) FFI_HIDDEN;
extern void ffi_closure_SYSV_V_alt (void) FFI_HIDDEN;
#endif
ffi_status
ffi_prep_closure_loc (ffi_closure *closure,
@ -777,22 +852,25 @@ ffi_prep_closure_loc (ffi_closure *closure,
void *user_data,
void *codeloc)
{
if (cif->abi != FFI_SYSV)
if (cif->abi != FFI_SYSV && cif->abi != FFI_WIN64)
return FFI_BAD_ABI;
void (*start)(void);
if (cif->flags & AARCH64_FLAG_ARG_V)
start = ffi_closure_SYSV_V;
else
start = ffi_closure_SYSV;
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
# ifdef __MACH__
# ifdef HAVE_PTRAUTH
codeloc = ptrauth_auth_data(codeloc, ptrauth_key_function_pointer, 0);
# endif
void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
config[0] = closure;
config[1] = start;
#endif
# endif
#else
static const unsigned char trampoline[16] = {
0x90, 0x00, 0x00, 0x58, /* ldr x16, tramp+16 */
@ -800,22 +878,39 @@ ffi_prep_closure_loc (ffi_closure *closure,
0x00, 0x02, 0x1f, 0xd6 /* br x16 */
};
char *tramp = closure->tramp;
# if defined(FFI_EXEC_STATIC_TRAMP)
if (ffi_tramp_is_present(closure))
{
/* Initialize the static trampoline's parameters. */
if (start == ffi_closure_SYSV_V)
start = ffi_closure_SYSV_V_alt;
else
start = ffi_closure_SYSV_alt;
ffi_tramp_set_parms (closure->ftramp, start, closure);
goto out;
}
# endif
/* Initialize the dynamic trampoline. */
memcpy (tramp, trampoline, sizeof(trampoline));
*(UINT64 *)(tramp + 16) = (uintptr_t)start;
ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
/* Also flush the cache for code mapping. */
#ifdef _M_ARM64
# ifdef _WIN32
// Not using dlmalloc.c for Windows ARM64 builds
// so calling ffi_data_to_code_pointer() isn't necessary
unsigned char *tramp_code = tramp;
#else
# else
unsigned char *tramp_code = ffi_data_to_code_pointer (tramp);
#endif
# endif
ffi_clear_cache (tramp_code, tramp_code + FFI_TRAMPOLINE_SIZE);
# if defined(FFI_EXEC_STATIC_TRAMP)
out:
# endif
#endif
closure->cif = cif;
@ -835,7 +930,7 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif,
{
void (*start)(void);
if (cif->abi != FFI_SYSV)
if (cif->abi != FFI_SYSV && cif->abi != FFI_WIN64)
return FFI_BAD_ABI;
if (cif->flags & AARCH64_FLAG_ARG_V)
@ -875,10 +970,17 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
void *stack, void *rvalue, void *struct_rvalue)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
int i, h, nargs, flags;
int i, h, nargs, flags, isvariadic = 0;
struct arg_state state;
arg_init (&state);
arg_init (&state, cif->bytes);
flags = cif->flags;
if (flags & AARCH64_FLAG_VARARG)
{
isvariadic = 1;
flags &= ~AARCH64_FLAG_VARARG;
}
for (i = 0, nargs = cif->nargs; i < nargs; i++)
{
@ -914,14 +1016,13 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
if (h)
{
n = 4 - (h & 3);
#ifdef _M_ARM64 /* for handling armasm calling convention */
if (cif->is_variadic)
if (cif->abi == FFI_WIN64 && isvariadic)
{
if (state.ngrn + n <= N_X_ARG_REG)
{
void *reg = &context->x[state.ngrn];
state.ngrn += (unsigned int)n;
/* Eeek! We need a pointer to the structure, however the
homogeneous float elements are being passed in individual
registers, therefore for float and double the structure
@ -941,7 +1042,6 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
}
else
{
#endif /* for handling armasm calling convention */
if (state.nsrn + n <= N_V_ARG_REG)
{
void *reg = &context->v[state.nsrn];
@ -954,17 +1054,24 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
avalue[i] = allocate_to_stack(&state, stack,
ty->alignment, s);
}
#ifdef _M_ARM64 /* for handling armasm calling convention */
}
#endif /* for handling armasm calling convention */
}
else if (s > 16)
{
/* Replace Composite type of size greater than 16 with a
pointer. */
#ifdef __ILP32__
UINT64 avalue_tmp;
memcpy (&avalue_tmp,
allocate_int_to_reg_or_stack (context, &state,
stack, sizeof (void *)),
sizeof (UINT64));
avalue[i] = (void *)(UINT32)avalue_tmp;
#else
avalue[i] = *(void **)
allocate_int_to_reg_or_stack (context, &state, stack,
sizeof (void *));
#endif
}
else
{
@ -997,7 +1104,6 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
#endif
}
flags = cif->flags;
if (flags & AARCH64_RET_IN_MEM)
rvalue = struct_rvalue;
@ -1006,4 +1112,18 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
return flags;
}
#if defined(FFI_EXEC_STATIC_TRAMP)
void *
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
{
extern void *trampoline_code_table;
*tramp_size = AARCH64_TRAMP_SIZE;
*map_size = AARCH64_TRAMP_MAP_SIZE;
return &trampoline_code_table;
}
#endif
#endif /* FFI_CLOSURES */
#endif /* (__aarch64__) || defined(__arm64__)|| defined (_M_ARM64)*/

View File

@ -32,7 +32,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define FFI_SIZEOF_JAVA_RAW 4
typedef unsigned long long ffi_arg;
typedef signed long long ffi_sarg;
#elif defined(_M_ARM64)
#elif defined(_WIN32)
#define FFI_SIZEOF_ARG 8
typedef unsigned long long ffi_arg;
typedef signed long long ffi_sarg;
@ -45,8 +45,13 @@ typedef enum ffi_abi
{
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_WIN64,
FFI_LAST_ABI,
#if defined(_WIN32)
FFI_DEFAULT_ABI = FFI_WIN64
#else
FFI_DEFAULT_ABI = FFI_SYSV
#endif
} ffi_abi;
#endif
@ -69,22 +74,22 @@ typedef enum ffi_abi
#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
#endif
#ifdef _M_ARM64
#ifdef _WIN32
#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic
#endif
#define FFI_TARGET_SPECIFIC_VARIADIC
/* ---- Internal ---- */
#if defined (__APPLE__)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
#elif !defined(_M_ARM64)
#elif !defined(_WIN32)
/* iOS and Windows reserve x18 for the system. Disable Go closures until
a new static chain is chosen. */
#define FFI_GO_CLOSURES 1
#endif
#ifndef _M_ARM64
#ifndef _WIN32
/* No complex type on Windows */
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif

View File

@ -61,7 +61,40 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define AARCH64_FLAG_ARG_V_BIT 7
#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT)
#define AARCH64_FLAG_VARARG (1 << 8)
#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)
#if defined(FFI_EXEC_STATIC_TRAMP)
/*
* For the trampoline code table mapping, a mapping size of 16K is chosen to
* cover the base page sizes of 4K and 16K.
*/
#define AARCH64_TRAMP_MAP_SHIFT 14
#define AARCH64_TRAMP_MAP_SIZE (1 << AARCH64_TRAMP_MAP_SHIFT)
#define AARCH64_TRAMP_SIZE 32
#endif
/* Helpers for writing assembly compatible with arm ptr auth */
#ifdef LIBFFI_ASM
#ifdef HAVE_PTRAUTH
#define SIGN_LR pacibsp
#define SIGN_LR_WITH_REG(x) pacib lr, x
#define AUTH_LR_AND_RET retab
#define AUTH_LR_WITH_REG(x) autib lr, x
#define BRANCH_AND_LINK_TO_REG blraaz
#define BRANCH_TO_REG braaz
#else
#define SIGN_LR
#define SIGN_LR_WITH_REG(x)
#define AUTH_LR_AND_RET ret
#define AUTH_LR_WITH_REG(x)
#define BRANCH_AND_LINK_TO_REG blr
#define BRANCH_TO_REG br
#endif
#endif

View File

@ -78,9 +78,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
cfi_startproc
CNAME(ffi_call_SYSV):
/* Sign the lr with x1 since that is where it will be stored */
SIGN_LR_WITH_REG(x1)
/* Use a stack frame allocated by our caller. */
cfi_def_cfa(x1, 32);
#if defined(HAVE_PTRAUTH) && defined(__APPLE__)
/* darwin's libunwind assumes that the cfa is the sp and that's the data
* used to sign the lr. In order to allow unwinding through this
* function it is necessary to point the cfa at the signing register.
*/
cfi_def_cfa(x1, 0);
#else
cfi_def_cfa(x1, 40);
#endif
stp x29, x30, [x1]
mov x9, sp
str x9, [x1, #32]
mov x29, x1
mov sp, x0
cfi_def_cfa_register(x29)
@ -111,13 +124,15 @@ CNAME(ffi_call_SYSV):
/* Deallocate the context, leaving the stacked arguments. */
add sp, sp, #CALL_CONTEXT_SIZE
blr x9 /* call fn */
BRANCH_AND_LINK_TO_REG x9 /* call fn */
ldp x3, x4, [x29, #16] /* reload rvalue and flags */
/* Partially deconstruct the stack frame. */
mov sp, x29
ldr x9, [x29, #32]
mov sp, x9
cfi_def_cfa_register (sp)
mov x2, x29 /* Preserve for auth */
ldp x29, x30, [x29]
/* Save the return value as directed. */
@ -131,71 +146,76 @@ CNAME(ffi_call_SYSV):
and therefore we want to extend to 64 bits; these types
have two consecutive entries allocated for them. */
.align 4
0: ret /* VOID */
0: b 99f /* VOID */
nop
1: str x0, [x3] /* INT64 */
ret
b 99f
2: stp x0, x1, [x3] /* INT128 */
ret
b 99f
3: brk #1000 /* UNUSED */
ret
b 99f
4: brk #1000 /* UNUSED */
ret
b 99f
5: brk #1000 /* UNUSED */
ret
b 99f
6: brk #1000 /* UNUSED */
ret
b 99f
7: brk #1000 /* UNUSED */
ret
b 99f
8: st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */
ret
b 99f
9: st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */
ret
b 99f
10: stp s0, s1, [x3] /* S2 */
ret
b 99f
11: str s0, [x3] /* S1 */
ret
b 99f
12: st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */
ret
b 99f
13: st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */
ret
b 99f
14: stp d0, d1, [x3] /* D2 */
ret
b 99f
15: str d0, [x3] /* D1 */
ret
b 99f
16: str q3, [x3, #48] /* Q4 */
nop
17: str q2, [x3, #32] /* Q3 */
nop
18: stp q0, q1, [x3] /* Q2 */
ret
b 99f
19: str q0, [x3] /* Q1 */
ret
b 99f
20: uxtb w0, w0 /* UINT8 */
str x0, [x3]
21: ret /* reserved */
21: b 99f /* reserved */
nop
22: uxth w0, w0 /* UINT16 */
str x0, [x3]
23: ret /* reserved */
23: b 99f /* reserved */
nop
24: mov w0, w0 /* UINT32 */
str x0, [x3]
25: ret /* reserved */
25: b 99f /* reserved */
nop
26: sxtb x0, w0 /* SINT8 */
str x0, [x3]
27: ret /* reserved */
27: b 99f /* reserved */
nop
28: sxth x0, w0 /* SINT16 */
str x0, [x3]
29: ret /* reserved */
29: b 99f /* reserved */
nop
30: sxtw x0, w0 /* SINT32 */
str x0, [x3]
31: ret /* reserved */
31: b 99f /* reserved */
nop
/* Return now that result has been populated. */
99:
AUTH_LR_WITH_REG(x2)
ret
cfi_endproc
.globl CNAME(ffi_call_SYSV)
@ -205,6 +225,8 @@ CNAME(ffi_call_SYSV):
.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
#endif
#if FFI_CLOSURES
/* ffi_closure_SYSV
Closure invocation glue. This is the low level code invoked directly by
@ -224,6 +246,7 @@ CNAME(ffi_call_SYSV):
.align 4
CNAME(ffi_closure_SYSV_V):
cfi_startproc
SIGN_LR
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
@ -247,6 +270,7 @@ CNAME(ffi_closure_SYSV_V):
.align 4
cfi_startproc
CNAME(ffi_closure_SYSV):
SIGN_LR
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
@ -263,7 +287,9 @@ CNAME(ffi_closure_SYSV):
/* Load ffi_closure_inner arguments. */
ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */
ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */
#ifdef FFI_GO_CLOSURES
.Ldo_closure:
#endif
add x3, sp, #16 /* load context */
add x4, sp, #ffi_closure_SYSV_FS /* load stack */
add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
@ -346,7 +372,7 @@ CNAME(ffi_closure_SYSV):
cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
cfi_restore (x29)
cfi_restore (x30)
ret
AUTH_LR_AND_RET
cfi_endproc
.globl CNAME(ffi_closure_SYSV)
@ -356,6 +382,76 @@ CNAME(ffi_closure_SYSV):
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
#endif
#if defined(FFI_EXEC_STATIC_TRAMP)
.align 4
CNAME(ffi_closure_SYSV_V_alt):
/* See the comments above trampoline_code_table. */
ldr x17, [sp, #8] /* Load closure in x17 */
add sp, sp, #16 /* Restore the stack */
b CNAME(ffi_closure_SYSV_V)
.globl CNAME(ffi_closure_SYSV_V_alt)
FFI_HIDDEN(CNAME(ffi_closure_SYSV_V_alt))
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV_V_alt), #function
.size CNAME(ffi_closure_SYSV_V_alt), . - CNAME(ffi_closure_SYSV_V_alt)
#endif
.align 4
CNAME(ffi_closure_SYSV_alt):
/* See the comments above trampoline_code_table. */
ldr x17, [sp, #8] /* Load closure in x17 */
add sp, sp, #16 /* Restore the stack */
b CNAME(ffi_closure_SYSV)
.globl CNAME(ffi_closure_SYSV_alt)
FFI_HIDDEN(CNAME(ffi_closure_SYSV_alt))
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV_alt), #function
.size CNAME(ffi_closure_SYSV_alt), . - CNAME(ffi_closure_SYSV_alt)
#endif
/*
* Below is the definition of the trampoline code table. Each element in
* the code table is a trampoline.
*/
/*
* The trampoline uses register x17. It saves the original value of x17 on
* the stack.
*
* The trampoline has two parameters - target code to jump to and data for
* the target code. The trampoline extracts the parameters from its parameter
* block (see tramp_table_map()). The trampoline saves the data address on
* the stack. Finally, it jumps to the target code.
*
* The target code can choose to:
*
* - restore the value of x17
* - load the data address in a register
* - restore the stack pointer to what it was when the trampoline was invoked.
*/
.align AARCH64_TRAMP_MAP_SHIFT
CNAME(trampoline_code_table):
.rept AARCH64_TRAMP_MAP_SIZE / AARCH64_TRAMP_SIZE
sub sp, sp, #16 /* Make space on the stack */
str x17, [sp] /* Save x17 on stack */
adr x17, #16376 /* Get data address */
ldr x17, [x17] /* Copy data into x17 */
str x17, [sp, #8] /* Save data on stack */
adr x17, #16372 /* Get code address */
ldr x17, [x17] /* Load code address into x17 */
br x17 /* Jump to code */
.endr
.globl CNAME(trampoline_code_table)
FFI_HIDDEN(CNAME(trampoline_code_table))
#ifdef __ELF__
.type CNAME(trampoline_code_table), #function
.size CNAME(trampoline_code_table), . - CNAME(trampoline_code_table)
#endif
.align AARCH64_TRAMP_MAP_SHIFT
#endif /* FFI_EXEC_STATIC_TRAMP */
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
@ -366,7 +462,7 @@ CNAME(ffi_closure_trampoline_table_page):
adr x16, -PAGE_MAX_SIZE
ldp x17, x16, [x16]
br x16
nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller that 16 bytes */
nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller than 16 bytes */
.endr
.globl CNAME(ffi_closure_trampoline_table_page)
@ -432,6 +528,7 @@ CNAME(ffi_go_closure_SYSV):
.size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
#endif
#endif /* FFI_GO_CLOSURES */
#endif /* FFI_CLOSURES */
#endif /* __arm64__ */
#if defined __ELF__ && defined __linux__

View File

@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
EXPORT ffi_go_closure_SYSV
#endif
TEXTAREA, ALLIGN=8
TEXTAREA, ALIGN=8
/* ffi_call_SYSV
extern void ffi_call_SYSV (void *stack, void *frame,

View File

@ -34,9 +34,10 @@
#include <ffi_common.h>
#include <stdint.h>
#include <stdlib.h>
#include <tramp.h>
#include "internal.h"
#if defined(_MSC_VER) && defined(_M_ARM)
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
@ -48,13 +49,25 @@
#endif
#else
#ifndef _M_ARM
#ifndef _WIN32
extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
#else
extern unsigned int ffi_arm_trampoline[3] FFI_HIDDEN;
// Declare this as an array of char, instead of array of int,
// otherwise Clang optimizes out the "& 0xFFFFFFFE" for clearing
// the thumb bit.
extern unsigned char ffi_arm_trampoline[12] FFI_HIDDEN;
#endif
#endif
#if defined(__FreeBSD__) && defined(__arm__)
#include <sys/types.h>
#include <machine/sysarch.h>
#endif
#if defined(__QNX__)
#include <sys/mman.h>
#endif
/* Forward declares. */
static int vfp_type_p (const ffi_type *);
static void layout_vfp_args (ffi_cif *);
@ -98,13 +111,13 @@ ffi_put_arg (ffi_type *ty, void *src, void *dst)
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
#ifndef _MSC_VER
#ifndef _WIN32
case FFI_TYPE_FLOAT:
#endif
*(UINT32 *)dst = *(UINT32 *)src;
break;
#ifdef _MSC_VER
#ifdef _WIN32
// casting a float* to a UINT32* doesn't work on Windows
case FFI_TYPE_FLOAT:
*(uintptr_t *)dst = 0;
@ -421,12 +434,14 @@ ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
#ifdef FFI_GO_CLOSURES
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
#endif
static void *
ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
@ -529,6 +544,8 @@ ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
return rvalue;
}
#if FFI_CLOSURES
struct closure_frame
{
char vfp_space[8*8] __attribute__((aligned(8)));
@ -564,11 +581,28 @@ ffi_closure_inner_VFP (ffi_cif *cif,
void ffi_closure_SYSV (void) FFI_HIDDEN;
void ffi_closure_VFP (void) FFI_HIDDEN;
#if defined(FFI_EXEC_STATIC_TRAMP)
void ffi_closure_SYSV_alt (void) FFI_HIDDEN;
void ffi_closure_VFP_alt (void) FFI_HIDDEN;
#endif
#ifdef FFI_GO_CLOSURES
void ffi_go_closure_SYSV (void) FFI_HIDDEN;
void ffi_go_closure_VFP (void) FFI_HIDDEN;
#endif
/* the cif must already be prep'ed */
#if defined(__FreeBSD__) && defined(__arm__)
#define __clear_cache(start, end) do { \
struct arm_sync_icache_args ua; \
\
ua.addr = (uintptr_t)(start); \
ua.len = (char *)(end) - (char *)start; \
sysarch(ARM_SYNC_ICACHE, &ua); \
} while (0);
#endif
ffi_status
ffi_prep_closure_loc (ffi_closure * closure,
ffi_cif * cif,
@ -592,27 +626,44 @@ ffi_prep_closure_loc (ffi_closure * closure,
config[1] = closure_func;
#else
#ifndef _M_ARM
# if defined(FFI_EXEC_STATIC_TRAMP)
if (ffi_tramp_is_present(closure))
{
/* Initialize the static trampoline's parameters. */
if (closure_func == ffi_closure_SYSV)
closure_func = ffi_closure_SYSV_alt;
else
closure_func = ffi_closure_VFP_alt;
ffi_tramp_set_parms (closure->ftramp, closure_func, closure);
goto out;
}
# endif
/* Initialize the dynamic trampoline. */
# ifndef _WIN32
memcpy(closure->tramp, ffi_arm_trampoline, 8);
#else
# else
// cast away function type so MSVC doesn't set the lower bit of the function pointer
memcpy(closure->tramp, (void*)((uintptr_t)ffi_arm_trampoline & 0xFFFFFFFE), FFI_TRAMPOLINE_CLOSURE_OFFSET);
#endif
# endif
#if defined (__QNX__)
msync(closure->tramp, 8, 0x1000000); /* clear data map */
msync(codeloc, 8, 0x1000000); /* clear insn map */
#elif defined(_MSC_VER)
# if defined(__QNX__)
msync (closure->tramp, 8, MS_INVALIDATE_ICACHE); /* clear data map */
msync (codeloc, 8, MS_INVALIDATE_ICACHE); /* clear insn map */
# elif defined(_WIN32)
FlushInstructionCache(GetCurrentProcess(), closure->tramp, FFI_TRAMPOLINE_SIZE);
#else
# else
__clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */
__clear_cache(codeloc, codeloc + 8); /* clear insn map */
#endif
#ifdef _M_ARM
# endif
# ifdef _WIN32
*(void(**)(void))(closure->tramp + FFI_TRAMPOLINE_CLOSURE_FUNCTION) = closure_func;
#else
# else
*(void (**)(void))(closure->tramp + 8) = closure_func;
#endif
# endif
# if defined(FFI_EXEC_STATIC_TRAMP)
out:
# endif
#endif
closure->cif = cif;
@ -622,6 +673,7 @@ ffi_prep_closure_loc (ffi_closure * closure,
return FFI_OK;
}
#ifdef FFI_GO_CLOSURES
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *))
@ -643,6 +695,9 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
return FFI_OK;
}
#endif
#endif /* FFI_CLOSURES */
/* Below are routines for VFP hard-float support. */
@ -851,4 +906,16 @@ layout_vfp_args (ffi_cif * cif)
}
}
#if defined(FFI_EXEC_STATIC_TRAMP)
void *
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
{
extern void *trampoline_code_table;
*tramp_size = ARM_TRAMP_SIZE;
*map_size = ARM_TRAMP_MAP_SIZE;
return &trampoline_code_table;
}
#endif
#endif /* __arm__ or _M_ARM */

View File

@ -43,7 +43,7 @@ typedef enum ffi_abi {
FFI_SYSV,
FFI_VFP,
FFI_LAST_ABI,
#if defined(__ARM_PCS_VFP) || defined(_M_ARM)
#if defined(__ARM_PCS_VFP) || defined(_WIN32)
FFI_DEFAULT_ABI = FFI_VFP,
#else
FFI_DEFAULT_ABI = FFI_SYSV,
@ -57,7 +57,7 @@ typedef enum ffi_abi {
signed char vfp_args[16] \
#define FFI_TARGET_SPECIFIC_VARIADIC
#ifndef _M_ARM
#ifndef _WIN32
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
@ -77,7 +77,7 @@ typedef enum ffi_abi {
#endif
#else
#ifdef _MSC_VER
#ifdef _WIN32
#define FFI_TRAMPOLINE_SIZE 16
#define FFI_TRAMPOLINE_CLOSURE_FUNCTION 12
#else

View File

@ -5,3 +5,13 @@
#define ARM_TYPE_INT 4
#define ARM_TYPE_VOID 5
#define ARM_TYPE_STRUCT 6
#if defined(FFI_EXEC_STATIC_TRAMP)
/*
* For the trampoline table mapping, a mapping size of 4K (base page size)
* is chosen.
*/
#define ARM_TRAMP_MAP_SHIFT 12
#define ARM_TRAMP_MAP_SIZE (1 << ARM_TRAMP_MAP_SHIFT)
#define ARM_TRAMP_SIZE 20
#endif

View File

@ -92,9 +92,25 @@
#define ARM_FUNC_END(name) \
SIZE(name)
.text
.syntax unified
#if defined(_WIN32)
/* Windows on ARM is thumb-only */
.thumb
#else
/* Keep the assembly in ARM mode in other cases, for simplicity
* (to avoid interworking issues). */
#undef __thumb__
.arm
#endif
/* Aid in defining a jump table with 8 bytes between entries. */
#ifdef __thumb__
/* In thumb mode, instructions can be shorter than expected in arm mode, so
* we need to align the start of each case. */
# define E(index) .align 3
#elif defined(__clang__)
/* ??? The clang assembler doesn't handle .if with symbolic expressions. */
#ifdef __clang__
# define E(index)
#else
# define E(index) \
@ -103,9 +119,6 @@
.endif
#endif
.text
.syntax unified
.arm
#ifndef __clang__
/* We require interworking on LDM, which implies ARMv5T,
@ -128,12 +141,13 @@ ARM_FUNC_START(ffi_call_VFP)
cfi_startproc
cmp r3, #3 @ load only d0 if possible
ite le
#ifdef __clang__
vldrle d0, [sp]
vldmgt sp, {d0-d7}
vldrle d0, [r0]
vldmgt r0, {d0-d7}
#else
ldcle p11, cr0, [r0] @ vldrle d0, [sp]
ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
ldcle p11, cr0, [r0] @ vldrle d0, [r0]
ldcgt p11, cr0, [r0], {16} @ vldmgt r0, {d0-d7}
#endif
add r0, r0, #64 @ discard the vfp register args
/* FALLTHRU */
@ -167,9 +181,16 @@ ARM_FUNC_START(ffi_call_SYSV)
cfi_def_cfa_register(sp)
@ Store values stored in registers.
#ifndef __thumb__
.align 3
add pc, pc, r3, lsl #3
nop
#else
adr ip, 0f
add ip, ip, r3, lsl #3
mov pc, ip
.align 3
#endif
0:
E(ARM_TYPE_VFP_S)
#ifdef __clang__
@ -208,6 +229,7 @@ E(ARM_TYPE_STRUCT)
UNWIND(.fnend)
ARM_FUNC_END(ffi_call_SYSV)
#if FFI_CLOSURES
/*
int ffi_closure_inner_* (cif, fun, user_data, frame)
@ -227,6 +249,9 @@ ARM_FUNC_END(ffi_go_closure_SYSV)
ARM_FUNC_START(ffi_closure_SYSV)
UNWIND(.fnstart)
cfi_startproc
#ifdef _WIN32
ldmfd sp!, {r0, ip} @ restore fp (r0 is used for stack alignment)
#endif
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
@ -255,7 +280,12 @@ ARM_FUNC_START(ffi_closure_SYSV)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
#ifndef __thumb__
add pc, r3, r0, lsl #3
#else
add r3, r3, r0, lsl #3
mov pc, r3
#endif
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_closure_SYSV)
@ -274,6 +304,9 @@ ARM_FUNC_END(ffi_go_closure_VFP)
ARM_FUNC_START(ffi_closure_VFP)
UNWIND(.fnstart)
cfi_startproc
#ifdef _WIN32
ldmfd sp!, {r0, ip} @ restore fp (r0 is used for stack alignment)
#endif
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
@ -305,7 +338,12 @@ ARM_FUNC_START(ffi_closure_VFP)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
#ifndef __thumb__
add pc, r3, r0, lsl #3
#else
add r3, r3, r0, lsl #3
mov pc, r3
#endif
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_closure_VFP)
@ -325,35 +363,92 @@ E(ARM_TYPE_VFP_S)
#else
ldc p10, cr0, [r2] @ vldr s0, [r2]
#endif
ldm sp, {sp,pc}
b call_epilogue
E(ARM_TYPE_VFP_D)
#ifdef __clang__
vldr d0, [r2]
#else
ldc p11, cr0, [r2] @ vldr d0, [r2]
#endif
ldm sp, {sp,pc}
b call_epilogue
E(ARM_TYPE_VFP_N)
#ifdef __clang__
vldm r2, {d0-d3}
#else
ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
#endif
ldm sp, {sp,pc}
b call_epilogue
E(ARM_TYPE_INT64)
ldr r1, [r2, #4]
nop
E(ARM_TYPE_INT)
ldr r0, [r2]
ldm sp, {sp,pc}
b call_epilogue
E(ARM_TYPE_VOID)
ldm sp, {sp,pc}
b call_epilogue
nop
E(ARM_TYPE_STRUCT)
b call_epilogue
call_epilogue:
#ifndef __thumb__
ldm sp, {sp,pc}
#else
ldm sp, {ip,lr}
mov sp, ip
bx lr
#endif
cfi_endproc
ARM_FUNC_END(ffi_closure_ret)
#if defined(FFI_EXEC_STATIC_TRAMP)
ARM_FUNC_START(ffi_closure_SYSV_alt)
/* See the comments above trampoline_code_table. */
ldr ip, [sp, #4] /* Load closure in ip */
add sp, sp, 8 /* Restore the stack */
b CNAME(ffi_closure_SYSV)
ARM_FUNC_END(ffi_closure_SYSV_alt)
ARM_FUNC_START(ffi_closure_VFP_alt)
/* See the comments above trampoline_code_table. */
ldr ip, [sp, #4] /* Load closure in ip */
add sp, sp, 8 /* Restore the stack */
b CNAME(ffi_closure_VFP)
ARM_FUNC_END(ffi_closure_VFP_alt)
/*
* Below is the definition of the trampoline code table. Each element in
* the code table is a trampoline.
*/
/*
* The trampoline uses register ip (r12). It saves the original value of ip
* on the stack.
*
* The trampoline has two parameters - target code to jump to and data for
* the target code. The trampoline extracts the parameters from its parameter
* block (see tramp_table_map()). The trampoline saves the data address on
* the stack. Finally, it jumps to the target code.
*
* The target code can choose to:
*
* - restore the value of ip
* - load the data address in a register
* - restore the stack pointer to what it was when the trampoline was invoked.
*/
.align ARM_TRAMP_MAP_SHIFT
ARM_FUNC_START(trampoline_code_table)
.rept ARM_TRAMP_MAP_SIZE / ARM_TRAMP_SIZE
sub sp, sp, #8 /* Make space on the stack */
str ip, [sp] /* Save ip on stack */
ldr ip, [pc, #4080] /* Copy data into ip */
str ip, [sp, #4] /* Save data on stack */
ldr pc, [pc, #4076] /* Copy code into PC */
.endr
ARM_FUNC_END(trampoline_code_table)
.align ARM_TRAMP_MAP_SHIFT
#endif /* FFI_EXEC_STATIC_TRAMP */
#endif /* FFI_CLOSURES */
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
@ -369,6 +464,15 @@ ARM_FUNC_START(ffi_closure_trampoline_table_page)
ARM_FUNC_END(ffi_closure_trampoline_table_page)
#endif
#elif defined(_WIN32)
ARM_FUNC_START(ffi_arm_trampoline)
0: adr ip, 0b
stmdb sp!, {r0, ip}
ldr pc, 1f
1: .long 0
ARM_FUNC_END(ffi_arm_trampoline)
#else
ARM_FUNC_START(ffi_arm_trampoline)

View File

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
closures.c - Copyright (c) 2019 Anthony Green
closures.c - Copyright (c) 2019, 2022 Anthony Green
Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
@ -27,13 +27,14 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#if defined __linux__ && !defined _GNU_SOURCE
#if (defined __linux__ || defined __CYGWIN__) && !defined _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_common.h>
#include <tramp.h>
#ifdef __NetBSD__
#include <sys/param.h>
@ -45,6 +46,9 @@
#include <stddef.h>
#include <unistd.h>
#ifdef HAVE_SYS_MEMFD_H
#include <sys/memfd.h>
#endif
static const size_t overhead =
(sizeof(max_align_t) > sizeof(void *) + sizeof(size_t)) ?
@ -109,6 +113,12 @@ ffi_closure_free (void *ptr)
munmap(dataseg, rounded_size);
munmap(codeseg, rounded_size);
}
int
ffi_tramp_is_present (__attribute__((unused)) void *ptr)
{
return 0;
}
#else /* !NetBSD with PROT_MPROTECT */
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
@ -123,22 +133,26 @@ ffi_closure_free (void *ptr)
# define FFI_MMAP_EXEC_WRIT 1
# define HAVE_MNTENT 1
# endif
# if defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)
/* Windows systems may have Data Execution Protection (DEP) enabled,
# if defined(__CYGWIN__) || defined(_WIN32) || defined(__OS2__)
/* Windows systems may have Data Execution Protection (DEP) enabled,
which requires the use of VirtualMalloc/VirtualFree to alloc/free
executable memory. */
# define FFI_MMAP_EXEC_WRIT 1
# endif
#endif
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
# if defined(__linux__) && !defined(__ANDROID__)
#if FFI_MMAP_EXEC_WRIT && defined(__linux__) && !defined(__ANDROID__)
# if !defined FFI_MMAP_EXEC_SELINUX
/* When defined to 1 check for SELinux and if SELinux is active,
don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
might cause audit messages. */
# define FFI_MMAP_EXEC_SELINUX 1
# endif
#endif
# endif /* !defined FFI_MMAP_EXEC_SELINUX */
# if !defined FFI_MMAP_PAX
/* Also check for PaX MPROTECT */
# define FFI_MMAP_PAX 1
# endif /* !defined FFI_MMAP_PAX */
#endif /* FFI_MMAP_EXEC_WRIT && defined(__linux__) && !defined(__ANDROID__) */
#if FFI_CLOSURES
@ -148,6 +162,9 @@ ffi_closure_free (void *ptr)
#include <mach/mach.h>
#include <pthread.h>
#ifdef HAVE_PTRAUTH
#include <ptrauth.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@ -160,7 +177,6 @@ struct ffi_trampoline_table
{
/* contiguous writable and executable pages */
vm_address_t config_page;
vm_address_t trampoline_page;
/* free list tracking */
uint16_t free_count;
@ -204,7 +220,13 @@ ffi_trampoline_table_alloc (void)
/* Remap the trampoline table on top of the placeholder page */
trampoline_page = config_page + PAGE_MAX_SIZE;
#ifdef HAVE_PTRAUTH
trampoline_page_template = (vm_address_t)(uintptr_t)ptrauth_auth_data((void *)&ffi_closure_trampoline_table_page, ptrauth_key_function_pointer, 0);
#else
trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page;
#endif
#ifdef __arm__
/* ffi_closure_trampoline_table_page can be thumb-biased on some ARM archs */
trampoline_page_template &= ~1UL;
@ -218,11 +240,22 @@ ffi_trampoline_table_alloc (void)
return NULL;
}
if (!(cur_prot & VM_PROT_EXECUTE))
{
/* If VM_PROT_EXECUTE isn't set on the remapped trampoline page, set it */
kt = vm_protect (mach_task_self (), trampoline_page, PAGE_MAX_SIZE,
FALSE, cur_prot | VM_PROT_EXECUTE);
if (kt != KERN_SUCCESS)
{
vm_deallocate (mach_task_self (), config_page, PAGE_MAX_SIZE * 2);
return NULL;
}
}
/* We have valid trampoline and config pages */
table = calloc (1, sizeof (ffi_trampoline_table));
table->free_count = FFI_TRAMPOLINE_COUNT;
table->config_page = config_page;
table->trampoline_page = trampoline_page;
/* Create and initialize the free list */
table->free_list_pool =
@ -232,7 +265,10 @@ ffi_trampoline_table_alloc (void)
{
ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
entry->trampoline =
(void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
(void *) (trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
#ifdef HAVE_PTRAUTH
entry->trampoline = ptrauth_sign_unauthenticated(entry->trampoline, ptrauth_key_function_pointer, 0);
#endif
if (i < table->free_count - 1)
entry->next = &table->free_list_pool[i + 1];
@ -386,7 +422,7 @@ ffi_closure_free (void *ptr)
#endif
#include <string.h>
#include <stdio.h>
#if !defined(X86_WIN32) && !defined(X86_WIN64) && !defined(_M_ARM64)
#if !defined(_WIN32)
#ifdef HAVE_MNTENT
#include <mntent.h>
#endif /* HAVE_MNTENT */
@ -447,14 +483,18 @@ selinux_enabled_check (void)
#endif /* !FFI_MMAP_EXEC_SELINUX */
/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
/* On PaX enable kernels that have MPROTECT enabled we can't use PROT_EXEC. */
#if defined FFI_MMAP_PAX
#include <stdlib.h>
static int emutramp_enabled = -1;
enum {
PAX_MPROTECT = (1 << 0),
PAX_EMUTRAMP = (1 << 1),
};
static int cached_pax_flags = -1;
static int
emutramp_enabled_check (void)
pax_flags_check (void)
{
char *buf = NULL;
size_t len = 0;
@ -468,9 +508,10 @@ emutramp_enabled_check (void)
while (getline (&buf, &len, f) != -1)
if (!strncmp (buf, "PaX:", 4))
{
char emutramp;
if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
ret = (emutramp == 'E');
if (NULL != strchr (buf + 4, 'M'))
ret |= PAX_MPROTECT;
if (NULL != strchr (buf + 4, 'E'))
ret |= PAX_EMUTRAMP;
break;
}
free (buf);
@ -478,9 +519,13 @@ emutramp_enabled_check (void)
return ret;
}
#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
: (emutramp_enabled = emutramp_enabled_check ()))
#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
#define get_pax_flags() (cached_pax_flags >= 0 ? cached_pax_flags \
: (cached_pax_flags = pax_flags_check ()))
#define has_pax_flags(flags) ((flags) == ((flags) & get_pax_flags ()))
#define is_mprotect_enabled() (has_pax_flags (PAX_MPROTECT))
#define is_emutramp_enabled() (has_pax_flags (PAX_EMUTRAMP))
#endif /* defined FFI_MMAP_PAX */
#elif defined (__CYGWIN__) || defined(__INTERIX)
@ -491,9 +536,10 @@ emutramp_enabled_check (void)
#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
#define is_emutramp_enabled() 0
#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
#if !defined FFI_MMAP_PAX
# define is_mprotect_enabled() 0
# define is_emutramp_enabled() 0
#endif /* !defined FFI_MMAP_PAX */
/* Declare all functions defined in dlmalloc.c as static. */
static void *dlmalloc(size_t);
@ -512,11 +558,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED;
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
static void dlmalloc_stats(void) MAYBE_UNUSED;
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
/* Use these for mmap and munmap within dlmalloc.c. */
static void *dlmmap(void *, size_t, int, int, int, off_t);
static int dlmunmap(void *, size_t);
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#define mmap dlmmap
#define munmap dlmunmap
@ -526,7 +572,7 @@ static int dlmunmap(void *, size_t);
#undef mmap
#undef munmap
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
/* A mutex used to synchronize access to *exec* variables in this file. */
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -538,6 +584,17 @@ static int execfd = -1;
/* The amount of space already allocated from the temporary file. */
static size_t execsize = 0;
#ifdef HAVE_MEMFD_CREATE
/* Open a temporary file name, and immediately unlink it. */
static int
open_temp_exec_file_memfd (const char *name)
{
int fd;
fd = memfd_create (name, MFD_CLOEXEC);
return fd;
}
#endif
/* Open a temporary file name, and immediately unlink it. */
static int
open_temp_exec_file_name (char *name, int flags)
@ -665,6 +722,10 @@ static struct
const char *arg;
int repeat;
} open_temp_exec_file_opts[] = {
#ifdef HAVE_MEMFD_CREATE
{ open_temp_exec_file_memfd, "libffi", 0 },
#endif
{ open_temp_exec_file_env, "LIBFFI_TMPDIR", 0 },
{ open_temp_exec_file_env, "TMPDIR", 0 },
{ open_temp_exec_file_dir, "/tmp", 0 },
{ open_temp_exec_file_dir, "/var/tmp", 0 },
@ -702,7 +763,7 @@ open_temp_exec_file_opts_next (void)
/* Return a file descriptor of a temporary zero-sized file in a
writable and executable filesystem. */
static int
int
open_temp_exec_file (void)
{
int fd;
@ -837,13 +898,29 @@ dlmmap (void *start, size_t length, int prot,
&& flags == (MAP_PRIVATE | MAP_ANONYMOUS)
&& fd == -1 && offset == 0);
if (execfd == -1 && is_emutramp_enabled ())
if (execfd == -1 && ffi_tramp_is_supported ())
{
ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
return ptr;
}
if (execfd == -1 && !is_selinux_enabled ())
/* -1 != execfd hints that we already decided to use dlmmap_locked
last time. */
if (execfd == -1 && is_mprotect_enabled ())
{
#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
if (is_emutramp_enabled ())
{
/* emutramp requires the kernel recognizing the trampoline pattern
generated by ffi_prep_closure_loc; there is no way to test
in advance whether this will work, so this is experimental. */
ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
return ptr;
}
#endif
/* fallback to dlmmap_locked. */
}
else if (execfd == -1 && !is_selinux_enabled ())
{
ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
@ -856,16 +933,11 @@ dlmmap (void *start, size_t length, int prot,
MREMAP_DUP and prot at this point. */
}
if (execsize == 0 || execfd == -1)
{
pthread_mutex_lock (&open_temp_exec_file_mutex);
ptr = dlmmap_locked (start, length, prot, flags, offset);
pthread_mutex_unlock (&open_temp_exec_file_mutex);
pthread_mutex_lock (&open_temp_exec_file_mutex);
ptr = dlmmap_locked (start, length, prot, flags, offset);
pthread_mutex_unlock (&open_temp_exec_file_mutex);
return ptr;
}
return dlmmap_locked (start, length, prot, flags, offset);
return ptr;
}
/* Release memory at the given address, as well as the corresponding
@ -908,7 +980,7 @@ segment_holding_code (mstate m, char* addr)
}
#endif
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
/* Allocate a chunk of memory with the given size. Returns a pointer
to the writable address, and sets *CODE to the executable
@ -916,18 +988,29 @@ segment_holding_code (mstate m, char* addr)
void *
ffi_closure_alloc (size_t size, void **code)
{
void *ptr;
void *ptr, *ftramp;
if (!code)
return NULL;
ptr = dlmalloc (size);
ptr = FFI_CLOSURE_PTR (dlmalloc (size));
if (ptr)
{
msegmentptr seg = segment_holding (gm, ptr);
*code = add_segment_exec_offset (ptr, seg);
if (!ffi_tramp_is_supported ())
return ptr;
ftramp = ffi_tramp_alloc (0);
if (ftramp == NULL)
{
dlfree (FFI_RESTORE_PTR (ptr));
return NULL;
}
*code = ffi_tramp_get_addr (ftramp);
((ffi_closure *) ptr)->ftramp = ftramp;
}
return ptr;
@ -942,7 +1025,11 @@ ffi_data_to_code_pointer (void *data)
burden of managing this memory themselves, in which case this
we'll just return data. */
if (seg)
return add_segment_exec_offset (data, seg);
{
if (!ffi_tramp_is_supported ())
return add_segment_exec_offset (data, seg);
return ffi_tramp_get_addr (((ffi_closure *) data)->ftramp);
}
else
return data;
}
@ -960,8 +1047,17 @@ ffi_closure_free (void *ptr)
if (seg)
ptr = sub_segment_exec_offset (ptr, seg);
#endif
if (ffi_tramp_is_supported ())
ffi_tramp_free (((ffi_closure *) ptr)->ftramp);
dlfree (ptr);
dlfree (FFI_RESTORE_PTR (ptr));
}
int
ffi_tramp_is_present (void *ptr)
{
msegmentptr seg = segment_holding (gm, ptr);
return seg != NULL && ffi_tramp_is_supported();
}
# else /* ! FFI_MMAP_EXEC_WRIT */
@ -977,13 +1073,13 @@ ffi_closure_alloc (size_t size, void **code)
if (!code)
return NULL;
return *code = malloc (size);
return *code = FFI_CLOSURE_PTR (malloc (size));
}
void
ffi_closure_free (void *ptr)
{
free (ptr);
free (FFI_RESTORE_PTR (ptr));
}
void *
@ -992,6 +1088,12 @@ ffi_data_to_code_pointer (void *data)
return data;
}
int
ffi_tramp_is_present (__attribute__((unused)) void *ptr)
{
return 0;
}
# endif /* ! FFI_MMAP_EXEC_WRIT */
#endif /* FFI_CLOSURES */

395
src/csky/ffi.c Normal file
View File

@ -0,0 +1,395 @@
/* -----------------------------------------------------------------------
ffi.c
CSKY 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;
argp = stack;
if ( ecif->cif->flags == 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;
size_t alignment;
/* Align if necessary */
alignment = (*p_arg)->alignment;
#ifdef __CSKYABIV1__
/*
* Adapt ABIV1 bug.
* If struct's size is larger than 8 bytes, then it always alignment as 4 bytes.
*/
if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) {
alignment = 4;
}
#endif
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) FFI_ALIGN(argp, alignment);
}
if ((*p_arg)->type == FFI_TYPE_STRUCT)
argp = (char *) FFI_ALIGN(argp, 4);
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:
#ifdef __CSKYBE__
memcpy((argp + 4 - (*p_arg)->size), *p_argv, (*p_arg)->size);
#else
memcpy(argp, *p_argv, (*p_arg)->size);
#endif
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;
}
return;
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
/* Round the stack up to a multiple of 8 bytes. This isn't needed
everywhere, but it is on some platforms, and it doesn't hcsky anything
when it isn't needed. */
cif->bytes = (cif->bytes + 7) & ~7;
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_DOUBLE:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = (unsigned) FFI_TYPE_SINT64;
break;
case FFI_TYPE_STRUCT:
if (cif->rtype->size <= 4)
/* A Composite Type not larger than 4 bytes is returned in r0. */
cif->flags = (unsigned)FFI_TYPE_INT;
else if (cif->rtype->size <= 8)
/* A Composite Type not larger than 8 bytes is returned in r0, r1. */
cif->flags = (unsigned)FFI_TYPE_SINT64;
else
/* A Composite Type larger than 8 bytes, or whose size cannot
be determined statically ... is stored in memory at an
address passed [in r0]. */
cif->flags = (unsigned)FFI_TYPE_STRUCT;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
}
return FFI_OK;
}
/* Perform machine dependent cif processing for variadic calls */
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs,
unsigned int ntotalargs)
{
return ffi_prep_cif_machdep(cif);
}
/* Prototypes for assembly functions, in sysv.S */
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
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->rtype->type == FFI_TYPE_STRUCT);
ecif.cif = cif;
ecif.avalue = avalue;
unsigned int 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)
#ifdef __CSKYBE__
memcpy (rvalue, ((unsigned char *)&temp + (4 - cif->rtype->size)), cif->rtype->size);
#else
memcpy (rvalue, &temp, cif->rtype->size);
#endif
}
/** private members **/
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
void** args, ffi_cif* cif);
void ffi_closure_SYSV (ffi_closure *);
/* This function is jumped to by the trampoline */
unsigned int
ffi_closure_SYSV_inner (closure, respp, args)
ffi_closure *closure;
void **respp;
void *args;
{
// our various things...
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);
(closure->fun) (cif, *respp, arg_area, closure->user_data);
#ifdef __CSKYBE__
if (cif->flags == FFI_TYPE_INT && cif->rtype->type == FFI_TYPE_STRUCT) {
unsigned int tmp = 0;
tmp = *(unsigned int *)(*respp);
*(unsigned int *)(*respp) = (tmp >> ((4 - cif->rtype->size) * 8));
}
#endif
return cif->flags;
}
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if ( cif->flags == FFI_TYPE_STRUCT ) {
*rvalue = *(void **) argp;
argp += 4;
}
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;
#ifdef __CSKYABIV1__
/*
* Adapt ABIV1 bug.
* If struct's size is larger than 8 bytes, then it always alignment as 4 bytes.
*/
if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) {
alignment = 4;
}
#endif
/* Align if necessary */
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) FFI_ALIGN(argp, alignment);
}
z = (*p_arg)->size;
#ifdef __CSKYBE__
unsigned int tmp = 0;
if ((*p_arg)->size < 4) {
tmp = *(unsigned int *)argp;
memcpy(argp, ((unsigned char *)&tmp + (4 - (*p_arg)->size)), (*p_arg)->size);
}
#else
/* because we're little endian, this is what it turns into. */
#endif
*p_argv = (void*) argp;
p_argv++;
argp += z;
}
return;
}
/* How to make a trampoline. */
extern unsigned char ffi_csky_trampoline[TRAMPOLINE_SIZE];
/*
* Since there is no __clear_cache in libgcc in csky toolchain.
* define ffi_csky_cacheflush in sysv.S.
* void ffi_csky_cacheflush(uint32 start_addr, uint32 size, int cache)
*/
#define CACHEFLUSH_IN_FFI 1
#if CACHEFLUSH_IN_FFI
extern void ffi_csky_cacheflush(unsigned char *__tramp, unsigned int k,
int i);
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned char *insns = (unsigned char *)(CTX); \
memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \
ffi_csky_cacheflush(&__tramp[0], TRAMPOLINE_SIZE, 3); /* Clear data mapping. */ \
ffi_csky_cacheflush(insns, TRAMPOLINE_SIZE, 3); \
/* Clear instruction \
mapping. */ \
})
#else
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned char *insns = (unsigned char *)(CTX); \
memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \
__clear_cache((&__tramp[0]), (&__tramp[TRAMPOLINE_SIZE-1])); /* Clear data mapping. */ \
__clear_cache(insns, insns + TRAMPOLINE_SIZE); \
/* Clear instruction \
mapping. */ \
})
#endif
/* the cif must already be prep'ed */
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 (&closure->tramp[0], \
closure_func, \
codeloc);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}

63
src/csky/ffitarget.h Normal file
View File

@ -0,0 +1,63 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2010 CodeSourcery
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for CSKY.
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
#ifdef __CSKYABIV2__
#define FFI_ASM_ARGREG_SIZE 16
#define TRAMPOLINE_SIZE 16
#define FFI_TRAMPOLINE_SIZE 24
#else
#define FFI_ASM_ARGREG_SIZE 24
#define TRAMPOLINE_SIZE 20
#define FFI_TRAMPOLINE_SIZE 28
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#endif

371
src/csky/sysv.S Normal file
View File

@ -0,0 +1,371 @@
/* -----------------------------------------------------------------------
sysv.S
CSKY 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>
.macro CSKY_FUNC_START name
.text
.align 2
.globl \name
.type \name, @function
\name:
.endm
#ifdef __CSKYABIV2__
/*
* a0: fn
* a1: &ecif
* a2: cif->bytes
* a3: fig->flags
* sp+0: ecif.rvalue
*/
CSKY_FUNC_START ffi_call_SYSV
/* Save registers */
.cfi_startproc
subi sp, 28
.cfi_def_cfa_offset 28
stw a0, (sp, 0x0)
.cfi_offset 0, -28
stw a1, (sp, 0x4)
.cfi_offset 1, -24
stw a2, (sp, 0x8)
.cfi_offset 2, -20
stw a3, (sp, 0xC)
.cfi_offset 3, -16
stw l0, (sp, 0x10)
.cfi_offset 4, -12
stw l1, (sp, 0x14)
.cfi_offset 5, -8
stw lr, (sp, 0x18)
.cfi_offset 15, -4
mov l0, sp
.cfi_def_cfa_register 4
/* Make room for all of the new args. */
subu sp, sp, a2
/* Place all of the ffi_prep_args in position */
mov a0, sp
/* a1 already set */
/* Call ffi_prep_args(stack, &ecif) */
jsri ffi_prep_args
/* move first 4 parameters in registers */
ldw a0, (sp, 0x0)
ldw a1, (sp, 0x4)
ldw a2, (sp, 0x8)
ldw a3, (sp, 0xC)
/* and adjust stack */
subu lr, l0, sp /* cif->bytes == l0 - sp */
cmphsi lr, 16
movi l1, 16
movt lr, l1
addu sp, sp, lr
ldw l1, (l0, 0) /* load fn() in advance */
/* call (fn) (...) */
jsr l1
/* Remove the space we pushed for the args */
mov sp, l0
/* Load r2 with the pointer to storage for the return value */
ldw a2, (sp, 0x1C)
/* Load r3 with the return type code */
ldw a3, (sp, 0xC)
/* If the return value pointer is NULL, assume no return value. */
cmpnei a2, 0
bf .Lepilogue
cmpnei a3, FFI_TYPE_STRUCT
bf .Lepilogue
/* return INT64 */
cmpnei a3, FFI_TYPE_SINT64
bt .Lretint
/* stw a0, (a2, 0x0) at .Lretint */
stw a1, (a2, 0x4)
.Lretint:
/* return INT */
stw a0, (a2, 0x0)
.Lepilogue:
ldw a0, (sp, 0x0)
ldw a1, (sp, 0x4)
ldw a2, (sp, 0x8)
ldw a3, (sp, 0xC)
ldw l0, (sp, 0x10)
ldw l1, (sp, 0x14)
ldw lr, (sp, 0x18)
addi sp, sp, 28
rts
.cfi_endproc
.size ffi_call_SYSV, .-ffi_call_SYSV
/*
* unsigned int FFI_HIDDEN
* ffi_closure_SYSV_inner (closure, respp, args)
* ffi_closure *closure;
* void **respp;
* void *args;
*/
CSKY_FUNC_START ffi_closure_SYSV
.cfi_startproc
mov a2, sp
addi a1, sp, 16
subi sp, sp, 24
.cfi_def_cfa_offset 40
stw a1, (sp, 0x10)
.cfi_offset 1, -24
stw lr, (sp, 0x14)
.cfi_offset 15, -20
stw sp, (sp, 0x8)
addi a1, sp, 8
jsri ffi_closure_SYSV_inner
ldw a0, (sp, 0x0)
/*
* if FFI_TYPE_SINT64, need a1.
* if FFI_TYPE_INT, ignore a1.
*/
ldw a1, (sp, 0x4)
ldw lr, (sp, 0x14)
addi sp, sp, 40
rts
.cfi_endproc
.size ffi_closure_SYSV, .-ffi_closure_SYSV
CSKY_FUNC_START ffi_csky_trampoline
subi sp, sp, 16
stw a0, (sp, 0x0)
stw a1, (sp, 0x4)
stw a2, (sp, 0x8)
stw a3, (sp, 0xC)
lrw a0, [.Lctx]
lrw a1, [.Lfun]
jmp a1
.Lctx:
mov a0, a0
mov a0, a0
.Lfun:
.size ffi_csky_trampoline, .-ffi_csky_trampoline
CSKY_FUNC_START ffi_csky_cacheflush
mov t0, r7
movi r7, 123
trap 0
mov r7, t0
rts
.size ffi_csky_cacheflush, .-ffi_csky_cacheflush
#else /* !__CSKYABIV2__ */
/*
* a0: fn
* a1: &ecif
* a2: cif->bytes
* a3: fig->flags
* a4: ecif.rvalue
*/
CSKY_FUNC_START ffi_call_SYSV
/* Save registers */
.cfi_startproc
subi sp, 32
subi sp, 8
.cfi_def_cfa_offset 40
stw a0, (sp, 0x0)
.cfi_offset 2, -40
stw a1, (sp, 0x4)
.cfi_offset 3, -36
stw a2, (sp, 0x8)
.cfi_offset 4, -32
stw a3, (sp, 0xC)
.cfi_offset 5, -28
stw a4, (sp, 0x10)
.cfi_offset 6, -24
stw a5, (sp, 0x14)
.cfi_offset 7, -20
stw l0, (sp, 0x18)
.cfi_offset 8, -16
stw l1, (sp, 0x1C)
.cfi_offset 9, -12
stw lr, (sp, 0x20)
.cfi_offset 15, -8
mov l0, sp
.cfi_def_cfa_register 8
/* Make room for all of the new args. */
subu sp, sp, a2
/* Place all of the ffi_prep_args in position */
mov a0, sp
/* a1 already set */
/* Call ffi_prep_args(stack, &ecif) */
jsri ffi_prep_args
/* move first 4 parameters in registers */
ldw a0, (sp, 0x0)
ldw a1, (sp, 0x4)
ldw a2, (sp, 0x8)
ldw a3, (sp, 0xC)
ldw a4, (sp, 0x10)
ldw a5, (sp, 0x14)
/* and adjust stack */
mov lr, l0
subu lr, sp /* cif->bytes == l0 - sp */
movi l1, 24
cmphs lr, l1
movt lr, l1
addu sp, sp, lr
ldw l1, (l0, 0) /* load fn() in advance */
/* call (fn) (...) */
jsr l1
/* Remove the space we pushed for the args */
mov sp, l0
/* Load r2 with the pointer to storage for the return value */
ldw a2, (sp, 0x10)
/* Load r3 with the return type code */
ldw a3, (sp, 0xC)
/* If the return value pointer is NULL, assume no return value. */
cmpnei a2, 0
bf .Lepilogue
cmpnei a3, FFI_TYPE_STRUCT
bf .Lepilogue
/* return INT64 */
cmpnei a3, FFI_TYPE_SINT64
bt .Lretint
/* stw a0, (a2, 0x0) at .Lretint */
stw a1, (a2, 0x4)
.Lretint:
/* return INT */
stw a0, (a2, 0x0)
.Lepilogue:
ldw a0, (sp, 0x0)
ldw a1, (sp, 0x4)
ldw a2, (sp, 0x8)
ldw a3, (sp, 0xC)
ldw a4, (sp, 0x10)
ldw a5, (sp, 0x14)
ldw l0, (sp, 0x18)
ldw l1, (sp, 0x1C)
ldw lr, (sp, 0x20)
addi sp, sp, 32
addi sp, sp, 8
rts
.cfi_endproc
.size ffi_call_SYSV, .-ffi_call_SYSV
/*
* unsigned int FFI_HIDDEN
* ffi_closure_SYSV_inner (closure, respp, args)
* ffi_closure *closure;
* void **respp;
* void *args;
*/
CSKY_FUNC_START ffi_closure_SYSV
.cfi_startproc
mov a2, sp
mov a1, sp
addi a1, 24
subi sp, sp, 24
.cfi_def_cfa_offset 48
stw a1, (sp, 0x10)
.cfi_offset 3, -32
stw lr, (sp, 0x14)
.cfi_offset 15, -28
stw sp, (sp, 0x8)
mov a1, sp
addi a1, 8
jsri ffi_closure_SYSV_inner
ldw a0, (sp, 0x0)
/*
* if FFI_TYPE_SINT64, need a1.
* if FFI_TYPE_INT, ignore a1.
*/
ldw a1, (sp, 0x4)
ldw lr, (sp, 0x14)
addi sp, sp, 24
addi sp, sp, 24
rts
.cfi_endproc
.size ffi_closure_SYSV, .-ffi_closure_SYSV
CSKY_FUNC_START ffi_csky_trampoline
subi sp, 24
stw a0, (sp, 0x0)
stw a1, (sp, 0x4)
stw a2, (sp, 0x8)
stw a3, (sp, 0xC)
stw a4, (sp, 0x10)
stw a5, (sp, 0x14)
lrw a0, [.Lctx]
lrw a1, [.Lfun]
jmp a1
.Lctx:
mov a0, a0
mov a0, a0
.Lfun:
.size ffi_csky_trampoline, .-ffi_csky_trampoline
CSKY_FUNC_START ffi_csky_cacheflush
lrw r1, 123
trap 0
rts
.size ffi_csky_cacheflush, .-ffi_csky_cacheflush
#endif /* __CSKYABIV2__ */

View File

@ -592,6 +592,11 @@ DEFAULT_MMAP_THRESHOLD default: 256K
malloc does support the following options.
*/
/* The system's malloc.h may have conflicting defines. */
#undef M_TRIM_THRESHOLD
#undef M_GRANULARITY
#undef M_MMAP_THRESHOLD
#define M_TRIM_THRESHOLD (-1)
#define M_GRANULARITY (-2)
#define M_MMAP_THRESHOLD (-3)
@ -2371,7 +2376,7 @@ static size_t traverse_and_check(mstate m);
#else /* GNUC */
#if USE_BUILTIN_FFS
#define compute_bit2idx(X, I) I = ffs(X)-1
#define compute_bit2idx(X, I) I = __builtin_ffs(X)-1
#else /* USE_BUILTIN_FFS */
#define compute_bit2idx(X, I)\

5
src/kvx/asm.h Normal file
View File

@ -0,0 +1,5 @@
/* args are passed on registers from r0 up to r11 => 12*8 bytes */
#define REG_ARGS_SIZE (12*8)
#define KVX_REGISTER_SIZE (8)
#define KVX_ABI_SLOT_SIZE (KVX_REGISTER_SIZE)
#define KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE (4*KVX_ABI_SLOT_SIZE)

273
src/kvx/ffi.c Normal file
View File

@ -0,0 +1,273 @@
/* Copyright (c) 2020 Kalray
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. */
#if defined(__kvx__)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fficonfig.h>
#include <ffi.h>
#include "ffi_common.h"
#include "asm.h"
#define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1)
#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define KVX_ABI_STACK_ALIGNMENT (32)
#define KVX_ABI_STACK_ARG_ALIGNMENT (8)
#define max(a,b) ((a) > (b) ? (a) : (b))
#ifdef FFI_DEBUG
#define DEBUG_PRINT(...) do{ fprintf( stderr, __VA_ARGS__ ); } while(0)
#else
#define DEBUG_PRINT(...)
#endif
struct ret_value {
unsigned long int r0;
unsigned long int r1;
unsigned long int r2;
unsigned long int r3;
};
extern struct ret_value ffi_call_SYSV(unsigned total_size,
unsigned size,
extended_cif *ecif,
unsigned *rvalue_addr,
void *fn,
unsigned int_ext_method);
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
cif->flags = cif->rtype->size;
return FFI_OK;
}
/* 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, unsigned int arg_slots_size, extended_cif *ecif)
{
char *stacktemp = stack;
char *current_arg_passed_by_value = stack + arg_slots_size;
int i, s;
ffi_type **arg;
int count = 0;
ffi_cif *cif = ecif->cif;
void **argv = ecif->avalue;
arg = cif->arg_types;
DEBUG_PRINT("stack: %p\n", stack);
DEBUG_PRINT("arg_slots_size: %u\n", arg_slots_size);
DEBUG_PRINT("current_arg_passed_by_value: %p\n", current_arg_passed_by_value);
DEBUG_PRINT("ecif: %p\n", ecif);
DEBUG_PRINT("ecif->avalue: %p\n", ecif->avalue);
for (i = 0; i < cif->nargs; i++) {
s = KVX_ABI_SLOT_SIZE;
switch((*arg)->type) {
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_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
DEBUG_PRINT("INT64/32/16/8/FLOAT/DOUBLE or POINTER @%p\n", stack);
*(uint64_t *) stack = *(uint64_t *)(* argv);
break;
case FFI_TYPE_COMPLEX:
if ((*arg)->size == 8)
*(_Complex float *) stack = *(_Complex float *)(* argv);
else if ((*arg)->size == 16) {
*(_Complex double *) stack = *(_Complex double *)(* argv);
s = 16;
} else
abort();
break;
case FFI_TYPE_STRUCT: {
char *value;
unsigned int written_size = 0;
DEBUG_PRINT("struct by value @%p\n", stack);
if ((*arg)->size > KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) {
DEBUG_PRINT("big struct\n");
*(uint64_t *) stack = (uintptr_t)current_arg_passed_by_value;
value = current_arg_passed_by_value;
current_arg_passed_by_value += (*arg)->size;
written_size = KVX_ABI_SLOT_SIZE;
} else {
value = stack;
written_size = (*arg)->size;
}
memcpy(value, *argv, (*arg)->size);
s = ALIGN(written_size, KVX_ABI_STACK_ARG_ALIGNMENT);
break;
}
default:
printf("Error: unsupported arg type %d\n", (*arg)->type);
abort();
break;
}
stack += s;
count += s;
argv++;
arg++;
}
#ifdef FFI_DEBUG
FFI_ASSERT(((intptr_t)(stacktemp + REG_ARGS_SIZE) & (KVX_ABI_STACK_ALIGNMENT-1)) == 0);
#endif
return stacktemp + REG_ARGS_SIZE;
}
/* Perform machine dependent cif processing when we have a variadic function */
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
unsigned int ntotalargs)
{
cif->flags = cif->rtype->size;
return FFI_OK;
}
static unsigned long handle_small_int_ext(kvx_intext_method *int_ext_method,
const ffi_type *rtype)
{
switch (rtype->type) {
case FFI_TYPE_SINT8:
*int_ext_method = KVX_RET_SXBD;
return KVX_REGISTER_SIZE;
case FFI_TYPE_SINT16:
*int_ext_method = KVX_RET_SXHD;
return KVX_REGISTER_SIZE;
case FFI_TYPE_SINT32:
*int_ext_method = KVX_RET_SXWD;
return KVX_REGISTER_SIZE;
case FFI_TYPE_UINT8:
*int_ext_method = KVX_RET_ZXBD;
return KVX_REGISTER_SIZE;
case FFI_TYPE_UINT16:
*int_ext_method = KVX_RET_ZXHD;
return KVX_REGISTER_SIZE;
case FFI_TYPE_UINT32:
*int_ext_method = KVX_RET_ZXWD;
return KVX_REGISTER_SIZE;
default:
*int_ext_method = KVX_RET_NONE;
return rtype->size;
}
}
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
int i;
unsigned long int slot_fitting_args_size = 0;
unsigned long int total_size = 0;
unsigned long int big_struct_size = 0;
kvx_intext_method int_extension_method;
ffi_type **arg;
struct ret_value local_rvalue = {0};
size_t wb_size;
/* Calculate size to allocate on stack */
for (i = 0, arg = cif->arg_types; i < cif->nargs; i++, arg++) {
DEBUG_PRINT("argument %d, type %d, size %lu\n", i, (*arg)->type, (*arg)->size);
if (((*arg)->type == FFI_TYPE_STRUCT) || ((*arg)->type == FFI_TYPE_COMPLEX)) {
if ((*arg)->size <= KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) {
slot_fitting_args_size += ALIGN((*arg)->size, KVX_ABI_SLOT_SIZE);
} else {
slot_fitting_args_size += KVX_ABI_SLOT_SIZE; /* aggregate passed by reference */
big_struct_size += ALIGN((*arg)->size, KVX_ABI_SLOT_SIZE);
}
} else if ((*arg)->size <= KVX_ABI_SLOT_SIZE) {
slot_fitting_args_size += KVX_ABI_SLOT_SIZE;
} else {
printf("Error: unsupported arg size %ld arg type %d\n", (*arg)->size, (*arg)->type);
abort(); /* should never happen? */
}
}
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
ecif.rvalue = rvalue;
/* This implementation allocates anyway for all register based args */
slot_fitting_args_size = max(slot_fitting_args_size, REG_ARGS_SIZE);
total_size = slot_fitting_args_size + big_struct_size;
total_size = ALIGN(total_size, KVX_ABI_STACK_ALIGNMENT);
/* wb_size: write back size, the size we will need to write back to user
* provided buffer. In theory it should always be cif->flags which is
* cif->rtype->size. But libffi API mandates that for integral types
* of size <= system register size, then we *MUST* write back
* the size of system register size.
* in our case, if size <= 8 bytes we must write back 8 bytes.
* floats, complex and structs are not affected, only integrals.
*/
wb_size = handle_small_int_ext(&int_extension_method, cif->rtype);
switch (cif->abi) {
case FFI_SYSV:
DEBUG_PRINT("total_size: %lu\n", total_size);
DEBUG_PRINT("slot fitting args size: %lu\n", slot_fitting_args_size);
DEBUG_PRINT("rvalue: %p\n", rvalue);
DEBUG_PRINT("fn: %p\n", fn);
DEBUG_PRINT("rsize: %u\n", cif->flags);
DEBUG_PRINT("wb_size: %u\n", wb_size);
DEBUG_PRINT("int_extension_method: %u\n", int_extension_method);
local_rvalue = ffi_call_SYSV(total_size, slot_fitting_args_size,
&ecif, rvalue, fn, int_extension_method);
if ((cif->flags <= KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE)
&& (cif->rtype->type != FFI_TYPE_VOID))
memcpy(rvalue, &local_rvalue, wb_size);
break;
default:
abort();
break;
}
}
/* Closures not supported yet */
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
return FFI_BAD_ABI;
}
#endif /* (__kvx__) */

75
src/kvx/ffitarget.h Normal file
View File

@ -0,0 +1,75 @@
/* -----------------------------------------------------------------------
ffitarget.h - Copyright (c) 2020 Kalray
KVX 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;
/* Those values are set depending on return type
* they are used in the assembly code in sysv.S
*/
typedef enum kvx_intext_method {
KVX_RET_NONE = 0,
KVX_RET_SXBD = 1,
KVX_RET_SXHD = 2,
KVX_RET_SXWD = 3,
KVX_RET_ZXBD = 4,
KVX_RET_ZXHD = 5,
KVX_RET_ZXWD = 6
} kvx_intext_method;
#endif
/* ---- Definitions for closures ----------------------------------------- */
/* This is only to allow Python to compile
* but closures are not supported yet
*/
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 0
#define FFI_NATIVE_RAW_API 0
#define FFI_TARGET_SPECIFIC_VARIADIC 1
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif

127
src/kvx/sysv.S Normal file
View File

@ -0,0 +1,127 @@
/* Copyright (c) 2020 Kalray
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. */
#if defined(__kvx__)
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include <kvx/asm.h>
.text
.global ffi_call_SYSV
.type ffi_call_SYSV, @function
.type ffi_prep_args, @function
.align 8
/* ffi_call_SYSV
r0: total size to allocate on stack
r1: size of arg slots
r2: extended cif structure, DO NOT REMOVE: it is used by ffi_prep_args()
r3: return value address
r4: function to call
r5: integer sign extension method to be used
*/
ffi_call_SYSV:
addd $r12 = $r12, -64
so (-32)[$r12] = $r20r21r22r23
;;
sd (0)[$r12] = $r24
;;
get $r23 = $ra
copyd $r20 = $r12
sbfd $r12 = $r0, $r12
;;
copyd $r0 = $r12
copyd $r21 = $r3
copyd $r22 = $r4
copyd $r24 = $r5
call ffi_prep_args
;;
lo $r8r9r10r11 = (64)[$r12]
;;
lo $r4r5r6r7 = (32)[$r12]
;;
lo $r0r1r2r3 = (0)[$r12]
copyd $r12 = $r0
/* $r15 is the register used by the ABI to return big (>32 bytes)
* structs by value.
* It is also referred to as the "struct register" in the ABI.
*/
copyd $r15 = $r21
icall $r22
;;
pcrel $r4 = @pcrel(.Ltable)
cb.deqz $r24 ? .Lend
;;
addx8d $r24 = $r24, $r4
;;
igoto $r24
;;
.Ltable:
0: /* we should never arrive here */
goto .Lerror
nop
;;
1: /* Sign extend byte to double */
sxbd $r0 = $r0
goto .Lend
;;
2: /* Sign extend half to double */
sxhd $r0 = $r0
goto .Lend
;;
3: /* Sign extend word to double */
sxwd $r0 = $r0
goto .Lend
;;
4: /* Zero extend byte to double */
zxbd $r0 = $r0
goto .Lend
;;
5: /* Zero extend half to double */
zxhd $r0 = $r0
goto .Lend
;;
6: /* Zero extend word to double */
zxwd $r0 = $r0
/* Fallthrough to .Lend */
;;
.Lend:
ld $r24 = (0)[$r12]
;;
set $ra = $r23
lo $r20r21r22r23 = (32)[$r20]
addd $r12 = $r20, 64
;;
ret
;;
.Lerror:
errop
;;
#endif /* __kvx__ */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits
#endif

621
src/loongarch64/ffi.c Normal file
View File

@ -0,0 +1,621 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2022 Xu Chenghua <xuchenghua@loongson.cn>
2022 Cheng Lulu <chenglulu@loongson.cn>
Based on RISC-V port
LoongArch 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 <stdint.h>
#if defined(__loongarch_soft_float)
# define ABI_FRLEN 0
#elif defined(__loongarch_single_float)
# define ABI_FRLEN 32
# define ABI_FLOAT float
#elif defined(__loongarch_double_float)
# define ABI_FRLEN 64
# define ABI_FLOAT double
#else
#error unsupported LoongArch floating-point ABI
#endif
#define NARGREG 8
#define STKALIGN 16
#define MAXCOPYARG (2 * sizeof (double))
/* call_context registers
- 8 floating point parameter/result registers.
- 8 integer parameter/result registers.
- 2 registers used by the assembly code to in-place construct its own
stack frame
- frame register
- return register
*/
typedef struct call_context
{
ABI_FLOAT fa[8];
size_t a[10];
} call_context;
typedef struct call_builder
{
call_context *aregs;
int used_integer;
int used_float;
size_t *used_stack;
size_t *stack;
size_t next_struct_area;
} call_builder;
/* Integer (not pointer) less than ABI GRLEN. */
/* FFI_TYPE_INT does not appear to be used. */
#if __SIZEOF_POINTER__ == 8
# define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT64)
#else
# define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT32)
#endif
#if ABI_FRLEN
typedef struct float_struct_info
{
char as_elements;
char type1;
char offset2;
char type2;
} float_struct_info;
#if ABI_FRLEN >= 64
# define IS_FLOAT(type) ((type) >= FFI_TYPE_FLOAT && (type) <= FFI_TYPE_DOUBLE)
#else
# define IS_FLOAT(type) ((type) == FFI_TYPE_FLOAT)
#endif
static ffi_type **
flatten_struct (ffi_type *in, ffi_type **out, ffi_type **out_end)
{
int i;
if (out == out_end)
return out;
if (in->type != FFI_TYPE_STRUCT)
*(out++) = in;
else
for (i = 0; in->elements[i]; i++)
out = flatten_struct (in->elements[i], out, out_end);
return out;
}
/* Structs with at most two fields after flattening, one of which is of
floating point type, are passed in multiple registers if sufficient
registers are available. */
static float_struct_info
struct_passed_as_elements (call_builder *cb, ffi_type *top)
{
float_struct_info ret = {0, 0, 0, 0};
ffi_type *fields[3];
int num_floats, num_ints;
int num_fields = flatten_struct (top, fields, fields + 3) - fields;
if (num_fields == 1)
{
if (IS_FLOAT (fields[0]->type))
{
ret.as_elements = 1;
ret.type1 = fields[0]->type;
}
}
else if (num_fields == 2)
{
num_floats = IS_FLOAT (fields[0]->type) + IS_FLOAT (fields[1]->type);
num_ints = IS_INT (fields[0]->type) + IS_INT (fields[1]->type);
if (num_floats == 0 || num_floats + num_ints != 2)
return ret;
if (cb->used_float + num_floats > NARGREG
|| cb->used_integer + (2 - num_floats) > NARGREG)
return ret;
if (!IS_FLOAT (fields[0]->type) && !IS_FLOAT (fields[1]->type))
return ret;
ret.type1 = fields[0]->type;
ret.type2 = fields[1]->type;
ret.offset2 = FFI_ALIGN (fields[0]->size, fields[1]->alignment);
ret.as_elements = 1;
}
return ret;
}
#endif
/* Allocates a single register, float register, or GRLEN-sized stack slot to a
datum. */
static void
marshal_atom (call_builder *cb, int type, void *data)
{
size_t value = 0;
switch (type)
{
case FFI_TYPE_UINT8:
value = *(uint8_t *) data;
break;
case FFI_TYPE_SINT8:
value = *(int8_t *) data;
break;
case FFI_TYPE_UINT16:
value = *(uint16_t *) data;
break;
case FFI_TYPE_SINT16:
value = *(int16_t *) data;
break;
/* 32-bit quantities are always sign-extended in the ABI. */
case FFI_TYPE_UINT32:
value = *(int32_t *) data;
break;
case FFI_TYPE_SINT32:
value = *(int32_t *) data;
break;
#if __SIZEOF_POINTER__ == 8
case FFI_TYPE_UINT64:
value = *(uint64_t *) data;
break;
case FFI_TYPE_SINT64:
value = *(int64_t *) data;
break;
#endif
case FFI_TYPE_POINTER:
value = *(size_t *) data;
break;
#if ABI_FRLEN >= 32
case FFI_TYPE_FLOAT:
*(float *)(cb->aregs->fa + cb->used_float++) = *(float *) data;
return;
#endif
#if ABI_FRLEN >= 64
case FFI_TYPE_DOUBLE:
(cb->aregs->fa[cb->used_float++]) = *(double *) data;
return;
#endif
default:
FFI_ASSERT (0);
break;
}
if (cb->used_integer == NARGREG)
*cb->used_stack++ = value;
else
cb->aregs->a[cb->used_integer++] = value;
}
static void
unmarshal_atom (call_builder *cb, int type, void *data)
{
size_t value;
switch (type)
{
#if ABI_FRLEN >= 32
case FFI_TYPE_FLOAT:
*(float *) data = *(float *)(cb->aregs->fa + cb->used_float++);
return;
#endif
#if ABI_FRLEN >= 64
case FFI_TYPE_DOUBLE:
*(double *) data = cb->aregs->fa[cb->used_float++];
return;
#endif
}
if (cb->used_integer == NARGREG)
value = *cb->used_stack++;
else
value = cb->aregs->a[cb->used_integer++];
switch (type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
#if __SIZEOF_POINTER__ == 8
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
#endif
case FFI_TYPE_POINTER:
*(ffi_arg *)data = value;
break;
default:
FFI_ASSERT (0);
break;
}
}
/* Allocate and copy a structure that is passed by value on the stack and
return a pointer to it. */
static void *
allocate_and_copy_struct_to_stack (call_builder *cb, void *data,
ffi_type *type)
{
size_t dest = cb->next_struct_area - type->size;
dest = FFI_ALIGN_DOWN (dest, type->alignment);
cb->next_struct_area = dest;
return memcpy ((char *)cb->stack + dest, data, type->size);
}
/* Adds an argument to a call, or a not by reference return value. */
static void
marshal (call_builder *cb, ffi_type *type, int var, void *data)
{
size_t realign[2];
#if ABI_FRLEN
if (!var && type->type == FFI_TYPE_STRUCT)
{
float_struct_info fsi = struct_passed_as_elements (cb, type);
if (fsi.as_elements)
{
marshal_atom (cb, fsi.type1, data);
if (fsi.offset2)
marshal_atom (cb, fsi.type2, ((char *) data) + fsi.offset2);
return;
}
}
if (!var && cb->used_float < NARGREG
&& IS_FLOAT (type->type))
{
marshal_atom (cb, type->type, data);
return;
}
double promoted;
if (var && type->type == FFI_TYPE_FLOAT)
{
/* C standard requires promoting float -> double for variable arg. */
promoted = *(float *) data;
type = &ffi_type_double;
data = &promoted;
}
#endif
if (type->size > 2 * __SIZEOF_POINTER__)
/* Pass by reference. */
{
allocate_and_copy_struct_to_stack (cb, data, type);
data = (char *)cb->stack + cb->next_struct_area;
marshal_atom (cb, FFI_TYPE_POINTER, &data);
}
else if (IS_INT (type->type) || type->type == FFI_TYPE_POINTER)
marshal_atom (cb, type->type, data);
else
{
/* Overlong integers, soft-float floats, and structs without special
float handling are treated identically from this point on. */
/* Variadics are aligned even in registers. */
if (type->alignment > __SIZEOF_POINTER__)
{
if (var)
cb->used_integer = FFI_ALIGN (cb->used_integer, 2);
cb->used_stack
= (size_t *) FFI_ALIGN (cb->used_stack, 2 * __SIZEOF_POINTER__);
}
memcpy (realign, data, type->size);
if (type->size > 0)
marshal_atom (cb, FFI_TYPE_POINTER, realign);
if (type->size > __SIZEOF_POINTER__)
marshal_atom (cb, FFI_TYPE_POINTER, realign + 1);
}
}
/* For arguments passed by reference returns the pointer, otherwise the arg
is copied (up to MAXCOPYARG bytes). */
static void *
unmarshal (call_builder *cb, ffi_type *type, int var, void *data)
{
size_t realign[2];
void *pointer;
#if ABI_FRLEN
if (!var && type->type == FFI_TYPE_STRUCT)
{
float_struct_info fsi = struct_passed_as_elements (cb, type);
if (fsi.as_elements)
{
unmarshal_atom (cb, fsi.type1, data);
if (fsi.offset2)
unmarshal_atom (cb, fsi.type2, ((char *) data) + fsi.offset2);
return data;
}
}
if (!var && cb->used_float < NARGREG
&& IS_FLOAT (type->type))
{
unmarshal_atom (cb, type->type, data);
return data;
}
if (var && type->type == FFI_TYPE_FLOAT)
{
int m = cb->used_integer;
void *promoted
= m < NARGREG ? cb->aregs->a + m : cb->used_stack + m - NARGREG + 1;
*(float *) promoted = *(double *) promoted;
}
#endif
if (type->size > 2 * __SIZEOF_POINTER__)
{
/* Pass by reference. */
unmarshal_atom (cb, FFI_TYPE_POINTER, (char *) &pointer);
return pointer;
}
else if (IS_INT (type->type) || type->type == FFI_TYPE_POINTER)
{
unmarshal_atom (cb, type->type, data);
return data;
}
else
{
/* Overlong integers, soft-float floats, and structs without special
float handling are treated identically from this point on. */
/* Variadics are aligned even in registers. */
if (type->alignment > __SIZEOF_POINTER__)
{
if (var)
cb->used_integer = FFI_ALIGN (cb->used_integer, 2);
cb->used_stack
= (size_t *) FFI_ALIGN (cb->used_stack, 2 * __SIZEOF_POINTER__);
}
if (type->size > 0)
unmarshal_atom (cb, FFI_TYPE_POINTER, realign);
if (type->size > __SIZEOF_POINTER__)
unmarshal_atom (cb, FFI_TYPE_POINTER, realign + 1);
memcpy (data, realign, type->size);
return data;
}
}
static int
passed_by_ref (call_builder *cb, ffi_type *type, int var)
{
#if ABI_FRLEN
if (!var && type->type == FFI_TYPE_STRUCT)
{
float_struct_info fsi = struct_passed_as_elements (cb, type);
if (fsi.as_elements)
return 0;
}
#endif
return type->size > 2 * __SIZEOF_POINTER__;
}
/* Perform machine dependent cif processing. */
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
cif->loongarch_nfixedargs = cif->nargs;
return FFI_OK;
}
/* Perform machine dependent cif processing when we have a variadic
function. */
ffi_status
ffi_prep_cif_machdep_var (ffi_cif *cif, unsigned int nfixedargs,
unsigned int ntotalargs)
{
cif->loongarch_nfixedargs = nfixedargs;
return FFI_OK;
}
/* Low level routine for calling functions. */
extern void ffi_call_asm (void *stack, struct call_context *regs,
void (*fn) (void), void *closure) FFI_HIDDEN;
static void
ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
void *closure)
{
/* This is a conservative estimate, assuming a complex return value and
that all remaining arguments are long long / __int128 */
size_t arg_bytes = cif->bytes;
size_t rval_bytes = 0;
if (rvalue == NULL && cif->rtype->size > 2 * __SIZEOF_POINTER__)
rval_bytes = FFI_ALIGN (cif->rtype->size, STKALIGN);
size_t alloc_size = arg_bytes + rval_bytes + sizeof (call_context);
/* The assembly code will deallocate all stack data at lower addresses
than the argument region, so we need to allocate the frame and the
return value after the arguments in a single allocation. */
size_t alloc_base;
/* Argument region must be 16-byte aligned in LP64 ABIs. */
if (_Alignof(max_align_t) >= STKALIGN)
/* Since sizeof long double is normally 16, the compiler will
guarantee alloca alignment to at least that much. */
alloc_base = (size_t) alloca (alloc_size);
else
alloc_base = FFI_ALIGN (alloca (alloc_size + STKALIGN - 1), STKALIGN);
if (rval_bytes)
rvalue = (void *) (alloc_base + arg_bytes);
call_builder cb;
cb.used_float = cb.used_integer = 0;
cb.aregs = (call_context *) (alloc_base + arg_bytes + rval_bytes);
cb.used_stack = (void *) alloc_base;
cb.stack = (void *) alloc_base;
cb.next_struct_area = arg_bytes;
int return_by_ref = passed_by_ref (&cb, cif->rtype, 0);
if (return_by_ref)
cb.aregs->a[cb.used_integer++] = (size_t)rvalue;
int i;
for (i = 0; i < cif->nargs; i++)
marshal (&cb, cif->arg_types[i], i >= cif->loongarch_nfixedargs,
avalue[i]);
ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure);
cb.used_float = cb.used_integer = 0;
if (!return_by_ref && rvalue)
unmarshal (&cb, cif->rtype, 0, rvalue);
}
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);
}
extern void ffi_closure_asm (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)
{
uint32_t *tramp = (uint32_t *) &closure->tramp[0];
uint64_t fn = (uint64_t) (uintptr_t) ffi_closure_asm;
if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
return FFI_BAD_ABI;
#if defined(FFI_EXEC_STATIC_TRAMP)
if (ffi_tramp_is_present(closure))
{
ffi_tramp_set_parms (closure->ftramp, ffi_closure_asm, closure);
goto out;
}
#endif
/* Fill the dynamic trampoline. We will call ffi_closure_inner with codeloc,
not closure, but as long as the memory is readable it should work. */
tramp[0] = 0x1800000c; /* pcaddi $t0, 0 (i.e. $t0 <- tramp) */
tramp[1] = 0x28c0418d; /* ld.d $t1, $t0, 16 */
tramp[2] = 0x4c0001a0; /* jirl $zero, $t1, 0 */
tramp[3] = 0x03400000; /* nop */
tramp[4] = fn;
tramp[5] = fn >> 32;
__builtin___clear_cache (codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
#if defined(FFI_EXEC_STATIC_TRAMP)
out:
#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}
extern void ffi_go_closure_asm (void) FFI_HIDDEN;
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *))
{
if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
return FFI_BAD_ABI;
closure->tramp = (void *) ffi_go_closure_asm;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}
/* Called by the assembly code with aregs pointing to saved argument registers
and stack pointing to the stacked arguments. Return values passed in
registers will be reloaded from aregs. */
void FFI_HIDDEN
ffi_closure_inner (ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data, size_t *stack, call_context *aregs)
{
void **avalue = alloca (cif->nargs * sizeof (void *));
/* Storage for arguments which will be copied by unmarshal(). We could
theoretically avoid the copies in many cases and use at most 128 bytes
of memory, but allocating disjoint storage for each argument is
simpler. */
char *astorage = alloca (cif->nargs * MAXCOPYARG);
void *rvalue;
call_builder cb;
int return_by_ref;
int i;
cb.aregs = aregs;
cb.used_integer = cb.used_float = 0;
cb.used_stack = stack;
return_by_ref = passed_by_ref (&cb, cif->rtype, 0);
if (return_by_ref)
unmarshal (&cb, &ffi_type_pointer, 0, &rvalue);
else
rvalue = alloca (cif->rtype->size);
for (i = 0; i < cif->nargs; i++)
avalue[i]
= unmarshal (&cb, cif->arg_types[i], i >= cif->loongarch_nfixedargs,
astorage + i * MAXCOPYARG);
fun (cif, rvalue, avalue, user_data);
if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID)
{
cb.used_integer = cb.used_float = 0;
marshal (&cb, cif->rtype, 0, rvalue);
}
}
#if defined(FFI_EXEC_STATIC_TRAMP)
void *
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
{
extern void *trampoline_code_table;
*tramp_size = 16;
/* A mapping size of 64K is chosen to cover the page sizes of 4K, 16K, and
64K. */
*map_size = 1 << 16;
return &trampoline_code_table;
}
#endif

View File

@ -0,0 +1,82 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2022 Xu Chenghua <xuchenghua@loongson.cn>
2022 Cheng Lulu <chenglulu@loongson.cn>
Target configuration macros for LoongArch.
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 __loongarch__
#error \
"libffi was configured for a LoongArch target but this does not appear to be a LoongArch compiler."
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi
{
FFI_FIRST_ABI = 0,
FFI_LP64S,
FFI_LP64F,
FFI_LP64D,
FFI_LAST_ABI,
#if defined(__loongarch64)
#if defined(__loongarch_soft_float)
FFI_DEFAULT_ABI = FFI_LP64S
#elif defined(__loongarch_single_float)
FFI_DEFAULT_ABI = FFI_LP64F
#elif defined(__loongarch_double_float)
FFI_DEFAULT_ABI = FFI_LP64D
#else
#error unsupported LoongArch floating-point ABI
#endif
#else
#error unsupported LoongArch base architecture
#endif
} ffi_abi;
#endif /* LIBFFI_ASM */
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0
#define FFI_EXTRA_CIF_FIELDS \
unsigned loongarch_nfixedargs; \
unsigned loongarch_unused;
#define FFI_TARGET_SPECIFIC_VARIADIC
#endif

327
src/loongarch64/sysv.S Normal file
View File

@ -0,0 +1,327 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2022 Xu Chenghua <xuchenghua@loongson.cn>
2022 Cheng Lulu <chenglulu@loongson.cn>
LoongArch 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>
/* Define aliases so that we can handle all ABIs uniformly. */
#if __SIZEOF_POINTER__ == 8
# define PTRS 8
# define LARG ld.d
# define SARG st.d
#else
# define PTRS 4
# define LARG ld.w
# define SARG st.w
#endif
#if defined(__loongarch_single_float)
# define FLTS 4
# define FLD fld.w
# define FST fst.w
#elif defined(__loongarch_double_float)
# define FLTS 8
# define FLARG fld.d
# define FSARG fst.d
#elif defined(__loongarch_soft_float)
# define FLTS 0
#else
#error unsupported LoongArch floating-point ABI
#endif
.text
.globl ffi_call_asm
.type ffi_call_asm, @function
.hidden ffi_call_asm
/* struct call_context
{
ABI_FLOAT fa[8];
size_t a[10];
}
- 8 floating point parameter/result registers (fa[0] - fa[7])
- 8 integer parameter/result registers (a[0] - a[7])
- 2 registers used by the assembly code to in-place construct its own stack
frame.
- frame pointer (a[8])
- return address (a[9])
void ffi_call_asm (size_t *stackargs, struct call_context *regargs,
void (*fn)(void), void *closure); */
#define FRAME_LEN (8 * FLTS + 10 * PTRS)
ffi_call_asm:
.cfi_startproc
/* We are NOT going to set up an ordinary stack frame. In order to pass
the stacked args to the called function, we adjust our stack pointer
to a0, which is in the _caller's_ alloca area. We establish our own
stack frame at the end of the call_context.
Anything below the arguments will be freed at this point, although
we preserve the call_context so that it can be read back in the
caller. */
.cfi_def_cfa 5, FRAME_LEN # Interim CFA based on a1.
SARG $fp, $a1, FRAME_LEN - 2*PTRS
.cfi_offset 22, -2*PTRS
SARG $ra, $a1, FRAME_LEN - 1*PTRS
.cfi_offset 1, -1*PTRS
addi.d $fp, $a1, FRAME_LEN
move $sp, $a0
.cfi_def_cfa 22, 0 # Our frame is fully set up.
# Load arguments.
move $t1, $a2
move $t2, $a3
#if FLTS
FLARG $fa0, $fp, -FRAME_LEN+0*FLTS
FLARG $fa1, $fp, -FRAME_LEN+1*FLTS
FLARG $fa2, $fp, -FRAME_LEN+2*FLTS
FLARG $fa3, $fp, -FRAME_LEN+3*FLTS
FLARG $fa4, $fp, -FRAME_LEN+4*FLTS
FLARG $fa5, $fp, -FRAME_LEN+5*FLTS
FLARG $fa6, $fp, -FRAME_LEN+6*FLTS
FLARG $fa7, $fp, -FRAME_LEN+7*FLTS
#endif
LARG $a0, $fp, -FRAME_LEN+8*FLTS+0*PTRS
LARG $a1, $fp, -FRAME_LEN+8*FLTS+1*PTRS
LARG $a2, $fp, -FRAME_LEN+8*FLTS+2*PTRS
LARG $a3, $fp, -FRAME_LEN+8*FLTS+3*PTRS
LARG $a4, $fp, -FRAME_LEN+8*FLTS+4*PTRS
LARG $a5, $fp, -FRAME_LEN+8*FLTS+5*PTRS
LARG $a6, $fp, -FRAME_LEN+8*FLTS+6*PTRS
LARG $a7, $fp, -FRAME_LEN+8*FLTS+7*PTRS
/* Call */
jirl $ra, $t1, 0
#if FLTS
/* Save return values - only a0/a1 (fa0/fa1) are used. */
FSARG $fa0, $fp, -FRAME_LEN+0*FLTS
FSARG $fa1, $fp, -FRAME_LEN+1*FLTS
#endif
SARG $a0, $fp, -FRAME_LEN+8*FLTS+0*PTRS
SARG $a1, $fp, -FRAME_LEN+8*FLTS+1*PTRS
/* Restore and return. */
addi.d $sp, $fp, -FRAME_LEN
.cfi_def_cfa 3, FRAME_LEN
LARG $ra, $fp, -1*PTRS
.cfi_restore 1
LARG $fp, $fp, -2*PTRS
.cfi_restore 22
jr $ra
.cfi_endproc
.size ffi_call_asm, .-ffi_call_asm
/* ffi_closure_asm. Expects address of the passed-in ffi_closure in t0.
void ffi_closure_inner (ffi_cif *cif,
void (*fun)(ffi_cif *, void *, void **, void *),
void *user_data,
size_t *stackargs, struct call_context *regargs) */
.globl ffi_closure_asm
.hidden ffi_closure_asm
.type ffi_closure_asm, @function
ffi_closure_asm:
.cfi_startproc
addi.d $sp, $sp, -FRAME_LEN
.cfi_def_cfa_offset FRAME_LEN
/* Make a frame. */
SARG $fp, $sp, FRAME_LEN - 2*PTRS
.cfi_offset 22, -2*PTRS
SARG $ra, $sp, FRAME_LEN - 1*PTRS
.cfi_offset 1, -1*PTRS
addi.d $fp, $sp, FRAME_LEN
/* Save arguments. */
#if FLTS
FSARG $fa0, $sp, 0*FLTS
FSARG $fa1, $sp, 1*FLTS
FSARG $fa2, $sp, 2*FLTS
FSARG $fa3, $sp, 3*FLTS
FSARG $fa4, $sp, 4*FLTS
FSARG $fa5, $sp, 5*FLTS
FSARG $fa6, $sp, 6*FLTS
FSARG $fa7, $sp, 7*FLTS
#endif
SARG $a0, $sp, 8*FLTS+0*PTRS
SARG $a1, $sp, 8*FLTS+1*PTRS
SARG $a2, $sp, 8*FLTS+2*PTRS
SARG $a3, $sp, 8*FLTS+3*PTRS
SARG $a4, $sp, 8*FLTS+4*PTRS
SARG $a5, $sp, 8*FLTS+5*PTRS
SARG $a6, $sp, 8*FLTS+6*PTRS
SARG $a7, $sp, 8*FLTS+7*PTRS
/* Enter C */
LARG $a0, $t0, FFI_TRAMPOLINE_SIZE+0*PTRS
LARG $a1, $t0, FFI_TRAMPOLINE_SIZE+1*PTRS
LARG $a2, $t0, FFI_TRAMPOLINE_SIZE+2*PTRS
addi.d $a3, $sp, FRAME_LEN
move $a4, $sp
bl ffi_closure_inner
/* Return values. */
#if FLTS
FLARG $fa0, $sp, 0*FLTS
FLARG $fa1, $sp, 1*FLTS
#endif
LARG $a0, $sp, 8*FLTS+0*PTRS
LARG $a1, $sp, 8*FLTS+1*PTRS
/* Restore and return. */
LARG $ra, $sp, FRAME_LEN-1*PTRS
.cfi_restore 1
LARG $fp, $sp, FRAME_LEN-2*PTRS
.cfi_restore 22
addi.d $sp, $sp, FRAME_LEN
.cfi_def_cfa_offset 0
jr $ra
.cfi_endproc
.size ffi_closure_asm, .-ffi_closure_asm
/* Static trampoline code table, in which each element is a trampoline.
The trampoline clobbers t0 and t1, but we don't save them on the stack
because our psABI explicitly says they are scratch registers, at least for
ELF. Our dynamic trampoline is already clobbering them anyway.
The trampoline has two parameters - target code to jump to and data for
the target code. The trampoline extracts the parameters from its parameter
block (see tramp_table_map()). The trampoline saves the data address in
t0 and jumps to the target code. As ffi_closure_asm() already expects the
data address to be in t0, we don't need a "ffi_closure_asm_alt". */
#if defined(FFI_EXEC_STATIC_TRAMP)
.align 16
.globl trampoline_code_table
.hidden trampoline_code_table
.type trampoline_code_table, @function
trampoline_code_table:
.rept 65536 / 16
pcaddu12i $t1, 16 # 65536 >> 12
ld.d $t0, $t1, 0
ld.d $t1, $t1, 8
jirl $zero, $t1, 0
.endr
.size trampoline_code_table, .-trampoline_code_table
.align 2
#endif
/* ffi_go_closure_asm. Expects address of the passed-in ffi_go_closure in t2.
void ffi_closure_inner (ffi_cif *cif,
void (*fun)(ffi_cif *, void *, void **, void *),
void *user_data,
size_t *stackargs, struct call_context *regargs) */
.globl ffi_go_closure_asm
.hidden ffi_go_closure_asm
.type ffi_go_closure_asm, @function
ffi_go_closure_asm:
.cfi_startproc
addi.d $sp, $sp, -FRAME_LEN
.cfi_def_cfa_offset FRAME_LEN
/* Make a frame. */
SARG $fp, $sp, FRAME_LEN - 2*PTRS
.cfi_offset 22, -2*PTRS
SARG $ra, $sp, FRAME_LEN - 1*PTRS
.cfi_offset 1, -1*PTRS
addi.d $fp, $sp, FRAME_LEN
/* Save arguments. */
#if FLTS
FSARG $fa0, $sp, 0*FLTS
FSARG $fa1, $sp, 1*FLTS
FSARG $fa2, $sp, 2*FLTS
FSARG $fa3, $sp, 3*FLTS
FSARG $fa4, $sp, 4*FLTS
FSARG $fa5, $sp, 5*FLTS
FSARG $fa6, $sp, 6*FLTS
FSARG $fa7, $sp, 7*FLTS
#endif
SARG $a0, $sp, 8*FLTS+0*PTRS
SARG $a1, $sp, 8*FLTS+1*PTRS
SARG $a2, $sp, 8*FLTS+2*PTRS
SARG $a3, $sp, 8*FLTS+3*PTRS
SARG $a4, $sp, 8*FLTS+4*PTRS
SARG $a5, $sp, 8*FLTS+5*PTRS
SARG $a6, $sp, 8*FLTS+6*PTRS
SARG $a7, $sp, 8*FLTS+7*PTRS
/* Enter C */
LARG $a0, $t2, 1*PTRS
LARG $a1, $t2, 2*PTRS
move $a2, $t2
addi.d $a3, $sp, FRAME_LEN
move $a4, $sp
bl ffi_closure_inner
/* Return values. */
#if FLTS
FLARG $fa0, $sp, 0*FLTS
FLARG $fa1, $sp, 1*FLTS
#endif
LARG $a0, $sp, 8*FLTS+0*PTRS
LARG $a1, $sp, 8*FLTS+1*PTRS
/* Restore and return. */
LARG $ra, $sp, FRAME_LEN-1*PTRS
.cfi_restore 1
LARG $fp, $sp, FRAME_LEN-2*PTRS
.cfi_restore 22
addi.d $sp, $sp, FRAME_LEN
.cfi_def_cfa_offset 0
jr $ra
.cfi_endproc
.size ffi_go_closure_asm, .-ffi_go_closure_asm
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits
#endif

View File

@ -1,8 +1,9 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2004 Renesas Technology
Copyright (c) 2008 Red Hat, Inc.
M32R Foreign Function Interface
Copyright (c) 2022 Anthony Green
M32R Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -63,7 +64,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
if (((*p_arg)->alignment - 1) & (unsigned) argp)
argp = (char *) FFI_ALIGN (argp, (*p_arg)->alignment);
if (avn != 0)
if (avn != 0)
{
avn--;
z = (*p_arg)->size;
@ -76,19 +77,19 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
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:
z = (*p_arg)->size;
if ((*p_arg)->alignment != 1)
@ -131,7 +132,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
argp += z;
}
}
return;
}
@ -178,24 +179,40 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
ffi_type **arg_types = cif->arg_types;
int i, nargs = cif->nargs;
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) &&
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca (cif->rtype->size);
}
else
ecif.rvalue = rvalue;
switch (cif->abi)
ecif.rvalue = rvalue;
/* If we have any large structure arguments, make a copy so we are passing
by value. */
for (i = 0; i < nargs; i++)
{
ffi_type *at = arg_types[i];
int size = at->size;
if (at->type == FFI_TYPE_STRUCT && size > 4)
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);
avalue[i] = argcopy;
}
}
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
if (cif->rtype->type == FFI_TYPE_STRUCT)
{

View File

@ -31,6 +31,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef __GNUC__
# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
@ -39,7 +40,9 @@
#endif
#ifndef USE__BUILTIN___CLEAR_CACHE
# if defined(__OpenBSD__)
# if defined(__FreeBSD__)
# include <machine/sysarch.h>
# elif defined(__OpenBSD__)
# include <mips64/sysarch.h>
# else
# include <sys/cachectl.h>
@ -75,22 +78,39 @@ static void ffi_prep_args(char *stack,
{
int i;
void **p_argv;
char *argp;
char *argp, *argp_f;
ffi_type **p_arg;
memset(stack, 0, bytes);
#ifdef FFI_MIPS_N32
int soft_float = (ecif->cif->abi == FFI_N32_SOFT_FLOAT
|| ecif->cif->abi == FFI_N64_SOFT_FLOAT);
/* If more than 8 double words are used, the remainder go
on the stack. We reorder stuff on the stack here to
support this easily. */
if (bytes > 8 * sizeof(ffi_arg))
argp = &stack[bytes - (8 * sizeof(ffi_arg))];
/* if ret is _Complex long double, args reg shift2, and a0 should holds pointer to rvalue */
if (ecif->cif->rtype->type == FFI_TYPE_COMPLEX && ecif->cif->rtype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
{
if (bytes + 16 > 8 * sizeof(ffi_arg))
argp = &stack[bytes - (8 * sizeof(ffi_arg))];
else
argp = stack;
* (unsigned long *) argp = (unsigned long) ecif->rvalue;
argp += 16;
}
else
argp = stack;
{
if (bytes > 8 * sizeof(ffi_arg))
argp = &stack[bytes - (8 * sizeof(ffi_arg))];
else
argp = stack;
}
#else
argp = stack;
#endif
memset(stack, 0, bytes);
argp_f = argp;
#ifdef FFI_MIPS_N32
if ( ecif->cif->rstruct_flag != 0 )
@ -131,7 +151,7 @@ static void ffi_prep_args(char *stack,
if (type == FFI_TYPE_POINTER)
type = (ecif->cif->abi == FFI_N64
|| ecif->cif->abi == FFI_N64_SOFT_FLOAT)
? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
? FFI_TYPE_SINT64 : FFI_TYPE_UINT32;
if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
|| ecif->cif->abi == FFI_N64_SOFT_FLOAT))
@ -181,6 +201,25 @@ static void ffi_prep_args(char *stack,
#endif
break;
#ifdef FFI_MIPS_N32
case FFI_TYPE_COMPLEX:
/* expand from 4+4 to 8+8 if pass with fpr reg */
/* argp will wind back to stack when we process all of reg args */
/* all var_args passed with gpr, should be expand */
if(!soft_float
&& (*p_arg)->elements[0]->type == FFI_TYPE_FLOAT
&& argp>=argp_f
&& i < ecif->cif->mips_nfixedargs)
{
*(float *) argp = *(float *)(* p_argv);
argp += z;
char *tmp = (void *) (*p_argv);
*(float *) argp = *(float *)(tmp+4);
}
else
memcpy(argp, *p_argv, (*p_arg)->size);
break;
#endif
/* This can only happen with 64bit slots. */
case FFI_TYPE_FLOAT:
*(float *) argp = *(float *)(* p_argv);
@ -233,6 +272,24 @@ static void ffi_prep_args(char *stack,
passed in an integer register". This code traverses structure
definitions and generates the appropriate flags. */
static int
calc_n32_struct_flags_element(unsigned *flags, ffi_type *e,
unsigned *loc, unsigned *arg_reg)
{
/* Align this object. */
*loc = FFI_ALIGN(*loc, e->alignment);
if (e->type == FFI_TYPE_DOUBLE)
{
/* Already aligned to FFI_SIZEOF_ARG. */
*arg_reg = *loc / FFI_SIZEOF_ARG;
if (*arg_reg > 7)
return 1;
*flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
}
*loc += e->size;
return 0;
}
static unsigned
calc_n32_struct_flags(int soft_float, ffi_type *arg,
unsigned *loc, unsigned *arg_reg)
@ -247,19 +304,16 @@ calc_n32_struct_flags(int soft_float, ffi_type *arg,
while ((e = arg->elements[index]))
{
/* Align this object. */
*loc = FFI_ALIGN(*loc, e->alignment);
if (e->type == FFI_TYPE_DOUBLE)
if (e->type == FFI_TYPE_COMPLEX)
{
/* Already aligned to FFI_SIZEOF_ARG. */
*arg_reg = *loc / FFI_SIZEOF_ARG;
if (*arg_reg > 7)
break;
flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
*loc += e->size;
if (calc_n32_struct_flags_element(&flags, e->elements[0], loc, arg_reg))
break;
if (calc_n32_struct_flags_element(&flags, e->elements[0], loc, arg_reg))
break;
}
else
*loc += e->size;
if (calc_n32_struct_flags_element(&flags, e, loc, arg_reg))
break;
index++;
}
/* Next Argument register at alignment of FFI_SIZEOF_ARG. */
@ -271,7 +325,7 @@ calc_n32_struct_flags(int soft_float, ffi_type *arg,
static unsigned
calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
{
unsigned flags = 0;
unsigned flags;
unsigned small = FFI_TYPE_SMALLSTRUCT;
ffi_type *e;
@ -290,33 +344,48 @@ calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
e = arg->elements[0];
if (e->type == FFI_TYPE_DOUBLE)
flags = FFI_TYPE_DOUBLE;
else if (e->type == FFI_TYPE_FLOAT)
flags = FFI_TYPE_FLOAT;
if (flags && (e = arg->elements[1]))
if (e->type == FFI_TYPE_COMPLEX)
{
if (e->type == FFI_TYPE_DOUBLE)
flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
else if (e->type == FFI_TYPE_FLOAT)
flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
else
int type = e->elements[0]->type;
if (type != FFI_TYPE_DOUBLE && type != FFI_TYPE_FLOAT)
return small;
if (flags && (arg->elements[2]))
if (arg->elements[1])
{
/* There are three arguments and the first two are
floats! This must be passed the old way. */
/* Two floating point fields with more fields!
This must be passed the old way. */
return small;
}
if (soft_float)
flags += FFI_TYPE_STRUCT_SOFT;
flags = (type << FFI_FLAG_BITS) + type;
}
else
if (!flags)
return small;
{
if (e->type != FFI_TYPE_DOUBLE && e->type != FFI_TYPE_FLOAT)
return small;
flags = e->type;
if (arg->elements[1])
{
e = arg->elements[1];
if (e->type != FFI_TYPE_DOUBLE && e->type != FFI_TYPE_FLOAT)
return small;
if (arg->elements[2])
{
/* There are three arguments and the first two are
floats! This must be passed the old way. */
return small;
}
flags += e->type << FFI_FLAG_BITS;
}
}
if (soft_float)
flags += FFI_TYPE_STRUCT_SOFT;
return flags;
}
@ -333,7 +402,7 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
* does not have special handling for floating point args.
*/
if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
if (cif->rtype->type != FFI_TYPE_STRUCT && cif->rtype->type != FFI_TYPE_COMPLEX && cif->abi == FFI_O32)
{
if (cif->nargs > 0 && cif->nargs == nfixedargs)
{
@ -401,7 +470,10 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
case FFI_TYPE_STRUCT:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_COMPLEX:
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
if (cif->rtype->type == FFI_TYPE_COMPLEX)
cif->flags += ((*cif->rtype->elements[0]).type) << (FFI_FLAG_BITS * 4);
break;
case FFI_TYPE_SINT64:
@ -419,7 +491,6 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
#ifdef FFI_MIPS_N32
/* Set the flags necessary for N32 processing */
{
int type;
unsigned arg_reg = 0;
unsigned loc = 0;
unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
@ -451,29 +522,14 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
while (count-- > 0 && arg_reg < 8)
{
type = (cif->arg_types)[index]->type;
ffi_type *t = cif->arg_types[index];
// Pass variadic arguments in integer registers even if they're floats
if (soft_float || index >= nfixedargs)
{
switch (type)
{
case FFI_TYPE_FLOAT:
type = FFI_TYPE_UINT32;
break;
case FFI_TYPE_DOUBLE:
type = FFI_TYPE_UINT64;
break;
default:
break;
}
}
switch (type)
switch (t->type)
{
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
cif->flags +=
((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
if (!soft_float && index < nfixedargs)
cif->flags += t->type << (arg_reg * FFI_FLAG_BITS);
arg_reg++;
break;
case FFI_TYPE_LONGDOUBLE:
@ -489,17 +545,71 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
cif->flags +=
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
arg_reg++;
if (arg_reg >= 8)
continue;
cif->flags +=
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
arg_reg++;
}
break;
case FFI_TYPE_COMPLEX:
switch (t->elements[0]->type)
{
case FFI_TYPE_LONGDOUBLE:
arg_reg = FFI_ALIGN(arg_reg, 2);
if (soft_float || index >= nfixedargs)
{
arg_reg += 2;
}
else
{
cif->flags +=
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
arg_reg++;
if (arg_reg >= 8)
continue;
cif->flags +=
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
arg_reg++;
if (arg_reg >= 8)
continue;
}
/* passthrough */
case FFI_TYPE_FLOAT:
// one fpr can only holds one arg even it is single
cif->bytes += 16;
/* passthrough */
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_DOUBLE:
if (soft_float || index >= nfixedargs)
{
arg_reg += 2;
}
else
{
uint32_t type = t->elements[0]->type != FFI_TYPE_LONGDOUBLE? t->elements[0]->type: FFI_TYPE_DOUBLE;
cif->flags +=
(type << (arg_reg * FFI_FLAG_BITS));
arg_reg++;
if (arg_reg >= 8)
continue;
cif->flags +=
(type << (arg_reg * FFI_FLAG_BITS));
arg_reg++;
}
break;
default:
arg_reg += 2;
break;
}
break;
case FFI_TYPE_STRUCT:
loc = arg_reg * FFI_SIZEOF_ARG;
cif->flags += calc_n32_struct_flags(soft_float || index >= nfixedargs,
(cif->arg_types)[index],
&loc, &arg_reg);
t, &loc, &arg_reg);
break;
default:
@ -537,7 +647,7 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
case FFI_TYPE_POINTER:
if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
cif->flags += FFI_TYPE_UINT32 << (FFI_FLAG_BITS * 8);
else
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
break;
@ -561,8 +671,9 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
two doubles. */
if (soft_float)
{
cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
/* if ret is long double, the ret is given by v0 and a0, no idea why
* Let's us VOID | VOID | LONGDOUBLE for it*/
cif->flags += FFI_TYPE_LONGDOUBLE << (FFI_FLAG_BITS * 8);
}
else
{
@ -572,13 +683,44 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
<< (4 + (FFI_FLAG_BITS * 8));
}
break;
case FFI_TYPE_COMPLEX:
{
int type = cif->rtype->elements[0]->type;
cif->flags += (FFI_TYPE_COMPLEX << (FFI_FLAG_BITS * 8));
if (soft_float || (type != FFI_TYPE_FLOAT && type != FFI_TYPE_DOUBLE && type != FFI_TYPE_LONGDOUBLE))
{
switch (type)
{
case FFI_TYPE_DOUBLE:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_INT:
type = FFI_TYPE_SMALLSTRUCT2;
break;
case FFI_TYPE_LONGDOUBLE:
type = FFI_TYPE_LONGDOUBLE;
break;
case FFI_TYPE_FLOAT:
default:
type = FFI_TYPE_SMALLSTRUCT;
}
cif->flags += type << (4 + (FFI_FLAG_BITS * 8));
}
else
{
//cif->flags += (type + (type << FFI_FLAG_BITS))
// << (4 + (FFI_FLAG_BITS * 8));
cif->flags += type << (4 + (FFI_FLAG_BITS * 8));
}
break;
}
default:
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
break;
}
}
#endif
return FFI_OK;
}
@ -616,7 +758,7 @@ void ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
/* value address then we need to make one */
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
(cif->rtype->type == FFI_TYPE_STRUCT || cif->rtype->type == FFI_TYPE_COMPLEX))
ecif.rvalue = alloca(cif->rtype->size);
else
ecif.rvalue = rvalue;
@ -777,11 +919,13 @@ ffi_prep_closure_loc (ffi_closure *closure,
closure->fun = fun;
closure->user_data = user_data;
#if !defined(__FreeBSD__)
#ifdef USE__BUILTIN___CLEAR_CACHE
__builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
#else
cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
#endif
#endif /* ! __FreeBSD__ */
return FFI_OK;
}
@ -826,6 +970,11 @@ ffi_closure_mips_inner_O32 (ffi_cif *cif,
argn = 1;
seen_int = 1;
}
if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_COMPLEX)
{
rvalue = fpr;
argn = 1;
}
i = 0;
avn = cif->nargs;
@ -898,6 +1047,9 @@ ffi_closure_mips_inner_O32 (ffi_cif *cif,
}
else
{
if (cif->rtype->type == FFI_TYPE_COMPLEX) {
__asm__ volatile ("move $v1, %0" : : "r"(cif->rtype->size));
}
return cif->rtype->type;
}
}
@ -987,6 +1139,8 @@ ffi_closure_mips_inner_N32 (ffi_cif *cif,
#endif
argn = 1;
}
if (cif->rtype->type == FFI_TYPE_COMPLEX && cif->rtype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
argn = 2;
i = 0;
avn = cif->nargs;
@ -1011,6 +1165,31 @@ ffi_closure_mips_inner_N32 (ffi_cif *cif,
#endif
avaluep[i] = (char *) argp;
}
else if (arg_types[i]->type == FFI_TYPE_COMPLEX && arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
{
argp = (argn >= 8 || i >= cif->mips_nfixedargs || soft_float) ? ar + argn : fpr + argn;
avaluep[i] = (char *) argp;
}
else if (arg_types[i]->type == FFI_TYPE_COMPLEX && arg_types[i]->elements[0]->type == FFI_TYPE_LONGDOUBLE)
{
/* align long double */
argn += ((argn & 0x1)? 1 : 0);
argp = (argn >= 8 || i >= cif->mips_nfixedargs || soft_float) ? ar + argn : fpr + argn;
avaluep[i] = (char *) argp;
}
else if (arg_types[i]->type == FFI_TYPE_COMPLEX && arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT)
{
if (argn >= 8 || i >= cif->mips_nfixedargs || soft_float)
argp = ar + argn;
else
{
argp = fpr + argn;
/* the normal args for function holds 8bytes, while here we convert it to ptr */
uint32_t *tmp = (uint32_t *)argp;
tmp[1] = tmp[2];
}
avaluep[i] = (char *) argp;
}
else
{
unsigned type = arg_types[i]->type;
@ -1023,10 +1202,10 @@ ffi_closure_mips_inner_N32 (ffi_cif *cif,
/* The size of a pointer depends on the ABI */
if (type == FFI_TYPE_POINTER)
type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
? FFI_TYPE_SINT64 : FFI_TYPE_UINT32;
if (soft_float && type == FFI_TYPE_FLOAT)
type = FFI_TYPE_UINT32;
type = FFI_TYPE_SINT32;
switch (type)
{

View File

@ -41,7 +41,7 @@
#define _MIPS_SIM_ABI32 1
#define _MIPS_SIM_NABI32 2
#define _MIPS_SIM_ABI64 3
#elif !defined(__OpenBSD__)
#elif !defined(__OpenBSD__) && !defined(__FreeBSD__)
# include <sgidefs.h>
#endif
@ -80,6 +80,7 @@
# endif
#endif
#define FFI_TARGET_HAS_COMPLEX_TYPE 1
#define FFI_FLAG_BITS 2
/* SGI's strange assembler requires that we multiply by 4 rather
@ -111,6 +112,12 @@
#define FFI_TYPE_STRUCT_SMALL 93
#define FFI_TYPE_STRUCT_SMALL2 109
#define FFI_TYPE_COMPLEX_SMALL 95
#define FFI_TYPE_COMPLEX_SMALL2 111
#define FFI_TYPE_COMPLEX_FF 47
#define FFI_TYPE_COMPLEX_DD 63
#define FFI_TYPE_COMPLEX_LDLD 79
/* and for n32 soft float, add 16 * 2^4 */
#define FFI_TYPE_STRUCT_D_SOFT 317
#define FFI_TYPE_STRUCT_F_SOFT 301

View File

@ -114,6 +114,16 @@ loadregs:
REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
# when retval is _Complex long double, $f12/$a0, $f13/$a1 will be skipped
# no idea why, but gcc does it.
SRL t4, t6, 8*FFI_FLAG_BITS
move t8, t6
bne t4, FFI_TYPE_COMPLEX_LDLD, loadregs1
SLL t8, t6, 2*FFI_FLAG_BITS
loadregs1:
#ifdef __mips_soft_float
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
@ -124,7 +134,7 @@ loadregs:
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
#else
and t4, t6, ((1<<FFI_FLAG_BITS)-1)
and t4, t8, ((1<<FFI_FLAG_BITS)-1)
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
beqz t4, arg1_next
bne t4, FFI_TYPE_FLOAT, arg1_doublep
@ -134,7 +144,7 @@ arg1_doublep:
l.d $f12, 0*FFI_SIZEOF_ARG(t9)
arg1_next:
SRL t4, t6, 1*FFI_FLAG_BITS
SRL t4, t8, 1*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
beqz t4, arg2_next
@ -145,7 +155,7 @@ arg2_doublep:
l.d $f13, 1*FFI_SIZEOF_ARG(t9)
arg2_next:
SRL t4, t6, 2*FFI_FLAG_BITS
SRL t4, t8, 2*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
beqz t4, arg3_next
@ -156,7 +166,7 @@ arg3_doublep:
l.d $f14, 2*FFI_SIZEOF_ARG(t9)
arg3_next:
SRL t4, t6, 3*FFI_FLAG_BITS
SRL t4, t8, 3*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
beqz t4, arg4_next
@ -167,7 +177,7 @@ arg4_doublep:
l.d $f15, 3*FFI_SIZEOF_ARG(t9)
arg4_next:
SRL t4, t6, 4*FFI_FLAG_BITS
SRL t4, t8, 4*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
beqz t4, arg5_next
@ -178,7 +188,7 @@ arg5_doublep:
l.d $f16, 4*FFI_SIZEOF_ARG(t9)
arg5_next:
SRL t4, t6, 5*FFI_FLAG_BITS
SRL t4, t8, 5*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
beqz t4, arg6_next
@ -189,7 +199,7 @@ arg6_doublep:
l.d $f17, 5*FFI_SIZEOF_ARG(t9)
arg6_next:
SRL t4, t6, 6*FFI_FLAG_BITS
SRL t4, t8, 6*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
beqz t4, arg7_next
@ -200,7 +210,7 @@ arg7_doublep:
l.d $f18, 6*FFI_SIZEOF_ARG(t9)
arg7_next:
SRL t4, t6, 7*FFI_FLAG_BITS
SRL t4, t8, 7*FFI_FLAG_BITS
and t4, ((1<<FFI_FLAG_BITS)-1)
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
beqz t4, arg8_next
@ -212,7 +222,7 @@ arg8_doublep:
arg8_next:
#endif
callit:
callit:
# Load the function pointer
REG_L t9, 5*FFI_SIZEOF_ARG($fp)
@ -226,14 +236,21 @@ callit:
# Shift the return type flag over
SRL t6, 8*FFI_FLAG_BITS
beq t6, FFI_TYPE_SINT32, retint
bne t6, FFI_TYPE_INT, retfloat
beq t6, FFI_TYPE_SINT32, retint
bne t6, FFI_TYPE_INT, retuint32
retint:
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
b epilogue
retuint32:
bne t6, FFI_TYPE_UINT32, retfloat
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
sw v0, 0(t4)
b epilogue
retfloat:
#ifndef __mips_soft_float
bne t6, FFI_TYPE_FLOAT, retdouble
@ -249,7 +266,7 @@ retdouble:
s.d $f0, 0(t4)
b epilogue
retstruct_d:
retstruct_d:
bne t6, FFI_TYPE_STRUCT_D, retstruct_f
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
@ -263,16 +280,37 @@ retstruct_f:
s.s $f0, 0(t4)
b epilogue
retstruct_d_d:
bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
retstruct_d_d:
bne t6, FFI_TYPE_STRUCT_DD, retcomplex_d_d
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
s.d $f0, 0(t4)
s.d $f2, 8(t4)
b epilogue
retcomplex_d_d:
bne t6, FFI_TYPE_COMPLEX_DD, retcomplex_ld_ld
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
s.d $f0, 0(t4)
s.d $f2, 8(t4)
b epilogue
retcomplex_ld_ld:
bne t6, FFI_TYPE_COMPLEX_LDLD, retstruct_f_f
jal t9
b epilogue
retstruct_f_f:
bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
retstruct_f_f:
bne t6, FFI_TYPE_STRUCT_FF, retcomplex_f_f
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
s.s $f0, 0(t4)
s.s $f2, 4(t4)
b epilogue
retcomplex_f_f:
bne t6, FFI_TYPE_COMPLEX_FF, retstruct_d_f
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
s.s $f0, 0(t4)
@ -315,7 +353,7 @@ retstruct_d_d_soft:
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
sd v0, 0(t4)
sd v1, 8(t4)
sd a0, 8(t4) # not typo, it is a0, I have no idea, gcc does do it
b epilogue
retstruct_f_f_soft:
@ -339,7 +377,7 @@ retstruct_f_d_soft:
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
sw v0, 0(t4)
sd v1, 8(t4)
sd a0, 8(t4) # not typo, it is a0, I have no idea, gcc does do it
b epilogue
retstruct_small:
@ -350,14 +388,37 @@ retstruct_small:
b epilogue
retstruct_small2:
bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
bne t6, FFI_TYPE_STRUCT_SMALL2, retlongdouble_soft
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
REG_S v1, 8(t4)
b epilogue
retstruct:
retlongdouble_soft:
bne t6, FFI_TYPE_LONGDOUBLE, retcomplex_small
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
REG_S a0, 8(t4) # not typo, it is a0, I have no idea, gcc does do it
b epilogue
retcomplex_small:
bne t6, FFI_TYPE_COMPLEX_SMALL, retcomplex_small2
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
b epilogue
retcomplex_small2:
bne t6, FFI_TYPE_COMPLEX_SMALL2, retstruct
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
REG_S v1, 8(t4)
b epilogue
retstruct:
noretval:
jal t9
@ -403,7 +464,7 @@ epilogue:
*/
#define SIZEOF_FRAME2 (20 * FFI_SIZEOF_ARG)
#define A7_OFF2 (19 * FFI_SIZEOF_ARG)
#define A6_OFF2 (18 * FFI_SIZEOF_ARG)
#define A5_OFF2 (17 * FFI_SIZEOF_ARG)
@ -451,8 +512,13 @@ ffi_go_closure_N32:
# Call ffi_closure_mips_inner_N32 to do the real work.
LA t9, ffi_closure_mips_inner_N32
#if _MIPS_SIM==_ABIN32
lw a0, 4($15) # cif
lw a1, 8($15) # fun
#else
REG_L a0, 8($15) # cif
REG_L a1, 16($15) # fun
#endif
move a2, t7 # userdata=closure
ADDU a3, $sp, V0_OFF2 # rvalue
ADDU a4, $sp, A0_OFF2 # ar
@ -485,10 +551,17 @@ ffi_closure_N32:
# Call ffi_closure_mips_inner_N32 to do the real work.
LA t9, ffi_closure_mips_inner_N32
#if _MIPS_SIM==_ABIN32
lw a0, 20($12) # cif
lw a1, 24($12) # fun
lw a2, 28($12) # user_data
#else
REG_L a0, 56($12) # cif
REG_L a1, 64($12) # fun
REG_L a2, 72($12) # user_data
#endif
ADDU a3, $sp, V0_OFF2
# FIXME: a4 does work, while if ret is _Complex long double, it will overwrite Fn_OFF2
ADDU a4, $sp, A0_OFF2
ADDU a5, $sp, F12_OFF2
@ -513,10 +586,15 @@ $do_closure:
jalr t9
# Return flags are in v0
bne v0, FFI_TYPE_SINT32, cls_retint
bne v0, FFI_TYPE_SINT32, cls_retuint32
lw v0, V0_OFF2($sp)
b cls_epilogue
cls_retuint32:
bne v0, FFI_TYPE_UINT32, cls_retint
lwu v0, V0_OFF2($sp)
b cls_epilogue
cls_retint:
bne v0, FFI_TYPE_INT, cls_retfloat
REG_L v0, V0_OFF2($sp)
@ -544,17 +622,29 @@ cls_retstruct_f:
b cls_epilogue
cls_retstruct_d_d:
bne v0, FFI_TYPE_STRUCT_DD, cls_retstruct_f_f
bne v0, FFI_TYPE_STRUCT_DD, cls_retcomplex_d_d
l.d $f0, V0_OFF2($sp)
l.d $f2, V1_OFF2($sp)
b cls_epilogue
cls_retcomplex_d_d:
bne v0, FFI_TYPE_COMPLEX_DD, cls_retcomplex_f_f
l.d $f0, V0_OFF2($sp)
l.d $f2, V1_OFF2($sp)
b cls_epilogue
cls_retstruct_f_f:
bne v0, FFI_TYPE_STRUCT_FF, cls_retstruct_d_f
cls_retstruct_f_f:
bne v0, FFI_TYPE_STRUCT_FF, cls_retcomplex_f_f
l.s $f0, V0_OFF2($sp)
l.s $f2, V1_OFF2($sp)
b cls_epilogue
cls_retcomplex_f_f:
bne v0, FFI_TYPE_COMPLEX_FF, cls_retstruct_d_f
l.s $f0, V0_OFF2($sp)
l.s $f2, (V0_OFF2+4)($sp)
b cls_epilogue
cls_retstruct_d_f:
bne v0, FFI_TYPE_STRUCT_DF, cls_retstruct_f_d
l.d $f0, V0_OFF2($sp)
@ -562,12 +652,31 @@ cls_retstruct_d_f:
b cls_epilogue
cls_retstruct_f_d:
bne v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
bne v0, FFI_TYPE_STRUCT_FD, cls_retcomplex_ld_ld
l.s $f0, V0_OFF2($sp)
l.d $f2, V1_OFF2($sp)
b cls_epilogue
#else
cls_longdouble_soft:
bne v0, FFI_TYPE_LONGDOUBLE, cls_retcomplex_ld_ld
REG_L v0, V0_OFF2($sp)
REG_L a0, V1_OFF2($sp) # not typo, it is a0, I have no idea, gcc does do it
b cls_epilogue
#endif
cls_retcomplex_ld_ld:
bne v0, FFI_TYPE_COMPLEX_LDLD, cls_retstruct_small2
REG_L t8, A0_OFF2($sp)
REG_L t9, 16($sp)
REG_S t9, 0(t8)
REG_L t9, 24($sp)
REG_S t9, 8(t8)
REG_L t9, 32($sp)
REG_S t9, 16(t8)
REG_L t9, 40($sp)
REG_S t9, 24(t8)
b cls_epilogue
cls_retstruct_small2:
REG_L v0, V0_OFF2($sp)
REG_L v1, V1_OFF2($sp)
@ -582,7 +691,7 @@ cls_epilogue:
.end ffi_closure_N32
#ifdef __GNUC__
.section .eh_frame,"aw",@progbits
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # length
.LSCIE1:

View File

@ -133,6 +133,7 @@ pass_f_d:
# bne t0, FFI_ARGS_F_D, call_it
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
#endif
call_it:
@ -146,7 +147,8 @@ call_it:
REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
beqz t1, noretval
bne t2, FFI_TYPE_INT, retlonglong
and t1, t2, ((1<<4)-1)
bne t1, FFI_TYPE_INT, retlonglong
jalr t9
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t0)
@ -154,7 +156,7 @@ call_it:
retlonglong:
# Really any 64-bit int, signed or not.
bne t2, FFI_TYPE_UINT64, retfloat
bne t1, FFI_TYPE_UINT64, retfloat
jalr t9
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
REG_S v1, 4(t0)
@ -162,7 +164,7 @@ retlonglong:
b epilogue
retfloat:
bne t2, FFI_TYPE_FLOAT, retdouble
bne t1, FFI_TYPE_FLOAT, retdouble
jalr t9
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
#ifndef __mips_soft_float
@ -173,7 +175,7 @@ retfloat:
b epilogue
retdouble:
bne t2, FFI_TYPE_DOUBLE, noretval
bne t1, FFI_TYPE_DOUBLE, retcomplex
jalr t9
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
#ifndef __mips_soft_float
@ -184,6 +186,48 @@ retdouble:
#endif
b epilogue
retcomplex:
# mask out the complex elements type.
# the struct of flags (bits):
# 0-1: arg0
# 2-3: arg1
# 4-7: return type
# 8-11: rtype elements type: for complex
# Note here: t2 is flags>>4
bne t1, FFI_TYPE_COMPLEX, noretval
jalr t9
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
REG_L t1, A3_OFF($fp) # load the flags word
SRL t1, t1, 8
li t3, 3
beq t1, t3, 3f # double
li t3, 2
beq t1, t3, 2f # float
# FIXME: long double
slti t3, t1, 5
beqz t3, 5f # (u)int8/16/32/64
2:
#ifndef __mips_soft_float
s.s $f0, 0(t0)
s.s $f2, 4(t0)
#else
# FIXME: do nothing can pass all of the testsuite
#endif
b epilogue
3:
#ifndef __mips_soft_float
s.d $f0, 0(t0)
s.d $f2, 8(t0)
#else
# FIXME: do nothing can pass all of the testsuite
#endif
b epilogue
5:
REG_S v1, 4(t0)
REG_S v0, 0(t0)
b epilogue
noretval:
jalr t9
@ -282,9 +326,11 @@ $LCFI12:
li $13, 1 # FFI_O32
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
#ifndef __mips_soft_float
# Store all possible float/double registers.
s.d $f12, FA_0_0_OFF2($fp)
s.d $f14, FA_1_0_OFF2($fp)
#endif
1:
# prepare arguments for ffi_closure_mips_inner_O32
REG_L a0, 4($15) # cif
@ -376,6 +422,19 @@ $do_closure:
li $9, FFI_TYPE_DOUBLE
l.d $f0, V0_OFF2($fp)
beq $8, $9, closure_done
li $9, FFI_TYPE_COMPLEX
bne $8, $9, 1f
li $9, 8
l.s $f0, V0_OFF2($fp)
l.s $f2, V1_OFF2($fp)
beq $3, $9, closure_done
li $9, 16
l.d $f0, V0_OFF2($fp)
l.d $f2, (V0_OFF2+8)($fp)
beq $3, $9, closure_done
#endif
1:
REG_L $3, V1_OFF2($fp)

View File

@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (C) 2012, 2013, 2018 Anthony Green
Moxie Foreign Function Interface
ffi.c - Copyright (C) 2012, 2013, 2018, 2021, 2022 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
@ -54,14 +54,14 @@ void *ffi_prep_args(char *stack, extended_cif *ecif)
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);
@ -70,19 +70,19 @@ void *ffi_prep_args(char *stack, extended_cif *ecif)
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);
}
@ -116,26 +116,28 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
extended_cif *,
unsigned, unsigned,
unsigned *,
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 ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue)
{
extended_cif ecif;
ffi_type **arg_types = cif->arg_types;
int i, nargs = cif->nargs;
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) &&
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
@ -143,10 +145,24 @@ void ffi_call(ffi_cif *cif,
else
ecif.rvalue = rvalue;
switch (cif->abi)
/* If we have any large structure arguments, make a copy so we are passing
by value. */
for (i = 0; i < nargs; i++)
{
ffi_type *at = arg_types[i];
int size = at->size;
if (at->type == FFI_TYPE_STRUCT) /* && size > 4) All struct args?? */
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);
avalue[i] = argcopy;
}
}
switch (cif->abi)
{
case FFI_EABI:
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
default:
@ -172,7 +188,7 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
void *struct_rvalue = (void *) arg1;
/* 6 words reserved for register args + 3 words from jsr */
char *stack_args = frame_pointer + 9*4;
char *stack_args = frame_pointer + 9*4;
/* Lay the register arguments down in a continuous chunk of memory. */
unsigned register_args[6] =
@ -211,7 +227,16 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
avalue[i] = ptr;
break;
case FFI_TYPE_STRUCT:
avalue[i] = *(void**)ptr;
{
if (arg_types[i]->size > 4)
{
void *copy = alloca(arg_types[i]->size);
memcpy(copy, *(void**)ptr, arg_types[i]->size);
avalue[i] = copy;
}
else
avalue[i] = *(void**)ptr;
}
break;
default:
/* This is an 8-byte value. */

View File

@ -37,7 +37,7 @@ void* ffi_prep_args(char *stack, extended_cif *ecif)
ffi_type **arg;
int count = 0;
int nfixedargs;
nfixedargs = ecif->cif->nfixedargs;
arg = ecif->cif->arg_types;
void **argv = ecif->avalue;
@ -47,7 +47,7 @@ void* ffi_prep_args(char *stack, extended_cif *ecif)
*(void **) stack = ecif->rvalue;
stack += 4;
count = 4;
}
}
for(i=0; i<ecif->cif->nargs; i++)
{
@ -55,12 +55,12 @@ void* ffi_prep_args(char *stack, extended_cif *ecif)
if ((nfixedargs == 0) && (count < 24))
{
count = 24;
stack = stacktemp + 24;
stack = stacktemp + 24;
}
nfixedargs--;
s = 4;
switch((*arg)->type)
switch((*arg)->type)
{
case FFI_TYPE_STRUCT:
*(void **)stack = *argv;
@ -94,7 +94,7 @@ void* ffi_prep_args(char *stack, extended_cif *ecif)
{
stack += 4;
count += 4;
}
}
s = (*arg)->size;
memcpy(stack, *argv, s);
break;
@ -133,6 +133,19 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
size += 4;
else
size += 8;
/* If we have any large structure arguments, make a copy so we are passing
by value. */
{
ffi_type *at = cif->arg_types[i];
int size = at->size;
if (at->type == FFI_TYPE_STRUCT) /* && size > 4) All struct args? */
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);
avalue[i] = argcopy;
}
}
}
/* for variadic functions more space is needed on the stack */
@ -148,7 +161,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ecif.avalue = avalue;
ecif.rvalue = rvalue;
switch (cif->abi)
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags);
@ -160,7 +173,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
}
void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
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");
@ -186,7 +199,7 @@ void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
/* preserve struct type return pointer passing */
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
{
ptr += 4;
count = 4;
@ -256,7 +269,7 @@ void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
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));
asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue));
}
}
@ -303,11 +316,11 @@ ffi_prep_closure_loc (ffi_closure* closure,
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
else
if (cif->rtype->size > 4)
cif->flags = FFI_TYPE_UINT64;
@ -325,4 +338,4 @@ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
status = ffi_prep_cif_machdep (cif);
cif->nfixedargs = nfixedargs;
return status;
}
}

View File

@ -421,12 +421,15 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
ffi_cif *cif;
void **avalue;
void *rvalue;
UINT32 ret[2]; /* function can return up to 64-bits in registers */
/* Functions can return up to 64-bits in registers. Return address
must be double word aligned. */
union { double rd; UINT32 ret[2]; } u;
ffi_type **p_arg;
char *tmp;
int i, avn;
unsigned int slot = FIRST_ARG_SLOT;
register UINT32 r28 asm("r28");
ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
cif = closure->cif;
@ -434,7 +437,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
if (cif->flags == FFI_TYPE_STRUCT)
rvalue = (void *)r28;
else
rvalue = &ret[0];
rvalue = &u;
avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
avn = cif->nargs;
@ -529,35 +532,35 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
}
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data);
(c->fun) (cif, rvalue, avalue, c->user_data);
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
ret[1]);
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0],
u.ret[1]);
/* Store the result using the lower 2 bytes of the flags. */
switch (cif->flags)
{
case FFI_TYPE_UINT8:
*(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
*(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24);
break;
case FFI_TYPE_SINT8:
*(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
*(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24);
break;
case FFI_TYPE_UINT16:
*(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
*(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16);
break;
case FFI_TYPE_SINT16:
*(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
*(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16);
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
*(stack - FIRST_ARG_SLOT) = ret[0];
*(stack - FIRST_ARG_SLOT) = u.ret[0];
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
*(stack - FIRST_ARG_SLOT) = ret[0];
*(stack - FIRST_ARG_SLOT - 1) = ret[1];
*(stack - FIRST_ARG_SLOT) = u.ret[0];
*(stack - FIRST_ARG_SLOT - 1) = u.ret[1];
break;
case FFI_TYPE_DOUBLE:
@ -577,7 +580,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
case FFI_TYPE_SMALL_STRUCT4:
tmp = (void*)(stack - FIRST_ARG_SLOT);
tmp += 4 - cif->rtype->size;
memcpy((void*)tmp, &ret[0], cif->rtype->size);
memcpy((void*)tmp, &u, cif->rtype->size);
break;
case FFI_TYPE_SMALL_STRUCT5:
@ -598,7 +601,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
}
memset (ret2, 0, sizeof (ret2));
memcpy ((char *)ret2 + off, ret, 8 - off);
memcpy ((char *)ret2 + off, &u, 8 - off);
*(stack - FIRST_ARG_SLOT) = ret2[0];
*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
@ -630,89 +633,41 @@ ffi_prep_closure_loc (ffi_closure* closure,
void *user_data,
void *codeloc)
{
UINT32 *tramp = (UINT32 *)(closure->tramp);
#ifdef PA_HPUX
UINT32 *tmp;
#endif
ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
/* The layout of a function descriptor. A function pointer with the PLABEL
bit set points to a function descriptor. */
struct pa32_fd
{
UINT32 code_pointer;
UINT32 gp;
};
struct ffi_pa32_trampoline_struct
{
UINT32 code_pointer; /* Pointer to ffi_closure_unix. */
UINT32 fake_gp; /* Pointer to closure, installed as gp. */
UINT32 real_gp; /* Real gp value. */
};
struct ffi_pa32_trampoline_struct *tramp;
struct pa32_fd *fd;
if (cif->abi != FFI_PA32)
return FFI_BAD_ABI;
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */
/* Get function descriptor address for ffi_closure_pa32. */
fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3);
#ifdef PA_LINUX
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
/* Setup trampoline. */
tramp = (struct ffi_pa32_trampoline_struct *)c->tramp;
tramp->code_pointer = fd->code_pointer;
tramp->fake_gp = (UINT32)codeloc & ~3;
tramp->real_gp = fd->gp;
/* Flush d/icache -- have to flush up 2 two lines because of
alignment. */
__asm__ volatile(
"fdc 0(%0)\n\t"
"fdc %1(%0)\n\t"
"fic 0(%%sr4, %0)\n\t"
"fic %1(%%sr4, %0)\n\t"
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n"
:
: "r"((unsigned long)tramp & ~31),
"r"(32 /* stride */)
: "memory");
#endif
#ifdef PA_HPUX
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
/* Flush d/icache -- have to flush three lines because of alignment. */
__asm__ volatile(
"copy %1,%0\n\t"
"fdc,m %2(%0)\n\t"
"fdc,m %2(%0)\n\t"
"fdc,m %2(%0)\n\t"
"ldsid (%1),%0\n\t"
"mtsp %0,%%sr0\n\t"
"copy %1,%0\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n"
: "=&r" ((unsigned long)tmp)
: "r" ((unsigned long)tramp & ~31),
"r" (32/* stride */)
: "memory");
#endif
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
c->cif = cif;
c->user_data = user_data;
c->fun = fun;
return FFI_OK;
}

View File

@ -68,12 +68,7 @@ typedef enum ffi_abi {
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#ifdef PA_LINUX
#define FFI_TRAMPOLINE_SIZE 32
#else
#define FFI_TRAMPOLINE_SIZE 40
#endif
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_TYPE_SMALL_STRUCT2 -1
#define FFI_TYPE_SMALL_STRUCT3 -2

View File

@ -259,7 +259,7 @@ L$done
L$FE1
/* void ffi_closure_pa32(void);
Called with closure argument in %r21 */
Called with closure argument in %r19 */
.SPACE $TEXT$
.SUBSPA $CODE$
@ -285,7 +285,9 @@ L$CFI22
stw %arg2, -44(%r3)
stw %arg3, -48(%r3)
copy %r21, %arg0
/* Retrieve closure pointer and real gp. */
copy %r19, %arg0
ldw 8(%r19), %r19
bl ffi_closure_inner_pa32, %r2
copy %r3, %arg1
ldwm -64(%sp), %r3

View File

@ -252,7 +252,7 @@ ffi_call_pa32:
.LFE1:
/* void ffi_closure_pa32(void);
Called with closure argument in %r21 */
Called with closure argument in %r19 */
.export ffi_closure_pa32,code
.import ffi_closure_inner_pa32,code
@ -277,7 +277,9 @@ ffi_closure_pa32:
stw %arg2, -44(%r3)
stw %arg3, -48(%r3)
copy %r21, %arg0
/* Retrieve closure pointer and real gp. */
copy %r19, %arg0
ldw 8(%r19), %r19
bl ffi_closure_inner_pa32, %r2
copy %r3, %arg1

View File

@ -33,7 +33,10 @@
#include <stdlib.h>
extern void ffi_closure_ASM (void);
#if defined (FFI_GO_CLOSURES)
extern void ffi_go_closure_ASM (void);
#endif
enum {
/* The assembly depends on these exact flags.
@ -909,8 +912,10 @@ ffi_prep_cif_machdep (ffi_cif *cif)
extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
void (*fn)(void), void (*fn2)(void));
#if defined (FFI_GO_CLOSURES)
extern void ffi_call_go_AIX(extended_cif *, long, unsigned, unsigned *,
void (*fn)(void), void (*fn2)(void), void *closure);
#endif
extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
void (*fn)(void), void (*fn2)(void), ffi_type*);
@ -950,6 +955,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
}
}
#if defined (FFI_GO_CLOSURES)
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
void *closure)
@ -981,6 +987,7 @@ ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
break;
}
}
#endif
static void flush_icache(char *);
static void flush_range(char *, int);
@ -1110,6 +1117,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK;
}
#if defined (FFI_GO_CLOSURES)
ffi_status
ffi_prep_go_closure (ffi_go_closure* closure,
ffi_cif* cif,
@ -1133,6 +1141,7 @@ ffi_prep_go_closure (ffi_go_closure* closure,
}
return FFI_OK;
}
#endif
static void
flush_icache(char *addr)
@ -1168,9 +1177,11 @@ ffi_type *
ffi_closure_helper_DARWIN (ffi_closure *, void *,
unsigned long *, ffi_dblfl *);
#if defined (FFI_GO_CLOSURES)
ffi_type *
ffi_go_closure_helper_DARWIN (ffi_go_closure*, void *,
unsigned long *, ffi_dblfl *);
#endif
/* Basically the trampoline invokes ffi_closure_ASM, and on
entry, r11 holds the address of the closure.
@ -1430,6 +1441,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
closure->user_data, rvalue, pgr, pfr);
}
#if defined (FFI_GO_CLOSURES)
ffi_type *
ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue,
unsigned long *pgr, ffi_dblfl *pfr)
@ -1437,4 +1449,4 @@ ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue,
return ffi_closure_helper_common (closure->cif, closure->fun,
closure, rvalue, pgr, pfr);
}
#endif

View File

@ -680,7 +680,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
{
if (vecarg_count < NUM_VEC_ARG_REGISTERS64
&& i < nfixedargs)
memcpy (vec_base.f128++, arg.f128, sizeof (float128));
memcpy (vec_base.f128++, arg.f128++, sizeof (float128));
else
memcpy (next_arg.f128, arg.f128++, sizeof (float128));
if (++next_arg.f128 == gpr_end.f128)

View File

@ -57,7 +57,7 @@ typedef union
double d;
} ffi_dblfl;
#if defined(__FLOAT128_TYPE__)
#if defined(__FLOAT128_TYPE__) && defined(__HAVE_FLOAT128)
typedef _Float128 float128;
#elif defined(__FLOAT128__)
typedef __float128 float128;

View File

@ -29,6 +29,8 @@
#include <fficonfig.h>
#include <ffi.h>
.machine altivec
#ifdef POWERPC64
.hidden ffi_call_LINUX64
.globl ffi_call_LINUX64
@ -36,8 +38,10 @@
.cfi_startproc
# if _CALL_ELF == 2
ffi_call_LINUX64:
# ifndef __PCREL__
addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_call_LINUX64@l
# endif
.localentry ffi_call_LINUX64, . - ffi_call_LINUX64
# else
.section ".opd","aw"
@ -89,9 +93,15 @@ ffi_call_LINUX64:
/* Call ffi_prep_args64. */
mr %r4, %r1
# if defined _CALL_LINUX || _CALL_ELF == 2
# ifdef __PCREL__
bl ffi_prep_args64@notoc
# else
bl ffi_prep_args64
nop
# endif
# else
bl .ffi_prep_args64
nop
# endif
# if _CALL_ELF == 2

View File

@ -30,6 +30,8 @@
.file "linux64_closure.S"
.machine altivec
#ifdef POWERPC64
FFI_HIDDEN (ffi_closure_LINUX64)
.globl ffi_closure_LINUX64
@ -37,8 +39,10 @@
.cfi_startproc
# if _CALL_ELF == 2
ffi_closure_LINUX64:
# ifndef __PCREL__
addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
# endif
.localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
# else
.section ".opd","aw"
@ -190,11 +194,19 @@ ffi_closure_LINUX64:
# make the call
# if defined _CALL_LINUX || _CALL_ELF == 2
# ifdef __PCREL__
bl ffi_closure_helper_LINUX64@notoc
.Lret:
# else
bl ffi_closure_helper_LINUX64
.Lret:
nop
# endif
# else
bl .ffi_closure_helper_LINUX64
# endif
.Lret:
nop
# endif
# now r3 contains the return type
# so use it to look up in a table
@ -460,8 +472,10 @@ ffi_closure_LINUX64:
.cfi_startproc
# if _CALL_ELF == 2
ffi_go_closure_linux64:
# ifndef __PCREL__
addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
# endif
.localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
# else
.section ".opd","aw"

5
src/powerpc/t-aix Normal file
View File

@ -0,0 +1,5 @@
# This file is needed by GCC in order to correctly build AIX FAT
# library for libffi.
# However, it has no sense to include this code here, as it depends
# on GCC multilib architecture.
# Thus, this file is a simple stub replaced in GCC repository.

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
prep_cif.c - Copyright (c) 2011, 2012, 2021 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Copyright (c) 2022 Oracle and/or its affiliates.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -129,7 +130,7 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
cif->rtype = rtype;
cif->flags = 0;
#ifdef _M_ARM64
#if (defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32)
cif->is_variadic = isvariadic;
#endif
#if HAVE_LONG_DOUBLE_VARIANT
@ -231,7 +232,26 @@ ffi_status ffi_prep_cif_var(ffi_cif *cif,
ffi_type *rtype,
ffi_type **atypes)
{
return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
ffi_status rc;
size_t int_size = ffi_type_sint.size;
int i;
rc = ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
if (rc != FFI_OK)
return rc;
for (i = nfixedargs; i < ntotalargs; i++)
{
ffi_type *arg_type = atypes[i];
if (arg_type == &ffi_type_float
|| ((arg_type->type != FFI_TYPE_STRUCT
&& arg_type->type != FFI_TYPE_COMPLEX)
&& arg_type->size < int_size))
return FFI_BAD_ARGTYPE;
}
return FFI_OK;
}
#if FFI_CLOSURES

View File

@ -61,6 +61,7 @@ typedef struct call_builder
int used_integer;
int used_float;
size_t *used_stack;
void *struct_stack;
} call_builder;
/* integer (not pointer) less than ABI XLEN */
@ -227,7 +228,9 @@ static void marshal(call_builder *cb, ffi_type *type, int var, void *data) {
#endif
if (type->size > 2 * __SIZEOF_POINTER__) {
/* pass by reference */
/* copy to stack and pass by reference */
data = memcpy (cb->struct_stack, data, type->size);
cb->struct_stack = (size_t *) FFI_ALIGN ((char *) cb->struct_stack + type->size, __SIZEOF_POINTER__);
marshal_atom(cb, FFI_TYPE_POINTER, &data);
} else if (IS_INT(type->type) || type->type == FFI_TYPE_POINTER) {
marshal_atom(cb, type->type, data);
@ -335,10 +338,12 @@ ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
that all remaining arguments are long long / __int128 */
size_t arg_bytes = cif->nargs <= 3 ? 0 :
FFI_ALIGN(2 * sizeof(size_t) * (cif->nargs - 3), STKALIGN);
/* Allocate space for copies of big structures. */
size_t struct_bytes = FFI_ALIGN (cif->bytes, STKALIGN);
size_t rval_bytes = 0;
if (rvalue == NULL && cif->rtype->size > 2*__SIZEOF_POINTER__)
rval_bytes = FFI_ALIGN(cif->rtype->size, STKALIGN);
size_t alloc_size = arg_bytes + rval_bytes + sizeof(call_context);
size_t alloc_size = arg_bytes + rval_bytes + struct_bytes + sizeof(call_context);
/* the assembly code will deallocate all stack data at lower addresses
than the argument region, so we need to allocate the frame and the
@ -358,8 +363,9 @@ ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
call_builder cb;
cb.used_float = cb.used_integer = 0;
cb.aregs = (call_context*)(alloc_base + arg_bytes + rval_bytes);
cb.aregs = (call_context*)(alloc_base + arg_bytes + rval_bytes + struct_bytes);
cb.used_stack = (void*)alloc_base;
cb.struct_stack = (void *) (alloc_base + arg_bytes + rval_bytes);
int return_by_ref = passed_by_ref(&cb, cif->rtype, 0);
if (return_by_ref)
@ -373,7 +379,32 @@ ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
cb.used_float = cb.used_integer = 0;
if (!return_by_ref && rvalue)
unmarshal(&cb, cif->rtype, 0, rvalue);
{
if (IS_INT(cif->rtype->type)
&& cif->rtype->size < sizeof (ffi_arg))
{
/* Integer types smaller than ffi_arg need to be extended. */
switch (cif->rtype->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
unmarshal_atom (&cb, (sizeof (ffi_arg) > 4
? FFI_TYPE_SINT64 : FFI_TYPE_SINT32),
rvalue);
break;
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_UINT32:
unmarshal_atom (&cb, (sizeof (ffi_arg) > 4
? FFI_TYPE_UINT64 : FFI_TYPE_UINT32),
rvalue);
break;
}
}
else
unmarshal(&cb, cif->rtype, 0, rvalue);
}
}
void
@ -417,7 +448,9 @@ ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(
closure->fun = fun;
closure->user_data = user_data;
#if !defined(__FreeBSD__)
__builtin___clear_cache(codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
#endif
return FFI_OK;
}

View File

@ -421,12 +421,28 @@ ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
size_t bytes = cif->bytes;
size_t i, nargs = cif->nargs;
ffi_type **arg_types = cif->arg_types;
FFI_ASSERT (cif->abi == FFI_V9);
if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
bytes += FFI_ALIGN (cif->rtype->size, 16);
/* If we have any large structure arguments, make a copy so we are passing
by value. */
for (i = 0; i < nargs; i++)
{
ffi_type *at = arg_types[i];
int size = at->size;
if (at->type == FFI_TYPE_STRUCT && size > 4)
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);
avalue[i] = argcopy;
}
}
ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
}

709
src/tramp.c Normal file
View File

@ -0,0 +1,709 @@
/* -----------------------------------------------------------------------
tramp.c - Copyright (c) 2020 Madhavan T. Venkataraman
Copyright (c) 2022 Anthony Green
API and support functions for managing statically defined closure
trampolines.
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 <fficonfig.h>
#ifdef FFI_EXEC_STATIC_TRAMP
/* -------------------------- Headers and Definitions ---------------------*/
/*
* Add support for other OSes later. For now, it is just Linux and Cygwin.
*/
#if defined (__linux__) || defined (__CYGWIN__)
#ifdef __linux__
#define _GNU_SOURCE 1
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/mman.h>
#include <tramp.h>
#ifdef __linux__
#include <linux/limits.h>
#include <linux/types.h>
#endif
#ifdef __CYGWIN__
#include <limits.h>
#endif
#endif
/*
* Each architecture defines static code for a trampoline code table. The
* trampoline code table is mapped into the address space of a process.
*
* The following architecture specific function returns:
*
* - the address of the trampoline code table in the text segment
* - the size of each trampoline in the trampoline code table
* - the size of the mapping for the whole trampoline code table
*/
void __attribute__((weak)) *ffi_tramp_arch (size_t *tramp_size,
size_t *map_size);
/* ------------------------- Trampoline Data Structures --------------------*/
struct tramp;
/*
* Trampoline table. Manages one trampoline code table and one trampoline
* parameter table.
*
* prev, next Links in the global trampoline table list.
* code_table Trampoline code table mapping.
* parm_table Trampoline parameter table mapping.
* array Array of trampolines malloced.
* free List of free trampolines.
* nfree Number of free trampolines.
*/
struct tramp_table
{
struct tramp_table *prev;
struct tramp_table *next;
void *code_table;
void *parm_table;
struct tramp *array;
struct tramp *free;
int nfree;
};
/*
* Parameters for each trampoline.
*
* data
* Data for the target code that the trampoline jumps to.
* target
* Target code that the trampoline jumps to.
*/
struct tramp_parm
{
void *data;
void *target;
};
/*
* Trampoline structure for each trampoline.
*
* prev, next Links in the trampoline free list of a trampoline table.
* table Trampoline table to which this trampoline belongs.
* code Address of this trampoline in the code table mapping.
* parm Address of this trampoline's parameters in the parameter
* table mapping.
*/
struct tramp
{
struct tramp *prev;
struct tramp *next;
struct tramp_table *table;
void *code;
struct tramp_parm *parm;
};
enum tramp_globals_status {
TRAMP_GLOBALS_UNINITIALIZED = 0,
TRAMP_GLOBALS_PASSED,
TRAMP_GLOBALS_FAILED,
};
/*
* Trampoline globals.
*
* fd
* File descriptor of binary file that contains the trampoline code table.
* offset
* Offset of the trampoline code table in that file.
* text
* Address of the trampoline code table in the text segment.
* map_size
* Size of the trampoline code table mapping.
* size
* Size of one trampoline in the trampoline code table.
* ntramp
* Total number of trampolines in the trampoline code table.
* free_tables
* List of trampoline tables that contain free trampolines.
* nfree_tables
* Number of trampoline tables that contain free trampolines.
* status
* Initialization status.
*/
struct tramp_globals
{
int fd;
off_t offset;
void *text;
size_t map_size;
size_t size;
int ntramp;
struct tramp_table *free_tables;
int nfree_tables;
enum tramp_globals_status status;
};
static struct tramp_globals tramp_globals;
/* --------------------- Trampoline File Initialization --------------------*/
/*
* The trampoline file is the file used to map the trampoline code table into
* the address space of a process. There are two ways to get this file:
*
* - From the OS. E.g., on Linux, /proc/<pid>/maps lists all the memory
* mappings for <pid>. For file-backed mappings, maps supplies the file name
* and the file offset. Using this, we can locate the mapping that maps
* libffi and get the path to the libffi binary. And, we can compute the
* offset of the trampoline code table within that binary.
*
* - Else, if we can create a temporary file, we can write the trampoline code
* table from the text segment into the temporary file.
*
* The first method is the preferred one. If the OS security subsystem
* disallows mapping unsigned files with PROT_EXEC, then the second method
* will fail.
*
* If an OS allows the trampoline code table in the text segment to be
* directly remapped (e.g., MACH vm_remap ()), then we don't need the
* trampoline file.
*/
static int tramp_table_alloc (void);
#if defined (__linux__) || defined (__CYGWIN__)
static int
ffi_tramp_get_libffi (void)
{
FILE *fp;
char file[PATH_MAX], line[PATH_MAX+100], perm[10], dev[10];
unsigned long start, end, offset, inode;
uintptr_t addr = (uintptr_t) tramp_globals.text;
int nfields, found;
snprintf (file, PATH_MAX, "/proc/%d/maps", getpid());
fp = fopen (file, "r");
if (fp == NULL)
return 0;
found = 0;
while (feof (fp) == 0) {
if (fgets (line, sizeof (line), fp) == 0)
break;
nfields = sscanf (line, "%lx-%lx %9s %lx %9s %ld %s",
&start, &end, perm, &offset, dev, &inode, file);
if (nfields != 7)
continue;
if (addr >= start && addr < end) {
tramp_globals.offset = offset + (addr - start);
found = 1;
break;
}
}
fclose (fp);
if (!found)
return 0;
tramp_globals.fd = open (file, O_RDONLY);
if (tramp_globals.fd == -1)
return 0;
/*
* Allocate a trampoline table just to make sure that the trampoline code
* table can be mapped.
*/
if (!tramp_table_alloc ())
{
close (tramp_globals.fd);
tramp_globals.fd = -1;
return 0;
}
return 1;
}
#endif /* defined (__linux__) || defined (__CYGWIN__) */
#if defined (__linux__) || defined (__CYGWIN__)
static int
ffi_tramp_get_temp_file (void)
{
ssize_t count;
tramp_globals.offset = 0;
tramp_globals.fd = open_temp_exec_file ();
/*
* Write the trampoline code table into the temporary file and allocate a
* trampoline table to make sure that the temporary file can be mapped.
*/
count = write(tramp_globals.fd, tramp_globals.text, tramp_globals.map_size);
if (count == tramp_globals.map_size && tramp_table_alloc ())
return 1;
close (tramp_globals.fd);
tramp_globals.fd = -1;
return 0;
}
#endif /* defined (__linux__) || defined (__CYGWIN__) */
/* ------------------------ OS-specific Initialization ----------------------*/
#if defined (__linux__) || defined (__CYGWIN__)
static int
ffi_tramp_init_os (void)
{
if (ffi_tramp_get_libffi ())
return 1;
return ffi_tramp_get_temp_file ();
}
#endif /* defined (__linux__) || defined (__CYGWIN__) */
/* --------------------------- OS-specific Locking -------------------------*/
#if defined (__linux__) || defined (__CYGWIN__)
static pthread_mutex_t tramp_globals_mutex = PTHREAD_MUTEX_INITIALIZER;
static void
ffi_tramp_lock(void)
{
pthread_mutex_lock (&tramp_globals_mutex);
}
static void
ffi_tramp_unlock()
{
pthread_mutex_unlock (&tramp_globals_mutex);
}
#endif /* defined (__linux__) || defined (__CYGWIN__) */
/* ------------------------ OS-specific Memory Mapping ----------------------*/
/*
* Create a trampoline code table mapping and a trampoline parameter table
* mapping. The two mappings must be adjacent to each other for PC-relative
* access.
*
* For each trampoline in the code table, there is a corresponding parameter
* block in the parameter table. The size of the parameter block is the same
* as the size of the trampoline. This means that the parameter block is at
* a fixed offset from its trampoline making it easy for a trampoline to find
* its parameters using PC-relative access.
*
* The parameter block will contain a struct tramp_parm. This means that
* sizeof (struct tramp_parm) cannot exceed the size of a parameter block.
*/
#if defined (__linux__) || defined (__CYGWIN__)
static int
tramp_table_map (struct tramp_table *table)
{
char *addr;
/*
* Create an anonymous mapping twice the map size. The top half will be used
* for the code table. The bottom half will be used for the parameter table.
*/
addr = mmap (NULL, tramp_globals.map_size * 2, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED)
return 0;
/*
* Replace the top half of the anonymous mapping with the code table mapping.
*/
table->code_table = mmap (addr, tramp_globals.map_size, PROT_READ | PROT_EXEC,
MAP_PRIVATE | MAP_FIXED, tramp_globals.fd, tramp_globals.offset);
if (table->code_table == MAP_FAILED)
{
(void) munmap (addr, tramp_globals.map_size * 2);
return 0;
}
table->parm_table = table->code_table + tramp_globals.map_size;
return 1;
}
static void
tramp_table_unmap (struct tramp_table *table)
{
(void) munmap (table->code_table, tramp_globals.map_size);
(void) munmap (table->parm_table, tramp_globals.map_size);
}
#endif /* defined (__linux__) || defined (__CYGWIN__) */
/* ------------------------ Trampoline Initialization ----------------------*/
/*
* Initialize the static trampoline feature.
*/
static int
ffi_tramp_init (void)
{
if (tramp_globals.status == TRAMP_GLOBALS_PASSED)
return 1;
if (tramp_globals.status == TRAMP_GLOBALS_FAILED)
return 0;
if (ffi_tramp_arch == NULL)
{
tramp_globals.status = TRAMP_GLOBALS_FAILED;
return 0;
}
tramp_globals.free_tables = NULL;
tramp_globals.nfree_tables = 0;
/*
* Get trampoline code table information from the architecture.
*/
tramp_globals.text = ffi_tramp_arch (&tramp_globals.size,
&tramp_globals.map_size);
tramp_globals.ntramp = tramp_globals.map_size / tramp_globals.size;
if (sysconf (_SC_PAGESIZE) > tramp_globals.map_size)
return 0;
if (ffi_tramp_init_os ())
{
tramp_globals.status = TRAMP_GLOBALS_PASSED;
return 1;
}
tramp_globals.status = TRAMP_GLOBALS_FAILED;
return 0;
}
/* ---------------------- Trampoline Table functions ---------------------- */
/* This code assumes that malloc () is available on all OSes. */
static void tramp_add (struct tramp *tramp);
/*
* Allocate and initialize a trampoline table.
*/
static int
tramp_table_alloc (void)
{
struct tramp_table *table;
struct tramp *tramp_array, *tramp;
size_t size;
char *code, *parm;
int i;
/*
* If we already have tables with free trampolines, there is no need to
* allocate a new table.
*/
if (tramp_globals.nfree_tables > 0)
return 1;
/*
* Allocate a new trampoline table structure.
*/
table = malloc (sizeof (*table));
if (table == NULL)
return 0;
/*
* Allocate new trampoline structures.
*/
tramp_array = malloc (sizeof (*tramp) * tramp_globals.ntramp);
if (tramp_array == NULL)
goto free_table;
/*
* Map a code table and a parameter table into the caller's address space.
*/
if (!tramp_table_map (table))
{
/*
* Failed to map the code and parameter tables.
*/
goto free_tramp_array;
}
/*
* Initialize the trampoline table.
*/
table->array = tramp_array;
table->free = NULL;
table->nfree = 0;
/*
* Populate the trampoline table free list. This will also add the trampoline
* table to the global list of trampoline tables.
*/
size = tramp_globals.size;
code = table->code_table;
parm = table->parm_table;
for (i = 0; i < tramp_globals.ntramp; i++)
{
tramp = &tramp_array[i];
tramp->table = table;
tramp->code = code;
tramp->parm = (struct tramp_parm *) parm;
tramp_add (tramp);
code += size;
parm += size;
}
/* Success */
return 1;
/* Failure */
free_tramp_array:
free (tramp_array);
free_table:
free (table);
return 0;
}
/*
* Free a trampoline table.
*/
static void
tramp_table_free (struct tramp_table *table)
{
tramp_table_unmap (table);
free (table->array);
free (table);
}
/*
* Add a new trampoline table to the global table list.
*/
static void
tramp_table_add (struct tramp_table *table)
{
table->next = tramp_globals.free_tables;
table->prev = NULL;
if (tramp_globals.free_tables != NULL)
tramp_globals.free_tables->prev = table;
tramp_globals.free_tables = table;
tramp_globals.nfree_tables++;
}
/*
* Delete a trampoline table from the global table list.
*/
static void
tramp_table_del (struct tramp_table *table)
{
tramp_globals.nfree_tables--;
if (table->prev != NULL)
table->prev->next = table->next;
if (table->next != NULL)
table->next->prev = table->prev;
if (tramp_globals.free_tables == table)
tramp_globals.free_tables = table->next;
}
/* ------------------------- Trampoline functions ------------------------- */
/*
* Add a trampoline to its trampoline table.
*/
static void
tramp_add (struct tramp *tramp)
{
struct tramp_table *table = tramp->table;
tramp->next = table->free;
tramp->prev = NULL;
if (table->free != NULL)
table->free->prev = tramp;
table->free = tramp;
table->nfree++;
if (table->nfree == 1)
tramp_table_add (table);
/*
* We don't want to keep too many free trampoline tables lying around.
*/
if (table->nfree == tramp_globals.ntramp &&
tramp_globals.nfree_tables > 1)
{
tramp_table_del (table);
tramp_table_free (table);
}
}
/*
* Remove a trampoline from its trampoline table.
*/
static void
tramp_del (struct tramp *tramp)
{
struct tramp_table *table = tramp->table;
table->nfree--;
if (tramp->prev != NULL)
tramp->prev->next = tramp->next;
if (tramp->next != NULL)
tramp->next->prev = tramp->prev;
if (table->free == tramp)
table->free = tramp->next;
if (table->nfree == 0)
tramp_table_del (table);
}
/* ------------------------ Trampoline API functions ------------------------ */
int
ffi_tramp_is_supported(void)
{
int ret;
ffi_tramp_lock();
ret = ffi_tramp_init ();
ffi_tramp_unlock();
return ret;
}
/*
* Allocate a trampoline and return its opaque address.
*/
void *
ffi_tramp_alloc (int flags)
{
struct tramp *tramp;
ffi_tramp_lock();
if (!ffi_tramp_init () || flags != 0)
{
ffi_tramp_unlock();
return NULL;
}
if (!tramp_table_alloc ())
{
ffi_tramp_unlock();
return NULL;
}
tramp = tramp_globals.free_tables->free;
tramp_del (tramp);
ffi_tramp_unlock();
return tramp;
}
/*
* Set the parameters for a trampoline.
*/
void
ffi_tramp_set_parms (void *arg, void *target, void *data)
{
struct tramp *tramp = arg;
ffi_tramp_lock();
tramp->parm->target = target;
tramp->parm->data = data;
ffi_tramp_unlock();
}
/*
* Get the invocation address of a trampoline.
*/
void *
ffi_tramp_get_addr (void *arg)
{
struct tramp *tramp = arg;
void *addr;
ffi_tramp_lock();
addr = tramp->code;
ffi_tramp_unlock();
return addr;
}
/*
* Free a trampoline.
*/
void
ffi_tramp_free (void *arg)
{
struct tramp *tramp = arg;
ffi_tramp_lock();
tramp_add (tramp);
ffi_tramp_unlock();
}
/* ------------------------------------------------------------------------- */
#else /* !FFI_EXEC_STATIC_TRAMP */
#include <stddef.h>
int
ffi_tramp_is_supported(void)
{
return 0;
}
void *
ffi_tramp_alloc (int flags)
{
return NULL;
}
void
ffi_tramp_set_parms (void *arg, void *target, void *data)
{
}
void *
ffi_tramp_get_addr (void *arg)
{
return NULL;
}
void
ffi_tramp_free (void *arg)
{
}
#endif /* FFI_EXEC_STATIC_TRAMP */

View File

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2017 Anthony Green
ffi.c - Copyright (c) 2017, 2022 Anthony Green
Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
Copyright (c) 2002 Ranjit Mathew
Copyright (c) 2002 Bo Thorsen
@ -34,6 +34,7 @@
#include <ffi_common.h>
#include <stdint.h>
#include <stdlib.h>
#include <tramp.h>
#include "internal.h"
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
@ -116,35 +117,37 @@ ffi_prep_cif_machdep(ffi_cif *cif)
flags = X86_RET_INT64;
break;
case FFI_TYPE_STRUCT:
#ifndef X86
/* ??? This should be a different ABI rather than an ifdef. */
if (cif->rtype->size == 1)
flags = X86_RET_STRUCT_1B;
else if (cif->rtype->size == 2)
flags = X86_RET_STRUCT_2B;
else if (cif->rtype->size == 4)
flags = X86_RET_INT32;
else if (cif->rtype->size == 8)
flags = X86_RET_INT64;
else
{
#ifdef X86_WIN32
size_t size = cif->rtype->size;
if (size == 1)
flags = X86_RET_STRUCT_1B;
else if (size == 2)
flags = X86_RET_STRUCT_2B;
else if (size == 4)
flags = X86_RET_INT32;
else if (size == 8)
flags = X86_RET_INT64;
else
#endif
{
do_struct:
switch (cabi)
{
case FFI_THISCALL:
case FFI_FASTCALL:
case FFI_STDCALL:
case FFI_MS_CDECL:
flags = X86_RET_STRUCTARG;
break;
default:
flags = X86_RET_STRUCTPOP;
break;
}
/* Allocate space for return value pointer. */
bytes += FFI_ALIGN (sizeof(void*), FFI_SIZEOF_ARG);
}
{
do_struct:
switch (cabi)
{
case FFI_THISCALL:
case FFI_FASTCALL:
case FFI_STDCALL:
case FFI_MS_CDECL:
flags = X86_RET_STRUCTARG;
break;
default:
flags = X86_RET_STRUCTPOP;
break;
}
/* Allocate space for return value pointer. */
bytes += FFI_ALIGN (sizeof(void*), FFI_SIZEOF_ARG);
}
}
break;
case FFI_TYPE_COMPLEX:
switch (cif->rtype->elements[0]->type)
@ -181,7 +184,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
{
ffi_type *t = cif->arg_types[i];
bytes = FFI_ALIGN (bytes, t->alignment);
#if defined(X86_WIN32)
if (cabi == FFI_STDCALL)
bytes = FFI_ALIGN (bytes, FFI_SIZEOF_ARG);
else
#endif
bytes = FFI_ALIGN (bytes, t->alignment);
bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG);
}
cif->bytes = bytes;
@ -255,6 +263,13 @@ static const struct abi_params abi_params[FFI_LAST_ABI] = {
extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN;
/* We perform some black magic here to use some of the parent's stack frame in
* ffi_call_i386() that breaks with the MSVC compiler with the /RTCs or /GZ
* flags. Disable the 'Stack frame run time error checking' for this function
* so we don't hit weird exceptions in debug builds. */
#if defined(_MSC_VER)
#pragma runtime_checks("s", off)
#endif
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
@ -353,7 +368,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
size_t align = FFI_SIZEOF_ARG;
/* Issue 434: For thiscall and fastcall, if the paramter passed
as 64-bit integer or struct, all following integer paramters
as 64-bit integer or struct, all following integer parameters
will be passed on stack. */
if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
&& (t == FFI_TYPE_SINT64
@ -370,7 +385,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
cases. */
if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
align = 16;
if (dir < 0)
{
/* ??? These reverse argument ABIs are probably too old
@ -390,6 +405,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
ffi_call_i386 (frame, stack);
}
#if defined(_MSC_VER)
#pragma runtime_checks("s", restore)
#endif
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
@ -397,18 +415,25 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
#ifdef FFI_GO_CLOSURES
void
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
#endif
/** private members **/
void FFI_HIDDEN ffi_closure_i386(void);
void FFI_HIDDEN ffi_closure_STDCALL(void);
void FFI_HIDDEN ffi_closure_REGISTER(void);
#if defined(FFI_EXEC_STATIC_TRAMP)
void FFI_HIDDEN ffi_closure_i386_alt(void);
void FFI_HIDDEN ffi_closure_STDCALL_alt(void);
void FFI_HIDDEN ffi_closure_REGISTER_alt(void);
#endif
struct closure_frame
{
@ -492,7 +517,7 @@ ffi_closure_inner (struct closure_frame *frame, char *stack)
align = 16;
/* Issue 434: For thiscall and fastcall, if the paramter passed
as 64-bit integer or struct, all following integer paramters
as 64-bit integer or struct, all following integer parameters
will be passed on stack. */
if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
&& (t == FFI_TYPE_SINT64
@ -520,10 +545,17 @@ ffi_closure_inner (struct closure_frame *frame, char *stack)
frame->fun (cif, rvalue, avalue, frame->user_data);
if (cabi == FFI_STDCALL)
return flags + (cif->bytes << X86_RET_POP_SHIFT);
else
return flags;
switch (cabi)
{
case FFI_STDCALL:
return flags | (cif->bytes << X86_RET_POP_SHIFT);
case FFI_THISCALL:
case FFI_FASTCALL:
return flags | ((cif->bytes - (narg_reg * FFI_SIZEOF_ARG))
<< X86_RET_POP_SHIFT);
default:
return flags;
}
}
ffi_status
@ -540,12 +572,12 @@ ffi_prep_closure_loc (ffi_closure* closure,
switch (cif->abi)
{
case FFI_SYSV:
case FFI_THISCALL:
case FFI_FASTCALL:
case FFI_MS_CDECL:
dest = ffi_closure_i386;
break;
case FFI_STDCALL:
case FFI_THISCALL:
case FFI_FASTCALL:
case FFI_PASCAL:
dest = ffi_closure_STDCALL;
break;
@ -557,14 +589,36 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_BAD_ABI;
}
#if defined(FFI_EXEC_STATIC_TRAMP)
if (ffi_tramp_is_present(closure))
{
/* Initialize the static trampoline's parameters. */
if (dest == ffi_closure_i386)
dest = ffi_closure_i386_alt;
else if (dest == ffi_closure_STDCALL)
dest = ffi_closure_STDCALL_alt;
else
dest = ffi_closure_REGISTER_alt;
ffi_tramp_set_parms (closure->ftramp, dest, closure);
goto out;
}
#endif
/* Initialize the dynamic trampoline. */
/* endbr32. */
*(UINT32 *) tramp = 0xfb1e0ff3;
/* movl or pushl immediate. */
tramp[0] = op;
*(void **)(tramp + 1) = codeloc;
tramp[4] = op;
*(void **)(tramp + 5) = codeloc;
/* jmp dest */
tramp[5] = 0xe9;
*(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
tramp[9] = 0xe9;
*(unsigned *)(tramp + 10) = (unsigned)dest - ((unsigned)codeloc + 14);
#if defined(FFI_EXEC_STATIC_TRAMP)
out:
#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
@ -572,6 +626,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK;
}
#ifdef FFI_GO_CLOSURES
void FFI_HIDDEN ffi_go_closure_EAX(void);
void FFI_HIDDEN ffi_go_closure_ECX(void);
void FFI_HIDDEN ffi_go_closure_STDCALL(void);
@ -608,6 +664,8 @@ ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
return FFI_OK;
}
#endif /* FFI_GO_CLOSURES */
/* ------- Native raw API support -------------------------------- */
#if !FFI_NO_RAW_API
@ -758,4 +816,17 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
ffi_call_i386 (frame, stack);
}
#endif /* !FFI_NO_RAW_API */
#if defined(FFI_EXEC_STATIC_TRAMP)
void *
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
{
extern void *trampoline_code_table;
*map_size = X86_TRAMP_MAP_SIZE;
*tramp_size = X86_TRAMP_SIZE;
return &trampoline_code_table;
}
#endif
#endif /* __i386__ */

View File

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffi64.c - Copyright (c) 2011, 2018 Anthony Green
ffi64.c - Copyright (c) 2011, 2018, 2022 Anthony Green
Copyright (c) 2013 The Written Word, Inc.
Copyright (c) 2008, 2010 Red Hat, Inc.
Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
@ -33,6 +33,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <tramp.h>
#include "internal64.h"
#ifdef __x86_64__
@ -217,7 +218,8 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
case FFI_TYPE_STRUCT:
{
const size_t UNITS_PER_WORD = 8;
size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1)
/ UNITS_PER_WORD;
ffi_type **ptr;
unsigned int i;
enum x86_64_reg_class subclasses[MAX_CLASSES];
@ -241,14 +243,15 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
/* Merge the fields of structure. */
for (ptr = type->elements; *ptr != NULL; ptr++)
{
size_t num;
size_t num, pos;
byte_offset = FFI_ALIGN (byte_offset, (*ptr)->alignment);
num = classify_argument (*ptr, subclasses, byte_offset % 8);
if (num == 0)
return 0;
for (i = 0; i < num; i++)
pos = byte_offset / 8;
for (i = 0; i < num && (i + pos) < words; i++)
{
size_t pos = byte_offset / 8;
classes[i + pos] =
@ -578,6 +581,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
flags = UNIX64_RET_VOID;
}
arg_types = cif->arg_types;
avn = cif->nargs;
/* Allocate the space for the arguments, plus 4 words of temp space. */
stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
reg_args = (struct register_args *) stack;
@ -592,9 +598,6 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
if (flags & UNIX64_FLAG_RET_IN_MEM)
reg_args->gpr[gprcount++] = (unsigned long) rvalue;
avn = cif->nargs;
arg_types = cif->arg_types;
for (i = 0; i < avn; ++i)
{
size_t n, size = arg_types[i]->size;
@ -610,11 +613,12 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
if (align < 8)
align = 8;
/* Pass this argument in memory. */
argp = (void *) FFI_ALIGN (argp, align);
memcpy (argp, avalue[i], size);
argp += size;
}
/* Pass this argument in memory. */
argp = (void *) FFI_ALIGN (argp, align);
memcpy (argp, avalue[i], size);
argp += size;
}
else
{
/* The argument is passed entirely in registers. */
@ -678,6 +682,24 @@ ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_type **arg_types = cif->arg_types;
int i, nargs = cif->nargs;
const int max_reg_struct_size = cif->abi == FFI_GNUW64 ? 8 : 16;
/* If we have any large structure arguments, make a copy so we are passing
by value. */
for (i = 0; i < nargs; i++)
{
ffi_type *at = arg_types[i];
int size = at->size;
if (at->type == FFI_TYPE_STRUCT && size > max_reg_struct_size)
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);
avalue[i] = argcopy;
}
}
#ifndef __ILP32__
if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64)
{
@ -688,6 +710,8 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
#ifdef FFI_GO_CLOSURES
#ifndef __ILP32__
extern void
ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue,
@ -708,9 +732,14 @@ ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
#endif /* FFI_GO_CLOSURES */
extern void ffi_closure_unix64(void) FFI_HIDDEN;
extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
#if defined(FFI_EXEC_STATIC_TRAMP)
extern void ffi_closure_unix64_alt(void) FFI_HIDDEN;
extern void ffi_closure_unix64_sse_alt(void) FFI_HIDDEN;
#endif
#ifndef __ILP32__
extern ffi_status
@ -728,13 +757,15 @@ ffi_prep_closure_loc (ffi_closure* closure,
void *user_data,
void *codeloc)
{
static const unsigned char trampoline[16] = {
/* leaq -0x7(%rip),%r10 # 0x0 */
0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
/* jmpq *0x3(%rip) # 0x10 */
0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
/* nopl (%rax) */
0x0f, 0x1f, 0x00
static const unsigned char trampoline[24] = {
/* endbr64 */
0xf3, 0x0f, 0x1e, 0xfa,
/* leaq -0xb(%rip),%r10 # 0x0 */
0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff,
/* jmpq *0x7(%rip) # 0x18 */
0xff, 0x25, 0x07, 0x00, 0x00, 0x00,
/* nopl 0(%rax) */
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00
};
void (*dest)(void);
char *tramp = closure->tramp;
@ -751,9 +782,26 @@ ffi_prep_closure_loc (ffi_closure* closure,
else
dest = ffi_closure_unix64;
memcpy (tramp, trampoline, sizeof(trampoline));
*(UINT64 *)(tramp + 16) = (uintptr_t)dest;
#if defined(FFI_EXEC_STATIC_TRAMP)
if (ffi_tramp_is_present(closure))
{
/* Initialize the static trampoline's parameters. */
if (dest == ffi_closure_unix64_sse)
dest = ffi_closure_unix64_sse_alt;
else
dest = ffi_closure_unix64_alt;
ffi_tramp_set_parms (closure->ftramp, dest, closure);
goto out;
}
#endif
/* Initialize the dynamic trampoline. */
memcpy (tramp, trampoline, sizeof(trampoline));
*(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)dest;
#if defined(FFI_EXEC_STATIC_TRAMP)
out:
#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
@ -854,6 +902,8 @@ ffi_closure_unix64_inner(ffi_cif *cif,
return flags;
}
#ifdef FFI_GO_CLOSURES
extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
@ -883,4 +933,18 @@ ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
return FFI_OK;
}
#endif /* FFI_GO_CLOSURES */
#if defined(FFI_EXEC_STATIC_TRAMP)
void *
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
{
extern void *trampoline_code_table;
*map_size = UNIX64_TRAMP_MAP_SIZE;
*tramp_size = UNIX64_TRAMP_SIZE;
return &trampoline_code_table;
}
#endif
#endif /* __x86_64__ */

View File

@ -41,6 +41,9 @@
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#warning ******************************************************
#warning ********** X86 IS DEFINED ****************************
#warning ******************************************************
#define X86
#endif
@ -85,9 +88,9 @@ typedef enum ffi_abi {
FFI_LAST_ABI,
#ifdef __GNUC__
FFI_DEFAULT_ABI = FFI_GNUW64
#else
#else
FFI_DEFAULT_ABI = FFI_WIN64
#endif
#endif
#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
FFI_FIRST_ABI = 1,
@ -136,12 +139,26 @@ typedef enum ffi_abi {
#if defined (X86_64) || defined(X86_WIN64) \
|| (defined (__x86_64__) && defined (X86_DARWIN))
# define FFI_TRAMPOLINE_SIZE 24
/* 4 bytes of ENDBR64 + 7 bytes of LEA + 6 bytes of JMP + 7 bytes of NOP
+ 8 bytes of pointer. */
# define FFI_TRAMPOLINE_SIZE 32
# define FFI_NATIVE_RAW_API 0
#else
# define FFI_TRAMPOLINE_SIZE 12
/* 4 bytes of ENDBR32 + 5 bytes of MOV + 5 bytes of JMP + 2 unused
bytes. */
# define FFI_TRAMPOLINE_SIZE 16
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
#if !defined(GENERATE_LIBFFI_MAP) && defined(__CET__)
# include <cet.h>
# if (__CET__ & 1) != 0
# define ENDBR_PRESENT
# endif
# define _CET_NOTRACK notrack
#else
# define _CET_ENDBR
# define _CET_NOTRACK
#endif
#endif

View File

@ -30,6 +30,7 @@
#include <ffi_common.h>
#include <stdlib.h>
#include <stdint.h>
#include <tramp.h>
#ifdef X86_WIN64
#define EFI64(name) name
@ -107,6 +108,13 @@ EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
return FFI_OK;
}
/* We perform some black magic here to use some of the parent's stack frame in
* ffi_call_win64() that breaks with the MSVC compiler with the /RTCs or /GZ
* flags. Disable the 'Stack frame run time error checking' for this function
* so we don't hit weird exceptions in debug builds. */
#if defined(_MSC_VER)
#pragma runtime_checks("s", off)
#endif
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
@ -115,9 +123,25 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
UINT64 *stack;
size_t rsize;
struct win64_call_frame *frame;
ffi_type **arg_types = cif->arg_types;
int nargs = cif->nargs;
FFI_ASSERT(cif->abi == FFI_GNUW64 || cif->abi == FFI_WIN64);
/* If we have any large structure arguments, make a copy so we are passing
by value. */
for (i = 0; i < nargs; i++)
{
ffi_type *at = arg_types[i];
int size = at->size;
if (at->type == FFI_TYPE_STRUCT && size > 8)
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);
avalue[i] = argcopy;
}
}
flags = cif->flags;
rsize = 0;
@ -171,6 +195,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
ffi_call_win64 (stack, frame, closure);
}
#if defined(_MSC_VER)
#pragma runtime_checks("s", restore)
#endif
void
EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
@ -187,7 +214,13 @@ EFI64(ffi_call_go)(ffi_cif *cif, void (*fn)(void), void *rvalue,
extern void ffi_closure_win64(void) FFI_HIDDEN;
#if defined(FFI_EXEC_STATIC_TRAMP)
extern void ffi_closure_win64_alt(void) FFI_HIDDEN;
#endif
#ifdef FFI_GO_CLOSURES
extern void ffi_go_closure_win64(void) FFI_HIDDEN;
#endif
ffi_status
EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
@ -196,13 +229,15 @@ EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
void *user_data,
void *codeloc)
{
static const unsigned char trampoline[16] = {
/* leaq -0x7(%rip),%r10 # 0x0 */
0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
/* jmpq *0x3(%rip) # 0x10 */
0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
/* nopl (%rax) */
0x0f, 0x1f, 0x00
static const unsigned char trampoline[FFI_TRAMPOLINE_SIZE - 8] = {
/* endbr64 */
0xf3, 0x0f, 0x1e, 0xfa,
/* leaq -0xb(%rip),%r10 # 0x0 */
0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff,
/* jmpq *0x7(%rip) # 0x18 */
0xff, 0x25, 0x07, 0x00, 0x00, 0x00,
/* nopl 0(%rax) */
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00
};
char *tramp = closure->tramp;
@ -215,9 +250,22 @@ EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
return FFI_BAD_ABI;
}
memcpy (tramp, trampoline, sizeof(trampoline));
*(UINT64 *)(tramp + 16) = (uintptr_t)ffi_closure_win64;
#if defined(FFI_EXEC_STATIC_TRAMP)
if (ffi_tramp_is_present(closure))
{
/* Initialize the static trampoline's parameters. */
ffi_tramp_set_parms (closure->ftramp, ffi_closure_win64_alt, closure);
goto out;
}
#endif
/* Initialize the dynamic trampoline. */
memcpy (tramp, trampoline, sizeof(trampoline));
*(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)ffi_closure_win64;
#if defined(FFI_EXEC_STATIC_TRAMP)
out:
#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
@ -225,6 +273,7 @@ EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
return FFI_OK;
}
#ifdef FFI_GO_CLOSURES
ffi_status
EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*))
@ -244,6 +293,7 @@ EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif,
return FFI_OK;
}
#endif
struct win64_closure_frame
{

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