116-struct-ret-vararg.c (1463B)
1 /* Struct return from a variadic function. 2 * 3 * Combines two ABI-shaped concerns: the variadic save area (cg.scm 4 * around L1027 has a TODO for variadic args >= 4) and the struct 5 * return slot (a single 8-byte slot). 6 * 7 * If the hidden return pointer is wired through arg0, the variadic 8 * save area's indexing must skip it; if it isn't wired, a 2-word 9 * struct return will silently truncate. Either way this surfaces 10 * the interaction. */ 11 12 #ifndef CCSCM 13 #include <stdarg.h> 14 #else 15 typedef char *va_list; 16 #define va_start(ap, n) __builtin_va_start(ap, n) 17 #define va_arg(ap, t) __builtin_va_arg(ap, t) 18 #define va_end(ap) __builtin_va_end(ap) 19 #endif 20 21 struct Pair { long a; long b; }; 22 23 struct Pair sum_pair(int n, ...) { 24 va_list ap; 25 long total_a = 0; 26 long total_b = 0; 27 int i = 0; 28 va_start(ap, n); 29 while (i < n) { 30 total_a = total_a + va_arg(ap, int); 31 total_b = total_b + va_arg(ap, int) * 10; 32 i = i + 1; 33 } 34 va_end(ap); 35 struct Pair r; 36 r.a = total_a; 37 r.b = total_b; 38 return r; 39 } 40 41 int main(int argc, char **argv) { 42 /* Two pairs of (int,int): (1,2) (3,4) -> a = 1+3 = 4, b = (2+4)*10 = 60 */ 43 struct Pair r = sum_pair(2, 1, 2, 3, 4); 44 if (r.a != 4) return 1; 45 if (r.b != 60) return 2; 46 47 /* Three pairs: (10,1) (20,2) (30,3) -> a = 60, b = 60 */ 48 struct Pair s = sum_pair(3, 10, 1, 20, 2, 30, 3); 49 if (s.a != 60) return 3; 50 if (s.b != 60) return 4; 51 return 0; 52 }