]>
git.saurik.com Git - cycript.git/blob - sig/ffi_type.cpp
1 /* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "sig/ffi_type.hpp"
25 #include "sig/types.hpp"
27 #if FFI_LONG_LONG_MAX == 9223372036854775807LL
28 #define ffi_type_slonglong ffi_type_sint64
29 #define ffi_type_ulonglong ffi_type_uint64
31 #error need to configure for long long
37 ffi_type
*Primitive
<bool>::GetFFI(CYPool
&pool
) const {
38 return &ffi_type_uchar
;
42 ffi_type
*Primitive
<char>::GetFFI(CYPool
&pool
) const {
43 return &ffi_type_schar
;
47 ffi_type
*Primitive
<float>::GetFFI(CYPool
&pool
) const {
48 return &ffi_type_float
;
52 ffi_type
*Primitive
<long double>::GetFFI(CYPool
&pool
) const {
53 return &ffi_type_longdouble
;
57 ffi_type
*Primitive
<double>::GetFFI(CYPool
&pool
) const {
58 return &ffi_type_double
;
62 ffi_type
*Primitive
<signed char>::GetFFI(CYPool
&pool
) const {
63 return &ffi_type_schar
;
67 ffi_type
*Primitive
<signed int>::GetFFI(CYPool
&pool
) const {
68 return &ffi_type_sint
;
71 #ifdef __SIZEOF_INT128__
73 ffi_type
*Primitive
<signed __int128
>::GetFFI(CYPool
&pool
) const {
79 ffi_type
*Primitive
<signed long int>::GetFFI(CYPool
&pool
) const {
80 return &ffi_type_slong
;
84 ffi_type
*Primitive
<signed long long int>::GetFFI(CYPool
&pool
) const {
85 return &ffi_type_slonglong
;
89 ffi_type
*Primitive
<signed short int>::GetFFI(CYPool
&pool
) const {
90 return &ffi_type_sshort
;
94 ffi_type
*Primitive
<unsigned char>::GetFFI(CYPool
&pool
) const {
95 return &ffi_type_uchar
;
99 ffi_type
*Primitive
<unsigned int>::GetFFI(CYPool
&pool
) const {
100 return &ffi_type_uint
;
103 #ifdef __SIZEOF_INT128__
105 ffi_type
*Primitive
<unsigned __int128
>::GetFFI(CYPool
&pool
) const {
111 ffi_type
*Primitive
<unsigned long int>::GetFFI(CYPool
&pool
) const {
112 return &ffi_type_ulong
;
116 ffi_type
*Primitive
<unsigned long long int>::GetFFI(CYPool
&pool
) const {
117 return &ffi_type_ulonglong
;
121 ffi_type
*Primitive
<unsigned short int>::GetFFI(CYPool
&pool
) const {
122 return &ffi_type_ushort
;
125 ffi_type
*Void::GetFFI(CYPool
&pool
) const {
126 return &ffi_type_void
;
129 ffi_type
*Unknown::GetFFI(CYPool
&pool
) const {
133 ffi_type
*String::GetFFI(CYPool
&pool
) const {
134 return &ffi_type_pointer
;
138 ffi_type
*Meta::GetFFI(CYPool
&pool
) const {
139 return &ffi_type_pointer
;
142 ffi_type
*Selector::GetFFI(CYPool
&pool
) const {
143 return &ffi_type_pointer
;
147 ffi_type
*Bits::GetFFI(CYPool
&pool
) const {
148 /* XXX: we can totally make this work */
152 ffi_type
*Pointer::GetFFI(CYPool
&pool
) const {
153 return &ffi_type_pointer
;
156 ffi_type
*Array::GetFFI(CYPool
&pool
) const {
157 // XXX: this is really lame
158 ffi_type
*ffi(new(pool
) ffi_type());
161 ffi
->type
= FFI_TYPE_STRUCT
;
163 ffi_type
*element(type
.GetFFI(pool
));
165 ffi
->elements
= new(pool
) ffi_type
*[size
+ 1];
166 for (size_t i(0); i
!= size
; ++i
)
167 ffi
->elements
[i
] = element
;
168 ffi
->elements
[size
] = NULL
;
174 ffi_type
*Object::GetFFI(CYPool
&pool
) const {
175 return &ffi_type_pointer
;
179 ffi_type
*Enum::GetFFI(CYPool
&pool
) const {
180 return type
.GetFFI(pool
);
183 ffi_type
*Aggregate::GetFFI(CYPool
&pool
) const {
185 _assert(signature
.count
!= _not(size_t));
187 ffi_type
*ffi(new(pool
) ffi_type());
190 ffi
->type
= FFI_TYPE_STRUCT
;
192 if (signature
.count
== 0) {
193 // https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01286.html
194 ffi
->elements
= new(pool
) ffi_type
*[2];
195 ffi
->elements
[0] = &ffi_type_void
;
196 ffi
->elements
[1] = NULL
;
198 ffi
->elements
= new(pool
) ffi_type
*[signature
.count
+ 1];
199 for (size_t index(0); index
!= signature
.count
; ++index
)
200 ffi
->elements
[index
] = signature
.elements
[index
].type
->GetFFI(pool
);
201 ffi
->elements
[signature
.count
] = NULL
;
207 ffi_type
*Function::GetFFI(CYPool
&pool
) const {
212 ffi_type
*Block::GetFFI(CYPool
&pool
) const {
213 return &ffi_type_pointer
;
217 void sig_ffi_cif(CYPool
&pool
, size_t variadic
, const Signature
&signature
, ffi_cif
*cif
) {
218 _assert(signature
.count
!= 0);
219 size_t count(signature
.count
- 1);
220 ffi_type
*type(signature
.elements
[0].type
->GetFFI(pool
));
222 ffi_type
**types(new(pool
) ffi_type
*[count
]);
223 for (size_t index(0); index
!= count
; ++index
)
224 types
[index
] = signature
.elements
[index
+ 1].type
->GetFFI(pool
);
227 #ifdef HAVE_FFI_PREP_CIF_VAR
230 status
= ffi_prep_cif(cif
, FFI_DEFAULT_ABI
, count
, type
, types
);
231 #ifdef HAVE_FFI_PREP_CIF_VAR
233 status
= ffi_prep_cif_var(cif
, FFI_DEFAULT_ABI
, variadic
- 1, count
, type
, types
);
235 _assert(status
== FFI_OK
);