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.

Files changed (159) hide show
  1. data/Rakefile +1 -1
  2. data/ext/ffi_c/AbstractMemory.c +9 -0
  3. data/ext/ffi_c/AbstractMemory.h +4 -0
  4. data/ext/ffi_c/Buffer.c +8 -0
  5. data/ext/ffi_c/Call.c +8 -0
  6. data/ext/ffi_c/ClosurePool.c +12 -0
  7. data/ext/ffi_c/DynamicLibrary.c +7 -1
  8. data/ext/ffi_c/Function.c +11 -1
  9. data/ext/ffi_c/Function.h +6 -0
  10. data/ext/ffi_c/FunctionInfo.c +8 -0
  11. data/ext/ffi_c/LastError.c +8 -0
  12. data/ext/ffi_c/MemoryPointer.c +8 -0
  13. data/ext/ffi_c/MemoryPointer.h +6 -0
  14. data/ext/ffi_c/MethodHandle.c +8 -0
  15. data/ext/ffi_c/Platform.c +8 -0
  16. data/ext/ffi_c/Pointer.c +8 -0
  17. data/ext/ffi_c/Pointer.h +6 -0
  18. data/ext/ffi_c/Struct.c +6 -0
  19. data/ext/ffi_c/StructByReference.c +8 -0
  20. data/ext/ffi_c/StructByValue.c +8 -0
  21. data/ext/ffi_c/StructLayout.c +6 -0
  22. data/ext/ffi_c/Thread.c +7 -0
  23. data/ext/ffi_c/Thread.h +6 -0
  24. data/ext/ffi_c/Type.c +3 -0
  25. data/ext/ffi_c/Types.h +4 -0
  26. data/ext/ffi_c/Variadic.c +8 -0
  27. data/ext/ffi_c/endian.h +3 -0
  28. data/ext/ffi_c/extconf.rb +6 -1
  29. data/ext/ffi_c/libffi.vc.mk +26 -0
  30. data/ext/ffi_c/libffi.vc64.mk +26 -0
  31. data/ext/ffi_c/libffi/ChangeLog +541 -0
  32. data/ext/ffi_c/libffi/ChangeLog.libffi +13 -87
  33. data/ext/ffi_c/libffi/LICENSE +3 -3
  34. data/ext/ffi_c/libffi/Makefile.am +41 -32
  35. data/ext/ffi_c/libffi/Makefile.in +95 -66
  36. data/ext/ffi_c/libffi/Makefile.vc +141 -0
  37. data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
  38. data/ext/ffi_c/libffi/README +40 -4
  39. data/ext/ffi_c/libffi/aclocal.m4 +729 -7854
  40. data/ext/ffi_c/libffi/build-ios.sh +67 -0
  41. data/ext/ffi_c/libffi/compile +11 -10
  42. data/ext/ffi_c/libffi/config.guess +4 -1
  43. data/ext/ffi_c/libffi/config.sub +6 -3
  44. data/ext/ffi_c/libffi/configure +6264 -6354
  45. data/ext/ffi_c/libffi/configure.ac +155 -63
  46. data/ext/ffi_c/libffi/depcomp +81 -35
  47. data/ext/ffi_c/libffi/doc/libffi.info +78 -18
  48. data/ext/ffi_c/libffi/doc/libffi.texi +64 -5
  49. data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
  50. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  51. data/ext/ffi_c/libffi/fficonfig.h.in +18 -0
  52. data/ext/ffi_c/libffi/fficonfig.hw +57 -0
  53. data/ext/ffi_c/libffi/include/Makefile.in +21 -3
  54. data/ext/ffi_c/libffi/include/ffi.h.in +42 -14
  55. data/ext/ffi_c/libffi/include/ffi.h.vc +427 -0
  56. data/ext/ffi_c/libffi/include/ffi.h.vc64 +427 -0
  57. data/ext/ffi_c/libffi/include/ffi_common.h +9 -5
  58. data/ext/ffi_c/libffi/install-sh +364 -167
  59. data/ext/ffi_c/libffi/ltmain.sh +2599 -1369
  60. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +176 -0
  61. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +195 -0
  62. data/ext/ffi_c/libffi/m4/ax_check_compiler_flags.m4 +76 -0
  63. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +63 -0
  64. data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
  65. data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +300 -0
  66. data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +215 -0
  67. data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +79 -0
  68. data/ext/ffi_c/libffi/m4/libtool.m4 +1239 -768
  69. data/ext/ffi_c/libffi/m4/ltoptions.m4 +7 -6
  70. data/ext/ffi_c/libffi/m4/ltversion.m4 +6 -6
  71. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +9 -3
  72. data/ext/ffi_c/libffi/man/Makefile.in +21 -3
  73. data/ext/ffi_c/libffi/mdate-sh +0 -0
  74. data/ext/ffi_c/libffi/missing +60 -44
  75. data/ext/ffi_c/libffi/msvcc.sh +197 -0
  76. data/ext/ffi_c/libffi/src/alpha/osf.S +39 -18
  77. data/ext/ffi_c/libffi/src/arm/ffi.c +443 -24
  78. data/ext/ffi_c/libffi/src/arm/ffitarget.h +17 -1
  79. data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
  80. data/ext/ffi_c/libffi/src/arm/sysv.S +206 -15
  81. data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
  82. data/ext/ffi_c/libffi/src/avr32/ffi.c +4 -2
  83. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +2 -2
  84. data/ext/ffi_c/libffi/src/closures.c +17 -35
  85. data/ext/ffi_c/libffi/src/cris/ffi.c +1 -1
  86. data/ext/ffi_c/libffi/src/cris/ffitarget.h +2 -2
  87. data/ext/ffi_c/libffi/src/dlmalloc.c +66 -4
  88. data/ext/ffi_c/libffi/src/frv/ffitarget.h +2 -6
  89. data/ext/ffi_c/libffi/src/ia64/ffi.c +7 -5
  90. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +2 -2
  91. data/ext/ffi_c/libffi/src/java_raw_api.c +1 -1
  92. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +2 -2
  93. data/ext/ffi_c/libffi/src/m68k/ffi.c +10 -0
  94. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +2 -2
  95. data/ext/ffi_c/libffi/src/m68k/sysv.S +36 -0
  96. data/ext/ffi_c/libffi/src/mips/ffi.c +12 -5
  97. data/ext/ffi_c/libffi/src/mips/ffitarget.h +18 -11
  98. data/ext/ffi_c/libffi/src/mips/n32.S +4 -4
  99. data/ext/ffi_c/libffi/src/moxie/eabi.S +128 -0
  100. data/ext/ffi_c/libffi/src/moxie/ffi.c +276 -0
  101. data/ext/ffi_c/libffi/src/pa/ffi.c +7 -4
  102. data/ext/ffi_c/libffi/src/pa/ffitarget.h +6 -5
  103. data/ext/ffi_c/libffi/src/powerpc/aix.S +5 -1
  104. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +2 -0
  105. data/ext/ffi_c/libffi/src/powerpc/asm.h +1 -1
  106. data/ext/ffi_c/libffi/src/powerpc/darwin.S +215 -77
  107. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +358 -100
  108. data/ext/ffi_c/libffi/src/powerpc/ffi.c +11 -5
  109. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +603 -172
  110. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +17 -4
  111. data/ext/ffi_c/libffi/src/prep_cif.c +16 -13
  112. data/ext/ffi_c/libffi/src/s390/ffitarget.h +4 -2
  113. data/ext/ffi_c/libffi/src/sh/ffitarget.h +2 -2
  114. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +2 -2
  115. data/ext/ffi_c/libffi/src/sparc/ffi.c +55 -11
  116. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +5 -3
  117. data/ext/ffi_c/libffi/src/x86/ffi.c +54 -92
  118. data/ext/ffi_c/libffi/src/x86/ffi64.c +17 -8
  119. data/ext/ffi_c/libffi/src/x86/ffitarget.h +15 -14
  120. data/ext/ffi_c/libffi/src/x86/sysv.S +40 -26
  121. data/ext/ffi_c/libffi/src/x86/unix64.S +4 -0
  122. data/ext/ffi_c/libffi/src/x86/win32.S +379 -191
  123. data/ext/ffi_c/libffi/src/x86/win64.S +15 -7
  124. data/ext/ffi_c/libffi/testsuite/Makefile.am +1 -1
  125. data/ext/ffi_c/libffi/testsuite/Makefile.in +22 -4
  126. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -0
  127. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +1 -5
  128. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +1 -1
  129. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +1 -1
  130. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +1 -0
  131. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +1 -0
  132. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +3 -0
  133. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +2 -2
  134. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +3 -0
  135. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +1 -1
  136. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +1 -1
  137. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +1 -0
  138. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +2 -3
  139. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -1
  140. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +36 -0
  141. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +17 -17
  142. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -0
  143. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +1 -0
  144. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +1 -1
  145. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +1 -3
  146. data/ext/ffi_c/win32/stdint.h +199 -0
  147. data/gen/Rakefile +18 -2
  148. data/lib/ffi/platform/arm-linux/types.conf +102 -0
  149. data/lib/ffi/platform/i486-gnu/types.conf +107 -0
  150. data/lib/ffi/platform/ia64-linux/types.conf +102 -0
  151. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  152. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  153. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  154. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  155. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  156. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  157. data/lib/ffi/tools/types_generator.rb +8 -1
  158. data/lib/ffi_c.bundle +0 -0
  159. 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
