Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima
3  Copyright (c) 2008 Red Hat, Inc.
4 
5  SuperH Foreign Function Interface
6 
7  Permission is hereby granted, free of charge, to any person obtaining
8  a copy of this software and associated documentation files (the
9  ``Software''), to deal in the Software without restriction, including
10  without limitation the rights to use, copy, modify, merge, publish,
11  distribute, sublicense, and/or sell copies of the Software, and to
12  permit persons to whom the Software is furnished to do so, subject to
13  the following conditions:
14 
15  The above copyright notice and this permission notice shall be included
16  in all copies or substantial portions of the Software.
17 
18  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  DEALINGS IN THE SOFTWARE.
26  ----------------------------------------------------------------------- */
27 
28 #include <ffi.h>
29 #include <ffi_common.h>
30 
31 #include <stdlib.h>
32 
33 #define NGREGARG 4
34 #if defined(__SH4__)
35 #define NFREGARG 8
36 #endif
37 
38 #if defined(__HITACHI__)
39 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40 #else
41 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
42 #endif
43 
44 /* If the structure has essentially an unique element, return its type. */
45 static int
46 simple_type (ffi_type *arg)
47 {
48  if (arg->type != FFI_TYPE_STRUCT)
49  return arg->type;
50  else if (arg->elements[1])
51  return FFI_TYPE_STRUCT;
52 
53  return simple_type (arg->elements[0]);
54 }
55 
56 static int
57 return_type (ffi_type *arg)
58 {
59  unsigned short type;
60 
61  if (arg->type != FFI_TYPE_STRUCT)
62  return arg->type;
63 
64  type = simple_type (arg->elements[0]);
65  if (! arg->elements[1])
66  {
67  switch (type)
68  {
69  case FFI_TYPE_SINT8:
70  case FFI_TYPE_UINT8:
71  case FFI_TYPE_SINT16:
72  case FFI_TYPE_UINT16:
73  case FFI_TYPE_SINT32:
74  case FFI_TYPE_UINT32:
75  return FFI_TYPE_INT;
76 
77  default:
78  return type;
79  }
80  }
81 
82  /* gcc uses r0/r1 pair for some kind of structures. */
83  if (arg->size <= 2 * sizeof (int))
84  {
85  int i = 0;
86  ffi_type *e;
87 
88  while ((e = arg->elements[i++]))
89  {
90  type = simple_type (e);
91  switch (type)
92  {
93  case FFI_TYPE_SINT32:
94  case FFI_TYPE_UINT32:
95  case FFI_TYPE_INT:
96  case FFI_TYPE_FLOAT:
97  return FFI_TYPE_UINT64;
98 
99  default:
100  break;
101  }
102  }
103  }
104 
105  return FFI_TYPE_STRUCT;
106 }
107 
108 /* ffi_prep_args is called by the assembly routine once stack space
109  has been allocated for the function's arguments */
110 
111 void ffi_prep_args(char *stack, extended_cif *ecif)
112 {
113  register unsigned int i;
114  register int tmp;
115  register unsigned int avn;
116  register void **p_argv;
117  register char *argp;
118  register ffi_type **p_arg;
119  int greg, ireg;
120 #if defined(__SH4__)
121  int freg = 0;
122 #endif
123 
124  tmp = 0;
125  argp = stack;
126 
127  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
128  {
129  *(void **) argp = ecif->rvalue;
130  argp += 4;
131  ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
132  }
133  else
134  ireg = 0;
135 
136  /* Set arguments for registers. */
137  greg = ireg;
138  avn = ecif->cif->nargs;
139  p_argv = ecif->avalue;
140 
141  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
142  {
143  size_t z;
144 
145  z = (*p_arg)->size;
146  if (z < sizeof(int))
147  {
148  if (greg++ >= NGREGARG)
149  continue;
150 
151  z = sizeof(int);
152  switch ((*p_arg)->type)
153  {
154  case FFI_TYPE_SINT8:
155  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
156  break;
157 
158  case FFI_TYPE_UINT8:
159  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
160  break;
161 
162  case FFI_TYPE_SINT16:
163  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
164  break;
165 
166  case FFI_TYPE_UINT16:
167  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
168  break;
169 
170  case FFI_TYPE_STRUCT:
171  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
172  break;
173 
174  default:
175  FFI_ASSERT(0);
176  }
177  argp += z;
178  }
179  else if (z == sizeof(int))
180  {
181 #if defined(__SH4__)
182  if ((*p_arg)->type == FFI_TYPE_FLOAT)
183  {
184  if (freg++ >= NFREGARG)
185  continue;
186  }
187  else
188 #endif
189  {
190  if (greg++ >= NGREGARG)
191  continue;
192  }
193  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
194  argp += z;
195  }
196 #if defined(__SH4__)
197  else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
198  {
199  if (freg + 1 >= NFREGARG)
200  continue;
201  freg = (freg + 1) & ~1;
202  freg += 2;
203  memcpy (argp, *p_argv, z);
204  argp += z;
205  }
206 #endif
207  else
208  {
209  int n = (z + sizeof (int) - 1) / sizeof (int);
210 #if defined(__SH4__)
211  if (greg + n - 1 >= NGREGARG)
212  continue;
213 #else
214  if (greg >= NGREGARG)
215  continue;
216 #endif
217  greg += n;
218  memcpy (argp, *p_argv, z);
219  argp += n * sizeof (int);
220  }
221  }
222 
223  /* Set arguments on stack. */
224  greg = ireg;
225 #if defined(__SH4__)
226  freg = 0;
227 #endif
228  p_argv = ecif->avalue;
229 
230  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
231  {
232  size_t z;
233 
234  z = (*p_arg)->size;
235  if (z < sizeof(int))
236  {
237  if (greg++ < NGREGARG)
238  continue;
239 
240  z = sizeof(int);
241  switch ((*p_arg)->type)
242  {
243  case FFI_TYPE_SINT8:
244  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
245  break;
246 
247  case FFI_TYPE_UINT8:
248  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
249  break;
250 
251  case FFI_TYPE_SINT16:
252  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
253  break;
254 
255  case FFI_TYPE_UINT16:
256  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
257  break;
258 
259  case FFI_TYPE_STRUCT:
260  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
261  break;
262 
263  default:
264  FFI_ASSERT(0);
265  }
266  argp += z;
267  }
268  else if (z == sizeof(int))
269  {
270 #if defined(__SH4__)
271  if ((*p_arg)->type == FFI_TYPE_FLOAT)
272  {
273  if (freg++ < NFREGARG)
274  continue;
275  }
276  else
277 #endif
278  {
279  if (greg++ < NGREGARG)
280  continue;
281  }
282  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
283  argp += z;
284  }
285 #if defined(__SH4__)
286  else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
287  {
288  if (freg + 1 < NFREGARG)
289  {
290  freg = (freg + 1) & ~1;
291  freg += 2;
292  continue;
293  }
294  memcpy (argp, *p_argv, z);
295  argp += z;
296  }
297 #endif
298  else
299  {
300  int n = (z + sizeof (int) - 1) / sizeof (int);
301  if (greg + n - 1 < NGREGARG)
302  {
303  greg += n;
304  continue;
305  }
306 #if (! defined(__SH4__))
307  else if (greg < NGREGARG)
308  {
309  greg = NGREGARG;
310  continue;
311  }
312 #endif
313  memcpy (argp, *p_argv, z);
314  argp += n * sizeof (int);
315  }
316  }
317 
318  return;
319 }
320 
321 /* Perform machine dependent cif processing */
322 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
323 {
324  int i, j;
325  int size, type;
326  int n, m;
327  int greg;
328 #if defined(__SH4__)
329  int freg = 0;
330 #endif
331 
332  cif->flags = 0;
333 
334  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
336 
337 #if defined(__SH4__)
338  for (i = j = 0; i < cif->nargs && j < 12; i++)
339  {
340  type = (cif->arg_types)[i]->type;
341  switch (type)
342  {
343  case FFI_TYPE_FLOAT:
344  if (freg >= NFREGARG)
345  continue;
346  freg++;
347  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
348  j++;
349  break;
350 
351  case FFI_TYPE_DOUBLE:
352  if ((freg + 1) >= NFREGARG)
353  continue;
354  freg = (freg + 1) & ~1;
355  freg += 2;
356  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
357  j++;
358  break;
359 
360  default:
361  size = (cif->arg_types)[i]->size;
362  n = (size + sizeof (int) - 1) / sizeof (int);
363  if (greg + n - 1 >= NGREGARG)
364  continue;
365  greg += n;
366  for (m = 0; m < n; m++)
367  cif->flags += FFI_TYPE_INT << (2 * j++);
368  break;
369  }
370  }
371 #else
372  for (i = j = 0; i < cif->nargs && j < 4; i++)
373  {
374  size = (cif->arg_types)[i]->size;
375  n = (size + sizeof (int) - 1) / sizeof (int);
376  if (greg >= NGREGARG)
377  continue;
378  else if (greg + n - 1 >= NGREGARG)
379  n = NGREGARG - greg;
380  greg += n;
381  for (m = 0; m < n; m++)
382  cif->flags += FFI_TYPE_INT << (2 * j++);
383  }
384 #endif
385 
386  /* Set the return type flag */
387  switch (cif->rtype->type)
388  {
389  case FFI_TYPE_STRUCT:
390  cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
391  break;
392 
393  case FFI_TYPE_VOID:
394  case FFI_TYPE_FLOAT:
395  case FFI_TYPE_DOUBLE:
396  case FFI_TYPE_SINT64:
397  case FFI_TYPE_UINT64:
398  cif->flags += (unsigned) cif->rtype->type << 24;
399  break;
400 
401  default:
402  cif->flags += FFI_TYPE_INT << 24;
403  break;
404  }
405 
406  return FFI_OK;
407 }
408 
409 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
410  unsigned, unsigned, unsigned *, void (*fn)(void));
411 
412 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
413 {
414  extended_cif ecif;
415  UINT64 trvalue;
416 
417  ecif.cif = cif;
418  ecif.avalue = avalue;
419 
420  /* If the return value is a struct and we don't have a return */
421  /* value address then we need to make one */
422 
423  if (cif->rtype->type == FFI_TYPE_STRUCT
424  && return_type (cif->rtype) != FFI_TYPE_STRUCT)
425  ecif.rvalue = &trvalue;
426  else if ((rvalue == NULL) &&
427  (cif->rtype->type == FFI_TYPE_STRUCT))
428  {
429  ecif.rvalue = alloca(cif->rtype->size);
430  }
431  else
432  ecif.rvalue = rvalue;
433 
434  switch (cif->abi)
435  {
436  case FFI_SYSV:
437  ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
438  fn);
439  break;
440  default:
441  FFI_ASSERT(0);
442  break;
443  }
444 
445  if (rvalue
446  && cif->rtype->type == FFI_TYPE_STRUCT
447  && return_type (cif->rtype) != FFI_TYPE_STRUCT)
448  memcpy (rvalue, &trvalue, cif->rtype->size);
449 }
450 
451 extern void ffi_closure_SYSV (void);
452 #if defined(__SH4__)
453 extern void __ic_invalidate (void *line);
454 #endif
455 
456 ffi_status
457 ffi_prep_closure_loc (ffi_closure* closure,
458  ffi_cif* cif,
459  void (*fun)(ffi_cif*, void*, void**, void*),
460  void *user_data,
461  void *codeloc)
462 {
463  unsigned int *tramp;
464  unsigned int insn;
465 
466  if (cif->abi != FFI_SYSV)
467  return FFI_BAD_ABI;
468 
469  tramp = (unsigned int *) &closure->tramp[0];
470  /* Set T bit if the function returns a struct pointed with R2. */
471  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
472  ? 0x0018 /* sett */
473  : 0x0008 /* clrt */);
474 
475 #ifdef __LITTLE_ENDIAN__
476  tramp[0] = 0xd301d102;
477  tramp[1] = 0x0000412b | (insn << 16);
478 #else
479  tramp[0] = 0xd102d301;
480  tramp[1] = 0x412b0000 | insn;
481 #endif
482  *(void **) &tramp[2] = (void *)codeloc; /* ctx */
483  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
484 
485  closure->cif = cif;
486  closure->fun = fun;
487  closure->user_data = user_data;
488 
489 #if defined(__SH4__)
490  /* Flush the icache. */
491  __ic_invalidate(codeloc);
492 #endif
493 
494  return FFI_OK;
495 }
496 
497 /* Basically the trampoline invokes ffi_closure_SYSV, and on
498  * entry, r3 holds the address of the closure.
499  * After storing the registers that could possibly contain
500  * parameters to be passed into the stack frame and setting
501  * up space for a return value, ffi_closure_SYSV invokes the
502  * following helper function to do most of the work.
503  */
504 
505 #ifdef __LITTLE_ENDIAN__
506 #define OFS_INT8 0
507 #define OFS_INT16 0
508 #else
509 #define OFS_INT8 3
510 #define OFS_INT16 2
511 #endif
512 
513 int
514 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
515  unsigned long *pgr, unsigned long *pfr,
516  unsigned long *pst)
517 {
518  void **avalue;
519  ffi_type **p_arg;
520  int i, avn;
521  int ireg, greg = 0;
522 #if defined(__SH4__)
523  int freg = 0;
524 #endif
525  ffi_cif *cif;
526 
527  cif = closure->cif;
528  avalue = alloca(cif->nargs * sizeof(void *));
529 
530  /* Copy the caller's structure return value address so that the closure
531  returns the data directly to the caller. */
532  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
533  {
534  rvalue = (void *) *pgr++;
535  ireg = 1;
536  }
537  else
538  ireg = 0;
539 
540  cif = closure->cif;
541  greg = ireg;
542  avn = cif->nargs;
543 
544  /* Grab the addresses of the arguments from the stack frame. */
545  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
546  {
547  size_t z;
548 
549  z = (*p_arg)->size;
550  if (z < sizeof(int))
551  {
552  if (greg++ >= NGREGARG)
553  continue;
554 
555  z = sizeof(int);
556  switch ((*p_arg)->type)
557  {
558  case FFI_TYPE_SINT8:
559  case FFI_TYPE_UINT8:
560  avalue[i] = (((char *)pgr) + OFS_INT8);
561  break;
562 
563  case FFI_TYPE_SINT16:
564  case FFI_TYPE_UINT16:
565  avalue[i] = (((char *)pgr) + OFS_INT16);
566  break;
567 
568  case FFI_TYPE_STRUCT:
569  avalue[i] = pgr;
570  break;
571 
572  default:
573  FFI_ASSERT(0);
574  }
575  pgr++;
576  }
577  else if (z == sizeof(int))
578  {
579 #if defined(__SH4__)
580  if ((*p_arg)->type == FFI_TYPE_FLOAT)
581  {
582  if (freg++ >= NFREGARG)
583  continue;
584  avalue[i] = pfr;
585  pfr++;
586  }
587  else
588 #endif
589  {
590  if (greg++ >= NGREGARG)
591  continue;
592  avalue[i] = pgr;
593  pgr++;
594  }
595  }
596 #if defined(__SH4__)
597  else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
598  {
599  if (freg + 1 >= NFREGARG)
600  continue;
601  if (freg & 1)
602  pfr++;
603  freg = (freg + 1) & ~1;
604  freg += 2;
605  avalue[i] = pfr;
606  pfr += 2;
607  }
608 #endif
609  else
610  {
611  int n = (z + sizeof (int) - 1) / sizeof (int);
612 #if defined(__SH4__)
613  if (greg + n - 1 >= NGREGARG)
614  continue;
615 #else
616  if (greg >= NGREGARG)
617  continue;
618 #endif
619  greg += n;
620  avalue[i] = pgr;
621  pgr += n;
622  }
623  }
624 
625  greg = ireg;
626 #if defined(__SH4__)
627  freg = 0;
628 #endif
629 
630  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
631  {
632  size_t z;
633 
634  z = (*p_arg)->size;
635  if (z < sizeof(int))
636  {
637  if (greg++ < NGREGARG)
638  continue;
639 
640  z = sizeof(int);
641  switch ((*p_arg)->type)
642  {
643  case FFI_TYPE_SINT8:
644  case FFI_TYPE_UINT8:
645  avalue[i] = (((char *)pst) + OFS_INT8);
646  break;
647 
648  case FFI_TYPE_SINT16:
649  case FFI_TYPE_UINT16:
650  avalue[i] = (((char *)pst) + OFS_INT16);
651  break;
652 
653  case FFI_TYPE_STRUCT:
654  avalue[i] = pst;
655  break;
656 
657  default:
658  FFI_ASSERT(0);
659  }
660  pst++;
661  }
662  else if (z == sizeof(int))
663  {
664 #if defined(__SH4__)
665  if ((*p_arg)->type == FFI_TYPE_FLOAT)
666  {
667  if (freg++ < NFREGARG)
668  continue;
669  }
670  else
671 #endif
672  {
673  if (greg++ < NGREGARG)
674  continue;
675  }
676  avalue[i] = pst;
677  pst++;
678  }
679 #if defined(__SH4__)
680  else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
681  {
682  if (freg + 1 < NFREGARG)
683  {
684  freg = (freg + 1) & ~1;
685  freg += 2;
686  continue;
687  }
688  avalue[i] = pst;
689  pst += 2;
690  }
691 #endif
692  else
693  {
694  int n = (z + sizeof (int) - 1) / sizeof (int);
695  if (greg + n - 1 < NGREGARG)
696  {
697  greg += n;
698  continue;
699  }
700 #if (! defined(__SH4__))
701  else if (greg < NGREGARG)
702  {
703  greg += n;
704  pst += greg - NGREGARG;
705  continue;
706  }
707 #endif
708  avalue[i] = pst;
709  pst += n;
710  }
711  }
712 
713  (closure->fun) (cif, rvalue, avalue, closure->user_data);
714 
715  /* Tell ffi_closure_SYSV how to perform return type promotions. */
716  return return_type (cif->rtype);
717 }
NFREGARG
#define NFREGARG
Definition: ffi.c:34
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5464
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))
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5456
NGREGARG
#define NGREGARG
Definition: ffi.c:33
ffi_common.h
STRUCT_VALUE_ADDRESS_WITH_ARG
#define STRUCT_VALUE_ADDRESS_WITH_ARG
Definition: ffi.c:41
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5601
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
OFS_INT8
#define OFS_INT8
Definition: ffi.c:509
NULL
#define NULL
Definition: _sdbm.c:101
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
OFS_INT16
#define OFS_INT16
Definition: ffi.c:510
unsigned
#define unsigned
Definition: rb_mjit_min_header-2.7.1.h:2875
__ic_invalidate
void __ic_invalidate(void *line)
size
int size
Definition: encoding.c:58
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
extended_cif
Definition: ffi_common.h:86
ffi_closure_SYSV
void ffi_closure_SYSV(ffi_closure *)
Definition: ffi.c:420
ffi_closure_helper_SYSV
void ffi_closure_helper_SYSV(ffi_closure *, unsigned long *, unsigned long long *, unsigned long *)
Definition: ffi.c:553
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2839
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
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.1.h:2487
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