Fix the handling of non-virtual calls made out of gsharedvt methods, we need to add...
[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;
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 public class Tests
44 {
45         public static int Main (String[] args) {
46                 return TestDriver.RunTests (typeof (Tests), args);
47         }
48
49         [MethodImplAttribute (MethodImplOptions.NoInlining)]
50         static void gshared<T> (T [] array, int i, int j) {
51                 T tmp = array [i];
52                 array [i] = array [j];
53                 array [j] = tmp;
54         }
55
56         // Test that the gshared and gsharedvt versions don't mix
57         public static int test_0_vt_gshared () {
58                 string[] sarr = new string [2] { "A", "B" };
59
60                 gshared<string> (sarr, 0, 1);
61
62                 Foo[] arr = new Foo [2];
63                 arr [0] = new Foo () { i = 1, j = 2 };
64                 arr [1] = new Foo () { i = 3, j = 4 };
65
66                 gshared<Foo> (arr, 0, 1);
67                 if (arr [0].i != 3 || arr [0].j != 4)
68                         return 1;
69                 if (arr [1].i != 1 || arr [1].j != 2)
70                         return 2;
71
72                 return 0;
73         }
74
75         static void ldelem_stelem<T> (T [] array, int i, int j) {
76                 T tmp = array [i];
77                 array [i] = array [j];
78                 array [j] = tmp;
79         }
80
81         public static int test_0_vt_ldelem_stelem () {
82                 Foo[] arr = new Foo [2];
83                 arr [0] = new Foo () { i = 1, j = 2 };
84                 arr [1] = new Foo () { i = 3, j = 4 };
85
86                 ldelem_stelem<Foo> (arr, 0, 1);
87                 if (arr [0].i != 3 || arr [0].j != 4)
88                         return 1;
89                 if (arr [1].i != 1 || arr [1].j != 2)
90                         return 2;
91
92                 int[] arr2 = new int [2] { 1, 2 };
93                 ldelem_stelem<int> (arr2, 0, 1);
94                 if (arr2 [0] !=2 || arr2 [1] != 1)
95                         return 3;
96
97                 return 0;
98         }
99
100         [MethodImplAttribute (MethodImplOptions.NoInlining)]
101         private static void initobj<T> (T [] array, int i, int j) {
102                 T x = default(T);
103                 array [i] = x;
104         }
105
106         public static int test_0_vt_initobj () {
107                 Foo[] arr = new Foo [2];
108                 arr [0] = new Foo () { i = 1, j = 2 };
109                 arr [1] = new Foo () { i = 3, j = 4 };
110
111                 initobj<Foo> (arr, 0, 1);
112                 if (arr [0].i != 0 || arr [0].j != 0)
113                         return 1;
114                 if (arr [1].i != 3 || arr [1].j != 4)
115                         return 2;
116                 return 0;
117         }
118
119         [MethodImplAttribute (MethodImplOptions.NoInlining)]
120         static T ldobj_stobj<T> (ref T t1, ref T t2) {
121                 t1 = t2;
122                 T t = t2;
123                 t2 = default(T);
124                 return t;
125         }
126
127         public static int test_0_vt_ldobj_stobj () {
128                 int i = 5;
129                 int j = 6;
130                 if (ldobj_stobj (ref i, ref j) != 6)
131                         return 1;
132                 if (i != 6 || j != 0)
133                         return 2;
134                 double d1 = 1.0;
135                 double d2 = 2.0;
136                 if (ldobj_stobj (ref d1, ref d2) != 2.0)
137                         return 3;
138                 if (d1 != 2.0 || d2 != 0.0)
139                         return 4;               
140                 return 0;
141         }
142
143         [MethodImplAttribute (MethodImplOptions.NoInlining)]
144         private static void box<T1, T> (T [] array, object[] arr) {
145                 object x = array [0];
146                 arr [0] = x;
147         }
148
149         public static int test_0_vt_box () {
150                 Foo[] arr = new Foo [2];
151                 arr [0] = new Foo () { i = 1, j = 2 };
152
153                 object[] arr2 = new object [16];
154                 box<int, Foo> (arr, arr2);
155                 if (arr2 [0].GetType () != typeof (Foo))
156                         return 1;
157                 Foo f = (Foo)arr2 [0];
158                 if (f.i != 1 || f.j != 2)
159                         return 2;
160                 string[] arr3 = new string [16];
161                 object[] arr4 = new object [16];
162                 arr3 [0] = "OK";
163                 box<int, string> (arr3, arr4);
164                 if (arr4 [0] != (object)arr3 [0])
165                         return 3;
166                 return 0;
167         }
168
169         [MethodImplAttribute (MethodImplOptions.NoInlining)]
170         private static void unbox_any<T> (T [] array, object[] arr) {
171                 T t = (T)arr [0];
172                 array [0] = t;
173         }
174
175         public static int test_0_vt_unbox_any () {
176                 Foo[] arr = new Foo [2];
177
178                 object[] arr2 = new object [16];
179                 arr2 [0] = new Foo () { i = 1, j = 2 };
180                 unbox_any<Foo> (arr, arr2);
181                 if (arr [0].i != 1 || arr [0].j != 2)
182                         return 2;
183                 return 0;
184         }
185
186         [MethodImplAttribute (MethodImplOptions.NoInlining)]
187         static void ldfld_nongeneric<T> (GFoo<T>[] foo, int[] arr) {
188                 arr [0] = foo [0].i;
189         }
190
191         [MethodImplAttribute (MethodImplOptions.NoInlining)]
192         static void ldfld<T> (GFoo<T>[] foo, T[] arr) {
193                 arr [0] = foo [0].t;
194         }
195
196         [MethodImplAttribute (MethodImplOptions.NoInlining)]
197         static void stfld_nongeneric<T> (GFoo<T>[] foo, int[] arr) {
198                 foo [0].i = arr [0];
199         }
200
201         [MethodImplAttribute (MethodImplOptions.NoInlining)]
202         static void stfld<T> (GFoo<T>[] foo, T[] arr) {
203                 foo [0].t = arr [0];
204         }
205
206         [MethodImplAttribute (MethodImplOptions.NoInlining)]
207         static void ldflda<T> (GFoo<T>[] foo, int[] arr) {
208                 arr [0] = foo [0].f.i;
209         }
210
211         public static int test_0_vt_ldfld_stfld () {
212                 var foo = new GFoo<Foo> () { t = new Foo () { i = 1, j = 2 }, i = 5, f = new Foo () { i = 5, j = 6 } };
213                 var farr = new GFoo<Foo>[] { foo };
214
215                 /* Normal fields with a variable offset */
216                 var iarr = new int [10];
217                 ldfld_nongeneric<Foo> (farr, iarr);
218                 if (iarr [0] != 5)
219                         return 1;
220                 iarr [0] = 16;
221                 stfld_nongeneric<Foo> (farr, iarr);
222                 if (farr [0].i != 16)
223                         return 2;
224
225                 /* Variable type field with a variable offset */
226                 var arr = new Foo [10];
227                 ldfld<Foo> (farr, arr);
228                 if (arr [0].i != 1 || arr [0].j != 2)
229                         return 3;
230                 arr [0] = new Foo () { i = 3, j = 4 };
231                 stfld<Foo> (farr, arr);
232                 if (farr [0].t.i != 3 || farr [0].t.j != 4)
233                         return 4;
234
235                 ldflda<Foo> (farr, iarr);
236                 if (iarr [0] != 5)
237                         return 5;
238
239                 return 0;
240         }
241
242         [MethodImplAttribute (MethodImplOptions.NoInlining)]
243         static void stsfld<T> (T[] arr) {
244                 GFoo<T>.static_t = arr [0];
245         }
246
247         [MethodImplAttribute (MethodImplOptions.NoInlining)]
248         static void ldsfld<T> (T[] arr) {
249                 arr [0] = GFoo<T>.static_t;
250         }
251
252         [MethodImplAttribute (MethodImplOptions.NoInlining)]
253         static void ldsflda<T> (int[] iarr) {
254                 iarr [0] = GFoo<T>.static_f.i;
255         }
256         
257         public static int test_0_stsfld () {
258                 Foo[] farr = new Foo [] { new Foo () { i = 1, j = 2 } };
259                 stsfld<Foo> (farr);
260
261                 if (GFoo<Foo>.static_t.i != 1 || GFoo<Foo>.static_t.j != 2)
262                         return 1;
263
264                 Foo[] farr2 = new Foo [1];
265                 ldsfld<Foo> (farr2);
266                 if (farr2 [0].i != 1 || farr2 [0].j != 2)
267                         return 2;
268
269                 var iarr = new int [10];
270                 GFoo<Foo>.static_f = new Foo () { i = 5, j = 6 };
271                 ldsflda<Foo> (iarr);
272                 if (iarr [0] != 5)
273                         return 3;
274
275                 return 0;
276         }
277
278         [MethodImplAttribute (MethodImplOptions.NoInlining)]
279         static object newarr<T> () {
280                 object o = new T[10];
281                 return o;
282         }
283
284         public static int test_0_vt_newarr () {
285                 object o = newarr<Foo> ();
286                 if (!(o is Foo[]))
287                         return 1;
288                 return 0;
289         }
290
291         [MethodImplAttribute (MethodImplOptions.NoInlining)]
292         static Type ldtoken<T> () {
293                 return typeof (GFoo<T>);
294         }
295
296         public static int test_0_vt_ldtoken () {
297                 Type t = ldtoken<Foo> ();
298                 if (t != typeof (GFoo<Foo>))
299                         return 1;
300                 t = ldtoken<int> ();
301                 if (t != typeof (GFoo<int>))
302                         return 2;
303
304                 return 0;
305         }
306
307         public static int test_0_vtype_list () {
308                 List<int> l = new List<int> ();
309
310                 l.Add (5);
311                 if (l.Count != 1)
312                         return 1;
313                 return 0;
314         }
315
316         [MethodImplAttribute (MethodImplOptions.NoInlining)]
317         static int args_simple<T> (T t, int i) {
318                 return i;
319         }
320
321         [MethodImplAttribute (MethodImplOptions.NoInlining)]
322         static int args_simple<T> (T t, int i, T t2) {
323                 return i;
324         }
325
326         [MethodImplAttribute (MethodImplOptions.NoInlining)]
327         static Type args_rgctx<T> (T t, int i) {
328                 return typeof (T);
329         }
330
331         [MethodImplAttribute (MethodImplOptions.NoInlining)]
332         static Type eh_in<T> (T t, int i) {
333                 throw new OverflowException ();
334         }
335
336         [MethodImplAttribute (MethodImplOptions.NoInlining)]
337         static T return_t<T> (T t) {
338                 return t;
339         }
340
341         [MethodImplAttribute (MethodImplOptions.NoInlining)]
342         T return_this_t<T> (T t) {
343                 return t;
344         }
345
346         public static int test_0_gsharedvt_in () {
347                 // Check that the non-generic argument is passed at the correct stack position
348                 int r = args_simple<bool> (true, 42);
349                 if (r != 42)
350                         return 1;
351                 r = args_simple<Foo> (new Foo (), 43);
352                 if (r != 43)
353                         return 2;
354                 // Check that the proper rgctx is passed to the method
355                 Type t = args_rgctx<int> (5, 42);
356                 if (t != typeof (int))
357                         return 3;
358                 var v = args_simple<GFoo2<int>> (new GFoo2<int> () { t = 11, t2 = 12 }, 44, new GFoo2<int> () { t = 11, t2 = 12 });
359                 if (v != 44)
360                         return 4;
361                 // Check that EH works properly
362                 try {
363                         eh_in<int> (1, 2);
364                 } catch (OverflowException) {
365                 }
366                 return 0;
367         }
368
369         public static int test_0_gsharedvt_in_ret () {
370                 int i = return_t<int> (42);
371                 if (i != 42)
372                         return 1;
373                 long l = return_t<long> (Int64.MaxValue);
374                 if (l != Int64.MaxValue)
375                         return 2;
376                 double d = return_t<double> (3.0);
377                 if (d != 3.0)
378                         return 3;
379                 float f = return_t<float> (3.0f);
380                 if (f != 3.0f)
381                         return 4;
382                 short s = return_t<short> (16);
383                 if (s != 16)
384                         return 5;
385                 var v = new GFoo2<int> () { t = 55, t2 = 32 };
386                 var v2 = return_t<GFoo2<int>> (v);
387                 if (v2.t != 55 || v2.t2 != 32)
388                         return 6;
389                 i = new Tests ().return_this_t<int> (42);
390                 if (i != 42)
391                         return 7;
392                 return 0;
393         }
394
395         public static int test_0_gsharedvt_in_delegates () {
396                 Func<int, int> f = new Func<int, int> (return_t<int>);
397                 if (f (42) != 42)
398                         return 1;
399                 return 0;
400         }
401
402         [MethodImplAttribute (MethodImplOptions.NoInlining)]
403         static T return2_t<T> (T t) {
404                 return return_t (t);
405         }
406
407         public static int test_0_gsharedvt_calls () {
408                 if (return2_t (2) != 2)
409                         return 1;
410                 if (return2_t ("A") != "A")
411                         return 2;
412                 if (return2_t (2.0) != 2.0)
413                         return 3;
414                 return 0;
415         }
416
417         static GFoo3<T> newobj<T> (T t1, T t2) {
418                 return new GFoo3<T> (t1, t2);
419         }
420         
421         public static int test_0_gshared_new () {
422                 var g1 = newobj (1, 2);
423                 if (g1.t != 1 || g1.t2 != 2)
424                         return 1;
425                 var g2 = newobj (1.0, 2.0);
426                 if (g1.t != 1.0 || g1.t2 != 2.0)
427                         return 2;
428
429                 return 0;
430         }
431
432         [MethodImplAttribute (MethodImplOptions.NoInlining)]
433         static GFoo2<T> newobj_vt<T> (T t1, T t2) {
434                 return new GFoo2<T> () { t = t1, t2 = t2 };
435         }
436
437         public static int test_0_gshared_new_vt () {
438                 GFoo2<int> v1 = newobj_vt (1, 2);
439                 if (v1.t != 1 || v1.t2 != 2)
440                         return 1;
441                 GFoo2<double> v2 = newobj_vt (1.0, 2.0);
442                 if (v2.t != 1.0 || v2.t2 != 2.0)
443                         return 2;
444                 return 0;
445         }
446
447         //
448         // Tests for transitioning out of gsharedvt code
449         //
450
451         [MethodImplAttribute (MethodImplOptions.NoInlining)]
452         static T return_t_nogshared<T> (T t) {
453                 // This is not currently supported by gsharedvt
454                 object o = t;
455                 T t2 = (T)o;
456                 //Console.WriteLine ("X: " + t);
457                 return t;
458         }
459
460         [MethodImplAttribute (MethodImplOptions.NoInlining)]
461         static int return_int_nogshared<T> (T t) {
462                 // This is not currently supported by gsharedvt
463                 object o = t;
464                 T t2 = (T)o;
465                 return 2;
466         }
467
468         [MethodImplAttribute (MethodImplOptions.NoInlining)]
469         static A return_vtype_nogshared<T> (T t) {
470                 // This is not currently supported by gsharedvt
471                 object o = t;
472                 T t2 = (T)o;
473                 return new A () { a = 1, b = 2, c = 3 };
474         }
475
476         [MethodImplAttribute (MethodImplOptions.NoInlining)]
477         static T return2_t_out<T> (T t) {
478                 return return_t_nogshared (t);
479         }
480
481         [MethodImplAttribute (MethodImplOptions.NoInlining)]
482         static int return2_int_out<T> (T t) {
483                 return return_int_nogshared (t);
484         }
485
486         [MethodImplAttribute (MethodImplOptions.NoInlining)]
487         static A return2_vtype_out<T> (T t) {
488                 return return_vtype_nogshared (t);
489         }
490
491         struct A {
492                 public int a, b, c;
493         }
494
495         public static int test_0_gsharedvt_out () {
496                 if (return2_t_out (2) != 2)
497                         return 1;
498                 if (return2_t_out ("A") != "A")
499                         return 2;
500                 if (return2_t_out (2.0) != 2.0)
501                         return 3;
502                 if (return2_t_out (2.0f) != 2.0f)
503                         return 4;
504                 A a = new A () { a = 1, b = 2, c = 3 };
505                 A a2 = return2_t_out (a);
506                 if (a2.a != 1 || a2.b != 2 || a2.c != 3)
507                         return 5;
508                 // Calls with non gsharedvt return types
509                 if (return2_int_out (1) != 2)
510                         return 6;
511                 A c = return2_vtype_out (a);
512                 if (a2.a != 1 || a2.b != 2 || a2.c != 3)
513                         return 7;
514                 return 0;
515         }
516
517         public class GenericClass<T> {
518                 public static T Z (IList<T> x, int index)
519                 {
520                         return x [index];
521                 }
522         }
523
524         public static int test_0_generic_array_helpers () {
525                 int[] x = new int[] {100, 200};
526
527                 // Generic array helpers should be treated as gsharedvt-out
528                 if (GenericClass<int>.Z (x, 0) != 100)
529                         return 1;
530
531                 return 0;
532         }
533
534         internal class IntComparer : IComparer<int>
535         {
536                 public int Compare (int ix, int iy)
537                 {
538                         if (ix == iy)
539                                 return 0;
540
541                         if (((uint) ix) < ((uint) iy))
542                                 return -1;
543                         return 1;
544                 }
545         }
546
547         [MethodImplAttribute (MethodImplOptions.NoInlining)]
548         static int gshared_out_iface<T> (T t1, T t2, IComparer<T> comp) {
549                 return comp.Compare (t1, t2);
550         }
551
552         public static int test_0_gshared_out_iface () {
553                 // Call out from gshared to a nongeneric method through a generic interface method
554                 if (gshared_out_iface (2, 2, new IntComparer ()) != 0)
555                         return 1;
556                 return 0;
557         }
558
559         struct Foo1 {
560                 public int i1, i2, i3;
561         }
562
563         struct Foo2<T> {
564                 int i1, i2, i3, i4, i5;
565                 public T foo;
566         }
567
568         [MethodImplAttribute (MethodImplOptions.NoInlining)]    
569         public static void locals<T> (T t) {
570                 Foo2<T> t2 = new Foo2<T> ();
571                 object o = t2;
572         }
573
574         public static int test_0_locals () {
575                 // Test that instantiations of type parameters are allocated the proper local type
576                 int i = 1;
577                 for (int j = 0; j < 10; ++j)
578                         i ++;
579                 locals<Foo1> (new Foo1 () { i1 = 1, i2 = 2, i3 = 3 });
580                 return 0;
581         }
582
583         public interface IFace<T> {
584                 T return_t_iface (T t);
585         }
586
587         public class Parent<T> {
588                 public virtual T return_t_vcall (T t) {
589                         throw new Exception ();
590                         return t;
591                 }
592         }
593
594         public class Child<T> : Parent<T>, IFace<T> {
595                 public override T return_t_vcall (T t) {
596                         return t;
597                 }
598                 public T return_t_iface (T t) {
599                         return t;
600                 }
601         }
602
603         [MethodImplAttribute (MethodImplOptions.NoInlining)]
604         static T return_t_vcall<T> (Parent<T> r, T t) {
605                 return r.return_t_vcall (t);
606         }
607
608         public static int test_0_vcalls () {
609                 if (return_t_vcall (new Child<int> (), 2) != 2)
610                         return 1;
611                 // Patching
612                 for (int i = 0; i < 10; ++i) {
613                         if (return_t_vcall (new Child<int> (), 2) != 2)
614                                 return 2;
615                 }
616                 if (return_t_vcall (new Child<double> (), 2.0) != 2.0)
617                         return 3;
618                 return 0;
619         }
620
621         [MethodImplAttribute (MethodImplOptions.NoInlining)]
622         static T return_t_iface<T> (IFace<T> r, T t) {
623                 return r.return_t_iface (t);
624         }
625
626         public static int test_0_iface_calls () {
627                 if (return_t_iface (new Child<int> (), 2) != 2)
628                         return 1;
629                 if (return_t_iface (new Child<double> (), 2.0) != 2.0)
630                         return 3;
631                 return 0;
632         }
633
634         static KeyValuePair<T1, T2> make_kvp<T1, T2> (T1 t1, T2 t2) {
635                 return new KeyValuePair<T1, T2> (t1, t2);
636         }
637
638         static T2 use_kvp<T1, T2> (KeyValuePair<T1, T2> kvp) {
639                 return kvp.Value;
640         }
641                 
642         [MethodImplAttribute (MethodImplOptions.NoInlining)]
643         static T do_kvp<T> (T a) {
644                 var t = make_kvp (a, a);
645                 // argument is an instance of a vtype instantiated with gsharedvt type arguments
646                 return use_kvp (t);
647         }
648
649         public static int test_0_gsharedvt_ginstvt_constructed_arg () {
650                 if (do_kvp<long> (1) != 1)
651                         return 1;
652                 return 0;
653         }
654
655         interface IGetter
656         {
657                 T Get<T>();
658         }
659
660         class Getter : IGetter
661         {
662                 public T Get<T>() { return default(T); }
663         }
664
665         abstract class Session
666         {
667                 public abstract IGetter Getter { get; }
668         }
669
670         class IosSession : Session
671         {
672                 private IGetter getter = new Getter();
673                 public override IGetter Getter { get { return getter; } }
674         }
675
676         enum ENUM_TYPE {
677         }
678
679         public static int test_0_regress_5156 () {
680                 new IosSession().Getter.Get<ENUM_TYPE>();
681                 return 0;
682         }
683
684         public struct VT
685         {
686                 public Action a;
687         }
688
689         public class D
690         {
691         }
692
693         public class A3
694         {
695                 public void OuterMethod<TArg1>(TArg1 value)
696                 {
697                         this.InnerMethod<TArg1, long>(value, 0);
698                 }
699
700                 private void InnerMethod<TArg1, TArg2>(TArg1 v1, TArg2 v2)
701                 {
702                         //Console.WriteLine("{0} {1}",v1,v2);
703                 }
704         }
705
706         public static int test_0_regress_2096 () {
707                 var a = new A3();
708
709                 // The following work:
710                 a.OuterMethod<int>(1);
711                 a.OuterMethod<DateTime>(DateTime.Now);
712
713                 var v = new VT();
714                 a.OuterMethod<VT>(v);
715
716                 var x = new D();
717                 // Next line will crash with Attempting to JIT compile method on device
718                 //  Attempting to JIT compile method
719                 a.OuterMethod<D>(x);
720                 return 0;
721         }
722
723         public class B
724         {
725                 public void Test<T>()
726                 {
727                         //System.Console.WriteLine(typeof(T));
728                 }
729         }
730
731         public class A<T>
732         {
733                 public void Test()
734                 {
735                         new B().Test<System.Collections.Generic.KeyValuePair<T, T>>();
736                 }
737         }
738
739     public static int test_0_regress_6040 () {
740         //new B().Test<System.Collections.Generic.KeyValuePair<string, string>>();
741         new A<int>().Test();
742         new A<object>().Test();
743         new A<string>().Test();
744                 return 0;
745     }
746
747         class ArrayContainer<T> {
748                 private T[,] container = new T[1,1];
749
750                 public T Prop {
751                         [MethodImplAttribute (MethodImplOptions.NoInlining)]
752                         get {
753                                 return container [0, 0];
754                         }
755                         [MethodImplAttribute (MethodImplOptions.NoInlining)]
756                         set {
757                                 container [0, 0] = value;
758                         }
759                 }
760         }
761
762         [MethodImplAttribute (MethodImplOptions.NoInlining)]
763         public static int test_0_multi_dim_arrays () {
764                 var c = new ArrayContainer<int> ();
765                 c.Prop = 5;
766                 return c.Prop == 5 ? 0 : 1;
767         }
768
769         [MethodImplAttribute (MethodImplOptions.NoInlining)]
770         static T2 rgctx_in_call_innner_inner<T1, T2> (T1 t1, T2 t2) {
771                 return t2;
772         }
773
774         [MethodImplAttribute (MethodImplOptions.NoInlining)]
775         static GFoo3<T> rgctx_in_call_inner<T> (T t) {
776                 return rgctx_in_call_innner_inner (1, new GFoo3<T> ());
777         }
778
779     public static int test_0_rgctx_in_call () {
780                 // The call is made through the rgctx call, and it needs an IN trampoline
781                 var t = rgctx_in_call_inner (1);
782                 if (t is GFoo3<int>)
783                         return 0;
784                 return 1;
785         }
786
787         [MethodImplAttribute (MethodImplOptions.NoInlining)]
788         static void arm_params1<T> (T t1, T t2, T t3, T t4, T t5, T t6) {
789         }
790
791         [MethodImplAttribute (MethodImplOptions.NoInlining)]
792         static void arm_params2<T> (T t1, T t2, T t3, long t4, T t5, T t6) {
793         }
794
795         public static int test_0_arm_param_passing () {
796                 arm_params1<int> (1, 2, 3, 4, 5, 6);
797                 arm_params1<int> (1, 2, 3, 4, 5, 6);
798                 return 0;
799         }
800
801         sealed class ScheduledItem<TAbsolute, TValue> {
802                 private readonly object _scheduler;
803                 private readonly TValue _state;
804                 private readonly object _action;
805
806                 public ScheduledItem(object o, TValue state, object action, TAbsolute dueTime) {
807                         _state = state;
808                 }
809         }
810
811     abstract class VirtualTimeSchedulerBase<TAbsolute, TRelative> {
812         public abstract void ScheduleAbsolute<TState>(TState state, TAbsolute dueTime);
813         }
814
815         class VirtualTimeScheduler<TAbsolute, TRelative> : VirtualTimeSchedulerBase<TAbsolute, TRelative> {
816                 public override void ScheduleAbsolute<TState>(TState state, TAbsolute dueTime) {
817                         var si = new ScheduledItem<TAbsolute, TState>(this, state, null, dueTime);
818                 }
819         }
820
821         public static int test_0_rx_mixed_regress () {
822                 var v = new VirtualTimeScheduler<long, long> ();
823                 v.ScheduleAbsolute<Action> (null, 22);
824                 return 0;
825         }
826
827         public class Base {
828                 public virtual T foo<T> (T t) {
829                         return t;
830                 }
831         }
832
833         class Class1 : Base {
834                 public object o;
835
836                 public override T foo<T> (T t) {
837                         o = t;
838                         return t;
839                 }
840         }
841
842         class Class2 : Base {
843                 public object o;
844
845                 public override T foo<T> (T t) {
846                         o = t;
847                         return t;
848                 }
849         }
850
851         [MethodImplAttribute (MethodImplOptions.NoInlining)]
852         public static void bar<T> (Base b, T t) {
853                 b.foo (t);
854         }
855
856         public static int test_0_virtual_generic () {
857                 Class1 c1 = new Class1 ();
858                 Class2 c2 = new Class2 ();
859                 bar (c1, 5);
860                 if (!(c1.o is int) || ((int)c1.o != 5))
861                         return 1;
862                 bar (c1, 6.0);
863                 if (!(c1.o is double) || ((double)c1.o != 6.0))
864                         return 2;
865                 bar (c1, 7.0f);
866                 if (!(c1.o is float) || ((float)c1.o != 7.0f))
867                         return 3;
868                 bar (c2, 5);
869                 if (!(c2.o is int) || ((int)c2.o != 5))
870                         return 4;
871                 bar (c2, 6.0);
872                 bar (c2, 7.0f);
873                 return 0;
874         }
875
876         [MethodImplAttribute (MethodImplOptions.NoInlining)]
877         static string to_string<T, T2>(T t, T2 t2) {
878                 return t.ToString ();
879         }
880
881         public static int test_0_constrained_tostring () {
882                 if (to_string<int, int> (1, 1) != "1")
883                         return 1;
884                 if (to_string<string, int> ("A", 1) != "A")
885                         return 2;
886                 return 0;
887         }
888
889         struct Pair<T1, T2> {
890                 public T1 First;
891                 public T2 Second;
892         }
893
894         [MethodImplAttribute (MethodImplOptions.NoInlining)]
895         public static TState call_del<TState>(TState state, Func<object, TState, TState> action) {
896                 return action(null, state);
897         }
898
899         public static int test_0_delegate_wrappers () {
900                 Func<object, Pair<int, int>, Pair<int, int>> del1 = delegate (object o, Pair<int, int> p) { return p; };
901                 Func<object, Pair<int, int>, Pair<int, int>> del2 = delegate (object o, Pair<int, int> p) { return p; };
902                 Func<object, Pair<double, int>, Pair<double, int>> del3 = delegate (object o, Pair<double, int> p) { return p; };
903                 var r1 = call_del<Pair<int, int>> (new Pair<int, int> { First = 1, Second = 2}, del1);
904                 if (r1.First != 1 || r1.Second != 2)
905                         return 1;
906                 var r2 = call_del<Pair<int, int>> (new Pair<int, int> { First = 3, Second = 4}, del2);
907                 if (r2.First != 3 || r2.Second != 4)
908                         return 2;
909                 var r3 = call_del<Pair<double, int>> (new Pair<double, int> { First = 1.0, Second = 2}, del3);
910                 if (r3.First != 1.0 || r3.Second != 2)
911                         return 3;
912                 return 0;
913         }
914
915         class Base<T> {
916                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
917                 public object foo<T1> (T1 t1, T t, object o) {
918                         return o;
919                 }
920         }
921
922         class AClass : Base<long> {
923
924                 [MethodImplAttribute (MethodImplOptions.NoInlining)]
925                 public object bar<T> (T t, long time, object o) {
926                         return foo (t, time, o);
927                 }
928         }
929
930         public static int test_0_out_in_wrappers () {
931                 var a = new AClass ();
932                 object o1 = "A";
933                 object o2 = a.bar<long> (1024, 0, o1);
934                 if (o1 != o2)
935                         return 1;
936                 return 0;               
937         }
938 }