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
----------------------------------------------------------------------- */
34
#include <ffi_common.h>
38
/* ffi_prep_args is called by the assembly routine once stack space
39
has been allocated for the function's arguments */
41
void ffi_prep_args(char *stack, extended_cif *ecif)
43
register unsigned int i;
44
register void **p_argv;
46
register ffi_type **p_arg;
50
if (ecif->cif->flags == FFI_TYPE_STRUCT)
52
*(void **) argp = ecif->rvalue;
56
p_argv = ecif->avalue;
58
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
64
/* Align if necessary */
65
if ((sizeof(int) - 1) & (unsigned) argp)
66
argp = (char *) ALIGN(argp, sizeof(int));
72
switch ((*p_arg)->type)
75
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
79
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
83
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
87
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
91
*(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
95
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
99
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
108
memcpy(argp, *p_argv, z);
117
/* Perform machine dependent cif processing */
118
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
120
/* Set the return type flag */
121
switch (cif->rtype->type)
125
case FFI_TYPE_STRUCT:
127
#if defined(X86) || defined(X86_DARWIN)
129
case FFI_TYPE_UINT16:
131
case FFI_TYPE_SINT16:
134
case FFI_TYPE_SINT64:
136
case FFI_TYPE_DOUBLE:
137
case FFI_TYPE_LONGDOUBLE:
138
cif->flags = (unsigned) cif->rtype->type;
141
case FFI_TYPE_UINT64:
142
cif->flags = FFI_TYPE_SINT64;
146
case FFI_TYPE_STRUCT:
147
if (cif->rtype->size == 1)
149
cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
151
else if (cif->rtype->size == 2)
153
cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
155
else if (cif->rtype->size == 4)
157
cif->flags = FFI_TYPE_INT; /* same as int type */
159
else if (cif->rtype->size == 8)
161
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
165
cif->flags = FFI_TYPE_STRUCT;
171
cif->flags = FFI_TYPE_INT;
176
cif->bytes = (cif->bytes + 15) & ~0xF;
182
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
183
unsigned, unsigned, unsigned *, void (*fn)(void));
186
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
187
unsigned, unsigned, unsigned *, void (*fn)(void));
189
#endif /* X86_WIN32 */
191
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
196
ecif.avalue = avalue;
198
/* If the return value is a struct and we don't have a return */
199
/* value address then we need to make one */
201
if ((rvalue == NULL) &&
202
(cif->flags == FFI_TYPE_STRUCT))
204
ecif.rvalue = alloca(cif->rtype->size);
207
ecif.rvalue = rvalue;
213
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
218
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
221
#endif /* X86_WIN32 */
229
/** private members **/
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)));
240
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
241
__attribute__ ((regparm(1)));
244
/* This function is jumped to by the trampoline */
246
unsigned int FFI_HIDDEN
247
ffi_closure_SYSV_inner (closure, respp, args)
248
ffi_closure *closure;
252
/* our various things... */
257
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
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. */
265
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
267
(closure->fun) (cif, *respp, arg_area, closure->user_data);
273
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
276
register unsigned int i;
277
register void **p_argv;
279
register ffi_type **p_arg;
283
if ( cif->flags == FFI_TYPE_STRUCT ) {
284
*rvalue = *(void **) argp;
290
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
294
/* Align if necessary */
295
if ((sizeof(int) - 1) & (unsigned) argp) {
296
argp = (char *) ALIGN(argp, sizeof(int));
301
/* because we're little endian, this is what it turns into. */
303
*p_argv = (void*) argp;
312
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
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 */ \
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 */ \
339
/* the cif must already be prep'ed */
342
ffi_prep_closure_loc (ffi_closure* closure,
344
void (*fun)(ffi_cif*,void*,void**,void*),
348
if (cif->abi == FFI_SYSV)
350
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
355
else if (cif->abi == FFI_STDCALL)
357
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
358
&ffi_closure_STDCALL,
359
(void*)codeloc, cif->bytes);
368
closure->user_data = user_data;
374
/* ------- Native raw API support -------------------------------- */
379
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
381
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
387
if (cif->abi != FFI_SYSV) {
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. */
396
for (i = cif->nargs-1; i >= 0; i--)
398
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
399
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
403
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
407
closure->user_data = user_data;
414
ffi_prep_args_raw(char *stack, extended_cif *ecif)
416
memcpy (stack, ecif->avalue, ecif->cif->bytes);
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.)
425
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
426
unsigned, unsigned *, void (*fn)(void));
430
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
431
unsigned, unsigned *, void (*fn)(void));
432
#endif /* X86_WIN32 */
435
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
438
void **avalue = (void **)fake_avalue;
441
ecif.avalue = avalue;
443
/* If the return value is a struct and we don't have a return */
444
/* value address then we need to make one */
446
if ((rvalue == NULL) &&
447
(cif->rtype->type == FFI_TYPE_STRUCT))
449
ecif.rvalue = alloca(cif->rtype->size);
452
ecif.rvalue = rvalue;
458
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
463
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
466
#endif /* X86_WIN32 */
475
#endif /* __x86_64__ */