private Func <IInternalContainer, IInjectionContext, object[], object> EmitConstruct(ConstructorInfo constructorInfo, int[] parametersInfo, Type wrapperType) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), TypeArray <IInternalContainer, IInjectionContext, object[]> .Instance, typeof(ClassCreator), true); using (var il = new GroboIL(method)) { var constructorParameters = constructorInfo.GetParameters(); for (var i = 0; i < constructorParameters.Length; i++) { ProcessParameter(constructorParameters[i], il, parametersInfo != null ? parametersInfo[i] : -1); } il.Newobj(constructorInfo); if (wrapperType != null) { var wrapperConstructor = wrapperType.GetConstructor(TypeArray <object> .Instance); if (wrapperConstructor == null) { throw new NoConstructorException(wrapperType); } il.Newobj(wrapperConstructor); } il.Ret(); } var @delegate = (Func <IInternalContainer, IInjectionContext, object[], object>) method.CreateDelegate(typeof(Func <IInternalContainer, IInjectionContext, object[], object>)); return(@delegate); }
private Func <TestClassA, int> Build1() { var typeBuilder = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public); var method = typeBuilder.DefineMethod("zzz", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(TestClassA) }); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Ldfld(typeof(TestClassA).GetField("Y")); var y = il.DeclareLocal(typeof(int)); il.Stloc(y); il.Ldarg(0); il.Ldfld(typeof(TestClassA).GetField("Z")); var z = il.DeclareLocal(typeof(int)); il.Stloc(z); il.Ldloc(y); il.Ldloc(z); il.Add(); il.Ret(); } var type = typeBuilder.CreateType(); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(Func <TestClassA, int>), Type.EmptyTypes, Module, true); using (var il = new GroboIL(dynamicMethod)) { il.Ldnull(); il.Ldftn(type.GetMethod("zzz")); il.Newobj(typeof(Func <TestClassA, int>).GetConstructor(new[] { typeof(object), typeof(IntPtr) })); il.Ret(); } return(((Func <Func <TestClassA, int> >)dynamicMethod.CreateDelegate(typeof(Func <Func <TestClassA, int> >)))()); }
private static TryParseDelegate EmitTryParseDelegate() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(string), typeof(DateTimeTypeCode), typeof(object).MakeByRefType() }, typeof(string), true); var xsdDateTimeType = typeof(XmlReader).Assembly.GetTypes().FirstOrDefault(type => type.Name == "XsdDateTime"); if (xsdDateTimeType == null) { throw new InvalidOperationException("The type 'XsdDateTime' is not found"); } var tryParseMethod = xsdDateTimeType.GetMethod("TryParse", BindingFlags.Static | BindingFlags.NonPublic); if (tryParseMethod == null) { throw new InvalidOperationException("The method 'XsdDateTime.TryParse' is not found"); } using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [value] il.Ldarg(1); // stack: [value, typeCode] var strongBoxType = typeof(StrongBox <>).MakeGenericType(xsdDateTimeType); var strongBox = il.DeclareLocal(strongBoxType); il.Ldarg(2); // stack: [value, typeCode, ref result] il.Newobj(strongBoxType.GetConstructor(Type.EmptyTypes)); // stack: [value, typeCode, ref result, new StrongBox<XsdDateTime>()] il.Dup(); il.Stloc(strongBox); // strongBox = new StrongBox<XsdDateTime>(); stack: [value, typeCode, ref result, strongBox] il.Stind(typeof(object)); // result = strongBox; stack: [value, typeCode] il.Ldloc(strongBox); // stack: [value, typeCode, strongBox] il.Ldflda(strongBoxType.GetField("Value", BindingFlags.Instance | BindingFlags.Public)); // stack: [value, typeCode, ref strongBox.Value] il.Call(tryParseMethod); // stack: [XsdDateTime.TryParse(value, typeCode, ref strongBox.Value] il.Ret(); } return((TryParseDelegate)method.CreateDelegate(typeof(TryParseDelegate))); }
protected override bool EmitInternal(NewExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { context.EmitLoadArguments(node.Arguments.ToArray()); // note ich: баг решарпера // ReSharper disable ConditionIsAlwaysTrueOrFalse // ReSharper disable HeuristicUnreachableCode GroboIL il = context.Il; if (node.Constructor != null) { il.Newobj(node.Constructor); } else { if (node.Type.IsValueType) { using (var temp = context.DeclareLocal(node.Type)) { il.Ldloca(temp); il.Initobj(node.Type); il.Ldloc(temp); } } else { throw new InvalidOperationException("Missing constructor for type '" + node.Type + "'"); } } resultType = node.Type; // ReSharper restore ConditionIsAlwaysTrueOrFalse // ReSharper restore HeuristicUnreachableCode return(false); }
public static Func <Dictionary <string, object>, object> GenerateMethod(Type type) { var da = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName("dyn"), // call it whatever you want AssemblyBuilderAccess.RunAndSave); var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll"); var dt = dm.DefineType("dyn_type"); var emiter = Emit <Func <int> > .NewDynamicMethod("MyMethod"); var method = dt.DefineMethod( "Foo", MethodAttributes.Public | MethodAttributes.Static, typeof(object), new[] { typeof(Dictionary <string, object>) }); method.DefineParameter(1, ParameterAttributes.None, "dictionary"); using (var il = new GroboIL(method)) { var target = il.DeclareLocal(type); var value = il.DeclareLocal(typeof(object)); il.Newobj(type.GetConstructor(Type.EmptyTypes)); // [Person] il.Stloc(target); // [] foreach (var property in type.GetProperties()) { var label = il.DefineLabel("ifLabel"); il.Ldarg(0); // [Dictionary<String, Object>] il.Ldstr(property.Name); // [Dictionary<String, Object>, String] il.Ldloca(value); // [Dictionary<String, Object>, String, Object&] il.Call(typeof(Dictionary <string, object>) .GetMethod("TryGetValue")); // [Boolean] il.Brfalse(label); // [] il.Ldloc(target); // [Person] il.Ldloc(value); // [Person, Object] il.Castclass(typeof(string)); // [Dictionary<String, Object>, String] il.Call(property.GetSetMethod(true)); // [] il.MarkLabel(label); } il.Ldloc(target); il.Ret(); Console.WriteLine(il.GetILCode()); } dt.CreateType(); da.Save("dyn.dll"); return((dic) => dt.GetMethod("Foo").Invoke(null, new object[] { dic })); }
private static Func <object, MethodBase, SignatureHelper, uint> BuildGetTokenFor() { var parameterTypes = new[] { typeof(object), typeof(MethodBase), typeof(SignatureHelper) }; var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(uint), parameterTypes, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); // stack: [scope] il.Castclass(dynamicScopeType); il.Ldarg(1); // stack: [scope, method] il.Castclass(runtimeMethodInfoType); // stack: [scope, (RuntimeMethodInfo)method] il.Ldarg(2); // stack: [scope, (RuntimeMethodInfo)method, signature] var constructor = varArgsMethodType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeMethodInfoType, typeof(SignatureHelper) }, null); if (constructor == null) { throw new MissingMethodException("VarArgsMethod", ".ctor"); } var getTokenForMethod = dynamicScopeType.GetMethod("GetTokenFor", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { varArgsMethodType }, null); if (getTokenForMethod == null) { throw new MissingMethodException("DynamicScope", "GetTokenFor"); } il.Newobj(constructor); // stack: [scope, new VarArgsMethod((RuntimeMethodInfo)method, signature)] il.Call(getTokenForMethod); // stack: [scope.GetTokenFor(new VarArgsMethod((RuntimeMethodInfo)method, signature))] il.Ret(); } return((Func <object, MethodBase, SignatureHelper, uint>)method.CreateDelegate(typeof(Func <object, MethodBase, SignatureHelper, uint>))); }
public static Type GenerateClass(ClassDescription description) { var name = new AssemblyName("MyAssembly"); AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly( name, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule( name.Name, name.Name + ".dll"); TypeBuilder typeBuilder = moduleBuilder.DefineType( description.TypeName, TypeAttributes.Class | TypeAttributes.Public); foreach (var constructorDescr in description.Constructors) { var staticOrDynamicAttr = constructorDescr.StaticOrDynamic == StaticOrDynamic.Static ? MethodAttributes.Static : MethodAttributes.Public; // второй вариант по сути ничего не добавляет, но атрибута Dynamic нет var inTypes = constructorDescr.InputTypes .Select(typeName => description.AllTypes[typeName].RealType) .ToArray(); typeBuilder.DefineConstructor( MethodAttributes.Public | staticOrDynamicAttr, CallingConventions.Standard, inTypes); } foreach (var methodDescr in description.Methods) { var staticOrDynamicAttr = methodDescr.StaticOrDynamic == StaticOrDynamic.Static ? MethodAttributes.Static : MethodAttributes.Public; var outType = description.AllTypes[methodDescr.OutputType].RealType; var inTypes = methodDescr.InputTypes .Select(typeName => description.AllTypes[typeName].RealType) .ToArray(); var method = typeBuilder.DefineMethod( methodDescr.MethodName, MethodAttributes.Public | staticOrDynamicAttr, outType, inTypes); GroboIL iLgenerator = new GroboIL(method); iLgenerator.Newobj(new NotImplementedException() .GetType() .GetConstructors()[0]); iLgenerator.Throw(); } var type = typeBuilder.CreateType(); assemblyBuilder.Save(name.Name + ".dll"); return(type); }
private GroboIL.Local EmitDictDeclaration(GroboIL il) { il.Newobj(typeof(Dictionary <string, object>).GetConstructor(new Type[0])); var dict = il.DeclareLocal(typeof(Dictionary <string, object>), "dict"); il.Stloc(dict); return(dict); }
public void Test_ldvirtftn3() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), Type.EmptyTypes, typeof(string), true); var il = new GroboIL(method); il.Newobj(typeof(C2).GetConstructor(Type.EmptyTypes)); Assert.Throws <InvalidOperationException>(() => il.Ldvirtftn(typeof(I1).GetMethod("Zzz"))); }
private void CompileReader() { DynamicMethod dm = new DynamicMethod(Guid.NewGuid().ToString(), typeof(Tuple <int, object>), new[] { typeof(byte[]), typeof(BinaryStruct), typeof(int) }); using (var il = new GroboIL(dm)) { var offset = il.DeclareLocal(typeof(int)); var result = il.DeclareLocal(this.Type); var typeSize = il.DeclareLocal(typeof(int)); var buffer = il.DeclareLocal(typeof(byte[])); var binaryStruct = il.DeclareLocal(typeof(BinaryStruct)); il.Ldarg(1); il.Stloc(binaryStruct); var constr = GetConstructor(result.Type, null); if (constr == null) { throw new Exception($"Type {result.Type} not have constructor with not parameters"); } il.Ldarg(0); il.Stloc(buffer); il.Ldarg(2); il.Stloc(offset); il.Newobj(constr); il.Stloc(result); CompileReader(this, il, binaryStruct, buffer, offset, result, typeSize); il.Ldloc(offset); il.Ldloc(result); il.Newobj(typeof(Tuple <int, object>).GetConstructor(new Type[] { typeof(int), typeof(object) })); il.Ret(); IlReadCode = il.GetILCode(); } //ReadMethod = (ReadMethodDelegate)dm.CreateDelegate(typeof(ReadMethodDelegate)); ReadMethod = CreateReader(dm); }
public void Test_ldvirtftn2() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), Type.EmptyTypes, typeof(string), true); using (var il = new GroboIL(method)) { il.Newobj(typeof(C1).GetConstructor(Type.EmptyTypes)); il.Ldvirtftn(typeof(I1).GetMethod("Zzz")); il.Pop(); il.Ret(); } }
private static void EmitCrashIfValueIsNull(GroboIL il) { var box = il.DefineLabel("box"); il.Dup(); il.Brtrue(box); var crashConstructor = typeof(ArgumentException).GetConstructor(new[] { typeof(string) }); il.Ldstr("bad parameter"); il.Newobj(crashConstructor); il.Throw(); il.MarkLabel(box); }
private static MethodBuilder DefineMethodInterceptingDelegate(TypeBuilder typeBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, Type[] genericParameterTypes, MethodBuilder @delegate, int index, Type interceptor) { ConstructorInfo delegateConstructor; MethodInfo interceptorMethod; // Define the method var method = typeBuilder.DefineMethod($"{overridedMethod.Name}-{interceptor.Name}_{index}_Interceptor", MethodAttributes.Private | MethodAttributes.HideBySig, overridedMethod.ReturnType, new[] { typeof(ParamInfo[]) }); SetupGenericMethodArguments(overridedMethod, method); using (var il = new GroboIL(method)) { if (overridedMethod.ReturnType != typeof(void)) { interceptorMethod = genericInterceptionAction.MakeGenericMethod(overridedMethod.ReturnType); delegateConstructor = typeof(TDelegate <>).MakeGenericType(overridedMethod.ReturnType).GetConstructor(new[] { typeof(object), typeof(IntPtr) }); } else { interceptorMethod = voidInterceptionAction; delegateConstructor = typeof(VoidDelegate).GetConstructor(new[] { typeof(object), typeof(IntPtr) }); } il.Ldarg(0); il.Ldfld(interceptorFields[interceptor]); il.Ldarg(0); if (overridedMethod.IsGenericMethodDefinition) { il.Ldftn(@delegate.MakeGenericMethod(genericParameterTypes)); } else { il.Ldftn(@delegate); } il.Newobj(delegateConstructor); il.Ldarg(1); il.Call(interceptorMethod); il.Ret(); @delegate = method; } return(@delegate); }
private static Func <IntPtr, RuntimeTypeHandle> EmitRuntimeTypeHandleCreator() { var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(RuntimeTypeHandle), new[] { typeof(IntPtr) }, typeof(string), true); using (var il = new GroboIL(dynamicMethod)) { var GetTypeFromHandleUnsafe_m = typeof(Type).GetMethod("GetTypeFromHandleUnsafe", BindingFlags.Static | BindingFlags.NonPublic); il.Ldarg(0); // stack: [ptr] il.Call(GetTypeFromHandleUnsafe_m); // stack: [Type.GetTypeFromHandleUnsafe(ptr)] var runtimeType = typeof(Type).Assembly.GetType("System.RuntimeType"); var constructor = typeof(RuntimeTypeHandle).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeType }, null); il.Newobj(constructor); il.Ret(); } return((Func <IntPtr, RuntimeTypeHandle>)dynamicMethod.CreateDelegate(typeof(Func <IntPtr, RuntimeTypeHandle>))); }
private static LambdaCreateDelegate BuildLambdaFactory(Type delegateType) { var resultType = typeof(Expression <>).MakeGenericType(delegateType); var parameterTypes = new[] { typeof(Expression), typeof(string), typeof(bool), typeof(ReadOnlyCollection <ParameterExpression>) }; var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(LambdaExpression), parameterTypes, typeof(LambdaExpressionCreator), true); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Ldarg(1); il.Ldarg(2); il.Ldarg(3); il.Newobj(resultType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).Single()); il.Ret(); } return((LambdaCreateDelegate)method.CreateDelegate(typeof(LambdaCreateDelegate))); }
protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { if (node.Type != typeof(bool) && node.Type != typeof(bool?)) { return(ExpressionEmittersCollection.Emit(Expression.OnesComplement(node.Operand, node.Method), context, returnDefaultValueLabel, whatReturn, extend, out resultType)); } GroboIL il = context.Il; if (node.Method != null) { throw new NotSupportedException("Custom operator '" + node.NodeType + "' is not supported"); } var operand = node.Operand; context.EmitLoadArgument(operand, false, out resultType); if (resultType == typeof(bool)) { il.Ldc_I4(1); il.Xor(); } else if (resultType == typeof(bool?)) { using (var value = context.DeclareLocal(typeof(bool?))) { il.Stloc(value); il.Ldloca(value); context.EmitHasValueAccess(typeof(bool?)); var returnLabel = il.DefineLabel("return"); il.Brfalse(returnLabel); il.Ldloca(value); context.EmitValueAccess(typeof(bool?)); il.Ldc_I4(1); il.Xor(); il.Newobj(nullableBoolConstructor); il.Stloc(value); context.MarkLabelAndSurroundWithSP(returnLabel); il.Ldloc(value); } } else { throw new InvalidOperationException("Cannot perform '" + node.NodeType + "' operator on type '" + resultType + "'"); } return(false); }
public static Func <int[], MethodCallNode[], MethodCallNodeEdges> Build(int n) { var typeBuilder = module.DefineType("MCNE_UnrolledBinarySearch_" + n, TypeAttributes.Public | TypeAttributes.Class, typeof(MethodCallNodeEdges)); var context = new Context { keys = new FieldInfo[n], values = new FieldInfo[n], }; for (int i = 0; i < n; ++i) { context.keys[i] = typeBuilder.DefineField("key_" + i, typeof(int), FieldAttributes.Private); context.values[i] = typeBuilder.DefineField("value_" + i, typeof(MethodCallNode), FieldAttributes.Private); } BuildConstructor(typeBuilder, n, context); BuildCount(typeBuilder, n); BuildMethodIds(typeBuilder, n, context); BuildChildren(typeBuilder, n, context); BuildJump(typeBuilder, n, context); var type = typeBuilder.CreateType(); var constructor = type.GetConstructor(new[] { typeof(int[]), typeof(MethodCallNode[]) }); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(MethodCallNodeEdges), new[] { typeof(int[]), typeof(MethodCallNode[]) }, typeof(string), true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); il.Ldarg(1); il.Newobj(constructor); il.Ret(); } var creator = (Func <int[], MethodCallNode[], MethodCallNodeEdges>)dynamicMethod.CreateDelegate(typeof(Func <int[], MethodCallNode[], MethodCallNodeEdges>)); return((keys, values) => { var indexes = new int[n]; for (int i = 0; i < n; ++i) { indexes[i] = i; } Array.Sort(indexes, (i, j) => keys[i].CompareTo(keys[j])); return creator(indexes.Select(i => keys[i]).ToArray(), indexes.Select(i => values[i]).ToArray()); }); }
protected TDelegate CompileToMethod <TDelegate>(Expression <TDelegate> lambda, CompilerOptions options) where TDelegate : class { var typeBuilder = TestPerformance.Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Public); var method = typeBuilder.DefineMethod("lambda", MethodAttributes.Public | MethodAttributes.Static, lambda.ReturnType, lambda.Parameters.Select(parameter => parameter.Type).ToArray()); LambdaCompiler.CompileToMethod(lambda, method, options); var type = typeBuilder.CreateType(); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(TDelegate), null, TestPerformance.Module, true); using (var il = new GroboIL(dynamicMethod)) { il.Ldnull(); il.Ldftn(type.GetMethod("lambda")); il.Newobj(typeof(TDelegate).GetConstructor(new[] { typeof(object), typeof(IntPtr) })); il.Ret(); } return(((Func <TDelegate>)dynamicMethod.CreateDelegate(typeof(Func <TDelegate>)))()); }
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 val = il.DeclareLocal(typeof(TType)); (new T()).GetReadILCode(prop, currentStruct, il, binaryStruct, buffer, val, typeSize, offset, true); il.Ldloc(result); il.Ldloc(val); il.Newobj(Setter); il.Call(prop.Setter); il.MarkLabel(exitLabel); }
private static void BuildFactoryByDynamicILInfo() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { dynamicILInfoType }, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); var constructor = dynamicResolverType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { dynamicILInfoType }, null); if (constructor == null) { throw new MissingMethodException("DynamicResolver", ".ctor"); } il.Newobj(constructor); il.Ret(); } factoryByDynamicILInfo = (Func <DynamicILInfo, object>)method.CreateDelegate(typeof(Func <DynamicILInfo, object>)); }
private static Func <ValidationResultTreeNode, ValidationResultTreeNode> BuildFactoryInternal(Type type) { var parameterTypes = new[] { typeof(ValidationResultTreeNode) }; var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(ValidationResultTreeNode), parameterTypes, typeof(string), true); using (var il = new GroboIL(method)) { var constructor = type.GetConstructor(parameterTypes); if (constructor == null) { throw new InvalidOperationException(string.Format("The type '{0}' has no constructor accepting one parameter of type '{1}'", type, typeof(ValidationResultTreeNode))); } il.Ldarg(0); il.Newobj(constructor); il.Ret(); } return((Func <ValidationResultTreeNode, ValidationResultTreeNode>)method.CreateDelegate(typeof(Func <ValidationResultTreeNode, ValidationResultTreeNode>))); }
public static void CompileReader(BinaryStruct bs, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local result, GroboIL.Local typeSize) { if (bs.PropertyList.Count > 0) { foreach (var item in bs.PropertyList) { if (item.IsBaseType) { item.BinaryType.GetReadILCode(item, bs, il, binaryStruct, buffer, result, typeSize, offset, false); continue; } var methodBreak = il.DefineLabel("breakReadMethod"); ReadObjectNull(il, methodBreak, buffer, offset, typeSize); var in_value = il.DeclareLocal(item.PropertyInfo.PropertyType); var constr = BinaryStruct.GetConstructor(item.PropertyInfo.PropertyType, null); if (constr == null) { throw new Exception($"Type {item.PropertyInfo.PropertyType} not have constructor with not parameters"); } il.Newobj(constr); il.Stloc(in_value); CompileReader(item.BinaryStruct, il, binaryStruct, buffer, offset, in_value, typeSize); il.Ldloc(result); il.Ldloc(in_value); il.Call(item.Setter, isVirtual: true); il.MarkLabel(methodBreak); //il.Pop(); } } }
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); }
public static void EmitConstructionOfType(Type type, GroboIL il) { ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); if (constructor != null) { il.Newobj(constructor); } else { il.Ldtoken(type); il.Call(getTypeFromHandle); il.Call(getUninitializedObject); if (type.IsValueType) { il.Unbox_Any(type); } else { il.Castclass(type); } } }
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 (node.NodeType == ExpressionType.IsTrue || node.NodeType == ExpressionType.IsFalse) { if (!operandType.IsNullable()) { if (node.Method != null) { il.Call(node.Method); } else if (operandType == typeof(bool)) { if (node.NodeType == ExpressionType.IsFalse) { il.Ldc_I4(1); il.Xor(); } } else { throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'"); } } else { using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldloca(temp); context.EmitHasValueAccess(operandType); var returnFalseLabel = il.DefineLabel("returnFalse"); il.Brfalse(returnFalseLabel); il.Ldloca(temp); context.EmitValueAccess(operandType); if (node.Method != null) { il.Call(node.Method); } else if (operandType == typeof(bool?)) { if (node.NodeType == ExpressionType.IsFalse) { il.Ldc_I4(1); il.Xor(); } } else { throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'"); } var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(returnFalseLabel); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(doneLabel); } } } else { if (!operandType.IsNullable()) { if (node.Method != null) { il.Call(node.Method); } else { if (operandType.IsStruct()) { throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a struct '" + operandType + "'"); } switch (node.NodeType) { case ExpressionType.UnaryPlus: break; case ExpressionType.Negate: il.Neg(); break; case ExpressionType.NegateChecked: using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldc_I4(0); context.EmitConvert(typeof(int), operandType); il.Ldloc(temp); il.Sub_Ovf(operandType.Unsigned()); } break; case ExpressionType.Increment: il.Ldc_I4(1); context.EmitConvert(typeof(int), operandType); il.Add(); break; case ExpressionType.Decrement: il.Ldc_I4(1); context.EmitConvert(typeof(int), operandType); il.Sub(); break; case ExpressionType.OnesComplement: il.Not(); break; default: throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point"); } } } else { using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldloca(temp); context.EmitHasValueAccess(operandType); var returnNullLabel = il.DefineLabel("returnLabel"); il.Brfalse(returnNullLabel); Type argumentType = operandType.GetGenericArguments()[0]; if (node.Method != null) { il.Ldloca(temp); context.EmitValueAccess(operandType); il.Call(node.Method); } else { switch (node.NodeType) { case ExpressionType.UnaryPlus: il.Ldloca(temp); context.EmitValueAccess(operandType); break; case ExpressionType.Negate: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Neg(); break; case ExpressionType.NegateChecked: il.Ldc_I4(0); context.EmitConvert(typeof(int), argumentType); il.Ldloca(temp); context.EmitValueAccess(operandType); il.Sub_Ovf(argumentType.Unsigned()); break; case ExpressionType.Increment: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Ldc_I4(1); context.EmitConvert(typeof(int), argumentType); il.Add(); break; case ExpressionType.Decrement: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Ldc_I4(1); context.EmitConvert(typeof(int), argumentType); il.Sub(); break; case ExpressionType.OnesComplement: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Not(); break; default: throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point"); } } il.Newobj(operandType.GetConstructor(new[] { argumentType })); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(returnNullLabel); context.EmitLoadDefaultValue(operandType); context.MarkLabelAndSurroundWithSP(doneLabel); } } } resultType = node.Type; return(result); }
private static void EmitConvertValue(GroboIL il, GroBufTypeCode typeCode, GroBufTypeCode expectedTypeCode) { if (expectedTypeCode == typeCode) { return; } switch (expectedTypeCode) { case GroBufTypeCode.Int8: il.Conv <sbyte>(); break; case GroBufTypeCode.UInt8: case GroBufTypeCode.Boolean: il.Conv <byte>(); break; case GroBufTypeCode.Int16: il.Conv <short>(); break; case GroBufTypeCode.UInt16: il.Conv <ushort>(); break; case GroBufTypeCode.Int32: if (typeCode == GroBufTypeCode.Int64 || typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.Double || typeCode == GroBufTypeCode.Single || typeCode == GroBufTypeCode.DateTimeNew) { il.Conv <int>(); } break; case GroBufTypeCode.UInt32: if (typeCode == GroBufTypeCode.Int64 || typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.Double || typeCode == GroBufTypeCode.Single || typeCode == GroBufTypeCode.DateTimeNew) { il.Conv <uint>(); } break; case GroBufTypeCode.Int64: if (typeCode != GroBufTypeCode.UInt64) { if (typeCode == GroBufTypeCode.UInt8 || typeCode == GroBufTypeCode.UInt16 || typeCode == GroBufTypeCode.UInt32) { il.Conv <ulong>(); } else { il.Conv <long>(); } } break; case GroBufTypeCode.UInt64: if (typeCode != GroBufTypeCode.Int64 && typeCode != GroBufTypeCode.DateTimeNew) { if (typeCode == GroBufTypeCode.Int8 || typeCode == GroBufTypeCode.Int16 || typeCode == GroBufTypeCode.Int32) { il.Conv <long>(); } else { il.Conv <ulong>(); } } break; case GroBufTypeCode.Single: if (typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.UInt32) { il.Conv_R_Un(); } il.Conv <float>(); break; case GroBufTypeCode.Double: if (typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.UInt32) { il.Conv_R_Un(); } il.Conv <double>(); break; case GroBufTypeCode.Decimal: switch (typeCode) { case GroBufTypeCode.Boolean: case GroBufTypeCode.Int8: case GroBufTypeCode.Int16: case GroBufTypeCode.Int32: case GroBufTypeCode.UInt8: case GroBufTypeCode.UInt16: il.Newobj(decimalByIntConstructor); break; case GroBufTypeCode.UInt32: il.Newobj(decimalByUIntConstructor); break; case GroBufTypeCode.Int64: case GroBufTypeCode.DateTimeNew: il.Newobj(decimalByLongConstructor); break; case GroBufTypeCode.UInt64: il.Newobj(decimalByULongConstructor); break; case GroBufTypeCode.Single: il.Call(decimalByFloatMethod); break; case GroBufTypeCode.Double: il.Call(decimalByDoubleMethod); break; default: throw new NotSupportedException("Type with type code '" + typeCode + "' is not supported"); } break; default: throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported"); } }
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); }
private Func <object> BuildConstants(Type type, ClosureSubstituter closureSubstituter) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object[]) }, typeof(ExpressionClosureBuilder), true); var root = Expression.Parameter(type); var consts = new object[hashtable.Count]; using (var il = new GroboIL(method)) { il.Newobj(type.GetConstructor(Type.EmptyTypes)); // stack: [new Constants()] var result = il.DeclareLocal(type, "result"); il.Stloc(result); // result = new Constants(); stack: [] int index = 0; foreach (DictionaryEntry entry in hashtable) { var pair = (Tuple <Type, object>)entry.Key; var constType = pair.Item1; consts[index] = pair.Item2 is Expression?closureSubstituter.Visit((Expression)pair.Item2) : pair.Item2; var fieldAccessor = constantsBuilder.MakeAccess(root, ((int?)entry.Value).Value); var pathToField = new List <FieldInfo>(); while (fieldAccessor.NodeType != ExpressionType.Parameter) { var memberExpression = (MemberExpression)fieldAccessor; pathToField.Add((FieldInfo)memberExpression.Member); fieldAccessor = memberExpression.Expression; } pathToField.Reverse(); il.Ldloc(result); for (int i = 0; i < pathToField.Count - 1; ++i) { il.Ldflda(pathToField[i]); // stack: [ref result.field] il.Dup(); // stack: [ref result.field, ref result.field] var fieldType = pathToField[i].FieldType; il.Ldind(fieldType); // stack: [ref result.field, result.field] var notNullLabel = il.DefineLabel("notNull"); il.Brtrue(notNullLabel); // if(result.field != null) goto notNull; stack: [ref result.field] il.Dup(); // stack: [ref result.field, ref result.field] il.Newobj(fieldType.GetConstructor(Type.EmptyTypes)); // stack: [ref result.field, ref result.field, new field()] il.Stind(fieldType); // result.field = new field(); stack: [ref result.field] il.MarkLabel(notNullLabel); il.Ldind(fieldType); // stack: [result.field] } il.Ldarg(0); // stack: [path, args] il.Ldc_I4(index++); // stack: [path, args, index] il.Ldelem(typeof(object)); // stack: [path, args[index]] var field = pathToField.Last(); if (!constType.IsValueType) { il.Castclass(field.FieldType); // stack: [path, (FieldType)args[index]] } else { il.Unbox_Any(constType); if (field.FieldType != constType) { var constructor = field.FieldType.GetConstructor(new[] { constType }); if (constructor == null) { throw new InvalidOperationException(string.Format("Missing constructor of type '{0}' with parameter of type '{1}'", Formatter.Format(field.FieldType), Formatter.Format(constType))); } il.Newobj(constructor); } } il.Stfld(field); // path.field = (FieldType)args[index]; stack: [] } il.Ldloc(result); il.Ret(); } var func = (Func <object[], object>)method.CreateDelegate(typeof(Func <object[], object>)); return(() => func(consts)); }
private void NumberToBitsValue(bool takeLength = false) { Generator.Newobj(takeLength ? BitsValueCtorLength : BitsValueCtor); ValueToReference(); }
public void Test1() { var overflow = typeof(OverflowException); var exCtorInfo = overflow.GetConstructor(new[] { typeof(string) }); var exToStrMI = overflow.GetMethod("ToString"); var writeLineMI = typeof(Console).GetMethod("WriteLine", new[] { typeof(string), typeof(object) }); var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(int), typeof(int) }, typeof(TestTryCatch)); using (var il = new GroboIL(method)) { GroboIL.Local tmp1 = il.DeclareLocal(typeof(int)); GroboIL.Local tmp2 = il.DeclareLocal(overflow); // In order to successfully branch, we need to create labels // representing the offset IL instruction block to branch to. // These labels, when the MarkLabel(Label) method is invoked, // will specify the IL instruction to branch to. // GroboIL.Label failed = il.DefineLabel("failed"); GroboIL.Label endOfMthd = il.DefineLabel("end"); // Begin the try block. il.BeginExceptionBlock(); // First, load argument 0 and the integer value of "100" onto the // stack. If arg0 > 100, branch to the label "failed", which is marked // as the address of the block that throws an exception. // il.Ldarg(0); il.Ldc_I4(100); il.Bgt(failed, false); // Now, check to see if argument 1 was greater than 100. If it was, // branch to "failed." Otherwise, fall through and perform the addition, // branching unconditionally to the instruction at the label "endOfMthd". // il.Ldarg(1); il.Ldc_I4(100); il.Bgt(failed, false); il.Ldarg(0); il.Ldarg(1); il.Add_Ovf(true); // Store the result of the addition. il.Stloc(tmp1); il.Leave(endOfMthd); // If one of the arguments was greater than 100, we need to throw an // exception. We'll use "OverflowException" with a customized message. // First, we load our message onto the stack, and then create a new // exception object using the constructor overload that accepts a // string message. // il.MarkLabel(failed); il.Ldstr("Cannot accept values over 100 for add."); il.Newobj(exCtorInfo); // We're going to need to refer to that exception object later, so let's // store it in a temporary variable. Since the store function pops the // the value/reference off the stack, and we'll need it to throw the // exception, we will subsequently load it back onto the stack as well. il.Stloc(tmp2); il.Ldloc(tmp2); // Throw the exception now on the stack. il.Throw(); // Start the catch block for OverflowException. // il.BeginCatchBlock(overflow); // When we enter the catch block, the thrown exception // is on the stack. Store it, then load the format string // for WriteLine. // il.Stloc(tmp2); il.Ldstr("Caught {0}"); // Push the thrown exception back on the stack, then // call its ToString() method. Note that if this catch block // were for a more general exception type, like Exception, // it would be necessary to use the ToString for that type. // il.Ldloc(tmp2); il.Call(exToStrMI); // The format string and the return value from ToString() are // now on the stack. Call WriteLine(string, object). // il.Call(writeLineMI); // Since our function has to return an integer value, we'll load -1 onto // the stack to indicate an error, and store it in local variable tmp1. // il.Ldc_I4(-1); il.Stloc(tmp1); // End the exception handling block. il.EndExceptionBlock(); // The end of the method. If no exception was thrown, the correct value // will be saved in tmp1. If an exception was thrown, tmp1 will be equal // to -1. Either way, we'll load the value of tmp1 onto the stack and return. // il.MarkLabel(endOfMthd); il.Ldloc(tmp1); il.Ret(); Console.WriteLine(il.GetILCode()); } }