summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOle André Vadla Ravnås <ole.andre.ravnas@tillitech.com>2014-04-06 20:54:13 +0200
committerOle André Vadla Ravnås <ole.andre.ravnas@tillitech.com>2014-04-06 20:59:25 +0200
commit419503f409c321fe31ff59d963ef34bb913420d0 (patch)
tree5d77554bc411ca514e99b4f3f7038962498de750 /src
parentdc33cb3c998da521a960385c1269c3aef552f69f (diff)
downloadlibffi-419503f409c321fe31ff59d963ef34bb913420d0.tar.gz
Fix handling of variadic calls on Darwin/AArch64
Diffstat (limited to 'src')
-rw-r--r--src/aarch64/ffi.c37
-rw-r--r--src/aarch64/ffitarget.h6
2 files changed, 41 insertions, 2 deletions
diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c
index 7d5aa40..b807a2d 100644
--- a/src/aarch64/ffi.c
+++ b/src/aarch64/ffi.c
@@ -408,6 +408,10 @@ struct arg_state
unsigned ngrn; /* Next general-purpose register number. */
unsigned nsrn; /* Next vector register number. */
size_t nsaa; /* Next stack offset. */
+
+#if defined (__APPLE__)
+ unsigned allocating_variadic;
+#endif
};
/* Initialize a procedure call argument marshalling state. */
@@ -417,6 +421,10 @@ arg_init (struct arg_state *state, size_t call_frame_size)
state->ngrn = 0;
state->nsrn = 0;
state->nsaa = 0;
+
+#if defined (__APPLE__)
+ state->allocating_variadic = 0;
+#endif
}
/* Return the number of available consecutive core argument
@@ -476,7 +484,10 @@ allocate_to_stack (struct arg_state *state, void *stack, size_t alignment,
alignment of the argument's type. */
state->nsaa = ALIGN (state->nsaa, alignment);
state->nsaa = ALIGN (state->nsaa, alignment);
-#if !defined (__APPLE__)
+#if defined (__APPLE__)
+ if (state->allocating_variadic)
+ state->nsaa = ALIGN (state->nsaa, 8);
+#else
state->nsaa = ALIGN (state->nsaa, 8);
#endif
@@ -725,6 +736,16 @@ aarch64_prep_args (struct call_context *context, unsigned char *stack,
FFI_ASSERT (0);
break;
}
+
+#if defined (__APPLE__)
+ if (i + 1 == ecif->cif->aarch64_nfixedargs)
+ {
+ state.ngrn = N_X_ARG_REG;
+ state.nsrn = N_V_ARG_REG;
+
+ state.allocating_variadic = 1;
+ }
+#endif
}
return ecif->cif->aarch64_flags;
@@ -761,6 +782,20 @@ ffi_prep_cif_machdep (ffi_cif *cif)
return FFI_OK;
}
+#if defined (__APPLE__)
+
+/* Perform Apple-specific cif processing for variadic calls */
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs)
+{
+ cif->aarch64_nfixedargs = nfixedargs;
+
+ return ffi_prep_cif_machdep(cif);
+}
+
+#endif
+
/* Call a function with the provided arguments and capture the return
value. */
void
diff --git a/src/aarch64/ffitarget.h b/src/aarch64/ffitarget.h
index 6f1a348..4bbced2 100644
--- a/src/aarch64/ffitarget.h
+++ b/src/aarch64/ffitarget.h
@@ -47,8 +47,12 @@ typedef enum ffi_abi
/* ---- Internal ---- */
-
+#if defined (__APPLE__)
+#define FFI_TARGET_SPECIFIC_VARIADIC
+#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags; unsigned aarch64_nfixedargs
+#else
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
+#endif
#define AARCH64_FFI_WITH_V_BIT 0