remogatto-ffi 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (324) hide show
  1. data/LICENSE +51 -0
  2. data/README.rdoc +69 -0
  3. data/Rakefile +144 -0
  4. data/ext/ffi_c/AbstractMemory.c +489 -0
  5. data/ext/ffi_c/AbstractMemory.h +160 -0
  6. data/ext/ffi_c/ArrayType.c +129 -0
  7. data/ext/ffi_c/ArrayType.h +58 -0
  8. data/ext/ffi_c/AutoPointer.c +61 -0
  9. data/ext/ffi_c/AutoPointer.h +18 -0
  10. data/ext/ffi_c/Buffer.c +187 -0
  11. data/ext/ffi_c/Call.c +431 -0
  12. data/ext/ffi_c/Call.h +77 -0
  13. data/ext/ffi_c/DynamicLibrary.c +216 -0
  14. data/ext/ffi_c/DynamicLibrary.h +22 -0
  15. data/ext/ffi_c/Function.c +498 -0
  16. data/ext/ffi_c/Function.h +73 -0
  17. data/ext/ffi_c/FunctionInfo.c +213 -0
  18. data/ext/ffi_c/LastError.c +159 -0
  19. data/ext/ffi_c/LastError.h +18 -0
  20. data/ext/ffi_c/MemoryPointer.c +178 -0
  21. data/ext/ffi_c/MemoryPointer.h +20 -0
  22. data/ext/ffi_c/MethodHandle.c +356 -0
  23. data/ext/ffi_c/MethodHandle.h +53 -0
  24. data/ext/ffi_c/Platform.c +59 -0
  25. data/ext/ffi_c/Platform.h +16 -0
  26. data/ext/ffi_c/Pointer.c +217 -0
  27. data/ext/ffi_c/Pointer.h +49 -0
  28. data/ext/ffi_c/Struct.c +770 -0
  29. data/ext/ffi_c/Struct.h +80 -0
  30. data/ext/ffi_c/StructByValue.c +140 -0
  31. data/ext/ffi_c/StructByValue.h +53 -0
  32. data/ext/ffi_c/StructLayout.c +450 -0
  33. data/ext/ffi_c/Type.c +329 -0
  34. data/ext/ffi_c/Type.h +57 -0
  35. data/ext/ffi_c/Types.c +103 -0
  36. data/ext/ffi_c/Types.h +85 -0
  37. data/ext/ffi_c/Variadic.c +260 -0
  38. data/ext/ffi_c/compat.h +72 -0
  39. data/ext/ffi_c/endian.h +40 -0
  40. data/ext/ffi_c/extconf.rb +34 -0
  41. data/ext/ffi_c/ffi.c +80 -0
  42. data/ext/ffi_c/libffi.bsd.mk +34 -0
  43. data/ext/ffi_c/libffi.darwin.mk +75 -0
  44. data/ext/ffi_c/libffi.gnu.mk +29 -0
  45. data/ext/ffi_c/libffi.mk +13 -0
  46. data/ext/ffi_c/libffi/ChangeLog +3243 -0
  47. data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
  48. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  49. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  50. data/ext/ffi_c/libffi/LICENSE +21 -0
  51. data/ext/ffi_c/libffi/Makefile.am +177 -0
  52. data/ext/ffi_c/libffi/Makefile.in +1640 -0
  53. data/ext/ffi_c/libffi/README +328 -0
  54. data/ext/ffi_c/libffi/TODO +1 -0
  55. data/ext/ffi_c/libffi/acinclude.m4 +92 -0
  56. data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
  57. data/ext/ffi_c/libffi/compile +142 -0
  58. data/ext/ffi_c/libffi/config.guess +1516 -0
  59. data/ext/ffi_c/libffi/config.sub +1626 -0
  60. data/ext/ffi_c/libffi/configure +24414 -0
  61. data/ext/ffi_c/libffi/configure.ac +365 -0
  62. data/ext/ffi_c/libffi/configure.host +11 -0
  63. data/ext/ffi_c/libffi/depcomp +584 -0
  64. data/ext/ffi_c/libffi/doc/libffi.info +533 -0
  65. data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
  66. data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
  67. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  68. data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
  69. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  70. data/ext/ffi_c/libffi/include/Makefile.in +422 -0
  71. data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
  72. data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
  73. data/ext/ffi_c/libffi/install-sh +323 -0
  74. data/ext/ffi_c/libffi/libffi.pc.in +10 -0
  75. data/ext/ffi_c/libffi/libtool-version +29 -0
  76. data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
  77. data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
  78. data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
  79. data/ext/ffi_c/libffi/ltconfig +2862 -0
  80. data/ext/ffi_c/libffi/ltmain.sh +6930 -0
  81. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  82. data/ext/ffi_c/libffi/man/Makefile.in +395 -0
  83. data/ext/ffi_c/libffi/man/ffi.3 +31 -0
  84. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  85. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
  86. data/ext/ffi_c/libffi/mdate-sh +201 -0
  87. data/ext/ffi_c/libffi/missing +353 -0
  88. data/ext/ffi_c/libffi/mkinstalldirs +158 -0
  89. data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
  90. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
  91. data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
  92. data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
  93. data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
  94. data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
  95. data/ext/ffi_c/libffi/src/closures.c +596 -0
  96. data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
  97. data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
  98. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  99. data/ext/ffi_c/libffi/src/debug.c +59 -0
  100. data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
  101. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  102. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  103. data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
  104. data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
  105. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
  106. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  107. data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
  108. data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
  109. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  110. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
  111. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  112. data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
  113. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
  114. data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
  115. data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
  116. data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
  117. data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
  118. data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
  119. data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
  120. data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
  121. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  122. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  123. data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
  124. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
  125. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  126. data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
  127. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
  128. data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
  129. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
  130. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
  131. data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
  132. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
  133. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
  134. data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
  135. data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
  136. data/ext/ffi_c/libffi/src/raw_api.c +254 -0
  137. data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
  138. data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
  139. data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
  140. data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
  141. data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
  142. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  143. data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
  144. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
  145. data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
  146. data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
  147. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
  148. data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
  149. data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
  150. data/ext/ffi_c/libffi/src/types.c +77 -0
  151. data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
  152. data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
  153. data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
  154. data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
  155. data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
  156. data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
  157. data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
  158. data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
  159. data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
  160. data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
  161. data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
  162. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  163. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
  164. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
  165. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
  184. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
  185. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
  186. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
  187. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
  188. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
  189. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
  190. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
  191. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
  192. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
  193. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
  194. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
  195. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
  196. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
  197. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
  198. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
  199. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
  273. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
  274. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
  275. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  276. data/ext/ffi_c/libffi/texinfo.tex +7482 -0
  277. data/ext/ffi_c/rbffi.h +26 -0
  278. data/gen/Rakefile +12 -0
  279. data/lib/ffi.rb +11 -0
  280. data/lib/ffi/autopointer.rb +61 -0
  281. data/lib/ffi/buffer.rb +0 -0
  282. data/lib/ffi/callback.rb +10 -0
  283. data/lib/ffi/enum.rb +78 -0
  284. data/lib/ffi/errno.rb +8 -0
  285. data/lib/ffi/ffi.rb +99 -0
  286. data/lib/ffi/io.rb +21 -0
  287. data/lib/ffi/library.rb +218 -0
  288. data/lib/ffi/managedstruct.rb +55 -0
  289. data/lib/ffi/memorypointer.rb +73 -0
  290. data/lib/ffi/platform.rb +78 -0
  291. data/lib/ffi/pointer.rb +119 -0
  292. data/lib/ffi/struct.rb +164 -0
  293. data/lib/ffi/tools/const_generator.rb +177 -0
  294. data/lib/ffi/tools/generator.rb +58 -0
  295. data/lib/ffi/tools/generator_task.rb +35 -0
  296. data/lib/ffi/tools/struct_generator.rb +194 -0
  297. data/lib/ffi/tools/types_generator.rb +123 -0
  298. data/lib/ffi/types.rb +153 -0
  299. data/lib/ffi/union.rb +12 -0
  300. data/lib/ffi/variadic.rb +25 -0
  301. data/spec/ffi/bool_spec.rb +24 -0
  302. data/spec/ffi/buffer_spec.rb +202 -0
  303. data/spec/ffi/callback_spec.rb +591 -0
  304. data/spec/ffi/enum_spec.rb +164 -0
  305. data/spec/ffi/errno_spec.rb +13 -0
  306. data/spec/ffi/function_spec.rb +47 -0
  307. data/spec/ffi/library_spec.rb +144 -0
  308. data/spec/ffi/managed_struct_spec.rb +56 -0
  309. data/spec/ffi/number_spec.rb +231 -0
  310. data/spec/ffi/pointer_spec.rb +195 -0
  311. data/spec/ffi/rbx/attach_function_spec.rb +27 -0
  312. data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
  313. data/spec/ffi/rbx/spec_helper.rb +1 -0
  314. data/spec/ffi/rbx/struct_spec.rb +13 -0
  315. data/spec/ffi/spec_helper.rb +17 -0
  316. data/spec/ffi/string_spec.rb +103 -0
  317. data/spec/ffi/struct_callback_spec.rb +62 -0
  318. data/spec/ffi/struct_initialize_spec.rb +30 -0
  319. data/spec/ffi/struct_spec.rb +529 -0
  320. data/spec/ffi/typedef_spec.rb +48 -0
  321. data/spec/ffi/union_spec.rb +60 -0
  322. data/spec/ffi/variadic_spec.rb +84 -0
  323. data/spec/spec.opts +4 -0
  324. metadata +432 -0
