Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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__
13void 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
25 unsigned, unsigned,
26 void *, void (*fn) ());
27void *ffi_prep_args (void *stack, extended_cif *ecif);
28void ffi_closure_SYSV (ffi_closure *);
29void ffi_closure_struct_SYSV (ffi_closure *);
30unsigned 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
36void *
37ffi_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 */
130ffi_status
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)
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
221void
222ffi_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
252static void
253ffi_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
308unsigned int
309ffi_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
324ffi_status
325ffi_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}
void ffi_closure_SYSV(ffi_closure *)
Definition: ffi.c:420
void FFI_HIDDEN ffi_closure_SYSV_inner(ffi_closure *closure, struct call_context *context, void *stack)
Definition: ffi.c:964
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
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
Definition: ffi.c:813
void ffi_call_SYSV(unsigned(*)(struct call_context *context, unsigned char *, extended_cif *), struct call_context *context, extended_cif *, size_t, void(*fn)(void))
#define FFI_TRAMPOLINE_SIZE
Definition: ffitarget.h:45
@ FFI_SYSV
Definition: ffitarget.h:36
#define FFI_TYPE_LONGDOUBLE
Definition: ffi.c:40
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
#define ALIGN(v, a)
Definition: ffi_common.h:77
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
void ffi_closure_struct_SYSV(ffi_closure *)
#define CIF_FLAGS_DINT
Definition: ffi.c:119
#define CIF_FLAGS_FLOAT
Definition: ffi.c:120
#define CIF_FLAGS_STRUCT2
Definition: ffi.c:125
#define CIF_FLAGS_SINT16
Definition: ffi.c:127
#define CIF_FLAGS_INT
Definition: ffi.c:118
#define CIF_FLAGS_LDOUBLE
Definition: ffi.c:122
#define CIF_FLAGS_POINTER
Definition: ffi.c:123
#define CIF_FLAGS_STRUCT1
Definition: ffi.c:124
#define CIF_FLAGS_SINT8
Definition: ffi.c:126
#define CIF_FLAGS_DOUBLE
Definition: ffi.c:121
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
#define alloca(size)
#define NULL
uint32_t i
void * memcpy(void *__restrict__, const void *__restrict__, size_t)
__inline__ int
void * rvalue
Definition: ffi_common.h:89
ffi_cif * cif
Definition: ffi_common.h:88
void ** avalue
Definition: ffi_common.h:90