diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1628,10 +1628,6 @@ // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; - // If required, include space for extra hidden slot for stashing base pointer. - if (X86FI->getRestoreBasePointer()) - FrameSize += SlotSize; - NumBytes = FrameSize - (X86FI->getCalleeSavedFrameSize() + TailCallArgReserveSize); @@ -2646,6 +2642,16 @@ I.setFrameIdx(SlotIndex); } + // Adjust the offset of spill slot as we know the accurate callee saved frame + // size. + if (X86FI->getRestoreBasePointer()) { + SpillSlotOffset -= SlotSize; + CalleeSavedFrameSize += SlotSize; + + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + // TODO: saving the slot index is better? + X86FI->setRestoreBasePointer(CalleeSavedFrameSize); + } X86FI->setCalleeSavedFrameSize(CalleeSavedFrameSize); MFI.setCVBytesOfCalleeSavedRegisters(CalleeSavedFrameSize); @@ -2728,6 +2734,15 @@ .setMIFlag(MachineInstr::FrameSetup); } + const X86MachineFunctionInfo *X86FI = MF.getInfo(); + if (X86FI->getRestoreBasePointer()) { + unsigned Opc = STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r; + Register BaseReg = this->TRI->getBaseRegister(); + BuildMI(MBB, MI, DL, TII.get(Opc)) + .addReg(BaseReg, getKillRegState(true)) + .setMIFlag(MachineInstr::FrameSetup); + } + // Make XMM regs spilled. X86 does not have ability of push/pop XMM. // It can be done by spilling XMMs to stack frame. for (const CalleeSavedInfo &I : llvm::reverse(CSI)) { @@ -2825,6 +2840,16 @@ Register()); } + // Clear the stack slot for spill base pointer register. + MachineFunction &MF = *MBB.getParent(); + const X86MachineFunctionInfo *X86FI = MF.getInfo(); + if (X86FI->getRestoreBasePointer()) { + unsigned Opc = STI.is64Bit() ? X86::POP64r : X86::POP32r; + Register BaseReg = this->TRI->getBaseRegister(); + BuildMI(MBB, MI, DL, TII.get(Opc), BaseReg) + .setMIFlag(MachineInstr::FrameDestroy); + } + // POP GPRs. unsigned Opc = STI.is64Bit() ? X86::POP64r : X86::POP32r; for (const CalleeSavedInfo &I : CSI) { diff --git a/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/llvm/lib/Target/X86/X86MachineFunctionInfo.h --- a/llvm/lib/Target/X86/X86MachineFunctionInfo.h +++ b/llvm/lib/Target/X86/X86MachineFunctionInfo.h @@ -149,6 +149,9 @@ bool getRestoreBasePointer() const { return RestoreBasePointerOffset!=0; } void setRestoreBasePointer(const MachineFunction *MF); + void setRestoreBasePointer(unsigned CalleeSavedFrameSize) { + RestoreBasePointerOffset = -CalleeSavedFrameSize; + } int getRestoreBasePointerOffset() const {return RestoreBasePointerOffset; } DenseMap& getWinEHXMMSlotInfo() { return WinEHXMMSlotInfo; } diff --git a/llvm/test/CodeGen/X86/sjlj-baseptr.ll b/llvm/test/CodeGen/X86/sjlj-baseptr.ll --- a/llvm/test/CodeGen/X86/sjlj-baseptr.ll +++ b/llvm/test/CodeGen/X86/sjlj-baseptr.ll @@ -21,16 +21,24 @@ %t = call i32 @llvm.eh.sjlj.setjmp(ptr %s) call void @whatever(i64 %n, ptr %f, ptr %p, ptr %q, ptr %s, i32 %t) #1 ret i32 0 +; X86: pushl %esi +; X86-NEXT: pushl %esi ; X86: movl %esp, %esi ; X86: movl %esp, -16(%ebp) ; X86: {{.LBB.*:}} ; X86: movl -16(%ebp), %esi ; X86: {{.LBB.*:}} +; X86: popl %esi +; X86-NEXT: popl %esi +; X64: pushq %rbx +; X64-NEXT: pushq %rbx ; X64: movq %rsp, %rbx ; X64: movq %rsp, -48(%rbp) ; X64: {{.LBB.*:}} ; X64: movq -48(%rbp), %rbx ; X64: {{.LBB.*:}} +; X64: popq %rbx +; X64-NEXT: popq %rbx }