diff options
author | Aditya Mandaleeka <adityam@microsoft.com> | 2018-08-07 15:17:52 -0700 |
---|---|---|
committer | Aditya Mandaleeka <adityam@microsoft.com> | 2018-08-07 15:17:52 -0700 |
commit | 87174a2fdf97938b0ee8d64a0b784f1c01bf2932 (patch) | |
tree | 24103edd4c7cabd88cbe6bd127df0de23a30af00 /src/vm/callingconvention.h | |
parent | a113b1c803783c9d64f1f0e946ff9a853e3bc140 (diff) | |
download | coreclr-87174a2fdf97938b0ee8d64a0b784f1c01bf2932.tar.gz coreclr-87174a2fdf97938b0ee8d64a0b784f1c01bf2932.tar.bz2 coreclr-87174a2fdf97938b0ee8d64a0b784f1c01bf2932.zip |
Make VM-side changes for ARM64 Windows calling convention.
Diffstat (limited to 'src/vm/callingconvention.h')
-rw-r--r-- | src/vm/callingconvention.h | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/src/vm/callingconvention.h b/src/vm/callingconvention.h index a0d7bd4fa0..a653d8570f 100644 --- a/src/vm/callingconvention.h +++ b/src/vm/callingconvention.h @@ -120,8 +120,9 @@ struct TransitionBlock INT64 x19, x20, x21, x22, x23, x24, x25, x26, x27, x28; }; }; - ArgumentRegisters m_argumentRegisters; TADDR padding; // Keep size of TransitionBlock as multiple of 16-byte. Simplifies code in PROLOG_WITH_TRANSITION_BLOCK + INT64 m_x8RetBuffReg; + ArgumentRegisters m_argumentRegisters; #else PORTABILITY_ASSERT("TransitionBlock"); #endif @@ -135,9 +136,19 @@ struct TransitionBlock return offsetof(TransitionBlock, m_ReturnAddress); } +#ifdef _TARGET_ARM64_ + static int GetOffsetOfRetBuffArgReg() + { + LIMITED_METHOD_CONTRACT; + return offsetof(TransitionBlock, m_x8RetBuffReg); + } +#endif + static BYTE GetOffsetOfArgs() { LIMITED_METHOD_CONTRACT; + + // Offset of the stack args (which are after the TransitionBlock) return sizeof(TransitionBlock); } @@ -491,9 +502,13 @@ public: // in signatures (this pointer and the like). Whether or not these can be used successfully before all the // explicit arguments have been scanned is platform dependent. void GetThisLoc(ArgLocDesc * pLoc) { WRAPPER_NO_CONTRACT; GetSimpleLoc(GetThisOffset(), pLoc); } - void GetRetBuffArgLoc(ArgLocDesc * pLoc) { WRAPPER_NO_CONTRACT; GetSimpleLoc(GetRetBuffArgOffset(), pLoc); } void GetParamTypeLoc(ArgLocDesc * pLoc) { WRAPPER_NO_CONTRACT; GetSimpleLoc(GetParamTypeArgOffset(), pLoc); } void GetVASigCookieLoc(ArgLocDesc * pLoc) { WRAPPER_NO_CONTRACT; GetSimpleLoc(GetVASigCookieOffset(), pLoc); } + +#ifndef CALLDESCR_RETBUFFARGREG + void GetRetBuffArgLoc(ArgLocDesc * pLoc) { WRAPPER_NO_CONTRACT; GetSimpleLoc(GetRetBuffArgOffset(), pLoc); } +#endif + #endif // !_TARGET_X86_ ArgLocDesc* GetArgLocDescForStructInRegs() @@ -584,11 +599,17 @@ public: cSlots = 1; } +#ifdef _TARGET_ARM64_ + // Sanity check to make sure no caller is trying to get an ArgLocDesc that + // describes the return buffer reg field that's in the TransitionBlock. + _ASSERTE(argOffset != TransitionBlock::GetOffsetOfRetBuffArgReg()); +#endif + if (!TransitionBlock::IsStackArgumentOffset(argOffset)) { pLoc->m_idxGenReg = TransitionBlock::GetArgumentIndexFromOffset(argOffset); pLoc->m_cGenReg = cSlots; - } + } else { pLoc->m_idxStack = TransitionBlock::GetStackArgumentIndexFromOffset(argOffset); @@ -709,6 +730,13 @@ protected: void GetSimpleLoc(int offset, ArgLocDesc * pLoc) { WRAPPER_NO_CONTRACT; + +#ifdef CALLDESCR_RETBUFFARGREG + // Codepaths where this could happen have been removed. If this occurs, something + // has been missed and this needs another look. + _ASSERTE(offset != TransitionBlock::GetOffsetOfRetBuffArgReg()); +#endif + pLoc->Init(); pLoc->m_idxGenReg = TransitionBlock::GetArgumentIndexFromOffset(offset); pLoc->m_cGenReg = 1; @@ -747,7 +775,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetRetBuffArgOffset() // x86 is special as always ret += this->HasThis() ? offsetof(ArgumentRegisters, EDX) : offsetof(ArgumentRegisters, ECX); #elif _TARGET_ARM64_ - ret += (int) offsetof(ArgumentRegisters, x[8]); + ret = TransitionBlock::GetOffsetOfRetBuffArgReg(); #else if (this->HasThis()) ret += TARGET_POINTER_SIZE; @@ -929,6 +957,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset() m_dwFlags |= ITERATION_STARTED; } + // We're done going through the args for this MetaSig if (m_argNum == this->NumFixedArgs()) return TransitionBlock::InvalidOffset; @@ -1312,15 +1341,40 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset() } else { + // Only x0-x7 are valid argument registers (x8 is always the return buffer) if (m_idxGenReg + cArgSlots <= 8) { + // The entirety of the arg fits in the register slots. + int argOfs = TransitionBlock::GetOffsetOfArgumentRegisters() + m_idxGenReg * 8; m_idxGenReg += cArgSlots; return argOfs; } else { - m_idxGenReg = 8; +#ifdef _WIN32 + if (this->IsVarArg() && m_idxGenReg < 8) + { + // Address the Windows ARM64 varargs case where an arg is split between regs and stack. + // This can happen in the varargs case because the first 64 bytes of the stack are loaded + // into x0-x7, and any remaining stack arguments are placed normally. + int argOfs = TransitionBlock::GetOffsetOfArgumentRegisters() + m_idxGenReg * 8; + + // Increase m_idxStack to account for the space used for the remainder of the arg after + // register slots are filled. + m_idxStack += (m_idxGenReg + cArgSlots - 8); + + // We used up the remaining reg slots. + m_idxGenReg = 8; + + return argOfs; + } + else +#endif + { + // Don't use reg slots for this. It will be passed purely on the stack arg space. + m_idxGenReg = 8; + } } } |