summaryrefslogtreecommitdiff
path: root/src/jit/lclvars.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/lclvars.cpp')
-rw-r--r--src/jit/lclvars.cpp95
1 files changed, 61 insertions, 34 deletions
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index e0c4f75599..f0015b2e8f 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -131,46 +131,28 @@ void Compiler::lvaInitTypeRef()
//
const bool hasRetBuffArg = impMethodInfo_hasRetBuffArg(info.compMethodInfo);
- // Change the compRetNativeType if we are returning a struct by value in a register
+ // Possibly change the compRetNativeType from TYP_STRUCT to a "primitive" type
+ // when we are returning a struct by value and it fits in one register
+ //
if (!hasRetBuffArg && varTypeIsStruct(info.compRetNativeType))
{
-#if FEATURE_MULTIREG_RET && defined(FEATURE_HFA)
- if (!info.compIsVarArgs && IsHfa(info.compMethodInfo->args.retTypeClass))
- {
- info.compRetNativeType = TYP_STRUCT;
- }
- else
-#endif // FEATURE_MULTIREG_RET && defined(FEATURE_HFA)
+ CORINFO_CLASS_HANDLE retClsHnd = info.compMethodInfo->args.retTypeClass;
+
+ Compiler::structPassingKind howToReturnStruct;
+ var_types returnType = getReturnTypeForStruct(retClsHnd, &howToReturnStruct);
+
+ if (howToReturnStruct == SPK_PrimitiveType)
{
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
- ReturnTypeDesc retTypeDesc;
- retTypeDesc.InitializeReturnType(this, info.compMethodInfo->args.retTypeClass);
+ assert(returnType != TYP_UNKNOWN);
+ assert(returnType != TYP_STRUCT);
- if (retTypeDesc.GetReturnRegCount() > 1)
- {
- info.compRetNativeType = TYP_STRUCT;
- }
- else
- {
- info.compRetNativeType = retTypeDesc.GetReturnRegType(0);
- }
-#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING
- // Check for TYP_STRUCT argument that can fit into a single register
- structPassingKind howToReturnStruct;
- var_types returnType = getReturnTypeForStruct(info.compMethodInfo->args.retTypeClass, &howToReturnStruct);
- assert(howToReturnStruct != SPK_ByReference); // hasRetBuffArg is false, so we can't have this answer here
info.compRetNativeType = returnType;
- if (returnType == TYP_UNKNOWN)
- {
- assert(!"Unexpected size when returning struct by value");
- }
// ToDo: Refactor this common code sequence into its own method as it is used 4+ times
if ((returnType == TYP_LONG) && (compLongUsed == false))
compLongUsed = true;
else if (((returnType == TYP_FLOAT) || (returnType == TYP_DOUBLE)) && (compFloatingPointUsed == false))
compFloatingPointUsed = true;
-#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING
}
}
@@ -548,8 +530,8 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo * varDscInfo)
CORINFO_CLASS_HANDLE typeHnd = NULL;
CorInfoTypeWithMod corInfoType = info.compCompHnd->getArgType(&info.compMethodInfo->args,
- argLst,
- &typeHnd);
+ argLst,
+ &typeHnd);
varDsc->lvIsParam = 1;
#if ASSERTION_PROP
varDsc->lvSingleDef = 1;
@@ -917,13 +899,23 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo * varDscInfo)
} // end if (canPassArgInRegisters)
else
{
-#ifdef _TARGET_ARM_
+#if defined(_TARGET_ARM_)
+
varDscInfo->setAllRegArgUsed(argType);
if (varTypeIsFloating(argType))
{
varDscInfo->setAnyFloatStackArgs();
}
-#endif
+
+#elif defined(_TARGET_ARM64_)
+
+ // If we needed to use the stack in order to pass this argument then
+ // record the fact that we have used up any remaining registers of this 'type'
+ // This prevents any 'backfilling' from occuring on ARM64
+ //
+ varDscInfo->setAllRegArgUsed(argType);
+
+#endif // _TARGET_XXX_
}
#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
@@ -1944,6 +1936,37 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(D
#endif
}
+// Returns true if this local var is a multireg struct
+bool Compiler::lvaIsMultiregStruct(LclVarDsc* varDsc)
+{
+ if (varDsc->TypeGet() == TYP_STRUCT)
+ {
+ CORINFO_CLASS_HANDLE clsHnd = varDsc->lvVerTypeInfo.GetClassHandleForValueClass();
+ structPassingKind howToPassStruct;
+
+ var_types type = getArgTypeForStruct(clsHnd,
+ &howToPassStruct,
+ varDsc->lvExactSize);
+
+ if (howToPassStruct == SPK_ByValueAsHfa)
+ {
+ assert(type = TYP_STRUCT);
+ return true;
+ }
+
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) || defined(_TARGET_ARM64_)
+ if (howToPassStruct == SPK_ByValue)
+ {
+ assert(type = TYP_STRUCT);
+ return true;
+ }
+#endif
+
+ }
+ return false;
+}
+
+
/*****************************************************************************
* Set the lvClass for a local variable of a struct type */
@@ -5952,7 +5975,7 @@ void Compiler::lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t
}
else if (varDsc->lvOnFrame == 0)
{
- printf("multi-reg ");
+ printf("registers ");
}
else
{
@@ -5985,12 +6008,16 @@ void Compiler::lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t
if (varDsc->lvLclFieldExpr) printf("F");
if (varDsc->lvLclBlockOpAddr) printf("B");
if (varDsc->lvLiveAcrossUCall) printf("U");
+ if (varDsc->lvIsMultiRegArg) printf("A");
+ if (varDsc->lvIsMultiRegRet) printf("R");
#ifdef JIT32_GCENCODER
if (varDsc->lvPinned) printf("P");
#endif // JIT32_GCENCODER
printf("]");
}
+ if (varDsc->lvIsMultiRegArg) printf(" multireg-arg");
+ if (varDsc->lvIsMultiRegRet) printf(" multireg-ret");
if (varDsc->lvMustInit) printf(" must-init");
if (varDsc->lvAddrExposed) printf(" addr-exposed");
if (varDsc->lvHasLdAddrOp) printf(" ld-addr-op");