}
regsToRestoreMask &= ~(RBM_FP | RBM_LR); // We'll restore FP/LR at the end, and post-index SP.
- calleeSaveSPOffset = totalFrameSize - genCountBits(regsToRestoreMask) * REGSIZE_BYTES;
+ // Compute callee save SP offset which is at the top of local frame while the FP/LR is saved at the bottom of stack.
+ calleeSaveSPOffset = compiler->compLclFrameSize + 2 * REGSIZE_BYTES;
}
else if (totalFrameSize <= 512)
{
}
regsToRestoreMask &= ~(RBM_FP | RBM_LR); // We'll restore FP/LR at the end, and post-index SP.
- calleeSaveSPOffset = totalFrameSize - genCountBits(regsToRestoreMask) * REGSIZE_BYTES;
+
+ // Compute callee save SP offset which is at the top of local frame while the FP/LR is saved at the bottom of stack.
+ calleeSaveSPOffset = compiler->compLclFrameSize + 2 * REGSIZE_BYTES;
}
else
{
assert((calleeSaveSPDeltaUnaligned % 8) == 0); // It better at least be 8 byte aligned.
calleeSaveSPDelta = AlignUp((UINT)calleeSaveSPDeltaUnaligned, STACK_ALIGN);
- calleeSaveSPOffset = calleeSaveSPDelta - calleeSaveSPDeltaUnaligned;
- assert((calleeSaveSPOffset == 0) || (calleeSaveSPOffset == REGSIZE_BYTES)); // At most one alignment slot between SP and where we store the callee-saved registers.
-
regsToRestoreMask &= ~(RBM_FP | RBM_LR); // We'll restore FP/LR at the end, and (hopefully) post-index SP.
int remainingFrameSz = totalFrameSize - calleeSaveSPDelta;
genEpilogRestoreRegPair(REG_FP, REG_LR, compiler->lvaOutgoingArgSpaceSize, remainingFrameSz, REG_IP0, nullptr);
}
}
- assert(calleeSaveSPOffset >= 0);
+
+ // Unlike frameType=1 or frameType=2 that restore SP at the end,
+ // frameType=3 already adjusted SP above to delete local frame.
+ // There is at most one alignment slot between SP and where we store the callee-saved registers.
+ calleeSaveSPOffset = calleeSaveSPDelta - calleeSaveSPDeltaUnaligned;
+ assert((calleeSaveSPOffset == 0) || (calleeSaveSPOffset == REGSIZE_BYTES));
}
else
{
// If the frame pointer is used, then we'll save FP/LR at the bottom of the stack.
// Otherwise, we won't store FP, and we'll store LR at the top, with the other callee-save
// registers (if any).
+
int initialStkOffs = 0;
+ if (info.compIsVarArgs)
+ {
+ // For varargs we always save all of the integer register arguments
+ // so that they are contiguous with the incoming stack arguments.
+ initialStkOffs = MAX_REG_ARG * REGSIZE_BYTES;
+ stkOffs -= initialStkOffs;
+ }
+
if (isFramePointerUsed())
{
// Subtract off FP and LR.
assert(compCalleeRegsPushed >= 2);
- initialStkOffs = (compCalleeRegsPushed - 2) * REGSIZE_BYTES;
+ stkOffs -= (compCalleeRegsPushed - 2) * REGSIZE_BYTES;
}
else
{
- initialStkOffs = compCalleeRegsPushed * REGSIZE_BYTES;
+ stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES;
}
- if (info.compIsVarArgs)
- {
- initialStkOffs += MAX_REG_ARG * REGSIZE_BYTES;
- }
-
- stkOffs -= initialStkOffs;
-
#else // !_TARGET_ARM64_
stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES;
#endif // !_TARGET_ARM64_
{
LIMITED_METHOD_CONTRACT;
-#if defined(_TARGET_ARM_) || defined(_TARGET_AMD64_)
+#if !defined(_TARGET_X86_)
if (hasRetBuffArg)
{
return GetEEFuncEntryPoint(VarargPInvokeStub_RetBuffArg);
WorkingDir=JIT\jit64\mcc\interop\mcc_i00
Expected=0
MaxAllowedDurationSeconds=600
-Categories=Pri0;EXPECTED_FAIL;NATIVE_INTEROP
+Categories=Pri0;JIT;EXPECTED_PASS
HostStyle=0
[mcc_i01.cmd_1693]
RelativePath=JIT\jit64\mcc\interop\mcc_i01\mcc_i01.cmd
WorkingDir=JIT\jit64\mcc\interop\mcc_i01
Expected=0
MaxAllowedDurationSeconds=600
-Categories=Pri0;EXPECTED_FAIL;NATIVE_INTEROP
+Categories=Pri0;JIT;EXPECTED_PASS
HostStyle=0
[mcc_i02.cmd_1694]
RelativePath=JIT\jit64\mcc\interop\mcc_i02\mcc_i02.cmd
WorkingDir=JIT\jit64\mcc\interop\mcc_i02
Expected=0
MaxAllowedDurationSeconds=600
-Categories=Pri0;EXPECTED_FAIL;NATIVE_INTEROP
+Categories=Pri0;JIT;EXPECTED_PASS
HostStyle=0
[mcc_i03.cmd_1695]
RelativePath=JIT\jit64\mcc\interop\mcc_i03\mcc_i03.cmd