1  /* Area:		ffi_call
       2     Purpose:		Test passing struct in variable argument lists.
       3     Limitations:	none.
       4     PR:			none.
       5     Originator: ARM Ltd. */
       6  
       7  /* { dg-do run } */
       8  /* { dg-output "" { xfail avr32*-*-* } } */
       9  
      10  #include "ffitest.h"
      11  #include <stdarg.h>
      12  
      13  struct small_tag
      14  {
      15    unsigned char a;
      16    unsigned char b;
      17  };
      18  
      19  struct large_tag
      20  {
      21    unsigned a;
      22    unsigned b;
      23    unsigned c;
      24    unsigned d;
      25    unsigned e;
      26  };
      27  
      28  static int
      29  test_fn (int n, ...)
      30  {
      31    va_list ap;
      32    struct small_tag s1;
      33    struct small_tag s2;
      34    struct large_tag l;
      35  
      36    va_start (ap, n);
      37    s1 = va_arg (ap, struct small_tag);
      38    l = va_arg (ap, struct large_tag);
      39    s2 = va_arg (ap, struct small_tag);
      40    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,
      41  	  s2.a, s2.b);
      42    va_end (ap);
      43    return n + 1;
      44  }
      45  
      46  int
      47  main (void)
      48  {
      49    ffi_cif cif;
      50    void* args[5];
      51    ffi_type* arg_types[5];
      52  
      53    ffi_type s_type;
      54    ffi_type *s_type_elements[3];
      55  
      56    ffi_type l_type;
      57    ffi_type *l_type_elements[6];
      58  
      59    struct small_tag s1;
      60    struct small_tag s2;
      61    struct large_tag l1;
      62  
      63    int n;
      64    ffi_arg res;
      65  
      66    s_type.size = 0;
      67    s_type.alignment = 0;
      68    s_type.type = FFI_TYPE_STRUCT;
      69    s_type.elements = s_type_elements;
      70  
      71    s_type_elements[0] = &ffi_type_uchar;
      72    s_type_elements[1] = &ffi_type_uchar;
      73    s_type_elements[2] = NULL;
      74  
      75    l_type.size = 0;
      76    l_type.alignment = 0;
      77    l_type.type = FFI_TYPE_STRUCT;
      78    l_type.elements = l_type_elements;
      79  
      80    l_type_elements[0] = &ffi_type_uint;
      81    l_type_elements[1] = &ffi_type_uint;
      82    l_type_elements[2] = &ffi_type_uint;
      83    l_type_elements[3] = &ffi_type_uint;
      84    l_type_elements[4] = &ffi_type_uint;
      85    l_type_elements[5] = NULL;
      86  
      87    arg_types[0] = &ffi_type_sint;
      88    arg_types[1] = &s_type;
      89    arg_types[2] = &l_type;
      90    arg_types[3] = &s_type;
      91    arg_types[4] = NULL;
      92  
      93    CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK);
      94  
      95    s1.a = 5;
      96    s1.b = 6;
      97  
      98    l1.a = 10;
      99    l1.b = 11;
     100    l1.c = 12;
     101    l1.d = 13;
     102    l1.e = 14;
     103  
     104    s2.a = 7;
     105    s2.b = 8;
     106  
     107    n = 41;
     108  
     109    args[0] = &n;
     110    args[1] = &s1;
     111    args[2] = &l1;
     112    args[3] = &s2;
     113    args[4] = NULL;
     114  
     115    ffi_call(&cif, FFI_FN(test_fn), &res, args);
     116    /* { dg-output "5 6 10 11 12 13 14 7 8" } */
     117    printf("res: %d\n", (int) res);
     118    /* { dg-output "\nres: 42" } */
     119  
     120    return 0;
     121  }