github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct1.c (about)

     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  }