]> git.saurik.com Git - cycript.git/blob - sig/ffi_type.cpp
This is getting seriously hot.
[cycript.git] / sig / ffi_type.cpp
1 #include "minimal/stdlib.h"
2
3 #include "sig/ffi_type.hpp"
4 #include "sig/types.hpp"
5
6 namespace sig {
7
8 ffi_type *sig_objc_ffi_type(apr_pool_t *pool, struct Type *type) {
9 switch (type->primitive) {
10 case typename_P: return &ffi_type_pointer;
11
12 case union_P:
13 /* XXX: we can totally make this work */
14 _assert(false);
15 break;
16
17 case string_P: return &ffi_type_pointer;
18 case selector_P: return &ffi_type_pointer;
19 case object_P: return &ffi_type_pointer;
20 case boolean_P: return &ffi_type_uchar;
21 case uchar_P: return &ffi_type_uchar;
22 case uint_P: return &ffi_type_uint;
23 case ulong_P: return &ffi_type_ulong;
24 case ulonglong_P: return &ffi_type_ulong;
25 case ushort_P: return &ffi_type_ushort;
26
27 case array_P:
28 /* XXX: implement */
29 _assert(false);
30 break;
31
32 case pointer_P: return &ffi_type_pointer;
33
34 case bit_P:
35 /* XXX: we can totally make this work */
36 _assert(false);
37 break;
38
39 case char_P: return &ffi_type_schar;
40 case double_P: return &ffi_type_double;
41 case float_P: return &ffi_type_float;
42 case int_P: return &ffi_type_sint;
43 case long_P: return &ffi_type_sint;
44 case longlong_P: return &ffi_type_slong;
45 case short_P: return &ffi_type_sshort;
46
47 case void_P: return &ffi_type_void;
48
49 case struct_P: {
50 ffi_type *aggregate = reinterpret_cast<ffi_type *>(apr_palloc(pool, sizeof(ffi_type)));
51 aggregate->size = 0;
52 aggregate->alignment = 0;
53 aggregate->type = FFI_TYPE_STRUCT;
54
55 aggregate->elements = reinterpret_cast<ffi_type **>(apr_palloc(pool, (type->data.signature.count + 1) * sizeof(ffi_type *)));
56 sig_ffi_types(pool, &sig_objc_ffi_type, &type->data.signature, aggregate->elements, 0, 0);
57 aggregate->elements[type->data.signature.count] = NULL;
58
59 return aggregate;
60 } break;
61
62 default:
63 _assert(false);
64 break;
65 }
66 }
67
68 ffi_type *sig_java_ffi_type(apr_pool_t *pool, struct Type *type) {
69 switch (type->primitive) {
70 case typename_P: return &ffi_type_pointer;
71 case union_P: return &ffi_type_pointer;
72 case string_P: return &ffi_type_pointer;
73 case selector_P: return &ffi_type_pointer;
74 case object_P: return &ffi_type_pointer;
75 case boolean_P: return &ffi_type_uchar;
76 case uchar_P: return &ffi_type_uchar;
77 case uint_P: return &ffi_type_uint;
78 case ulong_P: return &ffi_type_ulong;
79 case ulonglong_P: return &ffi_type_ulong;
80 case ushort_P: return &ffi_type_ushort;
81 case array_P: return &ffi_type_pointer;
82 case pointer_P: return &ffi_type_pointer;
83
84 /* XXX: bit type */
85 case bit_P: return &ffi_type_uint;
86
87 case char_P: return &ffi_type_schar;
88 case double_P: return &ffi_type_double;
89 case float_P: return &ffi_type_double;
90 case int_P: return &ffi_type_sint;
91 case long_P: return &ffi_type_sint;
92 case longlong_P: return &ffi_type_slong;
93 case short_P: return &ffi_type_sshort;
94 case void_P: return &ffi_type_void;
95 case struct_P: return &ffi_type_pointer;
96
97 default:
98 _assert(false);
99 break;
100 }
101 }
102
103 void sig_ffi_types(
104 apr_pool_t *pool,
105 ffi_type *(*sig_ffi_type)(apr_pool_t *, struct Type *),
106 struct Signature *signature,
107 ffi_type **ffi_types,
108 size_t skip,
109 size_t offset
110 ) {
111 _assert(signature->count >= skip);
112 for (size_t index = skip; index != signature->count; ++index)
113 ffi_types[index - skip + offset] = (*sig_ffi_type)(pool, signature->elements[index].type);
114 }
115
116 void sig_ffi_cif(
117 apr_pool_t *pool,
118 ffi_type *(*sig_ffi_type)(apr_pool_t *, struct Type *),
119 struct Signature *signature,
120 ffi_cif *ffi_cif,
121 size_t skip,
122 ffi_type **types,
123 size_t offset
124 ) {
125 if (types == NULL)
126 types = reinterpret_cast<ffi_type **>(apr_palloc(pool, (signature->count - 1) * sizeof(ffi_type *)));
127 ffi_type *type = (*sig_ffi_type)(pool, signature->elements[0].type);
128 sig_ffi_types(pool, sig_ffi_type, signature, types, 1 + skip, offset);
129 ffi_status status = ffi_prep_cif(ffi_cif, FFI_DEFAULT_ABI, signature->count - 1 - skip + offset, type, types);
130 _assert(status == FFI_OK);
131 }
132
133 }