]> git.saurik.com Git - cycript.git/blob - sig/ffi_type.cpp
e0c4d0f900bd41e73a873563c266ac02cb98540c
[cycript.git] / sig / ffi_type.cpp
1 /* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
3 */
4
5 /* GNU Affero General Public License, Version 3 {{{ */
6 /*
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.
11
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.
16
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/>.
19 **/
20 /* }}} */
21
22 #include "Error.hpp"
23
24 #include "sig/ffi_type.hpp"
25 #include "sig/types.hpp"
26
27 #if FFI_LONG_LONG_MAX == 9223372036854775807LL
28 #define ffi_type_slonglong ffi_type_sint64
29 #define ffi_type_ulonglong ffi_type_uint64
30 #else
31 #error need to configure for long long
32 #endif
33
34 namespace sig {
35
36 template <>
37 ffi_type *Primitive<bool>::GetFFI(CYPool &pool) const {
38 return &ffi_type_uchar;
39 }
40
41 template <>
42 ffi_type *Primitive<char>::GetFFI(CYPool &pool) const {
43 return &ffi_type_schar;
44 }
45
46 template <>
47 ffi_type *Primitive<float>::GetFFI(CYPool &pool) const {
48 return &ffi_type_float;
49 }
50
51 template <>
52 ffi_type *Primitive<double>::GetFFI(CYPool &pool) const {
53 return &ffi_type_double;
54 }
55
56 template <>
57 ffi_type *Primitive<signed char>::GetFFI(CYPool &pool) const {
58 return &ffi_type_schar;
59 }
60
61 template <>
62 ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
63 return &ffi_type_sint;
64 }
65
66 #ifdef __SIZEOF_INT128__
67 template <>
68 ffi_type *Primitive<signed __int128>::GetFFI(CYPool &pool) const {
69 _assert(false);
70 }
71 #endif
72
73 template <>
74 ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
75 return &ffi_type_slong;
76 }
77
78 template <>
79 ffi_type *Primitive<signed long long int>::GetFFI(CYPool &pool) const {
80 return &ffi_type_slonglong;
81 }
82
83 template <>
84 ffi_type *Primitive<signed short int>::GetFFI(CYPool &pool) const {
85 return &ffi_type_sshort;
86 }
87
88 template <>
89 ffi_type *Primitive<unsigned char>::GetFFI(CYPool &pool) const {
90 return &ffi_type_uchar;
91 }
92
93 template <>
94 ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
95 return &ffi_type_uint;
96 }
97
98 #ifdef __SIZEOF_INT128__
99 template <>
100 ffi_type *Primitive<unsigned __int128>::GetFFI(CYPool &pool) const {
101 _assert(false);
102 }
103 #endif
104
105 template <>
106 ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
107 return &ffi_type_ulong;
108 }
109
110 template <>
111 ffi_type *Primitive<unsigned long long int>::GetFFI(CYPool &pool) const {
112 return &ffi_type_ulonglong;
113 }
114
115 template <>
116 ffi_type *Primitive<unsigned short int>::GetFFI(CYPool &pool) const {
117 return &ffi_type_ushort;
118 }
119
120 ffi_type *Void::GetFFI(CYPool &pool) const {
121 return &ffi_type_void;
122 }
123
124 ffi_type *Unknown::GetFFI(CYPool &pool) const {
125 _assert(false);
126 }
127
128 ffi_type *String::GetFFI(CYPool &pool) const {
129 return &ffi_type_pointer;
130 }
131
132 #ifdef CY_OBJECTIVEC
133 ffi_type *Meta::GetFFI(CYPool &pool) const {
134 return &ffi_type_pointer;
135 }
136
137 ffi_type *Selector::GetFFI(CYPool &pool) const {
138 return &ffi_type_pointer;
139 }
140 #endif
141
142 ffi_type *Bits::GetFFI(CYPool &pool) const {
143 /* XXX: we can totally make this work */
144 _assert(false);
145 }
146
147 ffi_type *Pointer::GetFFI(CYPool &pool) const {
148 return &ffi_type_pointer;
149 }
150
151 ffi_type *Array::GetFFI(CYPool &pool) const {
152 // XXX: this is really lame
153 ffi_type *ffi(new(pool) ffi_type());
154 ffi->size = 0;
155 ffi->alignment = 0;
156 ffi->type = FFI_TYPE_STRUCT;
157
158 ffi_type *element(type.GetFFI(pool));
159
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;
164
165 return ffi;
166 }
167
168 #ifdef CY_OBJECTIVEC
169 ffi_type *Object::GetFFI(CYPool &pool) const {
170 return &ffi_type_pointer;
171 }
172 #endif
173
174 ffi_type *Enum::GetFFI(CYPool &pool) const {
175 return type.GetFFI(pool);
176 }
177
178 ffi_type *Aggregate::GetFFI(CYPool &pool) const {
179 _assert(!overlap);
180 _assert(signature.count != _not(size_t));
181
182 ffi_type *ffi(new(pool) ffi_type());
183 ffi->size = 0;
184 ffi->alignment = 0;
185 ffi->type = FFI_TYPE_STRUCT;
186
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;
192 } else {
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;
197 }
198
199 return ffi;
200 }
201
202 ffi_type *Function::GetFFI(CYPool &pool) const {
203 _assert(false);
204 }
205
206 #ifdef CY_OBJECTIVEC
207 ffi_type *Block::GetFFI(CYPool &pool) const {
208 return &ffi_type_pointer;
209 }
210 #endif
211
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));
216
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);
220
221 ffi_status status;
222 #ifdef HAVE_FFI_PREP_CIF_VAR
223 if (variadic == 0)
224 #endif
225 status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, type, types);
226 #ifdef HAVE_FFI_PREP_CIF_VAR
227 else
228 status = ffi_prep_cif_var(cif, FFI_DEFAULT_ABI, variadic - 1, count, type, types);
229 #endif
230 _assert(status == FFI_OK);
231 }
232
233 }