ffi 1.9.18 → 1.9.21

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 (366) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/Rakefile +14 -3
  4. data/ext/ffi_c/AbstractMemory.c +6 -1
  5. data/ext/ffi_c/Platform.c +10 -2
  6. data/ext/ffi_c/extconf.rb +7 -2
  7. data/ext/ffi_c/libffi.bsd.mk +9 -3
  8. data/ext/ffi_c/libffi.darwin.mk +14 -4
  9. data/ext/ffi_c/libffi.gnu.mk +2 -1
  10. data/ext/ffi_c/libffi.mk +9 -4
  11. data/ext/ffi_c/libffi/ChangeLog.libffi +2 -2
  12. data/ext/ffi_c/libffi/{ChangeLog → ChangeLog.libffi-3.1} +1402 -2
  13. data/ext/ffi_c/libffi/ChangeLog.v1 +1 -1
  14. data/ext/ffi_c/libffi/LICENSE +1 -1
  15. data/ext/ffi_c/libffi/Makefile.am +166 -157
  16. data/ext/ffi_c/libffi/README +164 -52
  17. data/ext/ffi_c/libffi/acinclude.m4 +381 -0
  18. data/ext/ffi_c/libffi/autogen.sh +2 -0
  19. data/ext/ffi_c/libffi/configure.ac +148 -256
  20. data/ext/ffi_c/libffi/configure.host +265 -4
  21. data/ext/ffi_c/libffi/doc/Makefile.am +3 -0
  22. data/ext/ffi_c/libffi/doc/libffi.texi +430 -45
  23. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  24. data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +207 -0
  25. data/ext/ffi_c/libffi/include/Makefile.am +3 -3
  26. data/ext/ffi_c/libffi/include/ffi.h.in +107 -50
  27. data/ext/ffi_c/libffi/include/ffi_cfi.h +55 -0
  28. data/ext/ffi_c/libffi/include/ffi_common.h +32 -11
  29. data/ext/ffi_c/libffi/libffi.map.in +80 -0
  30. data/ext/ffi_c/libffi/libffi.pc.in +3 -2
  31. data/ext/ffi_c/libffi/libffi.xcodeproj/project.pbxproj +637 -0
  32. data/ext/ffi_c/libffi/libtool-ldflags +106 -0
  33. data/ext/ffi_c/libffi/libtool-version +1 -1
  34. data/ext/ffi_c/libffi/m4/asmcfi.m4 +13 -0
  35. data/ext/ffi_c/libffi/m4/ax_append_flag.m4 +69 -0
  36. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +13 -8
  37. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +31 -104
  38. data/ext/ffi_c/libffi/m4/{ax_check_compiler_flags.m4 → ax_check_compile_flag.m4} +30 -34
  39. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +32 -11
  40. data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +6 -5
  41. data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +31 -21
  42. data/ext/ffi_c/libffi/man/Makefile.am +2 -2
  43. data/ext/ffi_c/libffi/man/ffi.3 +10 -0
  44. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +6 -4
  45. data/ext/ffi_c/libffi/man/ffi_prep_cif_var.3 +73 -0
  46. data/ext/ffi_c/libffi/msvcc.sh +72 -9
  47. data/ext/ffi_c/libffi/src/aarch64/ffi.c +941 -0
  48. data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +81 -0
  49. data/ext/ffi_c/libffi/src/aarch64/internal.h +67 -0
  50. data/ext/ffi_c/libffi/src/aarch64/sysv.S +438 -0
  51. data/ext/ffi_c/libffi/src/alpha/ffi.c +335 -98
  52. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +10 -1
  53. data/ext/ffi_c/libffi/src/alpha/internal.h +23 -0
  54. data/ext/ffi_c/libffi/src/alpha/osf.S +161 -266
  55. data/ext/ffi_c/libffi/src/arc/arcompact.S +135 -0
  56. data/ext/ffi_c/libffi/src/arc/ffi.c +266 -0
  57. data/ext/ffi_c/libffi/src/arc/ffitarget.h +53 -0
  58. data/ext/ffi_c/libffi/src/arm/ffi.c +597 -517
  59. data/ext/ffi_c/libffi/src/arm/ffitarget.h +24 -7
  60. data/ext/ffi_c/libffi/src/arm/internal.h +7 -0
  61. data/ext/ffi_c/libffi/src/arm/sysv.S +303 -417
  62. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +6 -1
  63. data/ext/ffi_c/libffi/src/bfin/ffi.c +196 -0
  64. data/ext/ffi_c/libffi/src/bfin/ffitarget.h +43 -0
  65. data/ext/ffi_c/libffi/src/bfin/sysv.S +179 -0
  66. data/ext/ffi_c/libffi/src/closures.c +319 -44
  67. data/ext/ffi_c/libffi/src/cris/ffi.c +10 -7
  68. data/ext/ffi_c/libffi/src/cris/ffitarget.h +6 -1
  69. data/ext/ffi_c/libffi/src/debug.c +6 -1
  70. data/ext/ffi_c/libffi/src/dlmalloc.c +16 -11
  71. data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
  72. data/ext/ffi_c/libffi/src/frv/ffitarget.h +6 -1
  73. data/ext/ffi_c/libffi/src/ia64/ffi.c +11 -7
  74. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +6 -1
  75. data/ext/ffi_c/libffi/src/java_raw_api.c +23 -5
  76. data/ext/ffi_c/libffi/src/m32r/ffi.c +1 -1
  77. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +6 -1
  78. data/ext/ffi_c/libffi/src/m68k/ffi.c +87 -13
  79. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +6 -1
  80. data/ext/ffi_c/libffi/src/m68k/sysv.S +119 -32
  81. data/ext/ffi_c/libffi/src/m88k/ffi.c +400 -0
  82. data/ext/ffi_c/libffi/src/m88k/ffitarget.h +49 -0
  83. data/ext/ffi_c/libffi/src/m88k/obsd.S +209 -0
  84. data/ext/ffi_c/libffi/src/metag/ffi.c +330 -0
  85. data/ext/ffi_c/libffi/{fficonfig.hw → src/metag/ffitarget.h} +22 -26
  86. data/ext/ffi_c/libffi/src/metag/sysv.S +311 -0
  87. data/ext/ffi_c/libffi/src/microblaze/ffi.c +321 -0
  88. data/ext/ffi_c/libffi/src/microblaze/ffitarget.h +53 -0
  89. data/ext/ffi_c/libffi/src/microblaze/sysv.S +302 -0
  90. data/ext/ffi_c/libffi/src/mips/ffi.c +95 -28
  91. data/ext/ffi_c/libffi/src/mips/ffitarget.h +9 -2
  92. data/ext/ffi_c/libffi/src/mips/n32.S +126 -56
  93. data/ext/ffi_c/libffi/src/mips/o32.S +148 -27
  94. data/ext/ffi_c/libffi/src/moxie/eabi.S +55 -82
  95. data/ext/ffi_c/libffi/src/moxie/ffi.c +40 -44
  96. data/ext/ffi_c/libffi/src/moxie/ffitarget.h +52 -0
  97. data/ext/ffi_c/libffi/src/nios2/ffi.c +304 -0
  98. data/ext/ffi_c/libffi/src/nios2/ffitarget.h +52 -0
  99. data/ext/ffi_c/libffi/src/nios2/sysv.S +136 -0
  100. data/ext/ffi_c/libffi/src/or1k/ffi.c +328 -0
  101. data/ext/ffi_c/libffi/src/or1k/ffitarget.h +58 -0
  102. data/ext/ffi_c/libffi/src/or1k/sysv.S +107 -0
  103. data/ext/ffi_c/libffi/src/pa/ffitarget.h +8 -1
  104. data/ext/ffi_c/libffi/src/powerpc/aix.S +6 -6
  105. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +3 -1
  106. data/ext/ffi_c/libffi/src/powerpc/asm.h +2 -2
  107. data/ext/ffi_c/libffi/src/powerpc/darwin.S +2 -7
  108. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +22 -26
  109. data/ext/ffi_c/libffi/src/powerpc/ffi.c +103 -1378
  110. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +25 -25
  111. data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +945 -0
  112. data/ext/ffi_c/libffi/src/powerpc/ffi_powerpc.h +94 -0
  113. data/ext/ffi_c/libffi/src/powerpc/ffi_sysv.c +923 -0
  114. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +100 -44
  115. data/ext/ffi_c/libffi/src/powerpc/linux64.S +100 -59
  116. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +360 -108
  117. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +138 -68
  118. data/ext/ffi_c/libffi/src/powerpc/sysv.S +68 -112
  119. data/ext/ffi_c/libffi/src/prep_cif.c +108 -24
  120. data/ext/ffi_c/libffi/src/raw_api.c +18 -5
  121. data/ext/ffi_c/libffi/src/s390/ffi.c +294 -318
  122. data/ext/ffi_c/libffi/src/s390/ffitarget.h +9 -1
  123. data/ext/ffi_c/libffi/src/s390/internal.h +11 -0
  124. data/ext/ffi_c/libffi/src/s390/sysv.S +257 -366
  125. data/ext/ffi_c/libffi/src/sh/ffi.c +4 -3
  126. data/ext/ffi_c/libffi/src/sh/ffitarget.h +6 -1
  127. data/ext/ffi_c/libffi/src/sh64/ffi.c +3 -2
  128. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +6 -1
  129. data/ext/ffi_c/libffi/src/sparc/ffi.c +326 -527
  130. data/ext/ffi_c/libffi/src/sparc/ffi64.c +608 -0
  131. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +20 -7
  132. data/ext/ffi_c/libffi/src/sparc/internal.h +26 -0
  133. data/ext/ffi_c/libffi/src/sparc/v8.S +364 -234
  134. data/ext/ffi_c/libffi/src/sparc/v9.S +340 -207
  135. data/ext/ffi_c/libffi/src/tile/ffi.c +355 -0
  136. data/ext/ffi_c/libffi/src/tile/ffitarget.h +65 -0
  137. data/ext/ffi_c/libffi/src/tile/tile.S +360 -0
  138. data/ext/ffi_c/libffi/src/types.c +43 -14
  139. data/ext/ffi_c/libffi/src/vax/elfbsd.S +195 -0
  140. data/ext/ffi_c/libffi/src/vax/ffi.c +276 -0
  141. data/ext/ffi_c/libffi/src/vax/ffitarget.h +49 -0
  142. data/ext/ffi_c/libffi/src/x86/asmnames.h +30 -0
  143. data/ext/ffi_c/libffi/src/x86/ffi.c +589 -500
  144. data/ext/ffi_c/libffi/src/x86/ffi64.c +338 -116
  145. data/ext/ffi_c/libffi/src/x86/ffitarget.h +55 -35
  146. data/ext/ffi_c/libffi/src/x86/ffiw64.c +287 -0
  147. data/ext/ffi_c/libffi/src/x86/internal.h +29 -0
  148. data/ext/ffi_c/libffi/src/x86/internal64.h +22 -0
  149. data/ext/ffi_c/libffi/src/x86/sysv.S +975 -400
  150. data/ext/ffi_c/libffi/src/x86/unix64.S +398 -299
  151. data/ext/ffi_c/libffi/src/x86/win64.S +222 -458
  152. data/ext/ffi_c/libffi/src/x86/win64_intel.S +237 -0
  153. data/ext/ffi_c/libffi/src/xtensa/ffi.c +298 -0
  154. data/ext/ffi_c/libffi/src/xtensa/ffitarget.h +53 -0
  155. data/ext/ffi_c/libffi/src/xtensa/sysv.S +253 -0
  156. data/ext/ffi_c/libffi/stamp-h.in +1 -0
  157. data/ext/ffi_c/libffi/testsuite/Makefile.am +78 -73
  158. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +120 -25
  159. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +21 -1
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/align_mixed.c +46 -0
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +4 -6
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/{closure_stdcall.c → closure_simple.c} +7 -16
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +4 -4
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +4 -4
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +4 -4
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +4 -4
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +4 -4
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +4 -4
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +4 -4
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +5 -5
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +4 -4
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +4 -4
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +4 -4
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +4 -4
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +4 -4
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +4 -4
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +4 -4
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +4 -4
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +5 -5
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +4 -4
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +4 -4
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +4 -4
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +4 -4
  184. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +4 -4
  185. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +4 -4
  186. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +4 -4
  187. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +4 -4
  188. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +4 -4
  189. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +4 -4
  190. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +4 -6
  191. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +4 -6
  192. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +4 -4
  193. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +4 -4
  194. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +4 -4
  195. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +4 -4
  196. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +4 -4
  197. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +4 -4
  198. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +4 -4
  199. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +4 -4
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +10 -9
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +3 -3
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +10 -9
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_many_mixed_args.c +70 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c +55 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +1 -1
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +11 -9
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_struct_va1.c +114 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar_va.c +44 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint_va.c +45 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulong_va.c +45 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +5 -5
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort_va.c +44 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -2
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +23 -40
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +3 -1
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +6 -4
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +4 -2
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/float_va.c +107 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +18 -19
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +6 -16
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/many2.c +57 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/many_double.c +70 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/many_mixed.c +78 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +0 -1
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +6 -6
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +8 -8
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +6 -6
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct11.c +121 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +5 -5
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +5 -5
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +5 -5
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +5 -5
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +6 -6
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +5 -5
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +6 -6
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +6 -6
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/offsets.c +46 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/pr1172638.c +127 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +1 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +1 -1
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +1 -1
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +1 -1
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +7 -7
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +7 -7
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +5 -5
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +5 -5
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +2 -2
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen2.c +49 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen3.c +49 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen4.c +55 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +9 -7
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +7 -7
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +7 -6
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +9 -8
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +9 -8
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +9 -9
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +9 -9
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +9 -8
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +9 -8
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +2 -2
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/uninitialized.c +61 -0
  262. data/ext/ffi_c/libffi/testsuite/{libffi.special → libffi.call}/unwindtest.cc +3 -10
  263. data/ext/ffi_c/libffi/testsuite/{libffi.special → libffi.call}/unwindtest_ffi_call.cc +2 -1
  264. data/ext/ffi_c/libffi/testsuite/libffi.call/va_1.c +196 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct1.c +121 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +123 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +125 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex.inc +91 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_double.c +10 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_float.c +10 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c +10 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex.inc +42 -0
  273. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_double.c +10 -0
  274. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_float.c +10 -0
  275. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_longdouble.c +10 -0
  276. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct.inc +71 -0
  277. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_double.c +10 -0
  278. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_float.c +10 -0
  279. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c +10 -0
  280. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va.inc +80 -0
  281. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_double.c +10 -0
  282. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_float.c +16 -0
  283. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c +10 -0
  284. data/ext/ffi_c/libffi/testsuite/{libffi.special/special.exp → libffi.complex/complex.exp} +9 -8
  285. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex.inc +51 -0
  286. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_double.inc +7 -0
  287. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_float.inc +7 -0
  288. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc +7 -0
  289. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_double.c +10 -0
  290. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_float.c +10 -0
  291. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_int.c +86 -0
  292. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_longdouble.c +10 -0
  293. data/ext/ffi_c/libffi/testsuite/libffi.complex/ffitest.h +1 -0
  294. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex.inc +78 -0
  295. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_double.c +10 -0
  296. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_float.c +10 -0
  297. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_longdouble.c +10 -0
  298. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex.inc +37 -0
  299. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1.inc +41 -0
  300. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_double.c +10 -0
  301. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_float.c +10 -0
  302. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_longdouble.c +10 -0
  303. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2.inc +44 -0
  304. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_double.c +10 -0
  305. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_float.c +10 -0
  306. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_longdouble.c +10 -0
  307. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_double.c +10 -0
  308. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_float.c +10 -0
  309. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_longdouble.c +10 -0
  310. data/ext/ffi_c/libffi/testsuite/libffi.go/aa-direct.c +34 -0
  311. data/ext/ffi_c/libffi/testsuite/libffi.go/closure1.c +28 -0
  312. data/ext/ffi_c/libffi/testsuite/libffi.go/ffitest.h +1 -0
  313. data/ext/ffi_c/libffi/testsuite/libffi.go/go.exp +36 -0
  314. data/ext/ffi_c/libffi/testsuite/libffi.go/static-chain.h +19 -0
  315. data/ffi.gemspec +2 -2
  316. data/lib/ffi/enum.rb +124 -0
  317. data/lib/ffi/library.rb +65 -13
  318. data/lib/ffi/platform.rb +7 -2
  319. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  320. data/lib/ffi/platform/x86_64-windows/types.conf +113 -20
  321. data/lib/ffi/pointer.rb +1 -0
  322. data/lib/ffi/struct.rb +0 -2
  323. data/lib/ffi/version.rb +1 -1
  324. data/spec/ffi/bitmask_spec.rb +575 -0
  325. data/spec/ffi/fixtures/BitmaskTest.c +51 -0
  326. data/spec/ffi/rbx/memory_pointer_spec.rb +4 -0
  327. data/spec/ffi/struct_spec.rb +0 -4
  328. metadata +143 -51
  329. data/ext/ffi_c/libffi/Makefile.in +0 -1820
  330. data/ext/ffi_c/libffi/Makefile.vc +0 -141
  331. data/ext/ffi_c/libffi/Makefile.vc64 +0 -141
  332. data/ext/ffi_c/libffi/aclocal.m4 +0 -1873
  333. data/ext/ffi_c/libffi/build-ios.sh +0 -67
  334. data/ext/ffi_c/libffi/compile +0 -143
  335. data/ext/ffi_c/libffi/config.guess +0 -1501
  336. data/ext/ffi_c/libffi/config.sub +0 -1705
  337. data/ext/ffi_c/libffi/configure +0 -17191
  338. data/ext/ffi_c/libffi/depcomp +0 -630
  339. data/ext/ffi_c/libffi/doc/libffi.info +0 -593
  340. data/ext/ffi_c/libffi/doc/stamp-vti +0 -4
  341. data/ext/ffi_c/libffi/fficonfig.h.in +0 -199
  342. data/ext/ffi_c/libffi/include/Makefile.in +0 -487
  343. data/ext/ffi_c/libffi/include/ffi.h.vc +0 -427
  344. data/ext/ffi_c/libffi/include/ffi.h.vc64 +0 -427
  345. data/ext/ffi_c/libffi/install-sh +0 -520
  346. data/ext/ffi_c/libffi/ltmain.sh +0 -9636
  347. data/ext/ffi_c/libffi/m4/libtool.m4 +0 -7831
  348. data/ext/ffi_c/libffi/m4/ltoptions.m4 +0 -369
  349. data/ext/ffi_c/libffi/m4/ltsugar.m4 +0 -123
  350. data/ext/ffi_c/libffi/m4/ltversion.m4 +0 -23
  351. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +0 -98
  352. data/ext/ffi_c/libffi/man/Makefile.in +0 -466
  353. data/ext/ffi_c/libffi/mdate-sh +0 -201
  354. data/ext/ffi_c/libffi/missing +0 -376
  355. data/ext/ffi_c/libffi/src/arm/gentramp.sh +0 -118
  356. data/ext/ffi_c/libffi/src/arm/trampoline.S +0 -4450
  357. data/ext/ffi_c/libffi/src/x86/darwin.S +0 -444
  358. data/ext/ffi_c/libffi/src/x86/darwin64.S +0 -416
  359. data/ext/ffi_c/libffi/src/x86/freebsd.S +0 -458
  360. data/ext/ffi_c/libffi/src/x86/win32.S +0 -1065
  361. data/ext/ffi_c/libffi/testsuite/Makefile.in +0 -500
  362. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +0 -300
  363. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +0 -63
  364. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +0 -44
  365. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +0 -96
  366. data/ext/ffi_c/libffi/texinfo.tex +0 -7210
