Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / gcc / testsuite / gcc.target / x86_64 / abi / test_struct_returning.c
blobef8d32904837a4639a35c11a2df7291679ceec1d
1 /* This tests returning of structures. */
3 #include <stdio.h>
4 #include "defines.h"
5 #include "macros.h"
6 #include "args.h"
8 struct IntegerRegisters iregs;
9 struct FloatRegisters fregs;
10 unsigned int num_iregs, num_fregs;
12 int current_test;
13 int num_failed = 0;
15 #undef assert
16 #define assert(test) do { if (!(test)) {fprintf (stderr, "failed in test %d\n", current_test); num_failed++; } } while (0)
18 #define xmm0f xmm_regs[0]._float
19 #define xmm0d xmm_regs[0]._double
20 #define xmm1f xmm_regs[1]._float
21 #define xmm1d xmm_regs[1]._double
23 typedef enum {
24 INT = 0,
25 SSE_F,
26 SSE_D,
27 X87,
28 MEM,
29 INT_SSE,
30 SSE_INT,
31 SSE_F_V
32 } Type;
34 /* Structures which should be returned in INTEGER. */
35 #define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT; \
36 struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
38 D(1,char m1, s.m1=42)
39 D(2,short m1, s.m1=42)
40 D(3,int m1, s.m1=42)
41 D(4,long m1, s.m1=42)
42 D(5,long long m1, s.m1=42)
43 D(6,char m1;short s, s.m1=42)
44 D(7,char m1;int i, s.m1=42)
45 D(8,char m1; long l, s.m1=42)
46 D(9,char m1; long long l, s.m1=42)
47 D(10,char m1[16], s.m1[0]=42)
48 D(11,short m1[8], s.m1[0]=42)
49 D(12,int m1[4], s.m1[0]=42)
50 D(13,long m1[2], s.m1[0]=42)
51 D(14,long long m1[2], s.m1[0]=42)
53 #undef D
55 /* Structures which should be returned in SSE. */
56 #define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
57 struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
59 D(100,float f,SSE_F, s.f=42)
60 D(101,double d,SSE_D, s.d=42)
61 D(102,float f;float f2,SSE_F, s.f=42)
62 D(103,float f;double d,SSE_F, s.f=42)
63 D(104,double d; float f,SSE_D, s.d=42)
64 D(105,double d; double d2,SSE_D, s.d=42)
65 D(106,float f[2],SSE_F, s.f[0]=42)
66 D(107,float f[3],SSE_F, s.f[0]=42)
67 D(108,float f[4],SSE_F, s.f[0]=42)
68 D(109,double d[2],SSE_D, s.d[0]=42)
69 D(110,float f[2]; double d,SSE_F, s.f[0]=42)
70 D(111,double d;float f[2],SSE_D, s.d=42)
72 #undef D
74 /* Structures which should be returned on x87 stack. */
75 #define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = X87; \
76 struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42 }; return s; }
78 /* The only struct containing a long double, which is returned in
79 registers at all, is the singleton struct. All others are too large.
80 This includes a struct containing complex long double, which is passed
81 in memory, although a complex long double type itself is returned in
82 two registers. */
83 D(200,long double ld)
85 #undef D
87 /* Structures which should be returned in INT (low) and SSE (high). */
88 #define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT_SSE; \
89 struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42,43 }; return s; }
91 D(300,char m1; float m2)
92 D(301,char m1; double m2)
93 D(302,short m1; float m2)
94 D(303,short m1; double m2)
95 D(304,int m1; float m2)
96 D(305,int m1; double m2)
97 D(306,long m1; float m2)
98 D(307,long m1; double m2)
100 #undef D
102 void check_300 (void)
104 XMM_T x;
105 x._ulong[0] = rax;
106 switch (current_test) {
107 case 300: assert ((rax & 0xff) == 42 && x._float[1] == 43); break;
108 case 301: assert ((rax & 0xff) == 42 && xmm0d[0] == 43); break;
109 case 302: assert ((rax & 0xffff) == 42 && x._float[1] == 43); break;
110 case 303: assert ((rax & 0xffff) == 42 && xmm0d[0] == 43); break;
111 case 304: assert ((rax & 0xffffffff) == 42 && x._float[1] == 43); break;
112 case 305: assert ((rax & 0xffffffff) == 42 && xmm0d[0] == 43); break;
113 case 306: assert (rax == 42 && xmm0f[0] == 43); break;
114 case 307: assert (rax == 42 && xmm0d[0] == 43); break;
115 default: assert (0); break;
119 /* Structures which should be returned in SSE (low) and INT (high). */
120 #define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = SSE_INT; \
121 struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
123 D(400,float f[2];char c, s.f[0]=42; s.c=43)
124 D(401,double d;char c, s.d=42; s.c=43)
126 #undef D
128 void check_400 (void)
130 switch (current_test) {
131 case 400: assert (xmm0f[0] == 42 && (rax & 0xff) == 43); break;
132 case 401: assert (xmm0d[0] == 42 && (rax & 0xff) == 43); break;
133 default: assert (0); break;
137 /* Structures which should be returned in MEM. */
138 void *struct_addr;
139 #define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
140 struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
142 /* Too large. */
143 D(500,char m1[17])
144 D(501,short m1[9])
145 D(502,int m1[5])
146 D(503,long m1[3])
147 D(504,short m1[8];char c)
148 D(505,char m1[1];int i[4])
149 D(506,float m1[5])
150 D(507,double m1[3])
151 D(508,char m1[1];float f[4])
152 D(509,char m1[1];double d[2])
153 D(510,__complex long double m1[1])
155 /* Too large due to padding. */
156 D(520,char m1[1];int i;char c2; int i2; char c3)
158 /* Unnaturally aligned members. */
159 D(530,short m1[1];int i PACKED)
161 #undef D
164 /* Special tests. */
165 #define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
166 struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
167 D(600,float f[4], SSE_F_V, s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
168 #undef D
170 void clear_all (void)
172 clear_int_registers;
173 clear_float_registers;
174 clear_x87_registers;
177 void check_all (Type class, unsigned long size)
179 switch (class) {
180 case INT: if (size < 8) rax &= ~0UL >> (64-8*size); assert (rax == 42); break;
181 case SSE_F: assert (xmm0f[0] == 42); break;
182 case SSE_D: assert (xmm0d[0] == 42); break;
183 case SSE_F_V: assert (xmm0f[0] == 42 && xmm0f[1]==42 && xmm1f[0] == 42 && xmm1f[1] == 42); break;
184 case X87: assert (x87_regs[0]._ldouble == 42); break;
185 case INT_SSE: check_300(); break;
186 case SSE_INT: check_400(); break;
187 /* Ideally we would like to check that rax == struct_addr.
188 Unfortunately the address of the target struct escapes (for setting
189 struct_addr), so the return struct is a temporary one whose address
190 is given to the f_* functions, otherwise a conforming program
191 could notice the struct changing already before the function returns.
192 This temporary struct could be anywhere. For GCC it will be on
193 stack, but noone is forbidding that it could be a static variable
194 if there's no threading or proper locking. Nobody in his right mind
195 will not use the stack for that. */
196 case MEM: assert (*(unsigned char*)struct_addr == 42 && rdi == rax); break;
200 #define D(I) { struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
201 clear_all(); \
202 s = WRAP_RET(f_ ## I) (); \
203 check_all(class_ ## I, sizeof(s)); \
207 main (void)
209 D(1) D(2) D(3) D(4) D(5) D(6) D(7) D(8) D(9) D(10) D(11) D(12) D(13) D(14)
211 D(100) D(101) D(102) D(103) D(104) D(105) D(106) D(107) D(108) D(109) D(110)
212 D(111)
214 D(200)
216 D(300) D(301) D(302) D(303) D(304) D(305) D(306) D(307)
218 D(400) D(401)
220 D(500) D(501) D(502) D(503) D(504) D(505) D(506) D(507) D(508) D(509)
221 D(520)
222 D(530)
224 D(600)
225 if (num_failed)
226 abort ();
228 return 0;
230 #undef D