]> git.saurik.com Git - apple/objc4.git/blob - test/forward.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / forward.m
1 // TEST_CONFIG MEM=mrc
2
3 #include "test.h"
4
5 #include <objc/runtime.h>
6 #include <objc/message.h>
7
8 id ID_RESULT = (id)0x12345678;
9 long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__;
10 double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__;
11 long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__;
12 // STRET_RESULT in test.h
13
14
15 static int state = 0;
16 static id receiver;
17
18 OBJC_ROOT_CLASS
19 @interface Super { id isa; } @end
20
21 @interface Super (Forwarded)
22 +(id)idret:
23 (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;
24
25 +(id)idre2:
26 (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;
27
28 +(id)idre3:
29 (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;
30
31 +(long long)llret:
32 (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;
33
34 +(long long)llre2:
35 (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;
36
37 +(long long)llre3:
38 (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;
39
40 +(struct stret)stret:
41 (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;
42
43 +(struct stret)stre2:
44 (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;
45
46 +(struct stret)stre3:
47 (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;
48
49 +(double)fpret:
50 (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;
51
52 +(double)fpre2:
53 (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;
54
55 +(double)fpre3:
56 (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;
57
58 @end
59
60
61 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)
62 {
63 #if __arm64__
64 # if __LP64__
65 # define p "x" // true arm64
66 # else
67 # define p "w" // arm64_32
68 # endif
69 void *struct_addr;
70 __asm__ volatile("mov %" p "0, " p "8" : "=r" (struct_addr) : : p "8");
71 #endif
72
73 testassert(self == receiver);
74
75 testassert(i1 == 1);
76 testassert(i2 == 2);
77 testassert(i3 == 3);
78 testassert(i4 == 4);
79 testassert(i5 == 5);
80 testassert(i6 == 6);
81 testassert(i7 == 7);
82 testassert(i8 == 8);
83 testassert(i9 == 9);
84 testassert(i10 == 10);
85 testassert(i11 == 11);
86 testassert(i12 == 12);
87 testassert(i13 == 13);
88
89 testassert(f1 == 1.0);
90 testassert(f2 == 2.0);
91 testassert(f3 == 3.0);
92 testassert(f4 == 4.0);
93 testassert(f5 == 5.0);
94 testassert(f6 == 6.0);
95 testassert(f7 == 7.0);
96 testassert(f8 == 8.0);
97 testassert(f9 == 9.0);
98 testassert(f10 == 10.0);
99 testassert(f11 == 11.0);
100 testassert(f12 == 12.0);
101 testassert(f13 == 13.0);
102 testassert(f14 == 14.0);
103 testassert(f15 == 15.0);
104
105 if (_cmd == @selector(idret::::::::::::::::::::::::::::) ||
106 _cmd == @selector(idre2::::::::::::::::::::::::::::) ||
107 _cmd == @selector(idre3::::::::::::::::::::::::::::))
108 {
109 union {
110 id idval;
111 long long llval;
112 } result;
113 testassert(state == 11);
114 state = 12;
115 result.idval = ID_RESULT;
116 return result.llval;
117 }
118 else if (_cmd == @selector(llret::::::::::::::::::::::::::::) ||
119 _cmd == @selector(llre2::::::::::::::::::::::::::::) ||
120 _cmd == @selector(llre3::::::::::::::::::::::::::::))
121 {
122 testassert(state == 13);
123 state = 14;
124 return LL_RESULT;
125 }
126 else if (_cmd == @selector(fpret::::::::::::::::::::::::::::) ||
127 _cmd == @selector(fpre2::::::::::::::::::::::::::::) ||
128 _cmd == @selector(fpre3::::::::::::::::::::::::::::))
129 {
130 testassert(state == 15);
131 state = 16;
132 #if defined(__i386__)
133 __asm__ volatile("fldl %0" : : "m" (FP_RESULT));
134 #elif defined(__x86_64__)
135 __asm__ volatile("movsd %0, %%xmm0" : : "m" (FP_RESULT));
136 #elif defined(__arm64__)
137 __asm__ volatile("ldr d0, %0" : : "m" (FP_RESULT));
138 #elif defined(__arm__) && __ARM_ARCH_7K__
139 __asm__ volatile("vld1.64 {d0}, %0" : : "m" (FP_RESULT));
140 #elif defined(__arm__)
141 union {
142 double fpval;
143 long long llval;
144 } result;
145 result.fpval = FP_RESULT;
146 return result.llval;
147 #else
148 # error unknown architecture
149 #endif
150 return 0;
151 }
152 else if (_cmd == @selector(stret::::::::::::::::::::::::::::) ||
153 _cmd == @selector(stre2::::::::::::::::::::::::::::) ||
154 _cmd == @selector(stre3::::::::::::::::::::::::::::))
155 {
156 #if __i386__ || __x86_64__ || __arm__
157 fail("stret message sent to non-stret forward_handler");
158 #elif __arm64_32__ || __arm64__
159 testassert(state == 17);
160 state = 18;
161 memcpy(struct_addr, &STRET_RESULT, sizeof(STRET_RESULT));
162 return 0;
163 #else
164 # error unknown architecture
165 #endif
166 }
167 else {
168 fail("unknown selector %s in forward_handler", sel_getName(_cmd));
169 }
170 }
171
172
173 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)
174 {
175 testassert(self == receiver);
176
177 testassert(i1 == 1);
178 testassert(i2 == 2);
179 testassert(i3 == 3);
180 testassert(i4 == 4);
181 testassert(i5 == 5);
182 testassert(i6 == 6);
183 testassert(i7 == 7);
184 testassert(i8 == 8);
185 testassert(i9 == 9);
186 testassert(i10 == 10);
187 testassert(i11 == 11);
188 testassert(i12 == 12);
189 testassert(i13 == 13);
190
191 testassert(f1 == 1.0);
192 testassert(f2 == 2.0);
193 testassert(f3 == 3.0);
194 testassert(f4 == 4.0);
195 testassert(f5 == 5.0);
196 testassert(f6 == 6.0);
197 testassert(f7 == 7.0);
198 testassert(f8 == 8.0);
199 testassert(f9 == 9.0);
200 testassert(f10 == 10.0);
201 testassert(f11 == 11.0);
202 testassert(f12 == 12.0);
203 testassert(f13 == 13.0);
204 testassert(f14 == 14.0);
205 testassert(f15 == 15.0);
206
207 if (_cmd == @selector(idret::::::::::::::::::::::::::::) ||
208 _cmd == @selector(idre2::::::::::::::::::::::::::::) ||
209 _cmd == @selector(idre3::::::::::::::::::::::::::::) ||
210 _cmd == @selector(llret::::::::::::::::::::::::::::) ||
211 _cmd == @selector(llre2::::::::::::::::::::::::::::) ||
212 _cmd == @selector(llre3::::::::::::::::::::::::::::) ||
213 _cmd == @selector(fpret::::::::::::::::::::::::::::) ||
214 _cmd == @selector(fpre2::::::::::::::::::::::::::::) ||
215 _cmd == @selector(fpre3::::::::::::::::::::::::::::))
216 {
217 fail("non-stret selector %s sent to forward_stret_handler", sel_getName(_cmd));
218 }
219 else if (_cmd == @selector(stret::::::::::::::::::::::::::::) ||
220 _cmd == @selector(stre2::::::::::::::::::::::::::::) ||
221 _cmd == @selector(stre3::::::::::::::::::::::::::::))
222 {
223 testassert(state == 17);
224 state = 18;
225 return STRET_RESULT;
226 }
227 else {
228 fail("unknown selector %s in forward_stret_handler", sel_getName(_cmd));
229 }
230
231 }
232
233
234 @implementation Super
235 +(void)initialize { }
236 +(id)class { return self; }
237 @end
238
239 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);
240
241 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);
242
243 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);
244
245 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);
246
247 #if __x86_64__
248 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);
249 #endif
250
251 __BEGIN_DECLS
252 extern void *getSP(void);
253 __END_DECLS
254
255 #if defined(__x86_64__)
256 asm(".text \n _getSP: movq %rsp, %rax \n retq \n");
257 #elif defined(__i386__)
258 asm(".text \n _getSP: movl %esp, %eax \n ret \n");
259 #elif defined(__arm__)
260 asm(".text \n .thumb \n .thumb_func _getSP \n "
261 "_getSP: mov r0, sp \n bx lr \n");
262 #elif defined(__arm64__)
263 asm(".text \n _getSP: mov x0, sp \n ret \n");
264 #else
265 # error unknown architecture
266 #endif
267
268 int main()
269 {
270 id idval;
271 long long llval;
272 struct stret stval;
273 #if __x86_64__
274 struct stret *stptr;
275 #endif
276 double fpval;
277 void *sp1 = (void*)1;
278 void *sp2 = (void*)2;
279
280 st_fn_t stret_fwd;
281 #if __arm64__
282 stret_fwd = (st_fn_t)_objc_msgForward;
283 #else
284 stret_fwd = (st_fn_t)_objc_msgForward_stret;
285 #endif
286
287 receiver = [Super class];
288
289 // Test user-defined forward handler
290
291 objc_setForwardHandler((void*)&forward_handler, (void*)&forward_stret_handler);
292
293 state = 11;
294 sp1 = getSP();
295 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];
296 sp2 = getSP();
297 testassert(sp1 == sp2);
298 testassert(state == 12);
299 testassert(idval == ID_RESULT);
300
301 state = 13;
302 sp1 = getSP();
303 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];
304 sp2 = getSP();
305 testassert(sp1 == sp2);
306 testassert(state == 14);
307 testassert(llval == LL_RESULT);
308
309 state = 15;
310 sp1 = getSP();
311 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];
312 sp2 = getSP();
313 testassert(sp1 == sp2);
314 testassert(state == 16);
315 testassert(fpval == FP_RESULT);
316
317 state = 17;
318 sp1 = getSP();
319 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];
320 sp2 = getSP();
321 testassert(sp1 == sp2);
322 testassert(state == 18);
323 testassert(stret_equal(stval, STRET_RESULT));
324
325 #if __x86_64__
326 // check stret return register
327 state = 17;
328 sp1 = getSP();
329 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);
330 sp2 = getSP();
331 testassert(sp1 == sp2);
332 testassert(state == 18);
333 testassert(stret_equal(stval, STRET_RESULT));
334 testassert(stptr == &stval);
335 #endif
336
337
338 // Test user-defined forward handler, cached
339
340 state = 11;
341 sp1 = getSP();
342 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];
343 sp2 = getSP();
344 testassert(sp1 == sp2);
345 testassert(state == 12);
346 testassert(idval == ID_RESULT);
347
348 state = 13;
349 sp1 = getSP();
350 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];
351 sp2 = getSP();
352 testassert(sp1 == sp2);
353 testassert(state == 14);
354 testassert(llval == LL_RESULT);
355
356 state = 15;
357 sp1 = getSP();
358 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];
359 sp2 = getSP();
360 testassert(sp1 == sp2);
361 testassert(state == 16);
362 testassert(fpval == FP_RESULT);
363
364 state = 17;
365 sp1 = getSP();
366 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];
367 sp2 = getSP();
368 testassert(sp1 == sp2);
369 testassert(state == 18);
370 testassert(stret_equal(stval, STRET_RESULT));
371
372 #if __x86_64__
373 // check stret return register
374 state = 17;
375 sp1 = getSP();
376 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);
377 sp2 = getSP();
378 testassert(sp1 == sp2);
379 testassert(state == 18);
380 testassert(stret_equal(stval, STRET_RESULT));
381 testassert(stptr == &stval);
382 #endif
383
384
385 // Test user-defined forward handler, uncached but fixed-up
386
387 _objc_flush_caches(nil);
388
389 state = 11;
390 sp1 = getSP();
391 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];
392 sp2 = getSP();
393 testassert(sp1 == sp2);
394 testassert(state == 12);
395 testassert(idval == ID_RESULT);
396
397 state = 13;
398 sp1 = getSP();
399 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];
400 sp2 = getSP();
401 testassert(sp1 == sp2);
402 testassert(state == 14);
403 testassert(llval == LL_RESULT);
404
405 state = 15;
406 sp1 = getSP();
407 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];
408 sp2 = getSP();
409 testassert(sp1 == sp2);
410 testassert(state == 16);
411 testassert(fpval == FP_RESULT);
412
413 state = 17;
414 sp1 = getSP();
415 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];
416 sp2 = getSP();
417 testassert(sp1 == sp2);
418 testassert(state == 18);
419 testassert(stret_equal(stval, STRET_RESULT));
420
421 #if __x86_64__
422 // check stret return register
423 state = 17;
424 sp1 = getSP();
425 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);
426 sp2 = getSP();
427 testassert(sp1 == sp2);
428 testassert(state == 18);
429 testassert(stret_equal(stval, STRET_RESULT));
430 testassert(stptr == &stval);
431 #endif
432
433
434
435 // Test user-defined forward handler, manual forwarding
436
437 state = 11;
438 sp1 = getSP();
439 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);
440 sp2 = getSP();
441 testassert(sp1 == sp2);
442 testassert(state == 12);
443 testassert(idval == ID_RESULT);
444
445 state = 13;
446 sp1 = getSP();
447 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);
448 sp2 = getSP();
449 testassert(sp1 == sp2);
450 testassert(state == 14);
451 testassert(llval == LL_RESULT);
452
453 state = 15;
454 sp1 = getSP();
455 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);
456 sp2 = getSP();
457 testassert(sp1 == sp2);
458 testassert(state == 16);
459 testassert(fpval == FP_RESULT);
460
461 state = 17;
462 sp1 = getSP();
463 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);
464 sp2 = getSP();
465 testassert(sp1 == sp2);
466 testassert(state == 18);
467 testassert(stret_equal(stval, STRET_RESULT));
468
469
470 // Test user-defined forward handler, manual forwarding, cached
471
472 state = 11;
473 sp1 = getSP();
474 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);
475 sp2 = getSP();
476 testassert(sp1 == sp2);
477 testassert(state == 12);
478 testassert(idval == ID_RESULT);
479
480 state = 13;
481 sp1 = getSP();
482 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);
483 sp2 = getSP();
484 testassert(sp1 == sp2);
485 testassert(state == 14);
486 testassert(llval == LL_RESULT);
487
488 state = 15;
489 sp1 = getSP();
490 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);
491 sp2 = getSP();
492 testassert(sp1 == sp2);
493 testassert(state == 16);
494 testassert(fpval == FP_RESULT);
495
496 state = 17;
497 sp1 = getSP();
498 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);
499 sp2 = getSP();
500 testassert(sp1 == sp2);
501 testassert(state == 18);
502 testassert(stret_equal(stval, STRET_RESULT));
503
504
505 // Test user-defined forward handler, manual forwarding, uncached but fixed-up
506
507 _objc_flush_caches(nil);
508
509 state = 11;
510 sp1 = getSP();
511 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);
512 sp2 = getSP();
513 testassert(sp1 == sp2);
514 testassert(state == 12);
515 testassert(idval == ID_RESULT);
516
517 state = 13;
518 sp1 = getSP();
519 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);
520 sp2 = getSP();
521 testassert(sp1 == sp2);
522 testassert(state == 14);
523 testassert(llval == LL_RESULT);
524
525 state = 15;
526 sp1 = getSP();
527 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);
528 sp2 = getSP();
529 testassert(sp1 == sp2);
530 testassert(state == 16);
531 testassert(fpval == FP_RESULT);
532
533 state = 17;
534 sp1 = getSP();
535 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);
536 sp2 = getSP();
537 testassert(sp1 == sp2);
538 testassert(state == 18);
539 testassert(stret_equal(stval, STRET_RESULT));
540
541
542 succeed(__FILE__);
543 }