This commit is contained in:
Benjamin Peterson 2015-05-08 21:32:36 -04:00
commit 43e3d22fee
1 changed files with 30 additions and 18 deletions

View File

@ -331,10 +331,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
extern int extern int
ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)(void)); unsigned, unsigned, unsigned *, void (*fn)(void));
#else #elif defined(X86_WIN32)
extern void extern void
ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
#else
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)(void)); unsigned, unsigned, unsigned *, void (*fn)(void));
#endif #endif
@ -376,16 +377,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn); cif->flags, ecif.rvalue, fn);
break; break;
#else #elif defined(X86_WIN32)
#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_SYSV:
case FFI_MS_CDECL: case FFI_MS_CDECL:
#endif
case FFI_STDCALL: case FFI_STDCALL:
ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
ecif.rvalue, fn); ecif.rvalue, fn);
@ -419,6 +413,11 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ecif.rvalue, fn); ecif.rvalue, fn);
} }
break; break;
#else
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
fn);
break;
#endif #endif
default: default:
FFI_ASSERT(0); FFI_ASSERT(0);
@ -787,28 +786,36 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
/* If the return value is a struct and we don't have a return */ /* If the return value is a struct and we don't have a return */
/* value address then we need to make one */ /* value address then we need to make one */
#ifdef X86_WIN64
if (rvalue == NULL
&& cif->flags == FFI_TYPE_STRUCT
&& cif->rtype->size != 1 && cif->rtype->size != 2
&& cif->rtype->size != 4 && cif->rtype->size != 8)
{
ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
}
#else
if (rvalue == NULL if (rvalue == NULL
&& (cif->flags == FFI_TYPE_STRUCT && (cif->flags == FFI_TYPE_STRUCT
|| cif->flags == FFI_TYPE_MS_STRUCT)) || cif->flags == FFI_TYPE_MS_STRUCT))
{ {
ecif.rvalue = alloca(cif->rtype->size); ecif.rvalue = alloca(cif->rtype->size);
} }
#endif
else else
ecif.rvalue = rvalue; ecif.rvalue = rvalue;
switch (cif->abi) switch (cif->abi)
{ {
#ifndef X86_WIN32 #ifdef X86_WIN64
case FFI_SYSV: case FFI_WIN64:
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ffi_call_win64(ffi_prep_args_raw, &ecif, cif->bytes,
ecif.rvalue, fn); cif->flags, ecif.rvalue, fn);
break; break;
#else #elif defined(X86_WIN32)
case FFI_SYSV: case FFI_SYSV:
case FFI_MS_CDECL: case FFI_MS_CDECL:
#endif
#ifndef X86_WIN64
case FFI_STDCALL: case FFI_STDCALL:
ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
ecif.rvalue, fn); ecif.rvalue, fn);
@ -835,13 +842,18 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
++passed_regs; ++passed_regs;
} }
if (passed_regs < 2 && abi == FFI_FASTCALL) if (passed_regs < 2 && abi == FFI_FASTCALL)
cif->abi = abi = FFI_THISCALL; abi = FFI_THISCALL;
if (passed_regs < 1 && abi == FFI_THISCALL) if (passed_regs < 1 && abi == FFI_THISCALL)
cif->abi = abi = FFI_STDCALL; abi = FFI_STDCALL;
ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
ecif.rvalue, fn); ecif.rvalue, fn);
} }
break; break;
#else
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ecif.rvalue,
fn);
break;
#endif #endif
default: default:
FFI_ASSERT(0); FFI_ASSERT(0);