private ITest BuildCalli() { var action = Build(); var typeBuilder = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public); var pointerField = typeBuilder.DefineField("pointer", typeof(IntPtr), FieldAttributes.Private | FieldAttributes.InitOnly); var delegateField = typeBuilder.DefineField("delegate", typeof(Delegate), FieldAttributes.Private | FieldAttributes.InitOnly); var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(IntPtr), typeof(Delegate) }); var il = new GroboIL(constructor); il.Ldarg(0); il.Ldarg(1); il.Stfld(pointerField); il.Ldarg(0); il.Ldarg(2); il.Stfld(delegateField); il.Ret(); var method = typeBuilder.DefineMethod("DoNothing", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); il = new GroboIL(method); il.Ldarg(0); il.Ldfld(pointerField); il.Calli(CallingConventions.Standard, typeof(void), Type.EmptyTypes); il.Ret(); typeBuilder.DefineMethodOverride(method, typeof(ITest).GetMethod("DoNothing")); typeBuilder.AddInterfaceImplementation(typeof(ITest)); var type = typeBuilder.CreateType(); return((ITest)Activator.CreateInstance(type, new object[] { DynamicMethodInvokerBuilder.DynamicMethodPointerExtractor((DynamicMethod)action.Item2), action.Item1 })); }
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 BuildIlWithNativeCallingConvention(MethodBuilder methodBuilder) { using (var il = new GroboIL(methodBuilder)) { il.Ldc_I4(10); il.Ldarg(0); il.Calli(CallingConvention.StdCall, typeof(int), new[] { typeof(int) }); il.Ret(); } }
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>))); }
public static void CallReader(GroboIL il, Type type, ReaderTypeBuilderContext context) { LoadReader(il, type, context); il.Calli(CallingConventions.Standard, typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), type.MakeByRefType(), typeof(ReaderContext) }); }
private Type BuildReaderInvoker() { var argument = Type.GetGenericArguments()[0]; var typeBuilder = module.DefineType("ReaderInvoker_" + Type, TypeAttributes.Public | TypeAttributes.Class); var reader = typeBuilder.DefineField("reader", typeof(IntPtr), FieldAttributes.Private); var serializerId = typeBuilder.DefineField("serializerId", typeof(long), FieldAttributes.Private); var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(IntPtr), typeof(long) }); using (var il = new GroboIL(constructor)) { il.Ldarg(0); // stack: [this] il.Ldarg(1); // stack: [this, reader] il.Stfld(reader); // this.reader = reader; stack: [] il.Ldarg(0); // stack: [this] il.Ldarg(2); // stack: [this, serializerId] il.Stfld(serializerId); // this.serializerId = serializerId; stack: [] il.Ret(); } var method = typeBuilder.DefineMethod("Read", MethodAttributes.Public, argument, new[] { typeof(byte[]) }); using (var il = new GroboIL(method)) { var pinnedData = il.DeclareLocal(typeof(byte).MakeByRefType(), "pinnedData", true); il.Ldarg(1); // stack: [data] il.Ldc_I4(0); // stack: [data, 0] il.Ldelema(typeof(byte)); // stack: [&data[0]] il.Stloc(pinnedData); // pinnedData = &data[0]; stack: [] var index = il.DeclareLocal(typeof(int), "index"); il.Ldc_I4(0); // stack: [0] il.Stloc(index); // index = 0; stack: [] var context = il.DeclareLocal(typeof(ReaderContext), "context"); il.Ldarg(0); // stack: [this] il.Ldfld(serializerId); // stack: [this.serializerId] il.Ldarg(1); // stack: [this.serializerId, data] il.Ldlen(); // stack: [this.serializerId, data.Length] il.Ldc_I4(0); // stack: [this.serializerId, data.Length, 0] il.Ldc_I4(0); // stack: [this.serializerId, data.Length, 0, 0] il.Newobj(typeof(ReaderContext).GetConstructor(new[] { typeof(long), typeof(int), typeof(int), typeof(int) })); // stack: [new ReaderContext(this.serializerId, data.Length, 0, 0)] il.Stloc(context); // context = new ReaderContext(..); stack: [] var result = il.DeclareLocal(argument, "result"); il.Ldloc(pinnedData); // stack: [data] il.Conv <IntPtr>(); // stack: [(IntPtr)data] il.Ldloca(index); // stack: [(IntPtr)data, ref index] il.Ldloca(result); // stack: [(IntPtr)data, ref index, ref result] il.Ldloc(context); // stack: [(IntPtr)data, ref index, ref result, context] il.Ldarg(0); // stack: [(IntPtr)data, ref index, ref result, context, this] il.Ldfld(reader); // stack: [(IntPtr)data, ref index, ref result, context, this.reader] var parameterTypes = new[] { typeof(IntPtr), typeof(int).MakeByRefType(), argument.MakeByRefType(), typeof(ReaderContext) }; il.Calli(CallingConventions.Standard, typeof(void), parameterTypes); // this.reader((IntPtr)data, ref index, ref result, context); stack: [] il.FreePinnedLocal(pinnedData); // pinnedData = null; stack: [] var retLabel = il.DefineLabel("ret"); il.Ldarg(1); // stack: [data] il.Ldlen(); // stack: [data.Length] il.Ldloc(index); // stack: [data.Length, index] il.Beq(retLabel); // if(data.Length == index) goto ret; stack: [] il.Ldstr("Encountered extra data"); il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) })); il.Throw(); il.MarkLabel(retLabel); il.Ldloc(result); il.Ret(); } return(typeBuilder.CreateType()); }