]> git.saurik.com Git - apple/objc4.git/blame - test/msgSend.m
objc4-493.11.tar.gz
[apple/objc4.git] / test / msgSend.m
CommitLineData
8972963c
A
1// TEST_CONFIG
2
7af964d1 3#include "test.h"
8972963c
A
4
5#ifdef __cplusplus
6
7int main()
8{
9 testwarn("c++ rdar://8366474 @selector(foo::)");
10 succeed(__FILE__);
11}
12
13#else
14
7af964d1
A
15#include <objc/objc.h>
16#include <objc/objc-runtime.h>
8972963c
A
17#include <objc/objc-abi.h>
18
19#if defined(__arm__)
20// rdar://8331406
21# define ALIGN_()
22#else
23# define ALIGN_() asm(".align 4");
24#endif
7af964d1
A
25
26@interface Super { id isa; }
27+class;
28@end
29
30@interface Sub : Super @end
31
32static int state = 0;
33
7af964d1
A
34
35#define CHECK_ARGS(cls, sel) \
36do { \
37 testassert(self == [cls class]); \
38 testassert(_cmd == sel_registerName(#sel "::::::::::::::::::::::::::::"));\
39 testassert(i1 == 1); \
40 testassert(i2 == 2); \
41 testassert(i3 == 3); \
42 testassert(i4 == 4); \
43 testassert(i5 == 5); \
44 testassert(i6 == 6); \
45 testassert(i7 == 7); \
46 testassert(i8 == 8); \
47 testassert(i9 == 9); \
48 testassert(i10 == 10); \
49 testassert(i11 == 11); \
50 testassert(i12 == 12); \
51 testassert(i13 == 13); \
52 testassert(f1 == 1.0); \
53 testassert(f2 == 2.0); \
54 testassert(f3 == 3.0); \
55 testassert(f4 == 4.0); \
56 testassert(f5 == 5.0); \
57 testassert(f6 == 6.0); \
58 testassert(f7 == 7.0); \
59 testassert(f8 == 8.0); \
60 testassert(f9 == 9.0); \
61 testassert(f10 == 10.0); \
62 testassert(f11 == 11.0); \
63 testassert(f12 == 12.0); \
64 testassert(f13 == 13.0); \
65 testassert(f14 == 14.0); \
66 testassert(f15 == 15.0); \
67} while (0)
68
8972963c
A
69#define CHECK_ARGS_NOARG(cls, sel) \
70do { \
71 testassert(self == [cls class]); \
72 testassert(_cmd == sel_registerName(#sel "_noarg"));\
73} while (0)
74
7af964d1
A
75struct stret {
76 int a;
77 int b;
78 int c;
79 int d;
80 int e;
7af964d1
A
81};
82
83BOOL stret_equal(struct stret a, struct stret b)
84{
85 return (a.a == b.a &&
86 a.b == b.b &&
87 a.c == b.c &&
88 a.d == b.d &&
89 a.e == b.e);
90}
91
92id ID_RESULT = (id)0x12345678;
93long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__;
8972963c 94struct stret STRET_RESULT = {1, 2, 3, 4, 5};
7af964d1
A
95double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__;
96long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__;
97
98
99@implementation Super
100+class { return self; }
8972963c 101+(struct stret)stret { return STRET_RESULT; }
7af964d1
A
102+(void)initialize { }
103
104+(id)idret:
105 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
106{
8972963c 107 if (state == 100) CHECK_ARGS(Sub, idret);
7af964d1
A
108 else CHECK_ARGS(Super, idret);
109 state = 1;
110 return ID_RESULT;
111}
112
113+(long long)llret:
114 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
115{
8972963c 116 if (state == 100) CHECK_ARGS(Sub, llret);
7af964d1
A
117 else CHECK_ARGS(Super, llret);
118 state = 2;
119 return LL_RESULT;
120}
121
122+(struct stret)stret:
123 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
124{
8972963c 125 if (state == 100) CHECK_ARGS(Sub, stret);
7af964d1
A
126 else CHECK_ARGS(Super, stret);
127 state = 3;
128 return STRET_RESULT;
129}
130
131+(double)fpret:
132 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
133{
8972963c 134 if (state == 100) CHECK_ARGS(Sub, fpret);
7af964d1
A
135 else CHECK_ARGS(Super, fpret);
136 state = 4;
137 return FP_RESULT;
138}
139
140+(long double)lfpret:
141 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
142{
8972963c 143 if (state == 100) CHECK_ARGS(Sub, lfpret);
7af964d1
A
144 else CHECK_ARGS(Super, lfpret);
145 state = 5;
146 return LFP_RESULT;
147}
148
149
8972963c
A
150+(id)idret_noarg
151{
152 if (state == 100) CHECK_ARGS_NOARG(Sub, idret);
153 else CHECK_ARGS_NOARG(Super, idret);
154 state = 11;
155 return ID_RESULT;
156}
157
158+(long long)llret_noarg
159{
160 if (state == 100) CHECK_ARGS_NOARG(Sub, llret);
161 else CHECK_ARGS_NOARG(Super, llret);
162 state = 12;
163 return LL_RESULT;
164}
165
166/* no objc_msgSend_stret_noarg
167+(struct stret)stret_noarg
168{
169 if (state == 100) CHECK_ARGS_NOARG(Sub, stret);
170 else CHECK_ARGS_NOARG(Super, stret);
171 state = 13;
172 return STRET_RESULT;
173}
174*/
175
176+(double)fpret_noarg
177{
178 if (state == 100) CHECK_ARGS_NOARG(Sub, fpret);
179 else CHECK_ARGS_NOARG(Super, fpret);
180 state = 14;
181 return FP_RESULT;
182}
183
184+(long double)lfpret_noarg
185{
186 if (state == 100) CHECK_ARGS_NOARG(Sub, lfpret);
187 else CHECK_ARGS_NOARG(Super, lfpret);
188 state = 15;
189 return LFP_RESULT;
190}
191
192
7af964d1
A
193-(id)idret:
194 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
195{
196 fail("-idret called instead of +idret");
197 CHECK_ARGS(Super, idret);
198}
199
200-(long long)llret:
201 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
202{
203 fail("-llret called instead of +llret");
204 CHECK_ARGS(Super, llret);
205}
206
207-(struct stret)stret:
208 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
209{
210 fail("-stret called instead of +stret");
211 CHECK_ARGS(Super, stret);
212}
213
214-(double)fpret:
215 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
216{
217 fail("-fpret called instead of +fpret");
218 CHECK_ARGS(Super, fpret);
219}
220
221-(long double)lfpret:
222 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
223{
224 fail("-lfpret called instead of +lfpret");
225 CHECK_ARGS(Super, lfpret);
226}
227
8972963c
A
228-(id)idret_noarg
229{
230 fail("-idret_ called instead of +idret_noarg");
231 CHECK_ARGS_NOARG(Super, idret);
232}
233
234-(long long)llret_noarg
235{
236 fail("-llret_noarg called instead of +llret_noarg");
237 CHECK_ARGS_NOARG(Super, llret);
238}
239
240-(struct stret)stret_noarg
241{
242 fail("-stret_noarg called instead of +stret_noarg");
243 CHECK_ARGS_NOARG(Super, stret);
244}
245
246-(double)fpret_noarg
247{
248 fail("-fpret_noarg called instead of +fpret_noarg");
249 CHECK_ARGS_NOARG(Super, fpret);
250}
251
252-(long double)lfpret_noarg
253{
254 fail("-lfpret_noarg called instead of +lfpret_noarg");
255 CHECK_ARGS_NOARG(Super, lfpret);
256}
257
7af964d1
A
258@end
259
260
261@implementation Sub
262
263+(id)idret:
264 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
265{
266 id result;
7af964d1 267 CHECK_ARGS(Sub, idret);
8972963c 268 state = 100;
7af964d1
A
269 result = [super idret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
270 testassert(state == 1);
271 testassert(result == ID_RESULT);
8972963c 272 state = 101;
7af964d1
A
273 return result;
274}
275
276+(long long)llret:
277 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
278{
279 long long result;
7af964d1 280 CHECK_ARGS(Sub, llret);
8972963c 281 state = 100;
7af964d1
A
282 result = [super llret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
283 testassert(state == 2);
284 testassert(result == LL_RESULT);
8972963c 285 state = 102;
7af964d1
A
286 return result;
287}
288
289+(struct stret)stret:
290 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
291{
292 struct stret result;
7af964d1 293 CHECK_ARGS(Sub, stret);
8972963c 294 state = 100;
7af964d1
A
295 result = [super stret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
296 testassert(state == 3);
297 testassert(stret_equal(result, STRET_RESULT));
8972963c 298 state = 103;
7af964d1
A
299 return result;
300}
301
302+(double)fpret:
303 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
304{
305 double result;
7af964d1 306 CHECK_ARGS(Sub, fpret);
8972963c 307 state = 100;
7af964d1
A
308 result = [super fpret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
309 testassert(state == 4);
310 testassert(result == FP_RESULT);
8972963c 311 state = 104;
7af964d1
A
312 return result;
313}
314
315+(long double)lfpret:
316 (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)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
317{
318 long double result;
7af964d1 319 CHECK_ARGS(Sub, lfpret);
8972963c 320 state = 100;
7af964d1
A
321 result = [super lfpret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15];
322 testassert(state == 5);
323 testassert(result == LFP_RESULT);
8972963c
A
324 state = 105;
325 return result;
326}
327
328
329+(id)idret_noarg
330{
331 id result;
332 CHECK_ARGS_NOARG(Sub, idret);
333 state = 100;
334 result = [super idret_noarg];
335 testassert(state == 11);
336 testassert(result == ID_RESULT);
337 state = 111;
338 return result;
339}
340
341+(long long)llret_noarg
342{
343 long long result;
344 CHECK_ARGS_NOARG(Sub, llret);
345 state = 100;
346 result = [super llret_noarg];
347 testassert(state == 12);
348 testassert(result == LL_RESULT);
349 state = 112;
350 return result;
351}
352/*
353+(struct stret)stret_noarg
354{
355 struct stret result;
356 CHECK_ARGS_NOARG(Sub, stret);
357 state = 100;
358 result = [super stret_noarg];
359 testassert(state == 13);
360 testassert(stret_equal(result, STRET_RESULT));
361 state = 113;
362 return result;
363}
364*/
365+(double)fpret_noarg
366{
367 double result;
368 CHECK_ARGS_NOARG(Sub, fpret);
369 state = 100;
370 result = [super fpret_noarg];
371 testassert(state == 14);
372 testassert(result == FP_RESULT);
373 state = 114;
374 return result;
375}
376
377+(long double)lfpret_noarg
378{
379 long double result;
380 CHECK_ARGS_NOARG(Sub, lfpret);
381 state = 100;
382 result = [super lfpret_noarg];
383 testassert(state == 15);
384 testassert(result == LFP_RESULT);
385 state = 115;
7af964d1
A
386 return result;
387}
388
389
390
391// performance-test code (do nothing for better comparability)
392
393+(id)idret_perf
394{
395 return ID_RESULT;
396}
397
398+(long long)llret_perf
399{
400 return LL_RESULT;
401}
402
403+(struct stret)stret_perf
404{
405 return STRET_RESULT;
406}
407
408+(double)fpret_perf
409{
410 return FP_RESULT;
411}
412
413+(long double)lfpret_perf
414{
415 return LFP_RESULT;
416}
417@end
418
419
420int main()
421{
422 int i;
423
424 id idval;
425 long long llval;
426 struct stret stretval;
427 double fpval;
428 long double lfpval;
429
430 uint64_t startTime;
431 uint64_t totalTime;
432 uint64_t targetTime;
433
434 Method idmethod;
435 Method llmethod;
436 Method stretmethod;
437 Method fpmethod;
438 Method lfpmethod;
439
440 id (*idfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
441 long long (*llfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
442 struct stret (*stretfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
443 double (*fpfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
444 long double (*lfpfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double);
445
8972963c
A
446 id (*idmsg)(id, SEL, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
447 long long (*llmsg)(id, SEL, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
448 struct stret (*stretmsg)(id, SEL, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
449 double (*fpmsg)(id, SEL, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
450 long double (*lfpmsg)(id, SEL, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) __attribute__((unused));
7af964d1 451
8972963c
A
452 id (*idmsg0)(id, SEL) __attribute__((unused));
453 long long (*llmsg0)(id, SEL) __attribute__((unused));
454 // struct stret (*stretmsg0)(id, SEL) __attribute__((unused));
455 double (*fpmsg0)(id, SEL) __attribute__((unused));
456 long double (*lfpmsg0)(id, SEL) __attribute__((unused));
7af964d1 457
8972963c 458 struct stret zero = {0, 0, 0, 0, 0};
7af964d1 459
8972963c
A
460 // get +initialize out of the way
461 [Sub class];
7af964d1
A
462
463 // message uncached
464 // message uncached long long
465 // message uncached stret
466 // message uncached fpret
467 // message uncached fpret long double
8972963c 468 // message uncached noarg (as above)
7af964d1
A
469 // message cached
470 // message cached long long
471 // message cached stret
472 // message cached fpret
473 // message cached fpret long double
8972963c 474 // message cached noarg (as above)
7af964d1 475 // fixme verify that uncached lookup didn't happen the 2nd time?
8972963c 476 // Do this first before anything below caches stuff.
7af964d1
A
477 for (i = 0; i < 5; i++) {
478 state = 0;
479 idval = nil;
480 idval = [Sub idret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
8972963c 481 testassert(state == 101);
7af964d1
A
482 testassert(idval == ID_RESULT);
483
484 llval = 0;
485 llval = [Sub llret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
8972963c 486 testassert(state == 102);
7af964d1
A
487 testassert(llval == LL_RESULT);
488
489 stretval = zero;
490 stretval = [Sub stret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
8972963c 491 testassert(state == 103);
7af964d1
A
492 testassert(stret_equal(stretval, STRET_RESULT));
493
494 fpval = 0;
495 fpval = [Sub fpret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
8972963c 496 testassert(state == 104);
7af964d1
A
497 testassert(fpval == FP_RESULT);
498
499 lfpval = 0;
500 lfpval = [Sub lfpret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0];
8972963c 501 testassert(state == 105);
7af964d1 502 testassert(lfpval == LFP_RESULT);
8972963c
A
503
504#if __OBJC2__
505 // explicitly call noarg messenger, even if compiler doesn't emit it
506 state = 0;
507 idval = nil;
508 idval = ((typeof(idmsg0))objc_msgSend_noarg)([Sub class], @selector(idret_noarg));
509 testassert(state == 111);
510 testassert(idval == ID_RESULT);
511
512 llval = 0;
513 llval = ((typeof(llmsg0))objc_msgSend_noarg)([Sub class], @selector(llret_noarg));
514 testassert(state == 112);
515 testassert(llval == LL_RESULT);
516 /*
517 stretval = zero;
518 stretval = ((typeof(stretmsg0))objc_msgSend_stret_noarg)([Sub class], @selector(stret_noarg));
519 stretval = [Sub 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];
520 testassert(state == 113);
521 testassert(stret_equal(stretval, STRET_RESULT));
522 */
523# if !__i386__
524 fpval = 0;
525 fpval = ((typeof(fpmsg0))objc_msgSend_noarg)([Sub class], @selector(fpret_noarg));
526 testassert(state == 114);
527 testassert(fpval == FP_RESULT);
528# endif
529# if !__i386__ && !__x86_64__
530 lfpval = 0;
531 lfpval = ((typeof(lfpmsg0))objc_msgSend_noarg)([Sub class], @selector(lfpret_noarg));
532 testassert(state == 115);
533 testassert(lfpval == LFP_RESULT);
534# endif
535#endif
7af964d1
A
536 }
537
8972963c
A
538 idmethod = class_getClassMethod([Super class], @selector(idret::::::::::::::::::::::::::::));
539 testassert(idmethod);
540 llmethod = class_getClassMethod([Super class], @selector(llret::::::::::::::::::::::::::::));
541 testassert(llmethod);
542 stretmethod = class_getClassMethod([Super class], @selector(stret::::::::::::::::::::::::::::));
543 testassert(stretmethod);
544 fpmethod = class_getClassMethod([Super class], @selector(fpret::::::::::::::::::::::::::::));
545 testassert(fpmethod);
546 lfpmethod = class_getClassMethod([Super class], @selector(lfpret::::::::::::::::::::::::::::));
547 testassert(lfpmethod);
548
549 idfn = (id (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
550 llfn = (long long (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
551 stretfn = (struct stret (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke_stret;
552 fpfn = (double (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
553 lfpfn = (long double (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke;
554
7af964d1
A
555 // cached message performance
556 // catches failure to cache or (abi=2) failure to fixup (#5584187)
557 // fixme unless they all fail
558 // `.align 4` matches loop alignment to make -O0 work
8972963c 559 // fill cache first
7af964d1 560 [Sub idret_perf];
8972963c
A
561 [Sub llret_perf];
562 [Sub stret_perf];
563 [Sub fpret_perf];
564 [Sub lfpret_perf];
565 [Sub idret_perf];
566 [Sub llret_perf];
567 [Sub stret_perf];
568 [Sub fpret_perf];
569 [Sub lfpret_perf];
570 [Sub idret_perf];
571 [Sub llret_perf];
572 [Sub stret_perf];
573 [Sub fpret_perf];
574 [Sub lfpret_perf];
575
576 // Some of these times have high variance on some compilers.
577 // The errors we're trying to catch should be catastrophically slow,
578 // so the margins here are generous to avoid false failures.
579
580#define COUNT 1000000
7af964d1 581 startTime = mach_absolute_time();
8972963c 582 ALIGN_();
7af964d1
A
583 for (i = 0; i < COUNT; i++) {
584 [Sub idret_perf];
585 }
586 totalTime = mach_absolute_time() - startTime;
8972963c 587 testprintf("time: idret %llu\n", totalTime);
7af964d1
A
588 targetTime = totalTime;
589
7af964d1 590 startTime = mach_absolute_time();
8972963c 591 ALIGN_();
7af964d1
A
592 for (i = 0; i < COUNT; i++) {
593 [Sub llret_perf];
594 }
595 totalTime = mach_absolute_time() - startTime;
8972963c
A
596 timecheck("llret ", totalTime, targetTime * 0.8, targetTime * 2.0);
597
7af964d1 598 startTime = mach_absolute_time();
8972963c 599 ALIGN_();
7af964d1
A
600 for (i = 0; i < COUNT; i++) {
601 [Sub stret_perf];
602 }
603 totalTime = mach_absolute_time() - startTime;
8972963c 604 timecheck("stret ", totalTime, targetTime * 0.8, targetTime * 5.0);
7af964d1 605
7af964d1 606 startTime = mach_absolute_time();
8972963c 607 ALIGN_();
7af964d1
A
608 for (i = 0; i < COUNT; i++) {
609 [Sub fpret_perf];
610 }
611 totalTime = mach_absolute_time() - startTime;
8972963c 612 timecheck("fpret ", totalTime, targetTime * 0.8, targetTime * 4.0);
7af964d1 613
7af964d1 614 startTime = mach_absolute_time();
8972963c 615 ALIGN_();
7af964d1
A
616 for (i = 0; i < COUNT; i++) {
617 [Sub lfpret_perf];
618 }
619 totalTime = mach_absolute_time() - startTime;
8972963c 620 timecheck("lfpret", totalTime, targetTime * 0.8, targetTime * 4.0);
7af964d1
A
621#undef COUNT
622
623 // method_invoke
624 // method_invoke long long
625 // method_invoke_stret stret
626 // method_invoke_stret fpret
627 // method_invoke fpret long double
628
629 state = 0;
630 idval = nil;
631 idval = (*idfn)([Super class], idmethod, 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);
632 testassert(state == 1);
633 testassert(idval == ID_RESULT);
634
635 llval = 0;
636 llval = (*llfn)([Super class], llmethod, 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);
637 testassert(state == 2);
638 testassert(llval == LL_RESULT);
639
640 stretval = zero;
641 stretval = (*stretfn)([Super class], stretmethod, 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);
642 testassert(state == 3);
643 testassert(stret_equal(stretval, STRET_RESULT));
644
645 fpval = 0;
646 fpval = (*fpfn)([Super class], fpmethod, 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);
647 testassert(state == 4);
648 testassert(fpval == FP_RESULT);
649
650 lfpval = 0;
651 lfpval = (*lfpfn)([Super class], lfpmethod, 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(state == 5);
653 testassert(lfpval == LFP_RESULT);
654
655
656 // message to nil
657 // message to nil long long
658 // message to nil stret
659 // message to nil fpret
660 // message to nil fpret long double
661 state = 0;
662 idval = ID_RESULT;
663 idval = [(id)nil 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];
664 testassert(state == 0);
665 testassert(idval == nil);
666
667 state = 0;
668 llval = LL_RESULT;
669 llval = [(id)nil 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];
670 testassert(state == 0);
671 testassert(llval == 0LL);
672
673 state = 0;
674 stretval = zero;
675 stretval = [(id)nil 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];
676 testassert(state == 0);
677 // no stret result guarantee
678
679 state = 0;
680 fpval = FP_RESULT;
681 fpval = [(id)nil 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];
682 testassert(state == 0);
683 testassert(fpval == 0.0);
684
685 state = 0;
686 lfpval = LFP_RESULT;
687 lfpval = [(id)nil lfpret :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];
688 testassert(state == 0);
689 testassert(lfpval == 0.0);
8972963c
A
690
691#if __OBCJ2__
692 // message to nil noarg
693 // explicitly call noarg messenger, even if compiler doesn't emit it
694 state = 0;
695 idval = ID_RESULT;
696 idval = ((typeof(idmsg0))objc_msgSend_noarg)(nil, @selector(idret_noarg));
697 testassert(state == 0);
698 testassert(idval == nil);
7af964d1 699
8972963c
A
700 state = 0;
701 llval = LL_RESULT;
702 llval = ((typeof(llmsg0))objc_msgSend_noarg)(nil, @selector(llret_noarg));
703 testassert(state == 0);
704 testassert(llval == 0LL);
705 /*
706 state = 0;
707 stretval = zero;
708 stretval = [(id)nil 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];
709 testassert(state == 0);
710 // no stret result guarantee
711 */
712# if !__i386__
713 state = 0;
714 fpval = FP_RESULT;
715 fpval = ((typeof(fpmsg0))objc_msgSend_noarg)(nil, @selector(fpret_noarg));
716 testassert(state == 0);
717 testassert(fpval == 0.0);
718# endif
719# if !__i386__ && !__x86_64__
720 state = 0;
721 lfpval = LFP_RESULT;
722 lfpval = ((typeof(lfpmsg0))objc_msgSend_noarg)(nil, @selector(lfpret_noarg));
723 testassert(state == 0);
724 testassert(lfpval == 0.0);
725# endif
726#endif
7af964d1
A
727
728 // message forwarded
729 // message forwarded long long
730 // message forwarded stret
731 // message forwarded fpret
732 // message forwarded fpret long double
733 // fixme
734
8972963c
A
735#if __OBJC2__
736 // rdar://8271364 objc_msgSendSuper2 must not change objc_super
737 struct objc_super sup = {
738 [Sub class],
739 object_getClass([Sub class]),
740 };
741
742 state = 100;
743 idval = nil;
744 idval = ((id(*)(struct objc_super *, SEL, int,int,int,int,int,int,int,int,int,int,int,int,int, double,double,double,double,double,double,double,double,double,double,double,double,double,double,double))objc_msgSendSuper2) (&sup, @selector(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);
745 testassert(state == 1);
746 testassert(idval == ID_RESULT);
747 testassert(sup.receiver == [Sub class]);
748 testassert(sup.super_class == object_getClass([Sub class]));
749
750 state = 100;
751 stretval = zero;
752 stretval = ((struct stret(*)(struct objc_super *, SEL, int,int,int,int,int,int,int,int,int,int,int,int,int, double,double,double,double,double,double,double,double,double,double,double,double,double,double,double))objc_msgSendSuper2_stret) (&sup, @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);
753 testassert(state == 3);
754 testassert(stret_equal(stretval, STRET_RESULT));
755 testassert(sup.receiver == [Sub class]);
756 testassert(sup.super_class == object_getClass([Sub class]));
757#endif
758
759#if __OBJC2__
760 // Debug messengers.
761 state = 0;
762 idmsg = (typeof(idmsg))objc_msgSend_debug;
763 idval = nil;
764 idval = (*idmsg)([Sub class], @selector(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);
765 testassert(state == 101);
766 testassert(idval == ID_RESULT);
767
768 state = 0;
769 llmsg = (typeof(llmsg))objc_msgSend_debug;
770 llval = 0;
771 llval = (*llmsg)([Sub class], @selector(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);
772 testassert(state == 102);
773 testassert(llval == LL_RESULT);
774
775 state = 0;
776 stretmsg = (typeof(stretmsg))objc_msgSend_stret_debug;
777 stretval = zero;
778 stretval = (*stretmsg)([Sub 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);
779 testassert(state == 103);
780 testassert(stret_equal(stretval, STRET_RESULT));
781
782 state = 100;
783 sup.receiver = [Sub class];
784 sup.super_class = object_getClass([Sub class]);
785 idmsg = (typeof(idmsg))objc_msgSendSuper2_debug;
786 idval = nil;
787 idval = (*idmsg)((id)&sup, @selector(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);
788 testassert(state == 1);
789 testassert(idval == ID_RESULT);
790
791 state = 100;
792 sup.receiver = [Sub class];
793 sup.super_class = object_getClass([Sub class]);
794 stretmsg = (typeof(stretmsg))objc_msgSendSuper2_stret_debug;
795 stretval = zero;
796 stretval = (*stretmsg)((id)&sup, @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);
797 testassert(state == 3);
798 testassert(stret_equal(stretval, STRET_RESULT));
799
800#if __i386__
801 state = 0;
802 fpmsg = (typeof(fpmsg))objc_msgSend_fpret_debug;
803 fpval = 0;
804 fpval = (*fpmsg)([Sub class], @selector(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);
805 testassert(state == 104);
806 testassert(fpval == FP_RESULT);
807#endif
808#if __x86_64__
809 state = 0;
810 lfpmsg = (typeof(lfpmsg))objc_msgSend_fpret_debug;
811 lfpval = 0;
812 lfpval = (*lfpmsg)([Sub class], @selector(lfpret::::::::::::::::::::::::::::), 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);
813 testassert(state == 105);
814 testassert(lfpval == LFP_RESULT);
815
816 // fixme fp2ret
817#endif
818
819// debug messengers
820#endif
821
7af964d1
A
822 succeed(__FILE__);
823}
8972963c
A
824
825#endif