/* Area: ffi_call Purpose: Test passing struct in variable argument lists. Limitations: none. PR: none. Originator: ARM Ltd. */ /* { dg-do run } */ /* { dg-output "" { xfail avr32*-*-* } } */ #include "ffitest.h" #include struct small_tag { unsigned char a; unsigned char b; }; struct large_tag { unsigned a; unsigned b; unsigned c; unsigned d; unsigned e; }; static int test_fn (int n, ...) { va_list ap; struct small_tag s1; struct small_tag s2; struct large_tag l; va_start (ap, n); s1 = va_arg (ap, struct small_tag); l = va_arg (ap, struct large_tag); s2 = va_arg (ap, struct small_tag); 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, s2.a, s2.b); va_end (ap); return n + 1; } int main (void) { ffi_cif cif; void* args[5]; ffi_type* arg_types[5]; ffi_type s_type; ffi_type *s_type_elements[3]; ffi_type l_type; ffi_type *l_type_elements[6]; struct small_tag s1; struct small_tag s2; struct large_tag l1; int n; ffi_arg res; s_type.size = 0; s_type.alignment = 0; s_type.type = FFI_TYPE_STRUCT; s_type.elements = s_type_elements; s_type_elements[0] = &ffi_type_uchar; s_type_elements[1] = &ffi_type_uchar; s_type_elements[2] = NULL; l_type.size = 0; l_type.alignment = 0; l_type.type = FFI_TYPE_STRUCT; l_type.elements = l_type_elements; l_type_elements[0] = &ffi_type_uint; l_type_elements[1] = &ffi_type_uint; l_type_elements[2] = &ffi_type_uint; l_type_elements[3] = &ffi_type_uint; l_type_elements[4] = &ffi_type_uint; l_type_elements[5] = NULL; arg_types[0] = &ffi_type_sint; arg_types[1] = &s_type; arg_types[2] = &l_type; arg_types[3] = &s_type; arg_types[4] = NULL; CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK); s1.a = 5; s1.b = 6; l1.a = 10; l1.b = 11; l1.c = 12; l1.d = 13; l1.e = 14; s2.a = 7; s2.b = 8; n = 41; args[0] = &n; args[1] = &s1; args[2] = &l1; args[3] = &s2; args[4] = NULL; ffi_call(&cif, FFI_FN(test_fn), &res, args); /* { dg-output "5 6 10 11 12 13 14 7 8" } */ printf("res: %d\n", (int) res); /* { dg-output "\nres: 42" } */ return 0; }