Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 2004 Renesas Technology
3  Copyright (c) 2008 Red Hat, Inc.
4 
5  M32R 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 RENESAS TECHNOLOGY 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 #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
33  space has been allocated for the function's arguments. */
34 
35 void ffi_prep_args(char *stack, extended_cif *ecif)
36 {
37  unsigned int i;
38  int tmp;
39  unsigned int avn;
40  void **p_argv;
41  char *argp;
42  ffi_type **p_arg;
43 
44  tmp = 0;
45  argp = stack;
46 
47  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
48  {
49  *(void **) argp = ecif->rvalue;
50  argp += 4;
51  }
52 
53  avn = ecif->cif->nargs;
54  p_argv = ecif->avalue;
55 
56  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
57  (i != 0) && (avn != 0);
58  i--, p_arg++)
59  {
60  size_t z;
61 
62  /* Align if necessary. */
63  if (((*p_arg)->alignment - 1) & (unsigned) argp)
64  argp = (char *) ALIGN (argp, (*p_arg)->alignment);
65 
66  if (avn != 0)
67  {
68  avn--;
69  z = (*p_arg)->size;
70  if (z < sizeof (int))
71  {
72  z = sizeof (int);
73 
74  switch ((*p_arg)->type)
75  {
76  case FFI_TYPE_SINT8:
77  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
78  break;
79 
80  case FFI_TYPE_UINT8:
81  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
82  break;
83 
84  case FFI_TYPE_SINT16:
85  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
86  break;
87 
88  case FFI_TYPE_UINT16:
89  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
90  break;
91 
92  case FFI_TYPE_STRUCT:
93  z = (*p_arg)->size;
94  if ((*p_arg)->alignment != 1)
95  memcpy (argp, *p_argv, z);
96  else
97  memcpy (argp + 4 - z, *p_argv, z);
98  z = sizeof (int);
99  break;
100 
101  default:
102  FFI_ASSERT(0);
103  }
104  }
105  else if (z == sizeof (int))
106  {
107  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
108  }
109  else
110  {
111  if ((*p_arg)->type == FFI_TYPE_STRUCT)
112  {
113  if (z > 8)
114  {
115  *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
116  z = sizeof(void *);
117  }
118  else
119  {
120  memcpy(argp, *p_argv, z);
121  z = 8;
122  }
123  }
124  else
125  {
126  /* Double or long long 64bit. */
127  memcpy (argp, *p_argv, z);
128  }
129  }
130  p_argv++;
131  argp += z;
132  }
133  }
134 
135  return;
136 }
137 
138 /* Perform machine dependent cif processing. */
139 ffi_status
140 ffi_prep_cif_machdep(ffi_cif *cif)
141 {
142  /* Set the return type flag. */
143  switch (cif->rtype->type)
144  {
145  case FFI_TYPE_VOID:
146  cif->flags = (unsigned) cif->rtype->type;
147  break;
148 
149  case FFI_TYPE_STRUCT:
150  if (cif->rtype->size <= 4)
151  cif->flags = FFI_TYPE_INT;
152 
153  else if (cif->rtype->size <= 8)
154  cif->flags = FFI_TYPE_DOUBLE;
155 
156  else
157  cif->flags = (unsigned) cif->rtype->type;
158  break;
159 
160  case FFI_TYPE_SINT64:
161  case FFI_TYPE_UINT64:
162  case FFI_TYPE_DOUBLE:
163  cif->flags = FFI_TYPE_DOUBLE;
164  break;
165 
166  case FFI_TYPE_FLOAT:
167  default:
168  cif->flags = FFI_TYPE_INT;
169  break;
170  }
171 
172  return FFI_OK;
173 }
174 
175 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
176  unsigned, unsigned, unsigned *, void (*fn)(void));
177 
178 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
179 {
180  extended_cif ecif;
181 
182  ecif.cif = cif;
183  ecif.avalue = avalue;
184 
185  /* If the return value is a struct and we don't have
186  a return value address then we need to make one. */
187  if ((rvalue == NULL) &&
188  (cif->rtype->type == FFI_TYPE_STRUCT))
189  {
190  ecif.rvalue = alloca (cif->rtype->size);
191  }
192  else
193  ecif.rvalue = rvalue;
194 
195  switch (cif->abi)
196  {
197  case FFI_SYSV:
198  ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
199  cif->flags, ecif.rvalue, fn);
200  if (cif->rtype->type == FFI_TYPE_STRUCT)
201  {
202  int size = cif->rtype->size;
203  int align = cif->rtype->alignment;
204 
205  if (size < 4)
206  {
207  if (align == 1)
208  *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
209  }
210  else if (4 < size && size < 8)
211  {
212  if (align == 1)
213  {
214  memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
215  }
216  else if (align == 2)
217  {
218  if (size & 1)
219  size += 1;
220 
221  if (size != 8)
222  memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
223  }
224  }
225  }
226  break;
227 
228  default:
229  FFI_ASSERT(0);
230  break;
231  }
232 }
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
ffi_common.h
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
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
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
unsigned
#define unsigned
Definition: rb_mjit_min_header-2.7.1.h:2875
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
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
extended_cif::cif
ffi_cif * cif
Definition: ffi_common.h:88