private static KeyValuePair <Delegate, IntPtr> GetReader(ReaderMethodBuilderContext context, Type type) { var method = new DynamicMethod("Read_" + type.Name + "_AndCastToObject_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), typeof(object).MakeByRefType(), typeof(ReaderContext) }, context.Context.Module, true); using (var il = new GroboIL(method)) { il.Ldarg(2); // stack: [ref result] il.Ldarg(0); // stack: [ref result, data] il.Ldarg(1); // stack: [ref result, data, ref index] var value = il.DeclareLocal(type); il.Ldloca(value); // stack: [ref result, data, ref index, ref value] il.Ldarg(3); // stack: [ref result, data, ref index, ref value, context] ReaderMethodBuilderContext.CallReader(il, type, context.Context); il.Ldloc(value); // stack: [ref result, value] if (type.IsValueType) { il.Box(type); // stack: [ref result, (object)value] } else { il.Castclass(type); } il.Stind(typeof(object)); // result = (object)value il.Ret(); } var @delegate = method.CreateDelegate(typeof(ReaderDelegate)); return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method))); }
private static Func <object, object> BuildExtractor(FieldInfo field) { var methodName = "FieldExtractor$"; if (field.IsStatic) { methodName += field.DeclaringType + "$"; } methodName += field.Name + "$" + Guid.NewGuid(); var dynamicMethod = new DynamicMethod(methodName, typeof(object), new[] { typeof(object) }, typeof(FieldsExtractor), true); using (var il = new GroboIL(dynamicMethod)) { if (!field.IsStatic) { il.Ldarg(0); il.Castclass(field.DeclaringType); } il.Ldfld(field); if (field.FieldType.IsValueType) { il.Box(field.FieldType); } il.Ret(); } return((Func <object, object>)dynamicMethod.CreateDelegate(typeof(Func <object, object>))); }
private void LoadTupleField(GroboIL il, ValueTupleField tupleFiled) { il.Ldstr(tupleFiled.NameInUserCode); il.Ldarga(0); il.Ldfld(tupleFiled.FieldInfo); if (tupleFiled.FieldInfo.FieldType.IsValueType) { il.Box(tupleFiled.FieldInfo.FieldType); } }
private static void EmitNullableEquals(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse) { // a.Equals(b) var type = getMethod.ReturnType; var local = il.DeclareLocal(type); il.Ldarg(0); il.Call(getMethod); il.Stloc(local); il.Ldloca(local); il.Ldarg(1); il.Call(getMethod); il.Box(type); il.Call(ObjectEquals, type); il.Brfalse(returnFalse); }
protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { Type operandType; var result = ExpressionEmittersCollection.Emit(node.Operand, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType); GroboIL il = context.Il; if (operandType.IsValueType) { il.Box(operandType); } il.Isinst(node.Type); if (node.Type.IsValueType) { il.Unbox_Any(node.Type); } resultType = node.Type; return(result); }
private static MethodBuilder GenerateOverloadedMethodDelegate(MethodInfo methodToIntercept, TypeBuilder typeBuilder, FieldInfo concrete) { // Define the method var method = typeBuilder.DefineMethod(methodToIntercept.Name + "-Delegate", MethodAttributes.Private | MethodAttributes.HideBySig, methodToIntercept.ReturnType, new[] { typeof(ParamInfo[]) }); SetupGenericMethodArguments(methodToIntercept, method); // Local for each out/ref parameter var parameters = methodToIntercept.GetParameters(); var locals = new Dictionary <string, Local>(); using (var il = new GroboIL(method)) { foreach (ParameterInfo parameter in parameters) { if (parameter.IsOut || parameter.ParameterType.IsByRef) { locals.Add(parameter.Name, il.DeclareLocal(parameter.ParameterType.GetElementType(), parameter.Name)); } } var paramInfoType = typeof(ParamInfo); var paramInfoGetValue = paramInfoType.GetProperty("Value").GetGetMethod(); // Initialize out parameters to default values for (var i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.IsByRef && !parameters[i].IsOut) { il.Ldarg(1); il.Ldc_I4(i); il.Ldelem(paramInfoType); il.Call(paramInfoGetValue); if (parameters[i].ParameterType.GetElementType().IsValueType) { il.Unbox_Any(parameters[i].ParameterType.GetElementType()); } else { il.Castclass(parameters[i].ParameterType.GetElementType()); } il.Stloc(locals[parameters[i].Name]); } } // Load target il.Ldarg(0); il.Ldfld(concrete); // Push call values onto stack for (var i = 0; i < parameters.Length; i++) { if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef) { il.Ldloca(locals[parameters[i].Name]); } else { il.Ldarg(1); il.Ldc_I4(i); il.Ldelem(paramInfoType); il.Call(paramInfoGetValue); if (parameters[i].ParameterType.IsValueType || parameters[i].ParameterType.IsGenericParameter) { il.Unbox_Any(parameters[i].ParameterType); } else { il.Castclass(parameters[i].ParameterType); } } } // Call intercepted method il.Call(methodToIntercept); var paramInfoSetValue = paramInfoType.GetProperty("Value").GetSetMethod(); // Copy out/ref parameter values back into passed-in parameters array for (var i = 0; i < parameters.Length; i++) { if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef) { il.Ldarg(1); il.Ldc_I4(i); il.Ldelem(paramInfoType); il.Ldloc(locals[parameters[i].Name]); if (parameters[i].ParameterType.GetElementType().IsValueType) { il.Box(parameters[i].ParameterType.GetElementType()); } il.Call(paramInfoSetValue); } } il.Ret(); LogIlCode(il); } return(method); }
private static void DefineMethodOverrideWithInterception(TypeBuilder typeBuilder, MethodBuilder methodBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, FieldBuilder concreteInstance, ParameterInfo[] methodParams, Type[] genericParameterTypes, Type[] interceptors) { var @delegate = GenerateOverloadedMethodDelegate(overridedMethod, typeBuilder, concreteInstance); for (var i = 0; i < interceptors.Length; i++) { var interceptor = interceptors[i]; @delegate = DefineMethodInterceptingDelegate(typeBuilder, overridedMethod, interceptorFields, genericInterceptionAction, voidInterceptionAction, genericParameterTypes, @delegate, i, interceptor); } using (var il = new GroboIL(methodBuilder)) { var paramInfoType = typeof(ParamInfo); var paramsInfoType = typeof(ParamInfo[]); var paramsInfo = il.DeclareLocal(paramsInfoType); var paramInfo = il.DeclareLocal(paramInfoType); il.Nop(); il.Ldc_I4(methodParams.Length); il.Newarr(typeof(ParamInfo)); il.Stloc(paramsInfo); var paramInfoConstructor = paramInfoType.GetConstructor(new[] { typeof(string), typeof(Type), typeof(bool), typeof(bool) }); var paramInfoValueSetter = paramInfoType.GetProperty("Value").GetSetMethod(); var getTypeMethod = typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) }); var idx = 0; foreach (var parameter in methodParams) { // load array at index il.Ldloc(paramsInfo); il.Ldc_I4(idx++); // Load ParamInfo.Name il.Ldstr(parameter.Name); // Load ParamInfo.Type if (parameter.IsOut || parameter.ParameterType.IsByRef) { il.Ldtoken(parameter.ParameterType.GetElementType()); } else { il.Ldtoken(parameter.ParameterType); } il.Call(getTypeMethod); // Load ParamInfo.IsByRef if (parameter.ParameterType.IsByRef) { il.Ldc_I4(1); } else { il.Ldc_I4(0); } // Load ParamInfo.IsOut if (parameter.IsOut) { il.Ldc_I4(1); } else { il.Ldc_I4(0); } // instantiate ParamInfo il.Newobj(paramInfoConstructor); il.Stloc(paramInfo); // Set ParamInfo.Value il.Ldloc(paramInfo); il.Ldarg(parameter.Position + 1); if (parameter.IsOut || parameter.ParameterType.IsByRef) { il.Ldobj(parameter.ParameterType.GetElementType()); if (parameter.ParameterType.GetElementType().IsValueType || parameter.ParameterType.GetElementType().IsGenericParameter) { il.Box(parameter.ParameterType.GetElementType()); } } else { if (parameter.ParameterType.IsValueType || parameter.ParameterType.IsGenericParameter) { il.Box(parameter.ParameterType); } } il.Call(paramInfoValueSetter); il.Nop(); // push to array il.Ldloc(paramInfo); il.Stelem(paramInfoType); } il.Ldarg(0); il.Ldloc(paramsInfo); if (overridedMethod.IsGenericMethodDefinition) { il.Call(@delegate.MakeGenericMethod(genericParameterTypes)); } else { il.Call(@delegate); } idx = 1; var paramInfoValueGetter = paramInfoType.GetProperty("Value").GetGetMethod(); foreach (var parameter in methodParams) { if (parameter.IsOut || parameter.ParameterType.IsByRef) { il.Ldarg(idx); il.Ldloc(paramsInfo); il.Ldc_I4(idx - 1); il.Ldelem(paramInfoType); il.Call(paramInfoValueGetter); if (parameter.ParameterType.GetElementType().IsValueType) { il.Unbox_Any(parameter.ParameterType.GetElementType()); } il.Stobj(parameter.ParameterType.GetElementType()); } idx++; } il.Ret(); LogIlCode(il); } }