@@ -1,10 +1,11 @@
1
1
  /* -----------------------------------------------------------------------
2
- ffi.c - Copyright (c) 2011 Plausible Labs Cooperative, Inc.
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
- /* ffi_prep_args is called by the assembly routine once stack space
40
- has been allocated for the function's arguments
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
- int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
119
+ static void
120
+ ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
121
+ void **avalue, char *argp)
47
122
  {
48
- register unsigned int i, vi = 0;
49
- register void **p_argv;
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
- argp = stack;
126
+ if (flags == ARM_TYPE_STRUCT)
127
+ {
128
+ *(void **) argp = rvalue;
129
+ argp += 4;
130
+ }
54
131
 
55
- if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
56
- *(void **) argp = ecif->rvalue;
57
- argp += 4;
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
- p_argv = ecif->avalue;
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 = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
63
- (i != 0);
64
- i--, p_arg++)
163
+ for (i = 0, n = cif->nargs; i < n; i++)
65
164
  {
66
- size_t z;
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 (ecif->cif->abi == FFI_VFP
70
- && vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
170
+ if (vi < cif->vfp_nargs && is_vfp_type)
71
171
  {
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++;
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
- /* Align if necessary */
84
- if (((*p_arg)->alignment - 1) & (unsigned) argp) {
85
- argp = (char *) ALIGN(argp, (*p_arg)->alignment);
86
- }
87
-
88
- if ((*p_arg)->type == FFI_TYPE_STRUCT)
89
- argp = (char *) ALIGN(argp, 4);
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
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
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
- else
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
- memcpy(argp, *p_argv, z);
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
- p_argv++;
130
- argp += z;
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 ffi_prep_cif_machdep(ffi_cif *cif)
212
+ ffi_status
213
+ ffi_prep_cif_machdep (ffi_cif *cif)
139
214
  {
140
- int type_code;
141
- /* Round the stack up to a multiple of 8 bytes. This isn't needed
142
- everywhere, but it is on some platforms, and it doesn't harm anything
143
- when it isn't needed. */
144
- cif->bytes = (cif->bytes + 7) & ~7;
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
- case FFI_TYPE_FLOAT:
151
- case FFI_TYPE_DOUBLE:
152
- cif->flags = (unsigned) cif->rtype->type;
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
- cif->flags = (unsigned) FFI_TYPE_SINT64;
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
- if (cif->abi == FFI_VFP
162
- && (type_code = vfp_type_p (cif->rtype)) != 0)
256
+ case FFI_TYPE_COMPLEX:
257
+ if (cabi == FFI_VFP)
163
258
  {
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;
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
- else if (cif->rtype->size <= 4)
169
- /* A Composite Type not larger than 4 bytes is returned in r0. */
170
- cif->flags = (unsigned)FFI_TYPE_INT;
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
- /* A Composite Type larger than 4 bytes, or whose size cannot
173
- be determined statically ... is stored in memory at an
174
- address passed [in r0]. */
175
- cif->flags = (unsigned)FFI_TYPE_STRUCT;
277
+ {
278
+ flags = ARM_TYPE_STRUCT;
279
+ bytes += 4;
280
+ }
176
281
  break;
177
282
 
178
283
  default:
179
- cif->flags = FFI_TYPE_INT;
180
- break;
284
+ abort();
181
285
  }
182
286
 
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);
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
- /* 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 *);
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
- extended_cif ecif;
307
+ /* VFP variadic calls actually use the SYSV ABI */
308
+ if (cif->abi == FFI_VFP)
309
+ cif->abi = FFI_SYSV;
199
310
 
