예제 #1
0
        public void TestEmitMethod()
        {
            var c        = new ILEngineUnitTestModel(1);
            var cType    = c.GetType();
            var cMethod  = cType.GetMethod(nameof(c.GetValue));
            var expected = c.Value;

            var builder = new ILInstructionBuilder();

            builder.Write(OpCodes.Ldarg_0);
            builder.Write(OpCodes.Call, cMethod.MetadataToken);
            builder.Write(OpCodes.Ret);

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

            frame.SetResolver(this.GetType());
            frame.Args = new object[] { c };
            frame.Execute();


            var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType());

            ilMethod.AddParameters(new[] { cType });
            ilMethod.AddInstructions(builder.Instructions.ToArray());
            ilMethod.Module = this.GetType().Module;
            var method = ilMethod.Compile();
            var actual = method.Invoke(null, new object[] { c });

            Assert.IsTrue((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");
        }
        public static MethodInfo Compile_Add_Ovf(Type returnType, params Type[] parameters)
        {
            var method = new ILMethod(nameof(ILOpCodeValues.Add_Ovf), returnType);

            method.AddParameters(parameters);
            method.AddInstructions(ILOpCodeValues.Ldarg_0,
                                   ILOpCodeValues.Ldarg_1,
                                   ILOpCodeValues.Add_Ovf,
                                   ILOpCodeValues.Ret);

            return(method.Compile());
        }
        public static MethodInfo CompileBinary(ILOpCodeValues opCodeValue, Type returnType, params Type[] parameters)
        {
            var methodName = $"{opCodeValue}";
            var method     = new ILMethod(methodName, returnType);

            method.AddParameters(parameters);
            method.AddInstructions(ILOpCodeValues.Ldarg_0,
                                   ILOpCodeValues.Ldarg_1,
                                   opCodeValue,
                                   ILOpCodeValues.Ret);

            return(method.Compile());
        }
예제 #4
0
        public void TestEmitShortInlineVar()
        {
            var expected = 1;
            var builder  = new ILInstructionBuilder();

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

            ilMethod.AddInstructions(builder.Instructions.ToArray());
            ilMethod.AddParameters(new[] { typeof(int) });
            ilMethod.Module = this.GetType().Module;
            var method = ilMethod.Compile();
            var actual = method.Invoke(null, new object[] { expected });

            Assert.IsTrue((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");
        }
예제 #5
0
        public void InlineTypeToken()
        {
            var expected = 4;
            var builder  = new ILInstructionBuilder();
            var intType  = typeof(int);

            builder.Write(OpCodes.Sizeof, intType.MetadataToken);
            builder.Write(OpCodes.Ret);
            var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType());

            ilMethod.AddInstructions(builder.Instructions.ToArray());
            ilMethod.AddParameters(new[] { typeof(int) });
            ilMethod.Module = intType.Module;
            var method = ilMethod.Compile();
            var actual = method.Invoke(null, new object[] { expected });

            Assert.IsTrue((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");
        }
예제 #6
0
        public void TestEmitField()
        {
            var c        = new FieldTest(1);
            var cType    = c.GetType();
            var cMethod  = cType.GetField(nameof(c.Value));
            var expected = c.Value;
            var builder  = new ILInstructionBuilder();

            builder.Write(OpCodes.Ldarg_0);
            builder.Write(OpCodes.Ldfld, cMethod.MetadataToken);
            builder.Write(OpCodes.Ret);
            var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType());

            ilMethod.AddParameters(new[] { cType });
            ilMethod.AddInstructions(builder.Instructions.ToArray());
            ilMethod.Module = this.GetType().Module;
            var method = ilMethod.Compile();
            var actual = method.Invoke(null, new[] { c });

            Assert.IsTrue((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");
        }
예제 #7
0
        public void TestEmitSwitch()
        {
            var endSwitchInstruction = ILInstruction.Create(ILOpCodeValues.Nop);

            endSwitchInstruction.Label = 2;
            var addInstructions = new[]
            {
                ILInstruction.Create(ILOpCodeValues.Add),
                ILInstruction.Create(ILOpCodeValues.Br_S, endSwitchInstruction)
            };
            var subInstructions = new[]
            {
                ILInstruction.Create(ILOpCodeValues.Sub),
                ILInstruction.Create(ILOpCodeValues.Br_S, endSwitchInstruction)
            };

            addInstructions[0].Label = 0;
            subInstructions[0].Label = 1;

            var exceptionType      = typeof(ArgumentOutOfRangeException);
            var ctor               = exceptionType.GetConstructor(Type.EmptyTypes);
            var defaultInstuctions = new[]
            {
                ILInstruction.Create(ILOpCodeValues.Newobj, ctor.MetadataToken),
                ILInstruction.Create(ILOpCodeValues.Throw)
            };

            var switchInstuction = ILInstruction.Create(ILOpCodeValues.Switch,
                                                        new[] { addInstructions[0], subInstructions[0] });
            var builder = new ILInstructionBuilder();

            //var b= arg[b];
            builder.Write(ILOpCodeValues.Ldarg_1);
            //var a= arg[1];
            builder.Write(ILOpCodeValues.Ldarg_2);
            //switch(arg[0])
            builder.Write(ILOpCodeValues.Ldarg_0);
            builder.Write(switchInstuction);
            //case default
            builder.Write(defaultInstuctions);
            //case 0: add
            builder.Write(addInstructions);
            //case 1: sub
            builder.Write(subInstructions);
            builder.Write(endSwitchInstruction);
            builder.Write(ILOpCodeValues.Ret);



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

            frame.Args = new object[] { 0, 1, 2 };
            frame.Execute();

            var expected = 3;

            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}");

            expected   = -1;
            frame.Args = new object[] { 1, 1, 2 };
            frame.Execute();
            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, 1, 2 };
            frame.Execute();
            Assert.IsNotNull(frame.Exception, $"Executing switch failed to execute default case to and throw and exception.");
            Assert.IsInstanceOfType(frame.Exception, typeof(ArgumentOutOfRangeException), $"Frame failed to throw {nameof(ArgumentOutOfRangeException)}");
            Assert.IsNull(frame.ReturnResult, $"Actual: {frame.ReturnResult}\r\nExpected: [null]");


            //var type = BuildSwitchTestType();
            //var switchMethod = type.GetMethod("SwitchTest");
            //Assert.IsNotNull(switchMethod);
            //var instructions = ILInstructionReader.FromMethod(switchMethod);

            var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType());

            ilMethod.AddParameters(new[] { typeof(int), typeof(int), typeof(int) });
            ilMethod.AddInstructions(builder.Instructions.ToArray());

            ilMethod.Module = exceptionType.Module;
            var method = ilMethod.Compile();
            var actual = method.Invoke(null, new object[] { 0, 1, 2 });

            expected = 3;
            Assert.IsTrue((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");

            actual   = method.Invoke(null, new object[] { 1, 1, 2 });
            expected = -1;
            Assert.IsTrue((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}");

            Exception exception = null;

            try
            {
                actual = method.Invoke(null, new object[] { 2, 1, 2 });
            }
            catch (TargetInvocationException ex)
            {
                exception = ex.InnerException;
            }
            Assert.IsNotNull(exception, $"Failed to catch argument exception");
            Assert.IsInstanceOfType(exception, exceptionType);
        }