if (compiler->compMethodReturnsMultiRegRetType())
{
ReturnTypeDesc retTypeDesc;
- retTypeDesc.Initialize(compiler, compiler->info.compMethodInfo->args.retTypeClass);
+ retTypeDesc.InitializeReturnType(compiler, compiler->info.compMethodInfo->args.retTypeClass);
unsigned regCount = retTypeDesc.GetReturnRegCount();
// Only x86 and x64 Unix ABI allows multi-reg return and
assert(varDsc->lvIsMultiRegArgOrRet);
ReturnTypeDesc retTypeDesc;
- retTypeDesc.Initialize(compiler, varDsc->lvVerTypeInfo.GetClassHandle());
+ retTypeDesc.InitializeReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle());
unsigned regCount = retTypeDesc.GetReturnRegCount();
assert(regCount == MAX_RET_REG_COUNT);
// Return Value
// None
//
-// Note:
-// Right now it is implemented only for x64 unix.
-void ReturnTypeDesc::Initialize(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd)
+void ReturnTypeDesc::InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd)
{
assert(!m_inited);
if (structDesc.passedInRegisters)
{
- if (structDesc.eightByteCount == 1)
- {
- m_regType0 = comp->GetEightByteType(structDesc, 0);
- }
- else
+ for (int i=0; i<structDesc.eightByteCount; i++)
{
- assert(structDesc.eightByteCount == 2);
- m_regType0 = comp->GetEightByteType(structDesc, 0);
- m_regType1 = comp->GetEightByteType(structDesc, 1);
+ assert(i < MAX_RET_REG_COUNT);
+ m_regType[i] = comp->GetEightByteType(structDesc, i);
}
}
#elif defined(_TARGET_X86_)
- // TODO-X86: Assumes we are only using ReturnTypeDesc for longs on x86. Will
- // need to be updated in the future to handle other return types
- m_regType0 = TYP_INT;
- m_regType1 = TYP_INT;
+ // TODO-X86: Assumes we are only using ReturnTypeDesc for longs on x86.
+ // Will need to be updated in the future to handle other return types
+ assert(MAX_RET_REG_COUNT == 2);
+ m_regType[0] = TYP_INT;
+ m_regType[1] = TYP_INT;
#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
#ifdef DEBUG
struct ReturnTypeDesc
{
private:
- var_types m_regType0;
- var_types m_regType1;
+ var_types m_regType[MAX_RET_REG_COUNT];
#ifdef DEBUG
bool m_inited;
Reset();
}
- // Initialize type descriptor given its type handle
- void Initialize(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd);
+ // Initialize the return type descriptor given its type handle
+ void InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd);
// Reset type descriptor to defaults
void Reset()
{
- m_regType0 = TYP_UNKNOWN;
- m_regType1 = TYP_UNKNOWN;
-
+ for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
+ {
+ m_regType[i] = TYP_UNKNOWN;
+ }
#ifdef DEBUG
m_inited = false;
#endif
assert(m_inited);
int regCount = 0;
- if (m_regType0 != TYP_UNKNOWN)
+ for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
{
- ++regCount;
-
- if (m_regType1 != TYP_UNKNOWN)
+ if (m_regType[i] == TYP_UNKNOWN)
{
- ++regCount;
+ break;
}
+ // otherwise
+ regCount++;
}
- else
+
+#ifdef DEBUG
+ // Any remaining elements in m_regTypes[] should also be TYP_UNKNOWN
+ for (unsigned i = regCount+1; i < MAX_RET_REG_COUNT; ++i)
{
- // If regType0 is TYP_UNKNOWN then regType1 must also be TYP_UNKNOWN.
- assert(m_regType1 == TYP_UNKNOWN);
+ assert(m_regType[i] == TYP_UNKNOWN);
}
+#endif
+
return regCount;
}
// Return Value:
// Returns true if the type is returned in multiple return registers.
// False otherwise.
+ // Note that we only have to examine the first two values to determine this
+ //
bool IsMultiRegRetType() const
{
- return GetReturnRegCount() > 1;
+ if (MAX_RET_REG_COUNT < 2)
+ {
+ return false;
+ }
+ else
+ {
+ return ((m_regType[0] != TYP_UNKNOWN) &&
+ (m_regType[1] != TYP_UNKNOWN));
+ }
}
//--------------------------------------------------------------------------
//
// Return Value:
// var_type of the return register specified by its index.
- // Return TYP_UNKNOWN if index > number of return registers.
+ // asserts if the index does not have a valid register return type.
+
var_types GetReturnRegType(unsigned index)
{
- assert(index < GetReturnRegCount());
-
- if (index == 0)
- {
- return m_regType0;
- }
- else if (index == 1)
- {
- return m_regType1;
- }
+ var_types result = m_regType[index];
+ assert(result != TYP_UNKNOWN);
- return TYP_UNKNOWN;
+ return result;
}
// Get ith ABI return register
// Return Value:
// None.
//
- // TODO-ARM: Implement this routine for Arm64 and Arm32
- // TODO-X86: Implement this routine for x86
void SetRegNumByIdx(regNumber reg, unsigned idx)
{
assert(idx < MAX_RET_REG_COUNT);
{
gtRegNum = reg;
}
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
+#if FEATURE_MULTIREG_RET
else
{
gtOtherRegs[idx - 1] = reg;
call->gtCall.gtRetClsHnd = retClsHnd;
+ GenTreeCall* callNode = call->AsCall();
+
+#if FEATURE_MULTIREG_RET
+ // Initialize Return type descriptor of call node
+ ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc();
+ retTypeDesc->InitializeReturnType(this, retClsHnd);
+#endif // FEATURE_MULTIREG_RET
+
#if FEATURE_MULTIREG_RET && defined(FEATURE_HFA)
// There is no fixup necessary if the return type is a HFA struct.
// HFA structs are returned in registers for ARM32 and ARM64
}
#elif defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
- GenTreeCall* callNode = call->AsCall();
-
// Not allowed for FEATURE_CORCLR which is the only SKU available for System V OSs.
assert(!callNode->IsVarargs() && "varargs not allowed for System V OSs.");
// single eightbyte return type below.
callNode->gtReturnType = call->gtType;
- // Initialize Return type descriptor of call node
- ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc();
- retTypeDesc->Initialize(this, retClsHnd);
-
unsigned retRegCount = retTypeDesc->GetReturnRegCount();
if (retRegCount != 0)
{
// Initialize Return type descriptor of call node
ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc();
- retTypeDesc->Initialize(this, retClsHnd);
+ retTypeDesc->InitializeReturnType(this, retClsHnd);
unsigned retRegCount = retTypeDesc->GetReturnRegCount();
// must be a long returned in two registers
// Same as !IsHfa but just don't bother with impAssignStructPtr.
#else // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
ReturnTypeDesc retTypeDesc;
- retTypeDesc.Initialize(this, retClsHnd);
+ retTypeDesc.InitializeReturnType(this, retClsHnd);
unsigned retRegCount = retTypeDesc.GetReturnRegCount();
if (retRegCount != 0)
{
#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
ReturnTypeDesc retTypeDesc;
- retTypeDesc.Initialize(this, info.compMethodInfo->args.retTypeClass);
+ retTypeDesc.InitializeReturnType(this, info.compMethodInfo->args.retTypeClass);
if (retTypeDesc.GetReturnRegCount() > 1)
{
GenTreeCall* callNode = tree->AsCall();
ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc();
retTypeDesc->Reset();
- retTypeDesc->Initialize(this, callNode->gtRetClsHnd);
+ retTypeDesc->InitializeReturnType(this, callNode->gtRetClsHnd);
callNode->ClearOtherRegs();
NYI("Helper with TYP_LONG return type");