]> git.saurik.com Git - cycript.git/blame - sig/ffi_type.cpp
Add workaround for zero-sized struct (and use it).
[cycript.git] / sig / ffi_type.cpp
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c1d3e52e 2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
b4aa79af
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
b4aa79af 6/*
f95d2598
JF
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
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
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/>.
b3378a02 19**/
b4aa79af
JF
20/* }}} */
21
37954781 22#include "Error.hpp"
ea2d184c
JF
23
24#include "sig/ffi_type.hpp"
25#include "sig/types.hpp"
26
5875f632
JF
27#define ffi_type_slonglong ffi_type_sint64
28#define ffi_type_ulonglong ffi_type_uint64
29
ea2d184c
JF
30namespace sig {
31
0559abf8
JF
32template <>
33ffi_type *Primitive<bool>::GetFFI(CYPool &pool) const {
34 return &ffi_type_uchar;
35}
36
37template <>
38ffi_type *Primitive<char>::GetFFI(CYPool &pool) const {
39 return &ffi_type_schar;
40}
41
42template <>
43ffi_type *Primitive<float>::GetFFI(CYPool &pool) const {
44 return &ffi_type_float;
45}
46
47template <>
48ffi_type *Primitive<double>::GetFFI(CYPool &pool) const {
49 return &ffi_type_double;
50}
51
52template <>
53ffi_type *Primitive<signed char>::GetFFI(CYPool &pool) const {
54 return &ffi_type_schar;
55}
56
57template <>
58ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
59 return &ffi_type_sint;
60}
61
62template <>
63ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
64 return &ffi_type_slong;
65}
66
67template <>
68ffi_type *Primitive<signed long long int>::GetFFI(CYPool &pool) const {
69 return &ffi_type_slonglong;
70}
71
72template <>
73ffi_type *Primitive<signed short int>::GetFFI(CYPool &pool) const {
74 return &ffi_type_sshort;
75}
76
77template <>
78ffi_type *Primitive<unsigned char>::GetFFI(CYPool &pool) const {
79 return &ffi_type_uchar;
80}
81
82template <>
83ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
84 return &ffi_type_uint;
85}
86
87template <>
88ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
89 return &ffi_type_ulong;
90}
91
92template <>
93ffi_type *Primitive<unsigned long long int>::GetFFI(CYPool &pool) const {
94 return &ffi_type_ulonglong;
95}
96
97template <>
98ffi_type *Primitive<unsigned short int>::GetFFI(CYPool &pool) const {
99 return &ffi_type_ushort;
100}
101
102ffi_type *Void::GetFFI(CYPool &pool) const {
103 return &ffi_type_void;
104}
105
106ffi_type *Unknown::GetFFI(CYPool &pool) const {
107 _assert(false);
108}
109
110ffi_type *String::GetFFI(CYPool &pool) const {
111 return &ffi_type_pointer;
112}
113
114ffi_type *Meta::GetFFI(CYPool &pool) const {
115 return &ffi_type_pointer;
116}
117
118ffi_type *Selector::GetFFI(CYPool &pool) const {
119 return &ffi_type_pointer;
120}
121
122ffi_type *Bits::GetFFI(CYPool &pool) const {
123 /* XXX: we can totally make this work */
124 _assert(false);
125}
126
127ffi_type *Pointer::GetFFI(CYPool &pool) const {
128 return &ffi_type_pointer;
129}
130
131ffi_type *Array::GetFFI(CYPool &pool) const {
132 // XXX: this is really lame
133 ffi_type *ffi(new(pool) ffi_type());
134 ffi->size = 0;
135 ffi->alignment = 0;
136 ffi->type = FFI_TYPE_STRUCT;
137
138 ffi_type *element(type.GetFFI(pool));
139
140 ffi->elements = new(pool) ffi_type *[size + 1];
141 for (size_t i(0); i != size; ++i)
142 ffi->elements[i] = element;
143 ffi->elements[size] = NULL;
144
145 return ffi;
146}
147
148ffi_type *Object::GetFFI(CYPool &pool) const {
149 return &ffi_type_pointer;
150}
151
152ffi_type *Aggregate::GetFFI(CYPool &pool) const {
153 // XXX: we can totally make overlap work
154 _assert(!overlap);
155
156 ffi_type *ffi(new(pool) ffi_type());
157 ffi->size = 0;
158 ffi->alignment = 0;
159 ffi->type = FFI_TYPE_STRUCT;
160
255fe37e
JF
161 if (signature.count == 0) {
162 // https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01286.html
163 ffi->elements = new(pool) ffi_type *[2];
164 ffi->elements[0] = &ffi_type_void;
165 ffi->elements[1] = NULL;
166 } else {
167 ffi->elements = new(pool) ffi_type *[signature.count + 1];
168 for (size_t index(0); index != signature.count; ++index)
169 ffi->elements[index] = signature.elements[index].type->GetFFI(pool);
170 ffi->elements[signature.count] = NULL;
171 }
0559abf8
JF
172
173 return ffi;
174}
175
176ffi_type *Function::GetFFI(CYPool &pool) const {
177 _assert(false);
178}
179
180ffi_type *Block::GetFFI(CYPool &pool) const {
181 return &ffi_type_pointer;
ea2d184c
JF
182}
183
574d4720
JF
184void sig_ffi_cif(CYPool &pool, size_t variadic, const Signature &signature, ffi_cif *cif) {
185 _assert(signature.count != 0);
186 size_t count(signature.count - 1);
187 ffi_type *type(signature.elements[0].type->GetFFI(pool));
188
189 ffi_type **types(new(pool) ffi_type *[count]);
190 for (size_t index(0); index != count; ++index)
191 types[index] = signature.elements[index + 1].type->GetFFI(pool);
192
193 ffi_status status;
194#ifdef HAVE_FFI_PREP_CIF_VAR
195 if (variadic == 0)
196#endif
197 status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, type, types);
198#ifdef HAVE_FFI_PREP_CIF_VAR
199 else
200 status = ffi_prep_cif_var(cif, FFI_DEFAULT_ABI, variadic - 1, count, type, types);
201#endif
ea2d184c
JF
202 _assert(status == FFI_OK);
203}
204
205}