Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
3 
4  ARC 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, EXPRESS
18  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  OTHER DEALINGS IN THE SOFTWARE.
24  ----------------------------------------------------------------------- */
25 
26 #include <ffi.h>
27 #include <ffi_common.h>
28 
29 #include <stdlib.h>
30 #include <stdint.h>
31 
32 #include <sys/cachectl.h>
33 
34 /* for little endian ARC, the code is in fact stored as mixed endian for
35  performance reasons */
36 #if __BIG_ENDIAN__
37 #define CODE_ENDIAN(x) (x)
38 #else
39 #define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
40 #endif
41 
42 /* ffi_prep_args is called by the assembly routine once stack
43  space has been allocated for the function's arguments. */
44 
45 void
46 ffi_prep_args (char *stack, extended_cif * ecif)
47 {
48  unsigned int i;
49  int tmp;
50  void **p_argv;
51  char *argp;
52  ffi_type **p_arg;
53 
54  tmp = 0;
55  argp = stack;
56 
57  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
58  {
59  *(void **) argp = ecif->rvalue;
60  argp += 4;
61  }
62 
63  p_argv = ecif->avalue;
64 
65  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
66  (i != 0); i--, p_arg++)
67  {
68  size_t z;
69  int alignment;
70 
71  /* align alignment to 4 */
72  alignment = (((*p_arg)->alignment - 1) | 3) + 1;
73 
74  /* Align if necessary. */
75  if ((alignment - 1) & (unsigned) argp)
76  argp = (char *) ALIGN (argp, alignment);
77 
78  z = (*p_arg)->size;
79  if (z < sizeof (int))
80  {
81  z = sizeof (int);
82 
83  switch ((*p_arg)->type)
84  {
85  case FFI_TYPE_SINT8:
86  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
87  break;
88 
89  case FFI_TYPE_UINT8:
90  *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
91  break;
92 
93  case FFI_TYPE_SINT16:
94  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
95  break;
96 
97  case FFI_TYPE_UINT16:
98  *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
99  break;
100 
101  case FFI_TYPE_STRUCT:
102  memcpy (argp, *p_argv, (*p_arg)->size);
103  break;
104 
105  default:
106  FFI_ASSERT (0);
107  }
108  }
109  else if (z == sizeof (int))
110  {
111  *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
112  }
113  else
114  {
115  if ((*p_arg)->type == FFI_TYPE_STRUCT)
116  {
117  memcpy (argp, *p_argv, z);
118  }
119  else
120  {
121  /* Double or long long 64bit. */
122  memcpy (argp, *p_argv, z);
123  }
124  }
125  p_argv++;
126  argp += z;
127  }
128 
129  return;
130 }
131 
132 /* Perform machine dependent cif processing. */
133 ffi_status
134 ffi_prep_cif_machdep (ffi_cif * cif)
135 {
136  /* Set the return type flag. */
137  switch (cif->rtype->type)
138  {
139  case FFI_TYPE_VOID:
140  cif->flags = (unsigned) cif->rtype->type;
141  break;
142 
143  case FFI_TYPE_STRUCT:
144  cif->flags = (unsigned) cif->rtype->type;
145  break;
146 
147  case FFI_TYPE_SINT64:
148  case FFI_TYPE_UINT64:
149  case FFI_TYPE_DOUBLE:
150  cif->flags = FFI_TYPE_DOUBLE;
151  break;
152 
153  case FFI_TYPE_FLOAT:
154  default:
155  cif->flags = FFI_TYPE_INT;
156  break;
157  }
158 
159  return FFI_OK;
160 }
161 
162 extern void ffi_call_ARCompact (void (*)(char *, extended_cif *),
163  extended_cif *, unsigned, unsigned,
164  unsigned *, void (*fn) (void));
165 
166 void
167 ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
168 {
169  extended_cif ecif;
170 
171  ecif.cif = cif;
172  ecif.avalue = avalue;
173 
174  /* If the return value is a struct and we don't have
175  a return value address then we need to make one. */
176  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
177  {
178  ecif.rvalue = alloca (cif->rtype->size);
179  }
180  else
181  ecif.rvalue = rvalue;
182 
183  switch (cif->abi)
184  {
185  case FFI_ARCOMPACT:
186  ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
187  cif->flags, ecif.rvalue, fn);
188  break;
189 
190  default:
191  FFI_ASSERT (0);
192  break;
193  }
194 }
195 
196 int
197 ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
198  ffi_arg * args)
199 {
200  void **arg_area, **p_argv;
201  ffi_cif *cif = closure->cif;
202  char *argp = (char *) args;
203  ffi_type **p_argt;
204  int i;
205 
206  arg_area = (void **) alloca (cif->nargs * sizeof (void *));
207 
208  /* handle hidden argument */
209  if (cif->flags == FFI_TYPE_STRUCT)
210  {
211  rvalue = *(void **) argp;
212  argp += 4;
213  }
214 
215  p_argv = arg_area;
216 
217  for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
218  i++, p_argt++, p_argv++)
219  {
220  size_t z;
221  int alignment;
222 
223  /* align alignment to 4 */
224  alignment = (((*p_argt)->alignment - 1) | 3) + 1;
225 
226  /* Align if necessary. */
227  if ((alignment - 1) & (unsigned) argp)
228  argp = (char *) ALIGN (argp, alignment);
229 
230  z = (*p_argt)->size;
231  *p_argv = (void *) argp;
232  argp += z;
233  }
234 
235  (closure->fun) (cif, rvalue, arg_area, closure->user_data);
236 
237  return cif->flags;
238 }
239 
240 extern void ffi_closure_ARCompact (void);
241 
242 ffi_status
243 ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
244  void (*fun) (ffi_cif *, void *, void **, void *),
245  void *user_data, void *codeloc)
246 {
247  uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
248 
249  switch (cif->abi)
250  {
251  case FFI_ARCOMPACT:
252  FFI_ASSERT (tramp == codeloc);
253  tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */
254  tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */
255  tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
256  break;
257 
258  default:
259  return FFI_BAD_ABI;
260  }
261 
262  closure->cif = cif;
263  closure->fun = fun;
264  closure->user_data = user_data;
265  cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
266 
267  return FFI_OK;
268 }
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
ffi_arg
unsigned long ffi_arg
Definition: ffitarget.h:30
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
CODE_ENDIAN
#define CODE_ENDIAN(x)
Definition: ffi.c:39
ffi_common.h
FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE
Definition: ffitarget.h:45
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_call_ARCompact
void ffi_call_ARCompact(void(*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void(*fn)(void))
ffi_closure_inner_ARCompact
int ffi_closure_inner_ARCompact(ffi_closure *closure, void *rvalue, ffi_arg *args)
Definition: ffi.c:197
ALIGN
#define ALIGN(v, a)
Definition: ffi_common.h:77
NULL
#define NULL
Definition: _sdbm.c:101
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
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)
FFI_ARCOMPACT
@ FFI_ARCOMPACT
Definition: ffitarget.h:43
ffi_closure_ARCompact
void ffi_closure_ARCompact(void)
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