OSDN Git Service

2008-02-26 Anthony Green <green@redhat.com>
[pf3gnuchains/gcc-fork.git] / libffi / src / x86 / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  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 #ifdef X86_WIN32
240 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
241      __attribute__ ((regparm(1)));
242 #endif
243
244 /* This function is jumped to by the trampoline */
245
246 unsigned int FFI_HIDDEN
247 ffi_closure_SYSV_inner (closure, respp, args)
248      ffi_closure *closure;
249      void **respp;
250      void *args;
251 {
252   /* our various things...  */
253   ffi_cif       *cif;
254   void         **arg_area;
255
256   cif         = closure->cif;
257   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
258
259   /* this call will initialize ARG_AREA, such that each
260    * element in that array points to the corresponding 
261    * value on the stack; and if the function returns
262    * a structure, it will re-set RESP to point to the
263    * structure return address.  */
264
265   ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
266
267   (closure->fun) (cif, *respp, arg_area, closure->user_data);
268
269   return cif->flags;
270 }
271
272 static void
273 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
274                             ffi_cif *cif)
275 {
276   register unsigned int i;
277   register void **p_argv;
278   register char *argp;
279   register ffi_type **p_arg;
280
281   argp = stack;
282
283   if ( cif->flags == FFI_TYPE_STRUCT ) {
284     *rvalue = *(void **) argp;
285     argp += 4;
286   }
287
288   p_argv = avalue;
289
290   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
291     {
292       size_t z;
293
294       /* Align if necessary */
295       if ((sizeof(int) - 1) & (unsigned) argp) {
296         argp = (char *) ALIGN(argp, sizeof(int));
297       }
298
299       z = (*p_arg)->size;
300
301       /* because we're little endian, this is what it turns into.   */
302
303       *p_argv = (void*) argp;
304
305       p_argv++;
306       argp += z;
307     }
308   
309   return;
310 }
311
312 /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
313
314 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
315 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
316    unsigned int  __fun = (unsigned int)(FUN); \
317    unsigned int  __ctx = (unsigned int)(CTX); \
318    unsigned int  __dis = __fun - (__ctx + 10);  \
319    *(unsigned char*) &__tramp[0] = 0xb8; \
320    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
321    *(unsigned char *)  &__tramp[5] = 0xe9; \
322    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
323  })
324
325 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
326 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
327    unsigned int  __fun = (unsigned int)(FUN); \
328    unsigned int  __ctx = (unsigned int)(CTX); \
329    unsigned int  __dis = __fun - (__ctx + 10); \
330    unsigned short __size = (unsigned short)(SIZE); \
331    *(unsigned char*) &__tramp[0] = 0xb8; \
332    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
333    *(unsigned char *)  &__tramp[5] = 0xe8; \
334    *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
335    *(unsigned char *)  &__tramp[10] = 0xc2; \
336    *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
337  })
338
339 /* the cif must already be prep'ed */
340
341 ffi_status
342 ffi_prep_closure_loc (ffi_closure* closure,
343                       ffi_cif* cif,
344                       void (*fun)(ffi_cif*,void*,void**,void*),
345                       void *user_data,
346                       void *codeloc)
347 {
348   if (cif->abi == FFI_SYSV)
349     {
350       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
351                            &ffi_closure_SYSV,
352                            (void*)codeloc);
353     }
354 #ifdef X86_WIN32
355   else if (cif->abi == FFI_STDCALL)
356     {
357       FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
358                                    &ffi_closure_STDCALL,
359                                    (void*)codeloc, cif->bytes);
360     }
361 #endif
362   else
363     {
364       return FFI_BAD_ABI;
365     }
366     
367   closure->cif  = cif;
368   closure->user_data = user_data;
369   closure->fun  = fun;
370
371   return FFI_OK;
372 }
373
374 /* ------- Native raw API support -------------------------------- */
375
376 #if !FFI_NO_RAW_API
377
378 ffi_status
379 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
380                           ffi_cif* cif,
381                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
382                           void *user_data,
383                           void *codeloc)
384 {
385   int i;
386
387   if (cif->abi != FFI_SYSV) {
388     return FFI_BAD_ABI;
389   }
390
391   // we currently don't support certain kinds of arguments for raw
392   // closures.  This should be implemented by a separate assembly language
393   // routine, since it would require argument processing, something we
394   // don't do now for performance.
395
396   for (i = cif->nargs-1; i >= 0; i--)
397     {
398       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
399       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
400     }
401   
402
403   FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
404                        codeloc);
405     
406   closure->cif  = cif;
407   closure->user_data = user_data;
408   closure->fun  = fun;
409
410   return FFI_OK;
411 }
412
413 static void 
414 ffi_prep_args_raw(char *stack, extended_cif *ecif)
415 {
416   memcpy (stack, ecif->avalue, ecif->cif->bytes);
417 }
418
419 /* we borrow this routine from libffi (it must be changed, though, to
420  * actually call the function passed in the first argument.  as of
421  * libffi-1.20, this is not the case.)
422  */
423
424 extern void
425 ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, 
426               unsigned, unsigned *, void (*fn)(void));
427
428 #ifdef X86_WIN32
429 extern void
430 ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
431                  unsigned, unsigned *, void (*fn)(void));
432 #endif /* X86_WIN32 */
433
434 void
435 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
436 {
437   extended_cif ecif;
438   void **avalue = (void **)fake_avalue;
439
440   ecif.cif = cif;
441   ecif.avalue = avalue;
442   
443   /* If the return value is a struct and we don't have a return */
444   /* value address then we need to make one                     */
445
446   if ((rvalue == NULL) && 
447       (cif->rtype->type == FFI_TYPE_STRUCT))
448     {
449       ecif.rvalue = alloca(cif->rtype->size);
450     }
451   else
452     ecif.rvalue = rvalue;
453     
454   
455   switch (cif->abi) 
456     {
457     case FFI_SYSV:
458       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
459                     ecif.rvalue, fn);
460       break;
461 #ifdef X86_WIN32
462     case FFI_STDCALL:
463       ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
464                        ecif.rvalue, fn);
465       break;
466 #endif /* X86_WIN32 */
467     default:
468       FFI_ASSERT(0);
469       break;
470     }
471 }
472
473 #endif
474
475 #endif /* __x86_64__  */