Merge pull request #2003 from esdrubal/seq_test_fix2
[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
9 /*
10  * Regression tests for the AOT/FULL-AOT code.
11  */
12
13 #if MOBILE
14 class AotTests
15 #else
16 class Tests
17 #endif
18 {
19 #if !MOBILE
20         static int Main (String[] args) {
21                 return TestDriver.RunTests (typeof (Tests), args);
22         }
23 #endif
24
25         public delegate void ArrayDelegate (int[,] arr);
26
27         static int test_0_array_delegate_full_aot () {
28                 ArrayDelegate d = delegate (int[,] arr) {
29                 };
30                 int[,] a = new int[5, 6];
31                 d.BeginInvoke (a, null, null);
32                 return 0;
33         }
34
35         struct Struct1 {
36                 public double a, b;
37         }
38
39         struct Struct2 {
40                 public float a, b;
41         }
42
43         class Foo<T> {
44                 /* The 'd' argument is used to shift the register indexes so 't' doesn't start at the first reg */
45                 public static T Get_T (double d, T t) {
46                         return t;
47                 }
48         }
49
50         class Foo2<T> {
51                 public static T Get_T (double d, T t) {
52                         return t;
53                 }
54                 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) {
55                         return t;
56                 }
57         }
58
59         class Foo3<T> {
60                 public static T Get_T (double d, T t) {
61                         return Foo2<T>.Get_T (d, t);
62                 }
63         }
64
65         [Category ("DYNCALL")]
66         static int test_0_arm64_dyncall_double () {
67                 double arg1 = 1.0f;
68                 double s = 2.0f;
69                 var res = (double)typeof (Foo<double>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
70                 if (res != 2.0f)
71                         return 1;
72                 return 0;
73         }
74
75         [Category ("DYNCALL")]
76         static int test_0_arm64_dyncall_float () {
77                 double arg1 = 1.0f;
78                 float s = 2.0f;
79                 var res = (float)typeof (Foo<float>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
80                 if (res != 2.0f)
81                         return 1;
82                 return 0;
83         }
84
85         [Category ("DYNCALL")]
86         static int test_0_arm64_dyncall_hfa_double () {
87                 double arg1 = 1.0f;
88                 // HFA with double members
89                 var s = new Struct1 ();
90                 s.a = 1.0f;
91                 s.b = 2.0f;
92                 var s_res = (Struct1)typeof (Foo<Struct1>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
93                 if (s_res.a != 1.0f || s_res.b != 2.0f)
94                         return 1;
95                 return 0;
96         }
97
98         [Category ("DYNCALL")]
99         static int test_0_arm64_dyncall_hfa_float () {
100                 double arg1 = 1.0f;
101                 var s = new Struct2 ();
102                 s.a = 1.0f;
103                 s.b = 2.0f;
104                 var s_res = (Struct2)typeof (Foo<Struct2>).GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
105                 if (s_res.a != 1.0f || s_res.b != 2.0f)
106                         return 1;
107                 return 0;
108         }
109
110         [Category ("DYNCALL")]
111         [Category ("GSHAREDVT")]
112         static int test_0_arm64_dyncall_gsharedvt_out_hfa_double () {
113                 /* gsharedvt out trampoline with double hfa argument */
114                 double arg1 = 1.0f;
115
116                 var s = new Struct1 ();
117                 s.a = 1.0f;
118                 s.b = 2.0f;
119                 // Call Foo2.Get_T directly, so its gets an instance
120                 Foo2<Struct1>.Get_T (arg1, s);
121                 Type t = typeof (Foo3<>).MakeGenericType (new Type [] { typeof (Struct1) });
122                 // Call Foo3.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
123                 var s_res = (Struct1)t.GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
124                 if (s_res.a != 1.0f || s_res.b != 2.0f)
125                         return 1;
126                 return 0;
127         }
128
129         [Category ("DYNCALL")]
130         [Category ("GSHAREDVT")]
131         static int test_0_arm64_dyncall_gsharedvt_out_hfa_float () {
132                 /* gsharedvt out trampoline with double hfa argument */
133                 double arg1 = 1.0f;
134
135                 var s = new Struct2 ();
136                 s.a = 1.0f;
137                 s.b = 2.0f;
138                 // Call Foo2.Get_T directly, so its gets an instance
139                 Foo2<Struct2>.Get_T (arg1, s);
140                 Type t = typeof (Foo3<>).MakeGenericType (new Type [] { typeof (Struct2) });
141                 // Call Foo3.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
142                 var s_res = (Struct2)t.GetMethod ("Get_T").Invoke (null, new object [] { arg1, s });
143                 if (s_res.a != 1.0f || s_res.b != 2.0f)
144                         return 1;
145                 return 0;
146         }
147
148         interface IFaceFoo4<T> {
149                 T Get_T (double d, T t);
150                 T Get_T2 (double d, T t);
151         }
152
153         class Foo4<T> : IFaceFoo4<T> {
154                 public T Get_T (double d, T t) {
155                         return Foo2<T>.Get_T (d, t);
156                 }
157                 public T Get_T2 (double d, T t) {
158                         return Foo2<T>.Get_T2 (d, 1, 2, 3, 4, 5, 6, 7, 8, t);
159                 }
160         }
161
162         struct VTypeByRefStruct {
163                 public long o1, o2, o3;
164         }
165
166         [Category ("GSHAREDVT")]
167         public static int test_0_arm64_gsharedvt_out_vtypebyref () {
168                 /* gsharedvt out trampoline with vtypebyref argument */
169                 var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 };
170
171                 // Call Foo2.Get_T directly, so its gets an instance
172                 Foo2<VTypeByRefStruct>.Get_T (1.0f, s);
173                 var o = (IFaceFoo4<VTypeByRefStruct>)Activator.CreateInstance (typeof (Foo4<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) }));
174                 // Call Foo4.Get_T, this will call the gsharedvt instance, which will call the non-gsharedvt instance
175                 var s_res = o.Get_T (1.0f, s);
176                 if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
177                         return 1;
178                 // Same with the byref argument passed on the stack
179                 s_res = o.Get_T2 (1.0f, s);
180                 if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
181                         return 2;
182                 return 0;
183         }
184
185         class Foo5<T> {
186                 public static T Get_T (object o) {
187                         return (T)o;
188                 }
189         }
190
191         [Category ("DYNCALL")]
192         static int test_0_arm64_dyncall_vtypebyref_ret () {
193                 var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 };
194                 Type t = typeof (Foo5<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) });
195                 var o = Activator.CreateInstance (t);
196                 try {
197                         var s_res = (VTypeByRefStruct)t.GetMethod ("Get_T").Invoke (o, new object [] { s });
198                         if (s_res.o1 != 1 || s_res.o2 != 2 || s_res.o3 != 3)
199                                 return 1;
200                 } catch (TargetInvocationException) {
201                         return 2;
202                 }
203                 return 0;
204         }
205
206         class Foo6 {
207                 public T reg_stack_split_inner<T> (int i, int j, T l) {
208                         return l;
209                 }
210         }
211
212         [Category("DYNCALL")]
213         static int test_0_arm_dyncall_reg_stack_split () {
214                 var m = typeof (Foo6).GetMethod ("reg_stack_split_inner").MakeGenericMethod (new Type[] { typeof (long) });
215                 var o = new Foo6 ();
216                 if ((long)m.Invoke (o, new object [] { 1, 2, 3 }) != 3)
217                         return 1;
218                 if ((long)m.Invoke (o, new object [] { 1, 2, Int64.MaxValue }) != Int64.MaxValue)
219                         return 2;
220                 return 0;
221         }
222
223         static int test_0_partial_sharing_regress_30204 () {
224                 var t = typeof (System.Collections.Generic.Comparer<System.Collections.Generic.KeyValuePair<string, string>>);
225                 var d = new SortedDictionary<string, string> ();
226                 d.Add ("key1", "banana");
227                 return d ["key1"] == "banana" ? 0 : 1;
228         }
229
230         class NullableMethods {
231                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
232                 public static bool GetHasValue<T>(Nullable<T> value) where T : struct {
233                         return value.HasValue;
234                 }
235
236                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
237                 public static T GetValue<T>(Nullable<T> value) where T : struct {
238                         return value.Value;
239                 }
240         }
241
242         [Category ("DYNCALL")]
243         public static int test_0_dyncall_nullable () {
244                 int? v;
245
246                 v = 42;
247                 NullableMethods.GetHasValue (v);
248                 bool b = (bool)typeof (NullableMethods).GetMethod ("GetHasValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
249                 if (!b)
250                         return 1;
251                 v = null;
252                 b = (bool)typeof (NullableMethods).GetMethod ("GetHasValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
253                 if (b)
254                         return 2;
255
256                 v = 42;
257                 NullableMethods.GetValue (v);
258                 var res = (int)typeof (NullableMethods).GetMethod ("GetValue").MakeGenericMethod (new Type [] { typeof (int) }).Invoke (null, new object [] { v });
259                 if (res != 42)
260                         return 3;
261                 return 0;
262         }
263
264         enum AnEnum {
265                 A = 0,
266                 B = 1
267         }
268
269         public static int test_0_enum_eq_comparer () {
270                 var c = EqualityComparer<AnEnum>.Default;
271                 return (!c.Equals (AnEnum.A, AnEnum.B) && c.Equals (AnEnum.A, AnEnum.A)) ? 0 : 1;
272         }
273
274         public static int test_0_enum_comparer () {
275                 var c = Comparer<AnEnum>.Default;
276                 return c.Compare (AnEnum.A, AnEnum.A);
277         }
278
279         private static Dictionary<long, TValue> ConvertDictionary<TValue>(Dictionary<long, IList<TValue>> source) {
280                 return source.ToDictionary(pair => pair.Key, pair => pair.Value[0]);
281         }
282
283         [Category ("GSHAREDVT")]
284         public static int test_0_gsharedvt_non_variable_arg () {
285                 Dictionary<long, IList<int>> data = new Dictionary<long, IList<int>>
286             {
287                                 {123L, new List<int> {2}}
288             };
289                 Dictionary<long, int> newDict = ConvertDictionary(data);
290                 if (newDict.Count != 1)
291                         return 1;
292                 return 0;
293         }
294 }