public void TestDifferentPathsGeneric() { var assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()), AssemblyBuilderAccess.Run); var module = assembly.DefineDynamicModule(Guid.NewGuid().ToString()); var type = module.DefineType("Zzz", TypeAttributes.Class | TypeAttributes.Public); var method = type.DefineMethod("Qzz", MethodAttributes.Public | MethodAttributes.Static); var genericParameters = method.DefineGenericParameters("TZzz"); var parameter = genericParameters[0]; method.SetParameters(typeof(bool), typeof(C1 <>).MakeGenericType(parameter), typeof(C2 <>).MakeGenericType(parameter)); method.SetReturnType(typeof(void)); using (var il = new GroboIL(method)) { il.Ldarg(0); var label1 = il.DefineLabel("L1"); il.Brfalse(label1); il.Ldarg(1); var label2 = il.DefineLabel("L2"); il.Br(label2); il.MarkLabel(label1); il.Ldarg(2); il.MarkLabel(label2); il.Dup(); il.Call(HackHelpers.GetMethodDefinition <I1 <int> >(x => F1(x)).GetGenericMethodDefinition().MakeGenericMethod(parameter)); il.Call(HackHelpers.GetMethodDefinition <I2 <int> >(x => F2(x)).GetGenericMethodDefinition().MakeGenericMethod(parameter)); il.Ret(); Console.Write(il.GetILCode()); } }
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 r = il.DeclareLocal(typeof(TimeSpan)); var v = il.DeclareLocal(typeof(double)); il.Ldloc(buffer); il.Ldloc(offset); il.Call(readBitConverterMethodInfo); il.Stloc(v); il.Ldloc(v); il.Call(timeSpanConstructor); if (listValue) { il.Stloc(result); } else { il.Stloc(r); } BinaryStruct.WriteOffsetAppend(il, offset, 8); if (!listValue) { il.Ldloc(result); il.Ldloc(r); il.Call(prop.Setter, isVirtual: true); } }
public void GetWriteILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local value, GroboIL.Local typeSize, GroboIL.Local buffer, GroboIL.Local offset, bool listValue) { BinaryStruct.WriteSizeChecker(il, buffer, offset, 2); var arr = il.DeclareLocal(typeof(byte[])); il.Ldloc(value); if (!listValue) { il.Call(prop.Getter); } il.Dup(); il.Pop(); il.Call(writeBitConverterMethodInfo); il.Stloc(arr); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(arr); il.Ldc_I4(0); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); for (int i = 1; i < 2; i++) { il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(i); il.Add(); il.Ldloc(arr); il.Ldc_I4(i); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); } BinaryStruct.WriteOffsetAppend(il, offset, 2); }
public void GetWriteILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local value, GroboIL.Local typeSize, GroboIL.Local buffer, GroboIL.Local offset, bool listValue) { BinaryStruct.WriteSizeChecker(il, buffer, offset, 8); var arr = il.DeclareLocal(typeof(byte[])); var v = il.DeclareLocal(typeof(DateTime)); var t = il.DeclareLocal(typeof(TimeSpan)); if (!listValue) { il.Ldloc(value); var v1 = il.DeclareLocal(typeof(DateTime)); il.Call(prop.Getter); il.Stloc(v1); il.Ldloca(v1); } else { il.Ldloca(value); } il.Ldloca(v); il.Ldc_I4(1970); il.Ldc_I4(1); il.Ldc_I4(1); il.Ldc_I4(0); il.Ldc_I4(0); il.Ldc_I4(0); il.Ldc_I4(0); il.Call(datetimeConstructor); il.Ldloc(v); il.Call(substractMethod); il.Stloc(t); il.Ldloca(t); il.Call(propertyGetter); il.Call(writeBitConverterMethodInfo); il.Stloc(arr); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(arr); il.Ldc_I4(0); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); for (int i = 1; i < 8; i++) { il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(i); il.Add(); il.Ldloc(arr); il.Ldc_I4(i); il.Ldelem(typeof(byte)); il.Stelem(typeof(byte)); } BinaryStruct.WriteOffsetAppend(il, offset, 8); }
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 void EmitBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse) { // a.Property == b.Property il.Ldarg(0); il.Call(getMethod); il.Ldarg(1); il.Call(getMethod); il.Bne_Un(returnFalse); }
private static void EmitStatic(GroboIL il, MethodInfo getMethod, MethodInfo staticMethod, GroboIL.Label returnFalse) { // Equals(a.Property, b.Property) il.Ldarg(0); il.Call(getMethod); il.Ldarg(1); il.Call(getMethod); il.Call(staticMethod); il.Brfalse(returnFalse); }
public void BuildSizeCounter(SizeCounterBuilderContext sizeCounterBuilderContext) { var method = new DynamicMethod("Count_" + Type.Name + "_" + Guid.NewGuid(), typeof(int), new[] { Type, typeof(bool), typeof(WriterContext) }, sizeCounterBuilderContext.Module, true); sizeCounterBuilderContext.SetSizeCounterMethod(Type, method); using (var il = new GroboIL(method)) { var context = new SizeCounterMethodBuilderContext(sizeCounterBuilderContext, il); var notEmptyLabel = il.DefineLabel("notEmpty"); if (CheckEmpty(context, notEmptyLabel)) // Check if obj is empty { context.ReturnForNull(); // return for null } il.MarkLabel(notEmptyLabel); // Now we know that obj is not empty if (!Type.IsValueType && IsReference && sizeCounterBuilderContext.GroBufWriter.Options.HasFlag(GroBufOptions.PackReferences)) { // Pack reference var index = il.DeclareLocal(typeof(int)); context.LoadContext(); // stack: [context] il.Dup(); // stack: [context, context] il.Ldfld(WriterContext.IndexField); // stack: [context, context.index] il.Stloc(index); // index = context.index; stack: [context] il.Ldfld(WriterContext.ObjectsField); // stack: [context.objects] context.LoadObj(); // stack: [context.objects, obj] il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.ContainsKey(null))); // stack: [context.object.ContainsKey(obj)] var storeLocationLabel = il.DefineLabel("storeLocation"); il.Brfalse(storeLocationLabel); // if(!context.objects.ContainsKey(obj)) goto storeLocation; stack: [] context.LoadContext(); // stack: [context] il.Dup(); // stack: [context, context] il.Ldfld(WriterContext.ReferencesField); // stack: [context, context.references] il.Ldc_I4(1); // stack: [context, context.references, 1] il.Add(); // stack: [context, context.references + 1] il.Stfld(WriterContext.ReferencesField); // context.references += 1; stack: [] il.Ldc_I4(5); // stack: [5] il.Ret(); // return 5 il.MarkLabel(storeLocationLabel); context.LoadContext(); // stack: [context] il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance)); // stack: [context.objects] context.LoadObj(); // stack: [context.objects, obj] il.Ldloc(index); // stack: [context.objects, obj, index] il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.Add(null, 0))); // context.objects.Add(obj, index); } CountSizeNotEmpty(context); // Count size il.Ret(); } var @delegate = method.CreateDelegate(typeof(SizeCounterDelegate <>).MakeGenericType(Type)); var pointer = GroBufHelpers.ExtractDynamicMethodPointer(method); sizeCounterBuilderContext.SetSizeCounterPointer(Type, pointer, @delegate); }
private void ProcessFuncParameter(ParameterInfo parameterInfo, GroboIL il, Type parameterType) { if (parameterInfo.Name.StartsWith("get", StringComparison.InvariantCultureIgnoreCase)) { il.Call(funcHelper.GetBuildGetFuncMethodInfo(parameterType)); } else if (parameterInfo.Name.StartsWith("create", StringComparison.InvariantCultureIgnoreCase)) { il.Call(funcHelper.GetBuildCreateFuncMethodInfo(parameterInfo.ParameterType)); } else { throw new NotSupportedException($"Failed to resolve func parameter {parameterInfo.Name} of type {parameterType}. Func parameter names should have 'get' or 'create' prefix."); } }
private static void EmitInstance(GroboIL il, MethodInfo getMethod, MethodInfo instanceMethod, GroboIL.Label returnFalse) { // a.Property.Equals(b.Property) 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.Call(instanceMethod, type); il.Brfalse(returnFalse); }
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 r = il.DeclareLocal(typeof(sbyte)); il.Ldloc(buffer); il.Ldloc(offset); il.Ldelem(typeof(byte)); if (listValue) { il.Stloc(result); } else { il.Stloc(r); } BinaryStruct.WriteOffsetAppend(il, offset, 1); if (!listValue) { il.Ldloc(result); il.Ldloc(r); il.Call(prop.Setter, isVirtual: true); } }
public static TryGetValueDelegate <T> Build <T>(string[] keys, T[] values) { var trie = BuildTrie(keys); 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)) { il.Ldarg(2); // stack: [ref value] il.Initobj(typeof(T)); // value = default(value); stack: [] var index = il.DeclareLocal(typeof(int), "index"); il.Ldc_I4(0); // stack: [0] il.Stloc(index); // index = 0; stack: [] var length = il.DeclareLocal(typeof(int), "length"); il.Ldarg(1); // stack: [key] il.Call(stringLengthGetter); // stack: [key.Length] il.Stloc(length); // length = key.Length; stack: [] var context = new EmittingContext { Il = il, Index = index, Length = length, CurChar = il.DeclareLocal(typeof(char)) }; InlineTrie <T>(trie, context); } return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), values)); }
private static Delegate BuildInvoker(MethodInfo method) { var parameterTypes = new List <Type>(); if (!method.IsStatic) { parameterTypes.Add(method.ReflectedType); } parameterTypes.AddRange(method.GetParameters().Select(p => p.ParameterType)); var prefix = "MethodInvoker"; if (method.IsStatic) { prefix += "$" + Formatter.Format(method.DeclaringType); } var dynamicMethod = new DynamicMethod(prefix + "$" + method.Name + "$" + Guid.NewGuid(), method.ReturnType, parameterTypes.ToArray(), typeof(MethodInvokerBuilder), true); using (var il = new GroboIL(dynamicMethod)) { for (var i = 0; i < parameterTypes.Count; ++i) { il.Ldarg(i); } il.Call(method); il.Ret(); } return(dynamicMethod.CreateDelegate(Extensions.GetDelegateType(parameterTypes.ToArray(), method.ReturnType))); }
private static Func <object, object, int> EmitCompareDelegate() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(object) }, 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 compareMethod = xsdDateTimeType.GetMethod("Compare", BindingFlags.Static | BindingFlags.Public); if (compareMethod == null) { throw new InvalidOperationException("The method 'XsdDateTime.Compare' is not found"); } using (var il = new GroboIL(method)) { var strongBoxType = typeof(StrongBox <>).MakeGenericType(xsdDateTimeType); var valueField = strongBoxType.GetField("Value", BindingFlags.Instance | BindingFlags.Public); il.Ldarg(0); // stack: [arg0] il.Castclass(strongBoxType); // stack: [(StrongBox<XsdDateTime>)arg0] il.Ldfld(valueField); // stack: [((StrongBox<XsdDateTime>)arg0).Value] il.Ldarg(1); // stack: [((StrongBox<XsdDateTime>)arg0).Value, arg1] il.Castclass(strongBoxType); // stack: [((StrongBox<XsdDateTime>)arg0).Value, (StrongBox<XsdDateTime>)arg1] il.Ldfld(valueField); // stack: [((StrongBox<XsdDateTime>)arg0).Value, ((StrongBox<XsdDateTime>)arg1).Value] il.Call(compareMethod); // stack: [XsdDateTime.CompareTo(((StrongBox<XsdDateTime>)arg0).Value, ((StrongBox<XsdDateTime>)arg1).Value)] il.Ret(); } return((Func <object, object, int>)method.CreateDelegate(typeof(Func <object, object, 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))); }
private ITest BuildDelegate() { var action = Build(); var typeBuilder = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public); var actionField = typeBuilder.DefineField("action", typeof(Action), FieldAttributes.Private | FieldAttributes.InitOnly); var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(Action) }); using (var il = new GroboIL(constructor)) { il.Ldarg(0); il.Ldarg(1); il.Stfld(actionField); il.Ret(); } var method = typeBuilder.DefineMethod("DoNothing", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Ldfld(actionField); il.Call(typeof(Action).GetMethod("Invoke", Type.EmptyTypes), typeof(Action)); il.Ret(); } typeBuilder.DefineMethodOverride(method, typeof(ITest).GetMethod("DoNothing")); typeBuilder.AddInterfaceImplementation(typeof(ITest)); var type = typeBuilder.CreateType(); return((ITest)Activator.CreateInstance(type, new object[] { action.Item1 })); }
private static Func <IntPtr, long, long> EmitRelJmpHooker() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(long), new[] { typeof(IntPtr), typeof(long) }, typeof(string), true); using (var il = new GroboIL(method)) { il.VerificationKind = TypesAssignabilityVerificationKind.LowLevelOnly; var cycleLabel = il.DefineLabel("cycle"); il.MarkLabel(cycleLabel); il.Ldarg(0); // stack: [ptr] il.Dup(); // stack: [ptr, ptr] var x = il.DeclareLocal(typeof(long)); il.Ldind(typeof(long)); // stack: [ptr, *ptr] il.Dup(); il.Stloc(x); // x = *ptr; stack: [ptr, newCode] il.Ldc_I8(unchecked ((long)0xFFFFFF0000000000)); il.And(); // stack: [ptr, x & 0xFFFFFF0000000000] il.Ldarg(1); // stack: [ptr, x & 0xFFFFFF0000000000, code] il.Or(); // stack: [ptr, (x & 0xFFFFFF0000000000) | code] il.Ldloc(x); // stack: [ptr, (x & 0xFFFFFF0000000000) | code, newCode] var methodInfo = typeof(Interlocked).GetMethod("CompareExchange", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(long).MakeByRefType(), typeof(long), typeof(long) }, null); il.Call(methodInfo); // stack: [Interlocked.CompareExchange(ptr, (x & 0xFFFFFF0000000000) | code, newCode)] il.Ldloc(x); // stack: [Interlocked.CompareExchange(ptr, (x & 0xFFFFFF0000000000) | code, newCode), newCode] il.Bne_Un(cycleLabel); // if(Interlocked.CompareExchange(ptr, (x & 0xFFFFFF0000000000) | code, newCode) != newCode) goto cycle; stack: [] il.Ldloc(x); il.Ret(); } return((Func <IntPtr, long, long>)method.CreateDelegate(typeof(Func <IntPtr, long, long>))); }
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); }
private ITest BuildCall() { var typeBuilder = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public); var doNothingMethod = typeBuilder.DefineMethod("DoNothingImpl", MethodAttributes.Public, typeof(void), Type.EmptyTypes); using (var il = new GroboIL(doNothingMethod)) { il.Ldfld(xField); il.Ldc_I4(1); il.Add(); il.Stfld(xField); il.Ret(); } var method = typeBuilder.DefineMethod("DoNothing", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Call(doNothingMethod); il.Ret(); } typeBuilder.DefineMethodOverride(method, typeof(ITest).GetMethod("DoNothing")); typeBuilder.AddInterfaceImplementation(typeof(ITest)); var type = typeBuilder.CreateType(); return((ITest)Activator.CreateInstance(type)); }
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 void TestBrfalse() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { typeof(C2) }, typeof(string), true); using (var il = new GroboIL(method)) { il.Ldarg(0); il.Dup(); var label = il.DefineLabel("L"); il.Brfalse(label); il.Call(HackHelpers.GetMethodDefinition <I1>(x => x.GetI2())); il.MarkLabel(label); il.Call(HackHelpers.GetMethodDefinition <int>(x => F2(null))); il.Ret(); Console.WriteLine(il.GetILCode()); } }
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 r = il.DeclareLocal(typeof(Vector3)); if (listValue) { il.Ldloca(result); } else { il.Ldloca(r); } il.Ldloc(buffer); il.Ldloc(offset); il.Call(readBitConverterMethodInfo); il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(4); il.Add(); il.Call(readBitConverterMethodInfo); il.Ldloc(buffer); il.Ldloc(offset); il.Ldc_I4(8); il.Add(); il.Call(readBitConverterMethodInfo); il.Call(initialConstructor); //if (listValue) // il.Stloc(result); //else // il.Stloc(r); BinaryStruct.WriteOffsetAppend(il, offset, 12); if (!listValue) { il.Ldloc(result); il.Ldloc(r); il.Call(prop.Setter, isVirtual: true); } }
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)); il.Ldloc(buffer); il.Ldloc(offset); il.Call(readBitConverterMethodInfo); il.Stloc(len); BinaryStruct.WriteOffsetAppend(il, offset, 4); if (!listValue) { il.Ldloc(result); il.Ldarg(1); } else { il.Ldloc(binaryStruct); } il.Call(codingMethodInfo); il.Castclass(typeof(UTF8Encoding)); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(len); il.Call(currentStruct.Coding.GetType().GetMethod("GetString", new Type[] { typeof(byte[]), typeof(int), typeof(int) }), isVirtual: true); if (!listValue) { il.Call(prop.Setter); } else { il.Stloc(result); } BinaryStruct.WriteOffsetAppend(il, offset, len); il.MarkLabel(exitLabel); }
private void ProcessFuncParameter(ParameterInfo parameterInfo, GroboIL il, Type parameterType) { if (parameterInfo.Name.StartsWith("get", StringComparison.InvariantCultureIgnoreCase)) { il.Call(funcHelper.GetBuildGetFuncMethodInfo(parameterType)); } else if (parameterInfo.Name.StartsWith("create", StringComparison.InvariantCultureIgnoreCase)) { il.Call(funcHelper.GetBuildCreateFuncMethodInfo(parameterInfo.ParameterType)); } else { throw new NotSupportedException( string.Format( "Невозможно разрешить параметр '{0}' типа {1}. Должен иметь имя с префиксом 'get' или 'create'", parameterInfo.Name, parameterType)); } }
protected override bool EmitInternal(TypeBinaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { bool result; GroboIL il = context.Il; if (!node.Expression.Type.IsAssignableFrom(node.TypeOperand)) { il.Ldc_I4(0); result = false; } else if (node.Expression.Type == node.TypeOperand && node.TypeOperand.IsValueType) { il.Ldc_I4(1); result = false; } else { Type operandType; result = ExpressionEmittersCollection.Emit(node.Expression, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType); if (operandType.IsValueType) { using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldloca(temp); } } var returnFalseLabel = il.DefineLabel("returnFalse"); il.Dup(); il.Brfalse(returnFalseLabel); il.Call(typeof(object).GetMethod("GetType"), operandType); il.Ldtoken(node.TypeOperand); il.Call(typeof(Type).GetMethod("GetTypeFromHandle")); il.Ceq(); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(returnFalseLabel); il.Pop(); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(doneLabel); } resultType = typeof(bool); return(result); }
public void TestCallFormat() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(string), new[] { typeof(string), typeof(decimal), typeof(decimal) }, typeof(string), true); var il = new GroboIL(method); il.Ldarg(0); il.Ldarg(1); il.Ldarg(2); Assert.Throws <InvalidOperationException>(() => il.Call(HackHelpers.GetMethodDefinition <string>(s => string.Format(s, "", "")))); }
public void Test_StaticMethod_NonVoid_NoParameters() { var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), Type.EmptyTypes, typeof(string), true); using (var il = new GroboIL(method)) { il.Call(HackHelpers.GetMethodDefinition <int>(x => NonVoidStaticMethod_NoParameters())); il.Ret(); } }
private Func <string, string> BuildSwitch4() { Init(new[] { "0", "2", "5", "1000001", "7", "1000000" }); var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(string) }, Module, true); using (var il = new GroboIL(dynamicMethod)) { var zzzLabel = il.DefineLabel("zzz"); var qxxLabel = il.DefineLabel("qxx"); var qzzLabel = il.DefineLabel("qzz"); var xxxLabel = il.DefineLabel("xxx"); var index = il.DeclareLocal(typeof(uint)); il.Ldfld(typeof(TestPerformance).GetField("testValues2")); il.Ldarg(0); il.Call(typeof(object).GetMethod("GetHashCode"), typeof(string)); il.Ldc_I4(testValues2.Length); il.Rem(true); il.Stloc(index); il.Ldloc(index); il.Ldelem(typeof(string)); il.Ldarg(0); il.Call(typeof(object).GetMethod("Equals", new[] { typeof(object) }), typeof(string)); il.Brfalse(xxxLabel); il.Ldfld(typeof(TestPerformance).GetField("indexes2")); il.Ldloc(index); il.Ldelem(typeof(int)); il.Switch(zzzLabel, zzzLabel, qxxLabel, qxxLabel, qzzLabel, qzzLabel); il.Br(xxxLabel); il.MarkLabel(zzzLabel); il.Ldstr("zzz"); il.Ret(); il.MarkLabel(qxxLabel); il.Ldstr("qxx"); il.Ret(); il.MarkLabel(qzzLabel); il.Ldstr("qzz"); il.Ret(); il.MarkLabel(xxxLabel); il.Ldstr("xxx"); il.Ret(); } return((Func <string, string>)dynamicMethod.CreateDelegate(typeof(Func <string, string>))); }
public static TTarget WithDefaultParametersPassed <TTarget>(MethodInfo sourceMethod) where TTarget : Delegate { var targetMethod = typeof(TTarget).GetMethod("Invoke"); if (targetMethod.ReturnType != sourceMethod.ReturnType) { throw new ArgumentException("Return must be the same for the source and the target."); } var sourceParameters = sourceMethod.GetParameters(); var targetParameters = targetMethod.GetParameters(); //Fast path for cases where we do not need to create a shim if (!sourceParameters.Any(x => x.HasDefaultValue)) { return((TTarget)Delegate.CreateDelegate(typeof(TTarget), sourceMethod)); } var shim = new DynamicMethod(Guid.NewGuid().ToString(), targetMethod.ReturnType, targetMethod.GetParameters().Select(x => x.ParameterType).ToArray()); using (var il = new GroboIL(shim)) { var j = 0; for (int i = 0; i < sourceParameters.Length; i++) { var sourceParameter = sourceParameters[i]; if (sourceParameter.HasDefaultValue) { EmitDefaultParameterValue(il, sourceParameter); } else { if (targetParameters[j].ParameterType == sourceParameter.ParameterType) { il.Ldarg(j); j++; } else { throw new ArgumentException($"The type of the required source parameter {sourceParameter} does not match that of the target {targetParameters[j]}."); } } } if (j != targetParameters.Length) { throw new ArgumentException("The parameters of target must be exactly the required parameters of source."); } il.Call(sourceMethod); il.Ret(); } return((TTarget)shim.CreateDelegate(typeof(TTarget))); }
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 EmitNullableBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse) { // a.GetValueOrDefault() == b.GetValueOrDefault() && a.HasValue == b.HasValue; var type = getMethod.ReturnType; var getValueOrDefault = type.GetMethod("GetValueOrDefault", new Type[0]); var hasValue = type.GetMethod("get_HasValue"); var a = il.DeclareLocal(type); var b = il.DeclareLocal(type); il.Ldarg(0); il.Call(getMethod); il.Stloc(a); il.Ldarg(1); il.Call(getMethod); il.Stloc(b); il.Ldloca(a); il.Call(getValueOrDefault); il.Ldloca(b); il.Call(getValueOrDefault); il.Bne_Un(returnFalse); il.Ldloca(a); il.Call(hasValue); il.Ldloca(b); il.Call(hasValue); il.Bne_Un(returnFalse); }