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 struct large_tag
      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    l.a += s1.a;
      44    l.b += s1.b;
      45    l.c += s2.a;
      46    l.d += s2.b;
      47    return l;
      48  }
      49  
      50  int
      51  main (void)
      52  {
      53    ffi_cif cif;
      54    void* args[5];
      55    ffi_type* arg_types[5];
      56  
      57    ffi_type s_type;
      58    ffi_type *s_type_elements[3];
      59  
      60    ffi_type l_type;
      61    ffi_type *l_type_elements[6];
      62  
      63    struct small_tag s1;
      64    struct small_tag s2;
      65    struct large_tag l1;
      66  
      67    int n;
      68    struct large_tag res;
      69  
      70    s_type.size = 0;
      71    s_type.alignment = 0;
      72    s_type.type = FFI_TYPE_STRUCT;
      73    s_type.elements = s_type_elements;
      74  
      75    s_type_elements[0] = &ffi_type_uchar;
      76    s_type_elements[1] = &ffi_type_uchar;
      77    s_type_elements[2] = NULL;
      78  
      79    l_type.size = 0;
      80    l_type.alignment = 0;
      81    l_type.type = FFI_TYPE_STRUCT;
      82    l_type.elements = l_type_elements;
      83  
      84    l_type_elements[0] = &ffi_type_uint;
      85    l_type_elements[1] = &ffi_type_uint;
      86    l_type_elements[2] = &ffi_type_uint;
      87    l_type_elements[3] = &ffi_type_uint;
      88    l_type_elements[4] = &ffi_type_uint;
      89    l_type_elements[5] = NULL;
      90  
      91    arg_types[0] = &ffi_type_sint;
      92    arg_types[1] = &s_type;
      93    arg_types[2] = &l_type;
      94    arg_types[3] = &s_type;
      95    arg_types[4] = NULL;
      96  
      97    CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK);
      98  
      99    s1.a = 5;
     100    s1.b = 6;
     101  
     102    l1.a = 10;
     103    l1.b = 11;
     104    l1.c = 12;
     105    l1.d = 13;
     106    l1.e = 14;
     107  
     108    s2.a = 7;
     109    s2.b = 8;
     110  
     111    n = 41;
     112  
     113    args[0] = &n;
     114    args[1] = &s1;
     115    args[2] = &l1;
     116    args[3] = &s2;
     117    args[4] = NULL;
     118  
     119    ffi_call(&cif, FFI_FN(test_fn), &res, args);
     120    /* { dg-output "5 6 10 11 12 13 14 7 8" } */
     121    printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e);
     122    /* { dg-output "\nres: 15 17 19 21 14" } */
     123  
     124    return 0;
     125  }