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 13struct small_tag 14{ 15 unsigned char a; 16 unsigned char b; 17}; 18 19struct large_tag 20{ 21 unsigned a; 22 unsigned b; 23 unsigned c; 24 unsigned d; 25 unsigned e; 26}; 27 28static int 29test_fn (int n, ...) 30{ 31 va_list ap; 32 struct small_tag s1; 33 struct small_tag s2; 34 struct large_tag l; 35 unsigned char uc; 36 signed char sc; 37 unsigned short us; 38 signed short ss; 39 unsigned int ui; 40 signed int si; 41 unsigned long ul; 42 signed long sl; 43 float f; 44 double d; 45 46 va_start (ap, n); 47 s1 = va_arg (ap, struct small_tag); 48 l = va_arg (ap, struct large_tag); 49 s2 = va_arg (ap, struct small_tag); 50 51 uc = va_arg (ap, unsigned); 52 sc = va_arg (ap, signed); 53 54 us = va_arg (ap, unsigned); 55 ss = va_arg (ap, signed); 56 57 ui = va_arg (ap, unsigned int); 58 si = va_arg (ap, signed int); 59 60 ul = va_arg (ap, unsigned long); 61 sl = va_arg (ap, signed long); 62 63 f = va_arg (ap, double); /* C standard promotes float->double 64 when anonymous */ 65 d = va_arg (ap, double); 66 67 printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n", 68 s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, 69 s2.a, s2.b, 70 uc, sc, 71 us, ss, 72 ui, si, 73 ul, sl, 74 f, d); 75 va_end (ap); 76 return n + 1; 77} 78 79int 80main (void) 81{ 82 ffi_cif cif; 83 void* args[15]; 84 ffi_type* arg_types[15]; 85 86 ffi_type s_type; 87 ffi_type *s_type_elements[3]; 88 89 ffi_type l_type; 90 ffi_type *l_type_elements[6]; 91 92 struct small_tag s1; 93 struct small_tag s2; 94 struct large_tag l1; 95 96 int n; 97 ffi_arg res; 98 99 unsigned char uc; 100 signed char sc; 101 unsigned short us; 102 signed short ss; 103 unsigned int ui; 104 signed int si; 105 unsigned long ul; 106 signed long sl; 107 double d1; 108 double f1; 109 110 s_type.size = 0; 111 s_type.alignment = 0; 112 s_type.type = FFI_TYPE_STRUCT; 113 s_type.elements = s_type_elements; 114 115 s_type_elements[0] = &ffi_type_uchar; 116 s_type_elements[1] = &ffi_type_uchar; 117 s_type_elements[2] = NULL; 118 119 l_type.size = 0; 120 l_type.alignment = 0; 121 l_type.type = FFI_TYPE_STRUCT; 122 l_type.elements = l_type_elements; 123 124 l_type_elements[0] = &ffi_type_uint; 125 l_type_elements[1] = &ffi_type_uint; 126 l_type_elements[2] = &ffi_type_uint; 127 l_type_elements[3] = &ffi_type_uint; 128 l_type_elements[4] = &ffi_type_uint; 129 l_type_elements[5] = NULL; 130 131 arg_types[0] = &ffi_type_sint; 132 arg_types[1] = &s_type; 133 arg_types[2] = &l_type; 134 arg_types[3] = &s_type; 135 arg_types[4] = &ffi_type_uchar; 136 arg_types[5] = &ffi_type_schar; 137 arg_types[6] = &ffi_type_ushort; 138 arg_types[7] = &ffi_type_sshort; 139 arg_types[8] = &ffi_type_uint; 140 arg_types[9] = &ffi_type_sint; 141 arg_types[10] = &ffi_type_ulong; 142 arg_types[11] = &ffi_type_slong; 143 arg_types[12] = &ffi_type_double; 144 arg_types[13] = &ffi_type_double; 145 arg_types[14] = NULL; 146 147 CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK); 148 149 s1.a = 5; 150 s1.b = 6; 151 152 l1.a = 10; 153 l1.b = 11; 154 l1.c = 12; 155 l1.d = 13; 156 l1.e = 14; 157 158 s2.a = 7; 159 s2.b = 8; 160 161 n = 41; 162 163 uc = 9; 164 sc = 10; 165 us = 11; 166 ss = 12; 167 ui = 13; 168 si = 14; 169 ul = 15; 170 sl = 16; 171 f1 = 2.12; 172 d1 = 3.13; 173 174 args[0] = &n; 175 args[1] = &s1; 176 args[2] = &l1; 177 args[3] = &s2; 178 args[4] = &uc; 179 args[5] = ≻ 180 args[6] = &us; 181 args[7] = &ss; 182 args[8] = &ui; 183 args[9] = &si; 184 args[10] = &ul; 185 args[11] = &sl; 186 args[12] = &f1; 187 args[13] = &d1; 188 args[14] = NULL; 189 190 ffi_call(&cif, FFI_FN(test_fn), &res, args); 191 /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */ 192 printf("res: %d\n", (int) res); 193 /* { dg-output "\nres: 42" } */ 194 195 return 0; 196} 197