Fix for MS x64 ABI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c
index 74a3003..22d43f5 100644
--- a/src/x86/ffi64.c
+++ b/src/x86/ffi64.c
@@ -581,6 +581,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
flags = UNIX64_RET_VOID;
}
+ arg_types = cif->arg_types;
+ avn = cif->nargs;
+
/* Allocate the space for the arguments, plus 4 words of temp space. */
stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
reg_args = (struct register_args *) stack;
@@ -595,9 +598,6 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
if (flags & UNIX64_FLAG_RET_IN_MEM)
reg_args->gpr[gprcount++] = (unsigned long) rvalue;
- avn = cif->nargs;
- arg_types = cif->arg_types;
-
for (i = 0; i < avn; ++i)
{
size_t n, size = arg_types[i]->size;
@@ -613,11 +613,12 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
if (align < 8)
align = 8;
- /* Pass this argument in memory. */
- argp = (void *) FFI_ALIGN (argp, align);
- memcpy (argp, avalue[i], size);
- argp += size;
- }
+ /* Pass this argument in memory. */
+ argp = (void *) FFI_ALIGN (argp, align);
+ memcpy (argp, avalue[i], size);
+
+ argp += size;
+ }
else
{
/* The argument is passed entirely in registers. */
@@ -683,6 +684,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_type **arg_types = cif->arg_types;
int i, nargs = cif->nargs;
+ const int max_reg_struct_size = cif->abi == FFI_GNUW64 ? 8 : 16;
/* If we have any large structure arguments, make a copy so we are passing
by value. */
@@ -690,7 +692,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_type *at = arg_types[i];
int size = at->size;
- if (at->type == FFI_TYPE_STRUCT && size > 16)
+ if (at->type == FFI_TYPE_STRUCT && size > max_reg_struct_size)
{
char *argcopy = alloca (size);
memcpy (argcopy, avalue[i], size);