1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include <stdarg.h>
6#include <stdio.h>
7#include <string.h>
8#include <stdlib.h>
9
10#ifdef _MSC_VER
11#define DLLEXPORT __declspec(dllexport)
12#else
13#define DLLEXPORT __attribute__((visibility("default")))
14
15#if __i386__
16#define _cdecl __attribute__((cdecl))
17#else
18#define _cdecl
19#endif
20
21#endif // _MSC_VER
22
23/* Structures */
24
25/*
26 * struct one_byte_struct (4 bytes)
27*/
28typedef struct
29{
30 int one;
31} one_int_struct;
32
33/*
34 * struct two_int_struct (8 bytes)
35*/
36typedef struct
37{
38 int one;
39 int two;
40} two_int_struct;
41
42/*
43 * struct one_long_long_struct (8 bytes)
44*/
45typedef struct
46{
47 __int64 one;
48} one_long_long_struct;
49
50/*
51 * struct two_long_long_struct (16 bytes)
52*/
53typedef struct
54{
55 __int64 one;
56 __int64 two;
57} two_long_long_struct;
58
59/*
60 * struct four_int_struct (16 bytes)
61*/
62typedef struct
63{
64 int one;
65 int two;
66 int three;
67 int four;
68} four_int_struct;
69
70/*
71 * struct four_long_long_struct (32 bytes)
72*/
73typedef struct
74{
75 __int64 one;
76 __int64 two;
77 __int64 three;
78 __int64 four;
79} four_long_long_struct;
80
81/*
82 * struct one_float_struct (4 bytes)
83*/
84typedef struct
85{
86 float one;
87} one_float_struct;
88
89/*
90 * struct two_float_struct (8 bytes)
91*/
92typedef struct
93{
94 float one;
95 float two;
96} two_float_struct;
97
98/*
99 * struct one_double_struct (8 bytes)
100*/
101typedef struct
102{
103 double one;
104} one_double_struct;
105
106/*
107 * struct two_double_struct (16 bytes)
108*/
109typedef struct
110{
111 double one;
112 double two;
113} two_double_struct;
114
115/*
116 * struct three_double_struct (24 bytes)
117*/
118typedef struct
119{
120 double one;
121 double two;
122 double three;
123} three_double_struct;
124
125/*
126 * struct four_float_struct (16 bytes)
127*/
128typedef struct
129{
130 float one;
131 float two;
132 float three;
133 float four;
134} four_float_struct;
135
136/*
137 * struct four_double_struct (32 bytes)
138*/
139typedef struct
140{
141 double one;
142 double two;
143 double three;
144 double four;
145} four_double_struct;
146
147/*
148 * struct eight_byte_struct (8 bytes)
149*/
150typedef struct
151{
152 char one;
153 char two;
154 char three;
155 char four;
156 char five;
157 char six;
158 char seven;
159 char eight;
160} eight_byte_struct;
161
162/*
163 * struct sixteen_byte_struct (8 bytes)
164*/
165typedef struct
166{
167 char one;
168 char two;
169 char three;
170 char four;
171 char five;
172 char six;
173 char seven;
174 char eight;
175 char nine;
176 char ten;
177 char eleven;
178 char twelve;
179 char thirteen;
180 char fourteen;
181 char fifteen;
182 char sixteen;
183} sixteen_byte_struct;
184
185/* Tests */
186
187DLLEXPORT int _cdecl test_passing_ints(int count, ...)
188{
189 va_list ap;
190 int index, sum;
191
192 va_start(ap, count);
193
194 sum = 0;
195 for (index = 0; index < count; ++index)
196 {
197 sum += va_arg(ap, int);
198 }
199
200 va_end(ap);
201 return sum;
202}
203
204DLLEXPORT __int64 _cdecl test_passing_longs(int count, ...)
205{
206 va_list ap;
207 int index;
208 __int64 sum;
209
210 va_start(ap, count);
211
212 sum = 0;
213 for (index = 0; index < count; ++index)
214 {
215 sum += va_arg(ap, __int64);
216 }
217
218 va_end(ap);
219 return sum;
220}
221
222DLLEXPORT float _cdecl test_passing_floats(int count, ...)
223{
224 va_list ap;
225 int index;
226 double sum;
227
228 va_start(ap, count);
229
230 sum = 0;
231 for (index = 0; index < count; ++index)
232 {
233 sum += va_arg(ap, double);
234 }
235
236 va_end(ap);
237 return (float)sum;
238}
239
240DLLEXPORT double _cdecl test_passing_doubles(int count, ...)
241{
242 va_list ap;
243 int index;
244 double sum;
245
246 va_start(ap, count);
247
248 sum = 0;
249 for (index = 0; index < count; ++index)
250 {
251 sum += va_arg(ap, double);
252 }
253
254 va_end(ap);
255 return sum;
256}
257
258DLLEXPORT __int64 _cdecl test_passing_int_and_longs(int int_count, int long_count, ...)
259{
260 va_list ap;
261 int index, count;
262 __int64 sum;
263
264 count = int_count + long_count;
265 va_start(ap, long_count);
266
267 sum = 0;
268 for (index = 0; index < int_count; ++index)
269 {
270 sum += va_arg(ap, int);
271 }
272
273 for (index = 0; index < long_count; ++index)
274 {
275 sum += va_arg(ap, __int64);
276 }
277
278 va_end(ap);
279 return sum;
280}
281
282DLLEXPORT double _cdecl test_passing_floats_and_doubles(int float_count, int double_count, ...)
283{
284 va_list ap;
285 int index, count;
286 double sum;
287
288 count = float_count + double_count;
289 va_start(ap, double_count);
290
291
292 sum = 0;
293 for (index = 0; index < float_count; ++index)
294 {
295 // Read a double, C ABI defines reading a float as undefined, or
296 // an error on unix. However, the managed side will correctly pass a
297 // float.
298 sum += va_arg(ap, double);
299 }
300
301 for (index = 0; index < double_count; ++index)
302 {
303 sum += va_arg(ap, double);
304 }
305
306 va_end(ap);
307 return sum;
308}
309
310/*
311 Args:
312 expected_value (double) : expected sum
313 int : first value
314 double : second value
315 int : third value
316 double : fourth value
317 int : fifth value
318 double : sixth value
319*/
320DLLEXPORT double _cdecl test_passing_int_and_double(double expected_value, ...)
321{
322 va_list ap;
323 int index, count;
324 double sum;
325
326 count = 6;
327 va_start(ap, expected_value);
328
329 sum = 0;
330 for (index = 0; index < 6; ++index)
331 {
332 if (index % 2 == 0) {
333 sum += va_arg(ap, int);
334 }
335 else
336 {
337 sum += va_arg(ap, double);
338 }
339 }
340
341 va_end(ap);
342 return sum;
343}
344
345/*
346 Args:
347 expected_value (double) : expected sum
348 __int64 : first value
349 double : second value
350 __int64 : third value
351 double : fourth value
352 __int64 : fifth value
353 double : sixth value
354*/
355DLLEXPORT double _cdecl test_passing_long_and_double(double expected_value, ...)
356{
357 va_list ap;
358 int index, count;
359 double sum;
360
361 count = 6;
362 va_start(ap, expected_value);
363
364 sum = 0;
365 for (index = 0; index < 6; ++index)
366 {
367 if (index % 2 == 0) {
368 sum += va_arg(ap, __int64);
369 }
370 else
371 {
372 sum += va_arg(ap, double);
373 }
374 }
375
376 va_end(ap);
377 return sum;
378}
379
380/*
381 Args:
382 count (int) : count of args
383 is_int_structs(int) : first value
384 is_float_value(int) : second value
385 is_mixed (int) : third value
386 byte_count (int) : fourth value
387 struct_count (int) : fifth value
388*/
389DLLEXPORT int _cdecl check_passing_struct(int count, ...)
390{
391 va_list ap;
392 int is_b, is_floating, is_mixed, byte_count, struct_count;
393
394 int expected_value_i;
395 __int64 expected_value_l;
396 double expected_value_f;
397 double expected_value_d;
398
399 int passed = 0;
400
401 va_start(ap, count);
402
403 is_b = va_arg(ap, int);
404 is_floating = va_arg(ap, int);
405 is_mixed = va_arg(ap, int);
406 byte_count = va_arg(ap, int);
407 struct_count = va_arg(ap, int);
408
409 if (!is_floating)
410 {
411 if (byte_count == 8)
412 {
413 // Eight byte structs.
414 if (is_b)
415 {
416 // This is one_long_long_struct
417 one_long_long_struct s;
418 __int64 sum;
419
420 expected_value_l = va_arg(ap, __int64);
421 sum = 0;
422
423 while (struct_count--) {
424 s = va_arg(ap, one_long_long_struct);
425 sum += s.one;
426 }
427
428 if (sum != expected_value_l) passed = 1;
429 }
430 else
431 {
432 // This is two_int_struct
433 two_int_struct s;
434 int sum;
435
436 expected_value_i = va_arg(ap, int);
437 sum = 0;
438
439 while (struct_count--) {
440 s = va_arg(ap, two_int_struct);
441 sum += s.one + s.two;
442 }
443
444 if (sum != expected_value_i) passed = 1;
445 }
446 }
447 else if (byte_count == 16)
448 {
449 // 16 byte structs.
450 if (is_b)
451 {
452 // This is four_int_struct
453 four_int_struct s;
454 int sum;
455
456 expected_value_i = va_arg(ap, int);
457 sum = 0;
458
459 while (struct_count--) {
460 s = va_arg(ap, four_int_struct);
461 sum += s.one + s.two + s.three + s.four;
462 }
463
464 if (sum != expected_value_i) passed = 1;
465 }
466 else
467 {
468 // This is two_long_long_struct
469 two_long_long_struct s;
470 __int64 sum;
471
472 expected_value_l = va_arg(ap, __int64);
473 sum = 0;
474
475 while (struct_count--) {
476 s = va_arg(ap, two_long_long_struct);
477 sum += s.one + s.two;
478 }
479
480 if (sum != expected_value_l) passed = 1;
481 }
482 }
483
484 else if (byte_count == 32)
485 {
486 // This is sixteen_byte_struct
487 four_long_long_struct s;
488 __int64 sum;
489
490 expected_value_l = va_arg(ap, __int64);
491 sum = 0;
492
493 while (struct_count--) {
494 s = va_arg(ap, four_long_long_struct);
495 sum += s.one + s.two + s.three + s.four;
496 }
497
498 if (sum != expected_value_l) passed = 1;
499 }
500 }
501 else
502 {
503 if (byte_count == 8)
504 {
505 // Eight byte structs.
506 if (is_b)
507 {
508 // This is one_double_struct
509 one_double_struct s;
510 double sum;
511
512 expected_value_d = va_arg(ap, double);
513 sum = 0;
514
515 while (struct_count--) {
516 s = va_arg(ap, one_double_struct);
517 sum += s.one;
518 }
519
520 if (sum != expected_value_d) passed = 1;
521 }
522 else
523 {
524 // This is two_float_struct
525 two_float_struct s;
526 float sum;
527
528 expected_value_f = va_arg(ap, double);
529 sum = 0;
530
531 while (struct_count--) {
532 s = va_arg(ap, two_float_struct);
533 sum += s.one + s.two;
534 }
535
536 if (sum != expected_value_f) passed = 1;
537 }
538 }
539 else if (byte_count == 16)
540 {
541 // 16 byte structs.
542 if (is_b)
543 {
544 // This is four_float_struct
545 four_float_struct s;
546 float sum;
547
548 expected_value_f = va_arg(ap, double);
549 sum = 0;
550
551 while (struct_count--) {
552 s = va_arg(ap, four_float_struct);
553 sum += s.one + s.two + s.three + s.four;
554 }
555
556 if (sum != expected_value_f) passed = 1;
557 }
558 else
559 {
560 // This is two_double_struct
561 two_double_struct s;
562 double sum;
563
564 expected_value_d = va_arg(ap, double);
565 sum = 0;
566
567 while (struct_count--) {
568 s = va_arg(ap, two_double_struct);
569 sum += s.one + s.two;
570 }
571
572 if (sum != expected_value_d) passed = 1;
573 }
574 }
575
576 else if (byte_count == 32)
577 {
578 // This is four_double_struct
579 four_double_struct s;
580 double sum;
581
582 expected_value_d = va_arg(ap, double);
583 sum = 0;
584
585 while (struct_count--) {
586 s = va_arg(ap, four_double_struct);
587 sum += s.one + s.two + s.three + s.four;
588 }
589
590 if (sum != expected_value_d) passed = 1;
591 }
592 }
593
594 va_end(ap);
595 return passed;
596}
597
598DLLEXPORT double _cdecl check_passing_four_three_double_struct(three_double_struct one, three_double_struct two, three_double_struct three, three_double_struct four, ...)
599{
600 double sum;
601
602 sum = 0;
603
604 sum += one.one + one.two + one.three;
605 sum += two.one + two.two + two.three;
606 sum += three.one + three.two + three.three;
607 sum += four.one + four.two + four.three;
608
609 return sum;
610}
611
612/*
613 Args:
614 count (int) : count of args
615 two_long_long_struct : first value
616 two_long_long_struct : second value
617 two_long_long_struct : third value
618 two_long_long_struct : fourth value
619*/
620DLLEXPORT int _cdecl check_passing_four_sixteen_byte_structs(int count, ...)
621{
622 va_list ap;
623 int passed, index;
624 two_long_long_struct s;
625 __int64 expected_value, calculated_value;
626
627 passed = 0;
628 calculated_value = 0;
629
630 va_start(ap, count);
631
632 expected_value = va_arg(ap, __int64);
633
634 for (index = 0; index < 4; ++index) {
635 s = va_arg(ap, two_long_long_struct);
636
637 calculated_value += s.one + s.two;
638 }
639
640 va_end(ap);
641
642 passed = expected_value == calculated_value ? 0 : 1;
643 return passed;
644}
645
646DLLEXPORT char _cdecl echo_byte(char arg, ...)
647{
648 return arg;
649}
650
651DLLEXPORT char _cdecl echo_char(char arg, ...)
652{
653 return arg;
654}
655
656DLLEXPORT __int8 _cdecl echo_short(__int8 arg, ...)
657{
658 return arg;
659}
660
661DLLEXPORT __int32 _cdecl echo_int(__int32 arg, ...)
662{
663 return arg;
664}
665
666DLLEXPORT __int64 _cdecl echo_int64(__int64 arg, ...)
667{
668 return arg;
669}
670
671DLLEXPORT float _cdecl echo_float(float arg, ...)
672{
673 return arg;
674}
675
676DLLEXPORT double _cdecl echo_double(double arg, ...)
677{
678 return arg;
679}
680
681DLLEXPORT one_int_struct _cdecl echo_one_int_struct(one_int_struct arg, ...)
682{
683 return arg;
684}
685
686DLLEXPORT two_int_struct _cdecl echo_two_int_struct(two_int_struct arg, ...)
687{
688 return arg;
689}
690
691DLLEXPORT one_long_long_struct _cdecl echo_one_long_struct(one_long_long_struct arg, ...)
692{
693 return arg;
694}
695
696DLLEXPORT two_long_long_struct _cdecl echo_two_long_struct(two_long_long_struct arg, ...)
697{
698 return arg;
699}
700
701DLLEXPORT four_long_long_struct _cdecl echo_four_long_struct(four_long_long_struct arg)
702{
703 return arg;
704}
705
706DLLEXPORT four_long_long_struct _cdecl echo_four_long_struct_with_vararg(four_long_long_struct arg, ...)
707{
708 return arg;
709}
710
711DLLEXPORT eight_byte_struct _cdecl echo_eight_byte_struct(eight_byte_struct arg, ...)
712{
713 return arg;
714}
715
716DLLEXPORT four_int_struct _cdecl echo_four_int_struct(four_int_struct arg, ...)
717{
718 return arg;
719}
720
721DLLEXPORT sixteen_byte_struct _cdecl echo_sixteen_byte_struct(sixteen_byte_struct arg, ...)
722{
723 return arg;
724}
725
726DLLEXPORT one_float_struct _cdecl echo_one_float_struct(one_float_struct arg, ...)
727{
728 return arg;
729}
730
731DLLEXPORT two_float_struct _cdecl echo_two_float_struct(two_float_struct arg, ...)
732{
733 return arg;
734}
735
736DLLEXPORT one_double_struct _cdecl echo_one_double_struct(one_double_struct arg, ...)
737{
738 return arg;
739}
740
741DLLEXPORT two_double_struct _cdecl echo_two_double_struct(two_double_struct arg, ...)
742{
743 return arg;
744}
745
746DLLEXPORT three_double_struct _cdecl echo_three_double_struct(three_double_struct arg, ...)
747{
748 return arg;
749}
750
751DLLEXPORT four_float_struct _cdecl echo_four_float_struct(four_float_struct arg, ...)
752{
753 return arg;
754}
755
756DLLEXPORT four_double_struct _cdecl echo_four_double_struct(four_double_struct arg, ...)
757{
758 return arg;
759}
760