200
- int small_struct = (cif->flags == FFI_TYPE_INT
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);
311
+ return ffi_prep_cif_machdep (cif);
312
+ }
204
313
 
205
- ecif.cif = cif;
206
- ecif.avalue = avalue;
314
+ /* Prototypes for assembly functions, in sysv.S. */
207
315
 
208
- unsigned int temp;
209
-
210
- /* If the return value is a struct and we don't have a return */
211
- /* value address then we need to make one */
316
+ struct call_frame
317
+ {
318
+ void *fp;
319
+ void *lr;
320
+ void *rvalue;
321
+ int flags;
322
+ void *closure;
323
+ };
212
324
 
213
- if ((rvalue == NULL) &&
214
- (cif->flags == FFI_TYPE_STRUCT))
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
- ecif.rvalue = alloca(cif->rtype->size);
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 (small_struct)
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
- ecif.rvalue = alloca(32);
354
+ rsize = 32;
224
355
  }
225
- else
226
- ecif.rvalue = rvalue;
356
+ else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
357
+ rsize = 4;
227
358
 
228
- switch (cif->abi)
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
- case FFI_VFP:
235
- ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
236
- break;
362
+ bytes = cif->bytes;
363
+ stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
237
364
 
238
- default:
239
- FFI_ASSERT(0);
240
- break;
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
- /** private members **/
372
+ frame = (struct call_frame *)(stack + bytes);
249
373
 
