private static void EmitNullableToReferenceConversion(this ILGenerator il, Type typeFrom) { Debug.Assert(TypeUtils.IsNullableType(typeFrom)); // We've got a conversion from nullable to Object, ValueType, Enum, etc. Just box it so that // we get the nullable semantics. il.Emit(OpCodes.Box, typeFrom); }
internal static void EmitGetValueOrDefault(this ILGenerator il, Type nullableType) { MethodInfo mi = nullableType.GetMethod("GetValueOrDefault", System.Type.EmptyTypes); Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); }
internal static void EmitGetValue(this ILGenerator il, Type nullableType) { MethodInfo mi = nullableType.GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public); Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); }
internal static void EmitLoadArg(this ILGenerator il, int index) { Debug.Assert(index >= 0); switch (index) { case 0: il.Emit(OpCodes.Ldarg_0); break; case 1: il.Emit(OpCodes.Ldarg_1); break; case 2: il.Emit(OpCodes.Ldarg_2); break; case 3: il.Emit(OpCodes.Ldarg_3); break; default: if (index <= Byte.MaxValue) { il.Emit(OpCodes.Ldarg_S, (byte)index); } else { il.Emit(OpCodes.Ldarg, index); } break; } }
/// <summary> /// Creates a lambda compiler that will compile to a dynamic method /// </summary> private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda) { Type[] parameterTypes = GetParameterTypes(lambda).AddFirst(typeof(Closure)); #if SILVERLIGHT && MICROSOFT_SCRIPTING_CORE var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes); #else var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes, true); #endif _tree = tree; _lambda = lambda; _method = method; #if MICROSOFT_SCRIPTING_CORE || SILVERLIGHT _ilg = new OffsetTrackingILGenerator(method.GetILGenerator()); #else _ilg = method.GetILGenerator(); #endif _hasClosureArgument = true; // These are populated by AnalyzeTree/VariableBinder _scope = tree.Scopes[lambda]; _boundConstants = tree.Constants[lambda]; InitializeMethod(); }
internal static void EmitDecimal(this ILGenerator il, decimal value) { if (Decimal.Truncate(value) == value) { if (Int32.MinValue <= value && value <= Int32.MaxValue) { int intValue = Decimal.ToInt32(value); il.EmitInt(intValue); il.EmitNew(typeof(Decimal).GetConstructor(new Type[] { typeof(int) })); } else if (Int64.MinValue <= value && value <= Int64.MaxValue) { long longValue = Decimal.ToInt64(value); il.EmitLong(longValue); il.EmitNew(typeof(Decimal).GetConstructor(new Type[] { typeof(long) })); } else { il.EmitDecimalBits(value); } } else { il.EmitDecimalBits(value); } }
internal static void EmitType(this ILGenerator il, Type type) { ContractUtils.RequiresNotNull(type, "type"); il.Emit(OpCodes.Ldtoken, type); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); }
internal static void EmitInt(this ILGenerator il, int value) { OpCode c; switch (value) { case -1: c = OpCodes.Ldc_I4_M1; break; case 0: c = OpCodes.Ldc_I4_0; break; case 1: c = OpCodes.Ldc_I4_1; break; case 2: c = OpCodes.Ldc_I4_2; break; case 3: c = OpCodes.Ldc_I4_3; break; case 4: c = OpCodes.Ldc_I4_4; break; case 5: c = OpCodes.Ldc_I4_5; break; case 6: c = OpCodes.Ldc_I4_6; break; case 7: c = OpCodes.Ldc_I4_7; break; case 8: c = OpCodes.Ldc_I4_8; break; default: if (value >= -128 && value <= 127) { il.Emit(OpCodes.Ldc_I4_S, (sbyte)value); } else { il.Emit(OpCodes.Ldc_I4, value); } return; } il.Emit(c); }
private static void EmitDecimalBits(this ILGenerator il, decimal value) { int[] bits = Decimal.GetBits(value); il.EmitInt(bits[0]); il.EmitInt(bits[1]); il.EmitInt(bits[2]); il.EmitBoolean((bits[3] & 0x80000000) != 0); il.EmitByte((byte)(bits[3] >> 16)); il.EmitNew(typeof(decimal).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte) })); }
internal static void EmitNew(this ILGenerator il, Type type, Type[] paramTypes) { ContractUtils.RequiresNotNull(type, "type"); ContractUtils.RequiresNotNull(paramTypes, "paramTypes"); ConstructorInfo ci = type.GetConstructor(paramTypes); ContractUtils.Requires(ci != null, "type", Strings.TypeDoesNotHaveConstructorForTheSignature); il.EmitNew(ci); }
/// <summary> /// Creates a lambda compiler for an inlined lambda /// </summary> private LambdaCompiler(LambdaCompiler parent, LambdaExpression lambda) { _tree = parent._tree; _lambda = lambda; _method = parent._method; _ilg = parent._ilg; _hasClosureArgument = parent._hasClosureArgument; _typeBuilder = parent._typeBuilder; _scope = _tree.Scopes[lambda]; _boundConstants = parent._boundConstants; }
// // Note: we support emitting more things as IL constants than // Linq does internal static void EmitConstant(this ILGenerator il, object value, Type type) { if (value == null) { // Smarter than the Linq implementation which uses the initobj // pattern for all value types (works, but requires a local and // more IL) il.EmitDefault(type); return; } // Handle the easy cases if (il.TryEmitILConstant(value, type)) { return; } // Check for a few more types that we support emitting as constants Type t = value as Type; if (t != null && ShouldLdtoken(t)) { il.EmitType(t); if (type != typeof(Type)) { il.Emit(OpCodes.Castclass, type); } return; } MethodBase mb = value as MethodBase; if (mb != null && ShouldLdtoken(mb)) { il.Emit(OpCodes.Ldtoken, mb); Type dt = mb.DeclaringType; if (dt != null && dt.IsGenericType) { il.Emit(OpCodes.Ldtoken, dt); il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) })); } else { il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle) })); } if (type != typeof(MethodBase)) { il.Emit(OpCodes.Castclass, type); } return; } throw ContractUtils.Unreachable; }
internal static void EmitBoolean(this ILGenerator il, bool value) { if (value) { il.Emit(OpCodes.Ldc_I4_1); } else { il.Emit(OpCodes.Ldc_I4_0); } }
internal static void EmitNew(this ILGenerator il, ConstructorInfo ci) { ContractUtils.RequiresNotNull(ci, "ci"); if (ci.DeclaringType.ContainsGenericParameters) { throw Error.IllegalNewGenericParams(ci.DeclaringType); } il.Emit(OpCodes.Newobj, ci); }
internal static void EmitLong(this ILGenerator il, long value) { il.Emit(OpCodes.Ldc_I8, value); // // Now, emit convert to give the constant type information. // // Otherwise, it is treated as unsigned and overflow is not // detected if it's used in checked ops. // il.Emit(OpCodes.Conv_I8); }
/// <summary> /// Emits a Stelem* instruction for the appropriate type. /// </summary> internal static void EmitStoreElement(this ILGenerator il, Type type) { ContractUtils.RequiresNotNull(type, "type"); if (type.IsEnum) { il.Emit(OpCodes.Stelem, type); return; } switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: case TypeCode.SByte: case TypeCode.Byte: il.Emit(OpCodes.Stelem_I1); break; case TypeCode.Char: case TypeCode.Int16: case TypeCode.UInt16: il.Emit(OpCodes.Stelem_I2); break; case TypeCode.Int32: case TypeCode.UInt32: il.Emit(OpCodes.Stelem_I4); break; case TypeCode.Int64: case TypeCode.UInt64: il.Emit(OpCodes.Stelem_I8); break; case TypeCode.Single: il.Emit(OpCodes.Stelem_R4); break; case TypeCode.Double: il.Emit(OpCodes.Stelem_R8); break; default: if (type.IsValueType) { il.Emit(OpCodes.Stelem, type); } else { il.Emit(OpCodes.Stelem_Ref); } break; } }
/// <summary> /// Emits a Ldind* instruction for the appropriate type /// </summary> internal static void EmitLoadValueIndirect(this ILGenerator il, Type type) { ContractUtils.RequiresNotNull(type, "type"); if (type.IsValueType) { if (type == typeof(int)) { il.Emit(OpCodes.Ldind_I4); } else if (type == typeof(uint)) { il.Emit(OpCodes.Ldind_U4); } else if (type == typeof(short)) { il.Emit(OpCodes.Ldind_I2); } else if (type == typeof(ushort)) { il.Emit(OpCodes.Ldind_U2); } else if (type == typeof(long) || type == typeof(ulong)) { il.Emit(OpCodes.Ldind_I8); } else if (type == typeof(char)) { il.Emit(OpCodes.Ldind_I2); } else if (type == typeof(bool)) { il.Emit(OpCodes.Ldind_I1); } else if (type == typeof(float)) { il.Emit(OpCodes.Ldind_R4); } else if (type == typeof(double)) { il.Emit(OpCodes.Ldind_R8); } else { il.Emit(OpCodes.Ldobj, type); } } else { il.Emit(OpCodes.Ldind_Ref); } }
internal static void Emit(this ILGenerator il, OpCode opcode, MethodBase methodBase) { Debug.Assert(methodBase is MethodInfo || methodBase is ConstructorInfo); if (methodBase.MemberType == MemberTypes.Constructor) { il.Emit(opcode, (ConstructorInfo)methodBase); } else { il.Emit(opcode, (MethodInfo)methodBase); } }
internal static void EmitStoreArg(this ILGenerator il, int index) { Debug.Assert(index >= 0); if (index <= Byte.MaxValue) { il.Emit(OpCodes.Starg_S, (byte)index); } else { il.Emit(OpCodes.Starg, index); } }
internal static void EmitFieldSet(this ILGenerator il, FieldInfo fi) { ContractUtils.RequiresNotNull(fi, "fi"); if (fi.IsStatic) { il.Emit(OpCodes.Stsfld, fi); } else { il.Emit(OpCodes.Stfld, fi); } }
private static void EmitNullableToNonNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(TypeUtils.IsNullableType(typeFrom)); Debug.Assert(!TypeUtils.IsNullableType(typeTo)); if (typeTo.IsValueType) { il.EmitNullableToNonNullableStructConversion(typeFrom, typeTo, isChecked); } else { il.EmitNullableToReferenceConversion(typeFrom); } }
internal static void EmitLoadArgAddress(this ILGenerator il, int index) { Debug.Assert(index >= 0); if (index <= Byte.MaxValue) { il.Emit(OpCodes.Ldarga_S, (byte)index); } else { il.Emit(OpCodes.Ldarga, index); } }
/// <summary> /// Emits an array of constant values provided in the given list. /// The array is strongly typed. /// </summary> internal static void EmitArray <T>(this ILGenerator il, IList <T> items) { ContractUtils.RequiresNotNull(items, "items"); il.EmitInt(items.Count); il.Emit(OpCodes.Newarr, typeof(T)); for (int i = 0; i < items.Count; i++) { il.Emit(OpCodes.Dup); il.EmitInt(i); il.EmitConstant(items[i], typeof(T)); il.EmitStoreElement(typeof(T)); } }
private static void EmitNullableToNonNullableStructConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(TypeUtils.IsNullableType(typeFrom)); Debug.Assert(!TypeUtils.IsNullableType(typeTo)); Debug.Assert(typeTo.IsValueType); LocalBuilder locFrom = null; locFrom = il.DeclareLocal(typeFrom); il.Emit(OpCodes.Stloc, locFrom); il.Emit(OpCodes.Ldloca, locFrom); il.EmitGetValue(typeFrom); Type nnTypeFrom = TypeUtils.GetNonNullableType(typeFrom); il.EmitConvertToType(nnTypeFrom, typeTo, isChecked); }
private static void EmitNonNullableToNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(!TypeUtils.IsNullableType(typeFrom)); Debug.Assert(TypeUtils.IsNullableType(typeTo)); LocalBuilder locTo = null; locTo = il.DeclareLocal(typeTo); Type nnTypeTo = TypeUtils.GetNonNullableType(typeTo); il.EmitConvertToType(typeFrom, nnTypeTo, isChecked); ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo }); il.Emit(OpCodes.Newobj, ci); il.Emit(OpCodes.Stloc, locTo); il.Emit(OpCodes.Ldloc, locTo); }
internal static void EmitConvertToType(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { if (TypeUtils.AreEquivalent(typeFrom, typeTo)) { return; } if (typeFrom == typeof(void) || typeTo == typeof(void)) { throw ContractUtils.Unreachable; } bool isTypeFromNullable = TypeUtils.IsNullableType(typeFrom); bool isTypeToNullable = TypeUtils.IsNullableType(typeTo); Type nnExprType = TypeUtils.GetNonNullableType(typeFrom); Type nnType = TypeUtils.GetNonNullableType(typeTo); if (typeFrom.IsInterface || // interface cast typeTo.IsInterface || typeFrom == typeof(object) || // boxing cast typeTo == typeof(object)) { il.EmitCastToType(typeFrom, typeTo); } else if (isTypeFromNullable || isTypeToNullable) { il.EmitNullableConversion(typeFrom, typeTo, isChecked); } else if (!(TypeUtils.IsConvertible(typeFrom) && TypeUtils.IsConvertible(typeTo)) // primitive runtime conversion && (nnExprType.IsAssignableFrom(nnType) || // down cast nnType.IsAssignableFrom(nnExprType))) // up cast { il.EmitCastToType(typeFrom, typeTo); } else if (typeFrom.IsArray && typeTo.IsArray) { // See DevDiv Bugs #94657. il.EmitCastToType(typeFrom, typeTo); } else { il.EmitNumericConversion(typeFrom, typeTo, isChecked); } }
/// <summary> /// Emits an array of values of count size. The items are emitted via the callback /// which is provided with the current item index to emit. /// </summary> internal static void EmitArray(this ILGenerator il, Type elementType, int count, Action <int> emit) { ContractUtils.RequiresNotNull(elementType, "elementType"); ContractUtils.RequiresNotNull(emit, "emit"); ContractUtils.Requires(count >= 0, "count", Strings.CountCannotBeNegative); il.EmitInt(count); il.Emit(OpCodes.Newarr, elementType); for (int i = 0; i < count; i++) { il.Emit(OpCodes.Dup); il.EmitInt(i); emit(i); il.EmitStoreElement(elementType); } }
private static void EmitNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { bool isTypeFromNullable = TypeUtils.IsNullableType(typeFrom); bool isTypeToNullable = TypeUtils.IsNullableType(typeTo); Debug.Assert(isTypeFromNullable || isTypeToNullable); if (isTypeFromNullable && isTypeToNullable) { il.EmitNullableToNullableConversion(typeFrom, typeTo, isChecked); } else if (isTypeFromNullable) { il.EmitNullableToNonNullableConversion(typeFrom, typeTo, isChecked); } else { il.EmitNonNullableToNullableConversion(typeFrom, typeTo, isChecked); } }
/// <summary> /// Emits an array construction code. /// The code assumes that bounds for all dimensions /// are already emitted. /// </summary> internal static void EmitArray(this ILGenerator il, Type arrayType) { ContractUtils.RequiresNotNull(arrayType, "arrayType"); ContractUtils.Requires(arrayType.IsArray, "arrayType", Strings.ArrayTypeMustBeArray); int rank = arrayType.GetArrayRank(); if (rank == 1) { il.Emit(OpCodes.Newarr, arrayType.GetElementType()); } else { Type[] types = new Type[rank]; for (int i = 0; i < rank; i++) { types[i] = typeof(int); } il.EmitNew(arrayType, types); } }
private static void EmitCastToType(this ILGenerator il, Type typeFrom, Type typeTo) { if (!typeFrom.IsValueType && typeTo.IsValueType) { il.Emit(OpCodes.Unbox_Any, typeTo); } else if (typeFrom.IsValueType && !typeTo.IsValueType) { il.Emit(OpCodes.Box, typeFrom); if (typeTo != typeof(object)) { il.Emit(OpCodes.Castclass, typeTo); } } else if (!typeFrom.IsValueType && !typeTo.IsValueType) { il.Emit(OpCodes.Castclass, typeTo); } else { throw Error.InvalidCast(typeFrom, typeTo); } }
internal virtual void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) { MarkSequencePoint(method, ilg.ILOffset, sequencePoint); }
internal LabelInfo(ILGenerator il, LabelTarget node, bool canReturn) { _ilg = il; _node = node; _canReturn = canReturn; }