Add a more functional (i.e. fewer-stubs) implementation of System.Data.Linq.
[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  * 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 struct Alpha {
27         public long a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v;
28 }
29
30 struct Beta {
31         public Alpha a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v;
32 }
33
34 struct Gamma {
35         public Beta a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v;
36 }
37
38 class Tests {
39
40         static int Main () {
41                 return TestDriver.RunTests (typeof (Tests));
42         }
43
44         static void dummy () {
45         }
46
47         static int test_0_return () {
48                 dummy ();
49                 return 0;
50         }
51
52         static int dummy1 () {
53                 return 1;
54         }
55
56         static int test_2_int_return () {
57                 int r = dummy1 ();
58                 if (r == 1)
59                         return 2;
60                 return 0;
61         }
62
63         static int add1 (int val) {
64                 return val + 1;
65         }
66
67         static int test_1_int_pass () {
68                 int r = add1 (5);
69                 if (r == 6)
70                         return 1;
71                 return 0;
72         }
73
74         static int add_many (int val, short t, byte b, int da) {
75                 return val + t + b + da;
76         }
77
78         static int test_1_int_pass_many () {
79                 byte b = 6;
80                 int r = add_many (5, 2, b, 1);
81                 if (r == 14)
82                         return 1;
83                 return 0;
84         }
85
86         unsafe static float GetFloat (byte *ptr) {
87                 return *(float*)ptr;
88         }
89
90         unsafe public static float GetFloat(float value)
91                 {
92                         return GetFloat((byte *)&value);
93                 }
94
95         /* bug #42134 */
96         static int test_2_inline_saved_arg_type () {
97                 float f = 100.0f;
98                 return GetFloat (f) == f? 2: 1;
99         }
100
101         static int pass_many_types (int a, long b, int c, long d) {
102                 return a + (int)b + c + (int)d;
103         }
104
105         static int test_5_pass_longs () {
106                 return pass_many_types (1, 2, -5, 7);
107         }
108
109         static int overflow_registers (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
110                 return a+b+c+d+e+f+g+h+i+j;
111         }
112
113         static int test_55_pass_even_more () {
114                 return overflow_registers (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
115         }
116
117         static int pass_ints_longs (int a, long b, long c, long d, long e, int f, long g) {
118                 return (int)(a + b + c + d + e + f + g);
119         }
120
121         static int test_1_sparc_argument_passing () {
122                 // The 4. argument tests split reg/mem argument passing
123                 // The 5. argument tests mem argument passing
124                 // The 7. argument tests passing longs in misaligned memory
125                 // The MaxValues are needed so the MS word of the long is not 0
126                 return pass_ints_longs (1, 2, System.Int64.MaxValue, System.Int64.MinValue, System.Int64.MaxValue, 0, System.Int64.MinValue);
127         }
128
129         static int pass_bytes (byte a, byte b, byte c, byte d, byte e, byte f, byte g) {
130                 return (int)(a + b + c + d + e + f + g);
131         }
132
133         static int test_21_sparc_byte_argument_passing () {
134                 return pass_bytes (0, 1, 2, 3, 4, 5, 6);
135         }
136
137         static int pass_sbytes (sbyte a, sbyte b, sbyte c, sbyte d, sbyte e, sbyte f, sbyte g) {
138                 return (int)(a + b + c + d + e + f + g);
139         }
140
141         static int test_21_sparc_sbyte_argument_passing () {
142                 return pass_sbytes (0, 1, 2, 3, 4, 5, 6);
143         }
144
145         static int pass_shorts (short a, short b, short c, short d, short e, short f, short g) {
146                 return (int)(a + b + c + d + e + f + g);
147         }
148
149         static int test_21_sparc_short_argument_passing () {
150                 return pass_shorts (0, 1, 2, 3, 4, 5, 6);
151         }
152
153         static int pass_floats_doubles (float a, double b, double c, double d, double e, float f, double g) {
154                 return (int)(a + b + c + d + e + f + g);
155         }
156
157         static int test_721_sparc_float_argument_passing () {
158                 return pass_floats_doubles (100.0f, 101.0, 102.0, 103.0, 104.0, 105.0f, 106.0);
159         }
160
161         static float pass_floats (float a, float b, float c, float d, float e, float f, float g, float h, float i, float j) {
162                 return a + b + c + d + e + f + g + h + i + j;
163         }
164
165         static int test_55_sparc_float_argument_passing2 () {
166                 return (int)pass_floats (1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f);
167         }
168
169         public static bool is_small (float value) {
170                 double d = (double)value;
171                 double d2 = 7.183757E-41;
172                 return d - d2 < 0.000001;
173         }
174                 
175         static int test_0_float_argument_passing_precision () {
176                 float f = 7.183757E-41f;
177                 return is_small (f) ? 0 : 1;
178         }
179
180         // The first argument must be passed on a dword aligned stack location
181         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) {
182                 return (int)(a + b + c + d + e + f + g);
183         }
184
185         static int pass_takeaddr_ints_longs (long a, int b, byte c, short d, long e, int f, long g) {
186                 return pass_byref_ints_longs (ref a, ref b, ref c, ref d, ref e, ref f, ref g);
187         }
188
189         // Test that arguments are moved to the stack from incoming registers
190         // when the argument must reside in the stack because its address is taken
191         static int test_2_sparc_takeaddr_argument_passing () {
192                 return pass_takeaddr_ints_longs (1, 2, 253, -253, System.Int64.MaxValue, 0, System.Int64.MinValue);
193         }
194
195         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) {
196                 return (int)(a + b + c + d + e + f + g);
197         }
198
199         static int pass_takeaddr_floats_doubles (float a, double b, double c, double d, double e, float f, double g) {
200                 return pass_byref_floats_doubles (ref a, ref b, ref c, ref d, ref e, ref f, ref g);
201         }
202
203         static int test_721_sparc_takeaddr_argument_passing2 () {
204                 return pass_takeaddr_floats_doubles (100.0f, 101.0, 102.0, 103.0, 104.0, 105.0f, 106.0);
205         }
206
207         static void pass_byref_double (out double d) {
208                 d = 5.0;
209         }
210
211         // Test byref double argument passing
212         static int test_0_sparc_byref_double_argument_passing () {
213                 double d;
214                 pass_byref_double (out d);
215                 return (d == 5.0) ? 0 : 1;
216         }
217
218         static void shift_un_arg (ulong value) {
219                 do {
220                         value = value >> 4;
221                 } while (value != 0);
222         }
223
224         // Test that assignment to long arguments work
225         static int test_0_long_arg_assign ()
226         {
227                 ulong c = 0x800000ff00000000;
228                         
229                 shift_un_arg (c >> 4);
230
231                 return 0;
232         }
233
234         static unsafe void* ptr_return (void *ptr)
235         {
236                 return ptr;
237         }
238
239         static unsafe int test_0_ptr_return ()
240         {
241                 void *ptr = new IntPtr (55).ToPointer ();
242
243                 if (ptr_return (ptr) == ptr)
244                         return 0;
245                 else
246                         return 1;
247         }
248
249         static bool isnan (float f) {
250                 return (f != f);
251         }
252
253         static int test_0_isnan () {
254                 float f = 1.0f;
255                 return isnan (f) ? 1 : 0;
256         }
257
258         static int first_is_zero (int v1, int v2) {
259                 if (v1 != 0)
260                         return -1;
261                 return v2;
262         }
263         static int test_1_handle_dup_stloc () {
264                 int index = 0;
265                 int val = first_is_zero (index, ++index);
266                 if (val != 1)
267                         return 2;
268                 return 1;
269         }
270
271         static long return_5low () {
272                 return 5;
273         }
274         
275         static long return_5high () {
276                 return 0x500000000;
277         }
278
279         public static int test_3_long_ret () {
280                 long val = return_5low ();
281                 return (int) (val - 2);
282         }
283
284         public static int test_1_long_ret2 () {
285                 long val = return_5high ();
286                 if (val > 0xffffffff)
287                         return 1;
288                 return 0;
289         }
290
291         static void doit (double value, out long m) {
292                 m = (long) value;
293         }
294
295         public static int test_0_ftol_clobber () {
296                 long m;
297                 doit (1.3, out m);
298                 if (m != 1)
299                         return 2;
300                 return 0;
301         }
302
303         static void InitMe (out Gamma noMercyWithTheStack) {
304                 noMercyWithTheStack = new Gamma ();
305         }
306
307         static int FunNoInline () {
308                 int x = 99;
309                 if (x > 344 && x < 22)
310                         throw new Exception ("333");
311                 return x;
312         }
313
314         static float DoNothingButDontInline (float a, int b) {
315                 if (b > 0)
316                         return a;
317                 else if (b < 0 && b > 10)
318                         throw new Exception ("444");
319                 return a;
320         }
321
322         /*
323          * The local register allocator emits loadr8_membase and storer8_membase
324          * to do spilling. This code is generated after mono_arch_lowering_pass so
325          * mono_arch_output_basic_block must know how to deal with big offsets.
326          * This only happens because the call in middle forces the temp for "(float)obj"
327          * to be spilled.
328         */
329         static int test_0_float_load_and_store_with_big_offset ()
330         {
331                 object obj = 1.0f;
332                 Gamma noMercyWithTheStack;
333                 float res;
334
335                 InitMe (out noMercyWithTheStack);
336
337                 res = DoNothingButDontInline ((float)obj, FunNoInline ());
338
339                 if (!(res == 1.0f)) {
340                         Console.WriteLine ("invalid number {0}", res);
341                         return 1;
342                 }
343                 return 0;
344         }
345 }
346