Fixed THISCALL/FASTCALL closures and added basic support for PASCAL/REGISTER closures.

This commit is contained in:
nielsAD
2014-08-25 12:23:29 +02:00
parent 098dca6b31
commit 6e346487b8
2 changed files with 100 additions and 56 deletions

View File

@@ -419,6 +419,8 @@ void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
__attribute__ ((regparm(1)));
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
__attribute__ ((regparm(1)));
unsigned int FFI_HIDDEN ffi_closure_WIN32_inner (ffi_closure *, void **, void *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
__attribute__ ((regparm(1)));
#ifdef X86_WIN32
@@ -426,12 +428,10 @@ void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
__attribute__ ((regparm(1)));
#endif
#ifndef X86_WIN64
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *);
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *);
void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *);
void FFI_HIDDEN ffi_closure_REGISTER (ffi_closure *);
#else
void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
#endif
@@ -490,6 +490,29 @@ ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
return cif->flags;
}
unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
ffi_closure_WIN32_inner (ffi_closure *closure, void **respp, void *args)
{
/* our various things... */
ffi_cif *cif;
void **arg_area;
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
/* this call will initialize ARG_AREA, such that each
* element in that array points to the corresponding
* value on the stack; and if the function returns
* a structure, it will change RESP to point to the
* structure return address. */
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
(closure->fun) (cif, *respp, arg_area, closure->user_data);
return cif->bytes;
}
#endif /* !X86_WIN64 */
static void
@@ -587,7 +610,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
unsigned int __dis = __fun - (__ctx + 10); \
*(unsigned char*) &__tramp[0] = 0xb8; \
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
*(unsigned char *) &__tramp[5] = 0xe9; \
*(unsigned char*) &__tramp[5] = 0xe9; \
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
}
@@ -618,15 +641,15 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
*(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
}
#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX) \
#define FFI_INIT_TRAMPOLINE_WIN32(TRAMP,FUN,CTX) \
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned int __dis = __fun - (__ctx + 10); \
*(unsigned char*) &__tramp[0] = 0xb8; \
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
*(unsigned char *) &__tramp[5] = 0xe8; \
*(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
*(unsigned char*) &__tramp[0] = 0x68; \
*(unsigned int*) &__tramp[1] = __ctx; /* push __ctx */ \
*(unsigned char*) &__tramp[5] = 0xe9; \
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
}
/* the cif must already be prep'ed */
@@ -656,21 +679,27 @@ ffi_prep_closure_loc (ffi_closure* closure,
&ffi_closure_SYSV,
(void*)codeloc);
}
else if (cif->abi == FFI_REGISTER)
{
FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
&ffi_closure_REGISTER,
(void*)codeloc);
}
else if (cif->abi == FFI_FASTCALL)
{
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
&ffi_closure_FASTCALL,
(void*)codeloc);
}
else if (cif->abi == FFI_THISCALL)
{
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
&ffi_closure_THISCALL,
(void*)codeloc);
}
else if (cif->abi == FFI_STDCALL)
else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL)
{
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
&ffi_closure_STDCALL,
(void*)codeloc);
}