Merge pull request #2290 from akoeplinger/msvc-mono-architecture
[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         static int test_0_arm64_dyncall_hfa_double () {
88                 double arg1 = 1.0f;
89                 // HFA with double members
90                 var s = new Struct1 ();
91                 s.a = 1.0f;
92                 s.b = 2.0f;
93                 var s_res = (Struct1)typeof (Foo<Struct1>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
94                 if (s_res.a != 1.0f || s_res.b != 2.0f)
95                         return 1;
96                 return 0;
97         }
98
99         [Category ("DYNCALL")]
100         static int test_0_arm64_dyncall_hfa_float () {
101                 double arg1 = 1.0f;
102                 var s = new Struct2 ();
103                 s.a = 1.0f;
104                 s.b = 2.0f;
105                 var s_res = (Struct2)typeof (Foo<Struct2>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
106                 if (s_res.a != 1.0f || s_res.b != 2.0f)
107                         return 1;
108                 return 0;
109         }
110
111         [Category ("DYNCALL")]
112         [Category ("GSHAREDVT")]
113         static int test_0_arm64_dyncall_gsharedvt_out_hfa_double () {
114                 /* gsharedvt out trampoline with double hfa argument */
115                 double arg1 = 1.0f;
116
117                 var s = new Struct1 ();
118                 s.a = 1.0f;
119                 s.b = 2.0f;
120                 // Call Foo2.Get_T directly, so its gets an instance
121                 Foo2<Struct1>.Get_T (arg1, s);
122                 Type t = typeof (Foo3<>).MakeGenericType (new Type [] { typeof (Struct1) });
123                 // Call Foo3.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
124                 var s_res = (Struct1)t.GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
125                 if (s_res.a != 1.0f || s_res.b != 2.0f)
126                         return 1;
127                 return 0;
128         }
129
130         [Category ("DYNCALL")]
131         [Category ("GSHAREDVT")]
132         static int test_0_arm64_dyncall_gsharedvt_out_hfa_float () {
133                 /* gsharedvt out trampoline with double hfa argument */
134                 double arg1 = 1.0f;
135
136                 var s = new Struct2 ();
137                 s.a = 1.0f;
138                 s.b = 2.0f;
139                 // Call Foo2.Get_T directly, so its gets an instance
140                 Foo2<Struct2>.Get_T (arg1, s);
141                 Type t = typeof (Foo3<>).MakeGenericType (new Type [] { typeof (Struct2) });
142                 // Call Foo3.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
143                 var s_res = (Struct2)t.GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
144                 if (s_res.a != 1.0f || s_res.b != 2.0f)
145                         return 1;
146                 return 0;
147         }
148
149         interface IFaceFoo4<T> {
150                 T Get_T (double d, T t);
151                 T Get_T2 (double d, T t);
152         }
153
154         class Foo4<T> : IFaceFoo4<T> {
155                 public T Get_T (double d, T t) {
156                         return Foo2<T>.Get_T (d, t);
157                 }
158                 public T Get_T2 (double d, T t) {
159                         return Foo2<T>.Get_T2 (d, 1, 2, 3, 4, 5, 6, 7, 8, t);
160                 }
161         }
162
163         struct VTypeByRefStruct {
164                 public long o1, o2, o3;
165         }
166
167         [Category ("GSHAREDVT")]
168         public static int test_0_arm64_gsharedvt_out_vtypebyref () {
169                 /* gsharedvt out trampoline with vtypebyref argument */
170                 var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 };
171
172                 // Call Foo2.Get_T directly, so its gets an instance
173                 Foo2<VTypeByRefStruct>.Get_T (1.0f, s);
174                 var o = (IFaceFoo4<VTypeByRefStruct>)Activator.CreateInstance (typeof (Foo4<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) }));
175                 // Call Foo4.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
176                 var s_res = o.Get_T (1.0f, s);
177                 if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
178                         return 1;
179                 // Same with the byref argument passed on the stack
180                 s_res = o.Get_T2 (1.0f, s);
181                 if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
182                         return 2;
183                 return 0;
184         }
185
186         class Foo5<T> {
187                 public static T Get_T (object o) {
188                         return (T)o;
189                 }
190         }
191
192         [Category ("DYNCALL")]
193         static int test_0_arm64_dyncall_vtypebyref_ret () {
194                 var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 };
195                 Type t = typeof (Foo5<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) });
196                 var o = Activator.CreateInstance (t);
197                 try {
198                         var s_res = (VTypeByRefStruct)t.GetMethod ("Get_T").Invoke (o, new object [] { s });
199                         if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
200                                 return 1;
201                 } catch (TargetInvocationException) {
202                         return 2;
203                 }
204                 return 0;
205         }
206
207         class Foo6 {
208                 public T reg_stack_split_inner<T> (int i, int j, T l) {
209                         return l;
210                 }
211         }
212
213         [Category("DYNCALL")]
214         static int test_0_arm_dyncall_reg_stack_split () {
215                 var m = typeof (Foo6).GetMethod ("reg_stack_split_inner").MakeGenericMethod (new Type[] { typeof (long) });
216                 var o = new Foo6 ();
217                 if ((long)m.Invoke (o, new object [] { 1, 2, 3 }) != 3)
218                         return 1;
219                 if ((long)m.Invoke (o, new object [] { 1, 2, Int64.MaxValue }) != Int64.MaxValue)
220                         return 2;
221                 return 0;
222         }
223
224         static int test_0_partial_sharing_regress_30204 () {
225                 var t = typeof (System.Collections.Generic.Comparer<System.Collections.Generic.KeyValuePair<string, string>>);
226                 var d = new SortedDictionary<string, string> ();
227                 d.Add ("key1", "banana");
228                 return d ["key1"] == "banana" ? 0 : 1;
229         }
230
231         class NullableMethods {
232                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
233                 public static bool GetHasValue<T>(Nullable<T> value) where T : struct {
234                         return value.HasValue;
235                 }
236
237                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
238                 public static T GetValue<T>(Nullable<T> value) where T : struct {
239                         return value.Value;
240                 }
241         }
242
243         [Category ("DYNCALL")]
244         public static int test_0_dyncall_nullable () {
245                 int? v;
246
247                 v = 42;
248                 NullableMethods.GetHasValue (v);
249                 bool b = (bool)typeof (NullableMethods).GetMethod ("GetHasValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
250                 if (!b)
251                         return 1;
252                 v = null;
253                 b = (bool)typeof (NullableMethods).GetMethod ("GetHasValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
254                 if (b)
255                         return 2;
256
257                 v = 42;
258                 NullableMethods.GetValue (v);
259                 var res = (int)typeof (NullableMethods).GetMethod ("GetValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
260                 if (res != 42)
261                         return 3;
262                 return 0;
263         }
264
265         enum AnEnum {
266                 A = 0,
267                 B = 1
268         }
269
270         public static int test_0_enum_eq_comparer () {
271                 var c = EqualityComparer<AnEnum>.Default;
272                 return (!c.Equals (AnEnum.A, AnEnum.B) && c.Equals (AnEnum.A, AnEnum.A)) ? 0 : 1;
273         }
274
275         public static int test_0_enum_comparer () {
276                 var c = Comparer<AnEnum>.Default;
277                 return c.Compare (AnEnum.A, AnEnum.A);
278         }
279
280         private static Dictionary<long, TValue> ConvertDictionary<TValue>(Dictionary<long, IList<TValue>> source) {
281                 return source.ToDictionary(pair => pair.Key, pair => pair.Value[0]);
282         }
283
284         [Category ("GSHAREDVT")]
285         public static int test_0_gsharedvt_non_variable_arg () {
286                 Dictionary<long, IList<int>> data = new Dictionary<long, IList<int>>
287             {
288                                 {123L, new List<int> {2}}
289             };
290                 Dictionary<long, int> newDict = ConvertDictionary(data);
291                 if (newDict.Count != 1)
292                         return 1;
293                 return 0;
294         }
295
296         enum LongEnum : ulong {
297                 A = 1
298                         }
299
300         public static int test_0_long_enum_eq_comparer () {
301                 var c = EqualityComparer<LongEnum>.Default;
302                 c.GetHashCode (LongEnum.A);
303                 return 0;
304         }
305
306         enum UInt32Enum : uint {
307                 A = 1
308                         }
309
310         enum Int32Enum : int {
311                 A = 1
312                         }
313
314         enum Int16Enum : short {
315                 A = 1
316                         }
317
318         enum UInt16Enum : ushort {
319                 A = 1
320                         }
321
322         enum Int8Enum : sbyte {
323                 A = 1
324                         }
325
326         enum UInt8Enum : byte {
327                 A = 1
328                         }
329
330         public static int test_0_int_enum_eq_comparer () {
331                 var t1 = new Dictionary<Int32Enum, object> ();
332                 t1 [Int32Enum.A] = "foo";
333
334                 var t2 = new Dictionary<UInt32Enum, object> ();
335                 t2 [UInt32Enum.A] = "foo";
336
337                 var t3 = new Dictionary<UInt16Enum, object> ();
338                 t3 [UInt16Enum.A] = "foo";
339
340                 var t4 = new Dictionary<Int16Enum, object> ();
341                 t4 [Int16Enum.A] = "foo";
342
343                 var t5 = new Dictionary<Int8Enum, object> ();
344                 t5 [Int8Enum.A] = "foo";
345
346                 var t6 = new Dictionary<UInt8Enum, object> ();
347                 t6 [UInt8Enum.A] = "foo";
348
349                 return 0;
350         }
351
352         public static int test_0_array_accessor_runtime_invoke_ref () {
353                 var t = typeof (string[]);
354                 var arr = Array.CreateInstance (typeof (string), 1);
355                 arr.GetType ().GetMethod ("Set").Invoke (arr, new object [] { 0, "A" });
356                 var res = (string)arr.GetType ().GetMethod ("Get").Invoke (arr, new object [] { 0 });
357                 if (res != "A")
358                         return 1;
359                 return 0;
360         }
361
362         public static void SetArrayValue_<T> (T[] values) {
363                 values.Select (x => x).ToArray ();
364         }
365
366         [Category ("GSHAREDVT")]
367         public static int test_0_delegate_invoke_wrappers_gsharedvt () {
368                 var enums = new LongEnum [] { LongEnum.A };
369                 SetArrayValue_ (enums);
370                 return 0;
371         }
372
373         struct LargeStruct {
374                 public int a, b, c, d;
375         }
376
377         [MethodImplAttribute (MethodImplOptions.NoInlining)]
378         public static bool GetHasValue<T>(T? value) where T : struct
379         {
380                 return value.HasValue;
381         }
382
383         [Category ("DYNCALL")]
384         public static int test_0_large_nullable_invoke () {
385                 var s = new LargeStruct () { a = 1, b = 2, c = 3, d = 4 };
386
387                 GetHasValue<LargeStruct> (s);
388
389 #if __MOBILE__
390                 var m = typeof(AotTests).GetMethod("GetHasValue", BindingFlags.Static | BindingFlags.Public);
391 #else
392                 var m = typeof(Tests).GetMethod("GetHasValue", BindingFlags.Static | BindingFlags.Public);
393 #endif
394
395                 Type type = typeof (LargeStruct?).GetGenericArguments () [0];
396                 bool b1 = (bool)m.MakeGenericMethod (new Type[] {type}).Invoke (null, new object[] { s });
397                 if (!b1)
398                         return 1;
399                 bool b2 = (bool)m.MakeGenericMethod (new Type[] {type}).Invoke (null, new object[] { null });
400                 if (b2)
401                         return 2;
402                 return 0;
403         }
404 }