forked from OSchip/llvm-project
[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:
parent
e4a77057a3
commit
f557d08325
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue