Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2 ffi.c
3
4 m68k Foreign Function Interface
5 ----------------------------------------------------------------------- */
6
7 #include <ffi.h>
8 #include <ffi_common.h>
9
10 #include <stdlib.h>
11 #include <unistd.h>
12 #ifdef __rtems__
13 void rtems_cache_flush_multiple_data_lines( const void *, size_t );
14 #else
15 #include <sys/syscall.h>
16 #ifdef __MINT__
17 #include <mint/mintbind.h>
18 #include <mint/ssystem.h>
19 #else
20 #include <asm/cachectl.h>
21 #endif
22 #endif
23
24 void ffi_call_SYSV (extended_cif *,
25 unsigned, unsigned,
26 void *, void (*fn) ());
27 void *ffi_prep_args (void *stack, extended_cif *ecif);
28 void ffi_closure_SYSV (ffi_closure *);
29 void ffi_closure_struct_SYSV (ffi_closure *);
30 unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
31 void *resp, void *args);
32
33 /* ffi_prep_args is called by the assembly routine once stack space has
34 been allocated for the function's arguments. */
35
36 void *
37 ffi_prep_args (void *stack, extended_cif *ecif)
38 {
39 unsigned int i;
40 void **p_argv;
41 char *argp;
42 ffi_type **p_arg;
43 void *struct_value_ptr;
44
45 argp = stack;
46
47 if (
48 #ifdef __MINT__
49 (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
50 #endif
51 (((ecif->cif->rtype->type == FFI_TYPE_STRUCT)
52 && !ecif->cif->flags)))
53 struct_value_ptr = ecif->rvalue;
54 else
55 struct_value_ptr = NULL;
56
57 p_argv = ecif->avalue;
58
59 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
60 i != 0;
61 i--, p_arg++)
62 {
63 size_t z = (*p_arg)->size;
64 int type = (*p_arg)->type;
65
66 if (z < sizeof (int))
67 {
68 switch (type)
69 {
70 case FFI_TYPE_SINT8:
71 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
72 break;
73
74 case FFI_TYPE_UINT8:
75 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
76 break;
77
78 case FFI_TYPE_SINT16:
79 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
80 break;
81
82 case FFI_TYPE_UINT16:
83 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
84 break;
85
86 case FFI_TYPE_STRUCT:
87 #ifdef __MINT__
88 if (z == 1 || z == 2)
89 memcpy (argp + 2, *p_argv, z);
90 else
91 memcpy (argp, *p_argv, z);
92 #else
93 memcpy (argp + sizeof (int) - z, *p_argv, z);
94 #endif
95 break;
96
97 default:
98 FFI_ASSERT (0);
99 }
100 z = sizeof (int);
101 }
102 else
103 {
104 memcpy (argp, *p_argv, z);
105
106 /* Align if necessary. */
107 if ((sizeof(int) - 1) & z)
108 z = ALIGN(z, sizeof(int));
109 }
110
111 p_argv++;
112 argp += z;
113 }
114
115 return struct_value_ptr;
116 }
117
118 #define CIF_FLAGS_INT 1
119 #define CIF_FLAGS_DINT 2
120 #define CIF_FLAGS_FLOAT 4
121 #define CIF_FLAGS_DOUBLE 8
122 #define CIF_FLAGS_LDOUBLE 16
123 #define CIF_FLAGS_POINTER 32
124 #define CIF_FLAGS_STRUCT1 64
125 #define CIF_FLAGS_STRUCT2 128
126 #define CIF_FLAGS_SINT8 256
127 #define CIF_FLAGS_SINT16 512
128
129 /* Perform machine dependent cif processing */
130 ffi_status
131 ffi_prep_cif_machdep (ffi_cif *cif)
132 {
133 /* Set the return type flag */
134 switch (cif->rtype->type)
135 {
136 case FFI_TYPE_VOID:
137 cif->flags = 0;
138 break;
139
140 case FFI_TYPE_STRUCT:
141 if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
142 cif->rtype->elements[1])
143 {
144 cif->flags = 0;
145 break;
146 }
147
148 switch (cif->rtype->size)
149 {
150 case 1:
151 #ifdef __MINT__
152 cif->flags = CIF_FLAGS_STRUCT2;
153 #else
154 cif->flags = CIF_FLAGS_STRUCT1;
155 #endif
156 break;
157 case 2:
158 cif->flags = CIF_FLAGS_STRUCT2;
159 break;
160 #ifdef __MINT__
161 case 3:
162 #endif
163 case 4:
164 cif->flags = CIF_FLAGS_INT;
165 break;
166 #ifdef __MINT__
167 case 7:
168 #endif
169 case 8:
170 cif->flags = CIF_FLAGS_DINT;
171 break;
172 default:
173 cif->flags = 0;
174 break;
175 }
176 break;
177
178 case FFI_TYPE_FLOAT:
179 cif->flags = CIF_FLAGS_FLOAT;
180 break;
181
182 case FFI_TYPE_DOUBLE:
183 cif->flags = CIF_FLAGS_DOUBLE;
184 break;
185
186 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
187 case FFI_TYPE_LONGDOUBLE:
188 #ifdef __MINT__
189 cif->flags = 0;
190 #else
191 cif->flags = CIF_FLAGS_LDOUBLE;
192 #endif
193 break;
194 #endif
195
196 case FFI_TYPE_POINTER:
197 cif->flags = CIF_FLAGS_POINTER;
198 break;
199
200 case FFI_TYPE_SINT64:
201 case FFI_TYPE_UINT64:
202 cif->flags = CIF_FLAGS_DINT;
203 break;
204
205 case FFI_TYPE_SINT16:
206 cif->flags = CIF_FLAGS_SINT16;
207 break;
208
209 case FFI_TYPE_SINT8:
210 cif->flags = CIF_FLAGS_SINT8;
211 break;
212
213 default:
214 cif->flags = CIF_FLAGS_INT;
215 break;
216 }
217
218 return FFI_OK;
219 }
220
221 void
222 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
223 {
224 extended_cif ecif;
225
226 ecif.cif = cif;
227 ecif.avalue = avalue;
228
229 /* If the return value is a struct and we don't have a return value
230 address then we need to make one. */
231
232 if (rvalue == NULL
233 && cif->rtype->type == FFI_TYPE_STRUCT
234 && cif->rtype->size > 8)
235 ecif.rvalue = alloca (cif->rtype->size);
236 else
237 ecif.rvalue = rvalue;
238
239 switch (cif->abi)
240 {
241 case FFI_SYSV:
242 ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
243 ecif.rvalue, fn);
244 break;
245
246 default:
247 FFI_ASSERT (0);
248 break;
249 }
250 }
251
252 static void
253 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
254 {
255 unsigned int i;
256 void **p_argv;
257 char *argp;
258 ffi_type **p_arg;
259
260 argp = stack;
261 p_argv = avalue;
262
263 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
264 {
265 size_t z;
266
267 z = (*p_arg)->size;
268 #ifdef __MINT__
269 if (cif->flags &&
270 cif->rtype->type == FFI_TYPE_STRUCT &&
271 (z == 1 || z == 2))
272 {
273 *p_argv = (void *) (argp + 2);
274
275 z = 4;
276 }
277 else
278 if (cif->flags &&
279 cif->rtype->type == FFI_TYPE_STRUCT &&
280 (z == 3 || z == 4))
281 {
282 *p_argv = (void *) (argp);
283
284 z = 4;
285 }
286 else
287 #endif
288 if (z <= 4)
289 {
290 *p_argv = (void *) (argp + 4 - z);
291
292 z = 4;
293 }
294 else
295 {
296 *p_argv = (void *) argp;
297
298 /* Align if necessary */
299 if ((sizeof(int) - 1) & z)
300 z = ALIGN(z, sizeof(int));
301 }
302
303 p_argv++;
304 argp += z;
305 }
306 }
307
308 unsigned int
309 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
310 {
311 ffi_cif *cif;
312 void **arg_area;
313
314 cif = closure->cif;
315 arg_area = (void**) alloca (cif->nargs * sizeof (void *));
316
317 ffi_prep_incoming_args_SYSV(args, arg_area, cif);
318
319 (closure->fun) (cif, resp, arg_area, closure->user_data);
320
321 return cif->flags;
322 }
323
324 ffi_status
325 ffi_prep_closure_loc (ffi_closure* closure,
326 ffi_cif* cif,
327 void (*fun)(ffi_cif*,void*,void**,void*),
328 void *user_data,
329 void *codeloc)
330 {
331 if (cif->abi != FFI_SYSV)
332 return FFI_BAD_ABI;
333
334 *(unsigned short *)closure->tramp = 0x207c;
335 *(void **)(closure->tramp + 2) = codeloc;
336 *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
337
338 if (
339 #ifdef __MINT__
340 (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
341 #endif
342 (((cif->rtype->type == FFI_TYPE_STRUCT)
343 && !cif->flags)))
344 *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
345 else
346 *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
347
348 #ifdef __rtems__
349 rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
350 #elif defined(__MINT__)
351 Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
352 #else
353 syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
354 FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
355 #endif
356
357 closure->cif = cif;
358 closure->user_data = user_data;
359 closure->fun = fun;
360
361 return FFI_OK;
362 }
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
CIF_FLAGS_LDOUBLE
#define CIF_FLAGS_LDOUBLE
Definition: ffi.c:122
FFI_TYPE_LONGDOUBLE
#define FFI_TYPE_LONGDOUBLE
Definition: ffi.c:40
ffi_call_SYSV
void ffi_call_SYSV(unsigned(*)(struct call_context *context, unsigned char *, extended_cif *), struct call_context *context, extended_cif *, size_t, void(*fn)(void))
CIF_FLAGS_DINT
#define CIF_FLAGS_DINT
Definition: ffi.c:119
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
ffi_common.h
FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE
Definition: ffitarget.h:45
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
ALIGN
#define ALIGN(v, a)
Definition: ffi_common.h:77
NULL
#define NULL
Definition: _sdbm.c:101
ffi_closure_struct_SYSV
void ffi_closure_struct_SYSV(ffi_closure *)
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
CIF_FLAGS_SINT16
#define CIF_FLAGS_SINT16
Definition: ffi.c:127
ffi_closure_SYSV_inner
void FFI_HIDDEN ffi_closure_SYSV_inner(ffi_closure *closure, struct call_context *context, void *stack)
Definition: ffi.c:964
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
CIF_FLAGS_DOUBLE
#define CIF_FLAGS_DOUBLE
Definition: ffi.c:121
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.0.h:2487
CIF_FLAGS_STRUCT1
#define CIF_FLAGS_STRUCT1
Definition: ffi.c:124
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
CIF_FLAGS_STRUCT2
#define CIF_FLAGS_STRUCT2
Definition: ffi.c:125
extended_cif
Definition: ffi_common.h:86
ffi_closure_SYSV
void ffi_closure_SYSV(ffi_closure *)
Definition: ffi.c:420
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
CIF_FLAGS_SINT8
#define CIF_FLAGS_SINT8
Definition: ffi.c:126
CIF_FLAGS_INT
#define CIF_FLAGS_INT
Definition: ffi.c:118
ffi_call
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
Definition: ffi.c:813
CIF_FLAGS_FLOAT
#define CIF_FLAGS_FLOAT
Definition: ffi.c:120
ffi_prep_closure_loc
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
Definition: ffi.c:928
extended_cif::cif
ffi_cif * cif
Definition: ffi_common.h:88
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
CIF_FLAGS_POINTER
#define CIF_FLAGS_POINTER
Definition: ffi.c:123