private SizeCounterDelegate BuildCounter(Type type, bool ignoreCustomSerialization) { IntPtr counter = GetCounter(type, ignoreCustomSerialization); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(bool), typeof(WriterContext) }, GetType(), true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); // stack: [obj] if (type.IsValueType) { il.Unbox_Any(type); // stack: [(type)obj] } else { il.Castclass(type); // stack: [(type)obj] } il.Ldarg(1); // stack: [(type)obj, writeEmpty] il.Ldarg(2); // stack: [(type)obj, writeEmpty, context] il.Ldc_IntPtr(counter); // stack: [(type)obj, writeEmpty, context, counter] il.Calli(CallingConventions.Standard, typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }); // counter((type)obj, writeEmpty, context); stack: [] il.Ret(); } return((SizeCounterDelegate)dynamicMethod.CreateDelegate(typeof(SizeCounterDelegate))); }
private WriterDelegate BuildWriter(Type type, bool ignoreCustomSerialization) { IntPtr writer = GetWriter(type, ignoreCustomSerialization); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { typeof(object), typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }, module, true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); // stack: [obj] if (type.IsValueType) { il.Unbox_Any(type); // stack: [(type)obj] } else { il.Castclass(type); // stack: [(type)obj] } il.Ldarg(1); // stack: [(type)obj, writeEmpty] il.Ldarg(2); // stack: [(type)obj, writeEmpty, result] il.Ldarg(3); // stack: [(type)obj, writeEmpty, result, ref index] il.Ldarg(4); // stack: [(type)obj, writeEmpty, result, ref index, context] il.Ldc_IntPtr(writer); il.Calli(CallingConventions.Standard, typeof(void), new[] { type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }); // writer.write<T>((type)obj, writeEmpty, result, ref index, context); stack: [] il.Ret(); } return((WriterDelegate)dynamicMethod.CreateDelegate(typeof(WriterDelegate))); }
private static void EmitDefaultTypeValue(GroboIL il, Type type) { switch (Type.GetTypeCode(type)) { case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Boolean: case TypeCode.Char: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: il.Ldc_I4(0); return; case TypeCode.Int64: case TypeCode.UInt64: il.Ldc_I8(0); return; case TypeCode.Single: il.Ldc_R4(0f); return; case TypeCode.Double: il.Ldc_R8(0d); return; } if (type.IsPointer || type == typeof(UIntPtr) || type == typeof(IntPtr)) { il.Ldc_IntPtr(IntPtr.Zero); il.Conv <UIntPtr>(); } else if (type.IsEnum) { EmitDefaultTypeValue(il, Enum.GetUnderlyingType(type)); } else if (type.IsValueType) { var local = il.DeclareLocal(type); il.Ldloca(local); il.Initobj(type); il.Ldloc(local); } else { il.Ldnull(); } }
public static void LoadReader(GroboIL il, Type type, ReaderTypeBuilderContext context) { var counter = context.GetReader(type); if (counter.Pointer != IntPtr.Zero) { il.Ldc_IntPtr(counter.Pointer); } else { il.Ldfld(context.ConstantsType.GetField("pointers", BindingFlags.Static | BindingFlags.NonPublic)); il.Ldc_I4(counter.Index); il.Ldelem(typeof(IntPtr)); } }
public void CallWriter(GroboIL il, Type type) { var counter = Context.GetWriter(type); if (counter.Pointer != IntPtr.Zero) { il.Ldc_IntPtr(counter.Pointer); } else { il.Ldfld(Context.ConstantsType.GetField("pointers", BindingFlags.Static | BindingFlags.NonPublic)); il.Ldc_I4(counter.Index); il.Ldelem(typeof(IntPtr)); } il.Calli(CallingConventions.Standard, typeof(void), new[] { type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }); }
private SizeCounterDelegate <T> BuildCounter <T>(bool ignoreCustomSerialization) { var type = typeof(T); IntPtr counter = GetCounter(type, ignoreCustomSerialization); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }, GetType(), true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); // stack: [obj] il.Ldarg(1); // stack: [obj, writeEmpty] il.Ldarg(2); // stack: [obj, writeEmpty, context] il.Ldc_IntPtr(counter); // stack: [obj, writeEmpty, context, counter] il.Calli(CallingConventions.Standard, typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }); // counter(obj, writeEmpty, context); stack: [] il.Ret(); } return((SizeCounterDelegate <T>)dynamicMethod.CreateDelegate(typeof(SizeCounterDelegate <T>))); }
private static void EmitValue(GroboIL il, object value) { //value.GetType() is the "real" type, only all pointers are UIntPtr and nullables are BoxedNullable //It can be: //Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Enum, IntPtr, UIntPtr //Or their nullable equivalents //Or string switch (value) { case bool boolean: il.Ldc_I4(boolean ? 1 : 0); break; case char character: il.Ldc_I4(character); break; case sbyte int8: il.Ldc_I4(int8); break; case byte uint8: il.Ldc_I4(uint8); break; case short int16: il.Ldc_I4(int16); break; case ushort uint16: il.Ldc_I4(uint16); break; case int int32: il.Ldc_I4(int32); break; case uint uint32: il.Ldc_I4((int)uint32); break; case long int64: il.Ldc_I8(int64); break; case ulong uint64: il.Ldc_I8((long)uint64); break; case float float32: il.Ldc_R4(float32); break; case double float64: il.Ldc_R8(float64); break; case decimal decimal128: il.LdDec(decimal128); break; case DateTime dateTime: var local = il.DeclareLocal(typeof(DateTime)); il.Ldloca(local); il.Ldc_I8(dateTime.Ticks); il.Ldc_I4((int)dateTime.Kind); il.Call(typeof(DateTime).GetConstructor(new[] { typeof(long), typeof(DateTimeKind) })); il.Ldloc(local); break; case UIntPtr unint: il.Ldc_IntPtr(Unsafe.As <UIntPtr, IntPtr>(ref unint)); break; case IntPtr nint: il.Ldc_IntPtr(nint); break; case Enum enumeration: var underlyingType = Enum.GetUnderlyingType(enumeration.GetType()); var underlyingValue = Convert.ChangeType(enumeration, underlyingType); EmitValue(il, underlyingValue); break; case BoxedNullable boxedNullable: EmitValue(il, boxedNullable.UnderlyingValue); il.Newobj(boxedNullable.NullableType.GetConstructor(new[] { boxedNullable.UnderlyingType })); break; case string str: il.Ldstr(str); break; default: throw new ArgumentException($"Value {value} of type {value.GetType()} is not supported by the emitter."); } }