forked from OSchip/llvm-project
[SystemZ] [SSP] Add support for LOAD_STACK_GUARD.
This fixes PR22248 on s390x. The previous attempt at this was D19101, which was before LOAD_STACK_GUARD existed. Compared to the previous version, this always emits a rather ugly block of 4 instructions, involving a thread pointer load that can't be shared with other potential users. However, this is necessary for SSP - spilling the guard value (or thread pointer used to load it) is counter to the goal, since it could be overwritten along with the frame it protects. Differential Revision: http://reviews.llvm.org/D19363 llvm-svn: 267340
This commit is contained in:
parent
7eedee938f
commit
aef3b5b5e2
|
@ -426,6 +426,13 @@ public:
|
|||
return SystemZ::R7D;
|
||||
}
|
||||
|
||||
/// Override to support customized stack guard loading.
|
||||
bool useLoadStackGuardNode() const override {
|
||||
return true;
|
||||
}
|
||||
void insertSSPDeclarations(Module &M) const override {
|
||||
}
|
||||
|
||||
MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const
|
||||
override;
|
||||
|
|
|
@ -160,6 +160,37 @@ void SystemZInstrInfo::expandZExtPseudo(MachineInstr *MI, unsigned LowOpcode,
|
|||
MI->eraseFromParent();
|
||||
}
|
||||
|
||||
void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const {
|
||||
MachineBasicBlock *MBB = MI->getParent();
|
||||
MachineFunction &MF = *MBB->getParent();
|
||||
const unsigned Reg = MI->getOperand(0).getReg();
|
||||
|
||||
// Conveniently, all 4 instructions are cloned from LOAD_STACK_GUARD,
|
||||
// so they already have operand 0 set to reg.
|
||||
|
||||
// ear <reg>, %a0
|
||||
MachineInstr *Ear1MI = MF.CloneMachineInstr(MI);
|
||||
MBB->insert(MI, Ear1MI);
|
||||
Ear1MI->setDesc(get(SystemZ::EAR));
|
||||
MachineInstrBuilder(MF, Ear1MI).addImm(0);
|
||||
|
||||
// sllg <reg>, <reg>, 32
|
||||
MachineInstr *SllgMI = MF.CloneMachineInstr(MI);
|
||||
MBB->insert(MI, SllgMI);
|
||||
SllgMI->setDesc(get(SystemZ::SLLG));
|
||||
MachineInstrBuilder(MF, SllgMI).addReg(Reg).addReg(0).addImm(32);
|
||||
|
||||
// ear <reg>, %a1
|
||||
MachineInstr *Ear2MI = MF.CloneMachineInstr(MI);
|
||||
MBB->insert(MI, Ear2MI);
|
||||
Ear2MI->setDesc(get(SystemZ::EAR));
|
||||
MachineInstrBuilder(MF, Ear2MI).addImm(1);
|
||||
|
||||
// lg <reg>, 40(<reg>)
|
||||
MI->setDesc(get(SystemZ::LG));
|
||||
MachineInstrBuilder(MF, MI).addReg(Reg).addImm(40).addReg(0);
|
||||
}
|
||||
|
||||
// Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR
|
||||
// DestReg before MBBI in MBB. Use LowLowOpcode when both DestReg and SrcReg
|
||||
// are low registers, otherwise use RISB[LH]G. Size is the number of bits
|
||||
|
@ -1100,6 +1131,10 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
|
|||
splitAdjDynAlloc(MI);
|
||||
return true;
|
||||
|
||||
case TargetOpcode::LOAD_STACK_GUARD:
|
||||
expandLoadStackGuard(MI);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
|
|||
unsigned HighOpcode) const;
|
||||
void expandZExtPseudo(MachineInstr *MI, unsigned LowOpcode,
|
||||
unsigned Size) const;
|
||||
void expandLoadStackGuard(MachineInstr *MI) const;
|
||||
void emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
DebugLoc DL, unsigned DestReg, unsigned SrcReg,
|
||||
unsigned LowLowOpcode, unsigned Size, bool KillSrc) const;
|
||||
|
|
|
@ -33,6 +33,15 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
|
|||
public:
|
||||
SystemZRegisterInfo();
|
||||
|
||||
/// getPointerRegClass - Return the register class to use to hold pointers.
|
||||
/// This is currently only used by LOAD_STACK_GUARD, which requires a non-%r0
|
||||
/// register, hence ADDR64.
|
||||
const TargetRegisterClass *
|
||||
getPointerRegClass(const MachineFunction &MF,
|
||||
unsigned Kind=0) const override {
|
||||
return &SystemZ::ADDR64BitRegClass;
|
||||
}
|
||||
|
||||
// Override TargetRegisterInfo.h.
|
||||
bool requiresRegisterScavenging(const MachineFunction &MF) const override {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: @test_stack_guard
|
||||
; CHECK: ear [[REG1:%r[1-9][0-9]?]], %a0
|
||||
; CHECK: sllg [[REG1]], [[REG1]], 32
|
||||
; CHECK: ear [[REG1]], %a1
|
||||
; CHECK: lg [[REG1]], 40([[REG1]])
|
||||
; CHECK: stg [[REG1]], {{[0-9]*}}(%r15)
|
||||
; CHECK: brasl %r14, foo3@PLT
|
||||
; CHECK: ear [[REG2:%r[1-9][0-9]?]], %a0
|
||||
; CHECK: sllg [[REG2]], [[REG2]], 32
|
||||
; CHECK: ear [[REG2]], %a1
|
||||
; CHECK: lg [[REG2]], 40([[REG2]])
|
||||
; CHECK: sg [[REG2]], {{[0-9]*}}(%r15)
|
||||
|
||||
define i32 @test_stack_guard() #0 {
|
||||
entry:
|
||||
%a1 = alloca [256 x i32], align 4
|
||||
%0 = bitcast [256 x i32]* %a1 to i8*
|
||||
call void @llvm.lifetime.start(i64 1024, i8* %0)
|
||||
%arraydecay = getelementptr inbounds [256 x i32], [256 x i32]* %a1, i64 0, i64 0
|
||||
call void @foo3(i32* %arraydecay)
|
||||
call void @llvm.lifetime.end(i64 1024, i8* %0)
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @llvm.lifetime.start(i64, i8* nocapture)
|
||||
|
||||
declare void @foo3(i32*)
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @llvm.lifetime.end(i64, i8* nocapture)
|
||||
|
||||
attributes #0 = { sspstrong }
|
Loading…
Reference in New Issue