]>
git.saurik.com Git - cycript.git/blob - sig/ffi_type.cpp
e0c4d0f900bd41e73a873563c266ac02cb98540c
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
<double>::GetFFI(CYPool
&pool
) const {
53 return &ffi_type_double
;
57 ffi_type
*Primitive
<signed char>::GetFFI(CYPool
&pool
) const {
58 return &ffi_type_schar
;
62 ffi_type
*Primitive
<signed int>::GetFFI(CYPool
&pool
) const {
63 return &ffi_type_sint
;
66 #ifdef __SIZEOF_INT128__
68 ffi_type
*Primitive
<signed __int128
>::GetFFI(CYPool
&pool
) const {
74 ffi_type
*Primitive
<signed long int>::GetFFI(CYPool
&pool
) const {
75 return &ffi_type_slong
;
79 ffi_type
*Primitive
<signed long long int>::GetFFI(CYPool
&pool
) const {
80 return &ffi_type_slonglong
;
84 ffi_type
*Primitive
<signed short int>::GetFFI(CYPool
&pool
) const {
85 return &ffi_type_sshort
;
89 ffi_type
*Primitive
<unsigned char>::GetFFI(CYPool
&pool
) const {
90 return &ffi_type_uchar
;
94 ffi_type
*Primitive
<unsigned int>::GetFFI(CYPool
&pool
) const {
95 return &ffi_type_uint
;
98 #ifdef __SIZEOF_INT128__
100 ffi_type
*Primitive
<unsigned __int128
>::GetFFI(CYPool
&pool
) const {
106 ffi_type
*Primitive
<unsigned long int>::GetFFI(CYPool
&pool
) const {
107 return &ffi_type_ulong
;
111 ffi_type
*Primitive
<unsigned long long int>::GetFFI(CYPool
&pool
) const {
112 return &ffi_type_ulonglong
;
116 ffi_type
*Primitive
<unsigned short int>::GetFFI(CYPool
&pool
) const {
117 return &ffi_type_ushort
;
120 ffi_type
*Void::GetFFI(CYPool
&pool
) const {
121 return &ffi_type_void
;
124 ffi_type
*Unknown::GetFFI(CYPool
&pool
) const {
128 ffi_type
*String::GetFFI(CYPool
&pool
) const {
129 return &ffi_type_pointer
;
133 ffi_type
*Meta::GetFFI(CYPool
&pool
) const {
134 return &ffi_type_pointer
;
137 ffi_type
*Selector::GetFFI(CYPool
&pool
) const {
138 return &ffi_type_pointer
;
142 ffi_type
*Bits::GetFFI(CYPool
&pool
) const {
143 /* XXX: we can totally make this work */
147 ffi_type
*Pointer::GetFFI(CYPool
&pool
) const {
148 return &ffi_type_pointer
;
151 ffi_type
*Array::GetFFI(CYPool
&pool
) const {
152 // XXX: this is really lame
153 ffi_type
*ffi(new(pool
) ffi_type());
156 ffi
->type
= FFI_TYPE_STRUCT
;
158 ffi_type
*element(type
.GetFFI(pool
));
160 ffi
->elements
= new(pool
) ffi_type
*[size
+ 1];
161 for (size_t i(0); i
!= size
; ++i
)
162 ffi
->elements
[i
] = element
;
163 ffi
->elements
[size
] = NULL
;
169 ffi_type
*Object::GetFFI(CYPool
&pool
) const {
170 return &ffi_type_pointer
;
174 ffi_type
*Enum::GetFFI(CYPool
&pool
) const {
175 return type
.GetFFI(pool
);
178 ffi_type
*Aggregate::GetFFI(CYPool
&pool
) const {
180 _assert(signature
.count
!= _not(size_t));
182 ffi_type
*ffi(new(pool
) ffi_type());
185 ffi
->type
= FFI_TYPE_STRUCT
;
187 if (signature
.count
== 0) {
188 // https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01286.html
189 ffi
->elements
= new(pool
) ffi_type
*[2];
190 ffi
->elements
[0] = &ffi_type_void
;
191 ffi
->elements
[1] = NULL
;
193 ffi
->elements
= new(pool
) ffi_type
*[signature
.count
+ 1];
194 for (size_t index(0); index
!= signature
.count
; ++index
)
195 ffi
->elements
[index
] = signature
.elements
[index
].type
->GetFFI(pool
);
196 ffi
->elements
[signature
.count
] = NULL
;
202 ffi_type
*Function::GetFFI(CYPool
&pool
) const {
207 ffi_type
*Block::GetFFI(CYPool
&pool
) const {
208 return &ffi_type_pointer
;
212 void sig_ffi_cif(CYPool
&pool
, size_t variadic
, const Signature
&signature
, ffi_cif
*cif
) {
213 _assert(signature
.count
!= 0);
214 size_t count(signature
.count
- 1);
215 ffi_type
*type(signature
.elements
[0].type
->GetFFI(pool
));
217 ffi_type
**types(new(pool
) ffi_type
*[count
]);
218 for (size_t index(0); index
!= count
; ++index
)
219 types
[index
] = signature
.elements
[index
+ 1].type
->GetFFI(pool
);
222 #ifdef HAVE_FFI_PREP_CIF_VAR
225 status
= ffi_prep_cif(cif
, FFI_DEFAULT_ABI
, count
, type
, types
);
226 #ifdef HAVE_FFI_PREP_CIF_VAR
228 status
= ffi_prep_cif_var(cif
, FFI_DEFAULT_ABI
, variadic
- 1, count
, type
, types
);
230 _assert(status
== FFI_OK
);