250
- static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
251
- void** args, ffi_cif* cif, float *vfp_stack);
374
+ new_rvalue = rvalue;
375
+ if (rsize)
376
+ new_rvalue = (void *)(frame + 1);
252
377
 
253
- void ffi_closure_SYSV (ffi_closure *);
378
+ frame->rvalue = new_rvalue;
379
+ frame->flags = flags;
380
+ frame->closure = closure;
254
381
 
255
- void ffi_closure_VFP (ffi_closure *);
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
- /* This function is jumped to by the trampoline */
393
+ if (rvalue && rvalue != new_rvalue)
394
+ memcpy (rvalue, new_rvalue, rtype->size);
395
+ }
258
396
 
259
- unsigned int
260
- ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
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
- // our various things...
267
- ffi_cif *cif;
268
- void **arg_area;
400
+ ffi_call_int (cif, fn, rvalue, avalue, NULL);
401
+ }
269
402
 
270
- cif = closure->cif;
271
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
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
- /* this call will initialize ARG_AREA, such that each
274
- * element in that array points to the corresponding
275
- * value on the stack; and if the function returns
276
- * a structure, it will re-set RESP to point to the
277
- * structure return address. */
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
- ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
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
- (closure->fun) (cif, *respp, arg_area, closure->user_data);
428
+ argp = ffi_align (ty, argp);
429
+ avalue[i] = (void *) argp;
430
+ argp += z;
431
+ }
282
432
 
