]> git.saurik.com Git - cycript.git/blob - sig/ffi_type.cpp
CYUTF8String cannot have a negative size, even -1.
[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<long double>::GetFFI(CYPool &pool) const {
53 return &ffi_type_longdouble;
54 }
55
56 template <>
57 ffi_type *Primitive<double>::GetFFI(CYPool &pool) const {
58 return &ffi_type_double;
59 }
60
61 template <>
62 ffi_type *Primitive<signed char>::GetFFI(CYPool &pool) const {
63 return &ffi_type_schar;
64 }
65
66 template <>
67 ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
68 return &ffi_type_sint;
69 }
70
71 #ifdef __SIZEOF_INT128__
72 template <>
73 ffi_type *Primitive<signed __int128>::GetFFI(CYPool &pool) const {
74 _assert(false);
75 }
76 #endif
77
78 template <>
79 ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
80 return &ffi_type_slong;
81 }
82
83 template <>
84 ffi_type *Primitive<signed long long int>::GetFFI(CYPool &pool) const {
85 return &ffi_type_slonglong;
86 }
87
88 template <>
89 ffi_type *Primitive<signed short int>::GetFFI(CYPool &pool) const {
90 return &ffi_type_sshort;
91 }
92
93 template <>
94 ffi_type *Primitive<unsigned char>::GetFFI(CYPool &pool) const {
95 return &ffi_type_uchar;
96 }
97
98 template <>
99 ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
100 return &ffi_type_uint;
101 }
102
103 #ifdef __SIZEOF_INT128__
104 template <>
105 ffi_type *Primitive<unsigned __int128>::GetFFI(CYPool &pool) const {
106 _assert(false);
107 }
108 #endif
109
110 template <>
111 ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
112 return &ffi_type_ulong;
113 }
114
115 template <>
116 ffi_type *Primitive<unsigned long long int>::GetFFI(CYPool &pool) const {
117 return &ffi_type_ulonglong;
118 }
119
120 template <>
121 ffi_type *Primitive<unsigned short int>::GetFFI(CYPool &pool) const {
122 return &ffi_type_ushort;
123 }
124
125 ffi_type *Void::GetFFI(CYPool &pool) const {
126 return &ffi_type_void;
127 }
128
129 ffi_type *Unknown::GetFFI(CYPool &pool) const {
130 _assert(false);
131 }
132
133 ffi_type *String::GetFFI(CYPool &pool) const {
134 return &ffi_type_pointer;
135 }
136
137 #ifdef CY_OBJECTIVEC
138 ffi_type *Meta::GetFFI(CYPool &pool) const {
139 return &ffi_type_pointer;
140 }
141
142 ffi_type *Selector::GetFFI(CYPool &pool) const {
143 return &ffi_type_pointer;
144 }
145 #endif
146
147 ffi_type *Bits::GetFFI(CYPool &pool) const {
148 /* XXX: we can totally make this work */
149 _assert(false);
150 }
151
152 ffi_type *Pointer::GetFFI(CYPool &pool) const {
153 return &ffi_type_pointer;
154 }
155
156 ffi_type *Array::GetFFI(CYPool &pool) const {
157 // XXX: this is really lame
158 ffi_type *ffi(new(pool) ffi_type());
159 ffi->size = 0;
160 ffi->alignment = 0;
161 ffi->type = FFI_TYPE_STRUCT;
162
163 ffi_type *element(type.GetFFI(pool));
164
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;
169
170 return ffi;
171 }
172
173 #ifdef CY_OBJECTIVEC
174 ffi_type *Object::GetFFI(CYPool &pool) const {
175 return &ffi_type_pointer;
176 }
177 #endif
178
179 ffi_type *Enum::GetFFI(CYPool &pool) const {
180 return type.GetFFI(pool);
181 }
182
183 ffi_type *Aggregate::GetFFI(CYPool &pool) const {
184 _assert(!overlap);
185 _assert(signature.count != _not(size_t));
186
187 ffi_type *ffi(new(pool) ffi_type());
188 ffi->size = 0;
189 ffi->alignment = 0;
190 ffi->type = FFI_TYPE_STRUCT;
191
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;
197 } else {
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;
202 }
203
204 return ffi;
205 }
206
207 ffi_type *Function::GetFFI(CYPool &pool) const {
208 _assert(false);
209 }
210
211 #ifdef CY_OBJECTIVEC
212 ffi_type *Block::GetFFI(CYPool &pool) const {
213 return &ffi_type_pointer;
214 }
215 #endif
216
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));
221
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);
225
226 ffi_status status;
227 #ifdef HAVE_FFI_PREP_CIF_VAR
228 if (variadic == 0)
229 #endif
230 status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, type, types);
231 #ifdef HAVE_FFI_PREP_CIF_VAR
232 else
233 status = ffi_prep_cif_var(cif, FFI_DEFAULT_ABI, variadic - 1, count, type, types);
234 #endif
235 _assert(status == FFI_OK);
236 }
237
238 }