mirror of https://gitee.com/openkylin/libffi.git
merge upstream 3.4.4
This commit is contained in:
parent
3489710a4d
commit
f9ba9b10fe
2
LICENSE
2
LICENSE
|
@ -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
|
||||
|
|
114
Makefile.am
114
Makefile.am
|
@ -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)
|
||||
|
|
274
Makefile.in
274
Makefile.in
|
@ -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
230
README.md
|
@ -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
|
||||
|
|
122
acinclude.m4
122
acinclude.m4
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
6
compile
6
compile
|
@ -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/*)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
119
configure.ac
119
configure.ac
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}
|
|
@ -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):
|
|
@ -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);
|
|
@ -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++;
|
||||
}
|
|
@ -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++;
|
2
depcomp
2
depcomp
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
114
doc/libffi.info
114
doc/libffi.info
|
@ -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:
|
||||
|
|
BIN
doc/libffi.pdf
BIN
doc/libffi.pdf
Binary file not shown.
115
doc/libffi.texi
115
doc/libffi.texi
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
1913
doc/texinfo.tex
1913
doc/texinfo.tex
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 */
|
157
install-sh
157
install-sh
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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)
|
||||
])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
2
missing
2
missing
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
24
msvcc.sh
24
msvcc.sh
|
@ -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"
|
||||
|
|
|
@ -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)*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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,
|
||||
|
|
101
src/arm/ffi.c
101
src/arm/ffi.c
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
130
src/arm/sysv.S
130
src/arm/sysv.S
|
@ -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)
|
||||
|
|
196
src/closures.c
196
src/closures.c
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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__ */
|
|
@ -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)\
|
||||
|
|
|
@ -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)
|
|
@ -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__) */
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
|
|
311
src/mips/ffi.c
311
src/mips/ffi.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
165
src/mips/n32.S
165
src/mips/n32.S
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
137
src/pa/ffi.c
137
src/pa/ffi.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
157
src/x86/ffi.c
157
src/x86/ffi.c
|
@ -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__ */
|
||||
|
|
106
src/x86/ffi64.c
106
src/x86/ffi64.c
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue