2 ===================================================================
5 @@ -51,6 +51,7 @@ tested:
6 |-----------------+------------------|
7 | Architecture | Operating System |
8 |-----------------+------------------|
13 @@ -152,6 +153,7 @@ See the ChangeLog files for details.
16 Add TILE-Gx/TILEPro support.
17 + Add AArch64 support.
21 @@ -323,6 +325,7 @@ Thorup.
22 Major processor architecture ports were contributed by the following
25 +aarch64 Marcus Shawcroft, James Greenhalgh
26 alpha Richard Henderson
28 blackfin Alexandre Keunecke I. de Mendonca
29 Index: libffi/src/aarch64/ffi.c
30 ===================================================================
32 +++ libffi/src/aarch64/ffi.c
34 +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
36 +Permission is hereby granted, free of charge, to any person obtaining
37 +a copy of this software and associated documentation files (the
38 +``Software''), to deal in the Software without restriction, including
39 +without limitation the rights to use, copy, modify, merge, publish,
40 +distribute, sublicense, and/or sell copies of the Software, and to
41 +permit persons to whom the Software is furnished to do so, subject to
42 +the following conditions:
44 +The above copyright notice and this permission notice shall be
45 +included in all copies or substantial portions of the Software.
47 +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
48 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
50 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
51 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
52 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
53 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
58 +#include <ffi_common.h>
62 +/* Stack alignment requirement in bytes */
63 +#define AARCH64_STACK_ALIGN 16
65 +#define N_X_ARG_REG 8
66 +#define N_V_ARG_REG 8
68 +#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT)
78 + UINT64 x [AARCH64_N_XREG];
82 + } v [AARCH64_N_VREG];
86 +get_x_addr (struct call_context *context, unsigned n)
88 + return &context->x[n];
92 +get_s_addr (struct call_context *context, unsigned n)
94 +#if defined __AARCH64EB__
95 + return &context->v[n].d[1].s[1];
97 + return &context->v[n].d[0].s[0];
102 +get_d_addr (struct call_context *context, unsigned n)
104 +#if defined __AARCH64EB__
105 + return &context->v[n].d[1];
107 + return &context->v[n].d[0];
112 +get_v_addr (struct call_context *context, unsigned n)
114 + return &context->v[n];
117 +/* Return the memory location at which a basic type would reside
118 + were it to have been stored in register n. */
121 +get_basic_type_addr (unsigned short type, struct call_context *context,
126 + case FFI_TYPE_FLOAT:
127 + return get_s_addr (context, n);
128 + case FFI_TYPE_DOUBLE:
129 + return get_d_addr (context, n);
130 + case FFI_TYPE_LONGDOUBLE:
131 + return get_v_addr (context, n);
132 + case FFI_TYPE_UINT8:
133 + case FFI_TYPE_SINT8:
134 + case FFI_TYPE_UINT16:
135 + case FFI_TYPE_SINT16:
136 + case FFI_TYPE_UINT32:
137 + case FFI_TYPE_SINT32:
139 + case FFI_TYPE_POINTER:
140 + case FFI_TYPE_UINT64:
141 + case FFI_TYPE_SINT64:
142 + return get_x_addr (context, n);
149 +/* Return the alignment width for each of the basic types. */
152 +get_basic_type_alignment (unsigned short type)
156 + case FFI_TYPE_FLOAT:
157 + case FFI_TYPE_DOUBLE:
158 + return sizeof (UINT64);
159 + case FFI_TYPE_LONGDOUBLE:
160 + return sizeof (long double);
161 + case FFI_TYPE_UINT8:
162 + case FFI_TYPE_SINT8:
163 + case FFI_TYPE_UINT16:
164 + case FFI_TYPE_SINT16:
165 + case FFI_TYPE_UINT32:
167 + case FFI_TYPE_SINT32:
168 + case FFI_TYPE_POINTER:
169 + case FFI_TYPE_UINT64:
170 + case FFI_TYPE_SINT64:
171 + return sizeof (UINT64);
179 +/* Return the size in bytes for each of the basic types. */
182 +get_basic_type_size (unsigned short type)
186 + case FFI_TYPE_FLOAT:
187 + return sizeof (UINT32);
188 + case FFI_TYPE_DOUBLE:
189 + return sizeof (UINT64);
190 + case FFI_TYPE_LONGDOUBLE:
191 + return sizeof (long double);
192 + case FFI_TYPE_UINT8:
193 + return sizeof (UINT8);
194 + case FFI_TYPE_SINT8:
195 + return sizeof (SINT8);
196 + case FFI_TYPE_UINT16:
197 + return sizeof (UINT16);
198 + case FFI_TYPE_SINT16:
199 + return sizeof (SINT16);
200 + case FFI_TYPE_UINT32:
201 + return sizeof (UINT32);
203 + case FFI_TYPE_SINT32:
204 + return sizeof (SINT32);
205 + case FFI_TYPE_POINTER:
206 + case FFI_TYPE_UINT64:
207 + return sizeof (UINT64);
208 + case FFI_TYPE_SINT64:
209 + return sizeof (SINT64);
218 +ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *,
220 + struct call_context *context,
226 +ffi_closure_SYSV (ffi_closure *);
228 +/* Test for an FFI floating point representation. */
231 +is_floating_type (unsigned short type)
233 + return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE
234 + || type == FFI_TYPE_LONGDOUBLE);
237 +/* Test for a homogeneous structure. */
239 +static unsigned short
240 +get_homogeneous_type (ffi_type *ty)
242 + if (ty->type == FFI_TYPE_STRUCT && ty->elements)
245 + unsigned short candidate_type
246 + = get_homogeneous_type (ty->elements[0]);
247 + for (i =1; ty->elements[i]; i++)
249 + unsigned short iteration_type = 0;
250 + /* If we have a nested struct, we must find its homogeneous type.
251 + If that fits with our candidate type, we are still
253 + if (ty->elements[i]->type == FFI_TYPE_STRUCT
254 + && ty->elements[i]->elements)
256 + iteration_type = get_homogeneous_type (ty->elements[i]);
260 + iteration_type = ty->elements[i]->type;
263 + /* If we are not homogeneous, return FFI_TYPE_STRUCT. */
264 + if (candidate_type != iteration_type)
265 + return FFI_TYPE_STRUCT;
267 + return candidate_type;
270 + /* Base case, we have no more levels of nesting, so we
271 + are a basic type, and so, trivially homogeneous in that type. */
275 +/* Determine the number of elements within a STRUCT.
277 + Note, we must handle nested structs.
279 + If ty is not a STRUCT this function will return 0. */
282 +element_count (ffi_type *ty)
284 + if (ty->type == FFI_TYPE_STRUCT && ty->elements)
287 + unsigned elems = 0;
288 + for (n = 0; ty->elements[n]; n++)
290 + if (ty->elements[n]->type == FFI_TYPE_STRUCT
291 + && ty->elements[n]->elements)
292 + elems += element_count (ty->elements[n]);
301 +/* Test for a homogeneous floating point aggregate.
303 + A homogeneous floating point aggregate is a homogeneous aggregate of
304 + a half- single- or double- precision floating point type with one
305 + to four elements. Note that this includes nested structs of the
309 +is_hfa (ffi_type *ty)
311 + if (ty->type == FFI_TYPE_STRUCT
313 + && is_floating_type (get_homogeneous_type (ty)))
315 + unsigned n = element_count (ty);
316 + return n >= 1 && n <= 4;
321 +/* Test if an ffi_type is a candidate for passing in a register.
323 + This test does not check that sufficient registers of the
324 + appropriate class are actually available, merely that IFF
325 + sufficient registers are available then the argument will be passed
328 + Note that an ffi_type that is deemed to be a register candidate
329 + will always be returned in registers.
331 + Returns 1 if a register candidate else 0. */
334 +is_register_candidate (ffi_type *ty)
338 + case FFI_TYPE_VOID:
339 + case FFI_TYPE_FLOAT:
340 + case FFI_TYPE_DOUBLE:
341 + case FFI_TYPE_LONGDOUBLE:
342 + case FFI_TYPE_UINT8:
343 + case FFI_TYPE_UINT16:
344 + case FFI_TYPE_UINT32:
345 + case FFI_TYPE_UINT64:
346 + case FFI_TYPE_POINTER:
347 + case FFI_TYPE_SINT8:
348 + case FFI_TYPE_SINT16:
349 + case FFI_TYPE_SINT32:
351 + case FFI_TYPE_SINT64:
354 + case FFI_TYPE_STRUCT:
359 + else if (ty->size > 16)
361 + /* Too large. Will be replaced with a pointer to memory. The
362 + pointer MAY be passed in a register, but the value will
363 + not. This test specifically fails since the argument will
364 + never be passed by value in registers. */
369 + /* Might be passed in registers depending on the number of
370 + registers required. */
371 + return (ty->size + 7) / 8 < N_X_ARG_REG;
383 +/* Test if an ffi_type argument or result is a candidate for a vector
387 +is_v_register_candidate (ffi_type *ty)
389 + return is_floating_type (ty->type)
390 + || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty));
393 +/* Representation of the procedure call argument marshalling
396 + The terse state variable names match the names used in the AARCH64
401 + unsigned ngrn; /* Next general-purpose register number. */
402 + unsigned nsrn; /* Next vector register number. */
403 + unsigned nsaa; /* Next stack offset. */
406 +/* Initialize a procedure call argument marshalling state. */
408 +arg_init (struct arg_state *state, unsigned call_frame_size)
415 +/* Return the number of available consecutive core argument
419 +available_x (struct arg_state *state)
421 + return N_X_ARG_REG - state->ngrn;
424 +/* Return the number of available consecutive vector argument
428 +available_v (struct arg_state *state)
430 + return N_V_ARG_REG - state->nsrn;
434 +allocate_to_x (struct call_context *context, struct arg_state *state)
436 + FFI_ASSERT (state->ngrn < N_X_ARG_REG)
437 + return get_x_addr (context, (state->ngrn)++);
441 +allocate_to_s (struct call_context *context, struct arg_state *state)
443 + FFI_ASSERT (state->nsrn < N_V_ARG_REG)
444 + return get_s_addr (context, (state->nsrn)++);
448 +allocate_to_d (struct call_context *context, struct arg_state *state)
450 + FFI_ASSERT (state->nsrn < N_V_ARG_REG)
451 + return get_d_addr (context, (state->nsrn)++);
455 +allocate_to_v (struct call_context *context, struct arg_state *state)
457 + FFI_ASSERT (state->nsrn < N_V_ARG_REG)
458 + return get_v_addr (context, (state->nsrn)++);
461 +/* Allocate an aligned slot on the stack and return a pointer to it. */
463 +allocate_to_stack (struct arg_state *state, void *stack, unsigned alignment,
468 + /* Round up the NSAA to the larger of 8 or the natural
469 + alignment of the argument's type. */
470 + state->nsaa = ALIGN (state->nsaa, alignment);
471 + state->nsaa = ALIGN (state->nsaa, alignment);
472 + state->nsaa = ALIGN (state->nsaa, 8);
474 + allocation = stack + state->nsaa;
476 + state->nsaa += size;
481 +copy_basic_type (void *dest, void *source, unsigned short type)
483 + /* This is neccessary to ensure that basic types are copied
484 + sign extended to 64-bits as libffi expects. */
487 + case FFI_TYPE_FLOAT:
488 + *(float *) dest = *(float *) source;
490 + case FFI_TYPE_DOUBLE:
491 + *(double *) dest = *(double *) source;
493 + case FFI_TYPE_LONGDOUBLE:
494 + *(long double *) dest = *(long double *) source;
496 + case FFI_TYPE_UINT8:
497 + *(ffi_arg *) dest = *(UINT8 *) source;
499 + case FFI_TYPE_SINT8:
500 + *(ffi_sarg *) dest = *(SINT8 *) source;
502 + case FFI_TYPE_UINT16:
503 + *(ffi_arg *) dest = *(UINT16 *) source;
505 + case FFI_TYPE_SINT16:
506 + *(ffi_sarg *) dest = *(SINT16 *) source;
508 + case FFI_TYPE_UINT32:
509 + *(ffi_arg *) dest = *(UINT32 *) source;
512 + case FFI_TYPE_SINT32:
513 + *(ffi_sarg *) dest = *(SINT32 *) source;
515 + case FFI_TYPE_POINTER:
516 + case FFI_TYPE_UINT64:
517 + *(ffi_arg *) dest = *(UINT64 *) source;
519 + case FFI_TYPE_SINT64:
520 + *(ffi_sarg *) dest = *(SINT64 *) source;
529 +copy_hfa_to_reg_or_stack (void *memory,
531 + struct call_context *context,
532 + unsigned char *stack,
533 + struct arg_state *state)
535 + unsigned elems = element_count (ty);
536 + if (available_v (state) < elems)
538 + /* There are insufficient V registers. Further V register allocations
539 + are prevented, the NSAA is adjusted (by allocate_to_stack ())
540 + and the argument is copied to memory at the adjusted NSAA. */
541 + state->nsrn = N_V_ARG_REG;
542 + memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size),
549 + unsigned short type = get_homogeneous_type (ty);
550 + unsigned elems = element_count (ty);
551 + for (i = 0; i < elems; i++)
553 + void *reg = allocate_to_v (context, state);
554 + copy_basic_type (reg, memory, type);
555 + memory += get_basic_type_size (type);
560 +/* Either allocate an appropriate register for the argument type, or if
561 + none are available, allocate a stack slot and return a pointer
562 + to the allocated space. */
565 +allocate_to_register_or_stack (struct call_context *context,
566 + unsigned char *stack,
567 + struct arg_state *state,
568 + unsigned short type)
570 + size_t alignment = get_basic_type_alignment (type);
571 + size_t size = alignment;
574 + case FFI_TYPE_FLOAT:
575 + /* This is the only case for which the allocated stack size
576 + should not match the alignment of the type. */
577 + size = sizeof (UINT32);
578 + /* Fall through. */
579 + case FFI_TYPE_DOUBLE:
580 + if (state->nsrn < N_V_ARG_REG)
581 + return allocate_to_d (context, state);
582 + state->nsrn = N_V_ARG_REG;
584 + case FFI_TYPE_LONGDOUBLE:
585 + if (state->nsrn < N_V_ARG_REG)
586 + return allocate_to_v (context, state);
587 + state->nsrn = N_V_ARG_REG;
589 + case FFI_TYPE_UINT8:
590 + case FFI_TYPE_SINT8:
591 + case FFI_TYPE_UINT16:
592 + case FFI_TYPE_SINT16:
593 + case FFI_TYPE_UINT32:
594 + case FFI_TYPE_SINT32:
596 + case FFI_TYPE_POINTER:
597 + case FFI_TYPE_UINT64:
598 + case FFI_TYPE_SINT64:
599 + if (state->ngrn < N_X_ARG_REG)
600 + return allocate_to_x (context, state);
601 + state->ngrn = N_X_ARG_REG;
607 + return allocate_to_stack (state, stack, alignment, size);
610 +/* Copy a value to an appropriate register, or if none are
611 + available, to the stack. */
614 +copy_to_register_or_stack (struct call_context *context,
615 + unsigned char *stack,
616 + struct arg_state *state,
618 + unsigned short type)
621 + allocate_to_register_or_stack (context, stack, state, type),
626 +/* Marshall the arguments from FFI representation to procedure call
627 + context and stack. */
630 +aarch64_prep_args (struct call_context *context, unsigned char *stack,
631 + extended_cif *ecif)
634 + struct arg_state state;
636 + arg_init (&state, ALIGN(ecif->cif->bytes, 16));
638 + for (i = 0; i < ecif->cif->nargs; i++)
640 + ffi_type *ty = ecif->cif->arg_types[i];
643 + case FFI_TYPE_VOID:
647 + /* If the argument is a basic type the argument is allocated to an
648 + appropriate register, or if none are available, to the stack. */
649 + case FFI_TYPE_FLOAT:
650 + case FFI_TYPE_DOUBLE:
651 + case FFI_TYPE_LONGDOUBLE:
652 + case FFI_TYPE_UINT8:
653 + case FFI_TYPE_SINT8:
654 + case FFI_TYPE_UINT16:
655 + case FFI_TYPE_SINT16:
656 + case FFI_TYPE_UINT32:
658 + case FFI_TYPE_SINT32:
659 + case FFI_TYPE_POINTER:
660 + case FFI_TYPE_UINT64:
661 + case FFI_TYPE_SINT64:
662 + copy_to_register_or_stack (context, stack, &state,
663 + ecif->avalue[i], ty->type);
666 + case FFI_TYPE_STRUCT:
669 + copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context,
672 + else if (ty->size > 16)
674 + /* If the argument is a composite type that is larger than 16
675 + bytes, then the argument has been copied to memory, and
676 + the argument is replaced by a pointer to the copy. */
678 + copy_to_register_or_stack (context, stack, &state,
679 + &(ecif->avalue[i]), FFI_TYPE_POINTER);
681 + else if (available_x (&state) >= (ty->size + 7) / 8)
683 + /* If the argument is a composite type and the size in
684 + double-words is not more than the number of available
685 + X registers, then the argument is copied into consecutive
688 + for (j = 0; j < (ty->size + 7) / 8; j++)
690 + memcpy (allocate_to_x (context, &state),
691 + &(((UINT64 *) ecif->avalue[i])[j]),
697 + /* Otherwise, there are insufficient X registers. Further X
698 + register allocations are prevented, the NSAA is adjusted
699 + (by allocate_to_stack ()) and the argument is copied to
700 + memory at the adjusted NSAA. */
701 + state.ngrn = N_X_ARG_REG;
703 + memcpy (allocate_to_stack (&state, stack, ty->alignment,
704 + ty->size), ecif->avalue + i, ty->size);
714 + return ecif->cif->aarch64_flags;
718 +ffi_prep_cif_machdep (ffi_cif *cif)
720 + /* Round the stack up to a multiple of the stack alignment requirement. */
722 + (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1);
724 + /* Initialize our flags. We are interested if this CIF will touch a
725 + vector register, if so we will enable context save and load to
726 + those registers, otherwise not. This is intended to be friendly
727 + to lazy float context switching in the kernel. */
728 + cif->aarch64_flags = 0;
730 + if (is_v_register_candidate (cif->rtype))
732 + cif->aarch64_flags |= AARCH64_FFI_WITH_V;
737 + for (i = 0; i < cif->nargs; i++)
738 + if (is_v_register_candidate (cif->arg_types[i]))
740 + cif->aarch64_flags |= AARCH64_FFI_WITH_V;
748 +/* Call a function with the provided arguments and capture the return
751 +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
756 + ecif.avalue = avalue;
757 + ecif.rvalue = rvalue;
763 + struct call_context context;
764 + unsigned stack_bytes;
766 + /* Figure out the total amount of stack space we need, the
767 + above call frame space needs to be 16 bytes aligned to
768 + ensure correct alignment of the first object inserted in
769 + that space hence the ALIGN applied to cif->bytes.*/
770 + stack_bytes = ALIGN(cif->bytes, 16);
772 + memset (&context, 0, sizeof (context));
773 + if (is_register_candidate (cif->rtype))
775 + ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn);
776 + switch (cif->rtype->type)
778 + case FFI_TYPE_VOID:
779 + case FFI_TYPE_FLOAT:
780 + case FFI_TYPE_DOUBLE:
781 + case FFI_TYPE_LONGDOUBLE:
782 + case FFI_TYPE_UINT8:
783 + case FFI_TYPE_SINT8:
784 + case FFI_TYPE_UINT16:
785 + case FFI_TYPE_SINT16:
786 + case FFI_TYPE_UINT32:
787 + case FFI_TYPE_SINT32:
788 + case FFI_TYPE_POINTER:
789 + case FFI_TYPE_UINT64:
791 + case FFI_TYPE_SINT64:
793 + void *addr = get_basic_type_addr (cif->rtype->type,
795 + copy_basic_type (rvalue, addr, cif->rtype->type);
799 + case FFI_TYPE_STRUCT:
800 + if (is_hfa (cif->rtype))
803 + unsigned short type = get_homogeneous_type (cif->rtype);
804 + unsigned elems = element_count (cif->rtype);
805 + for (j = 0; j < elems; j++)
807 + void *reg = get_basic_type_addr (type, &context, j);
808 + copy_basic_type (rvalue, reg, type);
809 + rvalue += get_basic_type_size (type);
812 + else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
814 + unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64));
815 + memcpy (rvalue, get_x_addr (&context, 0), size);
830 + memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64));
831 + ffi_call_SYSV (aarch64_prep_args, &context, &ecif,
843 +static unsigned char trampoline [] =
844 +{ 0x70, 0x00, 0x00, 0x58, /* ldr x16, 1f */
845 + 0x91, 0x00, 0x00, 0x10, /* adr x17, 2f */
846 + 0x00, 0x02, 0x1f, 0xd6 /* br x16 */
849 +/* Build a trampoline. */
851 +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS) \
852 + ({unsigned char *__tramp = (unsigned char*)(TRAMP); \
853 + UINT64 __fun = (UINT64)(FUN); \
854 + UINT64 __ctx = (UINT64)(CTX); \
855 + UINT64 __flags = (UINT64)(FLAGS); \
856 + memcpy (__tramp, trampoline, sizeof (trampoline)); \
857 + memcpy (__tramp + 12, &__fun, sizeof (__fun)); \
858 + memcpy (__tramp + 20, &__ctx, sizeof (__ctx)); \
859 + memcpy (__tramp + 28, &__flags, sizeof (__flags)); \
860 + __clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE); \
864 +ffi_prep_closure_loc (ffi_closure* closure,
866 + void (*fun)(ffi_cif*,void*,void**,void*),
870 + if (cif->abi != FFI_SYSV)
871 + return FFI_BAD_ABI;
873 + FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc,
874 + cif->aarch64_flags);
876 + closure->cif = cif;
877 + closure->user_data = user_data;
878 + closure->fun = fun;
883 +/* Primary handler to setup and invoke a function within a closure.
885 + A closure when invoked enters via the assembler wrapper
886 + ffi_closure_SYSV(). The wrapper allocates a call context on the
887 + stack, saves the interesting registers (from the perspective of
888 + the calling convention) into the context then passes control to
889 + ffi_closure_SYSV_inner() passing the saved context and a pointer to
890 + the stack at the point ffi_closure_SYSV() was invoked.
892 + On the return path the assembler wrapper will reload call context
895 + ffi_closure_SYSV_inner() marshalls the call context into ffi value
896 + desriptors, invokes the wrapped function, then marshalls the return
897 + value back into the call context. */
900 +ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context,
903 + ffi_cif *cif = closure->cif;
904 + void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
905 + void *rvalue = NULL;
907 + struct arg_state state;
909 + arg_init (&state, ALIGN(cif->bytes, 16));
911 + for (i = 0; i < cif->nargs; i++)
913 + ffi_type *ty = cif->arg_types[i];
917 + case FFI_TYPE_VOID:
921 + case FFI_TYPE_UINT8:
922 + case FFI_TYPE_SINT8:
923 + case FFI_TYPE_UINT16:
924 + case FFI_TYPE_SINT16:
925 + case FFI_TYPE_UINT32:
926 + case FFI_TYPE_SINT32:
928 + case FFI_TYPE_POINTER:
929 + case FFI_TYPE_UINT64:
930 + case FFI_TYPE_SINT64:
931 + case FFI_TYPE_FLOAT:
932 + case FFI_TYPE_DOUBLE:
933 + case FFI_TYPE_LONGDOUBLE:
934 + avalue[i] = allocate_to_register_or_stack (context, stack,
938 + case FFI_TYPE_STRUCT:
941 + unsigned n = element_count (ty);
942 + if (available_v (&state) < n)
944 + state.nsrn = N_V_ARG_REG;
945 + avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
950 + switch (get_homogeneous_type (ty))
952 + case FFI_TYPE_FLOAT:
954 + /* Eeek! We need a pointer to the structure,
955 + however the homogeneous float elements are
956 + being passed in individual S registers,
957 + therefore the structure is not represented as
958 + a contiguous sequence of bytes in our saved
959 + register context. We need to fake up a copy
960 + of the structure layed out in memory
961 + correctly. The fake can be tossed once the
962 + closure function has returned hence alloca()
965 + UINT32 *p = avalue[i] = alloca (ty->size);
966 + for (j = 0; j < element_count (ty); j++)
968 + allocate_to_s (context, &state),
973 + case FFI_TYPE_DOUBLE:
975 + /* Eeek! We need a pointer to the structure,
976 + however the homogeneous float elements are
977 + being passed in individual S registers,
978 + therefore the structure is not represented as
979 + a contiguous sequence of bytes in our saved
980 + register context. We need to fake up a copy
981 + of the structure layed out in memory
982 + correctly. The fake can be tossed once the
983 + closure function has returned hence alloca()
986 + UINT64 *p = avalue[i] = alloca (ty->size);
987 + for (j = 0; j < element_count (ty); j++)
989 + allocate_to_d (context, &state),
994 + case FFI_TYPE_LONGDOUBLE:
995 + memcpy (&avalue[i],
996 + allocate_to_v (context, &state),
1006 + else if (ty->size > 16)
1008 + /* Replace Composite type of size greater than 16 with a
1010 + memcpy (&avalue[i],
1011 + allocate_to_register_or_stack (context, stack,
1012 + &state, FFI_TYPE_POINTER),
1013 + sizeof (avalue[i]));
1015 + else if (available_x (&state) >= (ty->size + 7) / 8)
1017 + avalue[i] = get_x_addr (context, state.ngrn);
1018 + state.ngrn += (ty->size + 7) / 8;
1022 + state.ngrn = N_X_ARG_REG;
1024 + avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
1035 + /* Figure out where the return value will be passed, either in
1036 + registers or in a memory block allocated by the caller and passed
1039 + if (is_register_candidate (cif->rtype))
1041 + /* Register candidates are *always* returned in registers. */
1043 + /* Allocate a scratchpad for the return value, we will let the
1044 + callee scrible the result into the scratch pad then move the
1045 + contents into the appropriate return value location for the
1046 + call convention. */
1047 + rvalue = alloca (cif->rtype->size);
1048 + (closure->fun) (cif, rvalue, avalue, closure->user_data);
1050 + /* Copy the return value into the call context so that it is returned
1051 + as expected to our caller. */
1052 + switch (cif->rtype->type)
1054 + case FFI_TYPE_VOID:
1057 + case FFI_TYPE_UINT8:
1058 + case FFI_TYPE_UINT16:
1059 + case FFI_TYPE_UINT32:
1060 + case FFI_TYPE_POINTER:
1061 + case FFI_TYPE_UINT64:
1062 + case FFI_TYPE_SINT8:
1063 + case FFI_TYPE_SINT16:
1064 + case FFI_TYPE_INT:
1065 + case FFI_TYPE_SINT32:
1066 + case FFI_TYPE_SINT64:
1067 + case FFI_TYPE_FLOAT:
1068 + case FFI_TYPE_DOUBLE:
1069 + case FFI_TYPE_LONGDOUBLE:
1071 + void *addr = get_basic_type_addr (cif->rtype->type, context, 0);
1072 + copy_basic_type (addr, rvalue, cif->rtype->type);
1075 + case FFI_TYPE_STRUCT:
1076 + if (is_hfa (cif->rtype))
1079 + unsigned short type = get_homogeneous_type (cif->rtype);
1080 + unsigned elems = element_count (cif->rtype);
1081 + for (i = 0; i < elems; i++)
1083 + void *reg = get_basic_type_addr (type, context, i);
1084 + copy_basic_type (reg, rvalue, type);
1085 + rvalue += get_basic_type_size (type);
1088 + else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
1090 + unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64)) ;
1091 + memcpy (get_x_addr (context, 0), rvalue, size);
1105 + memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64));
1106 + (closure->fun) (cif, rvalue, avalue, closure->user_data);
1110 Index: libffi/src/aarch64/ffitarget.h
1111 ===================================================================
1113 +++ libffi/src/aarch64/ffitarget.h
1115 +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
1117 +Permission is hereby granted, free of charge, to any person obtaining
1118 +a copy of this software and associated documentation files (the
1119 +``Software''), to deal in the Software without restriction, including
1120 +without limitation the rights to use, copy, modify, merge, publish,
1121 +distribute, sublicense, and/or sell copies of the Software, and to
1122 +permit persons to whom the Software is furnished to do so, subject to
1123 +the following conditions:
1125 +The above copyright notice and this permission notice shall be
1126 +included in all copies or substantial portions of the Software.
1128 +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
1129 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1130 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1131 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1132 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1133 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1134 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
1136 +#ifndef LIBFFI_TARGET_H
1137 +#define LIBFFI_TARGET_H
1140 +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
1144 +typedef unsigned long ffi_arg;
1145 +typedef signed long ffi_sarg;
1147 +typedef enum ffi_abi
1149 + FFI_FIRST_ABI = 0,
1152 + FFI_DEFAULT_ABI = FFI_SYSV
1156 +/* ---- Definitions for closures ----------------------------------------- */
1158 +#define FFI_CLOSURES 1
1159 +#define FFI_TRAMPOLINE_SIZE 36
1160 +#define FFI_NATIVE_RAW_API 0
1162 +/* ---- Internal ---- */
1165 +#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
1167 +#define AARCH64_FFI_WITH_V_BIT 0
1169 +#define AARCH64_N_XREG 32
1170 +#define AARCH64_N_VREG 32
1171 +#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
1174 Index: libffi/src/aarch64/sysv.S
1175 ===================================================================
1177 +++ libffi/src/aarch64/sysv.S
1179 +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
1181 +Permission is hereby granted, free of charge, to any person obtaining
1182 +a copy of this software and associated documentation files (the
1183 +``Software''), to deal in the Software without restriction, including
1184 +without limitation the rights to use, copy, modify, merge, publish,
1185 +distribute, sublicense, and/or sell copies of the Software, and to
1186 +permit persons to whom the Software is furnished to do so, subject to
1187 +the following conditions:
1189 +The above copyright notice and this permission notice shall be
1190 +included in all copies or substantial portions of the Software.
1192 +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
1193 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1194 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1195 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1196 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1197 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1198 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
1201 +#include <fficonfig.h>
1204 +#define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
1205 +#define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
1206 +#define cfi_restore(reg) .cfi_restore reg
1207 +#define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
1210 + .globl ffi_call_SYSV
1211 + .type ffi_call_SYSV, #function
1215 + Create a stack frame, setup an argument context, call the callee
1216 + and extract the result.
1218 + The maximum required argument stack size is provided,
1219 + ffi_call_SYSV() allocates that stack space then calls the
1220 + prepare_fn to populate register context and stack. The
1221 + argument passing registers are loaded from the register
1222 + context and the callee called, on return the register passing
1223 + register are saved back to the context. Our caller will
1224 + extract the return value from the final state of the saved
1230 + ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
1232 + struct call_context *context,
1234 + unsigned required_stack_size,
1235 + void (*fn)(void));
1237 + Therefore on entry we have:
1245 + This function uses the following stack frame layout:
1249 + x29(fp)-> saved x29(fp)
1255 + sp -> (constructed callee stack arguments)
1260 +#define ffi_call_SYSV_FS (8 * 4)
1264 + stp x29, x30, [sp, #-16]!
1265 + cfi_adjust_cfa_offset (16)
1266 + cfi_rel_offset (x29, 0)
1267 + cfi_rel_offset (x30, 8)
1270 + cfi_def_cfa_register (x29)
1271 + sub sp, sp, #ffi_call_SYSV_FS
1273 + stp x21, x22, [sp, 0]
1274 + cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS)
1275 + cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS)
1277 + stp x23, x24, [sp, 16]
1278 + cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS)
1279 + cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS)
1285 + /* Allocate the stack space for the actual arguments, many
1286 + arguments will be passed in registers, but we assume
1287 + worst case and allocate sufficient stack for ALL of
1291 + /* unsigned (*prepare_fn) (struct call_context *context,
1292 + unsigned char *stack, extended_cif *ecif);
1297 + /* x2 already in place */
1300 + /* Preserve the flags returned. */
1303 + /* Figure out if we should touch the vector registers. */
1304 + tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f
1306 + /* Load the vector argument passing registers. */
1307 + ldp q0, q1, [x21, #8*32 + 0]
1308 + ldp q2, q3, [x21, #8*32 + 32]
1309 + ldp q4, q5, [x21, #8*32 + 64]
1310 + ldp q6, q7, [x21, #8*32 + 96]
1312 + /* Load the core argument passing registers. */
1313 + ldp x0, x1, [x21, #0]
1314 + ldp x2, x3, [x21, #16]
1315 + ldp x4, x5, [x21, #32]
1316 + ldp x6, x7, [x21, #48]
1318 + /* Don't forget x8 which may be holding the address of a return buffer.
1320 + ldr x8, [x21, #8*8]
1324 + /* Save the core argument passing registers. */
1325 + stp x0, x1, [x21, #0]
1326 + stp x2, x3, [x21, #16]
1327 + stp x4, x5, [x21, #32]
1328 + stp x6, x7, [x21, #48]
1330 + /* Note nothing useful ever comes back in x8! */
1332 + /* Figure out if we should touch the vector registers. */
1333 + tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f
1335 + /* Save the vector argument passing registers. */
1336 + stp q0, q1, [x21, #8*32 + 0]
1337 + stp q2, q3, [x21, #8*32 + 32]
1338 + stp q4, q5, [x21, #8*32 + 64]
1339 + stp q6, q7, [x21, #8*32 + 96]
1341 + /* All done, unwind our stack frame. */
1342 + ldp x21, x22, [x29, # - ffi_call_SYSV_FS]
1346 + ldp x23, x24, [x29, # - ffi_call_SYSV_FS + 16]
1351 + cfi_def_cfa_register (sp)
1353 + ldp x29, x30, [sp], #16
1354 + cfi_adjust_cfa_offset (-16)
1361 + .size ffi_call_SYSV, .-ffi_call_SYSV
1363 +#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
1365 +/* ffi_closure_SYSV
1367 + Closure invocation glue. This is the low level code invoked directly by
1368 + the closure trampoline to setup and call a closure.
1370 + On entry x17 points to a struct trampoline_data, x16 has been clobbered
1371 + all other registers are preserved.
1373 + We allocate a call context and save the argument passing registers,
1374 + then invoked the generic C ffi_closure_SYSV_inner() function to do all
1375 + the real work, on return we load the result passing registers back from
1381 + ffi_closure_SYSV (struct trampoline_data *);
1383 + struct trampoline_data
1385 + UINT64 *ffi_closure;
1389 + This function uses the following stack frame layout:
1393 + x29(fp)-> saved x29(fp)
1397 + sp -> call_context
1403 + .globl ffi_closure_SYSV
1406 + stp x29, x30, [sp, #-16]!
1407 + cfi_adjust_cfa_offset (16)
1408 + cfi_rel_offset (x29, 0)
1409 + cfi_rel_offset (x30, 8)
1413 + sub sp, sp, #ffi_closure_SYSV_FS
1414 + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
1416 + stp x21, x22, [x29, #-16]
1417 + cfi_rel_offset (x21, 0)
1418 + cfi_rel_offset (x22, 8)
1420 + /* Load x21 with &call_context. */
1422 + /* Preserve our struct trampoline_data * */
1425 + /* Save the rest of the argument passing registers. */
1426 + stp x0, x1, [x21, #0]
1427 + stp x2, x3, [x21, #16]
1428 + stp x4, x5, [x21, #32]
1429 + stp x6, x7, [x21, #48]
1430 + /* Don't forget we may have been given a result scratch pad address.
1432 + str x8, [x21, #64]
1434 + /* Figure out if we should touch the vector registers. */
1436 + tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f
1438 + /* Save the argument passing vector registers. */
1439 + stp q0, q1, [x21, #8*32 + 0]
1440 + stp q2, q3, [x21, #8*32 + 32]
1441 + stp q4, q5, [x21, #8*32 + 64]
1442 + stp q6, q7, [x21, #8*32 + 96]
1444 + /* Load &ffi_closure.. */
1447 + /* Compute the location of the stack at the point that the
1448 + trampoline was called. */
1451 + bl ffi_closure_SYSV_inner
1453 + /* Figure out if we should touch the vector registers. */
1455 + tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f
1457 + /* Load the result passing vector registers. */
1458 + ldp q0, q1, [x21, #8*32 + 0]
1459 + ldp q2, q3, [x21, #8*32 + 32]
1460 + ldp q4, q5, [x21, #8*32 + 64]
1461 + ldp q6, q7, [x21, #8*32 + 96]
1463 + /* Load the result passing core registers. */
1464 + ldp x0, x1, [x21, #0]
1465 + ldp x2, x3, [x21, #16]
1466 + ldp x4, x5, [x21, #32]
1467 + ldp x6, x7, [x21, #48]
1468 + /* Note nothing usefull is returned in x8. */
1470 + /* We are done, unwind our frame. */
1471 + ldp x21, x22, [x29, #-16]
1476 + cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
1478 + ldp x29, x30, [sp], #16
1479 + cfi_adjust_cfa_offset (-16)
1485 + .size ffi_closure_SYSV, .-ffi_closure_SYSV
1486 Index: libffi/testsuite/lib/libffi.exp
1487 ===================================================================
1488 --- libffi.orig/testsuite/lib/libffi.exp
1489 +++ libffi/testsuite/lib/libffi.exp
1490 @@ -203,6 +203,10 @@ proc libffi_target_compile { source dest
1492 lappend options "libs= -lffi"
1494 + if { [string match "aarch64*-*-linux*" $target_triplet] } {
1495 + lappend options "libs= -lpthread"
1498 verbose "options: $options"
1499 return [target_compile $source $dest $type $options]
1501 Index: libffi/testsuite/libffi.call/cls_struct_va1.c
1502 ===================================================================
1504 +++ libffi/testsuite/libffi.call/cls_struct_va1.c
1506 +/* Area: ffi_call, closure_call
1507 + Purpose: Test doubles passed in variable argument lists.
1508 + Limitations: none.
1510 + Originator: Blake Chaffin 6/6/2007 */
1512 +/* { dg-do run } */
1513 +/* { dg-output "" { xfail avr32*-*-* } } */
1514 +#include "ffitest.h"
1532 +test_fn (ffi_cif* cif __UNUSED__, void* resp,
1533 + void** args, void* userdata __UNUSED__)
1535 + int n = *(int*)args[0];
1536 + struct small_tag s1 = * (struct small_tag *) args[1];
1537 + struct large_tag l1 = * (struct large_tag *) args[2];
1538 + struct small_tag s2 = * (struct small_tag *) args[3];
1540 + printf ("%d %d %d %d %d %d %d %d %d %d\n", n, s1.a, s1.b,
1541 + l1.a, l1.b, l1.c, l1.d, l1.e,
1543 + * (int*) resp = 42;
1551 + ffi_closure *pcl = ffi_closure_alloc (sizeof (ffi_closure), &code);
1552 + ffi_type* arg_types[5];
1557 + ffi_type *s_type_elements[3];
1560 + ffi_type *l_type_elements[6];
1562 + struct small_tag s1;
1563 + struct small_tag s2;
1564 + struct large_tag l1;
1569 + s_type.alignment = 0;
1570 + s_type.type = FFI_TYPE_STRUCT;
1571 + s_type.elements = s_type_elements;
1573 + s_type_elements[0] = &ffi_type_uchar;
1574 + s_type_elements[1] = &ffi_type_uchar;
1575 + s_type_elements[2] = NULL;
1578 + l_type.alignment = 0;
1579 + l_type.type = FFI_TYPE_STRUCT;
1580 + l_type.elements = l_type_elements;
1582 + l_type_elements[0] = &ffi_type_uint;
1583 + l_type_elements[1] = &ffi_type_uint;
1584 + l_type_elements[2] = &ffi_type_uint;
1585 + l_type_elements[3] = &ffi_type_uint;
1586 + l_type_elements[4] = &ffi_type_uint;
1587 + l_type_elements[5] = NULL;
1589 + arg_types[0] = &ffi_type_sint;
1590 + arg_types[1] = &s_type;
1591 + arg_types[2] = &l_type;
1592 + arg_types[3] = &s_type;
1593 + arg_types[4] = NULL;
1595 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint,
1596 + arg_types) == FFI_OK);
1611 + CHECK(ffi_prep_closure_loc(pcl, &cif, test_fn, NULL, code) == FFI_OK);
1613 + res = ((int (*)(int, ...))(code))(si, s1, l1, s2);
1614 + // { dg-output "4 5 6 10 11 12 13 14 20 21" }
1615 + printf("res: %d\n", (int) res);
1616 + // { dg-output "\nres: 42" }
1620 Index: libffi/testsuite/libffi.call/cls_uchar_va.c
1621 ===================================================================
1623 +++ libffi/testsuite/libffi.call/cls_uchar_va.c
1625 +/* Area: closure_call
1626 + Purpose: Test anonymous unsigned char argument.
1627 + Limitations: none.
1629 + Originator: ARM Ltd. */
1631 +/* { dg-do run } */
1632 +#include "ffitest.h"
1634 +typedef unsigned char T;
1636 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1637 + void* userdata __UNUSED__)
1639 + *(T *)resp = *(T *)args[0];
1641 + printf("%d: %d %d\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1644 +typedef T (*cls_ret_T)(T, ...);
1650 + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1651 + ffi_type * cl_arg_types[3];
1654 + cl_arg_types[0] = &ffi_type_uchar;
1655 + cl_arg_types[1] = &ffi_type_uchar;
1656 + cl_arg_types[2] = NULL;
1658 + /* Initialize the cif */
1659 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1660 + &ffi_type_uchar, cl_arg_types) == FFI_OK);
1662 + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK);
1663 + res = ((((cls_ret_T)code)(67, 4)));
1664 + /* { dg-output "67: 67 4" } */
1665 + printf("res: %d\n", res);
1666 + /* { dg-output "\nres: 67" } */
1669 Index: libffi/testsuite/libffi.call/cls_uint_va.c
1670 ===================================================================
1672 +++ libffi/testsuite/libffi.call/cls_uint_va.c
1674 +/* Area: closure_call
1675 + Purpose: Test anonymous unsigned int argument.
1676 + Limitations: none.
1678 + Originator: ARM Ltd. */
1680 +/* { dg-do run } */
1682 +#include "ffitest.h"
1684 +typedef unsigned int T;
1686 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1687 + void* userdata __UNUSED__)
1689 + *(T *)resp = *(T *)args[0];
1691 + printf("%d: %d %d\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1694 +typedef T (*cls_ret_T)(T, ...);
1700 + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1701 + ffi_type * cl_arg_types[3];
1704 + cl_arg_types[0] = &ffi_type_uint;
1705 + cl_arg_types[1] = &ffi_type_uint;
1706 + cl_arg_types[2] = NULL;
1708 + /* Initialize the cif */
1709 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1710 + &ffi_type_uint, cl_arg_types) == FFI_OK);
1712 + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK);
1713 + res = ((((cls_ret_T)code)(67, 4)));
1714 + /* { dg-output "67: 67 4" } */
1715 + printf("res: %d\n", res);
1716 + /* { dg-output "\nres: 67" } */
1719 Index: libffi/testsuite/libffi.call/cls_ulong_va.c
1720 ===================================================================
1722 +++ libffi/testsuite/libffi.call/cls_ulong_va.c
1724 +/* Area: closure_call
1725 + Purpose: Test anonymous unsigned long argument.
1726 + Limitations: none.
1728 + Originator: ARM Ltd. */
1730 +/* { dg-do run } */
1732 +#include "ffitest.h"
1734 +typedef unsigned long T;
1736 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1737 + void* userdata __UNUSED__)
1739 + *(T *)resp = *(T *)args[0];
1741 + printf("%ld: %ld %ld\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1744 +typedef T (*cls_ret_T)(T, ...);
1750 + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1751 + ffi_type * cl_arg_types[3];
1754 + cl_arg_types[0] = &ffi_type_ulong;
1755 + cl_arg_types[1] = &ffi_type_ulong;
1756 + cl_arg_types[2] = NULL;
1758 + /* Initialize the cif */
1759 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1760 + &ffi_type_ulong, cl_arg_types) == FFI_OK);
1762 + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK);
1763 + res = ((((cls_ret_T)code)(67, 4)));
1764 + /* { dg-output "67: 67 4" } */
1765 + printf("res: %ld\n", res);
1766 + /* { dg-output "\nres: 67" } */
1769 Index: libffi/testsuite/libffi.call/cls_ushort_va.c
1770 ===================================================================
1772 +++ libffi/testsuite/libffi.call/cls_ushort_va.c
1774 +/* Area: closure_call
1775 + Purpose: Test anonymous unsigned short argument.
1776 + Limitations: none.
1778 + Originator: ARM Ltd. */
1780 +/* { dg-do run } */
1781 +#include "ffitest.h"
1783 +typedef unsigned short T;
1785 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1786 + void* userdata __UNUSED__)
1788 + *(T *)resp = *(T *)args[0];
1790 + printf("%d: %d %d\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1793 +typedef T (*cls_ret_T)(T, ...);
1799 + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1800 + ffi_type * cl_arg_types[3];
1803 + cl_arg_types[0] = &ffi_type_ushort;
1804 + cl_arg_types[1] = &ffi_type_ushort;
1805 + cl_arg_types[2] = NULL;
1807 + /* Initialize the cif */
1808 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1809 + &ffi_type_ushort, cl_arg_types) == FFI_OK);
1811 + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK);
1812 + res = ((((cls_ret_T)code)(67, 4)));
1813 + /* { dg-output "67: 67 4" } */
1814 + printf("res: %d\n", res);
1815 + /* { dg-output "\nres: 67" } */
1818 Index: libffi/testsuite/libffi.call/nested_struct11.c
1819 ===================================================================
1821 +++ libffi/testsuite/libffi.call/nested_struct11.c
1823 +/* Area: ffi_call, closure_call
1824 + Purpose: Check parameter passing with nested structs
1825 + of a single type. This tests the special cases
1826 + for homogenous floating-point aggregates in the
1828 + Limitations: none.
1830 + Originator: ARM Ltd. */
1832 +/* { dg-do run } */
1833 +#include "ffitest.h"
1850 +static C C_fn (int x, int y, int z, C source, int i, int j, int k)
1853 + result.a.a_x = source.a.a_x;
1854 + result.a.a_y = source.a.a_y;
1855 + result.b.b_x = source.b.b_x;
1856 + result.b.b_y = source.b.b_y;
1858 + printf ("%d, %d, %d, %d, %d, %d\n", x, y, z, i, j, k);
1860 + printf ("%.1f, %.1f, %.1f, %.1f, "
1861 + "%.1f, %.1f, %.1f, %.1f\n",
1862 + source.a.a_x, source.a.a_y,
1863 + source.b.b_x, source.b.b_y,
1864 + result.a.a_x, result.a.a_y,
1865 + result.b.b_x, result.b.b_y);
1874 + ffi_type* struct_fields_source_a[3];
1875 + ffi_type* struct_fields_source_b[3];
1876 + ffi_type* struct_fields_source_c[3];
1877 + ffi_type* arg_types[8];
1879 + ffi_type struct_type_a, struct_type_b, struct_type_c;
1881 + struct A source_fld_a = {1.0, 2.0};
1882 + struct B source_fld_b = {4.0, 8.0};
1886 + struct C source = {source_fld_a, source_fld_b};
1888 + struct_type_a.size = 0;
1889 + struct_type_a.alignment = 0;
1890 + struct_type_a.type = FFI_TYPE_STRUCT;
1891 + struct_type_a.elements = struct_fields_source_a;
1893 + struct_type_b.size = 0;
1894 + struct_type_b.alignment = 0;
1895 + struct_type_b.type = FFI_TYPE_STRUCT;
1896 + struct_type_b.elements = struct_fields_source_b;
1898 + struct_type_c.size = 0;
1899 + struct_type_c.alignment = 0;
1900 + struct_type_c.type = FFI_TYPE_STRUCT;
1901 + struct_type_c.elements = struct_fields_source_c;
1903 + struct_fields_source_a[0] = &ffi_type_float;
1904 + struct_fields_source_a[1] = &ffi_type_float;
1905 + struct_fields_source_a[2] = NULL;
1907 + struct_fields_source_b[0] = &ffi_type_float;
1908 + struct_fields_source_b[1] = &ffi_type_float;
1909 + struct_fields_source_b[2] = NULL;
1911 + struct_fields_source_c[0] = &struct_type_a;
1912 + struct_fields_source_c[1] = &struct_type_b;
1913 + struct_fields_source_c[2] = NULL;
1915 + arg_types[0] = &ffi_type_sint32;
1916 + arg_types[1] = &ffi_type_sint32;
1917 + arg_types[2] = &ffi_type_sint32;
1918 + arg_types[3] = &struct_type_c;
1919 + arg_types[4] = &ffi_type_sint32;
1920 + arg_types[5] = &ffi_type_sint32;
1921 + arg_types[6] = &ffi_type_sint32;
1922 + arg_types[7] = NULL;
1928 + args[3] = &source;
1932 + CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, 7, &struct_type_c,
1933 + arg_types) == FFI_OK);
1935 + ffi_call (&cif, FFI_FN (C_fn), &result, args);
1936 + /* { dg-output "1, 1, 1, 1, 1, 1\n" } */
1937 + /* { dg-output "1.0, 2.0, 4.0, 8.0, 1.0, 2.0, 4.0, 8.0" } */
1938 + CHECK (result.a.a_x == source.a.a_x);
1939 + CHECK (result.a.a_y == source.a.a_y);
1940 + CHECK (result.b.b_x == source.b.b_x);
1941 + CHECK (result.b.b_y == source.b.b_y);
1944 Index: libffi/testsuite/libffi.call/uninitialized.c
1945 ===================================================================
1947 +++ libffi/testsuite/libffi.call/uninitialized.c
1949 +/* { dg-do run } */
1950 +#include "ffitest.h"
1957 +} test_structure_1;
1959 +static test_structure_1 struct1(test_structure_1 ts)
1971 + ffi_type *args[MAX_ARGS];
1972 + void *values[MAX_ARGS];
1973 + ffi_type ts1_type;
1974 + ffi_type *ts1_type_elements[4];
1976 + memset(&cif, 1, sizeof(cif));
1977 + ts1_type.size = 0;
1978 + ts1_type.alignment = 0;
1979 + ts1_type.type = FFI_TYPE_STRUCT;
1980 + ts1_type.elements = ts1_type_elements;
1981 + ts1_type_elements[0] = &ffi_type_uchar;
1982 + ts1_type_elements[1] = &ffi_type_double;
1983 + ts1_type_elements[2] = &ffi_type_uint;
1984 + ts1_type_elements[3] = NULL;
1986 + test_structure_1 ts1_arg;
1987 + /* This is a hack to get a properly aligned result buffer */
1988 + test_structure_1 *ts1_result =
1989 + (test_structure_1 *) malloc (sizeof(test_structure_1));
1991 + args[0] = &ts1_type;
1992 + values[0] = &ts1_arg;
1994 + /* Initialize the cif */
1995 + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
1996 + &ts1_type, args) == FFI_OK);
1998 + ts1_arg.uc = '\x01';
1999 + ts1_arg.d = 3.14159;
2002 + ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
2004 + CHECK(ts1_result->ui == 556);
2005 + CHECK(ts1_result->d == 3.14159 - 1);
2007 + free (ts1_result);
2010 Index: libffi/testsuite/libffi.call/va_1.c
2011 ===================================================================
2013 +++ libffi/testsuite/libffi.call/va_1.c
2016 + Purpose: Test passing struct in variable argument lists.
2017 + Limitations: none.
2019 + Originator: ARM Ltd. */
2021 +/* { dg-do run } */
2022 +/* { dg-output "" { xfail avr32*-*-* x86_64-*-*-* } } */
2024 +#include "ffitest.h"
2025 +#include <stdarg.h>
2043 +test_fn (int n, ...)
2046 + struct small_tag s1;
2047 + struct small_tag s2;
2048 + struct large_tag l;
2051 + unsigned short us;
2061 + s1 = va_arg (ap, struct small_tag);
2062 + l = va_arg (ap, struct large_tag);
2063 + s2 = va_arg (ap, struct small_tag);
2065 + uc = va_arg (ap, unsigned);
2066 + sc = va_arg (ap, signed);
2068 + us = va_arg (ap, unsigned);
2069 + ss = va_arg (ap, signed);
2071 + ui = va_arg (ap, unsigned int);
2072 + si = va_arg (ap, signed int);
2074 + ul = va_arg (ap, unsigned long);
2075 + sl = va_arg (ap, signed long);
2077 + f = va_arg (ap, double); /* C standard promotes float->double
2079 + d = va_arg (ap, double);
2081 + printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
2082 + s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2098 + ffi_type* arg_types[15];
2101 + ffi_type *s_type_elements[3];
2104 + ffi_type *l_type_elements[6];
2106 + struct small_tag s1;
2107 + struct small_tag s2;
2108 + struct large_tag l1;
2115 + unsigned short us;
2125 + s_type.alignment = 0;
2126 + s_type.type = FFI_TYPE_STRUCT;
2127 + s_type.elements = s_type_elements;
2129 + s_type_elements[0] = &ffi_type_uchar;
2130 + s_type_elements[1] = &ffi_type_uchar;
2131 + s_type_elements[2] = NULL;
2134 + l_type.alignment = 0;
2135 + l_type.type = FFI_TYPE_STRUCT;
2136 + l_type.elements = l_type_elements;
2138 + l_type_elements[0] = &ffi_type_uint;
2139 + l_type_elements[1] = &ffi_type_uint;
2140 + l_type_elements[2] = &ffi_type_uint;
2141 + l_type_elements[3] = &ffi_type_uint;
2142 + l_type_elements[4] = &ffi_type_uint;
2143 + l_type_elements[5] = NULL;
2145 + arg_types[0] = &ffi_type_sint;
2146 + arg_types[1] = &s_type;
2147 + arg_types[2] = &l_type;
2148 + arg_types[3] = &s_type;
2149 + arg_types[4] = &ffi_type_uint;
2150 + arg_types[5] = &ffi_type_sint;
2151 + arg_types[6] = &ffi_type_uint;
2152 + arg_types[7] = &ffi_type_sint;
2153 + arg_types[8] = &ffi_type_uint;
2154 + arg_types[9] = &ffi_type_sint;
2155 + arg_types[10] = &ffi_type_ulong;
2156 + arg_types[11] = &ffi_type_slong;
2157 + arg_types[12] = &ffi_type_double;
2158 + arg_types[13] = &ffi_type_double;
2159 + arg_types[14] = NULL;
2161 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
2204 + ffi_call(&cif, FFI_FN(test_fn), &res, args);
2205 + /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
2206 + printf("res: %d\n", (int) res);
2207 + /* { dg-output "\nres: 42" } */
2211 Index: libffi/testsuite/libffi.call/va_struct1.c
2212 ===================================================================
2214 +++ libffi/testsuite/libffi.call/va_struct1.c
2217 + Purpose: Test passing struct in variable argument lists.
2218 + Limitations: none.
2220 + Originator: ARM Ltd. */
2222 +/* { dg-do run } */
2223 +/* { dg-output "" { xfail avr32*-*-* } } */
2225 +#include "ffitest.h"
2226 +#include <stdarg.h>
2244 +test_fn (int n, ...)
2247 + struct small_tag s1;
2248 + struct small_tag s2;
2249 + struct large_tag l;
2252 + s1 = va_arg (ap, struct small_tag);
2253 + l = va_arg (ap, struct large_tag);
2254 + s2 = va_arg (ap, struct small_tag);
2255 + printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2266 + ffi_type* arg_types[5];
2269 + ffi_type *s_type_elements[3];
2272 + ffi_type *l_type_elements[6];
2274 + struct small_tag s1;
2275 + struct small_tag s2;
2276 + struct large_tag l1;
2282 + s_type.alignment = 0;
2283 + s_type.type = FFI_TYPE_STRUCT;
2284 + s_type.elements = s_type_elements;
2286 + s_type_elements[0] = &ffi_type_uchar;
2287 + s_type_elements[1] = &ffi_type_uchar;
2288 + s_type_elements[2] = NULL;
2291 + l_type.alignment = 0;
2292 + l_type.type = FFI_TYPE_STRUCT;
2293 + l_type.elements = l_type_elements;
2295 + l_type_elements[0] = &ffi_type_uint;
2296 + l_type_elements[1] = &ffi_type_uint;
2297 + l_type_elements[2] = &ffi_type_uint;
2298 + l_type_elements[3] = &ffi_type_uint;
2299 + l_type_elements[4] = &ffi_type_uint;
2300 + l_type_elements[5] = NULL;
2302 + arg_types[0] = &ffi_type_sint;
2303 + arg_types[1] = &s_type;
2304 + arg_types[2] = &l_type;
2305 + arg_types[3] = &s_type;
2306 + arg_types[4] = NULL;
2308 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK);
2330 + ffi_call(&cif, FFI_FN(test_fn), &res, args);
2331 + /* { dg-output "5 6 10 11 12 13 14 7 8" } */
2332 + printf("res: %d\n", (int) res);
2333 + /* { dg-output "\nres: 42" } */
2337 Index: libffi/testsuite/libffi.call/va_struct2.c
2338 ===================================================================
2340 +++ libffi/testsuite/libffi.call/va_struct2.c
2343 + Purpose: Test passing struct in variable argument lists.
2344 + Limitations: none.
2346 + Originator: ARM Ltd. */
2348 +/* { dg-do run } */
2349 +/* { dg-output "" { xfail avr32*-*-* } } */
2351 +#include "ffitest.h"
2352 +#include <stdarg.h>
2369 +static struct small_tag
2370 +test_fn (int n, ...)
2373 + struct small_tag s1;
2374 + struct small_tag s2;
2375 + struct large_tag l;
2378 + s1 = va_arg (ap, struct small_tag);
2379 + l = va_arg (ap, struct large_tag);
2380 + s2 = va_arg (ap, struct small_tag);
2381 + printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2394 + ffi_type* arg_types[5];
2397 + ffi_type *s_type_elements[3];
2400 + ffi_type *l_type_elements[6];
2402 + struct small_tag s1;
2403 + struct small_tag s2;
2404 + struct large_tag l1;
2407 + struct small_tag res;
2410 + s_type.alignment = 0;
2411 + s_type.type = FFI_TYPE_STRUCT;
2412 + s_type.elements = s_type_elements;
2414 + s_type_elements[0] = &ffi_type_uchar;
2415 + s_type_elements[1] = &ffi_type_uchar;
2416 + s_type_elements[2] = NULL;
2419 + l_type.alignment = 0;
2420 + l_type.type = FFI_TYPE_STRUCT;
2421 + l_type.elements = l_type_elements;
2423 + l_type_elements[0] = &ffi_type_uint;
2424 + l_type_elements[1] = &ffi_type_uint;
2425 + l_type_elements[2] = &ffi_type_uint;
2426 + l_type_elements[3] = &ffi_type_uint;
2427 + l_type_elements[4] = &ffi_type_uint;
2428 + l_type_elements[5] = NULL;
2430 + arg_types[0] = &ffi_type_sint;
2431 + arg_types[1] = &s_type;
2432 + arg_types[2] = &l_type;
2433 + arg_types[3] = &s_type;
2434 + arg_types[4] = NULL;
2436 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &s_type, arg_types) == FFI_OK);
2458 + ffi_call(&cif, FFI_FN(test_fn), &res, args);
2459 + /* { dg-output "5 6 10 11 12 13 14 7 8" } */
2460 + printf("res: %d %d\n", res.a, res.b);
2461 + /* { dg-output "\nres: 12 14" } */
2465 Index: libffi/testsuite/libffi.call/va_struct3.c
2466 ===================================================================
2468 +++ libffi/testsuite/libffi.call/va_struct3.c
2471 + Purpose: Test passing struct in variable argument lists.
2472 + Limitations: none.
2474 + Originator: ARM Ltd. */
2476 +/* { dg-do run } */
2477 +/* { dg-output "" { xfail avr32*-*-* } } */
2479 +#include "ffitest.h"
2480 +#include <stdarg.h>
2497 +static struct large_tag
2498 +test_fn (int n, ...)
2501 + struct small_tag s1;
2502 + struct small_tag s2;
2503 + struct large_tag l;
2506 + s1 = va_arg (ap, struct small_tag);
2507 + l = va_arg (ap, struct large_tag);
2508 + s2 = va_arg (ap, struct small_tag);
2509 + printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2524 + ffi_type* arg_types[5];
2527 + ffi_type *s_type_elements[3];
2530 + ffi_type *l_type_elements[6];
2532 + struct small_tag s1;
2533 + struct small_tag s2;
2534 + struct large_tag l1;
2537 + struct large_tag res;
2540 + s_type.alignment = 0;
2541 + s_type.type = FFI_TYPE_STRUCT;
2542 + s_type.elements = s_type_elements;
2544 + s_type_elements[0] = &ffi_type_uchar;
2545 + s_type_elements[1] = &ffi_type_uchar;
2546 + s_type_elements[2] = NULL;
2549 + l_type.alignment = 0;
2550 + l_type.type = FFI_TYPE_STRUCT;
2551 + l_type.elements = l_type_elements;
2553 + l_type_elements[0] = &ffi_type_uint;
2554 + l_type_elements[1] = &ffi_type_uint;
2555 + l_type_elements[2] = &ffi_type_uint;
2556 + l_type_elements[3] = &ffi_type_uint;
2557 + l_type_elements[4] = &ffi_type_uint;
2558 + l_type_elements[5] = NULL;
2560 + arg_types[0] = &ffi_type_sint;
2561 + arg_types[1] = &s_type;
2562 + arg_types[2] = &l_type;
2563 + arg_types[3] = &s_type;
2564 + arg_types[4] = NULL;
2566 + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK);
2588 + ffi_call(&cif, FFI_FN(test_fn), &res, args);
2589 + /* { dg-output "5 6 10 11 12 13 14 7 8" } */
2590 + printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e);
2591 + /* { dg-output "\nres: 15 17 19 21 14" } */
2595 Index: libffi/ChangeLog
2596 ===================================================================
2597 --- libffi.orig/ChangeLog
2598 +++ libffi/ChangeLog
2600 +2012-10-30 James Greenhalgh <james.greenhalgh at arm.com>
2601 + Marcus Shawcroft <marcus.shawcroft at arm.com>
2603 + * README: Add details of aarch64 port.
2604 + * src/aarch64/ffi.c: New.
2605 + * src/aarch64/ffitarget.h: Likewise.
2606 + * src/aarch64/sysv.S: Likewise.
2608 +2012-10-30 James Greenhalgh <james.greenhalgh at arm.com>
2609 + Marcus Shawcroft <marcus.shawcroft at arm.com>
2611 + * testsuite/lib/libffi.exp: Add support for aarch64.
2612 + * testsuite/libffi.call/cls_struct_va1.c: New.
2613 + * testsuite/libffi.call/cls_uchar_va.c: Likewise.
2614 + * testsuite/libffi.call/cls_uint_va.c: Likewise.
2615 + * testsuite/libffi.call/cls_ulong_va.c: Liekwise.
2616 + * testsuite/libffi.call/cls_ushort_va.c: Likewise.
2617 + * testsuite/libffi.call/nested_struct11.c: Likewise.
2618 + * testsuite/libffi.call/uninitialized.c: Likewise.
2619 + * testsuite/libffi.call/va_1.c: Likewise.
2620 + * testsuite/libffi.call/va_struct1.c: Likewise.
2621 + * testsuite/libffi.call/va_struct2.c: Likewise.
2622 + * testsuite/libffi.call/va_struct3.c: Likewise.
2624 2012-10-12 Walter Lee <walt@tilera.com>
2626 * Makefile.am: Add TILE-Gx/TILEPro support.