llvm.org GIT mirror llvm / fd0832e
[X86] Restore X86 base pointer after call to llvm.eh.sjlj.setjmp Commit on - This patch fixes the bug described in http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-May/062343.html The fix allocates an extra slot just below the GPRs and stores the base pointer there. This is done only for functions containing llvm.eh.sjlj.setjmp that also need a base pointer. Because code containing llvm.eh.sjlj.setjmp saves all of the callee-save GPRs in the prologue, the offset to the extra slot can be computed before prologue generation runs. Impact at run-time on affected functions is:: - One extra store in the prologue, The store saves the base pointer. - One extra load after a llvm.eh.sjlj.setjmp. The load restores the base pointer. Because the extra slot is just above a gap between frame-pointer-relative and base-pointer-relative chunks of memory, there is no impact on other offset calculations other than ensuring there is room for the extra slot. http://reviews.llvm.org/D6388 Patch by Arch Robison <arch.robison@intel.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223329 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Liao 5 years ago
5 changed file(s) with 94 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
447447
448448 [if needs base pointer]
449449 mov %rsp, %rbx
450 [if needs to restore base pointer]
451 mov %rsp, -MMM(%rbp)
450452
451453 ; Emit CFI info
452454 [if needs FP]
569571 if (HasFP) {
570572 // Calculate required stack adjustment.
571573 uint64_t FrameSize = StackSize - SlotSize;
574 // If required, include space for extra hidden slot for stashing base pointer.
575 if (X86FI->getRestoreBasePointer())
576 FrameSize += SlotSize;
572577 if (RegInfo->needsStackRealignment(MF)) {
573578 // Callee-saved registers are pushed on stack before the stack
574579 // is realigned.
837842 BuildMI(MBB, MBBI, DL, TII.get(Opc), BasePtr)
838843 .addReg(StackPtr)
839844 .setMIFlag(MachineInstr::FrameSetup);
845 if (X86FI->getRestoreBasePointer()) {
846 // Stash value of base pointer. Saving RSP instead of EBP shortens dependence chain.
847 unsigned Opm = Uses64BitFramePtr ? X86::MOV64mr : X86::MOV32mr;
848 addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(Opm)),
849 FramePtr, true, X86FI->getRestoreBasePointerOffset())
850 .addReg(StackPtr)
851 .setMIFlag(MachineInstr::FrameSetup);
852 }
840853 }
841854
842855 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
2092420924 // v = phi(main, restore)
2092520925 //
2092620926 // restoreMBB:
20927 // if base pointer being used, load it from frame
2092720928 // v_restore = 1
2092820929
2092920930 MachineBasicBlock *thisMBB = MBB;
2100721008 .addReg(restoreDstReg).addMBB(restoreMBB);
2100821009
2100921010 // restoreMBB:
21011 if (RegInfo->hasBasePointer(*MF)) {
21012 const X86Subtarget &STI = MF->getTarget().getSubtarget();
21013 const bool Uses64BitFramePtr = STI.isTarget64BitLP64() || STI.isTargetNaCl64();
21014 X86MachineFunctionInfo *X86FI = MF->getInfo();
21015 X86FI->setRestoreBasePointer(MF);
21016 unsigned FramePtr = RegInfo->getFrameRegister(*MF);
21017 unsigned BasePtr = RegInfo->getBaseRegister();
21018 unsigned Opm = Uses64BitFramePtr ? X86::MOV64rm : X86::MOV32rm;
21019 addRegOffset(BuildMI(restoreMBB, DL, TII->get(Opm), BasePtr),
21020 FramePtr, true, X86FI->getRestoreBasePointerOffset())
21021 .setMIFlag(MachineInstr::FrameSetup);
21022 }
2101021023 BuildMI(restoreMBB, DL, TII->get(X86::MOV32ri), restoreDstReg).addImm(1);
2101121024 BuildMI(restoreMBB, DL, TII->get(X86::JMP_4)).addMBB(sinkMBB);
2101221025 restoreMBB->addSuccessor(sinkMBB);
77 //===----------------------------------------------------------------------===//
88
99 #include "X86MachineFunctionInfo.h"
10 #include "X86RegisterInfo.h"
11 #include "llvm/Target/TargetSubtargetInfo.h"
1012
1113 using namespace llvm;
1214
1315 void X86MachineFunctionInfo::anchor() { }
16
17 void X86MachineFunctionInfo::setRestoreBasePointer(const MachineFunction *MF) {
18 if (!RestoreBasePointerOffset) {
19 const X86RegisterInfo *RegInfo = static_cast(
20 MF->getSubtarget().getRegisterInfo());
21 unsigned SlotSize = RegInfo->getSlotSize();
22 for (const MCPhysReg *CSR =
23 RegInfo->X86RegisterInfo::getCalleeSavedRegs(MF);
24 unsigned Reg = *CSR;
25 ++CSR)
26 {
27 if (X86::GR64RegClass.contains(Reg) || X86::GR32RegClass.contains(Reg))
28 RestoreBasePointerOffset -= SlotSize;
29 }
30 }
31 }
32
3030 /// contains stack pointer re-alignment code which requires FP.
3131 bool ForceFramePointer;
3232
33 /// RestoreBasePointerOffset - Non-zero if the function has base pointer
34 /// and makes call to llvm.eh.sjlj.setjmp. When non-zero, the value is a
35 /// displacement from the frame pointer to a slot where the base pointer
36 /// is stashed.
37 signed char RestoreBasePointerOffset;
38
3339 /// CalleeSavedFrameSize - Size of the callee-saved register portion of the
3440 /// stack frame in bytes.
3541 unsigned CalleeSavedFrameSize;
8894
8995 public:
9096 X86MachineFunctionInfo() : ForceFramePointer(false),
97 RestoreBasePointerOffset(0),
9198 CalleeSavedFrameSize(0),
9299 BytesToPopOnReturn(0),
93100 ReturnAddrIndex(0),
103110
104111 explicit X86MachineFunctionInfo(MachineFunction &MF)
105112 : ForceFramePointer(false),
113 RestoreBasePointerOffset(0),
106114 CalleeSavedFrameSize(0),
107115 BytesToPopOnReturn(0),
108116 ReturnAddrIndex(0),
118126
119127 bool getForceFramePointer() const { return ForceFramePointer;}
120128 void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; }
129
130 bool getRestoreBasePointer() const { return RestoreBasePointerOffset!=0; }
131 void setRestoreBasePointer(const MachineFunction *MF);
132 int getRestoreBasePointerOffset() const {return RestoreBasePointerOffset; }
121133
122134 unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
123135 void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
0 ; RUN: llc < %s -mtriple=i386-pc-linux -mcpu=corei7 -relocation-model=static | FileCheck --check-prefix=X86 %s
1 ; RUN: llc < %s -mtriple=x86_64-pc-linux -mcpu=corei7 -relocation-model=static | FileCheck --check-prefix=X64 %s
2
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4
5 %Foo = type { [125 x i8] }
6
7 declare i32 @llvm.eh.sjlj.setjmp(i8*) nounwind
8
9 declare void @whatever(i64, %Foo*, i8**, i8*, i8*, i32) #0
10
11 attributes #0 = { nounwind uwtable "no-frame-pointer-elim"="true" }
12
13 define i32 @test1(i64 %n, %Foo* byval nocapture readnone align 8 %f) #0 {
14 entry:
15 %buf = alloca [5 x i8*], align 16
16 %p = alloca i8*, align 8
17 %q = alloca i8, align 64
18 %r = bitcast [5 x i8*]* %buf to i8*
19 %s = alloca i8, i64 %n, align 1
20 store i8* %s, i8** %p, align 8
21 %t = call i32 @llvm.eh.sjlj.setjmp(i8* %s)
22 call void @whatever(i64 %n, %Foo* %f, i8** %p, i8* %q, i8* %s, i32 %t) #1
23 ret i32 0
24 ; X86: movl %esp, %esi
25 ; X86: movl %esp, -16(%ebp)
26 ; X86: {{.LBB.*:}}
27 ; X86: movl -16(%ebp), %esi
28 ; X86: {{.LBB.*:}}
29 ; X64: movq %rsp, %rbx
30 ; X64: movq %rsp, -48(%rbp)
31 ; X64: {{.LBB.*:}}
32 ; X64: movq -48(%rbp), %rbx
33 ; X64: {{.LBB.*:}}
34 }
35
36