OSDN Git Service

2bca56e5ccb078cf281a80d597b6c60a1ca6d5d0
[pf3gnuchains/gcc-fork.git] / libffi / src / x86 / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007  Red Hat, Inc.
3            Copyright (c) 2002  Ranjit Mathew
4            Copyright (c) 2002  Bo Thorsen
5            Copyright (c) 2002  Roger Sayle
6            Copyright (C) 2008  Free Software Foundation, Inc.
7
8    x86 Foreign Function Interface
9
10    Permission is hereby granted, free of charge, to any person obtaining
11    a copy of this software and associated documentation files (the
12    ``Software''), to deal in the Software without restriction, including
13    without limitation the rights to use, copy, modify, merge, publish,
14    distribute, sublicense, and/or sell copies of the Software, and to
15    permit persons to whom the Software is furnished to do so, subject to
16    the following conditions:
17
18    The above copyright notice and this permission notice shall be included
19    in all copies or substantial portions of the Software.
20
21    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28    DEALINGS IN THE SOFTWARE.
29    ----------------------------------------------------------------------- */
30
31 #ifndef __x86_64__
32
33 #include <ffi.h>
34 #include <ffi_common.h>
35
36 #include <stdlib.h>
37
38 /* ffi_prep_args is called by the assembly routine once stack space
39    has been allocated for the function's arguments */
40
41 void ffi_prep_args(char *stack, extended_cif *ecif)
42 {
43   register unsigned int i;
44   register void **p_argv;
45   register char *argp;
46   register ffi_type **p_arg;
47
48   argp = stack;
49
50   if (ecif->cif->flags == FFI_TYPE_STRUCT)
51     {
52       *(void **) argp = ecif->rvalue;
53       argp += 4;
54     }
55
56   p_argv = ecif->avalue;
57
58   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
59        i != 0;
60        i--, p_arg++)
61     {
62       size_t z;
63
64       /* Align if necessary */
65       if ((sizeof(int) - 1) & (unsigned) argp)
66         argp = (char *) ALIGN(argp, sizeof(int));
67
68       z = (*p_arg)->size;
69       if (z < sizeof(int))
70         {
71           z = sizeof(int);
72           switch ((*p_arg)->type)
73             {
74             case FFI_TYPE_SINT8:
75               *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
76               break;
77
78             case FFI_TYPE_UINT8:
79               *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
80               break;
81
82             case FFI_TYPE_SINT16:
83               *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
84               break;
85
86             case FFI_TYPE_UINT16:
87               *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
88               break;
89
90             case FFI_TYPE_SINT32:
91               *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
92               break;
93
94             case FFI_TYPE_UINT32:
95               *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
96               break;
97
98             case FFI_TYPE_STRUCT:
99               *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
100               break;
101
102             default:
103               FFI_ASSERT(0);
104             }
105         }
106       else
107         {
108           memcpy(argp, *p_argv, z);
109         }
110       p_argv++;
111       argp += z;
112     }
113   
114   return;
115 }
116
117 /* Perform machine dependent cif processing */
118 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
119 {
120   /* Set the return type flag */
121   switch (cif->rtype->type)
122     {
123     case FFI_TYPE_VOID:
124 #ifdef X86
125     case FFI_TYPE_STRUCT:
126 #endif
127 #if defined(X86) || defined(X86_DARWIN)
128     case FFI_TYPE_UINT8:
129     case FFI_TYPE_UINT16:
130     case FFI_TYPE_SINT8:
131     case FFI_TYPE_SINT16:
132 #endif
133
134     case FFI_TYPE_SINT64:
135     case FFI_TYPE_FLOAT:
136     case FFI_TYPE_DOUBLE:
137     case FFI_TYPE_LONGDOUBLE:
138       cif->flags = (unsigned) cif->rtype->type;
139       break;
140
141     case FFI_TYPE_UINT64:
142       cif->flags = FFI_TYPE_SINT64;
143       break;
144
145 #ifndef X86
146     case FFI_TYPE_STRUCT:
147       if (cif->rtype->size == 1)
148         {
149           cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
150         }
151       else if (cif->rtype->size == 2)
152         {
153           cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
154         }
155       else if (cif->rtype->size == 4)
156         {
157           cif->flags = FFI_TYPE_INT; /* same as int type */
158         }
159       else if (cif->rtype->size == 8)
160         {
161           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
162         }
163       else
164         {
165           cif->flags = FFI_TYPE_STRUCT;
166         }
167       break;
168 #endif
169
170     default:
171       cif->flags = FFI_TYPE_INT;
172       break;
173     }
174
175 #ifdef X86_DARWIN
176   cif->bytes = (cif->bytes + 15) & ~0xF;
177 #endif
178
179   return FFI_OK;
180 }
181
182 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
183                           unsigned, unsigned, unsigned *, void (*fn)(void));
184
185 #ifdef X86_WIN32
186 extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
187                           unsigned, unsigned, unsigned *, void (*fn)(void));
188
189 #endif /* X86_WIN32 */
190
191 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
192 {
193   extended_cif ecif;
194
195   ecif.cif = cif;
196   ecif.avalue = avalue;
197   
198   /* If the return value is a struct and we don't have a return */
199   /* value address then we need to make one                     */
200
201   if ((rvalue == NULL) && 
202       (cif->flags == FFI_TYPE_STRUCT))
203     {
204       ecif.rvalue = alloca(cif->rtype->size);
205     }
206   else
207     ecif.rvalue = rvalue;
208     
209   
210   switch (cif->abi) 
211     {
212     case FFI_SYSV:
213       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
214                     fn);
215       break;
216 #ifdef X86_WIN32
217     case FFI_STDCALL:
218       ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
219                        ecif.rvalue, fn);
220       break;
221 #endif /* X86_WIN32 */
222     default:
223       FFI_ASSERT(0);
224       break;
225     }
226 }
227
228
229 /** private members **/
230
231 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
232                                          void** args, ffi_cif* cif);
233 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
234      __attribute__ ((regparm(1)));
235 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
236      __attribute__ ((regparm(1)));
237 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
238      __attribute__ ((regparm(1)));
239
240 /* This function is jumped to by the trampoline */
241
242 unsigned int FFI_HIDDEN
243 ffi_closure_SYSV_inner (closure, respp, args)
244      ffi_closure *closure;
245      void **respp;
246      void *args;
247 {
248   // our various things...
249   ffi_cif       *cif;
250   void         **arg_area;
251
252   cif         = closure->cif;
253   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
254
255   /* this call will initialize ARG_AREA, such that each
256    * element in that array points to the corresponding 
257    * value on the stack; and if the function returns
258    * a structure, it will re-set RESP to point to the
259    * structure return address.  */
260
261   ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
262
263   (closure->fun) (cif, *respp, arg_area, closure->user_data);
264
265   return cif->flags;
266 }
267
268 static void
269 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
270                             ffi_cif *cif)
271 {
272   register unsigned int i;
273   register void **p_argv;
274   register char *argp;
275   register ffi_type **p_arg;
276
277   argp = stack;
278
279   if ( cif->flags == FFI_TYPE_STRUCT ) {
280     *rvalue = *(void **) argp;
281     argp += 4;
282   }
283
284   p_argv = avalue;
285
286   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
287     {
288       size_t z;
289
290       /* Align if necessary */
291       if ((sizeof(int) - 1) & (unsigned) argp) {
292         argp = (char *) ALIGN(argp, sizeof(int));
293       }
294
295       z = (*p_arg)->size;
296
297       /* because we're little endian, this is what it turns into.   */
298
299       *p_argv = (void*) argp;
300
301       p_argv++;
302       argp += z;
303     }
304   
305   return;
306 }
307
308 /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
309
310 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
311 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
312    unsigned int  __fun = (unsigned int)(FUN); \
313    unsigned int  __ctx = (unsigned int)(CTX); \
314    unsigned int  __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
315    *(unsigned char*) &__tramp[0] = 0xb8; \
316    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
317    *(unsigned char *)  &__tramp[5] = 0xe9; \
318    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
319  })
320
321
322 /* the cif must already be prep'ed */
323
324 ffi_status
325 ffi_prep_closure_loc (ffi_closure* closure,
326                       ffi_cif* cif,
327                       void (*fun)(ffi_cif*,void*,void**,void*),
328                       void *user_data,
329                       void *codeloc)
330 {
331   FFI_ASSERT (cif->abi == FFI_SYSV);
332
333   FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
334                        &ffi_closure_SYSV,  \
335                        codeloc);
336     
337   closure->cif  = cif;
338   closure->user_data = user_data;
339   closure->fun  = fun;
340
341   return FFI_OK;
342 }
343
344 /* ------- Native raw API support -------------------------------- */
345
346 #if !FFI_NO_RAW_API
347
348 ffi_status
349 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
350                           ffi_cif* cif,
351                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
352                           void *user_data,
353                           void *codeloc)
354 {
355   int i;
356
357   FFI_ASSERT (cif->abi == FFI_SYSV);
358
359   // we currently don't support certain kinds of arguments for raw
360   // closures.  This should be implemented by a separate assembly language
361   // routine, since it would require argument processing, something we
362   // don't do now for performance.
363
364   for (i = cif->nargs-1; i >= 0; i--)
365     {
366       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
367       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
368     }
369   
370
371   FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
372                        codeloc);
373     
374   closure->cif  = cif;
375   closure->user_data = user_data;
376   closure->fun  = fun;
377
378   return FFI_OK;
379 }
380
381 static void 
382 ffi_prep_args_raw(char *stack, extended_cif *ecif)
383 {
384   memcpy (stack, ecif->avalue, ecif->cif->bytes);
385 }
386
387 /* we borrow this routine from libffi (it must be changed, though, to
388  * actually call the function passed in the first argument.  as of
389  * libffi-1.20, this is not the case.)
390  */
391
392 extern void
393 ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, 
394               unsigned, unsigned *, void (*fn)(void));
395
396 #ifdef X86_WIN32
397 extern void
398 ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
399                  unsigned, unsigned *, void (*fn)(void));
400 #endif /* X86_WIN32 */
401
402 void
403 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
404 {
405   extended_cif ecif;
406   void **avalue = (void **)fake_avalue;
407
408   ecif.cif = cif;
409   ecif.avalue = avalue;
410   
411   /* If the return value is a struct and we don't have a return */
412   /* value address then we need to make one                     */
413
414   if ((rvalue == NULL) && 
415       (cif->rtype->type == FFI_TYPE_STRUCT))
416     {
417       ecif.rvalue = alloca(cif->rtype->size);
418     }
419   else
420     ecif.rvalue = rvalue;
421     
422   
423   switch (cif->abi) 
424     {
425     case FFI_SYSV:
426       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
427                     ecif.rvalue, fn);
428       break;
429 #ifdef X86_WIN32
430     case FFI_STDCALL:
431       ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
432                        ecif.rvalue, fn);
433       break;
434 #endif /* X86_WIN32 */
435     default:
436       FFI_ASSERT(0);
437       break;
438     }
439 }
440
441 #endif
442
443 #endif /* __x86_64__  */