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