[runtime] Handle RuntimeWrappedException and dynamic methods using a SRE as module...
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / DynamicMethodTest.cs
1 //
2 // DynamicMethodTest.cs - NUnit Test Cases for the DynamicMethod class
3 //
4 // Gert Driesen (drieseng@users.sourceforge.net)
5 // Konrad Kruczynski
6 //
7 // (C) 2006 Novell
8
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Runtime.InteropServices;
14 using System.Runtime.CompilerServices;
15 using System.Text;
16 using System.Diagnostics;
17 using System.Runtime.ExceptionServices;
18 using System.Linq;
19
20 using NUnit.Framework;
21
22 namespace MonoTests.System.Reflection.Emit
23 {
24         [TestFixture]
25         public class DynamicMethodTest
26         {
27                 private delegate int HelloInvoker (string msg);
28
29                 [Test]
30                 public void Constructor1_Name_Null ()
31                 {
32                         try {
33                                 new DynamicMethod (null,
34                                         typeof (void),
35                                         new Type[] { typeof (string) },
36                                         typeof (DynamicMethodTest).Module);
37                                 Assert.Fail ("#1");
38                         } catch (ArgumentNullException ex) {
39                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
40                                 Assert.AreEqual ("name", ex.ParamName, "#3");
41                                 Assert.IsNull (ex.InnerException, "#4");
42                         }
43                 }
44
45                 [Test]
46                 public void Constructor2_Name_Null ()
47                 {
48                         try {
49                                 new DynamicMethod (null,
50                                         typeof (void),
51                                         new Type[] { typeof (string) },
52                                         typeof (DynamicMethodTest));
53                                 Assert.Fail ("#1");
54                         } catch (ArgumentNullException ex) {
55                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
56                                 Assert.AreEqual ("name", ex.ParamName, "#3");
57                                 Assert.IsNull (ex.InnerException, "#4");
58                         }
59                 }
60
61                 [Test]
62                 public void Constructor3_Name_Null ()
63                 {
64                         try {
65                                 new DynamicMethod (null,
66                                         typeof (void),
67                                         new Type[] { typeof (string) },
68                                         typeof (DynamicMethodTest).Module, true);
69                                 Assert.Fail ("#1");
70                         } catch (ArgumentNullException ex) {
71                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
72                                 Assert.AreEqual ("name", ex.ParamName, "#3");
73                                 Assert.IsNull (ex.InnerException, "#4");
74                         }
75                 }
76
77                 [Test]
78                 public void Constructor4_Name_Null ()
79                 {
80                         try {
81                                 new DynamicMethod (null,
82                                         typeof (void),
83                                         new Type[] { typeof (string) },
84                                         typeof (DynamicMethodTest), true);
85                                 Assert.Fail ("#1");
86                         } catch (ArgumentNullException ex) {
87                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
88                                 Assert.AreEqual ("name", ex.ParamName, "#3");
89                                 Assert.IsNull (ex.InnerException, "#4");
90                         }
91                 }
92
93                 [Test]
94                 public void Constructor5_Name_Null ()
95                 {
96                         try {
97                                 new DynamicMethod (null,
98                                         MethodAttributes.Public | MethodAttributes.Static,
99                                         CallingConventions.Standard,
100                                         typeof (void),
101                                         new Type[] { typeof (string) },
102                                         typeof (DynamicMethodTest).Module, true);
103                                 Assert.Fail ("#1");
104                         } catch (ArgumentNullException ex) {
105                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
106                                 Assert.AreEqual ("name", ex.ParamName, "#3");
107                                 Assert.IsNull (ex.InnerException, "#4");
108                         }
109                 }
110
111                 [Test]
112                 public void Constructor6_Name_Null ()
113                 {
114                         try {
115                                 new DynamicMethod (null,
116                                         MethodAttributes.Public | MethodAttributes.Static,
117                                         CallingConventions.Standard,
118                                         typeof (void),
119                                         new Type[] { typeof (string) },
120                                         typeof (DynamicMethodTest), true);
121                                 Assert.Fail ("#1");
122                         } catch (ArgumentNullException ex) {
123                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
124                                 Assert.AreEqual ("name", ex.ParamName, "#3");
125                                 Assert.IsNull (ex.InnerException, "#4");
126                         }
127                 }
128
129                 [Test]
130                 public void OwnerCantBeArray ()
131                 {
132                         TestOwner (typeof (int[]));
133                 }
134
135                 [Test]
136                 public void OwnerCantBeInterface ()
137                 {
138                         TestOwner (typeof (global::System.Collections.IEnumerable));
139                 }
140
141                 private void TestOwner (Type owner)
142                 {
143                         try {
144                                 new DynamicMethod ("Name", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
145                                                    typeof(void), new Type[] { }, owner, true);
146                                 Assert.Fail (string.Format ("Created dynamic method with owner being {0}.", owner));
147                         } catch (ArgumentException) {
148                         }
149                 }
150
151                 [Test] // bug #78253
152                 public void DynamicMethodReference ()
153                 {
154                         DynamicMethod hello = new DynamicMethod ("Hello",
155                                 typeof (int),
156                                 new Type[] { typeof (string) },
157                                 typeof (DynamicMethodTest).Module);
158                         Assert.IsNull (hello.DeclaringType, "#1");
159
160                         DynamicMethod write = new DynamicMethod ("Write",
161                                 typeof (int),
162                                 new Type[] { typeof (string) },
163                                 typeof (DynamicMethodTest));
164                         Assert.IsNull (hello.DeclaringType, "#2");
165
166                         MethodInfo invokeWrite = write.GetBaseDefinition ();
167
168                         ILGenerator helloIL = hello.GetILGenerator ();
169                         helloIL.Emit (OpCodes.Ldarg_0);
170                         helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
171                         helloIL.Emit (OpCodes.Ret);
172
173                         ILGenerator writeIL = write.GetILGenerator ();
174                         writeIL.Emit (OpCodes.Ldc_I4_2);
175                         writeIL.Emit (OpCodes.Ret);
176
177                         HelloInvoker hi =
178                                 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
179                         int ret = hi ("Hello, World!");
180                         Assert.AreEqual (2, ret, "#3");
181
182                         object[] invokeArgs = { "Hello, World!" };
183                         object objRet = hello.Invoke (null, invokeArgs);
184                         Assert.AreEqual (2, objRet, "#4");
185                 }
186
187                 [Test]
188                 public void EmptyMethodBody ()
189                 {
190                         DynamicMethod hello = new DynamicMethod ("Hello",
191                                 typeof (int),
192                                 new Type[] { typeof (string) },
193                                 typeof (DynamicMethodTest).Module);
194                         object[] invokeArgs = { "Hello, World!" };
195
196                         // no IL generator
197                         try {
198                                 hello.Invoke (null, invokeArgs);
199                                 Assert.Fail ("#1");
200                         } catch (InvalidOperationException) {
201                         }
202
203                         // empty method body
204                         hello.GetILGenerator ();
205                         try {
206                                 hello.Invoke (null, invokeArgs);
207                                 Assert.Fail ("#2");
208                         } catch (InvalidOperationException) {
209                         }
210                 }
211
212                 private delegate string ReturnString (string msg);
213                 private delegate void DoNothing (string msg);
214
215                 private static string private_method (string s) {
216                         return s;
217                 }
218
219                 [Test]
220                 public void SkipVisibility ()
221                 {
222                         DynamicMethod hello = new DynamicMethod ("Hello",
223                                 typeof (string),
224                                 new Type[] { typeof (string) },
225                                 typeof (DynamicMethodTest).Module, true);
226
227                         ILGenerator helloIL = hello.GetILGenerator ();
228                         helloIL.Emit (OpCodes.Ldarg_0);
229                         helloIL.EmitCall (OpCodes.Call, typeof (DynamicMethodTest).GetMethod ("private_method", BindingFlags.Static|BindingFlags.NonPublic), null);
230                         helloIL.Emit (OpCodes.Ret);
231
232                         ReturnString del =
233                                 (ReturnString) hello.CreateDelegate (typeof (ReturnString));
234                         Assert.AreEqual ("ABCD", del ("ABCD"));
235                 }
236
237                 [Test]
238                 public void ReturnType_Null ()
239                 {
240                         DynamicMethod hello = new DynamicMethod ("Hello",
241                                 null,
242                                 new Type[] { typeof (string) },
243                                 typeof (DynamicMethodTest).Module, true);
244                         Assert.AreEqual (typeof (void), hello.ReturnType, "#1");
245
246                         ILGenerator helloIL = hello.GetILGenerator ();
247                         helloIL.Emit (OpCodes.Ret);
248
249                         DoNothing dn = (DoNothing) hello.CreateDelegate (typeof (DoNothing));
250                         dn ("whatever");
251
252                         object[] invokeArgs = { "Hello, World!" };
253                         object objRet = hello.Invoke (null, invokeArgs);
254                         Assert.IsNull (objRet, "#2");
255                 }
256
257                 [Test]
258                 public void Name_Empty ()
259                 {
260                         DynamicMethod hello = new DynamicMethod (string.Empty,
261                                 typeof (int),
262                                 new Type[] { typeof (string) },
263                                 typeof (DynamicMethodTest).Module);
264                         Assert.AreEqual (string.Empty, hello.Name, "#1");
265
266                         DynamicMethod write = new DynamicMethod ("Write",
267                                 typeof (int),
268                                 new Type[] { typeof (string) },
269                                 typeof (DynamicMethodTest));
270
271                         MethodInfo invokeWrite = write.GetBaseDefinition ();
272
273                         ILGenerator helloIL = hello.GetILGenerator ();
274                         helloIL.Emit (OpCodes.Ldarg_0);
275                         helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
276                         helloIL.Emit (OpCodes.Ret);
277
278                         ILGenerator writeIL = write.GetILGenerator ();
279                         writeIL.Emit (OpCodes.Ldc_I4_2);
280                         writeIL.Emit (OpCodes.Ret);
281
282                         HelloInvoker hi =
283                                 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
284                         int ret = hi ("Hello, World!");
285                         Assert.AreEqual (2, ret, "#2");
286
287                         object[] invokeArgs = { "Hello, World!" };
288                         object objRet = hello.Invoke (null, invokeArgs);
289                         Assert.AreEqual (2, objRet, "#3");
290                 }
291
292                 [Test]
293                 public void Circular_Refs () {
294                         DynamicMethod m1 = new DynamicMethod("f1", typeof(int), new Type[] { typeof (int) },
295                                                                                                  typeof(object));
296                         DynamicMethod m2 = new DynamicMethod("f2", typeof(int), new Type[] { typeof (int) },
297                                                                                                  typeof(object));
298
299                         ILGenerator il1 = m1.GetILGenerator();
300                         ILGenerator il2 = m2.GetILGenerator();
301
302                         Label l = il1.DefineLabel ();
303                         //il1.EmitWriteLine ("f1");
304                         il1.Emit (OpCodes.Ldarg_0);
305                         il1.Emit (OpCodes.Ldc_I4_0);
306                         il1.Emit (OpCodes.Bne_Un, l);
307                         il1.Emit (OpCodes.Ldarg_0);
308                         il1.Emit (OpCodes.Ret);
309                         il1.MarkLabel (l);
310                         il1.Emit (OpCodes.Ldarg_0);
311                         il1.Emit (OpCodes.Ldc_I4_1);
312                         il1.Emit (OpCodes.Sub);
313                         il1.Emit (OpCodes.Call, m2);
314                         il1.Emit (OpCodes.Ret);
315
316                         //il2.EmitWriteLine("f2");
317                         il2.Emit(OpCodes.Ldarg_0);
318                         il2.Emit(OpCodes.Call, m1);
319                         il2.Emit(OpCodes.Ret);
320
321                         m1.Invoke(null, new object[] { 5 });
322                 }
323
324                 // Disabl known warning, the Field is never used directly from C#
325                 #pragma warning disable 414
326                 class Host {
327                         static string Field = "foo";
328                 }
329                 #pragma warning restore 414
330                 [Test]
331                 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
332                 public void TestOwnerMemberAccess ()
333                 {
334                         DynamicMethod method = new DynamicMethod ("GetField",
335                                 typeof (string), new Type [0], typeof (Host));
336
337                         ILGenerator il = method.GetILGenerator ();
338                         il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
339                                 "Field", BindingFlags.Static | BindingFlags.NonPublic));
340                         il.Emit (OpCodes.Ret);
341
342                         string ret = (string) method.Invoke (null, new object [] {});
343                         Assert.AreEqual ("foo", ret, "#1");
344                 }
345
346                 [Test]
347                 public void AnonHosted ()
348                 {
349                         DynamicMethod hello = new DynamicMethod ("Hello",
350                                                                                                          typeof (int),
351                                                                                                          new Type[] { typeof (string) });
352                         ILGenerator helloIL = hello.GetILGenerator ();
353                         helloIL.Emit (OpCodes.Ldc_I4_2);
354                         helloIL.Emit (OpCodes.Ret);
355
356                         HelloInvoker hi =
357                                 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
358                         int ret = hi ("Hello, World!");
359                         Assert.AreEqual (2, ret);
360
361                         object[] invokeArgs = { "Hello, World!" };
362                         object objRet = hello.Invoke (null, invokeArgs);
363                         Assert.AreEqual (2, objRet);
364                 }
365
366                 public delegate int IntInvoker();
367
368                 public class Foo<T> {
369                         public virtual int Test () { return 99; }
370                 } 
371
372                 [Test]
373                 public void ConstrainedPrexixDoesntCrash () //bug #529238
374                 {
375                         Type foo = typeof (Foo<int>);
376
377                         DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
378                         ILGenerator ilgen = dm.GetILGenerator ();
379                         ilgen.DeclareLocal (foo);
380                         ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
381                         ilgen.Emit (OpCodes.Stloc_0);
382                         ilgen.Emit (OpCodes.Ldloca_S, 0);
383                         ilgen.Emit (OpCodes.Constrained, foo);
384                         ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
385                         ilgen.Emit (OpCodes.Ret);
386
387                         IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
388                         Assert.AreEqual (99, hi (), "#1");      
389                 }
390
391                 // #575955
392                 [Test]
393                 public void Module_GetMethod () {
394                         AssemblyName assemblyName = new AssemblyName ();
395                         assemblyName.Name = "foo";
396
397                         AssemblyBuilder assembly =
398                                 AppDomain.CurrentDomain.DefineDynamicAssembly (
399                                                                                                                            assemblyName, AssemblyBuilderAccess.RunAndSave);
400
401                         ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
402
403                         var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
404                         var ig = d.GetILGenerator ();
405                         ig.Emit (OpCodes.Ldarg_0);
406                         ig.Emit (OpCodes.Ldc_I4, 1);
407                         ig.Emit (OpCodes.Ldc_I4, 1);
408                         ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
409                         ig.Emit (OpCodes.Ret);
410                 
411                         var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
412                         int[,] arr = new int [10, 10];
413                         arr [1, 1] = 5;
414                         Assert.AreEqual (5, del (arr));
415                 }
416
417                 [Test]
418                 [Category ("NotWorking")]
419                 public void InvalidUnicodeName ()
420                 {
421                         var name = new StringBuilder ().Append ('\udf45').Append ('\ud808');
422                         var method = new DynamicMethod (name.ToString (), typeof (bool), new Type [0]);
423                         var il = method.GetILGenerator ();
424                         il.Emit (OpCodes.Ldc_I4_1);
425                         il.Emit (OpCodes.Ret);
426
427                         var function = (Func<bool>) method.CreateDelegate (typeof (Func<bool>));
428
429                         Assert.IsTrue (function ());
430                 }
431
432                 [Test]
433                 [ExpectedException (typeof (InvalidOperationException))]
434                 public void GetMethodBody ()
435                 {
436                         var method = new DynamicMethod ("method", typeof (object), new Type [] { typeof (object) });
437
438                         var il = method.GetILGenerator ();
439                         il.Emit (OpCodes.Ldarg_0);
440                         il.Emit (OpCodes.Ret);
441
442                         var f = (Func<object, object>) method.CreateDelegate (typeof (Func<object, object>));
443                         f.Method.GetMethodBody ();
444                 }
445
446                 [Test]
447                 public void GetCustomAttributes ()
448                 {
449                         var method = new DynamicMethod ("method", typeof (void), new Type [] { });
450
451                         var methodImplAttrType = typeof (MethodImplAttribute);
452                         Assert.IsTrue (method.IsDefined (methodImplAttrType, true), "MethodImplAttribute is defined");
453
454                         // According to the spec, MethodImplAttribute is the
455                         // only custom attr that's present on a DynamicMethod.
456                         // And it's always a managed method with no inlining.
457                         var a1 = method.GetCustomAttributes (true);
458                         Assert.AreEqual (a1.Length, 1, "a1.Length == 1");
459                         Assert.AreEqual (a1[0].GetType (), methodImplAttrType, "a1[0] is a MethodImplAttribute");
460                         var options = (a1[0] as MethodImplAttribute).Value;
461                         Assert.IsTrue ((options & MethodImplOptions.NoInlining) != 0, "NoInlining is set");
462                         Assert.IsTrue ((options & MethodImplOptions.Unmanaged) == 0, "Unmanaged isn't set");
463
464
465                         // any other custom attribute type
466                         var extensionAttrType = typeof (ExtensionAttribute);
467                         Assert.IsFalse (method.IsDefined (extensionAttrType, true));
468                         Assert.AreEqual (Array.Empty<object>(), method.GetCustomAttributes (extensionAttrType, true));
469                 }
470
471         public delegate object RetObj();
472                 [Test] //#640702
473                 public void GetCurrentMethodWorksWithDynamicMethods ()
474                 {
475                 DynamicMethod dm = new DynamicMethod("Foo", typeof(object), null);
476                 ILGenerator ilgen = dm.GetILGenerator();
477                 ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
478                 ilgen.Emit(OpCodes.Ret);
479                 RetObj del = (RetObj)dm.CreateDelegate(typeof(RetObj));
480                     MethodInfo res = (MethodInfo)del();
481                         Assert.AreEqual (dm.Name, res.Name, "#1");
482
483                 }
484
485                 [StructLayout (LayoutKind.Explicit)]
486                 struct SizeOfTarget {
487                         [FieldOffset (0)] public int X;
488                         [FieldOffset (4)] public int Y;
489                 }
490
491                 [Test]
492                 public void SizeOf ()
493                 {
494                         var method = new DynamicMethod ("", typeof (int), Type.EmptyTypes);
495                         var il = method.GetILGenerator ();
496                         il.Emit (OpCodes.Sizeof, typeof (SizeOfTarget));
497                         il.Emit (OpCodes.Ret);
498
499                         var func = (Func<int>) method.CreateDelegate (typeof (Func<int>));
500                         var point_size = func ();
501
502                         Assert.AreEqual (8, point_size);
503                 }
504
505                 class TypedRefTarget {
506                         public string Name;
507                 }
508
509                 class ExceptionHandling_Test_Support
510                 {
511                         public static Exception Caught;
512                         public static string CaughtStackTrace;
513
514                         public static void ThrowMe ()
515                         {
516                                 Caught = null;
517                                 CaughtStackTrace = null;
518                                 throw new Exception("test");
519                         }
520
521                         public static void Handler (Exception e)
522                         {
523                                 Caught = e;
524                                 CaughtStackTrace = e.StackTrace.ToString ();
525                         }
526                 }
527
528                 [Test]
529                 public void ExceptionHandling ()
530                 {
531                         var method = new DynamicMethod ("", typeof(void), new[] { typeof(int) }, typeof (DynamicMethodTest));
532                         var ig = method.GetILGenerator ();
533
534                         ig.BeginExceptionBlock();
535                         ig.Emit(OpCodes.Call, typeof(ExceptionHandling_Test_Support).GetMethod("ThrowMe"));
536
537                         ig.BeginCatchBlock(typeof(Exception));
538                         ig.Emit(OpCodes.Call, typeof(ExceptionHandling_Test_Support).GetMethod("Handler"));
539                         ig.EndExceptionBlock();
540
541                         ig.Emit(OpCodes.Ret);
542
543                         var invoke = (Action<int>) method.CreateDelegate (typeof(Action<int>));
544                         invoke (456324);
545
546                         Assert.IsNotNull (ExceptionHandling_Test_Support.Caught, "#1");
547
548                         var lines = ExceptionHandling_Test_Support.CaughtStackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.None);
549                         lines = lines.Where (l => !l.StartsWith ("[")).ToArray ();
550                         Assert.AreEqual (2, lines.Length, "#2");
551
552                         var st = new StackTrace (ExceptionHandling_Test_Support.Caught, 0, true);
553
554                         // Caught stack trace when dynamic method is gone
555                         Assert.AreEqual (ExceptionHandling_Test_Support.CaughtStackTrace, st.ToString (), "#3");
556
557                         // Catch handler stack trace inside dynamic method match
558                         Assert.AreEqual (ExceptionHandling_Test_Support.Caught.StackTrace, st.ToString (), "#4");
559                 }
560
561                 class ExceptionHandlingWithExceptionDispatchInfo_Test_Support
562                 {
563                         public static Exception Caught;
564                         public static string CaughtStackTrace;
565
566                         public static void ThrowMe ()
567                         {
568                                 Caught = null;
569                                 CaughtStackTrace = null;
570
571                                 Exception e;
572                                 try {
573                                         throw new Exception("test");
574                                 } catch (Exception e2) {
575                                         e = e2;
576                                 }
577
578                                 var edi = ExceptionDispatchInfo.Capture(e);
579
580                                 edi.Throw();
581                         }
582
583                         public static void Handler (Exception e)
584                         {
585                                 var lines = e.StackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
586                                 // Ignore Metadata
587                                 lines = lines.Where (l => !l.StartsWith ("[")).ToArray ();
588
589                                 Assert.AreEqual (5, lines.Length, "#1");
590                                 Assert.IsTrue (lines [1].Contains ("---"), "#2");
591                         }
592                 }
593
594                 [Test]
595                 public void ExceptionHandlingWithExceptionDispatchInfo ()
596                 {
597                         var method = new DynamicMethod ("", typeof(void), new[] { typeof(int) }, typeof (DynamicMethodTest));
598                         var ig = method.GetILGenerator ();
599
600                         ig.BeginExceptionBlock();
601                         ig.Emit(OpCodes.Call, typeof(ExceptionHandlingWithExceptionDispatchInfo_Test_Support).GetMethod("ThrowMe"));
602
603                         ig.BeginCatchBlock(typeof(Exception));
604                         ig.Emit(OpCodes.Call, typeof(ExceptionHandlingWithExceptionDispatchInfo_Test_Support).GetMethod("Handler"));
605                         ig.EndExceptionBlock();
606
607                         ig.Emit(OpCodes.Ret);
608
609                         var invoke = (Action<int>) method.CreateDelegate (typeof(Action<int>));
610                         invoke (444);
611                 }
612
613                 static Func<int> EmitDelegate (DynamicMethod dm) {
614                         ILGenerator il = dm.GetILGenerator ();
615                         var ret_val = il.DeclareLocal (typeof (int));
616                         var leave_label = il.DefineLabel ();
617
618                         //ret = 1;
619                         il.Emit (OpCodes.Ldc_I4, 1);
620                         il.Emit (OpCodes.Stloc, ret_val);
621
622                         // try {
623                         il.BeginExceptionBlock ();
624                         //      throw "hello";
625                         il.Emit (OpCodes.Ldstr, "hello");
626                         il.Emit (OpCodes.Throw, typeof (string));
627                         //      ret = 2
628                         il.Emit (OpCodes.Ldc_I4, 2);
629                         il.Emit (OpCodes.Stloc, ret_val);
630                         // }
631                         il.Emit (OpCodes.Leave, leave_label);
632                         //catch (string)
633                         il.BeginCatchBlock (typeof (string));
634                         il.Emit (OpCodes.Pop);
635                         //      ret = 3
636                         il.Emit (OpCodes.Ldc_I4, 3);
637                         il.Emit (OpCodes.Stloc, ret_val);
638                         //}
639                         il.Emit (OpCodes.Leave, leave_label);
640                         il.EndExceptionBlock ();
641
642                         il.MarkLabel (leave_label);
643                         //return ret;
644                         il.Emit (OpCodes.Ldloc, ret_val);
645                         il.Emit (OpCodes.Ret);
646
647                         var dele = (Func<int>)dm.CreateDelegate (typeof (Func<int>));
648                         return dele;
649                 }
650
651                 [Test] //see bxc #59334
652                 public void ExceptionWrapping ()
653                 {
654                         AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ehatevfheiw"), AssemblyBuilderAccess.Run);
655                         AssemblyBuilder ab2 = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ddf4234"), AssemblyBuilderAccess.Run);
656                         CustomAttributeBuilder cab = new CustomAttributeBuilder (
657                                         typeof (RuntimeCompatibilityAttribute).GetConstructor (new Type [0]),
658                                         new object [0],
659                                         new PropertyInfo[] { typeof (RuntimeCompatibilityAttribute).GetProperty ("WrapNonExceptionThrows") },
660                                         new object[] { true });
661                         ab2.SetCustomAttribute (cab);
662
663                         AssemblyBuilder ab3 = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("frfhfher"), AssemblyBuilderAccess.Run);
664                         //1 NamedArg. Property name: WrapNonExceptionThrows value: true (0x01) 
665                         byte[] blob = new byte[] { 0x01, 0x00, 0x01, 0x00, 0x54, 0x02, 0x16, 0x57, 0x72, 0x61, 0x70, 0x4E, 0x6F, 0x6E, 0x45, 0x78,
666                                 0x63, 0x65, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x54, 0x68, 0x72, 0x6F, 0x77, 0x73, 0x01 };
667                         ab3.SetCustomAttribute (typeof (RuntimeCompatibilityAttribute).GetConstructor (new Type [0]), blob);
668                 
669                         DynamicMethod invoke_no_module = new DynamicMethod("throw_1", typeof (int), new Type [0]);
670                         DynamicMethod invoke_with_module = new DynamicMethod("throw_2", typeof (int), new Type [0], typeof (DynamicMethodTest).Module);
671                         DynamicMethod invoke_with_ab = new DynamicMethod("throw_3", typeof (int), new Type [0], ab.ManifestModule);
672                         DynamicMethod invoke_with_ab2 = new DynamicMethod("throw_4", typeof (int), new Type [0], ab2.ManifestModule);
673                         DynamicMethod invoke_with_ab3 = new DynamicMethod("throw_5", typeof (int), new Type [0], ab3.ManifestModule);
674
675                         int result = 0;
676                         try {
677                                 int res = EmitDelegate (invoke_no_module)();
678                                 Assert.AreEqual (3, res, "invoke_no_module bad return value");
679                         } catch (RuntimeWrappedException e) {
680                                 Assert.Fail ("invoke_no_module threw RWE");
681                         }
682
683                         try {
684                                 int res = EmitDelegate (invoke_with_module)();
685                                 Assert.Fail ("invoke_with_module did not throw RWE");
686                         } catch (RuntimeWrappedException e) {
687                         }
688
689                         try {
690                                 int res = EmitDelegate (invoke_with_ab)();
691                                 Assert.AreEqual (3, res, "invoke_with_ab bad return value");
692                         } catch (RuntimeWrappedException e) {
693                                 Assert.Fail ("invoke_with_ab threw RWE");
694                         }
695
696                         try {
697                                 int res = EmitDelegate (invoke_with_ab2)();
698                                 Assert.Fail ("invoke_with_ab2 did not throw RWE");
699                         } catch (RuntimeWrappedException e) {
700                         }
701
702                         try {
703                                 int res = EmitDelegate (invoke_with_ab3)();
704                                 Assert.Fail ("invoke_with_a3 did not throw RWE");
705                         } catch (RuntimeWrappedException e) {
706                         }                       
707                 }
708
709 #if !MONODROID
710                 // RUNTIME: crash
711                 [Test]
712                 public void TypedRef ()
713                 {
714                         var method = new DynamicMethod ("", typeof (TypedRefTarget), new [] {typeof (TypedRefTarget)}, true);
715                         var il = method.GetILGenerator ();
716                         var tr = il.DeclareLocal (typeof (TypedReference));
717
718                         il.Emit (OpCodes.Ldarga, 0);
719                         il.Emit (OpCodes.Mkrefany, typeof (TypedRefTarget));
720                         il.Emit (OpCodes.Stloc, tr);
721
722                         il.Emit (OpCodes.Ldloc, tr);
723                         il.Emit (OpCodes.Call, GetType ().GetMethod ("AssertTypedRef", BindingFlags.NonPublic | BindingFlags.Static));
724
725                         il.Emit (OpCodes.Ldloc, tr);
726                         il.Emit (OpCodes.Refanyval, typeof (TypedRefTarget));
727                         il.Emit (OpCodes.Ldobj, typeof (TypedRefTarget));
728                         il.Emit (OpCodes.Ret);
729
730                         var f = (Func<TypedRefTarget, TypedRefTarget>) method.CreateDelegate (typeof (Func<TypedRefTarget, TypedRefTarget>));
731
732                         var target = new TypedRefTarget { Name = "Foo" };
733                         var rt = f (target);
734
735                         Assert.AreEqual (target, rt);
736                 }
737
738                 private static void AssertTypedRef (TypedReference tr)
739                 {
740                         Assert.AreEqual (typeof (TypedRefTarget), TypedReference.GetTargetType (tr));
741                 }
742 #endif
743         }
744 }
745