public void TestJitFunction1() { JitFunction<int> method = new JitFunction<int>(); Compiler compiler = method.GetCompiler(); compiler.Logger = new FileLogger(Console.Error); GPVar var = compiler.NewGP(); compiler.Mov(var, 1); compiler.Ret(var); var f = method.GetDelegate<TestJitFunction1Fn>(); int result = f(); Assert.AreEqual(1, result); method.Dispose(); }
private static IntPtr CreateMethod(IntPtr stubAddress) { JitFunction<int> jitFunction = new JitFunction<int>(); Compiler compiler = jitFunction.GetCompiler(); GPVar x = compiler.NewGP(VariableType.INT32); compiler.Mov(x, 2); compiler.Ret(x); jitFunction.Compile(); return jitFunction.CompiledAddress; }
private JitAction<int> GenerateCode() { //Action<bool> sample = // throwException => // { // try // { // Console.WriteLine(0); // if (throwException) // throw new Exception("1"); // } // catch (Exception e) // { // Console.WriteLine(e.Message); // } // finally // { // Console.WriteLine(2); // } // }; JitFunction<IntPtr> getInstructionPointer = new JitFunction<IntPtr>(hints: FunctionHints.Naked); { Assembler assembler = getInstructionPointer.GetAssembler(); assembler.Mov(Register.nax, Register.nbp); assembler.Ret(); getInstructionPointer.Compile(); } JitAction<int> testMethod = new JitAction<int>(); unsafe { _threadData = (ThreadData*)Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ThreadData))); Marshal.StructureToPtr(new ThreadData(), (IntPtr)_threadData, false); Compiler c = testMethod.GetCompiler(); c.Logger = new FileLogger(Console.Error); // arguments GPVar argThrowException = c.ArgGP(0); // special variables GPVar currentException = c.NewGP(); GPVar nextException = c.NewGP(); GPVar position = c.NewGP(); // special prolog GPVar varMethodData = c.NewGP(); GPVar varThreadData = c.NewGP(); c.Mov(varThreadData, (IntPtr)_threadData); // labels Label leaveTry = c.DefineLabel(); Label enterCatch = c.DefineLabel(); Label leaveCatch = c.DefineLabel(); Label enterFinally = c.DefineLabel(); Label leaveFinally = c.DefineLabel(); Label enterThrowHandler = c.DefineLabel(); Label enterRethrowHandler = c.DefineLabel(); Label enterLeaveHandler = c.DefineLabel(); Label enterEndFinallyHandler = c.DefineLabel(); Label retLabel = c.DefineLabel(); // try c.Comment("Enter try"); GenerateWriteLine(c, (Imm)0); c.Test(argThrowException, argThrowException); c.Jz(leaveTry, Hint.Taken); GenerateNewException(c, nextException, (Imm)1); c.Call(getInstructionPointer, position); c.Jmp(enterThrowHandler); c.MarkLabel(leaveTry); c.Jmp(enterLeaveHandler); // catch c.Comment("Enter catch"); c.MarkLabel(enterCatch); GPVar varErrorCode = c.NewGP(); GenerateLoadCurrentException(c, varErrorCode, varThreadData); GenerateLoadExceptionMessage(c, varErrorCode, varErrorCode); GenerateWriteLine(c, varErrorCode); c.Xor(varErrorCode, varErrorCode); c.Mov(Mem.sysint_ptr(varThreadData, ThreadData_ExceptionDataOffset), varErrorCode); c.MarkLabel(leaveCatch); c.Jmp(enterLeaveHandler); // finally c.Comment("Enter finally"); c.MarkLabel(enterFinally); GenerateWriteLine(c, (Imm)2); c.MarkLabel(leaveFinally); c.Jmp(enterEndFinallyHandler); //// special epilog (throw and leave implementations) //c.Jmp(retLabel); c.Comment("Handler for 'throw' instructions"); c.MarkLabel(enterThrowHandler); c.Mov(Mem.sysint_ptr(varThreadData, ThreadData_ExceptionDataOffset), nextException); c.Jmp(enterCatch); c.Comment("Handler for 'rethrow' instructions"); c.MarkLabel(enterRethrowHandler); // rethrow is not implemented and not currently used c.Int3(); c.Comment("Handler for 'leave' instructions"); c.MarkLabel(enterLeaveHandler); c.Jmp(enterFinally); //c.Mov(Mem.sysint_ptr(varThreadData, ThreadData_ExceptionDataOffset), 0); //throw new NotImplementedException("TODO: check for a finally block"); //c.Jmp(leaveTarget); c.Comment("Handler for 'endfinally' instructions"); c.MarkLabel(enterEndFinallyHandler); GenerateLoadCurrentException(c, currentException, varThreadData); c.Test(currentException, currentException); c.Jnz(enterRethrowHandler, Hint.NotTaken); c.Jmp(retLabel); // return c.Comment("Return"); c.MarkLabel(retLabel); c.Ret(); testMethod.Compile(); } return testMethod; }
public void TestJitFunction2() { JitFunction<int, int> method = new JitFunction<int, int>(); Compiler compiler = method.GetCompiler(); compiler.Logger = new FileLogger(Console.Error); GPVar arg = compiler.ArgGP(0); GPVar var = compiler.NewGP(); compiler.Mov(var, arg); compiler.Imul(var, 2); compiler.Ret(var); var f = method.GetDelegate<TestJitFunction2Fn>(); int result = f(1); Assert.AreEqual(2, result); method.Dispose(); }
public void TestRecursiveFunction() { JitFunction<int, int> function = new JitFunction<int, int>(CallingConvention.Default, FunctionHints.Naked); Compiler c = function.GetCompiler(); c.Logger = new FileLogger(Console.Error); Label skip = c.DefineLabel(); GPVar var = c.ArgGP(0); c.Cmp(var, 1); c.Jle(skip); GPVar tmp = c.NewGP(VariableType.INT32); c.Mov(tmp, var); c.Dec(tmp); CompilerFunctionCall call = c.Call(c.Function.EntryLabel, CallingConvention.Default, typeof(Func<int, int>)); call.SetArgument(0, tmp); call.SetReturn(tmp); c.Mul(c.NewGP(VariableType.INT32), var, tmp); c.MarkLabel(skip); c.Ret(var); TestJitFunction2Fn fn = function.GetDelegate<TestJitFunction2Fn>(); Assert.AreEqual(5 * 4 * 3 * 2 * 1, fn(5)); }
public void TestJitFunctionCall1() { JitFunction<int, int> caller = new JitFunction<int, int>(); JitFunction<int, int> called = new JitFunction<int, int>(CallingConvention.MsFastCall); { Compiler compiler = called.GetCompiler(); compiler.Logger = new FileLogger(Console.Error); GPVar arg = compiler.ArgGP(0); GPVar var = compiler.NewGP(); compiler.Mov(var, arg); compiler.Imul(var, 2); compiler.Ret(var); called.Compile(); } { Compiler compiler = caller.GetCompiler(); compiler.Logger = new FileLogger(Console.Error); GPVar arg = compiler.ArgGP(0); GPVar var = compiler.NewGP(); compiler.Call(called, arg, var); compiler.Ret(var); } var f = caller.GetDelegate<TestJitFunction2Fn>(); int result = f(1); Assert.AreEqual(2, result); called.Dispose(); caller.Dispose(); }