Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 2000, 2007 Software AG
3  Copyright (c) 2008 Red Hat, Inc
4 
5  S390 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, EXPRESS
19  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  OTHER DEALINGS IN THE SOFTWARE.
25  ----------------------------------------------------------------------- */
26 /*====================================================================*/
27 /* Includes */
28 /* -------- */
29 /*====================================================================*/
30 
31 #include <ffi.h>
32 #include <ffi_common.h>
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 
37 /*====================== End of Includes =============================*/
38 
39 /*====================================================================*/
40 /* Defines */
41 /* ------- */
42 /*====================================================================*/
43 
44 /* Maximum number of GPRs available for argument passing. */
45 #define MAX_GPRARGS 5
46 
47 /* Maximum number of FPRs available for argument passing. */
48 #ifdef __s390x__
49 #define MAX_FPRARGS 4
50 #else
51 #define MAX_FPRARGS 2
52 #endif
53 
54 /* Round to multiple of 16. */
55 #define ROUND_SIZE(size) (((size) + 15) & ~15)
56 
57 /* If these values change, sysv.S must be adapted! */
58 #define FFI390_RET_VOID 0
59 #define FFI390_RET_STRUCT 1
60 #define FFI390_RET_FLOAT 2
61 #define FFI390_RET_DOUBLE 3
62 #define FFI390_RET_INT32 4
63 #define FFI390_RET_INT64 5
64 
65 /*===================== End of Defines ===============================*/
66 
67 /*====================================================================*/
68 /* Prototypes */
69 /* ---------- */
70 /*====================================================================*/
71 
72 static void ffi_prep_args (unsigned char *, extended_cif *);
73 void
74 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
75 __attribute__ ((visibility ("hidden")))
76 #endif
77 ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
78  unsigned long long *, unsigned long *);
79 
80 /*====================== End of Prototypes ===========================*/
81 
82 /*====================================================================*/
83 /* Externals */
84 /* --------- */
85 /*====================================================================*/
86 
87 extern void ffi_call_SYSV(unsigned,
88  extended_cif *,
89  void (*)(unsigned char *, extended_cif *),
90  unsigned,
91  void *,
92  void (*fn)(void));
93 
94 extern void ffi_closure_SYSV(void);
95 
96 /*====================== End of Externals ============================*/
97 
98 /*====================================================================*/
99 /* */
100 /* Name - ffi_check_struct_type. */
101 /* */
102 /* Function - Determine if a structure can be passed within a */
103 /* general purpose or floating point register. */
104 /* */
105 /*====================================================================*/
106 
107 static int
108 ffi_check_struct_type (ffi_type *arg)
109 {
110  size_t size = arg->size;
111 
112  /* If the struct has just one element, look at that element
113  to find out whether to consider the struct as floating point. */
114  while (arg->type == FFI_TYPE_STRUCT
115  && arg->elements[0] && !arg->elements[1])
116  arg = arg->elements[0];
117 
118  /* Structs of size 1, 2, 4, and 8 are passed in registers,
119  just like the corresponding int/float types. */
120  switch (size)
121  {
122  case 1:
123  return FFI_TYPE_UINT8;
124 
125  case 2:
126  return FFI_TYPE_UINT16;
127 
128  case 4:
129  if (arg->type == FFI_TYPE_FLOAT)
130  return FFI_TYPE_FLOAT;
131  else
132  return FFI_TYPE_UINT32;
133 
134  case 8:
135  if (arg->type == FFI_TYPE_DOUBLE)
136  return FFI_TYPE_DOUBLE;
137  else
138  return FFI_TYPE_UINT64;
139 
140  default:
141  break;
142  }
143 
144  /* Other structs are passed via a pointer to the data. */
145  return FFI_TYPE_POINTER;
146 }
147 
148 /*======================== End of Routine ============================*/
149 
150 /*====================================================================*/
151 /* */
152 /* Name - ffi_prep_args. */
153 /* */
154 /* Function - Prepare parameters for call to function. */
155 /* */
156 /* ffi_prep_args is called by the assembly routine once stack space */
157 /* has been allocated for the function's arguments. */
158 /* */
159 /*====================================================================*/
160 
161 static void
162 ffi_prep_args (unsigned char *stack, extended_cif *ecif)
163 {
164  /* The stack space will be filled with those areas:
165 
166  FPR argument register save area (highest addresses)
167  GPR argument register save area
168  temporary struct copies
169  overflow argument area (lowest addresses)
170 
171  We set up the following pointers:
172 
173  p_fpr: bottom of the FPR area (growing upwards)
174  p_gpr: bottom of the GPR area (growing upwards)
175  p_ov: bottom of the overflow area (growing upwards)
176  p_struct: top of the struct copy area (growing downwards)
177 
178  All areas are kept aligned to twice the word size. */
179 
180  int gpr_off = ecif->cif->bytes;
181  int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
182 
183  unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
184  unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
185  unsigned char *p_struct = (unsigned char *)p_gpr;
186  unsigned long *p_ov = (unsigned long *)stack;
187 
188  int n_fpr = 0;
189  int n_gpr = 0;
190  int n_ov = 0;
191 
192  ffi_type **ptr;
193  void **p_argv = ecif->avalue;
194  int i;
195 
196  /* If we returning a structure then we set the first parameter register
197  to the address of where we are returning this structure. */
198 
199  if (ecif->cif->flags == FFI390_RET_STRUCT)
200  p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
201 
202  /* Now for the arguments. */
203 
204  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
205  i > 0;
206  i--, ptr++, p_argv++)
207  {
208  void *arg = *p_argv;
209  int type = (*ptr)->type;
210 
211 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
212  /* 16-byte long double is passed like a struct. */
213  if (type == FFI_TYPE_LONGDOUBLE)
214  type = FFI_TYPE_STRUCT;
215 #endif
216 
217  /* Check how a structure type is passed. */
218  if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
219  {
220  if (type == FFI_TYPE_COMPLEX)
221  type = FFI_TYPE_POINTER;
222  else
223  type = ffi_check_struct_type (*ptr);
224 
225  /* If we pass the struct via pointer, copy the data. */
226  if (type == FFI_TYPE_POINTER)
227  {
228  p_struct -= ROUND_SIZE ((*ptr)->size);
229  memcpy (p_struct, (char *)arg, (*ptr)->size);
230  arg = &p_struct;
231  }
232  }
233 
234  /* Now handle all primitive int/pointer/float data types. */
235  switch (type)
236  {
237  case FFI_TYPE_DOUBLE:
238  if (n_fpr < MAX_FPRARGS)
239  p_fpr[n_fpr++] = *(unsigned long long *) arg;
240  else
241 #ifdef __s390x__
242  p_ov[n_ov++] = *(unsigned long *) arg;
243 #else
244  p_ov[n_ov++] = ((unsigned long *) arg)[0],
245  p_ov[n_ov++] = ((unsigned long *) arg)[1];
246 #endif
247  break;
248 
249  case FFI_TYPE_FLOAT:
250  if (n_fpr < MAX_FPRARGS)
251  p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
252  else
253  p_ov[n_ov++] = *(unsigned int *) arg;
254  break;
255 
256  case FFI_TYPE_POINTER:
257  if (n_gpr < MAX_GPRARGS)
258  p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
259  else
260  p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
261  break;
262 
263  case FFI_TYPE_UINT64:
264  case FFI_TYPE_SINT64:
265 #ifdef __s390x__
266  if (n_gpr < MAX_GPRARGS)
267  p_gpr[n_gpr++] = *(unsigned long *) arg;
268  else
269  p_ov[n_ov++] = *(unsigned long *) arg;
270 #else
271  if (n_gpr == MAX_GPRARGS-1)
272  n_gpr = MAX_GPRARGS;
273  if (n_gpr < MAX_GPRARGS)
274  p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
275  p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
276  else
277  p_ov[n_ov++] = ((unsigned long *) arg)[0],
278  p_ov[n_ov++] = ((unsigned long *) arg)[1];
279 #endif
280  break;
281 
282  case FFI_TYPE_UINT32:
283  if (n_gpr < MAX_GPRARGS)
284  p_gpr[n_gpr++] = *(unsigned int *) arg;
285  else
286  p_ov[n_ov++] = *(unsigned int *) arg;
287  break;
288 
289  case FFI_TYPE_INT:
290  case FFI_TYPE_SINT32:
291  if (n_gpr < MAX_GPRARGS)
292  p_gpr[n_gpr++] = *(signed int *) arg;
293  else
294  p_ov[n_ov++] = *(signed int *) arg;
295  break;
296 
297  case FFI_TYPE_UINT16:
298  if (n_gpr < MAX_GPRARGS)
299  p_gpr[n_gpr++] = *(unsigned short *) arg;
300  else
301  p_ov[n_ov++] = *(unsigned short *) arg;
302  break;
303 
304  case FFI_TYPE_SINT16:
305  if (n_gpr < MAX_GPRARGS)
306  p_gpr[n_gpr++] = *(signed short *) arg;
307  else
308  p_ov[n_ov++] = *(signed short *) arg;
309  break;
310 
311  case FFI_TYPE_UINT8:
312  if (n_gpr < MAX_GPRARGS)
313  p_gpr[n_gpr++] = *(unsigned char *) arg;
314  else
315  p_ov[n_ov++] = *(unsigned char *) arg;
316  break;
317 
318  case FFI_TYPE_SINT8:
319  if (n_gpr < MAX_GPRARGS)
320  p_gpr[n_gpr++] = *(signed char *) arg;
321  else
322  p_ov[n_ov++] = *(signed char *) arg;
323  break;
324 
325  default:
326  FFI_ASSERT (0);
327  break;
328  }
329  }
330 }
331 
332 /*======================== End of Routine ============================*/
333 
334 /*====================================================================*/
335 /* */
336 /* Name - ffi_prep_cif_machdep. */
337 /* */
338 /* Function - Perform machine dependent CIF processing. */
339 /* */
340 /*====================================================================*/
341 
342 ffi_status
343 ffi_prep_cif_machdep(ffi_cif *cif)
344 {
345  size_t struct_size = 0;
346  int n_gpr = 0;
347  int n_fpr = 0;
348  int n_ov = 0;
349 
350  ffi_type **ptr;
351  int i;
352 
353  /* Determine return value handling. */
354 
355  switch (cif->rtype->type)
356  {
357  /* Void is easy. */
358  case FFI_TYPE_VOID:
359  cif->flags = FFI390_RET_VOID;
360  break;
361 
362  /* Structures and complex are returned via a hidden pointer. */
363  case FFI_TYPE_STRUCT:
364  case FFI_TYPE_COMPLEX:
365  cif->flags = FFI390_RET_STRUCT;
366  n_gpr++; /* We need one GPR to pass the pointer. */
367  break;
368 
369  /* Floating point values are returned in fpr 0. */
370  case FFI_TYPE_FLOAT:
371  cif->flags = FFI390_RET_FLOAT;
372  break;
373 
374  case FFI_TYPE_DOUBLE:
375  cif->flags = FFI390_RET_DOUBLE;
376  break;
377 
378 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
379  case FFI_TYPE_LONGDOUBLE:
380  cif->flags = FFI390_RET_STRUCT;
381  n_gpr++;
382  break;
383 #endif
384  /* Integer values are returned in gpr 2 (and gpr 3
385  for 64-bit values on 31-bit machines). */
386  case FFI_TYPE_UINT64:
387  case FFI_TYPE_SINT64:
388  cif->flags = FFI390_RET_INT64;
389  break;
390 
391  case FFI_TYPE_POINTER:
392  case FFI_TYPE_INT:
393  case FFI_TYPE_UINT32:
394  case FFI_TYPE_SINT32:
395  case FFI_TYPE_UINT16:
396  case FFI_TYPE_SINT16:
397  case FFI_TYPE_UINT8:
398  case FFI_TYPE_SINT8:
399  /* These are to be extended to word size. */
400 #ifdef __s390x__
401  cif->flags = FFI390_RET_INT64;
402 #else
403  cif->flags = FFI390_RET_INT32;
404 #endif
405  break;
406 
407  default:
408  FFI_ASSERT (0);
409  break;
410  }
411 
412  /* Now for the arguments. */
413 
414  for (ptr = cif->arg_types, i = cif->nargs;
415  i > 0;
416  i--, ptr++)
417  {
418  int type = (*ptr)->type;
419 
420 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
421  /* 16-byte long double is passed like a struct. */
422  if (type == FFI_TYPE_LONGDOUBLE)
423  type = FFI_TYPE_STRUCT;
424 #endif
425 
426  /* Check how a structure type is passed. */
427  if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
428  {
429  if (type == FFI_TYPE_COMPLEX)
430  type = FFI_TYPE_POINTER;
431  else
432  type = ffi_check_struct_type (*ptr);
433 
434  /* If we pass the struct via pointer, we must reserve space
435  to copy its data for proper call-by-value semantics. */
436  if (type == FFI_TYPE_POINTER)
437  struct_size += ROUND_SIZE ((*ptr)->size);
438  }
439 
440  /* Now handle all primitive int/float data types. */
441  switch (type)
442  {
443  /* The first MAX_FPRARGS floating point arguments
444  go in FPRs, the rest overflow to the stack. */
445 
446  case FFI_TYPE_DOUBLE:
447  if (n_fpr < MAX_FPRARGS)
448  n_fpr++;
449  else
450  n_ov += sizeof (double) / sizeof (long);
451  break;
452 
453  case FFI_TYPE_FLOAT:
454  if (n_fpr < MAX_FPRARGS)
455  n_fpr++;
456  else
457  n_ov++;
458  break;
459 
460  /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
461  if one is still available, or else on the stack. If only one
462  register is free, skip the register (it won't be used for any
463  subsequent argument either). */
464 
465 #ifndef __s390x__
466  case FFI_TYPE_UINT64:
467  case FFI_TYPE_SINT64:
468  if (n_gpr == MAX_GPRARGS-1)
469  n_gpr = MAX_GPRARGS;
470  if (n_gpr < MAX_GPRARGS)
471  n_gpr += 2;
472  else
473  n_ov += 2;
474  break;
475 #endif
476 
477  /* Everything else is passed in GPRs (until MAX_GPRARGS
478  have been used) or overflows to the stack. */
479 
480  default:
481  if (n_gpr < MAX_GPRARGS)
482  n_gpr++;
483  else
484  n_ov++;
485  break;
486  }
487  }
488 
489  /* Total stack space as required for overflow arguments
490  and temporary structure copies. */
491 
492  cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
493 
494  return FFI_OK;
495 }
496 
497 /*======================== End of Routine ============================*/
498 
499 /*====================================================================*/
500 /* */
501 /* Name - ffi_call. */
502 /* */
503 /* Function - Call the FFI routine. */
504 /* */
505 /*====================================================================*/
506 
507 void
508 ffi_call(ffi_cif *cif,
509  void (*fn)(void),
510  void *rvalue,
511  void **avalue)
512 {
513  int ret_type = cif->flags;
514  extended_cif ecif;
515 
516  ecif.cif = cif;
517  ecif.avalue = avalue;
518  ecif.rvalue = rvalue;
519 
520  /* If we don't have a return value, we need to fake one. */
521  if (rvalue == NULL)
522  {
523  if (ret_type == FFI390_RET_STRUCT)
524  ecif.rvalue = alloca (cif->rtype->size);
525  else
526  ret_type = FFI390_RET_VOID;
527  }
528 
529  switch (cif->abi)
530  {
531  case FFI_SYSV:
532  ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
533  ret_type, ecif.rvalue, fn);
534  break;
535 
536  default:
537  FFI_ASSERT (0);
538  break;
539  }
540 }
541 
542 /*======================== End of Routine ============================*/
543 
544 /*====================================================================*/
545 /* */
546 /* Name - ffi_closure_helper_SYSV. */
547 /* */
548 /* Function - Call a FFI closure target function. */
549 /* */
550 /*====================================================================*/
551 
552 void
553 ffi_closure_helper_SYSV (ffi_closure *closure,
554  unsigned long *p_gpr,
555  unsigned long long *p_fpr,
556  unsigned long *p_ov)
557 {
558  unsigned long long ret_buffer;
559 
560  void *rvalue = &ret_buffer;
561  void **avalue;
562  void **p_arg;
563 
564  int n_gpr = 0;
565  int n_fpr = 0;
566  int n_ov = 0;
567 
568  ffi_type **ptr;
569  int i;
570 
571  /* Allocate buffer for argument list pointers. */
572 
573  p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
574 
575  /* If we returning a structure, pass the structure address
576  directly to the target function. Otherwise, have the target
577  function store the return value to the GPR save area. */
578 
579  if (closure->cif->flags == FFI390_RET_STRUCT)
580  rvalue = (void *) p_gpr[n_gpr++];
581 
582  /* Now for the arguments. */
583 
584  for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
585  i > 0;
586  i--, p_arg++, ptr++)
587  {
588  int deref_struct_pointer = 0;
589  int type = (*ptr)->type;
590 
591 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
592  /* 16-byte long double is passed like a struct. */
593  if (type == FFI_TYPE_LONGDOUBLE)
594  type = FFI_TYPE_STRUCT;
595 #endif
596 
597  /* Check how a structure type is passed. */
598  if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
599  {
600  if (type == FFI_TYPE_COMPLEX)
601  type = FFI_TYPE_POINTER;
602  else
603  type = ffi_check_struct_type (*ptr);
604 
605  /* If we pass the struct via pointer, remember to
606  retrieve the pointer later. */
607  if (type == FFI_TYPE_POINTER)
608  deref_struct_pointer = 1;
609  }
610 
611  /* Pointers are passed like UINTs of the same size. */
612  if (type == FFI_TYPE_POINTER)
613 #ifdef __s390x__
614  type = FFI_TYPE_UINT64;
615 #else
616  type = FFI_TYPE_UINT32;
617 #endif
618 
619  /* Now handle all primitive int/float data types. */
620  switch (type)
621  {
622  case FFI_TYPE_DOUBLE:
623  if (n_fpr < MAX_FPRARGS)
624  *p_arg = &p_fpr[n_fpr++];
625  else
626  *p_arg = &p_ov[n_ov],
627  n_ov += sizeof (double) / sizeof (long);
628  break;
629 
630  case FFI_TYPE_FLOAT:
631  if (n_fpr < MAX_FPRARGS)
632  *p_arg = &p_fpr[n_fpr++];
633  else
634  *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
635  break;
636 
637  case FFI_TYPE_UINT64:
638  case FFI_TYPE_SINT64:
639 #ifdef __s390x__
640  if (n_gpr < MAX_GPRARGS)
641  *p_arg = &p_gpr[n_gpr++];
642  else
643  *p_arg = &p_ov[n_ov++];
644 #else
645  if (n_gpr == MAX_GPRARGS-1)
646  n_gpr = MAX_GPRARGS;
647  if (n_gpr < MAX_GPRARGS)
648  *p_arg = &p_gpr[n_gpr], n_gpr += 2;
649  else
650  *p_arg = &p_ov[n_ov], n_ov += 2;
651 #endif
652  break;
653 
654  case FFI_TYPE_INT:
655  case FFI_TYPE_UINT32:
656  case FFI_TYPE_SINT32:
657  if (n_gpr < MAX_GPRARGS)
658  *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
659  else
660  *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
661  break;
662 
663  case FFI_TYPE_UINT16:
664  case FFI_TYPE_SINT16:
665  if (n_gpr < MAX_GPRARGS)
666  *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
667  else
668  *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
669  break;
670 
671  case FFI_TYPE_UINT8:
672  case FFI_TYPE_SINT8:
673  if (n_gpr < MAX_GPRARGS)
674  *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
675  else
676  *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
677  break;
678 
679  default:
680  FFI_ASSERT (0);
681  break;
682  }
683 
684  /* If this is a struct passed via pointer, we need to
685  actually retrieve that pointer. */
686  if (deref_struct_pointer)
687  *p_arg = *(void **)*p_arg;
688  }
689 
690 
691  /* Call the target function. */
692  (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
693 
694  /* Convert the return value. */
695  switch (closure->cif->rtype->type)
696  {
697  /* Void is easy, and so is struct. */
698  case FFI_TYPE_VOID:
699  case FFI_TYPE_STRUCT:
700  case FFI_TYPE_COMPLEX:
701 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
702  case FFI_TYPE_LONGDOUBLE:
703 #endif
704  break;
705 
706  /* Floating point values are returned in fpr 0. */
707  case FFI_TYPE_FLOAT:
708  p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
709  break;
710 
711  case FFI_TYPE_DOUBLE:
712  p_fpr[0] = *(unsigned long long *) rvalue;
713  break;
714 
715  /* Integer values are returned in gpr 2 (and gpr 3
716  for 64-bit values on 31-bit machines). */
717  case FFI_TYPE_UINT64:
718  case FFI_TYPE_SINT64:
719 #ifdef __s390x__
720  p_gpr[0] = *(unsigned long *) rvalue;
721 #else
722  p_gpr[0] = ((unsigned long *) rvalue)[0],
723  p_gpr[1] = ((unsigned long *) rvalue)[1];
724 #endif
725  break;
726 
727  case FFI_TYPE_POINTER:
728  case FFI_TYPE_UINT32:
729  case FFI_TYPE_UINT16:
730  case FFI_TYPE_UINT8:
731  p_gpr[0] = *(unsigned long *) rvalue;
732  break;
733 
734  case FFI_TYPE_INT:
735  case FFI_TYPE_SINT32:
736  case FFI_TYPE_SINT16:
737  case FFI_TYPE_SINT8:
738  p_gpr[0] = *(signed long *) rvalue;
739  break;
740 
741  default:
742  FFI_ASSERT (0);
743  break;
744  }
745 }
746 
747 /*======================== End of Routine ============================*/
748 
749 /*====================================================================*/
750 /* */
751 /* Name - ffi_prep_closure_loc. */
752 /* */
753 /* Function - Prepare a FFI closure. */
754 /* */
755 /*====================================================================*/
756 
757 ffi_status
758 ffi_prep_closure_loc (ffi_closure *closure,
759  ffi_cif *cif,
760  void (*fun) (ffi_cif *, void *, void **, void *),
761  void *user_data,
762  void *codeloc)
763 {
764  if (cif->abi != FFI_SYSV)
765  return FFI_BAD_ABI;
766 
767 #ifndef __s390x__
768  *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
769  *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
770  *(short *)&closure->tramp [4] = 0x1006;
771  *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
772  *(long *)&closure->tramp [8] = (long)codeloc;
773  *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
774 #else
775  *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
776  *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
777  *(short *)&closure->tramp [4] = 0x100e;
778  *(short *)&closure->tramp [6] = 0x0004;
779  *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
780  *(long *)&closure->tramp[16] = (long)codeloc;
781  *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
782 #endif
783 
784  closure->cif = cif;
785  closure->user_data = user_data;
786  closure->fun = fun;
787 
788  return FFI_OK;
789 }
790 
791 /*======================== End of Routine ============================*/
792 
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
FFI390_RET_INT64
#define FFI390_RET_INT64
Definition: ffi.c:63
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2848
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))
double
double
Definition: rb_mjit_min_header-2.7.1.h:5884
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
ffi_common.h
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5562
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
ptr
struct RIMemo * ptr
Definition: debug.c:74
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
FFI390_RET_DOUBLE
#define FFI390_RET_DOUBLE
Definition: ffi.c:61
FFI390_RET_STRUCT
#define FFI390_RET_STRUCT
Definition: ffi.c:59
FFI390_RET_INT32
#define FFI390_RET_INT32
Definition: ffi.c:62
MAX_GPRARGS
#define MAX_GPRARGS
Definition: ffi.c:45
size
int size
Definition: encoding.c:58
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
MAX_FPRARGS
#define MAX_FPRARGS
Definition: ffi.c:51
extended_cif
Definition: ffi_common.h:86
ffi_closure_SYSV
void ffi_closure_SYSV(ffi_closure *)
Definition: ffi.c:420
ROUND_SIZE
#define ROUND_SIZE(size)
Definition: ffi.c:55
FFI390_RET_FLOAT
#define FFI390_RET_FLOAT
Definition: ffi.c:60
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
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
FFI390_RET_VOID
#define FFI390_RET_VOID
Definition: ffi.c:58
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:2455
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