1 | // Some convenient things to return: |
2 | static char *g_first_pointer = "I am the first" ; |
3 | static char *g_second_pointer = "I am the second" ; |
4 | |
5 | // First we have some simple functions that return standard types, ints, floats and doubles. |
6 | // We have a function calling a function in a few cases to test that if you stop in the |
7 | // inner function then do "up/fin" you get the return value from the outer-most frame. |
8 | |
9 | int |
10 | inner_sint (int value) |
11 | { |
12 | return value; |
13 | } |
14 | |
15 | int |
16 | outer_sint (int value) |
17 | { |
18 | int outer_value = 2 * inner_sint (value); |
19 | return outer_value; |
20 | } |
21 | |
22 | float |
23 | inner_float (float value) |
24 | { |
25 | return value; |
26 | } |
27 | |
28 | float |
29 | outer_float (float value) |
30 | { |
31 | float outer_value = 2 * inner_float(value); |
32 | return outer_value; |
33 | } |
34 | |
35 | double |
36 | return_double (double value) |
37 | { |
38 | return value; |
39 | } |
40 | |
41 | long double |
42 | return_long_double (long double value) |
43 | { |
44 | return value; |
45 | } |
46 | |
47 | char * |
48 | return_pointer (char *value) |
49 | { |
50 | return value; |
51 | } |
52 | |
53 | struct one_int |
54 | { |
55 | int one_field; |
56 | }; |
57 | |
58 | struct one_int |
59 | return_one_int (struct one_int value) |
60 | { |
61 | return value; |
62 | } |
63 | |
64 | struct two_int |
65 | { |
66 | int first_field; |
67 | int second_field; |
68 | }; |
69 | |
70 | struct two_int |
71 | return_two_int (struct two_int value) |
72 | { |
73 | return value; |
74 | } |
75 | |
76 | struct three_int |
77 | { |
78 | int first_field; |
79 | int second_field; |
80 | int third_field; |
81 | }; |
82 | |
83 | struct three_int |
84 | return_three_int (struct three_int value) |
85 | { |
86 | return value; |
87 | } |
88 | |
89 | struct four_int |
90 | { |
91 | int first_field; |
92 | int second_field; |
93 | int third_field; |
94 | int fourth_field; |
95 | }; |
96 | |
97 | struct four_int |
98 | return_four_int (struct four_int value) |
99 | { |
100 | return value; |
101 | } |
102 | |
103 | struct five_int |
104 | { |
105 | int first_field; |
106 | int second_field; |
107 | int third_field; |
108 | int fourth_field; |
109 | int fifth_field; |
110 | }; |
111 | |
112 | struct five_int |
113 | return_five_int (struct five_int value) |
114 | { |
115 | return value; |
116 | } |
117 | |
118 | struct one_int_one_double |
119 | { |
120 | int first_field; |
121 | double second_field; |
122 | }; |
123 | |
124 | struct one_int_one_double |
125 | return_one_int_one_double (struct one_int_one_double value) |
126 | { |
127 | return value; |
128 | } |
129 | |
130 | struct one_int_one_double_one_int |
131 | { |
132 | int one_field; |
133 | double second_field; |
134 | int third_field; |
135 | }; |
136 | |
137 | struct one_int_one_double_one_int |
138 | return_one_int_one_double_one_int (struct one_int_one_double_one_int value) |
139 | { |
140 | return value; |
141 | } |
142 | |
143 | struct one_short_one_double_one_short |
144 | { |
145 | int one_field; |
146 | double second_field; |
147 | int third_field; |
148 | }; |
149 | |
150 | struct one_short_one_double_one_short |
151 | return_one_short_one_double_one_short (struct one_short_one_double_one_short value) |
152 | { |
153 | return value; |
154 | } |
155 | |
156 | struct three_short_one_float |
157 | { |
158 | short one_field; |
159 | short second_field; |
160 | short third_field; |
161 | float fourth_field; |
162 | }; |
163 | |
164 | struct three_short_one_float |
165 | return_three_short_one_float (struct three_short_one_float value) |
166 | { |
167 | return value; |
168 | } |
169 | |
170 | struct one_int_one_float_one_int |
171 | { |
172 | int one_field; |
173 | float second_field; |
174 | int third_field; |
175 | }; |
176 | |
177 | struct one_int_one_float_one_int |
178 | return_one_int_one_float_one_int (struct one_int_one_float_one_int value) |
179 | { |
180 | return value; |
181 | } |
182 | |
183 | struct one_float_one_int_one_float |
184 | { |
185 | float one_field; |
186 | int second_field; |
187 | float third_field; |
188 | }; |
189 | |
190 | struct one_float_one_int_one_float |
191 | return_one_float_one_int_one_float (struct one_float_one_int_one_float value) |
192 | { |
193 | return value; |
194 | } |
195 | |
196 | struct one_double_two_float |
197 | { |
198 | double one_field; |
199 | float second_field; |
200 | float third_field; |
201 | }; |
202 | |
203 | struct one_double_two_float |
204 | return_one_double_two_float (struct one_double_two_float value) |
205 | { |
206 | return value; |
207 | } |
208 | |
209 | struct two_double |
210 | { |
211 | double first_field; |
212 | double second_field; |
213 | }; |
214 | |
215 | struct two_double |
216 | return_two_double (struct two_double value) |
217 | { |
218 | return value; |
219 | } |
220 | |
221 | struct two_float |
222 | { |
223 | float first_field; |
224 | float second_field; |
225 | }; |
226 | |
227 | struct two_float |
228 | return_two_float (struct two_float value) |
229 | { |
230 | return value; |
231 | } |
232 | |
233 | struct one_int_one_double_packed |
234 | { |
235 | int first_field; |
236 | double second_field; |
237 | } __attribute__((__packed__)); |
238 | |
239 | struct one_int_one_double_packed |
240 | return_one_int_one_double_packed (struct one_int_one_double_packed value) |
241 | { |
242 | return value; |
243 | } |
244 | |
245 | struct one_int_one_long |
246 | { |
247 | int first_field; |
248 | long second_field; |
249 | }; |
250 | |
251 | struct one_int_one_long |
252 | return_one_int_one_long (struct one_int_one_long value) |
253 | { |
254 | return value; |
255 | } |
256 | |
257 | struct one_pointer |
258 | { |
259 | char *first_field; |
260 | }; |
261 | |
262 | struct one_pointer |
263 | return_one_pointer (struct one_pointer value) |
264 | { |
265 | return value; |
266 | } |
267 | |
268 | struct two_pointer |
269 | { |
270 | char *first_field; |
271 | char *second_field; |
272 | }; |
273 | |
274 | struct two_pointer |
275 | return_two_pointer (struct two_pointer value) |
276 | { |
277 | return value; |
278 | } |
279 | |
280 | struct one_float_one_pointer |
281 | { |
282 | float first_field; |
283 | char *second_field; |
284 | }; |
285 | |
286 | struct one_float_one_pointer |
287 | return_one_float_one_pointer (struct one_float_one_pointer value) |
288 | { |
289 | return value; |
290 | } |
291 | |
292 | struct one_int_one_pointer |
293 | { |
294 | int first_field; |
295 | char *second_field; |
296 | }; |
297 | |
298 | struct one_int_one_pointer |
299 | return_one_int_one_pointer (struct one_int_one_pointer value) |
300 | { |
301 | return value; |
302 | } |
303 | |
304 | struct base_one_char { |
305 | char c; |
306 | }; |
307 | |
308 | struct nested_one_float_three_base { |
309 | float f; |
310 | struct base_one_char b1; |
311 | struct base_one_char b2; |
312 | struct base_one_char b3; |
313 | }; // returned in RAX for both SysV and Windows |
314 | |
315 | struct nested_one_float_three_base |
316 | return_nested_one_float_three_base (struct nested_one_float_three_base value) |
317 | { |
318 | return value; |
319 | } |
320 | |
321 | struct double_nested_one_float_one_nested { |
322 | float f; |
323 | struct nested_one_float_three_base ns; |
324 | }; // SysV-ABI: returned in XMM0 + RAX |
325 | // Windows-ABI: returned in memory |
326 | |
327 | struct double_nested_one_float_one_nested |
328 | return_double_nested_one_float_one_nested(struct double_nested_one_float_one_nested value) |
329 | { |
330 | return value; |
331 | } |
332 | |
333 | struct base_float_struct { |
334 | float f1; |
335 | float f2; |
336 | }; |
337 | |
338 | struct nested_float_struct { |
339 | double d; |
340 | struct base_float_struct bfs; |
341 | }; // SysV-ABI: return in xmm0 + xmm1 |
342 | // Windows-ABI: returned in memory |
343 | |
344 | struct nested_float_struct |
345 | return_nested_float_struct (struct nested_float_struct value) |
346 | { |
347 | return value; |
348 | } |
349 | |
350 | struct six_double_three_int { |
351 | double d1; // 8 |
352 | double d2; // 8 |
353 | int i1; // 4 |
354 | double d3; // 8 |
355 | double d4; // 8 |
356 | int i2; // 4 |
357 | double d5; // 8 |
358 | double d6; // 8 |
359 | int i3; // 4 |
360 | }; // returned in memeory on both SysV and Windows |
361 | |
362 | struct six_double_three_int |
363 | return_six_double_three_int (struct six_double_three_int value) { |
364 | return value; |
365 | } |
366 | |
367 | typedef float vector_size_float32_8 __attribute__((__vector_size__(8))); |
368 | typedef float vector_size_float32_16 __attribute__((__vector_size__(16))); |
369 | typedef float vector_size_float32_32 __attribute__((__vector_size__(32))); |
370 | |
371 | typedef float ext_vector_size_float32_2 __attribute__((ext_vector_type(2))); |
372 | typedef float ext_vector_size_float32_4 __attribute__((ext_vector_type(4))); |
373 | typedef float ext_vector_size_float32_8 __attribute__((ext_vector_type(8))); |
374 | |
375 | vector_size_float32_8 |
376 | return_vector_size_float32_8 (vector_size_float32_8 value) |
377 | { |
378 | return value; |
379 | } |
380 | |
381 | vector_size_float32_16 |
382 | return_vector_size_float32_16 (vector_size_float32_16 value) |
383 | { |
384 | return value; |
385 | } |
386 | |
387 | vector_size_float32_32 |
388 | return_vector_size_float32_32 (vector_size_float32_32 value) |
389 | { |
390 | return value; |
391 | } |
392 | |
393 | ext_vector_size_float32_2 |
394 | return_ext_vector_size_float32_2 (ext_vector_size_float32_2 value) |
395 | { |
396 | return value; |
397 | } |
398 | |
399 | ext_vector_size_float32_4 |
400 | return_ext_vector_size_float32_4 (ext_vector_size_float32_4 value) |
401 | { |
402 | return value; |
403 | } |
404 | |
405 | ext_vector_size_float32_8 |
406 | return_ext_vector_size_float32_8 (ext_vector_size_float32_8 value) |
407 | { |
408 | return value; |
409 | } |
410 | |
411 | class base_class_one_char { |
412 | public: |
413 | char c = '!'; |
414 | }; // returned in RAX for both ABI |
415 | |
416 | base_class_one_char |
417 | return_base_class_one_char(base_class_one_char value) { |
418 | return value; |
419 | } |
420 | |
421 | class nested_class_float_and_base { |
422 | public: |
423 | float f = 0.1; |
424 | base_class_one_char b; |
425 | }; // returned in RAX for both ABI |
426 | |
427 | nested_class_float_and_base |
428 | return_nested_class_float_and_base(nested_class_float_and_base value) { |
429 | return value; |
430 | } |
431 | |
432 | class double_nested_class_float_and_nested { |
433 | public: |
434 | float f = 0.2; |
435 | nested_class_float_and_base n; |
436 | }; // SysV-ABI: returned in XMM0 + RAX |
437 | // Windows-ABI: returned in memory |
438 | |
439 | double_nested_class_float_and_nested |
440 | return_double_nested_class_float_and_nested( |
441 | double_nested_class_float_and_nested value) { |
442 | return value; |
443 | } |
444 | |
445 | class base_class { |
446 | public: |
447 | base_class() { |
448 | c = 'a'; |
449 | c2 = 'b'; |
450 | } |
451 | private: |
452 | char c; |
453 | protected: |
454 | char c2; |
455 | }; // returned in RAX for both ABI |
456 | |
457 | base_class |
458 | return_base_class(base_class value) { |
459 | return value; |
460 | } |
461 | |
462 | class sub_class : base_class { |
463 | public: |
464 | sub_class() { |
465 | c2 = '&'; |
466 | i = 10; |
467 | } |
468 | private: |
469 | int i; |
470 | }; // size 8; should be returned in RAX |
471 | // Since it's in register, lldb won't be able to get the |
472 | // fields in base class, expected to fail. |
473 | |
474 | sub_class |
475 | return_sub_class(sub_class value) { |
476 | return value; |
477 | } |
478 | |
479 | class abstract_class { |
480 | public: |
481 | virtual char getChar() = 0; |
482 | private: |
483 | int i = 8; |
484 | protected: |
485 | char c = '!'; |
486 | }; |
487 | |
488 | class derived_class : abstract_class { |
489 | public: |
490 | derived_class() { |
491 | c = '?'; |
492 | } |
493 | char getChar() { |
494 | return this->c; |
495 | } |
496 | private: |
497 | char c2 = '$'; |
498 | }; // size: 16; contains non POD member, returned in memory |
499 | |
500 | derived_class |
501 | return_derived_class(derived_class value) { |
502 | return value; |
503 | } |
504 | |
505 | int |
506 | main () |
507 | { |
508 | int first_int = 123456; |
509 | int second_int = 234567; |
510 | |
511 | outer_sint (value: first_int); |
512 | outer_sint (value: second_int); |
513 | |
514 | float first_float_value = 12.34; |
515 | float second_float_value = 23.45; |
516 | |
517 | outer_float (value: first_float_value); |
518 | outer_float (value: second_float_value); |
519 | |
520 | double double_value = -23.45; |
521 | |
522 | return_double (value: double_value); |
523 | |
524 | return_pointer(value: g_first_pointer); |
525 | |
526 | long double long_double_value = -3456789.987654321; |
527 | |
528 | return_long_double (value: long_double_value); |
529 | |
530 | // Okay, now the structures: |
531 | return_one_int (value: (struct one_int) {.one_field: 10}); |
532 | return_two_int (value: (struct two_int) {.first_field: 10, .second_field: 20}); |
533 | return_three_int (value: (struct three_int) {.first_field: 10, .second_field: 20, .third_field: 30}); |
534 | return_four_int (value: (struct four_int) {.first_field: 10, .second_field: 20, .third_field: 30, .fourth_field: 40}); |
535 | return_five_int (value: (struct five_int) {.first_field: 10, .second_field: 20, .third_field: 30, .fourth_field: 40, .fifth_field: 50}); |
536 | |
537 | return_two_double (value: (struct two_double) {.first_field: 10.0, .second_field: 20.0}); |
538 | return_one_double_two_float (value: (struct one_double_two_float) {.one_field: 10.0, .second_field: 20.0, .third_field: 30.0}); |
539 | return_one_int_one_float_one_int (value: (struct one_int_one_float_one_int) {.one_field: 10, .second_field: 20.0, .third_field: 30}); |
540 | |
541 | return_one_pointer (value: (struct one_pointer) {.first_field: g_first_pointer}); |
542 | return_two_pointer (value: (struct two_pointer) {.first_field: g_first_pointer, .second_field: g_second_pointer}); |
543 | return_one_float_one_pointer (value: (struct one_float_one_pointer) {.first_field: 10.0, .second_field: g_first_pointer}); |
544 | return_one_int_one_pointer (value: (struct one_int_one_pointer) {.first_field: 10, .second_field: g_first_pointer}); |
545 | return_three_short_one_float (value: (struct three_short_one_float) {.one_field: 10, .second_field: 20, .third_field: 30, .fourth_field: 40.0}); |
546 | |
547 | return_one_int_one_double (value: (struct one_int_one_double) {.first_field: 10, .second_field: 20.0}); |
548 | return_one_int_one_double_one_int (value: (struct one_int_one_double_one_int) {.one_field: 10, .second_field: 20.0, .third_field: 30}); |
549 | return_one_short_one_double_one_short (value: (struct one_short_one_double_one_short) {.one_field: 10, .second_field: 20.0, .third_field: 30}); |
550 | return_one_float_one_int_one_float (value: (struct one_float_one_int_one_float) {.one_field: 10.0, .second_field: 20, .third_field: 30.0}); |
551 | return_two_float (value: (struct two_float) { .first_field: 10.0, .second_field: 20.0}); |
552 | return_one_int_one_double_packed (value: (struct one_int_one_double_packed) {.first_field: 10, .second_field: 20.0}); |
553 | return_one_int_one_long (value: (struct one_int_one_long) {.first_field: 10, .second_field: 20}); |
554 | |
555 | return_nested_one_float_three_base(value: (struct nested_one_float_three_base) { |
556 | .f: 10.0, |
557 | .b1: (struct base_one_char) { |
558 | .c: 'x' |
559 | }, |
560 | .b2: (struct base_one_char) { |
561 | .c: 'y' |
562 | }, |
563 | .b3: (struct base_one_char) { |
564 | .c: 'z' |
565 | } |
566 | }); |
567 | return_double_nested_one_float_one_nested(value: (struct double_nested_one_float_one_nested) { |
568 | .f: 10.0, |
569 | .ns: (struct nested_one_float_three_base) { |
570 | .f: 20.0, |
571 | .b1: (struct base_one_char) { |
572 | .c: 'x' |
573 | }, |
574 | .b2: (struct base_one_char) { |
575 | .c: 'y' |
576 | }, |
577 | .b3: (struct base_one_char) { |
578 | .c: 'z' |
579 | } |
580 | }}); |
581 | return_nested_float_struct(value: (struct nested_float_struct) { |
582 | .d: 10.0, |
583 | .bfs: (struct base_float_struct) { |
584 | .f1: 20.0, |
585 | .f2: 30.0 |
586 | }}); |
587 | return_six_double_three_int(value: (struct six_double_three_int) { |
588 | .d1: 10.0, .d2: 20.0, .i1: 1, .d3: 30.0, .d4: 40.0, .i2: 2, .d5: 50.0, .d6: 60.0, .i3: 3}); |
589 | |
590 | return_base_class_one_char(value: base_class_one_char()); |
591 | return_nested_class_float_and_base(value: nested_class_float_and_base()); |
592 | return_double_nested_class_float_and_nested(value: double_nested_class_float_and_nested()); |
593 | return_base_class(value: base_class()); |
594 | // this is expected to fail |
595 | return_sub_class(value: sub_class()); |
596 | return_derived_class(value: derived_class()); |
597 | |
598 | return_vector_size_float32_8 (value: ( vector_size_float32_8 ){1.5, 2.25}); |
599 | return_vector_size_float32_16 (value: ( vector_size_float32_16 ){1.5, 2.25, 4.125, 8.0625}); |
600 | return_vector_size_float32_32 (value: ( vector_size_float32_32 ){1.5, 2.25, 4.125, 8.0625, 7.89, 8.52, 6.31, 9.12}); |
601 | |
602 | return_ext_vector_size_float32_2 (value: (ext_vector_size_float32_2){ 16.5, 32.25}); |
603 | return_ext_vector_size_float32_4 (value: (ext_vector_size_float32_4){ 16.5, 32.25, 64.125, 128.0625}); |
604 | return_ext_vector_size_float32_8 (value: (ext_vector_size_float32_8){ 16.5, 32.25, 64.125, 128.0625, 1.59, 3.57, 8.63, 9.12 }); |
605 | |
606 | return 0; |
607 | } |
608 | |