1 // TEST_CONFIG MEM=mrc,gc
2 // TEST_CFLAGS -Wno-deprecated-declarations
6 #if __cplusplus && !__clang__
10 // llvm-g++ is confused by @selector(foo::) and will never be fixed
16 #include <objc/runtime.h>
17 #include <objc/message.h>
19 id ID_RESULT = (id)0x12345678;
20 long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__;
21 double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__;
22 long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__;
23 // STRET_RESULT in test.h
30 @interface Super { id isa; } @end
32 @interface Super (Forwarded)
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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)
76 __asm__ volatile("mov %0, x8" : "=r" (struct_addr) : : "x8");
79 testassert(self == receiver);
90 testassert(i10 == 10);
91 testassert(i11 == 11);
92 testassert(i12 == 12);
93 testassert(i13 == 13);
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);
111 if (_cmd == @selector(idret::::::::::::::::::::::::::::) ||
112 _cmd == @selector(idre2::::::::::::::::::::::::::::) ||
113 _cmd == @selector(idre3::::::::::::::::::::::::::::))
119 testassert(state == 11);
121 result.idval = ID_RESULT;
124 else if (_cmd == @selector(llret::::::::::::::::::::::::::::) ||
125 _cmd == @selector(llre2::::::::::::::::::::::::::::) ||
126 _cmd == @selector(llre3::::::::::::::::::::::::::::))
128 testassert(state == 13);
132 else if (_cmd == @selector(fpret::::::::::::::::::::::::::::) ||
133 _cmd == @selector(fpre2::::::::::::::::::::::::::::) ||
134 _cmd == @selector(fpre3::::::::::::::::::::::::::::))
136 testassert(state == 15);
138 #if defined(__i386__)
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__)
147 result.fpval = FP_RESULT;
149 #elif defined(__arm64__)
150 __asm__ volatile("ldr d0, %0" : : "m" (FP_RESULT));
152 # error unknown architecture
156 else if (_cmd == @selector(stret::::::::::::::::::::::::::::) ||
157 _cmd == @selector(stre2::::::::::::::::::::::::::::) ||
158 _cmd == @selector(stre3::::::::::::::::::::::::::::))
160 #if __i386__ || __x86_64__ || __arm__
161 fail("stret message sent to non-stret forward_handler");
163 testassert(state == 17);
165 memcpy(struct_addr, &STRET_RESULT, sizeof(STRET_RESULT));
168 # error unknown architecture
172 fail("unknown selector %s in forward_handler", sel_getName(_cmd));
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)
179 testassert(self == receiver);
190 testassert(i10 == 10);
191 testassert(i11 == 11);
192 testassert(i12 == 12);
193 testassert(i13 == 13);
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);
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::::::::::::::::::::::::::::))
221 fail("non-stret selector %s sent to forward_stret_handler", sel_getName(_cmd));
223 else if (_cmd == @selector(stret::::::::::::::::::::::::::::) ||
224 _cmd == @selector(stre2::::::::::::::::::::::::::::) ||
225 _cmd == @selector(stre3::::::::::::::::::::::::::::))
227 testassert(state == 17);
232 fail("unknown selector %s in forward_stret_handler", sel_getName(_cmd));
238 @implementation Super
239 +(void)initialize { }
240 +(id)class { return self; }
243 // forward:: not supported
245 -(long long) forward:(SEL)sel :(marg_list)args
250 struct stret *struct_addr;
252 #if defined(__i386__)
253 struct_addr = ((struct stret **)args)[-1];
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);
259 # error unknown architecture
262 testassert(self == receiver);
263 testassert(_cmd == sel_registerName("forward::"));
266 #if defined(__x86_64__)
267 p += 8*16 + 4*8; // skip over xmm and linkage
268 if (sel == @selector(stret::::::::::::::::::::::::::::) ||
269 sel == @selector(stre2::::::::::::::::::::::::::::) ||
270 sel == @selector(stre3::::::::::::::::::::::::::::))
272 p += sizeof(void *); // struct return
274 #elif defined(__i386__)
276 #elif defined(__arm__)
277 if (sel == @selector(stret::::::::::::::::::::::::::::) ||
278 sel == @selector(stre2::::::::::::::::::::::::::::) ||
279 sel == @selector(stre3::::::::::::::::::::::::::::))
281 p += sizeof(void *); // struct return;
284 # error unknown architecture
287 testassert(*gp++ == (uintptr_t)self);
288 testassert(*gp++ == (uintptr_t)(void *)sel);
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);
303 #if defined(__i386__) || defined(__arm__)
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);
319 testassert(*fp++ == 14.0);
320 testassert(*fp++ == 15.0);
322 #elif defined(__x86_64__)
324 fp = (double *)args; // xmm, double-wide
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++;
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);
343 # error unknown architecture
346 if (sel == @selector(idret::::::::::::::::::::::::::::) ||
347 sel == @selector(idre2::::::::::::::::::::::::::::) ||
348 sel == @selector(idre3::::::::::::::::::::::::::::))
354 testassert(state == 1);
356 result.idval = ID_RESULT;
358 } else if (sel == @selector(llret::::::::::::::::::::::::::::) ||
359 sel == @selector(llre2::::::::::::::::::::::::::::) ||
360 sel == @selector(llre3::::::::::::::::::::::::::::))
362 testassert(state == 3);
365 } else if (sel == @selector(fpret::::::::::::::::::::::::::::) ||
366 sel == @selector(fpre2::::::::::::::::::::::::::::) ||
367 sel == @selector(fpre3::::::::::::::::::::::::::::))
369 testassert(state == 5);
371 #if defined(__i386__)
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__)
380 result.fpval = FP_RESULT;
383 # error unknown architecture
386 } else if (sel == @selector(stret::::::::::::::::::::::::::::) ||
387 sel == @selector(stre2::::::::::::::::::::::::::::) ||
388 sel == @selector(stre3::::::::::::::::::::::::::::))
390 testassert(state == 7);
392 *struct_addr = STRET_RESULT;
395 fail("unknown selector %s in forward::", sel_getName(sel));
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);
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);
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);
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);
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);
417 extern void *getSP(void);
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");
426 #elif defined(__arm64__)
427 asm(".text \n _getSP: mov x0, sp \n ret \n");
429 # error unknown architecture
441 void *sp1 = (void*)1;
442 void *sp2 = (void*)2;
446 stret_fwd = (st_fn_t)_objc_msgForward;
448 stret_fwd = (st_fn_t)_objc_msgForward_stret;
451 receiver = [Super class];
454 // forward:: not supported
456 // Test default forward handler
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];
462 testassert(sp1 == sp2);
463 testassert(state == 2);
464 testassert(idval == ID_RESULT);
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];
470 testassert(sp1 == sp2);
471 testassert(state == 4);
472 testassert(llval == LL_RESULT);
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];
478 testassert(sp1 == sp2);
479 testassert(state == 6);
480 testassert(fpval == FP_RESULT);
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];
486 testassert(sp1 == sp2);
487 testassert(state == 8);
488 testassert(stret_equal(stval, STRET_RESULT));
491 // check stret return register
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);
496 testassert(sp1 == sp2);
497 testassert(state == 8);
498 testassert(stret_equal(stval, STRET_RESULT));
499 testassert(stptr == &stval);
503 // Test default forward handler, cached
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];
509 testassert(sp1 == sp2);
510 testassert(state == 2);
511 testassert(idval == ID_RESULT);
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];
517 testassert(sp1 == sp2);
518 testassert(state == 4);
519 testassert(llval == LL_RESULT);
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];
525 testassert(sp1 == sp2);
526 testassert(state == 6);
527 testassert(fpval == FP_RESULT);
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];
533 testassert(sp1 == sp2);
534 testassert(state == 8);
535 testassert(stret_equal(stval, STRET_RESULT));
538 // check stret return register
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);
543 testassert(sp1 == sp2);
544 testassert(state == 8);
545 testassert(stret_equal(stval, STRET_RESULT));
546 testassert(stptr == &stval);
550 // Test default forward handler, uncached but fixed-up
552 _objc_flush_caches(nil);
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];
558 testassert(sp1 == sp2);
559 testassert(state == 2);
560 testassert(idval == ID_RESULT);
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];
566 testassert(sp1 == sp2);
567 testassert(state == 4);
568 testassert(llval == LL_RESULT);
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];
574 testassert(sp1 == sp2);
575 testassert(state == 6);
576 testassert(fpval == FP_RESULT);
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];
582 testassert(sp1 == sp2);
583 testassert(state == 8);
584 testassert(stret_equal(stval, STRET_RESULT));
587 // check stret return register
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);
592 testassert(sp1 == sp2);
593 testassert(state == 8);
594 testassert(stret_equal(stval, STRET_RESULT));
595 testassert(stptr == &stval);
599 // Test manual forwarding
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);
605 testassert(sp1 == sp2);
606 testassert(state == 2);
607 testassert(idval == ID_RESULT);
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);
613 testassert(sp1 == sp2);
614 testassert(state == 4);
615 testassert(llval == LL_RESULT);
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);
621 testassert(sp1 == sp2);
622 testassert(state == 6);
623 testassert(fpval == FP_RESULT);
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);
629 testassert(sp1 == sp2);
630 testassert(state == 8);
631 testassert(stret_equal(stval, STRET_RESULT));
634 // check stret return register
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);
639 testassert(sp1 == sp2);
640 testassert(state == 8);
641 testassert(stret_equal(stval, STRET_RESULT));
642 testassert(stptr == &stval);
646 // Test manual forwarding, cached
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);
652 testassert(sp1 == sp2);
653 testassert(state == 2);
654 testassert(idval == ID_RESULT);
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);
660 testassert(sp1 == sp2);
661 testassert(state == 4);
662 testassert(llval == LL_RESULT);
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);
668 testassert(sp1 == sp2);
669 testassert(state == 6);
670 testassert(fpval == FP_RESULT);
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);
676 testassert(sp1 == sp2);
677 testassert(state == 8);
678 testassert(stret_equal(stval, STRET_RESULT));
681 // check stret return register
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);
686 testassert(sp1 == sp2);
687 testassert(state == 8);
688 testassert(stret_equal(stval, STRET_RESULT));
689 testassert(stptr == &stval);
693 // Test manual forwarding, uncached but fixed-up
695 _objc_flush_caches(nil);
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);
701 testassert(sp1 == sp2);
702 testassert(state == 2);
703 testassert(idval == ID_RESULT);
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);
709 testassert(sp1 == sp2);
710 testassert(state == 4);
711 testassert(llval == LL_RESULT);
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);
717 testassert(sp1 == sp2);
718 testassert(state == 6);
719 testassert(fpval == FP_RESULT);
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);
725 testassert(sp1 == sp2);
726 testassert(state == 8);
727 testassert(stret_equal(stval, STRET_RESULT));
730 // check stret return register
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);
735 testassert(sp1 == sp2);
736 testassert(state == 8);
737 testassert(stret_equal(stval, STRET_RESULT));
738 testassert(stptr == &stval);
745 // Test user-defined forward handler
747 objc_setForwardHandler((void*)&forward_handler, (void*)&forward_stret_handler);
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];
753 testassert(sp1 == sp2);
754 testassert(state == 12);
755 testassert(idval == ID_RESULT);
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];
761 testassert(sp1 == sp2);
762 testassert(state == 14);
763 testassert(llval == LL_RESULT);
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];
769 testassert(sp1 == sp2);
770 testassert(state == 16);
771 testassert(fpval == FP_RESULT);
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];
777 testassert(sp1 == sp2);
778 testassert(state == 18);
779 testassert(stret_equal(stval, STRET_RESULT));
782 // check stret return register
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);
787 testassert(sp1 == sp2);
788 testassert(state == 18);
789 testassert(stret_equal(stval, STRET_RESULT));
790 testassert(stptr == &stval);
794 // Test user-defined forward handler, cached
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];
800 testassert(sp1 == sp2);
801 testassert(state == 12);
802 testassert(idval == ID_RESULT);
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];
808 testassert(sp1 == sp2);
809 testassert(state == 14);
810 testassert(llval == LL_RESULT);
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];
816 testassert(sp1 == sp2);
817 testassert(state == 16);
818 testassert(fpval == FP_RESULT);
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];
824 testassert(sp1 == sp2);
825 testassert(state == 18);
826 testassert(stret_equal(stval, STRET_RESULT));
829 // check stret return register
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);
834 testassert(sp1 == sp2);
835 testassert(state == 18);
836 testassert(stret_equal(stval, STRET_RESULT));
837 testassert(stptr == &stval);
841 // Test user-defined forward handler, uncached but fixed-up
843 _objc_flush_caches(nil);
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];
849 testassert(sp1 == sp2);
850 testassert(state == 12);
851 testassert(idval == ID_RESULT);
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];
857 testassert(sp1 == sp2);
858 testassert(state == 14);
859 testassert(llval == LL_RESULT);
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];
865 testassert(sp1 == sp2);
866 testassert(state == 16);
867 testassert(fpval == FP_RESULT);
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];
873 testassert(sp1 == sp2);
874 testassert(state == 18);
875 testassert(stret_equal(stval, STRET_RESULT));
878 // check stret return register
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);
883 testassert(sp1 == sp2);
884 testassert(state == 18);
885 testassert(stret_equal(stval, STRET_RESULT));
886 testassert(stptr == &stval);
891 // Test user-defined forward handler, manual forwarding
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);
897 testassert(sp1 == sp2);
898 testassert(state == 12);
899 testassert(idval == ID_RESULT);
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);
905 testassert(sp1 == sp2);
906 testassert(state == 14);
907 testassert(llval == LL_RESULT);
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);
913 testassert(sp1 == sp2);
914 testassert(state == 16);
915 testassert(fpval == FP_RESULT);
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);
921 testassert(sp1 == sp2);
922 testassert(state == 18);
923 testassert(stret_equal(stval, STRET_RESULT));
926 // Test user-defined forward handler, manual forwarding, cached
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);
932 testassert(sp1 == sp2);
933 testassert(state == 12);
934 testassert(idval == ID_RESULT);
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);
940 testassert(sp1 == sp2);
941 testassert(state == 14);
942 testassert(llval == LL_RESULT);
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);
948 testassert(sp1 == sp2);
949 testassert(state == 16);
950 testassert(fpval == FP_RESULT);
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);
956 testassert(sp1 == sp2);
957 testassert(state == 18);
958 testassert(stret_equal(stval, STRET_RESULT));
961 // Test user-defined forward handler, manual forwarding, uncached but fixed-up
963 _objc_flush_caches(nil);
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);
969 testassert(sp1 == sp2);
970 testassert(state == 12);
971 testassert(idval == ID_RESULT);
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);
977 testassert(sp1 == sp2);
978 testassert(state == 14);
979 testassert(llval == LL_RESULT);
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);
985 testassert(sp1 == sp2);
986 testassert(state == 16);
987 testassert(fpval == FP_RESULT);
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);
993 testassert(sp1 == sp2);
994 testassert(state == 18);
995 testassert(stret_equal(stval, STRET_RESULT));