Merge pull request #649 from DavidS/feature/implement-additional-reference-path
[mono.git] / mono / mini / gshared.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Runtime.CompilerServices;
4
5 struct Foo {
6         public int i, j, k, l, m, n;
7 }
8
9 struct GFoo<T> {
10         public T dummy;
11         public T t;
12         public int i;
13         public Foo f;
14         public static T static_dummy;
15         public static T static_t;
16         public static Foo static_f;
17 }
18
19 struct GFoo2<T> {
20         public T t, t2;
21 }
22
23 class GFoo3<T> {
24         public T t, t2;
25
26         public GFoo3 () {
27         }
28
29         [MethodImplAttribute (MethodImplOptions.NoInlining)]
30         public GFoo3 (T i1, T i2) {
31                 t = i1;
32                 t2 = i2;
33         }
34 }
35
36 //
37 // Tests for generic sharing of vtypes.
38 // The tests use arrays to pass/receive values to keep the calling convention of the methods stable, which is a current limitation of the runtime support for gsharedvt.
39 //
40
41 // FIXME: Add mixed ref/noref tests, i.e. Dictionary<string, int>
42
43 #if MOBILE
44 public class GSharedTests
45 #else
46 public class Tests
47 #endif
48 {
49 #if !MOBILE
50         public static int Main (String[] args) {
51                 return TestDriver.RunTests (typeof (Tests), args);
52         }
53 #endif
54
55         [MethodImplAttribute (MethodImplOptions.NoInlining)]
56         static void gshared<T> (T [] array, int i, int j) {
57                 T tmp = array [i];
58                 array [i] = array [j];
59                 array [j] = tmp;
60         }
61
62         // Test that the gshared and gsharedvt versions don't mix
63         public static int test_0_vt_gshared () {
64                 string[] sarr = new string [2] { "A", "B" };
65
66                 gshared<string> (sarr, 0, 1);
67
68                 Foo[] arr = new Foo [2];
69                 arr [0] = new Foo () { i = 1, j = 2 };
70                 arr [1] = new Foo () { i = 3, j = 4 };
71
72                 gshared<Foo> (arr, 0, 1);
73                 if (arr [0].i != 3 || arr [0].j != 4)
74                         return 1;
75                 if (arr [1].i != 1 || arr [1].j != 2)
76                         return 2;
77
78                 return 0;
79         }
80
81         static void ldelem_stelem<T> (T [] array, int i, int j) {
82                 T tmp = array [i];
83                 array [i] = array [j];
84                 array [j] = tmp;
85         }
86
87         public static int test_0_vt_ldelem_stelem () {
88                 Foo[] arr = new Foo [2];
89                 arr [0] = new Foo () { i = 1, j = 2 };
90                 arr [1] = new Foo () { i = 3, j = 4 };
91
92                 ldelem_stelem<Foo> (arr, 0, 1);
93                 if (arr [0].i != 3 || arr [0].j != 4)
94                         return 1;
95                 if (arr [1].i != 1 || arr [1].j != 2)
96                         return 2;
97
98                 int[] arr2 = new int [2] { 1, 2 };
99                 ldelem_stelem<int> (arr2, 0, 1);
100                 if (arr2 [0] !=2 || arr2 [1] != 1)
101                         return 3;
102
103                 return 0;
104         }
105
106         [MethodImplAttribute (MethodImplOptions.NoInlining)]
107         private static void initobj<T> (T [] array, int i, int j) {
108                 T x = default(T);
109                 array [i] = x;
110         }
111
112         public static int test_0_vt_initobj () {
113                 Foo[] arr = new Foo [2];
114                 arr [0] = new Foo () { i = 1, j = 2 };
115                 arr [1] = new Foo () { i = 3, j = 4 };
116
117                 initobj<Foo> (arr, 0, 1);
118                 if (arr [0].i != 0 || arr [0].j != 0)
119                         return 1;
120                 if (arr [1].i != 3 || arr [1].j != 4)
121                         return 2;
122                 return 0;
123         }
124
125         [MethodImplAttribute (MethodImplOptions.NoInlining)]
126         static T ldobj_stobj<T> (ref T t1, ref T t2) {
127                 t1 = t2;
128                 T t = t2;
129                 t2 = default(T);
130                 return t;
131         }
132
133         public static int test_0_vt_ldobj_stobj () {
134                 int i = 5;
135                 int j = 6;
136                 if (ldobj_stobj (ref i, ref j) != 6)
137                         return 1;
138                 if (i != 6 || j != 0)
139                         return 2;
140                 double d1 = 1.0;
141                 double d2 = 2.0;
142                 if (ldobj_stobj (ref d1, ref d2) != 2.0)
143                         return 3;
144                 if (d1 != 2.0 || d2 != 0.0)
145                         return 4;               
146                 return 0;
147         }
148
149         [MethodImplAttribute (MethodImplOptions.NoInlining)]
150         private static void box<T1, T> (T [] array, object[] arr) {
151                 object x = array [0];
152                 arr [0] = x;
153         }
154
155         public static int test_0_vt_box () {
156                 Foo[] arr = new Foo [2];
157                 arr [0] = new Foo () { i = 1, j = 2 };
158
159                 object[] arr2 = new object [16];
160                 box<int, Foo> (arr, arr2);
161                 if (arr2 [0].GetType () != typeof (Foo))
162                         return 1;
163                 Foo f = (Foo)arr2 [0];
164                 if (f.i != 1 || f.j != 2)
165                         return 2;
166                 string[] arr3 = new string [16];
167                 object[] arr4 = new object [16];
168                 arr3 [0] = "OK";
169                 box<int, string> (arr3, arr4);
170                 if (arr4 [0] != (object)arr3 [0])
171                         return 3;
172                 return 0;
173         }
174
175         [MethodImplAttribute (MethodImplOptions.NoInlining)]
176         private static void unbox_any<T> (T [] array, object[] arr) {
177                 T t = (T)arr [0];
178                 array [0] = t;
179         }
180
181         public static int test_0_vt_unbox_any () {
182                 int[] iarr = new int [16];
183                 unbox_any<int> (iarr, new object [] { 12 });
184
185                 Foo[] arr = new Foo [2];
186
187                 object[] arr2 = new object [16];
188                 arr2 [0] = new Foo () { i = 1, j = 2 };
189                 unbox_any<Foo> (arr, arr2);
190                 if (arr [0].i != 1 || arr [0].j != 2)
191                         return 2;
192                 return 0;
193         }
194
195         interface IFaceUnbox {
196                 T Unbox<T, T2> (T t, T2 t2, object o);
197         }
198
199         class ClassUnbox : IFaceUnbox {
200                 public T Unbox<T, T2> (T t, T2 t2, object o) {
201                         return (T)o;
202                 }
203         }
204
205         // unbox.any on a ref type in a gsharedvt method
206         public static int test_0_ref_gsharedvt_aot_unbox_any () {
207                 IFaceUnbox iface = new ClassUnbox ();
208                 string s = iface.Unbox<string, int> ("A", 2, "A");
209                 if (s != "A")
210                         return 1;
211                 return 0;
212         }
213
214         [MethodImplAttribute (MethodImplOptions.NoInlining)]
215         static void ldfld_nongeneric<T> (GFoo<T>[] foo, int[] arr) {
216                 arr [0] = foo [0].i;
217         }
218
219         [MethodImplAttribute (MethodImplOptions.NoInlining)]
220         static void ldfld<T> (GFoo<T>[] foo, T[] arr) {
221                 arr [0] = foo [0].t;
222         }
223
224         [MethodImplAttribute (MethodImplOptions.NoInlining)]
225         static void stfld_nongeneric<T> (GFoo<T>[] foo, int[] arr) {
226                 foo [0].i = arr [0];
227         }
228
229         [MethodImplAttribute (MethodImplOptions.NoInlining)]
230         static void stfld<T> (GFoo<T>[] foo, T[] arr) {
231                 foo [0].t = arr [0];
232         }
233
234         [MethodImplAttribute (MethodImplOptions.NoInlining)]
235         static void ldflda<T> (GFoo<T>[] foo, int[] arr) {
236                 arr [0] = foo [0].f.i;
237         }
238
239         public static int test_0_vt_ldfld_stfld () {
240                 var foo = new GFoo<Foo> () { t = new Foo () { i = 1, j = 2 }, i = 5, f = new Foo () { i = 5, j = 6 } };
241                 var farr = new GFoo<Foo>[] { foo };
242
243                 /* Normal fields with a variable offset */
244                 var iarr = new int [10];
245                 ldfld_nongeneric<Foo> (farr, iarr);
246                 if (iarr [0] != 5)
247                         return 1;
248                 iarr [0] = 16;
249                 stfld_nongeneric<Foo> (farr, iarr);
250                 if (farr [0].i != 16)
251                         return 2;
252
253                 /* Variable type field with a variable offset */
254                 var arr = new Foo [10];
255                 ldfld<Foo> (farr, arr);
256                 if (arr [0].i != 1 || arr [0].j != 2)
257                         return 3;
258                 arr [0] = new Foo () { i = 3, j = 4 };
259                 stfld<Foo> (farr, arr);
260                 if (farr [0].t.i != 3 || farr [0].t.j != 4)
261                         return 4;
262
263                 ldflda<Foo> (farr, iarr);
264                 if (iarr [0] != 5)
265                         return 5;
266
267                 return 0;
268         }
269
270         [MethodImplAttribute (MethodImplOptions.NoInlining)]
271         static void stsfld<T> (T[] arr) {
272                 GFoo<T>.static_t = arr [0];
273         }
274
275         [MethodImplAttribute (MethodImplOptions.NoInlining)]
276         static void ldsfld<T> (T[] arr) {
277                 arr [0] = GFoo<T>.static_t;
278         }
279
280         [MethodImplAttribute (MethodImplOptions.NoInlining)]
281         static void ldsflda<T> (int[] iarr) {
282                 iarr [0] = GFoo<T>.static_f.i;
283         }
284         
285         public static int test_0_stsfld () {
286                 Foo[] farr = new Foo [] { new Foo () { i = 1, j = 2 } };
287                 stsfld<Foo> (farr);
288
289                 if (GFoo<Foo>.static_t.i != 1 || GFoo<Foo>.static_t.j != 2)
290                         return 1;
291
292                 Foo[] farr2 = new Foo [1];
293                 ldsfld<Foo> (farr2);
294                 if (farr2 [0].i != 1 || farr2 [0].j != 2)
295                         return 2;
296
297                 var iarr = new int [10];
298                 GFoo<Foo>.static_f = new Foo () { i = 5, j = 6 };
299                 ldsflda<Foo> (iarr);
300                 if (iarr [0] != 5)
301                         return 3;
302
303                 return 0;
304         }
305
306         [MethodImplAttribute (MethodImplOptions.NoInlining)]
307         static object newarr<T> () {
308                 object o = new T[10];
309                 return o;
310         }
311
312         public static int test_0_vt_newarr () {
313                 object o = newarr<Foo> ();
314                 if (!(o is Foo[]))
315                         return 1;
316                 return 0;
317         }
318
319         [MethodImplAttribute (MethodImplOptions.NoInlining)]
320         static Type ldtoken<T> () {
321                 return typeof (GFoo<T>);
322         }
323
324         public static int test_0_vt_ldtoken () {
325                 Type t = ldtoken<Foo> ();
326                 if (t != typeof (GFoo<Foo>))
327                         return 1;
328                 t = ldtoken<int> ();
329                 if (t != typeof (GFoo<int>))
330                         return 2;
331
332                 return 0;
333         }
334
335         public static int test_0_vtype_list () {
336                 List<int> l = new List<int> ();
337
338                 l.Add (5);
339                 if (l.Count != 1)
340                         return 1;
341                 return 0;
342         }
343
344         [MethodImplAttribute (MethodImplOptions.NoInlining)]
345         static int args_simple<T> (T t, int i) {
346                 return i;
347         }
348
349         [MethodImplAttribute (MethodImplOptions.NoInlining)]
350         static int args_simple<T> (T t, int i, T t2) {
351                 return i;
352         }
353
354         [MethodImplAttribute (MethodImplOptions.NoInlining)]
355         static Type args_rgctx<T> (T t, int i) {
356                 return typeof (T);
357         }
358
359         [MethodImplAttribute (MethodImplOptions.NoInlining)]
360         static Type eh_in<T> (T t, int i) {
361                 throw new OverflowException ();
362         }
363
364         [MethodImplAttribute (MethodImplOptions.NoInlining)]
365         static T return_t<T> (T t) {
366                 return t;
367         }
368
369         [MethodImplAttribute (MethodImplOptions.NoInlining)]
370         T return_this_t<T> (T t) {
371                 return t;
372         }
373
374         public static int test_0_gsharedvt_in () {
375                 // Check that the non-generic argument is passed at the correct stack position
376                 int r = args_simple<bool> (true, 42);
377                 if (r != 42)
378                         return 1;
379                 r = args_simple<Foo> (new Foo (), 43);
380                 if (r != 43)
381                         return 2;
382                 // Check that the proper rgctx is passed to the method
383                 Type t = args_rgctx<int> (5, 42);
384                 if (t != typeof (int))
385                         return 3;
386                 var v = args_simple<GFoo2<int>> (new GFoo2<int> () { t = 11, t2 = 12 }, 44, new GFoo2<int> () { t = 11, t2 = 12 });
387                 if (v != 44)
388                         return 4;
389                 // Check that EH works properly
390                 try {
391                         eh_in<int> (1, 2);
392                 } catch (OverflowException) {
393                 }
394                 return 0;
395         }
396
397         public static int test_0_gsharedvt_in_ret () {
398                 int i = return_t<int> (42);
399                 if (i != 42)
400                         return 1;
401                 long l = return_t<long> (Int64.MaxValue);
402                 if (l != Int64.MaxValue)
403                         return 2;
404                 double d = return_t<double> (3.0);
405                 if (d != 3.0)
406                         return 3;
407                 float f = return_t<float> (3.0f);
408                 if (f != 3.0f)
409                         return 4;
410                 short s = return_t<short> (16);
411                 if (s != 16)
412                         return 5;
413                 var v = new GFoo2<int> () { t = 55, t2 = 32 };
414                 var v2 = return_t<GFoo2<int>> (v);
415                 if (v2.t != 55 || v2.t2 != 32)
416                         return 6;
417                 i = new GSharedTests ().return_this_t<int> (42);
418                 if (i != 42)
419                         return 7;
420                 return 0;
421         }
422
423         public static int test_0_gsharedvt_in_delegates () {
424                 Func<int, int> f = new Func<int, int> (return_t<int>);
425                 if (f (42) != 42)
426                         return 1;
427                 return 0;
428         }
429
430         [MethodImplAttribute (MethodImplOptions.NoInlining)]
431         static T return2_t<T> (T t) {
432                 return return_t (t);
433         }
434
435         public static int test_0_gsharedvt_calls () {
436                 if (return2_t (2) != 2)
437                         return 1;
438                 if (return2_t ("A") != "A")
439                         return 2;
440                 if (return2_t (2.0) != 2.0)
441                         return 3;
442                 return 0;
443         }
444
445         static GFoo3<T> newobj<T> (T t1, T t2) {
446                 return new GFoo3<T> (t1, t2);
447         }
448         
449         public static int test_0_gshared_new () {
450                 var g1 = newobj (1, 2);
451                 if (g1.t != 1 || g1.t2 != 2)
452                         return 1;
453                 var g2 = newobj (1.0, 2.0);
454                 if (g1.t != 1.0 || g1.t2 != 2.0)
455                         return 2;
456
457                 return 0;
458         }
459
460         [MethodImplAttribute (MethodImplOptions.NoInlining)]
461         static GFoo2<T> newobj_vt<T> (T t1, T t2) {
462                 return new GFoo2<T> () { t = t1, t2 = t2 };
463         }
464
465         public static int test_0_gshared_new_vt () {
466                 GFoo2<int> v1 = newobj_vt (1, 2);
467                 if (v1.t != 1 || v1.t2 != 2)
468                         return 1;
469                 GFoo2<double> v2 = newobj_vt (1.0, 2.0);
470                 if (v2.t != 1.0 || v2.t2 != 2.0)
471                         return 2;
472                 return 0;
473         }
474
475         //
476         // Tests for transitioning out of gsharedvt code
477         //
478
479         // T1=Nullable<..> is not currently supported by gsharedvt
480
481         [MethodImplAttribute (MethodImplOptions.NoInlining)]
482         static T return_t_nogshared<T,T1> (T t) {
483                 object o = t;
484                 T t2 = (T)o;
485                 //Console.WriteLine ("X: " + t);
486                 return t;
487         }
488
489         [MethodImplAttribute (MethodImplOptions.NoInlining)]
490         static int return_int_nogshared<T,T1> (T t) {
491                 object o = t;
492                 T t2 = (T)o;
493                 return 2;
494         }
495
496         [MethodImplAttribute (MethodImplOptions.NoInlining)]
497         static A return_vtype_nogshared<T,T1> (T t) {
498                 object o = t;
499                 T t2 = (T)o;
500                 return new A () { a = 1, b = 2, c = 3 };
501         }
502
503         [MethodImplAttribute (MethodImplOptions.NoInlining)]
504         static T return2_t_out<T> (T t) {
505                 return return_t_nogshared<T, int?> (t);
506         }
507
508         [MethodImplAttribute (MethodImplOptions.NoInlining)]
509         static int return2_int_out<T> (T t) {
510                 return return_int_nogshared<T, int?> (t);
511         }
512
513         [MethodImplAttribute (MethodImplOptions.NoInlining)]
514         static A return2_vtype_out<T> (T t) {
515                 return return_vtype_nogshared<T, int?> (t);
516         }
517
518         struct A {
519                 public int a, b, c;
520         }
521
522         [Category ("!FULLAOT")]
523         public static int test_0_gsharedvt_out () {
524                 if (return2_t_out (2) != 2)
525                         return 1;
526                 if (return2_t_out ("A") != "A")
527                         return 2;
528                 if (return2_t_out (2.0) != 2.0)
529                         return 3;
530                 if (return2_t_out (2.0f) != 2.0f)
531                         return 4;
532                 A a = new A () { a = 1, b = 2, c = 3 };
533                 A a2 = return2_t_out (a);
534                 if (a2.a != 1 || a2.b != 2 || a2.c != 3)
535                         return 5;
536                 // Calls with non gsharedvt return types
537                 if (return2_int_out (1) != 2)
538                         return 6;
539                 A c = return2_vtype_out (a);
540                 if (a2.a != 1 || a2.b != 2 || a2.c != 3)
541                         return 7;
542                 return 0;
543         }
544
545         public class GenericClass<T> {
546                 public static T Z (IList<T> x, int index)
547                 {
548                         return x [index];
549                 }
550         }
551
552         public static int test_0_generic_array_helpers () {
553                 int[] x = new int[] {100, 200};
554
555                 // Generic array helpers should be treated as gsharedvt-out
556                 if (GenericClass<int>.Z (x, 0) != 100)
557                         return 1;
558
559                 return 0;
560         }
561
562         internal class IntComparer : IComparer<int>
563         {
564                 public int Compare (int ix, int iy)
565                 {
566                         if (ix == iy)
567                                 return 0;
568
569                         if (((uint) ix) < ((uint) iy))
570                                 return -1;
571                         return 1;
572                 }
573         }
574
575         [MethodImplAttribute (MethodImplOptions.NoInlining)]
576         static int gshared_out_iface<T> (T t1, T t2, IComparer<T> comp) {
577                 return comp.Compare (t1, t2);
578         }
579
580         public static int test_0_gshared_out_iface () {
581                 // Call out from gshared to a nongeneric method through a generic interface method
582                 if (gshared_out_iface (2, 2, new IntComparer ()) != 0)
583                         return 1;
584                 return 0;
585         }
586
587         struct Foo1 {
588                 public int i1, i2, i3;
589         }
590
591         struct Foo2<T> {
592                 int i1, i2, i3, i4, i5;
593                 public T foo;
594         }
595
596         [MethodImplAttribute (MethodImplOptions.NoInlining)]    
597         public static void locals<T> (T t) {
598                 Foo2<T> t2 = new Foo2<T> ();
599                 object o = t2;
600         }
601
602         public static int test_0_locals () {
603                 // Test that instantiations of type parameters are allocated the proper local type
604                 int i = 1;
605                 for (int j = 0; j < 10; ++j)
606                         i ++;
607                 locals<Foo1> (new Foo1 () { i1 = 1, i2 = 2, i3 = 3 });
608                 return 0;
609         }
610
611         public interface IFace<T> {
612                 T return_t_iface (T t);
613         }
614
615         public class Parent<T> {
616                 public virtual T return_t_vcall (T t) {
617                         throw new Exception ();
618                         return t;
619                 }
620         }
621
622         public class Child<T> : Parent<T>, IFace<T> {
623                 public override T return_t_vcall (T t) {
624                         return t;
625                 }
626                 public T return_t_iface (T t) {
627                         return t;
628                 }
629         }
630
631         [MethodImplAttribute (MethodImplOptions.NoInlining)]
632         static T return_t_vcall<T> (Parent<T> r, T t) {
633                 return r.return_t_vcall (t);
634         }
635
636         public static int test_0_vcalls () {
637                 if (return_t_vcall (new Child<int> (), 2) != 2)
638                         return 1;
639                 // Patching
640                 for (int i = 0; i < 10; ++i) {
641                         if (return_t_vcall (new Child<int> (), 2) != 2)
642                                 return 2;
643                 }
644                 if (return_t_vcall (new Child<double> (), 2.0) != 2.0)
645                         return 3;
646                 return 0;
647         }
648
649         [MethodImplAttribute (MethodImplOptions.NoInlining)]
650         static T return_t_iface<T> (IFace<T> r, T t) {
651                 return r.return_t_iface (t);
652         }
653
654         public static int test_0_iface_calls () {
655                 if (return_t_iface (new Child<int> (), 2) != 2)
656                         return 1;
657                 if (return_t_iface (new Child<double> (), 2.0) != 2.0)
658                         return 3;
659                 return 0;
660         }
661
662         interface IFaceKVP {
663                 T do_kvp<T> (T a);
664         }
665
666         static KeyValuePair<T1, T2> make_kvp<T1, T2> (T1 t1, T2 t2) {
667                 return new KeyValuePair<T1, T2> (t1, t2);
668         }
669
670         static T2 use_kvp<T1, T2> (KeyValuePair<T1, T2> kvp) {
671                 return kvp.Value;
672         }
673
674         class ClassKVP : IFaceKVP {
675                 public T do_kvp<T> (T a) {
676                         var t = make_kvp (a, a);
677                         // argument is an instance of a vtype instantiated with gsharedvt type arguments
678                         return use_kvp (t);
679                 }
680         }
681
682         public static int test_0_gsharedvt_ginstvt_constructed_arg () {
683                 IFaceKVP c = new ClassKVP ();
684                 if (c.do_kvp<long> (1) != 1)
685                         return 1;
686                 return 0;
687         }
688
689         interface IGetter
690         {
691                 T Get<T>();
692         }
693
694         class Getter : IGetter
695         {
696                 public T Get<T>() { return default(T); }
697         }
698
699         abstract class Session
700         {
701                 public abstract IGetter Getter { get; }
702         }
703
704         class IosSession : Session
705         {
706                 private IGetter getter = new Getter();
707                 public override IGetter Getter { get { return getter; } }
708         }
709
710         enum ENUM_TYPE {
711         }
712
713         public static int test_0_regress_5156 () {
714                 new IosSession().Getter.Get<ENUM_TYPE>();
715                 return 0;
716         }
717
718         public struct VT
719         {
720                 public Action a;
721         }
722
723         public class D
724         {
725         }
726
727         public class A3
728         {
729                 public void OuterMethod<TArg1>(TArg1 value)
730                 {
731                         this.InnerMethod<TArg1, long>(value, 0);
732                 }
733
734                 private void InnerMethod<TArg1, TArg2>(TArg1 v1, TArg2 v2)
735                 {
736                         //Console.WriteLine("{0} {1}",v1,v2);
737                 }
738         }
739
740         public static int test_0_regress_2096 () {
741                 var a = new A3();
742
743                 // The following work:
744                 a.OuterMethod<int>(1);
745                 a.OuterMethod<DateTime>(DateTime.Now);
746
747                 var v = new VT();
748                 a.OuterMethod<VT>(v);
749
750                 var x = new D();
751                 // Next line will crash with Attempting to JIT compile method on device
752                 //  Attempting to JIT compile method
753                 a.OuterMethod<D>(x);
754                 return 0;
755         }
756
757         public class B
758         {
759                 public void Test<T>()
760                 {
761                         //System.Console.WriteLine(typeof(T));
762                 }
763         }
764
765         public class A<T>
766         {
767                 public void Test()
768                 {
769                         new B().Test<System.Collections.Generic.KeyValuePair<T, T>>();
770                 }
771         }
772
773     public static int test_0_regress_6040 () {
774         //new B().Test<System.Collections.Generic.KeyValuePair<string, string>>();
775         new A<int>().Test();
776         new A<object>().Test();
777         new A<string>().Test();
778                 return 0;
779     }
780
781         class ArrayContainer<T> {
782                 private T[,] container = new T[1,1];
783
784                 public T Prop {
785                         [MethodImplAttribute (MethodImplOptions.NoInlining)]
786                         get {
787                                 return container [0, 0];
788                         }
789                         [MethodImplAttribute (MethodImplOptions.NoInlining)]
790                         set {
791                                 container [0, 0] = value;
792                         }
793                 }
794         }
795
796         [MethodImplAttribute (MethodImplOptions.NoInlining)]
797         public static int test_0_multi_dim_arrays () {
798                 var c = new ArrayContainer<int> ();
799                 c.Prop = 5;
800                 return c.Prop == 5 ? 0 : 1;
801         }
802
803         [MethodImplAttribute (MethodImplOptions.NoInlining)]
804         static T2 rgctx_in_call_innner_inner<T1, T2> (T1 t1, T2 t2) {
805                 return t2;
806         }
807
808         [MethodImplAttribute (MethodImplOptions.NoInlining)]
809         static GFoo3<T> rgctx_in_call_inner<T> (T t) {
810                 return rgctx_in_call_innner_inner (1, new GFoo3<T> ());
811         }
812
813     public static int test_0_rgctx_in_call () {
814                 // The call is made through the rgctx call, and it needs an IN trampoline
815                 var t = rgctx_in_call_inner (1);
816                 if (t is GFoo3<int>)
817                         return 0;
818                 return 1;
819         }
820
821         [MethodImplAttribute (MethodImplOptions.NoInlining)]
822         static void arm_params1<T> (T t1, T t2, T t3, T t4, T t5, T t6) {
823         }
824
825         [MethodImplAttribute (MethodImplOptions.NoInlining)]
826         static void arm_params2<T> (T t1, T t2, T t3, long t4, T t5, T t6) {
827         }
828
829         public static int test_0_arm_param_passing () {
830                 arm_params1<int> (1, 2, 3, 4, 5, 6);
831                 arm_params1<int> (1, 2, 3, 4, 5, 6);
832                 return 0;
833         }
834
835         sealed class ScheduledItem<TAbsolute, TValue> {
836                 private readonly object _scheduler;
837                 private readonly TValue _state;
838                 private readonly object _action;
839
840                 public ScheduledItem(object o, TValue state, object action, TAbsolute dueTime) {
841                         _state = state;
842                 }
843         }
844
845     abstract class VirtualTimeSchedulerBase<TAbsolute, TRelative> {
846         public abstract void ScheduleAbsolute<TState>(TState state, TAbsolute dueTime);
847         }
848
849         class VirtualTimeScheduler<TAbsolute, TRelative> : VirtualTimeSchedulerBase<TAbsolute, TRelative> {
850                 public override void ScheduleAbsolute<TState>(TState state, TAbsolute dueTime) {
851                         var si = new ScheduledItem<TAbsolute, TState>(this, state, null, dueTime);
852                 }
853         }
854
855         public static int test_0_rx_mixed_regress () {
856                 var v = new VirtualTimeScheduler<long, long> ();
857                 v.ScheduleAbsolute<Action> (null, 22);
858                 return 0;
859         }
860
861         public class Base {
862                 public virtual T foo<T> (T t) {
863                         return t;
864                 }
865         }
866
867         class Class1 : Base {
868                 public object o;
869
870                 public override T foo<T> (T t) {
871                         o = t;
872                         return t;
873                 }
874         }
875
876         class Class2 : Base {
877                 public object o;
878
879                 public override T foo<T> (T t) {
880                         o = t;
881                         return t;
882                 }
883         }
884
885         [MethodImplAttribute (MethodImplOptions.NoInlining)]
886         public static void bar<T> (Base b, T t) {
887                 b.foo (t);
888         }
889
890         public static int test_0_virtual_generic () {
891                 Class1 c1 = new Class1 ();
892                 Class2 c2 = new Class2 ();
893                 bar (c1, 5);
894                 if (!(c1.o is int) || ((int)c1.o != 5))
895                         return 1;
896                 bar (c1, 6.0);
897                 if (!(c1.o is double) || ((double)c1.o != 6.0))
898                         return 2;
899                 bar (c1, 7.0f);
900                 if (!(c1.o is float) || ((float)c1.o != 7.0f))
901                         return 3;
902                 bar (c2, 5);
903                 if (!(c2.o is int) || ((int)c2.o != 5))
904                         return 4;
905                 bar (c2, 6.0);
906                 bar (c2, 7.0f);
907                 return 0;
908         }
909
910         [MethodImplAttribute (MethodImplOptions.NoInlining)]
911         static string to_string<T, T2>(T t, T2 t2) {
912                 return t.ToString ();
913         }
914
915         enum AnEnum {
916                 One
917         };
918
919         public static int test_0_constrained_tostring () {
920                 if (to_string<int, int> (1, 1) != "1")
921                         return 1;
922                 if (to_string<AnEnum, int> (AnEnum.One, 1) != "One")
923                         return 2;
924                 if (to_string<string, int> ("A", 1) != "A")
925                         return 3;
926                 return 0;
927         }
928
929         [MethodImplAttribute (MethodImplOptions.NoInlining)]
930         static int get_hash<T, T2>(T t, T2 t2) {
931                 return t.GetHashCode ();
932         }
933
934         public static int test_0_constrained_get_hash () {
935                 if (get_hash<int, int> (1, 1) != 1.GetHashCode ())
936                         return 1;
937                 if (get_hash<double, int> (1.0, 1) != 1.0.GetHashCode ())
938                         return 2;
939                 if (get_hash<AnEnum, int> (AnEnum.One, 1) != AnEnum.One.GetHashCode ())
940                         return 3;
941                 if (get_hash<string, int> ("A", 1) != "A".GetHashCode ())
942                         return 4;
943                 return 0;
944         }
945
946         [MethodImplAttribute (MethodImplOptions.NoInlining)]
947         static bool equals<T, T2>(T t, T2 t2) {
948                 return t.Equals (t);
949         }
950
951         public static int test_0_constrained_equals () {
952                 if (equals<int, int> (1, 1) != true)
953                         return 1;
954                 if (equals<double, int> (1.0, 1) != true)
955                         return 2;
956                 if (equals<AnEnum, int> (AnEnum.One, 1) != true)
957                         return 3;
958                 if (equals<string, int> ("A", 1) != true)
959                         return 4;
960                 return 0;
961         }
962
963         struct Pair<T1, T2> {
964                 public T1 First;
965                 public T2 Second;
966         }
967
968         [MethodImplAttribute (MethodImplOptions.NoInlining)]
969         public static TState call_del<TState>(TState state, Func<object, TState, TState> action) {
970                 return action(null, state);
971         }
972
973         public static int test_0_delegate_wrappers () {
974                 Func<object, Pair<int, int>, Pair<int, int>> del1 = delegate (object o, Pair<int, int> p) { return p; };
975                 Func<object, Pair<int, int>, Pair<int, int>> del2 = delegate (object o, Pair<int, int> p) { return p; };
976                 Func<object, Pair<double, int>, Pair<double, int>> del3 = delegate (object o, Pair<double, int> p) { return p; };
977                 var r1 = call_del<Pair<int, int>> (new Pair<int, int> { First = 1, Second = 2}, del1);
978                 if (r1.First != 1 || r1.Second != 2)
979                         return 1;
980                 var r2 = call_del<Pair<int, int>> (new Pair<int, int> { First = 3, Second = 4}, del2);
981                 if (r2.First != 3 || r2.Second != 4)
982                         return 2;
983                 var r3 = call_del<Pair<double, int>> (new Pair<double, int> { First = 1.0, Second = 2}, del3);
984                 if (r3.First != 1.0 || r3.Second != 2)
985                         return 3;
986                 return 0;
987         }
988
989         class Base<T> {
990                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
991                 public object foo<T1> (T1 t1, T t, object o) {
992                         return o;
993                 }
994         }
995
996         class AClass : Base<long> {
997
998                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
999                 public object bar<T> (T t, long time, object o) {
1000                         return foo (t, time, o);
1001                 }
1002         }
1003
1004         public static int test_0_out_in_wrappers () {
1005                 var a = new AClass ();
1006                 object o1 = "A";
1007                 object o2 = a.bar<long> (1024, 0, o1);
1008                 if (o1 != o2)
1009                         return 1;
1010                 return 0;               
1011         }
1012
1013                 interface BIFace {
1014                         object AMethod ();
1015                 }
1016
1017                 class Base<TAbsolute, T2> : BIFace {
1018
1019                         public TAbsolute Clock { get; set; }
1020
1021                         public virtual object AMethod () {
1022                                 return Clock;
1023                         }
1024                 }
1025
1026                 class BClass : Base<long, long> {
1027                 }
1028
1029         public static int test_0_regress_1 () {
1030                 BIFace c = new BClass ();
1031                 object o = c.AMethod ();
1032                 if (!(o is long) || ((long)o != 0))
1033                         return 1;
1034                 return 0;
1035         }
1036
1037         interface IFace3 {
1038                 T unbox_any<T> (object o);
1039         }
1040
1041         class Class3 : IFace3 {
1042                 public virtual T unbox_any<T> (object o) {
1043                         return (T)o;
1044                 }
1045         }
1046
1047         public static int test_0_unbox_any () {
1048                 IFace3 o = new Class3 ();
1049                 if (o.unbox_any<int> (16) != 16)
1050                         return 1;
1051                 if (o.unbox_any<long> ((long)32) != 32)
1052                         return 2;
1053                 if (o.unbox_any<double> (2.0) != 2.0)
1054                         return 3;
1055                 try {
1056                         o.unbox_any<int> (2.0);
1057                         return 4;
1058                 } catch (Exception) {
1059                 }
1060                 return 0;
1061         }
1062
1063         interface IFace4 {
1064                 TSource Catch<TSource, TException>(TSource t)  where TException : Exception;
1065         }
1066
1067         class Class4 : IFace4 {
1068                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
1069                         public TSource Catch<TSource, TException>(TSource t)  where TException : Exception {
1070                         return t;
1071                 }
1072         }
1073
1074         // Check that mixed instantiations are correctly created/found in AOT
1075         public static int test_0_constraints () {
1076                 IFace4 o = new Class4 ();
1077                 o.Catch<int, Exception> (1);
1078                 return 0;
1079         }
1080
1081         internal static Type Process<TSource, TElement> (TSource[] arr, Action<TElement, TElement> call) {
1082                 arr [0] = default (TSource);
1083                 return typeof (TSource);
1084         }
1085
1086         interface IFace5 {
1087                 Type foo<T> ();
1088         }
1089
1090         class Class5 : IFace5 {
1091                 public Type foo<T> () {
1092                         return Process<KeyValuePair<long, T>, T> (new KeyValuePair<long, T> [10], null);
1093                 }
1094         }
1095
1096         public static int test_0_rgctx_call_from_gshared_code () {
1097                 var c = new Class5 ();
1098                 if (c.foo<string> () != typeof (KeyValuePair<long, string>))
1099                         return 1;
1100                 return 0;
1101         }
1102
1103         public class Enumbers<T> {
1104                 public object Enumerate (List<KeyValuePair<T, string>> alist)
1105                 {
1106                         return alist.ToArray ();
1107                 }
1108         }
1109
1110         public static int test_0_checkthis_gshared_call () {
1111                 Enumbers<string> e = new Enumbers<string> ();
1112                 try {
1113                         e.Enumerate (null);
1114                         return 1;
1115                 }
1116                 catch (NullReferenceException) {
1117                 }
1118                 return 0;
1119         }
1120
1121         interface IFace6 {
1122                 T[] Del<T> (T t);
1123         }
1124
1125         class Class6 : IFace6 {
1126                 public T[] Del<T> (T t) {
1127                         var res = new T [5];
1128                         Func<T, T, T, T, T> func = delegate(T t1, T t2, T t3, T t4) { res [0] = t1; res [1] = t2; res [2] = t3; res [3] = t4; return t1; };
1129                         var v = func.BeginInvoke(t, t, t, t, null, null);
1130                         res [4] = func.EndInvoke (v);
1131                         return res;
1132                 }
1133         }
1134
1135         // FIXME: The runtime-invoke wrapper used by BeginInvoke is not found
1136         [Category ("!FULLAOT")]
1137         public static int test_0_begin_end_invoke () {
1138                 IFace6 o = new Class6 ();
1139                 var arr1 = o.Del (1);
1140                 if (arr1 [0] != 1 || arr1 [1] != 1 || arr1 [2] != 1 || arr1 [3] != 1 || arr1 [4] != 1)
1141                         return 1;
1142                 var arr2 = o.Del (2.0);
1143                 if (arr2 [0] != 2.0 || arr2 [1] != 2.0 || arr2 [2] != 2.0 || arr2 [3] != 2.0 || arr2 [4] != 2.0)
1144                         return 2;
1145                 return 0;
1146         }
1147
1148         public class TAbstractTableItem<TC> {
1149                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
1150                 public static void SetProperty<TV> () {    }
1151
1152                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
1153                 public static void Test () {
1154                         SetProperty<bool> ();
1155                 }
1156         }
1157
1158         public static int test_0_gsharedvt_method_on_shared_class () {
1159        TAbstractTableItem<object>.Test ();
1160            return 0;
1161         }
1162
1163         interface IFaceBox {
1164                 object box<T> (T t);
1165         }
1166
1167         class ClassBox : IFaceBox {
1168                 public object box<T> (T t) {
1169                         object o = t;
1170                         return o;
1171                 }
1172         }
1173
1174         public static int test_0_nullable_box () {
1175                 IFaceBox c = new ClassBox ();
1176                 int i = 5;
1177                 object o = c.box<int?> (i);
1178                 if ((int)o != i)
1179                         return 1;
1180                 if (c.box<int?> (null) != null)
1181                         return 2;
1182                 long l = Int64.MaxValue - 1;
1183                 o = c.box<long?> (l);
1184                 if ((long)o != l)
1185                         return 3;
1186                 if (c.box<long?> (null) != null)
1187                         return 4;
1188                 string s = "A";
1189                 if (c.box<string> (s) != (object)s)
1190                         return 5;
1191                 return 0;
1192         }
1193
1194         interface IFaceUnbox2 {
1195                 T unbox<T> (object o);
1196         }
1197
1198         class ClassUnbox2 : IFaceUnbox2 {
1199                 public T unbox<T> (object o) {
1200                         return (T)o;
1201                 }
1202         }
1203
1204         public static int test_0_nullable_unbox () {    
1205                 IFaceUnbox2 c = new ClassUnbox2 ();
1206                 int? i = c.unbox<int?> (5);
1207                 if (i != 5)
1208                         return 1;
1209                 int? j = c.unbox<int?> (null);
1210                 if (j != null)
1211                         return 2;
1212                 return 0;
1213         }
1214 }
1215
1216 #if !MOBILE
1217 public class GSharedTests : Tests {
1218 }
1219 #endif