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}"); }
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 void TestEmitConstructorInfo() { var c = new ILEngineUnitTestModel(0); var cType = c.GetType(); var cMethod = cType.GetConstructor(Type.EmptyTypes); var cResult = cMethod.Invoke(null); Assert.IsNotNull(cMethod); var expected = c; var builder = new ILInstructionBuilder(); builder.Write(OpCodes.Newobj, cMethod); builder.Write(OpCodes.Ret); var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType()); ilMethod.AddInstructions(builder.Instructions.ToArray()); ilMethod.Module = cType.GetType().Module; var method = ilMethod.Compile(); var actual = method.Invoke(null, null); Assert.IsTrue((ILEngineUnitTestModel)actual == expected, $"Actual: {actual}\r\nExpected:{expected}"); }
//protected void AssertEmptyStackResult<TResult>(TStackFrame frame, object expected, Func<object, TResult> converter) //{ // AssertExceptionIsNull(frame); // AssertEmptyStack(frame); // AssertFrameResult(frame, expected, converter); //} protected TStackFrame Build(params ILOpCodeValues[] instructions) { var builder = new ILInstructionBuilder(); builder.Write(instructions); var frame = BuildTestFrame(builder.Instructions); return(frame); }
public void TestExceptionHandling() { var builder = new ILInstructionBuilder(); builder.Write(ILOpCodeValues.Ldobj, "test"); builder.Write(ILOpCodeValues.Conv_I4); var frame = new ILStackFrameWithDiagnostics(); frame.Stream = builder.Instructions; frame.Execute(100); Assert.IsInstanceOfType(frame.Exception, typeof(FormatException)); }
public void WriteOpCodeTest() { var opCode1 = OpCodes.Nop; var builder = new ILInstructionBuilder(); builder.Write(opCode1); Assert.IsTrue(builder.Instructions.Count == 1); Assert.IsTrue(builder.Instructions[0].OpCode == opCode1); Assert.IsNull(builder.Instructions[0].Arg); }
public void WriteSingleILOpCodeValues() { var opCode1 = OpCodes.Ret; var builder = new ILInstructionBuilder(); builder.Write(ILOpCodeValues.Ret); Assert.IsTrue(builder.Instructions.Count == 1); Assert.IsTrue(builder.Instructions[0].OpCode == opCode1); Assert.IsNull(builder.Instructions[0].Arg); }
public void ClearTest() { var builder = new ILInstructionBuilder(); Assert.IsTrue(builder.Instructions.Count == 0); builder.Write(OpCodes.Ret); Assert.IsTrue(builder.Instructions.Count == 1); Assert.IsTrue(builder.Instructions[0].OpCode == OpCodes.Ret); builder.Clear(); Assert.IsTrue(builder.Instructions.Count == 0); }
public void WriteILInstructionTest() { var opCode = OpCodes.Nop; var instruction = ILInstruction.Create(opCode); var builder = new ILInstructionBuilder(); builder.Write(instruction); Assert.IsTrue(builder.Instructions.Count == 1); Assert.IsTrue(builder.Instructions[0].OpCode == opCode); Assert.IsNull(builder.Instructions[0].Arg); }
public void WriteOpCodeWithArgTest() { var opCode1 = OpCodes.Ldarga_S; var opCode1Arg = 1; var builder = new ILInstructionBuilder(); builder.Write(opCode1, opCode1Arg); Assert.IsTrue(builder.Instructions.Count == 1); Assert.IsTrue(builder.Instructions[0].OpCode == opCode1); Assert.IsNotNull(builder.Instructions[0].Arg); Assert.IsTrue((int)builder.Instructions[0].Arg == opCode1Arg); }
public void WriteILOpCodeValues() { var opCode1 = OpCodes.Nop; var opCode2 = OpCodes.Ret; var builder = new ILInstructionBuilder(); builder.Write(opCode1, opCode2); Assert.IsTrue(builder.Instructions.Count == 2); Assert.IsTrue(builder.Instructions[0].OpCode == opCode1); Assert.IsNull(builder.Instructions[0].Arg); Assert.IsTrue(builder.Instructions[1].OpCode == opCode2); Assert.IsNull(builder.Instructions[1].Arg); }
public void WriteILInstructionsTest() { var opCode1 = OpCodes.Nop; var opCode2 = OpCodes.Ret; var instruction1 = ILInstruction.Create(opCode1); var instruction2 = ILInstruction.Create(opCode2); var builder = new ILInstructionBuilder(); builder.Write(instruction1, instruction2); Assert.IsTrue(builder.Instructions.Count == 2); Assert.IsTrue(builder.Instructions[0].OpCode == opCode1); Assert.IsNull(builder.Instructions[0].Arg); Assert.IsTrue(builder.Instructions[1].OpCode == opCode2); Assert.IsNull(builder.Instructions[1].Arg); }
public void TestEmitInlineNone() { var expected = 1; var builder = new ILInstructionBuilder(); builder.Write(OpCodes.Ldc_I4_1); builder.Write(OpCodes.Ret); var ilMethod = new ILMethod(System.Reflection.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((int)actual == expected, $"Actual: {actual}\r\nExpected:{expected}"); }
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}"); }
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 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}"); }
public void ResetTest() { var builder = new ILInstructionBuilder(); builder.Write(ILOpCodeValues.Ldc_I4_0); builder.Write(ILOpCodeValues.Ldc_I4_1); builder.Write(ILOpCodeValues.Ret); var frame = new ILStackFrameWithDiagnostics(); frame.Stream = builder.Instructions; frame.Execute(); Assert.IsTrue(frame.ReturnResult == 1); Assert.IsTrue(frame.Stack.Count == 1); frame.Reset(); Assert.IsNull(frame.ReturnResult); Assert.IsTrue(frame.Stack.Count == 0); }
public void TestConvNoOverflowCheck() { var frame = new ILStackFrameWithDiagnostics(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Clear(); frame.Args = new object[] { uint.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I); stream.Write(OpCodes.Ret); frame.Execute(); int expected = unchecked((int)Convert.ToInt64(uint.MaxValue)); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == expected, $"Conv_I uint.MaxValue failed\r\nExpected: {expected}\r\nActual:{frame.ReturnResult ?? "null"}"); }
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}"); }
public void TestEmitLdtokenType() { var intType = typeof(int); var expected = intType.TypeHandle; var builder = new ILInstructionBuilder(); builder.Write(ILOpCodeValues.Ldtoken, intType.MetadataToken); builder.Write(OpCodes.Ret); var ilMethod = new ILMethod(MethodBase.GetCurrentMethod().Name, expected.GetType()); ilMethod.AddInstructions(builder.Instructions.ToArray()); ilMethod.Module = intType.Module; var method = ilMethod.Compile(); var actual = method.Invoke(null, null); Assert.IsTrue(actual == expected, $"Actual: {actual}\r\nExpected:{expected}"); }
public void TestConvUnsigned() { var frame = new TStackFrame(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Clear(); frame.Args = new object[] { byte.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)byte.MinValue, $"Conv_U byte.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { byte.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)byte.MaxValue, $"Conv_U byte.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { byte.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)byte.MinValue, $"Conv_U1 byte.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { byte.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)byte.MaxValue, $"Conv_U1 byte.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { ushort.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)ushort.MinValue, $"Conv_U2 ushort.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { ushort.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)ushort.MaxValue, $"Conv_U2 ushort.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { uint.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)uint.MinValue, $"Conv_U4 uint.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { uint.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (uint)uint.MaxValue, $"Conv_U4 uint.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { ulong.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U8); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == ulong.MinValue, $"ConvU_U8 ulong.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { ulong.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_U8); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == ulong.MaxValue, $"Conv_U8 ulong.MaxValue return result = {frame.ReturnResult ?? "null"}"); }
public void TesCheckInfinity() { var frame = new TStackFrame(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Clear(); stream.Write(ILOpCodeValues.Ldc_R4, float.NegativeInfinity); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == true, $"Ckfinite float.NegativeInfinity, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R4, float.PositiveInfinity); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == true, $"Ckfinite float.PositiveInfinity, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R4, 1.0f); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == false, $"Ckfinite float.PositiveInfinity, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R4, 1); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == false, $"Ckfinite float.PositiveInfinity, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, double.NegativeInfinity); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == true, $"Ckfinite double.NegativeInfinityd, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, double.PositiveInfinity); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == true, $"Ckfinite double.PositiveInfinity, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, 1.0); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == false, $"Ckfinite 1.0, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, 1); stream.Write(OpCodes.Ckfinite); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == false, $"Ckfinite 1, return result = {frame.ReturnResult ?? "null"}"); }
public void TestConvSigned() { var frame = new TStackFrame(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Clear(); frame.Args = new object[] { sbyte.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)sbyte.MinValue, $"Conv_I sbyte.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { byte.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)byte.MinValue, $"Conv_I byte.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { byte.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)byte.MaxValue, $"Conv_I byte.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { sbyte.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)sbyte.MinValue, $"Conv_I1 sbyte.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { sbyte.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)sbyte.MaxValue, $"Conv_I1 sbyte.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { short.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)short.MinValue, $"Conv_I1 short.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { short.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)short.MaxValue, $"Conv_I2 short.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { int.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)int.MinValue, $"Conv_I4 int.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { int.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == (int)int.MaxValue, $"Conv_I4 int.MaxValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { long.MinValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I8); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == long.MinValue, $"Conv_I8 long.MinValue return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); frame.Args = new object[] { long.MaxValue }; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Conv_I8); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsNull(frame.Exception, $"Frame returned exception: {frame.Exception?.Message}"); Assert.IsTrue(frame.ReturnResult == long.MaxValue, $"Conv_I8 long.MaxValue return result = {frame.ReturnResult ?? "null"}"); }
public void TestLoadConstants() { var frame = new TStackFrame(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Clear(); stream.Write(OpCodes.Ldc_I4_0); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 0, $"Ldc_I4_0 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 1, $"Ldc_I4_1 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 2, $"Ldc_I4_2 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_3); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 3, $"Ldc_I4_3 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 4, $"Ldc_I4_4 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_5); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 5, $"Ldc_I4_5 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_6); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 6, $"Ldc_I4_6 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_7); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 7, $"Ldc_I4_7 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_8); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 8, $"Ldc_I4_8 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_M1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == -1, $"Ldc_I4_M1 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4, 1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 1, $"Ldc_I4(1) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I4_S, byte.MaxValue); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == byte.MaxValue, $"Ldc_I4_s(255) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_I8, long.MaxValue); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == long.MaxValue, $"Ldc_I8(long.MaxValue) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R4, 0); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 0, $"Ldc_R4(float.MaxValue) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R4, float.MaxValue); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == float.MaxValue, $"Ldc_R4(float.MaxValue) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R4, float.MinValue); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == float.MinValue, $"Ldc_R4(float.MinValue) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, 0); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == 0, $"Ldc_R8(float.MaxValue) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, double.MaxValue); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == double.MaxValue, $"Ldc_R8(double.MaxValue) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldc_R8, double.MinValue); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == double.MinValue, $"Ldc_R8(double.MinValue) failed, return result = {frame.ReturnResult ?? "null"}"); }
public void TestLoadAndStoreArgs() { var frame = new TStackFrame(); var intType = typeof(int); var rng = Enumerable.Range(0, 8); frame.Args = rng .Select(idx => (object)idx).ToArray(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Starg, 0); stream.Write(OpCodes.Ldarg_0); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[0], $"Args 0 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldarg_1); stream.Write(OpCodes.Starg_S, 1); stream.Write(OpCodes.Ldarg_1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[1], $"Args 1 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldarg_2); stream.Write(OpCodes.Starg, 2); stream.Write(OpCodes.Ldarg_2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[2], $"Args 2 failed, return result = {frame.ReturnResult ?? "null"}");; stream.Clear(); stream.Write(OpCodes.Ldarg_3); stream.Write(OpCodes.Starg, 3); stream.Write(OpCodes.Ldarg_3); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[3], $"Args 3 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldarg, 4); stream.Write(OpCodes.Starg, 4); stream.Write(OpCodes.Ldarg, 4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[4], $"Args(arg=4) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldarg_S, 5); stream.Write(OpCodes.Starg_S, 5); stream.Write(OpCodes.Ldarg_S, 5); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[5], $"Args(arg=5) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldarga, 6); stream.Write(OpCodes.Starg_S, 6); stream.Write(OpCodes.Ldarga, 6); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[6], $"Ldarga(arg=6) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldarga_S, 7); stream.Write(OpCodes.Starg_S, 7); stream.Write(OpCodes.Ldarga_S, 7); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Args[7], $"Ldarga_S(arg=6) failed, return result = {frame.ReturnResult ?? "null"}"); }
public void TestLoadAndStoreLocals() { var frame = new TStackFrame(); var intType = typeof(int); var rng = Enumerable.Range(0, 8); frame.Locals = rng .Select(idx => new ILVariable { Index = idx, Type = intType, Value = idx }).ToArray(); var stream = new ILInstructionBuilder(); frame.Stream = stream.Instructions; stream.Write(OpCodes.Ldloc_0); stream.Write(OpCodes.Stloc_0); stream.Write(OpCodes.Ldloc_0); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[0].Value, $"Locals 0 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldloc_1); stream.Write(OpCodes.Stloc_1); stream.Write(OpCodes.Ldloc_1); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[1].Value, $"Locals 1 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldloc_2); stream.Write(OpCodes.Stloc_2); stream.Write(OpCodes.Ldloc_2); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[2].Value, $"Locals 2 failed, return result = {frame.ReturnResult ?? "null"}");; stream.Clear(); stream.Write(OpCodes.Ldloc_3); stream.Write(OpCodes.Stloc_3); stream.Write(OpCodes.Ldloc_3); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[3].Value, $"Locals 3 failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldloc, 4); stream.Write(OpCodes.Stloc, 4); stream.Write(OpCodes.Ldloc, 4); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[4].Value, $"Ldloc(arg=4) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldloc_S, 5); stream.Write(OpCodes.Stloc_S, 5); stream.Write(OpCodes.Ldloc_S, 5); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[5].Value, $"Ldloc_S(arg=5) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldloca, 6); stream.Write(OpCodes.Stloc_S, 6); stream.Write(OpCodes.Ldloca, 6); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[6].Value, $"Ldloca(arg=6) failed, return result = {frame.ReturnResult ?? "null"}"); stream.Clear(); stream.Write(OpCodes.Ldloca_S, 7); stream.Write(OpCodes.Stloc_S, 7); stream.Write(OpCodes.Ldloca_S, 7); stream.Write(OpCodes.Ret); frame.Execute(); Assert.IsTrue(frame.ReturnResult == (int)frame.Locals[7].Value, $"Ldloca_S(arg=6) failed, return result = {frame.ReturnResult ?? "null"}"); }
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}"); }
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); }