ffi 1.9.18 → 1.9.23

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