1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[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>

llvm-svn: 223329
This commit is contained in:
Michael Liao 2014-12-04 00:56:38 +00:00
parent 84b0b8cc3b
commit f24ea6579d
5 changed files with 94 additions and 0 deletions

View File

@ -448,6 +448,8 @@ void X86FrameLowering::getStackProbeFunction(const X86Subtarget &STI,
[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 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
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 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
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) {

View File

@ -20925,6 +20925,7 @@ X86TargetLowering::emitEHSjLjSetJmp(MachineInstr *MI,
// v = phi(main, restore)
//
// restoreMBB:
// if base pointer being used, load it from frame
// v_restore = 1
MachineBasicBlock *thisMBB = MBB;
@ -21008,6 +21009,18 @@ X86TargetLowering::emitEHSjLjSetJmp(MachineInstr *MI,
.addReg(restoreDstReg).addMBB(restoreMBB);
// restoreMBB:
if (RegInfo->hasBasePointer(*MF)) {
const X86Subtarget &STI = MF->getTarget().getSubtarget<X86Subtarget>();
const bool Uses64BitFramePtr = STI.isTarget64BitLP64() || STI.isTargetNaCl64();
X86MachineFunctionInfo *X86FI = MF->getInfo<X86MachineFunctionInfo>();
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);

View File

@ -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<const X86RegisterInfo *>(
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;
}
}
}

View File

@ -31,6 +31,12 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
/// 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 @@ private:
public:
X86MachineFunctionInfo() : ForceFramePointer(false),
RestoreBasePointerOffset(0),
CalleeSavedFrameSize(0),
BytesToPopOnReturn(0),
ReturnAddrIndex(0),
@ -104,6 +111,7 @@ public:
explicit X86MachineFunctionInfo(MachineFunction &MF)
: ForceFramePointer(false),
RestoreBasePointerOffset(0),
CalleeSavedFrameSize(0),
BytesToPopOnReturn(0),
ReturnAddrIndex(0),
@ -120,6 +128,10 @@ public:
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; }

View File

@ -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.*:}}
}