[arm64] Fix finally abort
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / Generation / CompilerHelpers.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 #if FEATURE_NUMERICS
17 using BigInt = System.Numerics.BigInteger;
18 #endif
19
20 #if FEATURE_CORE_DLR
21 using System.Linq.Expressions;
22 #endif
23
24 using System;
25 using System.Collections;
26 using System.Collections.Generic;
27 using System.ComponentModel;
28 using System.Diagnostics;
29 using System.Dynamic;
30 using System.Linq;
31 using System.Reflection;
32 using System.Threading;
33 #if FEATURE_REFEMIT
34 using System.Reflection.Emit;
35 #endif
36 using System.Runtime.CompilerServices;
37 using Microsoft.Scripting.Actions;
38 using Microsoft.Scripting.Ast;
39 using Microsoft.Scripting.Interpreter;
40 using Microsoft.Scripting.Math;
41 using Microsoft.Scripting.Runtime;
42 using Microsoft.Scripting.Utils;
43 using AstUtils = Microsoft.Scripting.Ast.Utils;
44
45 namespace Microsoft.Scripting.Generation {
46     // TODO: keep this?
47     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
48     public delegate void ActionRef<T0, T1>(ref T0 arg0, ref T1 arg1);
49
50     public static class CompilerHelpers {
51                 public const MethodAttributes PublicStatic = MethodAttributes.Public | MethodAttributes.Static;
52                 private static MethodInfo _CreateInstanceMethod;
53
54         private static int _Counter; // for generating unique names for lambda methods
55
56         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
57         public static object GetMissingValue(Type type) {
58             ContractUtils.RequiresNotNull(type, "type");
59
60             if (type.IsByRef) type = type.GetElementType();
61             if (type.IsEnum()) return Activator.CreateInstance(type);
62
63             switch (type.GetTypeCode()) {
64                 default:
65                 case TypeCode.Object:
66                     // struct
67                     if (type.IsSealed() && type.IsValueType()) {
68                         return Activator.CreateInstance(type);
69                     } else if (type == typeof(object)) {
70                         // parameter of type object receives the actual Missing value
71                         return Missing.Value;
72                     } else if (!type.IsValueType()) {
73                         return null;
74                     } else {
75                         throw Error.CantCreateDefaultTypeFor(type);
76                     }
77                 case TypeCode.Empty:
78                 case TypeCode.DBNull:
79                 case TypeCode.String:
80                     return null;
81
82                 case TypeCode.Boolean: return false;
83                 case TypeCode.Char: return '\0';
84                 case TypeCode.SByte: return (sbyte)0;
85                 case TypeCode.Byte: return (byte)0;
86                 case TypeCode.Int16: return (short)0;
87                 case TypeCode.UInt16: return (ushort)0;
88                 case TypeCode.Int32: return (int)0;
89                 case TypeCode.UInt32: return (uint)0;
90                 case TypeCode.Int64: return 0L;
91                 case TypeCode.UInt64: return 0UL;
92                 case TypeCode.Single: return 0.0f;
93                 case TypeCode.Double: return 0.0D;
94                 case TypeCode.Decimal: return (decimal)0;
95                 case TypeCode.DateTime: return DateTime.MinValue;
96             }
97         }
98
99         public static bool IsStatic(MethodBase mi) {
100             return mi.IsConstructor || mi.IsStatic;
101         }
102
103         /// <summary>
104         /// True if the MethodBase is method which is going to construct an object
105         /// </summary>
106         public static bool IsConstructor(MethodBase mb) {
107             if (mb.IsConstructor) {
108                 return true;
109             }
110
111             if (mb.IsGenericMethod) {
112                 MethodInfo mi = mb as MethodInfo;
113
114                                 if (_CreateInstanceMethod == null)
115                                         Interlocked.CompareExchange (ref _CreateInstanceMethod, typeof(ScriptingRuntimeHelpers).GetMethod ("CreateInstance"), null);
116
117                                 if (mi.GetGenericMethodDefinition() == _CreateInstanceMethod) {
118                     return true;
119                 }
120             }
121
122             return false;
123         }
124
125         public static T[] MakeRepeatedArray<T>(T item, int count) {
126             T[] ret = new T[count];
127             for (int i = 0; i < count; i++) ret[i] = item;
128             return ret;
129         }
130         
131         public static bool IsComparisonOperator(ExpressionType op) {
132             switch (op) {
133                 case ExpressionType.LessThan: return true;
134                 case ExpressionType.LessThanOrEqual: return true;
135                 case ExpressionType.GreaterThan: return true;
136                 case ExpressionType.GreaterThanOrEqual: return true;
137                 case ExpressionType.Equal: return true;
138                 case ExpressionType.NotEqual: return true;
139             }
140             return false;
141         }
142
143         /// <summary>
144         /// Returns the System.Type for any object, including null.  The type of null
145         /// is represented by None.Type and all other objects just return the 
146         /// result of Object.GetType
147         /// </summary>
148         public static Type GetType(object obj) {
149             if (obj == null) {
150                 return typeof(DynamicNull);
151             }
152
153             return obj.GetType();
154         }
155
156         /// <summary>
157         /// Simply returns a Type[] from calling GetType on each element of args.
158         /// </summary>
159         public static Type[] GetTypes(object[] args) {
160             Type[] types = new Type[args.Length];
161             for (int i = 0; i < args.Length; i++) {
162                 types[i] = GetType(args[i]);
163             }
164             return types;
165         }
166
167         /// <summary>
168         /// EMITTED
169         /// Used by default method binder to check types of splatted arguments.
170         /// </summary>
171         public static bool TypesEqual(IList args, int start, Type[] types) {
172             for (int i = 0; i < types.Length; i++) {
173                 object arg = args[start + i];
174                 if (types[i] != (arg != null ? arg.GetType() : null)) {
175                     return false;
176                 }
177             }
178             return true;
179         }
180
181         public static bool CanOptimizeMethod(MethodBase method) {
182             if (method.ContainsGenericParameters ||
183                 method.IsProtected() ||
184                 method.IsPrivate ||
185                 !method.DeclaringType.IsVisible()) {
186                 return false;
187             }
188             return true;
189         }
190
191         /// <summary>
192         /// Given a MethodInfo which may be declared on a non-public type this attempts to
193         /// return a MethodInfo which will dispatch to the original MethodInfo but is declared
194         /// on a public type.
195         /// 
196         /// Returns the original method if the method if a public version cannot be found.
197         /// </summary>
198         public static MethodInfo TryGetCallableMethod(Type targetType, MethodInfo method) {
199             if (method.DeclaringType == null || method.DeclaringType.IsVisible()) {
200                 return method;
201             }
202
203             // first try and get it from the base type we're overriding...
204             MethodInfo baseMethod = method.GetRuntimeBaseDefinition();
205
206             if (baseMethod.DeclaringType.IsVisible() || baseMethod.DeclaringType.IsInterface()) {
207                 // We need to instantiate the method as GetBaseDefinition might return a generic definition of the base method:
208                 if (baseMethod.IsGenericMethodDefinition) {
209                     baseMethod = baseMethod.MakeGenericMethod(method.GetGenericArguments());
210                 }
211                 return baseMethod;
212             }
213
214 #if WIN8 // TODO: interface map, method handle
215             foreach (Type iface in targetType.GetImplementedInterfaces()) {
216                 dynamic mapping = ((dynamic)targetType).GetInterfaceMap(iface);
217                 for (int i = 0; i < mapping.TargetMethods.Length; i++) {
218                     MethodInfo targetMethod = mapping.TargetMethods[i];
219                     if (targetMethod != null && ((dynamic)targetMethod).MethodHandle == ((dynamic)method).MethodHandle) {
220                         return mapping.InterfaceMethods[i];
221                     }
222                 }
223             }
224 #else
225             // maybe we can get it from an interface on the type this
226             // method came from...
227             foreach (Type iface in targetType.GetImplementedInterfaces()) {
228                 if (iface.IsPublic()) {
229                     InterfaceMapping mapping = targetType.GetInterfaceMap(iface);
230                     for (int i = 0; i < mapping.TargetMethods.Length; i++) {
231                         MethodInfo targetMethod = mapping.TargetMethods[i];
232                         if (targetMethod != null && targetMethod.MethodHandle == method.MethodHandle) {
233                             return mapping.InterfaceMethods[i];
234                         }
235                     }
236                 }
237             }
238 #endif
239             return method;
240         }
241
242         /// <summary>
243         /// Non-public types can have public members that we find when calling type.GetMember(...).  This
244         /// filters out the non-visible members by attempting to resolve them to the correct visible type.
245         /// 
246         /// If no correct visible type can be found then the member is not visible and we won't call it.
247         /// </summary>
248         public static IEnumerable<MemberInfo> FilterNonVisibleMembers(Type targetType, IEnumerable<MemberInfo> members) {
249             if (targetType.IsVisible()) {
250                 return members;
251             } else {
252                 return FilterNonVisibleMembersIterator(targetType, members);
253             }
254         }
255
256         public static IEnumerable<MemberInfo> FilterNonVisibleMembersIterator(Type targetType, IEnumerable<MemberInfo> members) {
257             foreach (var member in members) {
258                 MemberInfo visible = TryGetVisibleMember(targetType, member);
259                 if (visible != null) {
260                     yield return visible;
261                 }
262             }
263         }
264
265         public static MemberInfo TryGetVisibleMember(Type targetType, MemberInfo member) {
266             MethodInfo method;
267             PropertyInfo property;
268             EventInfo evnt;
269
270             MethodInfo mi;
271             MemberInfo visible = null;
272
273             if ((method = member as MethodInfo) != null) {
274                 mi = TryGetCallableMethod(targetType, method);
275                 if (CompilerHelpers.IsVisible(mi)) {
276                     visible = mi;
277                 }
278             } else if ((property = member as PropertyInfo) != null) {
279                 mi = TryGetCallableMethod(targetType, property.GetGetMethod() ?? property.GetSetMethod());
280                 if (CompilerHelpers.IsVisible(mi)) {
281                     visible = mi.DeclaringType.GetDeclaredProperty(property.Name);
282                 }
283             } else if ((evnt = member as EventInfo) != null) {
284                 mi = TryGetCallableMethod(targetType, evnt.GetAddMethod() ?? evnt.GetRemoveMethod() ?? evnt.GetRaiseMethod());
285                 if (CompilerHelpers.IsVisible(mi)) {
286                     visible = mi.DeclaringType.GetDeclaredEvent(evnt.Name);
287                 }
288             }
289         
290             // all others can't be exposed out this way
291             return visible;
292         }
293
294 #if !WIN8
295         /// <summary>
296         /// Sees if two MemberInfos point to the same underlying construct in IL.  This
297         /// ignores the ReflectedType property which exists on MemberInfos which
298         /// causes direct comparisons to be false even if they are the same member.
299         /// </summary>
300         public static bool MemberEquals(this MemberInfo self, MemberInfo other) {
301             if ((self == null) != (other == null)) {
302                 // one null, the other isn't.
303                 return false;
304             } else if (self == null) {
305                 // both null
306                 return true;
307             }
308
309             if (self.MemberType != other.MemberType) {
310                 return false;
311             }
312
313             switch (self.MemberType) {
314                 case MemberTypes.Field:
315                     return ((FieldInfo)self).FieldHandle.Equals(((FieldInfo)other).FieldHandle);
316                 case MemberTypes.Method:
317                     return ((MethodInfo)self).MethodHandle.Equals(((MethodInfo)other).MethodHandle);
318                 case MemberTypes.Constructor:
319                     return ((ConstructorInfo)self).MethodHandle.Equals(((ConstructorInfo)other).MethodHandle);
320                 case MemberTypes.NestedType:
321                 case MemberTypes.TypeInfo:
322                     return ((Type)self).TypeHandle.Equals(((Type)other).TypeHandle);
323                 case MemberTypes.Event:
324                 case MemberTypes.Property:
325                 default:
326                     return
327                         ((MemberInfo)self).Module == ((MemberInfo)other).Module &&
328                         ((MemberInfo)self).MetadataToken == ((MemberInfo)other).MetadataToken;
329             }
330         }
331 #endif
332
333         public static bool IsVisible(MethodBase info) {
334             return info.IsPublic && (info.DeclaringType == null || info.DeclaringType.IsVisible());
335         }
336
337         public static bool IsVisible(FieldInfo info) {
338             return info.IsPublic && (info.DeclaringType == null || info.DeclaringType.IsVisible());
339         }
340
341         public static bool IsProtected(this MethodBase info) {
342             return info.IsFamily || info.IsFamilyOrAssembly;
343         }
344
345         public static bool IsProtected(this FieldInfo info) {
346             return info.IsFamily || info.IsFamilyOrAssembly;
347         }
348
349         public static bool IsProtected(this Type type) {
350             return type.GetTypeInfo().IsNestedFamily || type.GetTypeInfo().IsNestedFamORAssem;
351         }
352
353         public static Type GetVisibleType(object value) {
354             return GetVisibleType(GetType(value));
355         }
356
357         public static Type GetVisibleType(Type t) {
358             while (!t.IsVisible()) {
359                 t = t.GetBaseType();
360             }
361             return t;
362         }
363
364         public static MethodBase[] GetConstructors(Type t, bool privateBinding) {
365             return GetConstructors(t, privateBinding, false);
366         }
367
368         public static MethodBase[] GetConstructors(Type t, bool privateBinding, bool includeProtected) {
369             if (t.IsArray) {
370                 // The JIT verifier doesn't like new int[](3) even though it appears as a ctor.
371                 // We could do better and return newarr in the future.
372                 return new MethodBase[] { GetArrayCtor(t) };
373             }
374
375             BindingFlags bf = BindingFlags.Instance | BindingFlags.Public;
376             if (privateBinding || includeProtected) {
377                 bf |= BindingFlags.NonPublic;
378             }
379
380             IEnumerable<ConstructorInfo> ctors = t.GetDeclaredConstructors().WithBindingFlags(bf);
381
382             // leave in protected ctors, even if we're not in private binding mode.
383             if (!privateBinding && includeProtected) {
384                 ctors = FilterConstructorsToPublicAndProtected(ctors);
385             }
386
387             if (t.IsValueType()
388 #if !SILVERLIGHT && !WIN8 && !WP75
389                 && t != typeof(ArgIterator)
390 #endif
391 ) {
392                 // structs don't define a parameterless ctor, add a generic method for that.
393                 List<MethodBase> result = new List<MethodBase>();
394                 result.Add(GetStructDefaultCtor(t));
395                 result.AddRange(ctors.Cast<ConstructorInfo, MethodBase>());
396                 return result.ToArray();
397             } else {
398                 return ctors.ToArray();
399             }
400         }
401
402         public static IEnumerable<ConstructorInfo> FilterConstructorsToPublicAndProtected(IEnumerable<ConstructorInfo> ctors) {
403             foreach (var ctor in ctors) {
404                 if (ctor.IsPublic || ctor.IsProtected()) {
405                     yield return ctor;
406                 }
407             }
408         }
409
410         private static MethodBase GetStructDefaultCtor(Type t) {
411             return typeof(ScriptingRuntimeHelpers).GetDeclaredMethods("CreateInstance").Single().MakeGenericMethod(t);
412         }
413
414         private static MethodBase GetArrayCtor(Type t) {
415             return typeof(ScriptingRuntimeHelpers).GetDeclaredMethods("CreateArray").Single().MakeGenericMethod(t.GetElementType());
416         }
417
418         #region Type Conversions
419
420         public static MethodInfo GetImplicitConverter(Type fromType, Type toType) {
421             return GetConverter(fromType, fromType, toType, "op_Implicit") ?? GetConverter(toType, fromType, toType, "op_Implicit");
422         }
423
424         public static MethodInfo GetExplicitConverter(Type fromType, Type toType) {
425             return GetConverter(fromType, fromType, toType, "op_Explicit") ?? GetConverter(toType, fromType, toType, "op_Explicit");
426         }
427
428         private static MethodInfo GetConverter(Type type, Type fromType, Type toType, string opMethodName) {
429             foreach (MethodInfo mi in type.GetInheritedMembers(opMethodName).WithBindingFlags(BindingFlags.Public | BindingFlags.Static)) {
430                 if ((mi.DeclaringType == null || mi.DeclaringType.IsVisible()) && mi.IsPublic &&
431                     mi.ReturnType == toType && mi.GetParameters()[0].ParameterType.IsAssignableFrom(fromType)) {
432                     return mi;
433                 }
434             }
435             return null;
436         }
437
438         public static bool TryImplicitConversion(Object value, Type to, out object result) {
439             if (CompilerHelpers.TryImplicitConvert(value, to, to.GetInheritedMethods("op_Implicit").WithBindingFlags(BindingFlags.Public | BindingFlags.Static), out result)) {
440                 return true;
441             }
442
443             Type curType = CompilerHelpers.GetType(value);
444             do {
445                 if (CompilerHelpers.TryImplicitConvert(value, to, curType.GetInheritedMethods("op_Implicit").WithBindingFlags(BindingFlags.Public | BindingFlags.Static), out result)) {
446                     return true;
447                 }
448                 curType = curType.GetBaseType();
449             } while (curType != null);
450
451             return false;
452         }
453
454         private static bool TryImplicitConvert(Object value, Type to, IEnumerable<MethodInfo> implicitConv, out object result) {
455             foreach (MethodInfo mi in implicitConv) {
456                 if (to.IsValueType() == mi.ReturnType.IsValueType() && to.IsAssignableFrom(mi.ReturnType)) {
457                     if (mi.IsStatic) {
458                         result = mi.Invoke(null, new object[] { value });
459                     } else {
460                         result = mi.Invoke(value, ArrayUtils.EmptyObjects);
461                     }
462                     return true;
463                 }
464             }
465
466             result = null;
467             return false;
468         }
469
470         public static bool IsStrongBox(object target) {
471             Type t = CompilerHelpers.GetType(target);
472
473             return IsStrongBox(t);
474         }
475
476         public static bool IsStrongBox(Type t) {
477             return t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(StrongBox<>);
478         }
479
480         /// <summary>
481         /// Returns a value which indicates failure when a OldConvertToAction of ImplicitTry or
482         /// ExplicitTry.
483         /// </summary>
484         public static Expression GetTryConvertReturnValue(Type type) {
485             Expression res;
486             var info = type.GetTypeInfo();
487             if (info.IsInterface || info.IsClass || (info.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))) {
488                 res = AstUtils.Constant(null, type);
489             } else {
490                 res = AstUtils.Constant(Activator.CreateInstance(type));
491             }
492
493             return res;
494         }
495
496         public static bool HasTypeConverter(Type fromType, Type toType) {
497 #if FEATURE_TYPECONVERTER
498              TypeConverter _;
499             return TryGetTypeConverter(fromType, toType, out _);
500 #else
501             return false;
502 #endif
503         }
504
505         public static bool TryApplyTypeConverter(object value, Type toType, out object result) {
506 #if FEATURE_TYPECONVERTER
507             TypeConverter converter;
508             if (value != null && CompilerHelpers.TryGetTypeConverter(value.GetType(), toType, out converter)) {
509                 result = converter.ConvertFrom(value);
510                 return true;
511             } else {
512                 result = value;
513                 return false;
514             }
515 #else
516             result = value;
517             return false;
518 #endif
519         }
520
521 #if FEATURE_TYPECONVERTER
522         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
523         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
524         public static bool TryGetTypeConverter(Type fromType, Type toType, out TypeConverter converter) {
525             ContractUtils.RequiresNotNull(fromType, "fromType");
526             ContractUtils.RequiresNotNull(toType, "toType");
527
528             // try available type conversions...
529             foreach (TypeConverterAttribute tca in toType.GetCustomAttributes(typeof(TypeConverterAttribute), true)) {
530                 try {
531                     converter = Activator.CreateInstance(Type.GetType(tca.ConverterTypeName)) as TypeConverter;
532                 } catch (Exception) {
533                     converter = null;
534                 }
535
536                 if (converter != null && converter.CanConvertFrom(fromType)) {
537                     return true;
538                 }
539             }
540
541             converter = null;
542             return false;
543         }
544 #endif
545
546         #endregion
547
548 #if !MONO_INTERPRETER
549         public static MethodBase[] GetMethodTargets(object obj) {
550             Type t = CompilerHelpers.GetType(obj);
551
552             if (typeof(Delegate).IsAssignableFrom(t)) {
553                 MethodInfo mi = t.GetMethod("Invoke");
554                 return new MethodBase[] { mi };
555             } else if (typeof(BoundMemberTracker).IsAssignableFrom(t)) {
556                 BoundMemberTracker bmt = obj as BoundMemberTracker;
557                 if (bmt.BoundTo.MemberType == TrackerTypes.Method) {
558                 }
559             } else if (typeof(MethodGroup).IsAssignableFrom(t)) {
560             } else if (typeof(MemberGroup).IsAssignableFrom(t)) {
561             } else {
562                 return MakeCallSignatureForCallableObject(t);
563             }
564
565             return null;
566         }
567 #endif
568
569         private static MethodBase[] MakeCallSignatureForCallableObject(Type t) {
570             List<MethodBase> res = new List<MethodBase>();
571             foreach (MethodInfo method in t.GetInheritedMethods("Call")) {
572                 if (method.IsSpecialName) {
573                     res.Add(method);
574                 }
575             }
576             return res.ToArray();
577         }
578
579         public static Type[] GetSiteTypes(IList<Expression> arguments, Type returnType) {
580             int count = arguments.Count;
581
582             Type[] ret = new Type[count + 1];
583
584             for (int i = 0; i < count; i++) {
585                 ret[i] = arguments[i].Type;
586             }
587
588             ret[count] = returnType;
589             return ret;
590         }
591
592         public static Type[] GetExpressionTypes(Expression[] expressions) {
593             ContractUtils.RequiresNotNull(expressions, "expressions");
594
595             Type[] res = new Type[expressions.Length];
596             for (int i = 0; i < res.Length; i++) {
597                 ContractUtils.RequiresNotNull(expressions[i], "expressions[i]");
598
599                 res[i] = expressions[i].Type;
600             }
601
602             return res;
603         }
604
605         public static Type MakeCallSiteType(params Type[] types) {
606             return typeof(CallSite<>).MakeGenericType(DelegateHelpers.MakeDelegate(types));
607         }
608
609         public static Type MakeCallSiteDelegateType(Type[] types) {
610             return DelegateHelpers.MakeDelegate(types);
611         }
612
613         /// <summary>
614         /// Creates an interpreted delegate for the lambda.
615         /// </summary>
616         /// <param name="lambda">The lambda to compile.</param>
617         /// <returns>A delegate which can interpret the lambda.</returns>
618         public static Delegate LightCompile(this LambdaExpression lambda) {
619             return new LightCompiler(-1).CompileTop(lambda).CreateDelegate();
620         }
621
622         /// <summary>
623         /// Creates an interpreted delegate for the lambda.
624         /// </summary>
625         /// <param name="lambda">The lambda to compile.</param>
626         /// <param name="compilationThreshold">The number of iterations before the interpreter starts compiling</param>
627         /// <returns>A delegate which can interpret the lambda.</returns>
628         public static Delegate LightCompile(this LambdaExpression lambda, int compilationThreshold) {
629             return new LightCompiler(compilationThreshold).CompileTop(lambda).CreateDelegate();
630         }
631
632         /// <summary>
633         /// Creates an interpreted delegate for the lambda.
634         /// </summary>
635         /// <typeparam name="T">The lambda's delegate type.</typeparam>
636         /// <param name="lambda">The lambda to compile.</param>
637         /// <returns>A delegate which can interpret the lambda.</returns>
638         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
639         public static T LightCompile<T>(this Expression<T> lambda) {
640             return (T)(object)LightCompile((LambdaExpression)lambda);
641         }
642
643         /// <summary>
644         /// Creates an interpreted delegate for the lambda.
645         /// </summary>
646         /// <param name="lambda">The lambda to compile.</param>
647         /// <param name="compilationThreshold">The number of iterations before the interpreter starts compiling</param>
648         /// <returns>A delegate which can interpret the lambda.</returns>
649         public static T LightCompile<T>(this Expression<T> lambda, int compilationThreshold) {
650             return (T)(object)LightCompile((LambdaExpression)lambda, compilationThreshold);
651         }
652
653 #if FEATURE_REFEMIT
654         /// <summary>
655         /// Compiles the lambda into a method definition.
656         /// </summary>
657         /// <param name="lambda">the lambda to compile</param>
658         /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
659         /// <param name="emitDebugSymbols">A parameter that indicates if debugging information should be emitted to a PDB symbol store.</param>
660         public static void CompileToMethod(this LambdaExpression lambda, MethodBuilder method, bool emitDebugSymbols) {
661 #if FEATURE_PDBEMIT
662             if (emitDebugSymbols) {
663                 var module = method.Module as ModuleBuilder;
664                 ContractUtils.Requires(module != null, "method", "MethodBuilder does not have a valid ModuleBuilder");
665                 lambda.CompileToMethod(method, DebugInfoGenerator.CreatePdbGenerator());
666                 return;
667             }
668 #endif
669
670 #if WIN8 // TODO
671             ((dynamic)lambda).CompileToMethod(method);
672 #else
673             lambda.CompileToMethod(method);
674 #endif
675         }
676 #endif
677
678         /// <summary>
679         /// Compiles the LambdaExpression.
680         /// 
681         /// If the lambda is compiled with emitDebugSymbols, it will be
682         /// generated into a TypeBuilder. Otherwise, this method is the same as
683         /// calling LambdaExpression.Compile()
684         /// 
685         /// This is a workaround for a CLR limitiation: DynamicMethods cannot
686         /// have debugging information.
687         /// </summary>
688         /// <param name="lambda">the lambda to compile</param>
689         /// <param name="emitDebugSymbols">true to generate a debuggable method, false otherwise</param>
690         /// <returns>the compiled delegate</returns>
691         public static T Compile<T>(this Expression<T> lambda, bool emitDebugSymbols) {
692 #if FEATURE_PDBEMIT && FEATURE_REFEMIT
693             if (emitDebugSymbols) {
694                 return CompileToMethod(lambda, DebugInfoGenerator.CreatePdbGenerator(), true);
695             }
696 #endif
697             return lambda.Compile();
698         }
699
700 #if FEATURE_REFEMIT
701         /// <summary>
702         /// Compiles the LambdaExpression, emitting it into a new type, and
703         /// optionally making it debuggable.
704         /// 
705         /// This is a workaround for a CLR limitiation: DynamicMethods cannot
706         /// have debugging information.
707         /// </summary>
708         /// <param name="lambda">the lambda to compile</param>
709         /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
710         /// <param name="emitDebugSymbols">True if debug symbols (PDBs) are emitted by the <paramref name="debugInfoGenerator"/>.</param>
711         /// <returns>the compiled delegate</returns>
712         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
713         public static T CompileToMethod<T>(Expression<T> lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
714             return (T)(object)CompileToMethod((LambdaExpression)lambda, debugInfoGenerator, emitDebugSymbols);
715         }
716
717         public static Delegate CompileToMethod(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
718             string methodName = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
719
720             var type = Snippets.Shared.DefineType(methodName, typeof(object), false, emitDebugSymbols).TypeBuilder;
721             var rewriter = new DebuggableCodeRewriter(type);
722             lambda = (LambdaExpression)rewriter.Visit(lambda);
723
724             //Create a unique method name when the lambda doesn't have a name or the name is empty.
725             var method = type.DefineMethod(methodName, CompilerHelpers.PublicStatic);
726
727             lambda.CompileToMethod(method, debugInfoGenerator);
728             var finished = type.CreateType();
729
730             rewriter.InitializeFields(finished);
731             
732             return finished.GetMethod(method.Name).CreateDelegate(lambda.Type);
733         }
734
735         /// <summary>
736         /// Removes all live objects and places them in static fields of a type.
737         /// </summary>
738         private sealed class DebuggableCodeRewriter : DynamicExpressionVisitor {
739             private readonly Dictionary<object, FieldBuilder> _fields = new Dictionary<object, FieldBuilder>(ReferenceEqualityComparer<object>.Instance);
740             private readonly TypeBuilder _type;
741             private readonly HashSet<string> _methodNames = new HashSet<string>();
742
743             internal DebuggableCodeRewriter(TypeBuilder type) {
744                 _type = type;
745             }
746
747             internal void InitializeFields(Type type) {
748                 foreach (var pair in _fields) {
749                     type.GetInheritedFields(pair.Value.Name).First().SetValue(null, pair.Key);
750                 }
751             }
752
753             protected override Expression VisitLambda<T>(Expression<T> node) {
754                 if (_methodNames.Contains(node.Name)) {
755                     int count = _methodNames.Count;
756
757                     string newName;
758                     do {
759                         newName = node.Name + "$" + count++;
760                     } while (_methodNames.Contains(newName));
761
762                     _methodNames.Add(newName);
763                     return Expression.Lambda<T>(
764                         base.Visit(node.Body),
765                         newName,
766                         node.TailCall,
767                         node.Parameters
768                     );
769                 } else {
770                     _methodNames.Add(node.Name);
771                     return base.VisitLambda<T>(node);
772                 }
773             }
774
775             protected override Expression VisitExtension(Expression node) {
776                 // LightDynamicExpressions override Visit but we want to really reduce them
777                 // because they reduce to DynamicExpressions.
778                 LightDynamicExpression lightDyn = node as LightDynamicExpression;
779                 if (lightDyn != null) {
780                     return Visit(lightDyn.Reduce());
781                 }
782
783                 return Visit(node.Reduce());
784             }
785
786             protected override Expression VisitConstant(ConstantExpression node) {
787                 if (CanEmitConstant(node.Value, node.Type)) {
788                     return node;
789                 }
790
791                 FieldBuilder field;
792                 if (!_fields.TryGetValue(node.Value, out field)) {
793                     field = _type.DefineField(
794                         "$constant" + _fields.Count,
795                         GetVisibleType(node.Value.GetType()),
796                         FieldAttributes.Public | FieldAttributes.Static
797                     );
798                     _fields.Add(node.Value, field);
799                 }
800
801                 Expression result = Expression.Field(null, field);
802                 if (result.Type != node.Type) {
803                     result = Expression.Convert(result, node.Type);
804                 }
805                 return result;
806             }
807
808             protected override Expression VisitDynamic(DynamicExpression node) {
809                 return Visit(Reduce(node));
810             }
811         }
812 #endif
813
814         public static string GetUniqueMethodName() {
815             return "lambda_method" + "$" + System.Threading.Interlocked.Increment(ref _Counter);
816         }
817
818 #if FEATURE_LCG
819         // Matches ILGen.TryEmitConstant
820         public static bool CanEmitConstant(object value, Type type) {
821             if (value == null || CanEmitILConstant(type)) {
822                 return true;
823             }
824
825             Type t = value as Type;
826             if (t != null && ILGen.ShouldLdtoken(t)) {
827                 return true;
828             }
829
830             MethodBase mb = value as MethodBase;
831             if (mb != null && ILGen.ShouldLdtoken(mb)) {
832                 return true;
833             }
834
835             return false;
836         }
837
838         // Matches ILGen.TryEmitILConstant
839         internal static bool CanEmitILConstant(Type type) {
840             switch (type.GetTypeCode()) {
841                 case TypeCode.Boolean:
842                 case TypeCode.SByte:
843                 case TypeCode.Int16:
844                 case TypeCode.Int32:
845                 case TypeCode.Int64:
846                 case TypeCode.Single:
847                 case TypeCode.Double:
848                 case TypeCode.Char:
849                 case TypeCode.Byte:
850                 case TypeCode.UInt16:
851                 case TypeCode.UInt32:
852                 case TypeCode.UInt64:
853                 case TypeCode.Decimal:
854                 case TypeCode.String:
855                     return true;
856             }
857             return false;
858         }
859 #endif
860
861         /// <summary>
862         /// Reduces the provided DynamicExpression into site.Target(site, *args).
863         /// </summary>
864         public static Expression Reduce(DynamicExpression node) {
865             // Store the callsite as a constant
866             var siteConstant = AstUtils.Constant(CallSite.Create(node.DelegateType, node.Binder));
867
868             // ($site = siteExpr).Target.Invoke($site, *args)
869             var site = Expression.Variable(siteConstant.Type, "$site");
870             return Expression.Block(
871                 new[] { site },
872                 Expression.Call(
873                     Expression.Field(
874                         Expression.Assign(site, siteConstant),
875                         siteConstant.Type.GetDeclaredField("Target")
876                     ),
877                     node.DelegateType.GetMethod("Invoke"),
878                     ArrayUtils.Insert(site, node.Arguments)
879                 )
880             );
881         }
882 #if !MONO_INTERPRETER
883         #region Factories
884 #if !FEATURE_NUMERICS
885         [CLSCompliant(false)]
886         public static BigInteger CreateBigInteger(int sign, uint[] data) {
887             return new BigInteger(sign, data);
888         }
889 #else
890         public static BigInteger CreateBigInteger(bool isNegative, byte[] data) {
891             return new BigInteger(CreateBigInt(isNegative, data));
892         }
893
894         public static BigInt CreateBigInt(int value) {
895             return (BigInt)value;
896         }
897
898         public static BigInt CreateBigInt(long value) {
899             return (BigInt)value;
900         }
901
902         public static BigInt CreateBigInt(bool isNegative, byte[] data) {
903             BigInt res = new BigInt(data);
904             return isNegative ? -res : res;
905         }
906
907 #endif
908         #endregion
909 #endif
910     }
911 }