コード例 #1
0
        public void RewriteVirtualMethod()
        {
            var methodInfo = typeof(ExampleClassChild).GetMethod(nameof(ExampleClassChild.VirtualTestMethod), BindingFlags.Public | BindingFlags.Instance);
            var context    = new ShimContext();
            var rewrite    = ILRewriter.ILRewriter.Rewrite(methodInfo, context);

            var result = (int)rewrite.Invoke(null, new object[] { new ExampleClassChild(2), 3, context });

            Assert.Equal(12, result);
        }
コード例 #2
0
        public void RewriteStaticMethod()
        {
            var methodInfo = typeof(ExampleClass).GetMethod(nameof(ExampleClass.StaticTestMethod), BindingFlags.Public | BindingFlags.Static);
            var context    = new ShimContext();
            var rewrite    = ILRewriter.ILRewriter.Rewrite(methodInfo, context);

            var result = (int)rewrite.Invoke(null, new object[] { 3, context });

            Assert.Equal(6, result);
        }
コード例 #3
0
        public void RewriteInstanceMethod()
        {
            var methodInfo = typeof(ExampleClass).GetMethod(nameof(ExampleClass.InstanceTestMethod), BindingFlags.Public | BindingFlags.Instance);
            var context    = new ShimContext();
            var rewrite    = ILRewriter.ILRewriter.Rewrite(methodInfo, context);

            //This is not possible with the current generator
            //var result = (int)rewrite.Invoke(new TestClass(2), new object[] { 3, new ShimContext() });

            var result = (int)rewrite.Invoke(null, new object[] { new ExampleClass(2), 3, context });

            Assert.Equal(6, result);
        }
コード例 #4
0
        public void RewriteConstructor()
        {
            var info    = typeof(ExampleClass).GetConstructor(new[] { typeof(int) });
            var context = new ShimContext();
            var rewrite = ILRewriter.ILRewriter.Rewrite(info, context);

            var exampleClass = new ExampleClass(2);

            rewrite.Invoke(null, new object[] { exampleClass, 3, context });
            Assert.Equal(3, exampleClass.Factor);

            info    = typeof(ExampleStruct).GetConstructor(new[] { typeof(int) });
            rewrite = ILRewriter.ILRewriter.Rewrite(info, new ShimContext());
            var dele = (ExampleStructConstructor)rewrite.CreateDelegate(typeof(ExampleStructConstructor));

            var exampleStruct = new ExampleStruct(2);

            dele(ref exampleStruct, 3, context);

            Assert.Equal(3, exampleStruct.Factor);
        }
コード例 #5
0
 public virtual void TearDown()
 {
     HttpContextFake?.Dispose();
     ParentPage?.Dispose();
     ShimContext?.Dispose();
 }
コード例 #6
0
ファイル: ILRewriter.cs プロジェクト: dr-BEat/NShim
        private static void EmitILForMethod(ILGenerator ilGenerator, OperandInstruction <MethodBase> instruction, MethodInfo methodInfo, ShimContext context, int contextParamIndex)
        {
            /*if (context.StubCache.TryGetValue(methodInfo, out DynamicMethod stub))
             * {
             *  ilGenerator.Emit(OpCodes.Ldtoken, methodInfo);
             *  ilGenerator.Emit(OpCodes.Ldtoken, methodInfo.DeclaringType);
             *  ilGenerator.Emit(OpCodes.Call, stub);
             *  return;
             * }*/

            var methodBody = methodInfo.GetMethodBody();

            if (methodBody == null)
            {
                ilGenerator.Emit(instruction.OpCode, methodInfo);
                return;
            }

            MethodInfo stub;

            if (instruction.OpCode == OpCodes.Call)
            {
                stub = StubGenerator.GenerateStubForMethod(methodInfo);
            }
            else if (instruction.OpCode == OpCodes.Callvirt)
            {
                stub = StubGenerator.GenerateStubForVirtualMethod(methodInfo);
            }

            /*else if (instruction.OpCode == OpCodes.Ldftn)
             * {
             *  stub = StubGenerator.GenerateStubForMethodPointer(methodInfo);
             * }
             * else if (instruction.OpCode == OpCodes.Ldvirtftn)
             * {
             *  stub = StubGenerator.GenerateStubForMethodPointer(methodInfo);
             * }*/
            else
            {
                ilGenerator.Emit(instruction.OpCode, methodInfo);
                return;
            }

            ilGenerator.Emit(OpCodes.Ldarg, contextParamIndex);
            ilGenerator.Emit(OpCodes.Call, stub);
            //PoseContext.StubCache.TryAdd(methodInfo, stub);
        }
