]> git.saurik.com Git - cycript.git/blame_incremental - sig/ffi_type.cpp
Hold JavaRef<jstring> throughout CYJavaUTF8String.
[cycript.git] / sig / ffi_type.cpp
... / ...
CommitLineData
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
34namespace sig {
35
36template <>
37ffi_type *Primitive<bool>::GetFFI(CYPool &pool) const {
38 return &ffi_type_uchar;
39}
40
41template <>
42ffi_type *Primitive<char>::GetFFI(CYPool &pool) const {
43 return &ffi_type_schar;
44}
45
46template <>
47ffi_type *Primitive<float>::GetFFI(CYPool &pool) const {
48 return &ffi_type_float;
49}
50
51template <>
52ffi_type *Primitive<long double>::GetFFI(CYPool &pool) const {
53 return &ffi_type_longdouble;
54}
55
56template <>
57ffi_type *Primitive<double>::GetFFI(CYPool &pool) const {
58 return &ffi_type_double;
59}
60
61template <>
62ffi_type *Primitive<signed char>::GetFFI(CYPool &pool) const {
63 return &ffi_type_schar;
64}
65
66template <>
67ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
68 return &ffi_type_sint;
69}
70
71#ifdef __SIZEOF_INT128__
72template <>
73ffi_type *Primitive<signed __int128>::GetFFI(CYPool &pool) const {
74 _assert(false);
75}
76#endif
77
78template <>
79ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
80 return &ffi_type_slong;
81}
82
83template <>
84ffi_type *Primitive<signed long long int>::GetFFI(CYPool &pool) const {
85 return &ffi_type_slonglong;
86}
87
88template <>
89ffi_type *Primitive<signed short int>::GetFFI(CYPool &pool) const {
90 return &ffi_type_sshort;
91}
92
93template <>
94ffi_type *Primitive<unsigned char>::GetFFI(CYPool &pool) const {
95 return &ffi_type_uchar;
96}
97
98template <>
99ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
100 return &ffi_type_uint;
101}
102
103#ifdef __SIZEOF_INT128__
104template <>
105ffi_type *Primitive<unsigned __int128>::GetFFI(CYPool &pool) const {
106 _assert(false);
107}
108#endif
109
110template <>
111ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
112 return &ffi_type_ulong;
113}
114
115template <>
116ffi_type *Primitive<unsigned long long int>::GetFFI(CYPool &pool) const {
117 return &ffi_type_ulonglong;
118}
119
120template <>
121ffi_type *Primitive<unsigned short int>::GetFFI(CYPool &pool) const {
122 return &ffi_type_ushort;
123}
124
125ffi_type *Void::GetFFI(CYPool &pool) const {
126 return &ffi_type_void;
127}
128
129ffi_type *Unknown::GetFFI(CYPool &pool) const {
130 _assert(false);
131}
132
133ffi_type *String::GetFFI(CYPool &pool) const {
134 return &ffi_type_pointer;
135}
136
137#ifdef CY_OBJECTIVEC
138ffi_type *Meta::GetFFI(CYPool &pool) const {
139 return &ffi_type_pointer;
140}
141
142ffi_type *Selector::GetFFI(CYPool &pool) const {
143 return &ffi_type_pointer;
144}
145#endif
146
147ffi_type *Bits::GetFFI(CYPool &pool) const {
148 /* XXX: we can totally make this work */
149 _assert(false);
150}
151
152ffi_type *Pointer::GetFFI(CYPool &pool) const {
153 return &ffi_type_pointer;
154}
155
156ffi_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
174ffi_type *Object::GetFFI(CYPool &pool) const {
175 return &ffi_type_pointer;
176}
177#endif
178
179ffi_type *Enum::GetFFI(CYPool &pool) const {
180 return type.GetFFI(pool);
181}
182
183ffi_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
207ffi_type *Function::GetFFI(CYPool &pool) const {
208 _assert(false);
209}
210
211#ifdef CY_OBJECTIVEC
212ffi_type *Block::GetFFI(CYPool &pool) const {
213 return &ffi_type_pointer;
214}
215#endif
216
217void 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}