2008-07-28 Marek Habersack <mhabersack@novell.com>
[mono.git] / mono / mini / tests.cs
1 using System;
2
3 public class Tests {
4
5         public static int Main (String[] args) {
6                 return TestDriver.RunTests (typeof (Tests));
7         }
8
9         static void call_clobber_inner () {
10         }
11
12         public static int test_15_clobber_1 () {
13                 int a = 0;
14                 int b = 0;
15                 for (int i = 0; i < 10; ++i)
16                         a ++;
17                 for (int i = 0; i < 5; ++i)
18                         b ++;
19
20                 // clob == '1' and dreg == sreg2
21                 a = b + a;
22                 return a;
23         }
24
25         public static int test_15_clobber_1_fp () {
26                 float a = 0;
27                 float b = 0;
28                 for (int i = 0; i < 10; ++i)
29                         a ++;
30                 for (int i = 0; i < 5; ++i)
31                         b ++;
32
33                 // clob == '1' and dreg == sreg2
34                 a = b + a;
35                 return (int)a;
36         }
37
38         public static int test_5_call_clobber () {
39                 // A call clobbers some registers so variables in those registers need to be spilled
40                 // and later reloaded to a register
41                 int a = 2;
42                 int b = 3;
43
44                 call_clobber_inner ();
45
46                 return a + b;
47         }
48
49         static int call_clobber_inner2 () {
50                 return 3;
51         }
52
53         public static int test_7_call_clobber_dreg () {
54                 // A call doesn't clobber its dreg
55                 int a = 3;
56                 int b = 4;
57
58                 a = call_clobber_inner2 ();
59
60                 return a + b;
61         }
62
63         public static int test_9_spill_if_then_else () {
64                 // Spilling variables in one branch of an if-then-else
65                 int a = 4;
66                 int b = 5;
67
68                 if (a != b) {
69                 } else {
70                         call_clobber_inner ();
71                 }
72
73                 return a + b;
74         }
75
76         public static int test_3_spill_reload_if_then_else () {
77                 // Spilling and reloading variables in one branch of an if-then-else
78                 int a = 4;
79                 int b = 5;
80                 int c = 3;
81
82                 if (a != b) {
83                 } else {
84                         call_clobber_inner ();
85                         c = a + b;
86                 }
87
88                 return c;
89         }
90
91         public static int test_5_spill_loop () {
92                 int i;
93
94                 for (i = 0; i < 5; ++i)
95                         call_clobber_inner ();
96
97                 return i;
98         }
99
100         public unsafe static int test_0_volatile () {
101                 int i = 1;
102                 int*p = &i;
103
104                 if (*p != 1)
105                         return 1;
106                 if (i != 1)
107                         return 2;
108                 *p = 5;
109                 if (i != 5)
110                         return 3;
111                 i = 2;
112                 if (i != 2)
113                         return 4;
114                 if (*p != 2)
115                         return 5;
116
117                 return 0;
118         }
119
120         public unsafe static int test_0_volatile_unused () {
121                 int i = 1;
122                 int*p = &i;
123
124                 if (*p != 1)
125                         return 1;
126
127                 return 0;
128         }
129
130         public unsafe static int test_0_volatile_unused_2 () {
131                 int i = 1;
132                 int *p = &i;
133
134                 i = 2;
135                 if (i != 2)
136                         return 1;
137
138                 return 0;
139         }
140
141         static int ref_int (int i, ref int b, int j) {
142                 int res = b;
143                 b = 1;
144                 return res;
145         }
146
147         public static int test_0_volatile_unused_3 () {
148                 // b's def has no use so its interval is split at a position not covered by the interval
149                 int b = 42;
150                 if (ref_int (99, ref b, 100) != 42)
151                         return 1;
152                 b = 43;
153                 if (ref_int (99, ref b, 100) != 43)
154                         return 2;
155                 if (b != 1)
156                         return 13;
157                 return 0;
158         }
159
160         static int ref_bool (int i, ref bool b1, ref bool b2, ref bool b3) {
161                 b1 = !b1;
162                 b2 = !b2;
163                 b3 = !b3;
164
165                 return 0;
166         }
167
168         public static int test_0_volatile_regress_1 () {
169                 // Spill stores should precede spill loads at a given position
170                 for (int i = 0; i < 8; i++) {
171                         bool b1 = (i & 4) != 0;
172                         bool b2 = (i & 2) != 0;
173                         bool b3 = (i & 1) != 0;
174                         bool orig_b1 = b1, orig_b2 = b2, orig_b3 = b3;
175                         if (ref_bool(i, ref b1, ref b2, ref b3) != 0)
176                                 return 4 * i + 1;
177                         if (b1 != !orig_b1)
178                                 return 4 * i + 2;
179                         if (b2 != !orig_b2)
180                                 return 4 * i + 3;
181                         if (b3 != !orig_b3)
182                                 return 4 * i + 4;
183                 }
184
185                 return 0;
186         }
187
188         public static int test_0_clobber_regress_1 () {
189                 object[] a11 = new object [10];
190                 object o = new Object ();
191                 // A spill load is inserted before the backward branch, clobbering one of the
192                 // registers used in the comparison
193                 for (int i = 0; i < 10; ++i)
194                         a11 [i] = null;
195
196                 return 0;
197         }
198
199         static int return_arg (int i) {
200                 return i;
201         }
202
203         public static int test_0_spill_regress_1 () {
204                 int j = 5;
205                 for (int i = 0; i < 3; i++) {
206                         // i is spilled by the call, then reloaded for the loop check
207                         // make sure the move from its first reg to its second is inserted in the
208                         // if body bblock, not the for body bblock
209                         if (i == 0) {
210                         } else {
211                                 if (return_arg (j) != 5)
212                                         return 1;
213                         }
214                 }
215
216                 return 0;
217         }
218
219         public static int test_0_spill_regress_2 () {
220                 double[] temporaries = new double[3];
221                 for (int i = 0; i < 3; i++) {
222                         // i and temporaries are spilled by the call, then reloaded after the call
223                         // make sure the two moves inserted in the if bblock are in the proper order
224                         if (i == 0) {
225                         } else {
226                                 temporaries [i] = return_arg (i);
227                         }
228                 }
229
230                 return 0;
231         }
232
233         static int many_args_unused (int i, int j, int k, int l, int m, int n, int p, int q) {
234                 return 0;
235         }
236
237         public static int test_0_unused_args () {
238                 return many_args_unused (0, 1, 2, 3, 4, 5, 6, 7);
239         }
240                         
241         public unsafe void ClearBuffer (byte *buffer, int i) {
242                 // Avoid inlining
243                 byte *b = stackalloc byte [4];
244         }
245
246         public unsafe bool instance_method_1 (string s, string target, int start, int length, int opt) {
247                 byte* alwaysMatchFlags = stackalloc byte [16];
248                 byte* neverMatchFlags = stackalloc byte [16];
249                 byte* targetSortKey = stackalloc byte [4];
250                 byte* sk1 = stackalloc byte [4];
251                 byte* sk2 = stackalloc byte [4];
252                 ClearBuffer (alwaysMatchFlags, 16);
253                 ClearBuffer (neverMatchFlags, 16);
254                 ClearBuffer (targetSortKey, 4);
255                 ClearBuffer (sk1, 4);
256                 ClearBuffer (sk2, 4);
257
258                 return this == null && s == target && start == length && length == opt && alwaysMatchFlags == neverMatchFlags && neverMatchFlags == targetSortKey && sk1 == sk2;
259         }
260
261         public static int test_0_spill_regress_3 () {
262                 new Tests ().instance_method_1 (null, null, 0, 0, 0);
263                 return 0;
264         }
265
266         unsafe bool MatchesBackward (string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, ref object ctx) {
267                 // Avoid inlining
268                 byte *b = stackalloc byte [4];
269
270                 if (ctx == null)
271                         throw new Exception ();
272
273                 idx -= 1;
274                 return false;
275         }
276
277         unsafe int LastIndexOfSortKey (string s, int start, int orgStart, int length, byte* sortkey, int ti, bool noLv4, ref object ctx)
278         {
279                 // ctx is initially allocated to the stack, when it is reloaded before the call,
280                 // %rax is spilled to free up the register, then ctx is allocated to %rax for its
281                 // whole lifetime, but %rax is not available for this since it is clobbered by the
282                 // call
283                 int end = start - length;
284                 int idx = start;
285                 while (idx > end) {
286                         int cur = idx;
287                         if (MatchesBackward (s, ref idx, end, orgStart,
288                                                                  ti, sortkey, noLv4, ref ctx))
289                                 return cur;
290                 }
291                 return -1;
292         }
293
294         public unsafe static int test_0_spill_regress_4 () {
295                 object o = new Object ();
296                 new Tests ().LastIndexOfSortKey ("", 10, 0, 5, null, 0, false, ref o);
297
298                 return 0;
299         }
300 }