aarch64: Fix closures for win64 (#606)
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c
index fccc7f2..fd7f9d1 100644
--- a/src/aarch64/ffi.c
+++ b/src/aarch64/ffi.c
@@ -797,7 +797,7 @@ ffi_prep_closure_loc (ffi_closure *closure,
void *user_data,
void *codeloc)
{
- if (cif->abi != FFI_SYSV)
+ if (cif->abi != FFI_SYSV && cif->abi != FFI_WIN64)
return FFI_BAD_ABI;
void (*start)(void);
@@ -873,7 +873,7 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif,
{
void (*start)(void);
- if (cif->abi != FFI_SYSV)
+ if (cif->abi != FFI_SYSV && cif->abi != FFI_WIN64)
return FFI_BAD_ABI;
if (cif->flags & AARCH64_FLAG_ARG_V)
@@ -913,11 +913,18 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
void *stack, void *rvalue, void *struct_rvalue)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
- int i, h, nargs, flags;
+ int i, h, nargs, flags, isvariadic = 0;
struct arg_state state;
arg_init (&state);
+ flags = cif->flags;
+ if (flags & AARCH64_FLAG_VARARG)
+ {
+ isvariadic = 1;
+ flags &= ~AARCH64_FLAG_VARARG;
+ }
+
for (i = 0, nargs = cif->nargs; i < nargs; i++)
{
ffi_type *ty = cif->arg_types[i];
@@ -952,8 +959,7 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
if (h)
{
n = 4 - (h & 3);
-#ifdef _WIN32 /* for handling armasm calling convention */
- if (cif->is_variadic)
+ if (cif->abi == FFI_WIN64 && isvariadic)
{
if (state.ngrn + n <= N_X_ARG_REG)
{
@@ -979,7 +985,6 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
}
else
{
-#endif /* for handling armasm calling convention */
if (state.nsrn + n <= N_V_ARG_REG)
{
void *reg = &context->v[state.nsrn];
@@ -992,9 +997,7 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
avalue[i] = allocate_to_stack(&state, stack,
ty->alignment, s);
}
-#ifdef _WIN32 /* for handling armasm calling convention */
}
-#endif /* for handling armasm calling convention */
}
else if (s > 16)
{
@@ -1035,7 +1038,6 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
#endif
}
- flags = cif->flags;
if (flags & AARCH64_RET_IN_MEM)
rvalue = struct_rvalue;