github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/testsuite/libffi.call/va_struct3.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 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  }