]>
Commit | Line | Data |
---|---|---|
cd5f04f5 | 1 | // TEST_CONFIG MEM=mrc,gc |
8972963c A |
2 | // TEST_CFLAGS -Wno-deprecated-declarations |
3 | ||
7af964d1 | 4 | #include "test.h" |
8972963c | 5 | |
cd5f04f5 | 6 | #if __cplusplus && !__clang__ |
8972963c A |
7 | |
8 | int main() | |
9 | { | |
cd5f04f5 | 10 | // llvm-g++ is confused by @selector(foo::) and will never be fixed |
8972963c A |
11 | succeed(__FILE__); |
12 | } | |
13 | ||
14 | #else | |
15 | ||
7af964d1 A |
16 | #include <objc/runtime.h> |
17 | #include <objc/message.h> | |
18 | ||
7af964d1 A |
19 | id ID_RESULT = (id)0x12345678; |
20 | long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__; | |
7af964d1 A |
21 | double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__; |
22 | long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__; | |
cd5f04f5 | 23 | // STRET_RESULT in test.h |
7af964d1 A |
24 | |
25 | ||
26 | static int state = 0; | |
27 | static id receiver; | |
28 | ||
7257e56c | 29 | OBJC_ROOT_CLASS |
7af964d1 A |
30 | @interface Super { id isa; } @end |
31 | ||
32 | @interface Super (Forwarded) | |
33 | +(id)idret: | |
7257e56c | 34 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
35 | |
36 | +(id)idre2: | |
7257e56c | 37 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
38 | |
39 | +(id)idre3: | |
7257e56c | 40 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
41 | |
42 | +(long long)llret: | |
7257e56c | 43 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
44 | |
45 | +(long long)llre2: | |
7257e56c | 46 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
47 | |
48 | +(long long)llre3: | |
7257e56c | 49 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
50 | |
51 | +(struct stret)stret: | |
7257e56c | 52 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
53 | |
54 | +(struct stret)stre2: | |
7257e56c | 55 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
56 | |
57 | +(struct stret)stre3: | |
7257e56c | 58 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
59 | |
60 | +(double)fpret: | |
7257e56c | 61 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
62 | |
63 | +(double)fpre2: | |
7257e56c | 64 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
65 | |
66 | +(double)fpre3: | |
7257e56c | 67 | (long)i1 :(long)i2 :(long)i3 :(long)i4 :(long)i5 :(long)i6 :(long)i7 :(long)i8 :(long)i9 :(long)i10 :(long)i11 :(long)i12 :(long)i13 :(double)f1 :(double)f2 :(double)f3 :(double)f4 :(double)f5 :(double)f6 :(double)f7 :(double)f8 :(double)f9 :(double)f10 :(double)f11 :(double)f12 :(double)f13 :(double)f14 :(double)f15; |
7af964d1 A |
68 | |
69 | @end | |
70 | ||
71 | ||
72 | long long forward_handler(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15) | |
73 | { | |
8070259c A |
74 | #if __arm64__ |
75 | void *struct_addr; | |
76 | __asm__ volatile("mov %0, x8" : "=r" (struct_addr) : : "x8"); | |
77 | #endif | |
78 | ||
7af964d1 A |
79 | testassert(self == receiver); |
80 | ||
81 | testassert(i1 == 1); | |
82 | testassert(i2 == 2); | |
83 | testassert(i3 == 3); | |
84 | testassert(i4 == 4); | |
85 | testassert(i5 == 5); | |
86 | testassert(i6 == 6); | |
87 | testassert(i7 == 7); | |
88 | testassert(i8 == 8); | |
89 | testassert(i9 == 9); | |
90 | testassert(i10 == 10); | |
91 | testassert(i11 == 11); | |
92 | testassert(i12 == 12); | |
93 | testassert(i13 == 13); | |
94 | ||
95 | testassert(f1 == 1.0); | |
96 | testassert(f2 == 2.0); | |
97 | testassert(f3 == 3.0); | |
98 | testassert(f4 == 4.0); | |
99 | testassert(f5 == 5.0); | |
100 | testassert(f6 == 6.0); | |
101 | testassert(f7 == 7.0); | |
102 | testassert(f8 == 8.0); | |
103 | testassert(f9 == 9.0); | |
104 | testassert(f10 == 10.0); | |
105 | testassert(f11 == 11.0); | |
106 | testassert(f12 == 12.0); | |
107 | testassert(f13 == 13.0); | |
108 | testassert(f14 == 14.0); | |
109 | testassert(f15 == 15.0); | |
110 | ||
111 | if (_cmd == @selector(idret::::::::::::::::::::::::::::) || | |
112 | _cmd == @selector(idre2::::::::::::::::::::::::::::) || | |
113 | _cmd == @selector(idre3::::::::::::::::::::::::::::)) | |
114 | { | |
115 | union { | |
116 | id idval; | |
117 | long long llval; | |
118 | } result; | |
119 | testassert(state == 11); | |
120 | state = 12; | |
121 | result.idval = ID_RESULT; | |
122 | return result.llval; | |
7257e56c A |
123 | } |
124 | else if (_cmd == @selector(llret::::::::::::::::::::::::::::) || | |
125 | _cmd == @selector(llre2::::::::::::::::::::::::::::) || | |
126 | _cmd == @selector(llre3::::::::::::::::::::::::::::)) | |
7af964d1 A |
127 | { |
128 | testassert(state == 13); | |
129 | state = 14; | |
130 | return LL_RESULT; | |
7257e56c A |
131 | } |
132 | else if (_cmd == @selector(fpret::::::::::::::::::::::::::::) || | |
133 | _cmd == @selector(fpre2::::::::::::::::::::::::::::) || | |
134 | _cmd == @selector(fpre3::::::::::::::::::::::::::::)) | |
7af964d1 A |
135 | { |
136 | testassert(state == 15); | |
137 | state = 16; | |
8972963c | 138 | #if defined(__i386__) |
7af964d1 A |
139 | __asm__ volatile("fldl %0" : : "m" (FP_RESULT)); |
140 | #elif defined(__x86_64__) | |
141 | __asm__ volatile("movsd %0, %%xmm0" : : "m" (FP_RESULT)); | |
142 | #elif defined(__arm__) | |
143 | union { | |
144 | double fpval; | |
145 | long long llval; | |
146 | } result; | |
147 | result.fpval = FP_RESULT; | |
148 | return result.llval; | |
8070259c A |
149 | #elif defined(__arm64__) |
150 | __asm__ volatile("ldr d0, %0" : : "m" (FP_RESULT)); | |
7af964d1 A |
151 | #else |
152 | # error unknown architecture | |
153 | #endif | |
154 | return 0; | |
7257e56c A |
155 | } |
156 | else if (_cmd == @selector(stret::::::::::::::::::::::::::::) || | |
157 | _cmd == @selector(stre2::::::::::::::::::::::::::::) || | |
158 | _cmd == @selector(stre3::::::::::::::::::::::::::::)) | |
7af964d1 | 159 | { |
8070259c | 160 | #if __i386__ || __x86_64__ || __arm__ |
7af964d1 | 161 | fail("stret message sent to non-stret forward_handler"); |
8070259c A |
162 | #elif __arm64__ |
163 | testassert(state == 17); | |
164 | state = 18; | |
165 | memcpy(struct_addr, &STRET_RESULT, sizeof(STRET_RESULT)); | |
166 | return 0; | |
167 | #else | |
168 | # error unknown architecture | |
169 | #endif | |
7257e56c A |
170 | } |
171 | else { | |
7af964d1 A |
172 | fail("unknown selector %s in forward_handler", sel_getName(_cmd)); |
173 | } | |
174 | } | |
175 | ||
176 | ||
177 | struct stret forward_stret_handler(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15) | |
178 | { | |
179 | testassert(self == receiver); | |
180 | ||
181 | testassert(i1 == 1); | |
182 | testassert(i2 == 2); | |
183 | testassert(i3 == 3); | |
184 | testassert(i4 == 4); | |
185 | testassert(i5 == 5); | |
186 | testassert(i6 == 6); | |
187 | testassert(i7 == 7); | |
188 | testassert(i8 == 8); | |
189 | testassert(i9 == 9); | |
190 | testassert(i10 == 10); | |
191 | testassert(i11 == 11); | |
192 | testassert(i12 == 12); | |
193 | testassert(i13 == 13); | |
194 | ||
195 | testassert(f1 == 1.0); | |
196 | testassert(f2 == 2.0); | |
197 | testassert(f3 == 3.0); | |
198 | testassert(f4 == 4.0); | |
199 | testassert(f5 == 5.0); | |
200 | testassert(f6 == 6.0); | |
201 | testassert(f7 == 7.0); | |
202 | testassert(f8 == 8.0); | |
203 | testassert(f9 == 9.0); | |
204 | testassert(f10 == 10.0); | |
205 | testassert(f11 == 11.0); | |
206 | testassert(f12 == 12.0); | |
207 | testassert(f13 == 13.0); | |
208 | testassert(f14 == 14.0); | |
209 | testassert(f15 == 15.0); | |
210 | ||
211 | if (_cmd == @selector(idret::::::::::::::::::::::::::::) || | |
212 | _cmd == @selector(idre2::::::::::::::::::::::::::::) || | |
213 | _cmd == @selector(idre3::::::::::::::::::::::::::::) || | |
214 | _cmd == @selector(llret::::::::::::::::::::::::::::) || | |
215 | _cmd == @selector(llre2::::::::::::::::::::::::::::) || | |
216 | _cmd == @selector(llre3::::::::::::::::::::::::::::) || | |
217 | _cmd == @selector(fpret::::::::::::::::::::::::::::) || | |
218 | _cmd == @selector(fpre2::::::::::::::::::::::::::::) || | |
219 | _cmd == @selector(fpre3::::::::::::::::::::::::::::)) | |
220 | { | |
221 | fail("non-stret selector %s sent to forward_stret_handler", sel_getName(_cmd)); | |
7257e56c A |
222 | } |
223 | else if (_cmd == @selector(stret::::::::::::::::::::::::::::) || | |
224 | _cmd == @selector(stre2::::::::::::::::::::::::::::) || | |
225 | _cmd == @selector(stre3::::::::::::::::::::::::::::)) | |
7af964d1 A |
226 | { |
227 | testassert(state == 17); | |
228 | state = 18; | |
229 | return STRET_RESULT; | |
7257e56c A |
230 | } |
231 | else { | |
232 | fail("unknown selector %s in forward_stret_handler", sel_getName(_cmd)); | |
7af964d1 A |
233 | } |
234 | ||
235 | } | |
236 | ||
7257e56c | 237 | |
7af964d1 A |
238 | @implementation Super |
239 | +(void)initialize { } | |
cd5f04f5 | 240 | +(id)class { return self; } |
7af964d1 | 241 | |
8070259c A |
242 | #if __OBJC2__ |
243 | // forward:: not supported | |
244 | #else | |
7af964d1 A |
245 | -(long long) forward:(SEL)sel :(marg_list)args |
246 | { | |
247 | char *p; | |
248 | uintptr_t *gp; | |
249 | double *fp; | |
250 | struct stret *struct_addr; | |
251 | ||
252 | #if defined(__i386__) | |
253 | struct_addr = ((struct stret **)args)[-1]; | |
7af964d1 A |
254 | #elif defined(__x86_64__) |
255 | struct_addr = *(struct stret **)((char *)args + 8*16+4*8); | |
256 | #elif defined(__arm__) | |
257 | struct_addr = *(struct stret **)((char *)args + 0); | |
258 | #else | |
259 | # error unknown architecture | |
260 | #endif | |
261 | ||
262 | testassert(self == receiver); | |
263 | testassert(_cmd == sel_registerName("forward::")); | |
264 | ||
cd5f04f5 | 265 | p = (char *)args; |
8972963c | 266 | #if defined(__x86_64__) |
7af964d1 A |
267 | p += 8*16 + 4*8; // skip over xmm and linkage |
268 | if (sel == @selector(stret::::::::::::::::::::::::::::) || | |
269 | sel == @selector(stre2::::::::::::::::::::::::::::) || | |
270 | sel == @selector(stre3::::::::::::::::::::::::::::)) | |
271 | { | |
272 | p += sizeof(void *); // struct return | |
273 | } | |
274 | #elif defined(__i386__) | |
275 | // nothing to do | |
276 | #elif defined(__arm__) | |
277 | if (sel == @selector(stret::::::::::::::::::::::::::::) || | |
278 | sel == @selector(stre2::::::::::::::::::::::::::::) || | |
279 | sel == @selector(stre3::::::::::::::::::::::::::::)) | |
280 | { | |
281 | p += sizeof(void *); // struct return; | |
282 | } | |
283 | #else | |
284 | # error unknown architecture | |
285 | #endif | |
286 | gp = (uintptr_t *)p; | |
287 | testassert(*gp++ == (uintptr_t)self); | |
7257e56c | 288 | testassert(*gp++ == (uintptr_t)(void *)sel); |
7af964d1 A |
289 | testassert(*gp++ == 1); |
290 | testassert(*gp++ == 2); | |
291 | testassert(*gp++ == 3); | |
292 | testassert(*gp++ == 4); | |
293 | testassert(*gp++ == 5); | |
294 | testassert(*gp++ == 6); | |
295 | testassert(*gp++ == 7); | |
296 | testassert(*gp++ == 8); | |
297 | testassert(*gp++ == 9); | |
298 | testassert(*gp++ == 10); | |
299 | testassert(*gp++ == 11); | |
300 | testassert(*gp++ == 12); | |
301 | testassert(*gp++ == 13); | |
302 | ||
8972963c | 303 | #if defined(__i386__) || defined(__arm__) |
7af964d1 | 304 | |
7af964d1 | 305 | fp = (double *)gp; |
7af964d1 A |
306 | testassert(*fp++ == 1.0); |
307 | testassert(*fp++ == 2.0); | |
308 | testassert(*fp++ == 3.0); | |
309 | testassert(*fp++ == 4.0); | |
310 | testassert(*fp++ == 5.0); | |
311 | testassert(*fp++ == 6.0); | |
312 | testassert(*fp++ == 7.0); | |
313 | testassert(*fp++ == 8.0); | |
314 | testassert(*fp++ == 9.0); | |
315 | testassert(*fp++ == 10.0); | |
316 | testassert(*fp++ == 11.0); | |
317 | testassert(*fp++ == 12.0); | |
318 | testassert(*fp++ == 13.0); | |
7af964d1 A |
319 | testassert(*fp++ == 14.0); |
320 | testassert(*fp++ == 15.0); | |
321 | ||
322 | #elif defined(__x86_64__) | |
323 | ||
cd5f04f5 | 324 | fp = (double *)args; // xmm, double-wide |
7af964d1 A |
325 | testassert(*fp++ == 1.0); fp++; |
326 | testassert(*fp++ == 2.0); fp++; | |
327 | testassert(*fp++ == 3.0); fp++; | |
328 | testassert(*fp++ == 4.0); fp++; | |
329 | testassert(*fp++ == 5.0); fp++; | |
330 | testassert(*fp++ == 6.0); fp++; | |
331 | testassert(*fp++ == 7.0); fp++; | |
332 | testassert(*fp++ == 8.0); fp++; | |
333 | fp = (double *)gp; | |
334 | testassert(*fp++ == 9.0); | |
335 | testassert(*fp++ == 10.0); | |
336 | testassert(*fp++ == 11.0); | |
337 | testassert(*fp++ == 12.0); | |
338 | testassert(*fp++ == 13.0); | |
339 | testassert(*fp++ == 14.0); | |
340 | testassert(*fp++ == 15.0); | |
341 | ||
342 | #else | |
343 | # error unknown architecture | |
344 | #endif | |
345 | ||
346 | if (sel == @selector(idret::::::::::::::::::::::::::::) || | |
347 | sel == @selector(idre2::::::::::::::::::::::::::::) || | |
348 | sel == @selector(idre3::::::::::::::::::::::::::::)) | |
349 | { | |
350 | union { | |
351 | id idval; | |
352 | long long llval; | |
353 | } result; | |
354 | testassert(state == 1); | |
355 | state = 2; | |
356 | result.idval = ID_RESULT; | |
357 | return result.llval; | |
358 | } else if (sel == @selector(llret::::::::::::::::::::::::::::) || | |
359 | sel == @selector(llre2::::::::::::::::::::::::::::) || | |
360 | sel == @selector(llre3::::::::::::::::::::::::::::)) | |
361 | { | |
362 | testassert(state == 3); | |
363 | state = 4; | |
364 | return LL_RESULT; | |
365 | } else if (sel == @selector(fpret::::::::::::::::::::::::::::) || | |
366 | sel == @selector(fpre2::::::::::::::::::::::::::::) || | |
367 | sel == @selector(fpre3::::::::::::::::::::::::::::)) | |
368 | { | |
369 | testassert(state == 5); | |
370 | state = 6; | |
8972963c | 371 | #if defined(__i386__) |
7af964d1 A |
372 | __asm__ volatile("fldl %0" : : "m" (FP_RESULT)); |
373 | #elif defined(__x86_64__) | |
374 | __asm__ volatile("movsd %0, %%xmm0" : : "m" (FP_RESULT)); | |
375 | #elif defined(__arm__) | |
376 | union { | |
377 | double fpval; | |
378 | long long llval; | |
379 | } result; | |
380 | result.fpval = FP_RESULT; | |
381 | return result.llval; | |
382 | #else | |
383 | # error unknown architecture | |
384 | #endif | |
385 | return 0; | |
386 | } else if (sel == @selector(stret::::::::::::::::::::::::::::) || | |
387 | sel == @selector(stre2::::::::::::::::::::::::::::) || | |
388 | sel == @selector(stre3::::::::::::::::::::::::::::)) | |
389 | { | |
390 | testassert(state == 7); | |
391 | state = 8; | |
392 | *struct_addr = STRET_RESULT; | |
393 | return 0; | |
394 | } else { | |
395 | fail("unknown selector %s in forward::", sel_getName(sel)); | |
396 | } | |
397 | return 0; | |
398 | } | |
399 | ||
8070259c A |
400 | #endif |
401 | ||
7af964d1 A |
402 | @end |
403 | ||
404 | typedef id (*id_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15); | |
405 | ||
406 | typedef long long (*ll_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15); | |
407 | ||
408 | typedef double (*fp_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15); | |
409 | ||
410 | typedef struct stret (*st_fn_t)(id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15); | |
411 | ||
7257e56c A |
412 | #if __x86_64__ |
413 | typedef struct stret * (*fake_st_fn_t)(struct stret *, id self, SEL _cmd, long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10, long i11, long i12, long i13, double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15); | |
414 | #endif | |
415 | ||
cd5f04f5 | 416 | __BEGIN_DECLS |
8972963c | 417 | extern void *getSP(void); |
cd5f04f5 | 418 | __END_DECLS |
8972963c A |
419 | |
420 | #if defined(__x86_64__) | |
421 | asm(".text \n _getSP: movq %rsp, %rax \n retq \n"); | |
422 | #elif defined(__i386__) | |
423 | asm(".text \n _getSP: movl %esp, %eax \n ret \n"); | |
424 | #elif defined(__arm__) | |
425 | asm(".text \n _getSP: mov r0, sp \n bx lr \n"); | |
8070259c A |
426 | #elif defined(__arm64__) |
427 | asm(".text \n _getSP: mov x0, sp \n ret \n"); | |
8972963c A |
428 | #else |
429 | # error unknown architecture | |
430 | #endif | |
431 | ||
7af964d1 A |
432 | int main() |
433 | { | |
434 | id idval; | |
435 | long long llval; | |
436 | struct stret stval; | |
7257e56c A |
437 | #if __x86_64__ |
438 | struct stret *stptr; | |
439 | #endif | |
7af964d1 | 440 | double fpval; |
8972963c A |
441 | void *sp1 = (void*)1; |
442 | void *sp2 = (void*)2; | |
7af964d1 | 443 | |
8070259c A |
444 | st_fn_t stret_fwd; |
445 | #if __arm64__ | |
446 | stret_fwd = (st_fn_t)_objc_msgForward; | |
447 | #else | |
448 | stret_fwd = (st_fn_t)_objc_msgForward_stret; | |
449 | #endif | |
450 | ||
7af964d1 A |
451 | receiver = [Super class]; |
452 | ||
8070259c A |
453 | #if __OBJC2__ |
454 | // forward:: not supported | |
455 | #else | |
7af964d1 A |
456 | // Test default forward handler |
457 | ||
458 | state = 1; | |
8972963c | 459 | sp1 = getSP(); |
7af964d1 | 460 | idval = [Super idret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
461 | sp2 = getSP(); |
462 | testassert(sp1 == sp2); | |
7af964d1 A |
463 | testassert(state == 2); |
464 | testassert(idval == ID_RESULT); | |
465 | ||
466 | state = 3; | |
8972963c | 467 | sp1 = getSP(); |
7af964d1 | 468 | llval = [Super llret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
469 | sp2 = getSP(); |
470 | testassert(sp1 == sp2); | |
7af964d1 A |
471 | testassert(state == 4); |
472 | testassert(llval == LL_RESULT); | |
473 | ||
474 | state = 5; | |
8972963c | 475 | sp1 = getSP(); |
7af964d1 | 476 | fpval = [Super fpret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
477 | sp2 = getSP(); |
478 | testassert(sp1 == sp2); | |
7af964d1 A |
479 | testassert(state == 6); |
480 | testassert(fpval == FP_RESULT); | |
481 | ||
482 | state = 7; | |
8972963c | 483 | sp1 = getSP(); |
7af964d1 | 484 | stval = [Super stret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
485 | sp2 = getSP(); |
486 | testassert(sp1 == sp2); | |
7af964d1 A |
487 | testassert(state == 8); |
488 | testassert(stret_equal(stval, STRET_RESULT)); | |
489 | ||
7257e56c A |
490 | #if __x86_64__ |
491 | // check stret return register | |
492 | state = 7; | |
493 | sp1 = getSP(); | |
494 | stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stret::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
495 | sp2 = getSP(); | |
496 | testassert(sp1 == sp2); | |
497 | testassert(state == 8); | |
498 | testassert(stret_equal(stval, STRET_RESULT)); | |
499 | testassert(stptr == &stval); | |
500 | #endif | |
501 | ||
7af964d1 A |
502 | |
503 | // Test default forward handler, cached | |
504 | ||
505 | state = 1; | |
8972963c | 506 | sp1 = getSP(); |
7af964d1 | 507 | idval = [Super idret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
508 | sp2 = getSP(); |
509 | testassert(sp1 == sp2); | |
7af964d1 A |
510 | testassert(state == 2); |
511 | testassert(idval == ID_RESULT); | |
512 | ||
513 | state = 3; | |
8972963c | 514 | sp1 = getSP(); |
7af964d1 | 515 | llval = [Super llret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
516 | sp2 = getSP(); |
517 | testassert(sp1 == sp2); | |
7af964d1 A |
518 | testassert(state == 4); |
519 | testassert(llval == LL_RESULT); | |
520 | ||
521 | state = 5; | |
8972963c | 522 | sp1 = getSP(); |
7af964d1 | 523 | fpval = [Super fpret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
524 | sp2 = getSP(); |
525 | testassert(sp1 == sp2); | |
7af964d1 A |
526 | testassert(state == 6); |
527 | testassert(fpval == FP_RESULT); | |
528 | ||
529 | state = 7; | |
8972963c | 530 | sp1 = getSP(); |
7af964d1 | 531 | stval = [Super stret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
532 | sp2 = getSP(); |
533 | testassert(sp1 == sp2); | |
7af964d1 A |
534 | testassert(state == 8); |
535 | testassert(stret_equal(stval, STRET_RESULT)); | |
536 | ||
7257e56c A |
537 | #if __x86_64__ |
538 | // check stret return register | |
539 | state = 7; | |
540 | sp1 = getSP(); | |
541 | stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stret::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
542 | sp2 = getSP(); | |
543 | testassert(sp1 == sp2); | |
544 | testassert(state == 8); | |
545 | testassert(stret_equal(stval, STRET_RESULT)); | |
546 | testassert(stptr == &stval); | |
547 | #endif | |
548 | ||
7af964d1 A |
549 | |
550 | // Test default forward handler, uncached but fixed-up | |
551 | ||
8972963c | 552 | _objc_flush_caches(nil); |
7af964d1 A |
553 | |
554 | state = 1; | |
8972963c | 555 | sp1 = getSP(); |
7af964d1 | 556 | idval = [Super idret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
557 | sp2 = getSP(); |
558 | testassert(sp1 == sp2); | |
7af964d1 A |
559 | testassert(state == 2); |
560 | testassert(idval == ID_RESULT); | |
561 | ||
562 | state = 3; | |
8972963c | 563 | sp1 = getSP(); |
7af964d1 | 564 | llval = [Super llret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
565 | sp2 = getSP(); |
566 | testassert(sp1 == sp2); | |
7af964d1 A |
567 | testassert(state == 4); |
568 | testassert(llval == LL_RESULT); | |
569 | ||
570 | state = 5; | |
8972963c | 571 | sp1 = getSP(); |
7af964d1 | 572 | fpval = [Super fpret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
573 | sp2 = getSP(); |
574 | testassert(sp1 == sp2); | |
7af964d1 A |
575 | testassert(state == 6); |
576 | testassert(fpval == FP_RESULT); | |
577 | ||
578 | state = 7; | |
8972963c | 579 | sp1 = getSP(); |
7af964d1 | 580 | stval = [Super stret:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
581 | sp2 = getSP(); |
582 | testassert(sp1 == sp2); | |
7af964d1 A |
583 | testassert(state == 8); |
584 | testassert(stret_equal(stval, STRET_RESULT)); | |
585 | ||
7257e56c A |
586 | #if __x86_64__ |
587 | // check stret return register | |
588 | state = 7; | |
589 | sp1 = getSP(); | |
590 | stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stret::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
591 | sp2 = getSP(); | |
592 | testassert(sp1 == sp2); | |
593 | testassert(state == 8); | |
594 | testassert(stret_equal(stval, STRET_RESULT)); | |
595 | testassert(stptr == &stval); | |
596 | #endif | |
597 | ||
7af964d1 A |
598 | |
599 | // Test manual forwarding | |
600 | ||
601 | state = 1; | |
8972963c | 602 | sp1 = getSP(); |
7af964d1 | 603 | idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
604 | sp2 = getSP(); |
605 | testassert(sp1 == sp2); | |
7af964d1 A |
606 | testassert(state == 2); |
607 | testassert(idval == ID_RESULT); | |
608 | ||
609 | state = 3; | |
8972963c | 610 | sp1 = getSP(); |
7af964d1 | 611 | llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
612 | sp2 = getSP(); |
613 | testassert(sp1 == sp2); | |
7af964d1 A |
614 | testassert(state == 4); |
615 | testassert(llval == LL_RESULT); | |
616 | ||
617 | state = 5; | |
8972963c | 618 | sp1 = getSP(); |
7af964d1 | 619 | fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
620 | sp2 = getSP(); |
621 | testassert(sp1 == sp2); | |
7af964d1 A |
622 | testassert(state == 6); |
623 | testassert(fpval == FP_RESULT); | |
624 | ||
625 | state = 7; | |
8972963c | 626 | sp1 = getSP(); |
8070259c | 627 | stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
628 | sp2 = getSP(); |
629 | testassert(sp1 == sp2); | |
7af964d1 A |
630 | testassert(state == 8); |
631 | testassert(stret_equal(stval, STRET_RESULT)); | |
632 | ||
7257e56c A |
633 | #if __x86_64__ |
634 | // check stret return register | |
635 | state = 7; | |
636 | sp1 = getSP(); | |
637 | stptr = ((fake_st_fn_t)_objc_msgForward_stret)(&stval, receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
638 | sp2 = getSP(); | |
639 | testassert(sp1 == sp2); | |
640 | testassert(state == 8); | |
641 | testassert(stret_equal(stval, STRET_RESULT)); | |
642 | testassert(stptr == &stval); | |
643 | #endif | |
644 | ||
7af964d1 A |
645 | |
646 | // Test manual forwarding, cached | |
647 | ||
648 | state = 1; | |
8972963c | 649 | sp1 = getSP(); |
7af964d1 | 650 | idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
651 | sp2 = getSP(); |
652 | testassert(sp1 == sp2); | |
7af964d1 A |
653 | testassert(state == 2); |
654 | testassert(idval == ID_RESULT); | |
655 | ||
656 | state = 3; | |
8972963c | 657 | sp1 = getSP(); |
7af964d1 | 658 | llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
659 | sp2 = getSP(); |
660 | testassert(sp1 == sp2); | |
7af964d1 A |
661 | testassert(state == 4); |
662 | testassert(llval == LL_RESULT); | |
663 | ||
664 | state = 5; | |
8972963c | 665 | sp1 = getSP(); |
7af964d1 | 666 | fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
667 | sp2 = getSP(); |
668 | testassert(sp1 == sp2); | |
7af964d1 A |
669 | testassert(state == 6); |
670 | testassert(fpval == FP_RESULT); | |
671 | ||
672 | state = 7; | |
8972963c | 673 | sp1 = getSP(); |
8070259c | 674 | stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
675 | sp2 = getSP(); |
676 | testassert(sp1 == sp2); | |
7af964d1 A |
677 | testassert(state == 8); |
678 | testassert(stret_equal(stval, STRET_RESULT)); | |
679 | ||
7257e56c A |
680 | #if __x86_64__ |
681 | // check stret return register | |
682 | state = 7; | |
683 | sp1 = getSP(); | |
684 | stptr = ((fake_st_fn_t)_objc_msgForward_stret)(&stval, receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
685 | sp2 = getSP(); | |
686 | testassert(sp1 == sp2); | |
687 | testassert(state == 8); | |
688 | testassert(stret_equal(stval, STRET_RESULT)); | |
689 | testassert(stptr == &stval); | |
690 | #endif | |
691 | ||
7af964d1 A |
692 | |
693 | // Test manual forwarding, uncached but fixed-up | |
694 | ||
8972963c | 695 | _objc_flush_caches(nil); |
7af964d1 A |
696 | |
697 | state = 1; | |
8972963c | 698 | sp1 = getSP(); |
7af964d1 | 699 | idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
700 | sp2 = getSP(); |
701 | testassert(sp1 == sp2); | |
7af964d1 A |
702 | testassert(state == 2); |
703 | testassert(idval == ID_RESULT); | |
704 | ||
705 | state = 3; | |
8972963c | 706 | sp1 = getSP(); |
7af964d1 | 707 | llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
708 | sp2 = getSP(); |
709 | testassert(sp1 == sp2); | |
7af964d1 A |
710 | testassert(state == 4); |
711 | testassert(llval == LL_RESULT); | |
712 | ||
713 | state = 5; | |
8972963c | 714 | sp1 = getSP(); |
7af964d1 | 715 | fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
716 | sp2 = getSP(); |
717 | testassert(sp1 == sp2); | |
7af964d1 A |
718 | testassert(state == 6); |
719 | testassert(fpval == FP_RESULT); | |
720 | ||
721 | state = 7; | |
8972963c | 722 | sp1 = getSP(); |
8070259c | 723 | stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
8972963c A |
724 | sp2 = getSP(); |
725 | testassert(sp1 == sp2); | |
7af964d1 A |
726 | testassert(state == 8); |
727 | testassert(stret_equal(stval, STRET_RESULT)); | |
728 | ||
7257e56c A |
729 | #if __x86_64__ |
730 | // check stret return register | |
731 | state = 7; | |
732 | sp1 = getSP(); | |
733 | stptr = ((fake_st_fn_t)_objc_msgForward_stret)(&stval, receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
734 | sp2 = getSP(); | |
735 | testassert(sp1 == sp2); | |
736 | testassert(state == 8); | |
737 | testassert(stret_equal(stval, STRET_RESULT)); | |
738 | testassert(stptr == &stval); | |
739 | #endif | |
740 | ||
8070259c A |
741 | // !__OBJC2__ |
742 | #endif | |
743 | ||
7af964d1 A |
744 | |
745 | // Test user-defined forward handler | |
746 | ||
cd5f04f5 | 747 | objc_setForwardHandler((void*)&forward_handler, (void*)&forward_stret_handler); |
7af964d1 A |
748 | |
749 | state = 11; | |
8972963c | 750 | sp1 = getSP(); |
7af964d1 | 751 | idval = [Super idre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
752 | sp2 = getSP(); |
753 | testassert(sp1 == sp2); | |
7af964d1 A |
754 | testassert(state == 12); |
755 | testassert(idval == ID_RESULT); | |
756 | ||
757 | state = 13; | |
8972963c | 758 | sp1 = getSP(); |
7af964d1 | 759 | llval = [Super llre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
760 | sp2 = getSP(); |
761 | testassert(sp1 == sp2); | |
7af964d1 A |
762 | testassert(state == 14); |
763 | testassert(llval == LL_RESULT); | |
764 | ||
765 | state = 15; | |
8972963c | 766 | sp1 = getSP(); |
7af964d1 | 767 | fpval = [Super fpre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
768 | sp2 = getSP(); |
769 | testassert(sp1 == sp2); | |
7af964d1 A |
770 | testassert(state == 16); |
771 | testassert(fpval == FP_RESULT); | |
772 | ||
773 | state = 17; | |
8972963c | 774 | sp1 = getSP(); |
7af964d1 | 775 | stval = [Super stre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
776 | sp2 = getSP(); |
777 | testassert(sp1 == sp2); | |
7af964d1 A |
778 | testassert(state == 18); |
779 | testassert(stret_equal(stval, STRET_RESULT)); | |
780 | ||
7257e56c A |
781 | #if __x86_64__ |
782 | // check stret return register | |
783 | state = 17; | |
784 | sp1 = getSP(); | |
785 | stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stre3::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
786 | sp2 = getSP(); | |
787 | testassert(sp1 == sp2); | |
788 | testassert(state == 18); | |
789 | testassert(stret_equal(stval, STRET_RESULT)); | |
790 | testassert(stptr == &stval); | |
791 | #endif | |
792 | ||
7af964d1 A |
793 | |
794 | // Test user-defined forward handler, cached | |
795 | ||
796 | state = 11; | |
8972963c | 797 | sp1 = getSP(); |
7af964d1 | 798 | idval = [Super idre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
799 | sp2 = getSP(); |
800 | testassert(sp1 == sp2); | |
7af964d1 A |
801 | testassert(state == 12); |
802 | testassert(idval == ID_RESULT); | |
803 | ||
804 | state = 13; | |
8972963c | 805 | sp1 = getSP(); |
7af964d1 | 806 | llval = [Super llre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
807 | sp2 = getSP(); |
808 | testassert(sp1 == sp2); | |
7af964d1 A |
809 | testassert(state == 14); |
810 | testassert(llval == LL_RESULT); | |
811 | ||
812 | state = 15; | |
8972963c | 813 | sp1 = getSP(); |
7af964d1 | 814 | fpval = [Super fpre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
815 | sp2 = getSP(); |
816 | testassert(sp1 == sp2); | |
7af964d1 A |
817 | testassert(state == 16); |
818 | testassert(fpval == FP_RESULT); | |
819 | ||
820 | state = 17; | |
8972963c | 821 | sp1 = getSP(); |
7af964d1 | 822 | stval = [Super stre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
823 | sp2 = getSP(); |
824 | testassert(sp1 == sp2); | |
7af964d1 A |
825 | testassert(state == 18); |
826 | testassert(stret_equal(stval, STRET_RESULT)); | |
827 | ||
7257e56c A |
828 | #if __x86_64__ |
829 | // check stret return register | |
830 | state = 17; | |
831 | sp1 = getSP(); | |
832 | stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stre3::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
833 | sp2 = getSP(); | |
834 | testassert(sp1 == sp2); | |
835 | testassert(state == 18); | |
836 | testassert(stret_equal(stval, STRET_RESULT)); | |
837 | testassert(stptr == &stval); | |
838 | #endif | |
839 | ||
7af964d1 A |
840 | |
841 | // Test user-defined forward handler, uncached but fixed-up | |
842 | ||
8972963c | 843 | _objc_flush_caches(nil); |
7af964d1 A |
844 | |
845 | state = 11; | |
8972963c | 846 | sp1 = getSP(); |
7af964d1 | 847 | idval = [Super idre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
848 | sp2 = getSP(); |
849 | testassert(sp1 == sp2); | |
7af964d1 A |
850 | testassert(state == 12); |
851 | testassert(idval == ID_RESULT); | |
852 | ||
853 | state = 13; | |
8972963c | 854 | sp1 = getSP(); |
7af964d1 | 855 | llval = [Super llre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
856 | sp2 = getSP(); |
857 | testassert(sp1 == sp2); | |
7af964d1 A |
858 | testassert(state == 14); |
859 | testassert(llval == LL_RESULT); | |
860 | ||
861 | state = 15; | |
8972963c | 862 | sp1 = getSP(); |
7af964d1 | 863 | fpval = [Super fpre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
864 | sp2 = getSP(); |
865 | testassert(sp1 == sp2); | |
7af964d1 A |
866 | testassert(state == 16); |
867 | testassert(fpval == FP_RESULT); | |
868 | ||
869 | state = 17; | |
8972963c | 870 | sp1 = getSP(); |
7af964d1 | 871 | stval = [Super stre3:1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; |
8972963c A |
872 | sp2 = getSP(); |
873 | testassert(sp1 == sp2); | |
7af964d1 A |
874 | testassert(state == 18); |
875 | testassert(stret_equal(stval, STRET_RESULT)); | |
876 | ||
7257e56c A |
877 | #if __x86_64__ |
878 | // check stret return register | |
879 | state = 17; | |
880 | sp1 = getSP(); | |
881 | stptr = ((fake_st_fn_t)objc_msgSend_stret)(&stval, [Super class], @selector(stre3::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
882 | sp2 = getSP(); | |
883 | testassert(sp1 == sp2); | |
884 | testassert(state == 18); | |
885 | testassert(stret_equal(stval, STRET_RESULT)); | |
886 | testassert(stptr == &stval); | |
887 | #endif | |
888 | ||
889 | ||
890 | ||
891 | // Test user-defined forward handler, manual forwarding | |
892 | ||
893 | state = 11; | |
894 | sp1 = getSP(); | |
895 | idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
896 | sp2 = getSP(); | |
897 | testassert(sp1 == sp2); | |
898 | testassert(state == 12); | |
899 | testassert(idval == ID_RESULT); | |
900 | ||
901 | state = 13; | |
902 | sp1 = getSP(); | |
903 | llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
904 | sp2 = getSP(); | |
905 | testassert(sp1 == sp2); | |
906 | testassert(state == 14); | |
907 | testassert(llval == LL_RESULT); | |
908 | ||
909 | state = 15; | |
910 | sp1 = getSP(); | |
911 | fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
912 | sp2 = getSP(); | |
913 | testassert(sp1 == sp2); | |
914 | testassert(state == 16); | |
915 | testassert(fpval == FP_RESULT); | |
916 | ||
917 | state = 17; | |
918 | sp1 = getSP(); | |
8070259c | 919 | stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
7257e56c A |
920 | sp2 = getSP(); |
921 | testassert(sp1 == sp2); | |
922 | testassert(state == 18); | |
923 | testassert(stret_equal(stval, STRET_RESULT)); | |
924 | ||
925 | ||
926 | // Test user-defined forward handler, manual forwarding, cached | |
927 | ||
928 | state = 11; | |
929 | sp1 = getSP(); | |
930 | idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
931 | sp2 = getSP(); | |
932 | testassert(sp1 == sp2); | |
933 | testassert(state == 12); | |
934 | testassert(idval == ID_RESULT); | |
935 | ||
936 | state = 13; | |
937 | sp1 = getSP(); | |
938 | llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
939 | sp2 = getSP(); | |
940 | testassert(sp1 == sp2); | |
941 | testassert(state == 14); | |
942 | testassert(llval == LL_RESULT); | |
943 | ||
944 | state = 15; | |
945 | sp1 = getSP(); | |
946 | fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
947 | sp2 = getSP(); | |
948 | testassert(sp1 == sp2); | |
949 | testassert(state == 16); | |
950 | testassert(fpval == FP_RESULT); | |
951 | ||
952 | state = 17; | |
953 | sp1 = getSP(); | |
8070259c | 954 | stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
7257e56c A |
955 | sp2 = getSP(); |
956 | testassert(sp1 == sp2); | |
957 | testassert(state == 18); | |
958 | testassert(stret_equal(stval, STRET_RESULT)); | |
959 | ||
960 | ||
961 | // Test user-defined forward handler, manual forwarding, uncached but fixed-up | |
962 | ||
963 | _objc_flush_caches(nil); | |
964 | ||
965 | state = 11; | |
966 | sp1 = getSP(); | |
967 | idval = ((id_fn_t)_objc_msgForward)(receiver, @selector(idre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
968 | sp2 = getSP(); | |
969 | testassert(sp1 == sp2); | |
970 | testassert(state == 12); | |
971 | testassert(idval == ID_RESULT); | |
972 | ||
973 | state = 13; | |
974 | sp1 = getSP(); | |
975 | llval = ((ll_fn_t)_objc_msgForward)(receiver, @selector(llre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
976 | sp2 = getSP(); | |
977 | testassert(sp1 == sp2); | |
978 | testassert(state == 14); | |
979 | testassert(llval == LL_RESULT); | |
980 | ||
981 | state = 15; | |
982 | sp1 = getSP(); | |
983 | fpval = ((fp_fn_t)_objc_msgForward)(receiver, @selector(fpre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
984 | sp2 = getSP(); | |
985 | testassert(sp1 == sp2); | |
986 | testassert(state == 16); | |
987 | testassert(fpval == FP_RESULT); | |
988 | ||
989 | state = 17; | |
990 | sp1 = getSP(); | |
8070259c | 991 | stval = stret_fwd(receiver, @selector(stre2::::::::::::::::::::::::::::), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); |
7257e56c A |
992 | sp2 = getSP(); |
993 | testassert(sp1 == sp2); | |
994 | testassert(state == 18); | |
995 | testassert(stret_equal(stval, STRET_RESULT)); | |
996 | ||
7af964d1 A |
997 | |
998 | succeed(__FILE__); | |
999 | } | |
8972963c A |
1000 | |
1001 | #endif |