@@ -0,0 +1,1429 @@
1
+ /* -----------------------------------------------------------------------
2
+ ffi.c - Copyright (c) 1998 Geoffrey Keating
3
+ Copyright (C) 2007 Free Software Foundation, Inc
4
+ Copyright (C) 2008 Red Hat, Inc
5
+
6
+ PowerPC Foreign Function Interface
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ ``Software''), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
23
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
26
+ ----------------------------------------------------------------------- */
27
+
28
+ #include <ffi.h>
29
+ #include <ffi_common.h>
30
+
31
+ #include <stdlib.h>
32
+ #include <stdio.h>
33
+
34
+
35
+ extern void ffi_closure_SYSV (void);
36
+ extern void FFI_HIDDEN ffi_closure_LINUX64 (void);
37
+
38
+ enum {
39
+ /* The assembly depends on these exact flags. */
40
+ FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */
41
+ FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
42
+ FLAG_RETURNS_FP = 1 << (31-29),
43
+ FLAG_RETURNS_64BITS = 1 << (31-28),
44
+
45
+ FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
46
+
47
+ FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
48
+ FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
49
+ FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
50
+ FLAG_RETVAL_REFERENCE = 1 << (31- 4)
51
+ };
52
+
53
+ /* About the SYSV ABI. */
54
+ unsigned int NUM_GPR_ARG_REGISTERS = 8;
55
+ #ifndef __NO_FPRS__
56
+ unsigned int NUM_FPR_ARG_REGISTERS = 8;
57
+ #else
58
+ unsigned int NUM_FPR_ARG_REGISTERS = 0;
59
+ #endif
60
+
61
+ enum { ASM_NEEDS_REGISTERS = 4 };
62
+
63
+ /* ffi_prep_args_SYSV is called by the assembly routine once stack space
64
+ has been allocated for the function's arguments.
65
+
66
+ The stack layout we want looks like this:
67
+
68
+ | Return address from ffi_call_SYSV 4bytes | higher addresses
69
+ |--------------------------------------------|
70
+ | Previous backchain pointer 4 | stack pointer here
71
+ |--------------------------------------------|<+ <<< on entry to
72
+ | Saved r28-r31 4*4 | | ffi_call_SYSV
73
+ |--------------------------------------------| |
74
+ | GPR registers r3-r10 8*4 | | ffi_call_SYSV
75
+ |--------------------------------------------| |
76
+ | FPR registers f1-f8 (optional) 8*8 | |
77
+ |--------------------------------------------| | stack |
78
+ | Space for copied structures | | grows |
79
+ |--------------------------------------------| | down V
80
+ | Parameters that didn't fit in registers | |
81
+ |--------------------------------------------| | lower addresses
82
+ | Space for callee's LR 4 | |
83
+ |--------------------------------------------| | stack pointer here
84
+ | Current backchain pointer 4 |-/ during
85
+ |--------------------------------------------| <<< ffi_call_SYSV
86
+
87
+ */
88
+
89
+ void
90
+ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
91
+ {
92
+ const unsigned bytes = ecif->cif->bytes;
93
+ const unsigned flags = ecif->cif->flags;
94
+
95
+ typedef union {
96
+ char *c;
97
+ unsigned *u;
98
+ long long *ll;
99
+ float *f;
100
+ double *d;
101
+ } valp;
102
+
103
+ /* 'stacktop' points at the previous backchain pointer. */
104
+ valp stacktop;
105
+
106
+ /* 'gpr_base' points at the space for gpr3, and grows upwards as
107
+ we use GPR registers. */
108
+ valp gpr_base;
109
+ int intarg_count;
110
+
111
+ /* 'fpr_base' points at the space for fpr1, and grows upwards as
112
+ we use FPR registers. */
113
+ valp fpr_base;
114
+ int fparg_count;
115
+
116
+ /* 'copy_space' grows down as we put structures in it. It should
117
+ stay 16-byte aligned. */
118
+ valp copy_space;
119
+
120
+ /* 'next_arg' grows up as we put parameters in it. */
121
+ valp next_arg;
122
+
123
+ int i, ii MAYBE_UNUSED;
124
+ ffi_type **ptr;
125
+ double double_tmp;
126
+ union {
127
+ void **v;
128
+ char **c;
129
+ signed char **sc;
130
+ unsigned char **uc;
131
+ signed short **ss;
132
+ unsigned short **us;
133
+ unsigned int **ui;
134
+ long long **ll;
135
+ float **f;
136
+ double **d;
137
+ } p_argv;
138
+ size_t struct_copy_size;
139
+ unsigned gprvalue;
140
+
141
+ if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
142
+ NUM_FPR_ARG_REGISTERS = 0;
143
+
144
+ stacktop.c = (char *) stack + bytes;
145
+ gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
146
+ intarg_count = 0;
147
+ fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
148
+ fparg_count = 0;
149
+ copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
150
+ next_arg.u = stack + 2;
151
+
152
+ /* Check that everything starts aligned properly. */
153
+ FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0);
154
+ FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0);
155
+ FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0);
156
+ FFI_ASSERT ((bytes & 0xF) == 0);
157
+ FFI_ASSERT (copy_space.c >= next_arg.c);
158
+
159
+ /* Deal with return values that are actually pass-by-reference. */
160
+ if (flags & FLAG_RETVAL_REFERENCE)
161
+ {
162
+ *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
163
+ intarg_count++;
164
+ }
165
+
166
+ /* Now for the arguments. */
167
+ p_argv.v = ecif->avalue;
168
+ for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
169
+ i > 0;
170
+ i--, ptr++, p_argv.v++)
171
+ {
172
+ switch ((*ptr)->type)
173
+ {
174
+ case FFI_TYPE_FLOAT:
175
+ /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
176
+ if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
177
+ goto soft_float_prep;
178
+ double_tmp = **p_argv.f;
179
+ if (fparg_count >= NUM_FPR_ARG_REGISTERS)
180
+ {
181
+ *next_arg.f = (float) double_tmp;
182
+ next_arg.u += 1;
183
+ }
184
+ else
185
+ *fpr_base.d++ = double_tmp;
186
+ fparg_count++;
187
+ FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
188
+ break;
189
+
190
+ case FFI_TYPE_DOUBLE:
191
+ /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
192
+ if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
193
+ goto soft_double_prep;
194
+ double_tmp = **p_argv.d;
195
+
196
+ if (fparg_count >= NUM_FPR_ARG_REGISTERS)
197
+ {
198
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS
199
+ && intarg_count % 2 != 0)
200
+ {
201
+ intarg_count++;
202
+ next_arg.u++;
203
+ }
204
+ *next_arg.d = double_tmp;
205
+ next_arg.u += 2;
206
+ }
207
+ else
208
+ *fpr_base.d++ = double_tmp;
209
+ fparg_count++;
210
+ FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
211
+ break;
212
+
213
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
214
+ case FFI_TYPE_LONGDOUBLE:
215
+ if ((ecif->cif->abi != FFI_LINUX)
216
+ && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
217
+ goto do_struct;
218
+ /* The soft float ABI for long doubles works like this,
219
+ a long double is passed in four consecutive gprs if available.
220
+ A maximum of 2 long doubles can be passed in gprs.
221
+ If we do not have 4 gprs left, the long double is passed on the
222
+ stack, 4-byte aligned. */
223
+ if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
224
+ {
225
+ unsigned int int_tmp = (*p_argv.ui)[0];
226
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
227
+ {
228
+ if (intarg_count < NUM_GPR_ARG_REGISTERS)
229
+ intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
230
+ *next_arg.u = int_tmp;
231
+ next_arg.u++;
232
+ for (ii = 1; ii < 4; ii++)
233
+ {
234
+ int_tmp = (*p_argv.ui)[ii];
235
+ *next_arg.u = int_tmp;
236
+ next_arg.u++;
237
+ }
238
+ }
239
+ else
240
+ {
241
+ *gpr_base.u++ = int_tmp;
242
+ for (ii = 1; ii < 4; ii++)
243
+ {
244
+ int_tmp = (*p_argv.ui)[ii];
245
+ *gpr_base.u++ = int_tmp;
246
+ }
247
+ }
248
+ intarg_count +=4;
249
+ }
250
+ else
251
+ {
252
+ double_tmp = (*p_argv.d)[0];
253
+
254
+ if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
255
+ {
256
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS
257
+ && intarg_count % 2 != 0)
258
+ {
259
+ intarg_count++;
260
+ next_arg.u++;
261
+ }
262
+ *next_arg.d = double_tmp;
263
+ next_arg.u += 2;
264
+ double_tmp = (*p_argv.d)[1];
265
+ *next_arg.d = double_tmp;
266
+ next_arg.u += 2;
267
+ }
268
+ else
269
+ {
270
+ *fpr_base.d++ = double_tmp;
271
+ double_tmp = (*p_argv.d)[1];
272
+ *fpr_base.d++ = double_tmp;
273
+ }
274
+
275
+ fparg_count += 2;
276
+ FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
277
+ }
278
+ break;
279
+ #endif
280
+
281
+ case FFI_TYPE_UINT64:
282
+ case FFI_TYPE_SINT64:
283
+ soft_double_prep:
284
+ if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
285
+ intarg_count++;
286
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS)
287
+ {
288
+ if (intarg_count % 2 != 0)
289
+ {
290
+ intarg_count++;
291
+ next_arg.u++;
292
+ }
293
+ *next_arg.ll = **p_argv.ll;
294
+ next_arg.u += 2;
295
+ }
296
+ else
297
+ {
298
+ /* whoops: abi states only certain register pairs
299
+ * can be used for passing long long int
300
+ * specifically (r3,r4), (r5,r6), (r7,r8),
301
+ * (r9,r10) and if next arg is long long but
302
+ * not correct starting register of pair then skip
303
+ * until the proper starting register
304
+ */
305
+ if (intarg_count % 2 != 0)
306
+ {
307
+ intarg_count ++;
308
+ gpr_base.u++;
309
+ }
310
+ *gpr_base.ll++ = **p_argv.ll;
311
+ }
312
+ intarg_count += 2;
313
+ break;
314
+
315
+ case FFI_TYPE_STRUCT:
316
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
317
+ do_struct:
318
+ #endif
319
+ struct_copy_size = ((*ptr)->size + 15) & ~0xF;
320
+ copy_space.c -= struct_copy_size;
321
+ memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
322
+
323
+ gprvalue = (unsigned long) copy_space.c;
324
+
325
+ FFI_ASSERT (copy_space.c > next_arg.c);
326
+ FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
327
+ goto putgpr;
328
+
329
+ case FFI_TYPE_UINT8:
330
+ gprvalue = **p_argv.uc;
331
+ goto putgpr;
332
+ case FFI_TYPE_SINT8:
333
+ gprvalue = **p_argv.sc;
334
+ goto putgpr;
335
+ case FFI_TYPE_UINT16:
336
+ gprvalue = **p_argv.us;
337
+ goto putgpr;
338
+ case FFI_TYPE_SINT16:
339
+ gprvalue = **p_argv.ss;
340
+ goto putgpr;
341
+
342
+ case FFI_TYPE_INT:
343
+ case FFI_TYPE_UINT32:
344
+ case FFI_TYPE_SINT32:
345
+ case FFI_TYPE_POINTER:
346
+ soft_float_prep:
347
+
348
+ gprvalue = **p_argv.ui;
349
+
350
+ putgpr:
351
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS)
352
+ *next_arg.u++ = gprvalue;
353
+ else
354
+ *gpr_base.u++ = gprvalue;
355
+ intarg_count++;
356
+ break;
357
+ }
358
+ }
359
+
360
+ /* Check that we didn't overrun the stack... */
361
+ FFI_ASSERT (copy_space.c >= next_arg.c);
362
+ FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
363
+ FFI_ASSERT (fpr_base.u
364
+ <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
365
+ FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
366
+ }
367
+
368
+ /* About the LINUX64 ABI. */
369
+ enum {
370
+ NUM_GPR_ARG_REGISTERS64 = 8,
371
+ NUM_FPR_ARG_REGISTERS64 = 13
372
+ };
373
+ enum { ASM_NEEDS_REGISTERS64 = 4 };
374
+
375
+ /* ffi_prep_args64 is called by the assembly routine once stack space
376
+ has been allocated for the function's arguments.
377
+
378
+ The stack layout we want looks like this:
379
+
380
+ | Ret addr from ffi_call_LINUX64 8bytes | higher addresses
381
+ |--------------------------------------------|
382
+ | CR save area 8bytes |
383
+ |--------------------------------------------|
384
+ | Previous backchain pointer 8 | stack pointer here
385
+ |--------------------------------------------|<+ <<< on entry to
386
+ | Saved r28-r31 4*8 | | ffi_call_LINUX64
387
+ |--------------------------------------------| |
388
+ | GPR registers r3-r10 8*8 | |
389
+ |--------------------------------------------| |
390
+ | FPR registers f1-f13 (optional) 13*8 | |
391
+ |--------------------------------------------| |
392
+ | Parameter save area | |
393
+ |--------------------------------------------| |
394
+ | TOC save area 8 | |
395
+ |--------------------------------------------| | stack |
396
+ | Linker doubleword 8 | | grows |
397
+ |--------------------------------------------| | down V
398
+ | Compiler doubleword 8 | |
399
+ |--------------------------------------------| | lower addresses
400
+ | Space for callee's LR 8 | |
401
+ |--------------------------------------------| |
402
+ | CR save area 8 | |
403
+ |--------------------------------------------| | stack pointer here
404
+ | Current backchain pointer 8 |-/ during
405
+ |--------------------------------------------| <<< ffi_call_LINUX64
406
+
407
+ */
408
+
409
+ void FFI_HIDDEN
410
+ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
411
+ {
412
+ const unsigned long bytes = ecif->cif->bytes;
413
+ const unsigned long flags = ecif->cif->flags;
414
+
415
+ typedef union {
416
+ char *c;
417
+ unsigned long *ul;
418
+ float *f;
419
+ double *d;
420
+ } valp;
421
+
422
+ /* 'stacktop' points at the previous backchain pointer. */
423
+ valp stacktop;
424
+
425
+ /* 'next_arg' points at the space for gpr3, and grows upwards as
426
+ we use GPR registers, then continues at rest. */
427
+ valp gpr_base;
428
+ valp gpr_end;
429
+ valp rest;
430
+ valp next_arg;
431
+
432
+ /* 'fpr_base' points at the space for fpr3, and grows upwards as
433
+ we use FPR registers. */
434
+ valp fpr_base;
435
+ int fparg_count;
436
+
437
+ int i, words;
438
+ ffi_type **ptr;
439
+ double double_tmp;
440
+ union {
441
+ void **v;
442
+ char **c;
443
+ signed char **sc;
444
+ unsigned char **uc;
445
+ signed short **ss;
446
+ unsigned short **us;
447
+ signed int **si;
448
+ unsigned int **ui;
449
+ unsigned long **ul;
450
+ float **f;
451
+ double **d;
452
+ } p_argv;
453
+ unsigned long gprvalue;
454
+
455
+ stacktop.c = (char *) stack + bytes;
456
+ gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
457
+ gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
458
+ rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
459
+ fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
460
+ fparg_count = 0;
461
+ next_arg.ul = gpr_base.ul;
462
+
463
+ /* Check that everything starts aligned properly. */
464
+ FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
465
+ FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
466
+ FFI_ASSERT ((bytes & 0xF) == 0);
467
+
468
+ /* Deal with return values that are actually pass-by-reference. */
469
+ if (flags & FLAG_RETVAL_REFERENCE)
470
+ *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
471
+
472
+ /* Now for the arguments. */
473
+ p_argv.v = ecif->avalue;
474
+ for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
475
+ i > 0;
476
+ i--, ptr++, p_argv.v++)
477
+ {
478
+ switch ((*ptr)->type)
479
+ {
480
+ case FFI_TYPE_FLOAT:
481
+ double_tmp = **p_argv.f;
482
+ *next_arg.f = (float) double_tmp;
483
+ if (++next_arg.ul == gpr_end.ul)
484
+ next_arg.ul = rest.ul;
485
+ if (fparg_count < NUM_FPR_ARG_REGISTERS64)
486
+ *fpr_base.d++ = double_tmp;
487
+ fparg_count++;
488
+ FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
489
+ break;
490
+
491
+ case FFI_TYPE_DOUBLE:
492
+ double_tmp = **p_argv.d;
493
+ *next_arg.d = double_tmp;
494
+ if (++next_arg.ul == gpr_end.ul)
495
+ next_arg.ul = rest.ul;
496
+ if (fparg_count < NUM_FPR_ARG_REGISTERS64)
497
+ *fpr_base.d++ = double_tmp;
498
+ fparg_count++;
499
+ FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
500
+ break;
501
+
502
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
503
+ case FFI_TYPE_LONGDOUBLE:
504
+ double_tmp = (*p_argv.d)[0];
505
+ *next_arg.d = double_tmp;
506
+ if (++next_arg.ul == gpr_end.ul)
507
+ next_arg.ul = rest.ul;
508
+ if (fparg_count < NUM_FPR_ARG_REGISTERS64)
509
+ *fpr_base.d++ = double_tmp;
510
+ fparg_count++;
511
+ double_tmp = (*p_argv.d)[1];
512
+ *next_arg.d = double_tmp;
513
+ if (++next_arg.ul == gpr_end.ul)
514
+ next_arg.ul = rest.ul;
515
+ if (fparg_count < NUM_FPR_ARG_REGISTERS64)
516
+ *fpr_base.d++ = double_tmp;
517
+ fparg_count++;
518
+ FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
519
+ FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
520
+ break;
521
+ #endif
522
+
523
+ case FFI_TYPE_STRUCT:
524
+ words = ((*ptr)->size + 7) / 8;
525
+ if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
526
+ {
527
+ size_t first = gpr_end.c - next_arg.c;
528
+ memcpy (next_arg.c, *p_argv.c, first);
529
+ memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
530
+ next_arg.c = rest.c + words * 8 - first;
531
+ }
532
+ else
533
+ {
534
+ char *where = next_arg.c;
535
+
536
+ /* Structures with size less than eight bytes are passed
537
+ left-padded. */
538
+ if ((*ptr)->size < 8)
539
+ where += 8 - (*ptr)->size;
540
+
541
+ memcpy (where, *p_argv.c, (*ptr)->size);
542
+ next_arg.ul += words;
543
+ if (next_arg.ul == gpr_end.ul)
544
+ next_arg.ul = rest.ul;
545
+ }
546
+ break;
547
+
548
+ case FFI_TYPE_UINT8:
549
+ gprvalue = **p_argv.uc;
550
+ goto putgpr;
551
+ case FFI_TYPE_SINT8:
552
+ gprvalue = **p_argv.sc;
553
+ goto putgpr;
554
+ case FFI_TYPE_UINT16:
555
+ gprvalue = **p_argv.us;
556
+ goto putgpr;
557
+ case FFI_TYPE_SINT16:
558
+ gprvalue = **p_argv.ss;
559
+ goto putgpr;
560
+ case FFI_TYPE_UINT32:
561
+ gprvalue = **p_argv.ui;
562
+ goto putgpr;
563
+ case FFI_TYPE_INT:
564
+ case FFI_TYPE_SINT32:
565
+ gprvalue = **p_argv.si;
566
+ goto putgpr;
567
+
568
+ case FFI_TYPE_UINT64:
569
+ case FFI_TYPE_SINT64:
570
+ case FFI_TYPE_POINTER:
571
+ gprvalue = **p_argv.ul;
572
+ putgpr:
573
+ *next_arg.ul++ = gprvalue;
574
+ if (next_arg.ul == gpr_end.ul)
575
+ next_arg.ul = rest.ul;
576
+ break;
577
+ }
578
+ }
579
+
580
+ FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
581
+ || (next_arg.ul >= gpr_base.ul
582
+ && next_arg.ul <= gpr_base.ul + 4));
583
+ }
584
+
585
+
586
+
587
+ /* Perform machine dependent cif processing */
588
+ ffi_status
589
+ ffi_prep_cif_machdep (ffi_cif *cif)
590
+ {
591
+ /* All this is for the SYSV and LINUX64 ABI. */
592
+ int i;
593
+ ffi_type **ptr;
594
+ unsigned bytes;
595
+ int fparg_count = 0, intarg_count = 0;
596
+ unsigned flags = 0;
597
+ unsigned struct_copy_size = 0;
598
+ unsigned type = cif->rtype->type;
599
+ unsigned size = cif->rtype->size;
600
+
601
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
602
+ NUM_FPR_ARG_REGISTERS = 0;
603
+
604
+ if (cif->abi != FFI_LINUX64)
605
+ {
606
+ /* All the machine-independent calculation of cif->bytes will be wrong.
607
+ Redo the calculation for SYSV. */
608
+
609
+ /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
610
+ bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
611
+
612
+ /* Space for the GPR registers. */
613
+ bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
614
+ }
615
+ else
616
+ {
617
+ /* 64-bit ABI. */
618
+
619
+ /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
620
+ regs. */
621
+ bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
622
+
623
+ /* Space for the mandatory parm save area and general registers. */
624
+ bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
625
+ }
626
+
627
+ /* Return value handling. The rules for SYSV are as follows:
628
+ - 32-bit (or less) integer values are returned in gpr3;
629
+ - Structures of size <= 4 bytes also returned in gpr3;
630
+ - 64-bit integer values and structures between 5 and 8 bytes are returned
631
+ in gpr3 and gpr4;
632
+ - Single/double FP values are returned in fpr1;
633
+ - Larger structures are allocated space and a pointer is passed as
634
+ the first argument.
635
+ - long doubles (if not equivalent to double) are returned in
636
+ fpr1,fpr2 for Linux and as for large structs for SysV.
637
+ For LINUX64:
638
+ - integer values in gpr3;
639
+ - Structures/Unions by reference;
640
+ - Single/double FP values in fpr1, long double in fpr1,fpr2.
641
+ - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
642
+ - soft-float long doubles are returned in gpr3-gpr6. */
643
+ switch (type)
644
+ {
645
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
646
+ case FFI_TYPE_LONGDOUBLE:
647
+ if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
648
+ && cif->abi != FFI_LINUX_SOFT_FLOAT)
649
+ goto byref;
650
+ flags |= FLAG_RETURNS_128BITS;
651
+ /* Fall through. */
652
+ #endif
653
+ case FFI_TYPE_DOUBLE:
654
+ flags |= FLAG_RETURNS_64BITS;
655
+ /* Fall through. */
656
+ case FFI_TYPE_FLOAT:
657
+ /* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */
658
+ if (cif->abi != FFI_LINUX_SOFT_FLOAT)
659
+ flags |= FLAG_RETURNS_FP;
660
+ break;
661
+
662
+ case FFI_TYPE_UINT64:
663
+ case FFI_TYPE_SINT64:
664
+ flags |= FLAG_RETURNS_64BITS;
665
+ break;
666
+
667
+ case FFI_TYPE_STRUCT:
668
+ if (cif->abi == FFI_SYSV)
669
+ {
670
+ /* The final SYSV ABI says that structures smaller or equal 8 bytes
671
+ are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
672
+ in memory. */
673
+
674
+ /* Treat structs with size <= 8 bytes. */
675
+ if (size <= 8)
676
+ {
677
+ flags |= FLAG_RETURNS_SMST;
678
+ /* These structs are returned in r3. We pack the type and the
679
+ precalculated shift value (needed in the sysv.S) into flags.
680
+ The same applies for the structs returned in r3/r4. */
681
+ if (size <= 4)
682
+ {
683
+ flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 1);
684
+ flags |= 8 * (4 - size) << 4;
685
+ break;
686
+ }
687
+ /* These structs are returned in r3 and r4. See above. */
688
+ if (size <= 8)
689
+ {
690
+ flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 2);
691
+ flags |= 8 * (8 - size) << 4;
692
+ break;
693
+ }
694
+ }
695
+ }
696
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
697
+ byref:
698
+ #endif
699
+ intarg_count++;
700
+ flags |= FLAG_RETVAL_REFERENCE;
701
+ /* Fall through. */
702
+ case FFI_TYPE_VOID:
703
+ flags |= FLAG_RETURNS_NOTHING;
704
+ break;
705
+
706
+ default:
707
+ /* Returns 32-bit integer, or similar. Nothing to do here. */
708
+ break;
709
+ }
710
+
711
+ if (cif->abi != FFI_LINUX64)
712
+ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
713
+ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
714
+ goes on the stack. Structures and long doubles (if not equivalent
715
+ to double) are passed as a pointer to a copy of the structure.
716
+ Stuff on the stack needs to keep proper alignment. */
717
+ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
718
+ {
719
+ switch ((*ptr)->type)
720
+ {
721
+ case FFI_TYPE_FLOAT:
722
+ /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
723
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
724
+ goto soft_float_cif;
725
+ fparg_count++;
726
+ /* floating singles are not 8-aligned on stack */
727
+ break;
728
+
729
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
730
+ case FFI_TYPE_LONGDOUBLE:
731
+ if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
732
+ goto do_struct;
733
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
734
+ {
735
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
736
+ || intarg_count < NUM_GPR_ARG_REGISTERS)
737
+ /* A long double in FFI_LINUX_SOFT_FLOAT can use only
738
+ a set of four consecutive gprs. If we have not enough,
739
+ we have to adjust the intarg_count value. */
740
+ intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
741
+ intarg_count += 4;
742
+ break;
743
+ }
744
+ else
745
+ fparg_count++;
746
+ /* Fall thru */
747
+ #endif
748
+ case FFI_TYPE_DOUBLE:
749
+ /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
750
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
751
+ goto soft_double_cif;
752
+ fparg_count++;
753
+ /* If this FP arg is going on the stack, it must be
754
+ 8-byte-aligned. */
755
+ if (fparg_count > NUM_FPR_ARG_REGISTERS
756
+ && intarg_count >= NUM_GPR_ARG_REGISTERS
757
+ && intarg_count % 2 != 0)
758
+ intarg_count++;
759
+ break;
760
+
761
+ case FFI_TYPE_UINT64:
762
+ case FFI_TYPE_SINT64:
763
+ soft_double_cif:
764
+ /* 'long long' arguments are passed as two words, but
765
+ either both words must fit in registers or both go
766
+ on the stack. If they go on the stack, they must
767
+ be 8-byte-aligned.
768
+
769
+ Also, only certain register pairs can be used for
770
+ passing long long int -- specifically (r3,r4), (r5,r6),
771
+ (r7,r8), (r9,r10).
772
+ */
773
+ if (intarg_count == NUM_GPR_ARG_REGISTERS-1
774
+ || intarg_count % 2 != 0)
775
+ intarg_count++;
776
+ intarg_count += 2;
777
+ break;
778
+
779
+ case FFI_TYPE_STRUCT:
780
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
781
+ do_struct:
782
+ #endif
783
+ /* We must allocate space for a copy of these to enforce
784
+ pass-by-value. Pad the space up to a multiple of 16
785
+ bytes (the maximum alignment required for anything under
786
+ the SYSV ABI). */
787
+ struct_copy_size += ((*ptr)->size + 15) & ~0xF;
788
+ /* Fall through (allocate space for the pointer). */
789
+
790
+ default:
791
+ soft_float_cif:
792
+ /* Everything else is passed as a 4-byte word in a GPR, either
793
+ the object itself or a pointer to it. */
794
+ intarg_count++;
795
+ break;
796
+ }
797
+ }
798
+ else
799
+ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
800
+ {
801
+ switch ((*ptr)->type)
802
+ {
803
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
804
+ case FFI_TYPE_LONGDOUBLE:
805
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
806
+ intarg_count += 4;
807
+ else
808
+ {
809
+ fparg_count += 2;
810
+ intarg_count += 2;
811
+ }
812
+ break;
813
+ #endif
814
+ case FFI_TYPE_FLOAT:
815
+ case FFI_TYPE_DOUBLE:
816
+ fparg_count++;
817
+ intarg_count++;
818
+ break;
819
+
820
+ case FFI_TYPE_STRUCT:
821
+ intarg_count += ((*ptr)->size + 7) / 8;
822
+ break;
823
+
824
+ default:
825
+ /* Everything else is passed as a 8-byte word in a GPR, either
826
+ the object itself or a pointer to it. */
827
+ intarg_count++;
828
+ break;
829
+ }
830
+ }
831
+
832
+ if (fparg_count != 0)
833
+ flags |= FLAG_FP_ARGUMENTS;
834
+ if (intarg_count > 4)
835
+ flags |= FLAG_4_GPR_ARGUMENTS;
836
+ if (struct_copy_size != 0)
837
+ flags |= FLAG_ARG_NEEDS_COPY;
838
+
839
+ if (cif->abi != FFI_LINUX64)
840
+ {
841
+ /* Space for the FPR registers, if needed. */
842
+ if (fparg_count != 0)
843
+ bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
844
+
845
+ /* Stack space. */
846
+ if (intarg_count > NUM_GPR_ARG_REGISTERS)
847
+ bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
848
+ if (fparg_count > NUM_FPR_ARG_REGISTERS)
849
+ bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
850
+ }
851
+ else
852
+ {
853
+ /* Space for the FPR registers, if needed. */
854
+ if (fparg_count != 0)
855
+ bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
856
+
857
+ /* Stack space. */
858
+ if (intarg_count > NUM_GPR_ARG_REGISTERS64)
859
+ bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
860
+ }
861
+
862
+ /* The stack space allocated needs to be a multiple of 16 bytes. */
863
+ bytes = (bytes + 15) & ~0xF;
864
+
865
+ /* Add in the space for the copied structures. */
866
+ bytes += struct_copy_size;
867
+
868
+ cif->flags = flags;
869
+ cif->bytes = bytes;
870
+
871
+ return FFI_OK;
872
+ }
873
+
874
+ extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
875
+ void (*fn)(void));
876
+ extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
877
+ unsigned long, unsigned long *,
878
+ void (*fn)(void));
879
+
880
+ void
881
+ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
882
+ {
883
+ extended_cif ecif;
884
+
885
+ ecif.cif = cif;
886
+ ecif.avalue = avalue;
887
+
888
+ /* If the return value is a struct and we don't have a return */
889
+ /* value address then we need to make one */
890
+
891
+ if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
892
+ {
893
+ ecif.rvalue = alloca(cif->rtype->size);
894
+ }
895
+ else
896
+ ecif.rvalue = rvalue;
897
+
898
+
899
+ switch (cif->abi)
900
+ {
901
+ #ifndef POWERPC64
902
+ case FFI_SYSV:
903
+ case FFI_GCC_SYSV:
904
+ case FFI_LINUX:
905
+ case FFI_LINUX_SOFT_FLOAT:
906
+ ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
907
+ break;
908
+ #else
909
+ case FFI_LINUX64:
910
+ ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
911
+ break;
912
+ #endif
913
+ default:
914
+ FFI_ASSERT (0);
915
+ break;
916
+ }
917
+ }
918
+
919
+
920
+ #ifndef POWERPC64
921
+ #define MIN_CACHE_LINE_SIZE 8
922
+
923
+ static void
924
+ flush_icache (char *wraddr, char *xaddr, int size)
925
+ {
926
+ int i;
927
+ for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
928
+ __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
929
+ : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
930
+ __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
931
+ : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
932
+ : "memory");
933
+ }
934
+ #endif
935
+
936
+ ffi_status
937
+ ffi_prep_closure_loc (ffi_closure *closure,
938
+ ffi_cif *cif,
939
+ void (*fun) (ffi_cif *, void *, void **, void *),
940
+ void *user_data,
941
+ void *codeloc)
942
+ {
943
+ #ifdef POWERPC64
944
+ void **tramp = (void **) &closure->tramp[0];
945
+
946
+ FFI_ASSERT (cif->abi == FFI_LINUX64);
947
+ /* Copy function address and TOC from ffi_closure_LINUX64. */
948
+ memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
949
+ tramp[2] = codeloc;
950
+ #else
951
+ unsigned int *tramp;
952
+
953
+ FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
954
+
955
+ tramp = (unsigned int *) &closure->tramp[0];
956
+ tramp[0] = 0x7c0802a6; /* mflr r0 */
957
+ tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
958
+ tramp[4] = 0x7d6802a6; /* mflr r11 */
959
+ tramp[5] = 0x7c0803a6; /* mtlr r0 */
960
+ tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
961
+ tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
962
+ tramp[8] = 0x7c0903a6; /* mtctr r0 */
963
+ tramp[9] = 0x4e800420; /* bctr */
964
+ *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
965
+ *(void **) &tramp[3] = codeloc; /* context */
966
+
967
+ /* Flush the icache. */
968
+ flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
969
+ #endif
970
+
971
+ closure->cif = cif;
972
+ closure->fun = fun;
973
+ closure->user_data = user_data;
974
+
975
+ return FFI_OK;
976
+ }
977
+
978
+ typedef union
979
+ {
980
+ float f;
981
+ double d;
982
+ } ffi_dblfl;
983
+
984
+ int ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
985
+ ffi_dblfl *, unsigned long *);
986
+
987
+ /* Basically the trampoline invokes ffi_closure_SYSV, and on
988
+ * entry, r11 holds the address of the closure.
989
+ * After storing the registers that could possibly contain
990
+ * parameters to be passed into the stack frame and setting
991
+ * up space for a return value, ffi_closure_SYSV invokes the
992
+ * following helper function to do most of the work
993
+ */
994
+
995
+ int
996
+ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
997
+ unsigned long *pgr, ffi_dblfl *pfr,
998
+ unsigned long *pst)
999
+ {
1000
+ /* rvalue is the pointer to space for return value in closure assembly */
1001
+ /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
1002
+ /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
1003
+ /* pst is the pointer to outgoing parameter stack in original caller */
1004
+
1005
+ void ** avalue;
1006
+ ffi_type ** arg_types;
1007
+ long i, avn;
1008
+ long nf; /* number of floating registers already used */
1009
+ long ng; /* number of general registers already used */
1010
+ ffi_cif * cif;
1011
+ double temp;
1012
+ unsigned size;
1013
+
1014
+ cif = closure->cif;
1015
+ avalue = alloca (cif->nargs * sizeof (void *));
1016
+ size = cif->rtype->size;
1017
+
1018
+ nf = 0;
1019
+ ng = 0;
1020
+
1021
+ /* Copy the caller's structure return value address so that the closure
1022
+ returns the data directly to the caller.
1023
+ For FFI_SYSV the result is passed in r3/r4 if the struct size is less
1024
+ or equal 8 bytes. */
1025
+
1026
+ if ((cif->rtype->type == FFI_TYPE_STRUCT
1027
+ && !((cif->abi == FFI_SYSV) && (size <= 8)))
1028
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1029
+ || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
1030
+ && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1031
+ #endif
1032
+ )
1033
+ {
1034
+ rvalue = (void *) *pgr;
1035
+ ng++;
1036
+ pgr++;
1037
+ }
1038
+
1039
+ i = 0;
1040
+ avn = cif->nargs;
1041
+ arg_types = cif->arg_types;
1042
+
1043
+ /* Grab the addresses of the arguments from the stack frame. */
1044
+ while (i < avn)
1045
+ {
1046
+ switch (arg_types[i]->type)
1047
+ {
1048
+ case FFI_TYPE_SINT8:
1049
+ case FFI_TYPE_UINT8:
1050
+ /* there are 8 gpr registers used to pass values */
1051
+ if (ng < 8)
1052
+ {
1053
+ avalue[i] = (char *) pgr + 3;
1054
+ ng++;
1055
+ pgr++;
1056
+ }
1057
+ else
1058
+ {
1059
+ avalue[i] = (char *) pst + 3;
1060
+ pst++;
1061
+ }
1062
+ break;
1063
+
1064
+ case FFI_TYPE_SINT16:
1065
+ case FFI_TYPE_UINT16:
1066
+ /* there are 8 gpr registers used to pass values */
1067
+ if (ng < 8)
1068
+ {
1069
+ avalue[i] = (char *) pgr + 2;
1070
+ ng++;
1071
+ pgr++;
1072
+ }
1073
+ else
1074
+ {
1075
+ avalue[i] = (char *) pst + 2;
1076
+ pst++;
1077
+ }
1078
+ break;
1079
+
1080
+ case FFI_TYPE_SINT32:
1081
+ case FFI_TYPE_UINT32:
1082
+ case FFI_TYPE_POINTER:
1083
+ soft_float_closure:
1084
+ /* there are 8 gpr registers used to pass values */
1085
+ if (ng < 8)
1086
+ {
1087
+ avalue[i] = pgr;
1088
+ ng++;
1089
+ pgr++;
1090
+ }
1091
+ else
1092
+ {
1093
+ avalue[i] = pst;
1094
+ pst++;
1095
+ }
1096
+ break;
1097
+
1098
+ case FFI_TYPE_STRUCT:
1099
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1100
+ do_struct:
1101
+ #endif
1102
+ /* Structs are passed by reference. The address will appear in a
1103
+ gpr if it is one of the first 8 arguments. */
1104
+ if (ng < 8)
1105
+ {
1106
+ avalue[i] = (void *) *pgr;
1107
+ ng++;
1108
+ pgr++;
1109
+ }
1110
+ else
1111
+ {
1112
+ avalue[i] = (void *) *pst;
1113
+ pst++;
1114
+ }
1115
+ break;
1116
+
1117
+ case FFI_TYPE_SINT64:
1118
+ case FFI_TYPE_UINT64:
1119
+ soft_double_closure:
1120
+ /* passing long long ints are complex, they must
1121
+ * be passed in suitable register pairs such as
1122
+ * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
1123
+ * and if the entire pair aren't available then the outgoing
1124
+ * parameter stack is used for both but an alignment of 8
1125
+ * must will be kept. So we must either look in pgr
1126
+ * or pst to find the correct address for this type
1127
+ * of parameter.
1128
+ */
1129
+ if (ng < 7)
1130
+ {
1131
+ if (ng & 0x01)
1132
+ {
1133
+ /* skip r4, r6, r8 as starting points */
1134
+ ng++;
1135
+ pgr++;
1136
+ }
1137
+ avalue[i] = pgr;
1138
+ ng += 2;
1139
+ pgr += 2;
1140
+ }
1141
+ else
1142
+ {
1143
+ if (((long) pst) & 4)
1144
+ pst++;
1145
+ avalue[i] = pst;
1146
+ pst += 2;
1147
+ }
1148
+ break;
1149
+
1150
+ case FFI_TYPE_FLOAT:
1151
+ /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
1152
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1153
+ goto soft_float_closure;
1154
+ /* unfortunately float values are stored as doubles
1155
+ * in the ffi_closure_SYSV code (since we don't check
1156
+ * the type in that routine).
1157
+ */
1158
+
1159
+ /* there are 8 64bit floating point registers */
1160
+
1161
+ if (nf < 8)
1162
+ {
1163
+ temp = pfr->d;
1164
+ pfr->f = (float) temp;
1165
+ avalue[i] = pfr;
1166
+ nf++;
1167
+ pfr++;
1168
+ }
1169
+ else
1170
+ {
1171
+ /* FIXME? here we are really changing the values
1172
+ * stored in the original calling routines outgoing
1173
+ * parameter stack. This is probably a really
1174
+ * naughty thing to do but...
1175
+ */
1176
+ avalue[i] = pst;
1177
+ pst += 1;
1178
+ }
1179
+ break;
1180
+
1181
+ case FFI_TYPE_DOUBLE:
1182
+ /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
1183
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1184
+ goto soft_double_closure;
1185
+ /* On the outgoing stack all values are aligned to 8 */
1186
+ /* there are 8 64bit floating point registers */
1187
+
1188
+ if (nf < 8)
1189
+ {
1190
+ avalue[i] = pfr;
1191
+ nf++;
1192
+ pfr++;
1193
+ }
1194
+ else
1195
+ {
1196
+ if (((long) pst) & 4)
1197
+ pst++;
1198
+ avalue[i] = pst;
1199
+ pst += 2;
1200
+ }
1201
+ break;
1202
+
1203
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1204
+ case FFI_TYPE_LONGDOUBLE:
1205
+ if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1206
+ goto do_struct;
1207
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1208
+ { /* Test if for the whole long double, 4 gprs are available.
1209
+ otherwise the stuff ends up on the stack. */
1210
+ if (ng < 5)
1211
+ {
1212
+ avalue[i] = pgr;
1213
+ pgr += 4;
1214
+ ng += 4;
1215
+ }
1216
+ else
1217
+ {
1218
+ avalue[i] = pst;
1219
+ pst += 4;
1220
+ }
1221
+ break;
1222
+ }
1223
+ if (nf < 7)
1224
+ {
1225
+ avalue[i] = pfr;
1226
+ pfr += 2;
1227
+ nf += 2;
1228
+ }
1229
+ else
1230
+ {
1231
+ if (((long) pst) & 4)
1232
+ pst++;
1233
+ avalue[i] = pst;
1234
+ pst += 4;
1235
+ nf = 8;
1236
+ }
1237
+ break;
1238
+ #endif
1239
+
1240
+ default:
1241
+ FFI_ASSERT (0);
1242
+ }
1243
+
1244
+ i++;
1245
+ }
1246
+
1247
+
1248
+ (closure->fun) (cif, rvalue, avalue, closure->user_data);
1249
+
1250
+ /* Tell ffi_closure_SYSV how to perform return type promotions.
1251
+ Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
1252
+ we have to tell ffi_closure_SYSV how to treat them. */
1253
+ if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
1254
+ && size <= 8)
1255
+ return FFI_SYSV_TYPE_SMALL_STRUCT + size;
1256
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1257
+ else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
1258
+ && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1259
+ return FFI_TYPE_STRUCT;
1260
+ #endif
1261
+ /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
1262
+ respectivley UINT64. */
1263
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1264
+ {
1265
+ switch (cif->rtype->type)
1266
+ {
1267
+ case FFI_TYPE_FLOAT:
1268
+ return FFI_TYPE_UINT32;
1269
+ break;
1270
+ case FFI_TYPE_DOUBLE:
1271
+ return FFI_TYPE_UINT64;
1272
+ break;
1273
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1274
+ case FFI_TYPE_LONGDOUBLE:
1275
+ return FFI_TYPE_UINT128;
1276
+ break;
1277
+ #endif
1278
+ default:
1279
+ return cif->rtype->type;
1280
+ }
1281
+ }
1282
+ else
1283
+ {
1284
+ return cif->rtype->type;
1285
+ }
1286
+ }
1287
+
1288
+ int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
1289
+ unsigned long *, ffi_dblfl *);
1290
+
1291
+ int FFI_HIDDEN
1292
+ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
1293
+ unsigned long *pst, ffi_dblfl *pfr)
1294
+ {
1295
+ /* rvalue is the pointer to space for return value in closure assembly */
1296
+ /* pst is the pointer to parameter save area
1297
+ (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
1298
+ /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
1299
+
1300
+ void **avalue;
1301
+ ffi_type **arg_types;
1302
+ long i, avn;
1303
+ ffi_cif *cif;
1304
+ ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
1305
+
1306
+ cif = closure->cif;
1307
+ avalue = alloca (cif->nargs * sizeof (void *));
1308
+
1309
+ /* Copy the caller's structure return value address so that the closure
1310
+ returns the data directly to the caller. */
1311
+ if (cif->rtype->type == FFI_TYPE_STRUCT)
1312
+ {
1313
+ rvalue = (void *) *pst;
1314
+ pst++;
1315
+ }
1316
+
1317
+ i = 0;
1318
+ avn = cif->nargs;
1319
+ arg_types = cif->arg_types;
1320
+
1321
+ /* Grab the addresses of the arguments from the stack frame. */
1322
+ while (i < avn)
1323
+ {
1324
+ switch (arg_types[i]->type)
1325
+ {
1326
+ case FFI_TYPE_SINT8:
1327
+ case FFI_TYPE_UINT8:
1328
+ avalue[i] = (char *) pst + 7;
1329
+ pst++;
1330
+ break;
1331
+
1332
+ case FFI_TYPE_SINT16:
1333
+ case FFI_TYPE_UINT16:
1334
+ avalue[i] = (char *) pst + 6;
1335
+ pst++;
1336
+ break;
1337
+
1338
+ case FFI_TYPE_SINT32:
1339
+ case FFI_TYPE_UINT32:
1340
+ avalue[i] = (char *) pst + 4;
1341
+ pst++;
1342
+ break;
1343
+
1344
+ case FFI_TYPE_SINT64:
1345
+ case FFI_TYPE_UINT64:
1346
+ case FFI_TYPE_POINTER:
1347
+ avalue[i] = pst;
1348
+ pst++;
1349
+ break;
1350
+
1351
+ case FFI_TYPE_STRUCT:
1352
+ /* Structures with size less than eight bytes are passed
1353
+ left-padded. */
1354
+ if (arg_types[i]->size < 8)
1355
+ avalue[i] = (char *) pst + 8 - arg_types[i]->size;
1356
+ else
1357
+ avalue[i] = pst;
1358
+ pst += (arg_types[i]->size + 7) / 8;
1359
+ break;
1360
+
1361
+ case FFI_TYPE_FLOAT:
1362
+ /* unfortunately float values are stored as doubles
1363
+ * in the ffi_closure_LINUX64 code (since we don't check
1364
+ * the type in that routine).
1365
+ */
1366
+
1367
+ /* there are 13 64bit floating point registers */
1368
+
1369
+ if (pfr < end_pfr)
1370
+ {
1371
+ double temp = pfr->d;
1372
+ pfr->f = (float) temp;
1373
+ avalue[i] = pfr;
1374
+ pfr++;
1375
+ }
1376
+ else
1377
+ avalue[i] = pst;
1378
+ pst++;
1379
+ break;
1380
+
1381
+ case FFI_TYPE_DOUBLE:
1382
+ /* On the outgoing stack all values are aligned to 8 */
1383
+ /* there are 13 64bit floating point registers */
1384
+
1385
+ if (pfr < end_pfr)
1386
+ {
1387
+ avalue[i] = pfr;
1388
+ pfr++;
1389
+ }
1390
+ else
1391
+ avalue[i] = pst;
1392
+ pst++;
1393
+ break;
1394
+
1395
+ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1396
+ case FFI_TYPE_LONGDOUBLE:
1397
+ if (pfr + 1 < end_pfr)
1398
+ {
1399
+ avalue[i] = pfr;
1400
+ pfr += 2;
1401
+ }
1402
+ else
1403
+ {
1404
+ if (pfr < end_pfr)
1405
+ {
1406
+ /* Passed partly in f13 and partly on the stack.
1407
+ Move it all to the stack. */
1408
+ *pst = *(unsigned long *) pfr;
1409
+ pfr++;
1410
+ }
1411
+ avalue[i] = pst;
1412
+ }
1413
+ pst += 2;
1414
+ break;
1415
+ #endif
1416
+
1417
+ default:
1418
+ FFI_ASSERT (0);
1419
+ }
1420
+
1421
+ i++;
1422
+ }
1423
+
1424
+
1425
+ (closure->fun) (cif, rvalue, avalue, closure->user_data);
1426
+
1427
+ /* Tell ffi_closure_LINUX64 how to perform return type promotions. */
1428
+ return cif->rtype->type;
1429
+ }