]> git.saurik.com Git - cycript.git/blob - sig/ffi_type.cpp
Make Functor/struct output fancy type definitions.
[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 #define ffi_type_slonglong ffi_type_sint64
28 #define ffi_type_ulonglong ffi_type_uint64
29
30 namespace sig {
31
32 template <>
33 ffi_type *Primitive<bool>::GetFFI(CYPool &pool) const {
34 return &ffi_type_uchar;
35 }
36
37 template <>
38 ffi_type *Primitive<char>::GetFFI(CYPool &pool) const {
39 return &ffi_type_schar;
40 }
41
42 template <>
43 ffi_type *Primitive<float>::GetFFI(CYPool &pool) const {
44 return &ffi_type_float;
45 }
46
47 template <>
48 ffi_type *Primitive<double>::GetFFI(CYPool &pool) const {
49 return &ffi_type_double;
50 }
51
52 template <>
53 ffi_type *Primitive<signed char>::GetFFI(CYPool &pool) const {
54 return &ffi_type_schar;
55 }
56
57 template <>
58 ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
59 return &ffi_type_sint;
60 }
61
62 template <>
63 ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
64 return &ffi_type_slong;
65 }
66
67 template <>
68 ffi_type *Primitive<signed long long int>::GetFFI(CYPool &pool) const {
69 return &ffi_type_slonglong;
70 }
71
72 template <>
73 ffi_type *Primitive<signed short int>::GetFFI(CYPool &pool) const {
74 return &ffi_type_sshort;
75 }
76
77 template <>
78 ffi_type *Primitive<unsigned char>::GetFFI(CYPool &pool) const {
79 return &ffi_type_uchar;
80 }
81
82 template <>
83 ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
84 return &ffi_type_uint;
85 }
86
87 template <>
88 ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
89 return &ffi_type_ulong;
90 }
91
92 template <>
93 ffi_type *Primitive<unsigned long long int>::GetFFI(CYPool &pool) const {
94 return &ffi_type_ulonglong;
95 }
96
97 template <>
98 ffi_type *Primitive<unsigned short int>::GetFFI(CYPool &pool) const {
99 return &ffi_type_ushort;
100 }
101
102 ffi_type *Void::GetFFI(CYPool &pool) const {
103 return &ffi_type_void;
104 }
105
106 ffi_type *Unknown::GetFFI(CYPool &pool) const {
107 _assert(false);
108 }
109
110 ffi_type *String::GetFFI(CYPool &pool) const {
111 return &ffi_type_pointer;
112 }
113
114 #ifdef CY_OBJECTIVEC
115 ffi_type *Meta::GetFFI(CYPool &pool) const {
116 return &ffi_type_pointer;
117 }
118
119 ffi_type *Selector::GetFFI(CYPool &pool) const {
120 return &ffi_type_pointer;
121 }
122 #endif
123
124 ffi_type *Bits::GetFFI(CYPool &pool) const {
125 /* XXX: we can totally make this work */
126 _assert(false);
127 }
128
129 ffi_type *Pointer::GetFFI(CYPool &pool) const {
130 return &ffi_type_pointer;
131 }
132
133 ffi_type *Array::GetFFI(CYPool &pool) const {
134 // XXX: this is really lame
135 ffi_type *ffi(new(pool) ffi_type());
136 ffi->size = 0;
137 ffi->alignment = 0;
138 ffi->type = FFI_TYPE_STRUCT;
139
140 ffi_type *element(type.GetFFI(pool));
141
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;
146
147 return ffi;
148 }
149
150 #ifdef CY_OBJECTIVEC
151 ffi_type *Object::GetFFI(CYPool &pool) const {
152 return &ffi_type_pointer;
153 }
154 #endif
155
156 ffi_type *Aggregate::GetFFI(CYPool &pool) const {
157 // XXX: we can totally make overlap work
158 _assert(!overlap);
159
160 ffi_type *ffi(new(pool) ffi_type());
161 ffi->size = 0;
162 ffi->alignment = 0;
163 ffi->type = FFI_TYPE_STRUCT;
164
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;
170 } else {
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;
175 }
176
177 return ffi;
178 }
179
180 ffi_type *Function::GetFFI(CYPool &pool) const {
181 _assert(false);
182 }
183
184 #ifdef CY_OBJECTIVEC
185 ffi_type *Block::GetFFI(CYPool &pool) const {
186 return &ffi_type_pointer;
187 }
188 #endif
189
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));
194
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);
198
199 ffi_status status;
200 #ifdef HAVE_FFI_PREP_CIF_VAR
201 if (variadic == 0)
202 #endif
203 status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, type, types);
204 #ifdef HAVE_FFI_PREP_CIF_VAR
205 else
206 status = ffi_prep_cif_var(cif, FFI_DEFAULT_ABI, variadic - 1, count, type, types);
207 #endif
208 _assert(status == FFI_OK);
209 }
210
211 }