Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / basic-calls.cs
1 using System;
2 using System.Reflection;
3
4 /*
5  * Regression tests for the mono JIT.
6  *
7  * Each test needs to be of the form:
8  *
9  * public static int test_<result>_<name> ();
10  *
11  * where <result> is an integer (the value that needs to be returned by
12  * the method to make it pass.
13  * <name> is a user-displayed name used to identify the test.
14  *
15  * The tests can be driven in two ways:
16  * *) running the program directly: Main() uses reflection to find and invoke
17  *      the test methods (this is useful mostly to check that the tests are correct)
18  * *) with the --regression switch of the jit (this is the preferred way since
19  *      all the tests will be run with optimizations on and off)
20  *
21  * The reflection logic could be moved to a .dll since we need at least another
22  * regression test file written in IL code to have better control on how
23  * the IL code looks.
24  */
25
26 #if __MOBILE__
27 class CallsTests
28 #else
29 class Tests
30 #endif
31 {
32
33 #if !__MOBILE__
34         public static int Main (string[] args) {
35                 return TestDriver.RunTests (typeof (Tests), args);
36         }
37 #endif
38
39         static void dummy () {
40         }
41
42         public static int test_0_return () {
43                 dummy ();
44                 return 0;
45         }
46
47         static int dummy1 () {
48                 return 1;
49         }
50
51         public static int test_2_int_return () {
52                 int r = dummy1 ();
53                 if (r == 1)
54                         return 2;
55                 return 0;
56         }
57
58         static int add1 (int val) {
59                 return val + 1;
60         }
61
62         public static int test_1_int_pass () {
63                 int r = add1 (5);
64                 if (r == 6)
65                         return 1;
66                 return 0;
67         }
68
69         static int add_many (int val, short t, byte b, int da) {
70                 return val + t + b + da;
71         }
72
73         public static int test_1_int_pass_many () {
74                 byte b = 6;
75                 int r = add_many (5, 2, b, 1);
76                 if (r == 14)
77                         return 1;
78                 return 0;
79         }
80
81         unsafe static float GetFloat (byte *ptr) {
82                 return *(float*)ptr;
83         }
84
85         unsafe public static float GetFloat(float value)
86                 {
87                         return GetFloat((byte *)&value);
88                 }
89
90         /* bug #42134 */
91         public static int test_2_inline_saved_arg_type () {
92                 float f = 100.0f;
93                 return GetFloat (f) == f? 2: 1;
94         }
95
96         static int pass_many_types (int a, long b, int c, long d) {
97                 return a + (int)b + c + (int)d;
98         }
99
100         public static int test_5_pass_longs () {
101                 return pass_many_types (1, 2, -5, 7);
102         }
103
104         static int overflow_registers (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
105                 return a+b+c+d+e+f+g+h+i+j;
106         }
107
108         public static int test_55_pass_even_more () {
109                 return overflow_registers (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
110         }
111
112         static int pass_ints_longs (int a, long b, long c, long d, long e, int f, long g) {
113                 return (int)(a + b + c + d + e + f + g);
114         }
115
116         public static int test_1_sparc_argument_passing () {
117                 // The 4. argument tests split reg/mem argument passing
118                 // The 5. argument tests mem argument passing
119                 // The 7. argument tests passing longs in misaligned memory
120                 // The MaxValues are needed so the MS word of the long is not 0
121                 return pass_ints_longs (1, 2, System.Int64.MaxValue, System.Int64.MinValue, System.Int64.MaxValue, 0, System.Int64.MinValue);
122         }
123
124         static int pass_bytes (byte a, byte b, byte c, byte d, byte e, byte f, byte g) {
125                 return (int)(a + b + c + d + e + f + g);
126         }
127
128         public static int test_21_sparc_byte_argument_passing () {
129                 return pass_bytes (0, 1, 2, 3, 4, 5, 6);
130         }
131
132         static int pass_sbytes (sbyte a, sbyte b, sbyte c, sbyte d, sbyte e, sbyte f, sbyte g, sbyte h1, sbyte h2, sbyte h3, sbyte h4) {
133                 return (int)(a + b + c + d + e + f + g + h1 + h2 + h3 + h4);
134         }
135
136         public static int test_55_sparc_sbyte_argument_passing () {
137                 return pass_sbytes (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
138         }
139
140         static int pass_shorts (short a, short b, short c, short d, short e, short f, short g) {
141                 return (int)(a + b + c + d + e + f + g);
142         }
143
144         public static int test_21_sparc_short_argument_passing () {
145                 return pass_shorts (0, 1, 2, 3, 4, 5, 6);
146         }
147
148         static int pass_floats_doubles (float a, double b, double c, double d, double e, float f, double g) {
149                 return (int)(a + b + c + d + e + f + g);
150         }
151
152         public static int test_721_sparc_float_argument_passing () {
153                 return pass_floats_doubles (100.0f, 101.0, 102.0, 103.0, 104.0, 105.0f, 106.0);
154         }
155
156         static float pass_floats (float a, float b, float c, float d, float e, float f, float g, float h, float i, float j) {
157                 return a + b + c + d + e + f + g + h + i + j;
158         }
159
160         public static int test_55_sparc_float_argument_passing2 () {
161                 return (int)pass_floats (1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f);
162         }
163
164         public static bool is_small (float value) {
165                 double d = (double)value;
166                 double d2 = 7.183757E-41;
167                 return d - d2 < 0.000001;
168         }
169                 
170         public static int test_0_float_argument_passing_precision () {
171                 float f = 7.183757E-41f;
172                 return is_small (f) ? 0 : 1;
173         }
174
175         // The first argument must be passed on a dword aligned stack location
176         static int pass_byref_ints_longs (ref long a, ref int b, ref byte c, ref short d, ref long e, ref int f, ref long g) {
177                 return (int)(a + b + c + d + e + f + g);
178         }
179
180         static int pass_takeaddr_ints_longs (long a, int b, byte c, short d, long e, int f, long g) {
181                 return pass_byref_ints_longs (ref a, ref b, ref c, ref d, ref e, ref f, ref g);
182         }
183
184         // Test that arguments are moved to the stack from incoming registers
185         // when the argument must reside in the stack because its address is taken
186         public static int test_2_sparc_takeaddr_argument_passing () {
187                 return pass_takeaddr_ints_longs (1, 2, 253, -253, System.Int64.MaxValue, 0, System.Int64.MinValue);
188         }
189
190         static int pass_byref_floats_doubles (ref float a, ref double b, ref double c, ref double d, ref double e, ref float f, ref double g) {
191                 return (int)(a + b + c + d + e + f + g);
192         }
193
194         static int pass_takeaddr_floats_doubles (float a, double b, double c, double d, double e, float f, double g) {
195                 return pass_byref_floats_doubles (ref a, ref b, ref c, ref d, ref e, ref f, ref g);
196         }
197
198         public static int test_721_sparc_takeaddr_argument_passing2 () {
199                 return pass_takeaddr_floats_doubles (100.0f, 101.0, 102.0, 103.0, 104.0, 105.0f, 106.0);
200         }
201
202         static void pass_byref_double (out double d) {
203                 d = 5.0;
204         }
205
206         // Test byref double argument passing
207         public static int test_0_sparc_byref_double_argument_passing () {
208                 double d;
209                 pass_byref_double (out d);
210                 return (d == 5.0) ? 0 : 1;
211         }
212
213         static void shift_un_arg (ulong value) {
214                 do {
215                         value = value >> 4;
216                 } while (value != 0);
217         }
218
219         // Test that assignment to long arguments work
220         public static int test_0_long_arg_assign ()
221         {
222                 ulong c = 0x800000ff00000000;
223                         
224                 shift_un_arg (c >> 4);
225
226                 return 0;
227         }
228
229         static unsafe void* ptr_return (void *ptr)
230         {
231                 return ptr;
232         }
233
234         public static unsafe int test_0_ptr_return ()
235         {
236                 void *ptr = new IntPtr (55).ToPointer ();
237
238                 if (ptr_return (ptr) == ptr)
239                         return 0;
240                 else
241                         return 1;
242         }
243
244         static bool isnan (float f) {
245                 return (f != f);
246         }
247
248         public static int test_0_isnan () {
249                 float f = 1.0f;
250                 return isnan (f) ? 1 : 0;
251         }
252
253         static int first_is_zero (int v1, int v2) {
254                 if (v1 != 0)
255                         return -1;
256                 return v2;
257         }
258         public static int test_1_handle_dup_stloc () {
259                 int index = 0;
260                 int val = first_is_zero (index, ++index);
261                 if (val != 1)
262                         return 2;
263                 return 1;
264         }
265
266         static long return_5low () {
267                 return 5;
268         }
269         
270         static long return_5high () {
271                 return 0x500000000;
272         }
273
274         public static int test_3_long_ret () {
275                 long val = return_5low ();
276                 return (int) (val - 2);
277         }
278
279         public static int test_1_long_ret2 () {
280                 long val = return_5high ();
281                 if (val > 0xffffffff)
282                         return 1;
283                 return 0;
284         }
285
286         public static void use_long_arg (ulong l) {
287                 for (int i = 0; i < 10; ++i)
288                         l ++;
289         }
290
291         public static ulong return_long_arg (object o, ulong perm) {
292                 use_long_arg (perm);
293
294         perm = 0x8000000000000FFF;
295
296                 use_long_arg (perm);
297
298                 return perm;
299         }
300
301     public static int test_0_sparc_long_ret_regress_541577 () {
302         ulong perm = 0x8000000000000FFF;
303
304         ulong work = return_long_arg (null, perm);
305
306                 return work == perm ? 0 : 1;
307         }
308
309         static void doit (double value, out long m) {
310                 m = (long) value;
311         }
312
313         public static int test_0_ftol_clobber () {
314                 long m;
315                 doit (1.3, out m);
316                 if (m != 1)
317                         return 2;
318                 return 0;
319         }
320
321         public static bool arm64_stack_arg_reg_bool (object o1, object o2, object o3, object o4, object o5, object o6, object o7,
322                                                                                                  bool foo, bool bar) {
323                 bool res1 = bar || foo;
324                 bool res2 = bar || foo;
325                 return res1 | res2;
326         }
327
328         public static int arm64_stack_arg_reg_sbyte (object o1, object o2, object o3, object o4, object o5, object o6, object o7,
329                                                                                                  sbyte foo, sbyte bar) {
330                 int res1 = bar + foo;
331                 int res2 = bar + foo;
332                 return res1 + res2;
333         }
334
335         // bool argument passed on the stack and promoted to a register
336         public static int test_0_arm64_stack_arg_reg_bool () {
337             bool res = arm64_stack_arg_reg_bool (null, null, null, null, null, null, null, false, false);
338                 return res ? 1 : 0;
339         }
340
341         public static int test_0_arm64_stack_arg_reg_sbyte () {
342             int res = arm64_stack_arg_reg_sbyte (null, null, null, null, null, null, null, -4, -7);
343                 return res == -22 ? 0 : 1;
344         }
345 }