Skip to content

tionReflection invoke arm64 saved #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/vm/argdestination.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class ArgDestination
LIMITED_METHOD_CONTRACT;
#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
_ASSERTE((argLocDescForStructInRegs != NULL) || (offset != TransitionBlock::StructInRegsOffset));
#elif defined(_TARGET_ARM64_)
// This assert is not interesting on arm64. argLocDescForStructInRegs could be
// initialized if the args are being enregistered.
#else
_ASSERTE(argLocDescForStructInRegs == NULL);
#endif
Expand All @@ -42,6 +45,44 @@ class ArgDestination
return dac_cast<PTR_VOID>(dac_cast<TADDR>(m_base) + m_offset);
}

#if defined(_TARGET_ARM64_)

// Returns true if the ArgDestination represents an HFA struct
bool IsHFA()
{
return m_argLocDescForStructInRegs != NULL;
}

// Copy struct argument into registers described by the current ArgDestination.
// Arguments:
// src = source data of the structure
// fieldBytes - size of the structure
void CopyHFAStructToRegister(void *src, int fieldBytes)
{
// We are either copying either a float or double HFA and need to
// enregister each field.

int floatRegCount = m_argLocDescForStructInRegs->m_cFloatReg;
bool typeFloat = m_argLocDescForStructInRegs->m_isSinglePrecision;
void* dest = this->GetDestinationAddress();

if (typeFloat)
{
for (int i = 0; i < floatRegCount; ++i)
{
// Copy 4 bytes on 8 bytes alignment
*((UINT64*)dest + i) = *((UINT32*)src + i);
}
}
else
{
// We can just do a memcpy.
memcpyNoGCRefs(dest, src, fieldBytes);
}
}

#endif // defined(_TARGET_ARM64_)

#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)

// Returns true if the ArgDestination represents a struct passed in registers.
Expand Down
29 changes: 21 additions & 8 deletions src/vm/callingconvention.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,26 @@ BOOL IsRetBuffPassedAsFirstArg();
// and possibly on to the stack as well.
struct ArgLocDesc
{
int m_idxFloatReg; // First floating point register used (or -1)
int m_cFloatReg; // Count of floating point registers used (or 0)
int m_idxFloatReg; // First floating point register used (or -1)
int m_cFloatReg; // Count of floating point registers used (or 0)

int m_idxGenReg; // First general register used (or -1)
int m_cGenReg; // Count of general registers used (or 0)
int m_idxGenReg; // First general register used (or -1)
int m_cGenReg; // Count of general registers used (or 0)

int m_idxStack; // First stack slot used (or -1)
int m_cStack; // Count of stack slots used (or 0)
int m_idxStack; // First stack slot used (or -1)
int m_cStack; // Count of stack slots used (or 0)

#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)

EEClass* m_eeClass; // For structs passed in register, it points to the EEClass of the struct
EEClass* m_eeClass; // For structs passed in register, it points to the EEClass of the struct

#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING

#if defined(_TARGET_ARM64_)
bool m_isSinglePrecision; // For determining if HFA is single or double
// precision
#endif // defined(_TARGET_ARM64_)

#if defined(_TARGET_ARM_)
BOOL m_fRequires64BitAlignment; // True if the argument should always be aligned (in registers or on the stack
#endif
Expand All @@ -70,6 +75,9 @@ struct ArgLocDesc
#if defined(_TARGET_ARM_)
m_fRequires64BitAlignment = FALSE;
#endif
#if defined(_TARGET_ARM64_)
m_isSinglePrecision = FALSE;
#endif // defined(_TARGET_ARM64_)
#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
m_eeClass = NULL;
#endif
Expand Down Expand Up @@ -556,7 +564,10 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE
if (!m_argTypeHandle.IsNull() && m_argTypeHandle.IsHFA())
{
CorElementType type = m_argTypeHandle.GetHFAType();
pLoc->m_cFloatReg = (type == ELEMENT_TYPE_R4)? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double);
bool isFloatType = (type == ELEMENT_TYPE_R4);

pLoc->m_cFloatReg = isFloatType ? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double);
pLoc->m_isSinglePrecision = isFloatType;
}
else
{
Expand Down Expand Up @@ -1103,7 +1114,9 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
// Handle HFAs: packed structures of 1-4 floats or doubles that are passed in FP argument
// registers if possible.
if (thValueType.IsHFA())
{
fFloatingPoint = true;
}
#endif

break;
Expand Down
7 changes: 7 additions & 0 deletions src/vm/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,13 @@ void STDCALL CopyValueClassArgUnchecked(ArgDestination *argDest, void* src, Meth
return;
}

#elif defined(_TARGET_ARM64_)

if (argDest->IsHFA())
{
argDest->CopyHFAStructToRegister(src, pMT->GetAlignedNumInstanceFieldBytes());
}

#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
// destOffset is only valid for Nullable<T> passed in registers
_ASSERTE(destOffset == 0);
Expand Down
10 changes: 10 additions & 0 deletions src/vm/reflectioninvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1383,8 +1383,18 @@ FCIMPL4(Object*, RuntimeMethodHandle::InvokeMethod,
}
#endif

#ifdef defined(_TARGET_ARM64_)
ArgLocDesc argLocDescForStructInRegs;
argit.GetArgLoc(ofs, &argLocDescForStructInRegs);

ArgDestination argDest(pTransitionBlock, ofs, &argLocDescForStructInRegs);

#else // !_TARGET_ARM64_

ArgDestination argDest(pTransitionBlock, ofs, argit.GetArgLocDescForStructInRegs());

#endif // defined(_TARGET_ARM64_)

if(needsStackCopy)
{
MethodTable * pMT = th.GetMethodTable();
Expand Down