ffi 1.9.18-x64-mingw32 → 1.9.21-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/README.md +3 -2
- data/Rakefile +14 -4
- data/ext/ffi_c/AbstractMemory.c +6 -1
- data/ext/ffi_c/Platform.c +10 -2
- data/ext/ffi_c/extconf.rb +7 -2
- data/ext/ffi_c/libffi.bsd.mk +9 -3
- data/ext/ffi_c/libffi.darwin.mk +14 -4
- data/ext/ffi_c/libffi.gnu.mk +2 -1
- data/ext/ffi_c/libffi.mk +9 -4
- data/ext/ffi_c/libffi/ChangeLog.libffi +2 -2
- data/ext/ffi_c/libffi/{ChangeLog → ChangeLog.libffi-3.1} +1402 -2
- data/ext/ffi_c/libffi/ChangeLog.v1 +1 -1
- data/ext/ffi_c/libffi/LICENSE +1 -1
- data/ext/ffi_c/libffi/Makefile.am +166 -157
- data/ext/ffi_c/libffi/Makefile.in +923 -938
- data/ext/ffi_c/libffi/README +164 -52
- data/ext/ffi_c/libffi/acinclude.m4 +381 -0
- data/ext/ffi_c/libffi/aclocal.m4 +645 -384
- data/ext/ffi_c/libffi/autogen.sh +2 -0
- data/ext/ffi_c/libffi/autom4te.cache/output.0 +21972 -0
- data/ext/ffi_c/libffi/autom4te.cache/output.1 +21972 -0
- data/ext/ffi_c/libffi/autom4te.cache/output.2 +21972 -0
- data/ext/ffi_c/libffi/autom4te.cache/output.3 +21972 -0
- data/ext/ffi_c/libffi/autom4te.cache/requests +331 -0
- data/ext/ffi_c/libffi/autom4te.cache/traces.0 +4010 -0
- data/ext/ffi_c/libffi/autom4te.cache/traces.1 +1005 -0
- data/ext/ffi_c/libffi/autom4te.cache/traces.2 +4010 -0
- data/ext/ffi_c/libffi/autom4te.cache/traces.3 +4010 -0
- data/ext/ffi_c/libffi/compile +218 -14
- data/ext/ffi_c/libffi/config.guess +329 -368
- data/ext/ffi_c/libffi/config.sub +232 -112
- data/ext/ffi_c/libffi/configure +6970 -2189
- data/ext/ffi_c/libffi/configure.ac +148 -256
- data/ext/ffi_c/libffi/configure.host +265 -4
- data/ext/ffi_c/libffi/depcomp +346 -185
- data/ext/ffi_c/libffi/doc/Makefile.am +3 -0
- data/ext/ffi_c/libffi/doc/Makefile.in +811 -0
- data/ext/ffi_c/libffi/doc/libffi.texi +430 -45
- data/ext/ffi_c/libffi/{mdate-sh → doc/mdate-sh} +40 -13
- data/ext/ffi_c/libffi/{texinfo.tex → doc/texinfo.tex} +3990 -1121
- data/ext/ffi_c/libffi/doc/version.texi +4 -4
- data/ext/ffi_c/libffi/fficonfig.h.in +24 -13
- data/ext/ffi_c/libffi/fficonfig.h.in~ +210 -0
- data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +207 -0
- data/ext/ffi_c/libffi/include/Makefile.am +3 -3
- data/ext/ffi_c/libffi/include/Makefile.in +188 -71
- data/ext/ffi_c/libffi/include/ffi.h.in +107 -50
- data/ext/ffi_c/libffi/include/ffi_cfi.h +55 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +32 -11
- data/ext/ffi_c/libffi/install-sh +190 -202
- data/ext/ffi_c/libffi/libffi.map.in +80 -0
- data/ext/ffi_c/libffi/libffi.pc.in +3 -2
- data/ext/ffi_c/libffi/libffi.xcodeproj/project.pbxproj +637 -0
- data/ext/ffi_c/libffi/libtool-ldflags +106 -0
- data/ext/ffi_c/libffi/libtool-version +1 -1
- data/ext/ffi_c/libffi/ltmain.sh +3553 -2033
- data/ext/ffi_c/libffi/m4/asmcfi.m4 +13 -0
- data/ext/ffi_c/libffi/m4/ax_append_flag.m4 +69 -0
- data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +13 -8
- data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +31 -104
- data/ext/ffi_c/libffi/m4/{ax_check_compiler_flags.m4 → ax_check_compile_flag.m4} +30 -34
- data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +32 -11
- data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +6 -5
- data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +31 -21
- data/ext/ffi_c/libffi/m4/libtool.m4 +1691 -1135
- data/ext/ffi_c/libffi/m4/ltoptions.m4 +104 -36
- data/ext/ffi_c/libffi/m4/ltsugar.m4 +4 -3
- data/ext/ffi_c/libffi/m4/ltversion.m4 +6 -6
- data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +4 -3
- data/ext/ffi_c/libffi/man/Makefile.am +2 -2
- data/ext/ffi_c/libffi/man/Makefile.in +141 -49
- data/ext/ffi_c/libffi/man/ffi.3 +10 -0
- data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +6 -4
- data/ext/ffi_c/libffi/man/ffi_prep_cif_var.3 +73 -0
- data/ext/ffi_c/libffi/missing +150 -311
- data/ext/ffi_c/libffi/msvcc.sh +72 -9
- data/ext/ffi_c/libffi/src/aarch64/ffi.c +941 -0
- data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +81 -0
- data/ext/ffi_c/libffi/src/aarch64/internal.h +67 -0
- data/ext/ffi_c/libffi/src/aarch64/sysv.S +438 -0
- data/ext/ffi_c/libffi/src/alpha/ffi.c +335 -98
- data/ext/ffi_c/libffi/src/alpha/ffitarget.h +10 -1
- data/ext/ffi_c/libffi/src/alpha/internal.h +23 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +161 -266
- data/ext/ffi_c/libffi/src/arc/arcompact.S +135 -0
- data/ext/ffi_c/libffi/src/arc/ffi.c +266 -0
- data/ext/ffi_c/libffi/src/arc/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/arm/ffi.c +597 -517
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +24 -7
- data/ext/ffi_c/libffi/src/arm/internal.h +7 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +303 -417
- data/ext/ffi_c/libffi/src/avr32/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/bfin/ffi.c +196 -0
- data/ext/ffi_c/libffi/src/bfin/ffitarget.h +43 -0
- data/ext/ffi_c/libffi/src/bfin/sysv.S +179 -0
- data/ext/ffi_c/libffi/src/closures.c +319 -44
- data/ext/ffi_c/libffi/src/cris/ffi.c +10 -7
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/debug.c +6 -1
- data/ext/ffi_c/libffi/src/dlmalloc.c +16 -11
- data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/ia64/ffi.c +11 -7
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/java_raw_api.c +23 -5
- data/ext/ffi_c/libffi/src/m32r/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/m68k/ffi.c +87 -13
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/m68k/sysv.S +119 -32
- data/ext/ffi_c/libffi/src/m88k/ffi.c +400 -0
- data/ext/ffi_c/libffi/src/m88k/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/m88k/obsd.S +209 -0
- data/ext/ffi_c/libffi/src/metag/ffi.c +330 -0
- data/ext/ffi_c/libffi/{fficonfig.hw → src/metag/ffitarget.h} +22 -26
- data/ext/ffi_c/libffi/src/metag/sysv.S +311 -0
- data/ext/ffi_c/libffi/src/microblaze/ffi.c +321 -0
- data/ext/ffi_c/libffi/src/microblaze/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/microblaze/sysv.S +302 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +95 -28
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +9 -2
- data/ext/ffi_c/libffi/src/mips/n32.S +126 -56
- data/ext/ffi_c/libffi/src/mips/o32.S +148 -27
- data/ext/ffi_c/libffi/src/moxie/eabi.S +55 -82
- data/ext/ffi_c/libffi/src/moxie/ffi.c +40 -44
- data/ext/ffi_c/libffi/src/moxie/ffitarget.h +52 -0
- data/ext/ffi_c/libffi/src/nios2/ffi.c +304 -0
- data/ext/ffi_c/libffi/src/nios2/ffitarget.h +52 -0
- data/ext/ffi_c/libffi/src/nios2/sysv.S +136 -0
- data/ext/ffi_c/libffi/src/or1k/ffi.c +328 -0
- data/ext/ffi_c/libffi/src/or1k/ffitarget.h +58 -0
- data/ext/ffi_c/libffi/src/or1k/sysv.S +107 -0
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +8 -1
- data/ext/ffi_c/libffi/src/powerpc/aix.S +6 -6
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +3 -1
- data/ext/ffi_c/libffi/src/powerpc/asm.h +2 -2
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +2 -7
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +22 -26
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +103 -1378
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +25 -25
- data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +945 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_powerpc.h +94 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_sysv.c +923 -0
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +100 -44
- data/ext/ffi_c/libffi/src/powerpc/linux64.S +100 -59
- data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +360 -108
- data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +138 -68
- data/ext/ffi_c/libffi/src/powerpc/sysv.S +68 -112
- data/ext/ffi_c/libffi/src/prep_cif.c +108 -24
- data/ext/ffi_c/libffi/src/raw_api.c +18 -5
- data/ext/ffi_c/libffi/src/s390/ffi.c +294 -318
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +9 -1
- data/ext/ffi_c/libffi/src/s390/internal.h +11 -0
- data/ext/ffi_c/libffi/src/s390/sysv.S +257 -366
- data/ext/ffi_c/libffi/src/sh/ffi.c +4 -3
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/sh64/ffi.c +3 -2
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +6 -1
- data/ext/ffi_c/libffi/src/sparc/ffi.c +326 -527
- data/ext/ffi_c/libffi/src/sparc/ffi64.c +608 -0
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +20 -7
- data/ext/ffi_c/libffi/src/sparc/internal.h +26 -0
- data/ext/ffi_c/libffi/src/sparc/v8.S +364 -234
- data/ext/ffi_c/libffi/src/sparc/v9.S +340 -207
- data/ext/ffi_c/libffi/src/tile/ffi.c +355 -0
- data/ext/ffi_c/libffi/src/tile/ffitarget.h +65 -0
- data/ext/ffi_c/libffi/src/tile/tile.S +360 -0
- data/ext/ffi_c/libffi/src/types.c +43 -14
- data/ext/ffi_c/libffi/src/vax/elfbsd.S +195 -0
- data/ext/ffi_c/libffi/src/vax/ffi.c +276 -0
- data/ext/ffi_c/libffi/src/vax/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/x86/asmnames.h +30 -0
- data/ext/ffi_c/libffi/src/x86/ffi.c +589 -500
- data/ext/ffi_c/libffi/src/x86/ffi64.c +338 -116
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +55 -35
- data/ext/ffi_c/libffi/src/x86/ffiw64.c +287 -0
- data/ext/ffi_c/libffi/src/x86/internal.h +29 -0
- data/ext/ffi_c/libffi/src/x86/internal64.h +22 -0
- data/ext/ffi_c/libffi/src/x86/sysv.S +975 -400
- data/ext/ffi_c/libffi/src/x86/unix64.S +398 -299
- data/ext/ffi_c/libffi/src/x86/win64.S +222 -458
- data/ext/ffi_c/libffi/src/x86/win64_intel.S +237 -0
- data/ext/ffi_c/libffi/src/xtensa/ffi.c +298 -0
- data/ext/ffi_c/libffi/src/xtensa/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/xtensa/sysv.S +253 -0
- data/ext/ffi_c/libffi/stamp-h.in +1 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.am +78 -73
- data/ext/ffi_c/libffi/testsuite/Makefile.in +218 -111
- data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +120 -25
- data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +21 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/align_mixed.c +46 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +4 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/{closure_stdcall.c → closure_simple.c} +7 -16
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +4 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +4 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +4 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +10 -9
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +3 -3
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +10 -9
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_many_mixed_args.c +70 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c +55 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +11 -9
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_struct_va1.c +114 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar_va.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint_va.c +45 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulong_va.c +45 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort_va.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +23 -40
- data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +3 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +6 -4
- data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +4 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/float_va.c +107 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +18 -19
- data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +6 -16
- data/ext/ffi_c/libffi/testsuite/libffi.call/many2.c +57 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many_double.c +70 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many_mixed.c +78 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +0 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +6 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +8 -8
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +6 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct11.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +6 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +6 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +6 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/offsets.c +46 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/pr1172638.c +127 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +7 -7
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +7 -7
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +5 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen2.c +49 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen3.c +49 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen4.c +55 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +9 -7
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +7 -7
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +7 -6
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +9 -8
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +9 -8
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +9 -9
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +9 -9
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +9 -8
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +9 -8
- data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/uninitialized.c +61 -0
- data/ext/ffi_c/libffi/testsuite/{libffi.special → libffi.call}/unwindtest.cc +3 -10
- data/ext/ffi_c/libffi/testsuite/{libffi.special → libffi.call}/unwindtest_ffi_call.cc +2 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/va_1.c +196 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct1.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +123 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +125 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex.inc +91 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex.inc +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct.inc +71 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va.inc +80 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_float.c +16 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/{libffi.special/special.exp → libffi.complex/complex.exp} +9 -8
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex.inc +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_double.inc +7 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_float.inc +7 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc +7 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_int.c +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/ffitest.h +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex.inc +78 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex.inc +37 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1.inc +41 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2.inc +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_double.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_float.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_longdouble.c +10 -0
- data/ext/ffi_c/libffi/testsuite/libffi.go/aa-direct.c +34 -0
- data/ext/ffi_c/libffi/testsuite/libffi.go/closure1.c +28 -0
- data/ext/ffi_c/libffi/testsuite/libffi.go/ffitest.h +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.go/go.exp +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.go/static-chain.h +19 -0
- data/ffi.gemspec +2 -2
- data/lib/2.0/ffi_c.so +0 -0
- data/lib/2.1/ffi_c.so +0 -0
- data/lib/2.2/ffi_c.so +0 -0
- data/lib/2.3/ffi_c.so +0 -0
- data/lib/2.4/ffi_c.so +0 -0
- data/lib/2.5/ffi_c.so +0 -0
- data/lib/ffi/enum.rb +124 -0
- data/lib/ffi/library.rb +65 -13
- data/lib/ffi/platform.rb +7 -2
- data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
- data/lib/ffi/platform/x86_64-windows/types.conf +113 -20
- data/lib/ffi/pointer.rb +1 -0
- data/lib/ffi/struct.rb +0 -2
- data/lib/ffi/version.rb +1 -1
- data/spec/ffi/bitmask_spec.rb +575 -0
- data/spec/ffi/embed-test/ext/Makefile +242 -0
- data/spec/ffi/fixtures/BitmaskTest.c +51 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +4 -0
- data/spec/ffi/struct_spec.rb +0 -4
- metadata +158 -32
- data/ext/ffi_c/libffi/Makefile.vc +0 -141
- data/ext/ffi_c/libffi/Makefile.vc64 +0 -141
- data/ext/ffi_c/libffi/build-ios.sh +0 -67
- data/ext/ffi_c/libffi/doc/libffi.info +0 -593
- data/ext/ffi_c/libffi/doc/stamp-vti +0 -4
- data/ext/ffi_c/libffi/include/ffi.h.vc +0 -427
- data/ext/ffi_c/libffi/include/ffi.h.vc64 +0 -427
- data/ext/ffi_c/libffi/src/arm/gentramp.sh +0 -118
- data/ext/ffi_c/libffi/src/arm/trampoline.S +0 -4450
- data/ext/ffi_c/libffi/src/x86/darwin.S +0 -444
- data/ext/ffi_c/libffi/src/x86/darwin64.S +0 -416
- data/ext/ffi_c/libffi/src/x86/freebsd.S +0 -458
- data/ext/ffi_c/libffi/src/x86/win32.S +0 -1065
- data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +0 -300
- data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +0 -63
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +0 -44
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +0 -96
@@ -1,10 +1,11 @@
|
|
1
1
|
/* -----------------------------------------------------------------------
|
2
|
-
ffi.c - Copyright (c) 2011
|
2
|
+
ffi.c - Copyright (c) 2011 Timothy Wall
|
3
|
+
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
|
3
4
|
Copyright (c) 2011 Anthony Green
|
4
5
|
Copyright (c) 2011 Free Software Foundation
|
5
6
|
Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
|
6
|
-
|
7
|
-
ARM Foreign Function Interface
|
7
|
+
|
8
|
+
ARM Foreign Function Interface
|
8
9
|
|
9
10
|
Permission is hereby granted, free of charge, to any person obtaining
|
10
11
|
a copy of this software and associated documentation files (the
|
@@ -27,660 +28,734 @@
|
|
27
28
|
DEALINGS IN THE SOFTWARE.
|
28
29
|
----------------------------------------------------------------------- */
|
29
30
|
|
31
|
+
#include <fficonfig.h>
|
30
32
|
#include <ffi.h>
|
31
33
|
#include <ffi_common.h>
|
32
|
-
|
33
34
|
#include <stdlib.h>
|
35
|
+
#include "internal.h"
|
36
|
+
|
37
|
+
#if FFI_EXEC_TRAMPOLINE_TABLE
|
38
|
+
|
39
|
+
#ifdef __MACH__
|
40
|
+
#include <mach/vm_param.h>
|
41
|
+
#endif
|
42
|
+
|
43
|
+
#else
|
44
|
+
extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
|
45
|
+
#endif
|
34
46
|
|
35
47
|
/* Forward declares. */
|
36
|
-
static int vfp_type_p (ffi_type *);
|
48
|
+
static int vfp_type_p (const ffi_type *);
|
37
49
|
static void layout_vfp_args (ffi_cif *);
|
38
50
|
|
39
|
-
|
40
|
-
|
41
|
-
|
51
|
+
static void *
|
52
|
+
ffi_align (ffi_type *ty, void *p)
|
53
|
+
{
|
54
|
+
/* Align if necessary */
|
55
|
+
size_t alignment;
|
56
|
+
#ifdef _WIN32_WCE
|
57
|
+
alignment = 4;
|
58
|
+
#else
|
59
|
+
alignment = ty->alignment;
|
60
|
+
if (alignment < 4)
|
61
|
+
alignment = 4;
|
62
|
+
#endif
|
63
|
+
return (void *) FFI_ALIGN (p, alignment);
|
64
|
+
}
|
65
|
+
|
66
|
+
static size_t
|
67
|
+
ffi_put_arg (ffi_type *ty, void *src, void *dst)
|
68
|
+
{
|
69
|
+
size_t z = ty->size;
|
70
|
+
|
71
|
+
switch (ty->type)
|
72
|
+
{
|
73
|
+
case FFI_TYPE_SINT8:
|
74
|
+
*(UINT32 *)dst = *(SINT8 *)src;
|
75
|
+
break;
|
76
|
+
case FFI_TYPE_UINT8:
|
77
|
+
*(UINT32 *)dst = *(UINT8 *)src;
|
78
|
+
break;
|
79
|
+
case FFI_TYPE_SINT16:
|
80
|
+
*(UINT32 *)dst = *(SINT16 *)src;
|
81
|
+
break;
|
82
|
+
case FFI_TYPE_UINT16:
|
83
|
+
*(UINT32 *)dst = *(UINT16 *)src;
|
84
|
+
break;
|
85
|
+
|
86
|
+
case FFI_TYPE_INT:
|
87
|
+
case FFI_TYPE_SINT32:
|
88
|
+
case FFI_TYPE_UINT32:
|
89
|
+
case FFI_TYPE_POINTER:
|
90
|
+
case FFI_TYPE_FLOAT:
|
91
|
+
*(UINT32 *)dst = *(UINT32 *)src;
|
92
|
+
break;
|
93
|
+
|
94
|
+
case FFI_TYPE_SINT64:
|
95
|
+
case FFI_TYPE_UINT64:
|
96
|
+
case FFI_TYPE_DOUBLE:
|
97
|
+
*(UINT64 *)dst = *(UINT64 *)src;
|
98
|
+
break;
|
99
|
+
|
100
|
+
case FFI_TYPE_STRUCT:
|
101
|
+
case FFI_TYPE_COMPLEX:
|
102
|
+
memcpy (dst, src, z);
|
103
|
+
break;
|
104
|
+
|
105
|
+
default:
|
106
|
+
abort();
|
107
|
+
}
|
108
|
+
|
109
|
+
return FFI_ALIGN (z, 4);
|
110
|
+
}
|
111
|
+
|
112
|
+
/* ffi_prep_args is called once stack space has been allocated
|
113
|
+
for the function's arguments.
|
114
|
+
|
42
115
|
The vfp_space parameter is the load area for VFP regs, the return
|
43
116
|
value is cif->vfp_used (word bitset of VFP regs used for passing
|
44
117
|
arguments). These are only used for the VFP hard-float ABI.
|
45
118
|
*/
|
46
|
-
|
119
|
+
static void
|
120
|
+
ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
|
121
|
+
void **avalue, char *argp)
|
47
122
|
{
|
48
|
-
|
49
|
-
|
50
|
-
register char *argp;
|
51
|
-
register ffi_type **p_arg;
|
123
|
+
ffi_type **arg_types = cif->arg_types;
|
124
|
+
int i, n;
|
52
125
|
|
53
|
-
|
126
|
+
if (flags == ARM_TYPE_STRUCT)
|
127
|
+
{
|
128
|
+
*(void **) argp = rvalue;
|
129
|
+
argp += 4;
|
130
|
+
}
|
54
131
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
132
|
+
for (i = 0, n = cif->nargs; i < n; i++)
|
133
|
+
{
|
134
|
+
ffi_type *ty = arg_types[i];
|
135
|
+
argp = ffi_align (ty, argp);
|
136
|
+
argp += ffi_put_arg (ty, avalue[i], argp);
|
137
|
+
}
|
138
|
+
}
|
59
139
|
|
60
|
-
|
140
|
+
static void
|
141
|
+
ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
|
142
|
+
void **avalue, char *stack, char *vfp_space)
|
143
|
+
{
|
144
|
+
ffi_type **arg_types = cif->arg_types;
|
145
|
+
int i, n, vi = 0;
|
146
|
+
char *argp, *regp, *eo_regp;
|
147
|
+
char stack_used = 0;
|
148
|
+
char done_with_regs = 0;
|
149
|
+
|
150
|
+
/* The first 4 words on the stack are used for values
|
151
|
+
passed in core registers. */
|
152
|
+
regp = stack;
|
153
|
+
eo_regp = argp = regp + 16;
|
154
|
+
|
155
|
+
/* If the function returns an FFI_TYPE_STRUCT in memory,
|
156
|
+
that address is passed in r0 to the function. */
|
157
|
+
if (flags == ARM_TYPE_STRUCT)
|
158
|
+
{
|
159
|
+
*(void **) regp = rvalue;
|
160
|
+
regp += 4;
|
161
|
+
}
|
61
162
|
|
62
|
-
for (i =
|
63
|
-
(i != 0);
|
64
|
-
i--, p_arg++)
|
163
|
+
for (i = 0, n = cif->nargs; i < n; i++)
|
65
164
|
{
|
66
|
-
|
165
|
+
ffi_type *ty = arg_types[i];
|
166
|
+
void *a = avalue[i];
|
167
|
+
int is_vfp_type = vfp_type_p (ty);
|
67
168
|
|
68
169
|
/* Allocated in VFP registers. */
|
69
|
-
if (
|
70
|
-
&& vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
|
170
|
+
if (vi < cif->vfp_nargs && is_vfp_type)
|
71
171
|
{
|
72
|
-
|
73
|
-
|
74
|
-
*((float*)vfp_slot) = *((float*)*p_argv);
|
75
|
-
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
76
|
-
*((double*)vfp_slot) = *((double*)*p_argv);
|
77
|
-
else
|
78
|
-
memcpy(vfp_slot, *p_argv, (*p_arg)->size);
|
79
|
-
p_argv++;
|
172
|
+
char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
|
173
|
+
ffi_put_arg (ty, a, vfp_slot);
|
80
174
|
continue;
|
81
175
|
}
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
z = (*p_arg)->size;
|
92
|
-
if (z < sizeof(int))
|
93
|
-
{
|
94
|
-
z = sizeof(int);
|
95
|
-
switch ((*p_arg)->type)
|
96
|
-
{
|
97
|
-
case FFI_TYPE_SINT8:
|
98
|
-
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
99
|
-
break;
|
100
|
-
|
101
|
-
case FFI_TYPE_UINT8:
|
102
|
-
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
103
|
-
break;
|
104
|
-
|
105
|
-
case FFI_TYPE_SINT16:
|
106
|
-
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
107
|
-
break;
|
108
|
-
|
109
|
-
case FFI_TYPE_UINT16:
|
110
|
-
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
111
|
-
break;
|
112
|
-
|
113
|
-
case FFI_TYPE_STRUCT:
|
114
|
-
memcpy(argp, *p_argv, (*p_arg)->size);
|
115
|
-
break;
|
116
|
-
|
117
|
-
default:
|
118
|
-
FFI_ASSERT(0);
|
119
|
-
}
|
120
|
-
}
|
121
|
-
else if (z == sizeof(int))
|
176
|
+
/* Try allocating in core registers. */
|
177
|
+
else if (!done_with_regs && !is_vfp_type)
|
178
|
+
{
|
179
|
+
char *tregp = ffi_align (ty, regp);
|
180
|
+
size_t size = ty->size;
|
181
|
+
size = (size < 4) ? 4 : size; // pad
|
182
|
+
/* Check if there is space left in the aligned register
|
183
|
+
area to place the argument. */
|
184
|
+
if (tregp + size <= eo_regp)
|
122
185
|
{
|
123
|
-
|
186
|
+
regp = tregp + ffi_put_arg (ty, a, tregp);
|
187
|
+
done_with_regs = (regp == argp);
|
188
|
+
// ensure we did not write into the stack area
|
189
|
+
FFI_ASSERT (regp <= argp);
|
190
|
+
continue;
|
124
191
|
}
|
125
|
-
|
192
|
+
/* In case there are no arguments in the stack area yet,
|
193
|
+
the argument is passed in the remaining core registers
|
194
|
+
and on the stack. */
|
195
|
+
else if (!stack_used)
|
126
196
|
{
|
127
|
-
|
197
|
+
stack_used = 1;
|
198
|
+
done_with_regs = 1;
|
199
|
+
argp = tregp + ffi_put_arg (ty, a, tregp);
|
200
|
+
FFI_ASSERT (eo_regp < argp);
|
201
|
+
continue;
|
128
202
|
}
|
129
|
-
|
130
|
-
|
203
|
+
}
|
204
|
+
/* Base case, arguments are passed on the stack */
|
205
|
+
stack_used = 1;
|
206
|
+
argp = ffi_align (ty, argp);
|
207
|
+
argp += ffi_put_arg (ty, a, argp);
|
131
208
|
}
|
132
|
-
|
133
|
-
/* Indicate the VFP registers used. */
|
134
|
-
return ecif->cif->vfp_used;
|
135
209
|
}
|
136
210
|
|
137
211
|
/* Perform machine dependent cif processing */
|
138
|
-
ffi_status
|
212
|
+
ffi_status
|
213
|
+
ffi_prep_cif_machdep (ffi_cif *cif)
|
139
214
|
{
|
140
|
-
int
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
215
|
+
int flags = 0, cabi = cif->abi;
|
216
|
+
size_t bytes = cif->bytes;
|
217
|
+
|
218
|
+
/* Map out the register placements of VFP register args. The VFP
|
219
|
+
hard-float calling conventions are slightly more sophisticated
|
220
|
+
than the base calling conventions, so we do it here instead of
|
221
|
+
in ffi_prep_args(). */
|
222
|
+
if (cabi == FFI_VFP)
|
223
|
+
layout_vfp_args (cif);
|
145
224
|
|
146
225
|
/* Set the return type flag */
|
147
226
|
switch (cif->rtype->type)
|
148
227
|
{
|
149
228
|
case FFI_TYPE_VOID:
|
150
|
-
|
151
|
-
|
152
|
-
|
229
|
+
flags = ARM_TYPE_VOID;
|
230
|
+
break;
|
231
|
+
|
232
|
+
case FFI_TYPE_INT:
|
233
|
+
case FFI_TYPE_UINT8:
|
234
|
+
case FFI_TYPE_SINT8:
|
235
|
+
case FFI_TYPE_UINT16:
|
236
|
+
case FFI_TYPE_SINT16:
|
237
|
+
case FFI_TYPE_UINT32:
|
238
|
+
case FFI_TYPE_SINT32:
|
239
|
+
case FFI_TYPE_POINTER:
|
240
|
+
flags = ARM_TYPE_INT;
|
153
241
|
break;
|
154
242
|
|
155
243
|
case FFI_TYPE_SINT64:
|
156
244
|
case FFI_TYPE_UINT64:
|
157
|
-
|
245
|
+
flags = ARM_TYPE_INT64;
|
246
|
+
break;
|
247
|
+
|
248
|
+
case FFI_TYPE_FLOAT:
|
249
|
+
flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
|
250
|
+
break;
|
251
|
+
case FFI_TYPE_DOUBLE:
|
252
|
+
flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
|
158
253
|
break;
|
159
254
|
|
160
255
|
case FFI_TYPE_STRUCT:
|
161
|
-
|
162
|
-
|
256
|
+
case FFI_TYPE_COMPLEX:
|
257
|
+
if (cabi == FFI_VFP)
|
163
258
|
{
|
164
|
-
|
165
|
-
|
166
|
-
|
259
|
+
int h = vfp_type_p (cif->rtype);
|
260
|
+
|
261
|
+
flags = ARM_TYPE_VFP_N;
|
262
|
+
if (h == 0x100 + FFI_TYPE_FLOAT)
|
263
|
+
flags = ARM_TYPE_VFP_S;
|
264
|
+
if (h == 0x100 + FFI_TYPE_DOUBLE)
|
265
|
+
flags = ARM_TYPE_VFP_D;
|
266
|
+
if (h != 0)
|
267
|
+
break;
|
167
268
|
}
|
168
|
-
|
169
|
-
|
170
|
-
|
269
|
+
|
270
|
+
/* A Composite Type not larger than 4 bytes is returned in r0.
|
271
|
+
A Composite Type larger than 4 bytes, or whose size cannot
|
272
|
+
be determined statically ... is stored in memory at an
|
273
|
+
address passed [in r0]. */
|
274
|
+
if (cif->rtype->size <= 4)
|
275
|
+
flags = ARM_TYPE_INT;
|
171
276
|
else
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
277
|
+
{
|
278
|
+
flags = ARM_TYPE_STRUCT;
|
279
|
+
bytes += 4;
|
280
|
+
}
|
176
281
|
break;
|
177
282
|
|
178
283
|
default:
|
179
|
-
|
180
|
-
break;
|
284
|
+
abort();
|
181
285
|
}
|
182
286
|
|
183
|
-
/*
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
287
|
+
/* Round the stack up to a multiple of 8 bytes. This isn't needed
|
288
|
+
everywhere, but it is on some platforms, and it doesn't harm anything
|
289
|
+
when it isn't needed. */
|
290
|
+
bytes = FFI_ALIGN (bytes, 8);
|
291
|
+
|
292
|
+
/* Minimum stack space is the 4 register arguments that we pop. */
|
293
|
+
if (bytes < 4*4)
|
294
|
+
bytes = 4*4;
|
295
|
+
|
296
|
+
cif->bytes = bytes;
|
297
|
+
cif->flags = flags;
|
188
298
|
|
189
299
|
return FFI_OK;
|
190
300
|
}
|
191
301
|
|
192
|
-
/*
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
302
|
+
/* Perform machine dependent cif processing for variadic calls */
|
303
|
+
ffi_status
|
304
|
+
ffi_prep_cif_machdep_var (ffi_cif * cif,
|
305
|
+
unsigned int nfixedargs, unsigned int ntotalargs)
|
197
306
|
{
|
198
|
-
|
307
|
+
/* VFP variadic calls actually use the SYSV ABI */
|
308
|
+
if (cif->abi == FFI_VFP)
|
309
|
+
cif->abi = FFI_SYSV;
|
199
310
|
|
200
|
-
|
201
|
-
|
202
|
-
int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
|
203
|
-
|| cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
|
311
|
+
return ffi_prep_cif_machdep (cif);
|
312
|
+
}
|
204
313
|
|
205
|
-
|
206
|
-
ecif.avalue = avalue;
|
314
|
+
/* Prototypes for assembly functions, in sysv.S. */
|
207
315
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
316
|
+
struct call_frame
|
317
|
+
{
|
318
|
+
void *fp;
|
319
|
+
void *lr;
|
320
|
+
void *rvalue;
|
321
|
+
int flags;
|
322
|
+
void *closure;
|
323
|
+
};
|
212
324
|
|
213
|
-
|
214
|
-
|
325
|
+
extern void ffi_call_SYSV (void *stack, struct call_frame *,
|
326
|
+
void (*fn) (void)) FFI_HIDDEN;
|
327
|
+
extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
|
328
|
+
void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
|
329
|
+
|
330
|
+
static void
|
331
|
+
ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
|
332
|
+
void **avalue, void *closure)
|
333
|
+
{
|
334
|
+
int flags = cif->flags;
|
335
|
+
ffi_type *rtype = cif->rtype;
|
336
|
+
size_t bytes, rsize, vfp_size;
|
337
|
+
char *stack, *vfp_space, *new_rvalue;
|
338
|
+
struct call_frame *frame;
|
339
|
+
|
340
|
+
rsize = 0;
|
341
|
+
if (rvalue == NULL)
|
215
342
|
{
|
216
|
-
|
343
|
+
/* If the return value is a struct and we don't have a return
|
344
|
+
value address then we need to make one. Otherwise the return
|
345
|
+
value is in registers and we can ignore them. */
|
346
|
+
if (flags == ARM_TYPE_STRUCT)
|
347
|
+
rsize = rtype->size;
|
348
|
+
else
|
349
|
+
flags = ARM_TYPE_VOID;
|
217
350
|
}
|
218
|
-
else if (
|
219
|
-
ecif.rvalue = &temp;
|
220
|
-
else if (vfp_struct)
|
351
|
+
else if (flags == ARM_TYPE_VFP_N)
|
221
352
|
{
|
222
353
|
/* Largest case is double x 4. */
|
223
|
-
|
354
|
+
rsize = 32;
|
224
355
|
}
|
225
|
-
else
|
226
|
-
|
356
|
+
else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
|
357
|
+
rsize = 4;
|
227
358
|
|
228
|
-
|
229
|
-
|
230
|
-
case FFI_SYSV:
|
231
|
-
ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
|
232
|
-
break;
|
359
|
+
/* Largest case. */
|
360
|
+
vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
|
233
361
|
|
234
|
-
|
235
|
-
|
236
|
-
break;
|
362
|
+
bytes = cif->bytes;
|
363
|
+
stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
|
237
364
|
|
238
|
-
|
239
|
-
|
240
|
-
|
365
|
+
vfp_space = NULL;
|
366
|
+
if (vfp_size)
|
367
|
+
{
|
368
|
+
vfp_space = stack;
|
369
|
+
stack += vfp_size;
|
241
370
|
}
|
242
|
-
if (small_struct)
|
243
|
-
memcpy (rvalue, &temp, cif->rtype->size);
|
244
|
-
else if (vfp_struct)
|
245
|
-
memcpy (rvalue, ecif.rvalue, cif->rtype->size);
|
246
|
-
}
|
247
371
|
|
248
|
-
|
372
|
+
frame = (struct call_frame *)(stack + bytes);
|
249
373
|
|
250
|
-
|
251
|
-
|
374
|
+
new_rvalue = rvalue;
|
375
|
+
if (rsize)
|
376
|
+
new_rvalue = (void *)(frame + 1);
|
252
377
|
|
253
|
-
|
378
|
+
frame->rvalue = new_rvalue;
|
379
|
+
frame->flags = flags;
|
380
|
+
frame->closure = closure;
|
254
381
|
|
255
|
-
|
382
|
+
if (vfp_space)
|
383
|
+
{
|
384
|
+
ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
|
385
|
+
ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
|
386
|
+
}
|
387
|
+
else
|
388
|
+
{
|
389
|
+
ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
|
390
|
+
ffi_call_SYSV (stack, frame, fn);
|
391
|
+
}
|
256
392
|
|
257
|
-
|
393
|
+
if (rvalue && rvalue != new_rvalue)
|
394
|
+
memcpy (rvalue, new_rvalue, rtype->size);
|
395
|
+
}
|
258
396
|
|
259
|
-
|
260
|
-
|
261
|
-
ffi_closure *closure;
|
262
|
-
void **respp;
|
263
|
-
void *args;
|
264
|
-
void *vfp_args;
|
397
|
+
void
|
398
|
+
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
|
265
399
|
{
|
266
|
-
|
267
|
-
|
268
|
-
void **arg_area;
|
400
|
+
ffi_call_int (cif, fn, rvalue, avalue, NULL);
|
401
|
+
}
|
269
402
|
|
270
|
-
|
271
|
-
|
403
|
+
void
|
404
|
+
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
|
405
|
+
void **avalue, void *closure)
|
406
|
+
{
|
407
|
+
ffi_call_int (cif, fn, rvalue, avalue, closure);
|
408
|
+
}
|
272
409
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
410
|
+
static void *
|
411
|
+
ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
|
412
|
+
char *argp, void **avalue)
|
413
|
+
{
|
414
|
+
ffi_type **arg_types = cif->arg_types;
|
415
|
+
int i, n;
|
416
|
+
|
417
|
+
if (cif->flags == ARM_TYPE_STRUCT)
|
418
|
+
{
|
419
|
+
rvalue = *(void **) argp;
|
420
|
+
argp += 4;
|
421
|
+
}
|
278
422
|
|
279
|
-
|
423
|
+
for (i = 0, n = cif->nargs; i < n; i++)
|
424
|
+
{
|
425
|
+
ffi_type *ty = arg_types[i];
|
426
|
+
size_t z = ty->size;
|
280
427
|
|
281
|
-
|
428
|
+
argp = ffi_align (ty, argp);
|
429
|
+
avalue[i] = (void *) argp;
|
430
|
+
argp += z;
|
431
|
+
}
|
282
432
|
|
283
|
-
return
|
433
|
+
return rvalue;
|
284
434
|
}
|
285
435
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
void **avalue, ffi_cif *cif,
|
290
|
-
/* Used only under VFP hard-float ABI. */
|
291
|
-
float *vfp_stack)
|
292
|
-
/*@=exportheader@*/
|
436
|
+
static void *
|
437
|
+
ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
|
438
|
+
char *vfp_space, void **avalue)
|
293
439
|
{
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
argp = stack;
|
440
|
+
ffi_type **arg_types = cif->arg_types;
|
441
|
+
int i, n, vi = 0;
|
442
|
+
char *argp, *regp, *eo_regp;
|
443
|
+
char done_with_regs = 0;
|
444
|
+
char stack_used = 0;
|
300
445
|
|
301
|
-
|
302
|
-
|
303
|
-
argp += 4;
|
304
|
-
}
|
446
|
+
regp = stack;
|
447
|
+
eo_regp = argp = regp + 16;
|
305
448
|
|
306
|
-
|
449
|
+
if (cif->flags == ARM_TYPE_STRUCT)
|
450
|
+
{
|
451
|
+
rvalue = *(void **) regp;
|
452
|
+
regp += 4;
|
453
|
+
}
|
307
454
|
|
308
|
-
for (i =
|
455
|
+
for (i = 0, n = cif->nargs; i < n; i++)
|
309
456
|
{
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
457
|
+
ffi_type *ty = arg_types[i];
|
458
|
+
int is_vfp_type = vfp_type_p (ty);
|
459
|
+
size_t z = ty->size;
|
460
|
+
|
461
|
+
if (vi < cif->vfp_nargs && is_vfp_type)
|
315
462
|
{
|
316
|
-
|
463
|
+
avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
|
317
464
|
continue;
|
318
465
|
}
|
466
|
+
else if (!done_with_regs && !is_vfp_type)
|
467
|
+
{
|
468
|
+
char *tregp = ffi_align (ty, regp);
|
319
469
|
|
320
|
-
|
321
|
-
if (alignment < 4)
|
322
|
-
alignment = 4;
|
323
|
-
/* Align if necessary */
|
324
|
-
if ((alignment - 1) & (unsigned) argp) {
|
325
|
-
argp = (char *) ALIGN(argp, alignment);
|
326
|
-
}
|
327
|
-
|
328
|
-
z = (*p_arg)->size;
|
329
|
-
|
330
|
-
/* because we're little endian, this is what it turns into. */
|
470
|
+
z = (z < 4) ? 4 : z; // pad
|
331
471
|
|
332
|
-
|
472
|
+
/* If the arguments either fits into the registers or uses registers
|
473
|
+
and stack, while we haven't read other things from the stack */
|
474
|
+
if (tregp + z <= eo_regp || !stack_used)
|
475
|
+
{
|
476
|
+
/* Because we're little endian, this is what it turns into. */
|
477
|
+
avalue[i] = (void *) tregp;
|
478
|
+
regp = tregp + z;
|
479
|
+
|
480
|
+
/* If we read past the last core register, make sure we
|
481
|
+
have not read from the stack before and continue
|
482
|
+
reading after regp. */
|
483
|
+
if (regp > eo_regp)
|
484
|
+
{
|
485
|
+
FFI_ASSERT (!stack_used);
|
486
|
+
argp = regp;
|
487
|
+
}
|
488
|
+
if (regp >= eo_regp)
|
489
|
+
{
|
490
|
+
done_with_regs = 1;
|
491
|
+
stack_used = 1;
|
492
|
+
}
|
493
|
+
continue;
|
494
|
+
}
|
495
|
+
}
|
333
496
|
|
334
|
-
|
497
|
+
stack_used = 1;
|
498
|
+
argp = ffi_align (ty, argp);
|
499
|
+
avalue[i] = (void *) argp;
|
335
500
|
argp += z;
|
336
501
|
}
|
337
|
-
|
338
|
-
return;
|
339
|
-
}
|
340
|
-
|
341
|
-
/* How to make a trampoline. */
|
342
502
|
|
343
|
-
|
344
|
-
|
345
|
-
#include <mach/mach.h>
|
346
|
-
#include <pthread.h>
|
347
|
-
#include <stdio.h>
|
348
|
-
#include <stdlib.h>
|
349
|
-
|
350
|
-
extern void *ffi_closure_trampoline_table_page;
|
351
|
-
|
352
|
-
typedef struct ffi_trampoline_table ffi_trampoline_table;
|
353
|
-
typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
|
354
|
-
|
355
|
-
struct ffi_trampoline_table {
|
356
|
-
/* contigious writable and executable pages */
|
357
|
-
vm_address_t config_page;
|
358
|
-
vm_address_t trampoline_page;
|
359
|
-
|
360
|
-
/* free list tracking */
|
361
|
-
uint16_t free_count;
|
362
|
-
ffi_trampoline_table_entry *free_list;
|
363
|
-
ffi_trampoline_table_entry *free_list_pool;
|
364
|
-
|
365
|
-
ffi_trampoline_table *prev;
|
366
|
-
ffi_trampoline_table *next;
|
367
|
-
};
|
503
|
+
return rvalue;
|
504
|
+
}
|
368
505
|
|
369
|
-
struct
|
370
|
-
|
371
|
-
|
506
|
+
struct closure_frame
|
507
|
+
{
|
508
|
+
char vfp_space[8*8] __attribute__((aligned(8)));
|
509
|
+
char result[8*4];
|
510
|
+
char argp[];
|
372
511
|
};
|
373
512
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
|
380
|
-
#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
|
381
|
-
|
382
|
-
/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
|
383
|
-
#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
|
384
|
-
|
385
|
-
/* Total number of trampolines that fit in one trampoline table */
|
386
|
-
#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
|
387
|
-
|
388
|
-
static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
|
389
|
-
static ffi_trampoline_table *ffi_trampoline_tables = NULL;
|
390
|
-
|
391
|
-
static ffi_trampoline_table *
|
392
|
-
ffi_trampoline_table_alloc ()
|
513
|
+
int FFI_HIDDEN
|
514
|
+
ffi_closure_inner_SYSV (ffi_cif *cif,
|
515
|
+
void (*fun) (ffi_cif *, void *, void **, void *),
|
516
|
+
void *user_data,
|
517
|
+
struct closure_frame *frame)
|
393
518
|
{
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
/* Try to allocate two pages */
|
402
|
-
kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
|
403
|
-
if (kt != KERN_SUCCESS) {
|
404
|
-
fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
|
405
|
-
break;
|
406
|
-
}
|
519
|
+
void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
|
520
|
+
void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
|
521
|
+
frame->argp, avalue);
|
522
|
+
fun (cif, rvalue, avalue, user_data);
|
523
|
+
return cif->flags;
|
524
|
+
}
|
407
525
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
526
|
+
int FFI_HIDDEN
|
527
|
+
ffi_closure_inner_VFP (ffi_cif *cif,
|
528
|
+
void (*fun) (ffi_cif *, void *, void **, void *),
|
529
|
+
void *user_data,
|
530
|
+
struct closure_frame *frame)
|
531
|
+
{
|
532
|
+
void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
|
533
|
+
void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
|
534
|
+
frame->vfp_space, avalue);
|
535
|
+
fun (cif, rvalue, avalue, user_data);
|
536
|
+
return cif->flags;
|
537
|
+
}
|
415
538
|
|
416
|
-
|
417
|
-
|
418
|
-
|
539
|
+
void ffi_closure_SYSV (void) FFI_HIDDEN;
|
540
|
+
void ffi_closure_VFP (void) FFI_HIDDEN;
|
541
|
+
void ffi_go_closure_SYSV (void) FFI_HIDDEN;
|
542
|
+
void ffi_go_closure_VFP (void) FFI_HIDDEN;
|
419
543
|
|
420
|
-
|
544
|
+
/* the cif must already be prep'ed */
|
421
545
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
546
|
+
ffi_status
|
547
|
+
ffi_prep_closure_loc (ffi_closure * closure,
|
548
|
+
ffi_cif * cif,
|
549
|
+
void (*fun) (ffi_cif *, void *, void **, void *),
|
550
|
+
void *user_data, void *codeloc)
|
551
|
+
{
|
552
|
+
void (*closure_func) (void) = ffi_closure_SYSV;
|
428
553
|
|
429
|
-
|
430
|
-
|
554
|
+
if (cif->abi == FFI_VFP)
|
555
|
+
{
|
556
|
+
/* We only need take the vfp path if there are vfp arguments. */
|
557
|
+
if (cif->vfp_used)
|
558
|
+
closure_func = ffi_closure_VFP;
|
431
559
|
}
|
560
|
+
else if (cif->abi != FFI_SYSV)
|
561
|
+
return FFI_BAD_ABI;
|
432
562
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
for (i = 0; i < table->free_count; i++) {
|
444
|
-
ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
|
445
|
-
entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
|
446
|
-
|
447
|
-
if (i < table->free_count - 1)
|
448
|
-
entry->next = &table->free_list_pool[i+1];
|
449
|
-
}
|
563
|
+
#if FFI_EXEC_TRAMPOLINE_TABLE
|
564
|
+
void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
|
565
|
+
config[0] = closure;
|
566
|
+
config[1] = closure_func;
|
567
|
+
#else
|
568
|
+
memcpy (closure->tramp, ffi_arm_trampoline, 8);
|
569
|
+
__clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */
|
570
|
+
__clear_cache(codeloc, codeloc + 8); /* clear insn map */
|
571
|
+
*(void (**)(void))(closure->tramp + 8) = closure_func;
|
572
|
+
#endif
|
450
573
|
|
451
|
-
|
452
|
-
|
574
|
+
closure->cif = cif;
|
575
|
+
closure->fun = fun;
|
576
|
+
closure->user_data = user_data;
|
453
577
|
|
454
|
-
return
|
578
|
+
return FFI_OK;
|
455
579
|
}
|
456
580
|
|
457
|
-
|
458
|
-
|
581
|
+
ffi_status
|
582
|
+
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
|
583
|
+
void (*fun) (ffi_cif *, void *, void **, void *))
|
459
584
|
{
|
460
|
-
|
461
|
-
ffi_closure *closure = malloc(size);
|
462
|
-
if (closure == NULL)
|
463
|
-
return NULL;
|
464
|
-
|
465
|
-
pthread_mutex_lock(&ffi_trampoline_lock);
|
466
|
-
|
467
|
-
/* Check for an active trampoline table with available entries. */
|
468
|
-
ffi_trampoline_table *table = ffi_trampoline_tables;
|
469
|
-
if (table == NULL || table->free_list == NULL) {
|
470
|
-
table = ffi_trampoline_table_alloc ();
|
471
|
-
if (table == NULL) {
|
472
|
-
free(closure);
|
473
|
-
return NULL;
|
474
|
-
}
|
585
|
+
void (*closure_func) (void) = ffi_go_closure_SYSV;
|
475
586
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
587
|
+
if (cif->abi == FFI_VFP)
|
588
|
+
{
|
589
|
+
/* We only need take the vfp path if there are vfp arguments. */
|
590
|
+
if (cif->vfp_used)
|
591
|
+
closure_func = ffi_go_closure_VFP;
|
592
|
+
}
|
593
|
+
else if (cif->abi != FFI_SYSV)
|
594
|
+
return FFI_BAD_ABI;
|
483
595
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
ffi_trampoline_tables->free_count--;
|
488
|
-
entry->next = NULL;
|
596
|
+
closure->tramp = closure_func;
|
597
|
+
closure->cif = cif;
|
598
|
+
closure->fun = fun;
|
489
599
|
|
490
|
-
|
600
|
+
return FFI_OK;
|
601
|
+
}
|
491
602
|
|
492
|
-
|
493
|
-
*code = entry->trampoline;
|
494
|
-
closure->trampoline_table = table;
|
495
|
-
closure->trampoline_table_entry = entry;
|
603
|
+
/* Below are routines for VFP hard-float support. */
|
496
604
|
|
497
|
-
return
|
498
|
-
|
605
|
+
/* A subroutine of vfp_type_p. Given a structure type, return the type code
|
606
|
+
of the first non-structure element. Recurse for structure elements.
|
607
|
+
Return -1 if the structure is in fact empty, i.e. no nested elements. */
|
499
608
|
|
500
|
-
|
501
|
-
|
609
|
+
static int
|
610
|
+
is_hfa0 (const ffi_type *ty)
|
502
611
|
{
|
503
|
-
|
504
|
-
|
505
|
-
pthread_mutex_lock(&ffi_trampoline_lock);
|
506
|
-
|
507
|
-
/* Fetch the table and entry references */
|
508
|
-
ffi_trampoline_table *table = closure->trampoline_table;
|
509
|
-
ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
|
510
|
-
|
511
|
-
/* Return the entry to the free list */
|
512
|
-
entry->next = table->free_list;
|
513
|
-
table->free_list = entry;
|
514
|
-
table->free_count++;
|
515
|
-
|
516
|
-
/* If all trampolines within this table are free, and at least one other table exists, deallocate
|
517
|
-
* the table */
|
518
|
-
if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
|
519
|
-
/* Remove from the list */
|
520
|
-
if (table->prev != NULL)
|
521
|
-
table->prev->next = table->next;
|
522
|
-
|
523
|
-
if (table->next != NULL)
|
524
|
-
table->next->prev = table->prev;
|
525
|
-
|
526
|
-
/* Deallocate pages */
|
527
|
-
kern_return_t kt;
|
528
|
-
kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
|
529
|
-
if (kt != KERN_SUCCESS)
|
530
|
-
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
|
531
|
-
|
532
|
-
kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
|
533
|
-
if (kt != KERN_SUCCESS)
|
534
|
-
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
|
535
|
-
|
536
|
-
/* Deallocate free list */
|
537
|
-
free (table->free_list_pool);
|
538
|
-
free (table);
|
539
|
-
} else if (ffi_trampoline_tables != table) {
|
540
|
-
/* Otherwise, bump this table to the top of the list */
|
541
|
-
table->prev = NULL;
|
542
|
-
table->next = ffi_trampoline_tables;
|
543
|
-
if (ffi_trampoline_tables != NULL)
|
544
|
-
ffi_trampoline_tables->prev = table;
|
545
|
-
|
546
|
-
ffi_trampoline_tables = table;
|
547
|
-
}
|
548
|
-
|
549
|
-
pthread_mutex_unlock (&ffi_trampoline_lock);
|
550
|
-
|
551
|
-
/* Free the closure */
|
552
|
-
free (closure);
|
553
|
-
}
|
554
|
-
|
555
|
-
#else
|
612
|
+
ffi_type **elements = ty->elements;
|
613
|
+
int i, ret = -1;
|
556
614
|
|
557
|
-
|
558
|
-
(
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
/* Clear instruction \
|
570
|
-
mapping. */ \
|
571
|
-
})
|
615
|
+
if (elements != NULL)
|
616
|
+
for (i = 0; elements[i]; ++i)
|
617
|
+
{
|
618
|
+
ret = elements[i]->type;
|
619
|
+
if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
|
620
|
+
{
|
621
|
+
ret = is_hfa0 (elements[i]);
|
622
|
+
if (ret < 0)
|
623
|
+
continue;
|
624
|
+
}
|
625
|
+
break;
|
626
|
+
}
|
572
627
|
|
573
|
-
|
628
|
+
return ret;
|
629
|
+
}
|
574
630
|
|
575
|
-
/*
|
631
|
+
/* A subroutine of vfp_type_p. Given a structure type, return true if all
|
632
|
+
of the non-structure elements are the same as CANDIDATE. */
|
576
633
|
|
577
|
-
|
578
|
-
|
579
|
-
ffi_cif* cif,
|
580
|
-
void (*fun)(ffi_cif*,void*,void**,void*),
|
581
|
-
void *user_data,
|
582
|
-
void *codeloc)
|
634
|
+
static int
|
635
|
+
is_hfa1 (const ffi_type *ty, int candidate)
|
583
636
|
{
|
584
|
-
|
585
|
-
|
586
|
-
if (cif->abi == FFI_SYSV)
|
587
|
-
closure_func = &ffi_closure_SYSV;
|
588
|
-
else if (cif->abi == FFI_VFP)
|
589
|
-
closure_func = &ffi_closure_VFP;
|
590
|
-
else
|
591
|
-
return FFI_BAD_ABI;
|
592
|
-
|
593
|
-
#if FFI_EXEC_TRAMPOLINE_TABLE
|
594
|
-
void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
|
595
|
-
config[0] = closure;
|
596
|
-
config[1] = closure_func;
|
597
|
-
#else
|
598
|
-
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
599
|
-
closure_func, \
|
600
|
-
codeloc);
|
601
|
-
#endif
|
637
|
+
ffi_type **elements = ty->elements;
|
638
|
+
int i;
|
602
639
|
|
603
|
-
|
604
|
-
|
605
|
-
|
640
|
+
if (elements != NULL)
|
641
|
+
for (i = 0; elements[i]; ++i)
|
642
|
+
{
|
643
|
+
int t = elements[i]->type;
|
644
|
+
if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
|
645
|
+
{
|
646
|
+
if (!is_hfa1 (elements[i], candidate))
|
647
|
+
return 0;
|
648
|
+
}
|
649
|
+
else if (t != candidate)
|
650
|
+
return 0;
|
651
|
+
}
|
606
652
|
|
607
|
-
return
|
653
|
+
return 1;
|
608
654
|
}
|
609
655
|
|
610
|
-
/*
|
656
|
+
/* Determine if TY is an homogenous floating point aggregate (HFA).
|
657
|
+
That is, a structure consisting of 1 to 4 members of all the same type,
|
658
|
+
where that type is a floating point scalar.
|
659
|
+
|
660
|
+
Returns non-zero iff TY is an HFA. The result is an encoded value where
|
661
|
+
bits 0-7 contain the type code, and bits 8-10 contain the element count. */
|
611
662
|
|
612
|
-
static int
|
663
|
+
static int
|
664
|
+
vfp_type_p (const ffi_type *ty)
|
613
665
|
{
|
614
|
-
|
666
|
+
ffi_type **elements;
|
667
|
+
int candidate, i;
|
668
|
+
size_t size, ele_count;
|
669
|
+
|
670
|
+
/* Quickest tests first. */
|
671
|
+
candidate = ty->type;
|
672
|
+
switch (ty->type)
|
615
673
|
{
|
674
|
+
default:
|
675
|
+
return 0;
|
616
676
|
case FFI_TYPE_FLOAT:
|
617
677
|
case FFI_TYPE_DOUBLE:
|
618
|
-
|
619
|
-
|
620
|
-
|
678
|
+
ele_count = 1;
|
679
|
+
goto done;
|
680
|
+
case FFI_TYPE_COMPLEX:
|
681
|
+
candidate = ty->elements[0]->type;
|
682
|
+
if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
|
683
|
+
return 0;
|
684
|
+
ele_count = 2;
|
685
|
+
goto done;
|
686
|
+
case FFI_TYPE_STRUCT:
|
687
|
+
break;
|
688
|
+
}
|
621
689
|
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
690
|
+
/* No HFA types are smaller than 4 bytes, or larger than 32 bytes. */
|
691
|
+
size = ty->size;
|
692
|
+
if (size < 4 || size > 32)
|
693
|
+
return 0;
|
626
694
|
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
695
|
+
/* Find the type of the first non-structure member. */
|
696
|
+
elements = ty->elements;
|
697
|
+
candidate = elements[0]->type;
|
698
|
+
if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
|
699
|
+
{
|
700
|
+
for (i = 0; ; ++i)
|
701
|
+
{
|
702
|
+
candidate = is_hfa0 (elements[i]);
|
703
|
+
if (candidate >= 0)
|
704
|
+
break;
|
705
|
+
}
|
706
|
+
}
|
631
707
|
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
*elt = base_elt;
|
649
|
-
return 1;
|
650
|
-
}
|
651
|
-
default: ;
|
708
|
+
/* If the first member is not a floating point type, it's not an HFA.
|
709
|
+
Also quickly re-check the size of the structure. */
|
710
|
+
switch (candidate)
|
711
|
+
{
|
712
|
+
case FFI_TYPE_FLOAT:
|
713
|
+
ele_count = size / sizeof(float);
|
714
|
+
if (size != ele_count * sizeof(float))
|
715
|
+
return 0;
|
716
|
+
break;
|
717
|
+
case FFI_TYPE_DOUBLE:
|
718
|
+
ele_count = size / sizeof(double);
|
719
|
+
if (size != ele_count * sizeof(double))
|
720
|
+
return 0;
|
721
|
+
break;
|
722
|
+
default:
|
723
|
+
return 0;
|
652
724
|
}
|
653
|
-
|
654
|
-
|
725
|
+
if (ele_count > 4)
|
726
|
+
return 0;
|
655
727
|
|
656
|
-
|
657
|
-
|
658
|
-
int elt, elnum;
|
659
|
-
if (rec_vfp_type_p (t, &elt, &elnum))
|
728
|
+
/* Finally, make sure that all scalar elements are the same type. */
|
729
|
+
for (i = 0; elements[i]; ++i)
|
660
730
|
{
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
}
|
670
|
-
return (int) t->type;
|
731
|
+
int t = elements[i]->type;
|
732
|
+
if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
|
733
|
+
{
|
734
|
+
if (!is_hfa1 (elements[i], candidate))
|
735
|
+
return 0;
|
736
|
+
}
|
737
|
+
else if (t != candidate)
|
738
|
+
return 0;
|
671
739
|
}
|
672
|
-
|
740
|
+
|
741
|
+
/* All tests succeeded. Encode the result. */
|
742
|
+
done:
|
743
|
+
return (ele_count << 8) | candidate;
|
673
744
|
}
|
674
745
|
|
675
|
-
static
|
746
|
+
static int
|
747
|
+
place_vfp_arg (ffi_cif *cif, int h)
|
676
748
|
{
|
677
|
-
|
678
|
-
int nregs =
|
679
|
-
|
680
|
-
|
749
|
+
unsigned short reg = cif->vfp_reg_free;
|
750
|
+
int align = 1, nregs = h >> 8;
|
751
|
+
|
752
|
+
if ((h & 0xff) == FFI_TYPE_DOUBLE)
|
753
|
+
align = 2, nregs *= 2;
|
754
|
+
|
681
755
|
/* Align register number. */
|
682
756
|
if ((reg & 1) && align == 2)
|
683
757
|
reg++;
|
758
|
+
|
684
759
|
while (reg + nregs <= 16)
|
685
760
|
{
|
686
761
|
int s, new_used = 0;
|
@@ -705,24 +780,29 @@ static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
|
|
705
780
|
reg += 1;
|
706
781
|
cif->vfp_reg_free = reg;
|
707
782
|
}
|
708
|
-
return;
|
709
|
-
next_reg
|
783
|
+
return 0;
|
784
|
+
next_reg:;
|
710
785
|
}
|
786
|
+
// done, mark all regs as used
|
787
|
+
cif->vfp_reg_free = 16;
|
788
|
+
cif->vfp_used = 0xFFFF;
|
789
|
+
return 1;
|
711
790
|
}
|
712
791
|
|
713
|
-
static void
|
792
|
+
static void
|
793
|
+
layout_vfp_args (ffi_cif * cif)
|
714
794
|
{
|
715
795
|
int i;
|
716
796
|
/* Init VFP fields */
|
717
797
|
cif->vfp_used = 0;
|
718
798
|
cif->vfp_nargs = 0;
|
719
799
|
cif->vfp_reg_free = 0;
|
720
|
-
memset (cif->vfp_args, -1, 16);
|
800
|
+
memset (cif->vfp_args, -1, 16); /* Init to -1. */
|
721
801
|
|
722
802
|
for (i = 0; i < cif->nargs; i++)
|
723
803
|
{
|
724
|
-
|
725
|
-
if (
|
726
|
-
|
804
|
+
int h = vfp_type_p (cif->arg_types[i]);
|
805
|
+
if (h && place_vfp_arg (cif, h) == 1)
|
806
|
+
break;
|
727
807
|
}
|
728
808
|
}
|