283
- return cif->flags;
433
+ return rvalue;
284
434
  }
285
435
 
286
- /*@-exportheader@*/
287
- static void
288
- ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
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
- register unsigned int i, vi = 0;
295
- register void **p_argv;
296
- register char *argp;
297
- register ffi_type **p_arg;
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
- if ( cif->flags == FFI_TYPE_STRUCT ) {
302
- *rvalue = *(void **) argp;
303
- argp += 4;
304
- }
446
+ regp = stack;
447
+ eo_regp = argp = regp + 16;
305
448
 
306
- p_argv = avalue;
449
+ if (cif->flags == ARM_TYPE_STRUCT)
450
+ {
451
+ rvalue = *(void **) regp;
452
+ regp += 4;
453
+ }
307
454
 
308
- for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
455
+ for (i = 0, n = cif->nargs; i < n; i++)
309
456
  {
310
- size_t z;
311
- size_t alignment;
312
-
313
- if (cif->abi == FFI_VFP
314
- && vi < cif->vfp_nargs && vfp_type_p (*p_arg))
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
- *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
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
- alignment = (*p_arg)->alignment;
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
- *p_argv = (void*) argp;
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
- p_argv++;
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
- #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
- };
503
+ return rvalue;
504
+ }
368
505
 
369
- struct ffi_trampoline_table_entry {
370
- void *(*trampoline)();
371
- ffi_trampoline_table_entry *next;
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
- /* 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 ()
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
- 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
- }
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
- /* 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
- }
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
- /* Remap the trampoline table to directly follow the config page */
417
- vm_prot_t cur_prot;
418
- vm_prot_t max_prot;
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
- 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);
544
+ /* the cif must already be prep'ed */
421
545
 
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
- }
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
- vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
430
- continue;
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
- /* 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
- }
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
- table->free_list = table->free_list_pool;
452
- }
574
+ closure->cif = cif;
575
+ closure->fun = fun;
576
+ closure->user_data = user_data;
453
577
 
454
- return table;
578
+ return FFI_OK;
455
579
  }
456
580
 
457
- void *
458
- ffi_closure_alloc (size_t size, void **code)
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
- /* 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
- }
585
+ void (*closure_func) (void) = ffi_go_closure_SYSV;
475
586
 
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
- }
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
- /* 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;
596
+ closure->tramp = closure_func;
597
+ closure->cif = cif;
598
+ closure->fun = fun;
489
599
 
490
- pthread_mutex_unlock(&ffi_trampoline_lock);
600
+ return FFI_OK;
601
+ }
491
602
 
492
- /* Initialize the return values */
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 closure;
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
- void
501
- ffi_closure_free (void *ptr)
609
+ static int
610
+ is_hfa0 (const ffi_type *ty)
502
611
  {
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
612
+ ffi_type **elements = ty->elements;
613
+ int i, ret = -1;
556
614
 
557
- #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
558
- ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
559
- unsigned int __fun = (unsigned int)(FUN); \
560
- unsigned int __ctx = (unsigned int)(CTX); \
561
- unsigned char *insns = (unsigned char *)(CTX); \
562
- *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \
563
- *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
564
- *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
565
- *(unsigned int*) &__tramp[12] = __ctx; \
566
- *(unsigned int*) &__tramp[16] = __fun; \
567
- __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \
568
- __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \
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
- #endif
628
+ return ret;
629
+ }
574
630
 