- .4byte $LECIE1-$LSCIE1 # Length of Common Information Entry
322
+ UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry
305
323
  $LSCIE1:
306
- .4byte 0x0 # CIE Identifier Tag
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 0x1b # FDE Encoding (pcrel sdata4)
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
- .4byte $LEFDE1-$LASFDE1 # FDE Length
338
+ UA_SI $LEFDE1-$LASFDE1 # FDE Length
321
339
  $LASFDE1:
322
- .4byte $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
323
- .4byte $LFB1-. # FDE initial location
324
- .4byte $LFE1-$LFB1 # FDE address range
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
- .4byte $LCFI1-$LFB1
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
- .4byte $LCFI2-$LCFI1
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
- .4byte $LEFDE3-$LASFDE3 # FDE Length
362
+ UA_SI $LEFDE3-$LASFDE3 # FDE Length
345
363
  $LASFDE3:
346
- .4byte $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
347
- .4byte $LFB2-. # FDE initial location
348
- .4byte $LFE2-$LFB2 # FDE address range
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
- .4byte $LCFI5-$LFB2
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
- .4byte $LCFI6-$LCFI5
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
- #ifdef __linux__
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) 1998, 2008 Red Hat, Inc.
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
- /* ffi_prep_args is called by the assembly routine once stack space
33
- has been allocated for the function's arguments */
35
+ /* Forward declares. */
36
+ static int vfp_type_p (ffi_type *);
37
+ static void layout_vfp_args (ffi_cif *);
34
38
 
35
- void ffi_prep_args(char *stack, extended_cif *ecif)
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
- return;
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->rtype->size <= 4)
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
- extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
152
- unsigned, unsigned, unsigned *, void (*fn)(void));
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(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
183
- fn);
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
- size_t alignment = (*p_arg)->alignment;
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
- FFI_ASSERT (cif->abi == FFI_SYSV);
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
- &ffi_closure_SYSV, \
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
+ }