public void Create(Type type) { if (!type.IsArray) { var constructor = type.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new InvalidOperationException("Missing parameterless constructor for type '" + type + "'"); } Il.Newobj(constructor); } else { var rank = type.GetArrayRank(); if (rank == 1) { Il.Ldc_I4(0); Il.Newarr(type.GetElementType()); } else { var constructor = type.GetConstructor(Enumerable.Repeat(typeof(int), rank).ToArray()); if (constructor == null) { throw new InvalidOperationException(string.Format("Missing constructor accepting {0} integers for type '{1}'", rank, type)); } for (int i = 0; i < rank; ++i) { Il.Ldc_I4(0); } Il.Newobj(constructor); } } }
/// <summary> /// Asserts that the specified number of bytes can be read from <c>data</c> starting at <c>index</c> /// <para></para> /// The number of bytes must be pushed onto the evaluation stack /// </summary> public void AssertLength() { LoadIndex(); // stack: [length, index] Il.Add(); // stack: [length + index] LoadDataLength(); // stack: [length + index, dataLength] var bigEnoughLabel = Il.DefineLabel("bigEnough"); Il.Ble(bigEnoughLabel, true); Il.Ldstr("Unexpected end of data"); var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }); if (constructor == null) { throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string)); } Il.Newobj(constructor); Il.Throw(); Il.MarkLabel(bigEnoughLabel); }
/// <summary> /// Asserts that the specified number of bytes can be written to <c>result</c> starting at <c>index</c> /// <para></para> /// The number of bytes must be pushed onto the evaluation stack /// </summary> public void AssertLength() { LoadIndex(); // stack: [length, index] Il.Add(); // stack: [length + index] LoadResultLength(); // stack: [length + index, resultLength] var bigEnoughLabel = Il.DefineLabel("bigEnough"); Il.Ble(bigEnoughLabel, true); Il.Ldstr("Seems like the object being serialized has been changed during serialization"); var constructor = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }); if (constructor == null) { throw new MissingConstructorException(typeof(InvalidOperationException), typeof(string)); } Il.Newobj(constructor); Il.Throw(); Il.MarkLabel(bigEnoughLabel); }
/// <summary> /// Checks TypeCode and throws Exception if it is invalid /// </summary> public void CheckTypeCode() { LoadField(Context.Lengths); Il.Ldloc(TypeCode); // stack: [lengths, typeCode] Il.Ldelem(typeof(int)); // stack: [lengths[typeCode]] var okLabel = Il.DefineLabel("ok"); Il.Brtrue(okLabel); // if(lengths[typeCode] != 0) goto ok; Il.Ldstr("Unknown type code: "); Il.Ldloca(TypeCode); Il.Call(HackHelpers.GetMethodDefinition <int>(x => x.ToString()), typeof(int)); Il.Call(HackHelpers.GetMethodDefinition <string>(s => s + "zzz")); var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }); if (constructor == null) { throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string)); } Il.Newobj(constructor); Il.Throw(); Il.MarkLabel(okLabel); }
public void EmitConvert(Type from, Type to, bool check = false) { if (from == to) { return; } if (!from.IsValueType) { if (!to.IsValueType) { Il.Castclass(to); } else { if (from != typeof(object) && !(from == typeof(Enum) && to.IsEnum)) { throw new InvalidCastException("Cannot cast an object of type '" + from + "' to type '" + to + "'"); } Il.Unbox_Any(to); } } else { if (!to.IsValueType) { if (to != typeof(object) && !(to == typeof(Enum) && from.IsEnum)) { throw new InvalidCastException("Cannot cast an object of type '" + from + "' to type '" + to + "'"); } Il.Box(from); } else { if (to.IsNullable()) { var toArgument = to.GetGenericArguments()[0]; if (from.IsNullable()) { var fromArgument = from.GetGenericArguments()[0]; using (var temp = DeclareLocal(from)) { Il.Stloc(temp); Il.Ldloca(temp); EmitHasValueAccess(from); var valueIsNullLabel = Il.DefineLabel("valueIsNull"); Il.Brfalse(valueIsNullLabel); Il.Ldloca(temp); EmitValueAccess(from); if (toArgument != fromArgument) { EmitConvert(fromArgument, toArgument, check); } Il.Newobj(to.GetConstructor(new[] { toArgument })); var doneLabel = Il.DefineLabel("done"); Il.Br(doneLabel); MarkLabelAndSurroundWithSP(valueIsNullLabel); EmitLoadDefaultValue(to); MarkLabelAndSurroundWithSP(doneLabel); } } else { if (toArgument != from) { EmitConvert(from, toArgument, check); } Il.Newobj(to.GetConstructor(new[] { toArgument })); } } else if (from.IsNullable()) { var fromArgument = from.GetGenericArguments()[0]; using (var temp = DeclareLocal(from)) { Il.Stloc(temp); Il.Ldloca(temp); var valueIsNullLabel = Il.DefineLabel("valueIsNull"); Il.Brfalse(valueIsNullLabel); Il.Ldloca(temp); EmitValueAccess(from); if (to != fromArgument) { EmitConvert(fromArgument, to, check); } var doneLabel = Il.DefineLabel("done"); Il.Br(doneLabel); MarkLabelAndSurroundWithSP(valueIsNullLabel); EmitLoadDefaultValue(to); MarkLabelAndSurroundWithSP(doneLabel); } } else if (to.IsEnum || to == typeof(Enum)) { EmitConvert(from, typeof(int), check); } else if (from.IsEnum || from == typeof(Enum)) { EmitConvert(typeof(int), to, check); } else { if (!check) { EmitConvertValue(Il, from, to); } else { EmitConvertValueChecked(Il, from, to); } } } } }
public void EmitArithmeticOperation(ExpressionType nodeType, Type resultType, Type leftType, Type rightType, MethodInfo method) { if (!leftType.IsNullable() && !rightType.IsNullable()) { if (method != null) { Il.Call(method); } else { if (leftType.IsStruct()) { throw new InvalidOperationException("Unable to perfrom operation '" + nodeType + "' to a struct of type '" + leftType + "'"); } if (rightType.IsStruct()) { throw new InvalidOperationException("Unable to perfrom operation '" + nodeType + "' to a struct of type '" + rightType + "'"); } EmitOp(Il, nodeType, resultType); } } else { using (var localLeft = DeclareLocal(leftType)) using (var localRight = DeclareLocal(rightType)) { Il.Stloc(localRight); Il.Stloc(localLeft); var returnNullLabel = Il.DefineLabel("returnNull"); if (leftType.IsNullable()) { Il.Ldloca(localLeft); EmitHasValueAccess(leftType); Il.Brfalse(returnNullLabel); } if (rightType.IsNullable()) { Il.Ldloca(localRight); EmitHasValueAccess(rightType); Il.Brfalse(returnNullLabel); } if (!leftType.IsNullable()) { Il.Ldloc(localLeft); } else { Il.Ldloca(localLeft); EmitValueAccess(leftType); } if (!rightType.IsNullable()) { Il.Ldloc(localRight); } else { Il.Ldloca(localRight); EmitValueAccess(rightType); } Type argumentType = resultType.GetGenericArguments()[0]; if (method != null) { Il.Call(method); } else { EmitOp(Il, nodeType, argumentType); } Il.Newobj(resultType.GetConstructor(new[] { argumentType })); var doneLabel = Il.DefineLabel("done"); Il.Br(doneLabel); MarkLabelAndSurroundWithSP(returnNullLabel); EmitLoadDefaultValue(resultType); MarkLabelAndSurroundWithSP(doneLabel); } } }