Example #1
0
        public void TestIlInstructionReader()
        {
            Type[] args = { typeof(string), typeof(int) };


            var opCodeFields = typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static);

            ILOpCodeValues parseResult = ILOpCodeValues.Nop;

            foreach (var field in opCodeFields)
            {
                var OpCode = (OpCode)field.GetValue(null);

                var name       = field.Name;
                var lookup     = Enum.TryParse(name, out parseResult);
                var shortValue = unchecked ((short)parseResult);
                if (shortValue == 254)
                {
                    continue;                    //Prefix 1 is used to indicate a two byte instruction.
                }
                Assert.IsTrue(OpCode.Value == shortValue);

                var il       = CompileMethod(OpCode);
                var ilStream = ILInstructionReader.FromByteCode(il);
                var first    = ilStream.First();
                Assert.IsTrue(first.OpCode == OpCode);
                Assert.IsTrue(first.OpCode.Value == shortValue);
            }
        }
        private static MethodInfo GetCustomFunc <T1, T2, T3>(Func <T1, T2, T3> target)
        {
            var method   = target.Method;
            var body     = method.GetMethodBody();
            var locals   = body.LocalVariables.OrderBy(x => x.LocalIndex).ToList();
            var resolver = new ILInstructionResolver(method);

            switch (method.Name)
            {
            case nameof(TestMethods.Add_Ovf):
            case nameof(TestMethods.Add_Ovf_Un):
            {
                var instructions = ILInstructionReader.FromMethod(method);
                var parsed       = Enum.TryParse <ILOpCodeValues>(method.Name, out ILOpCodeValues result);
                var opCode       = OpCodeLookup.GetILOpcode((int)result);
                instructions[2] = new ILInstruction()
                {
                    OpCode = opCode
                };

                var compiled = ILEngineOpCodeTestMethodCompiler.CompileMethod(opCode, method, (gen) =>
                    {
                        locals.ForEach(x => gen.DeclareLocal(x.LocalType));
                        instructions.ForEach(x => x.Emit(gen, resolver));
                    });
                return(method);
            }

            default: throw new NotImplementedException();
            }
        }
Example #3
0
        public void TestEmitString()
        {
            Func <string> tst      = () => "hello";
            Func <int>    tstToken = () =>
            {
                var tstMethod   = tst.Method;
                var methodBytes = tstMethod.GetMethodBody().GetILAsByteArray();
                var ilStream    = ILInstructionReader.FromByteCode(tstMethod.GetMethodBody().GetILAsByteArray());
                return((int)ilStream[0].Arg);
            };
            int stringToken = tstToken();

            var expected = tst();
            var builder  = new ILInstructionBuilder();

            builder.Write(OpCodes.Ldstr, stringToken);
            builder.Write(OpCodes.Ret);
            var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType());

            ilMethod.AddInstructions(builder.Instructions.ToArray());
            ilMethod.Module = this.GetType().Module;
            var method = ilMethod.Compile();
            var actual = method.Invoke(null, Type.EmptyTypes);

            Assert.IsTrue((string)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");
        }
