protected override bool EmitInternal(TypeBinaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { bool result; GroboIL il = context.Il; if (!node.Expression.Type.IsAssignableFrom(node.TypeOperand)) { il.Ldc_I4(0); result = false; } else if (node.Expression.Type == node.TypeOperand && node.TypeOperand.IsValueType) { il.Ldc_I4(1); result = false; } else { Type operandType; result = ExpressionEmittersCollection.Emit(node.Expression, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType); if (operandType.IsValueType) { using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldloca(temp); } } var returnFalseLabel = il.DefineLabel("returnFalse"); il.Dup(); il.Brfalse(returnFalseLabel); il.Call(typeof(object).GetMethod("GetType"), operandType); il.Ldtoken(node.TypeOperand); il.Call(typeof(Type).GetMethod("GetTypeFromHandle")); il.Ceq(); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(returnFalseLabel); il.Pop(); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(doneLabel); } resultType = typeof(bool); return(result); }
public static void WriteObjectNull(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local typeSize) { var _null = il.DeclareLocal(typeof(bool)); il.Ldnull(); il.Ceq(); il.Stloc(_null); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(_null); il.Stelem(typeof(byte)); WriteOffsetAppend(il, offset, 1); il.Ldloc(_null); il.Brtrue(finishMethod); }
public static void WriteNullableType <T>(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset) where T : struct { var _null = il.DeclareLocal(typeof(bool)); il.Call(typeof(Nullable <T>).GetProperty("HasValue").GetGetMethod()); il.Ldc_I4(0); //il.Ldnull(); il.Ceq(); il.Stloc(_null); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(_null); il.Stelem(typeof(byte)); WriteOffsetAppend(il, offset, 1); il.Ldloc(_null); il.Brtrue(finishMethod); }
private KeyValuePair <Delegate, IntPtr> BuildPrimitiveValueReader(ModuleBuilder module, GroBufTypeCode typeCode) { var method = new DynamicMethod("Read_" + Type.Name + "_from_" + typeCode + "_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), Type.MakeByRefType() }, module, true); using (var il = new GroboIL(method)) { var expectedTypeCode = GroBufTypeCodeMap.GetTypeCode(Type); il.Ldarg(1); // stack: [ref result] if (typeCode == GroBufTypeCode.Decimal) { if (expectedTypeCode == GroBufTypeCode.Boolean) { il.Ldarg(0); // stack: [ref result, &temp, address] il.Ldind(typeof(long)); // stack: [ref result, &temp, (long)*address] il.Ldarg(0); // stack: [ref result, &temp + 8, address] il.Ldc_I4(8); // stack: [ref result, &temp + 8, address, 8] il.Add(); // stack: [ref result, &temp + 8, address + 8] il.Ldind(typeof(long)); // stack: [ref result, &temp + 8, (long)*(address + 8)] il.Or(); il.Ldc_I4(0); // stack: [ref result, value, 0] il.Conv <long>(); il.Ceq(); // stack: [ref result, value == 0] il.Ldc_I4(1); // stack: [ref result, value == 0, 1] il.Xor(); // stack: [ref result, value != 0] } else { var temp = il.DeclareLocal(typeof(decimal)); il.Ldloca(temp); // stack: [ref result, &temp] il.Ldarg(0); // stack: [ref result, &temp, address] il.Ldind(typeof(long)); // stack: [ref result, &temp, (long)*address] il.Stind(typeof(long)); // *temp = *address; il.Ldloca(temp); // stack: [ref result, &temp] il.Ldc_I4(8); // stack: [ref result, &temp, 8] il.Add(); // stack: [ref result, &temp + 8] il.Ldarg(0); // stack: [ref result, &temp + 8, address] il.Ldc_I4(8); // stack: [ref result, &temp + 8, address, 8] il.Add(); // stack: [ref result, &temp + 8, address + 8] il.Ldind(typeof(long)); // stack: [ref result, &temp + 8, (long)*(address + 8)] il.Stind(typeof(long)); // *(temp + 8) = *(address + 8); il.Ldloc(temp); // stack: [ref result, ref temp] switch (expectedTypeCode) { case GroBufTypeCode.Int8: il.Call(decimalToInt8Method); // stack: [ref result, (sbyte)temp] break; case GroBufTypeCode.UInt8: il.Call(decimalToUInt8Method); // stack: [ref result, (byte)temp] break; case GroBufTypeCode.Int16: il.Call(decimalToInt16Method); // stack: [ref result, (short)temp] break; case GroBufTypeCode.UInt16: il.Call(decimalToUInt16Method); // stack: [ref result, (ushort)temp] break; case GroBufTypeCode.Int32: il.Call(decimalToInt32Method); // stack: [ref result, (int)temp] break; case GroBufTypeCode.UInt32: il.Call(decimalToUInt32Method); // stack: [ref result, (uint)temp] break; case GroBufTypeCode.Int64: il.Call(decimalToInt64Method); // stack: [ref result, (long)temp] break; case GroBufTypeCode.UInt64: il.Call(decimalToUInt64Method); // stack: [ref result, (ulong)temp] break; case GroBufTypeCode.Single: il.Call(decimalToSingleMethod); // stack: [ref result, (float)temp] break; case GroBufTypeCode.Double: il.Call(decimalToDoubleMethod); // stack: [ref result, (double)temp] break; case GroBufTypeCode.Decimal: break; default: throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported"); } } } else { il.Ldarg(0); // stack: [ref result, address] EmitReadPrimitiveValue(il, Type == typeof(bool) ? GetTypeCodeForBool(typeCode) : typeCode); // stack: [ref result, value] if (Type == typeof(bool)) { il.Conv <long>(); il.Ldc_I4(0); // stack: [ref result, value, 0] il.Conv <long>(); il.Ceq(); // stack: [ref result, value == 0] il.Ldc_I4(1); // stack: [ref result, value == 0, 1] il.Xor(); // stack: [ref result, value != 0] } else { EmitConvertValue(il, typeCode, expectedTypeCode); } } switch (expectedTypeCode) { case GroBufTypeCode.Int8: case GroBufTypeCode.UInt8: case GroBufTypeCode.Boolean: il.Stind(typeof(byte)); // result = value break; case GroBufTypeCode.Int16: case GroBufTypeCode.UInt16: il.Stind(typeof(short)); // result = value break; case GroBufTypeCode.Int32: case GroBufTypeCode.UInt32: il.Stind(typeof(int)); // result = value break; case GroBufTypeCode.Int64: case GroBufTypeCode.UInt64: il.Stind(typeof(long)); // result = value break; case GroBufTypeCode.Single: il.Stind(typeof(float)); // result = value break; case GroBufTypeCode.Double: il.Stind(typeof(double)); // result = value break; case GroBufTypeCode.Decimal: il.Stobj(typeof(decimal)); // result = value break; default: throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported"); } il.Ret(); } var @delegate = method.CreateDelegate(typeof(PrimitiveValueReaderDelegate <>).MakeGenericType(Type)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
public void TestZzz() { var asm = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave); var mod = asm.DefineDynamicModule("mymod", "tmp.dll", true); var type = mod.DefineType("baz", TypeAttributes.Public | TypeAttributes.Class); var meth = type.DefineMethod("go", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(int) }); var document = mod.DefineDocument("TestDebug2.txt", Guid.Empty, Guid.Empty, Guid.Empty); //Expression.SymbolDocument("TestDebug2.txt"); meth.DefineParameter(1, ParameterAttributes.In, "$x"); //var di = Expression.DebugInfo(sdi, 2, 2, 2, 13); //var exp = Expression.Divide(Expression.Constant(2), Expression.Subtract(Expression.Constant(4), Expression.Constant(4))); //var block = Expression.Block(di, exp); using (var il = new GroboIL(meth)) { // var tst = Expression.Block(Expression.DebugInfo(sdi, 6, 20, 6, 27), Expression.Equal(variable, zero)); // var iftrue = Expression.Block(Expression.DebugInfo(sdi, 10, 20, 10, 26), Expression.Add(variable, two)); // var iffalse = Expression.Block(Expression.DebugInfo(sdi, 14, 20, 14, 26), Expression.Divide(variable, two)); // var exp = Expression.Condition(tst, iftrue, iffalse); // var block = Expression.Block(Expression.DebugInfo(sdi, 4, 16, 15, 10), exp); // nop // [] // nop // [] // ldarg.0 // [Int32] // ldc.i4.0 // [Int32, Int32] // ceq // [Int32] // brfalse ifFalse_5 // [] // nop // [] // ldarg.0 // [Int32] // ldc.i4.2 // [Int32, Int32] // add // [Int32] // br done_8 // [Int32] //ifFalse_5: // [] // nop // [] // ldarg.0 // [Int32] // ldc.i4.2 // [Int32, Int32] // div // [Int32] //done_8: // [Int32] // ret // [] il.MarkSequencePoint(document, 3, 9, 3, 15); il.Nop(); il.MarkSequencePoint(document, 4, 13, 4, 19); il.Nop(); il.Ldarg(0); il.Ldc_I4(0); il.Ceq(); var label = il.DefineLabel("ifFalse"); il.Brfalse(label); il.MarkSequencePoint(document, 7, 13, 7, 19); il.Nop(); il.Ldarg(0); il.Ldc_I4(2); il.Add(); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); il.MarkLabel(label); il.MarkSequencePoint(document, 10, 13, 10, 19); il.Nop(); il.Ldarg(0); il.Ldc_I4(2); il.Mul(); il.MarkLabel(doneLabel); il.MarkSequencePoint(document, 12, 5, 12, 6); il.Nop(); il.Ret(); } var newtype = type.CreateType(); asm.Save("tmp.dll"); newtype.GetMethod("go").Invoke(null, new object[] { 0 }); //meth.Invoke(null, new object[0]); //lambda.DynamicInvoke(new object[0]); Console.WriteLine(" "); }
public void GetReadILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local result, GroboIL.Local typeSize, GroboIL.Local offset, bool listValue) { var exitLabel = il.DefineLabel("exit"); BinaryStruct.ReadObjectNull(il, exitLabel, buffer, offset, typeSize); var len = il.DeclareLocal(typeof(int)); var list = il.DeclareLocal(prop.PropertyInfo.PropertyType); il.Ldloc(buffer); il.Ldloc(offset); il.Call(readBitConverterMethodInfo); il.Stloc(len); BinaryStruct.WriteOffsetAppend(il, offset, 4); il.Newobj(BinaryStruct.GetConstructor(prop.PropertyInfo.PropertyType, null)); il.Stloc(list); il.Ldloc(result); il.Ldloc(list); il.Call(prop.Setter, isVirtual: true); il.Ldloc(len); il.Ldc_I4(0); il.Ceq(); il.Brtrue(exitLabel); var typeKey = prop.PropertyInfo.PropertyType.GetGenericArguments()[0]; var typeValue = prop.PropertyInfo.PropertyType.GetGenericArguments()[1]; var ivar = il.DeclareLocal(typeof(int)); var currentItemKey = il.DeclareLocal(typeKey); var currentItemValue = il.DeclareLocal(typeValue); var point = il.DefineLabel("for_label"); il.Ldc_I4(0); il.Stloc(ivar); il.MarkLabel(point); //body //key if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[0])) { IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[0]); t.GetReadILCode(prop, currentStruct, il, binaryStruct, buffer, currentItemKey, typeSize, offset, true); } else { var constr = BinaryStruct.GetConstructor(typeKey, null); if (constr == null) { throw new Exception($"Type {typeKey} not have constructor with not parameters"); } il.Newobj(constr); il.Stloc(currentItemKey); BinaryStruct.CompileReader(currentStruct.CurrentStorage.GetTypeInfo(typeKey, currentStruct.Scheme), il, binaryStruct, buffer, offset, currentItemKey, typeSize); } //value if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[1])) { IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[1]); t.GetReadILCode(prop, currentStruct, il, binaryStruct, buffer, currentItemValue, typeSize, offset, true); } else { var constr = BinaryStruct.GetConstructor(typeValue, null); if (constr == null) { throw new Exception($"Type {typeValue} not have constructor with not parameters"); } il.Newobj(constr); il.Stloc(currentItemValue); BinaryStruct.CompileReader(currentStruct.CurrentStorage.GetTypeInfo(typeValue, currentStruct.Scheme), il, binaryStruct, buffer, offset, currentItemValue, typeSize); } il.Ldloc(list); il.Ldloc(currentItemKey); il.Ldloc(currentItemValue); il.Call(prop.PropertyInfo.PropertyType.GetMethod("Add"), isVirtual: true); //end body il.Ldc_I4(1); il.Ldloc(ivar); il.Add(); il.Stloc(ivar); il.Ldloc(ivar); il.Ldloc(len); il.Clt(false); il.Brtrue(point); il.MarkLabel(exitLabel); }
public void GetWriteILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local value, GroboIL.Local typeSize, GroboIL.Local buffer, GroboIL.Local offset, bool listValue) { var arr = il.DeclareLocal(prop.PropertyInfo.PropertyType); il.Ldloc(value); il.Call(prop.Getter); il.Stloc(arr); var exitLabel = il.DefineLabel("exit"); BinaryStruct.WriteSizeChecker(il, buffer, offset, 5); BinaryStruct.WriteObjectNull(il, exitLabel, arr, buffer, offset, typeSize); var arrSize = il.DeclareLocal(typeof(byte[])); var len = il.DeclareLocal(typeof(int)); il.Ldloc(value); il.Call(prop.Getter); il.Call(typeof(ICollection).GetProperty("Count").GetMethod); il.Stloc(len); il.Ldloc(len); il.Call(writeBitConverterMethodInfo); il.Stloc(arrSize); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(arrSize); il.Ldc_I4(0); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); for (int i = 1; i < 4; i++) { il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(i); il.Add(); il.Ldloc(arrSize); il.Ldc_I4(i); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); } BinaryStruct.WriteOffsetAppend(il, offset, 4); il.Ldloc(len); il.Ldc_I4(0); il.Ceq(); il.Brtrue(exitLabel); var typeKey = prop.PropertyInfo.PropertyType.GetGenericArguments()[0]; var typeValue = prop.PropertyInfo.PropertyType.GetGenericArguments()[1]; var ivar = il.DeclareLocal(typeof(int)); var currentItemKey = il.DeclareLocal(typeKey); var currentItemValue = il.DeclareLocal(typeValue); var point = il.DefineLabel("for_label"); il.Ldc_I4(0); il.Stloc(ivar); var enumeratorMethod = prop.PropertyInfo.PropertyType.GetMethod("GetEnumerator"); var enumerator = il.DeclareLocal(enumeratorMethod.ReturnType); var moveNext = enumerator.Type.GetMethod("MoveNext"); var getCurrent = enumerator.Type.GetMethod("get_Current"); var temp = il.DeclareLocal(getCurrent.ReturnType); var exist = il.DeclareLocal(typeof(bool)); il.Ldloc(arr); il.Call(enumeratorMethod, isVirtual: true); il.Stloc(enumerator); var keyGetter = getCurrent.ReturnType.GetMethod("get_Key"); var valueGetter = getCurrent.ReturnType.GetMethod("get_Value"); il.MarkLabel(point); //body il.Ldloca(enumerator); il.Call(moveNext, enumerator.Type); il.Stloc(exist); il.Ldloca(enumerator); //il.Calli(CallingConventions.Any, typeof(KeyValuePair<int, int>),new Type[] { typeof(int),typeof(int) }); il.Call(getCurrent, enumerator.Type); il.Stloc(temp); il.Ldloca(temp); il.Call(keyGetter, typeof(int)); il.Stloc(currentItemKey); if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[0])) { IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[0]); t.GetWriteILCode(prop, currentStruct, il, binaryStruct, currentItemKey, typeSize, buffer, offset, true); } else { BinaryStruct.CompileWriter(currentStruct.CurrentStorage.GetTypeInfo(typeKey, currentStruct.Scheme), il, binaryStruct, currentItemKey, buffer, offset, typeSize); } il.Ldloca(temp); il.Call(valueGetter); il.Stloc(currentItemValue); if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[1])) { IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[1]); t.GetWriteILCode(prop, currentStruct, il, binaryStruct, currentItemValue, typeSize, buffer, offset, true); } else { BinaryStruct.CompileWriter(currentStruct.CurrentStorage.GetTypeInfo(typeValue, currentStruct.Scheme), il, binaryStruct, currentItemValue, buffer, offset, typeSize); } //end body il.Ldc_I4(1); il.Ldloc(ivar); il.Add(); il.Stloc(ivar); il.Ldloc(ivar); il.Ldloc(len); il.Clt(false); il.Brtrue(point); il.MarkLabel(exitLabel); }
protected override bool EmitInternal(SwitchExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { GroboIL il = context.Il; var defaultLabel = il.DefineLabel("default"); var caseLabels = new GroboIL.Label[node.Cases.Count]; GroboIL.Label switchValueIsNullLabel = null; for (int index = 0; index < node.Cases.Count; index++) { caseLabels[index] = il.DefineLabel("case#" + index); } context.EmitLoadArguments(node.SwitchValue); using (var switchValue = context.DeclareLocal(node.SwitchValue.Type)) { il.Stloc(switchValue); Tuple <int, int, int> switchCase; if (context.ParsedLambda.ParsedSwitches.TryGetValue(node, out switchCase)) { // use simplified hashtable to locate the proper case var labels = new List <GroboIL.Label>(); for (int index = 0; index < node.Cases.Count; index++) { foreach (var testValue in node.Cases[index].TestValues) { if (((ConstantExpression)testValue).Value != null) { labels.Add(caseLabels[index]); } else { switchValueIsNullLabel = caseLabels[index]; } } } if (switchValueIsNullLabel != null) { if (!node.SwitchValue.Type.IsNullable()) { il.Ldloc(switchValue); } else { il.Ldloca(switchValue); context.EmitHasValueAccess(node.SwitchValue.Type); } il.Brfalse(switchValueIsNullLabel); } EmittingContext.LocalHolder pureSwitchValue = switchValue; if (node.SwitchValue.Type.IsNullable()) { pureSwitchValue = context.DeclareLocal(node.SwitchValue.Type.GetGenericArguments()[0]); il.Ldloca(switchValue); context.EmitValueAccess(node.SwitchValue.Type); il.Stloc(pureSwitchValue); } Type temp; ExpressionEmittersCollection.Emit(context.ParsedLambda.ConstantsBuilder.MakeAccess(context.ParsedLambda.ConstantsParameter, switchCase.Item1), context, out temp); var type = node.SwitchValue.Type.IsNullable() ? node.SwitchValue.Type.GetGenericArguments()[0] : node.SwitchValue.Type; var typeCode = Type.GetTypeCode(type); switch (typeCode) { case TypeCode.Byte: case TypeCode.Char: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.SByte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: il.Ldloc(pureSwitchValue); break; default: if (type.IsValueType) { il.Ldloca(pureSwitchValue); } else { il.Ldloc(pureSwitchValue); } il.Call(typeof(object).GetMethod("GetHashCode"), type); break; } using (var index = context.DeclareLocal(typeof(int))) { if (typeCode == TypeCode.Int64 || typeCode == TypeCode.UInt64) { il.Ldc_I8(switchCase.Item3); } else { il.Ldc_I4(switchCase.Item3); } il.Rem(true); if (typeCode == TypeCode.Int64 || typeCode == TypeCode.UInt64) { il.Conv <int>(); } il.Stloc(index); il.Ldloc(index); il.Ldelem(type); il.Ldloc(pureSwitchValue); if (node.Comparison != null) { il.Call(node.Comparison); } else { il.Ceq(); } il.Brfalse(defaultLabel); ExpressionEmittersCollection.Emit(context.ParsedLambda.ConstantsBuilder.MakeAccess(context.ParsedLambda.ConstantsParameter, switchCase.Item2), context, out temp); il.Ldloc(index); il.Ldelem(typeof(int)); il.Switch(labels.ToArray()); } if (pureSwitchValue != switchValue) { pureSwitchValue.Dispose(); } } else { // use a number of if/else branches to locate the proper case EmittingContext.LocalHolder pureSwitchValue = switchValue; EmittingContext.LocalHolder switchValueIsNull = null; if (node.SwitchValue.Type.IsNullable()) { pureSwitchValue = context.DeclareLocal(node.SwitchValue.Type.GetGenericArguments()[0]); switchValueIsNull = context.DeclareLocal(typeof(bool)); il.Ldloca(switchValue); il.Dup(); context.EmitValueAccess(node.SwitchValue.Type); il.Stloc(pureSwitchValue); context.EmitHasValueAccess(node.SwitchValue.Type); il.Stloc(switchValueIsNull); } for (int index = 0; index < node.Cases.Count; index++) { var caSe = node.Cases[index]; var label = caseLabels[index]; foreach (var testValue in caSe.TestValues) { context.EmitLoadArguments(testValue); GroboIL.Label elseLabel = null; if (testValue.Type.IsNullable()) { elseLabel = il.DefineLabel("else"); using (var temp = context.DeclareLocal(testValue.Type)) { il.Stloc(temp); il.Ldloca(temp); context.EmitHasValueAccess(testValue.Type); if (switchValueIsNull != null) { il.Ldloc(switchValueIsNull); il.Or(); il.Brfalse(label); il.Ldloca(temp); context.EmitHasValueAccess(testValue.Type); il.Ldloc(switchValueIsNull); il.And(); } il.Brfalse(elseLabel); il.Ldloca(temp); context.EmitValueAccess(testValue.Type); } } il.Ldloc(pureSwitchValue); if (node.Comparison != null) { il.Call(node.Comparison); } else { il.Ceq(); } il.Brtrue(label); if (elseLabel != null) { context.MarkLabelAndSurroundWithSP(elseLabel); } } } } } context.MarkLabelAndSurroundWithSP(defaultLabel); var doneLabel = il.DefineLabel("done"); context.EmitLoadArguments(node.DefaultBody); il.Br(doneLabel); for (int index = 0; index < node.Cases.Count; ++index) { context.MarkLabelAndSurroundWithSP(caseLabels[index]); context.EmitLoadArguments(node.Cases[index].Body); if (index < node.Cases.Count - 1) { il.Br(doneLabel); } } context.MarkLabelAndSurroundWithSP(doneLabel); resultType = node.Type; return(false); }
public void GetWriteILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local value, GroboIL.Local typeSize, GroboIL.Local buffer, GroboIL.Local offset, bool listValue) { var arr = il.DeclareLocal(prop.PropertyInfo.PropertyType); il.Ldloc(value); il.Call(prop.Getter); il.Stloc(arr); var exitLabel = il.DefineLabel("exit"); BinaryStruct.WriteSizeChecker(il, buffer, offset, 5); BinaryStruct.WriteObjectNull(il, exitLabel, arr, buffer, offset, typeSize); var arrSize = il.DeclareLocal(typeof(byte[])); var len = il.DeclareLocal(typeof(int)); il.Ldloc(value); il.Call(prop.Getter); il.Call(typeof(ICollection).GetProperty("Count").GetMethod); il.Stloc(len); il.Ldloc(len); il.Call(writeBitConverterMethodInfo); il.Stloc(arrSize); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(arrSize); il.Ldc_I4(0); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); for (int i = 1; i < 4; i++) { il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(i); il.Add(); il.Ldloc(arrSize); il.Ldc_I4(i); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); } BinaryStruct.WriteOffsetAppend(il, offset, 4); il.Ldloc(len); il.Ldc_I4(0); il.Ceq(); il.Brtrue(exitLabel); var type = prop.PropertyInfo.PropertyType.GetElementType(); var ivar = il.DeclareLocal(typeof(int)); var currentValue = il.DeclareLocal(type); var point = il.DefineLabel("for_label"); il.Ldc_I4(0); il.Stloc(ivar); il.MarkLabel(point); //body il.Ldloc(arr); il.Ldloc(ivar); il.Ldelem(type); //il.Call(prop.PropertyInfo.PropertyType.GetMethod("Get"), isVirtual: true); il.Stloc(currentValue); if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[0])) { IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[0]); t.GetWriteILCode(prop, currentStruct, il, binaryStruct, currentValue, typeSize, buffer, offset, true); } else { BinaryStruct.CompileWriter(currentStruct.CurrentStorage.GetTypeInfo(type, currentStruct.Scheme), il, binaryStruct, currentValue, buffer, offset, typeSize); } //end body il.Ldc_I4(1); il.Ldloc(ivar); il.Add(); il.Stloc(ivar); il.Ldloc(ivar); il.Ldloc(len); il.Clt(false); il.Brtrue(point); il.MarkLabel(exitLabel); }
private KeyValuePair <Delegate, IntPtr> GetMemberSetter(ReaderTypeBuilderContext context, MemberInfo member) { var method = new DynamicMethod("Set_" + Type.Name + "_" + member.Name + "_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext) }, context.Module, true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [data] il.Ldarg(1); // stack: [data, ref index] switch (member.MemberType) { case MemberTypes.Field: var field = (FieldInfo)member; var done = false; if (member.GetCustomAttributes(typeof(IgnoreDefaultOnMergeAttribute), false).Length > 0 && field.FieldType.IsValueType) { var equalityOperator = field.FieldType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (field.FieldType.IsPrimitive || equalityOperator != null) { var fieldValue = il.DeclareLocal(field.FieldType); il.Ldarg(2); // stack: [data, ref index, ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Ldfld(field); il.Stloc(fieldValue); il.Ldloca(fieldValue); il.Ldarg(3); // stack: [data, ref index, ref result.field, context] ReaderMethodBuilderContext.CallReader(il, field.FieldType, context); // reader(data, ref index, ref result.field, context); stack: [] var temp = il.DeclareLocal(field.FieldType); il.Ldloca(temp); il.Initobj(field.FieldType); il.Ldloc(temp); il.Ldloc(fieldValue); if (field.FieldType.IsPrimitive) { il.Ceq(); } else { il.Call(equalityOperator); } var notDefaultLabel = il.DefineLabel("notDefault"); il.Brfalse(notDefaultLabel); il.Ret(); il.MarkLabel(notDefaultLabel); il.Ldarg(2); if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Ldloc(fieldValue); il.Stfld(field); done = true; } } if (!done) { il.Ldarg(2); // stack: [data, ref index, ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Ldflda(field); // stack: [data, ref index, ref result.field] il.Ldarg(3); // stack: [data, ref index, ref result.field, context] ReaderMethodBuilderContext.CallReader(il, field.FieldType, context); // reader(data, ref index, ref result.field, context); stack: [] } break; case MemberTypes.Property: var property = (PropertyInfo)member; var propertyValue = il.DeclareLocal(property.PropertyType); if (context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead)) { var getter = property.GetGetMethod(true); if (getter == null) { throw new MissingMethodException(Type.Name, property.Name + "_get"); } il.Ldarg(2); // stack: [data, ref index, ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [data, ref index, result] } il.Call(getter, Type); // stack: [ data, ref index, result.property] il.Stloc(propertyValue); // propertyValue = result.property; stack: [data, ref index] } il.Ldloca(propertyValue); // stack: [data, ref index, ref propertyValue] il.Ldarg(3); // stack: [data, ref index, ref propertyValue, context] ReaderMethodBuilderContext.CallReader(il, property.PropertyType, context); // reader(data, ref index, ref propertyValue, context); stack: [] if (member.GetCustomAttributes(typeof(IgnoreDefaultOnMergeAttribute), false).Length > 0 && property.PropertyType.IsValueType) { var equalityOperator = property.PropertyType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (property.PropertyType.IsPrimitive || equalityOperator != null) { var temp = il.DeclareLocal(property.PropertyType); il.Ldloca(temp); il.Initobj(property.PropertyType); il.Ldloc(temp); il.Ldloc(propertyValue); if (property.PropertyType.IsPrimitive) { il.Ceq(); } else { il.Call(equalityOperator); } var notDefaultLabel = il.DefineLabel("notDefault"); il.Brfalse(notDefaultLabel); il.Ret(); il.MarkLabel(notDefaultLabel); } } il.Ldarg(2); // stack: [ref result] if (!Type.IsValueType) { il.Ldind(Type); // stack: [result] } il.Ldloc(propertyValue); // stack: [result, propertyValue] var setter = property.GetSetMethod(true); if (setter == null) { throw new MissingMethodException(Type.Name, property.Name + "_set"); } il.Call(setter, Type); // result.property = propertyValue break; default: throw new NotSupportedException("Data member of type '" + member.MemberType + "' is not supported"); } il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
public void GetWriteILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local value, GroboIL.Local typeSize, GroboIL.Local buffer, GroboIL.Local offset, bool listValue) { BinaryStruct.WriteSizeChecker(il, buffer, offset, 5); var arr = il.DeclareLocal(typeof(byte[])); var arrSize = il.DeclareLocal(typeof(byte[])); var temp = il.DeclareLocal(typeof(string)); var exitLabel = il.DefineLabel("exit"); il.Ldloc(value); if (!listValue) { il.Call(prop.Getter); } il.Stloc(temp); il.Ldloc(temp); BinaryStruct.WriteObjectNull(il, exitLabel, buffer, offset, typeSize); il.Ldloc(temp); il.Call(typeof(string).GetProperty("Length").GetMethod); il.Stloc(typeSize); il.Ldarg(1); il.Call(codingMethodInfo); il.Ldloc(temp); il.Call(currentStruct.Coding.GetType().GetMethod("GetBytes", new Type[] { typeof(string) })); il.Stloc(arr); il.Ldloc(arr); il.Call(typeof(byte[]).GetProperty("Length").GetMethod); il.Stloc(typeSize); il.Ldloc(typeSize); il.Call(writeBitConverterMethodInfo); il.Stloc(arrSize); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(arrSize); il.Ldc_I4(0); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); for (int i = 1; i < 4; i++) { il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(i); il.Add(); il.Ldloc(arrSize); il.Ldc_I4(i); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); } BinaryStruct.WriteOffsetAppend(il, offset, 4); il.Ldloc(typeSize); il.Ldc_I4(0); il.Ceq(); il.Brtrue(exitLabel); BinaryStruct.WriteSizeChecker(il, buffer, offset, typeSize); var ivar = il.DeclareLocal(typeof(int)); var point = il.DefineLabel("for_label"); il.Ldc_I4(0); il.Stloc(ivar); il.MarkLabel(point); //body il.Ldloc(buffer); il.Ldloc(ivar); il.Ldloc(offset); il.Add(); il.Ldloc(arr); il.Ldloc(ivar); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); //end body il.Ldc_I4(1); il.Ldloc(ivar); il.Add(); il.Stloc(ivar); il.Ldloc(ivar); il.Ldloc(typeSize); il.Clt(false); il.Brtrue(point); BinaryStruct.WriteOffsetAppend(il, offset, typeSize); il.MarkLabel(exitLabel); }
protected override bool EmitInternal(BinaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { Expression left = node.Left; Expression right = node.Right; Type leftType, rightType; context.EmitLoadArgument(left, false, out leftType); context.EmitLoadArgument(right, false, out rightType); GroboIL il = context.Il; if (!leftType.IsNullable() && !rightType.IsNullable()) { if (node.Method != null) { il.Call(node.Method); } else { if (leftType.IsStruct() || rightType.IsStruct()) { throw new InvalidOperationException("Cannot compare structs"); } il.Ceq(); if (node.NodeType == ExpressionType.NotEqual) { il.Ldc_I4(1); il.Xor(); } } } else { var type = leftType; if (type != rightType) { throw new InvalidOperationException("Cannot compare objects of different types '" + leftType + "' and '" + rightType + "'"); } using (var localLeft = context.DeclareLocal(type)) using (var localRight = context.DeclareLocal(type)) { il.Stloc(localRight); il.Stloc(localLeft); if (node.Method != null) { il.Ldloca(localLeft); // stack: [&left] context.EmitHasValueAccess(type); // stack: [left.HasValue] il.Dup(); // stack: [left.HasValue, left.HasValue] il.Ldloca(localRight); // stack: [left.HasValue, left.HasValue, &right] context.EmitHasValueAccess(type); // stack: [left.HasValue, left.HasValue, right.HasValue] var notEqualLabel = il.DefineLabel("notEqual"); il.Bne_Un(notEqualLabel); // stack: [left.HasValue] var equalLabel = il.DefineLabel("equal"); il.Brfalse(equalLabel); il.Ldloca(localLeft); context.EmitValueAccess(type); il.Ldloca(localRight); context.EmitValueAccess(type); il.Call(node.Method); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(notEqualLabel); il.Pop(); il.Ldc_I4(node.NodeType == ExpressionType.Equal ? 0 : 1); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(equalLabel); il.Ldc_I4(node.NodeType == ExpressionType.Equal ? 1 : 0); context.MarkLabelAndSurroundWithSP(doneLabel); } else { il.Ldloca(localLeft); context.EmitValueAccess(type); il.Ldloca(localRight); context.EmitValueAccess(type); var notEqualLabel = il.DefineLabel("notEqual"); il.Bne_Un(notEqualLabel); il.Ldloca(localLeft); context.EmitHasValueAccess(type); il.Ldloca(localRight); context.EmitHasValueAccess(type); il.Ceq(); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(notEqualLabel); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(doneLabel); if (node.NodeType == ExpressionType.NotEqual) { il.Ldc_I4(1); il.Xor(); } } } } resultType = typeof(bool); return(false); }