private void CompileWriter() { DynamicMethod dm = new DynamicMethod(Guid.NewGuid().ToString(), typeof(Tuple <int, byte[]>), new[] { Type, typeof(BinaryStruct) }); using (var il = new GroboIL(dm)) { var buffer = il.DeclareLocal(typeof(byte[])); var offset = il.DeclareLocal(typeof(int)); var typeSize = il.DeclareLocal(typeof(int)); var value = il.DeclareLocal(Type); var binaryStruct = il.DeclareLocal(typeof(BinaryStruct)); il.Ldarg(1); il.Stloc(binaryStruct); il.Ldarg(0); //il.Castclass(Type); il.Stloc(value); il.Ldc_I4(InitLen); il.Newarr(typeof(byte)); il.Stloc(buffer); CompileWriter(this, il, binaryStruct, value, buffer, offset, typeSize); il.Ldloc(offset); il.Ldloc(buffer); il.Newobj(typeof(Tuple <int, byte[]>).GetConstructor(new Type[] { typeof(int), typeof(byte[]) })); il.Ret(); IlWriteCode = il.GetILCode(); } WriteMethod = CreateWriter(dm); }
private static void BuildChildren(TypeBuilder typeBuilder, int n, Context context) { var property = typeBuilder.DefineProperty("Children", PropertyAttributes.None, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes); var getter = typeBuilder.DefineMethod("get_Children", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes); using (var il = new GroboIL(getter)) { il.Ldc_I4(n); // stack: [n] il.Newarr(typeof(MethodCallNode)); // stack: [new int[n] -> values] for (int i = 0; i < n; ++i) { il.Dup(); // stack: [values, values] il.Ldc_I4(i); // stack: [values, values, i] il.Ldarg(0); // stack: [values, values, i, this] il.Ldfld(context.values[i]); // stack: [values, values, i, this.values_{i}] il.Stelem(typeof(MethodCallNode)); // values[i] = this.values_{i}; stack: [values] } il.Castclass(typeof(IEnumerable <MethodCallNode>)); il.Ret(); } property.SetGetMethod(getter); typeBuilder.DefineMethodOverride(getter, typeof(MethodCallNodeEdges).GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod()); }
public void TestEnumerable() { var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()), AssemblyBuilderAccess.RunAndSave); var module = assembly.DefineDynamicModule(Guid.NewGuid().ToString(), "test.cil", true); var symWriter = module.GetSymWriter(); var symbolDocumentWriter = symWriter.DefineDocument("test.cil", Guid.Empty, Guid.Empty, Guid.Empty); var typeBuilder = module.DefineType("Zzz", TypeAttributes.Class | TypeAttributes.Public); var method = typeBuilder.DefineMethod("Qzz", MethodAttributes.Public); var genericParameters = method.DefineGenericParameters("TZzz"); var parameter = genericParameters[0]; method.SetParameters(typeof(List <>).MakeGenericType(parameter), typeof(Func <,>).MakeGenericType(parameter, typeof(int))); method.DefineParameter(2, ParameterAttributes.In, "list"); method.SetReturnType(typeof(int)); using (var il = new GroboIL(method, symbolDocumentWriter)) { il.Ldarg(1); il.Dup(); var notNullLabel = il.DefineLabel("notNull"); il.Brtrue(notNullLabel); il.Pop(); il.Ldc_I4(0); il.Newarr(parameter); il.MarkLabel(notNullLabel); var temp = il.DeclareLocal(typeof(IEnumerable <>).MakeGenericType(parameter), "arr"); il.Stloc(temp); il.Ldloc(temp); il.Ldarg(2); il.Call(HackHelpers.GetMethodDefinition <int[]>(ints => ints.Sum(x => x)).GetGenericMethodDefinition().MakeGenericMethod(parameter)); il.Ret(); Console.WriteLine(il.GetILCode()); } var type = typeBuilder.CreateType(); var instance = Activator.CreateInstance(type); type.GetMethod("Qzz", BindingFlags.Instance | BindingFlags.Public).MakeGenericMethod(typeof(int)).Invoke(instance, new object[] { null, null }); }
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); var type = prop.PropertyInfo.PropertyType.GetElementType(); il.Ldloc(len); il.Newarr(type); 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 ivar = il.DeclareLocal(typeof(int)); var point = il.DefineLabel("for_label"); il.Ldc_I4(0); il.Stloc(ivar); il.MarkLabel(point); //body var tempVar = il.DeclareLocal(type); 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, tempVar, typeSize, offset, true); il.Ldloc(list); il.Ldloc(ivar); il.Ldloc(tempVar); il.Stelem(type); } else { var constr = BinaryStruct.GetConstructor(type, null); if (constr == null) { throw new Exception($"Type {type} not have constructor with not parameters"); } il.Newobj(constr); il.Stloc(tempVar); BinaryStruct.CompileReader(currentStruct.CurrentStorage.GetTypeInfo(type, currentStruct.Scheme), il, binaryStruct, buffer, offset, tempVar, typeSize); il.Ldloc(list); il.Ldloc(ivar); il.Ldloc(tempVar); il.Stelem(type); } //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(MethodCallExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { var result = false; GroboIL il = context.Il; var method = node.Method; Expression obj; IEnumerable <Expression> arguments; IEnumerable <ParameterInfo> parameters; bool isStatic = method.IsStatic; if (!isStatic) { obj = node.Object; arguments = node.Arguments; parameters = method.GetParameters(); } else if (method.DeclaringType == typeof(Enumerable)) { obj = node.Arguments[0]; arguments = node.Arguments.Skip(1); parameters = method.GetParameters().Skip(1); } else { obj = null; arguments = node.Arguments; parameters = method.GetParameters(); } Type type = obj == null ? null : obj.Type; if (obj != null) { Type actualType; result |= ExpressionEmittersCollection.Emit(obj, context, returnDefaultValueLabel, isStatic ? ResultType.Value : ResultType.ByRefValueTypesOnly, extend, out actualType); // stack: [obj] if (actualType == typeof(void)) { throw new InvalidOperationException("Unable to call method on void"); } if (actualType.IsValueType && !isStatic) { using (var temp = context.DeclareLocal(actualType)) { il.Stloc(temp); il.Ldloca(temp); } actualType = actualType.MakeByRefType(); } if (context.Options.HasFlag(CompilerOptions.CheckNullReferences) && !actualType.IsValueType) { if (method.DeclaringType != typeof(Enumerable)) { result |= context.EmitNullChecking(type, returnDefaultValueLabel); } else { var arrIsNotNullLabel = il.DefineLabel("arrIsNotNull"); il.Dup(); il.Brtrue(arrIsNotNullLabel); il.Pop(); il.Ldc_I4(0); il.Newarr(GetElementType(type)); context.MarkLabelAndSurroundWithSP(arrIsNotNullLabel); } } } var parametersArray = parameters.ToArray(); var argumentsArray = arguments.ToArray(); for (int i = 0; i < argumentsArray.Length; i++) { var argument = argumentsArray[i]; var parameter = parametersArray[i]; if (parameter.ParameterType.IsByRef) { Type argumentType; var options = context.Options; context.Options = CompilerOptions.None; ExpressionEmittersCollection.Emit(argument, context, null, ResultType.ByRefAll, false, out argumentType); context.Options = options; if (!argumentType.IsByRef) { throw new InvalidOperationException("Expected type by reference"); } } else { Type argumentType; context.EmitLoadArgument(argument, true, out argumentType); } } il.Call(method, type); resultType = node.Type; return(result); }
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); } }