Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 1998 Cygnus Solutions
3  Copyright (c) 2004 Simon Posnjak
4  Copyright (c) 2005 Axis Communications AB
5  Copyright (C) 2007 Free Software Foundation, Inc.
6 
7  CRIS Foreign Function Interface
8 
9  Permission is hereby granted, free of charge, to any person obtaining
10  a copy of this software and associated documentation files (the
11  ``Software''), to deal in the Software without restriction, including
12  without limitation the rights to use, copy, modify, merge, publish,
13  distribute, sublicense, and/or sell copies of the Software, and to
14  permit persons to whom the Software is furnished to do so, subject to
15  the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
24  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26  OTHER DEALINGS IN THE SOFTWARE.
27  ----------------------------------------------------------------------- */
28 
29 #include <ffi.h>
30 #include <ffi_common.h>
31 
32 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
33 
34 static ffi_status
35 initialize_aggregate_packed_struct (ffi_type * arg)
36 {
37  ffi_type **ptr;
38 
39  FFI_ASSERT (arg != NULL);
40 
41  FFI_ASSERT (arg->elements != NULL);
42  FFI_ASSERT (arg->size == 0);
43  FFI_ASSERT (arg->alignment == 0);
44 
45  ptr = &(arg->elements[0]);
46 
47  while ((*ptr) != NULL)
48  {
49  if (((*ptr)->size == 0)
50  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
51  return FFI_BAD_TYPEDEF;
52 
54 
55  arg->size += (*ptr)->size;
56 
57  arg->alignment = (arg->alignment > (*ptr)->alignment) ?
58  arg->alignment : (*ptr)->alignment;
59 
60  ptr++;
61  }
62 
63  if (arg->size == 0)
64  return FFI_BAD_TYPEDEF;
65  else
66  return FFI_OK;
67 }
68 
69 int
70 ffi_prep_args (char *stack, extended_cif * ecif)
71 {
72  unsigned int i;
73  unsigned int struct_count = 0;
74  void **p_argv;
75  char *argp;
76  ffi_type **p_arg;
77 
78  argp = stack;
79 
80  p_argv = ecif->avalue;
81 
82  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
83  (i != 0); i--, p_arg++)
84  {
85  size_t z;
86 
87  switch ((*p_arg)->type)
88  {
89  case FFI_TYPE_STRUCT:
90  {
91  z = (*p_arg)->size;
92  if (z <= 4)
93  {
94  memcpy (argp, *p_argv, z);
95  z = 4;
96  }
97  else if (z <= 8)
98  {
99  memcpy (argp, *p_argv, z);
100  z = 8;
101  }
102  else
103  {
104  unsigned int uiLocOnStack;
105  z = sizeof (void *);
106  uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
107  struct_count = struct_count + (*p_arg)->size;
108  *(unsigned int *) argp =
109  (unsigned int) (UINT32 *) (stack + uiLocOnStack);
110  memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
111  }
112  break;
113  }
114  default:
115  z = (*p_arg)->size;
116  if (z < sizeof (int))
117  {
118  switch ((*p_arg)->type)
119  {
120  case FFI_TYPE_SINT8:
121  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
122  break;
123 
124  case FFI_TYPE_UINT8:
125  *(unsigned int *) argp =
126  (unsigned int) *(UINT8 *) (*p_argv);
127  break;
128 
129  case FFI_TYPE_SINT16:
130  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
131  break;
132 
133  case FFI_TYPE_UINT16:
134  *(unsigned int *) argp =
135  (unsigned int) *(UINT16 *) (*p_argv);
136  break;
137 
138  default:
139  FFI_ASSERT (0);
140  }
141  z = sizeof (int);
142  }
143  else if (z == sizeof (int))
144  *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
145  else
146  memcpy (argp, *p_argv, z);
147  break;
148  }
149  p_argv++;
150  argp += z;
151  }
152 
153  return (struct_count);
154 }
155 
156 ffi_status FFI_HIDDEN
157 ffi_prep_cif_core (ffi_cif * cif,
158  ffi_abi abi, unsigned int isvariadic,
159  unsigned int nfixedargs, unsigned int ntotalargs,
160  ffi_type * rtype, ffi_type ** atypes)
161 {
162  unsigned bytes = 0;
163  unsigned int i;
164  ffi_type **ptr;
165 
166  FFI_ASSERT (cif != NULL);
167  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
168  FFI_ASSERT(nfixedargs <= ntotalargs);
169  FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
170 
171  cif->abi = abi;
172  cif->arg_types = atypes;
173  cif->nargs = ntotalargs;
174  cif->rtype = rtype;
175 
176  cif->flags = 0;
177 
178  if ((cif->rtype->size == 0)
179  && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
180  return FFI_BAD_TYPEDEF;
181 
182  FFI_ASSERT_VALID_TYPE (cif->rtype);
183 
184  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
185  {
186  if (((*ptr)->size == 0)
187  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
188  return FFI_BAD_TYPEDEF;
189 
191 
192  if (((*ptr)->alignment - 1) & bytes)
193  bytes = ALIGN (bytes, (*ptr)->alignment);
194  if ((*ptr)->type == FFI_TYPE_STRUCT)
195  {
196  if ((*ptr)->size > 8)
197  {
198  bytes += (*ptr)->size;
199  bytes += sizeof (void *);
200  }
201  else
202  {
203  if ((*ptr)->size > 4)
204  bytes += 8;
205  else
206  bytes += 4;
207  }
208  }
209  else
210  bytes += STACK_ARG_SIZE ((*ptr)->size);
211  }
212 
213  cif->bytes = bytes;
214 
215  return ffi_prep_cif_machdep (cif);
216 }
217 
218 ffi_status
219 ffi_prep_cif_machdep (ffi_cif * cif)
220 {
221  switch (cif->rtype->type)
222  {
223  case FFI_TYPE_VOID:
224  case FFI_TYPE_STRUCT:
225  case FFI_TYPE_FLOAT:
226  case FFI_TYPE_DOUBLE:
227  case FFI_TYPE_SINT64:
228  case FFI_TYPE_UINT64:
229  cif->flags = (unsigned) cif->rtype->type;
230  break;
231 
232  default:
233  cif->flags = FFI_TYPE_INT;
234  break;
235  }
236 
237  return FFI_OK;
238 }
239 
240 extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
241  extended_cif *,
242  unsigned, unsigned, unsigned *, void (*fn) ())
243  __attribute__ ((__visibility__ ("hidden")));
244 
245 void
246 ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
247 {
248  extended_cif ecif;
249 
250  ecif.cif = cif;
251  ecif.avalue = avalue;
252 
253  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
254  {
255  ecif.rvalue = alloca (cif->rtype->size);
256  }
257  else
258  ecif.rvalue = rvalue;
259 
260  switch (cif->abi)
261  {
262  case FFI_SYSV:
263  ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
264  cif->flags, ecif.rvalue, fn);
265  break;
266  default:
267  FFI_ASSERT (0);
268  break;
269  }
270 }
271 
272 /* Because the following variables are not exported outside libffi, we
273  mark them hidden. */
274 
275 /* Assembly code for the jump stub. */
276 extern const char ffi_cris_trampoline_template[]
277  __attribute__ ((__visibility__ ("hidden")));
278 
279 /* Offset into ffi_cris_trampoline_template of where to put the
280  ffi_prep_closure_inner function. */
281 extern const int ffi_cris_trampoline_fn_offset
282  __attribute__ ((__visibility__ ("hidden")));
283 
284 /* Offset into ffi_cris_trampoline_template of where to put the
285  closure data. */
286 extern const int ffi_cris_trampoline_closure_offset
287  __attribute__ ((__visibility__ ("hidden")));
288 
289 /* This function is sibling-called (jumped to) by the closure
290  trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
291  PARAMS[4] to simplify handling of a straddling parameter. A copy
292  of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are
293  put at the appropriate place in CLOSURE which is then executed and
294  the return value is passed back to the caller. */
295 
296 static unsigned long long
297 ffi_prep_closure_inner (void **params, ffi_closure* closure)
298 {
299  char *register_args = (char *) params;
300  void *struct_ret = params[5];
301  char *stack_args = params[6];
302  char *ptr = register_args;
303  ffi_cif *cif = closure->cif;
304  ffi_type **arg_types = cif->arg_types;
305 
306  /* Max room needed is number of arguments as 64-bit values. */
307  void **avalue = alloca (closure->cif->nargs * sizeof(void *));
308  int i;
309  int doing_regs;
310  long long llret = 0;
311 
312  /* Find the address of each argument. */
313  for (i = 0, doing_regs = 1; i < cif->nargs; i++)
314  {
315  /* Types up to and including 8 bytes go by-value. */
316  if (arg_types[i]->size <= 4)
317  {
318  avalue[i] = ptr;
319  ptr += 4;
320  }
321  else if (arg_types[i]->size <= 8)
322  {
323  avalue[i] = ptr;
324  ptr += 8;
325  }
326  else
327  {
328  FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
329 
330  /* Passed by-reference, so copy the pointer. */
331  avalue[i] = *(void **) ptr;
332  ptr += 4;
333  }
334 
335  /* If we've handled more arguments than fit in registers, start
336  looking at the those passed on the stack. Step over the
337  first one if we had a straddling parameter. */
338  if (doing_regs && ptr >= register_args + 4*4)
339  {
340  ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
341  doing_regs = 0;
342  }
343  }
344 
345  /* Invoke the closure. */
346  (closure->fun) (cif,
347 
348  cif->rtype->type == FFI_TYPE_STRUCT
349  /* The caller allocated space for the return
350  structure, and passed a pointer to this space in
351  R9. */
352  ? struct_ret
353 
354  /* We take advantage of being able to ignore that
355  the high part isn't set if the return value is
356  not in R10:R11, but in R10 only. */
357  : (void *) &llret,
358 
359  avalue, closure->user_data);
360 
361  return llret;
362 }
363 
364 /* API function: Prepare the trampoline. */
365 
366 ffi_status
367 ffi_prep_closure_loc (ffi_closure* closure,
368  ffi_cif* cif,
369  void (*fun)(ffi_cif *, void *, void **, void*),
370  void *user_data,
371  void *codeloc)
372 {
373  void *innerfn = ffi_prep_closure_inner;
374  FFI_ASSERT (cif->abi == FFI_SYSV);
375  closure->cif = cif;
376  closure->user_data = user_data;
377  closure->fun = fun;
378  memcpy (closure->tramp, ffi_cris_trampoline_template,
380  memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
381  &innerfn, sizeof (void *));
382  memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
383  &codeloc, sizeof (void *));
384 
385  return FFI_OK;
386 }
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
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))
ffi_abi
ffi_abi
Definition: ffitarget.h:34
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
int
__inline__ int
Definition: rb_mjit_min_header-2.7.2.h:2877
i
uint32_t i
Definition: rb_mjit_min_header-2.7.2.h:5499
ffi_prep_cif_core
ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, unsigned int isvariadic, unsigned int nfixedargs, unsigned int ntotalargs, ffi_type *rtype, ffi_type **atypes)
Definition: ffi.c:157
ffi_common.h
FFI_HIDDEN
const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN
unsigned
#define unsigned
Definition: rb_mjit_min_header-2.7.2.h:2915
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.2.h:2525
FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE
#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE
Definition: ffitarget.h:50
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
ptr
struct RIMemo * ptr
Definition: debug.c:65
ALIGN
#define ALIGN(v, a)
Definition: ffi_common.h:77
NULL
#define NULL
Definition: _sdbm.c:101
__attribute__
void *PTR64 __attribute__((mode(DI)))
Definition: ffi.c:41
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
ffi_type_test
void ffi_type_test(ffi_type *a, char *file, int line)
Definition: debug.c:50
FFI_ASSERT_VALID_TYPE
#define FFI_ASSERT_VALID_TYPE(x)
Definition: ffi_common.h:74
FFI_LAST_ABI
@ FFI_LAST_ABI
Definition: ffitarget.h:37
size
int size
Definition: encoding.c:58
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.2.h:5636
extended_cif
Definition: ffi_common.h:87
STACK_ARG_SIZE
#define STACK_ARG_SIZE(x)
Definition: ffi.c:32
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
ffi_call
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
Definition: ffi.c:813
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
FFI_FIRST_ABI
@ FFI_FIRST_ABI
Definition: ffitarget.h:35
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39