@@ -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
243247struct 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. */
255260static 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+
289310static ffi_arg
290311extend_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