Add support for stdcall, thiscall, and fastcall on non-Windows x86-32
Linux supports the stdcall calling convention, either via functions explicitly declared with the stdcall attribute, or via code compiled with -mrtd which effectively makes stdcall the default. This introduces FFI_STDCALL, FFI_THISCALL, and FFI_FASTCALL on non-Windows x86-32 platforms, as non-default calling conventions.
This commit is contained in:
@@ -50,7 +50,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
size_t p_stack_args[2];
|
||||
void *p_stack_data[2];
|
||||
char *argp2 = stack;
|
||||
@@ -69,7 +69,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
/* For fastcall/thiscall this is first register-passed
|
||||
argument. */
|
||||
if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
|
||||
@@ -155,7 +155,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
/* For thiscall/fastcall convention register-passed arguments
|
||||
are the first two none-floating-point arguments with a size
|
||||
smaller or equal to sizeof (void*). */
|
||||
@@ -180,7 +180,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
/* We need to move the register-passed arguments for thiscall/fastcall
|
||||
on top of stack, so that those can be moved to registers ecx/edx by
|
||||
call-handler. */
|
||||
@@ -318,7 +318,8 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
#endif
|
||||
|
||||
#ifndef X86_WIN32
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
if (cif->abi != FFI_STDCALL && cif->abi != FFI_THISCALL && cif->abi != FFI_FASTCALL)
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
@@ -328,11 +329,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
extern int
|
||||
ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#elif defined(X86_WIN32)
|
||||
#else
|
||||
extern void
|
||||
ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#else
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#endif
|
||||
@@ -374,10 +374,17 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
#elif defined(X86_WIN32)
|
||||
#else
|
||||
#ifndef X86_WIN32
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
case FFI_MS_CDECL:
|
||||
#endif
|
||||
case FFI_STDCALL:
|
||||
ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
@@ -410,11 +417,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
ecif.rvalue, fn);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
@@ -435,15 +437,14 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#endif
|
||||
#ifdef X86_WIN64
|
||||
#else
|
||||
void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
|
||||
#endif
|
||||
|
||||
@@ -670,7 +671,6 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
||||
&ffi_closure_SYSV,
|
||||
(void*)codeloc);
|
||||
}
|
||||
#ifdef X86_WIN32
|
||||
else if (cif->abi == FFI_THISCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
|
||||
@@ -684,6 +684,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
||||
&ffi_closure_STDCALL,
|
||||
(void*)codeloc, cif->bytes);
|
||||
}
|
||||
#ifdef X86_WIN32
|
||||
else if (cif->abi == FFI_MS_CDECL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
||||
@@ -717,12 +718,12 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cif->abi != FFI_SYSV) {
|
||||
#ifdef X86_WIN32
|
||||
if (cif->abi != FFI_THISCALL)
|
||||
if (cif->abi != FFI_SYSV
|
||||
#ifndef X86_WIN64
|
||||
&& cif->abi != FFI_THISCALL
|
||||
#endif
|
||||
)
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
/* we currently don't support certain kinds of arguments for raw
|
||||
closures. This should be implemented by a separate assembly
|
||||
@@ -735,13 +736,13 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
if (cif->abi == FFI_SYSV)
|
||||
{
|
||||
#endif
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||
codeloc);
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN64
|
||||
}
|
||||
else if (cif->abi == FFI_THISCALL)
|
||||
{
|
||||
@@ -791,10 +792,17 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifdef X86_WIN32
|
||||
#ifndef X86_WIN32
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
case FFI_MS_CDECL:
|
||||
#endif
|
||||
#ifndef X86_WIN64
|
||||
case FFI_STDCALL:
|
||||
ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
@@ -827,11 +835,6 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
|
||||
ecif.rvalue, fn);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
|
||||
Reference in New Issue
Block a user