575
- /* the cif must already be prep'ed */
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
- ffi_status
578
- ffi_prep_closure_loc (ffi_closure* closure,
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
- void (*closure_func)(ffi_closure*) = NULL;
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
- closure->cif = cif;
604
- closure->user_data = user_data;
605
- closure->fun = fun;
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 FFI_OK;
653
+ return 1;
608
654
  }
609
655
 
610
- /* Below are routines for VFP hard-float support. */
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 rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
663
+ static int
664
+ vfp_type_p (const ffi_type *ty)
613
665
  {
614
- switch (t->type)
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
- *elt = (int) t->type;
619
- *elnum = 1;
620
- return 1;
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
- case FFI_TYPE_STRUCT_VFP_FLOAT:
623
- *elt = FFI_TYPE_FLOAT;
624
- *elnum = t->size / sizeof (float);
625
- return 1;
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
- case FFI_TYPE_STRUCT_VFP_DOUBLE:
628
- *elt = FFI_TYPE_DOUBLE;
629
- *elnum = t->size / sizeof (double);
630
- return 1;
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
- 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: ;
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
- return 0;
654
- }
725
+ if (ele_count > 4)
726
+ return 0;
655
727
 
656
- static int vfp_type_p (ffi_type *t)
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
- 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;
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
- return 0;
740
+
741
+ /* All tests succeeded. Encode the result. */
742
+ done:
743
+ return (ele_count << 8) | candidate;
673
744
  }
674
745
 
675
- static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
746
+ static int
747
+ place_vfp_arg (ffi_cif *cif, int h)
676
748
  {
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);
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 layout_vfp_args (ffi_cif *cif)
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); /* Init to -1. */
800
+ memset (cif->vfp_args, -1, 16); /* Init to -1. */
721
801
 
722
802
  for (i = 0; i < cif->nargs; i++)
723
803
  {
724
- ffi_type *t = cif->arg_types[i];
725
- if (vfp_type_p (t))
726
- place_vfp_arg (cif, t);
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
  }