diff options
author | Kyungwoo Lee <kyulee@microsoft.com> | 2016-04-22 06:49:35 -0700 |
---|---|---|
committer | Kyungwoo Lee <kyulee@microsoft.com> | 2016-04-22 11:30:12 -0700 |
commit | 8737b292d81a753fc78ba600f574edaddfc37834 (patch) | |
tree | b4212ee072a9108f5318365f1341ab07cc831e28 /src | |
parent | 4e769b7658f239cff2a0c80b673b91de8d686388 (diff) | |
download | coreclr-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.cpp | 6 | ||||
-rw-r--r-- | src/jit/codegencommon.cpp | 5 | ||||
-rw-r--r-- | src/jit/lclvars.cpp | 30 |
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) |