Skip to content

Commit

Permalink
amend the LoongArch64-ABI for GCstress and NullableObject. (#72573)
Browse files Browse the repository at this point in the history
  • Loading branch information
shushanhf authored Jul 22, 2022
1 parent a8ef21c commit 0e7432f
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 62 deletions.
52 changes: 42 additions & 10 deletions src/coreclr/vm/argdestination.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,13 @@ class ArgDestination
}

#ifndef DACCESS_COMPILE
void CopyStructToRegisters(void *src, int fieldBytes)
// Copy struct argument into registers described by the current ArgDestination.
// Arguments:
// src = source data of the structure
// fieldBytes - size of the structure
// destOffset - nonzero when copying values into Nullable<T>, it is the offset
// of the T value inside of the Nullable<T>
void CopyStructToRegisters(void *src, int fieldBytes, int destOffset)
{
_ASSERTE(IsStructPassedInRegs());
_ASSERTE(fieldBytes <= 16);
Expand All @@ -106,33 +112,59 @@ class ArgDestination
}
else if ((m_argLocDescForStructInRegs->m_structFields & STRUCT_FLOAT_FIELD_FIRST) != 0)
{ // the first field is float or double.
_ASSERTE(m_argLocDescForStructInRegs->m_cFloatReg == 1);
_ASSERTE(m_argLocDescForStructInRegs->m_cGenReg == 1);
_ASSERTE((m_argLocDescForStructInRegs->m_structFields & STRUCT_FLOAT_FIELD_SECOND) == 0);//the second field is integer.

if ((m_argLocDescForStructInRegs->m_structFields & STRUCT_FIRST_FIELD_SIZE_IS8) == 0)
{
*(INT64*)((char*)m_base + argOfs) = *(INT32*)src; // the first field is float
}
else
{
*(UINT64*)((char*)m_base + argOfs) = *(UINT64*)src; // the first field is double.
_ASSERTE(m_argLocDescForStructInRegs->m_cFloatReg == 1);
_ASSERTE(m_argLocDescForStructInRegs->m_cGenReg == 1);
_ASSERTE((m_argLocDescForStructInRegs->m_structFields & STRUCT_FLOAT_FIELD_SECOND) == 0);//the second field is integer.
}

argOfs = TransitionBlock::GetOffsetOfArgumentRegisters() + m_argLocDescForStructInRegs->m_idxGenReg * 8;
if ((m_argLocDescForStructInRegs->m_structFields & STRUCT_HAS_8BYTES_FIELDS_MASK) != 0)
{
*(UINT64*)((char*)m_base + argOfs) = *((UINT64*)src + 1);
}
else
{
*(INT64*)((char*)m_base + argOfs) = *((INT32*)src + 1); // the second field is int32.
}
}
else if ((m_argLocDescForStructInRegs->m_structFields & STRUCT_FLOAT_FIELD_SECOND) != 0)
{ // the second field is float or double.
*(UINT64*)((char*)m_base + argOfs) = *(UINT64*)src; // NOTE: here ignoring the first size.
if ((m_argLocDescForStructInRegs->m_structFields & STRUCT_HAS_8BYTES_FIELDS_MASK) == 0)
*(UINT64*)((char*)m_base + argOfs) = *((INT32*)src + 1); // the second field is int32.
else
*(UINT64*)((char*)m_base + argOfs) = *((UINT64*)src + 1);
_ASSERTE(m_argLocDescForStructInRegs->m_cFloatReg == 1);
_ASSERTE(m_argLocDescForStructInRegs->m_cGenReg == 1);
_ASSERTE((m_argLocDescForStructInRegs->m_structFields & STRUCT_FLOAT_FIELD_FIRST) == 0);//the first field is integer.
argOfs = TransitionBlock::GetOffsetOfArgumentRegisters() + m_argLocDescForStructInRegs->m_idxGenReg * 8;

// destOffset - nonzero when copying values into Nullable<T>, it is the offset of the T value inside of the Nullable<T>.
// here the first field maybe Nullable.
if ((m_argLocDescForStructInRegs->m_structFields & STRUCT_HAS_8BYTES_FIELDS_MASK) == 0)
{
// the second field is float.
*(INT64*)((char*)m_base + argOfs) = destOffset == 0 ? *((INT32*)src + 1) : *(INT32*)src;
}
else
{
// the second field is double.
*(UINT64*)((char*)m_base + argOfs) = destOffset == 0 ? *((UINT64*)src + 1) : *(UINT64*)src;
}

if (0 == destOffset)
{
// NOTE: here ignoring the first size.
argOfs = TransitionBlock::GetOffsetOfArgumentRegisters() + m_argLocDescForStructInRegs->m_idxGenReg * 8;
*(UINT64*)((char*)m_base + argOfs) = *(UINT64*)src;
}
}
else
{
_ASSERTE(!"---------UNReachable-------LoongArch64!!!");
}
}
#endif // !DACCESS_COMPILE

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/callhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
#elif defined(TARGET_LOONGARCH64)
if (argDest.IsStructPassedInRegs())
{
argDest.CopyStructToRegisters(pSrc, stackSize);
argDest.CopyStructToRegisters(pSrc, stackSize, 0);
}
else
#endif // TARGET_LOONGARCH64
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/gcinfodecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD)
{
_ASSERTE(regNum >= 0 && regNum <= 31);

return (regNum <= 21 && regNum >= 4);
return (regNum <= 21 && ((regNum >= 4) || (regNum == 1)));
}

bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD)
Expand Down
Loading

0 comments on commit 0e7432f

Please sign in to comment.