Example #4
0
        private ILOpCodeValues[] RunAndTest <T>(MethodInfo method, T expected, object[] parameters, Func <T, T, bool> comparer)
        {
            var result = ILInstructionReader
                         .FromMethod(method)
                         .Select(x => (ILOpCodeValues)x.OpCode.Value).ToArray();


            bool      invokedResult    = false;
            Exception caughtCompiled   = null;
            T         invocationResult = default;

            try
            {
                invocationResult = (T)method.Invoke(null, parameters);
                invokedResult    = comparer(expected, invocationResult);
            }
            catch (Exception ex)
            {
                caughtCompiled = ex.InnerException;
            }

            var       engineResult = false;
            Exception caughtEngine = null;

            try
            {
                var frame = new TStackFrame();
                frame.CopyFrom(method);
                frame.Args = parameters;
                engine.ExecuteFrame(frame);
                //var actualEngine = engine.ExecuteTyped<T>(method, parameters);
                if (!(frame.ReturnResult is T tresult))
                {
                    if (frame.ReturnResult is IConvertible tConvertible)
                    {
                        frame.ReturnResult = Convert.ChangeType(tConvertible, typeof(T));
                    }
                    else
                    {
                        frame.ReturnResult = (T)frame.ReturnResult;
                    }
                }
                var actualEngine = (T)frame.ReturnResult;
                engineResult = comparer(expected, actualEngine);
            }
            catch (Exception ex)
            {
                caughtEngine = ex;
            }


            if (caughtCompiled is null && caughtEngine is null)
            {
                Assert.IsTrue(invokedResult == engineResult);
            }
        void TestFromMethod(Func <MethodInfo> mResolver, OperandType operandType)
        {
            var method = mResolver();

            Assert.IsNotNull(method, "Failed to resolve test method");
            var expected     = method.Invoke(null, Type.EmptyTypes);
            var instructions = ILInstructionReader.FromMethod(method);
            var frame        = Build(instructions);

            frame.CopyFrom(method);
            ExecuteAndAssertResult(frame, expected, operandType);
        }
        public void TestReadInlineBrTarget()
        {
            var builder = new ILInstructionBuilder();

            builder.Write(ILInstruction.Create(ILOpCodeValues.Br, 0));
            builder.Write(ILOpCodeValues.Ldc_I8, 1L);
            builder.Write(ILOpCodeValues.Ret);
            var ilMethod = new Models.ILMethod(MethodBase.GetCurrentMethod().Name, typeof(long));

            ilMethod.AddInstructions(builder.Instructions.ToArray());
            var method = ilMethod.Compile();

            var expected     = method.Invoke(null, Type.EmptyTypes);
            var instructions = ILInstructionReader.FromMethod(method);

            ExecuteAndAssertResult(instructions, expected, OperandType.InlineBrTarget);
        }
        public void ExecuteTest()
        {
            var frame = new ILStackFrameWithDiagnostics();
            Action empty = () => { };
            var instructions = ILInstructionReader.FromMethod(empty.Method);
            frame.Stream = instructions;
            frame.SetResolver(empty.Method);
            frame.Execute();

            Assert.IsNull(frame.ReturnResult);
            Assert.IsNull(frame.Exception);

            Assert.IsTrue(frame.Module.MetadataToken == empty.Method.Module.MetadataToken);

            var thisType = this.GetType();
            var testMethod = thisType.GetMethod(nameof(ExecuteTest));
            Assert.IsNotNull(testMethod);
            var methodSigToken = testMethod.GetMethodBody().LocalSignatureMetadataToken;
            Assert.IsTrue(methodSigToken >0);
            var resolvedSig = frame.ResolveSignatureToken(methodSigToken);
            Assert.IsNotNull(resolvedSig);
            Assert.IsTrue(resolvedSig.Length > 0);

            frame.Execute(1);
            Assert.IsNull(frame.ReturnResult);
            Assert.IsNull(frame.Exception);

            Action sleepToLong = () => System.Threading.Thread.Sleep(4000);
            instructions = ILInstructionReader.FromMethod(sleepToLong.Method);
            frame.Stream = instructions;
            frame.Execute(1);

            Assert.IsNull(frame.ReturnResult);
            Assert.IsNotNull(frame.Exception);
            Assert.IsInstanceOfType(frame.Exception, typeof(ActionTimeoutException));

            Action throwException = () => throw new ArgumentException(nameof(throwException));
            instructions = ILInstructionReader.FromMethod(throwException.Method);
            frame.Stream = instructions;
            frame.Execute(1);

            Assert.IsNull(frame.ReturnResult);
            Assert.IsNotNull(frame.Exception);
            Assert.IsInstanceOfType(frame.Exception, typeof(ArgumentException));
        }
Example #8
0
        protected ILOpCodeValues[] CompileAndRun <T>(OpCode opCode, MethodInfo srcMethod, T expected, object[] parameters, Func <T, T, bool> comparer)
        {
            var methodParameters = srcMethod.GetParameters();
            var body             = srcMethod.GetMethodBody();
            var locals           = body.LocalVariables.OrderBy(x => x.LocalIndex).ToList();

            var parameterTypes = methodParameters.Select(x => x.ParameterType).ToArray();

            var instructions = ILInstructionReader.FromMethod(srcMethod);

            if (opCode != OpCodes.Arglist)
            {
                Assert.IsTrue(instructions.Any(x => x.OpCode == opCode), $"Opcode {opCode} missing from compiled method");
            }


            var result = ILInstructionReader
                         .FromMethod(srcMethod)
                         .Select(x => (ILOpCodeValues)x.OpCode.Value).ToArray();
            var resolver = new ILInstructionResolver(srcMethod);
            Action <ILGenerator> emitAction = (gen) =>
            {
                locals.ForEach(x => gen.DeclareLocal(x.LocalType));
                instructions.ForEach(x => x.Emit(gen, resolver));
            };

            MethodInfo method = null;

            try
            {
                method = ILEngineOpCodeTestMethodCompiler.CompileMethod(opCode, typeof(T), parameterTypes, emitAction);
            }
            catch (Exception ex)
            {
                Assert.Fail("Failed to compile method:", ex.Message);
                return(null);
            }
            return(RunAndTest <T>(method, expected, parameters, comparer));
        }
 protected List <ILInstruction> GetIlInstructions(MethodInfo method)
 => ILInstructionReader.FromByteCode(method.GetMethodBody().GetILAsByteArray());
Example #10
0
        public void TestEmitCompiledSwitch()
        {
            var compiledType   = BuildSwitchTestType();
            var compiledMethod = compiledType.GetMethod("SwitchTest");

            Assert.IsNotNull(compiledMethod);


            var compiledInstructions = ILInstructionReader.FromMethod(compiledMethod).ToArray();

            //TODO: auto label read instructions.

            //mark default case jump target
            compiledInstructions[7].Label = 0;
            //set default case jump target
            compiledInstructions[2].Arg = compiledInstructions[7];
            // set break target;
            compiledInstructions[8].Label = 1;

            //set jump targets for switch breaks statements
            compiledInstructions[4].Arg = compiledInstructions[6].Arg = compiledInstructions[8];

            //mark switch jump targets;

            compiledInstructions[3].Label = 2;
            compiledInstructions[5].Label = 3;

            //set switch jump targets =
            compiledInstructions[1].Arg = new[] { compiledInstructions[3], compiledInstructions[5] };


            var builder = new ILInstructionBuilder();

            builder.Write(compiledInstructions.ToArray());

            //TODO: implement auto fixup of instuctions.

            var frame = ILStackFrameBuilder.Build(builder.Instructions);

            frame.Args = new object[] { 1 };
            frame.Reset();
            int Position  = -1;
            var jumpTable = frame.Stream.ToDictionary(x => (int)x.ByteIndex, x => ++ Position);

            frame.Execute();
            var expected = 1;

            Assert.IsNull(frame.Exception, $"Executing switch: add throw an exception {frame?.Exception}");
            Assert.IsTrue(frame.Stack.Count == 0, "Stack was not cleared executing switch: add");
            Assert.IsTrue((int)frame.ReturnResult == expected, $"Actual: {frame.ReturnResult}\r\nExpected: {expected}");

            frame.Args = new object[] { 0 };
            frame.Execute();
            expected = 0;
            Assert.IsNull(frame.Exception, $"Executing switch: add throw an exception {frame?.Exception}");
            Assert.IsTrue(frame.Stack.Count == 0, "Stack was not cleared executing switch: add");
            Assert.IsTrue((int)frame.ReturnResult == expected, $"Actual: {frame.ReturnResult}\r\nExpected: {expected}");

            frame.Args = new object[] { 2 };
            frame.Execute();
            expected = 2;
            Assert.IsNull(frame.Exception, $"Executing switch: add throw an exception {frame?.Exception}");
            Assert.IsTrue(frame.Stack.Count == 0, "Stack was not cleared executing switch: add");
            Assert.IsTrue((int)frame.ReturnResult == expected, $"Actual: {frame.ReturnResult}\r\nExpected: {expected}");
        }
Example #11
0
 public ILSearchResult(MethodInfo method)
 {
     Method            = method;
     this.Instructions = ILInstructionReader.FromMethod(method);
 }