]>
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 #define ffi_type_slonglong ffi_type_sint64
28 #define ffi_type_ulonglong ffi_type_uint64
33 ffi_type
*Primitive
<bool>::GetFFI(CYPool
&pool
) const {
34 return &ffi_type_uchar
;
38 ffi_type
*Primitive
<char>::GetFFI(CYPool
&pool
) const {
39 return &ffi_type_schar
;
43 ffi_type
*Primitive
<float>::GetFFI(CYPool
&pool
) const {
44 return &ffi_type_float
;
48 ffi_type
*Primitive
<double>::GetFFI(CYPool
&pool
) const {
49 return &ffi_type_double
;
53 ffi_type
*Primitive
<signed char>::GetFFI(CYPool
&pool
) const {
54 return &ffi_type_schar
;
58 ffi_type
*Primitive
<signed int>::GetFFI(CYPool
&pool
) const {
59 return &ffi_type_sint
;
63 ffi_type
*Primitive
<signed long int>::GetFFI(CYPool
&pool
) const {
64 return &ffi_type_slong
;
68 ffi_type
*Primitive
<signed long long int>::GetFFI(CYPool
&pool
) const {
69 return &ffi_type_slonglong
;
73 ffi_type
*Primitive
<signed short int>::GetFFI(CYPool
&pool
) const {
74 return &ffi_type_sshort
;
78 ffi_type
*Primitive
<unsigned char>::GetFFI(CYPool
&pool
) const {
79 return &ffi_type_uchar
;
83 ffi_type
*Primitive
<unsigned int>::GetFFI(CYPool
&pool
) const {
84 return &ffi_type_uint
;
88 ffi_type
*Primitive
<unsigned long int>::GetFFI(CYPool
&pool
) const {
89 return &ffi_type_ulong
;
93 ffi_type
*Primitive
<unsigned long long int>::GetFFI(CYPool
&pool
) const {
94 return &ffi_type_ulonglong
;
98 ffi_type
*Primitive
<unsigned short int>::GetFFI(CYPool
&pool
) const {
99 return &ffi_type_ushort
;
102 ffi_type
*Void::GetFFI(CYPool
&pool
) const {
103 return &ffi_type_void
;
106 ffi_type
*Unknown::GetFFI(CYPool
&pool
) const {
110 ffi_type
*String::GetFFI(CYPool
&pool
) const {
111 return &ffi_type_pointer
;
115 ffi_type
*Meta::GetFFI(CYPool
&pool
) const {
116 return &ffi_type_pointer
;
119 ffi_type
*Selector::GetFFI(CYPool
&pool
) const {
120 return &ffi_type_pointer
;
124 ffi_type
*Bits::GetFFI(CYPool
&pool
) const {
125 /* XXX: we can totally make this work */
129 ffi_type
*Pointer::GetFFI(CYPool
&pool
) const {
130 return &ffi_type_pointer
;
133 ffi_type
*Array::GetFFI(CYPool
&pool
) const {
134 // XXX: this is really lame
135 ffi_type
*ffi(new(pool
) ffi_type());
138 ffi
->type
= FFI_TYPE_STRUCT
;
140 ffi_type
*element(type
.GetFFI(pool
));
142 ffi
->elements
= new(pool
) ffi_type
*[size
+ 1];
143 for (size_t i(0); i
!= size
; ++i
)
144 ffi
->elements
[i
] = element
;
145 ffi
->elements
[size
] = NULL
;
151 ffi_type
*Object::GetFFI(CYPool
&pool
) const {
152 return &ffi_type_pointer
;
156 ffi_type
*Aggregate::GetFFI(CYPool
&pool
) const {
157 // XXX: we can totally make overlap work
160 ffi_type
*ffi(new(pool
) ffi_type());
163 ffi
->type
= FFI_TYPE_STRUCT
;
165 if (signature
.count
== 0) {
166 // https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01286.html
167 ffi
->elements
= new(pool
) ffi_type
*[2];
168 ffi
->elements
[0] = &ffi_type_void
;
169 ffi
->elements
[1] = NULL
;
171 ffi
->elements
= new(pool
) ffi_type
*[signature
.count
+ 1];
172 for (size_t index(0); index
!= signature
.count
; ++index
)
173 ffi
->elements
[index
] = signature
.elements
[index
].type
->GetFFI(pool
);
174 ffi
->elements
[signature
.count
] = NULL
;
180 ffi_type
*Function::GetFFI(CYPool
&pool
) const {
185 ffi_type
*Block::GetFFI(CYPool
&pool
) const {
186 return &ffi_type_pointer
;
190 void sig_ffi_cif(CYPool
&pool
, size_t variadic
, const Signature
&signature
, ffi_cif
*cif
) {
191 _assert(signature
.count
!= 0);
192 size_t count(signature
.count
- 1);
193 ffi_type
*type(signature
.elements
[0].type
->GetFFI(pool
));
195 ffi_type
**types(new(pool
) ffi_type
*[count
]);
196 for (size_t index(0); index
!= count
; ++index
)
197 types
[index
] = signature
.elements
[index
+ 1].type
->GetFFI(pool
);
200 #ifdef HAVE_FFI_PREP_CIF_VAR
203 status
= ffi_prep_cif(cif
, FFI_DEFAULT_ABI
, count
, type
, types
);
204 #ifdef HAVE_FFI_PREP_CIF_VAR
206 status
= ffi_prep_cif_var(cif
, FFI_DEFAULT_ABI
, variadic
- 1, count
, type
, types
);
208 _assert(status
== FFI_OK
);