Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -448,6 +448,8 @@ [if needs base pointer] mov %rsp, %rbx + [if needs to restore base pointer] + mov %rsp, -MMM(%rbp) ; Emit CFI info [if needs FP] @@ -570,6 +572,9 @@ if (HasFP) { // 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; if (RegInfo->needsStackRealignment(MF)) { // Callee-saved registers are pushed on stack before the stack // is realigned. @@ -838,6 +843,14 @@ BuildMI(MBB, MBBI, DL, TII.get(Opc), BasePtr) .addReg(StackPtr) .setMIFlag(MachineInstr::FrameSetup); + if (X86FI->getRestoreBasePointer()) { + // Stash value of base pointer. Saving RSP instead of EBP shortens dependence chain. + unsigned Opm = Uses64BitFramePtr ? X86::MOV64mr : X86::MOV32mr; + addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(Opm)), + FramePtr, true, X86FI->getRestoreBasePointerOffset()) + .addReg(StackPtr) + .setMIFlag(MachineInstr::FrameSetup); + } } if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) { Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -20882,6 +20882,7 @@ // v = phi(main, restore) // // restoreMBB: + // if base pointer being used, load it from frame // v_restore = 1 MachineBasicBlock *thisMBB = MBB; @@ -20965,6 +20966,18 @@ .addReg(restoreDstReg).addMBB(restoreMBB); // restoreMBB: + if (RegInfo->hasBasePointer(*MF)) { + const X86Subtarget &STI = MF->getTarget().getSubtarget(); + const bool Uses64BitFramePtr = STI.isTarget64BitLP64() || STI.isTargetNaCl64(); + X86MachineFunctionInfo *X86FI = MF->getInfo(); + X86FI->setRestoreBasePointer(MF); + unsigned FramePtr = RegInfo->getFrameRegister(*MF); + unsigned BasePtr = RegInfo->getBaseRegister(); + unsigned Opm = Uses64BitFramePtr ? X86::MOV64rm : X86::MOV32rm; + addRegOffset(BuildMI(restoreMBB, DL, TII->get(Opm), BasePtr), + FramePtr, true, X86FI->getRestoreBasePointerOffset()) + .setMIFlag(MachineInstr::FrameSetup); + } BuildMI(restoreMBB, DL, TII->get(X86::MOV32ri), restoreDstReg).addImm(1); BuildMI(restoreMBB, DL, TII->get(X86::JMP_4)).addMBB(sinkMBB); restoreMBB->addSuccessor(sinkMBB); Index: lib/Target/X86/X86MachineFunctionInfo.h =================================================================== --- lib/Target/X86/X86MachineFunctionInfo.h +++ lib/Target/X86/X86MachineFunctionInfo.h @@ -31,6 +31,12 @@ /// contains stack pointer re-alignment code which requires FP. bool ForceFramePointer; + /// RestoreBasePointerOffset - Non-zero if the function has base pointer + /// and makes call to llvm.eh.sjlj.setjmp. When non-zero, the value is a + /// displacement from the frame pointer to a slot where the base pointer + /// is stashed. + signed char RestoreBasePointerOffset; + /// CalleeSavedFrameSize - Size of the callee-saved register portion of the /// stack frame in bytes. unsigned CalleeSavedFrameSize; @@ -89,6 +95,7 @@ public: X86MachineFunctionInfo() : ForceFramePointer(false), + RestoreBasePointerOffset(0), CalleeSavedFrameSize(0), BytesToPopOnReturn(0), ReturnAddrIndex(0), @@ -104,6 +111,7 @@ explicit X86MachineFunctionInfo(MachineFunction &MF) : ForceFramePointer(false), + RestoreBasePointerOffset(0), CalleeSavedFrameSize(0), BytesToPopOnReturn(0), ReturnAddrIndex(0), @@ -120,6 +128,10 @@ bool getForceFramePointer() const { return ForceFramePointer;} void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; } + bool getRestoreBasePointer() const { return RestoreBasePointerOffset!=0; } + void setRestoreBasePointer(const MachineFunction *MF); + int getRestoreBasePointerOffset() const {return RestoreBasePointerOffset; } + unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; } void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } Index: lib/Target/X86/X86MachineFunctionInfo.cpp =================================================================== --- lib/Target/X86/X86MachineFunctionInfo.cpp +++ lib/Target/X86/X86MachineFunctionInfo.cpp @@ -8,7 +8,26 @@ //===----------------------------------------------------------------------===// #include "X86MachineFunctionInfo.h" +#include "X86RegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; void X86MachineFunctionInfo::anchor() { } + +void X86MachineFunctionInfo::setRestoreBasePointer(const MachineFunction *MF) { + if (!RestoreBasePointerOffset) { + const X86RegisterInfo *RegInfo = static_cast( + MF->getSubtarget().getRegisterInfo()); + unsigned SlotSize = RegInfo->getSlotSize(); + for (const MCPhysReg *CSR = + RegInfo->X86RegisterInfo::getCalleeSavedRegs(MF); + unsigned Reg = *CSR; + ++CSR) + { + if (X86::GR64RegClass.contains(Reg) || X86::GR32RegClass.contains(Reg)) + RestoreBasePointerOffset -= SlotSize; + } + } +} + Index: test/CodeGen/X86/sjlj-baseptr.ll =================================================================== --- test/CodeGen/X86/sjlj-baseptr.ll +++ test/CodeGen/X86/sjlj-baseptr.ll @@ -0,0 +1,37 @@ +; RUN: llc < %s -mtriple=i386-pc-linux -mcpu=corei7 -relocation-model=static | FileCheck --check-prefix=X86 %s +; RUN: llc < %s -mtriple=x86_64-pc-linux -mcpu=corei7 -relocation-model=static | FileCheck --check-prefix=X64 %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +%Foo = type { [125 x i8] } + +declare i32 @llvm.eh.sjlj.setjmp(i8*) nounwind + +declare void @whatever(i64, %Foo*, i8**, i8*, i8*, i32) #0 + +attributes #0 = { nounwind uwtable "no-frame-pointer-elim"="true" } + +define i32 @test1(i64 %n, %Foo* byval nocapture readnone align 8 %f) #0 { +entry: + %buf = alloca [5 x i8*], align 16 + %p = alloca i8*, align 8 + %q = alloca i8, align 64 + %r = bitcast [5 x i8*]* %buf to i8* + %s = alloca i8, i64 %n, align 1 + store i8* %s, i8** %p, align 8 + %t = call i32 @llvm.eh.sjlj.setjmp(i8* %s) + call void @whatever(i64 %n, %Foo* %f, i8** %p, i8* %q, i8* %s, i32 %t) #1 + ret i32 0 +; X86: movl %esp, %esi +; X86: movl %esp, -16(%ebp) +; X86: {{.LBB.*:}} +; X86: movl -16(%ebp), %esi +; X86: {{.LBB.*:}} +; X64: movq %rsp, %rbx +; X64: movq %rsp, -48(%rbp) +; X64: {{.LBB.*:}} +; X64: movq -48(%rbp), %rbx +; X64: {{.LBB.*:}} +} + +