summaryrefslogtreecommitdiff
path: root/src/jit/morph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/morph.cpp')
-rw-r--r--src/jit/morph.cpp40
1 files changed, 29 insertions, 11 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 94b176eae3..f9c81819ae 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -1473,13 +1473,13 @@ void fgArgInfo::ArgsComplete()
continue;
#endif
}
-#if defined(_TARGET_ARM_)
+#if FEATURE_ARG_SPLIT
else if (curArgTabEntry->isSplit)
{
hasStructRegArg = true;
hasStackArgs = true;
}
-#endif // _TARGET_ARM_
+#endif // FEATURE_ARG_SPLIT
else // we have a register argument, next we look for a struct type.
{
if (varTypeIsStruct(argx) UNIX_AMD64_ABI_ONLY(|| curArgTabEntry->isStruct))
@@ -1599,7 +1599,7 @@ void fgArgInfo::ArgsComplete()
{
prevArgTabEntry->needPlace = true;
}
-#if defined(_TARGET_ARM_)
+#if FEATURE_ARG_SPLIT
else if (prevArgTabEntry->isSplit)
{
prevArgTabEntry->needPlace = true;
@@ -3323,6 +3323,12 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
}
}
+#if defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_)
+ // Make sure for vararg methods isHfaArg is not
+ // true.
+ isHfaArg = callIsVararg ? false : isHfaArg;
+#endif // defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_)
+
if (isHfaArg)
{
// If we have a HFA struct it's possible we transition from a method that originally
@@ -3972,13 +3978,25 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
//
if (!isRegArg && (size > 1))
{
- // We also must update intArgRegNum so that we no longer try to
- // allocate any new general purpose registers for args
- //
- intArgRegNum = maxRegArgs;
+#if defined(_TARGET_WINDOWS_)
+ // Arm64 windows native varargs allows splitting a 16 byte struct between stack
+ // and the last general purpose register.
+ if (callIsVararg)
+ {
+ // Override the decision and force a split.
+ isRegArg = isRegArg = (intArgRegNum + (size - 1)) <= maxRegArgs;
+ }
+ else
+#endif // defined(_TARGET_WINDOWS_)
+ {
+ // We also must update intArgRegNum so that we no longer try to
+ // allocate any new general purpose registers for args
+ //
+ intArgRegNum = maxRegArgs;
+ }
}
}
-#else // not _TARGET_ARM_ or _TARGET_ARM64_
+#else // not _TARGET_ARM_ or _TARGET_ARM64_
#if defined(UNIX_AMD64_ABI)
@@ -4177,7 +4195,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
else
#endif // defined(UNIX_AMD64_ABI)
{
-#ifdef _TARGET_ARM_
+#if FEATURE_ARG_SPLIT
// Check for a split (partially enregistered) struct
if (!passUsingFloatRegs && (intArgRegNum + size) > MAX_REG_ARG)
{
@@ -4189,7 +4207,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
call->fgArgInfo->SplitArg(argIndex, numRegsPartial, size - numRegsPartial);
fgPtrArgCntCur += size - numRegsPartial;
}
-#endif // _TARGET_ARM_
+#endif // FEATURE_ARG_SPLIT
newArgEntry->SetMultiRegNums();
if (passUsingFloatRegs)
@@ -4230,7 +4248,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
else
{
// This is a stack argument - put it in the table
- call->fgArgInfo->AddStkArg(argIndex, argx, args, size, argAlign, isStructArg);
+ call->fgArgInfo->AddStkArg(argIndex, argx, args, size, argAlign, isStructArg, callIsVararg);
}
}