| 1 | // Licensed to the .NET Foundation under one or more agreements. |
|---|---|
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | // =========================================================================== |
| 5 | // File: JITHelpers.CPP |
| 6 | // =========================================================================== |
| 7 | |
| 8 | // This contains JITinterface routines that are specific to the |
| 9 | // AMD64 platform. They are modeled after the X86 specific routines |
| 10 | // found in JIThelp.asm |
| 11 | |
| 12 | |
| 13 | #include "common.h" |
| 14 | #include "jitinterface.h" |
| 15 | #include "eeconfig.h" |
| 16 | #include "excep.h" |
| 17 | #include "ecall.h" |
| 18 | #include "asmconstants.h" |
| 19 | |
| 20 | EXTERN_C void JIT_TailCallHelperStub_ReturnAddress(); |
| 21 | |
| 22 | TailCallFrame * TailCallFrame::GetFrameFromContext(CONTEXT * pContext) |
| 23 | { |
| 24 | _ASSERTE((void*)::GetIP(pContext) == JIT_TailCallHelperStub_ReturnAddress); |
| 25 | return (TailCallFrame*)(pContext->R13 + sizeof(GSCookie)); |
| 26 | } |
| 27 | |
| 28 | // Assuming pContext is a plain generic call-site, adjust it to look like |
| 29 | // it called into TailCallHelperStub, and is at the point of the call. |
| 30 | TailCallFrame * TailCallFrame::AdjustContextForTailCallHelperStub(CONTEXT * pContext, size_t cbNewArgArea, Thread * pThread) |
| 31 | { |
| 32 | TailCallFrame * pNewFrame = (TailCallFrame *)(GetSP(pContext) - sizeof(TailCallFrame)); |
| 33 | |
| 34 | // R13 is the frame pointer (for popping the stack) |
| 35 | pContext->R13 = (size_t)pNewFrame - sizeof(GSCookie); |
| 36 | // R12 is the previous stack pointer, so we can determine if a return buffer from the |
| 37 | // immediate caller (and thus being discarded via the tail call), or someplace else |
| 38 | pContext->R12 = GetSP(pContext); |
| 39 | // for the args and pushed return address of the 'call' |
| 40 | SetSP(pContext, (size_t)pNewFrame - (cbNewArgArea + sizeof(void*) + sizeof(GSCookie))); |
| 41 | |
| 42 | // For popping the Frame, store the Thread |
| 43 | pContext->R14 = (DWORD_PTR)pThread; |
| 44 | // And the current head/top |
| 45 | pContext->R15 = (DWORD_PTR)pThread->GetFrame(); // m_Next |
| 46 | |
| 47 | return (TailCallFrame *) pNewFrame; |
| 48 | } |
| 49 |