private void TestSuccess(Type type1, Type type2) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { type1, type2, }.Where(type => type != null).ToArray(), typeof(string), true); using (var il = new GroboIL(method)) { var index = 0; if (type1 != null) { il.Ldarg(index++); } else { il.Ldnull(); } if (type2 != null) { il.Ldarg(index++); } else { il.Ldnull(); } il.Xor(); il.Pop(); il.Ret(); Console.WriteLine(il.GetILCode()); } }
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> >)))()); }
public static TryGetValueDelegate <T> Build <T>(string[] keys, T[] values, Func <string, int> hashCodeEvaluator) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(Closure <T>), typeof(string), typeof(T).MakeByRefType() }, typeof(string), true); var hashCodes = keys.Select(hashCodeEvaluator).ToArray(); int n = keys.Length; var indexes = new int[n]; for (int i = 0; i < n; ++i) { indexes[i] = i; } Array.Sort(indexes, (lhs, rhs) => hashCodes[lhs].CompareTo(hashCodes[rhs])); using (var il = new GroboIL(method)) { var retFalseLabel = il.DefineLabel("retFalse"); var hashCode = il.DeclareLocal(typeof(int), "hashCode"); il.Ldarg(0); // stack: [closure] il.Ldfld(HackHelpers.GetField <Closure <T> >(x => x.hashCodeEvaluator)); // stack: [closure.hashCodeEvaluator] il.Ldarg(1); // stack: [closure.hashCodeEvaluator, key] il.Call(typeof(Func <string, int>).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public)); // stack: [closure.hashCodeEvaluator(key)] il.Stloc(hashCode); // hashCode = closure.hashCodeEvaluator(key); stack: [] var context = new EmittingContext { Il = il, Keys = keys, HashCodes = hashCodes, Indexes = indexes, HashCode = hashCode, RetFalseLabel = retFalseLabel }; DoBinarySearch <T>(context, 0, n - 1); il.MarkLabel(retFalseLabel); il.Ldarg(2); // stack: [ref value] if (typeof(T).IsValueType) { il.Initobj(typeof(T)); // value = default(T); stack: [] } else { il.Ldnull(); // stack: [ref value, null] il.Stind(typeof(T)); // value = null; stack: [] } il.Ldc_I4(0); // stack: [false] il.Ret(); } var closure = new Closure <T> { hashCodeEvaluator = hashCodeEvaluator, values = values }; return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), closure)); }
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(); } }
private static Func <Type, bool> BuildIsATypeBuilderInstChecker() { var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(Type) }, typeof(ReflectionExtensions), true); using (var il = new GroboIL(dynamicMethod)) { il.Ldarg(0); il.Isinst(typeBuilderInstType); il.Ldnull(); il.Cgt(true); il.Ret(); } return((Func <Type, bool>)dynamicMethod.CreateDelegate(typeof(Func <Type, bool>))); }
private void TestFailure(Type type1, Type type2) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { type1, type2, }.Where(type => type != null).ToArray(), typeof(string), true); var il = new GroboIL(method); var index = 0; if (type1 != null) { il.Ldarg(index++); } else { il.Ldnull(); } if (type2 != null) { il.Ldarg(index++); } else { il.Ldnull(); } Assert.Throws <InvalidOperationException>(il.Xor); }
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 static void WriteObjectNull(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local typeSize) { var _null = il.DeclareLocal(typeof(bool)); il.Ldnull(); il.Ceq(); il.Stloc(_null); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(_null); il.Stelem(typeof(byte)); WriteOffsetAppend(il, offset, 1); il.Ldloc(_null); il.Brtrue(finishMethod); }
private static void BuildJump(TypeBuilder typeBuilder, int n, Context context) { var method = typeBuilder.DefineMethod("Jump", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(MethodCallNode), new[] { typeof(int) }); using (var il = new GroboIL(method)) { var retNullLabel = il.DefineLabel("retNull"); var emittingContext = new MethodJumpEmittingContext { context = context, il = il, retNullLabel = retNullLabel }; DoBinarySearch(emittingContext, 0, n - 1); il.MarkLabel(retNullLabel); il.Ldnull(); il.Ret(); } typeBuilder.DefineMethodOverride(method, typeof(MethodCallNodeEdges).GetMethod(method.Name, BindingFlags.Public | BindingFlags.Instance)); }
public static TryGetValueDelegate <T> Build <T>(char[] keys, T[] values) { // Assuming keys are sorted var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(T[]), typeof(char), typeof(T).MakeByRefType() }, typeof(string), true); //var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("zzz"), AssemblyBuilderAccess.RunAndSave); //var module = assembly.DefineDynamicModule("qxx", "zzz.dll"); //var typeBuilder = module.DefineType("Zzz", TypeAttributes.Class | TypeAttributes.Public); //var method = typeBuilder.DefineMethod("do_switch", MethodAttributes.Public | MethodAttributes.Static, // typeof(bool), new[] {typeof(T[]), typeof(char), typeof(T).MakeByRefType()}); int n = keys.Length; using (var il = new GroboIL(method)) { var retFalseLabel = il.DefineLabel("retFalse"); var context = new EmittingContext { Il = il, Keys = keys, RetFalseLabel = retFalseLabel }; DoBinarySearch <T>(context, 0, n - 1); il.MarkLabel(retFalseLabel); il.Ldarg(2); // stack: [ref value] if (typeof(T).IsValueType) { il.Initobj(typeof(T)); // value = default(T); stack: [] } else { il.Ldnull(); // stack: [ref value, null] il.Stind(typeof(T)); // value = null; stack: [] } il.Ldc_I4(0); // stack: [false] il.Ret(); } //typeBuilder.CreateType(); //assembly.Save("zzz.dll"); //return null; return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), values)); }
public static TryGetValueDelegate <T> Build <T>(string[] keys, T[] values) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(T[]), typeof(string), typeof(T).MakeByRefType() }, typeof(string), true); using (var il = new GroboIL(method)) { for (int i = 0; i < keys.Length; ++i) { il.Ldarg(1); // stack: [key] il.Ldstr(keys[i]); // stack: [key, keys[i]] var nextKeyLabel = il.DefineLabel("nextKey"); il.Call(stringEqualityOperator); // stack: [key == keys[i]] il.Brfalse(nextKeyLabel); // if(key != keys[i]) goto nextKey; stack: [] il.Ldarg(2); // stack: [ref value] il.Ldarg(0); // stack: [ref value, values] il.Ldc_I4(i); // stack: [ref value, values, i] il.Ldelem(typeof(T)); // stack: [ref value, values[i]] il.Stind(typeof(T)); // value = values[i]; stack: [] il.Ldc_I4(1); // stack: [true] il.Ret(); il.MarkLabel(nextKeyLabel); } il.Ldarg(2); // stack: [ref value] if (typeof(T).IsValueType) { il.Initobj(typeof(T)); // value = default(T); stack: [] } else { il.Ldnull(); // stack: [ref value, null] il.Stind(typeof(T)); // value = null; stack: [] } il.Ldc_I4(0); // stack: [false] il.Ret(); } return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), values)); }
private static EnumParserDelegate EmitEnumParser() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(Type), typeof(string), typeof(bool) }, typeof(string), true); var il = new GroboIL(method); var enumResultType = typeof(Enum).GetNestedType("EnumResult", BindingFlags.NonPublic); var enumResult = il.DeclareLocal(enumResultType); il.Ldarg(0); il.Ldarg(1); il.Ldarg(2); il.Ldloca(enumResult); il.Call(typeof(Enum).GetMethod("TryParseEnum", BindingFlags.Static | BindingFlags.NonPublic)); var returnNullLabel = il.DefineLabel("returnNull"); il.Brfalse(returnNullLabel); il.Ldloca(enumResult); il.Ldfld(enumResultType.GetField("parsedEnum", BindingFlags.Instance | BindingFlags.NonPublic)); il.Ret(); il.MarkLabel(returnNullLabel); il.Ldnull(); il.Ret(); return((EnumParserDelegate)method.CreateDelegate(typeof(EnumParserDelegate))); }
private static Type BuildTypeInternal(Type type) { var parentType = typeof(ValidationResultTreeNode); var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); var typeBuilder = module.DefineType(type.Name + "_" + id++, TypeAttributes.Class | TypeAttributes.Public, parentType); typesBeingBuilt[type] = typeBuilder; var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { parentType }); using (var il = new GroboIL(constructor)) { il.Ldarg(0); // stack: [this] il.Ldarg(1); // stack: [this, parent] var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { parentType }, null); il.Call(baseConstructor); // base(parent); stack: [] il.Ret(); } var fields = new Dictionary <string, FieldBuilder>(); foreach (var property in properties) { var propertyType = property.PropertyType; Type fieldType; if (propertyType.IsArray) { fieldType = typeof(ValidationResultTreeArrayNode <>).MakeGenericType(BuildType(propertyType.GetElementType())); } else if (propertyType.IsDictionary() || propertyType == typeof(Hashtable)) { fieldType = typeof(ValidationResultTreeUniversalNode); } else { fieldType = BuildType(propertyType, true); } var field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Public); fields.Add(property.Name, field); } var getChildrenMethod = parentType.GetMethod("GetChildren", BindingFlags.Instance | BindingFlags.NonPublic); var getChildrenMethodBuilder = typeBuilder.DefineMethod(getChildrenMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(IEnumerable <KeyValuePair <object, ValidationResultTreeNode> >), Type.EmptyTypes); using (var il = new GroboIL(getChildrenMethodBuilder)) { var listType = typeof(List <KeyValuePair <object, ValidationResultTreeNode> >); var addMethod = listType.GetMethod("Add", new[] { typeof(KeyValuePair <object, ValidationResultTreeNode>) }); var itemConstructor = typeof(KeyValuePair <object, ValidationResultTreeNode>).GetConstructor(new[] { typeof(object), parentType }); var list = il.DeclareLocal(listType); il.Newobj(listType.GetConstructor(Type.EmptyTypes)); // stack: [new List<>()] il.Stloc(list); // list = new List<>(); stack: [] foreach (var field in fields.Values) { il.Ldarg(0); // stack: [this] il.Ldfld(field); // stack: [this.field] var nextLabel = il.DefineLabel("next"); il.Brfalse(nextLabel); // if(this.field == null) goto next; stack: [] il.Ldloc(list); // stack: [list] il.Ldstr(field.Name); // stack: [list, field.Name] il.Ldarg(0); // stack: [list, field.Name, this] il.Ldfld(field); // stack: [list, field.Name, this.field] il.Newobj(itemConstructor); // stack: [list, new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)] il.Call(addMethod); // list.Add(new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)); stack: [] il.MarkLabel(nextLabel); } il.Ldloc(list); il.Ret(); } typeBuilder.DefineMethodOverride(getChildrenMethodBuilder, getChildrenMethod); var traverseEdgeMethod = parentType.GetMethod("TraverseEdge", BindingFlags.Instance | BindingFlags.NonPublic); var traverseEdgeMethodBuilder = typeBuilder.DefineMethod(traverseEdgeMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, parentType, new[] { typeof(Expression) }); using (var il = new GroboIL(traverseEdgeMethodBuilder)) { il.Ldarg(1); // stack: [edge] il.Castclass(typeof(MemberExpression)); // stack: [(MemberExpression)edge] il.Call(HackHelpers.GetProp <MemberExpression>(x => x.Member).GetGetMethod()); // stack: [((MemberExpresion)edge).Member] il.Call(HackHelpers.GetProp <MemberInfo>(x => x.Name).GetGetMethod()); // stack: [((MemberExpresion)edge).Member.Name] var member = il.DeclareLocal(typeof(string)); il.Stloc(member); foreach (var property in properties) { il.Ldstr(property.Name); // stack: [property.Name] il.Ldloc(member); // stack: [property.Name, member] il.Call(typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public)); var nextLabel = il.DefineLabel("next"); il.Brfalse(nextLabel); // if(property.Name != member) goto next; stack: [] il.Ldarg(0); // stack: [this] il.Ldfld(fields[property.Name]); // stack: [this.field] il.Ret(); // return this.field; il.MarkLabel(nextLabel); } il.Ldnull(); il.Ret(); } typeBuilder.DefineMethodOverride(traverseEdgeMethodBuilder, traverseEdgeMethod); var result = typeBuilder.CreateTypeInfo(); typesBeingBuilt[type] = null; return(result); }
public static TryGetValueDelegate <T> Build <T>(char[] keys, T[] values, int numberOfSegments, int numberOfKeysPerSegment) { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(Closure <T>), typeof(char), typeof(T).MakeByRefType() }, typeof(string), true); var indices = new List <int>(); using (var il = new GroboIL(method)) { var idx = il.DeclareLocal(typeof(int), "idx"); var retFalseLabel = il.DefineLabel("retFalse"); for (int i = 0; i < numberOfSegments; ++i) { var firstKeyInSegment = keys[i * numberOfKeysPerSegment]; var lastKeyInSegment = keys[numberOfKeysPerSegment - 1 + i * numberOfKeysPerSegment]; il.Ldarg(1); // stack: [key] il.Ldc_I4(firstKeyInSegment); // stack: [key, firstKey] var nextSegmentLabel = il.DefineLabel("nextSegment"); il.Blt(nextSegmentLabel, false); // if(key < firstKey) goto nextSegment; stack: [] il.Ldarg(1); // stack: [key] il.Ldc_I4(lastKeyInSegment); // stack: [key, lastKey] il.Bgt(nextSegmentLabel, false); // if(key > lastKey) goto nextSegment; stack: [] il.Ldarg(0); // stack: [closure] il.Ldfld(HackHelpers.GetField <Closure <T> >(x => x.indices)); // stack: [closure.indices] il.Ldarg(1); // stack: [closure.indices, key] il.Ldc_I4(firstKeyInSegment - indices.Count); // stack: [closure.indices, key, diff] il.Sub(); // stack: [closure.indices, key - diff] il.Ldelem(typeof(int)); // stack: [closure.indices[key - diff]] il.Dup(); il.Stloc(idx); // idx = closure.indices[key - diff]; stack: [idx] il.Ldc_I4(0); // stack: [idx, 0] il.Blt(retFalseLabel, false); // if(idx < 0) goto retFalse; stack: [] il.Ldarg(2); // stack: [ref value] il.Ldarg(0); // stack: [ref value, closure] il.Ldfld(HackHelpers.GetField <Closure <T> >(x => x.values)); // stack: [ref value, closure.values] il.Ldloc(idx); // stack: [ref value, closure.values, idx] il.Ldelem(typeof(T)); // stack: [ref value, closure.values[idx]] il.Stind(typeof(T)); // value = closure.values[idx]; stack: [] il.Ldc_I4(1); // stack: [true] il.Ret(); il.MarkLabel(nextSegmentLabel); var segmentLength = lastKeyInSegment - firstKeyInSegment + 1; int start = indices.Count; for (int j = 0; j < segmentLength; ++j) { indices.Add(-1); } for (int j = 0; j < numberOfKeysPerSegment; ++j) { indices[start + keys[i * numberOfKeysPerSegment + j] - firstKeyInSegment] = i * numberOfKeysPerSegment + j; } } il.MarkLabel(retFalseLabel); il.Ldarg(2); // stack: [ref value] if (typeof(T).IsValueType) { il.Initobj(typeof(T)); // value = default(T); stack: [] } else { il.Ldnull(); // stack: [ref value, null] il.Stind(typeof(T)); // value = null; stack: [] } il.Ldc_I4(0); // stack: [false] il.Ret(); } var closure = new Closure <T> { indices = indices.ToArray(), values = values }; return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), closure)); }
public static TryGetValueDelegate <T> Build <T>(char[] keys, T[] values, int numberOfSegments, int numberOfKeysPerSegment) { // Assuming keys are sorted var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(Closure <T>), typeof(char), typeof(T).MakeByRefType() }, typeof(string), true); var indices = new List <int>(); using (var il = new GroboIL(method)) { var idx = il.DeclareLocal(typeof(int), "idx"); var retFalseLabel = il.DefineLabel("retFalse"); var segments = new Segment[numberOfSegments]; for (int i = 0; i < numberOfSegments; ++i) { var firstKeyInSegment = keys[i * numberOfKeysPerSegment]; var lastKeyInSegment = keys[numberOfKeysPerSegment - 1 + i * numberOfKeysPerSegment]; segments[i] = new Segment { FirstKey = firstKeyInSegment, LastKey = lastKeyInSegment, Diff = firstKeyInSegment - indices.Count }; var segmentLength = lastKeyInSegment - firstKeyInSegment + 1; int start = indices.Count; for (int j = 0; j < segmentLength; ++j) { indices.Add(-1); } for (int j = 0; j < numberOfKeysPerSegment; ++j) { indices[start + keys[i * numberOfKeysPerSegment + j] - firstKeyInSegment] = i * numberOfKeysPerSegment + j; } } var context = new EmittingContext { Il = il, Segments = segments, RetFalseLabel = retFalseLabel, Idx = idx }; DoBinarySearch <T>(context, 0, numberOfSegments - 1); il.MarkLabel(retFalseLabel); il.Ldarg(2); // stack: [ref value] if (typeof(T).IsValueType) { il.Initobj(typeof(T)); // value = default(T); stack: [] } else { il.Ldnull(); // stack: [ref value, null] il.Stind(typeof(T)); // value = null; stack: [] } il.Ldc_I4(0); // stack: [false] il.Ret(); } var closure = new Closure <T> { indices = indices.ToArray(), values = values }; return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), closure)); }