]>
git.ipfire.org Git - thirdparty/gcc.git/blob - 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.
8 x86 Foreign Function Interface
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:
18 The above copyright notice and this permission notice shall be included
19 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
31 #if !defined(__x86_64__) || defined(_WIN64)
38 #include <ffi_common.h>
42 /* ffi_prep_args is called by the assembly routine once stack space
43 has been allocated for the function's arguments */
45 void ffi_prep_args(char *stack
, extended_cif
*ecif
)
47 register unsigned int i
;
48 register void **p_argv
;
50 register ffi_type
**p_arg
;
54 if (ecif
->cif
->flags
== FFI_TYPE_STRUCT
56 && (ecif
->cif
->rtype
->size
!= 1 && ecif
->cif
->rtype
->size
!= 2
57 && ecif
->cif
->rtype
->size
!= 4 && ecif
->cif
->rtype
->size
!= 8)
61 *(void **) argp
= ecif
->rvalue
;
62 argp
+= sizeof(void*);
65 p_argv
= ecif
->avalue
;
67 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
;
73 /* Align if necessary */
74 if ((sizeof(void*) - 1) & (size_t) argp
)
75 argp
= (char *) ALIGN(argp
, sizeof(void*));
79 if (z
> sizeof(ffi_arg
)
80 || ((*p_arg
)->type
== FFI_TYPE_STRUCT
81 && (z
!= 1 && z
!= 2 && z
!= 4 && z
!= 8))
82 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
83 || ((*p_arg
)->type
== FFI_TYPE_LONGDOUBLE
)
88 *(void **)argp
= *p_argv
;
90 else if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
92 memcpy(argp
, *p_argv
, z
);
96 if (z
< sizeof(ffi_arg
))
99 switch ((*p_arg
)->type
)
102 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT8
*)(* p_argv
);
106 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT8
*)(* p_argv
);
109 case FFI_TYPE_SINT16
:
110 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT16
*)(* p_argv
);
113 case FFI_TYPE_UINT16
:
114 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT16
*)(* p_argv
);
117 case FFI_TYPE_SINT32
:
118 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT32
*)(* p_argv
);
121 case FFI_TYPE_UINT32
:
122 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT32
*)(* p_argv
);
125 case FFI_TYPE_STRUCT
:
126 *(ffi_arg
*) argp
= *(ffi_arg
*)(* p_argv
);
135 memcpy(argp
, *p_argv
, z
);
139 argp
+= (z
+ sizeof(void*) - 1) & ~(sizeof(void*) - 1);
148 /* Perform machine dependent cif processing */
149 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
151 /* Set the return type flag */
152 switch (cif
->rtype
->type
)
156 case FFI_TYPE_STRUCT
:
158 #if defined(X86) || defined (X86_WIN32) || defined(X86_DARWIN) || defined(X86_WIN64)
160 case FFI_TYPE_UINT16
:
162 case FFI_TYPE_SINT16
:
165 case FFI_TYPE_UINT32
:
166 case FFI_TYPE_SINT32
:
169 case FFI_TYPE_SINT64
:
171 case FFI_TYPE_DOUBLE
:
173 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
174 case FFI_TYPE_LONGDOUBLE
:
177 cif
->flags
= (unsigned) cif
->rtype
->type
;
180 case FFI_TYPE_UINT64
:
182 case FFI_TYPE_POINTER
:
184 cif
->flags
= FFI_TYPE_SINT64
;
188 case FFI_TYPE_STRUCT
:
189 if (cif
->rtype
->size
== 1)
191 cif
->flags
= FFI_TYPE_SMALL_STRUCT_1B
; /* same as char size */
193 else if (cif
->rtype
->size
== 2)
195 cif
->flags
= FFI_TYPE_SMALL_STRUCT_2B
; /* same as short size */
197 else if (cif
->rtype
->size
== 4)
200 cif
->flags
= FFI_TYPE_SMALL_STRUCT_4B
;
202 cif
->flags
= FFI_TYPE_INT
; /* same as int type */
205 else if (cif
->rtype
->size
== 8)
207 cif
->flags
= FFI_TYPE_SINT64
; /* same as int64 type */
211 cif
->flags
= FFI_TYPE_STRUCT
;
213 // allocate space for return value pointer
214 cif
->bytes
+= ALIGN(sizeof(void*), FFI_SIZEOF_ARG
);
222 cif
->flags
= FFI_TYPE_SINT64
;
225 cif
->flags
= FFI_TYPE_SINT32
;
227 cif
->flags
= FFI_TYPE_INT
;
233 cif
->bytes
= (cif
->bytes
+ 15) & ~0xF;
241 for (ptr
= cif
->arg_types
, i
= cif
->nargs
; i
> 0; i
--, ptr
++)
243 if (((*ptr
)->alignment
- 1) & cif
->bytes
)
244 cif
->bytes
= ALIGN(cif
->bytes
, (*ptr
)->alignment
);
245 cif
->bytes
+= ALIGN((*ptr
)->size
, FFI_SIZEOF_ARG
);
248 // ensure space for storing four registers
249 cif
->bytes
+= 4 * sizeof(ffi_arg
);
255 extern void ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*,
256 unsigned, unsigned, unsigned *, void (*fn
)(void));
259 extern void ffi_call_STDCALL(void (*)(char *, extended_cif
*), extended_cif
*,
260 unsigned, unsigned, unsigned *, void (*fn
)(void));
262 #endif /* X86_WIN32 */
265 ffi_call_win64(void (*)(char *, extended_cif
*), extended_cif
*,
266 unsigned, unsigned, unsigned *, void (*fn
)(void));
269 void ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
274 ecif
.avalue
= avalue
;
276 /* If the return value is a struct and we don't have a return */
277 /* value address then we need to make one */
281 && cif
->flags
== FFI_TYPE_STRUCT
282 && cif
->rtype
->size
!= 1 && cif
->rtype
->size
!= 2
283 && cif
->rtype
->size
!= 4 && cif
->rtype
->size
!= 8)
285 ecif
.rvalue
= alloca((cif
->rtype
->size
+ 0xF) & ~0xF);
289 && cif
->flags
== FFI_TYPE_STRUCT
)
291 ecif
.rvalue
= alloca(cif
->rtype
->size
);
295 ecif
.rvalue
= rvalue
;
303 // Make copies of all struct arguments
304 // NOTE: not sure if responsibility should be here or in caller
306 for (i
=0; i
< cif
->nargs
;i
++) {
307 size_t size
= cif
->arg_types
[i
]->size
;
308 if ((cif
->arg_types
[i
]->type
== FFI_TYPE_STRUCT
309 && (size
!= 1 && size
!= 2 && size
!= 4 && size
!= 8))
310 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
311 || cif
->arg_types
[i
]->type
== FFI_TYPE_LONGDOUBLE
315 void *local
= alloca(size
);
316 memcpy(local
, avalue
[i
], size
);
320 ffi_call_win64(ffi_prep_args
, &ecif
, cif
->bytes
,
321 cif
->flags
, ecif
.rvalue
, fn
);
326 ffi_call_SYSV(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
,
331 ffi_call_STDCALL(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
,
334 #endif /* X86_WIN32 */
335 #endif /* X86_WIN64 */
343 /** private members **/
345 static void ffi_prep_incoming_args_SYSV (char *stack
, void **ret
,
346 void** args
, ffi_cif
* cif
);
347 void FFI_HIDDEN
ffi_closure_SYSV (ffi_closure
*)
348 __attribute__ ((regparm(1)));
349 unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (ffi_closure
*, void **, void *)
350 __attribute__ ((regparm(1)));
351 void FFI_HIDDEN
ffi_closure_raw_SYSV (ffi_raw_closure
*)
352 __attribute__ ((regparm(1)));
354 void FFI_HIDDEN
ffi_closure_STDCALL (ffi_closure
*)
355 __attribute__ ((regparm(1)));
358 void FFI_HIDDEN
ffi_closure_win64 (ffi_closure
*);
361 /* This function is jumped to by the trampoline */
365 ffi_closure_win64_inner (ffi_closure
*closure
, void *args
) {
369 void *resp
= &result
;
372 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
374 /* this call will initialize ARG_AREA, such that each
375 * element in that array points to the corresponding
376 * value on the stack; and if the function returns
377 * a structure, it will change RESP to point to the
378 * structure return address. */
380 ffi_prep_incoming_args_SYSV(args
, &resp
, arg_area
, cif
);
382 (closure
->fun
) (cif
, resp
, arg_area
, closure
->user_data
);
384 /* The result is returned in rax. This does the right thing for
385 result types except for floats; we have to 'mov xmm0, rax' in the
386 caller to correct this.
387 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
389 return cif
->rtype
->size
> sizeof(void *) ? resp
: *(void **)resp
;
393 unsigned int FFI_HIDDEN
394 ffi_closure_SYSV_inner (closure
, respp
, args
)
395 ffi_closure
*closure
;
399 /* our various things... */
404 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
406 /* this call will initialize ARG_AREA, such that each
407 * element in that array points to the corresponding
408 * value on the stack; and if the function returns
409 * a structure, it will change RESP to point to the
410 * structure return address. */
412 ffi_prep_incoming_args_SYSV(args
, respp
, arg_area
, cif
);
414 (closure
->fun
) (cif
, *respp
, arg_area
, closure
->user_data
);
418 #endif /* !X86_WIN64 */
421 ffi_prep_incoming_args_SYSV(char *stack
, void **rvalue
, void **avalue
,
424 register unsigned int i
;
425 register void **p_argv
;
427 register ffi_type
**p_arg
;
432 if (cif
->rtype
->size
> sizeof(ffi_arg
)
433 || (cif
->flags
== FFI_TYPE_STRUCT
434 && (cif
->rtype
->size
!= 1 && cif
->rtype
->size
!= 2
435 && cif
->rtype
->size
!= 4 && cif
->rtype
->size
!= 8))) {
436 *rvalue
= *(void **) argp
;
437 argp
+= sizeof(void *);
440 if ( cif
->flags
== FFI_TYPE_STRUCT
) {
441 *rvalue
= *(void **) argp
;
442 argp
+= sizeof(void *);
448 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; (i
!= 0); i
--, p_arg
++)
452 /* Align if necessary */
453 if ((sizeof(void*) - 1) & (size_t) argp
) {
454 argp
= (char *) ALIGN(argp
, sizeof(void*));
458 if ((*p_arg
)->size
> sizeof(ffi_arg
)
459 || ((*p_arg
)->type
== FFI_TYPE_STRUCT
460 && ((*p_arg
)->size
!= 1 && (*p_arg
)->size
!= 2
461 && (*p_arg
)->size
!= 4 && (*p_arg
)->size
!= 8)))
464 *p_argv
= *(void **)argp
;
471 /* because we're little endian, this is what it turns into. */
473 *p_argv
= (void*) argp
;
478 argp
+= (z
+ sizeof(void*) - 1) & ~(sizeof(void*) - 1);
487 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
488 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
489 void* __fun = (void*)(FUN); \
490 void* __ctx = (void*)(CTX); \
491 *(unsigned char*) &__tramp[0] = 0x41; \
492 *(unsigned char*) &__tramp[1] = 0xbb; \
493 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
494 *(unsigned char*) &__tramp[6] = 0x48; \
495 *(unsigned char*) &__tramp[7] = 0xb8; \
496 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
497 *(unsigned char *) &__tramp[16] = 0x49; \
498 *(unsigned char *) &__tramp[17] = 0xba; \
499 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
500 *(unsigned char *) &__tramp[26] = 0x41; \
501 *(unsigned char *) &__tramp[27] = 0xff; \
502 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
505 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
507 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
508 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
509 unsigned int __fun = (unsigned int)(FUN); \
510 unsigned int __ctx = (unsigned int)(CTX); \
511 unsigned int __dis = __fun - (__ctx + 10); \
512 *(unsigned char*) &__tramp[0] = 0xb8; \
513 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
514 *(unsigned char *) &__tramp[5] = 0xe9; \
515 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
518 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
519 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
520 unsigned int __fun = (unsigned int)(FUN); \
521 unsigned int __ctx = (unsigned int)(CTX); \
522 unsigned int __dis = __fun - (__ctx + 10); \
523 unsigned short __size = (unsigned short)(SIZE); \
524 *(unsigned char*) &__tramp[0] = 0xb8; \
525 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
526 *(unsigned char *) &__tramp[5] = 0xe8; \
527 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
528 *(unsigned char *) &__tramp[10] = 0xc2; \
529 *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
532 /* the cif must already be prep'ed */
535 ffi_prep_closure_loc (ffi_closure
* closure
,
537 void (*fun
)(ffi_cif
*,void*,void**,void*),
542 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
543 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
544 if (cif
->abi
== FFI_WIN64
)
546 int mask
= FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
547 FFI_INIT_TRAMPOLINE_WIN64 (&closure
->tramp
[0],
550 /* make sure we can execute here */
553 if (cif
->abi
== FFI_SYSV
)
555 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0],
560 else if (cif
->abi
== FFI_STDCALL
)
562 FFI_INIT_TRAMPOLINE_STDCALL (&closure
->tramp
[0],
563 &ffi_closure_STDCALL
,
564 (void*)codeloc
, cif
->bytes
);
566 #endif /* X86_WIN32 */
567 #endif /* !X86_WIN64 */
574 closure
->user_data
= user_data
;
580 /* ------- Native raw API support -------------------------------- */
585 ffi_prep_raw_closure_loc (ffi_raw_closure
* closure
,
587 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*),
593 if (cif
->abi
!= FFI_SYSV
) {
597 // we currently don't support certain kinds of arguments for raw
598 // closures. This should be implemented by a separate assembly language
599 // routine, since it would require argument processing, something we
600 // don't do now for performance.
602 for (i
= cif
->nargs
-1; i
>= 0; i
--)
604 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_STRUCT
);
605 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_LONGDOUBLE
);
609 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0], &ffi_closure_raw_SYSV
,
613 closure
->user_data
= user_data
;
620 ffi_prep_args_raw(char *stack
, extended_cif
*ecif
)
622 memcpy (stack
, ecif
->avalue
, ecif
->cif
->bytes
);
625 /* we borrow this routine from libffi (it must be changed, though, to
626 * actually call the function passed in the first argument. as of
627 * libffi-1.20, this is not the case.)
631 ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*, unsigned,
632 unsigned, unsigned *, void (*fn
)(void));
636 ffi_call_STDCALL(void (*)(char *, extended_cif
*), extended_cif
*, unsigned,
637 unsigned, unsigned *, void (*fn
)(void));
638 #endif /* X86_WIN32 */
641 ffi_raw_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, ffi_raw
*fake_avalue
)
644 void **avalue
= (void **)fake_avalue
;
647 ecif
.avalue
= avalue
;
649 /* If the return value is a struct and we don't have a return */
650 /* value address then we need to make one */
652 if ((rvalue
== NULL
) &&
653 (cif
->rtype
->type
== FFI_TYPE_STRUCT
))
655 ecif
.rvalue
= alloca(cif
->rtype
->size
);
658 ecif
.rvalue
= rvalue
;
664 ffi_call_SYSV(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
669 ffi_call_STDCALL(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
672 #endif /* X86_WIN32 */
681 #endif /* !__x86_64__ || X86_WIN64 */