summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKyungwoo Lee <kyulee@microsoft.com>2016-04-22 06:49:35 -0700
committerKyungwoo Lee <kyulee@microsoft.com>2016-04-22 11:30:12 -0700
commit8737b292d81a753fc78ba600f574edaddfc37834 (patch)
treeb4212ee072a9108f5318365f1341ab07cc831e28 /src
parent4e769b7658f239cff2a0c80b673b91de8d686388 (diff)
downloadcoreclr-8737b292d81a753fc78ba600f574edaddfc37834.tar.gz
coreclr-8737b292d81a753fc78ba600f574edaddfc37834.tar.bz2
coreclr-8737b292d81a753fc78ba600f574edaddfc37834.zip
ARM64: Fix Frame with VarArg
Fixes https://github.com/dotnet/coreclr/issues/4424 JIT homes incoming vararg (8) registers to the top of the stack. When stack location is computed for local vars, JIT didn't take it into consideration causing the overlapped stack offsets for local vars and varargs. The stack offsets of local vars corresponding to varargs should point to this home area instead of the newly alloacted slot.
Diffstat (limited to 'src')
-rw-r--r--src/jit/codegenarm64.cpp6
-rw-r--r--src/jit/codegencommon.cpp5
-rw-r--r--src/jit/lclvars.cpp30
3 files changed, 38 insertions, 3 deletions
diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp
index a79a1279e8..dc13b31746 100644
--- a/src/jit/codegenarm64.cpp
+++ b/src/jit/codegenarm64.cpp
@@ -1135,6 +1135,12 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
unsigned saveRegsCount = genCountBits(rsMaskSaveRegs);
unsigned saveRegsPlusPSPSize = saveRegsCount * REGSIZE_BYTES + /* PSPSym */ REGSIZE_BYTES;
+ if (compiler->info.compIsVarArgs)
+ {
+ // For varargs we always save all of the integer register arguments
+ // so that they are contiguous with the incoming stack arguments.
+ saveRegsPlusPSPSize += MAX_REG_ARG * REGSIZE_BYTES;
+ }
unsigned saveRegsPlusPSPSizeAligned = (unsigned)roundUp(saveRegsPlusPSPSize, STACK_ALIGN);
assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0);
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index ab65d576c4..7daaff4826 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -3099,7 +3099,10 @@ void CodeGen::genGenerateCode(void * * codePtr,
trackedStackPtrsContig = false;
#elif defined(_TARGET_ARM_)
// On arm due to prespilling of arguments, tracked stk-ptrs may not be contiguous
- trackedStackPtrsContig = !compiler->opts.compDbgEnC && !compiler->compIsProfilerHookNeeded();
+ trackedStackPtrsContig = !compiler->opts.compDbgEnC && !compiler->compIsProfilerHookNeeded();
+#elif defined(_TARGET_ARM64_)
+ // Incoming vararg registers are homed on the top of the stack. Tracked var may not be contiguous.
+ trackedStackPtrsContig = !compiler->opts.compDbgEnC && !compiler->info.compIsVarArgs;
#else
trackedStackPtrsContig = !compiler->opts.compDbgEnC;
#endif
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index d09f123a32..d5f760deee 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -4731,16 +4731,25 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
// 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 (isFramePointerUsed())
{
// Subtract off FP and LR.
assert(compCalleeRegsPushed >= 2);
- stkOffs -= (compCalleeRegsPushed - 2) * REGSIZE_BYTES;
+ initialStkOffs = (compCalleeRegsPushed - 2) * REGSIZE_BYTES;
}
else
{
- stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES;
+ initialStkOffs = compCalleeRegsPushed * REGSIZE_BYTES;
}
+
+ if (info.compIsVarArgs)
+ {
+ initialStkOffs += MAX_REG_ARG * REGSIZE_BYTES;
+ }
+
+ stkOffs -= initialStkOffs;
+
#else // !_TARGET_ARM64_
stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES;
#endif // !_TARGET_ARM64_
@@ -5093,6 +5102,15 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
if (!varDsc->lvIsRegArg)
continue;
+#ifdef _TARGET_ARM64_
+ if (info.compIsVarArgs)
+ {
+ // Stack offset to varargs (parameters) should point to home area which will be preallocated.
+ varDsc->lvStkOffs = -initialStkOffs + genMapIntRegNumToRegArgNum(varDsc->GetArgReg()) * REGSIZE_BYTES;
+ continue;
+ }
+#endif
+
#ifdef _TARGET_ARM_
// On ARM we spill the registers in codeGen->regSet.rsMaskPreSpillRegArg
// in the prolog, thus they don't need stack frame space.
@@ -5321,6 +5339,14 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
// compLclFrameSize equals our negated virtual stack offset minus the pushed registers and return address
// and the pushed frame pointer register which for some strange reason isn't part of 'compCalleeRegsPushed'.
int pushedCount = compCalleeRegsPushed;
+
+#ifdef _TARGET_ARM64_
+ if (info.compIsVarArgs)
+ {
+ pushedCount += MAX_REG_ARG;
+ }
+#endif
+
#ifdef _TARGET_XARCH_
if (codeGen->doubleAlignOrFramePointerUsed())
pushedCount += 1; // pushed EBP (frame pointer)