public void GetDynamicILInfo_Unique() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(string), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); DynamicILInfo il2 = dm.GetDynamicILInfo(); Assert.IsTrue(Object.ReferenceEquals(il, il2)); }
public void GetDynamicILInfo_NotSameNotNull(bool skipVisibility) { DynamicMethod method = GetDynamicMethod(skipVisibility); DynamicILInfo dynamicILInfo = method.GetDynamicILInfo(); Assert.NotNull(dynamicILInfo); Assert.Equal(dynamicILInfo, method.GetDynamicILInfo()); Assert.Equal(method, dynamicILInfo.DynamicMethod); }
public void GetTokenFor_String_Success() { DynamicMethod dynamicMethod = new DynamicMethod(nameof(HelloWorld), typeof(string), new Type[] { }, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(string), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x72, 0x01, 0x00, 0x00, 0x70, 0x6f, 0x04, 0x00, 0x00, 0x0a, 0x0a, 0x2b, 0x00, 0x06, 0x2a }; int token0 = dynamicILInfo.GetTokenFor("hello, world"); int token1 = dynamicILInfo.GetTokenFor(typeof(string).GetMethod("ToUpper", Type.EmptyTypes).MethodHandle); PutInteger4(token0, 0x0002, code); PutInteger4(token1, 0x0007, code); dynamicILInfo.SetCode(code, 1); string ret = (string)dynamicMethod.Invoke(null, null); Assert.Equal(ret, HelloWorld()); }
public void GetDynamicMethod() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(string), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); Assert.AreEqual(dm, il.DynamicMethod); }
/// <summary> /// Compiles a DynamicMethodState and returns a delegate. /// </summary> /// <typeparam name="R">The return type of the expression</typeparam> /// <typeparam name="C">The type of the function class</typeparam> /// <param name="methodState">The serialized version of a method on the functionClass</param> /// <returns>ExecuteExpression<R, C> - a delegate that calls the compiled expression</returns> public ExecuteExpression <R, C> CreateExpressionDelegate <R, C>(DynamicMethodState methodState) { //create a dynamic method var dynamicMethod = new DynamicMethod("_" + Guid.NewGuid().ToString("N"), typeof(R), new[] { typeof(C) }, typeof(C)); //get the IL writer for it DynamicILInfo dynamicInfo = dynamicMethod.GetDynamicILInfo(); //set the properties gathered from the compiled expression dynamicMethod.InitLocals = methodState.InitLocals; //set local variables SignatureHelper locals = SignatureHelper.GetLocalVarSigHelper(); foreach (int localIndex in methodState.LocalVariables.Keys) { LocalVariable localVar = methodState.LocalVariables[localIndex]; locals.AddArgument(Type.GetTypeFromHandle(localVar.LocalType), localVar.IsPinned); } dynamicInfo.SetLocalSignature(locals.GetSignature()); //resolve any metadata tokens var tokenResolver = new IlTokenResolver(methodState.TokenOffset.Fields, methodState.TokenOffset.Methods, methodState.TokenOffset.Types, methodState.TokenOffset.LiteralStrings); methodState.CodeBytes = tokenResolver.ResolveCodeTokens(methodState.CodeBytes, dynamicInfo); //set the IL code for the dynamic method dynamicInfo.SetCode(methodState.CodeBytes, methodState.MaxStackSize); //create a delegate for fast execution var expressionDelegate = (ExecuteExpression <R, C>)dynamicMethod.CreateDelegate(typeof(ExecuteExpression <R, C>)); return(expressionDelegate); }
public void GetTokenFor_DynamicMethod_Success() { // Calling DynamicMethod recursively DynamicMethod dynamicMethod = new DynamicMethod(nameof(Fib), typeof(long), new Type[] { typeof(long) }, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(long), false); sigHelper.AddArgument(typeof(bool), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x02, 0x16, 0x6a, 0x2e, 0x0a, 0x02, 0x17, 0x6a, 0xfe, 0x01, 0x16, 0xfe, 0x01, 0x2b, 0x01, 0x16, 0x0b, 0x07, 0x2d, 0x04, 0x02, 0x0a, 0x2b, 0x16, 0x02, 0x17, 0x6a, 0x59, 0x28, 0x02, 0x00, 0x00, 0x06, 0x02, 0x18, 0x6a, 0x59, 0x28, 0x02, 0x00, 0x00, 0x06, 0x58, 0x0a, 0x2b, 0x00, 0x06, 0x2a }; int token0 = dynamicILInfo.GetTokenFor(dynamicMethod); PutInteger4(token0, 0x001e, code); PutInteger4(token0, 0x0027, code); dynamicILInfo.SetCode(code, 3); long ret = (long)dynamicMethod.Invoke(null, new object[] { 20 }); Assert.Equal(ret, Fib(20)); }
public static DynamicMethod ConvertFrom(MethodInfo method) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new InvalidOperationException("the method is expected to be static"); } if (method.IsGenericMethod) { throw new InvalidOperationException("currently dynamic method cannot be generic"); } var body = method.GetMethodBody(); if (body == null) { throw new InvalidOperationException("the method does not have method body"); } var dm = new DynamicMethod(method.Name, method.ReturnType, GetParameterTypes(method), typeof(DynamicMethodHelper)); var ilInfo = dm.GetDynamicILInfo(); SetLocalSignature(body, ilInfo); SetCode(method, body, ilInfo); SetExceptions(body, ilInfo); return(dm); }
public void GetTokenFor_StringGenerics_Success() { DynamicMethod dynamicMethod = new DynamicMethod(nameof(ContactString), typeof(string), Type.EmptyTypes, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(MyList <string>), false); sigHelper.AddArgument(typeof(string), false); sigHelper.AddArgument(typeof(string), false); sigHelper.AddArgument(typeof(string), false); sigHelper.AddArgument(typeof(System.Collections.Generic.IEnumerator <string>), false); sigHelper.AddArgument(typeof(bool), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x73, 0x26, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x72, 0x29, 0x01, 0x00, 0x70, 0x6f, 0x27, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x72, 0x37, 0x01, 0x00, 0x70, 0x6f, 0x27, 0x00, 0x00, 0x0a, 0x00, 0x7e, 0x28, 0x00, 0x00, 0x0a, 0x0b, 0x00, 0x06, 0x6f, 0x29, 0x00, 0x00, 0x0a, 0x13, 0x04, 0x2b, 0x12, 0x11, 0x04, 0x6f, 0x2a, 0x00, 0x00, 0x0a, 0x0c, 0x00, 0x07, 0x08, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0b, 0x00, 0x11, 0x04, 0x6f, 0x20, 0x00, 0x00, 0x0a, 0x13, 0x05, 0x11, 0x05, 0x2d, 0xe1, 0xde, 0x14, 0x11, 0x04, 0x14, 0xfe, 0x01, 0x13, 0x05, 0x11, 0x05, 0x2d, 0x08, 0x11, 0x04, 0x6f, 0x21, 0x00, 0x00, 0x0a, 0x00, 0xdc, 0x00, 0x07, 0x0d, 0x2b, 0x00, 0x09, 0x2a }; int token0 = dynamicILInfo.GetTokenFor(typeof(MyList <string>).GetConstructor(Type.EmptyTypes).MethodHandle, typeof(MyList <string>).TypeHandle); int token1 = dynamicILInfo.GetTokenFor("Hello~"); int token2 = dynamicILInfo.GetTokenFor(typeof(MyList <string>).GetMethod("Add").MethodHandle, typeof(MyList <string>).TypeHandle); int token3 = dynamicILInfo.GetTokenFor("World!"); int token4 = dynamicILInfo.GetTokenFor(typeof(string).GetField("Empty").FieldHandle); int token5 = dynamicILInfo.GetTokenFor(typeof(MyList <string>).GetMethod("GetEnumerator").MethodHandle, typeof(MyList <string>).TypeHandle); int token6 = dynamicILInfo.GetTokenFor(typeof(System.Collections.Generic.IEnumerator <string>).GetMethod("get_Current").MethodHandle, typeof(System.Collections.Generic.IEnumerator <string>).TypeHandle); int token7 = dynamicILInfo.GetTokenFor(typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }).MethodHandle); int token8 = dynamicILInfo.GetTokenFor(typeof(System.Collections.IEnumerator).GetMethod("MoveNext").MethodHandle); int token9 = dynamicILInfo.GetTokenFor(typeof(System.IDisposable).GetMethod("Dispose").MethodHandle); PutInteger4(token0, 0x0002, code); PutInteger4(token1, 0x0009, code); PutInteger4(token2, 0x000e, code); PutInteger4(token3, 0x0015, code); PutInteger4(token2, 0x001a, code); PutInteger4(token4, 0x0020, code); PutInteger4(token5, 0x0028, code); PutInteger4(token6, 0x0033, code); PutInteger4(token7, 0x003c, code); PutInteger4(token8, 0x0045, code); PutInteger4(token9, 0x005f, code); dynamicILInfo.SetCode(code, 2); byte[] exceptions = { 0x41, 0x1c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; dynamicILInfo.SetExceptions(exceptions); string ret = (string)dynamicMethod.Invoke(null, null); Assert.Equal(ret, ContactString()); }
[Test] // bug #13969 public void GetTokenFor_Constructor() { var m = typeof(object).GetConstructor(Type.EmptyTypes); var dm = new DynamicMethod("Foo", typeof(void), Type.EmptyTypes); var dil = dm.GetDynamicILInfo(); dil.GetTokenFor(m.MethodHandle); }
public unsafe void SetX_NullInput_ThrowsArgumentNullException(bool skipVisibility) { DynamicMethod method = GetDynamicMethod(skipVisibility); DynamicILInfo dynamicILInfo = method.GetDynamicILInfo(); Assert.Throws <ArgumentNullException>(() => dynamicILInfo.SetCode(null, 1, 8)); Assert.Throws <ArgumentNullException>(() => dynamicILInfo.SetExceptions(null, 1)); Assert.Throws <ArgumentNullException>(() => dynamicILInfo.SetLocalSignature(null, 1)); }
public void GetTokenFor_Exception_Success() { DynamicMethod dynamicMethod = new DynamicMethod(nameof(ExceptionTest), typeof(int), Type.EmptyTypes, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(string), false); sigHelper.AddArgument(typeof(int), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x16, 0x0a, 0x00, 0x00, 0x16, 0x0b, 0x17, 0x07, 0x5b, 0x0c, 0x00, 0xde, 0x09, 0x26, 0x00, 0x06, 0x17, 0x58, 0x0a, 0x00, 0xde, 0x00, 0x00, 0x00, 0x72, 0xed, 0x01, 0x00, 0x70, 0x17, 0x28, 0x32, 0x00, 0x00, 0x0a, 0x26, 0x00, 0xde, 0x09, 0x26, 0x00, 0x06, 0x17, 0x58, 0x0a, 0x00, 0xde, 0x00, 0x00, 0x14, 0x0d, 0x09, 0x6f, 0x05, 0x00, 0x00, 0x0a, 0x26, 0x00, 0xde, 0x09, 0x26, 0x00, 0x06, 0x17, 0x58, 0x0a, 0x00, 0xde, 0x00, 0x00, 0xde, 0x07, 0x00, 0x06, 0x18, 0x58, 0x0a, 0x00, 0xdc, 0x00, 0x06, 0x13, 0x04, 0x2b, 0x00, 0x11, 0x04, 0x2a }; int token0 = dynamicILInfo.GetTokenFor("A.B"); int token1 = dynamicILInfo.GetTokenFor(typeof(System.Type).GetMethod("GetType", new Type[] { typeof(string), typeof(bool) }).MethodHandle); int token2 = dynamicILInfo.GetTokenFor(typeof(string).GetMethod("ToUpper", Type.EmptyTypes).MethodHandle); PutInteger4(token0, 0x001a, code); PutInteger4(token1, 0x0020, code); PutInteger4(token2, 0x0036, code); dynamicILInfo.SetCode(code, 2); int token3 = dynamicILInfo.GetTokenFor(typeof(System.Object).TypeHandle); int token4 = dynamicILInfo.GetTokenFor(typeof(System.Exception).TypeHandle); int token5 = dynamicILInfo.GetTokenFor(typeof(System.NullReferenceException).TypeHandle); byte[] exceptions = { 0x41, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; PutInteger4(token3, 0x0018, exceptions); PutInteger4(token4, 0x0030, exceptions); PutInteger4(token5, 0x0048, exceptions); dynamicILInfo.SetExceptions(exceptions); int ret = (int)dynamicMethod.Invoke(null, null); Assert.Equal(ret, ExceptionTest()); }
public void GetTokenFor_IntGenerics_Success() { DynamicMethod dynamicMethod = new DynamicMethod(nameof(SumInteger), typeof(int), new Type[] { }, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(MyList <int>), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(System.Collections.Generic.IEnumerator <int>), false); sigHelper.AddArgument(typeof(bool), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x73, 0x1c, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x1f, 0x64, 0x6f, 0x1d, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x20, 0xc8, 0x00, 0x00, 0x00, 0x6f, 0x1d, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x20, 0x2c, 0x01, 0x00, 0x00, 0x6f, 0x1d, 0x00, 0x00, 0x0a, 0x00, 0x16, 0x0b, 0x00, 0x06, 0x6f, 0x1e, 0x00, 0x00, 0x0a, 0x13, 0x04, 0x2b, 0x0e, 0x11, 0x04, 0x6f, 0x1f, 0x00, 0x00, 0x0a, 0x0c, 0x00, 0x07, 0x08, 0x58, 0x0b, 0x00, 0x11, 0x04, 0x6f, 0x20, 0x00, 0x00, 0x0a, 0x13, 0x05, 0x11, 0x05, 0x2d, 0xe5, 0xde, 0x14, 0x11, 0x04, 0x14, 0xfe, 0x01, 0x13, 0x05, 0x11, 0x05, 0x2d, 0x08, 0x11, 0x04, 0x6f, 0x21, 0x00, 0x00, 0x0a, 0x00, 0xdc, 0x00, 0x07, 0x0d, 0x2b, 0x00, 0x09, 0x2a }; int token0 = dynamicILInfo.GetTokenFor(typeof(MyList <int>).GetConstructors()[0].MethodHandle, typeof(MyList <int>).TypeHandle); int token1 = dynamicILInfo.GetTokenFor(typeof(MyList <int>).GetMethod("Add").MethodHandle, typeof(MyList <int>).TypeHandle); int token2 = dynamicILInfo.GetTokenFor(typeof(MyList <int>).GetMethod("GetEnumerator").MethodHandle, typeof(MyList <int>).TypeHandle); int token3 = dynamicILInfo.GetTokenFor(typeof(System.Collections.Generic.IEnumerator <int>).GetMethod("get_Current").MethodHandle, typeof(System.Collections.Generic.IEnumerator <int>).TypeHandle); int token4 = dynamicILInfo.GetTokenFor(typeof(System.Collections.IEnumerator).GetMethod("MoveNext").MethodHandle); int token5 = dynamicILInfo.GetTokenFor(typeof(System.IDisposable).GetMethod("Dispose").MethodHandle); PutInteger4(token0, 0x0002, code); PutInteger4(token1, 0x000b, code); PutInteger4(token1, 0x0017, code); PutInteger4(token1, 0x0023, code); PutInteger4(token2, 0x002d, code); PutInteger4(token3, 0x0038, code); PutInteger4(token4, 0x0046, code); PutInteger4(token5, 0x0060, code); dynamicILInfo.SetCode(code, 2); byte[] exceptions = { 0x41, 0x1c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; dynamicILInfo.SetExceptions(exceptions); int ret = (int)dynamicMethod.Invoke(null, null); Assert.Equal(ret, SumInteger()); }
internal static void _EmitCallSite(DynamicMethod dm, ILGenerator il, System.Reflection.Emit.OpCode opcode, CallSite csite) { /* The mess in this method is heavily based off of the code available at the following links: * https://github.com/Microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/mscorlib/system/reflection/emit/dynamicmethod.cs#L791 * https://github.com/Microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/mscorlib/system/reflection/emit/dynamicilgenerator.cs#L353 * https://github.com/mono/mono/blob/82e573122a55482bf6592f36f819597238628385/mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs#L411 * https://github.com/mono/mono/blob/82e573122a55482bf6592f36f819597238628385/mcs/class/corlib/System.Reflection.Emit/ILGenerator.cs#L800 * https://github.com/dotnet/coreclr/blob/0fbd855e38bc3ec269479b5f6bf561dcfd67cbb6/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs#L57 */ List<object> _tokens = null; int _GetTokenForType(Type v) { _tokens.Add(v.TypeHandle); return _tokens.Count - 1 | 0x02000000 /* (int) MetadataTokenType.TypeDef */; } int _GetTokenForSig(byte[] v) { _tokens.Add(v); return _tokens.Count - 1 | 0x11000000 /* (int) MetadataTokenType.Signature */; } #if !NETSTANDARD DynamicILInfo _info = null; if (DynamicMethodDefinition._IsMono) { // GetDynamicILInfo throws "invalid signature" in .NET - let's hope for the best for mono... _info = dm.GetDynamicILInfo(); } else { #endif // For .NET, we need to access DynamicScope m_scope and its List<object> m_tokens _tokens = f_DynScope_m_tokens.GetValue(f_DynILGen_m_scope.GetValue(il)) as List<object>; #if !NETSTANDARD } int GetTokenForType(Type v) => _info != null ? _info.GetTokenFor(v.TypeHandle) : _GetTokenForType(v); int GetTokenForSig(byte[] v) => _info != null ? _info.GetTokenFor(v) : _GetTokenForSig(v); #else int GetTokenForType(Type v) => _GetTokenForType(v); int GetTokenForSig(byte[] v) => _GetTokenForSig(v); #endif byte[] signature = new byte[32]; int currSig = 0; int sizeLoc = -1; // This expects a MdSigCallingConvention AddData((byte) csite.CallingConvention); sizeLoc = currSig++; List<Type> modReq = new List<Type>(); List<Type> modOpt = new List<Type>(); ResolveWithModifiers(csite.ReturnType, out Type returnType, out Type[] returnTypeModReq, out Type[] returnTypeModOpt, modReq, modOpt);
public void Test_TwoDimTest() { // 2-D array (set/address/get) DynamicMethod dynamicMethod = new DynamicMethod(nameof(TwoDimTest), typeof(int), Type.EmptyTypes, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(System.Int32[, ]), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(bool), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x1c, 0x0a, 0x1e, 0x0b, 0x06, 0x07, 0x73, 0x3e, 0x00, 0x00, 0x0a, 0x0c, 0x16, 0x0d, 0x2b, 0x27, 0x16, 0x13, 0x04, 0x2b, 0x13, 0x08, 0x09, 0x11, 0x04, 0x09, 0x11, 0x04, 0x5a, 0x28, 0x3f, 0x00, 0x00, 0x0a, 0x11, 0x04, 0x17, 0x58, 0x13, 0x04, 0x11, 0x04, 0x07, 0xfe, 0x04, 0x13, 0x06, 0x11, 0x06, 0x2d, 0xe2, 0x09, 0x17, 0x58, 0x0d, 0x09, 0x06, 0xfe, 0x04, 0x13, 0x06, 0x11, 0x06, 0x2d, 0xcf, 0x17, 0x0d, 0x2b, 0x3c, 0x17, 0x13, 0x04, 0x2b, 0x28, 0x08, 0x09, 0x11, 0x04, 0x28, 0x40, 0x00, 0x00, 0x0a, 0x25, 0x71, 0x1f, 0x00, 0x00, 0x01, 0x08, 0x09, 0x17, 0x59, 0x11, 0x04, 0x17, 0x59, 0x28, 0x41, 0x00, 0x00, 0x0a, 0x58, 0x81, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x04, 0x17, 0x58, 0x13, 0x04, 0x11, 0x04, 0x07, 0xfe, 0x04, 0x13, 0x06, 0x11, 0x06, 0x2d, 0xcd, 0x09, 0x17, 0x58, 0x0d, 0x09, 0x06, 0xfe, 0x04, 0x13, 0x06, 0x11, 0x06, 0x2d, 0xba, 0x08, 0x06, 0x17, 0x59, 0x07, 0x17, 0x59, 0x28, 0x41, 0x00, 0x00, 0x0a, 0x13, 0x05, 0x2b, 0x00, 0x11, 0x05, 0x2a }; int token0 = dynamicILInfo.GetTokenFor(typeof(System.Int32[, ]).GetConstructor(new Type[] { typeof(int), typeof(int) }).MethodHandle); int token1 = dynamicILInfo.GetTokenFor(typeof(System.Int32[, ]).GetMethod("Set").MethodHandle); int token2 = dynamicILInfo.GetTokenFor(typeof(System.Int32[, ]).GetMethod("Address").MethodHandle); int token3 = dynamicILInfo.GetTokenFor(typeof(int).TypeHandle); int token4 = dynamicILInfo.GetTokenFor(typeof(System.Int32[, ]).GetMethod("Get").MethodHandle); PutInteger4(token0, 0x0008, code); PutInteger4(token1, 0x001f, code); PutInteger4(token2, 0x0050, code); PutInteger4(token3, 0x0056, code); PutInteger4(token4, 0x0063, code); PutInteger4(token3, 0x0069, code); PutInteger4(token4, 0x0094, code); dynamicILInfo.SetCode(code, 6); int ret = (int)dynamicMethod.Invoke(null, null); Assert.Equal(ret, TwoDimTest()); }
public void GetTokenFor_DynamicMethod() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(RuntimeMethodHandle), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); byte[] code = { 0x00, 0xd0, 0x01, 0x00, 0x00, 0x70, 0x2a }; int token0 = il.GetTokenFor(dm); PutInteger4(token0, 0x0002, code); il.SetCode(code, 8); var res = dm.Invoke(null, null); Assert.AreEqual(dm.MethodHandle, res); }
public void GetTokenFor_String() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(string), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); byte[] code = { 0x00, 0x72, 0x01, 0x00, 0x00, 0x70, 0x2a }; int token0 = il.GetTokenFor("ABCD"); PutInteger4(token0, 0x0002, code); il.SetCode(code, 8); var res = dm.Invoke(null, null); Assert.AreEqual("ABCD", res); }
public void GetTokenFor_Type() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(Type), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); byte[] code = { 0x00, 0xd0, 0x01, 0x00, 0x00, 0x70, 0x28, 0x04, 0x00, 0x00, 0x0a, 0x00, 0x2a }; int token0 = il.GetTokenFor(typeof(int).TypeHandle); int token1 = il.GetTokenFor(typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }).MethodHandle); PutInteger4(token0, 0x0002, code); PutInteger4(token1, 0x0007, code); il.SetCode(code, 8); var res = dm.Invoke(null, null); Assert.AreEqual(typeof(int), res); }
public void GetTokenFor_FieldInfo() { aField = aField + 1; DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(RuntimeFieldHandle), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); var f = typeof(DynamicILInfoTest).GetField("aField", BindingFlags.Static | BindingFlags.NonPublic).FieldHandle; byte[] code = { 0x00, 0xd0, 0x01, 0x00, 0x00, 0x70, 0x2a }; int token0 = il.GetTokenFor(f); PutInteger4(token0, 0x0002, code); il.SetCode(code, 8); var res = dm.Invoke(null, null); Assert.AreEqual(f, res); }
public void GetTokenFor_Method() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(string), Type.EmptyTypes, typeof(DynamicILInfoTest), false); DynamicILInfo il = dm.GetDynamicILInfo(); // ldstr "ABCD"; call string::ToLower (); ret byte[] code = { 0x00, 0x72, 0x01, 0x00, 0x00, 0x70, 0x28, 0x04, 0x00, 0x00, 0x0a, 0x00, 0x2a }; int token0 = il.GetTokenFor("ABCD"); int token1 = il.GetTokenFor(typeof(string).GetMethod("ToLower", Type.EmptyTypes).MethodHandle); PutInteger4(token0, 0x0002, code); PutInteger4(token1, 0x0007, code); il.SetCode(code, 8); var res = dm.Invoke(null, null); Assert.AreEqual("abcd", res); }
public unsafe void SetX_NegativeInputSize_ThrowsArgumentOutOfRangeException(bool skipVisibility) { DynamicMethod method = GetDynamicMethod(skipVisibility); DynamicILInfo dynamicILInfo = method.GetDynamicILInfo(); var bytes = new byte[] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *bytesPtr = bytes) { dynamicILInfo.SetCode(bytesPtr, -1, 8); } }); Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *bytesPtr = bytes) { dynamicILInfo.SetExceptions(bytesPtr, -1); } }); Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *bytesPtr = bytes) { dynamicILInfo.SetLocalSignature(bytesPtr, -1); } }); }
public ExecuteExpression <T> CreateExpressionDelegate <T>(DynamicMethodState methodState, object functionClass) { ExecuteExpression <T> expressionDelegate; Stopwatch stopWatch = new Stopwatch(); Trace.WriteLine("Dynamic dll creation - " + stopWatch.ElapsedMilliseconds.ToString()); stopWatch = new Stopwatch(); stopWatch.Start(); //create DynamicMethod dynamicMethod = new DynamicMethod("", typeof(T), new Type[] { functionClass.GetType() }, functionClass.GetType()); DynamicILInfo dynamicInfo = dynamicMethod.GetDynamicILInfo(); dynamicMethod.InitLocals = methodState.InitLocals; SignatureHelper locals = SignatureHelper.GetLocalVarSigHelper(); foreach (int localIndex in methodState.LocalVariables.Keys) { LocalVariable localVar = methodState.LocalVariables[localIndex]; locals.AddArgument(localVar.LocalType, localVar.IsPinned); } dynamicInfo.SetLocalSignature(locals.GetSignature()); IlTokenResolver tokenResolver = new IlTokenResolver(methodState.TokenOffset.Fields, methodState.TokenOffset.Methods, methodState.TokenOffset.Members, methodState.TokenOffset.Types, methodState.TokenOffset.LiteralStrings); methodState.CodeBytes = tokenResolver.ResolveCodeTokens(methodState.CodeBytes, dynamicInfo); dynamicInfo.SetCode(methodState.CodeBytes, methodState.MaxStackSize); expressionDelegate = (ExecuteExpression <T>)dynamicMethod.CreateDelegate(typeof(ExecuteExpression <T>), functionClass); stopWatch.Stop(); Trace.WriteLine("Dynamic Method Creation - " + stopWatch.ElapsedMilliseconds.ToString()); return(expressionDelegate); }
public static void Run() { // IL code to execute byte[] code = { 0, // IL_0000: nop 27, // IL_0001: ldc.i4.5 10, // IL_0002: stloc.0 31, // IL_0003: ldc.i4.s 10 10, // IL_0004: 10 11, // IL_0005: stloc.1 6, // IL_0006: ldloc.0 7, // IL_0007: ldloc.1 88, // IL_0008: add 12, // IL_0009: stloc.2 43, // IL_000a: br.s 0, // IL_000b: 0 8, // IL_000c: ldloc.2 42 // IL_000d: ret }; // the code above is equal to the following method body // int a = 5; // int c = 10; // return a+c; var dynamicMethod = new DynamicMethod("", typeof(int), new Type[0]); var ilInfo = dynamicMethod.GetDynamicILInfo(); // local variables signature helper var signatureHelper = SignatureHelper.GetLocalVarSigHelper(); signatureHelper.AddArgument(typeof(int)); // 1st local variable a signatureHelper.AddArgument(typeof(int)); // 2nd local variable c signatureHelper.AddArgument(typeof(int)); // 3rd local variable - result of {a+c} // assembly dynamic info setup ilInfo.SetCode(code, 2); // minimal stack size for this code is 2 ilInfo.SetLocalSignature(signatureHelper.GetSignature()); // create delegate var dynamicDelegate = (Func <int>)dynamicMethod.CreateDelegate(typeof(Func <int>)); var result = dynamicDelegate(); Debug.Assert(result == 20); // result should be 15 }
public void GetTokenFor_CtorMethodAndField_Success() { DynamicMethod dynamicMethod = new DynamicMethod(nameof(Mock), typeof(Person), new Type[] { }, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(Person), false); sigHelper.AddArgument(typeof(Person), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x72, 0x49, 0x00, 0x00, 0x70, 0x1f, 0x32, 0x22, 0x00, 0x60, 0xea, 0x46, 0x73, 0x0f, 0x00, 0x00, 0x06, 0x0a, 0x06, 0x72, 0x53, 0x00, 0x00, 0x70, 0x7d, 0x04, 0x00, 0x00, 0x04, 0x06, 0x25, 0x6f, 0x0c, 0x00, 0x00, 0x06, 0x17, 0x58, 0x6f, 0x0d, 0x00, 0x00, 0x06, 0x00, 0x06, 0x22, 0x00, 0x00, 0x96, 0x43, 0x6f, 0x10, 0x00, 0x00, 0x06, 0x00, 0x06, 0x0b, 0x2b, 0x00, 0x07, 0x2a }; int token0 = dynamicILInfo.GetTokenFor("Bill"); int token1 = dynamicILInfo.GetTokenFor(typeof(Person).GetConstructor(new Type[] { typeof(string), typeof(int), typeof(float) }).MethodHandle); int token2 = dynamicILInfo.GetTokenFor("Bill Gates"); int token3 = dynamicILInfo.GetTokenFor(typeof(Person).GetField("m_name").FieldHandle); int token4 = dynamicILInfo.GetTokenFor(typeof(Person).GetMethod("get_Age").MethodHandle); int token5 = dynamicILInfo.GetTokenFor(typeof(Person).GetMethod("set_Age").MethodHandle); int token6 = dynamicILInfo.GetTokenFor(typeof(Person).GetMethod("IncSalary").MethodHandle); PutInteger4(token0, 0x0002, code); PutInteger4(token1, 0x000e, code); PutInteger4(token2, 0x0015, code); PutInteger4(token3, 0x001a, code); PutInteger4(token4, 0x0021, code); PutInteger4(token5, 0x0028, code); PutInteger4(token6, 0x0034, code); dynamicILInfo.SetCode(code, 4); Person ret = (Person)dynamicMethod.Invoke(null, null); Assert.Equal(ret, Mock()); }
static void HelloFromDynamicILInfo() { DynamicMethod dm = new DynamicMethod("HelloWorld", typeof(void), Type.EmptyTypes, typeof(Foo), false); DynamicILInfo il = dm.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); il.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { /* ldstr */ 0x72, 0x00, 0x00, 0x00, 0x00, /* call */ 0x28, 0x00, 0x00, 0x00, 0x00, /* ret */ 0x2a }; byte[] strTokenBytes = BitConverter.GetBytes(il.GetTokenFor("Hello world!")); var writeLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); byte[] mTokenBytes = BitConverter.GetBytes(il.GetTokenFor(writeLine.MethodHandle)); Array.Copy(strTokenBytes, 0, code, 1, strTokenBytes.Length); Array.Copy(mTokenBytes, 0, code, 5, mTokenBytes.Length); il.SetCode(code, 3); var hello = (Action)dm.CreateDelegate(typeof(Action)); }
private static bool _checkIfDynamicILInfoFullyImplemented() { try { var dynamicMethod = new DynamicMethod("_", typeof(void), Array.Empty <Type>(), typeof(RuntimeDispatch)); var dynamicILInfo = dynamicMethod.GetDynamicILInfo(); // Should support getting tokens for methods on generic types var genericTypeMethod = typeof(Tuple <int, int>).GetProperty(nameof(Tuple <int, int> .Item1)).GetMethod; dynamicILInfo.GetTokenFor(genericTypeMethod.MethodHandle, genericTypeMethod.DeclaringType.TypeHandle); // Should support getting tokens for fields on generic types var genericTypeField = typeof(ValueTuple <int, int>).GetField(nameof(ValueTuple <int, int> .Item1)); dynamicILInfo.GetTokenFor(genericTypeField.FieldHandle, genericTypeField.DeclaringType.TypeHandle); // Should support SetLocalSignature dynamicILInfo.SetLocalSignature(new byte[] { 7, 0 }); return(true); } catch (NotImplementedException) { return(false); } }
public void Test_CallGM() { // GenericMethod inside GenericType DynamicMethod dynamicMethod = new DynamicMethod(nameof(CallGM), typeof(string), Type.EmptyTypes, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(string), false); sigHelper.AddArgument(typeof(G <int>), false); sigHelper.AddArgument(typeof(G <string>), false); sigHelper.AddArgument(typeof(G <System.Type>), false); sigHelper.AddArgument(typeof(string), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x14, 0x0a, 0x73, 0x42, 0x00, 0x00, 0x0a, 0x0b, 0x06, 0x07, 0x1f, 0x64, 0x6f, 0x09, 0x00, 0x00, 0x2b, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x07, 0x72, 0x5f, 0x03, 0x00, 0x70, 0x6f, 0x0a, 0x00, 0x00, 0x2b, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0a, 0x73, 0x44, 0x00, 0x00, 0x0a, 0x0c, 0x06, 0x08, 0x1f, 0x64, 0x6f, 0x0b, 0x00, 0x00, 0x2b, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x08, 0x72, 0x95, 0x02, 0x00, 0x70, 0x6f, 0x0c, 0x00, 0x00, 0x2b, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0a, 0x73, 0x46, 0x00, 0x00, 0x0a, 0x0d, 0x06, 0x09, 0x1f, 0x64, 0x6a, 0x6f, 0x0d, 0x00, 0x00, 0x2b, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x09, 0x73, 0x2c, 0x00, 0x00, 0x0a, 0x6f, 0x0e, 0x00, 0x00, 0x2b, 0x28, 0x2b, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x13, 0x04, 0x2b, 0x00, 0x11, 0x04, 0x2a }; int token0 = dynamicILInfo.GetTokenFor(typeof(G <int>).GetConstructor(Type.EmptyTypes).MethodHandle, typeof(G <int>).TypeHandle); int token1 = dynamicILInfo.GetTokenFor(typeof(G <int>).GetMethod("M").MakeGenericMethod(typeof(int)).MethodHandle, typeof(G <int>).TypeHandle); int token2 = dynamicILInfo.GetTokenFor(typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }).MethodHandle); int token3 = dynamicILInfo.GetTokenFor("hello"); int token4 = dynamicILInfo.GetTokenFor(typeof(G <int>).GetMethod("M").MakeGenericMethod(typeof(string)).MethodHandle, typeof(G <int>).TypeHandle); int token5 = dynamicILInfo.GetTokenFor(typeof(G <string>).GetConstructor(Type.EmptyTypes).MethodHandle, typeof(G <string>).TypeHandle); int token6 = dynamicILInfo.GetTokenFor(typeof(G <string>).GetMethod("M").MakeGenericMethod(typeof(int)).MethodHandle, typeof(G <string>).TypeHandle); int token7 = dynamicILInfo.GetTokenFor("world"); int token8 = dynamicILInfo.GetTokenFor(typeof(G <string>).GetMethod("M").MakeGenericMethod(typeof(string)).MethodHandle, typeof(G <string>).TypeHandle); int token9 = dynamicILInfo.GetTokenFor(typeof(G <System.Type>).GetConstructor(Type.EmptyTypes).MethodHandle, typeof(G <System.Type>).TypeHandle); int token10 = dynamicILInfo.GetTokenFor(typeof(G <System.Type>).GetMethod("M").MakeGenericMethod(typeof(long)).MethodHandle, typeof(G <System.Type>).TypeHandle); int token11 = dynamicILInfo.GetTokenFor(typeof(System.Object).GetConstructor(Type.EmptyTypes).MethodHandle); int token12 = dynamicILInfo.GetTokenFor(typeof(G <System.Type>).GetMethod("M").MakeGenericMethod(typeof(System.Object)).MethodHandle, typeof(G <System.Type>).TypeHandle); PutInteger4(token0, 0x0004, code); PutInteger4(token1, 0x000e, code); PutInteger4(token2, 0x0013, code); PutInteger4(token3, 0x001b, code); PutInteger4(token4, 0x0020, code); PutInteger4(token2, 0x0025, code); PutInteger4(token5, 0x002b, code); PutInteger4(token6, 0x0035, code); PutInteger4(token2, 0x003a, code); PutInteger4(token7, 0x0042, code); PutInteger4(token8, 0x0047, code); PutInteger4(token2, 0x004c, code); PutInteger4(token9, 0x0052, code); PutInteger4(token10, 0x005d, code); PutInteger4(token2, 0x0062, code); PutInteger4(token11, 0x006a, code); PutInteger4(token12, 0x006f, code); PutInteger4(token2, 0x0074, code); dynamicILInfo.SetCode(code, 3); string ret = (string)dynamicMethod.Invoke(null, null); Assert.Equal(ret, CallGM()); }
// Token: 0x060000FB RID: 251 RVA: 0x0000A864 File Offset: 0x00008A64 internal static void c10af80cdad4c9dbe717681a9cd86af7a(int caf80c5c2bc19055f4eb1069181edd5e4, int c6b0ef7a04772650ed28a3de279ed2ed9, int cabf1aeb6e91698f7db067652c7916847) { Type typeFromHandle; MethodBase methodBase; try { typeFromHandle = Type.GetTypeFromHandle(c112201421a408a8f2963cee12a5d2e69.c5b2cbb035f512aa824f5593dd0096224.ResolveTypeHandle(caf80c5c2bc19055f4eb1069181edd5e4)); object methodFromHandle = MethodBase.GetMethodFromHandle(c112201421a408a8f2963cee12a5d2e69.c5b2cbb035f512aa824f5593dd0096224.ResolveMethodHandle(c6b0ef7a04772650ed28a3de279ed2ed9), c112201421a408a8f2963cee12a5d2e69.c5b2cbb035f512aa824f5593dd0096224.ResolveTypeHandle(cabf1aeb6e91698f7db067652c7916847)); methodBase = c19240ce50a3f99cf68eac460a5f219eb.cd24593c859565ebb8c9faabbc5c75bef(methodFromHandle); } catch (Exception) { throw; } FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField); for (int i = 0; i < (int)ca6d7950a54c7ffb24dd0caad95a2614f.cfeb04651f165d0166e7c10ab1acf8b28(fields); i++) { FieldInfo fieldInfo = fields[i]; try { DynamicMethod dynamicMethod = c1bb66ba0941923c66aa96bbf66e7ba95.cab55a050df275722227783d6686266c9; MethodBody methodBody = methodBase.GetMethodBody(); Type[] parameterTypes = c112201421a408a8f2963cee12a5d2e69.c66499b087455255e2b006f8a7688f7b1(methodBase); string name = c009279a45243b14127222aa793e3eb2e.c8d9bd1b5f903cbc3ebfaf48b8b440c7a(methodBase.DeclaringType.FullName, ".", methodBase.Name, "_Encrypted$"); Type returnType; if (c0d90fcf706c7ee22fef7d88368977990.c0b398ab350e72b0d64d512bae8520b85(methodBase) == null) { for (;;) { switch (3) { case 0: continue; } break; } if (!true) { RuntimeMethodHandle runtimeMethodHandle = methodof(c112201421a408a8f2963cee12a5d2e69.c10af80cdad4c9dbe717681a9cd86af7a(int, int, int)).MethodHandle; } returnType = c2616c42177f749f99e07d405c040207f.cd24593c859565ebb8c9faabbc5c75bef(methodBase).ReturnType; } else { returnType = null; } dynamicMethod = new DynamicMethod(name, returnType, parameterTypes, methodBase.DeclaringType, true); int num; c112201421a408a8f2963cee12a5d2e69.c38c4c8069b226b1e8dc3975f03305f77.TryGetValue(caf80c5c2bc19055f4eb1069181edd5e4, out num); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); c112201421a408a8f2963cee12a5d2e69.c9caeb49525e24fdeaf8f5bc58177b94e(methodBody, dynamicILInfo); c112201421a408a8f2963cee12a5d2e69.c792380fd21eca6e08b9631600cc2d331(ref num, methodBase, dynamicILInfo); c112201421a408a8f2963cee12a5d2e69.c8619f80da50369e47fcfd41a1f31ff9b(ref num, dynamicILInfo); Delegate value = dynamicMethod.CreateDelegate(typeFromHandle); fieldInfo.SetValue(null, value); } catch (Exception) { } } for (;;) { switch (2) { case 0: continue; } break; } }
internal static void EmitCallSite(DynamicMethod dm, ILGenerator il, System.Reflection.Emit.OpCode opcode, CallSite csite) { /* The mess in this method is heavily based off of the code available at the following links: * https://github.com/Microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/mscorlib/system/reflection/emit/dynamicmethod.cs#L791 * https://github.com/Microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/mscorlib/system/reflection/emit/dynamicilgenerator.cs#L353 * https://github.com/mono/mono/blob/82e573122a55482bf6592f36f819597238628385/mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs#L411 * https://github.com/mono/mono/blob/82e573122a55482bf6592f36f819597238628385/mcs/class/corlib/System.Reflection.Emit/ILGenerator.cs#L800 * https://github.com/dotnet/coreclr/blob/0fbd855e38bc3ec269479b5f6bf561dcfd67cbb6/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs#L57 */ List<object> _tokens = null; int _GetTokenForType(Type v) { _tokens.Add(v.TypeHandle); return _tokens.Count - 1 | 0x02000000 /* (int) MetadataTokenType.TypeDef */; } int _GetTokenForSig(byte[] v) { _tokens.Add(v); return _tokens.Count - 1 | 0x11000000 /* (int) MetadataTokenType.Signature */; } #if !NETSTANDARD DynamicILInfo _info = null; if (Type.GetType("Mono.Runtime") != null) { // GetDynamicILInfo throws "invalid signature" in .NET - let's hope for the best for mono... _info = dm.GetDynamicILInfo(); } else { #endif // For .NET, we need to access DynamicScope m_scope and its List<object> m_tokens _tokens = f_DynScope_m_tokens.GetValue(f_DynILGen_m_scope.GetValue(il)) as List<object>; #if !NETSTANDARD } int GetTokenForType(Type v) => _info != null ? _info.GetTokenFor(v.TypeHandle) : _GetTokenForType(v); int GetTokenForSig(byte[] v) => _info != null ? _info.GetTokenFor(v) : _GetTokenForSig(v); #else int GetTokenForType(Type v) => _GetTokenForType(v); int GetTokenForSig(byte[] v) => _GetTokenForSig(v); #endif byte[] signature = new byte[32]; int currSig = 0; int sizeLoc = -1; // This expects a MdSigCallingConvention AddData((byte) csite.CallingConvention); sizeLoc = currSig++; List<Type> modReq = new List<Type>(); List<Type> modOpt = new List<Type>(); for ( TypeReference returnTypeRef = csite.ReturnType; returnTypeRef is TypeSpecification returnTypeSpec; returnTypeRef = returnTypeSpec.ElementType ) { switch (returnTypeRef) { case RequiredModifierType paramTypeModReq: modReq.Add(paramTypeModReq.ModifierType.ResolveReflection()); break; case OptionalModifierType paramTypeOptReq: modOpt.Add(paramTypeOptReq.ModifierType.ResolveReflection()); break; } } AddArgument(csite.ReturnType.ResolveReflection(), modReq.ToArray(), modOpt.ToArray()); foreach (ParameterDefinition param in csite.Parameters) { if (param.ParameterType.IsSentinel) AddElementType(0x41 /* CorElementType.Sentinel */); if (param.ParameterType.IsPinned) { AddElementType(0x45 /* CorElementType.Pinned */); // AddArgument(param.ParameterType.ResolveReflection()); // continue; } modOpt.Clear(); modReq.Clear(); for ( TypeReference paramTypeRef = param.ParameterType; paramTypeRef is TypeSpecification paramTypeSpec; paramTypeRef = paramTypeSpec.ElementType ) { switch (paramTypeRef) { case RequiredModifierType paramTypeModReq: modReq.Add(paramTypeModReq.ModifierType.ResolveReflection()); break; case OptionalModifierType paramTypeOptReq: modOpt.Add(paramTypeOptReq.ModifierType.ResolveReflection()); break; } } AddArgument(param.ParameterType.ResolveReflection(), modReq.ToArray(), modOpt.ToArray()); } AddElementType(0x00 /* CorElementType.End */); // For most signatures, this will set the number of elements in a byte which we have reserved for it. // However, if we have a field signature, we don't set the length and return. // If we have a signature with more than 128 arguments, we can't just set the number of elements, // we actually have to allocate more space (e.g. shift everything in the array one or more spaces to the // right. We do this by making a copy of the array and leaving the correct number of blanks. This new // array is now set to be m_signature and we use the AddData method to set the number of elements properly. // The forceCopy argument can be used to force SetNumberOfSignatureElements to make a copy of // the array. This is useful for GetSignature which promises to trim the array to be the correct size anyway. byte[] temp; int newSigSize; int currSigHolder = currSig; // We need to have more bytes for the size. Figure out how many bytes here. // Since we need to copy anyway, we're just going to take the cost of doing a // new allocation. if (csite.Parameters.Count < 0x80) { newSigSize = 1; } else if (csite.Parameters.Count < 0x4000) { newSigSize = 2; } else { newSigSize = 4; } // Allocate the new array. temp = new byte[currSig + newSigSize - 1]; // Copy the calling convention. The calling convention is always just one byte // so we just copy that byte. Then copy the rest of the array, shifting everything // to make room for the new number of elements. temp[0] = signature[0]; Buffer.BlockCopy(signature, sizeLoc + 1, temp, sizeLoc + newSigSize, currSigHolder - (sizeLoc + 1)); signature = temp; //Use the AddData method to add the number of elements appropriately compressed. currSig = sizeLoc; AddData(csite.Parameters.Count); currSig = currSigHolder + (newSigSize - 1); // This case will only happen if the user got the signature through // InternalGetSignature first and then called GetSignature. if (signature.Length > currSig) { temp = new byte[currSig]; Array.Copy(signature, temp, currSig); signature = temp; } // Emit. if (_ILGen_emit_int != null) { // Mono _ILGen_make_room(il, 6); _ILGen_ll_emit(il, opcode); _ILGen_emit_int(il, GetTokenForSig(signature)); } else { // .NET _ILGen_EnsureCapacity(il, 7); _ILGen_InternalEmit(il, opcode); // The only IL instruction that has VarPop behaviour, that takes a // Signature token as a parameter is calli. Pop the parameters and // the native function pointer. To be conservative, do not pop the // this pointer since this information is not easily derived from // SignatureHelper. if (opcode.StackBehaviourPop == System.Reflection.Emit.StackBehaviour.Varpop) { // Pop the arguments and native function pointer off the stack. _ILGen_UpdateStackSize(il, opcode, -csite.Parameters.Count - 1); } _ILGen_PutInteger4(il, GetTokenForSig(signature)); } void AddArgument(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) { if (optionalCustomModifiers != null) foreach (Type t in optionalCustomModifiers) InternalAddTypeToken(GetTokenForType(t), 0x20 /* CorElementType.CModOpt */); if (requiredCustomModifiers != null) foreach (Type t in requiredCustomModifiers) InternalAddTypeToken(GetTokenForType(t), 0x1F /* CorElementType.CModReqd */); AddOneArgTypeHelper(clsArgument); } void AddData(int data) { // A managed representation of CorSigCompressData; if (currSig + 4 > signature.Length) { signature = ExpandArray(signature); } if (data <= 0x7F) { signature[currSig++] = (byte) (data & 0xFF); } else if (data <= 0x3FFF) { signature[currSig++] = (byte) ((data >> 8) | 0x80); signature[currSig++] = (byte) (data & 0xFF); } else if (data <= 0x1FFFFFFF) { signature[currSig++] = (byte) ((data >> 24) | 0xC0); signature[currSig++] = (byte) ((data >> 16) & 0xFF); signature[currSig++] = (byte) ((data >> 8) & 0xFF); signature[currSig++] = (byte) ((data) & 0xFF); } else { throw new ArgumentException("Integer or token was too large to be encoded."); } } byte[] ExpandArray(byte[] inArray, int requiredLength = -1) { if (requiredLength < inArray.Length) requiredLength = inArray.Length * 2; byte[] outArray = new byte[requiredLength]; Buffer.BlockCopy(inArray, 0, outArray, 0, inArray.Length); return outArray; } void AddElementType(byte cvt) { // Adds an element to the signature. A managed represenation of CorSigCompressElement if (currSig + 1 > signature.Length) signature = ExpandArray(signature); signature[currSig++] = cvt; } void AddToken(int token) { // A managed represenation of CompressToken // Pulls the token appart to get a rid, adds some appropriate bits // to the token and then adds this to the signature. int rid = (token & 0x00FFFFFF); //This is RidFromToken; int type = (token & unchecked((int) 0xFF000000)); //This is TypeFromToken; if (rid > 0x3FFFFFF) { // token is too big to be compressed throw new ArgumentException("Integer or token was too large to be encoded."); } rid = (rid << 2); // TypeDef is encoded with low bits 00 // TypeRef is encoded with low bits 01 // TypeSpec is encoded with low bits 10 if (type == 0x01000000 /* MetadataTokenType.TypeRef */) { //if type is mdtTypeRef rid |= 0x1; } else if (type == 0x1b000000 /* MetadataTokenType.TypeSpec */) { //if type is mdtTypeSpec rid |= 0x2; } AddData(rid); } void InternalAddTypeToken(int clsToken, byte CorType) { // Add a type token into signature. CorType will be either CorElementType.Class or CorElementType.ValueType AddElementType(CorType); AddToken(clsToken); } void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); } void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst) { if (clsArgument.GetTypeInfo().IsGenericType && (!clsArgument.GetTypeInfo().IsGenericTypeDefinition || !lastWasGenericInst)) { AddElementType(0x15 /* CorElementType.GenericInst */); AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true); Type[] genargs = clsArgument.GetGenericArguments(); AddData(genargs.Length); foreach (Type t in genargs) AddOneArgTypeHelper(t); } else if (clsArgument.IsByRef) { AddElementType(0x10 /* CorElementType.ByRef */); clsArgument = clsArgument.GetElementType(); AddOneArgTypeHelper(clsArgument); } else if (clsArgument.IsPointer) { AddElementType(0x0F /* CorElementType.Ptr */); AddOneArgTypeHelper(clsArgument.GetElementType()); } else if (clsArgument.IsArray) { #if false if (clsArgument.IsArray && clsArgument == clsArgument.GetElementType().MakeArrayType()) { // .IsSZArray unavailable. AddElementType(0x1D /* CorElementType.SzArray */); AddOneArgTypeHelper(clsArgument.GetElementType()); } else #endif { AddElementType(0x14 /* CorElementType.Array */); AddOneArgTypeHelper(clsArgument.GetElementType()); // put the rank information int rank = clsArgument.GetArrayRank(); AddData(rank); // rank AddData(0); // upper bounds AddData(rank); // lower bound for (int i = 0; i < rank; i++) AddData(0); } } else { // This isn't 100% accurate, but... oh well. byte type = 0; // 0 is reserved anyway. for (int i = 0; i < CorElementTypes.Length; i++) { if (clsArgument == CorElementTypes[i]) { type = (byte) i; break; } } if (type == 0) { if (clsArgument == typeof(object)) { type = 0x1C /* CorElementType.Object */; } else if (clsArgument.GetTypeInfo().IsValueType) { type = 0x11 /* CorElementType.ValueType */; } else { // Let's hope for the best. type = 0x12 /* CorElementType.Class */; } } if (type <= 0x0E /* CorElementType.String */ || type == 0x16 /* CorElementType.TypedByRef */ || type == 0x18 /* CorElementType.I */ || type == 0x19 /* CorElementType.U */ || type == 0x1C /* CorElementType.Object */ ) { AddElementType(type); } else if (clsArgument.GetTypeInfo().IsValueType) { InternalAddTypeToken(GetTokenForType(clsArgument), 0x11 /* CorElementType.ValueType */); } else { InternalAddTypeToken(GetTokenForType(clsArgument), 0x12 /* CorElementType.Class */); } } } }
public void Test_GenericMethod() { DynamicMethod dynamicMethod = new DynamicMethod(nameof(GenericMethod), typeof(bool), Type.EmptyTypes, typeof(DynamicILInfoTests), false); DynamicILInfo dynamicILInfo = dynamicMethod.GetDynamicILInfo(); SignatureHelper sigHelper = SignatureHelper.GetLocalVarSigHelper(); sigHelper.AddArgument(typeof(System.Int32[]), false); sigHelper.AddArgument(typeof(int), false); sigHelper.AddArgument(typeof(System.String[]), false); sigHelper.AddArgument(typeof(string), false); sigHelper.AddArgument(typeof(bool), false); sigHelper.AddArgument(typeof(System.String[]), false); dynamicILInfo.SetLocalSignature(sigHelper.GetSignature()); byte[] code = { 0x00, 0x1c, 0x8d, 0x1f, 0x00, 0x00, 0x01, 0x0a, 0x06, 0x16, 0x18, 0x9e, 0x06, 0x17, 0x1f, 0x09, 0x9e, 0x06, 0x18, 0x15, 0x9e, 0x06, 0x19, 0x1f, 0x0e, 0x9e, 0x06, 0x1a, 0x19, 0x9e, 0x06, 0x1b, 0x1f, 0x37, 0x9e, 0x06, 0x14, 0xfe, 0x06, 0x12, 0x00, 0x00, 0x06, 0x73, 0x3a, 0x00, 0x00, 0x0a, 0x28, 0x06, 0x00, 0x00, 0x2b, 0x0b, 0x1b, 0x8d, 0x0e, 0x00, 0x00, 0x01, 0x13, 0x05, 0x11, 0x05, 0x16, 0x72, 0x85, 0x02, 0x00, 0x70, 0xa2, 0x11, 0x05, 0x17, 0x72, 0x91, 0x02, 0x00, 0x70, 0xa2, 0x11, 0x05, 0x18, 0x72, 0x95, 0x02, 0x00, 0x70, 0xa2, 0x11, 0x05, 0x19, 0x72, 0xa1, 0x02, 0x00, 0x70, 0xa2, 0x11, 0x05, 0x1a, 0x72, 0xbd, 0x02, 0x00, 0x70, 0xa2, 0x11, 0x05, 0x0c, 0x08, 0x73, 0x18, 0x00, 0x00, 0x06, 0xfe, 0x06, 0x13, 0x00, 0x00, 0x06, 0x73, 0x3b, 0x00, 0x00, 0x0a, 0x28, 0x07, 0x00, 0x00, 0x2b, 0x0d, 0x07, 0x06, 0x19, 0x94, 0x33, 0x0b, 0x09, 0x08, 0x19, 0x9a, 0x28, 0x3c, 0x00, 0x00, 0x0a, 0x2b, 0x01, 0x16, 0x13, 0x04, 0x2b, 0x00, 0x11, 0x04, 0x2a }; int token0 = dynamicILInfo.GetTokenFor(typeof(int).TypeHandle); int token1 = dynamicILInfo.GetTokenFor(typeof(DynamicILInfoTests).GetMethod("MyRule", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle); int token2 = dynamicILInfo.GetTokenFor(typeof(Satisfy <int>).GetConstructor(new Type[] { typeof(System.Object), typeof(System.IntPtr) }).MethodHandle, typeof(Satisfy <int>).TypeHandle); int token3 = dynamicILInfo.GetTokenFor(typeof(Finder).GetMethod("Find").MakeGenericMethod(typeof(int)).MethodHandle); int token4 = dynamicILInfo.GetTokenFor(typeof(string).TypeHandle); int token5 = dynamicILInfo.GetTokenFor("Hello"); int token6 = dynamicILInfo.GetTokenFor("1"); int token7 = dynamicILInfo.GetTokenFor("world"); int token8 = dynamicILInfo.GetTokenFor("dynamicmethod"); int token9 = dynamicILInfo.GetTokenFor("find it already"); int token10 = dynamicILInfo.GetTokenFor(typeof(DynamicILInfoTests).GetConstructor(Type.EmptyTypes).MethodHandle); int token11 = dynamicILInfo.GetTokenFor(typeof(DynamicILInfoTests).GetMethod("MyRule", BindingFlags.NonPublic | BindingFlags.Instance).MethodHandle); int token12 = dynamicILInfo.GetTokenFor(typeof(Satisfy <string>).GetConstructor(new Type[] { typeof(System.Object), typeof(System.IntPtr) }).MethodHandle, typeof(Satisfy <string>).TypeHandle); int token13 = dynamicILInfo.GetTokenFor(typeof(Finder).GetMethod("Find").MakeGenericMethod(typeof(string)).MethodHandle); int token14 = dynamicILInfo.GetTokenFor(typeof(string).GetMethod("op_Equality").MethodHandle); PutInteger4(token0, 0x0003, code); PutInteger4(token1, 0x0027, code); PutInteger4(token2, 0x002c, code); PutInteger4(token3, 0x0031, code); PutInteger4(token4, 0x0038, code); PutInteger4(token5, 0x0042, code); PutInteger4(token6, 0x004b, code); PutInteger4(token7, 0x0054, code); PutInteger4(token8, 0x005d, code); PutInteger4(token9, 0x0066, code); PutInteger4(token10, 0x0070, code); PutInteger4(token11, 0x0076, code); PutInteger4(token12, 0x007b, code); PutInteger4(token13, 0x0080, code); PutInteger4(token14, 0x0090, code); dynamicILInfo.SetCode(code, 4); bool ret = (bool)dynamicMethod.Invoke(null, null); Assert.Equal(ret, GenericMethod()); }