internal LocalBuilder GetLocal(Type type) { Debug.Assert(type != null); LocalBuilder local; if (_freeLocals.TryDequeue(type, out local)) { Debug.Assert(type == local.LocalType); return(local); } return(_ilg.DeclareLocal(type)); }
private void EnsureLabelAndValue() { if (!_labelDefined) { _labelDefined = true; _label = _ilg.DefineLabel(); if (_node != null && _node.Type != typeof(void)) { _value = _ilg.DeclareLocal(_node.Type); } } }
private static void EmitNullableToNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { Debug.Assert(TypeUtils.IsNullableType(typeFrom)); Debug.Assert(TypeUtils.IsNullableType(typeTo)); Label labIfNull = default(Label); Label labEnd = default(Label); LocalBuilder locFrom = null; LocalBuilder locTo = null; locFrom = il.DeclareLocal(typeFrom); il.Emit(OpCodes.Stloc, locFrom); locTo = il.DeclareLocal(typeTo); // test for null il.Emit(OpCodes.Ldloca, locFrom); il.EmitHasValue(typeFrom); labIfNull = il.DefineLabel(); il.Emit(OpCodes.Brfalse_S, labIfNull); il.Emit(OpCodes.Ldloca, locFrom); il.EmitGetValueOrDefault(typeFrom); Type nnTypeFrom = TypeUtils.GetNonNullableType(typeFrom); Type nnTypeTo = TypeUtils.GetNonNullableType(typeTo); il.EmitConvertToType(nnTypeFrom, nnTypeTo, isChecked); // construct result type ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo }); il.Emit(OpCodes.Newobj, ci); il.Emit(OpCodes.Stloc, locTo); labEnd = il.DefineLabel(); il.Emit(OpCodes.Br_S, labEnd); // if null then create a default one il.MarkLabel(labIfNull); il.Emit(OpCodes.Ldloca, locTo); il.Emit(OpCodes.Initobj, typeTo); il.MarkLabel(labEnd); il.Emit(OpCodes.Ldloc, locTo); }
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); }
/// <summary> /// Emits default(T) /// Semantics match C# compiler behavior /// </summary> internal static void EmitDefault(this ILGenerator il, Type type) { switch (Type.GetTypeCode(type)) { case TypeCode.Object: case TypeCode.DateTime: if (type.IsValueType) { // Type.GetTypeCode on an enum returns the underlying // integer TypeCode, so we won't get here. Debug.Assert(!type.IsEnum); // This is the IL for default(T) if T is a generic type // parameter, so it should work for any type. It's also // the standard pattern for structs. LocalBuilder lb = il.DeclareLocal(type); il.Emit(OpCodes.Ldloca, lb); il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Ldloc, lb); } else { il.Emit(OpCodes.Ldnull); } break; case TypeCode.Empty: case TypeCode.String: case TypeCode.DBNull: il.Emit(OpCodes.Ldnull); break; case TypeCode.Boolean: case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: il.Emit(OpCodes.Ldc_I4_0); break; case TypeCode.Int64: case TypeCode.UInt64: il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Conv_I8); break; case TypeCode.Single: il.Emit(OpCodes.Ldc_R4, default(Single)); break; case TypeCode.Double: il.Emit(OpCodes.Ldc_R8, default(Double)); break; case TypeCode.Decimal: il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Newobj, typeof(Decimal).GetConstructor(new Type[] { typeof(int) })); break; default: throw ContractUtils.Unreachable; } }