Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
3 
4  OpenRISC 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 /* ffi_prep_args is called by the assembly routine once stack space
31  has been allocated for the function's arguments */
32 
33 void* ffi_prep_args(char *stack, extended_cif *ecif)
34 {
35  char *stacktemp = stack;
36  int i, s;
37  ffi_type **arg;
38  int count = 0;
39  int nfixedargs;
40 
41  nfixedargs = ecif->cif->nfixedargs;
42  arg = ecif->cif->arg_types;
43  void **argv = ecif->avalue;
44 
45  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
46  {
47  *(void **) stack = ecif->rvalue;
48  stack += 4;
49  count = 4;
50  }
51  for(i=0; i<ecif->cif->nargs; i++)
52  {
53 
54  /* variadic args are saved on stack */
55  if ((nfixedargs == 0) && (count < 24))
56  {
57  count = 24;
58  stack = stacktemp + 24;
59  }
60  nfixedargs--;
61 
62  s = 4;
63  switch((*arg)->type)
64  {
65  case FFI_TYPE_STRUCT:
66  *(void **)stack = *argv;
67  break;
68 
69  case FFI_TYPE_SINT8:
70  *(signed int *) stack = (signed int)*(SINT8 *)(* argv);
71  break;
72 
73  case FFI_TYPE_UINT8:
74  *(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv);
75  break;
76 
77  case FFI_TYPE_SINT16:
78  *(signed int *) stack = (signed int)*(SINT16 *)(* argv);
79  break;
80 
81  case FFI_TYPE_UINT16:
82  *(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv);
83  break;
84 
85  case FFI_TYPE_SINT32:
86  case FFI_TYPE_UINT32:
87  case FFI_TYPE_FLOAT:
88  case FFI_TYPE_POINTER:
89  *(int *)stack = *(int*)(*argv);
90  break;
91 
92  default: /* 8 byte types */
93  if (count == 20) /* never split arguments */
94  {
95  stack += 4;
96  count += 4;
97  }
98  s = (*arg)->size;
99  memcpy(stack, *argv, s);
100  break;
101  }
102 
103  stack += s;
104  count += s;
105  argv++;
106  arg++;
107  }
108  return stacktemp + ((count>24)?24:0);
109 }
110 
111 extern void ffi_call_SYSV(unsigned,
112  extended_cif *,
113  void *(*)(int *, extended_cif *),
114  unsigned *,
115  void (*fn)(void),
116  unsigned);
117 
118 
119 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
120 {
121  int i;
122  int size;
123  ffi_type **arg;
124 
125  /* Calculate size to allocate on stack */
126 
127  for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++)
128  {
129  if ((*arg)->type == FFI_TYPE_STRUCT)
130  size += 4;
131  else
132  if ((*arg)->size <= 4)
133  size += 4;
134  else
135  size += 8;
136  }
137 
138  /* for variadic functions more space is needed on the stack */
139  if (cif->nargs != cif->nfixedargs)
140  size += 24;
141 
142  if (cif->rtype->type == FFI_TYPE_STRUCT)
143  size += 4;
144 
145 
146  extended_cif ecif;
147  ecif.cif = cif;
148  ecif.avalue = avalue;
149  ecif.rvalue = rvalue;
150 
151  switch (cif->abi)
152  {
153  case FFI_SYSV:
154  ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags);
155  break;
156  default:
157  FFI_ASSERT(0);
158  break;
159  }
160 }
161 
162 
163 void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
164  unsigned long r6, unsigned long r7, unsigned long r8)
165 {
166  register int *sp __asm__ ("r17");
167  register int *r13 __asm__ ("r13");
168 
169  ffi_closure* closure = (ffi_closure*) r13;
170  char *stack_args = sp;
171 
172  /* Lay the register arguments down in a continuous chunk of memory. */
173  unsigned register_args[6] =
174  { r3, r4, r5, r6, r7, r8 };
175 
176  /* Pointer to a struct return value. */
177  void *struct_rvalue = (void *) r3;
178 
179  ffi_cif *cif = closure->cif;
180  ffi_type **arg_types = cif->arg_types;
181  void **avalue = alloca (cif->nargs * sizeof(void *));
182  char *ptr = (char *) register_args;
183  int count = 0;
184  int nfixedargs = cif->nfixedargs;
185  int i;
186 
187  /* preserve struct type return pointer passing */
188 
189  if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
190  {
191  ptr += 4;
192  count = 4;
193  }
194 
195  /* Find the address of each argument. */
196  for (i = 0; i < cif->nargs; i++)
197  {
198 
199  /* variadic args are saved on stack */
200  if ((nfixedargs == 0) && (count < 24))
201  {
202  ptr = stack_args;
203  count = 24;
204  }
205  nfixedargs--;
206 
207  switch (arg_types[i]->type)
208  {
209  case FFI_TYPE_SINT8:
210  case FFI_TYPE_UINT8:
211  avalue[i] = ptr + 3;
212  break;
213 
214  case FFI_TYPE_SINT16:
215  case FFI_TYPE_UINT16:
216  avalue[i] = ptr + 2;
217  break;
218 
219  case FFI_TYPE_SINT32:
220  case FFI_TYPE_UINT32:
221  case FFI_TYPE_FLOAT:
222  case FFI_TYPE_POINTER:
223  avalue[i] = ptr;
224  break;
225 
226  case FFI_TYPE_STRUCT:
227  avalue[i] = *(void**)ptr;
228  break;
229 
230  default:
231  /* 8-byte values */
232 
233  /* arguments are never splitted */
234  if (ptr == &register_args[5])
235  ptr = stack_args;
236  avalue[i] = ptr;
237  ptr += 4;
238  count += 4;
239  break;
240  }
241  ptr += 4;
242  count += 4;
243 
244  /* If we've handled more arguments than fit in registers,
245  start looking at the those passed on the stack. */
246 
247  if (count == 24)
248  ptr = stack_args;
249  }
250 
251  if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
252  {
253  (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
254  } else
255  {
256  long long rvalue;
257  (closure->fun) (cif, &rvalue, avalue, closure->user_data);
258  if (cif->rtype)
259  asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue));
260  }
261 }
262 
263 
264 ffi_status
265 ffi_prep_closure_loc (ffi_closure* closure,
266  ffi_cif* cif,
267  void (*fun)(ffi_cif*,void*,void**,void*),
268  void *user_data,
269  void *codeloc)
270 {
271  unsigned short *tramp = (unsigned short *) closure->tramp;
272  unsigned long fn = (unsigned long) ffi_closure_SYSV;
273  unsigned long cls = (unsigned long) codeloc;
274 
275  if (cif->abi != FFI_SYSV)
276  return FFI_BAD_ABI;
277 
278  closure->cif = cif;
279  closure->user_data = user_data;
280  closure->fun = fun;
281 
282  /* write pointers to temporary registers */
283  tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */
284  tramp[1] = cls >> 16;
285  tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */
286  tramp[3] = cls & 0xFFFF;
287 
288  tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */
289  tramp[5] = fn >> 16;
290  tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */
291  tramp[7] = fn & 0xFFFF;
292 
293  tramp[8] = (0x11 << 10); /* l.jr r15 */
294  tramp[9] = 15 << 11;
295 
296  tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */
297  tramp[11] = 0x0;
298 
299  return FFI_OK;
300 }
301 
302 
303 ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
304 {
305  cif->flags = 0;
306 
307  /* structures are returned as pointers */
308  if (cif->rtype->type == FFI_TYPE_STRUCT)
309  cif->flags = FFI_TYPE_STRUCT;
310  else
311  if (cif->rtype->size > 4)
312  cif->flags = FFI_TYPE_UINT64;
313 
314  cif->nfixedargs = cif->nargs;
315 
316  return FFI_OK;
317 }
318 
319 
320 ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
321  unsigned int nfixedargs, unsigned int ntotalargs)
322 {
323  ffi_status status;
324 
325  status = ffi_prep_cif_machdep (cif);
326  cif->nfixedargs = nfixedargs;
327  return status;
328 }
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
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2880
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
ffi_common.h
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5601
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
ptr
struct RIMemo * ptr
Definition: debug.c:74
NULL
#define NULL
Definition: _sdbm.c:101
r3
#define r3
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
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
argv
char ** argv
Definition: ruby.c:223
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
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
ffi_prep_cif_machdep_var
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs)
Definition: ffi.c:289