コード例 #7
0
ファイル: ILRewriter.cs プロジェクト: dr-BEat/NShim
        public static MethodInfo Rewrite(MethodBase method, ShimContext context)
        {
            var parameterTypes = new List <Type>();

            if (!method.IsStatic)
            {
                parameterTypes.Add(method.IsForValueType() ?
                                   method.DeclaringType.MakeByRefType() :
                                   method.DeclaringType);
            }

            parameterTypes.AddRange(method.GetParameters().Select(p => p.ParameterType));
            parameterTypes.Add(typeof(ShimContext));

            var returnType = method.IsConstructor ? typeof(void) : ((MethodInfo)method).ReturnType;

            var dynamicMethod = new DynamicMethod(
                string.Format("dynamic_{0}_{1}", method.DeclaringType, method.Name),
                returnType,
                parameterTypes.ToArray(),
                typeof(ILRewriter).Module,
                true);

            var ilGenerator = dynamicMethod.GetILGenerator();

            var targetInstructions = new Dictionary <ILProcessorInstruction, Label>();

            foreach (var local in method.GetMethodBody().LocalVariables)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ilReader     = new ILReader.ILReader(method);
            var instructions = ilReader.ToList();
            var processor    = ILProcessor.FromILInstructions(instructions);

            var steps = new IILRewriterStep[]
            {
                new RemoveShortBranchsStep(),
                new RemoveConstrainedStep(),
                new OptimizeBranchesStep(),
            };

            foreach (var step in steps)
            {
                step.Rewriter(processor);
            }

            foreach (var instruction in processor.Instructions)
            {
                switch (instruction)
                {
                case OperandInstruction <ILProcessorInstruction> branchInstruction:
                    targetInstructions.TryAdd(branchInstruction.Operand, ilGenerator.DefineLabel);
                    break;

                case OperandInstruction <IReadOnlyList <ILProcessorInstruction> > switchInstruction:
                    foreach (var target in switchInstruction.Operand)
                    {
                        targetInstructions.TryAdd(target, ilGenerator.DefineLabel);
                    }
                    break;
                }
            }

            foreach (var instruction in processor.Instructions)
            {
                if (targetInstructions.TryGetValue(instruction, out var label))
                {
                    ilGenerator.MarkLabel(label);
                }
                var opCode = instruction.OpCode;
                switch (instruction)
                {
                case NoneInstruction _:
                    ilGenerator.Emit(opCode);
                    break;

                case OperandInstruction <byte> i:
                    if (instruction.OpCode == OpCodes.Ldc_I4_S)
                    {
                        ilGenerator.Emit(opCode, (sbyte)i.Operand);
                    }
                    else
                    {
                        ilGenerator.Emit(opCode, i.Operand);
                    }
                    break;

                case OperandInstruction <short> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <ushort> i:
                    //Some instructions like ldarg require a unsigned int16 operand but ilGenerator only supports signed int16
                    ilGenerator.Emit(opCode, (short)i.Operand);
                    break;

                case OperandInstruction <int> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <long> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <float> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <double> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <string> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <FieldInfo> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                case OperandInstruction <Type> i:
                    ilGenerator.Emit(opCode, i.Operand);
                    break;

                /*case OperandInstruction<MemberInfo> i:
                 *  ilGenerator.Emit(opCode, i.Operand);
                 *  break;*/

                case OperandInstruction <ILProcessorInstruction> i:
                    ilGenerator.Emit(i.OpCode, targetInstructions[i.Operand]);
                    break;

                case OperandInstruction <IReadOnlyList <ILProcessorInstruction> > i:
                    ilGenerator.Emit(i.OpCode, i.Operand.Select(t => targetInstructions[t]).ToArray());
                    break;

                case OperandInstruction <MethodBase> i:
                    if (i.Operand is ConstructorInfo constructorInfo)
                    {
                        EmitILForConstructor(ilGenerator, i, constructorInfo, parameterTypes.Count - 1);
                    }
                    else
                    {
                        EmitILForMethod(ilGenerator, i, (MethodInfo)i.Operand, context, parameterTypes.Count - 1);
                    }
                    break;

                /*case InlineTokInstruction tok:
                 *  ilGenerator.Emit(instruction.OpCode, tok.Token);
                 *  break;*/
                default:
                    throw new NotSupportedException();
                }
            }

            return(dynamicMethod);
        }