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