diff options
author | Reid Kleckner <rnk@google.com> | 2015-10-16 23:43:27 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2015-10-16 23:43:27 +0000 |
commit | 28e490342b570ca1f261811e98f31b52e7111cec (patch) | |
tree | eef4a798a32aab53eb3653bf976bd9a170e3a0f6 /llvm/lib/Target/X86/X86FrameLowering.cpp | |
parent | 02b74368ce181614741c7f5aa3a39a86df78f9af (diff) | |
download | bcm5719-llvm-28e490342b570ca1f261811e98f31b52e7111cec.tar.gz bcm5719-llvm-28e490342b570ca1f261811e98f31b52e7111cec.zip |
[WinEH] Fix stack alignment in funclets and ParentFrameOffset calculation
Our previous value of "16 + 8 + MaxCallFrameSize" for ParentFrameOffset
is incorrect when CSRs are involved. We were supposed to have a test
case to catch this, but it wasn't very rigorous.
The main effect here is that calling _CxxThrowException inside a
catchpad doesn't immediately crash on MOVAPS when you have an odd number
of CSRs.
llvm-svn: 250583
Diffstat (limited to 'llvm/lib/Target/X86/X86FrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 83a4acd7a4a..b4dccb60ccc 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -786,7 +786,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // NumBytes value that we would've used for the parent frame. unsigned ParentFrameNumBytes = NumBytes; if (IsFunclet) - NumBytes = MFI->getMaxCallFrameSize(); + NumBytes = getWinEHFuncletFrameSize(MF); // Skip the callee-saved push instructions. bool PushedRegs = false; @@ -1039,6 +1039,22 @@ static bool isFuncletReturnInstr(MachineInstr *MI) { llvm_unreachable("impossible"); } +unsigned X86FrameLowering::getWinEHFuncletFrameSize(const MachineFunction &MF) const { + // This is the size of the pushed CSRs. + unsigned CSSize = + MF.getInfo<X86MachineFunctionInfo>()->getCalleeSavedFrameSize(); + // This is the amount of stack a funclet needs to allocate. + unsigned MaxCallSize = MF.getFrameInfo()->getMaxCallFrameSize(); + // RBP is not included in the callee saved register block. After pushing RBP, + // everything is 16 byte aligned. Everything we allocate before an outgoing + // call must also be 16 byte aligned. + unsigned FrameSizeMinusRBP = + RoundUpToAlignment(CSSize + MaxCallSize, getStackAlignment()); + // Subtract out the size of the callee saved registers. This is how much stack + // each funclet will allocate. + return FrameSizeMinusRBP - CSSize; +} + void X86FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -1067,7 +1083,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, uint64_t NumBytes = 0; if (MBBI->getOpcode() == X86::CATCHRET) { - NumBytes = MFI->getMaxCallFrameSize(); + NumBytes = getWinEHFuncletFrameSize(MF); assert(hasFP(MF) && "EH funclets without FP not yet implemented"); MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB(); @@ -1107,7 +1123,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, .addMBB(TargetMBB); } } else if (MBBI->getOpcode() == X86::CLEANUPRET) { - NumBytes = MFI->getMaxCallFrameSize(); + NumBytes = getWinEHFuncletFrameSize(MF); assert(hasFP(MF) && "EH funclets without FP not yet implemented"); BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) @@ -2211,3 +2227,15 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( } return MBBI; } + +unsigned X86FrameLowering::getWinEHParentFrameOffset(const MachineFunction &MF) const { + // RDX, the parent frame pointer, is homed into 16(%rsp) in the prologue. + unsigned Offset = 16; + // RBP is immediately pushed. + Offset += SlotSize; + // All callee-saved registers are then pushed. + Offset += MF.getInfo<X86MachineFunctionInfo>()->getCalleeSavedFrameSize(); + // Every funclet allocates enough stack space for the largest outgoing call. + Offset += getWinEHFuncletFrameSize(MF); + return Offset; +} |