[SystemZ] Support llvm.frameaddress/llvm.returnaddress intrinsics

Enable the SystemZ back-end to lower FRAMEADDR and RETURNADDR, which
previously would cause the back-end to crash.  Currently, only a
frame count of zero is supported.

Author: bryanpkc
Differential Revision: http://reviews.llvm.org/D18514

llvm-svn: 265291
This commit is contained in:
Ulrich Weigand 2016-04-04 12:44:55 +00:00
parent e4a77057a3
commit f557d08325
5 changed files with 107 additions and 2 deletions

View File

@ -2676,6 +2676,57 @@ SDValue SystemZTargetLowering::lowerConstantPool(ConstantPoolSDNode *CP,
return DAG.getNode(SystemZISD::PCREL_WRAPPER, DL, PtrVT, Result);
}
SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MFI->setFrameAddressIsTaken(true);
SDLoc DL(Op);
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
EVT PtrVT = getPointerTy(DAG.getDataLayout());
// If the back chain frame index has not been allocated yet, do so.
SystemZMachineFunctionInfo *FI = MF.getInfo<SystemZMachineFunctionInfo>();
int BackChainIdx = FI->getFramePointerSaveIndex();
if (!BackChainIdx) {
// By definition, the frame address is the address of the back chain.
BackChainIdx = MFI->CreateFixedObject(8, -SystemZMC::CallFrameSize, false);
FI->setFramePointerSaveIndex(BackChainIdx);
}
SDValue BackChain = DAG.getFrameIndex(BackChainIdx, PtrVT);
// FIXME The frontend should detect this case.
if (Depth > 0) {
report_fatal_error("Unsupported stack frame traversal count");
}
return BackChain;
}
SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op,
SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MFI->setReturnAddressIsTaken(true);
if (verifyReturnAddressArgumentIsConstant(Op, DAG))
return SDValue();
SDLoc DL(Op);
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
EVT PtrVT = getPointerTy(DAG.getDataLayout());
// FIXME The frontend should detect this case.
if (Depth > 0) {
report_fatal_error("Unsupported stack frame traversal count");
}
// Return R14D, which has the return address. Mark it an implicit live-in.
unsigned LinkReg = MF.addLiveIn(SystemZ::R14D, &SystemZ::GR64BitRegClass);
return DAG.getCopyFromReg(DAG.getEntryNode(), DL, LinkReg, PtrVT);
}
SDValue SystemZTargetLowering::lowerBITCAST(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
@ -4347,6 +4398,10 @@ SDValue SystemZTargetLowering::lowerShift(SDValue Op, SelectionDAG &DAG,
SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
case ISD::FRAMEADDR:
return lowerFRAMEADDR(Op, DAG);
case ISD::RETURNADDR:
return lowerRETURNADDR(Op, DAG);
case ISD::BR_CC:
return lowerBR_CC(Op, DAG);
case ISD::SELECT_CC:

View File

@ -467,6 +467,8 @@ private:
SelectionDAG &DAG) const;
SDValue lowerJumpTable(JumpTableSDNode *JT, SelectionDAG &DAG) const;
SDValue lowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVACOPY(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;

View File

@ -22,14 +22,15 @@ class SystemZMachineFunctionInfo : public MachineFunctionInfo {
unsigned VarArgsFirstFPR;
unsigned VarArgsFrameIndex;
unsigned RegSaveFrameIndex;
int FramePointerSaveIndex;
bool ManipulatesSP;
unsigned NumLocalDynamics;
public:
explicit SystemZMachineFunctionInfo(MachineFunction &MF)
: LowSavedGPR(0), HighSavedGPR(0), VarArgsFirstGPR(0), VarArgsFirstFPR(0),
VarArgsFrameIndex(0), RegSaveFrameIndex(0), ManipulatesSP(false),
NumLocalDynamics(0) {}
VarArgsFrameIndex(0), RegSaveFrameIndex(0), FramePointerSaveIndex(0),
ManipulatesSP(false), NumLocalDynamics(0) {}
// Get and set the first call-saved GPR that should be saved and restored
// by this function. This is 0 if no GPRs need to be saved or restored.
@ -59,6 +60,10 @@ public:
unsigned getRegSaveFrameIndex() const { return RegSaveFrameIndex; }
void setRegSaveFrameIndex(unsigned FI) { RegSaveFrameIndex = FI; }
// Get and set the frame index of where the old frame pointer is stored.
int getFramePointerSaveIndex() const { return FramePointerSaveIndex; }
void setFramePointerSaveIndex(int Idx) { FramePointerSaveIndex = Idx; }
// Get and set whether the function directly manipulates the stack pointer,
// e.g. through STACKSAVE or STACKRESTORE.
bool getManipulatesSP() const { return ManipulatesSP; }

View File

@ -0,0 +1,28 @@
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
; The current function's frame address is the address of
; the optional back chain slot.
define i8* @fp0() nounwind {
entry:
; CHECK-LABEL: fp0:
; CHECK: la %r2, 0(%r15)
; CHECK: br %r14
%0 = tail call i8* @llvm.frameaddress(i32 0)
ret i8* %0
}
; Check that the frame address is correct in a presence
; of a stack frame.
define i8* @fp0f() nounwind {
entry:
; CHECK-LABEL: fp0f:
; CHECK: aghi %r15, -168
; CHECK: la %r2, 168(%r15)
; CHECK: aghi %r15, 168
; CHECK: br %r14
%0 = alloca i64, align 8
%1 = tail call i8* @llvm.frameaddress(i32 0)
ret i8* %1
}
declare i8* @llvm.frameaddress(i32) nounwind readnone

View File

@ -0,0 +1,15 @@
; Test support for the llvm.returnaddress intrinsic.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
; The current function's return address is in the link register.
define i8* @rt0() norecurse nounwind readnone {
entry:
; CHECK-LABEL: rt0:
; CHECK: lgr %r2, %r14
; CHECK: br %r14
%0 = tail call i8* @llvm.returnaddress(i32 0)
ret i8* %0
}
declare i8* @llvm.returnaddress(i32) nounwind readnone