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