]>
Commit | Line | Data |
---|---|---|
8972963c A |
1 | // TEST_CONFIG |
2 | ||
7af964d1 | 3 | #include "test.h" |
8972963c A |
4 | |
5 | #ifdef __cplusplus | |
6 | ||
7 | int 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 | ||
32 | static int state = 0; | |
33 | ||
7af964d1 A |
34 | |
35 | #define CHECK_ARGS(cls, sel) \ | |
36 | do { \ | |
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) \ |
70 | do { \ | |
71 | testassert(self == [cls class]); \ | |
72 | testassert(_cmd == sel_registerName(#sel "_noarg"));\ | |
73 | } while (0) | |
74 | ||
7af964d1 A |
75 | struct stret { |
76 | int a; | |
77 | int b; | |
78 | int c; | |
79 | int d; | |
80 | int e; | |
7af964d1 A |
81 | }; |
82 | ||
83 | BOOL 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 | ||
92 | id ID_RESULT = (id)0x12345678; | |
93 | long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__; | |
8972963c | 94 | struct stret STRET_RESULT = {1, 2, 3, 4, 5}; |
7af964d1 A |
95 | double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__; |
96 | long 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 | ||
420 | int 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 |