From c3a7ed0dcc7a58eaaaee2fa5d5900bb0efb4694a Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Tue, 13 Sep 2016 05:48:27 -0700 Subject: [PATCH] Fix funceval for enregistered value types arguments. (#7149) Issue #7115. MethodDescCallSide.CallTargetWorker used by funceval needed to deal with enregistered 16 byte value types arguments not just return values. --- src/vm/callhelpers.cpp | 88 ++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/vm/callhelpers.cpp b/src/vm/callhelpers.cpp index 9152f71..addd519 100644 --- a/src/vm/callhelpers.cpp +++ b/src/vm/callhelpers.cpp @@ -16,6 +16,8 @@ // To include declaration of "SignatureNative" #include "runtimehandles.h" +#include "invokeutil.h" +#include "argdestination.h" #if defined(FEATURE_MULTICOREJIT) && defined(_DEBUG) @@ -536,7 +538,7 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT * } #endif - int ofs; + int ofs; for (; TransitionBlock::InvalidOffset != (ofs = m_argIt.GetNextOffset()); arg++) { #ifdef CALLDESCR_REGTYPEMAP @@ -567,46 +569,56 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT * } #endif // CHECK_APP_DOMAIN_LEAKS -#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) - _ASSERTE(ofs != TransitionBlock::StructInRegsOffset); -#endif - PVOID pDest = pTransitionBlock + ofs; + ArgDestination argDest(pTransitionBlock, ofs, m_argIt.GetArgLocDescForStructInRegs()); UINT32 stackSize = m_argIt.GetArgSize(); - switch (stackSize) + // We need to pass in a pointer, but be careful of the ARG_SLOT calling convention. We might already have a pointer in the ARG_SLOT. + PVOID pSrc = stackSize > sizeof(ARG_SLOT) ? (LPVOID)ArgSlotToPtr(pArguments[arg]) : (LPVOID)ArgSlotEndianessFixup((ARG_SLOT*)&pArguments[arg], stackSize); + +#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + if (argDest.IsStructPassedInRegs()) + { + TypeHandle th; + m_argIt.GetArgType(&th); + + argDest.CopyStructToRegisters(pSrc, th.AsMethodTable()->GetNumInstanceFieldBytes(), 0); + } + else +#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING { - case 1: - case 2: - case 4: - *((INT32*)pDest) = (INT32)pArguments[arg]; - break; - - case 8: - *((INT64*)pDest) = pArguments[arg]; - break; - - default: - // The ARG_SLOT contains a pointer to the value-type -#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE - if (m_argIt.IsArgPassedByRef()) - { - // We need to pass in a pointer, but be careful of the ARG_SLOT calling convention. - // We might already have a pointer in the ARG_SLOT - *(PVOID*)pDest = stackSize>sizeof(ARG_SLOT) ? - (LPVOID)ArgSlotToPtr(pArguments[arg]) : - (LPVOID)ArgSlotEndianessFixup((ARG_SLOT*)&pArguments[arg], stackSize); - } - else -#endif // ENREGISTERED_PARAMTYPE_MAXSIZE - if (stackSize>sizeof(ARG_SLOT)) - { - CopyMemory(pDest, ArgSlotToPtr(pArguments[arg]), stackSize); - } - else - { - CopyMemory(pDest, (LPVOID) (&pArguments[arg]), stackSize); - } - break; + PVOID pDest = argDest.GetDestinationAddress(); + + switch (stackSize) + { + case 1: + case 2: + case 4: + *((INT32*)pDest) = (INT32)pArguments[arg]; + break; + + case 8: + *((INT64*)pDest) = pArguments[arg]; + break; + + default: + // The ARG_SLOT contains a pointer to the value-type + #ifdef ENREGISTERED_PARAMTYPE_MAXSIZE + if (m_argIt.IsArgPassedByRef()) + { + *(PVOID*)pDest = pSrc; + } + else + #endif // ENREGISTERED_PARAMTYPE_MAXSIZE + if (stackSize > sizeof(ARG_SLOT)) + { + CopyMemory(pDest, ArgSlotToPtr(pArguments[arg]), stackSize); + } + else + { + CopyMemory(pDest, (LPVOID) (&pArguments[arg]), stackSize); + } + break; + } } } -- 2.7.4