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 
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