2 using System.Reflection;
5 * Regression tests for the mono JIT.
7 * Each test needs to be of the form:
9 * public static int test_<result>_<name> ();
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.
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)
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
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;
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;
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;
41 return TestDriver.RunTests (typeof (Tests));
44 static void dummy () {
47 public static int test_0_return () {
52 static int dummy1 () {
56 public static int test_2_int_return () {
63 static int add1 (int val) {
67 public static int test_1_int_pass () {
74 static int add_many (int val, short t, byte b, int da) {
75 return val + t + b + da;
78 public static int test_1_int_pass_many () {
80 int r = add_many (5, 2, b, 1);
86 unsafe static float GetFloat (byte *ptr) {
90 unsafe public static float GetFloat(float value)
92 return GetFloat((byte *)&value);
96 public static int test_2_inline_saved_arg_type () {
98 return GetFloat (f) == f? 2: 1;
101 static int pass_many_types (int a, long b, int c, long d) {
102 return a + (int)b + c + (int)d;
105 public static int test_5_pass_longs () {
106 return pass_many_types (1, 2, -5, 7);
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;
113 public static int test_55_pass_even_more () {
114 return overflow_registers (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
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);
121 public 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);
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);
133 public static int test_21_sparc_byte_argument_passing () {
134 return pass_bytes (0, 1, 2, 3, 4, 5, 6);
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);
141 public static int test_21_sparc_sbyte_argument_passing () {
142 return pass_sbytes (0, 1, 2, 3, 4, 5, 6);
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);
149 public static int test_21_sparc_short_argument_passing () {
150 return pass_shorts (0, 1, 2, 3, 4, 5, 6);
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);
157 public 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);
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;
165 public 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);
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;
175 public static int test_0_float_argument_passing_precision () {
176 float f = 7.183757E-41f;
177 return is_small (f) ? 0 : 1;
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);
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);
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 public 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);
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);
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);
203 public 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);
207 static void pass_byref_double (out double d) {
211 // Test byref double argument passing
212 public static int test_0_sparc_byref_double_argument_passing () {
214 pass_byref_double (out d);
215 return (d == 5.0) ? 0 : 1;
218 static void shift_un_arg (ulong value) {
221 } while (value != 0);
224 // Test that assignment to long arguments work
225 public static int test_0_long_arg_assign ()
227 ulong c = 0x800000ff00000000;
229 shift_un_arg (c >> 4);
234 static unsafe void* ptr_return (void *ptr)
239 public static unsafe int test_0_ptr_return ()
241 void *ptr = new IntPtr (55).ToPointer ();
243 if (ptr_return (ptr) == ptr)
249 static bool isnan (float f) {
253 public static int test_0_isnan () {
255 return isnan (f) ? 1 : 0;
258 static int first_is_zero (int v1, int v2) {
263 public static int test_1_handle_dup_stloc () {
265 int val = first_is_zero (index, ++index);
271 static long return_5low () {
275 static long return_5high () {
279 public static int test_3_long_ret () {
280 long val = return_5low ();
281 return (int) (val - 2);
284 public static int test_1_long_ret2 () {
285 long val = return_5high ();
286 if (val > 0xffffffff)
291 static void doit (double value, out long m) {
295 public static int test_0_ftol_clobber () {
303 static void InitMe (out Gamma noMercyWithTheStack) {
304 noMercyWithTheStack = new Gamma ();
307 static int FunNoInline () {
309 if (x > 344 && x < 22)
310 throw new Exception ("333");
314 static float DoNothingButDontInline (float a, int b) {
317 else if (b < 0 && b > 10)
318 throw new Exception ("444");
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"
329 public static int test_0_float_load_and_store_with_big_offset ()
332 Gamma noMercyWithTheStack;
335 InitMe (out noMercyWithTheStack);
337 res = DoNothingButDontInline ((float)obj, FunNoInline ());
339 if (!(res == 1.0f)) {
340 Console.WriteLine ("invalid number {0}", res);