Skip to content

Commit 482b37f

Browse files
Fix passing struct by value on aarch64
This fixes the ctypes test in the python testsuite.
1 parent c194448 commit 482b37f

1 file changed

Lines changed: 31 additions & 8 deletions

File tree

src/aarch64/ffi.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,18 @@ is_vfp_type (const ffi_type *ty)
238238
state.
239239
240240
The terse state variable names match the names used in the AARCH64
241-
PCS. */
241+
PCS.
242+
243+
The struct area is allocated downwards from the top of the argument
244+
area. It is used to hold copies of structures passed by value that are
245+
bigger than 16 bytes. */
242246

243247
struct arg_state
244248
{
245249
unsigned ngrn; /* Next general-purpose register number. */
246250
unsigned nsrn; /* Next vector register number. */
247251
size_t nsaa; /* Next stack offset. */
252+
size_t next_struct_area; /* Place to allocate big structs. */
248253

249254
#if defined (__APPLE__)
250255
unsigned allocating_variadic;
@@ -253,11 +258,12 @@ struct arg_state
253258

254259
/* Initialize a procedure call argument marshalling state. */
255260
static void
256-
arg_init (struct arg_state *state)
261+
arg_init (struct arg_state *state, size_t size)
257262
{
258263
state->ngrn = 0;
259264
state->nsrn = 0;
260265
state->nsaa = 0;
266+
state->next_struct_area = size;
261267
#if defined (__APPLE__)
262268
state->allocating_variadic = 0;
263269
#endif
@@ -286,6 +292,21 @@ allocate_to_stack (struct arg_state *state, void *stack,
286292
return (char *)stack + nsaa;
287293
}
288294

295+
/* Allocate and copy a structure that is passed by value on the stack and
296+
return a pointer to it. */
297+
static void *
298+
allocate_and_copy_struct_to_stack (struct arg_state *state, void *stack,
299+
size_t alignment, size_t size, void *value)
300+
{
301+
size_t dest = state->next_struct_area - size;
302+
303+
/* Round down to the natural alignment of the value. */
304+
dest = ALIGN_DOWN (dest, alignment);
305+
state->next_struct_area = dest;
306+
307+
return memcpy ((char *) stack + dest, value, size);
308+
}
309+
289310
static ffi_arg
290311
extend_integer_type (void *source, int type)
291312
{
@@ -591,13 +612,14 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
591612
frame = stack + stack_bytes;
592613
rvalue = (rsize ? frame + 32 : orig_rvalue);
593614

594-
arg_init (&state);
615+
arg_init (&state, stack_bytes);
595616
for (i = 0, nargs = cif->nargs; i < nargs; i++)
596617
{
597618
ffi_type *ty = cif->arg_types[i];
598619
size_t s = ty->size;
599620
void *a = avalue[i];
600621
int h, t;
622+
void *dest;
601623

602624
t = ty->type;
603625
switch (t)
@@ -645,8 +667,6 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
645667
case FFI_TYPE_STRUCT:
646668
case FFI_TYPE_COMPLEX:
647669
{
648-
void *dest;
649-
650670
h = is_vfp_type (ty);
651671
if (h)
652672
{
@@ -664,9 +684,12 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
664684
else if (s > 16)
665685
{
666686
/* If the argument is a composite type that is larger than 16
667-
bytes, then the argument has been copied to memory, and
687+
bytes, then the argument is copied to memory, and
668688
the argument is replaced by a pointer to the copy. */
669-
a = &avalue[i];
689+
dest = allocate_and_copy_struct_to_stack (&state, stack,
690+
ty->alignment, s,
691+
avalue[i]);
692+
a = &dest;
670693
t = FFI_TYPE_POINTER;
671694
s = sizeof (void *);
672695
goto do_pointer;
@@ -835,7 +858,7 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
835858
int i, h, nargs, flags;
836859
struct arg_state state;
837860

838-
arg_init (&state);
861+
arg_init (&state, cif->bytes);
839862

840863
for (i = 0, nargs = cif->nargs; i < nargs; i++)
841864
{

0 commit comments

Comments
 (0)