Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (C) 2012, 2013 Anthony Green
3 
4  Moxie Foreign Function Interface
5 
6  Permission is hereby granted, free of charge, to any person obtaining
7  a copy of this software and associated documentation files (the
8  ``Software''), to deal in the Software without restriction, including
9  without limitation the rights to use, copy, modify, merge, publish,
10  distribute, sublicense, and/or sell copies of the Software, and to
11  permit persons to whom the Software is furnished to do so, subject to
12  the following conditions:
13 
14  The above copyright notice and this permission notice shall be included
15  in all copies or substantial portions of the Software.
16 
17  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  DEALINGS IN THE SOFTWARE.
25  ----------------------------------------------------------------------- */
26 
27 #include <ffi.h>
28 #include <ffi_common.h>
29 
30 #include <stdlib.h>
31 
32 /* ffi_prep_args is called by the assembly routine once stack space
33  has been allocated for the function's arguments */
34 
35 void *ffi_prep_args(char *stack, extended_cif *ecif)
36 {
37  register unsigned int i;
38  register void **p_argv;
39  register char *argp;
40  register ffi_type **p_arg;
41  register int count = 0;
42 
43  p_argv = ecif->avalue;
44  argp = stack;
45 
46  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
47  {
48  *(void **) argp = ecif->rvalue;
49  argp += 4;
50  }
51 
52  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
53  (i != 0);
54  i--, p_arg++)
55  {
56  size_t z;
57 
58  z = (*p_arg)->size;
59 
60  if ((*p_arg)->type == FFI_TYPE_STRUCT)
61  {
62  z = sizeof(void*);
63  *(void **) argp = *p_argv;
64  }
65  else if (z < sizeof(int))
66  {
67  z = sizeof(int);
68  switch ((*p_arg)->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  default:
87  FFI_ASSERT(0);
88  }
89  }
90  else if (z == sizeof(int))
91  {
92  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
93  }
94  else
95  {
96  memcpy(argp, *p_argv, z);
97  }
98  p_argv++;
99  argp += z;
100  count += z;
101  }
102 
103  return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
104 }
105 
106 /* Perform machine dependent cif processing */
107 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
108 {
109  if (cif->rtype->type == FFI_TYPE_STRUCT)
110  cif->flags = -1;
111  else
112  cif->flags = cif->rtype->size;
113 
114  cif->bytes = ALIGN (cif->bytes, 8);
115 
116  return FFI_OK;
117 }
118 
119 extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
120  extended_cif *,
121  unsigned, unsigned,
122  unsigned *,
123  void (*fn)(void));
124 
125 void ffi_call(ffi_cif *cif,
126  void (*fn)(void),
127  void *rvalue,
128  void **avalue)
129 {
130  extended_cif ecif;
131 
132  ecif.cif = cif;
133  ecif.avalue = avalue;
134 
135  /* If the return value is a struct and we don't have a return */
136  /* value address then we need to make one */
137 
138  if ((rvalue == NULL) &&
139  (cif->rtype->type == FFI_TYPE_STRUCT))
140  {
141  ecif.rvalue = alloca(cif->rtype->size);
142  }
143  else
144  ecif.rvalue = rvalue;
145 
146  switch (cif->abi)
147  {
148  case FFI_EABI:
149  ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
150  cif->flags, ecif.rvalue, fn);
151  break;
152  default:
153  FFI_ASSERT(0);
154  break;
155  }
156 }
157 
158 void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
159  unsigned arg4, unsigned arg5, unsigned arg6)
160 {
161  /* This function is called by a trampoline. The trampoline stows a
162  pointer to the ffi_closure object in $r7. We must save this
163  pointer in a place that will persist while we do our work. */
164  register ffi_closure *creg __asm__ ("$r12");
165  ffi_closure *closure = creg;
166 
167  /* Arguments that don't fit in registers are found on the stack
168  at a fixed offset above the current frame pointer. */
169  register char *frame_pointer __asm__ ("$fp");
170 
171  /* Pointer to a struct return value. */
172  void *struct_rvalue = (void *) arg1;
173 
174  /* 6 words reserved for register args + 3 words from jsr */
175  char *stack_args = frame_pointer + 9*4;
176 
177  /* Lay the register arguments down in a continuous chunk of memory. */
178  unsigned register_args[6] =
179  { arg1, arg2, arg3, arg4, arg5, arg6 };
180  char *register_args_ptr = (char *) register_args;
181 
182  ffi_cif *cif = closure->cif;
183  ffi_type **arg_types = cif->arg_types;
184  void **avalue = alloca (cif->nargs * sizeof(void *));
185  char *ptr = (char *) register_args;
186  int i;
187 
188  /* preserve struct type return pointer passing */
189  if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
190  ptr += 4;
191  register_args_ptr = (char *)&register_args[1];
192  }
193 
194  /* Find the address of each argument. */
195  for (i = 0; i < cif->nargs; i++)
196  {
197  switch (arg_types[i]->type)
198  {
199  case FFI_TYPE_SINT8:
200  case FFI_TYPE_UINT8:
201  avalue[i] = ptr + 3;
202  break;
203  case FFI_TYPE_SINT16:
204  case FFI_TYPE_UINT16:
205  avalue[i] = ptr + 2;
206  break;
207  case FFI_TYPE_SINT32:
208  case FFI_TYPE_UINT32:
209  case FFI_TYPE_FLOAT:
210  case FFI_TYPE_POINTER:
211  avalue[i] = ptr;
212  break;
213  case FFI_TYPE_STRUCT:
214  avalue[i] = *(void**)ptr;
215  break;
216  default:
217  /* This is an 8-byte value. */
218  avalue[i] = ptr;
219  ptr += 4;
220  break;
221  }
222  ptr += 4;
223 
224  /* If we've handled more arguments than fit in registers,
225  start looking at the those passed on the stack. */
226  if (ptr == &register_args[6])
227  ptr = stack_args;
228  }
229 
230  /* Invoke the closure. */
231  if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
232  {
233  (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
234  }
235  else
236  {
237  /* Allocate space for the return value and call the function. */
238  long long rvalue;
239  (closure->fun) (cif, &rvalue, avalue, closure->user_data);
240  asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue));
241  }
242 }
243 
244 ffi_status
245 ffi_prep_closure_loc (ffi_closure* closure,
246  ffi_cif* cif,
247  void (*fun)(ffi_cif*, void*, void**, void*),
248  void *user_data,
249  void *codeloc)
250 {
251  unsigned short *tramp = (unsigned short *) &closure->tramp[0];
252  unsigned long fn = (long) ffi_closure_eabi;
253  unsigned long cls = (long) codeloc;
254 
255  if (cif->abi != FFI_EABI)
256  return FFI_BAD_ABI;
257 
258  fn = (unsigned long) ffi_closure_eabi;
259 
260  tramp[0] = 0x01e0; /* ldi.l $r7, .... */
261  tramp[1] = cls >> 16;
262  tramp[2] = cls & 0xffff;
263  tramp[3] = 0x1a00; /* jmpa .... */
264  tramp[4] = fn >> 16;
265  tramp[5] = fn & 0xffff;
266 
267  closure->cif = cif;
268  closure->fun = fun;
269  closure->user_data = user_data;
270 
271  return FFI_OK;
272 }
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
FFI_EABI
@ FFI_EABI
Definition: ffitarget.h:43
ffi_call_EABI
void ffi_call_EABI(void *(*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void(*fn)(void))
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
long
#define long
Definition: rb_mjit_min_header-2.7.2.h:2921
ffi_common.h
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.2.h:2525
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
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
ffi_closure_eabi
void ffi_closure_eabi(unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5, unsigned arg6)
Definition: ffi.c:166
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
extended_cif
Definition: ffi_common.h:87
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
__asm__
#define __asm__
Definition: Context.c:12
count
int count
Definition: encoding.c:57
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
ALIGN_DOWN
#define ALIGN_DOWN(v, a)
Definition: ffi_common.h:78
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39