ffi 1.0.11 → 1.0.12.pre
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.
- data/Rakefile +1 -1
- data/ext/ffi_c/AbstractMemory.c +9 -0
- data/ext/ffi_c/AbstractMemory.h +4 -0
- data/ext/ffi_c/Buffer.c +8 -0
- data/ext/ffi_c/Call.c +8 -0
- data/ext/ffi_c/ClosurePool.c +12 -0
- data/ext/ffi_c/DynamicLibrary.c +7 -1
- data/ext/ffi_c/Function.c +11 -1
- data/ext/ffi_c/Function.h +6 -0
- data/ext/ffi_c/FunctionInfo.c +8 -0
- data/ext/ffi_c/LastError.c +8 -0
- data/ext/ffi_c/MemoryPointer.c +8 -0
- data/ext/ffi_c/MemoryPointer.h +6 -0
- data/ext/ffi_c/MethodHandle.c +8 -0
- data/ext/ffi_c/Platform.c +8 -0
- data/ext/ffi_c/Pointer.c +8 -0
- data/ext/ffi_c/Pointer.h +6 -0
- data/ext/ffi_c/Struct.c +6 -0
- data/ext/ffi_c/StructByReference.c +8 -0
- data/ext/ffi_c/StructByValue.c +8 -0
- data/ext/ffi_c/StructLayout.c +6 -0
- data/ext/ffi_c/Thread.c +7 -0
- data/ext/ffi_c/Thread.h +6 -0
- data/ext/ffi_c/Type.c +3 -0
- data/ext/ffi_c/Types.h +4 -0
- data/ext/ffi_c/Variadic.c +8 -0
- data/ext/ffi_c/endian.h +3 -0
- data/ext/ffi_c/extconf.rb +6 -1
- data/ext/ffi_c/libffi.vc.mk +26 -0
- data/ext/ffi_c/libffi.vc64.mk +26 -0
- data/ext/ffi_c/libffi/ChangeLog +541 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +13 -87
- data/ext/ffi_c/libffi/LICENSE +3 -3
- data/ext/ffi_c/libffi/Makefile.am +41 -32
- data/ext/ffi_c/libffi/Makefile.in +95 -66
- data/ext/ffi_c/libffi/Makefile.vc +141 -0
- data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
- data/ext/ffi_c/libffi/README +40 -4
- data/ext/ffi_c/libffi/aclocal.m4 +729 -7854
- data/ext/ffi_c/libffi/build-ios.sh +67 -0
- data/ext/ffi_c/libffi/compile +11 -10
- data/ext/ffi_c/libffi/config.guess +4 -1
- data/ext/ffi_c/libffi/config.sub +6 -3
- data/ext/ffi_c/libffi/configure +6264 -6354
- data/ext/ffi_c/libffi/configure.ac +155 -63
- data/ext/ffi_c/libffi/depcomp +81 -35
- data/ext/ffi_c/libffi/doc/libffi.info +78 -18
- data/ext/ffi_c/libffi/doc/libffi.texi +64 -5
- data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
- data/ext/ffi_c/libffi/doc/version.texi +4 -4
- data/ext/ffi_c/libffi/fficonfig.h.in +18 -0
- data/ext/ffi_c/libffi/fficonfig.hw +57 -0
- data/ext/ffi_c/libffi/include/Makefile.in +21 -3
- data/ext/ffi_c/libffi/include/ffi.h.in +42 -14
- data/ext/ffi_c/libffi/include/ffi.h.vc +427 -0
- data/ext/ffi_c/libffi/include/ffi.h.vc64 +427 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +9 -5
- data/ext/ffi_c/libffi/install-sh +364 -167
- data/ext/ffi_c/libffi/ltmain.sh +2599 -1369
- data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +176 -0
- data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +195 -0
- data/ext/ffi_c/libffi/m4/ax_check_compiler_flags.m4 +76 -0
- data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +63 -0
- data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
- data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +300 -0
- data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +215 -0
- data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +79 -0
- data/ext/ffi_c/libffi/m4/libtool.m4 +1239 -768
- data/ext/ffi_c/libffi/m4/ltoptions.m4 +7 -6
- data/ext/ffi_c/libffi/m4/ltversion.m4 +6 -6
- data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +9 -3
- data/ext/ffi_c/libffi/man/Makefile.in +21 -3
- data/ext/ffi_c/libffi/mdate-sh +0 -0
- data/ext/ffi_c/libffi/missing +60 -44
- data/ext/ffi_c/libffi/msvcc.sh +197 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +39 -18
- data/ext/ffi_c/libffi/src/arm/ffi.c +443 -24
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +17 -1
- data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +206 -15
- data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
- data/ext/ffi_c/libffi/src/avr32/ffi.c +4 -2
- data/ext/ffi_c/libffi/src/avr32/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/closures.c +17 -35
- data/ext/ffi_c/libffi/src/cris/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/dlmalloc.c +66 -4
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +2 -6
- data/ext/ffi_c/libffi/src/ia64/ffi.c +7 -5
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/java_raw_api.c +1 -1
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/m68k/ffi.c +10 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/m68k/sysv.S +36 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +12 -5
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +18 -11
- data/ext/ffi_c/libffi/src/mips/n32.S +4 -4
- data/ext/ffi_c/libffi/src/moxie/eabi.S +128 -0
- data/ext/ffi_c/libffi/src/moxie/ffi.c +276 -0
- data/ext/ffi_c/libffi/src/pa/ffi.c +7 -4
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +6 -5
- data/ext/ffi_c/libffi/src/powerpc/aix.S +5 -1
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +2 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +1 -1
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +215 -77
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +358 -100
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +11 -5
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +603 -172
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +17 -4
- data/ext/ffi_c/libffi/src/prep_cif.c +16 -13
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +4 -2
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/sparc/ffi.c +55 -11
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +5 -3
- data/ext/ffi_c/libffi/src/x86/ffi.c +54 -92
- data/ext/ffi_c/libffi/src/x86/ffi64.c +17 -8
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +15 -14
- data/ext/ffi_c/libffi/src/x86/sysv.S +40 -26
- data/ext/ffi_c/libffi/src/x86/unix64.S +4 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +379 -191
- data/ext/ffi_c/libffi/src/x86/win64.S +15 -7
- data/ext/ffi_c/libffi/testsuite/Makefile.am +1 -1
- data/ext/ffi_c/libffi/testsuite/Makefile.in +22 -4
- data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +1 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +3 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +3 -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 +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +2 -3
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +17 -17
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +1 -3
- data/ext/ffi_c/win32/stdint.h +199 -0
- data/gen/Rakefile +18 -2
- data/lib/ffi/platform/arm-linux/types.conf +102 -0
- data/lib/ffi/platform/i486-gnu/types.conf +107 -0
- data/lib/ffi/platform/ia64-linux/types.conf +102 -0
- data/lib/ffi/platform/mips-linux/types.conf +102 -0
- data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
- data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
- data/lib/ffi/platform/s390-linux/types.conf +102 -0
- data/lib/ffi/platform/s390x-linux/types.conf +102 -0
- data/lib/ffi/platform/sparc-linux/types.conf +102 -0
- data/lib/ffi/tools/types_generator.rb +8 -1
- data/lib/ffi_c.bundle +0 -0
- metadata +72 -42
@@ -0,0 +1,197 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# ***** BEGIN LICENSE BLOCK *****
|
4
|
+
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with
|
8
|
+
# the License. You may obtain a copy of the License at
|
9
|
+
# http://www.mozilla.org/MPL/
|
10
|
+
#
|
11
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
12
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
13
|
+
# for the specific language governing rights and limitations under the
|
14
|
+
# License.
|
15
|
+
#
|
16
|
+
# The Original Code is the MSVC wrappificator.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is
|
19
|
+
# Timothy Wall <twalljava@dev.java.net>.
|
20
|
+
# Portions created by the Initial Developer are Copyright (C) 2009
|
21
|
+
# the Initial Developer. All Rights Reserved.
|
22
|
+
#
|
23
|
+
# Contributor(s):
|
24
|
+
# Daniel Witte <dwitte@mozilla.com>
|
25
|
+
#
|
26
|
+
# Alternatively, the contents of this file may be used under the terms of
|
27
|
+
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
28
|
+
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
29
|
+
# in which case the provisions of the GPL or the LGPL are applicable instead
|
30
|
+
# of those above. If you wish to allow use of your version of this file only
|
31
|
+
# under the terms of either the GPL or the LGPL, and not to allow others to
|
32
|
+
# use your version of this file under the terms of the MPL, indicate your
|
33
|
+
# decision by deleting the provisions above and replace them with the notice
|
34
|
+
# and other provisions required by the GPL or the LGPL. If you do not delete
|
35
|
+
# the provisions above, a recipient may use your version of this file under
|
36
|
+
# the terms of any one of the MPL, the GPL or the LGPL.
|
37
|
+
#
|
38
|
+
# ***** END LICENSE BLOCK *****
|
39
|
+
|
40
|
+
#
|
41
|
+
# GCC-compatible wrapper for cl.exe and ml.exe. Arguments are given in GCC
|
42
|
+
# format and translated into something sensible for cl or ml.
|
43
|
+
#
|
44
|
+
|
45
|
+
args="-nologo -W3"
|
46
|
+
md=-MD
|
47
|
+
cl="cl"
|
48
|
+
ml="ml"
|
49
|
+
safeseh="-safeseh"
|
50
|
+
output=
|
51
|
+
|
52
|
+
while [ $# -gt 0 ]
|
53
|
+
do
|
54
|
+
case $1
|
55
|
+
in
|
56
|
+
-fexceptions)
|
57
|
+
# Don't enable exceptions for now.
|
58
|
+
#args="$args -EHac"
|
59
|
+
shift 1
|
60
|
+
;;
|
61
|
+
-m32)
|
62
|
+
shift 1
|
63
|
+
;;
|
64
|
+
-m64)
|
65
|
+
cl="cl" # "$MSVC/x86_amd64/cl"
|
66
|
+
ml="ml64" # "$MSVC/x86_amd64/ml64"
|
67
|
+
safeseh=
|
68
|
+
shift 1
|
69
|
+
;;
|
70
|
+
-O0)
|
71
|
+
args="$args -Od"
|
72
|
+
shift 1
|
73
|
+
;;
|
74
|
+
-O*)
|
75
|
+
# If we're optimizing, make sure we explicitly turn on some optimizations
|
76
|
+
# that are implicitly disabled by debug symbols (-Zi).
|
77
|
+
args="$args $1 -OPT:REF -OPT:ICF -INCREMENTAL:NO"
|
78
|
+
shift 1
|
79
|
+
;;
|
80
|
+
-g)
|
81
|
+
# Enable debug symbol generation.
|
82
|
+
args="$args -Zi -DEBUG"
|
83
|
+
shift 1
|
84
|
+
;;
|
85
|
+
-DFFI_DEBUG)
|
86
|
+
# Link against debug CRT and enable runtime error checks.
|
87
|
+
args="$args -RTC1"
|
88
|
+
defines="$defines $1"
|
89
|
+
md=-MDd
|
90
|
+
shift 1
|
91
|
+
;;
|
92
|
+
-c)
|
93
|
+
args="$args -c"
|
94
|
+
args="$(echo $args | sed 's%/Fe%/Fo%g')"
|
95
|
+
single="-c"
|
96
|
+
shift 1
|
97
|
+
;;
|
98
|
+
-D*=*)
|
99
|
+
name="$(echo $1|sed 's/-D\([^=][^=]*\)=.*/\1/g')"
|
100
|
+
value="$(echo $1|sed 's/-D[^=][^=]*=//g')"
|
101
|
+
args="$args -D${name}='$value'"
|
102
|
+
defines="$defines -D${name}='$value'"
|
103
|
+
shift 1
|
104
|
+
;;
|
105
|
+
-D*)
|
106
|
+
args="$args $1"
|
107
|
+
defines="$defines $1"
|
108
|
+
shift 1
|
109
|
+
;;
|
110
|
+
-I)
|
111
|
+
args="$args -I$2"
|
112
|
+
includes="$includes -I$2"
|
113
|
+
shift 2
|
114
|
+
;;
|
115
|
+
-I*)
|
116
|
+
args="$args $1"
|
117
|
+
includes="$includes $1"
|
118
|
+
shift 1
|
119
|
+
;;
|
120
|
+
-W|-Wextra)
|
121
|
+
# TODO map extra warnings
|
122
|
+
shift 1
|
123
|
+
;;
|
124
|
+
-Wall)
|
125
|
+
# -Wall on MSVC is overzealous, and we already build with -W3. Nothing
|
126
|
+
# to do here.
|
127
|
+
shift 1
|
128
|
+
;;
|
129
|
+
-Werror)
|
130
|
+
args="$args -WX"
|
131
|
+
shift 1
|
132
|
+
;;
|
133
|
+
-W*)
|
134
|
+
# TODO map specific warnings
|
135
|
+
shift 1
|
136
|
+
;;
|
137
|
+
-S)
|
138
|
+
args="$args -FAs"
|
139
|
+
shift 1
|
140
|
+
;;
|
141
|
+
-o)
|
142
|
+
outdir="$(dirname $2)"
|
143
|
+
base="$(basename $2|sed 's/\.[^.]*//g')"
|
144
|
+
if [ -n "$single" ]; then
|
145
|
+
output="-Fo$2"
|
146
|
+
else
|
147
|
+
output="-Fe$2"
|
148
|
+
fi
|
149
|
+
if [ -n "$assembly" ]; then
|
150
|
+
args="$args $output"
|
151
|
+
else
|
152
|
+
args="$args $output -Fd$outdir/$base -Fp$outdir/$base -Fa$outdir/$base"
|
153
|
+
fi
|
154
|
+
shift 2
|
155
|
+
;;
|
156
|
+
*.S)
|
157
|
+
src=$1
|
158
|
+
assembly="true"
|
159
|
+
shift 1
|
160
|
+
;;
|
161
|
+
*.c)
|
162
|
+
args="$args $1"
|
163
|
+
shift 1
|
164
|
+
;;
|
165
|
+
*)
|
166
|
+
# Assume it's an MSVC argument, and pass it through.
|
167
|
+
args="$args $1"
|
168
|
+
shift 1
|
169
|
+
;;
|
170
|
+
esac
|
171
|
+
done
|
172
|
+
|
173
|
+
if [ -n "$assembly" ]; then
|
174
|
+
if [ -z "$outdir" ]; then
|
175
|
+
outdir="."
|
176
|
+
fi
|
177
|
+
ppsrc="$outdir/$(basename $src|sed 's/.S$/.asm/g')"
|
178
|
+
echo "$cl -nologo -EP $includes $defines $src > $ppsrc"
|
179
|
+
"$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $?
|
180
|
+
output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')"
|
181
|
+
args="-nologo $safeseh $single $output $ppsrc"
|
182
|
+
|
183
|
+
echo "$ml $args"
|
184
|
+
eval "\"$ml\" $args"
|
185
|
+
result=$?
|
186
|
+
|
187
|
+
# required to fix ml64 broken output?
|
188
|
+
#mv *.obj $outdir
|
189
|
+
else
|
190
|
+
args="$md $args"
|
191
|
+
echo "$cl $args"
|
192
|
+
eval "\"$cl\" $args"
|
193
|
+
result=$?
|
194
|
+
fi
|
195
|
+
|
196
|
+
exit $result
|
197
|
+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/* -----------------------------------------------------------------------
|
2
|
-
osf.S - Copyright (c) 1998, 2001, 2007, 2008 Red Hat
|
2
|
+
osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
|
3
3
|
|
4
4
|
Alpha/OSF Foreign Function Interface
|
5
5
|
|
@@ -298,34 +298,52 @@ $load_table:
|
|
298
298
|
#error "osf.S out of sync with ffi.h"
|
299
299
|
#endif
|
300
300
|
|
301
|
+
#ifdef __ELF__
|
302
|
+
# define UA_SI .4byte
|
303
|
+
# define FDE_ENCODING 0x1b /* pcrel sdata4 */
|
304
|
+
# define FDE_ENCODE(X) .4byte X-.
|
305
|
+
# define FDE_ARANGE(X) .4byte X
|
306
|
+
#elif defined __osf__
|
307
|
+
# define UA_SI .align 0; .long
|
308
|
+
# define FDE_ENCODING 0x50 /* aligned absolute */
|
309
|
+
# define FDE_ENCODE(X) .align 3; .quad X
|
310
|
+
# define FDE_ARANGE(X) .align 0; .quad X
|
311
|
+
#endif
|
312
|
+
|
301
313
|
#ifdef __ELF__
|
302
314
|
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
315
|
+
#elif defined __osf__
|
316
|
+
.data
|
317
|
+
.align 3
|
318
|
+
.globl _GLOBAL__F_ffi_call_osf
|
319
|
+
_GLOBAL__F_ffi_call_osf:
|
320
|
+
#endif
|
303
321
|
__FRAME_BEGIN__:
|
304
|
-
|
322
|
+
UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry
|
305
323
|
$LSCIE1:
|
306
|
-
|
324
|
+
UA_SI 0x0 # CIE Identifier Tag
|
307
325
|
.byte 0x1 # CIE Version
|
308
326
|
.ascii "zR\0" # CIE Augmentation
|
309
327
|
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
310
328
|
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
311
329
|
.byte 26 # CIE RA Column
|
312
330
|
.byte 0x1 # uleb128 0x1; Augmentation size
|
313
|
-
.byte
|
331
|
+
.byte FDE_ENCODING # FDE Encoding
|
314
332
|
.byte 0xc # DW_CFA_def_cfa
|
315
333
|
.byte 30 # uleb128 column 30
|
316
334
|
.byte 0 # uleb128 offset 0
|
317
335
|
.align 3
|
318
336
|
$LECIE1:
|
319
337
|
$LSFDE1:
|
320
|
-
|
338
|
+
UA_SI $LEFDE1-$LASFDE1 # FDE Length
|
321
339
|
$LASFDE1:
|
322
|
-
|
323
|
-
|
324
|
-
|
340
|
+
UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
|
341
|
+
FDE_ENCODE($LFB1) # FDE initial location
|
342
|
+
FDE_ARANGE($LFE1-$LFB1) # FDE address range
|
325
343
|
.byte 0x0 # uleb128 0x0; Augmentation size
|
326
344
|
|
327
345
|
.byte 0x4 # DW_CFA_advance_loc4
|
328
|
-
|
346
|
+
UA_SI $LCFI1-$LFB1
|
329
347
|
.byte 0x9a # DW_CFA_offset, column 26
|
330
348
|
.byte 4 # uleb128 4*-8
|
331
349
|
.byte 0x8f # DW_CFA_offset, column 15
|
@@ -335,32 +353,35 @@ $LASFDE1:
|
|
335
353
|
.byte 32 # uleb128 offset 32
|
336
354
|
|
337
355
|
.byte 0x4 # DW_CFA_advance_loc4
|
338
|
-
|
356
|
+
UA_SI $LCFI2-$LCFI1
|
339
357
|
.byte 0xda # DW_CFA_restore, column 26
|
340
358
|
.align 3
|
341
359
|
$LEFDE1:
|
342
360
|
|
343
361
|
$LSFDE3:
|
344
|
-
|
362
|
+
UA_SI $LEFDE3-$LASFDE3 # FDE Length
|
345
363
|
$LASFDE3:
|
346
|
-
|
347
|
-
|
348
|
-
|
364
|
+
UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
|
365
|
+
FDE_ENCODE($LFB2) # FDE initial location
|
366
|
+
FDE_ARANGE($LFE2-$LFB2) # FDE address range
|
349
367
|
.byte 0x0 # uleb128 0x0; Augmentation size
|
350
368
|
|
351
369
|
.byte 0x4 # DW_CFA_advance_loc4
|
352
|
-
|
370
|
+
UA_SI $LCFI5-$LFB2
|
353
371
|
.byte 0xe # DW_CFA_def_cfa_offset
|
354
372
|
.byte 0x80,0x1 # uleb128 128
|
355
373
|
|
356
374
|
.byte 0x4 # DW_CFA_advance_loc4
|
357
|
-
|
375
|
+
UA_SI $LCFI6-$LCFI5
|
358
376
|
.byte 0x9a # DW_CFA_offset, column 26
|
359
377
|
.byte 16 # uleb128 offset 16*-8
|
360
378
|
.align 3
|
361
379
|
$LEFDE3:
|
380
|
+
#if defined __osf__
|
381
|
+
.align 0
|
382
|
+
.long 0 # End of Table
|
383
|
+
#endif
|
362
384
|
|
363
|
-
#
|
385
|
+
#if defined __ELF__ && defined __linux__
|
364
386
|
.section .note.GNU-stack,"",@progbits
|
365
387
|
#endif
|
366
|
-
#endif
|
@@ -1,6 +1,9 @@
|
|
1
1
|
/* -----------------------------------------------------------------------
|
2
|
-
ffi.c - Copyright (c)
|
3
|
-
|
2
|
+
ffi.c - Copyright (c) 2011 Plausible Labs Cooperative, Inc.
|
3
|
+
Copyright (c) 2011 Anthony Green
|
4
|
+
Copyright (c) 2011 Free Software Foundation
|
5
|
+
Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
|
6
|
+
|
4
7
|
ARM Foreign Function Interface
|
5
8
|
|
6
9
|
Permission is hereby granted, free of charge, to any person obtaining
|
@@ -29,12 +32,20 @@
|
|
29
32
|
|
30
33
|
#include <stdlib.h>
|
31
34
|
|
32
|
-
/*
|
33
|
-
|
35
|
+
/* Forward declares. */
|
36
|
+
static int vfp_type_p (ffi_type *);
|
37
|
+
static void layout_vfp_args (ffi_cif *);
|
34
38
|
|
35
|
-
|
39
|
+
/* ffi_prep_args is called by the assembly routine once stack space
|
40
|
+
has been allocated for the function's arguments
|
41
|
+
|
42
|
+
The vfp_space parameter is the load area for VFP regs, the return
|
43
|
+
value is cif->vfp_used (word bitset of VFP regs used for passing
|
44
|
+
arguments). These are only used for the VFP hard-float ABI.
|
45
|
+
*/
|
46
|
+
int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
|
36
47
|
{
|
37
|
-
register unsigned int i;
|
48
|
+
register unsigned int i, vi = 0;
|
38
49
|
register void **p_argv;
|
39
50
|
register char *argp;
|
40
51
|
register ffi_type **p_arg;
|
@@ -54,6 +65,21 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
|
54
65
|
{
|
55
66
|
size_t z;
|
56
67
|
|
68
|
+
/* Allocated in VFP registers. */
|
69
|
+
if (ecif->cif->abi == FFI_VFP
|
70
|
+
&& vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
|
71
|
+
{
|
72
|
+
float* vfp_slot = vfp_space + ecif->cif->vfp_args[vi++];
|
73
|
+
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
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++;
|
80
|
+
continue;
|
81
|
+
}
|
82
|
+
|
57
83
|
/* Align if necessary */
|
58
84
|
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
|
59
85
|
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
@@ -103,13 +129,15 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
|
103
129
|
p_argv++;
|
104
130
|
argp += z;
|
105
131
|
}
|
106
|
-
|
107
|
-
|
132
|
+
|
133
|
+
/* Indicate the VFP registers used. */
|
134
|
+
return ecif->cif->vfp_used;
|
108
135
|
}
|
109
136
|
|
110
137
|
/* Perform machine dependent cif processing */
|
111
138
|
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
112
139
|
{
|
140
|
+
int type_code;
|
113
141
|
/* Round the stack up to a multiple of 8 bytes. This isn't needed
|
114
142
|
everywhere, but it is on some platforms, and it doesn't harm anything
|
115
143
|
when it isn't needed. */
|
@@ -130,7 +158,14 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|
130
158
|
break;
|
131
159
|
|
132
160
|
case FFI_TYPE_STRUCT:
|
133
|
-
if (cif->
|
161
|
+
if (cif->abi == FFI_VFP
|
162
|
+
&& (type_code = vfp_type_p (cif->rtype)) != 0)
|
163
|
+
{
|
164
|
+
/* A Composite Type passed in VFP registers, either
|
165
|
+
FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
|
166
|
+
cif->flags = (unsigned) type_code;
|
167
|
+
}
|
168
|
+
else if (cif->rtype->size <= 4)
|
134
169
|
/* A Composite Type not larger than 4 bytes is returned in r0. */
|
135
170
|
cif->flags = (unsigned)FFI_TYPE_INT;
|
136
171
|
else
|
@@ -145,11 +180,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|
145
180
|
break;
|
146
181
|
}
|
147
182
|
|
183
|
+
/* Map out the register placements of VFP register args.
|
184
|
+
The VFP hard-float calling conventions are slightly more sophisticated than
|
185
|
+
the base calling conventions, so we do it here instead of in ffi_prep_args(). */
|
186
|
+
if (cif->abi == FFI_VFP)
|
187
|
+
layout_vfp_args (cif);
|
188
|
+
|
148
189
|
return FFI_OK;
|
149
190
|
}
|
150
191
|
|
151
|
-
|
152
|
-
|
192
|
+
/* Prototypes for assembly functions, in sysv.S */
|
193
|
+
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
|
194
|
+
extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
|
153
195
|
|
154
196
|
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
155
197
|
{
|
@@ -157,6 +199,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|
157
199
|
|
158
200
|
int small_struct = (cif->flags == FFI_TYPE_INT
|
159
201
|
&& cif->rtype->type == FFI_TYPE_STRUCT);
|
202
|
+
int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
|
203
|
+
|| cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
|
160
204
|
|
161
205
|
ecif.cif = cif;
|
162
206
|
ecif.avalue = avalue;
|
@@ -173,38 +217,51 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|
173
217
|
}
|
174
218
|
else if (small_struct)
|
175
219
|
ecif.rvalue = &temp;
|
220
|
+
else if (vfp_struct)
|
221
|
+
{
|
222
|
+
/* Largest case is double x 4. */
|
223
|
+
ecif.rvalue = alloca(32);
|
224
|
+
}
|
176
225
|
else
|
177
226
|
ecif.rvalue = rvalue;
|
178
227
|
|
179
228
|
switch (cif->abi)
|
180
229
|
{
|
181
230
|
case FFI_SYSV:
|
182
|
-
ffi_call_SYSV(
|
183
|
-
|
231
|
+
ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
|
232
|
+
break;
|
184
233
|
|
234
|
+
case FFI_VFP:
|
235
|
+
ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
|
185
236
|
break;
|
237
|
+
|
186
238
|
default:
|
187
239
|
FFI_ASSERT(0);
|
188
240
|
break;
|
189
241
|
}
|
190
242
|
if (small_struct)
|
191
243
|
memcpy (rvalue, &temp, cif->rtype->size);
|
244
|
+
else if (vfp_struct)
|
245
|
+
memcpy (rvalue, ecif.rvalue, cif->rtype->size);
|
192
246
|
}
|
193
247
|
|
194
248
|
/** private members **/
|
195
249
|
|
196
250
|
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
197
|
-
void** args, ffi_cif* cif);
|
251
|
+
void** args, ffi_cif* cif, float *vfp_stack);
|
198
252
|
|
199
253
|
void ffi_closure_SYSV (ffi_closure *);
|
200
254
|
|
255
|
+
void ffi_closure_VFP (ffi_closure *);
|
256
|
+
|
201
257
|
/* This function is jumped to by the trampoline */
|
202
258
|
|
203
259
|
unsigned int
|
204
|
-
ffi_closure_SYSV_inner (closure, respp, args)
|
260
|
+
ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
|
205
261
|
ffi_closure *closure;
|
206
262
|
void **respp;
|
207
263
|
void *args;
|
264
|
+
void *vfp_args;
|
208
265
|
{
|
209
266
|
// our various things...
|
210
267
|
ffi_cif *cif;
|
@@ -219,7 +276,7 @@ ffi_closure_SYSV_inner (closure, respp, args)
|
|
219
276
|
* a structure, it will re-set RESP to point to the
|
220
277
|
* structure return address. */
|
221
278
|
|
222
|
-
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
279
|
+
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
|
223
280
|
|
224
281
|
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
225
282
|
|
@@ -229,10 +286,12 @@ ffi_closure_SYSV_inner (closure, respp, args)
|
|
229
286
|
/*@-exportheader@*/
|
230
287
|
static void
|
231
288
|
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
232
|
-
void **avalue, ffi_cif *cif
|
289
|
+
void **avalue, ffi_cif *cif,
|
290
|
+
/* Used only under VFP hard-float ABI. */
|
291
|
+
float *vfp_stack)
|
233
292
|
/*@=exportheader@*/
|
234
293
|
{
|
235
|
-
register unsigned int i;
|
294
|
+
register unsigned int i, vi = 0;
|
236
295
|
register void **p_argv;
|
237
296
|
register char *argp;
|
238
297
|
register ffi_type **p_arg;
|
@@ -249,8 +308,16 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
|
249
308
|
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
250
309
|
{
|
251
310
|
size_t z;
|
252
|
-
|
253
|
-
|
311
|
+
size_t alignment;
|
312
|
+
|
313
|
+
if (cif->abi == FFI_VFP
|
314
|
+
&& vi < cif->vfp_nargs && vfp_type_p (*p_arg))
|
315
|
+
{
|
316
|
+
*p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
|
317
|
+
continue;
|
318
|
+
}
|
319
|
+
|
320
|
+
alignment = (*p_arg)->alignment;
|
254
321
|
if (alignment < 4)
|
255
322
|
alignment = 4;
|
256
323
|
/* Align if necessary */
|
@@ -273,18 +340,237 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
|
273
340
|
|
274
341
|
/* How to make a trampoline. */
|
275
342
|
|
343
|
+
#if FFI_EXEC_TRAMPOLINE_TABLE
|
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
|
+
};
|
368
|
+
|
369
|
+
struct ffi_trampoline_table_entry {
|
370
|
+
void *(*trampoline)();
|
371
|
+
ffi_trampoline_table_entry *next;
|
372
|
+
};
|
373
|
+
|
374
|
+
/* Override the standard architecture trampoline size */
|
375
|
+
// XXX TODO - Fix
|
376
|
+
#undef FFI_TRAMPOLINE_SIZE
|
377
|
+
#define FFI_TRAMPOLINE_SIZE 12
|
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 ()
|
393
|
+
{
|
394
|
+
ffi_trampoline_table *table = NULL;
|
395
|
+
|
396
|
+
/* Loop until we can allocate two contigious pages */
|
397
|
+
while (table == NULL) {
|
398
|
+
vm_address_t config_page = 0x0;
|
399
|
+
kern_return_t kt;
|
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
|
+
}
|
407
|
+
|
408
|
+
/* Now drop the second half of the allocation to make room for the trampoline table */
|
409
|
+
vm_address_t trampoline_page = config_page+PAGE_SIZE;
|
410
|
+
kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
|
411
|
+
if (kt != KERN_SUCCESS) {
|
412
|
+
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
|
413
|
+
break;
|
414
|
+
}
|
415
|
+
|
416
|
+
/* Remap the trampoline table to directly follow the config page */
|
417
|
+
vm_prot_t cur_prot;
|
418
|
+
vm_prot_t max_prot;
|
419
|
+
|
420
|
+
kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
|
421
|
+
|
422
|
+
/* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
|
423
|
+
if (kt != KERN_SUCCESS) {
|
424
|
+
/* Log unexpected failures */
|
425
|
+
if (kt != KERN_NO_SPACE) {
|
426
|
+
fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
|
427
|
+
}
|
428
|
+
|
429
|
+
vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
|
430
|
+
continue;
|
431
|
+
}
|
432
|
+
|
433
|
+
/* We have valid trampoline and config pages */
|
434
|
+
table = calloc (1, sizeof(ffi_trampoline_table));
|
435
|
+
table->free_count = FFI_TRAMPOLINE_COUNT;
|
436
|
+
table->config_page = config_page;
|
437
|
+
table->trampoline_page = trampoline_page;
|
438
|
+
|
439
|
+
/* Create and initialize the free list */
|
440
|
+
table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
|
441
|
+
|
442
|
+
uint16_t i;
|
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
|
+
}
|
450
|
+
|
451
|
+
table->free_list = table->free_list_pool;
|
452
|
+
}
|
453
|
+
|
454
|
+
return table;
|
455
|
+
}
|
456
|
+
|
457
|
+
void *
|
458
|
+
ffi_closure_alloc (size_t size, void **code)
|
459
|
+
{
|
460
|
+
/* Create the closure */
|
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
|
+
}
|
475
|
+
|
476
|
+
/* Insert the new table at the top of the list */
|
477
|
+
table->next = ffi_trampoline_tables;
|
478
|
+
if (table->next != NULL)
|
479
|
+
table->next->prev = table;
|
480
|
+
|
481
|
+
ffi_trampoline_tables = table;
|
482
|
+
}
|
483
|
+
|
484
|
+
/* Claim the free entry */
|
485
|
+
ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
|
486
|
+
ffi_trampoline_tables->free_list = entry->next;
|
487
|
+
ffi_trampoline_tables->free_count--;
|
488
|
+
entry->next = NULL;
|
489
|
+
|
490
|
+
pthread_mutex_unlock(&ffi_trampoline_lock);
|
491
|
+
|
492
|
+
/* Initialize the return values */
|
493
|
+
*code = entry->trampoline;
|
494
|
+
closure->trampoline_table = table;
|
495
|
+
closure->trampoline_table_entry = entry;
|
496
|
+
|
497
|
+
return closure;
|
498
|
+
}
|
499
|
+
|
500
|
+
void
|
501
|
+
ffi_closure_free (void *ptr)
|
502
|
+
{
|
503
|
+
ffi_closure *closure = ptr;
|
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
|
556
|
+
|
276
557
|
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
277
558
|
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
278
559
|
unsigned int __fun = (unsigned int)(FUN); \
|
279
560
|
unsigned int __ctx = (unsigned int)(CTX); \
|
561
|
+
unsigned char *insns = (unsigned char *)(CTX); \
|
280
562
|
*(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \
|
281
563
|
*(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
|
282
564
|
*(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
|
283
565
|
*(unsigned int*) &__tramp[12] = __ctx; \
|
284
566
|
*(unsigned int*) &__tramp[16] = __fun; \
|
285
|
-
__clear_cache((&__tramp[0]), (&__tramp[19]));
|
567
|
+
__clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \
|
568
|
+
__clear_cache(insns, insns + 3 * sizeof (unsigned int)); \
|
569
|
+
/* Clear instruction \
|
570
|
+
mapping. */ \
|
286
571
|
})
|
287
572
|
|
573
|
+
#endif
|
288
574
|
|
289
575
|
/* the cif must already be prep'ed */
|
290
576
|
|
@@ -295,15 +581,148 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|
295
581
|
void *user_data,
|
296
582
|
void *codeloc)
|
297
583
|
{
|
298
|
-
|
584
|
+
void (*closure_func)(ffi_closure*) = NULL;
|
299
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
|
300
598
|
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
301
|
-
|
599
|
+
closure_func, \
|
302
600
|
codeloc);
|
303
|
-
|
601
|
+
#endif
|
602
|
+
|
304
603
|
closure->cif = cif;
|
305
604
|
closure->user_data = user_data;
|
306
605
|
closure->fun = fun;
|
307
606
|
|
308
607
|
return FFI_OK;
|
309
608
|
}
|
609
|
+
|
610
|
+
/* Below are routines for VFP hard-float support. */
|
611
|
+
|
612
|
+
static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
|
613
|
+
{
|
614
|
+
switch (t->type)
|
615
|
+
{
|
616
|
+
case FFI_TYPE_FLOAT:
|
617
|
+
case FFI_TYPE_DOUBLE:
|
618
|
+
*elt = (int) t->type;
|
619
|
+
*elnum = 1;
|
620
|
+
return 1;
|
621
|
+
|
622
|
+
case FFI_TYPE_STRUCT_VFP_FLOAT:
|
623
|
+
*elt = FFI_TYPE_FLOAT;
|
624
|
+
*elnum = t->size / sizeof (float);
|
625
|
+
return 1;
|
626
|
+
|
627
|
+
case FFI_TYPE_STRUCT_VFP_DOUBLE:
|
628
|
+
*elt = FFI_TYPE_DOUBLE;
|
629
|
+
*elnum = t->size / sizeof (double);
|
630
|
+
return 1;
|
631
|
+
|
632
|
+
case FFI_TYPE_STRUCT:;
|
633
|
+
{
|
634
|
+
int base_elt = 0, total_elnum = 0;
|
635
|
+
ffi_type **el = t->elements;
|
636
|
+
while (*el)
|
637
|
+
{
|
638
|
+
int el_elt = 0, el_elnum = 0;
|
639
|
+
if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
|
640
|
+
|| (base_elt && base_elt != el_elt)
|
641
|
+
|| total_elnum + el_elnum > 4)
|
642
|
+
return 0;
|
643
|
+
base_elt = el_elt;
|
644
|
+
total_elnum += el_elnum;
|
645
|
+
el++;
|
646
|
+
}
|
647
|
+
*elnum = total_elnum;
|
648
|
+
*elt = base_elt;
|
649
|
+
return 1;
|
650
|
+
}
|
651
|
+
default: ;
|
652
|
+
}
|
653
|
+
return 0;
|
654
|
+
}
|
655
|
+
|
656
|
+
static int vfp_type_p (ffi_type *t)
|
657
|
+
{
|
658
|
+
int elt, elnum;
|
659
|
+
if (rec_vfp_type_p (t, &elt, &elnum))
|
660
|
+
{
|
661
|
+
if (t->type == FFI_TYPE_STRUCT)
|
662
|
+
{
|
663
|
+
if (elnum == 1)
|
664
|
+
t->type = elt;
|
665
|
+
else
|
666
|
+
t->type = (elt == FFI_TYPE_FLOAT
|
667
|
+
? FFI_TYPE_STRUCT_VFP_FLOAT
|
668
|
+
: FFI_TYPE_STRUCT_VFP_DOUBLE);
|
669
|
+
}
|
670
|
+
return (int) t->type;
|
671
|
+
}
|
672
|
+
return 0;
|
673
|
+
}
|
674
|
+
|
675
|
+
static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
|
676
|
+
{
|
677
|
+
int reg = cif->vfp_reg_free;
|
678
|
+
int nregs = t->size / sizeof (float);
|
679
|
+
int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
|
680
|
+
|| t->type == FFI_TYPE_FLOAT) ? 1 : 2);
|
681
|
+
/* Align register number. */
|
682
|
+
if ((reg & 1) && align == 2)
|
683
|
+
reg++;
|
684
|
+
while (reg + nregs <= 16)
|
685
|
+
{
|
686
|
+
int s, new_used = 0;
|
687
|
+
for (s = reg; s < reg + nregs; s++)
|
688
|
+
{
|
689
|
+
new_used |= (1 << s);
|
690
|
+
if (cif->vfp_used & (1 << s))
|
691
|
+
{
|
692
|
+
reg += align;
|
693
|
+
goto next_reg;
|
694
|
+
}
|
695
|
+
}
|
696
|
+
/* Found regs to allocate. */
|
697
|
+
cif->vfp_used |= new_used;
|
698
|
+
cif->vfp_args[cif->vfp_nargs++] = reg;
|
699
|
+
|
700
|
+
/* Update vfp_reg_free. */
|
701
|
+
if (cif->vfp_used & (1 << cif->vfp_reg_free))
|
702
|
+
{
|
703
|
+
reg += nregs;
|
704
|
+
while (cif->vfp_used & (1 << reg))
|
705
|
+
reg += 1;
|
706
|
+
cif->vfp_reg_free = reg;
|
707
|
+
}
|
708
|
+
return;
|
709
|
+
next_reg: ;
|
710
|
+
}
|
711
|
+
}
|
712
|
+
|
713
|
+
static void layout_vfp_args (ffi_cif *cif)
|
714
|
+
{
|
715
|
+
int i;
|
716
|
+
/* Init VFP fields */
|
717
|
+
cif->vfp_used = 0;
|
718
|
+
cif->vfp_nargs = 0;
|
719
|
+
cif->vfp_reg_free = 0;
|
720
|
+
memset (cif->vfp_args, -1, 16); /* Init to -1. */
|
721
|
+
|
722
|
+
for (i = 0; i < cif->nargs; i++)
|
723
|
+
{
|
724
|
+
ffi_type *t = cif->arg_types[i];
|
725
|
+
if (vfp_type_p (t))
|
726
|
+
place_vfp_arg (cif, t);
|
727
|
+
}
|
728
|
+
}
|