1// TEST_CONFIG MEM=mrc,gc
2// TEST_CFLAGS -Wno-deprecated-declarations
3
4#include "test.h"
5
6#if __cplusplus  &&  !__clang__
7
8int main()
9{
10    // llvm-g++ is confused by @selector(foo::) and will never be fixed
11    succeed(__FILE__);
12}
13
14#else
15
16#include <objc/runtime.h>
17#include <objc/message.h>
18
19id ID_RESULT = (id)0x12345678;
20long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__;
21double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__;
22long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__;
23// STRET_RESULT in test.h
24
25
26static int state = 0;
27static id receiver;
28
29OBJC_ROOT_CLASS
30@interface Super { id isa; } @end
31
32@interface Super (Forwarded) 
33+(id)idret: 
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;
35
36+(id)idre2: 
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;
38
39+(id)idre3: 
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;
41
42+(long long)llret: 
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;
44
45+(long long)llre2: 
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;
47
48+(long long)llre3: 
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;
50
51+(struct stret)stret: 
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;
53
54+(struct stret)stre2: 
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;
56
57+(struct stret)stre3: 
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;
59
60+(double)fpret: 
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;
62
63+(double)fpre2: 
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;
65
66+(double)fpre3: 
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;
68
69@end
70
71
72long 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{
74#if __arm64__
75    void *struct_addr;
76    __asm__ volatile("mov %0, x8" : "=r" (struct_addr) : : "x8");
77#endif
78
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;
123    }
124    else if (_cmd == @selector(llret::::::::::::::::::::::::::::)  ||  
125             _cmd == @selector(llre2::::::::::::::::::::::::::::)  ||  
126             _cmd == @selector(llre3::::::::::::::::::::::::::::)) 
127    {
128        testassert(state == 13);
129        state = 14;
130        return LL_RESULT;
131    }
132    else if (_cmd == @selector(fpret::::::::::::::::::::::::::::)  ||  
133             _cmd == @selector(fpre2::::::::::::::::::::::::::::)  ||  
134             _cmd == @selector(fpre3::::::::::::::::::::::::::::)) 
135    {
136        testassert(state == 15);
137        state = 16;
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__)
143        union {
144            double fpval;
145            long long llval;
146        } result;
147        result.fpval = FP_RESULT;
148        return result.llval;
149#elif defined(__arm64__)
150        __asm__ volatile("ldr d0, %0" : : "m" (FP_RESULT));
151#else
152#       error unknown architecture
153#endif
154        return 0;
155    }
156    else if (_cmd == @selector(stret::::::::::::::::::::::::::::)  ||  
157             _cmd == @selector(stre2::::::::::::::::::::::::::::)  ||  
158             _cmd == @selector(stre3::::::::::::::::::::::::::::)) 
159    {
160#if __i386__  ||  __x86_64__  ||  __arm__
161        fail("stret message sent to non-stret forward_handler");
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
170    } 
171    else {
172        fail("unknown selector %s in forward_handler", sel_getName(_cmd));
173    }
174}
175
176
177struct 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));
222    }
223    else if (_cmd == @selector(stret::::::::::::::::::::::::::::)  ||  
224             _cmd == @selector(stre2::::::::::::::::::::::::::::)  ||  
225             _cmd == @selector(stre3::::::::::::::::::::::::::::)) 
226    {
227        testassert(state == 17);
228        state = 18;
229        return STRET_RESULT;
230    }
231    else {
232        fail("unknown selector %s in forward_stret_handler", sel_getName(_cmd));
233    }
234
235}
236
237
238@implementation Super
239+(void)initialize { }
240+(id)class { return self; }
241
242#if __OBJC2__
243// forward:: not supported
244#else
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];
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
265    p = (char *)args;
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::::::::::::::::::::::::::::)) 
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);
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);
302
303#if defined(__i386__)  ||  defined(__arm__)
304
305    fp = (double *)gp;
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);
321
322#elif defined(__x86_64__)
323
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++;
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;
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__)
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
400#endif
401
402@end
403
404typedef 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
406typedef 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
408typedef 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
410typedef 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
412#if __x86_64__
413typedef 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
416__BEGIN_DECLS
417extern void *getSP(void);
418__END_DECLS
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");
426#elif defined(__arm64__)
427    asm(".text \n _getSP: mov x0, sp \n ret \n");
428#else
429#   error unknown architecture
430#endif
431
432int main()
433{
434    id idval;
435    long long llval;
436    struct stret stval;
437#if __x86_64__
438    struct stret *stptr;
439#endif
440    double fpval;
441    void *sp1 = (void*)1;
442    void *sp2 = (void*)2;
443
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
451    receiver = [Super class];
452
453#if __OBJC2__
454    // forward:: not supported
455#else
456    // Test default forward handler
457
458    state = 1;
459    sp1 = getSP();
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];
461    sp2 = getSP();
462    testassert(sp1 == sp2);
463    testassert(state == 2);
464    testassert(idval == ID_RESULT);
465
466    state = 3;
467    sp1 = getSP();
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];
469    sp2 = getSP();
470    testassert(sp1 == sp2);
471    testassert(state == 4);
472    testassert(llval == LL_RESULT);
473
474    state = 5;
475    sp1 = getSP();
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];
477    sp2 = getSP();
478    testassert(sp1 == sp2);
479    testassert(state == 6);
480    testassert(fpval == FP_RESULT);
481
482    state = 7;
483    sp1 = getSP();
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];
485    sp2 = getSP();
486    testassert(sp1 == sp2);
487    testassert(state == 8);
488    testassert(stret_equal(stval, STRET_RESULT));
489
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
502
503    // Test default forward handler, cached
504
505    state = 1;
506    sp1 = getSP();
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];
508    sp2 = getSP();
509    testassert(sp1 == sp2);
510    testassert(state == 2);
511    testassert(idval == ID_RESULT);
512
513    state = 3;
514    sp1 = getSP();
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];
516    sp2 = getSP();
517    testassert(sp1 == sp2);
518    testassert(state == 4);
519    testassert(llval == LL_RESULT);
520
521    state = 5;
522    sp1 = getSP();
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];
524    sp2 = getSP();
525    testassert(sp1 == sp2);
526    testassert(state == 6);
527    testassert(fpval == FP_RESULT);
528
529    state = 7;
530    sp1 = getSP();
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];
532    sp2 = getSP();
533    testassert(sp1 == sp2);
534    testassert(state == 8);
535    testassert(stret_equal(stval, STRET_RESULT));
536
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
549
550    // Test default forward handler, uncached but fixed-up
551
552    _objc_flush_caches(nil);
553
554    state = 1;
555    sp1 = getSP();
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];
557    sp2 = getSP();
558    testassert(sp1 == sp2);
559    testassert(state == 2);
560    testassert(idval == ID_RESULT);
561
562    state = 3;
563    sp1 = getSP();
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];
565    sp2 = getSP();
566    testassert(sp1 == sp2);
567    testassert(state == 4);
568    testassert(llval == LL_RESULT);
569
570    state = 5;
571    sp1 = getSP();
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];
573    sp2 = getSP();
574    testassert(sp1 == sp2);
575    testassert(state == 6);
576    testassert(fpval == FP_RESULT);
577
578    state = 7;
579    sp1 = getSP();
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];
581    sp2 = getSP();
582    testassert(sp1 == sp2);
583    testassert(state == 8);
584    testassert(stret_equal(stval, STRET_RESULT));
585
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
598
599    // Test manual forwarding
600
601    state = 1;
602    sp1 = getSP();
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);
604    sp2 = getSP();
605    testassert(sp1 == sp2);
606    testassert(state == 2);
607    testassert(idval == ID_RESULT);
608
609    state = 3;
610    sp1 = getSP();
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);
612    sp2 = getSP();
613    testassert(sp1 == sp2);
614    testassert(state == 4);
615    testassert(llval == LL_RESULT);
616
617    state = 5;
618    sp1 = getSP();
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);
620    sp2 = getSP();
621    testassert(sp1 == sp2);
622    testassert(state == 6);
623    testassert(fpval == FP_RESULT);
624
625    state = 7;
626    sp1 = getSP();
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);
628    sp2 = getSP();
629    testassert(sp1 == sp2);
630    testassert(state == 8);
631    testassert(stret_equal(stval, STRET_RESULT));
632
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
645
646    // Test manual forwarding, cached
647
648    state = 1;
649    sp1 = getSP();
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);
651    sp2 = getSP();
652    testassert(sp1 == sp2);
653    testassert(state == 2);
654    testassert(idval == ID_RESULT);
655
656    state = 3;
657    sp1 = getSP();
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);
659    sp2 = getSP();
660    testassert(sp1 == sp2);
661    testassert(state == 4);
662    testassert(llval == LL_RESULT);
663
664    state = 5;
665    sp1 = getSP();
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);
667    sp2 = getSP();
668    testassert(sp1 == sp2);
669    testassert(state == 6);
670    testassert(fpval == FP_RESULT);
671
672    state = 7;
673    sp1 = getSP();
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);
675    sp2 = getSP();
676    testassert(sp1 == sp2);
677    testassert(state == 8);
678    testassert(stret_equal(stval, STRET_RESULT));
679
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
692
693    // Test manual forwarding, uncached but fixed-up
694
695    _objc_flush_caches(nil);
696
697    state = 1;
698    sp1 = getSP();
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);
700    sp2 = getSP();
701    testassert(sp1 == sp2);
702    testassert(state == 2);
703    testassert(idval == ID_RESULT);
704
705    state = 3;
706    sp1 = getSP();
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);
708    sp2 = getSP();
709    testassert(sp1 == sp2);
710    testassert(state == 4);
711    testassert(llval == LL_RESULT);
712
713    state = 5;
714    sp1 = getSP();
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);
716    sp2 = getSP();
717    testassert(sp1 == sp2);
718    testassert(state == 6);
719    testassert(fpval == FP_RESULT);
720
721    state = 7;
722    sp1 = getSP();
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);
724    sp2 = getSP();
725    testassert(sp1 == sp2);
726    testassert(state == 8);
727    testassert(stret_equal(stval, STRET_RESULT));
728
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
741// !__OBJC2__
742#endif
743
744
745    // Test user-defined forward handler
746
747    objc_setForwardHandler((void*)&forward_handler, (void*)&forward_stret_handler);
748
749    state = 11;
750    sp1 = getSP();
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];
752    sp2 = getSP();
753    testassert(sp1 == sp2);
754    testassert(state == 12);
755    testassert(idval == ID_RESULT);
756
757    state = 13;
758    sp1 = getSP();
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];
760    sp2 = getSP();
761    testassert(sp1 == sp2);
762    testassert(state == 14);
763    testassert(llval == LL_RESULT);
764
765    state = 15;
766    sp1 = getSP();
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];
768    sp2 = getSP();
769    testassert(sp1 == sp2);
770    testassert(state == 16);
771    testassert(fpval == FP_RESULT);
772
773    state = 17;
774    sp1 = getSP();
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];
776    sp2 = getSP();
777    testassert(sp1 == sp2);
778    testassert(state == 18);
779    testassert(stret_equal(stval, STRET_RESULT));
780
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
793
794    // Test user-defined forward handler, cached
795
796    state = 11;
797    sp1 = getSP();
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];
799    sp2 = getSP();
800    testassert(sp1 == sp2);
801    testassert(state == 12);
802    testassert(idval == ID_RESULT);
803
804    state = 13;
805    sp1 = getSP();
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];
807    sp2 = getSP();
808    testassert(sp1 == sp2);
809    testassert(state == 14);
810    testassert(llval == LL_RESULT);
811
812    state = 15;
813    sp1 = getSP();
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];
815    sp2 = getSP();
816    testassert(sp1 == sp2);
817    testassert(state == 16);
818    testassert(fpval == FP_RESULT);
819
820    state = 17;
821    sp1 = getSP();
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];
823    sp2 = getSP();
824    testassert(sp1 == sp2);
825    testassert(state == 18);
826    testassert(stret_equal(stval, STRET_RESULT));
827
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
840
841    // Test user-defined forward handler, uncached but fixed-up
842
843    _objc_flush_caches(nil);
844
845    state = 11;
846    sp1 = getSP();
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];
848    sp2 = getSP();
849    testassert(sp1 == sp2);
850    testassert(state == 12);
851    testassert(idval == ID_RESULT);
852
853    state = 13;
854    sp1 = getSP();
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];
856    sp2 = getSP();
857    testassert(sp1 == sp2);
858    testassert(state == 14);
859    testassert(llval == LL_RESULT);
860
861    state = 15;
862    sp1 = getSP();
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];
864    sp2 = getSP();
865    testassert(sp1 == sp2);
866    testassert(state == 16);
867    testassert(fpval == FP_RESULT);
868
869    state = 17;
870    sp1 = getSP();
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];
872    sp2 = getSP();
873    testassert(sp1 == sp2);
874    testassert(state == 18);
875    testassert(stret_equal(stval, STRET_RESULT));
876
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();
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);
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();
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);
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();
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);
992    sp2 = getSP();
993    testassert(sp1 == sp2);
994    testassert(state == 18);
995    testassert(stret_equal(stval, STRET_RESULT));
996
997
998    succeed(__FILE__);
999}
1000
1001#endif
1002