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