Merge pull request #2734 from nealef/master
[mono.git] / mono / mini / aot-tests.cs
1 using System;
2 using System.Text;
3 using System.Linq;
4 using System.Reflection;
5 using System.Runtime.InteropServices;
6 using System.Runtime.CompilerServices;
7 using System.Collections.Generic;
8 using System.Collections.ObjectModel;
9
10 /*
11  * Regression tests for the AOT/FULL-AOT code.
12  */
13
14 #if __MOBILE__
15 class AotTests
16 #else
17 class Tests
18 #endif
19 {
20 #if !__MOBILE__
21         static int Main (String[] args) {
22                 return TestDriver.RunTests (typeof (Tests), args);
23         }
24 #endif
25
26         public delegate void ArrayDelegate (int[,] arr);
27
28         static int test_0_array_delegate_full_aot () {
29                 ArrayDelegate d = delegate (int[,] arr) {
30                 };
31                 int[,] a = new int[5, 6];
32                 d.BeginInvoke (a, null, null);
33                 return 0;
34         }
35
36         struct Struct1 {
37                 public double a, b;
38         }
39
40         struct Struct2 {
41                 public float a, b;
42         }
43
44         class Foo<T> {
45                 /* The 'd' argument is used to shift the register indexes so 't' doesn't start at the first reg */
46                 public static T Get_T (double d, T t) {
47                         return t;
48                 }
49         }
50
51         class Foo2<T> {
52                 public static T Get_T (double d, T t) {
53                         return t;
54                 }
55                 public static T Get_T2 (double d, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, T t) {
56                         return t;
57                 }
58         }
59
60         class Foo3<T> {
61                 public static T Get_T (double d, T t) {
62                         return Foo2<T>.Get_T (d, t);
63                 }
64         }
65
66         [Category ("DYNCALL")]
67         static int test_0_arm64_dyncall_double () {
68                 double arg1 = 1.0f;
69                 double s = 2.0f;
70                 var res = (double)typeof (Foo<double>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
71                 if (res != 2.0f)
72                         return 1;
73                 return 0;
74         }
75
76         [Category ("DYNCALL")]
77         static int test_0_arm64_dyncall_float () {
78                 double arg1 = 1.0f;
79                 float s = 2.0f;
80                 var res = (float)typeof (Foo<float>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
81                 if (res != 2.0f)
82                         return 1;
83                 return 0;
84         }
85
86         [Category ("DYNCALL")]
87         [Category ("!FULLAOT-AMD64")]
88         static int test_0_arm64_dyncall_hfa_double () {
89                 double arg1 = 1.0f;
90                 // HFA with double members
91                 var s = new Struct1 ();
92                 s.a = 1.0f;
93                 s.b = 2.0f;
94                 var s_res = (Struct1)typeof (Foo<Struct1>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
95                 if (s_res.a != 1.0f || s_res.b != 2.0f)
96                         return 1;
97                 return 0;
98         }
99
100         [Category ("DYNCALL")]
101         [Category ("!FULLAOT-AMD64")]
102         static int test_0_arm64_dyncall_hfa_float () {
103                 double arg1 = 1.0f;
104                 var s = new Struct2 ();
105                 s.a = 1.0f;
106                 s.b = 2.0f;
107                 var s_res = (Struct2)typeof (Foo<Struct2>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
108                 if (s_res.a != 1.0f || s_res.b != 2.0f)
109                         return 1;
110                 return 0;
111         }
112
113         [Category ("DYNCALL")]
114         [Category ("GSHAREDVT")]
115         [Category ("!FULLAOT-AMD64")]
116         static int test_0_arm64_dyncall_gsharedvt_out_hfa_double () {
117                 /* gsharedvt out trampoline with double hfa argument */
118                 double arg1 = 1.0f;
119
120                 var s = new Struct1 ();
121                 s.a = 1.0f;
122                 s.b = 2.0f;
123                 // Call Foo2.Get_T directly, so its gets an instance
124                 Foo2<Struct1>.Get_T (arg1, s);
125                 Type t = typeof (Foo3<>).MakeGenericType (new Type [] { typeof (Struct1) });
126                 // Call Foo3.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
127                 var s_res = (Struct1)t.GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
128                 if (s_res.a != 1.0f || s_res.b != 2.0f)
129                         return 1;
130                 return 0;
131         }
132
133         [Category ("DYNCALL")]
134         [Category ("GSHAREDVT")]
135         [Category ("!FULLAOT-AMD64")]
136         static int test_0_arm64_dyncall_gsharedvt_out_hfa_float () {
137                 /* gsharedvt out trampoline with double hfa argument */
138                 double arg1 = 1.0f;
139
140                 var s = new Struct2 ();
141                 s.a = 1.0f;
142                 s.b = 2.0f;
143                 // Call Foo2.Get_T directly, so its gets an instance
144                 Foo2<Struct2>.Get_T (arg1, s);
145                 Type t = typeof (Foo3<>).MakeGenericType (new Type [] { typeof (Struct2) });
146                 // Call Foo3.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
147                 var s_res = (Struct2)t.GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
148                 if (s_res.a != 1.0f || s_res.b != 2.0f)
149                         return 1;
150                 return 0;
151         }
152
153         interface IFaceFoo4<T> {
154                 T Get_T (double d, T t);
155                 T Get_T2 (double d, T t);
156         }
157
158         class Foo4<T> : IFaceFoo4<T> {
159                 public T Get_T (double d, T t) {
160                         return Foo2<T>.Get_T (d, t);
161                 }
162                 public T Get_T2 (double d, T t) {
163                         return Foo2<T>.Get_T2 (d, 1, 2, 3, 4, 5, 6, 7, 8, t);
164                 }
165         }
166
167         struct VTypeByRefStruct {
168                 public long o1, o2, o3;
169         }
170
171         [Category ("GSHAREDVT")]
172         public static int test_0_arm64_gsharedvt_out_vtypebyref () {
173                 /* gsharedvt out trampoline with vtypebyref argument */
174                 var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 };
175
176                 // Call Foo2.Get_T directly, so its gets an instance
177                 Foo2<VTypeByRefStruct>.Get_T (1.0f, s);
178                 var o = (IFaceFoo4<VTypeByRefStruct>)Activator.CreateInstance (typeof (Foo4<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) }));
179                 // Call Foo4.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
180                 var s_res = o.Get_T (1.0f, s);
181                 if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
182                         return 1;
183                 // Same with the byref argument passed on the stack
184                 s_res = o.Get_T2 (1.0f, s);
185                 if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
186                         return 2;
187                 return 0;
188         }
189
190         class Foo5<T> {
191                 public static T Get_T (object o) {
192                         return (T)o;
193                 }
194         }
195
196         [Category ("DYNCALL")]
197         [Category ("GSHAREDVT")]
198         [Category ("!FULLAOT-AMD64")]
199         static int test_0_arm64_dyncall_vtypebyref_ret () {
200                 var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 };
201                 Type t = typeof (Foo5<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) });
202                 var o = Activator.CreateInstance (t);
203                 try {
204                         var s_res = (VTypeByRefStruct)t.GetMethod ("Get_T").Invoke (o, new object [] { s });
205                         if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
206                                 return 1;
207                 } catch (TargetInvocationException) {
208                         return 2;
209                 }
210                 return 0;
211         }
212
213         class Foo6 {
214                 public T reg_stack_split_inner<T> (int i, int j, T l) {
215                         return l;
216                 }
217         }
218
219         [Category ("DYNCALL")]
220         [Category ("GSHAREDVT")]
221         static int test_0_arm_dyncall_reg_stack_split () {
222                 var m = typeof (Foo6).GetMethod ("reg_stack_split_inner").MakeGenericMethod (new Type[] { typeof (long) });
223                 var o = new Foo6 ();
224                 if ((long)m.Invoke (o, new object [] { 1, 2, 3 }) != 3)
225                         return 1;
226                 if ((long)m.Invoke (o, new object [] { 1, 2, Int64.MaxValue }) != Int64.MaxValue)
227                         return 2;
228                 return 0;
229         }
230
231         static int test_0_partial_sharing_regress_30204 () {
232                 var t = typeof (System.Collections.Generic.Comparer<System.Collections.Generic.KeyValuePair<string, string>>);
233                 var d = new SortedDictionary<string, string> ();
234                 d.Add ("key1", "banana");
235                 return d ["key1"] == "banana" ? 0 : 1;
236         }
237
238         class NullableMethods {
239                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
240                 public static bool GetHasValue<T>(Nullable<T> value) where T : struct {
241                         return value.HasValue;
242                 }
243
244                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
245                 public static T GetValue<T>(Nullable<T> value) where T : struct {
246                         return value.Value;
247                 }
248
249                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
250                 public static Nullable<T> Get<T>(T t) where T : struct {
251                         return t;
252                 }
253
254                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
255                 public static Nullable<T> GetNull<T>() where T : struct {
256                         return null;
257                 }
258         }
259
260         [Category ("DYNCALL")]
261         [Category ("!FULLAOT-AMD64")]
262         public static int test_0_dyncall_nullable () {
263                 int? v;
264
265                 v = 42;
266                 NullableMethods.GetHasValue (v);
267                 bool b = (bool)typeof (NullableMethods).GetMethod ("GetHasValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
268                 if (!b)
269                         return 1;
270                 v = null;
271                 b = (bool)typeof (NullableMethods).GetMethod ("GetHasValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
272                 if (b)
273                         return 2;
274
275                 v = 42;
276                 NullableMethods.GetValue (v);
277                 var res = (int)typeof (NullableMethods).GetMethod ("GetValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
278                 if (res != 42)
279                         return 3;
280
281                 NullableMethods.Get (42);
282                 var res2 = (int?)typeof (NullableMethods).GetMethod ("Get").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { 42 });
283                 if (res2 != 42)
284                         return 4;
285                 res2 = (int?)typeof (NullableMethods).GetMethod ("GetNull").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { });
286                 if (res2.HasValue)
287                         return 5;
288                 return 0;
289         }
290
291         enum AnEnum {
292                 A = 0,
293                 B = 1
294         }
295
296         public static int test_0_enum_eq_comparer () {
297                 var c = EqualityComparer<AnEnum>.Default;
298                 return (!c.Equals (AnEnum.A, AnEnum.B) && c.Equals (AnEnum.A, AnEnum.A)) ? 0 : 1;
299         }
300
301         public static int test_0_enum_comparer () {
302                 var c = Comparer<AnEnum>.Default;
303                 return c.Compare (AnEnum.A, AnEnum.A);
304         }
305
306         private static Dictionary<long, TValue> ConvertDictionary<TValue>(Dictionary<long, IList<TValue>> source) {
307                 return source.ToDictionary(pair => pair.Key, pair => pair.Value[0]);
308         }
309
310         [Category ("GSHAREDVT")]
311         public static int test_0_gsharedvt_non_variable_arg () {
312                 Dictionary<long, IList<int>> data = new Dictionary<long, IList<int>>
313             {
314                                 {123L, new List<int> {2}}
315             };
316                 Dictionary<long, int> newDict = ConvertDictionary(data);
317                 if (newDict.Count != 1)
318                         return 1;
319                 return 0;
320         }
321
322         enum LongEnum : ulong {
323                 A = 1
324                         }
325
326         public static int test_0_long_enum_eq_comparer () {
327                 var c = EqualityComparer<LongEnum>.Default;
328                 c.GetHashCode (LongEnum.A);
329                 return 0;
330         }
331
332         enum UInt32Enum : uint {
333                 A = 1
334                         }
335
336         enum Int32Enum : int {
337                 A = 1
338                         }
339
340         enum Int16Enum : short {
341                 A = 1
342                         }
343
344         enum UInt16Enum : ushort {
345                 A = 1
346                         }
347
348         enum Int8Enum : sbyte {
349                 A = 1
350                         }
351
352         enum UInt8Enum : byte {
353                 A = 1
354                         }
355
356         public static int test_0_int_enum_eq_comparer () {
357                 var t1 = new Dictionary<Int32Enum, object> ();
358                 t1 [Int32Enum.A] = "foo";
359
360                 var t2 = new Dictionary<UInt32Enum, object> ();
361                 t2 [UInt32Enum.A] = "foo";
362
363                 var t3 = new Dictionary<UInt16Enum, object> ();
364                 t3 [UInt16Enum.A] = "foo";
365
366                 var t4 = new Dictionary<Int16Enum, object> ();
367                 t4 [Int16Enum.A] = "foo";
368
369                 var t5 = new Dictionary<Int8Enum, object> ();
370                 t5 [Int8Enum.A] = "foo";
371
372                 var t6 = new Dictionary<UInt8Enum, object> ();
373                 t6 [UInt8Enum.A] = "foo";
374
375                 return 0;
376         }
377
378         [Category ("DYNCALL")]
379         public static int test_0_array_accessor_runtime_invoke_ref () {
380                 var t = typeof (string[]);
381                 var arr = Array.CreateInstance (typeof (string), 1);
382                 arr.GetType ().GetMethod ("Set").Invoke (arr, new object [] { 0, "A" });
383                 var res = (string)arr.GetType ().GetMethod ("Get").Invoke (arr, new object [] { 0 });
384                 if (res != "A")
385                         return 1;
386                 return 0;
387         }
388
389         public static void SetArrayValue_<T> (T[] values) {
390                 values.Select (x => x).ToArray ();
391         }
392
393         [Category ("GSHAREDVT")]
394         public static int test_0_delegate_invoke_wrappers_gsharedvt () {
395                 var enums = new LongEnum [] { LongEnum.A };
396                 SetArrayValue_ (enums);
397                 return 0;
398         }
399
400         struct LargeStruct {
401                 public int a, b, c, d;
402         }
403
404         [MethodImplAttribute (MethodImplOptions.NoInlining)]
405         public static bool GetHasValue<T>(T? value) where T : struct
406         {
407                 return value.HasValue;
408         }
409
410         [Category ("DYNCALL")]
411         [Category ("!FULLAOT-AMD64")]
412         public static int test_0_large_nullable_invoke () {
413                 var s = new LargeStruct () { a = 1, b = 2, c = 3, d = 4 };
414
415                 GetHasValue<LargeStruct> (s);
416
417 #if __MOBILE__
418                 var m = typeof(AotTests).GetMethod("GetHasValue", BindingFlags.Static | BindingFlags.Public);
419 #else
420                 var m = typeof(Tests).GetMethod("GetHasValue", BindingFlags.Static | BindingFlags.Public);
421 #endif
422
423                 Type type = typeof (LargeStruct?).GetGenericArguments () [0];
424                 bool b1 = (bool)m.MakeGenericMethod (new Type[] {type}).Invoke (null, new object[] { s });
425                 if (!b1)
426                         return 1;
427                 bool b2 = (bool)m.MakeGenericMethod (new Type[] {type}).Invoke (null, new object[] { null });
428                 if (b2)
429                         return 2;
430                 return 0;
431         }
432
433         struct FpStruct {
434                 public float a, b, c;
435         }
436
437         struct LargeStruct2 {
438                 public FpStruct x;
439                 public int a, b, c, d, e, f, g, h;
440         }
441
442         [MethodImplAttribute (MethodImplOptions.NoInlining)]
443         static int pass_hfa_on_stack (FpStruct s1, FpStruct s2, FpStruct s3) {
444                 return (int)s3.c;
445         }
446
447         public static int test_10_arm64_hfa_on_stack_llvm () {
448                 var arr = new LargeStruct2 [10, 10];
449                 for (int i = 0; i < 10; ++i)
450                         for (int j = 0; j < 10; ++j)
451                                 arr [i, j].x = new FpStruct ();
452
453                 var s1 = new FpStruct () { a = 1, b = 1, c = 10 };
454                 return pass_hfa_on_stack (s1, s1, s1);
455         }
456
457         public static int test_0_get_current_method () {
458                 var m = MethodBase.GetCurrentMethod ();
459 #if __MOBILE__
460                 var m2 = typeof (AotTests).GetMethod ("test_0_get_current_method");
461 #else
462                 var m2 = typeof (Tests).GetMethod ("test_0_get_current_method");
463 #endif
464                 return m == m2 ? 0 : 1;
465         }
466
467         class GetCurrentMethodClass<T> {
468                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
469                 public MethodBase get_current () {
470                         return MethodBase.GetCurrentMethod ();
471                 }
472         }
473
474         public static int test_0_get_current_method_generic () {
475                 var c = new GetCurrentMethodClass<string> ();
476                 var m = c.get_current ();
477                 var m2 = typeof (GetCurrentMethodClass<>).GetMethod ("get_current");
478                 return m == m2 ? 0 : 1;
479         }
480
481         public static int test_0_array_wrappers_runtime_invoke () {
482                 string[][] arr = new string [10][];
483                 IEnumerable<string[]> iface = arr;
484                 var m = typeof(IEnumerable<string[]>).GetMethod ("GetEnumerator");
485                 m.Invoke (arr, null);
486                 return 0;
487         }
488 }